const map = require('lodash/map'); const retry = require('async-retry'); const generate = require('nanoid/generate'); const markdown = require('markdown').markdown; const config = require('../../config'); 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.description = values.description || null; self.message = values.message || null; self.messageHTML = values.messageHTML || null; } } class CodeRepository { constructor(store) { var self = this; self.store = store; } init() { var self = this; return new Promise((resolve, reject) => { resolve(); }); } getUserId(code) { var self = this; return new Promise((resolve, reject) => { self.store.findOne({ _id: code }, (err, doc) => { if (err) { reject(err); return; } resolve(doc !== null ? doc.userId : null); }); }); } async insert(code) { var self = this; return await retry(async bail => { var codeId = generate(config.code.alphabet, config.code.length); if ((await self.findCodeUserId(codeId)) !== null) throw new Error('Code ' + codeId + ' already exists'); self.store.insert({ _id: codeId, userId: code.userId, created: code.created || new Date(), expiration: code.expiration, description: code.description, message: code.message, messageHTML: self.getMessageHTML(code.message) }) 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, description: code.description, message: code.message, messageHTML: self.getMessageHTML(code.message) }}, (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(code) { var self = this; return new Promise((resolve, reject) => { self.store.remove({ _id: code }, (err, numRemoved) => { if (err) { reject(err); return; } resolve(); }); }); } } module.exports = { Code, CodeRepository }