Skip to content

Commit

Permalink
Add support for intercom allowed users
Browse files Browse the repository at this point in the history
  • Loading branch information
DQGriffin committed Jul 21, 2023
1 parent feb4eba commit 517026d
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 7 deletions.
Binary file modified frontend/public/migration-template.xlsx
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const useFetchUserData = (postMessage: (message: Message) => void, postTimedMess
const basePresenseSettingsURL = 'https://platform.ringcentral.com/restapi/v1.0/account/~/extension/extensionId/presence'
const basePresenseAllowedUsersURL = 'https://platform.ringcentral.com/restapi/v1.0/account/~/extension/extensionId/presence/permission'
const baseIntercomURL = 'https://platform.ringcentral.com/restapi/v1.0/account/~/extension/extensionId/intercom'
const baseIntercomUsersURL = 'https://platform.ringcentral.com/restapi/v1.0/account/~/extension/extensionId/intercom/permissions'
const baseDelegatesURL = 'https://platform.ringcentral.com/restapi/v1.0/account/~/extension/extensionId/delegates'
const basePERLURL = 'https://platform.ringcentral.com/restapi/v1.0/account/~/extension/extensionId/emergency-locations?perPage=1000'
const baseRoleURL = 'https://platform.ringcentral.com/restapi/v1.0/account/~/extension/extensionId/assigned-role'
Expand Down Expand Up @@ -48,6 +49,7 @@ const useFetchUserData = (postMessage: (message: Message) => void, postTimedMess
await fetchPresenseSettings(userDataBundle, accessToken)
await fetchPresenseAllowedUsers(userDataBundle, extensions, accessToken)
await fetchIntercomStatus(userDataBundle, accessToken)
await fetchIntercomUsers(userDataBundle, accessToken)
if (shouldFetchDelegates) {
await fetchDelegates(userDataBundle, accessToken)
}
Expand Down Expand Up @@ -471,6 +473,34 @@ const useFetchUserData = (postMessage: (message: Message) => void, postTimedMess
}
}

const fetchIntercomUsers = async (userDataBundle: UserDataBundle, token: string) => {
try {
const headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`
}
const response = await RestCentral.get(baseIntercomUsersURL.replace('extensionId', `${userDataBundle.extension.data.id}`), headers)
userDataBundle.extendedData!.intercomUsers = response.data.extensions || []

if (response.rateLimitInterval > 0) {
postTimedMessage(new Message(`Rale limit reached. Waiting ${response.rateLimitInterval / 1000} seconds`, 'info'), response.rateLimitInterval)
}

response.rateLimitInterval > 0 ? await wait(response.rateLimitInterval) : await wait(baseWaitingPeriod)
}
catch (e: any) {
if (e.rateLimitInterval > 0) {
postTimedMessage(new Message(`Rale limit reached. Waiting ${e.rateLimitInterval / 1000} seconds`, 'info'), e.rateLimitInterval)
}
console.log(`Failed to get intercom users`)
console.log(e)
postMessage(new Message(`Failed to get intercom allowed users for ${userDataBundle.extension.data.name} ${e.error ?? ''}`, 'error'))
postError(new SyncError(userDataBundle.extension.data.name, parseInt(userDataBundle.extension.data.extensionNumber), ['Failed to fetch intercom allowed users', ''], e.error ?? ''))
e.rateLimitInterval > 0 ? await wait(e.rateLimitInterval) : await wait(baseWaitingPeriod)
}
}

const fetchDelegates = async (userDataBundle: UserDataBundle, token: string) => {
try {
const headers = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,20 @@ export class UserDataBundle {
actualDevices = this.extendedData.devices.filter((device) => device.phoneLines && device.phoneLines.length !== 0)

for (let i = 0; i < actualDevices.length; i++) {
const row = new UserDataRow(this.extension, 'Full DL', actualDevices[i], undefined, this.extendedData.businessHoursCallHandling, this.extendedData.afterHoursCallHandling, this.extendedData.notifications, this.extendedData.callerID, this.extendedData.blockedCallSettings, this.extendedData.blockedPhoneNumbers, this.extendedData.presenseLines, this.extendedData.presenseSettings, this.extendedData.presenseAllowedUsers, this.extendedData.intercomStatus, this.extendedData.delegates, this.extendedData.pERLs, this.extendedData.roles, this.extendedData.incommingCallInfo, this.extendedData.businessHours, this.extendedData.forwardAllCalls, this.extendedData.defaultBridge, this.userGroups, this.phoneNumberMap, this.tempExtension)
const row = new UserDataRow(this.extension, 'Full DL', actualDevices[i], undefined, this.extendedData.businessHoursCallHandling, this.extendedData.afterHoursCallHandling, this.extendedData.notifications, this.extendedData.callerID, this.extendedData.blockedCallSettings, this.extendedData.blockedPhoneNumbers, this.extendedData.presenseLines, this.extendedData.presenseSettings, this.extendedData.presenseAllowedUsers, this.extendedData.intercomStatus, this.extendedData.delegates, this.extendedData.pERLs, this.extendedData.roles, this.extendedData.incommingCallInfo, this.extendedData.businessHours, this.extendedData.forwardAllCalls, this.extendedData.defaultBridge, this.userGroups, this.phoneNumberMap, this.tempExtension, this.extendedData.intercomUsers)
rows.push(row)
}
}

if (this.extendedData.directNumbers) {
for (const directNumber of this.extendedData.directNumbers) {
const row = new UserDataRow(this.extension, 'Additional DID', undefined, directNumber.phoneNumber, this.extendedData.businessHoursCallHandling, this.extendedData.afterHoursCallHandling, this.extendedData.notifications, this.extendedData.callerID, this.extendedData.blockedCallSettings, this.extendedData.blockedPhoneNumbers, this.extendedData.presenseLines, this.extendedData.presenseSettings, this.extendedData.presenseAllowedUsers, this.extendedData.intercomStatus, this.extendedData.delegates, this.extendedData.pERLs, this.extendedData.roles, this.extendedData.incommingCallInfo, this.extendedData.businessHours, this.extendedData.forwardAllCalls, this.extendedData.defaultBridge, this.userGroups, this.phoneNumberMap, this.tempExtension)
const row = new UserDataRow(this.extension, 'Additional DID', undefined, directNumber.phoneNumber, this.extendedData.businessHoursCallHandling, this.extendedData.afterHoursCallHandling, this.extendedData.notifications, this.extendedData.callerID, this.extendedData.blockedCallSettings, this.extendedData.blockedPhoneNumbers, this.extendedData.presenseLines, this.extendedData.presenseSettings, this.extendedData.presenseAllowedUsers, this.extendedData.intercomStatus, this.extendedData.delegates, this.extendedData.pERLs, this.extendedData.roles, this.extendedData.incommingCallInfo, this.extendedData.businessHours, this.extendedData.forwardAllCalls, this.extendedData.defaultBridge, this.userGroups, this.phoneNumberMap, this.tempExtension, this.extendedData.intercomUsers)
rows.push(row)
}
}

if ((!this.extendedData.devices && !this.extendedData.directNumbers) || (this.extendedData.devices.length === 0 && this.extendedData.directNumbers?.length === 0) || actualDevices.length === 0) {
const row = new UserDataRow(this.extension, 'Virtual', undefined, undefined, this.extendedData.businessHoursCallHandling, this.extendedData.afterHoursCallHandling, this.extendedData.notifications, this.extendedData.callerID, this.extendedData.blockedCallSettings, this.extendedData.blockedPhoneNumbers, this.extendedData.presenseLines, this.extendedData.presenseSettings, this.extendedData.presenseAllowedUsers, this.extendedData.intercomStatus, this.extendedData.delegates, this.extendedData.pERLs, this.extendedData.roles, this.extendedData.incommingCallInfo, this.extendedData.businessHours, this.extendedData.forwardAllCalls, this.extendedData.defaultBridge, this.userGroups, this.phoneNumberMap, this.tempExtension)
const row = new UserDataRow(this.extension, 'Virtual', undefined, undefined, this.extendedData.businessHoursCallHandling, this.extendedData.afterHoursCallHandling, this.extendedData.notifications, this.extendedData.callerID, this.extendedData.blockedCallSettings, this.extendedData.blockedPhoneNumbers, this.extendedData.presenseLines, this.extendedData.presenseSettings, this.extendedData.presenseAllowedUsers, this.extendedData.intercomStatus, this.extendedData.delegates, this.extendedData.pERLs, this.extendedData.roles, this.extendedData.incommingCallInfo, this.extendedData.businessHours, this.extendedData.forwardAllCalls, this.extendedData.defaultBridge, this.userGroups, this.phoneNumberMap, this.tempExtension, this.extendedData.intercomUsers)
rows.push(row)
}

Expand All @@ -59,6 +59,7 @@ export interface ExtendedUserData {
presenseSettings?: PresenseSettings
presenseAllowedUsers?: PresenseAllowedUser[]
intercomStatus?: IntercomStatus
intercomUsers?: IntercomUser[]
delegates?: Delegate[]
pERLs?: PERL[]
roles?: Role[]
Expand Down Expand Up @@ -500,4 +501,11 @@ export interface DefaultBridge {
pins: {
web: string
}
}

export interface IntercomUser {
uri?: string
id: string
extensionNumber: string
name: string
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import ExcelFormattable from "../../../../../models/ExcelFormattable";
import { Extension } from "../../../../../models/Extension";
import { BlockedCallSettings, BlockedPhoneNumber, BusinessHours, CallerID, CallHandling, DefaultBridge, Delegate, Device, PERL, ForwardAllCalls, IncommingCallInfo, IntercomStatus, Notifications, PresenseAllowedUser, PresenseLine, PresenseSettings, Role, PhoneNumber } from "./UserDataBundle";
import { BlockedCallSettings, BlockedPhoneNumber, BusinessHours, CallerID, CallHandling, DefaultBridge, Delegate, Device, PERL, ForwardAllCalls, IncommingCallInfo, IntercomStatus, Notifications, PresenseAllowedUser, PresenseLine, PresenseSettings, Role, PhoneNumber, IntercomUser } from "./UserDataBundle";

export class UserDataRow implements ExcelFormattable {
constructor(public extension: Extension, public type: string, public device?: Device, public directNumber?: string,
Expand All @@ -9,7 +9,7 @@ export class UserDataRow implements ExcelFormattable {
public blockedPhoneNumbers?: BlockedPhoneNumber[], public presenseLines?: PresenseLine[], public presenseSettings?: PresenseSettings,
public presenseAllowedUsers?: PresenseAllowedUser[], public intercomStatus?: IntercomStatus, public delegates?: Delegate[], public erls?: PERL[],
public roles?: Role[], public incommingCallInfo?: IncommingCallInfo, public businessHours?: BusinessHours, public forwardAllCalls?: ForwardAllCalls,
public defaultBridge?: DefaultBridge, public userGroups?: string, public phoneNumberMap?: Map<string, PhoneNumber>, public tempExtension?: string) {}
public defaultBridge?: DefaultBridge, public userGroups?: string, public phoneNumberMap?: Map<string, PhoneNumber>, public tempExtension?: string, public intercomUsers?: IntercomUser[]) {}

toExcelRow(): string[] {
return [
Expand Down Expand Up @@ -56,6 +56,7 @@ export class UserDataRow implements ExcelFormattable {
this.presenseSettings?.allowSeeMyPresence === true ? 'ON' : 'OFF',
this.prettyPresenseUsers(),
this.intercomStatus?.enabled ? 'ON' : 'OFF',
this.prettyIntercomUsers(),
this.prettyDelegates(),
this.defaultBridge?.pins.web ?? '',
this.greeting('Introductory'),
Expand Down Expand Up @@ -357,6 +358,17 @@ export class UserDataRow implements ExcelFormattable {
return result
}

prettyIntercomUsers() {
if (!this.intercomUsers) return ''
let result = ''

for (const intercomUser of this.intercomUsers) {
result += `${intercomUser.name} - ${intercomUser.extensionNumber}\n`
}

return result
}

prettyIncommingCallInfo() {
let result = ''
if (!this.incommingCallInfo) return result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Message } from "../../../../../models/Message";
import { SyncError } from "../../../../../models/SyncError";
import { RestCentral } from "../../../../../rcapi/RestCentral";
import { ERL } from "../../../Automatic Location Updates/models/ERL";
import { BlockedPhoneNumber, CalledNumber, CallerIDDevice, CallerIDFeature, CallHandling, CallHandlingForwardingNumber, CallHandlingForwardingRule, CustomRule, Device, ForwardingNumber, PERL, PhoneNumber, PresenseAllowedUser, PresenseLine, UserDataBundle } from "../../User Data Download/models/UserDataBundle";
import { BlockedPhoneNumber, CalledNumber, CallerIDDevice, CallerIDFeature, CallHandling, CallHandlingForwardingNumber, CallHandlingForwardingRule, CustomRule, Device, ForwardingNumber, IntercomUser, PERL, PhoneNumber, PresenseAllowedUser, PresenseLine, UserDataBundle } from "../../User Data Download/models/UserDataBundle";
import { Role } from "../models/Role";

interface DeviceModelPayload {
Expand All @@ -31,6 +31,7 @@ const useConfigureUser = (postMessage: (message: Message) => void, postTimedMess
const basePresenceSettingsURL = 'https://platform.ringcentral.com/restapi/v1.0/account/~/extension/extensionId/presence'
const baseNotificationsSettingsURL = 'https://platform.ringcentral.com/restapi/v1.0/account/~/extension/extensionId/notification-settings'
const baseIntercomURL = 'https://platform.ringcentral.com/restapi/v1.0/account/~/extension/extensionId/intercom'
const baseIntercomUsersURL = 'https://platform.ringcentral.com/restapi/v1.0/account/~/extension/extensionId/intercom/permissions'
const baseCallHandlingURL = 'https://platform.ringcentral.com/restapi/v1.0/account/~/extension/extensionId/answering-rule/ruleId?showInactiveNumbers=true'
const baseBlockedCallsURL = 'https://platform.ringcentral.com/restapi/v1.0/account/~/extension/extensionId/caller-blocking'
const baseBlockedPnoneNumbersURL = 'https://platform.ringcentral.com/restapi/v1.0/account/~/extension/extensionId/caller-blocking/phone-numbers'
Expand Down Expand Up @@ -85,6 +86,7 @@ const useConfigureUser = (postMessage: (message: Message) => void, postTimedMess
await setNotifications(bundle, emailSuffix, accessToken)
if (deviceIDs && deviceIDs.length > 0) {
await enableIntercom(bundle, deviceIDs[0], accessToken)
await setIntercomUsers(bundle, originalExtensions, targetExtensions, accessToken)
}

for (let customRule of bundle.extendedData!.customRules!) {
Expand Down Expand Up @@ -580,6 +582,68 @@ const useConfigureUser = (postMessage: (message: Message) => void, postTimedMess
}
}

const setIntercomUsers = async (bundle: UserDataBundle, originalExtensions: Extension[], targetExtensions: Extension[], token: string) => {
if (!bundle.extendedData?.intercomStatus?.enabled || !bundle.extendedData.intercomUsers || bundle.extendedData.intercomUsers.length === 0) return

try {
const headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`
}
// const response = await RestCentral.get(baseIntercomUsersURL.replace('extensionId', `${bundle.extension.data.id}`), headers)

const goodUsers: IntercomUser[] = []
const badUsers: IntercomUser[] = []

for(const user of bundle.extendedData!.intercomUsers) {
const originalExtension = originalExtensions.find((extension) => `${extension.data.id}` === `${user.id}`)
if (!originalExtension) {
badUsers.push(user)
continue
}

const targetExtension = targetExtensions.find((extension) => extension.data.name === originalExtension.data.name && originalExtension.prettyType() === extension.prettyType())
if (!targetExtension) {
badUsers.push(user)
continue
}

goodUsers.push({
id: `${targetExtension.data.id}`,
extensionNumber: targetExtension.data.extensionNumber,
name: targetExtension.data.name,
})
}

if (badUsers.length > 0) {
postMessage(new Message(`${badUsers.length} users were removed from ${bundle.extension.data.name}'s intercom allowed users because they could not be found`, 'warning'))
postError(new SyncError(bundle.extension.data.name, bundle.extension.data.extensionNumber, ['Users removed from intercom allowed users', badUsers.map((user) => user.name).join(', ')]))
}

if (goodUsers.length === 0) return

const response = await RestCentral.put(baseIntercomUsersURL.replace('extensionId', `${bundle.extension.data.id}`), headers, {extensions: goodUsers})


if (response.rateLimitInterval > 0) {
postTimedMessage(new Message(`Rale limit reached. Waiting ${response.rateLimitInterval / 1000} seconds`, 'info'), response.rateLimitInterval)
}

response.rateLimitInterval > 0 ? await wait(response.rateLimitInterval) : await wait(baseWaitingPeriod)
}
catch (e: any) {
if (e.rateLimitInterval > 0) {
postTimedMessage(new Message(`Rale limit reached. Waiting ${e.rateLimitInterval / 1000} seconds`, 'info'), e.rateLimitInterval)
}
console.log(`Failed to set intercom users`)
console.log(e)
postMessage(new Message(`Failed to set intercom users for ${bundle.extension.data.name} ${e.error ?? ''}`, 'error'))
postError(new SyncError(bundle.extension.data.name, parseInt(bundle.extension.data.extensionNumber), ['Failed to set intercom users', ''], e.error ?? ''))
e.rateLimitInterval > 0 ? await wait(e.rateLimitInterval) : await wait(baseWaitingPeriod)
}
}

const setDuringHoursGreetings = async (bundle: UserDataBundle, token: string) => {
try {
const headers = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const useMigrateUsers = (postMessage: (message: Message) => void, postTimedMessa
continue
}
const unassignedExt = unassignedExtensions.pop()!
bundle.phoneNumberMap.set(bundle.extendedData!.devices[i].phoneLines[0].phoneInfo.phoneNumber, unassignedExt.data!.phoneNumbers![0])
bundle.phoneNumberMap.set(actualDevices[i].phoneLines[0].phoneInfo.phoneNumber, unassignedExt.data!.phoneNumbers![0])
unassignedIDs.push(`${unassignedExt.data.id}`)
}

Expand Down

0 comments on commit 517026d

Please sign in to comment.