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