Skip to content

Commit

Permalink
Merge pull request #28 from CMU-313/Static_analysis_prettier_fixed
Browse files Browse the repository at this point in the history
Static Analysis Tool "Prettier" Integration
  • Loading branch information
gpxxlt authored Oct 30, 2024
2 parents 716eef0 + ebd7a34 commit d98b88e
Show file tree
Hide file tree
Showing 12 changed files with 108 additions and 142 deletions.
3 changes: 2 additions & 1 deletion UserGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
7. Added hover element for green endorsement checkmark to indicate that instructor has endorsed a post
8. Remove limitation on the number of messages allowed to be send in a minute, which we removed the error message that shows up when someone sent multiple messages in the minute


### 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.
Expand All @@ -24,7 +25,7 @@
- Start Nodebb and manual testing by sending multiple message in a minute to see if the error message still pops up
- Tested back end testing by letting users to send multiple messages in a minute (message flooding) and the user will be able to send out the messages
- As the feature is visual, these checks are enough to verify its accuracy and that it is working. Originally, there would have been an error message that would indicate if the feature implemented was working/ not working.


### Back-end Features
1. Added API calls for `endorse` and `unendorse`
Expand Down
1 change: 1 addition & 0 deletions public/src/client/topic/threadTools.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 2 additions & 8 deletions src/api/categories.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)),
Expand Down Expand Up @@ -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]]');
Expand Down
13 changes: 5 additions & 8 deletions src/api/chats.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ chatsAPI.list = async (caller, { uid = caller.uid, start, stop, page, perPage }
throw new Error('[[error:invalid-data]]');
}
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;
}
Expand Down Expand Up @@ -134,10 +136,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]]');
}
Expand Down Expand Up @@ -228,9 +227,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}`),
]);
Expand Down
10 changes: 2 additions & 8 deletions src/api/flags.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
};

Expand All @@ -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 };
};
17 changes: 4 additions & 13 deletions src/api/groups.js
Original file line number Diff line number Diff line change
Expand Up @@ -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]]');
}

Expand All @@ -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]]');
}

Expand Down Expand Up @@ -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]]');
Expand Down
23 changes: 11 additions & 12 deletions src/api/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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]]');
Expand Down
42 changes: 13 additions & 29 deletions src/api/posts.js
Original file line number Diff line number Diff line change
Expand Up @@ -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']}]]`);
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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]]');
}

Expand Down Expand Up @@ -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];
}
Expand Down
40 changes: 23 additions & 17 deletions src/api/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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);
Expand All @@ -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`);
Expand Down Expand Up @@ -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);
}
});

Expand Down
Loading

0 comments on commit d98b88e

Please sign in to comment.