diff --git a/services/web/app/src/models/SSOConfig.js b/services/web/app/src/models/SSOConfig.js index 8daab2d7b7..53ef70fb6f 100644 --- a/services/web/app/src/models/SSOConfig.js +++ b/services/web/app/src/models/SSOConfig.js @@ -4,7 +4,7 @@ const { Schema } = mongoose const SSOConfigSchema = new Schema( { entryPoint: { type: String, required: true }, - certificate: { type: String, required: true }, + certificates: { type: Array, default: [''], required: true }, signatureAlgorithm: { type: String, required: true }, userIdAttribute: { type: String, required: true }, userFirstNameAttribute: { type: String }, diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json index 2d871c4830..06ec2dc65f 100644 --- a/services/web/frontend/extracted-translations.json +++ b/services/web/frontend/extracted-translations.json @@ -30,6 +30,7 @@ "acct_linked_to_institution_acct_2": "", "actions": "", "add": "", + "add_additional_certificate": "", "add_affiliation": "", "add_another_address_line": "", "add_another_email": "", @@ -49,6 +50,7 @@ "add_your_first_group_member_now": "", "added_by_on": "", "adding": "", + "additional_certificate": "", "additional_licenses": "", "address_line_1": "", "address_second_line_optional": "", diff --git a/services/web/locales/en.json b/services/web/locales/en.json index 7f5ab1eb2c..c4bcebedc7 100644 --- a/services/web/locales/en.json +++ b/services/web/locales/en.json @@ -51,6 +51,7 @@ "activating": "Activating", "activation_token_expired": "Your activation token has expired, you will need to get another one sent to you.", "add": "Add", + "add_additional_certificate": "Add additional certificate", "add_affiliation": "Add Affiliation", "add_another_address_line": "Add another address line", "add_another_email": "Add another email", @@ -72,6 +73,7 @@ "added": "added", "added_by_on": "Added by __name__ on __date__", "adding": "Adding", + "additional_certificate": "Additional certificate", "additional_licenses": "Your subscription includes <0>__additionalLicenses__ additional license(s) for a total of <1>__totalLicenses__ licenses.", "address": "Address", "address_line_1": "Address", diff --git a/services/web/migrations/20231025094810_sso_config_certificates_array.js b/services/web/migrations/20231025094810_sso_config_certificates_array.js new file mode 100644 index 0000000000..c9ad073485 --- /dev/null +++ b/services/web/migrations/20231025094810_sso_config_certificates_array.js @@ -0,0 +1,35 @@ +exports.tags = ['saas'] + +exports.migrate = async client => { + const { db } = client + await db.ssoConfigs.updateMany( + { certificate: { $exists: true }, certificates: { $exists: false } }, + [ + { $set: { certificates: ['$certificate'] } }, + { + $unset: 'certificate', + }, + ] + ) + await db.ssoConfigs.updateMany( + { userFirstNameAttribute: null }, + { $unset: { userFirstNameAttribute: true } } + ) + await db.ssoConfigs.updateMany( + { userLastNameAttribute: null }, + { $unset: { userLastNameAttribute: true } } + ) +} + +exports.rollback = async client => { + const { db } = client + await db.ssoConfigs.updateMany( + { certificate: { $exists: false }, certificates: { $exists: true } }, + [ + { $set: { certificate: { $arrayElemAt: ['$certificates', 0] } } }, + { + $unset: 'certificates', + }, + ] + ) +} diff --git a/services/web/test/frontend/features/group-management/components/sso/group-settings-sso.spec.tsx b/services/web/test/frontend/features/group-management/components/sso/group-settings-sso.spec.tsx index 4c4cc13ec4..927d260814 100644 --- a/services/web/test/frontend/features/group-management/components/sso/group-settings-sso.spec.tsx +++ b/services/web/test/frontend/features/group-management/components/sso/group-settings-sso.spec.tsx @@ -48,7 +48,7 @@ describe('GroupSettingsSSO', function () { statusCode: 200, body: { entryPoint: 'entrypoint', - certificate: 'cert', + certificates: ['cert1', 'cert2'], signatureAlgorithm: 'sha1', userIdAttribute: 'email', enabled: true, @@ -66,12 +66,13 @@ describe('GroupSettingsSSO', function () { }) }) }) + it('updates the configuration, and checks the success message', function () { cy.intercept('GET', `/manage/groups/${GROUP_ID}/settings/sso`, { statusCode: 200, body: { entryPoint: 'entrypoint', - certificate: 'cert', + certificates: ['cert'], signatureAlgorithm: 'sha1', userIdAttribute: 'email', enabled: true, @@ -82,7 +83,7 @@ describe('GroupSettingsSSO', function () { statusCode: 200, body: { entryPoint: 'entrypoint', - certificate: 'certi', + certificates: ['certi'], signatureAlgorithm: 'sha1', userIdAttribute: 'email', enabled: false, @@ -113,7 +114,7 @@ describe('GroupSettingsSSO', function () { statusCode: 200, body: { entryPoint: 'entrypoint', - certificate: 'cert', + certificates: ['cert'], signatureAlgorithm: 'sha1', userIdAttribute: 'email', enabled: false, @@ -156,7 +157,7 @@ describe('GroupSettingsSSO', function () { statusCode: 200, body: { entryPoint: 'entrypoint', - certificate: 'cert', + certificates: ['cert'], signatureAlgorithm: 'sha1', userIdAttribute: 'email', enabled: true, @@ -176,13 +177,14 @@ describe('GroupSettingsSSO', function () { cy.findByText('SSO is enabled') }) }) + describe('SSO disable modal', function () { beforeEach(function () { cy.intercept('GET', `/manage/groups/${GROUP_ID}/settings/sso`, { statusCode: 200, body: { entryPoint: 'entrypoint', - certificate: 'cert', + certificates: ['cert'], signatureAlgorithm: 'sha1', userIdAttribute: 'email', enabled: true, @@ -227,7 +229,7 @@ describe('GroupSettingsSSO', function () { statusCode: 200, body: { entryPoint: 'entrypoint', - certificate: 'cert', + certificates: ['cert'], signatureAlgorithm: 'sha1', userIdAttribute: 'email', enabled: false, diff --git a/services/web/types/subscription/sso.ts b/services/web/types/subscription/sso.ts index 78a2a29b0c..faf66ac871 100644 --- a/services/web/types/subscription/sso.ts +++ b/services/web/types/subscription/sso.ts @@ -1,6 +1,6 @@ export type SSOConfig = { entryPoint?: string - certificate?: string + certificates: (string | undefined)[] signatureAlgorithm: 'sha1' | 'sha256' | 'sha512' userIdAttribute?: string userFirstNameAttribute?: string