Recv/lib/repository/code.js

289 lines
5.5 KiB
JavaScript

const map = require('lodash/map');
const retry = require('async-retry');
const generate = require('nanoid/generate');
const markdown = require('markdown').markdown;
const async = require('async');
const ExpirationUnits = require('../expirationunits');
class Code
{
constructor(values)
{
var self = this;
self.id = values.id || values._id || null;
self.userId = values.userId || null;
self.created = values.created || new Date();
self.expiration = values.expiration || null;
self.expirationDate = values.expirationDate || null;
self.description = values.description || null;
self.message = values.message || null;
self.messageHTML = values.messageHTML || null;
self.history = values.history || [{
userId: self.userId,
date: self.created
}];
}
}
class CodeRepository
{
constructor(store)
{
var self = this;
self.store = store;
}
init()
{
var self = this;
return new Promise((resolve, reject) =>
{
resolve();
});
}
async insert(code)
{
var self = this;
return await retry(async bail =>
{
var codeId = generate(config.code.alphabet, config.code.length);
if ((await self.get(codeId)) !== null)
throw new Error('Code ' + codeId + ' already exists');
let now = new Date();
self.store.insert({
_id: codeId,
userId: code.userId,
created: code.created || now,
expiration: code.expiration,
expirationDate: ExpirationUnits.apply(code.expiration, code.created),
description: code.description,
message: code.message,
messageHTML: self.getMessageHTML(code.message),
history: [
{
userId: code.userId,
date: code.created || now
}
]
})
return codeId;
}, {
retries: 100,
minTimeout: 0,
maxTimeout: 0
});
}
update(code)
{
var self = this;
return new Promise((resolve, reject) =>
{
self.store.update({ _id: code.id }, { $set: {
expiration: code.expiration,
expirationDate: ExpirationUnits.apply(code.expiration, code.created),
description: code.description,
message: code.message,
messageHTML: self.getMessageHTML(code.message)
}},
(err, numAffected) =>
{
if (err)
{
reject(err);
return;
}
if (numAffected == 0)
{
reject();
}
resolve();
});
});
}
move(codeId, userId)
{
var self = this;
return new Promise((resolve, reject) =>
{
self.store.update({ _id: codeId }, {
$set: {
userId: userId
},
$push: {
history: {
userId: userId,
date: new Date()
}
}
},
(err, numAffected) =>
{
if (err)
{
reject(err);
return;
}
if (numAffected == 0)
{
reject();
}
resolve();
});
});
}
list(userId)
{
var self = this;
return new Promise((resolve, reject) =>
{
self.store.find(userId != null ? { userId: userId } : {}, (err, docs) =>
{
if (err)
{
reject(err);
return;
}
resolve(map(docs, (doc) => new Code(doc)));
});
});
}
getDescriptions()
{
var self = this;
return new Promise((resolve, reject) =>
{
self.store.find({}, (err, docs) =>
{
if (err)
{
reject(err);
return;
}
var descriptions = {};
docs.forEach((dbCode) =>
{
if (dbCode.description)
descriptions[dbCode._id] = dbCode.description;
});
resolve(descriptions);
});
});
}
get(codeId)
{
var self = this;
return new Promise((resolve, reject) =>
{
self.store.findOne({ _id: codeId }, (err, doc) =>
{
if (err)
{
reject(err);
return;
}
resolve(doc !== null ? new Code(doc) : null);
});
});
}
getMessageHTML(message)
{
return message !== null ? markdown.toHTML(message) : null;
}
delete(codeId)
{
var self = this;
return new Promise((resolve, reject) =>
{
self.store.remove({ _id: codeId }, (err, numRemoved) =>
{
if (err)
{
reject(err);
return;
}
resolve();
});
});
}
deleteExpired()
{
var self = this;
return new Promise((resolve, reject) =>
{
let now = new Date();
self.store.find({ $where: function() { return this.expirationDate !== null && this.expirationDate < now }}, (err, docs) =>
{
if (err)
{
reject(err);
return;
}
async.eachOfSeries(docs,
async (doc) =>
{
console.log('Expired code: ' + doc._id);
await self.delete(doc._id);
},
(err) =>
{
if (err)
reject(err);
else
resolve();
});
});
});
}
}
module.exports = {
Code,
CodeRepository
}