UNPKG

mattermost-redux

Version:

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

1,606 lines (1,305 loc) 116 kB
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. import {General} from '../constants'; import {ClusterInfo, AnalyticsRow} from 'types/admin'; import {Audit} from 'types/audits'; import {UserAutocomplete, AutocompleteSuggestion} from 'types/autocomplete'; import {Bot, BotPatch} from 'types/bots'; import {Product, Subscription, CloudCustomer, Address, CloudCustomerPatch, Invoice, SubscriptionStats} from 'types/cloud'; import {ChannelCategory, OrderedChannelCategories} from 'types/channel_categories'; import { Channel, ChannelMemberCountsByGroup, ChannelMembership, ChannelModeration, ChannelModerationPatch, ChannelStats, ChannelsWithTotalCount, ChannelUnread, ChannelViewResponse, ChannelWithTeamData, ChannelSearchOpts, } from 'types/channels'; import {Options, StatusOK, ClientResponse} from 'types/client4'; import {Compliance} from 'types/compliance'; import { ClientConfig, ClientLicense, DataRetentionPolicy, License, AdminConfig, EnvironmentConfig, } from 'types/config'; import {CustomEmoji} from 'types/emojis'; import {ServerError} from 'types/errors'; import {FileInfo, FileUploadResponse} from 'types/files'; import { Group, GroupPatch, GroupSyncable, MixedUnlinkedGroup, SyncablePatch, UsersWithGroupsAndCount, GroupsWithCount, } from 'types/groups'; import {PostActionResponse} from 'types/integration_actions'; import { Command, CommandArgs, CommandResponse, DialogSubmission, IncomingWebhook, OAuthApp, OutgoingWebhook, SubmitDialogResponse, } from 'types/integrations'; import {Job} from 'types/jobs'; import {MfaSecret} from 'types/mfa'; import { ClientPluginManifest, MarketplacePlugin, PluginManifest, PluginsResponse, PluginStatus, } from 'types/plugins'; import {Post, PostList, PostSearchResults, OpenGraphMetadata} from 'types/posts'; import {PreferenceType} from 'types/preferences'; import {Reaction} from 'types/reactions'; import {Role} from 'types/roles'; import {SamlCertificateStatus, SamlMetadataResponse} from 'types/saml'; import {Scheme} from 'types/schemes'; import {Session} from 'types/sessions'; import { GetTeamMembersOpts, Team, TeamInviteWithError, TeamMembership, TeamMemberWithError, TeamStats, TeamsWithCount, TeamUnread, TeamSearchOpts, } from 'types/teams'; import {TermsOfService} from 'types/terms_of_service'; import { AuthChangeResponse, UserAccessToken, UserProfile, UsersStats, UserStatus, GetFilteredUsersStatsOpts, UserCustomStatus, } from 'types/users'; import {$ID, RelationOneToOne} from 'types/utilities'; import {ProductNotices} from 'types/product_notices'; import {buildQueryString, isMinimumServerVersion} from 'utils/helpers'; import {cleanUrlForLogging} from 'utils/sentry'; import {isSystemAdmin} from 'utils/user_utils'; import fetch from './fetch_etag'; import {TelemetryHandler} from './telemetry'; import {UserThreadList, UserThread} from 'types/threads'; const FormData = require('form-data'); const HEADER_AUTH = 'Authorization'; const HEADER_BEARER = 'BEARER'; const HEADER_REQUESTED_WITH = 'X-Requested-With'; const HEADER_USER_AGENT = 'User-Agent'; const HEADER_X_CLUSTER_ID = 'X-Cluster-Id'; const HEADER_X_CSRF_TOKEN = 'X-CSRF-Token'; export const HEADER_X_VERSION_ID = 'X-Version-Id'; const PER_PAGE_DEFAULT = 60; const LOGS_PER_PAGE_DEFAULT = 10000; export const DEFAULT_LIMIT_BEFORE = 30; export const DEFAULT_LIMIT_AFTER = 30; /* eslint-disable no-throw-literal */ export default class Client4 { logToConsole = false; serverVersion = ''; clusterId = ''; token = ''; csrf = ''; url = ''; urlVersion = '/api/v4'; userAgent: string|null = null; enableLogging = false; defaultHeaders: {[x: string]: string} = {}; userId = ''; diagnosticId = ''; includeCookies = true; translations = { connectionError: 'There appears to be a problem with your internet connection.', unknownError: 'We received an unexpected status code from the server.', }; userRoles?: string; telemetryHandler?: TelemetryHandler; getUrl() { return this.url; } getAbsoluteUrl(baseUrl: string) { if (typeof baseUrl !== 'string' || !baseUrl.startsWith('/')) { return baseUrl; } return this.getUrl() + baseUrl; } setUrl(url: string) { this.url = url; } setUserAgent(userAgent: string) { this.userAgent = userAgent; } getToken() { return this.token; } setToken(token: string) { this.token = token; } setCSRF(csrfToken: string) { this.csrf = csrfToken; } setAcceptLanguage(locale: string) { this.defaultHeaders['Accept-Language'] = locale; } setEnableLogging(enable: boolean) { this.enableLogging = enable; } setIncludeCookies(include: boolean) { this.includeCookies = include; } setUserId(userId: string) { this.userId = userId; } setUserRoles(roles: string) { this.userRoles = roles; } setDiagnosticId(diagnosticId: string) { this.diagnosticId = diagnosticId; } setTelemetryHandler(telemetryHandler?: TelemetryHandler) { this.telemetryHandler = telemetryHandler; } getServerVersion() { return this.serverVersion; } getUrlVersion() { return this.urlVersion; } getBaseRoute() { return `${this.url}${this.urlVersion}`; } getUsersRoute() { return `${this.getBaseRoute()}/users`; } getUserRoute(userId: string) { return `${this.getUsersRoute()}/${userId}`; } getTeamsRoute() { return `${this.getBaseRoute()}/teams`; } getTeamRoute(teamId: string) { return `${this.getTeamsRoute()}/${teamId}`; } getTeamSchemeRoute(teamId: string) { return `${this.getTeamRoute(teamId)}/scheme`; } getTeamNameRoute(teamName: string) { return `${this.getTeamsRoute()}/name/${teamName}`; } getTeamMembersRoute(teamId: string) { return `${this.getTeamRoute(teamId)}/members`; } getTeamMemberRoute(teamId: string, userId: string) { return `${this.getTeamMembersRoute(teamId)}/${userId}`; } getChannelsRoute() { return `${this.getBaseRoute()}/channels`; } getChannelRoute(channelId: string) { return `${this.getChannelsRoute()}/${channelId}`; } getChannelMembersRoute(channelId: string) { return `${this.getChannelRoute(channelId)}/members`; } getChannelMemberRoute(channelId: string, userId: string) { return `${this.getChannelMembersRoute(channelId)}/${userId}`; } getChannelSchemeRoute(channelId: string) { return `${this.getChannelRoute(channelId)}/scheme`; } getChannelCategoriesRoute(userId: string, teamId: string) { return `${this.getBaseRoute()}/users/${userId}/teams/${teamId}/channels/categories`; } getPostsRoute() { return `${this.getBaseRoute()}/posts`; } getPostRoute(postId: string) { return `${this.getPostsRoute()}/${postId}`; } getReactionsRoute() { return `${this.getBaseRoute()}/reactions`; } getCommandsRoute() { return `${this.getBaseRoute()}/commands`; } getFilesRoute() { return `${this.getBaseRoute()}/files`; } getFileRoute(fileId: string) { return `${this.getFilesRoute()}/${fileId}`; } getPreferencesRoute(userId: string) { return `${this.getUserRoute(userId)}/preferences`; } getIncomingHooksRoute() { return `${this.getBaseRoute()}/hooks/incoming`; } getIncomingHookRoute(hookId: string) { return `${this.getBaseRoute()}/hooks/incoming/${hookId}`; } getOutgoingHooksRoute() { return `${this.getBaseRoute()}/hooks/outgoing`; } getOutgoingHookRoute(hookId: string) { return `${this.getBaseRoute()}/hooks/outgoing/${hookId}`; } getOAuthRoute() { return `${this.url}/oauth`; } getOAuthAppsRoute() { return `${this.getBaseRoute()}/oauth/apps`; } getOAuthAppRoute(appId: string) { return `${this.getOAuthAppsRoute()}/${appId}`; } getEmojisRoute() { return `${this.getBaseRoute()}/emoji`; } getEmojiRoute(emojiId: string) { return `${this.getEmojisRoute()}/${emojiId}`; } getBrandRoute() { return `${this.getBaseRoute()}/brand`; } getBrandImageUrl(timestamp: string) { return `${this.getBrandRoute()}/image?t=${timestamp}`; } getDataRetentionRoute() { return `${this.getBaseRoute()}/data_retention`; } getJobsRoute() { return `${this.getBaseRoute()}/jobs`; } getPluginsRoute() { return `${this.getBaseRoute()}/plugins`; } getPluginRoute(pluginId: string) { return `${this.getPluginsRoute()}/${pluginId}`; } getPluginsMarketplaceRoute() { return `${this.getPluginsRoute()}/marketplace`; } getRolesRoute() { return `${this.getBaseRoute()}/roles`; } getTimezonesRoute() { return `${this.getBaseRoute()}/system/timezones`; } getSchemesRoute() { return `${this.getBaseRoute()}/schemes`; } getRedirectLocationRoute() { return `${this.getBaseRoute()}/redirect_location`; } getBotsRoute() { return `${this.getBaseRoute()}/bots`; } getBotRoute(botUserId: string) { return `${this.getBotsRoute()}/${botUserId}`; } getGroupsRoute() { return `${this.getBaseRoute()}/groups`; } getGroupRoute(groupID: string) { return `${this.getGroupsRoute()}/${groupID}`; } getNoticesRoute() { return `${this.getBaseRoute()}/system/notices`; } getCloudRoute() { return `${this.getBaseRoute()}/cloud`; } getUserThreadsRoute(userID: string, teamID: string): string { return `${this.getUserRoute(userID)}/teams/${teamID}/threads`; } getUserThreadRoute(userId: string, teamId: string, threadId: string): string { return `${this.getUserThreadsRoute(userId, teamId)}/${threadId}`; } getCSRFFromCookie() { if (typeof document !== 'undefined' && typeof document.cookie !== 'undefined') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.startsWith('MMCSRF=')) { return cookie.replace('MMCSRF=', ''); } } } return ''; } getOptions(options: Options) { const newOptions: Options = {...options}; const headers: {[x: string]: string} = { [HEADER_REQUESTED_WITH]: 'XMLHttpRequest', ...this.defaultHeaders, }; if (this.token) { headers[HEADER_AUTH] = `${HEADER_BEARER} ${this.token}`; } const csrfToken = this.csrf || this.getCSRFFromCookie(); if (options.method && options.method.toLowerCase() !== 'get' && csrfToken) { headers[HEADER_X_CSRF_TOKEN] = csrfToken; } if (this.includeCookies) { newOptions.credentials = 'include'; } if (this.userAgent) { headers[HEADER_USER_AGENT] = this.userAgent; } if (newOptions.headers) { Object.assign(headers, newOptions.headers); } return { ...newOptions, headers, }; } // User Routes createUser = (user: UserProfile, token: string, inviteId: string, redirect: string) => { this.trackEvent('api', 'api_users_create'); const queryParams: any = {}; if (token) { queryParams.t = token; } if (inviteId) { queryParams.iid = inviteId; } if (redirect) { queryParams.r = redirect; } return this.doFetch<UserProfile>( `${this.getUsersRoute()}${buildQueryString(queryParams)}`, {method: 'post', body: JSON.stringify(user)}, ); } patchMe = (userPatch: Partial<UserProfile>) => { return this.doFetch<UserProfile>( `${this.getUserRoute('me')}/patch`, {method: 'put', body: JSON.stringify(userPatch)}, ); } patchUser = (userPatch: Partial<UserProfile> & {id: string}) => { this.trackEvent('api', 'api_users_patch'); return this.doFetch<UserProfile>( `${this.getUserRoute(userPatch.id)}/patch`, {method: 'put', body: JSON.stringify(userPatch)}, ); } updateUser = (user: UserProfile) => { this.trackEvent('api', 'api_users_update'); return this.doFetch<UserProfile>( `${this.getUserRoute(user.id)}`, {method: 'put', body: JSON.stringify(user)}, ); } promoteGuestToUser = (userId: string) => { this.trackEvent('api', 'api_users_promote_guest_to_user'); return this.doFetch<StatusOK>( `${this.getUserRoute(userId)}/promote`, {method: 'post'}, ); } demoteUserToGuest = (userId: string) => { this.trackEvent('api', 'api_users_demote_user_to_guest'); return this.doFetch<StatusOK>( `${this.getUserRoute(userId)}/demote`, {method: 'post'}, ); } updateUserRoles = (userId: string, roles: string) => { this.trackEvent('api', 'api_users_update_roles'); return this.doFetch<StatusOK>( `${this.getUserRoute(userId)}/roles`, {method: 'put', body: JSON.stringify({roles})}, ); }; updateUserMfa = (userId: string, activate: boolean, code: string) => { const body: any = { activate, }; if (activate) { body.code = code; } return this.doFetch<StatusOK>( `${this.getUserRoute(userId)}/mfa`, {method: 'put', body: JSON.stringify(body)}, ); } updateUserPassword = (userId: string, currentPassword: string, newPassword: string) => { this.trackEvent('api', 'api_users_newpassword'); return this.doFetch<StatusOK>( `${this.getUserRoute(userId)}/password`, {method: 'put', body: JSON.stringify({current_password: currentPassword, new_password: newPassword})}, ); } resetUserPassword = (token: string, newPassword: string) => { this.trackEvent('api', 'api_users_reset_password'); return this.doFetch<StatusOK>( `${this.getUsersRoute()}/password/reset`, {method: 'post', body: JSON.stringify({token, new_password: newPassword})}, ); } getKnownUsers = () => { this.trackEvent('api', 'api_get_known_users'); return this.doFetch<Array<$ID<UserProfile>>>( `${this.getUsersRoute()}/known`, {method: 'get'}, ); } sendPasswordResetEmail = (email: string) => { this.trackEvent('api', 'api_users_send_password_reset'); return this.doFetch<StatusOK>( `${this.getUsersRoute()}/password/reset/send`, {method: 'post', body: JSON.stringify({email})}, ); } updateUserActive = (userId: string, active: boolean) => { this.trackEvent('api', 'api_users_update_active'); return this.doFetch<StatusOK>( `${this.getUserRoute(userId)}/active`, {method: 'put', body: JSON.stringify({active})}, ); } uploadProfileImage = (userId: string, imageData: File) => { this.trackEvent('api', 'api_users_update_profile_picture'); const formData = new FormData(); formData.append('image', imageData); const request: any = { method: 'post', body: formData, }; if (formData.getBoundary) { request.headers = { 'Content-Type': `multipart/form-data; boundary=${formData.getBoundary()}`, }; } return this.doFetch<StatusOK>( `${this.getUserRoute(userId)}/image`, request, ); }; setDefaultProfileImage = (userId: string) => { this.trackEvent('api', 'api_users_set_default_profile_picture'); return this.doFetch<StatusOK>( `${this.getUserRoute(userId)}/image`, {method: 'delete'}, ); }; verifyUserEmail = (token: string) => { return this.doFetch<StatusOK>( `${this.getUsersRoute()}/email/verify`, {method: 'post', body: JSON.stringify({token})}, ); } updateMyTermsOfServiceStatus = (termsOfServiceId: string, accepted: boolean) => { return this.doFetch<StatusOK>( `${this.getUserRoute('me')}/terms_of_service`, {method: 'post', body: JSON.stringify({termsOfServiceId, accepted})}, ); } getTermsOfService = () => { return this.doFetch<TermsOfService>( `${this.getBaseRoute()}/terms_of_service`, {method: 'get'}, ); } createTermsOfService = (text: string) => { return this.doFetch<TermsOfService>( `${this.getBaseRoute()}/terms_of_service`, {method: 'post', body: JSON.stringify({text})}, ); } sendVerificationEmail = (email: string) => { return this.doFetch<StatusOK>( `${this.getUsersRoute()}/email/verify/send`, {method: 'post', body: JSON.stringify({email})}, ); } login = (loginId: string, password: string, token = '', deviceId = '', ldapOnly = false) => { this.trackEvent('api', 'api_users_login'); if (ldapOnly) { this.trackEvent('api', 'api_users_login_ldap'); } const body: any = { device_id: deviceId, login_id: loginId, password, token, }; if (ldapOnly) { body.ldap_only = 'true'; } return this.doFetch<UserProfile>( `${this.getUsersRoute()}/login`, {method: 'post', body: JSON.stringify(body)}, ); }; loginById = (id: string, password: string, token = '', deviceId = '') => { this.trackEvent('api', 'api_users_login'); const body: any = { device_id: deviceId, id, password, token, }; return this.doFetch<UserProfile>( `${this.getUsersRoute()}/login`, {method: 'post', body: JSON.stringify(body)}, ); }; logout = async () => { this.trackEvent('api', 'api_users_logout'); const {response} = await this.doFetchWithResponse( `${this.getUsersRoute()}/logout`, {method: 'post'}, ); if (response.ok) { this.token = ''; } this.serverVersion = ''; return response; }; getProfiles = (page = 0, perPage = PER_PAGE_DEFAULT, options = {}) => { this.trackEvent('api', 'api_profiles_get'); return this.doFetch<UserProfile[]>( `${this.getUsersRoute()}${buildQueryString({page, per_page: perPage, ...options})}`, {method: 'get'}, ); }; getProfilesByIds = (userIds: string[], options = {}) => { this.trackEvent('api', 'api_profiles_get_by_ids'); return this.doFetch<UserProfile[]>( `${this.getUsersRoute()}/ids${buildQueryString(options)}`, {method: 'post', body: JSON.stringify(userIds)}, ); }; getProfilesByUsernames = (usernames: string[]) => { this.trackEvent('api', 'api_profiles_get_by_usernames'); return this.doFetch<UserProfile[]>( `${this.getUsersRoute()}/usernames`, {method: 'post', body: JSON.stringify(usernames)}, ); }; getProfilesInTeam = (teamId: string, page = 0, perPage = PER_PAGE_DEFAULT, sort = '', options = {}) => { this.trackEvent('api', 'api_profiles_get_in_team', {team_id: teamId, sort}); return this.doFetch<UserProfile[]>( `${this.getUsersRoute()}${buildQueryString({...options, in_team: teamId, page, per_page: perPage, sort})}`, {method: 'get'}, ); }; getProfilesNotInTeam = (teamId: string, groupConstrained: boolean, page = 0, perPage = PER_PAGE_DEFAULT) => { this.trackEvent('api', 'api_profiles_get_not_in_team', {team_id: teamId, group_constrained: groupConstrained}); const queryStringObj: any = {not_in_team: teamId, page, per_page: perPage}; if (groupConstrained) { queryStringObj.group_constrained = true; } return this.doFetch<UserProfile[]>( `${this.getUsersRoute()}${buildQueryString(queryStringObj)}`, {method: 'get'}, ); }; getProfilesWithoutTeam = (page = 0, perPage = PER_PAGE_DEFAULT, options = {}) => { this.trackEvent('api', 'api_profiles_get_without_team'); return this.doFetch<UserProfile[]>( `${this.getUsersRoute()}${buildQueryString({...options, without_team: 1, page, per_page: perPage})}`, {method: 'get'}, ); }; getProfilesInChannel = (channelId: string, page = 0, perPage = PER_PAGE_DEFAULT, sort = '', options: {active?: boolean} = {}) => { this.trackEvent('api', 'api_profiles_get_in_channel', {channel_id: channelId}); const serverVersion = this.getServerVersion(); let queryStringObj; if (isMinimumServerVersion(serverVersion, 4, 7)) { queryStringObj = {in_channel: channelId, page, per_page: perPage, sort}; } else { queryStringObj = {in_channel: channelId, page, per_page: perPage}; } return this.doFetch<UserProfile[]>( `${this.getUsersRoute()}${buildQueryString({...queryStringObj, ...options})}`, {method: 'get'}, ); }; getProfilesInGroupChannels = (channelsIds: string[]) => { this.trackEvent('api', 'api_profiles_get_in_group_channels', {channelsIds}); return this.doFetch<Record<string, UserProfile[]>>( `${this.getUsersRoute()}/group_channels`, {method: 'post', body: JSON.stringify(channelsIds)}, ); }; getProfilesNotInChannel = (teamId: string, channelId: string, groupConstrained: boolean, page = 0, perPage = PER_PAGE_DEFAULT) => { this.trackEvent('api', 'api_profiles_get_not_in_channel', {team_id: teamId, channel_id: channelId, group_constrained: groupConstrained}); const queryStringObj: any = {in_team: teamId, not_in_channel: channelId, page, per_page: perPage}; if (groupConstrained) { queryStringObj.group_constrained = true; } return this.doFetch<UserProfile[]>( `${this.getUsersRoute()}${buildQueryString(queryStringObj)}`, {method: 'get'}, ); }; getProfilesInGroup = (groupId: string, page = 0, perPage = PER_PAGE_DEFAULT) => { return this.doFetch<UserProfile[]>( `${this.getUsersRoute()}${buildQueryString({in_group: groupId, page, per_page: perPage})}`, {method: 'get'}, ); }; getMe = () => { return this.doFetch<UserProfile>( `${this.getUserRoute('me')}`, {method: 'get'}, ); }; getUser = (userId: string) => { return this.doFetch<UserProfile>( `${this.getUserRoute(userId)}`, {method: 'get'}, ); }; getUserByUsername = (username: string) => { return this.doFetch<UserProfile>( `${this.getUsersRoute()}/username/${username}`, {method: 'get'}, ); }; getUserByEmail = (email: string) => { return this.doFetch<UserProfile>( `${this.getUsersRoute()}/email/${email}`, {method: 'get'}, ); }; getProfilePictureUrl = (userId: string, lastPictureUpdate: number) => { const params: any = {}; if (lastPictureUpdate) { params._ = lastPictureUpdate; } return `${this.getUserRoute(userId)}/image${buildQueryString(params)}`; }; getDefaultProfilePictureUrl = (userId: string) => { return `${this.getUserRoute(userId)}/image/default`; }; autocompleteUsers = (name: string, teamId: string, channelId: string, options = { limit: General.AUTOCOMPLETE_LIMIT_DEFAULT, }) => { return this.doFetch<UserAutocomplete>(`${this.getUsersRoute()}/autocomplete${buildQueryString({ in_team: teamId, in_channel: channelId, name, limit: options.limit, })}`, { method: 'get', }); }; getSessions = (userId: string) => { return this.doFetch<Session[]>( `${this.getUserRoute(userId)}/sessions`, {method: 'get'}, ); }; revokeSession = (userId: string, sessionId: string) => { return this.doFetch<StatusOK>( `${this.getUserRoute(userId)}/sessions/revoke`, {method: 'post', body: JSON.stringify({session_id: sessionId})}, ); }; revokeAllSessionsForUser = (userId: string) => { return this.doFetch<StatusOK>( `${this.getUserRoute(userId)}/sessions/revoke/all`, {method: 'post'}, ); }; revokeSessionsForAllUsers = () => { return this.doFetch<StatusOK>( `${this.getUsersRoute()}/sessions/revoke/all`, {method: 'post'}, ); }; getUserAudits = (userId: string, page = 0, perPage = PER_PAGE_DEFAULT) => { return this.doFetch<Audit[]>( `${this.getUserRoute(userId)}/audits${buildQueryString({page, per_page: perPage})}`, {method: 'get'}, ); }; checkUserMfa = (loginId: string) => { return this.doFetch<{mfa_required: boolean}>( `${this.getUsersRoute()}/mfa`, {method: 'post', body: JSON.stringify({login_id: loginId})}, ); }; generateMfaSecret = (userId: string) => { return this.doFetch<MfaSecret>( `${this.getUserRoute(userId)}/mfa/generate`, {method: 'post'}, ); }; attachDevice = (deviceId: string) => { return this.doFetch<StatusOK>( `${this.getUsersRoute()}/sessions/device`, {method: 'put', body: JSON.stringify({device_id: deviceId})}, ); }; searchUsers = (term: string, options: any) => { this.trackEvent('api', 'api_search_users'); return this.doFetch<UserProfile[]>( `${this.getUsersRoute()}/search`, {method: 'post', body: JSON.stringify({term, ...options})}, ); }; getStatusesByIds = (userIds: string[]) => { return this.doFetch<UserStatus[]>( `${this.getUsersRoute()}/status/ids`, {method: 'post', body: JSON.stringify(userIds)}, ); }; getStatus = (userId: string) => { return this.doFetch<UserStatus>( `${this.getUserRoute(userId)}/status`, {method: 'get'}, ); }; updateStatus = (status: UserStatus) => { return this.doFetch<UserStatus>( `${this.getUserRoute(status.user_id)}/status`, {method: 'put', body: JSON.stringify(status)}, ); }; updateCustomStatus = (customStatus: UserCustomStatus) => { return this.doFetch( `${this.getUserRoute('me')}/status/custom`, {method: 'put', body: JSON.stringify(customStatus)}, ); }; unsetCustomStatus = () => { return this.doFetch( `${this.getUserRoute('me')}/status/custom`, {method: 'delete'}, ); } removeRecentCustomStatus = (customStatus: UserCustomStatus) => { return this.doFetch( `${this.getUserRoute('me')}/status/custom/recent`, {method: 'delete', body: JSON.stringify(customStatus)}, ); } switchEmailToOAuth = (service: string, email: string, password: string, mfaCode = '') => { this.trackEvent('api', 'api_users_email_to_oauth'); return this.doFetch<AuthChangeResponse>( `${this.getUsersRoute()}/login/switch`, {method: 'post', body: JSON.stringify({current_service: 'email', new_service: service, email, password, mfa_code: mfaCode})}, ); }; switchOAuthToEmail = (currentService: string, email: string, password: string) => { this.trackEvent('api', 'api_users_oauth_to_email'); return this.doFetch<AuthChangeResponse>( `${this.getUsersRoute()}/login/switch`, {method: 'post', body: JSON.stringify({current_service: currentService, new_service: 'email', email, new_password: password})}, ); }; switchEmailToLdap = (email: string, emailPassword: string, ldapId: string, ldapPassword: string, mfaCode = '') => { this.trackEvent('api', 'api_users_email_to_ldap'); return this.doFetch<AuthChangeResponse>( `${this.getUsersRoute()}/login/switch`, {method: 'post', body: JSON.stringify({current_service: 'email', new_service: 'ldap', email, password: emailPassword, ldap_id: ldapId, new_password: ldapPassword, mfa_code: mfaCode})}, ); }; switchLdapToEmail = (ldapPassword: string, email: string, emailPassword: string, mfaCode = '') => { this.trackEvent('api', 'api_users_ldap_to_email'); return this.doFetch<AuthChangeResponse>( `${this.getUsersRoute()}/login/switch`, {method: 'post', body: JSON.stringify({current_service: 'ldap', new_service: 'email', email, password: ldapPassword, new_password: emailPassword, mfa_code: mfaCode})}, ); }; getAuthorizedOAuthApps = (userId: string) => { return this.doFetch<OAuthApp[]>( `${this.getUserRoute(userId)}/oauth/apps/authorized`, {method: 'get'}, ); } authorizeOAuthApp = (responseType: string, clientId: string, redirectUri: string, state: string, scope: string) => { return this.doFetch<void>( `${this.url}/oauth/authorize`, {method: 'post', body: JSON.stringify({client_id: clientId, response_type: responseType, redirect_uri: redirectUri, state, scope})}, ); } deauthorizeOAuthApp = (clientId: string) => { return this.doFetch<StatusOK>( `${this.url}/oauth/deauthorize`, {method: 'post', body: JSON.stringify({client_id: clientId})}, ); } createUserAccessToken = (userId: string, description: string) => { this.trackEvent('api', 'api_users_create_access_token'); return this.doFetch<UserAccessToken>( `${this.getUserRoute(userId)}/tokens`, {method: 'post', body: JSON.stringify({description})}, ); } getUserAccessToken = (tokenId: string) => { return this.doFetch<UserAccessToken>( `${this.getUsersRoute()}/tokens/${tokenId}`, {method: 'get'}, ); } getUserAccessTokensForUser = (userId: string, page = 0, perPage = PER_PAGE_DEFAULT) => { return this.doFetch<UserAccessToken[]>( `${this.getUserRoute(userId)}/tokens${buildQueryString({page, per_page: perPage})}`, {method: 'get'}, ); } getUserAccessTokens = (page = 0, perPage = PER_PAGE_DEFAULT) => { return this.doFetch<UserAccessToken[]>( `${this.getUsersRoute()}/tokens${buildQueryString({page, per_page: perPage})}`, {method: 'get'}, ); } revokeUserAccessToken = (tokenId: string) => { this.trackEvent('api', 'api_users_revoke_access_token'); return this.doFetch<StatusOK>( `${this.getUsersRoute()}/tokens/revoke`, {method: 'post', body: JSON.stringify({token_id: tokenId})}, ); } disableUserAccessToken = (tokenId: string) => { return this.doFetch<StatusOK>( `${this.getUsersRoute()}/tokens/disable`, {method: 'post', body: JSON.stringify({token_id: tokenId})}, ); } enableUserAccessToken = (tokenId: string) => { return this.doFetch<StatusOK>( `${this.getUsersRoute()}/tokens/enable`, {method: 'post', body: JSON.stringify({token_id: tokenId})}, ); } // Team Routes createTeam = (team: Team) => { this.trackEvent('api', 'api_teams_create'); return this.doFetch<Team>( `${this.getTeamsRoute()}`, {method: 'post', body: JSON.stringify(team)}, ); }; deleteTeam = (teamId: string) => { this.trackEvent('api', 'api_teams_delete'); return this.doFetch<StatusOK>( `${this.getTeamRoute(teamId)}`, {method: 'delete'}, ); }; updateTeam = (team: Team) => { this.trackEvent('api', 'api_teams_update_name', {team_id: team.id}); return this.doFetch<Team>( `${this.getTeamRoute(team.id)}`, {method: 'put', body: JSON.stringify(team)}, ); }; patchTeam = (team: Partial<Team> & {id: string}) => { this.trackEvent('api', 'api_teams_patch_name', {team_id: team.id}); return this.doFetch<Team>( `${this.getTeamRoute(team.id)}/patch`, {method: 'put', body: JSON.stringify(team)}, ); }; regenerateTeamInviteId = (teamId: string) => { this.trackEvent('api', 'api_teams_regenerate_invite_id', {team_id: teamId}); return this.doFetch<Team>( `${this.getTeamRoute(teamId)}/regenerate_invite_id`, {method: 'post'}, ); }; updateTeamScheme = (teamId: string, schemeId: string) => { const patch = {scheme_id: schemeId}; this.trackEvent('api', 'api_teams_update_scheme', {team_id: teamId, ...patch}); return this.doFetch<StatusOK>( `${this.getTeamSchemeRoute(teamId)}`, {method: 'put', body: JSON.stringify(patch)}, ); }; checkIfTeamExists = (teamName: string) => { return this.doFetch<{exists: boolean}>( `${this.getTeamNameRoute(teamName)}/exists`, {method: 'get'}, ); }; getTeams = (page = 0, perPage = PER_PAGE_DEFAULT, includeTotalCount = false) => { return this.doFetch<Team[] | TeamsWithCount>( `${this.getTeamsRoute()}${buildQueryString({page, per_page: perPage, include_total_count: includeTotalCount})}`, {method: 'get'}, ); }; searchTeams = (term: string, opts: TeamSearchOpts) => { this.trackEvent('api', 'api_search_teams'); return this.doFetch<Team[] | TeamsWithCount>( `${this.getTeamsRoute()}/search`, {method: 'post', body: JSON.stringify({term, ...opts})}, ); }; getTeam = (teamId: string) => { return this.doFetch<Team>( this.getTeamRoute(teamId), {method: 'get'}, ); }; getTeamByName = (teamName: string) => { this.trackEvent('api', 'api_teams_get_team_by_name'); return this.doFetch<Team>( this.getTeamNameRoute(teamName), {method: 'get'}, ); }; getMyTeams = () => { return this.doFetch<Team[]>( `${this.getUserRoute('me')}/teams`, {method: 'get'}, ); }; getTeamsForUser = (userId: string) => { return this.doFetch<Team[]>( `${this.getUserRoute(userId)}/teams`, {method: 'get'}, ); }; getMyTeamMembers = () => { return this.doFetch<TeamMembership[]>( `${this.getUserRoute('me')}/teams/members`, {method: 'get'}, ); }; getMyTeamUnreads = () => { return this.doFetch<TeamUnread[]>( `${this.getUserRoute('me')}/teams/unread`, {method: 'get'}, ); }; getTeamMembers = (teamId: string, page = 0, perPage = PER_PAGE_DEFAULT, options: GetTeamMembersOpts) => { return this.doFetch<TeamMembership>( `${this.getTeamMembersRoute(teamId)}${buildQueryString({page, per_page: perPage, ...options})}`, {method: 'get'}, ); }; getTeamMembersForUser = (userId: string) => { return this.doFetch<TeamMembership[]>( `${this.getUserRoute(userId)}/teams/members`, {method: 'get'}, ); }; getTeamMember = (teamId: string, userId: string) => { return this.doFetch<TeamMembership>( `${this.getTeamMemberRoute(teamId, userId)}`, {method: 'get'}, ); }; getTeamMembersByIds = (teamId: string, userIds: string[]) => { return this.doFetch<TeamMembership[]>( `${this.getTeamMembersRoute(teamId)}/ids`, {method: 'post', body: JSON.stringify(userIds)}, ); }; addToTeam = (teamId: string, userId: string) => { this.trackEvent('api', 'api_teams_invite_members', {team_id: teamId}); const member = {user_id: userId, team_id: teamId}; return this.doFetch<TeamMembership>( `${this.getTeamMembersRoute(teamId)}`, {method: 'post', body: JSON.stringify(member)}, ); }; addToTeamFromInvite = (token = '', inviteId = '') => { this.trackEvent('api', 'api_teams_invite_members'); const query = buildQueryString({token, invite_id: inviteId}); return this.doFetch<TeamMembership>( `${this.getTeamsRoute()}/members/invite${query}`, {method: 'post'}, ); }; addUsersToTeam = (teamId: string, userIds: string[]) => { this.trackEvent('api', 'api_teams_batch_add_members', {team_id: teamId, count: userIds.length}); const members: any = []; userIds.forEach((id) => members.push({team_id: teamId, user_id: id})); return this.doFetch<TeamMembership[]>( `${this.getTeamMembersRoute(teamId)}/batch`, {method: 'post', body: JSON.stringify(members)}, ); }; addUsersToTeamGracefully = (teamId: string, userIds: string[]) => { this.trackEvent('api', 'api_teams_batch_add_members', {team_id: teamId, count: userIds.length}); const members: any = []; userIds.forEach((id) => members.push({team_id: teamId, user_id: id})); return this.doFetch<TeamMemberWithError[]>( `${this.getTeamMembersRoute(teamId)}/batch?graceful=true`, {method: 'post', body: JSON.stringify(members)}, ); }; joinTeam = (inviteId: string) => { const query = buildQueryString({invite_id: inviteId}); return this.doFetch<TeamMembership>( `${this.getTeamsRoute()}/members/invite${query}`, {method: 'post'}, ); }; removeFromTeam = (teamId: string, userId: string) => { this.trackEvent('api', 'api_teams_remove_members', {team_id: teamId}); return this.doFetch<StatusOK>( `${this.getTeamMemberRoute(teamId, userId)}`, {method: 'delete'}, ); }; getTeamStats = (teamId: string) => { return this.doFetch<TeamStats>( `${this.getTeamRoute(teamId)}/stats`, {method: 'get'}, ); }; getTotalUsersStats = () => { return this.doFetch<UsersStats>( `${this.getUsersRoute()}/stats`, {method: 'get'}, ); }; getFilteredUsersStats = (options: GetFilteredUsersStatsOpts) => { return this.doFetch<UsersStats>( `${this.getUsersRoute()}/stats/filtered${buildQueryString(options)}`, {method: 'get'}, ); }; invalidateAllEmailInvites = () => { return this.doFetch<StatusOK>( `${this.getTeamsRoute()}/invites/email`, {method: 'delete'}, ); }; getTeamInviteInfo = (inviteId: string) => { return this.doFetch<{ display_name: string; description: string; name: string; id: string; }>( `${this.getTeamsRoute()}/invite/${inviteId}`, {method: 'get'}, ); }; updateTeamMemberRoles = (teamId: string, userId: string, roles: string[]) => { this.trackEvent('api', 'api_teams_update_member_roles', {team_id: teamId}); return this.doFetch<StatusOK>( `${this.getTeamMemberRoute(teamId, userId)}/roles`, {method: 'put', body: JSON.stringify({roles})}, ); }; sendEmailInvitesToTeam = (teamId: string, emails: string[]) => { this.trackEvent('api', 'api_teams_invite_members', {team_id: teamId}); return this.doFetch<StatusOK>( `${this.getTeamRoute(teamId)}/invite/email`, {method: 'post', body: JSON.stringify(emails)}, ); }; sendEmailGuestInvitesToChannels = (teamId: string, channelIds: string[], emails: string[], message: string) => { this.trackEvent('api', 'api_teams_invite_guests', {team_id: teamId, channel_ids: channelIds}); return this.doFetch<StatusOK>( `${this.getTeamRoute(teamId)}/invite-guests/email`, {method: 'post', body: JSON.stringify({emails, channels: channelIds, message})}, ); }; sendEmailInvitesToTeamGracefully = (teamId: string, emails: string[]) => { this.trackEvent('api', 'api_teams_invite_members', {team_id: teamId}); return this.doFetch<TeamInviteWithError>( `${this.getTeamRoute(teamId)}/invite/email?graceful=true`, {method: 'post', body: JSON.stringify(emails)}, ); }; sendEmailGuestInvitesToChannelsGracefully = async (teamId: string, channelIds: string[], emails: string[], message: string) => { this.trackEvent('api', 'api_teams_invite_guests', {team_id: teamId, channel_ids: channelIds}); return this.doFetch<TeamInviteWithError>( `${this.getTeamRoute(teamId)}/invite-guests/email?graceful=true`, {method: 'post', body: JSON.stringify({emails, channels: channelIds, message})}, ); }; importTeam = (teamId: string, file: File, importFrom: string) => { const formData = new FormData(); formData.append('file', file, file.name); formData.append('filesize', file.size); formData.append('importFrom', importFrom); const request: any = { method: 'post', body: formData, }; if (formData.getBoundary) { request.headers = { 'Content-Type': `multipart/form-data; boundary=${formData.getBoundary()}`, }; } return this.doFetch<{ results: string; }>( `${this.getTeamRoute(teamId)}/import`, request, ); }; getTeamIconUrl = (teamId: string, lastTeamIconUpdate: number) => { const params: any = {}; if (lastTeamIconUpdate) { params._ = lastTeamIconUpdate; } return `${this.getTeamRoute(teamId)}/image${buildQueryString(params)}`; }; setTeamIcon = (teamId: string, imageData: File) => { this.trackEvent('api', 'api_team_set_team_icon'); const formData = new FormData(); formData.append('image', imageData); const request: any = { method: 'post', body: formData, }; if (formData.getBoundary) { request.headers = { 'Content-Type': `multipart/form-data; boundary=${formData.getBoundary()}`, }; } return this.doFetch<StatusOK>( `${this.getTeamRoute(teamId)}/image`, request, ); }; removeTeamIcon = (teamId: string) => { this.trackEvent('api', 'api_team_remove_team_icon'); return this.doFetch<StatusOK>( `${this.getTeamRoute(teamId)}/image`, {method: 'delete'}, ); }; updateTeamMemberSchemeRoles = (teamId: string, userId: string, isSchemeUser: boolean, isSchemeAdmin: boolean) => { const body = {scheme_user: isSchemeUser, scheme_admin: isSchemeAdmin}; return this.doFetch<StatusOK>( `${this.getTeamRoute(teamId)}/members/${userId}/schemeRoles`, {method: 'put', body: JSON.stringify(body)}, ); }; // Channel Routes getAllChannels = (page = 0, perPage = PER_PAGE_DEFAULT, notAssociatedToGroup = '', excludeDefaultChannels = false, includeTotalCount = false, includeDeleted = false) => { const queryData = { page, per_page: perPage, not_associated_to_group: notAssociatedToGroup, exclude_default_channels: excludeDefaultChannels, include_total_count: includeTotalCount, include_deleted: includeDeleted, }; return this.doFetch<ChannelWithTeamData[] | ChannelsWithTotalCount>( `${this.getChannelsRoute()}${buildQueryString(queryData)}`, {method: 'get'}, ); }; createChannel = (channel: Channel) => { this.trackEvent('api', 'api_channels_create', {team_id: channel.team_id}); return this.doFetch<Channel>( `${this.getChannelsRoute()}`, {method: 'post', body: JSON.stringify(channel)}, ); }; createDirectChannel = (userIds: string[]) => { this.trackEvent('api', 'api_channels_create_direct'); return this.doFetch<Channel>( `${this.getChannelsRoute()}/direct`, {method: 'post', body: JSON.stringify(userIds)}, ); }; createGroupChannel = (userIds: string[]) => { this.trackEvent('api', 'api_channels_create_group'); return this.doFetch<Channel>( `${this.getChannelsRoute()}/group`, {method: 'post', body: JSON.stringify(userIds)}, ); }; deleteChannel = (channelId: string) => { this.trackEvent('api', 'api_channels_delete', {channel_id: channelId}); return this.doFetch<StatusOK>( `${this.getChannelRoute(channelId)}`, {method: 'delete'}, ); }; unarchiveChannel = (channelId: string) => { this.trackEvent('api', 'api_channels_unarchive', {channel_id: channelId}); return this.doFetch<Channel>( `${this.getChannelRoute(channelId)}/restore`, {method: 'post'}, ); }; updateChannel = (channel: Channel) => { this.trackEvent('api', 'api_channels_update', {channel_id: channel.id}); return this.doFetch<Channel>( `${this.getChannelRoute(channel.id)}`, {method: 'put', body: JSON.stringify(channel)}, ); }; convertChannelToPrivate = (channelId: string) => { this.trackEvent('api', 'api_channels_convert_to_private', {channel_id: channelId}); return this.doFetch<Channel>( `${this.getChannelRoute(channelId)}/convert`, {method: 'post'}, ); }; updateChannelPrivacy = (channelId: string, privacy: any) => { this.trackEvent('api', 'api_channels_update_privacy', {channel_id: channelId, privacy}); return this.doFetch<Channel>( `${this.getChannelRoute(channelId)}/privacy`, {method: 'put', body: JSON.stringify({privacy})}, ); }; patchChannel = (channelId: string, channelPatch: Partial<Channel>) => { this.trackEvent('api', 'api_channels_patch', {channel_id: channelId}); return this.doFetch<Channel>( `${this.getChannelRoute(channelId)}/patch`, {method: 'put', body: JSON.stringify(channelPatch)}, ); }; updateChannelNotifyProps = (props: any) => { this.trackEvent('api', 'api_users_update_channel_notifications', {channel_id: props.channel_id}); return this.doFetch<StatusOK>( `${this.getChannelMemberRoute(props.channel_id, props.user_id)}/notify_props`, {method: 'put', body: JSON.stringify(props)}, ); }; updateChannelScheme = (channelId: string, schemeId: string) => { const patch = {scheme_id: schemeId}; this.trackEvent('api', 'api_channels_update_scheme', {channel_id: channelId, ...patch}); return this.doFetch<StatusOK>( `${this.getChannelSchemeRoute(channelId)}`, {method: 'put', body: JSON.stringify(patch)}, ); }; getChannel = (channelId: string) => { this.trackEvent('api', 'api_channel_get', {channel_id: channelId}); return this.doFetch<Channel>( `${this.getChannelRoute(channelId)}`, {method: 'get'}, ); }; getChannelByName = (teamId: string, channelName: string, includeDeleted = false) => { return this.doFetch<Channel>( `${this.getTeamRoute(teamId)}/channels/name/${channelName}?include_deleted=${includeDeleted}`, {method: 'get'}, ); }; getChannelByNameAndTeamName = (teamName: string, channelName: string, includeDeleted = false) => { this.trackEvent('api', 'api_channel_get_by_name_and_teamName', {include_deleted: includeDeleted}); return this.doFetch<Channel>( `${this.getTeamNameRoute(teamName)}/channels/name/${channelName}?include_deleted=${includeDeleted}`, {method: 'get'}, ); }; getChannels = (teamId: string, page = 0, perPage =