refactor: remove async.waterfall from remaining upgrade scripts
parent
04ee5c0dfb
commit
6b34065f2a
@ -1,107 +1,52 @@
|
||||
'use strict';
|
||||
/* eslint-disable no-await-in-loop */
|
||||
|
||||
'use strict';
|
||||
|
||||
const async = require('async');
|
||||
const winston = require('winston');
|
||||
const db = require('../../database');
|
||||
|
||||
module.exports = {
|
||||
name: 'Granting edit/delete/delete topic on existing categories',
|
||||
timestamp: Date.UTC(2016, 7, 7),
|
||||
method: function (callback) {
|
||||
method: async function () {
|
||||
const groupsAPI = require('../../groups');
|
||||
const privilegesAPI = require('../../privileges');
|
||||
|
||||
db.getSortedSetRange('categories:cid', 0, -1, (err, cids) => {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
const cids = await db.getSortedSetRange('categories:cid', 0, -1);
|
||||
|
||||
for (const cid of cids) {
|
||||
const data = await privilegesAPI.categories.list(cid);
|
||||
const { groups, users } = data;
|
||||
|
||||
for (const group of groups) {
|
||||
if (group.privileges['groups:topics:reply']) {
|
||||
await Promise.all([
|
||||
groupsAPI.join(`cid:${cid}:privileges:groups:posts:edit`, group.name),
|
||||
groupsAPI.join(`cid:${cid}:privileges:groups:posts:delete`, group.name),
|
||||
]);
|
||||
winston.verbose(`cid:${cid}:privileges:groups:posts:edit, cid:${cid}:privileges:groups:posts:delete granted to gid: ${group.name}`);
|
||||
}
|
||||
|
||||
if (group.privileges['groups:topics:create']) {
|
||||
await groupsAPI.join(`cid:${cid}:privileges:groups:topics:delete`, group.name);
|
||||
winston.verbose(`cid:${cid}:privileges:groups:topics:delete granted to gid: ${group.name}`);
|
||||
}
|
||||
}
|
||||
|
||||
async.eachSeries(cids, (cid, next) => {
|
||||
privilegesAPI.categories.list(cid, (err, data) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
const { groups } = data;
|
||||
const { users } = data;
|
||||
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
async.eachSeries(groups, (group, next) => {
|
||||
if (group.privileges['groups:topics:reply']) {
|
||||
return async.parallel([
|
||||
async.apply(groupsAPI.join, `cid:${cid}:privileges:groups:posts:edit`, group.name),
|
||||
async.apply(groupsAPI.join, `cid:${cid}:privileges:groups:posts:delete`, group.name),
|
||||
], (err) => {
|
||||
if (!err) {
|
||||
winston.verbose(`cid:${cid}:privileges:groups:posts:edit, cid:${cid}:privileges:groups:posts:delete granted to gid: ${group.name}`);
|
||||
}
|
||||
|
||||
return next(err);
|
||||
});
|
||||
}
|
||||
|
||||
next(null);
|
||||
}, next);
|
||||
},
|
||||
function (next) {
|
||||
async.eachSeries(groups, (group, next) => {
|
||||
if (group.privileges['groups:topics:create']) {
|
||||
return groupsAPI.join(`cid:${cid}:privileges:groups:topics:delete`, group.name, (err) => {
|
||||
if (!err) {
|
||||
winston.verbose(`cid:${cid}:privileges:groups:topics:delete granted to gid: ${group.name}`);
|
||||
}
|
||||
|
||||
return next(err);
|
||||
});
|
||||
}
|
||||
|
||||
next(null);
|
||||
}, next);
|
||||
},
|
||||
function (next) {
|
||||
async.eachSeries(users, (user, next) => {
|
||||
if (user.privileges['topics:reply']) {
|
||||
return async.parallel([
|
||||
async.apply(groupsAPI.join, `cid:${cid}:privileges:posts:edit`, user.uid),
|
||||
async.apply(groupsAPI.join, `cid:${cid}:privileges:posts:delete`, user.uid),
|
||||
], (err) => {
|
||||
if (!err) {
|
||||
winston.verbose(`cid:${cid}:privileges:posts:edit, cid:${cid}:privileges:posts:delete granted to uid: ${user.uid}`);
|
||||
}
|
||||
|
||||
return next(err);
|
||||
});
|
||||
}
|
||||
|
||||
next(null);
|
||||
}, next);
|
||||
},
|
||||
function (next) {
|
||||
async.eachSeries(users, (user, next) => {
|
||||
if (user.privileges['topics:create']) {
|
||||
return groupsAPI.join(`cid:${cid}:privileges:topics:delete`, user.uid, (err) => {
|
||||
if (!err) {
|
||||
winston.verbose(`cid:${cid}:privileges:topics:delete granted to uid: ${user.uid}`);
|
||||
}
|
||||
|
||||
return next(err);
|
||||
});
|
||||
}
|
||||
|
||||
next(null);
|
||||
}, next);
|
||||
},
|
||||
], (err) => {
|
||||
if (!err) {
|
||||
winston.verbose(`-- cid ${cid} upgraded`);
|
||||
}
|
||||
|
||||
next(err);
|
||||
});
|
||||
});
|
||||
}, callback);
|
||||
});
|
||||
for (const user of users) {
|
||||
if (user.privileges['topics:reply']) {
|
||||
await Promise.all([
|
||||
groupsAPI.join(`cid:${cid}:privileges:posts:edit`, user.uid),
|
||||
groupsAPI.join(`cid:${cid}:privileges:posts:delete`, user.uid),
|
||||
]);
|
||||
winston.verbose(`cid:${cid}:privileges:posts:edit, cid:${cid}:privileges:posts:delete granted to uid: ${user.uid}`);
|
||||
}
|
||||
if (user.privileges['topics:create']) {
|
||||
await groupsAPI.join(`cid:${cid}:privileges:topics:delete`, user.uid);
|
||||
winston.verbose(`cid:${cid}:privileges:topics:delete granted to uid: ${user.uid}`);
|
||||
}
|
||||
}
|
||||
winston.verbose(`-- cid ${cid} upgraded`);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -1,56 +1,39 @@
|
||||
'use strict';
|
||||
|
||||
const async = require('async');
|
||||
const db = require('../../database');
|
||||
|
||||
|
||||
module.exports = {
|
||||
name: 'Favourites to Bookmarks',
|
||||
timestamp: Date.UTC(2016, 9, 8),
|
||||
method: function (callback) {
|
||||
method: async function () {
|
||||
const { progress } = this;
|
||||
const batch = require('../../batch');
|
||||
|
||||
function upgradePosts(next) {
|
||||
const batch = require('../../batch');
|
||||
|
||||
batch.processSortedSet('posts:pid', (ids, next) => {
|
||||
async.each(ids, (id, next) => {
|
||||
async function upgradePosts() {
|
||||
await batch.processSortedSet('posts:pid', async (ids) => {
|
||||
await Promise.all(ids.map(async (id) => {
|
||||
progress.incr();
|
||||
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.rename(`pid:${id}:users_favourited`, `pid:${id}:users_bookmarked`, next);
|
||||
},
|
||||
function (next) {
|
||||
db.getObjectField(`post:${id}`, 'reputation', next);
|
||||
},
|
||||
function (reputation, next) {
|
||||
if (parseInt(reputation, 10)) {
|
||||
db.setObjectField(`post:${id}`, 'bookmarks', reputation, next);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
},
|
||||
function (next) {
|
||||
db.deleteObjectField(`post:${id}`, 'reputation', next);
|
||||
},
|
||||
], next);
|
||||
}, next);
|
||||
await db.rename(`pid:${id}:users_favourited`, `pid:${id}:users_bookmarked`);
|
||||
const reputation = await db.getObjectField(`post:${id}`, 'reputation');
|
||||
if (parseInt(reputation, 10)) {
|
||||
await db.setObjectField(`post:${id}`, 'bookmarks', reputation);
|
||||
}
|
||||
await db.deleteObjectField(`post:${id}`, 'reputation');
|
||||
}));
|
||||
}, {
|
||||
progress: progress,
|
||||
}, next);
|
||||
});
|
||||
}
|
||||
|
||||
function upgradeUsers(next) {
|
||||
const batch = require('../../batch');
|
||||
|
||||
batch.processSortedSet('users:joindate', (ids, next) => {
|
||||
async.each(ids, (id, next) => {
|
||||
db.rename(`uid:${id}:favourites`, `uid:${id}:bookmarks`, next);
|
||||
}, next);
|
||||
}, {}, next);
|
||||
async function upgradeUsers() {
|
||||
await batch.processSortedSet('users:joindate', async (ids) => {
|
||||
await Promise.all(ids.map(async (id) => {
|
||||
await db.rename(`uid:${id}:favourites`, `uid:${id}:bookmarks`);
|
||||
}));
|
||||
}, {});
|
||||
}
|
||||
|
||||
async.series([upgradePosts, upgradeUsers], callback);
|
||||
await upgradePosts();
|
||||
await upgradeUsers();
|
||||
},
|
||||
};
|
||||
|
@ -1,57 +1,37 @@
|
||||
'use strict';
|
||||
|
||||
const async = require('async');
|
||||
const db = require('../../database');
|
||||
|
||||
|
||||
module.exports = {
|
||||
name: 'Update global and user language keys',
|
||||
timestamp: Date.UTC(2016, 10, 22),
|
||||
method: function (callback) {
|
||||
method: async function () {
|
||||
const { progress } = this;
|
||||
const user = require('../../user');
|
||||
const meta = require('../../meta');
|
||||
const batch = require('../../batch');
|
||||
let newLanguage;
|
||||
async.parallel([
|
||||
function (next) {
|
||||
meta.configs.get('defaultLang', (err, defaultLang) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
if (!defaultLang) {
|
||||
return setImmediate(next);
|
||||
}
|
||||
const defaultLang = await meta.configs.get('defaultLang');
|
||||
if (defaultLang) {
|
||||
const newLanguage = defaultLang.replace('_', '-').replace('@', '-x-');
|
||||
if (newLanguage !== defaultLang) {
|
||||
await meta.configs.set('defaultLang', newLanguage);
|
||||
}
|
||||
}
|
||||
|
||||
newLanguage = defaultLang.replace('_', '-').replace('@', '-x-');
|
||||
if (newLanguage !== defaultLang) {
|
||||
meta.configs.set('defaultLang', newLanguage, next);
|
||||
} else {
|
||||
setImmediate(next);
|
||||
await batch.processSortedSet('users:joindate', async (ids) => {
|
||||
await Promise.all(ids.map(async (uid) => {
|
||||
progress.incr();
|
||||
const language = await db.getObjectField(`user:${uid}:settings`, 'userLang');
|
||||
if (language) {
|
||||
const newLanguage = language.replace('_', '-').replace('@', '-x-');
|
||||
if (newLanguage !== language) {
|
||||
await user.setSetting(uid, 'userLang', newLanguage);
|
||||
}
|
||||
});
|
||||
},
|
||||
function (next) {
|
||||
batch.processSortedSet('users:joindate', (ids, next) => {
|
||||
async.each(ids, (uid, next) => {
|
||||
async.waterfall([
|
||||
async.apply(db.getObjectField, `user:${uid}:settings`, 'userLang'),
|
||||
function (language, next) {
|
||||
if (!language) {
|
||||
return setImmediate(next);
|
||||
}
|
||||
|
||||
newLanguage = language.replace('_', '-').replace('@', '-x-');
|
||||
if (newLanguage !== language) {
|
||||
user.setSetting(uid, 'userLang', newLanguage, next);
|
||||
} else {
|
||||
setImmediate(next);
|
||||
}
|
||||
},
|
||||
], next);
|
||||
}, next);
|
||||
}, next);
|
||||
},
|
||||
], callback);
|
||||
}
|
||||
}));
|
||||
}, {
|
||||
progress: progress,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
@ -1,36 +1,34 @@
|
||||
'use strict';
|
||||
|
||||
const async = require('async');
|
||||
const db = require('../../database');
|
||||
|
||||
const db = require('../../database');
|
||||
|
||||
module.exports = {
|
||||
name: 'Upgrading config urls to use assets route',
|
||||
timestamp: Date.UTC(2017, 1, 28),
|
||||
method: function (callback) {
|
||||
async.waterfall([
|
||||
function (cb) {
|
||||
db.getObject('config', cb);
|
||||
},
|
||||
function (config, cb) {
|
||||
if (!config) {
|
||||
return cb();
|
||||
method: async function () {
|
||||
const config = await db.getObject('config');
|
||||
if (config) {
|
||||
const keys = [
|
||||
'brand:favicon',
|
||||
'brand:touchicon',
|
||||
'og:image',
|
||||
'brand:logo:url',
|
||||
'defaultAvatar',
|
||||
'profile:defaultCovers',
|
||||
];
|
||||
|
||||
keys.forEach((key) => {
|
||||
const oldValue = config[key];
|
||||
|
||||
if (!oldValue || typeof oldValue !== 'string') {
|
||||
return;
|
||||
}
|
||||
|
||||
const keys = ['brand:favicon', 'brand:touchicon', 'og:image', 'brand:logo:url', 'defaultAvatar', 'profile:defaultCovers'];
|
||||
|
||||
keys.forEach((key) => {
|
||||
const oldValue = config[key];
|
||||
|
||||
if (!oldValue || typeof oldValue !== 'string') {
|
||||
return;
|
||||
}
|
||||
|
||||
config[key] = oldValue.replace(/(?:\/assets)?\/(images|uploads)\//g, '/assets/$1/');
|
||||
});
|
||||
config[key] = oldValue.replace(/(?:\/assets)?\/(images|uploads)\//g, '/assets/$1/');
|
||||
});
|
||||
|
||||
db.setObject('config', config, cb);
|
||||
},
|
||||
], callback);
|
||||
await db.setObject('config', config);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -1,88 +1,56 @@
|
||||
'use strict';
|
||||
|
||||
const async = require('async');
|
||||
const db = require('../../database');
|
||||
|
||||
|
||||
module.exports = {
|
||||
name: 'Migrating flags to new schema',
|
||||
timestamp: Date.UTC(2016, 11, 7),
|
||||
method: function (callback) {
|
||||
method: async function () {
|
||||
const batch = require('../../batch');
|
||||
const posts = require('../../posts');
|
||||
const flags = require('../../flags');
|
||||
const { progress } = this;
|
||||
|
||||
batch.processSortedSet('posts:pid', (ids, next) => {
|
||||
posts.getPostsByPids(ids, 1, (err, posts) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
posts = posts.filter(post => post.hasOwnProperty('flags'));
|
||||
|
||||
async.each(posts, (post, next) => {
|
||||
progress.incr();
|
||||
|
||||
async.parallel({
|
||||
uids: async.apply(db.getSortedSetRangeWithScores, `pid:${post.pid}:flag:uids`, 0, -1),
|
||||
reasons: async.apply(db.getSortedSetRange, `pid:${post.pid}:flag:uid:reason`, 0, -1),
|
||||
}, (err, data) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
await batch.processSortedSet('posts:pid', async (ids) => {
|
||||
let postData = await posts.getPostsByPids(ids, 1);
|
||||
postData = postData.filter(post => post.hasOwnProperty('flags'));
|
||||
await Promise.all(postData.map(async (post) => {
|
||||
progress.incr();
|
||||
|
||||
const [uids, reasons] = await Promise.all([
|
||||
db.getSortedSetRangeWithScores(`pid:${post.pid}:flag:uids`, 0, -1),
|
||||
db.getSortedSetRange(`pid:${post.pid}:flag:uid:reason`, 0, -1),
|
||||
]);
|
||||
|
||||
// Adding in another check here in case a post was improperly dismissed (flag count > 1 but no flags in db)
|
||||
if (uids.length && reasons.length) {
|
||||
// Just take the first entry
|
||||
const datetime = uids[0].score;
|
||||
const reason = reasons[0].split(':')[1];
|
||||
|
||||
try {
|
||||
const flagObj = await flags.create('post', post.pid, uids[0].value, reason, datetime);
|
||||
if (post['flag:state'] || post['flag:assignee']) {
|
||||
await flags.update(flagObj.flagId, 1, {
|
||||
state: post['flag:state'],
|
||||
assignee: post['flag:assignee'],
|
||||
datetime: datetime,
|
||||
});
|
||||
}
|
||||
|
||||
// Adding in another check here in case a post was improperly dismissed (flag count > 1 but no flags in db)
|
||||
if (!data.uids.length || !data.reasons.length) {
|
||||
return setImmediate(next);
|
||||
if (post.hasOwnProperty('flag:notes') && post['flag:notes'].length) {
|
||||
let history = JSON.parse(post['flag:history']);
|
||||
history = history.filter(event => event.type === 'notes')[0];
|
||||
await flags.appendNote(flagObj.flagId, history.uid, post['flag:notes'], history.timestamp);
|
||||
}
|
||||
|
||||
// Just take the first entry
|
||||
const datetime = data.uids[0].score;
|
||||
const reason = data.reasons[0].split(':')[1];
|
||||
let flagObj;
|
||||
|
||||
async.waterfall([
|
||||
async.apply(flags.create, 'post', post.pid, data.uids[0].value, reason, datetime),
|
||||
function (_flagObj, next) {
|
||||
flagObj = _flagObj;
|
||||
if (post['flag:state'] || post['flag:assignee']) {
|
||||
flags.update(flagObj.flagId, 1, {
|
||||
state: post['flag:state'],
|
||||
assignee: post['flag:assignee'],
|
||||
datetime: datetime,
|
||||
}, next);
|
||||
} else {
|
||||
setImmediate(next);
|
||||
}
|
||||
},
|
||||
function (next) {
|
||||
if (post.hasOwnProperty('flag:notes') && post['flag:notes'].length) {
|
||||
try {
|
||||
let history = JSON.parse(post['flag:history']);
|
||||
history = history.filter(event => event.type === 'notes')[0];
|
||||
|
||||
flags.appendNote(flagObj.flagId, history.uid, post['flag:notes'], history.timestamp, next);
|
||||
} catch (e) {
|
||||
next(e);
|
||||
}
|
||||
} else {
|
||||
setImmediate(next);
|
||||
}
|
||||
},
|
||||
], (err) => {
|
||||
if (err && err.message === '[[error:post-already-flagged]]') {
|
||||
// Already flagged, no need to parse, but not an error
|
||||
next();
|
||||
} else {
|
||||
next(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
}, next);
|
||||
});
|
||||
} catch (err) {
|
||||
if (err.message !== '[[error:post-already-flagged]]') {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
}, {
|
||||
progress: this.progress,
|
||||
}, callback);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
@ -1,36 +1,26 @@
|
||||
'use strict';
|
||||
|
||||
const async = require('async');
|
||||
const db = require('../../database');
|
||||
const batch = require('../../batch');
|
||||
|
||||
|
||||
module.exports = {
|
||||
name: 'Remove relative_path from uploaded profile cover urls',
|
||||
timestamp: Date.UTC(2017, 3, 26),
|
||||
method: function (callback) {
|
||||
method: async function () {
|
||||
const { progress } = this;
|
||||
|
||||
batch.processSortedSet('users:joindate', (ids, done) => {
|
||||
async.each(ids, (uid, cb) => {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.getObjectField(`user:${uid}`, 'cover:url', next);
|
||||
},
|
||||
function (url, next) {
|
||||
progress.incr();
|
||||
|
||||
if (!url) {
|
||||
return next();
|
||||
}
|
||||
await batch.processSortedSet('users:joindate', async (ids) => {
|
||||
await Promise.all(ids.map(async (uid) => {
|
||||
const url = await db.getObjectField(`user:${uid}`, 'cover:url');
|
||||
progress.incr();
|
||||
|
||||
const newUrl = url.replace(/^.*?\/uploads\//, '/assets/uploads/');
|
||||
db.setObjectField(`user:${uid}`, 'cover:url', newUrl, next);
|
||||
},
|
||||
], cb);
|
||||
}, done);
|
||||
if (url) {
|
||||
const newUrl = url.replace(/^.*?\/uploads\//, '/assets/uploads/');
|
||||
await db.setObjectField(`user:${uid}`, 'cover:url', newUrl);
|
||||
}
|
||||
}));
|
||||
}, {
|
||||
progress: this.progress,
|
||||
}, callback);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
@ -1,31 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
const async = require('async');
|
||||
const crypto = require('crypto');
|
||||
const meta = require('../../meta');
|
||||
|
||||
module.exports = {
|
||||
name: 'Clearing stale digest templates that were accidentally saved as custom',
|
||||
timestamp: Date.UTC(2017, 8, 6),
|
||||
method: function (callback) {
|
||||
method: async function () {
|
||||
const matches = [
|
||||
'112e541b40023d6530dd44df4b0d9c5d', // digest @ 75917e25b3b5ad7bed8ed0c36433fb35c9ab33eb
|
||||
'110b8805f70395b0282fd10555059e9f', // digest @ 9b02bb8f51f0e47c6e335578f776ffc17bc03537
|
||||
'9538e7249edb369b2a25b03f2bd3282b', // digest @ 3314ab4b83138c7ae579ac1f1f463098b8c2d414
|
||||
];
|
||||
|
||||
async.waterfall([
|
||||
async.apply(meta.configs.getFields, ['email:custom:digest']),
|
||||
function (fieldset, next) {
|
||||
const hash = fieldset['email:custom:digest'] ? crypto.createHash('md5').update(fieldset['email:custom:digest']).digest('hex') : null;
|
||||
|
||||
if (matches.includes(hash)) {
|
||||
meta.configs.remove('email:custom:digest', next);
|
||||
} else {
|
||||
setImmediate(next);
|
||||
}
|
||||
},
|
||||
], callback);
|
||||
const fieldset = await meta.configs.getFields(['email:custom:digest']);
|
||||
const hash = fieldset['email:custom:digest'] ? crypto.createHash('md5').update(fieldset['email:custom:digest']).digest('hex') : null;
|
||||
if (matches.includes(hash)) {
|
||||
await meta.configs.remove('email:custom:digest');
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -1,25 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
const async = require('async');
|
||||
|
||||
const db = require('../../database');
|
||||
|
||||
module.exports = {
|
||||
name: 'Changing ip blacklist storage to object',
|
||||
timestamp: Date.UTC(2017, 8, 7),
|
||||
method: function (callback) {
|
||||
let rules;
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.get('ip-blacklist-rules', next);
|
||||
},
|
||||
function (_rules, next) {
|
||||
rules = _rules;
|
||||
db.delete('ip-blacklist-rules', rules ? next : callback);
|
||||
},
|
||||
function (next) {
|
||||
db.setObject('ip-blacklist-rules', { rules: rules }, next);
|
||||
},
|
||||
], callback);
|
||||
method: async function () {
|
||||
const rules = await db.get('ip-blacklist-rules');
|
||||
await db.delete('ip-blacklist-rules');
|
||||
await db.setObject('ip-blacklist-rules', { rules: rules });
|
||||
},
|
||||
};
|
||||
|
@ -1,35 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
const async = require('async');
|
||||
const db = require('../../database');
|
||||
|
||||
module.exports = {
|
||||
name: 'Fix incorrect robots.txt schema',
|
||||
timestamp: Date.UTC(2017, 6, 10),
|
||||
method: function (callback) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.getObject('config', next);
|
||||
},
|
||||
function (config, next) {
|
||||
if (!config) {
|
||||
return callback();
|
||||
}
|
||||
// fix mongo nested data
|
||||
if (config.robots && config.robots.txt) {
|
||||
db.setObjectField('config', 'robots:txt', config.robots.txt, next);
|
||||
} else if (typeof config['robots.txt'] === 'string' && config['robots.txt']) {
|
||||
db.setObjectField('config', 'robots:txt', config['robots.txt'], next);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
},
|
||||
function (next) {
|
||||
db.deleteObjectField('config', 'robots', next);
|
||||
},
|
||||
function (next) {
|
||||
db.deleteObjectField('config', 'robots.txt', next);
|
||||
},
|
||||
], callback);
|
||||
method: async function () {
|
||||
const config = await db.getObject('config');
|
||||
if (config) {
|
||||
// fix mongo nested data
|
||||
if (config.robots && config.robots.txt) {
|
||||
await db.setObjectField('config', 'robots:txt', config.robots.txt);
|
||||
} else if (typeof config['robots.txt'] === 'string' && config['robots.txt']) {
|
||||
await db.setObjectField('config', 'robots:txt', config['robots.txt']);
|
||||
}
|
||||
await db.deleteObjectField('config', 'robots');
|
||||
await db.deleteObjectField('config', 'robots.txt');
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -1,48 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
const async = require('async');
|
||||
const batch = require('../../batch');
|
||||
const db = require('../../database');
|
||||
|
||||
module.exports = {
|
||||
name: 'Convert old notification digest settings',
|
||||
timestamp: Date.UTC(2017, 10, 15),
|
||||
method: function (callback) {
|
||||
method: async function () {
|
||||
const { progress } = this;
|
||||
|
||||
batch.processSortedSet('users:joindate', (uids, next) => {
|
||||
async.eachLimit(uids, 500, (uid, next) => {
|
||||
await batch.processSortedSet('users:joindate', async (uids) => {
|
||||
await Promise.all(uids.map(async (uid) => {
|
||||
progress.incr();
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.getObjectFields(`user:${uid}:settings`, ['sendChatNotifications', 'sendPostNotifications'], next);
|
||||
},
|
||||
function (userSettings, _next) {
|
||||
if (!userSettings) {
|
||||
return next();
|
||||
}
|
||||
const tasks = [];
|
||||
if (parseInt(userSettings.sendChatNotifications, 10) === 1) {
|
||||
tasks.push(async.apply(db.setObjectField, `user:${uid}:settings`, 'notificationType_new-chat', 'notificationemail'));
|
||||
}
|
||||
if (parseInt(userSettings.sendPostNotifications, 10) === 1) {
|
||||
tasks.push(async.apply(db.setObjectField, `user:${uid}:settings`, 'notificationType_new-reply', 'notificationemail'));
|
||||
}
|
||||
if (!tasks.length) {
|
||||
return next();
|
||||
}
|
||||
|
||||
async.series(tasks, (err) => {
|
||||
_next(err);
|
||||
});
|
||||
},
|
||||
function (next) {
|
||||
db.deleteObjectFields(`user:${uid}:settings`, ['sendChatNotifications', 'sendPostNotifications'], next);
|
||||
},
|
||||
], next);
|
||||
}, next);
|
||||
const userSettings = await db.getObjectFields(`user:${uid}:settings`, ['sendChatNotifications', 'sendPostNotifications']);
|
||||
if (userSettings) {
|
||||
if (parseInt(userSettings.sendChatNotifications, 10) === 1) {
|
||||
await db.setObjectField(`user:${uid}:settings`, 'notificationType_new-chat', 'notificationemail');
|
||||
}
|
||||
if (parseInt(userSettings.sendPostNotifications, 10) === 1) {
|
||||
await db.setObjectField(`user:${uid}:settings`, 'notificationType_new-reply', 'notificationemail');
|
||||
}
|
||||
}
|
||||
await db.deleteObjectFields(`user:${uid}:settings`, ['sendChatNotifications', 'sendPostNotifications']);
|
||||
}));
|
||||
}, {
|
||||
progress: progress,
|
||||
}, callback);
|
||||
batch: 500,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
@ -1,53 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
const async = require('async');
|
||||
const batch = require('../../batch');
|
||||
const db = require('../../database');
|
||||
|
||||
module.exports = {
|
||||
name: 'Fix sort by votes for moved topics',
|
||||
timestamp: Date.UTC(2018, 0, 8),
|
||||
method: function (callback) {
|
||||
method: async function () {
|
||||
const { progress } = this;
|
||||
|
||||
batch.processSortedSet('topics:tid', (tids, next) => {
|
||||
async.eachLimit(tids, 500, (tid, _next) => {
|
||||
await batch.processSortedSet('topics:tid', async (tids) => {
|
||||
await Promise.all(tids.map(async (tid) => {
|
||||
progress.incr();
|
||||
let topicData;
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.getObjectFields(`topic:${tid}`, ['cid', 'oldCid', 'upvotes', 'downvotes', 'pinned'], next);
|
||||
},
|
||||
function (_topicData, next) {
|
||||
topicData = _topicData;
|
||||
if (!topicData.cid || !topicData.oldCid) {
|
||||
return _next();
|
||||
}
|
||||
|
||||
const upvotes = parseInt(topicData.upvotes, 10) || 0;
|
||||
const downvotes = parseInt(topicData.downvotes, 10) || 0;
|
||||
const votes = upvotes - downvotes;
|
||||
|
||||
async.series([
|
||||
function (next) {
|
||||
db.sortedSetRemove(`cid:${topicData.oldCid}:tids:votes`, tid, next);
|
||||
},
|
||||
function (next) {
|
||||
if (parseInt(topicData.pinned, 10) !== 1) {
|
||||
db.sortedSetAdd(`cid:${topicData.cid}:tids:votes`, votes, tid, next);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
},
|
||||
], (err) => {
|
||||
next(err);
|
||||
});
|
||||
},
|
||||
], _next);
|
||||
}, next);
|
||||
const topicData = await db.getObjectFields(`topic:${tid}`, ['cid', 'oldCid', 'upvotes', 'downvotes', 'pinned']);
|
||||
if (topicData.cid && topicData.oldCid) {
|
||||
const upvotes = parseInt(topicData.upvotes, 10) || 0;
|
||||
const downvotes = parseInt(topicData.downvotes, 10) || 0;
|
||||
const votes = upvotes - downvotes;
|
||||
await db.sortedSetRemove(`cid:${topicData.oldCid}:tids:votes`, tid);
|
||||
if (parseInt(topicData.pinned, 10) !== 1) {
|
||||
await db.sortedSetAdd(`cid:${topicData.cid}:tids:votes`, votes, tid);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}, {
|
||||
progress: progress,
|
||||
batch: 500,
|
||||
}, callback);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
@ -1,52 +1,29 @@
|
||||
'use strict';
|
||||
|
||||
const async = require('async');
|
||||
const batch = require('../../batch');
|
||||
const db = require('../../database');
|
||||
|
||||
module.exports = {
|
||||
name: 'Fix topics in categories per user if they were moved',
|
||||
timestamp: Date.UTC(2018, 0, 22),
|
||||
method: function (callback) {
|
||||
method: async function () {
|
||||
const { progress } = this;
|
||||
|
||||
batch.processSortedSet('topics:tid', (tids, next) => {
|
||||
async.eachLimit(tids, 500, (tid, _next) => {
|
||||
await batch.processSortedSet('topics:tid', async (tids) => {
|
||||
await Promise.all(tids.map(async (tid) => {
|
||||
progress.incr();
|
||||
let topicData;
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.getObjectFields(`topic:${tid}`, ['cid', 'tid', 'uid', 'oldCid', 'timestamp'], next);
|
||||
},
|
||||
function (_topicData, next) {
|
||||
topicData = _topicData;
|
||||
if (!topicData.cid || !topicData.oldCid) {
|
||||
return _next();
|
||||
}
|
||||
|
||||
db.isSortedSetMember(`cid:${topicData.oldCid}:uid:${topicData.uid}`, topicData.tid, next);
|
||||
},
|
||||
function (isMember, next) {
|
||||
if (isMember) {
|
||||
async.series([
|
||||
function (next) {
|
||||
db.sortedSetRemove(`cid:${topicData.oldCid}:uid:${topicData.uid}:tids`, tid, next);
|
||||
},
|
||||
function (next) {
|
||||
db.sortedSetAdd(`cid:${topicData.cid}:uid:${topicData.uid}:tids`, topicData.timestamp, tid, next);
|
||||
},
|
||||
], (err) => {
|
||||
next(err);
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
},
|
||||
], _next);
|
||||
}, next);
|
||||
const topicData = await db.getObjectFields(`topic:${tid}`, ['cid', 'tid', 'uid', 'oldCid', 'timestamp']);
|
||||
if (topicData.cid && topicData.oldCid) {
|
||||
const isMember = await db.isSortedSetMember(`cid:${topicData.oldCid}:uid:${topicData.uid}`, topicData.tid);
|
||||
if (isMember) {
|
||||
await db.sortedSetRemove(`cid:${topicData.oldCid}:uid:${topicData.uid}:tids`, tid);
|
||||
await db.sortedSetAdd(`cid:${topicData.cid}:uid:${topicData.uid}:tids`, topicData.timestamp, tid);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}, {
|
||||
progress: progress,
|
||||
batch: 500,
|
||||
}, callback);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
@ -1,38 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
const async = require('async');
|
||||
const db = require('../../database');
|
||||
|
||||
module.exports = {
|
||||
name: 'Flatten navigation data',
|
||||
timestamp: Date.UTC(2018, 1, 17),
|
||||
method: function (callback) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.getSortedSetRangeWithScores('navigation:enabled', 0, -1, next);
|
||||
},
|
||||
function (data, next) {
|
||||
const order = [];
|
||||
const items = [];
|
||||
data.forEach((item) => {
|
||||
let navItem = JSON.parse(item.value);
|
||||
const keys = Object.keys(navItem);
|
||||
if (keys.length && parseInt(keys[0], 10) >= 0) {
|
||||
navItem = navItem[keys[0]];
|
||||
}
|
||||
order.push(item.score);
|
||||
items.push(JSON.stringify(navItem));
|
||||
});
|
||||
|
||||
async.series([
|
||||
function (next) {
|
||||
db.delete('navigation:enabled', next);
|
||||
},
|
||||
function (next) {
|
||||
db.sortedSetAdd('navigation:enabled', order, items, next);
|
||||
},
|
||||
], next);
|
||||
},
|
||||
], callback);
|
||||
method: async function () {
|
||||
const data = await db.getSortedSetRangeWithScores('navigation:enabled', 0, -1);
|
||||
const order = [];
|
||||
const items = [];
|
||||
data.forEach((item) => {
|
||||
let navItem = JSON.parse(item.value);
|
||||
const keys = Object.keys(navItem);
|
||||
if (keys.length && parseInt(keys[0], 10) >= 0) {
|
||||
navItem = navItem[keys[0]];
|
||||
}
|
||||
order.push(item.score);
|
||||
items.push(JSON.stringify(navItem));
|
||||
});
|
||||
await db.delete('navigation:enabled');
|
||||
await db.sortedSetAdd('navigation:enabled', order, items);
|
||||
},
|
||||
};
|
||||
|
@ -1,28 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
const async = require('async');
|
||||
const db = require('../../database');
|
||||
|
||||
module.exports = {
|
||||
name: 'Add default settings for notification delivery types',
|
||||
timestamp: Date.UTC(2018, 1, 14),
|
||||
method: function (callback) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.getObject('config', next);
|
||||
},
|
||||
function (config, next) {
|
||||
const postNotifications = parseInt(config.sendPostNotifications, 10) === 1 ? 'notification' : 'none';
|
||||
const chatNotifications = parseInt(config.sendChatNotifications, 10) === 1 ? 'notification' : 'none';
|
||||
db.setObject('config', {
|
||||
notificationType_upvote: config.notificationType_upvote || 'notification',
|
||||
'notificationType_new-topic': config['notificationType_new-topic'] || 'notification',
|
||||
'notificationType_new-reply': config['notificationType_new-reply'] || postNotifications,
|
||||
notificationType_follow: config.notificationType_follow || 'notification',
|
||||
'notificationType_new-chat': config['notificationType_new-chat'] || chatNotifications,
|
||||
'notificationType_group-invite': config['notificationType_group-invite'] || 'notification',
|
||||
}, next);
|
||||
},
|
||||
], callback);
|
||||
method: async function () {
|
||||
const config = await db.getObject('config');
|
||||
const postNotifications = parseInt(config.sendPostNotifications, 10) === 1 ? 'notification' : 'none';
|
||||
const chatNotifications = parseInt(config.sendChatNotifications, 10) === 1 ? 'notification' : 'none';
|
||||
await db.setObject('config', {
|
||||
notificationType_upvote: config.notificationType_upvote || 'notification',
|
||||
'notificationType_new-topic': config['notificationType_new-topic'] || 'notification',
|
||||
'notificationType_new-reply': config['notificationType_new-reply'] || postNotifications,
|
||||
notificationType_follow: config.notificationType_follow || 'notification',
|
||||
'notificationType_new-chat': config['notificationType_new-chat'] || chatNotifications,
|
||||
'notificationType_group-invite': config['notificationType_group-invite'] || 'notification',
|
||||
});
|
||||
},
|
||||
};
|
||||
|
@ -1,22 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
const async = require('async');
|
||||
const db = require('../../database');
|
||||
|
||||
|
||||
module.exports = {
|
||||
name: 'Revising minimum password strength to 1 (from 0)',
|
||||
timestamp: Date.UTC(2018, 1, 21),
|
||||
method: function (callback) {
|
||||
async.waterfall([
|
||||
async.apply(db.getObjectField.bind(db), 'config', 'minimumPasswordStrength'),
|
||||
function (strength, next) {
|
||||
if (!strength) {
|
||||
return db.setObjectField('config', 'minimumPasswordStrength', 1, next);
|
||||
}
|
||||
|
||||
setImmediate(next);
|
||||
},
|
||||
], callback);
|
||||
method: async function () {
|
||||
const strength = await db.getObjectField('config', 'minimumPasswordStrength');
|
||||
if (!strength) {
|
||||
await db.setObjectField('config', 'minimumPasswordStrength', 1);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
Loading…
Reference in New Issue