feat: #7743 , meta/cachebuster, meta/configs

v1.18.x
Barış Soner Uşaklı 6 years ago
parent 756a717eb8
commit 7f72181ec8

@ -1,48 +1,45 @@
'use strict'; 'use strict';
var async = require('async'); const fs = require('fs');
var fs = require('fs'); const path = require('path');
var path = require('path'); const mkdirp = require('mkdirp');
var mkdirp = require('mkdirp'); const winston = require('winston');
var winston = require('winston'); const util = require('util');
const mkdirpAsync = util.promisify(mkdirp);
const writeFileAsync = util.promisify(fs.writeFile);
const readFileAsync = util.promisify(fs.readFile);
var filePath = path.join(__dirname, '../../build/cache-buster'); const filePath = path.join(__dirname, '../../build/cache-buster');
var cached; let cached;
// cache buster is an 11-character, lowercase, alphanumeric string // cache buster is an 11-character, lowercase, alphanumeric string
function generate() { function generate() {
return (Math.random() * 1e18).toString(32).slice(0, 11); return (Math.random() * 1e18).toString(32).slice(0, 11);
} }
exports.write = function write(callback) { exports.write = async function write() {
async.waterfall([ await mkdirpAsync(path.dirname(filePath));
function (next) { await writeFileAsync(filePath, generate());
mkdirp(path.dirname(filePath), next);
},
function (data, next) {
fs.writeFile(filePath, generate(), next);
},
], callback);
}; };
exports.read = function read(callback) { exports.read = async function read() {
if (cached) { if (cached) {
return callback(null, cached); return cached;
} }
try {
fs.readFile(filePath, 'utf8', function (err, buster) { const buster = await readFileAsync(filePath, 'utf8');
if (err) {
winston.warn('[cache-buster] could not read cache buster', err);
return callback(null, generate());
}
if (!buster || buster.length !== 11) { if (!buster || buster.length !== 11) {
winston.warn('[cache-buster] cache buster string invalid: expected /[a-z0-9]{11}/, got `' + buster + '`'); winston.warn('[cache-buster] cache buster string invalid: expected /[a-z0-9]{11}/, got `' + buster + '`');
return callback(null, generate()); return generate();
} }
cached = buster; cached = buster;
callback(null, cached); return cached;
}); } catch (err) {
winston.warn('[cache-buster] could not read cache buster', err);
return generate();
}
}; };
require('../promisify')(exports);

