1import React, { PureComponent } from 'react'; 2import { css } from '@emotion/css'; 3import { ConfirmButton, ConfirmModal, Button } from '@grafana/ui'; 4import { AccessControlAction, UserSession } from 'app/types'; 5import { contextSrv } from 'app/core/core'; 6 7interface Props { 8 sessions: UserSession[]; 9 10 onSessionRevoke: (id: number) => void; 11 onAllSessionsRevoke: () => void; 12} 13 14interface State { 15 showLogoutModal: boolean; 16} 17 18export class UserSessions extends PureComponent<Props, State> { 19 forceAllLogoutButton = React.createRef<HTMLButtonElement>(); 20 state: State = { 21 showLogoutModal: false, 22 }; 23 24 showLogoutConfirmationModal = () => { 25 this.setState({ showLogoutModal: true }); 26 }; 27 28 dismissLogoutConfirmationModal = () => { 29 this.setState({ showLogoutModal: false }, () => { 30 this.forceAllLogoutButton.current?.focus(); 31 }); 32 }; 33 34 onSessionRevoke = (id: number) => { 35 return () => { 36 this.props.onSessionRevoke(id); 37 }; 38 }; 39 40 onAllSessionsRevoke = () => { 41 this.setState({ showLogoutModal: false }); 42 this.props.onAllSessionsRevoke(); 43 }; 44 45 render() { 46 const { sessions } = this.props; 47 const { showLogoutModal } = this.state; 48 49 const logoutFromAllDevicesClass = css` 50 margin-top: 0.8rem; 51 `; 52 53 const canLogout = contextSrv.hasPermission(AccessControlAction.UsersLogout); 54 55 return ( 56 <> 57 <h3 className="page-heading">Sessions</h3> 58 <div className="gf-form-group"> 59 <div className="gf-form"> 60 <table className="filter-table form-inline"> 61 <thead> 62 <tr> 63 <th>Last seen</th> 64 <th>Logged on</th> 65 <th>IP address</th> 66 <th colSpan={2}>Browser and OS</th> 67 </tr> 68 </thead> 69 <tbody> 70 {sessions && 71 sessions.map((session, index) => ( 72 <tr key={`${session.id}-${index}`}> 73 <td>{session.isActive ? 'Now' : session.seenAt}</td> 74 <td>{session.createdAt}</td> 75 <td>{session.clientIp}</td> 76 <td>{`${session.browser} on ${session.os} ${session.osVersion}`}</td> 77 <td> 78 <div className="pull-right"> 79 {canLogout && ( 80 <ConfirmButton 81 confirmText="Confirm logout" 82 confirmVariant="destructive" 83 onConfirm={this.onSessionRevoke(session.id)} 84 autoFocus 85 > 86 Force logout 87 </ConfirmButton> 88 )} 89 </div> 90 </td> 91 </tr> 92 ))} 93 </tbody> 94 </table> 95 </div> 96 <div className={logoutFromAllDevicesClass}> 97 {canLogout && sessions.length > 0 && ( 98 <Button variant="secondary" onClick={this.showLogoutConfirmationModal} ref={this.forceAllLogoutButton}> 99 Force logout from all devices 100 </Button> 101 )} 102 <ConfirmModal 103 isOpen={showLogoutModal} 104 title="Force logout from all devices" 105 body="Are you sure you want to force logout from all devices?" 106 confirmText="Force logout" 107 onConfirm={this.onAllSessionsRevoke} 108 onDismiss={this.dismissLogoutConfirmationModal} 109 /> 110 </div> 111 </div> 112 </> 113 ); 114 } 115} 116