From 1e480eb542c1404f3c8e7d25e89975c3a881a69d Mon Sep 17 00:00:00 2001 From: Akshra Paimagam Date: Thu, 10 Oct 2024 18:26:08 -0400 Subject: [PATCH 1/3] Added functionality that displays green endorsement checkmark when 'Endorse Topic' button is pressed and removes checkmark when 'Unendorse Topic' is pressed --- public/src/client/topic/threadTools.js | 1 + 1 file changed, 1 insertion(+) diff --git a/public/src/client/topic/threadTools.js b/public/src/client/topic/threadTools.js index 79fcc049f5..66d6fdb4ed 100644 --- a/public/src/client/topic/threadTools.js +++ b/public/src/client/topic/threadTools.js @@ -349,6 +349,7 @@ define('forum/topic/threadTools', [ $('[component="topic/labels"] [component="topic/locked"]').toggleClass('hidden', !data.isLocked); $('[component="topic/endorsed"]').toggleClass('hidden', !data.isEndorsed); + $('[component="topic/endorsed-checkmark"]').toggleClass('hidden', !data.isEndorsed); ajaxify.data.endorsed = data.isEndorsed; posts.addTopicEvents(data.events); From d8b70c3013a4d7bf010d9a6fc528e703d7af632b Mon Sep 17 00:00:00 2001 From: Akshra-school <107316876+Akshra-school@users.noreply.github.com> Date: Thu, 10 Oct 2024 19:19:56 -0400 Subject: [PATCH 2/3] Updated UserGuide.md to include instructions for using green endorsement checkmark --- UserGuide.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/UserGuide.md b/UserGuide.md index 3d0db742c8..db99f9546e 100644 --- a/UserGuide.md +++ b/UserGuide.md @@ -4,10 +4,20 @@ 3. Endorsement actions are logged just like other actions, i.e., lock and pin. 4. Added Endorsed tag in topic list (displayed after clicking on a category) for endorsed topics. 5. Configured `topic.json` and `error.json` for correct rendering. +6. Added functionality for green endorsement checkmark to appear upon click of 'Endorse topic' button and disappear upon click of 'Unendorse topic' button +7. Added hover element for green endorsement checkmark to indicate that instructor has endorsed a post ### Front-end New Testing 1. Ensures correct API calls and privileged users have access to this feature. 2. Rendering test is done by user testing. All new features won't trigger explicit errors. +3. Manually tested green endorsement checkmark by building on personal NodeBB account + - Navigating to Announcements page + - Click on a post (if no existing post, click New Topic and enter relevant content and submit) + - Click on Topic Tools and click the menu option that states Endorse Topic + - Upon clicking on this button, you will see a green checkmark next to the post number + - When you hover over the green checkmark, you will see a note that says 'An instructor endorsed this post' + - To unendorse, click on Topic Tools again and click the menu option that states Unendorse Topic + - The green checkmark will disappear ### Back-end Features 1. Added API calls for `endorse` and `unendorse` From 1e04ea7febda19845c738638d57f42173f7f95d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A1=BE=E8=B6=8A=E9=B9=8F?= Date: Wed, 30 Oct 2024 11:10:48 -0400 Subject: [PATCH 3/3] Running small scale experiments with prettier in conjunction with eslint. Worked locally. --- src/api/categories.js | 10 ++------- src/api/chats.js | 13 +++++------ src/api/flags.js | 10 ++------- src/api/groups.js | 17 ++++---------- src/api/helpers.js | 23 +++++++++---------- src/api/posts.js | 42 +++++++++++----------------------- src/api/search.js | 40 +++++++++++++++++++-------------- src/api/topics.js | 17 +++++++------- src/api/users.js | 52 ++++++++++++++++++++++++------------------- src/api/utils.js | 22 ++++++------------ 10 files changed, 105 insertions(+), 141 deletions(-) diff --git a/src/api/categories.js b/src/api/categories.js index 9a43a81526..36fe0595e8 100644 --- a/src/api/categories.js +++ b/src/api/categories.js @@ -23,10 +23,7 @@ categoriesAPI.list = async (caller) => { return await categories.getCategoriesData(cids); } - const [isAdmin, categoriesData] = await Promise.all([ - user.isAdministrator(caller.uid), - getCategories(), - ]); + const [isAdmin, categoriesData] = await Promise.all([user.isAdministrator(caller.uid), getCategories()]); return { categories: categoriesData.filter(category => category && (!category.disabled || isAdmin)), @@ -196,10 +193,7 @@ categoriesAPI.getPrivileges = async (caller, { cid }) => { categoriesAPI.setPrivilege = async (caller, data) => { await hasAdminPrivilege(caller.uid, 'privileges'); - const [userExists, groupExists] = await Promise.all([ - user.exists(data.member), - groups.exists(data.member), - ]); + const [userExists, groupExists] = await Promise.all([user.exists(data.member), groups.exists(data.member)]); if (!userExists && !groupExists) { throw new Error('[[error:no-user-or-group]]'); diff --git a/src/api/chats.js b/src/api/chats.js index abd5c908f2..bd58611ceb 100644 --- a/src/api/chats.js +++ b/src/api/chats.js @@ -42,7 +42,9 @@ chatsAPI.list = async (caller, { uid = caller.uid, start, stop, page, perPage } } if (!start && !stop && page) { - winston.warn('[api/chats] Sending `page` and `perPage` to .list() is deprecated in favour of `start` and `stop`. The deprecated parameters will be removed in v4.'); + winston.warn( + '[api/chats] Sending `page` and `perPage` to .list() is deprecated in favour of `start` and `stop`. The deprecated parameters will be removed in v4.' + ); start = Math.max(0, page - 1) * perPage; stop = start + perPage - 1; } @@ -147,10 +149,7 @@ chatsAPI.update = async (caller, data) => { } await messaging.renameRoom(caller.uid, data.roomId, data.name); } - const [roomData, isAdmin] = await Promise.all([ - messaging.getRoomData(data.roomId), - user.isAdministrator(caller.uid), - ]); + const [roomData, isAdmin] = await Promise.all([messaging.getRoomData(data.roomId), user.isAdministrator(caller.uid)]); if (!roomData) { throw new Error('[[error:invalid-data]]'); } @@ -241,9 +240,7 @@ chatsAPI.users = async (caller, data) => { const [isOwner, isUserInRoom, users, isAdmin, onlineUids] = await Promise.all([ messaging.isRoomOwner(caller.uid, data.roomId), messaging.isUserInRoom(caller.uid, data.roomId), - messaging.getUsersInRoomFromSet( - `chat:room:${data.roomId}:uids:online`, data.roomId, start, stop, true - ), + messaging.getUsersInRoomFromSet(`chat:room:${data.roomId}:uids:online`, data.roomId, start, stop, true), user.isAdministrator(caller.uid), io.getUidsInRoom(`chat_room_${data.roomId}`), ]); diff --git a/src/api/flags.js b/src/api/flags.js index ffa56e2782..9ca3f4198b 100644 --- a/src/api/flags.js +++ b/src/api/flags.js @@ -78,10 +78,7 @@ flagsApi.appendNote = async (caller, data) => { } } await flags.appendNote(data.flagId, caller.uid, data.note, data.datetime); - const [notes, history] = await Promise.all([ - flags.getNotes(data.flagId), - flags.getHistory(data.flagId), - ]); + const [notes, history] = await Promise.all([flags.getNotes(data.flagId), flags.getHistory(data.flagId)]); return { notes: notes, history: history }; }; @@ -97,9 +94,6 @@ flagsApi.deleteNote = async (caller, data) => { datetime: Date.now(), }); - const [notes, history] = await Promise.all([ - flags.getNotes(data.flagId), - flags.getHistory(data.flagId), - ]); + const [notes, history] = await Promise.all([flags.getNotes(data.flagId), flags.getHistory(data.flagId)]); return { notes: notes, history: history }; }; diff --git a/src/api/groups.js b/src/api/groups.js index 95074c4b6a..d0fd9ac0dd 100644 --- a/src/api/groups.js +++ b/src/api/groups.js @@ -60,10 +60,7 @@ groupsAPI.update = async function (caller, data) { groupsAPI.delete = async function (caller, data) { const groupName = await groups.getGroupNameByGroupSlug(data.slug); await isOwner(caller, groupName); - if ( - groups.systemGroups.includes(groupName) || - groups.ephemeralGroups.includes(groupName) - ) { + if (groups.systemGroups.includes(groupName) || groups.ephemeralGroups.includes(groupName)) { throw new Error('[[error:not-allowed]]'); } @@ -78,7 +75,7 @@ groupsAPI.listMembers = async (caller, data) => { const groupName = await groups.getGroupNameByGroupSlug(data.slug); await canSearchMembers(caller.uid, groupName); - if (!await privileges.global.can('search:users', caller.uid)) { + if (!(await privileges.global.can('search:users', caller.uid))) { throw new Error('[[error:no-privileges]]'); } @@ -132,17 +129,11 @@ groupsAPI.join = async function (caller, data) { } const isCallerAdmin = await privileges.admin.can('admin:groups', caller.uid); - if (!isCallerAdmin && ( - groups.systemGroups.includes(groupName) || - groups.isPrivilegeGroup(groupName) - )) { + if (!isCallerAdmin && (groups.systemGroups.includes(groupName) || groups.isPrivilegeGroup(groupName))) { throw new Error('[[error:not-allowed]]'); } - const [groupData, userExists] = await Promise.all([ - groups.getGroupData(groupName), - user.exists(data.uid), - ]); + const [groupData, userExists] = await Promise.all([groups.getGroupData(groupName), user.exists(data.uid)]); if (!userExists) { throw new Error('[[error:invalid-uid]]'); diff --git a/src/api/helpers.js b/src/api/helpers.js index 3e8704cb0c..62e99e4251 100644 --- a/src/api/helpers.js +++ b/src/api/helpers.js @@ -64,14 +64,16 @@ exports.doTopicAction = async function (action, event, caller, { tids }) { const uids = await user.getUidsFromSet('users:online', 0, -1); - await Promise.all(tids.map(async (tid) => { - const title = await topics.getTopicField(tid, 'title'); - // A generic call that handles toggling actions. - const data = await topics.tools[action](tid, caller.uid); - const notifyUids = await privileges.categories.filterUids('topics:read', data.cid, uids); - socketHelpers.emitToUids(event, data, notifyUids); - await logTopicAction(action, caller, tid, title); - })); + await Promise.all( + tids.map(async (tid) => { + const title = await topics.getTopicField(tid, 'title'); + // A generic call that handles toggling actions. + const data = await topics.tools[action](tid, caller.uid); + const notifyUids = await privileges.categories.filterUids('topics:read', data.cid, uids); + socketHelpers.emitToUids(event, data, notifyUids); + await logTopicAction(action, caller, tid, title); + }) + ); }; async function logTopicAction(action, req, tid, title) { @@ -101,10 +103,7 @@ exports.postCommand = async function (caller, command, eventName, notification, if (!data.room_id) { throw new Error(`[[error:invalid-room-id, ${data.room_id}]]`); } - const [exists, deleted] = await Promise.all([ - posts.exists(data.pid), - posts.getPostField(data.pid, 'deleted'), - ]); + const [exists, deleted] = await Promise.all([posts.exists(data.pid), posts.getPostField(data.pid, 'deleted')]); if (!exists) { throw new Error('[[error:invalid-pid]]'); diff --git a/src/api/posts.js b/src/api/posts.js index 4e3917a008..da55d8b2a5 100644 --- a/src/api/posts.js +++ b/src/api/posts.js @@ -101,7 +101,7 @@ postsAPI.edit = async function (caller, data) { throw new Error(`[[error:content-too-short, ${meta.config.minimumPostLength}]]`); } else if (contentLen > meta.config.maximumPostLength) { throw new Error(`[[error:content-too-long, ${meta.config.maximumPostLength}]]`); - } else if (!await posts.canUserPostContentWithLinks(caller.uid, data.content)) { + } else if (!(await posts.canUserPostContentWithLinks(caller.uid, data.content))) { throw new Error(`[[error:not-enough-reputation-to-post-links, ${meta.config['min:rep:post-links']}]]`); } @@ -200,12 +200,10 @@ async function deleteOrRestoreTopicOf(command, pid, caller) { return; } // command: delete/restore - await apiHelpers.doTopicAction( - command, - topic.deleted ? 'event:topic_restored' : 'event:topic_deleted', - caller, - { tids: [topic.tid], cid: topic.cid } - ); + await apiHelpers.doTopicAction(command, topic.deleted ? 'event:topic_restored' : 'event:topic_deleted', caller, { + tids: [topic.tid], + cid: topic.cid, + }); } postsAPI.purge = async function (caller, data) { @@ -242,20 +240,12 @@ postsAPI.purge = async function (caller, data) { }); if (isMainAndLast) { - await apiHelpers.doTopicAction( - 'purge', - 'event:topic_purged', - caller, - { tids: [postData.tid], cid: topicData.cid } - ); + await apiHelpers.doTopicAction('purge', 'event:topic_purged', caller, { tids: [postData.tid], cid: topicData.cid }); } }; async function isMainAndLastPost(pid) { - const [isMain, topicData] = await Promise.all([ - posts.isMain(pid), - posts.getTopicFields(pid, ['postcount']), - ]); + const [isMain, topicData] = await Promise.all([posts.isMain(pid), posts.getTopicFields(pid, ['postcount'])]); return { isMain: isMain, isLast: topicData && topicData.postcount === 1, @@ -351,7 +341,7 @@ postsAPI.getUpvoters = async function (caller, data) { } const { pid } = data; const cid = await posts.getCidByPid(pid); - if (!await canSeeVotes(caller.uid, cid, 'upvoteVisibility')) { + if (!(await canSeeVotes(caller.uid, cid, 'upvoteVisibility'))) { throw new Error('[[error:no-privileges]]'); } @@ -385,22 +375,16 @@ async function canSeeVotes(uid, cids, type) { } const uniqCids = _.uniq(cids); const [canRead, isAdmin, isMod] = await Promise.all([ - privileges.categories.isUserAllowedTo( - 'topics:read', uniqCids, uid - ), + privileges.categories.isUserAllowedTo('topics:read', uniqCids, uid), privileges.users.isAdministrator(uid), privileges.users.isModerator(uid, cids), ]); const cidToAllowed = _.zipObject(uniqCids, canRead); const checks = cids.map( - (cid, index) => isAdmin || isMod[index] || - ( - cidToAllowed[cid] && - ( - meta.config[type] === 'all' || - (meta.config[type] === 'loggedin' && parseInt(uid, 10) > 0) - ) - ) + (cid, index) => isAdmin || + isMod[index] || + (cidToAllowed[cid] && + (meta.config[type] === 'all' || (meta.config[type] === 'loggedin' && parseInt(uid, 10) > 0))) ); return isArray ? checks : checks[0]; } diff --git a/src/api/search.js b/src/api/search.js index b9645ee567..82cc7ef7b3 100644 --- a/src/api/search.js +++ b/src/api/search.js @@ -32,7 +32,12 @@ searchApi.categories = async (caller, data) => { } const visibleCategories = await controllersHelpers.getVisibleCategories({ - cids, uid: caller.uid, states: data.states, privilege, showLinks: data.showLinks, parentCid: data.parentCid, + cids, + uid: caller.uid, + states: data.states, + privilege, + showLinks: data.showLinks, + parentCid: data.parentCid, }); if (Array.isArray(data.selectedCids)) { @@ -67,8 +72,7 @@ async function findMatchedCids(uid, data) { let matchedCids = result.categories.map(c => c.cid); // no need to filter if all 3 states are used - const filterByWatchState = !Object.values(categories.watchStates) - .every(state => data.states.includes(state)); + const filterByWatchState = !Object.values(categories.watchStates).every(state => data.states.includes(state)); if (filterByWatchState) { const states = await categories.getWatchState(matchedCids, uid); @@ -89,14 +93,16 @@ async function loadCids(uid, parentCid) { async function getCidsRecursive(cids) { const categoryData = await categories.getCategoriesFields(cids, ['subCategoriesPerPage']); const cidToData = _.zipObject(cids, categoryData); - await Promise.all(cids.map(async (cid) => { - const allChildCids = await categories.getAllCidsFromSet(`cid:${cid}:children`); - if (allChildCids.length) { - const childCids = await privileges.categories.filterCids('find', allChildCids, uid); - resultCids.push(...childCids.slice(0, cidToData[cid].subCategoriesPerPage)); - await getCidsRecursive(childCids); - } - })); + await Promise.all( + cids.map(async (cid) => { + const allChildCids = await categories.getAllCidsFromSet(`cid:${cid}:children`); + if (allChildCids.length) { + const childCids = await privileges.categories.filterCids('find', allChildCids, uid); + resultCids.push(...childCids.slice(0, cidToData[cid].subCategoriesPerPage)); + await getCidsRecursive(childCids); + } + }) + ); } const allRootCids = await categories.getAllCidsFromSet(`cid:${parentCid}:children`); @@ -127,18 +133,18 @@ searchApi.roomUsers = async (caller, { query, roomId }) => { const { users } = results; const foundUids = users.map(user => user && user.uid); - const isUidInRoom = _.zipObject( - foundUids, - await messaging.isUsersInRoom(foundUids, roomId) - ); + const isUidInRoom = _.zipObject(foundUids, await messaging.isUsersInRoom(foundUids, roomId)); const roomUsers = users.filter(user => isUidInRoom[user.uid]); - const isOwners = await messaging.isRoomOwner(roomUsers.map(u => u.uid), roomId); + const isOwners = await messaging.isRoomOwner( + roomUsers.map(u => u.uid), + roomId + ); roomUsers.forEach((user, index) => { if (user) { user.isOwner = isOwners[index]; - user.canKick = isRoomOwner && (parseInt(user.uid, 10) !== parseInt(caller.uid, 10)); + user.canKick = isRoomOwner && parseInt(user.uid, 10) !== parseInt(caller.uid, 10); } }); diff --git a/src/api/topics.js b/src/api/topics.js index f4f344cee7..5a08febe2f 100644 --- a/src/api/topics.js +++ b/src/api/topics.js @@ -23,12 +23,12 @@ topicsAPI._checkThumbPrivileges = async function ({ tid, uid }) { const isUUID = validator.isUUID(tid); // Sanity-check the tid if it's strictly not a uuid - if (!isUUID && (isNaN(parseInt(tid, 10)) || !await topics.exists(tid))) { + if (!isUUID && (isNaN(parseInt(tid, 10)) || !(await topics.exists(tid)))) { throw new Error('[[error:no-topic]]'); } // While drafts are not protected, tids are - if (!isUUID && !await privileges.topics.canEdit(tid, uid)) { + if (!isUUID && !(await privileges.topics.canEdit(tid, uid))) { throw new Error('[[error:no-privileges]]'); } }; @@ -188,7 +188,7 @@ topicsAPI.unfollow = async function (caller, data) { }; topicsAPI.updateTags = async (caller, { tid, tags }) => { - if (!await privileges.topics.canEdit(tid, caller.uid)) { + if (!(await privileges.topics.canEdit(tid, caller.uid))) { throw new Error('[[error:no-privileges]]'); } @@ -199,7 +199,7 @@ topicsAPI.updateTags = async (caller, { tid, tags }) => { }; topicsAPI.addTags = async (caller, { tid, tags }) => { - if (!await privileges.topics.canEdit(tid, caller.uid)) { + if (!(await privileges.topics.canEdit(tid, caller.uid))) { throw new Error('[[error:no-privileges]]'); } @@ -212,7 +212,7 @@ topicsAPI.addTags = async (caller, { tid, tags }) => { }; topicsAPI.deleteTags = async (caller, { tid }) => { - if (!await privileges.topics.canEdit(tid, caller.uid)) { + if (!(await privileges.topics.canEdit(tid, caller.uid))) { throw new Error('[[error:no-privileges]]'); } @@ -220,7 +220,8 @@ topicsAPI.deleteTags = async (caller, { tid }) => { }; topicsAPI.getThumbs = async (caller, { tid }) => { - if (isFinite(tid)) { // post_uuids can be passed in occasionally, in that case no checks are necessary + if (isFinite(tid)) { + // post_uuids can be passed in occasionally, in that case no checks are necessary const [exists, canRead] = await Promise.all([ topics.exists(tid), privileges.topics.can('topics:read', tid, caller.uid), @@ -268,7 +269,7 @@ topicsAPI.reorderThumbs = async (caller, { tid, path, order }) => { }; topicsAPI.getEvents = async (caller, { tid }) => { - if (!await privileges.topics.can('topics:read', tid, caller.uid)) { + if (!(await privileges.topics.can('topics:read', tid, caller.uid))) { throw new Error('[[error:no-privileges]]'); } @@ -276,7 +277,7 @@ topicsAPI.getEvents = async (caller, { tid }) => { }; topicsAPI.deleteEvent = async (caller, { tid, eventId }) => { - if (!await privileges.topics.isAdminOrMod(tid, caller.uid)) { + if (!(await privileges.topics.isAdminOrMod(tid, caller.uid))) { throw new Error('[[error:no-privileges]]'); } diff --git a/src/api/users.js b/src/api/users.js index c4f4add772..98d8aa14bd 100644 --- a/src/api/users.js +++ b/src/api/users.js @@ -207,7 +207,7 @@ usersAPI.unfollow = async function (caller, data) { }; usersAPI.ban = async function (caller, data) { - if (!await privileges.users.hasBanPrivilege(caller.uid)) { + if (!(await privileges.users.hasBanPrivilege(caller.uid))) { throw new Error('[[error:no-privileges]]'); } else if (await user.isAdministrator(data.uid)) { throw new Error('[[error:cant-ban-other-admins]]'); @@ -248,7 +248,7 @@ usersAPI.ban = async function (caller, data) { }; usersAPI.unban = async function (caller, data) { - if (!await privileges.users.hasBanPrivilege(caller.uid)) { + if (!(await privileges.users.hasBanPrivilege(caller.uid))) { throw new Error('[[error:no-privileges]]'); } @@ -271,7 +271,7 @@ usersAPI.unban = async function (caller, data) { }; usersAPI.mute = async function (caller, data) { - if (!await privileges.users.hasMutePrivilege(caller.uid)) { + if (!(await privileges.users.hasMutePrivilege(caller.uid))) { throw new Error('[[error:no-privileges]]'); } else if (await user.isAdministrator(data.uid)) { throw new Error('[[error:cant-mute-other-admins]]'); @@ -312,7 +312,7 @@ usersAPI.mute = async function (caller, data) { }; usersAPI.unmute = async function (caller, data) { - if (!await privileges.users.hasMutePrivilege(caller.uid)) { + if (!(await privileges.users.hasMutePrivilege(caller.uid))) { throw new Error('[[error:no-privileges]]'); } @@ -367,7 +367,7 @@ usersAPI.deleteToken = async (caller, { uid, token }) => { usersAPI.revokeSession = async (caller, { uid, uuid }) => { // Only admins or global mods (besides the user themselves) can revoke sessions - if (parseInt(uid, 10) !== caller.uid && !await user.isAdminOrGlobalMod(caller.uid)) { + if (parseInt(uid, 10) !== caller.uid && !(await user.isAdminOrGlobalMod(caller.uid))) { throw new Error('[[error:invalid-uid]]'); } @@ -417,7 +417,10 @@ usersAPI.invite = async (caller, { emails, groupsToJoin, uid }) => { } const max = meta.config.maximumInvites; - const emailsArr = emails.split(',').map(email => email.trim()).filter(Boolean); + const emailsArr = emails + .split(',') + .map(email => email.trim()) + .filter(Boolean); for (const email of emailsArr) { /* eslint-disable no-await-in-loop */ @@ -450,7 +453,7 @@ usersAPI.addEmail = async (caller, { email, skipConfirmation, uid }) => { if (!email.length) { await user.email.remove(uid); } else { - if (!await user.email.available(email)) { + if (!(await user.email.available(email))) { throw new Error('[[error:email-taken]]'); } await user.setUserField(uid, 'email', email); @@ -464,10 +467,7 @@ usersAPI.addEmail = async (caller, { email, skipConfirmation, uid }) => { }; usersAPI.listEmails = async (caller, { uid }) => { - const [isPrivileged, { showemail }] = await Promise.all([ - user.isPrivileged(caller.uid), - user.getSettings(uid), - ]); + const [isPrivileged, { showemail }] = await Promise.all([user.isPrivileged(caller.uid), user.getSettings(uid)]); const isSelf = caller.uid === parseInt(uid, 10); if (isSelf || isPrivileged || showemail) { @@ -499,11 +499,13 @@ usersAPI.confirmEmail = async (caller, { uid, email, sessionId }) => { throw new Error('[[error:no-privileges]]'); } - if (pending) { // has active confirmation request + if (pending) { + // has active confirmation request const code = await db.get(`confirm:byUid:${uid}`); await user.email.confirmByCode(code, sessionId); return true; - } else if (current && current === email) { // i.e. old account w/ unconf. email in user hash + } else if (current && current === email) { + // i.e. old account w/ unconf. email in user hash await user.email.confirmByUid(uid, caller.uid); return true; } @@ -607,13 +609,13 @@ usersAPI.search = async function (caller, data) { ]); let filters = data.filters || []; filters = Array.isArray(filters) ? filters : [filters]; - if (!allowed || - (( - data.searchBy === 'ip' || + if ( + !allowed || + ((data.searchBy === 'ip' || data.searchBy === 'email' || filters.includes('banned') || - filters.includes('flagged') - ) && !isPrivileged) + filters.includes('flagged')) && + !isPrivileged) ) { throw new Error('[[error:no-privileges]]'); } @@ -661,11 +663,15 @@ usersAPI.changePicture = async (caller, data) => { data.bgColor = validBackgrounds[0]; } - await user.updateProfile(caller.uid, { - uid: data.uid, - picture: picture, - 'icon:bgColor': data.bgColor, - }, ['picture', 'icon:bgColor']); + await user.updateProfile( + caller.uid, + { + uid: data.uid, + picture: picture, + 'icon:bgColor': data.bgColor, + }, + ['picture', 'icon:bgColor'] + ); }; const exportMetadata = new Map([ diff --git a/src/api/utils.js b/src/api/utils.js index 67e496a5f5..bd14a6757c 100644 --- a/src/api/utils.js +++ b/src/api/utils.js @@ -80,25 +80,21 @@ utils.tokens.add = async ({ token, uid, description = '', timestamp = Date.now() }; utils.tokens.update = async (token, { uid, description }) => { - await Promise.all([ - db.setObject(`token:${token}`, { uid, description }), - db.sortedSetAdd(`tokens:uid`, uid, token), - ]); + await Promise.all([db.setObject(`token:${token}`, { uid, description }), db.sortedSetAdd(`tokens:uid`, uid, token)]); return await utils.tokens.get(token); }; utils.tokens.roll = async (token) => { - const [createTime, uid, lastSeen] = await db.sortedSetsScore([`tokens:createtime`, `tokens:uid`, `tokens:lastSeen`], token); + const [createTime, uid, lastSeen] = await db.sortedSetsScore( + [`tokens:createtime`, `tokens:uid`, `tokens:lastSeen`], + token + ); const newToken = srcUtils.generateUUID(); const updates = [ db.rename(`token:${token}`, `token:${newToken}`), - db.sortedSetsRemove([ - `tokens:createtime`, - `tokens:uid`, - `tokens:lastSeen`, - ], token), + db.sortedSetsRemove([`tokens:createtime`, `tokens:uid`, `tokens:lastSeen`], token), db.sortedSetAdd(`tokens:createtime`, createTime, newToken), db.sortedSetAdd(`tokens:uid`, uid, newToken), ]; @@ -115,11 +111,7 @@ utils.tokens.roll = async (token) => { utils.tokens.delete = async (token) => { await Promise.all([ db.delete(`token:${token}`), - db.sortedSetsRemove([ - `tokens:createtime`, - `tokens:uid`, - `tokens:lastSeen`, - ], token), + db.sortedSetsRemove([`tokens:createtime`, `tokens:uid`, `tokens:lastSeen`], token), ]); };