| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- const crypto = require('crypto')
- const { db } = require('../../infrastructure/mongodb')
- const Errors = require('../Errors/Errors')
- const { promisifyAll } = require('@overleaf/promise-utils')
- const ONE_HOUR_IN_S = 60 * 60
- const OneTimeTokenHandler = {
- MAX_PEEKS: 4,
- getNewToken(use, data, options, callback) {
- // options is optional
- if (!options) {
- options = {}
- }
- if (typeof options === 'function') {
- callback = options
- options = {}
- }
- const expiresIn = options.expiresIn || ONE_HOUR_IN_S
- const createdAt = new Date()
- const expiresAt = new Date(createdAt.getTime() + expiresIn * 1000)
- const token = crypto.randomBytes(32).toString('hex')
- db.tokens.insertOne(
- {
- use,
- token,
- data,
- createdAt,
- expiresAt,
- },
- function (error) {
- if (error) {
- return callback(error)
- }
- callback(null, token)
- }
- )
- },
- getValueFromTokenAndExpire(use, token, callback) {
- const now = new Date()
- db.tokens.findOneAndUpdate(
- {
- use,
- token,
- expiresAt: { $gt: now },
- usedAt: { $exists: false },
- peekCount: { $not: { $gte: OneTimeTokenHandler.MAX_PEEKS } },
- },
- {
- $set: {
- usedAt: now,
- },
- },
- function (error, result) {
- if (error) {
- return callback(error)
- }
- const token = result.value
- if (!token) {
- return callback(new Errors.NotFoundError('no token found'))
- }
- callback(null, token.data)
- }
- )
- },
- peekValueFromToken(use, token, callback) {
- db.tokens.findOneAndUpdate(
- {
- use,
- token,
- expiresAt: { $gt: new Date() },
- usedAt: { $exists: false },
- peekCount: { $not: { $gte: OneTimeTokenHandler.MAX_PEEKS } },
- },
- {
- $inc: { peekCount: 1 },
- },
- {
- returnDocument: 'after',
- },
- function (error, result) {
- if (error) {
- return callback(error)
- }
- const token = result.value
- if (!token) {
- return callback(new Errors.NotFoundError('no token found'))
- }
- const remainingPeeks = OneTimeTokenHandler.MAX_PEEKS - token.peekCount
- callback(null, token.data, remainingPeeks)
- }
- )
- },
- expireToken(use, token, callback) {
- const now = new Date()
- db.tokens.updateOne(
- {
- use,
- token,
- },
- {
- $set: {
- usedAt: now,
- },
- },
- error => {
- callback(error)
- }
- )
- },
- 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)
- module.exports = OneTimeTokenHandler
|