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
JavaScript
"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,
};