Преглед изворни кода

Add linked accounts section to user settings page (#1705)

Add linked accounts section to user settings page

GitOrigin-RevId: d2bb26a3bfb3946144a05b98f58d50a2c57f3040
Timothée Alby пре 7 година
родитељ
комит
54186d9db1

+ 8 - 0
services/web/app/coffee/Features/Authentication/AuthenticationController.coffee

@@ -31,6 +31,7 @@ module.exports = AuthenticationController =
 			session_created: (new Date()).toISOString()
 			session_created: (new Date()).toISOString()
 			ip_address: user._login_req_ip
 			ip_address: user._login_req_ip
 			must_reconfirm: user.must_reconfirm
 			must_reconfirm: user.must_reconfirm
+			v1_id: user.overleaf?.id
 		callback(null, lightUser)
 		callback(null, lightUser)
 
 
 	deserializeUser: (user, cb) ->
 	deserializeUser: (user, cb) ->
@@ -160,6 +161,13 @@ module.exports = AuthenticationController =
 		else
 		else
 			return null
 			return null
 
 
+	getLoggedInUserV1Id: (req) ->
+		user = AuthenticationController.getSessionUser(req)
+		if user?.v1_id?
+			return user.v1_id
+		else
+			return null
+
 	getSessionUser: (req) ->
 	getSessionUser: (req) ->
 		if req?.session?.user?
 		if req?.session?.user?
 			return req.session.user
 			return req.session.user

+ 2 - 0
services/web/app/coffee/infrastructure/Features.coffee

@@ -18,6 +18,8 @@ module.exports = Features =
 				return Settings.accountMerge? and Settings.overleaf? and !Settings.forceImportToV2
 				return Settings.accountMerge? and Settings.overleaf? and !Settings.forceImportToV2
 			when 'custom-togglers'
 			when 'custom-togglers'
 				return Settings.overleaf?
 				return Settings.overleaf?
+			when 'oauth'
+				return Settings.oauth?
 			when 'publish-templates'
 			when 'publish-templates'
 				return true
 				return true
 			when 'view-templates'
 			when 'view-templates'

+ 7 - 3
services/web/app/views/user/settings.pug

@@ -9,9 +9,10 @@ block content
 						.page-header
 						.page-header
 							h1  #{translate("account_settings")}
 							h1  #{translate("account_settings")}
 						.account-settings(ng-controller="AccountSettingsController", ng-cloak)
 						.account-settings(ng-controller="AccountSettingsController", ng-cloak)
+
 							if hasFeature('affiliations')
 							if hasFeature('affiliations')
 								include settings/user-affiliations
 								include settings/user-affiliations
-								
+
 							form-messages(for="settingsForm")
 							form-messages(for="settingsForm")
 								.alert.alert-success(ng-show="settingsForm.response.success")
 								.alert.alert-success(ng-show="settingsForm.response.success")
 									|  #{translate("thanks_settings_updated")}
 									|  #{translate("thanks_settings_updated")}
@@ -145,7 +146,7 @@ block content
 
 
 							| !{moduleIncludes("userSettings", locals)}
 							| !{moduleIncludes("userSettings", locals)}
 							hr
 							hr
-							
+
 							h3
 							h3
 								| #{translate("sharelatex_beta_program")}
 								| #{translate("sharelatex_beta_program")}
 							
 							
@@ -164,13 +165,16 @@ block content
 							div
 							div
 								a(id="sessions-link", href="/user/sessions") #{translate("manage_sessions")}
 								a(id="sessions-link", href="/user/sessions") #{translate("manage_sessions")}
 
 
-							if settings.overleaf
+							if settings.overleaf && !hasFeature('oauth')
 								hr
 								hr
 								p
 								p
 									| To manage your account's connection to Google, Twitter, ORCID and IEEE, please
 									| To manage your account's connection to Google, Twitter, ORCID and IEEE, please
 									|
 									|
 									a(href="/sign_in_to_v1?return_to=/users/edit#linked-accounts") click here
 									a(href="/sign_in_to_v1?return_to=/users/edit#linked-accounts") click here
 									| .
 									| .
+							else if hasFeature('oauth')
+								hr
+								include settings/user-oauth
 
 
 							hr
 							hr
 
 

+ 35 - 0
services/web/app/views/user/settings/user-oauth.pug

@@ -0,0 +1,35 @@
+form.row(
+	ng-controller="UserOauthController"
+	name="oauthForm"
+	ng-cloak
+)
+	.col-xs-12
+		h3.text-capitalize #{translate("linked_accounts")}
+		p.small #{translate("linked_accounts_explained", {appName:'{{settings.appName}}'})}
+
+		div.text-center(ng-if="ui.isLoadingProviders") 
+			i.fa.fa-fw.fa-spin.fa-refresh(aria-hidden="true")
+			|  #{translate("loading")}...
+
+		ul(
+			class="list-like-table"
+			ng-if="ui.isLoadingProviders == false && ui.hasError == false"
+		)
+			li(ng-repeat="provider in providers")
+				.row
+					.col-xs-12.col-sm-8.col-md-10
+						h4 {{provider.name}}
+						p.small(ng-if="provider.key != 'orcid'")
+							| #{translate("login_with_service", {service:'{{provider.name}}'})}
+						p.small(ng-if="provider.key == 'orcid'")
+							| !{translate('oauth_orcid_description', {link: '/blog/434'})}
+					.col-xs-2.col-sm-4.col-md-2.text-right
+						button.btn.btn-default(ng-if="userProviders[provider.key]") #{translate("unlink")}
+						button.btn.btn-primary(ng-if="!userProviders[provider.key]")  #{translate("link")}
+
+		.alert.alert-danger(
+			ng-if="ui.hasError"
+		)
+			i.fa.fa-fw.fa-exclamation-triangle(aria-hidden="true")
+			span(ng-if="!ui.errorMessage")  #{translate("error_performing_request")}
+			span(ng-if="ui.errorMessage")  {{ui.errorMessage}}

+ 2 - 0
services/web/public/src/main.js

@@ -33,6 +33,8 @@ define([
   'main/affiliations/components/affiliationForm',
   'main/affiliations/components/affiliationForm',
   'main/affiliations/controllers/UserAffiliationsController',
   'main/affiliations/controllers/UserAffiliationsController',
   'main/affiliations/factories/UserAffiliationsDataService',
   'main/affiliations/factories/UserAffiliationsDataService',
+  'main/oauth/factories/UserOauthDataService',
+  'main/oauth/controllers/UserOauthController',
   'main/keys',
   'main/keys',
   'main/cms/blog',
   'main/cms/blog',
   'main/cms/index',
   'main/cms/index',

+ 3 - 1
services/web/public/src/main/account-settings.js

@@ -20,12 +20,14 @@ define(['base'], function(App) {
     '$modal',
     '$modal',
     'event_tracking',
     'event_tracking',
     'UserAffiliationsDataService',
     'UserAffiliationsDataService',
+    'UserOauthDataService',
     function(
     function(
       $scope,
       $scope,
       $http,
       $http,
       $modal,
       $modal,
       event_tracking,
       event_tracking,
-      UserAffiliationsDataService
+      UserAffiliationsDataService,
+      UserOauthDataService
     ) {
     ) {
       $scope.subscribed = true
       $scope.subscribed = true
 
 

+ 48 - 0
services/web/public/src/main/oauth/controllers/UserOauthController.js

@@ -0,0 +1,48 @@
+define(['base'], App =>
+  App.controller('UserOauthController', [
+    '$scope',
+    '$q',
+    '_',
+    'UserOauthDataService',
+    function($scope, $q, _, UserOauthDataService) {
+      $scope.providers = [
+        { key: 'google', name: 'Google' },
+        { key: 'orcid', name: 'Orcid' },
+        { key: 'twitter', name: 'Twitter' }
+      ]
+      const _monitorRequest = function(promise) {
+        $scope.ui.hasError = false
+        $scope.ui.isLoadingProviders = true
+        promise
+          .catch(response => {
+            $scope.ui.hasError = true
+            $scope.ui.errorMessage =
+              response && response.data && response.data.message
+                ? response.data.message
+                : 'error'
+          })
+          .finally(() => {
+            $scope.ui.isLoadingProviders = false
+          })
+        return promise
+      }
+      const _reset = function() {
+        $scope.ui = {
+          hasError: false,
+          errorMessage: '',
+          isLoadingProviders: false
+        }
+        $scope.userProviders = {}
+      }
+      const _getUserV1OauthProviders = () => {
+        $scope.ui.isLoadingProviders = true
+        return _monitorRequest(UserOauthDataService.getUserOauthV1()).then(
+          userProviders => {
+            $scope.userProviders = userProviders
+          }
+        )
+      }
+      _reset()
+      return _getUserV1OauthProviders()
+    }
+  ]))

+ 20 - 0
services/web/public/src/main/oauth/factories/UserOauthDataService.js

@@ -0,0 +1,20 @@
+define(['base'], function(App) {
+  return App.factory('UserOauthDataService', [
+    '$http',
+    function($http) {
+      const getUserOauthV1 = () => {
+        if (window.ExposedSettings.isOverleaf) {
+          return $http.get('/user/v1-oauth-uids').then(response => {
+            return response.data
+          })
+        } else {
+          return {}
+        }
+      }
+
+      return {
+        getUserOauthV1
+      }
+    }
+  ])
+})

+ 1 - 0
services/web/public/stylesheets/_ol_style_includes.less

@@ -8,4 +8,5 @@
 @import "app/publisher-hub.less";
 @import "app/publisher-hub.less";
 @import "app/admin-hub.less";
 @import "app/admin-hub.less";
 @import "app/import.less";
 @import "app/import.less";
+@import "components/lists.less";
 @import "components/overbox.less";
 @import "components/overbox.less";

+ 22 - 0
services/web/public/stylesheets/components/lists.less

@@ -0,0 +1,22 @@
+.list-like-table {
+	border: 1px solid @hr-border;
+	border-radius: @border-radius-base;
+	list-style: none;
+	margin: 0;
+	padding: @padding-sm;
+	li {
+		border-top: 1px solid @hr-border;
+		div {
+			display: table-cell;
+			float: none;
+			vertical-align: middle;
+		}
+		.row {
+			display: table;
+			width: 100%;
+		}
+		&:first-child {
+			border-top: 0;
+		}
+	}
+}