From 074d457f98c148da0ad29568fc75baa50c8bfc3d Mon Sep 17 00:00:00 2001 From: nate stemen Date: Thu, 2 Jan 2020 14:22:06 -0500 Subject: [PATCH] Merge pull request #2466 from overleaf/jel-sso-beta-dashboard Beta testing SSO on the dashboard GitOrigin-RevId: 9899f0ed0212180fde40e9e19bfd53bccafa3e7a --- .../src/Features/Project/ProjectController.js | 28 ++++++---- .../project-list/notifications-controller.js | 20 ++++--- .../src/Project/ProjectControllerTests.js | 52 ++++++++++++++++--- 3 files changed, 77 insertions(+), 23 deletions(-) diff --git a/services/web/app/src/Features/Project/ProjectController.js b/services/web/app/src/Features/Project/ProjectController.js index 893d99cb8c..6afa5ca0ee 100644 --- a/services/web/app/src/Features/Project/ProjectController.js +++ b/services/web/app/src/Features/Project/ProjectController.js @@ -38,6 +38,21 @@ const V1Handler = require('../V1/V1Handler') const UserController = require('../User/UserController') const SystemMessageManager = require('../SystemMessages/SystemMessageManager') +const _ssoAvailable = (affiliation, session, linkedInstitutionIds) => { + if (!affiliation.institution) return false + + // Could have multiple emails at the same institution, and if any are + // linked to the institution then do not show notification for others + if ( + linkedInstitutionIds.indexOf(affiliation.institution.id.toString()) === -1 + ) { + if (affiliation.institution.ssoEnabled) return true + if (affiliation.institution.ssoBeta && session.samlBeta) return true + return false + } + return false +} + const ProjectController = { _isInPercentageRollout(rolloutName, objectId, percentage) { if (Settings.bypassPercentageRollouts === true) { @@ -440,28 +455,19 @@ const ProjectController = { } // Institution SSO Notifications - if (Features.hasFeature('saml') || req.session.samlBeta) { + if (Features.hasFeature('saml')) { const samlSession = req.session.saml // Notification: SSO Available - // Could have multiple emails at the same institution, and if any are - // linked to the institution then do not show notification for others const linkedInstitutionIds = [] - const linkedInstitutionEmails = [] user.emails.forEach(email => { if (email.samlProviderId) { - linkedInstitutionEmails.push(email.email) linkedInstitutionIds.push(email.samlProviderId) } }) if (Array.isArray(userAffiliations)) { userAffiliations.forEach(affiliation => { if ( - affiliation.institution && - affiliation.institution.ssoEnabled && - linkedInstitutionEmails.indexOf(affiliation.email) === -1 && - linkedInstitutionIds.indexOf( - affiliation.institution.id.toString() - ) === -1 + _ssoAvailable(affiliation, req.session, linkedInstitutionIds) ) { notificationsInstitution.push({ email: affiliation.email, diff --git a/services/web/frontend/js/main/project-list/notifications-controller.js b/services/web/frontend/js/main/project-list/notifications-controller.js index 011774b081..5eef6ce7dc 100644 --- a/services/web/frontend/js/main/project-list/notifications-controller.js +++ b/services/web/frontend/js/main/project-list/notifications-controller.js @@ -101,21 +101,29 @@ define(['base'], function(App) { UserAffiliationsDataService ) { $scope.userEmails = [] + const _ssoAvailable = email => { + if (!ExposedSettings.hasSamlFeature) return false + if (!email.affiliation || !email.affiliation.institution) return false + if (email.affiliation.institution.ssoEnabled) return true + if ( + ExposedSettings.hasSamlBeta && + email.affiliation.institution.ssoBeta + ) { + return true + } + return false + } $scope.showConfirmEmail = email => { if (ExposedSettings.emailConfirmationDisabled) { return false } if (!email.confirmedAt && !email.hide) { - if ( - email.affiliation && - email.affiliation.institution && - email.affiliation.institution.ssoEnabled && - (ExposedSettings.hasSamlBeta || ExposedSettings.hasSamlFeature) - ) { + if (_ssoAvailable(email)) { return false } return true } + return false } for (let userEmail of Array.from($scope.userEmails)) { userEmail.hide = false diff --git a/services/web/test/unit/src/Project/ProjectControllerTests.js b/services/web/test/unit/src/Project/ProjectControllerTests.js index be3f9ba370..ff4a760e65 100644 --- a/services/web/test/unit/src/Project/ProjectControllerTests.js +++ b/services/web/test/unit/src/Project/ProjectControllerTests.js @@ -110,10 +110,7 @@ describe('ProjectController', function() { } } this.Features = { - hasFeature: sinon - .stub() - .withArgs('saml') - .returns(false) + hasFeature: sinon.stub() } this.BrandVariationsHandler = { getBrandVariationById: sinon @@ -129,6 +126,7 @@ describe('ProjectController', function() { institution: { id: 1, name: 'Overleaf', + ssoBeta: false, ssoEnabled: true } } @@ -705,11 +703,13 @@ describe('ProjectController', function() { }) }) - describe('When Institution SSO is released', function() { + describe('With Institution SSO feature', function() { beforeEach(function(done) { this.institutionEmail = 'test@overleaf.com' this.institutionName = 'Overleaf' this.Features.hasFeature.withArgs('saml').returns(true) + this.Features.hasFeature.withArgs('affiliations').returns(true) + this.Features.hasFeature.withArgs('overleaf-integration').returns(true) done() }) it('should show institution SSO available notification', function() { @@ -849,9 +849,49 @@ describe('ProjectController', function() { this.ProjectController.projectListPage(this.req, this.res) }) }) + describe('Institution with SSO beta testable', function() { + beforeEach(function(done) { + this.getUserAffiliations.yields(null, [ + { + email: 'beta@beta.com', + institution: { + id: 2, + name: 'Beta University', + ssoBeta: true, + ssoEnabled: false + } + } + ]) + done() + }) + it('should show institution SSO available notification when on a beta testing session', function() { + this.req.session.samlBeta = true + this.res.render = (pageName, opts) => { + expect(opts.notificationsInstitution).to.deep.include({ + email: 'beta@beta.com', + institutionId: 2, + institutionName: 'Beta University', + templateKey: 'notification_institution_sso_available' + }) + } + this.ProjectController.projectListPage(this.req, this.res) + }) + it('should not show institution SSO available notification when not on a beta testing session', function() { + this.req.session.samlBeta = false + this.res.render = (pageName, opts) => { + expect(opts.notificationsInstitution).to.deep.not.include({ + email: 'test@overleaf.com', + institutionId: 1, + institutionName: 'Overleaf', + templateKey: 'notification_institution_sso_available' + }) + } + this.ProjectController.projectListPage(this.req, this.res) + }) + }) }) - describe('When Institution SSO is not released', function() { + describe('Without Institution SSO feature', function() { beforeEach(function(done) { this.Features.hasFeature.withArgs('saml').returns(false) done()