123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- import { debounce } from 'lodash';
- import { dateTimeFormatTimeAgo } from '@grafana/data';
- import { featureEnabled, getBackendSrv, locationService } from '@grafana/runtime';
- import config from 'app/core/config';
- import { contextSrv } from 'app/core/core';
- import { accessControlQueryParam } from 'app/core/utils/accessControl';
- import { ThunkResult, LdapUser, UserSession, UserDTO, AccessControlAction, UserFilter } from 'app/types';
- import {
- userAdminPageLoadedAction,
- userProfileLoadedAction,
- userOrgsLoadedAction,
- userSessionsLoadedAction,
- userAdminPageFailedAction,
- ldapConnectionInfoLoadedAction,
- ldapSyncStatusLoadedAction,
- userMappingInfoLoadedAction,
- userMappingInfoFailedAction,
- clearUserMappingInfoAction,
- clearUserErrorAction,
- ldapFailedAction,
- usersFetched,
- queryChanged,
- pageChanged,
- filterChanged,
- usersFetchBegin,
- usersFetchEnd,
- } from './reducers';
- // UserAdminPage
- export function loadAdminUserPage(userId: number): ThunkResult<void> {
- return async (dispatch) => {
- try {
- dispatch(userAdminPageLoadedAction(false));
- await dispatch(loadUserProfile(userId));
- await dispatch(loadUserOrgs(userId));
- await dispatch(loadUserSessions(userId));
- if (config.ldapEnabled && featureEnabled('ldapsync')) {
- await dispatch(loadLdapSyncStatus());
- }
- dispatch(userAdminPageLoadedAction(true));
- } catch (error) {
- console.error(error);
- const userError = {
- title: error.data.message,
- body: error.data.error,
- };
- dispatch(userAdminPageFailedAction(userError));
- }
- };
- }
- export function loadUserProfile(userId: number): ThunkResult<void> {
- return async (dispatch) => {
- const user = await getBackendSrv().get(`/api/users/${userId}`, accessControlQueryParam());
- dispatch(userProfileLoadedAction(user));
- };
- }
- export function updateUser(user: UserDTO): ThunkResult<void> {
- return async (dispatch) => {
- await getBackendSrv().put(`/api/users/${user.id}`, user);
- dispatch(loadAdminUserPage(user.id));
- };
- }
- export function setUserPassword(userId: number, password: string): ThunkResult<void> {
- return async (dispatch) => {
- const payload = { password };
- await getBackendSrv().put(`/api/admin/users/${userId}/password`, payload);
- dispatch(loadAdminUserPage(userId));
- };
- }
- export function disableUser(userId: number): ThunkResult<void> {
- return async (dispatch) => {
- await getBackendSrv().post(`/api/admin/users/${userId}/disable`);
- locationService.push('/admin/users');
- };
- }
- export function enableUser(userId: number): ThunkResult<void> {
- return async (dispatch) => {
- await getBackendSrv().post(`/api/admin/users/${userId}/enable`);
- dispatch(loadAdminUserPage(userId));
- };
- }
- export function deleteUser(userId: number): ThunkResult<void> {
- return async (dispatch) => {
- await getBackendSrv().delete(`/api/admin/users/${userId}`);
- locationService.push('/admin/users');
- };
- }
- export function updateUserPermissions(userId: number, isGrafanaAdmin: boolean): ThunkResult<void> {
- return async (dispatch) => {
- const payload = { isGrafanaAdmin };
- await getBackendSrv().put(`/api/admin/users/${userId}/permissions`, payload);
- dispatch(loadAdminUserPage(userId));
- };
- }
- export function loadUserOrgs(userId: number): ThunkResult<void> {
- return async (dispatch) => {
- const orgs = await getBackendSrv().get(`/api/users/${userId}/orgs`);
- dispatch(userOrgsLoadedAction(orgs));
- };
- }
- export function addOrgUser(user: UserDTO, orgId: number, role: string): ThunkResult<void> {
- return async (dispatch) => {
- const payload = {
- loginOrEmail: user.login,
- role: role,
- };
- await getBackendSrv().post(`/api/orgs/${orgId}/users/`, payload);
- dispatch(loadAdminUserPage(user.id));
- };
- }
- export function updateOrgUserRole(userId: number, orgId: number, role: string): ThunkResult<void> {
- return async (dispatch) => {
- const payload = { role };
- await getBackendSrv().patch(`/api/orgs/${orgId}/users/${userId}`, payload);
- dispatch(loadAdminUserPage(userId));
- };
- }
- export function deleteOrgUser(userId: number, orgId: number): ThunkResult<void> {
- return async (dispatch) => {
- await getBackendSrv().delete(`/api/orgs/${orgId}/users/${userId}`);
- dispatch(loadAdminUserPage(userId));
- };
- }
- export function loadUserSessions(userId: number): ThunkResult<void> {
- return async (dispatch) => {
- if (!contextSrv.hasPermission(AccessControlAction.UsersAuthTokenList)) {
- return;
- }
- const tokens = await getBackendSrv().get(`/api/admin/users/${userId}/auth-tokens`);
- tokens.reverse();
- const sessions = tokens.map((session: UserSession) => {
- return {
- id: session.id,
- isActive: session.isActive,
- seenAt: dateTimeFormatTimeAgo(session.seenAt),
- createdAt: session.createdAt,
- clientIp: session.clientIp,
- browser: session.browser,
- browserVersion: session.browserVersion,
- os: session.os,
- osVersion: session.osVersion,
- device: session.device,
- };
- });
- dispatch(userSessionsLoadedAction(sessions));
- };
- }
- export function revokeSession(tokenId: number, userId: number): ThunkResult<void> {
- return async (dispatch) => {
- const payload = { authTokenId: tokenId };
- await getBackendSrv().post(`/api/admin/users/${userId}/revoke-auth-token`, payload);
- dispatch(loadUserSessions(userId));
- };
- }
- export function revokeAllSessions(userId: number): ThunkResult<void> {
- return async (dispatch) => {
- await getBackendSrv().post(`/api/admin/users/${userId}/logout`);
- dispatch(loadUserSessions(userId));
- };
- }
- // LDAP user actions
- export function loadLdapSyncStatus(): ThunkResult<void> {
- return async (dispatch) => {
- // Available only in enterprise
- const canReadLDAPStatus = contextSrv.hasPermission(AccessControlAction.LDAPStatusRead);
- if (featureEnabled('ldapsync') && canReadLDAPStatus) {
- const syncStatus = await getBackendSrv().get(`/api/admin/ldap-sync-status`);
- dispatch(ldapSyncStatusLoadedAction(syncStatus));
- }
- };
- }
- export function syncLdapUser(userId: number): ThunkResult<void> {
- return async (dispatch) => {
- await getBackendSrv().post(`/api/admin/ldap/sync/${userId}`);
- dispatch(loadAdminUserPage(userId));
- };
- }
- // LDAP debug page
- export function loadLdapState(): ThunkResult<void> {
- return async (dispatch) => {
- if (!contextSrv.hasPermission(AccessControlAction.LDAPStatusRead)) {
- return;
- }
- try {
- const connectionInfo = await getBackendSrv().get(`/api/admin/ldap/status`);
- dispatch(ldapConnectionInfoLoadedAction(connectionInfo));
- } catch (error) {
- error.isHandled = true;
- const ldapError = {
- title: error.data.message,
- body: error.data.error,
- };
- dispatch(ldapFailedAction(ldapError));
- }
- };
- }
- export function loadUserMapping(username: string): ThunkResult<void> {
- return async (dispatch) => {
- try {
- const response = await getBackendSrv().get(`/api/admin/ldap/${encodeURIComponent(username)}`);
- const { name, surname, email, login, isGrafanaAdmin, isDisabled, roles, teams } = response;
- const userInfo: LdapUser = {
- info: { name, surname, email, login },
- permissions: { isGrafanaAdmin, isDisabled },
- roles,
- teams,
- };
- dispatch(userMappingInfoLoadedAction(userInfo));
- } catch (error) {
- error.isHandled = true;
- const userError = {
- title: error.data.message,
- body: error.data.error,
- };
- dispatch(clearUserMappingInfoAction());
- dispatch(userMappingInfoFailedAction(userError));
- }
- };
- }
- export function clearUserError(): ThunkResult<void> {
- return (dispatch) => {
- dispatch(clearUserErrorAction());
- };
- }
- export function clearUserMappingInfo(): ThunkResult<void> {
- return (dispatch) => {
- dispatch(clearUserErrorAction());
- dispatch(clearUserMappingInfoAction());
- };
- }
- // UserListAdminPage
- const getFilters = (filters: UserFilter[]) => {
- return filters
- .map((filter) => {
- if (Array.isArray(filter.value)) {
- return filter.value.map((v) => `${filter.name}=${v.value}`).join('&');
- }
- return `${filter.name}=${filter.value}`;
- })
- .join('&');
- };
- export function fetchUsers(): ThunkResult<void> {
- return async (dispatch, getState) => {
- try {
- const { perPage, page, query, filters } = getState().userListAdmin;
- const result = await getBackendSrv().get(
- `/api/users/search?perpage=${perPage}&page=${page}&query=${query}&${getFilters(filters)}`
- );
- dispatch(usersFetched(result));
- } catch (error) {
- usersFetchEnd();
- console.error(error);
- }
- };
- }
- const fetchUsersWithDebounce = debounce((dispatch) => dispatch(fetchUsers()), 500);
- export function changeQuery(query: string): ThunkResult<void> {
- return async (dispatch) => {
- dispatch(usersFetchBegin());
- dispatch(queryChanged(query));
- fetchUsersWithDebounce(dispatch);
- };
- }
- export function changeFilter(filter: UserFilter): ThunkResult<void> {
- return async (dispatch) => {
- dispatch(usersFetchBegin());
- dispatch(filterChanged(filter));
- fetchUsersWithDebounce(dispatch);
- };
- }
- export function changePage(page: number): ThunkResult<void> {
- return async (dispatch) => {
- dispatch(usersFetchBegin());
- dispatch(pageChanged(page));
- dispatch(fetchUsers());
- };
- }
|