-
Notifications
You must be signed in to change notification settings - Fork 354
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(internal-plugin-calendar): support unified scheduler in beta bra…
…nch (merge from master) (#3076) Co-authored-by: Vic Wang <[email protected]>
- Loading branch information
Showing
9 changed files
with
761 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
121 changes: 121 additions & 0 deletions
121
packages/@webex/internal-plugin-calendar/src/calendar.decrypt.helper.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
const _decryptTextProp = (ctx, name, key, object) => { | ||
if (!object[name]) { | ||
return Promise.resolve(); | ||
} | ||
|
||
return ctx.webex.internal.encryption | ||
.decryptText(key.uri || key, object[name]) | ||
.then((plaintext) => { | ||
object[name] = plaintext; | ||
}); | ||
}; | ||
|
||
const DecryptHelper = { | ||
/** | ||
* Decrypt scheduler data response | ||
* @param {object} [ctx] context | ||
* @param {object} [data] scheduler data response | ||
* @returns {Promise} Resolves with decrypted response | ||
* */ | ||
decryptSchedulerDataResponse: (ctx, data) => { | ||
if (!data) { | ||
return Promise.resolve(); | ||
} | ||
|
||
if (!data.encryptionKeyUrl) { | ||
return Promise.resolve(); | ||
} | ||
|
||
// Decrypt participant properties if meeting object contains participants | ||
const decryptedParticipants = data.encryptedParticipants | ||
? data.encryptedParticipants.map((participant) => | ||
Promise.all([ | ||
_decryptTextProp(ctx, 'encryptedEmailAddress', data.encryptionKeyUrl, participant), | ||
_decryptTextProp(ctx, 'encryptedName', data.encryptionKeyUrl, participant), | ||
]) | ||
) | ||
: []; | ||
|
||
// Decrypt encryptedScheduleFor properties if meeting object contains SOB | ||
const decryptedScheduleFor = Promise.all( | ||
Object.values(data.encryptedScheduleFor || {}).flatMap((item) => [ | ||
_decryptTextProp(ctx, 'encryptedEmail', data.encryptionKeyUrl, item), | ||
_decryptTextProp(ctx, 'encryptedDisplayName', data.encryptionKeyUrl, item), | ||
]) | ||
); | ||
|
||
// Decrypt meetingJoinInfo properties if meeting object contains meetingJoinInfo | ||
const decryptedMeetingJoinInfo = data.meetingJoinInfo | ||
? Promise.all([ | ||
_decryptTextProp(ctx, 'meetingJoinURI', data.encryptionKeyUrl, data.meetingJoinInfo), | ||
_decryptTextProp(ctx, 'meetingJoinURL', data.encryptionKeyUrl, data.meetingJoinInfo), | ||
]) | ||
: []; | ||
|
||
const decryptedOrganizer = data.encryptedOrganizer | ||
? Promise.all([ | ||
_decryptTextProp( | ||
ctx, | ||
'encryptedEmailAddress', | ||
data.encryptionKeyUrl, | ||
data.encryptedOrganizer | ||
), | ||
_decryptTextProp(ctx, 'encryptedName', data.encryptionKeyUrl, data.encryptedOrganizer), | ||
]) | ||
: []; | ||
|
||
return Promise.all( | ||
[ | ||
_decryptTextProp(ctx, 'encryptedSubject', data.encryptionKeyUrl, data), | ||
_decryptTextProp(ctx, 'encryptedLocation', data.encryptionKeyUrl, data), | ||
_decryptTextProp(ctx, 'encryptedNotes', data.encryptionKeyUrl, data), | ||
_decryptTextProp(ctx, 'webexURI', data.encryptionKeyUrl, data), | ||
_decryptTextProp(ctx, 'webexURL', data.encryptionKeyUrl, data), | ||
_decryptTextProp(ctx, 'spaceMeetURL', data.encryptionKeyUrl, data), | ||
_decryptTextProp(ctx, 'spaceURI', data.encryptionKeyUrl, data), | ||
_decryptTextProp(ctx, 'spaceURL', data.encryptionKeyUrl, data), | ||
].concat( | ||
decryptedOrganizer, | ||
decryptedParticipants, | ||
decryptedScheduleFor, | ||
decryptedMeetingJoinInfo | ||
) | ||
); | ||
}, | ||
/** | ||
* Decrypt free-busy response | ||
* @param {object} [ctx] context | ||
* @param {object} [data] free-busy response | ||
* @returns {Promise} Resolves with decrypted response | ||
* */ | ||
decryptFreeBusyResponse: (ctx, data) => { | ||
if (!data) { | ||
return Promise.resolve(); | ||
} | ||
|
||
if (!data.calendarFreeBusyScheduleResponse) { | ||
return Promise.resolve(); | ||
} | ||
|
||
if (!data.calendarFreeBusyScheduleResponse.encryptionKeyUrl) { | ||
return Promise.resolve(); | ||
} | ||
|
||
const calendarFreeBusyItems = data.calendarFreeBusyScheduleResponse.calendarFreeBusyItems | ||
? data.calendarFreeBusyScheduleResponse.calendarFreeBusyItems.map((calendarFreeBusyItem) => | ||
Promise.all([ | ||
_decryptTextProp( | ||
ctx, | ||
'email', | ||
data.calendarFreeBusyScheduleResponse.encryptionKeyUrl, | ||
calendarFreeBusyItem | ||
), | ||
]) | ||
) | ||
: []; | ||
|
||
return Promise.all([].concat(calendarFreeBusyItems)); | ||
}, | ||
}; | ||
|
||
export default DecryptHelper; |
98 changes: 98 additions & 0 deletions
98
packages/@webex/internal-plugin-calendar/src/calendar.encrypt.helper.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import {isArray} from 'lodash'; | ||
|
||
const _encryptTextProp = (ctx, name, key, object) => { | ||
if (!object[name]) { | ||
return Promise.resolve(); | ||
} | ||
|
||
return ctx.webex.internal.encryption | ||
.encryptText(key.uri || key, object[name]) | ||
.then((ciphertext) => { | ||
object[name] = ciphertext; | ||
}); | ||
}; | ||
|
||
const _encryptCalendarEventPayload = (data, ctx) => { | ||
Object.assign(data, {encryptionKeyUrl: ctx.encryptionKeyUrl}); | ||
|
||
const encryptedAttendees = data.attendees | ||
? data.attendees.map((attendee) => | ||
Promise.all([ | ||
_encryptTextProp(ctx, 'displayName', data.encryptionKeyUrl, attendee), | ||
_encryptTextProp(ctx, 'email', data.encryptionKeyUrl, attendee), | ||
]) | ||
) | ||
: []; | ||
|
||
return Promise.all( | ||
[ | ||
_encryptTextProp(ctx, 'subject', data.encryptionKeyUrl, data), | ||
_encryptTextProp(ctx, 'notes', data.encryptionKeyUrl, data), | ||
_encryptTextProp(ctx, 'webexOptions', data.encryptionKeyUrl, data), | ||
].concat([encryptedAttendees]) | ||
); | ||
}; | ||
|
||
const _encryptFreeBusyPayload = (data, ctx) => { | ||
Object.assign(data, {encryptionKeyUrl: ctx.encryptionKeyUrl}); | ||
|
||
const promises = []; | ||
if (data.emails && Array.isArray(data.emails)) { | ||
data.emails.map((item, index) => | ||
promises.push( | ||
ctx.webex.internal.encryption | ||
.encryptText(data.encryptionKeyUrl, item) | ||
.then((encryptText) => { | ||
data.emails[index] = encryptText; | ||
}) | ||
) | ||
); | ||
} | ||
|
||
return Promise.all(promises); | ||
}; | ||
|
||
const EncryptHelper = { | ||
/** | ||
* Encrypt create / update calendar event request payload | ||
* @param {object} [ctx] context | ||
* @param {object} [data] meeting payload data | ||
* @returns {Promise} Resolves with encrypted request payload | ||
* */ | ||
encryptCalendarEventRequest: (ctx, data) => { | ||
if (ctx.encryptionKeyUrl) { | ||
return _encryptCalendarEventPayload(data, ctx); | ||
} | ||
|
||
return ctx.webex.internal.encryption.kms.createUnboundKeys({count: 1}).then((keys) => { | ||
const key = isArray(keys) ? keys[0] : keys; | ||
ctx.encryptionKeyUrl = key.uri; | ||
|
||
return _encryptCalendarEventPayload(data, ctx); | ||
}); | ||
}, | ||
/** | ||
* Encrypt free-busy request payload, if request payload only includes the sensitive data, like email, need to encrypt these reqeust parameters, and playload includes encrypt url. | ||
* Otherwise, don't encrypt playload and without encrypt url,Due to calendar serivce will vaild both encrypt url and sensitive that are both present. if not, will return 400 bad reqeust to caller. | ||
* @param {object} [ctx] context | ||
* @param {object} [data] free busy payload data | ||
* @returns {Promise} Resolves with encrypted request payload | ||
* */ | ||
encryptFreeBusyRequest: (ctx, data) => { | ||
if (!data.emails || !Array.isArray(data.emails)) { | ||
return Promise.resolve(); | ||
} | ||
if (ctx.encryptionKeyUrl) { | ||
return _encryptFreeBusyPayload(data, ctx); | ||
} | ||
|
||
return ctx.webex.internal.encryption.kms.createUnboundKeys({count: 1}).then((keys) => { | ||
const key = isArray(keys) ? keys[0] : keys; | ||
ctx.encryptionKeyUrl = key.uri; | ||
|
||
return _encryptFreeBusyPayload(data, ctx); | ||
}); | ||
}, | ||
}; | ||
|
||
export default EncryptHelper; |
Oops, something went wrong.