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