UNPKG

mattermost-redux

Version:

Common code (API client, Redux stores, logic, utility functions) for building a Mattermost client

1,336 lines (1,335 loc) 48.3 kB
"use strict"; // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. Object.defineProperty(exports, "__esModule", { value: true }); exports.ProfilesInChannelSortBy = exports.maxUserIdsPerStatusesRequest = exports.maxUserIdsPerProfilesRequest = void 0; exports.generateMfaSecret = generateMfaSecret; exports.createUser = createUser; exports.loadMe = loadMe; exports.logout = logout; exports.getTotalUsersStats = getTotalUsersStats; exports.getFilteredUsersStats = getFilteredUsersStats; exports.getProfiles = getProfiles; exports.getMissingProfilesByIds = getMissingProfilesByIds; exports.getMissingProfilesByUsernames = getMissingProfilesByUsernames; exports.getProfilesByIds = getProfilesByIds; exports.getProfilesByUsernames = getProfilesByUsernames; exports.getProfilesInTeam = getProfilesInTeam; exports.getProfilesNotInTeam = getProfilesNotInTeam; exports.getProfilesInChannel = getProfilesInChannel; exports.batchGetProfilesInChannel = batchGetProfilesInChannel; exports.getProfilesInGroupChannels = getProfilesInGroupChannels; exports.getProfilesNotInChannel = getProfilesNotInChannel; exports.getMe = getMe; exports.getCustomProfileAttributeValues = getCustomProfileAttributeValues; exports.updateMyTermsOfServiceStatus = updateMyTermsOfServiceStatus; exports.getProfilesInGroup = getProfilesInGroup; exports.getProfilesNotInGroup = getProfilesNotInGroup; exports.getTermsOfService = getTermsOfService; exports.promoteGuestToUser = promoteGuestToUser; exports.demoteUserToGuest = demoteUserToGuest; exports.createTermsOfService = createTermsOfService; exports.getUser = getUser; exports.getUserByUsername = getUserByUsername; exports.getUserByEmail = getUserByEmail; exports.canUserDirectMessage = canUserDirectMessage; exports.getStatusesByIds = getStatusesByIds; exports.setStatus = setStatus; exports.setCustomStatus = setCustomStatus; exports.unsetCustomStatus = unsetCustomStatus; exports.removeRecentCustomStatus = removeRecentCustomStatus; exports.getSessions = getSessions; exports.revokeSession = revokeSession; exports.revokeAllSessionsForUser = revokeAllSessionsForUser; exports.revokeSessionsForAllUsers = revokeSessionsForAllUsers; exports.getUserAudits = getUserAudits; exports.autocompleteUsers = autocompleteUsers; exports.searchProfiles = searchProfiles; exports.updateMe = updateMe; exports.saveCustomProfileAttribute = saveCustomProfileAttribute; exports.patchUser = patchUser; exports.updateUserRoles = updateUserRoles; exports.updateUserMfa = updateUserMfa; exports.updateUserPassword = updateUserPassword; exports.resetFailedAttempts = resetFailedAttempts; exports.updateUserActive = updateUserActive; exports.verifyUserEmail = verifyUserEmail; exports.sendVerificationEmail = sendVerificationEmail; exports.resetUserPassword = resetUserPassword; exports.sendPasswordResetEmail = sendPasswordResetEmail; exports.setDefaultProfileImage = setDefaultProfileImage; exports.uploadProfileImage = uploadProfileImage; exports.switchEmailToOAuth = switchEmailToOAuth; exports.switchOAuthToEmail = switchOAuthToEmail; exports.switchEmailToLdap = switchEmailToLdap; exports.switchLdapToEmail = switchLdapToEmail; exports.createUserAccessToken = createUserAccessToken; exports.getUserAccessToken = getUserAccessToken; exports.getUserAccessTokensForUser = getUserAccessTokensForUser; exports.revokeUserAccessToken = revokeUserAccessToken; exports.disableUserAccessToken = disableUserAccessToken; exports.enableUserAccessToken = enableUserAccessToken; exports.getKnownUsers = getKnownUsers; exports.clearUserAccessTokens = clearUserAccessTokens; exports.checkForModifiedUsers = checkForModifiedUsers; const redux_batched_actions_1 = require("redux-batched-actions"); const action_types_1 = require("mattermost-redux/action_types"); const errors_1 = require("mattermost-redux/actions/errors"); const general_1 = require("mattermost-redux/actions/general"); const helpers_1 = require("mattermost-redux/actions/helpers"); const limits_1 = require("mattermost-redux/actions/limits"); const preferences_1 = require("mattermost-redux/actions/preferences"); const roles_1 = require("mattermost-redux/actions/roles"); const teams_1 = require("mattermost-redux/actions/teams"); const client_1 = require("mattermost-redux/client"); const constants_1 = require("mattermost-redux/constants"); const common_1 = require("mattermost-redux/selectors/entities/common"); const general_2 = require("mattermost-redux/selectors/entities/general"); const preferences_2 = require("mattermost-redux/selectors/entities/preferences"); const users_1 = require("mattermost-redux/selectors/entities/users"); const data_loader_1 = require("mattermost-redux/utils/data_loader"); const helpers_2 = require("mattermost-redux/utils/helpers"); // Delay requests for missing profiles for up to 100ms to allow for simulataneous requests to be batched const missingProfilesWait = 100; exports.maxUserIdsPerProfilesRequest = 100; // users ids per 'users/ids' request exports.maxUserIdsPerStatusesRequest = 200; // users ids per 'users/status/ids'request function generateMfaSecret(userId) { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.generateMfaSecret, params: [ userId, ], }); } function createUser(user, token, inviteId, redirect) { return async (dispatch, getState) => { let created; try { created = await client_1.Client4.createUser(user, token, inviteId, redirect); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } const profiles = { [created.id]: created, }; dispatch({ type: action_types_1.UserTypes.RECEIVED_PROFILES, data: profiles }); return { data: created }; }; } function loadMe() { return async (dispatch, getState) => { // Sometimes the server version is set in one or the other const serverVersion = getState().entities.general.serverVersion || client_1.Client4.getServerVersion(); dispatch((0, general_1.setServerVersion)(serverVersion)); try { await Promise.all([ dispatch((0, general_1.getClientConfig)()), dispatch((0, general_1.getLicenseConfig)()), dispatch(getMe()), dispatch((0, preferences_1.getMyPreferences)()), dispatch((0, teams_1.getMyTeams)()), dispatch((0, teams_1.getMyTeamMembers)()), ]); const isCollapsedThreads = (0, preferences_2.isCollapsedThreadsEnabled)(getState()); await dispatch((0, teams_1.getMyTeamUnreads)(isCollapsedThreads)); await dispatch((0, limits_1.getServerLimits)()); } catch (error) { dispatch((0, errors_1.logError)(error)); return { error: error }; } return { data: true }; }; } function logout() { return async (dispatch) => { dispatch({ type: action_types_1.UserTypes.LOGOUT_REQUEST, data: null }); try { await client_1.Client4.logout(); } catch (error) { // nothing to do here } dispatch({ type: action_types_1.UserTypes.LOGOUT_SUCCESS, data: null }); return { data: true }; }; } function getTotalUsersStats() { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.getTotalUsersStats, onSuccess: action_types_1.UserTypes.RECEIVED_USER_STATS, }); } function getFilteredUsersStats(options = {}, updateGlobalState = true) { return async (dispatch, getState) => { let stats; try { stats = await client_1.Client4.getFilteredUsersStats(options); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } if (updateGlobalState) { dispatch({ type: action_types_1.UserTypes.RECEIVED_FILTERED_USER_STATS, data: stats, }); } return { data: stats }; }; } function getProfiles(page = 0, perPage = constants_1.General.PROFILE_CHUNK_SIZE, options = {}) { return async (dispatch, getState) => { let profiles; try { profiles = await client_1.Client4.getProfiles(page, perPage, options); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } dispatch({ type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST, data: profiles, }); return { data: profiles }; }; } function getMissingProfilesByIds(userIds) { return async (dispatch, getState, { loaders }) => { if (!loaders.missingStatusLoader) { loaders.missingStatusLoader = new data_loader_1.DelayedDataLoader({ fetchBatch: (userIds) => dispatch(getStatusesByIds(userIds)), maxBatchSize: exports.maxUserIdsPerProfilesRequest, wait: missingProfilesWait, }); } if (!loaders.missingProfileLoader) { loaders.missingProfileLoader = new data_loader_1.DelayedDataLoader({ fetchBatch: (userIds) => dispatch(getProfilesByIds(userIds)), maxBatchSize: exports.maxUserIdsPerProfilesRequest, wait: missingProfilesWait, }); } const state = getState(); const missingIds = userIds.filter((id) => !(0, users_1.getUser)(state, id)); if (missingIds.length > 0) { if ((0, common_1.getIsUserStatusesConfigEnabled)(state)) { loaders.missingStatusLoader.queue(missingIds); } await loaders.missingProfileLoader.queueAndWait(missingIds); } return { data: missingIds, }; }; } function getMissingProfilesByUsernames(usernames) { return async (dispatch, getState, { loaders }) => { if (!loaders.userByUsernameLoader) { loaders.userByUsernameLoader = new data_loader_1.DelayedDataLoader({ fetchBatch: (usernames) => dispatch(getProfilesByUsernames(usernames)), maxBatchSize: exports.maxUserIdsPerProfilesRequest, wait: missingProfilesWait, }); } const usersByUsername = (0, users_1.getUsersByUsername)(getState()); const missingUsernames = usernames.filter((username) => !usersByUsername[username]); if (missingUsernames.length > 0) { await loaders.userByUsernameLoader.queueAndWait(missingUsernames); } return { data: missingUsernames }; }; } function getProfilesByIds(userIds, options) { return async (dispatch, getState) => { let profiles; try { profiles = await client_1.Client4.getProfilesByIds(userIds, options); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } dispatch({ type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST, data: profiles, }); return { data: profiles }; }; } function getProfilesByUsernames(usernames) { return async (dispatch, getState) => { let profiles; try { profiles = await client_1.Client4.getProfilesByUsernames(usernames); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } dispatch({ type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST, data: profiles, }); return { data: profiles }; }; } function getProfilesInTeam(teamId, page, perPage = constants_1.General.PROFILE_CHUNK_SIZE, sort = '', options = {}) { return async (dispatch, getState) => { let profiles; try { profiles = await client_1.Client4.getProfilesInTeam(teamId, page, perPage, sort, options); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } dispatch((0, redux_batched_actions_1.batchActions)([ { type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST_IN_TEAM, data: profiles, id: teamId, }, { type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST, data: profiles, }, ])); return { data: profiles }; }; } function getProfilesNotInTeam(teamId, groupConstrained, page, perPage = constants_1.General.PROFILE_CHUNK_SIZE) { return async (dispatch, getState) => { let profiles; try { profiles = await client_1.Client4.getProfilesNotInTeam(teamId, groupConstrained, page, perPage); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } const receivedProfilesListActionType = groupConstrained ? action_types_1.UserTypes.RECEIVED_PROFILES_LIST_NOT_IN_TEAM_AND_REPLACE : action_types_1.UserTypes.RECEIVED_PROFILES_LIST_NOT_IN_TEAM; dispatch((0, redux_batched_actions_1.batchActions)([ { type: receivedProfilesListActionType, data: profiles, id: teamId, }, { type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST, data: profiles, }, ])); return { data: profiles }; }; } var ProfilesInChannelSortBy; (function (ProfilesInChannelSortBy) { ProfilesInChannelSortBy["None"] = ""; ProfilesInChannelSortBy["Admin"] = "admin"; })(ProfilesInChannelSortBy || (exports.ProfilesInChannelSortBy = ProfilesInChannelSortBy = {})); function getProfilesInChannel(channelId, page, perPage = constants_1.General.PROFILE_CHUNK_SIZE, sort = '', options = {}) { return async (dispatch, getState) => { let profiles; try { profiles = await client_1.Client4.getProfilesInChannel(channelId, page, perPage, sort, options); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } dispatch((0, redux_batched_actions_1.batchActions)([ { type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST_IN_CHANNEL, data: profiles, id: channelId, }, { type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST, data: profiles, }, ])); return { data: profiles }; }; } function batchGetProfilesInChannel(channelId) { return async (dispatch, getState, { loaders }) => { if (!loaders.profilesInChannelLoader) { loaders.profilesInChannelLoader = new data_loader_1.DelayedDataLoader({ fetchBatch: (channelIds) => dispatch(getProfilesInChannel(channelIds[0], 0)), maxBatchSize: 1, wait: missingProfilesWait, }); } await loaders.profilesInChannelLoader.queueAndWait([channelId]); return {}; }; } function getProfilesInGroupChannels(channelsIds) { return async (dispatch, getState) => { let channelProfiles; try { channelProfiles = await client_1.Client4.getProfilesInGroupChannels(channelsIds.slice(0, constants_1.General.MAX_GROUP_CHANNELS_FOR_PROFILES)); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } const actions = []; for (const channelId in channelProfiles) { if (Object.hasOwn(channelProfiles, channelId)) { const profiles = channelProfiles[channelId]; actions.push({ type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST_IN_CHANNEL, data: profiles, id: channelId, }, { type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST, data: profiles, }); } } dispatch((0, redux_batched_actions_1.batchActions)(actions)); return { data: channelProfiles }; }; } function getProfilesNotInChannel(teamId, channelId, groupConstrained, page, perPage = constants_1.General.PROFILE_CHUNK_SIZE, cursorId = '') { return async (dispatch, getState) => { let profiles; try { profiles = await client_1.Client4.getProfilesNotInChannel(teamId, channelId, groupConstrained, page, perPage, cursorId); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } const receivedProfilesListActionType = groupConstrained ? action_types_1.UserTypes.RECEIVED_PROFILES_LIST_NOT_IN_CHANNEL_AND_REPLACE : action_types_1.UserTypes.RECEIVED_PROFILES_LIST_NOT_IN_CHANNEL; dispatch((0, redux_batched_actions_1.batchActions)([ { type: receivedProfilesListActionType, data: profiles, id: channelId, }, { type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST, data: profiles, }, ])); return { data: profiles }; }; } function getMe() { return async (dispatch) => { const getMeFunc = (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.getMe, onSuccess: action_types_1.UserTypes.RECEIVED_ME, }); const me = await dispatch(getMeFunc); if ('error' in me) { return me; } if ('data' in me) { dispatch((0, roles_1.loadRolesIfNeeded)(me.data.roles.split(' '))); } return me; }; } function getCustomProfileAttributeValues(userID) { return async (dispatch) => { let data; try { data = await client_1.Client4.getUserCustomProfileAttributesValues(userID); } catch (error) { return { error }; } dispatch({ type: action_types_1.UserTypes.RECEIVED_CPA_VALUES, data: { userID, customAttributeValues: data }, }); return { data }; }; } function updateMyTermsOfServiceStatus(termsOfServiceId, accepted) { return async (dispatch, getState) => { const response = await dispatch((0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.updateMyTermsOfServiceStatus, params: [ termsOfServiceId, accepted, ], })); if ('data' in response) { if (accepted) { dispatch({ type: action_types_1.UserTypes.RECEIVED_TERMS_OF_SERVICE_STATUS, data: { terms_of_service_create_at: new Date().getTime(), terms_of_service_id: accepted ? termsOfServiceId : null, user_id: (0, users_1.getCurrentUserId)(getState()), }, }); } return { data: response.data, }; } return { error: response.error, }; }; } function getProfilesInGroup(groupId, page = 0, perPage = constants_1.General.PROFILE_CHUNK_SIZE, sort = '') { return async (dispatch, getState) => { let profiles; try { profiles = await client_1.Client4.getProfilesInGroup(groupId, page, perPage, sort); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } dispatch((0, redux_batched_actions_1.batchActions)([ { type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST_IN_GROUP, data: profiles, id: groupId, }, { type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST, data: profiles, }, ])); return { data: profiles }; }; } function getProfilesNotInGroup(groupId, page = 0, perPage = constants_1.General.PROFILE_CHUNK_SIZE) { return async (dispatch, getState) => { let profiles; try { profiles = await client_1.Client4.getProfilesNotInGroup(groupId, page, perPage); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } dispatch((0, redux_batched_actions_1.batchActions)([ { type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST_NOT_IN_GROUP, data: profiles, id: groupId, }, { type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST, data: profiles, }, ])); return { data: profiles }; }; } function getTermsOfService() { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.getTermsOfService, }); } function promoteGuestToUser(userId) { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.promoteGuestToUser, params: [userId], }); } function demoteUserToGuest(userId) { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.demoteUserToGuest, params: [userId], }); } function createTermsOfService(text) { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.createTermsOfService, params: [ text, ], }); } function getUser(id) { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.getUser, onSuccess: action_types_1.UserTypes.RECEIVED_PROFILE, params: [ id, ], }); } function getUserByUsername(username) { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.getUserByUsername, onSuccess: action_types_1.UserTypes.RECEIVED_PROFILE, params: [ username, ], }); } function getUserByEmail(email) { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.getUserByEmail, onSuccess: action_types_1.UserTypes.RECEIVED_PROFILE, params: [ email, ], }); } function canUserDirectMessage(userId, otherUserId) { return async (dispatch, getState) => { try { const result = await client_1.Client4.canUserDirectMessage(userId, otherUserId); return { data: result }; } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } }; } function getStatusesByIds(userIds) { return async (dispatch, getState) => { if (!userIds || userIds.length === 0) { return { data: [] }; } let receivedStatuses; try { receivedStatuses = await client_1.Client4.getStatusesByIds(userIds); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } const statuses = {}; const dndEndTimes = {}; const isManualStatuses = {}; const lastActivity = {}; for (const receivedStatus of receivedStatuses) { statuses[receivedStatus.user_id] = receivedStatus?.status ?? ''; dndEndTimes[receivedStatus.user_id] = receivedStatus?.dnd_end_time ?? 0; isManualStatuses[receivedStatus.user_id] = receivedStatus?.manual ?? false; lastActivity[receivedStatus.user_id] = receivedStatus?.last_activity_at ?? 0; } dispatch((0, redux_batched_actions_1.batchActions)([ { type: action_types_1.UserTypes.RECEIVED_STATUSES, data: statuses, }, { type: action_types_1.UserTypes.RECEIVED_DND_END_TIMES, data: dndEndTimes, }, { type: action_types_1.UserTypes.RECEIVED_STATUSES_IS_MANUAL, data: isManualStatuses, }, { type: action_types_1.UserTypes.RECEIVED_LAST_ACTIVITIES, data: lastActivity, }, ], 'BATCHING_STATUSES')); return { data: receivedStatuses }; }; } function setStatus(status) { return async (dispatch, getState) => { let recievedStatus; try { recievedStatus = await client_1.Client4.updateStatus(status); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } const updatedStatus = { [recievedStatus.user_id]: recievedStatus.status }; const dndEndTimes = { [recievedStatus.user_id]: recievedStatus?.dnd_end_time ?? 0 }; const isManualStatus = { [recievedStatus.user_id]: recievedStatus?.manual ?? false }; const lastActivity = { [recievedStatus.user_id]: recievedStatus?.last_activity_at ?? 0 }; dispatch((0, redux_batched_actions_1.batchActions)([ { type: action_types_1.UserTypes.RECEIVED_STATUSES, data: updatedStatus, }, { type: action_types_1.UserTypes.RECEIVED_DND_END_TIMES, data: dndEndTimes, }, { type: action_types_1.UserTypes.RECEIVED_STATUSES_IS_MANUAL, data: isManualStatus, }, { type: action_types_1.UserTypes.RECEIVED_LAST_ACTIVITIES, data: lastActivity, }, ], 'BATCHING_STATUS')); return { data: recievedStatus }; }; } function setCustomStatus(customStatus) { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.updateCustomStatus, params: [ customStatus, ], }); } function unsetCustomStatus() { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.unsetCustomStatus, }); } function removeRecentCustomStatus(customStatus) { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.removeRecentCustomStatus, params: [ customStatus, ], }); } function getSessions(userId) { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.getSessions, onSuccess: action_types_1.UserTypes.RECEIVED_SESSIONS, params: [ userId, ], }); } function revokeSession(userId, sessionId) { return async (dispatch, getState) => { try { await client_1.Client4.revokeSession(userId, sessionId); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } dispatch({ type: action_types_1.UserTypes.RECEIVED_REVOKED_SESSION, sessionId, data: null, }); return { data: true }; }; } function revokeAllSessionsForUser(userId) { return async (dispatch, getState) => { try { await client_1.Client4.revokeAllSessionsForUser(userId); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } const data = { isCurrentUser: userId === (0, users_1.getCurrentUserId)(getState()) }; dispatch((0, redux_batched_actions_1.batchActions)([ { type: action_types_1.UserTypes.REVOKE_ALL_USER_SESSIONS_SUCCESS, data, }, ])); return { data: true }; }; } function revokeSessionsForAllUsers() { return async (dispatch, getState) => { try { await client_1.Client4.revokeSessionsForAllUsers(); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error: error }; } dispatch({ type: action_types_1.UserTypes.REVOKE_SESSIONS_FOR_ALL_USERS_SUCCESS, data: null, }); return { data: true }; }; } function getUserAudits(userId, page = 0, perPage = constants_1.General.AUDITS_CHUNK_SIZE) { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.getUserAudits, onSuccess: action_types_1.UserTypes.RECEIVED_AUDITS, params: [ userId, page, perPage, ], }); } function autocompleteUsers(term, teamId = '', channelId = '', options) { return async (dispatch, getState) => { dispatch({ type: action_types_1.UserTypes.AUTOCOMPLETE_USERS_REQUEST, data: null }); let data; try { data = await client_1.Client4.autocompleteUsers(term, teamId, channelId, options); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch({ type: action_types_1.UserTypes.AUTOCOMPLETE_USERS_FAILURE, error }); dispatch((0, errors_1.logError)(error)); return { error }; } let users = [...data.users]; if (data.out_of_channel) { users = [...users, ...data.out_of_channel]; } const actions = [{ type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST, data: users, }, { type: action_types_1.UserTypes.AUTOCOMPLETE_USERS_SUCCESS, }]; if (channelId) { actions.push({ type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST_IN_CHANNEL, data: data.users, id: channelId, }); actions.push({ type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST_NOT_IN_CHANNEL, data: data.out_of_channel || [], id: channelId, }); } if (teamId) { actions.push({ type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST_IN_TEAM, data: users, id: teamId, }); } dispatch((0, redux_batched_actions_1.batchActions)(actions)); return { data }; }; } function searchProfiles(term, options = {}) { return async (dispatch, getState) => { let profiles; try { profiles = await client_1.Client4.searchUsers(term, options); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } const actions = [{ type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST, data: profiles }]; if (options.in_channel_id) { actions.push({ type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST_IN_CHANNEL, data: profiles, id: options.in_channel_id, }); } if (options.not_in_channel_id) { actions.push({ type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST_NOT_IN_CHANNEL, data: profiles, id: options.not_in_channel_id, }); } if (options.team_id) { actions.push({ type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST_IN_TEAM, data: profiles, id: options.team_id, }); } if (options.not_in_team_id) { actions.push({ type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST_NOT_IN_TEAM, data: profiles, id: options.not_in_team_id, }); } if (options.in_group_id) { actions.push({ type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST_IN_GROUP, data: profiles, id: options.in_group_id, }); } if (options.not_in_group_id) { actions.push({ type: action_types_1.UserTypes.RECEIVED_PROFILES_LIST_NOT_IN_GROUP, data: profiles, id: options.not_in_group_id, }); } dispatch((0, redux_batched_actions_1.batchActions)(actions)); return { data: profiles }; }; } function updateMe(user) { return async (dispatch) => { dispatch({ type: action_types_1.UserTypes.UPDATE_ME_REQUEST, data: null }); let data; try { data = await client_1.Client4.patchMe(user); } catch (error) { dispatch({ type: action_types_1.UserTypes.UPDATE_ME_FAILURE, error }); dispatch((0, errors_1.logError)(error)); return { error }; } dispatch((0, redux_batched_actions_1.batchActions)([ { type: action_types_1.UserTypes.RECEIVED_ME, data }, { type: action_types_1.UserTypes.UPDATE_ME_SUCCESS }, ])); dispatch((0, roles_1.loadRolesIfNeeded)(data.roles.split(' '))); return { data }; }; } function saveCustomProfileAttribute(userID, attributeID, attributeValue) { return async (dispatch) => { try { const values = { [attributeID]: attributeValue || '' }; const data = await client_1.Client4.updateUserCustomProfileAttributesValues(userID, values); return { data }; } catch (error) { // Extract user-friendly error message from server response let errorMessage = 'Failed to update custom profile attribute'; if (error && typeof error === 'object' && 'message' in error && error.message) { errorMessage = error.message; } const serverError = { ...error, message: errorMessage, }; dispatch((0, errors_1.logError)(serverError)); return { error: serverError }; } }; } function patchUser(user) { return async (dispatch) => { let data; try { data = await client_1.Client4.patchUser(user); } catch (error) { dispatch((0, errors_1.logError)(error)); return { error }; } dispatch({ type: action_types_1.UserTypes.RECEIVED_PROFILE, data }); return { data }; }; } function updateUserRoles(userId, roles) { return async (dispatch, getState) => { try { await client_1.Client4.updateUserRoles(userId, roles); } catch (error) { return { error }; } const profile = getState().entities.users.profiles[userId]; if (profile) { dispatch({ type: action_types_1.UserTypes.RECEIVED_PROFILE, data: { ...profile, roles } }); } return { data: true }; }; } function updateUserMfa(userId, activate, code = '') { return async (dispatch, getState) => { try { await client_1.Client4.updateUserMfa(userId, activate, code); } catch (error) { dispatch((0, errors_1.logError)(error)); return { error }; } const profile = getState().entities.users.profiles[userId]; if (profile) { dispatch({ type: action_types_1.UserTypes.RECEIVED_PROFILE, data: { ...profile, mfa_active: activate } }); } return { data: true }; }; } function updateUserPassword(userId, currentPassword, newPassword) { return async (dispatch, getState) => { try { await client_1.Client4.updateUserPassword(userId, currentPassword, newPassword); } catch (error) { dispatch((0, errors_1.logError)(error)); return { error }; } const profile = getState().entities.users.profiles[userId]; if (profile) { dispatch({ type: action_types_1.UserTypes.RECEIVED_PROFILE, data: { ...profile, last_password_update: new Date().getTime() } }); } return { data: true }; }; } function resetFailedAttempts(userId) { return async (dispatch, getState) => { try { await client_1.Client4.resetFailedAttempts(userId); } catch (error) { dispatch((0, errors_1.logError)(error)); return { error }; } const profile = getState().entities.users.profiles[userId]; if (profile) { dispatch({ type: action_types_1.UserTypes.RECEIVED_PROFILE, data: { ...profile, failed_attempts: 0 } }); } return { data: true }; }; } function updateUserActive(userId, active) { return async (dispatch, getState) => { try { await client_1.Client4.updateUserActive(userId, active); } catch (error) { dispatch((0, errors_1.logError)(error)); return { error }; } const profile = getState().entities.users.profiles[userId]; if (profile) { const deleteAt = active ? 0 : new Date().getTime(); dispatch({ type: action_types_1.UserTypes.RECEIVED_PROFILE, data: { ...profile, delete_at: deleteAt } }); } return { data: true }; }; } function verifyUserEmail(token) { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.verifyUserEmail, params: [ token, ], }); } function sendVerificationEmail(email) { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.sendVerificationEmail, params: [ email, ], }); } function resetUserPassword(token, newPassword) { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.resetUserPassword, params: [ token, newPassword, ], }); } function sendPasswordResetEmail(email) { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.sendPasswordResetEmail, params: [ email, ], }); } function setDefaultProfileImage(userId) { return async (dispatch, getState) => { try { await client_1.Client4.setDefaultProfileImage(userId); } catch (error) { dispatch((0, errors_1.logError)(error)); return { error }; } const profile = getState().entities.users.profiles[userId]; if (profile) { dispatch({ type: action_types_1.UserTypes.RECEIVED_PROFILE, data: { ...profile, last_picture_update: 0 } }); } return { data: true }; }; } function uploadProfileImage(userId, imageData) { return async (dispatch, getState) => { try { await client_1.Client4.uploadProfileImage(userId, imageData); } catch (error) { return { error }; } const profile = getState().entities.users.profiles[userId]; if (profile) { dispatch({ type: action_types_1.UserTypes.RECEIVED_PROFILE, data: { ...profile, last_picture_update: new Date().getTime() } }); } return { data: true }; }; } function switchEmailToOAuth(service, email, password, mfaCode = '') { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.switchEmailToOAuth, params: [ service, email, password, mfaCode, ], }); } function switchOAuthToEmail(currentService, email, password) { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.switchOAuthToEmail, params: [ currentService, email, password, ], }); } function switchEmailToLdap(email, emailPassword, ldapId, ldapPassword, mfaCode = '') { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.switchEmailToLdap, params: [ email, emailPassword, ldapId, ldapPassword, mfaCode, ], }); } function switchLdapToEmail(ldapPassword, email, emailPassword, mfaCode = '') { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.switchLdapToEmail, params: [ ldapPassword, email, emailPassword, mfaCode, ], }); } function createUserAccessToken(userId, description) { return async (dispatch, getState) => { let data; try { data = await client_1.Client4.createUserAccessToken(userId, description); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } const actions = [{ type: action_types_1.AdminTypes.RECEIVED_USER_ACCESS_TOKEN, data: { ...data, token: '', }, }]; const { currentUserId } = getState().entities.users; if (userId === currentUserId) { actions.push({ type: action_types_1.UserTypes.RECEIVED_MY_USER_ACCESS_TOKEN, data: { ...data, token: '' }, }); } dispatch((0, redux_batched_actions_1.batchActions)(actions)); return { data }; }; } function getUserAccessToken(tokenId) { return async (dispatch, getState) => { let data; try { data = await client_1.Client4.getUserAccessToken(tokenId); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } const actions = [{ type: action_types_1.AdminTypes.RECEIVED_USER_ACCESS_TOKEN, data, }]; const { currentUserId } = getState().entities.users; if (data.user_id === currentUserId) { actions.push({ type: action_types_1.UserTypes.RECEIVED_MY_USER_ACCESS_TOKEN, data, }); } dispatch((0, redux_batched_actions_1.batchActions)(actions)); return { data }; }; } function getUserAccessTokensForUser(userId, page = 0, perPage = constants_1.General.PROFILE_CHUNK_SIZE) { return async (dispatch, getState) => { let data; try { data = await client_1.Client4.getUserAccessTokensForUser(userId, page, perPage); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } const actions = [{ type: action_types_1.AdminTypes.RECEIVED_USER_ACCESS_TOKENS_FOR_USER, data, userId, }]; const { currentUserId } = getState().entities.users; if (userId === currentUserId) { actions.push({ type: action_types_1.UserTypes.RECEIVED_MY_USER_ACCESS_TOKENS, data, }); } dispatch((0, redux_batched_actions_1.batchActions)(actions)); return { data }; }; } function revokeUserAccessToken(tokenId) { return async (dispatch, getState) => { try { await client_1.Client4.revokeUserAccessToken(tokenId); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } dispatch({ type: action_types_1.UserTypes.REVOKED_USER_ACCESS_TOKEN, data: tokenId, }); return { data: true }; }; } function disableUserAccessToken(tokenId) { return async (dispatch, getState) => { try { await client_1.Client4.disableUserAccessToken(tokenId); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } dispatch({ type: action_types_1.UserTypes.DISABLED_USER_ACCESS_TOKEN, data: tokenId, }); return { data: true }; }; } function enableUserAccessToken(tokenId) { return async (dispatch, getState) => { try { await client_1.Client4.enableUserAccessToken(tokenId); } catch (error) { (0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState); dispatch((0, errors_1.logError)(error)); return { error }; } dispatch({ type: action_types_1.UserTypes.ENABLED_USER_ACCESS_TOKEN, data: tokenId, }); return { data: true }; }; } function getKnownUsers() { return (0, helpers_1.bindClientFunc)({ clientFunc: client_1.Client4.getKnownUsers, }); } function clearUserAccessTokens() { return async (dispatch) => { dispatch({ type: action_types_1.UserTypes.CLEAR_MY_USER_ACCESS_TOKENS, data: null }); return { data: true }; }; } function checkForModifiedUsers() { return async (dispatch, getState) => { const state = getState(); const users = (0, users_1.getUsers)(state); const lastDisconnectAt = state.websocket.lastDisconnectAt; const serverVersion = (0, general_2.getServerVersion)(state); if (!(0, helpers_2.isMinimumServerVersion)(serverVersion, 5, 14)) { return { data: true }; } await dispatch(getProfilesByIds(Object.keys(users), { since: lastDisconnectAt })); return { data: true }; }; } exports.default = { generateMfaSecret, logout, getProfiles, getProfilesByIds, getProfilesInTeam, getProfilesInChannel, getProfilesNotInChannel, getUser, getMe, getUserByUsername, getStatusesByIds, getSessions, getTotalUsersStats, revokeSession, revokeAllSessionsForUser, revokeSessionsForAllUsers, getUserAudits, searchProfiles, updateMe, updateUserRoles, updateUserMfa, updateUserPassword, updateUserActive, verifyUserEmail, sendVerificationEmail, resetUserPassword, sendPasswordResetEmail, uploadProfileImage, switchEmailToOAuth, switchOAuthToEmail, switchEmailToLdap, switchLdapToEmail, getTermsOfService, createTermsOfService, updateMyTermsOfServiceStatus, createUserAccessToken, getUserAccessToken, getUserAccessTokensForUser, revokeUserAccessToken, disableUserAccessToken, enableUserAccessToken, checkForModifiedUsers, };