You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
3.2 KiB
JavaScript
125 lines
3.2 KiB
JavaScript
'use strict';
|
|
|
|
const db = require('../database');
|
|
|
|
const user = require('../user');
|
|
const srcUtils = require('../utils');
|
|
|
|
const utils = module.exports;
|
|
|
|
// internal token management utilities only
|
|
utils.tokens = {};
|
|
|
|
utils.tokens.list = async () => {
|
|
// Validation handled at higher level
|
|
const tokens = await db.getSortedSetRange(`tokens:createtime`, 0, -1);
|
|
return await utils.tokens.get(tokens);
|
|
};
|
|
|
|
utils.tokens.get = async (tokens) => {
|
|
// Validation handled at higher level
|
|
if (!tokens) {
|
|
throw new Error('[[error:invalid-data]]');
|
|
}
|
|
|
|
let singular = false;
|
|
if (!Array.isArray(tokens)) {
|
|
tokens = [tokens];
|
|
singular = true;
|
|
}
|
|
|
|
let [tokenObjs, lastSeen] = await Promise.all([
|
|
db.getObjects(tokens.map(t => `token:${t}`)),
|
|
utils.tokens.getLastSeen(tokens),
|
|
]);
|
|
|
|
tokenObjs = tokenObjs.map((tokenObj, idx) => {
|
|
if (!tokenObj) {
|
|
return null;
|
|
}
|
|
|
|
tokenObj.token = tokens[idx];
|
|
tokenObj.lastSeen = lastSeen[idx];
|
|
tokenObj.lastSeenISO = lastSeen[idx] ? new Date(lastSeen[idx]).toISOString() : null;
|
|
tokenObj.timestampISO = new Date(parseInt(tokenObj.timestamp, 10)).toISOString();
|
|
|
|
return tokenObj;
|
|
});
|
|
|
|
return singular ? tokenObjs[0] : tokenObjs;
|
|
};
|
|
|
|
utils.tokens.generate = async ({ uid, description }) => {
|
|
if (parseInt(uid, 10) !== 0) {
|
|
const uidExists = await user.exists(uid);
|
|
if (!uidExists) {
|
|
throw new Error('[[error:no-user]]');
|
|
}
|
|
}
|
|
|
|
const token = srcUtils.generateUUID();
|
|
const timestamp = Date.now();
|
|
|
|
return utils.tokens.add({ token, uid, description, timestamp });
|
|
};
|
|
|
|
utils.tokens.add = async ({ token, uid, description = '', timestamp = Date.now() }) => {
|
|
if (!token || uid === undefined) {
|
|
throw new Error('[[error:invalid-data]]');
|
|
}
|
|
|
|
await Promise.all([
|
|
db.setObject(`token:${token}`, { uid, description, timestamp }),
|
|
db.sortedSetAdd(`tokens:createtime`, timestamp, token),
|
|
db.sortedSetAdd(`tokens:uid`, uid, token),
|
|
]);
|
|
|
|
return token;
|
|
};
|
|
|
|
utils.tokens.update = async (token, { uid, description }) => {
|
|
await Promise.all([
|
|
db.setObject(`token:${token}`, { uid, description }),
|
|
db.sortedSetAdd(`tokens:uid`, uid, token),
|
|
]);
|
|
|
|
return await utils.tokens.get(token);
|
|
};
|
|
|
|
utils.tokens.roll = async (token) => {
|
|
const [createTime, uid, lastSeen] = await db.sortedSetsScore([`tokens:createtime`, `tokens:uid`, `tokens:lastSeen`], token);
|
|
const newToken = srcUtils.generateUUID();
|
|
|
|
const updates = [
|
|
db.rename(`token:${token}`, `token:${newToken}`),
|
|
db.sortedSetRemove(`tokens:createtime`, token),
|
|
db.sortedSetRemove(`tokens:uid`, token),
|
|
db.sortedSetRemove(`tokens:lastSeen`, token),
|
|
db.sortedSetAdd(`tokens:createtime`, createTime, newToken),
|
|
db.sortedSetAdd(`tokens:uid`, uid, newToken),
|
|
];
|
|
|
|
if (lastSeen) {
|
|
updates.push(db.sortedSetAdd(`tokens:lastSeen`, lastSeen, newToken));
|
|
}
|
|
|
|
await Promise.all(updates);
|
|
|
|
return newToken;
|
|
};
|
|
|
|
utils.tokens.delete = async (token) => {
|
|
await Promise.all([
|
|
db.delete(`token:${token}`),
|
|
db.sortedSetRemove(`tokens:createtime`, token),
|
|
db.sortedSetRemove(`tokens:uid`, token),
|
|
db.sortedSetRemove(`tokens:lastSeen`, token),
|
|
]);
|
|
};
|
|
|
|
utils.tokens.log = async (token) => {
|
|
await db.sortedSetAdd('tokens:lastSeen', Date.now(), token);
|
|
};
|
|
|
|
utils.tokens.getLastSeen = async tokens => await db.sortedSetScores('tokens:lastSeen', tokens);
|