From 827fb7119c33dc04abd5ac2a40c0af4aa1a9e7b2 Mon Sep 17 00:00:00 2001 From: Jessica Lawshe Date: Mon, 9 Dec 2019 09:10:07 -0600 Subject: [PATCH] Merge pull request #2444 from overleaf/jel-beta-test-saml Refactor account setttings SSO UI checks and allow beta testing GitOrigin-RevId: 882c6aed107a2facfb0941bc49ef6cbd86473efb --- .../views/user/settings/user-affiliations.pug | 84 +++++++++---------- .../controllers/UserAffiliationsController.js | 63 +++++++------- 2 files changed, 73 insertions(+), 74 deletions(-) diff --git a/services/web/app/views/user/settings/user-affiliations.pug b/services/web/app/views/user/settings/user-affiliations.pug index 11544fd11f..cb972f2801 100644 --- a/services/web/app/views/user/settings/user-affiliations.pug +++ b/services/web/app/views/user/settings/user-affiliations.pug @@ -33,12 +33,12 @@ form.row( | {{ userEmail.email + (userEmail.default ? ' (primary)' : '') }} div(ng-if="!userEmail.confirmedAt").small strong #{translate('unconfirmed')}. - span(ng-if="!hasSamlFeature || (hasSamlFeature && !userEmail.affiliation.institution.ssoEnabled)")  #{translate('please_check_your_inbox')}. + span(ng-if="!userEmail.ssoAvailable")  #{translate('please_check_your_inbox')}. br a( href, ng-click="resendConfirmationEmail(userEmail)", - ng-if="!hasSamlFeature || (hasSamlFeature && !userEmail.affiliation.institution.ssoEnabled)" + ng-if="!userEmail.ssoAvailable" ) #{translate('resend_confirmation_email')} div(ng-if="userEmail.confirmedAt && userEmail.affiliation.institution && userEmail.affiliation.institution.confirmed && userEmail.affiliation.institution.licence != 'free'").small span.label.label-primary #{translate("professional")} @@ -84,9 +84,9 @@ form.row( td.affiliations-table-inline-actions // Disabled buttons don't work with tooltips, due to pointer-events: none, // so create a wrapper for the tooltip - .affiliations-table-inline-action-disabled-wrapper(ng-if="showInstitutionTooltip(userEmail)") + .affiliations-table-inline-action-disabled-wrapper(ng-if="userEmail.ssoAvailable") +btnMakePrimaryDisabled("Please confirm your email by linking to your institutional account before making it the primary email.") - .affiliations-table-inline-action-disabled-wrapper(ng-if="!showInstitutionTooltip(userEmail)") + .affiliations-table-inline-action-disabled-wrapper(ng-if="!userEmail.ssoAvailable") +btnMakePrimaryDisabled(translate("please_confirm_your_email_before_making_it_default")) button.btn.btn-sm.btn-success.affiliations-table-inline-action( tooltip=translate("make_email_primary_description") @@ -104,28 +104,27 @@ form.row( ) i.fa.fa-fw.fa-trash(aria-hidden="true") span.sr-only #{translate("remove")} - tr.affiliations-table-saml-row(ng-repeat-end ng-if="userEmail.affiliation && userEmail.affiliation && userEmail.affiliation.institution.ssoEnabled") - if hasFeature('saml') || samlBeta - td - td(ng-attr-colspan="{{userEmail.samlProviderId ? '2' : '1'}}" ng-class="institutionAlreadyLinked(userEmail) ? '' : 'with-border'") - p.small(ng-if="userEmail.samlProviderId") - | !{translate("acct_linked_to_institution_acct", {institutionName: '{{userEmail.affiliation.institution.name}}'})} - div(ng-if="!userEmail.samlProviderId && !institutionAlreadyLinked(userEmail)") - //- this email is not linked to institution login but - //- cannot have multiple emails at same institution linked for "institution login" - //- so check if institution is already linked - p.small - | !{translate("can_link_your_institution_acct", {institutionName: '{{userEmail.affiliation.institution.name}}'})} - p.small - | !{translate("doing_this_allow_log_in_through_institution")}  - +aboutInstitutionLink() - td.with-border.affiliations-table-inline-actions(ng-if="!userEmail.samlProviderId && !institutionAlreadyLinked(userEmail)") - button.btn-sm.btn.btn-info( - ng-click="linkInstitutionAcct(userEmail.email, userEmail.affiliation.institution.id)" - ng-disabled="ui.isMakingRequest" - type="button" - ) - | #{translate("link_accounts")} + tr.affiliations-table-saml-row(ng-repeat-end ng-if="userEmail.affiliation && userEmail.affiliation && userEmail.ssoAvailable") + td + td(ng-attr-colspan="{{userEmail.samlProviderId ? '2' : '1'}}" ng-class="institutionAlreadyLinked(userEmail) ? '' : 'with-border'") + p.small(ng-if="userEmail.samlProviderId") + | !{translate("acct_linked_to_institution_acct", {institutionName: '{{userEmail.affiliation.institution.name}}'})} + div(ng-if="!userEmail.samlProviderId && !institutionAlreadyLinked(userEmail)") + //- this email is not linked to institution login but + //- cannot have multiple emails at same institution linked for "institution login" + //- so check if institution is already linked + p.small + | !{translate("can_link_your_institution_acct", {institutionName: '{{userEmail.affiliation.institution.name}}'})} + p.small + | !{translate("doing_this_allow_log_in_through_institution")}  + +aboutInstitutionLink() + td.with-border.affiliations-table-inline-actions(ng-if="!userEmail.samlProviderId && !institutionAlreadyLinked(userEmail)") + button.btn-sm.btn.btn-info( + ng-click="linkInstitutionAcct(userEmail.email, userEmail.affiliation.institution.id)" + ng-disabled="ui.isMakingRequest" + type="button" + ) + | #{translate("link_accounts")} tr.affiliations-table-highlighted-row( ng-if="!ui.showAddEmailUI && !ui.isMakingRequest" ) @@ -151,23 +150,22 @@ form.row( input-type="email" input-required="true" ) - if hasFeature('saml') || samlBeta - td( - colspan="2" - ng-if="newAffiliation && newAffiliation.university && newAffiliation.university.ssoEnabled" - ) - p.affiliations-table-label {{ newAffiliation.university.name }} - p !{translate("to_add_email_accounts_need_to_be_linked", {institutionName: "{{newAffiliation.university.name}}"})} - p !{translate("doing_this_will_verify_affiliation_and_allow_log_in", {institutionName: "{{newAffiliation.university.name}}"})}  - +aboutInstitutionLink() - button.btn-sm.btn.btn-primary.btn-link-accounts( - ng-click="linkInstitutionAcct(newAffiliation.email, newAffiliation.university.id)" - ng-disabled="ui.isMakingRequest" - type="button" - ) - | #{translate("link_accounts_and_add_email")} td( - ng-if="shouldShowRolesAndAddEmailButton()" + colspan="2" + ng-if="newAffiliation.ssoAvailable" + ) + p.affiliations-table-label {{ newAffiliation.university.name }} + p !{translate("to_add_email_accounts_need_to_be_linked", {institutionName: "{{newAffiliation.university.name}}"})} + p !{translate("doing_this_will_verify_affiliation_and_allow_log_in", {institutionName: "{{newAffiliation.university.name}}"})}  + +aboutInstitutionLink() + button.btn-sm.btn.btn-primary.btn-link-accounts( + ng-click="linkInstitutionAcct(newAffiliation.email, newAffiliation.university.id)" + ng-disabled="ui.isMakingRequest" + type="button" + ) + | #{translate("link_accounts_and_add_email")} + td( + ng-if="!newAffiliation.ssoAvailable" ) p.affiliations-table-label( ng-if="newAffiliation.university && !ui.showManualUniversitySelectionUI" @@ -198,7 +196,7 @@ form.row( show-role-and-department="ui.isValidEmail && newAffiliation.university" ) td( - ng-if="shouldShowRolesAndAddEmailButton()" + ng-if="!newAffiliation.ssoAvailable" ) button.btn.btn-sm.btn-primary( ng-disabled="affiliationsForm.$invalid || ui.isMakingRequest" diff --git a/services/web/frontend/js/main/affiliations/controllers/UserAffiliationsController.js b/services/web/frontend/js/main/affiliations/controllers/UserAffiliationsController.js index 7caf55e815..32dd4fc275 100644 --- a/services/web/frontend/js/main/affiliations/controllers/UserAffiliationsController.js +++ b/services/web/frontend/js/main/affiliations/controllers/UserAffiliationsController.js @@ -14,6 +14,7 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ + define(['base'], App => App.controller('UserAffiliationsController', function( $scope, @@ -28,36 +29,9 @@ define(['base'], App => $scope.closeInstitutionNotification = type => { $scope.hideInstitutionNotifications[type] = true } - $scope.hasSamlBeta = ExposedSettings.hasSamlBeta - $scope.hasSamlFeature = ExposedSettings.hasSamlFeature - $scope.canUseSamlFeature = $scope.hasSamlFeature || $scope.hasSamlBeta + $scope.samlBetaSession = ExposedSettings.hasSamlBeta $scope.samlInitPath = ExposedSettings.samlInitPath - $scope.showInstitutionTooltip = emailData => { - if (!emailData.affiliation || !$scope.canUseSamlFeature) { - return false - } - if ( - emailData.affiliation.institution && - emailData.affiliation.institution.ssoEnabled - ) { - return true - } - return false - } - $scope.shouldShowRolesAndAddEmailButton = () => { - const newAffiliation = $scope.newAffiliation - return ( - !newAffiliation || - (newAffiliation && !newAffiliation.university) || - (!$scope.canUseSamlFeature && - newAffiliation && - newAffiliation.university) || - ($scope.canUseSamlFeature && - newAffiliation && - newAffiliation.university && - !newAffiliation.university.ssoEnabled) - ) - } + const LOCAL_AND_DOMAIN_REGEX = /([^@]+)@(.+)/ const EMAIL_REGEX = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\ ".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA -Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ @@ -72,6 +46,27 @@ define(['base'], App => return { local: null, domain: null } } } + const _ssoAvailable = affiliation => { + if (!affiliation) { + return false + } + + // university via v1 for new affiliations + const institution = affiliation.university || affiliation.institution + if (!institution) { + return false + } + + if (institution && institution.ssoEnabled) { + return true + } + + if ($scope.samlBetaSession && institution && institution.ssoBeta) { + return true + } + + return false + } $scope.getEmailSuggestion = function(userInput) { const userInputLocalAndDomain = _matchLocalAndDomain(userInput) @@ -95,6 +90,9 @@ define(['base'], App => ) { $scope.newAffiliation.university = universityDomain.university $scope.newAffiliation.department = universityDomain.department + $scope.newAffiliation.ssoAvailable = _ssoAvailable( + universityDomain + ) } else { $scope.newAffiliation.university = null $scope.newAffiliation.department = null @@ -314,9 +312,12 @@ define(['base'], App => var _getUserEmails = function() { _resetMakingRequestType() $scope.ui.isLoadingEmails = true - return _monitorRequest(UserAffiliationsDataService.getUserEmails()) + _monitorRequest(UserAffiliationsDataService.getUserEmails()) .then(emails => { - $scope.userEmails = emails + $scope.userEmails = emails.map(email => { + email.ssoAvailable = _ssoAvailable(email.affiliation) + return email + }) $scope.linkedInstitutionIds = emails .filter(email => { if (email.samlProviderId) {