/*jshint esversion: 6 */ /* globals Buffer*/ const Quota = module.exports; //const Util = require("../common-util"); const Keys = require("../keys"); const Package = require('../../package.json'); const Https = require("https"); const Util = require("../common-util"); var validLimitFields = ['limit', 'plan', 'note', 'users', 'origin']; Quota.isValidLimit = function (o) { var valid = o && typeof(o) === 'object' && typeof(o.limit) === 'number' && typeof(o.plan) === 'string' && typeof(o.note) === 'string' && // optionally contains a 'users' array (Array.isArray(o.users) || typeof(o.users) === 'undefined') && // check that the object contains only the expected fields !Object.keys(o).some(function (k) { return validLimitFields.indexOf(k) === -1; }); return valid; }; Quota.applyCustomLimits = function (Env) { // DecreedLimits > customLimits > serverLimits; // XXX perform an integrity check on shared limits // especially relevant because we use Env.limits // when considering whether to archive inactive accounts // read custom limits from the Environment (taken from config) var customLimits = (function (custom) { var limits = {}; Object.keys(custom).forEach(function (k) { var user; // XXX this length (44) is also hardcoded in decrees.js // before calling Keys.parseUser. // Maybe we should improve Keys.parseUser to handle this // option directly if (k.length === 44) { user = { pubkey: Util.unescapeKeyCharacters(k) }; } else { try { user = Keys.parseUser(k); } catch (err) { return void Env.Log.error("PARSE_CUSTOM_LIMIT_BLOCK", { user: k, error: err.message, }); } } var unsafeKey = user.pubkey; limits[unsafeKey] = custom[k]; }); return limits; }(Env.customLimits || {})); Env.limits = Env.limits || {}; Object.keys(customLimits).forEach(function (k) { if (!Quota.isValidLimit(customLimits[k])) { return; } Env.limits[k] = customLimits[k]; }); // console.log(Env.limits); }; /* Env = { myDomain, mySubdomain, adminEmail, Package.version, }; */ var queryAccountServer = function (Env, cb) { var done = Util.once(Util.mkAsync(cb)); var body = JSON.stringify({ domain: Env.myDomain, subdomain: Env.mySubdomain || null, adminEmail: Env.adminEmail, version: Package.version }); var options = { host: 'accounts.cryptpad.fr', path: '/api/getauthorized', method: 'POST', headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(body) } }; var req = Https.request(options, function (response) { if (!('' + response.statusCode).match(/^2\d\d$/)) { return void cb('SERVER ERROR ' + response.statusCode); } var str = ''; response.on('data', function (chunk) { str += chunk; }); response.on('end', function () { try { var json = JSON.parse(str); // don't overwrite the limits with junk data if (json && json.message === 'EINVAL') { return void cb(); } done(void 0, json); } catch (e) { done(e); } }); }); req.on('error', function (e) { Quota.applyCustomLimits(Env); if (!Env.myDomain) { return done(); } // only return an error if your server allows subscriptions done(e); }); req.end(body); }; Quota.queryAccountServer = function (Env, cb) { Env.batchAccountQuery('', cb, function (done) { queryAccountServer(Env, done); }); }; Quota.updateCachedLimits = function (Env, cb) { Quota.applyCustomLimits(Env); if (Env.blockDailyCheck === true || (typeof(Env.blockDailyCheck) === 'undefined' && Env.adminEmail === false && Env.allowSubscriptions === false)) { return void cb(); } Quota.queryAccountServer(Env, function (err, json) { if (err) { return void cb(err); } if (!json) { return void cb(); } for (var k in json) { if (k.length === 44 && json[k]) { json[k].origin = 'remote'; } } Env.limits = json; Quota.applyCustomLimits(Env); cb(); }); }; // The limits object contains storage limits for all the publicKey that have paid // To each key is associated an object containing the 'limit' value and a 'note' explaining that limit Quota.getUpdatedLimit = function (Env, safeKey, cb) { Quota.updateCachedLimits(Env, function (err) { if (err) { return void cb(err); } var limit = Env.limits[safeKey]; if (limit && typeof(limit.limit) === 'number') { return void cb(void 0, [limit.limit, limit.plan, limit.note]); } return void cb(void 0, [Env.defaultStorageLimit, '', '']); }); };