@ -1,15 +1,15 @@
'use strict'; 'use strict';
var async = require('async'); const nconf = require('nconf');
var nconf = require('nconf'); const path = require('path');
var path = require('path'); const winston = require('winston');
var winston = require('winston'); const util = require('util');
var db = require('../database'); const db = require('../database');
var pubsub = require('../pubsub'); const pubsub = require('../pubsub');
var Meta = require('../meta'); const Meta = require('../meta');
var cacheBuster = require('./cacheBuster'); const cacheBuster = require('./cacheBuster');
const defaults = require('../../install/data/defaults'); const defaults = require('../../install/data/defaults');
var Configs = module.exports; var Configs = module.exports;
@ -48,152 +48,114 @@ function deserialize(config) {
Configs.deserialize = deserialize; Configs.deserialize = deserialize;
Configs.init = function (callback) { Configs.init = async function () {
var config; const config = await Configs.list();
async.waterfall([ const buster = await cacheBuster.read();
function (next) { config['cache-buster'] = 'v=' + (buster || Date.now());
Configs.list(next); Meta.config = config;
},
function (_config, next) {
config = _config;
cacheBuster.read(next);
},
function (buster, next) {
config['cache-buster'] = 'v=' + (buster || Date.now());
Meta.config = config;
next();
},
], callback);
}; };
Configs.list = function (callback) { Configs.list = async function () {
Configs.getFields([], callback); return await Configs.getFields([]);
}; };
Configs.get = function (field, callback) { Configs.get = async function (field) {
Configs.getFields([field], function (err, values) { const values = await Configs.getFields([field]);
callback(err, values ? values[field] : null); return (values.hasOwnProperty(field) && values[field] !== undefined) ? values[field] : null;
});
}; };
Configs.getFields = function (fields, callback) { Configs.getFields = async function (fields) {
async.waterfall([ let values;
function (next) { if (fields.length) {
if (fields.length) { values = await db.getObjectFields('config', fields);
db.getObjectFields('config', fields, next); } else {
} else { values = await db.getObject('config');
db.getObject('config', next); }
}
}, values = Object.assign({}, defaults, values ? deserialize(values) : {});
function (values, next) {
try { if (!fields.length) {
values = Object.assign({}, defaults, values ? deserialize(values) : {}); values.version = nconf.get('version');
} catch (err) { values.registry = nconf.get('registry');
return next(err); }
} return values;
if (!fields.length) {
values.version = nconf.get('version');
values.registry = nconf.get('registry');
}
next(null, values);
},
], callback);
}; };
Configs.set = function (field, value, callback) { Configs.set = async function (field, value) {
callback = callback || function () {};
if (!field) { if (!field) {
return callback(new Error('[[error:invalid-data]]')); throw new Error('[[error:invalid-data]]');
} }
Configs.setMultiple({ await Configs.setMultiple({
[field]: value, [field]: value,
}, callback); });
}; };
// data comes from client-side Configs.setMultiple = async function (data) {
Configs.setMultiple = function (data, callback) {
data = deserialize(data); data = deserialize(data);
await processConfig(data);
async.waterfall([ await db.setObject('config', data);
function (next) { updateConfig(data);
processConfig(data, next);
},
function (next) {
db.setObject('config', data, next);
},
function (next) {
updateConfig(data);
setImmediate(next);
},
], callback);
}; };
Configs.setOnEmpty = function (values, callback) { Configs.setOnEmpty = async function (values) {
async.waterfall([ const data = await db.getObject('config');
function (next) { const config = Object.assign({}, values, data ? deserialize(data) : {});
db.getObject('config', next); await db.setObject('config', config);
},
function (data, next) {
var config = Object.assign({}, values, data ? deserialize(data) : {});
db.setObject('config', config, next);
},
], callback);
}; };
Configs.remove = function (field, callback) { Configs.remove = async function (field) {
db.deleteObjectField('config', field, callback); await db.deleteObjectField('config', field);
}; };
function processConfig(data, callback) { async function processConfig(data) {
async.parallel([ await Promise.all([
async.apply(saveRenderedCss, data), saveRenderedCss(data),
function (next) { getLogoSize(data),
var image = require('../image'); ]);
if (data['brand:logo']) {
image.size(path.join(nconf.get('upload_path'), 'system', 'site-logo-x50.png'), function (err, size) {
if (err && err.code === 'ENOENT') {
// For whatever reason the x50 logo wasn't generated, gracefully error out
winston.warn('[logo] The email-safe logo doesn\'t seem to have been created, please re-upload your site logo.');
size = {
height: 0,
width: 0,
};
} else if (err) {
return next(err);
}
data['brand:emailLogo'] = nconf.get('url') + path.join(nconf.get('upload_url'), 'system', 'site-logo-x50.png');
data['brand:emailLogo:height'] = size.height;
data['brand:emailLogo:width'] = size.width;
next();
});
} else {
setImmediate(next);
}
},
], function (err) {
callback(err);
});
} }
function saveRenderedCss(data, callback) { function lessRender(string, callback) {
var less = require('less');
less.render(string, {
compress: true,
}, callback);
}
const lessRenderAsync = util.promisify(lessRender);
async function saveRenderedCss(data) {
if (!data.customCSS) { if (!data.customCSS) {
return setImmediate(callback); return;
} }
var less = require('less'); const lessObject = await lessRenderAsync(data.customCSS);
async.waterfall([ data.renderedCustomCSS = lessObject.css;
function (next) { }
less.render(data.customCSS, {
compress: true, async function getLogoSize(data) {
}, next); var image = require('../image');
}, if (!data['brand:logo']) {
function (lessObject, next) { return;
data.renderedCustomCSS = lessObject.css; }
setImmediate(next); let size;
}, try {
], callback); size = await image.size(path.join(nconf.get('upload_path'), 'system', 'site-logo-x50.png'));
} catch (err) {
if (err.code === 'ENOENT') {
// For whatever reason the x50 logo wasn't generated, gracefully error out
winston.warn('[logo] The email-safe logo doesn\'t seem to have been created, please re-upload your site logo.');
size = {
height: 0,
width: 0,
};
} else {
throw err;
}
}
data['brand:emailLogo'] = nconf.get('url') + path.join(nconf.get('upload_url'), 'system', 'site-logo-x50.png');
data['brand:emailLogo:height'] = size.height;
data['brand:emailLogo:width'] = size.width;
} }
function updateConfig(config) { function updateConfig(config) {

Loading…
Cancel
Save