Просмотр исходного кода

Merge pull request #17569 from overleaf/tm-account-suspension

Add the ability to suspend user accounts

GitOrigin-RevId: 5e57f29941434c78a47354baca83527213f9b9b5
Thomas 2 лет назад
Родитель
Сommit
811173d32d

+ 4 - 0
services/web/app/src/Features/Authentication/AuthenticationController.js

@@ -121,6 +121,10 @@ const AuthenticationController = {
       return AsyncFormHelper.redirect(req, res, '/login')
     } // OAuth2 'state' mismatch
 
+    if (user.suspended) {
+      return AsyncFormHelper.redirect(req, res, '/account-suspended')
+    }
+
     if (Settings.adminOnlyLogin && !hasAdminAccess(user)) {
       return res.status(403).json({
         message: { type: 'error', text: 'Admin only panel' },

+ 11 - 0
services/web/app/src/Features/User/UserPagesController.js

@@ -196,7 +196,18 @@ async function settingsPage(req, res) {
   })
 }
 
+async function accountSuspended(req, res) {
+  if (SessionManager.isUserLoggedIn(req.session)) {
+    return res.redirect('/project')
+  }
+  res.render('user/accountSuspended', {
+    title: 'your_account_is_suspended',
+  })
+}
+
 const UserPagesController = {
+  accountSuspended: expressify(accountSuspended),
+
   registerPage(req, res) {
     const sharedProjectData = {
       project_name: req.query.project_name,

+ 1 - 0
services/web/app/src/models/User.js

@@ -196,6 +196,7 @@ const UserSchema = new Schema(
     splitTests: Schema.Types.Mixed,
     analyticsId: { type: String },
     completedTutorials: Schema.Types.Mixed,
+    suspended: { type: Boolean },
   },
   { minimize: false }
 )

+ 2 - 0
services/web/app/src/router.js

@@ -224,6 +224,8 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
     AuthenticationController.passportLogin
   )
 
+  webRouter.get('/account-suspended', UserPagesController.accountSuspended)
+
   if (Settings.enableLegacyLogin) {
     AuthenticationController.addEndpointToLoginWhitelist('/login/legacy')
     webRouter.get('/login/legacy', UserPagesController.loginPage)

+ 14 - 0
services/web/app/views/user/accountSuspended.pug

@@ -0,0 +1,14 @@
+extends ../layout-marketing
+
+block vars
+	- var suppressNavbar = true
+	- var suppressFooter = true
+	- metadata.robotsNoindexNofollow = true
+
+block content
+	main.content.content-alt#main-content
+		.container-custom-sm.mx-auto
+			.card
+				h3 #{translate('your_account_is_suspended')}
+				p #{translate('sorry_this_account_has_been_suspended')}
+				p !{translate('please_contact_us_if_you_think_this_is_in_error', {}, [{name: 'a', attrs: {href: `mailto:${settings.adminEmail}`}}])}

+ 3 - 0
services/web/locales/en.json

@@ -1335,6 +1335,7 @@
   "please_confirm_email": "Please confirm your email __emailAddress__ by clicking on the link in the confirmation email ",
   "please_confirm_your_email_before_making_it_default": "Please confirm your email before making it the primary.",
   "please_contact_support_to_makes_change_to_your_plan": "Please <0>contact support</0> to make changes to your plan",
+  "please_contact_us_if_you_think_this_is_in_error": "Please <0>contact us</0> if you think this is in error.",
   "please_enter_confirmation_code": "Please enter your confirmation code",
   "please_enter_email": "Please enter your email address",
   "please_get_in_touch": "Please get in touch",
@@ -1714,6 +1715,7 @@
   "sorry_detected_sales_restricted_region": "Sorry, we’ve detected that you are in a region from which we cannot presently accept payments. If you think you’ve received this message in error, please <a href=\"__link__\">contact us</a> with details of your location, and we will look into this for you. We apologize for the inconvenience.",
   "sorry_something_went_wrong_opening_the_document_please_try_again": "Sorry, an unexpected error occurred when trying to open this content on Overleaf. Please try again.",
   "sorry_the_connection_to_the_server_is_down": "Sorry, the connection to the server is down.",
+  "sorry_this_account_has_been_suspended": "Sorry, this account has been suspended.",
   "sorry_your_table_cant_be_displayed_at_the_moment": "Sorry, your table can’t be displayed at the moment.",
   "sorry_your_token_expired": "Sorry, your token expired",
   "sort_by": "Sort by",
@@ -2209,6 +2211,7 @@
   "youll_need_to_ask_the_github_repository_owner": "You’ll need to ask the GitHub repository owner (<0>__repoOwnerEmail__</0>) to reconnect the project.",
   "youll_no_longer_need_to_remember_credentials": "You’ll no longer need to remember a separate email address and password. Instead, you will use single-sign on to login to Overleaf. <0>Read more about SSO</0>.",
   "your_account_is_managed_by_admin_cant_join_additional_group": "Your __appName__ account is managed by your current group admin (__admin__). This means you can’t join additional group subscriptions. <0>Read more about Managed Users.</0>",
+  "your_account_is_suspended": "Your account is suspended",
   "your_affiliation_is_confirmed": "Your <0>__institutionName__</0> affiliation is confirmed.",
   "your_browser_does_not_support_this_feature": "Sorry, your browser doesn’t support this feature. Please update your browser to its latest version.",
   "your_compile_timed_out": "Your compile timed out",

+ 4 - 0
services/web/test/acceptance/src/helpers/User.js

@@ -237,6 +237,10 @@ class User {
     UserModel.updateOne({ _id: this.id }, { emails }, callback)
   }
 
+  setSuspended(suspended, callback) {
+    UserModel.updateOne({ _id: this.id }, { suspended }, callback)
+  }
+
   logout(callback) {
     this.getCsrfToken(error => {
       if (error != null) {

+ 22 - 0
services/web/test/unit/src/Authentication/AuthenticationControllerTests.js

@@ -1188,6 +1188,28 @@ describe('AuthenticationController', function () {
       })
     })
 
+    describe('when user account is suspended', function () {
+      beforeEach(function () {
+        this.req.session = {}
+        this.user.suspended = true
+      })
+      it('should not log in and instead redirect to suspended account page', function () {
+        this.AuthenticationController.finishLogin(
+          this.user,
+          this.req,
+          this.res,
+          this.next
+        )
+        sinon.assert.notCalled(this.req.login)
+        sinon.assert.calledWith(
+          this.AsyncFormHelper.redirect,
+          this.req,
+          this.res,
+          '/account-suspended'
+        )
+      })
+    })
+
     describe('preFinishLogin hook', function () {
       it('call hook and proceed', function () {
         this.Modules.hooks.fire = sinon.stub().yields(null, [])