enigma-bbs/core/user_temp_token.js

146 lines
4.0 KiB
JavaScript

/* jslint node: true */
'use strict';
// ENiGMA½
const UserDb = require('./database.js').dbs.user;
const { getISOTimestampString } = require('./database.js');
const { Errors } = require('./enig_error.js');
const User = require('./user.js');
const Log = require('./logger.js').log;
// deps
const crypto = require('crypto');
const async = require('async');
const moment = require('moment');
exports.createToken = createToken;
exports.deleteToken = deleteToken;
exports.deleteTokenByUserAndType = deleteTokenByUserAndType;
exports.getTokenInfo = getTokenInfo;
exports.temporaryTokenMaintenanceTask = temporaryTokenMaintenanceTask;
exports.WellKnownTokenTypes = {
AuthFactor2OTPRegister: 'auth_factor2_otp_register',
};
function createToken(userId, tokenType, options = { bits: 128 }, cb) {
async.waterfall(
[
callback => {
return crypto.randomBytes(options.bits, callback);
},
(token, callback) => {
token = token.toString('hex');
UserDb.run(
`INSERT OR REPLACE INTO user_temporary_token (user_id, token, token_type, timestamp)
VALUES (?, ?, ?, ?);`,
[userId, token, tokenType, getISOTimestampString()],
err => {
return callback(err, token);
}
);
},
],
(err, token) => {
return cb(err, token);
}
);
}
function deleteToken(token, cb) {
UserDb.run(
`DELETE FROM user_temporary_token
WHERE token = ?;`,
[token],
err => {
return cb(err);
}
);
}
function deleteTokenByUserAndType(userId, tokenType, cb) {
UserDb.run(
`DELETE FROM user_temporary_token
WHERE user_id = ? AND token_type = ?;`,
[userId, tokenType],
err => {
return cb(err);
}
);
}
function getTokenInfo(token, cb) {
async.waterfall(
[
callback => {
UserDb.get(
`SELECT user_id, token_type, timestamp
FROM user_temporary_token
WHERE token = ?;`,
[token],
(err, row) => {
if (err) {
return callback(err);
}
if (!row) {
return callback(
Errors.DoesNotExist('No entry found for token')
);
}
const info = {
userId: row.user_id,
tokenType: row.token_type,
timestamp: moment(row.timestamp),
};
return callback(null, info);
}
);
},
(info, callback) => {
User.getUser(info.userId, (err, user) => {
info.user = user;
return callback(err, info);
});
},
],
(err, info) => {
return cb(err, info);
}
);
}
function temporaryTokenMaintenanceTask(args, cb) {
const tokenType = args[0];
if (!tokenType) {
return Log.error(
'Cannot run temporary token maintenance task with out specifying "tokenType" as argument 0'
);
}
const expTime = args[1] || '24 hours';
UserDb.run(
`DELETE FROM user_temporary_token
WHERE token IN (
SELECT token
FROM user_temporary_token
WHERE token_type = ?
AND DATETIME("now") >= DATETIME(timestamp, "+${expTime}")
);`,
[tokenType],
err => {
if (err) {
Log.warn(
{ error: err.message, tokenType },
'Failed deleting user temporary token'
);
}
return cb(err);
}
);
}