diff --git a/src/upgrades/1.10.0/view_deleted_privilege.js b/src/upgrades/1.10.0/view_deleted_privilege.js index ddf4b9c3fc..a483bcf417 100644 --- a/src/upgrades/1.10.0/view_deleted_privilege.js +++ b/src/upgrades/1.10.0/view_deleted_privilege.js @@ -1,27 +1,22 @@ +/* eslint-disable no-await-in-loop */ + 'use strict'; - -const async = require('async'); - const groups = require('../../groups'); const db = require('../../database'); module.exports = { name: 'Give deleted post viewing privilege to moderators on all categories', timestamp: Date.UTC(2018, 5, 8), - method: function (callback) { - db.getSortedSetRange('categories:cid', 0, -1, (err, cids) => { - if (err) { - return callback(err); + method: async function () { + const { progress } = this; + const cids = await db.getSortedSetRange('categories:cid', 0, -1); + for (const cid of cids) { + const uids = await db.getSortedSetRange(`group:cid:${cid}:privileges:moderate:members`, 0, -1); + for (const uid of uids) { + await groups.join(`cid:${cid}:privileges:posts:view_deleted`, uid); } - async.eachSeries(cids, (cid, next) => { - async.waterfall([ - async.apply(db.getSortedSetRange.bind(db), `group:cid:${cid}:privileges:moderate:members`, 0, -1), - function (uids, next) { - async.eachSeries(uids, (uid, next) => groups.join(`cid:${cid}:privileges:posts:view_deleted`, uid, next), next); - }, - ], next); - }, callback); - }); + progress.incr(); + } }, }; diff --git a/src/upgrades/1.10.2/event_filters.js b/src/upgrades/1.10.2/event_filters.js index d87a526d5e..cf2709a5ab 100644 --- a/src/upgrades/1.10.2/event_filters.js +++ b/src/upgrades/1.10.2/event_filters.js @@ -1,6 +1,7 @@ +/* eslint-disable no-await-in-loop */ + 'use strict'; -const async = require('async'); const db = require('../../database'); const batch = require('../../batch'); @@ -8,39 +9,29 @@ const batch = require('../../batch'); module.exports = { name: 'add filters to events', timestamp: Date.UTC(2018, 9, 4), - method: function (callback) { + method: async function () { const { progress } = this; - batch.processSortedSet('events:time', (eids, next) => { - async.eachSeries(eids, (eid, next) => { + await batch.processSortedSet('events:time', async (eids) => { + for (const eid of eids) { progress.incr(); - db.getObject(`event:${eid}`, (err, eventData) => { - if (err) { - return next(err); - } - if (!eventData) { - return db.sortedSetRemove('events:time', eid, next); - } - // privilege events we're missing type field - if (!eventData.type && eventData.privilege) { - eventData.type = 'privilege-change'; - async.waterfall([ - function (next) { - db.setObjectField(`event:${eid}`, 'type', 'privilege-change', next); - }, - function (next) { - db.sortedSetAdd(`events:time:${eventData.type}`, eventData.timestamp, eid, next); - }, - ], next); - return; - } - - db.sortedSetAdd(`events:time:${eventData.type || ''}`, eventData.timestamp, eid, next); - }); - }, next); + const eventData = await db.getObject(`event:${eid}`); + if (!eventData) { + await db.sortedSetRemove('events:time', eid); + return; + } + // privilege events we're missing type field + if (!eventData.type && eventData.privilege) { + eventData.type = 'privilege-change'; + await db.setObjectField(`event:${eid}`, 'type', 'privilege-change'); + await db.sortedSetAdd(`events:time:${eventData.type}`, eventData.timestamp, eid); + return; + } + await db.sortedSetAdd(`events:time:${eventData.type || ''}`, eventData.timestamp, eid); + } }, { progress: this.progress, - }, callback); + }); }, }; diff --git a/src/upgrades/1.10.2/fix_category_topic_zsets.js b/src/upgrades/1.10.2/fix_category_topic_zsets.js index 692d35af18..999383feac 100644 --- a/src/upgrades/1.10.2/fix_category_topic_zsets.js +++ b/src/upgrades/1.10.2/fix_category_topic_zsets.js @@ -1,6 +1,7 @@ +/* eslint-disable no-await-in-loop */ + 'use strict'; -const async = require('async'); const db = require('../../database'); const batch = require('../../batch'); @@ -8,32 +9,22 @@ const batch = require('../../batch'); module.exports = { name: 'Fix category topic zsets', timestamp: Date.UTC(2018, 9, 11), - method: function (callback) { + method: async function () { const { progress } = this; const topics = require('../../topics'); - batch.processSortedSet('topics:tid', (tids, next) => { - async.eachSeries(tids, (tid, next) => { + await batch.processSortedSet('topics:tid', async (tids) => { + for (const tid of tids) { progress.incr(); - - async.waterfall([ - function (next) { - db.getObjectFields(`topic:${tid}`, ['cid', 'pinned', 'postcount'], next); - }, - function (topicData, next) { - if (parseInt(topicData.pinned, 10) === 1) { - return setImmediate(next); - } - topicData.postcount = parseInt(topicData.postcount, 10) || 0; - db.sortedSetAdd(`cid:${topicData.cid}:tids:posts`, topicData.postcount, tid, next); - }, - function (next) { - topics.updateLastPostTimeFromLastPid(tid, next); - }, - ], next); - }, next); + const topicData = await db.getObjectFields(`topic:${tid}`, ['cid', 'pinned', 'postcount']); + if (parseInt(topicData.pinned, 10) !== 1) { + topicData.postcount = parseInt(topicData.postcount, 10) || 0; + await db.sortedSetAdd(`cid:${topicData.cid}:tids:posts`, topicData.postcount, tid); + } + await topics.updateLastPostTimeFromLastPid(tid); + } }, { progress: progress, - }, callback); + }); }, }; diff --git a/src/upgrades/1.10.2/upgrade_bans_to_hashes.js b/src/upgrades/1.10.2/upgrade_bans_to_hashes.js index 24a2cd8cc0..84c7a0ed4d 100644 --- a/src/upgrades/1.10.2/upgrade_bans_to_hashes.js +++ b/src/upgrades/1.10.2/upgrade_bans_to_hashes.js @@ -1,69 +1,39 @@ +/* eslint-disable no-await-in-loop */ + 'use strict'; -const async = require('async'); const db = require('../../database'); - const batch = require('../../batch'); -// var user = require('../../user'); module.exports = { name: 'Upgrade bans to hashes', timestamp: Date.UTC(2018, 8, 24), - method: function (callback) { + method: async function () { const { progress } = this; - batch.processSortedSet('users:joindate', (uids, next) => { - async.eachSeries(uids, (uid, next) => { + await batch.processSortedSet('users:joindate', async (uids) => { + for (const uid of uids) { progress.incr(); + const [bans, reasons, userData] = await Promise.all([ + db.getSortedSetRevRangeWithScores(`uid:${uid}:bans`, 0, -1), + db.getSortedSetRevRangeWithScores(`banned:${uid}:reasons`, 0, -1), + db.getObjectFields(`user:${uid}`, ['banned', 'banned:expire', 'joindate', 'lastposttime', 'lastonline']), + ]); - async.parallel({ - bans: function (next) { - db.getSortedSetRevRangeWithScores(`uid:${uid}:bans`, 0, -1, next); - }, - reasons: function (next) { - db.getSortedSetRevRangeWithScores(`banned:${uid}:reasons`, 0, -1, next); - }, - userData: function (next) { - db.getObjectFields(`user:${uid}`, ['banned', 'banned:expire', 'joindate', 'lastposttime', 'lastonline'], next); - }, - }, (err, results) => { - function addBan(key, data, callback) { - async.waterfall([ - function (next) { - db.setObject(key, data, next); - }, - function (next) { - db.sortedSetAdd(`uid:${uid}:bans:timestamp`, data.timestamp, key, next); - }, - ], callback); - } - if (err) { - return next(err); - } - // has no ban history and isn't banned, skip - if (!results.bans.length && !parseInt(results.userData.banned, 10)) { - return next(); - } - - // has no history, but is banned, create plain object with just uid and timestmap - if (!results.bans.length && parseInt(results.userData.banned, 10)) { - const banTimestamp = ( - results.userData.lastonline || - results.userData.lastposttime || - results.userData.joindate || - Date.now() - ); - const banKey = `uid:${uid}:ban:${banTimestamp}`; - addBan(banKey, { uid: uid, timestamp: banTimestamp }, next); - return; - } - + // has no history, but is banned, create plain object with just uid and timestmap + if (!bans.length && parseInt(userData.banned, 10)) { + const banTimestamp = ( + userData.lastonline || + userData.lastposttime || + userData.joindate || + Date.now() + ); + const banKey = `uid:${uid}:ban:${banTimestamp}`; + await addBan(uid, banKey, { uid: uid, timestamp: banTimestamp }); + } else if (bans.length) { // process ban history - async.eachSeries(results.bans, (ban, next) => { - function findReason(score) { - return results.reasons.find(reasonData => reasonData.score === score); - } - const reasonData = findReason(ban.score); + for (const ban of bans) { + const reasonData = reasons.find(reasonData => reasonData.score === ban.score); const banKey = `uid:${uid}:ban:${ban.score}`; const data = { uid: uid, @@ -73,14 +43,17 @@ module.exports = { if (reasonData) { data.reason = reasonData.value; } - addBan(banKey, data, next); - }, (err) => { - next(err); - }); - }); - }, next); + await addBan(uid, banKey, data); + } + } + } }, { progress: this.progress, - }, callback); + }); }, }; + +async function addBan(uid, key, data) { + await db.setObject(key, data); + await db.sortedSetAdd(`uid:${uid}:bans:timestamp`, data.timestamp, key); +} diff --git a/src/upgrades/1.10.2/username_email_history.js b/src/upgrades/1.10.2/username_email_history.js index 69bae687d3..3b03568a69 100644 --- a/src/upgrades/1.10.2/username_email_history.js +++ b/src/upgrades/1.10.2/username_email_history.js @@ -1,6 +1,5 @@ 'use strict'; -const async = require('async'); const db = require('../../database'); const batch = require('../../batch'); @@ -9,61 +8,30 @@ const user = require('../../user'); module.exports = { name: 'Record first entry in username/email history', timestamp: Date.UTC(2018, 7, 28), - method: function (callback) { + method: async function () { const { progress } = this; - batch.processSortedSet('users:joindate', (ids, next) => { - async.each(ids, (uid, next) => { - async.parallel([ - function (next) { - // Username - async.waterfall([ - async.apply(db.sortedSetCard, `user:${uid}:usernames`), - (count, next) => { - if (count > 0) { - // User has changed their username before, no record of original username, skip. - return setImmediate(next, null, null); - } + await batch.processSortedSet('users:joindate', async (uids) => { + async function updateHistory(uid, set, fieldName) { + const count = await db.sortedSetCard(set); + if (count <= 0) { + // User has not changed their username/email before, record original username + const userData = await user.getUserFields(uid, [fieldName, 'joindate']); + if (userData && userData.joindate && userData[fieldName]) { + await db.sortedSetAdd(set, userData.joindate, [userData[fieldName], userData.joindate].join(':')); + } + } + } - user.getUserFields(uid, ['username', 'joindate'], next); - }, - (userdata, next) => { - if (!userdata || !userdata.joindate) { - return setImmediate(next); - } - - db.sortedSetAdd(`user:${uid}:usernames`, userdata.joindate, [userdata.username, userdata.joindate].join(':'), next); - }, - ], next); - }, - function (next) { - // Email - async.waterfall([ - async.apply(db.sortedSetCard, `user:${uid}:emails`), - (count, next) => { - if (count > 0) { - // User has changed their email before, no record of original email, skip. - return setImmediate(next, null, null); - } - - user.getUserFields(uid, ['email', 'joindate'], next); - }, - (userdata, next) => { - if (!userdata || !userdata.joindate) { - return setImmediate(next); - } - - db.sortedSetAdd(`user:${uid}:emails`, userdata.joindate, [userdata.email, userdata.joindate].join(':'), next); - }, - ], next); - }, - ], (err) => { - progress.incr(); - setImmediate(next, err); - }); - }, next); + await Promise.all(uids.map(async (uid) => { + await Promise.all([ + updateHistory(uid, `user:${uid}:usernames`, 'username'), + updateHistory(uid, `user:${uid}:emails`, 'email'), + ]); + progress.incr(); + })); }, { progress: this.progress, - }, callback); + }); }, }; diff --git a/src/upgrades/1.11.0/navigation_visibility_groups.js b/src/upgrades/1.11.0/navigation_visibility_groups.js index 0a5e0b733d..3567b3c9c1 100644 --- a/src/upgrades/1.11.0/navigation_visibility_groups.js +++ b/src/upgrades/1.11.0/navigation_visibility_groups.js @@ -1,36 +1,28 @@ 'use strict'; -const async = require('async'); - module.exports = { name: 'Navigation item visibility groups', timestamp: Date.UTC(2018, 10, 10), - method: function (callback) { + method: async function () { const navigationAdmin = require('../../navigation/admin'); - async.waterfall([ - function (next) { - navigationAdmin.get(next); - }, - function (data, next) { - data.forEach((navItem) => { - if (navItem && navItem.properties) { - navItem.groups = []; - if (navItem.properties.adminOnly) { - navItem.groups.push('administrators'); - } else if (navItem.properties.globalMod) { - navItem.groups.push('Global Moderators'); - } + const data = await navigationAdmin.get(); + data.forEach((navItem) => { + if (navItem && navItem.properties) { + navItem.groups = []; + if (navItem.properties.adminOnly) { + navItem.groups.push('administrators'); + } else if (navItem.properties.globalMod) { + navItem.groups.push('Global Moderators'); + } - if (navItem.properties.loggedIn) { - navItem.groups.push('registered-users'); - } else if (navItem.properties.guestOnly) { - navItem.groups.push('guests'); - } - } - }); - navigationAdmin.save(data, next); - }, - ], callback); + if (navItem.properties.loggedIn) { + navItem.groups.push('registered-users'); + } else if (navItem.properties.guestOnly) { + navItem.groups.push('guests'); + } + } + }); + await navigationAdmin.save(data); }, };