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

finish saml link after sso login

GitOrigin-RevId: 688ce78ddfb0cfd6a025985dc2dd6f62bce76523
Ersun Warncke 7 лет назад
Родитель
Сommit
8d44f44784

+ 174 - 162
services/web/app/src/Features/User/ThirdPartyIdentityManager.js

@@ -1,184 +1,196 @@
-const EmailHandler = require('../../../../app/src/Features/Email/EmailHandler')
+const APP_ROOT = '../../../../app/src'
+const EmailHandler = require(`${APP_ROOT}/Features/Email/EmailHandler`)
 const Errors = require('../Errors/Errors')
+const _ = require('lodash')
 const logger = require('logger-sharelatex')
-const { User } = require('../../models/User')
 const settings = require('settings-sharelatex')
-const _ = require('lodash')
+const { User } = require(`${APP_ROOT}/models/User`)
+const { promisifyAll } = require(`${APP_ROOT}/util/promises`)
 
 const oauthProviders = settings.oauthProviders || {}
 
-const ThirdPartyIdentityManager = (module.exports = {
-  getUser(providerId, externalUserId, callback) {
-    if (providerId == null || externalUserId == null) {
-      return callback(new Error('invalid arguments'))
+function getUser(providerId, externalUserId, callback) {
+  if (providerId == null || externalUserId == null) {
+    return callback(new Error('invalid arguments'))
+  }
+  const query = _getUserQuery(providerId, externalUserId)
+  User.findOne(query, function(err, user) {
+    if (err != null) {
+      return callback(err)
     }
-    const query = ThirdPartyIdentityManager._getUserQuery(
-      providerId,
-      externalUserId
-    )
-    User.findOne(query, function(err, user) {
-      if (err != null) {
-        return callback(err)
-      }
-      if (!user) {
-        return callback(new Errors.ThirdPartyUserNotFoundError())
-      }
-      callback(null, user)
-    })
-  },
-
-  login(providerId, externalUserId, externalData, callback) {
-    ThirdPartyIdentityManager.getUser(providerId, externalUserId, function(
-      err,
-      user
-    ) {
-      if (err != null) {
-        return callback(err)
-      }
-      if (!externalData) {
-        return callback(null, user)
-      }
-      const query = ThirdPartyIdentityManager._getUserQuery(
-        providerId,
-        externalUserId
-      )
-      const update = ThirdPartyIdentityManager._thirdPartyIdentifierUpdate(
-        user,
-        providerId,
-        externalUserId,
-        externalData
-      )
-      User.findOneAndUpdate(query, update, { new: true }, callback)
-    })
-  },
-
-  _getUserQuery(providerId, externalUserId) {
-    externalUserId = externalUserId.toString()
-    providerId = providerId.toString()
-    const query = {
-      'thirdPartyIdentifiers.externalUserId': externalUserId,
-      'thirdPartyIdentifiers.providerId': providerId
+    if (!user) {
+      return callback(new Errors.ThirdPartyUserNotFoundError())
     }
-    return query
-  },
+    callback(null, user)
+  })
+}
 
-  _thirdPartyIdentifierUpdate(user, providerId, externalUserId, externalData) {
-    providerId = providerId.toString()
-    // get third party identifier object from array
-    const thirdPartyIdentifier = user.thirdPartyIdentifiers.find(
-      tpi =>
-        tpi.externalUserId === externalUserId && tpi.providerId === providerId
+function login(providerId, externalUserId, externalData, callback) {
+  ThirdPartyIdentityManager.getUser(providerId, externalUserId, function(
+    err,
+    user
+  ) {
+    if (err != null) {
+      return callback(err)
+    }
+    if (!externalData) {
+      return callback(null, user)
+    }
+    const query = _getUserQuery(providerId, externalUserId)
+    const update = _thirdPartyIdentifierUpdate(
+      user,
+      providerId,
+      externalUserId,
+      externalData
     )
-    // do recursive merge of new data over existing data
-    _.merge(thirdPartyIdentifier.externalData, externalData)
-    const update = { 'thirdPartyIdentifiers.$': thirdPartyIdentifier }
-    return update
-  },
-
-  // register: () ->
-  // this should be implemented once we move to having v2 as the master
-  // but for now we need to register with v1 then call link once that
-  // is complete
+    User.findOneAndUpdate(query, update, { new: true }, callback)
+  })
+}
 
-  link(userId, providerId, externalUserId, externalData, callback, retry) {
-    if (!oauthProviders[providerId]) {
-      return callback(new Error('Not a valid provider'))
+function link(
+  userId,
+  providerId,
+  externalUserId,
+  externalData,
+  callback,
+  retry
+) {
+  if (!oauthProviders[providerId]) {
+    return callback(new Error('Not a valid provider'))
+  }
+  const query = {
+    _id: userId,
+    'thirdPartyIdentifiers.providerId': {
+      $ne: providerId
     }
-    const query = {
-      _id: userId,
-      'thirdPartyIdentifiers.providerId': {
-        $ne: providerId
+  }
+  const update = {
+    $push: {
+      thirdPartyIdentifiers: {
+        externalUserId,
+        externalData,
+        providerId
       }
     }
-    const update = {
-      $push: {
-        thirdPartyIdentifiers: {
-          externalUserId,
-          externalData,
-          providerId
-        }
+  }
+  // add new tpi only if an entry for the provider does not exist
+  // projection includes thirdPartyIdentifiers for tests
+  User.findOneAndUpdate(query, update, { new: 1 }, (err, res) => {
+    if (err && err.code === 11000) {
+      callback(new Errors.ThirdPartyIdentityExistsError())
+    } else if (err != null) {
+      callback(err)
+    } else if (res) {
+      const emailOptions = {
+        to: res.email,
+        provider: oauthProviders[providerId].name
       }
-    }
-    // add new tpi only if an entry for the provider does not exist
-    // projection includes thirdPartyIdentifiers for tests
-    User.findOneAndUpdate(query, update, { new: 1 }, (err, res) => {
-      if (err && err.code === 11000) {
-        callback(new Errors.ThirdPartyIdentityExistsError())
-      } else if (err != null) {
-        callback(err)
-      } else if (res) {
-        const emailOptions = {
-          to: res.email,
-          provider: oauthProviders[providerId].name
-        }
-        EmailHandler.sendEmail(
-          'emailThirdPartyIdentifierLinked',
-          emailOptions,
-          error => {
-            if (error != null) {
-              logger.warn(error)
-            }
-            return callback(null, res)
+      EmailHandler.sendEmail(
+        'emailThirdPartyIdentifierLinked',
+        emailOptions,
+        error => {
+          if (error != null) {
+            logger.warn(error)
           }
+          return callback(null, res)
+        }
+      )
+    } else if (retry) {
+      // if already retried then throw error
+      callback(new Error('update failed'))
+    } else {
+      // attempt to clear existing entry then retry
+      ThirdPartyIdentityManager.unlink(userId, providerId, function(err) {
+        if (err != null) {
+          return callback(err)
+        }
+        ThirdPartyIdentityManager.link(
+          userId,
+          providerId,
+          externalUserId,
+          externalData,
+          callback,
+          true
         )
-      } else if (retry) {
-        // if already retried then throw error
-        callback(new Error('update failed'))
-      } else {
-        // attempt to clear existing entry then retry
-        ThirdPartyIdentityManager.unlink(userId, providerId, function(err) {
-          if (err != null) {
-            return callback(err)
-          }
-          ThirdPartyIdentityManager.link(
-            userId,
-            providerId,
-            externalUserId,
-            externalData,
-            callback,
-            true
-          )
-        })
-      }
-    })
-  },
-
-  unlink(userId, providerId, callback) {
-    if (!oauthProviders[providerId]) {
-      return callback(new Error('Not a valid provider'))
-    }
-    const query = {
-      _id: userId
+      })
     }
-    const update = {
-      $pull: {
-        thirdPartyIdentifiers: {
-          providerId
-        }
+  })
+}
+
+function unlink(userId, providerId, callback) {
+  if (!oauthProviders[providerId]) {
+    return callback(new Error('Not a valid provider'))
+  }
+  const query = {
+    _id: userId
+  }
+  const update = {
+    $pull: {
+      thirdPartyIdentifiers: {
+        providerId
       }
     }
-    // projection includes thirdPartyIdentifiers for tests
-    User.findOneAndUpdate(query, update, { new: 1 }, (err, res) => {
-      if (err != null) {
-        callback(err)
-      } else if (!res) {
-        callback(new Error('update failed'))
-      } else {
-        const emailOptions = {
-          to: res.email,
-          provider: oauthProviders[providerId].name
-        }
-        EmailHandler.sendEmail(
-          'emailThirdPartyIdentifierUnlinked',
-          emailOptions,
-          error => {
-            if (error != null) {
-              logger.warn(error)
-            }
-            return callback(null, res)
-          }
-        )
+  }
+  // projection includes thirdPartyIdentifiers for tests
+  User.findOneAndUpdate(query, update, { new: 1 }, (err, res) => {
+    if (err != null) {
+      callback(err)
+    } else if (!res) {
+      callback(new Error('update failed'))
+    } else {
+      const emailOptions = {
+        to: res.email,
+        provider: oauthProviders[providerId].name
       }
-    })
+      EmailHandler.sendEmail(
+        'emailThirdPartyIdentifierUnlinked',
+        emailOptions,
+        error => {
+          if (error != null) {
+            logger.warn(error)
+          }
+          return callback(null, res)
+        }
+      )
+    }
+  })
+}
+
+function _getUserQuery(providerId, externalUserId) {
+  externalUserId = externalUserId.toString()
+  providerId = providerId.toString()
+  const query = {
+    'thirdPartyIdentifiers.externalUserId': externalUserId,
+    'thirdPartyIdentifiers.providerId': providerId
   }
-})
+  return query
+}
+
+function _thirdPartyIdentifierUpdate(
+  user,
+  providerId,
+  externalUserId,
+  externalData
+) {
+  providerId = providerId.toString()
+  // get third party identifier object from array
+  const thirdPartyIdentifier = user.thirdPartyIdentifiers.find(
+    tpi =>
+      tpi.externalUserId === externalUserId && tpi.providerId === providerId
+  )
+  // do recursive merge of new data over existing data
+  _.merge(thirdPartyIdentifier.externalData, externalData)
+  const update = { 'thirdPartyIdentifiers.$': thirdPartyIdentifier }
+  return update
+}
+
+const ThirdPartyIdentityManager = {
+  getUser,
+  login,
+  link,
+  unlink
+}
+
+ThirdPartyIdentityManager.promises = promisifyAll(ThirdPartyIdentityManager)
+
+module.exports = ThirdPartyIdentityManager

+ 3 - 1
services/web/test/acceptance/src/helpers/UserHelper.js

@@ -41,13 +41,15 @@ module.exports = class UserHelper {
     this.user = null
     // cookie jar
     this.jar = request.jar()
+    // create new request instance
+    this.request = request.defaults({})
     // initialize request instance with default options
     this.setRequestDefaults()
   }
 
   setRequestDefaults(defaults = {}) {
     // request-promise instance for making requests
-    this.request = request.defaults({
+    this.request = this.request.defaults({
       baseUrl: UserHelper.baseUrl(),
       followRedirect: false,
       jar: this.jar,