mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #15728 from overleaf/td-lg-expire-password-tokens
Expire user password reset tokens when user changes their password GitOrigin-RevId: 2d303eba947c224e71ebe60083abc7a8ff5207a5
This commit is contained in:
parent
fa0ea24f53
commit
2807a35e24
4 changed files with 63 additions and 0 deletions
|
@ -112,6 +112,25 @@ const OneTimeTokenHandler = {
|
|||
}
|
||||
)
|
||||
},
|
||||
|
||||
expireAllTokensForUser(userId, use, callback) {
|
||||
const now = new Date()
|
||||
db.tokens.updateMany(
|
||||
{
|
||||
use,
|
||||
'data.user_id': userId.toString(),
|
||||
usedAt: { $exists: false },
|
||||
},
|
||||
{
|
||||
$set: {
|
||||
usedAt: now,
|
||||
},
|
||||
},
|
||||
error => {
|
||||
callback(error)
|
||||
}
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
OneTimeTokenHandler.promises = promisifyAll(OneTimeTokenHandler)
|
||||
|
|
|
@ -22,6 +22,7 @@ const {
|
|||
acceptsJson,
|
||||
} = require('../../infrastructure/RequestContentTypeDetection')
|
||||
const Modules = require('../../infrastructure/Modules')
|
||||
const OneTimeTokenHandler = require('../Security/OneTimeTokenHandler')
|
||||
|
||||
async function _sendSecurityAlertClearedSessions(user) {
|
||||
const emailOptions = {
|
||||
|
@ -131,6 +132,11 @@ async function changePassword(req, res, next) {
|
|||
req.sessionID,
|
||||
])
|
||||
|
||||
await OneTimeTokenHandler.promises.expireAllTokensForUser(
|
||||
userId.toString(),
|
||||
'password'
|
||||
)
|
||||
|
||||
return res.json({
|
||||
message: {
|
||||
type: 'success',
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/* eslint-disable no-unused-vars */
|
||||
|
||||
const Helpers = require('./lib/helpers')
|
||||
|
||||
exports.tags = ['server-ce', 'server-pro', 'saas']
|
||||
|
||||
const index = {
|
||||
key: {
|
||||
'data.user_id': 1,
|
||||
},
|
||||
name: 'data.user_id_1',
|
||||
}
|
||||
|
||||
exports.migrate = async client => {
|
||||
const { db } = client
|
||||
await Helpers.addIndexesToCollection(db.tokens, [index])
|
||||
}
|
||||
|
||||
exports.rollback = async client => {
|
||||
const { db } = client
|
||||
await Helpers.dropIndexesFromCollection(db.tokens, [index])
|
||||
}
|
|
@ -129,6 +129,10 @@ describe('UserController', function () {
|
|||
promises: { sendEmail: sinon.stub().resolves() },
|
||||
}
|
||||
|
||||
this.OneTimeTokenHandler = {
|
||||
promises: { expireAllTokensForUser: sinon.stub().resolves() },
|
||||
}
|
||||
|
||||
this.UserController = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'../Helpers/UrlHelper': this.UrlHelper,
|
||||
|
@ -149,6 +153,7 @@ describe('UserController', function () {
|
|||
'@overleaf/settings': this.settings,
|
||||
'@overleaf/o-error': OError,
|
||||
'../Email/EmailHandler': this.EmailHandler,
|
||||
'../Security/OneTimeTokenHandler': this.OneTimeTokenHandler,
|
||||
'../../infrastructure/RequestContentTypeDetection':
|
||||
this.RequestContentTypeDetection,
|
||||
},
|
||||
|
@ -739,6 +744,17 @@ describe('UserController', function () {
|
|||
})
|
||||
this.UserController.changePassword(this.req, this.res)
|
||||
})
|
||||
|
||||
it('should expire password reset tokens', function (done) {
|
||||
this.res.json.callsFake(() => {
|
||||
this.OneTimeTokenHandler.promises.expireAllTokensForUser.should.have.been.calledWith(
|
||||
this.user._id,
|
||||
'password'
|
||||
)
|
||||
done()
|
||||
})
|
||||
this.UserController.changePassword(this.req, this.res)
|
||||
})
|
||||
})
|
||||
|
||||
describe('errors', function () {
|
||||
|
|
Loading…
Reference in a new issue