-
Notifications
You must be signed in to change notification settings - Fork 271
Added api for updating discord group role in firestore and discord #2406
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Summary by CodeRabbit
WalkthroughA new feature was introduced to allow editing of Discord group roles via a controller function, Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Router
participant Controller as editGroupRoles
participant Model as discordRolesModel
participant Service as discordService
Client->>Router: PATCH /groups/:groupId (with body)
Router->>Controller: editGroupRoles(req, res)
Controller->>Model: isGroupRoleExists(groupId)
alt Group role exists
alt roleName to update
Controller->>Service: updateDiscordGroupRole(roleId, roleName, description)
Service-->>Controller: Success/Failure
end
alt description to update
Controller->>Model: updateGroupRole(groupId, {description})
Model-->>Controller: Success/Failure
end
Controller-->>Client: 200 Success or 500 Partial Failure
else Group role not found
Controller-->>Client: 404 Not Found
end
Poem
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 12
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (4)
controllers/discordactions.js
(2 hunks)routes/discordactions.js
(2 hunks)services/discordService.js
(2 hunks)test/unit/models/discordactions.test.js
(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
services/discordService.js (5)
controllers/discordactions.js (2)
authToken
(574-577)DISCORD_BASE_URL
(22-22)utils/discord-actions.js (6)
authToken
(11-14)authToken
(18-18)authToken
(47-50)generateAuthTokenForCloudflare
(8-16)DISCORD_BASE_URL
(4-4)error
(61-61)controllers/external-accounts.js (1)
logger
(9-9)models/events.js (1)
logger
(4-4)controllers/events.js (1)
logger
(6-6)
🪛 GitHub Check: CodeQL
routes/discordactions.js
[failure] 38-38: Missing rate limiting
This route handler performs authorization, but is not rate-limited.
This route handler performs authorization, but is not rate-limited.
This route handler performs authorization, but is not rate-limited.
🪛 GitHub Actions: Tests
controllers/discordactions.js
[warning] 439-439: ESLint warning: Variable Assigned to Object Injection Sink (security/detect-object-injection)
[warning] 455-455: ESLint warning: Generic Object Injection Sink (security/detect-object-injection)
test/unit/models/discordactions.test.js
[warning] 720-859: ESLint warning: Variable Assigned and Generic Object Injection Sink (security/detect-object-injection)
[error] 191-191: Test failure: AssertionError: expected false to equal true at test/unit/models/discordactions.test.js:191:45 in 'discordactions editGroupRoles should update roleName and description successfully'
🪛 Biome (1.9.4)
test/unit/models/discordactions.test.js
[error] 104-104: Declare variables separately
Unsafe fix: Break out into multiple declarations
(lint/style/useSingleVarDeclarator)
services/discordService.js
Outdated
const response = await ( | ||
await fetch(`${DISCORD_BASE_URL}/roles/${roleId})`, { | ||
method: "PATCH", | ||
body: JSON.stringify({ | ||
roleName, | ||
description, | ||
}), | ||
headers: { | ||
"Content-Type": "application/json", | ||
Authorization: `Bearer ${authToken}`, | ||
}, | ||
}) | ||
).json(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix malformed URL & response-handling logic
${DISCORD_BASE_URL}/roles/${roleId})
has an unmatched right-paren, resulting in a 404 from Cloudflare/Discord.await (await fetch()).json()
will throw on 204 No Content.response.status
is read from the parsed JSON rather than the originalResponse
object, so it is alwaysundefined
.
A safe, minimal patch:
- const response = await (
- await fetch(`${DISCORD_BASE_URL}/roles/${roleId})`, {
- method: "PATCH",
- body: JSON.stringify({
- roleName,
- description,
- }),
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${authToken}`,
- },
- })
- ).json();
-
- if (response.status === 204) {
+ const fetchResponse = await fetch(`${DISCORD_BASE_URL}/roles/${roleId}`, {
+ method: "PATCH",
+ body: JSON.stringify({ roleName, description }),
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${authToken}`,
+ },
+ });
+
+ if (fetchResponse.status === 204) {
return {
success: true,
message: "Role updated successfully",
};
}
- return {
- success: false,
- message: response.message || "Failed to update role in Discord",
- };
+ const parsed = await fetchResponse.json().catch(() => ({}));
+ return {
+ success: false,
+ message: parsed.message || "Failed to update role in Discord",
+ };
This removes the stray )
and robustly handles the 204 body-less response.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const response = await ( | |
await fetch(`${DISCORD_BASE_URL}/roles/${roleId})`, { | |
method: "PATCH", | |
body: JSON.stringify({ | |
roleName, | |
description, | |
}), | |
headers: { | |
"Content-Type": "application/json", | |
Authorization: `Bearer ${authToken}`, | |
}, | |
}) | |
).json(); | |
const fetchResponse = await fetch(`${DISCORD_BASE_URL}/roles/${roleId}`, { | |
method: "PATCH", | |
body: JSON.stringify({ roleName, description }), | |
headers: { | |
"Content-Type": "application/json", | |
Authorization: `Bearer ${authToken}`, | |
}, | |
}); | |
if (fetchResponse.status === 204) { | |
return { | |
success: true, | |
message: "Role updated successfully", | |
}; | |
} | |
const parsed = await fetchResponse.json().catch(() => ({})); | |
return { | |
success: false, | |
message: parsed.message || "Failed to update role in Discord", | |
}; |
if (updateRequest.roleName) { | ||
const discordUpdateResponse = await discordServices.updateDiscordGroupRole( | ||
roleData.roleid, | ||
updateRequest.roleName, | ||
updateRequest.description | ||
); | ||
if (!discordUpdateResponse.success) { | ||
discordUpdateSuccess = false; | ||
logger.error(`Failed to update role name in Discord for groupId: ${groupId}`); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Handle Discord API failures explicitly
discordUpdateSuccess
is set to false
only when the service returns { success:false }
, but the preceding await
can throw (network, 5xx).
Wrap the call in its own try…catch
to avoid an unhandled exception that would skip Firestore rollback logic.
if (roleName) { | ||
updateRequest.roleName = roleName; | ||
} | ||
if (description) { | ||
updateRequest.description = description; | ||
} | ||
|
||
let discordUpdateSuccess = true; | ||
if (updateRequest.roleName) { | ||
const discordUpdateResponse = await discordServices.updateDiscordGroupRole( | ||
roleData.roleid, | ||
updateRequest.roleName, | ||
updateRequest.description | ||
); | ||
if (!discordUpdateResponse.success) { | ||
discordUpdateSuccess = false; | ||
logger.error(`Failed to update role name in Discord for groupId: ${groupId}`); | ||
} | ||
} | ||
|
||
let firestoreUpdateSuccess = true; | ||
if (updateRequest.description) { | ||
try { | ||
await discordRolesModel.updateGroupRole(groupId, { | ||
description: updateRequest.description, | ||
}); | ||
} catch (error) { | ||
firestoreUpdateSuccess = false; | ||
logger.error(`Failed to update description in Firestore for groupId: ${groupId}`); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Firestore update arguments swapped & rolename not persisted
discordRolesModel.updateGroupRole
accepts (dataToUpdate, docId)
(see call at L511-515 in the same file), but here the parameters are reversed and only description
is saved.
This leaves Firestore out-of-sync when the role name changes.
- await discordRolesModel.updateGroupRole(groupId, {
- description: updateRequest.description,
- });
+ await discordRolesModel.updateGroupRole(
+ {
+ ...(updateRequest.roleName && { rolename: updateRequest.roleName }),
+ ...(updateRequest.description && { description: updateRequest.description }),
+ },
+ groupId
+ );
Fixing the order and including rolename
keeps the DB consistent with Discord.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
if (roleName) { | |
updateRequest.roleName = roleName; | |
} | |
if (description) { | |
updateRequest.description = description; | |
} | |
let discordUpdateSuccess = true; | |
if (updateRequest.roleName) { | |
const discordUpdateResponse = await discordServices.updateDiscordGroupRole( | |
roleData.roleid, | |
updateRequest.roleName, | |
updateRequest.description | |
); | |
if (!discordUpdateResponse.success) { | |
discordUpdateSuccess = false; | |
logger.error(`Failed to update role name in Discord for groupId: ${groupId}`); | |
} | |
} | |
let firestoreUpdateSuccess = true; | |
if (updateRequest.description) { | |
try { | |
await discordRolesModel.updateGroupRole(groupId, { | |
description: updateRequest.description, | |
}); | |
} catch (error) { | |
firestoreUpdateSuccess = false; | |
logger.error(`Failed to update description in Firestore for groupId: ${groupId}`); | |
} | |
} | |
let firestoreUpdateSuccess = true; | |
if (updateRequest.description) { | |
try { | |
await discordRolesModel.updateGroupRole( | |
{ | |
...(updateRequest.roleName && { rolename: updateRequest.roleName }), | |
...(updateRequest.description && { description: updateRequest.description }), | |
}, | |
groupId | |
); | |
} catch (error) { | |
firestoreUpdateSuccess = false; | |
logger.error(`Failed to update description in Firestore for groupId: ${groupId}`); | |
} | |
} |
routes/discordactions.js
Outdated
router.patch("/groups/:groupId", authenticate, authorizeRoles([SUPERUSER]), editGroupRoles); | ||
router.patch("/groups/:groupId", editGroupRoles); | ||
router.get("/groups", authenticate, checkIsVerifiedDiscord, validateLazyLoadingParams, getPaginatedAllGroupRoles); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unprotected duplicate PATCH route bypasses authentication/authorization
router.patch("/groups/:groupId", editGroupRoles);
(L39-L40) is registered after the secured route, but Express will still match it if the first route short-circuits (e.g., authenticate
sends 401 without next()
).
Attackers can therefore hit the second route and modify group roles without credentials.
-router.patch("/groups/:groupId", editGroupRoles);
+// Duplicate unsecured route removed – all updates must pass auth & SUPERUSER checks
Delete the unsecured definition or add the same middleware chain.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
router.patch("/groups/:groupId", authenticate, authorizeRoles([SUPERUSER]), editGroupRoles); | |
router.patch("/groups/:groupId", editGroupRoles); | |
router.get("/groups", authenticate, checkIsVerifiedDiscord, validateLazyLoadingParams, getPaginatedAllGroupRoles); | |
router.patch("/groups/:groupId", authenticate, authorizeRoles([SUPERUSER]), editGroupRoles); | |
// Duplicate unsecured route removed – all updates must pass auth & SUPERUSER checks | |
router.get("/groups", authenticate, checkIsVerifiedDiscord, validateLazyLoadingParams, getPaginatedAllGroupRoles); |
🧰 Tools
🪛 GitHub Check: CodeQL
[failure] 38-38: Missing rate limiting
This route handler performs authorization, but is not rate-limited.
This route handler performs authorization, but is not rate-limited.
This route handler performs authorization, but is not rate-limited.
it("should return 400 if neither roleName nor description is provided", async function () { | ||
await editGroupRoles(req, res); | ||
|
||
expect(res.boom.badRequest.calledWith("At least one field (roleName or description) must be provided")).to.equal( | ||
true | ||
); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Add test for combined field validation.
The test cases cover individual validation scenarios, but it would be valuable to test the case where both fields are provided but one is invalid.
Consider adding a test case like:
it("should return 400 if roleName is valid but description exceeds limit", async function () {
req.body = {
roleName: "valid-name",
description: "a".repeat(201)
};
await editGroupRoles(req, res);
expect(res.boom.badRequest.calledWith("Description must not exceed 200 characters")).to.equal(true);
});
it("should return 500 if Discord update fails", async function () { | ||
req.body.roleName = "new-role-name"; | ||
sinon.stub(discordRolesModel, "isGroupRoleExists").resolves({ | ||
roleExists: true, | ||
existingRoles: { | ||
data: () => ({ | ||
roleid: "12345", | ||
}), | ||
}, | ||
}); | ||
sinon.stub(discordServices, "updateDiscordGroupRole").resolves({ | ||
success: false, | ||
}); | ||
|
||
await editGroupRoles(req, res); | ||
|
||
expect(res.boom.badImplementation.calledWith("Partial update failed. Check logs for details.")).to.equal(true); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Verify error handling consistency in test.
The test is checking for a 500 response on Discord update failure, but it would be good to ensure the controller doesn't attempt to update Firestore after a Discord failure.
Add an additional assertion to verify that updateGroupRole
is not called when the Discord update fails:
await editGroupRoles(req, res);
expect(res.boom.badImplementation.calledWith("Partial update failed. Check logs for details.")).to.equal(true);
+ expect(discordRolesModel.updateGroupRole.called).to.equal(false);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
it("should return 500 if Discord update fails", async function () { | |
req.body.roleName = "new-role-name"; | |
sinon.stub(discordRolesModel, "isGroupRoleExists").resolves({ | |
roleExists: true, | |
existingRoles: { | |
data: () => ({ | |
roleid: "12345", | |
}), | |
}, | |
}); | |
sinon.stub(discordServices, "updateDiscordGroupRole").resolves({ | |
success: false, | |
}); | |
await editGroupRoles(req, res); | |
expect(res.boom.badImplementation.calledWith("Partial update failed. Check logs for details.")).to.equal(true); | |
}); | |
it("should return 500 if Discord update fails", async function () { | |
req.body.roleName = "new-role-name"; | |
sinon.stub(discordRolesModel, "isGroupRoleExists").resolves({ | |
roleExists: true, | |
existingRoles: { | |
data: () => ({ | |
roleid: "12345", | |
}), | |
}, | |
}); | |
sinon.stub(discordServices, "updateDiscordGroupRole").resolves({ | |
success: false, | |
}); | |
await editGroupRoles(req, res); | |
expect(res.boom.badImplementation.calledWith("Partial update failed. Check logs for details.")).to.equal(true); | |
expect(discordRolesModel.updateGroupRole.called).to.equal(false); | |
}); |
const { editGroupRoles } = require("../../../controllers/discordactions"); | ||
const discordRolesModel = require("../../../models/discordactions"); | ||
const discordServices = require("../../../services/discordService"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Consider prefixing imported module with original name.
The file imports both discordService
and discordServices
which could lead to confusion.
const { editGroupRoles } = require("../../../controllers/discordactions");
const discordRolesModel = require("../../../models/discordactions");
- const discordServices = require("../../../services/discordService");
+ const discordServices = require("../../../services/discordService"); // Ensure this is consistent with line 16
Consider using the same variable name (either discordService
or discordServices
) for consistency.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const { editGroupRoles } = require("../../../controllers/discordactions"); | |
const discordRolesModel = require("../../../models/discordactions"); | |
const discordServices = require("../../../services/discordService"); | |
// test/unit/models/discordactions.test.js | |
const { editGroupRoles } = require("../../../controllers/discordactions"); | |
const discordRolesModel = require("../../../models/discordactions"); | |
const discordServices = require("../../../services/discordService"); // Ensure this is consistent with line 16 |
sinon.restore(); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Consider using more precise sinon cleanup method.
Using sinon.restore()
restores all stubs, spies, and mocks. For better isolation between tests, use the more specific sinon.resetHistory()
to only reset call history without removing stubs.
- sinon.restore();
+ sinon.resetHistory();
Then use afterEach(sinon.restore)
at the suite level to fully clean up after all tests in the suite have completed.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
sinon.restore(); | |
}); | |
sinon.resetHistory(); | |
}); |
roleExists: true, | ||
existingRoles: { | ||
data: () => ({ | ||
roleid: "12345", | ||
}), | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Improve test stub structure for better readability.
The nested structure for the stub return value is complex and could be simplified for better readability.
sinon.stub(discordRolesModel, "isGroupRoleExists").resolves({
roleExists: true,
- existingRoles: {
- data: () => ({
- roleid: "12345",
- }),
- },
+ existingRoles: {
+ data() {
+ return { roleid: "12345" };
+ }
+ },
});
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
roleExists: true, | |
existingRoles: { | |
data: () => ({ | |
roleid: "12345", | |
}), | |
}, | |
sinon.stub(discordRolesModel, "isGroupRoleExists").resolves({ | |
roleExists: true, | |
existingRoles: { | |
data() { | |
return { roleid: "12345" }; | |
} | |
}, | |
}); |
expect(discordServices.updateDiscordGroupRole.calledWith("12345", "new-role-name")).to.equal(true); | ||
expect( | ||
discordRolesModel.updateGroupRole.calledWith("group1", { | ||
description: "Updated description", | ||
}) | ||
).to.equal(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Improve test assertion clarity by using sinon.assert.calledWith
.
Sinon provides dedicated assertion methods that offer clearer error messages when tests fail.
- expect(discordServices.updateDiscordGroupRole.calledWith("12345", "new-role-name")).to.equal(true);
- expect(
- discordRolesModel.updateGroupRole.calledWith("group1", {
- description: "Updated description",
- })
- ).to.equal(true);
+ sinon.assert.calledWith(discordServices.updateDiscordGroupRole, "12345", "new-role-name");
+ sinon.assert.calledWith(discordRolesModel.updateGroupRole, "group1", {
+ description: "Updated description",
+ });
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
expect(discordServices.updateDiscordGroupRole.calledWith("12345", "new-role-name")).to.equal(true); | |
expect( | |
discordRolesModel.updateGroupRole.calledWith("group1", { | |
description: "Updated description", | |
}) | |
).to.equal(true); | |
sinon.assert.calledWith(discordServices.updateDiscordGroupRole, "12345", "new-role-name"); | |
sinon.assert.calledWith(discordRolesModel.updateGroupRole, "group1", { | |
description: "Updated description", | |
}); |
@@ -34,6 +35,7 @@ | |||
const router = express.Router(); | |||
|
|||
router.post("/groups", authenticate, checkIsVerifiedDiscord, validateGroupRoleBody, createGroupRole); | |||
router.patch("/groups/:groupId", authenticate, authorizeRoles([SUPERUSER]), editGroupRoles); |
Check failure
Code scanning / CodeQL
Missing rate limiting High
authorization
This route handler performs
authorization
This route handler performs
authorization
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
Test coverage is missing — please add relevant tests.
-
A working video demo would be more helpful than just a screenshot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
Test coverage is missing — please add relevant tests.
-
A working video demo would be more helpful than just a screenshot.
|
||
if (roleName && (roleName.length < 3 || roleName.length > 50)) { | ||
return res.boom.badRequest("Role name must be between 3 and 50 characters"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Why are we performing these validations in the controller?
- Consider moving them to the validator layer so all incoming data is validated consistently before reaching the controller.
const { dev } = req.query; | ||
const { roleName, description } = req.body; | ||
|
||
if (!dev === "true") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The feature flag check contains a logical error. The expression !dev === "true"
will always evaluate to false because !dev
produces a boolean value which cannot equal the string "true"
.
The correct condition should be dev !== "true"
to properly check if the feature flag is not enabled.
// Current:
if (!dev === "true") { ... }
// Corrected:
if (dev !== "true") { ... }
if (!dev === "true") { | |
if (dev !== "true") { |
Spotted by Diamond
Is this helpful? React 👍 or 👎 to let us know.
const discordUpdateResponse = await discordServices.updateDiscordGroupRole( | ||
roleData.roleid, | ||
updateRequest.roleName, | ||
updateRequest.description | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dev
parameter from the request query is not being passed to the updateDiscordGroupRole
function, though the function signature includes it as a fourth parameter. This will result in the dev
flag being undefined
when making the Discord API call. Consider passing req.query.dev
as the fourth argument to ensure the feature flag is properly propagated to the Discord service.
const discordUpdateResponse = await discordServices.updateDiscordGroupRole( | |
roleData.roleid, | |
updateRequest.roleName, | |
updateRequest.description | |
); | |
const discordUpdateResponse = await discordServices.updateDiscordGroupRole( | |
roleData.roleid, | |
updateRequest.roleName, | |
updateRequest.description, | |
req.query.dev | |
); |
Spotted by Diamond
Is this helpful? React 👍 or 👎 to let us know.
boom: { | ||
badRequest: sinon.stub(), | ||
notFound: sinon.stub(), | ||
badImplementation: sinon.stub(), | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test setup is missing a stub for res.boom.success
and res.boom.notImplemented
, which are used in the controller. The success
method is called when the update is successful, and notImplemented
is used in the feature flag check. Without these stubs, tests will fail when testing both the happy path and feature flag functionality. Consider adding:
res = {
boom: {
badRequest: sinon.stub(),
notFound: sinon.stub(),
badImplementation: sinon.stub(),
success: sinon.stub(),
notImplemented: sinon.stub()
},
// ...
};
boom: { | |
badRequest: sinon.stub(), | |
notFound: sinon.stub(), | |
badImplementation: sinon.stub(), | |
}, | |
boom: { | |
badRequest: sinon.stub(), | |
notFound: sinon.stub(), | |
badImplementation: sinon.stub(), | |
success: sinon.stub(), | |
notImplemented: sinon.stub(), | |
}, |
Spotted by Diamond
Is this helpful? React 👍 or 👎 to let us know.
Date: 29-04-2025
Developer Name: Akshat bhatnagar
Issue Ticket Number #2403
Description
Added an API to update the role name and description in discord group.
Documentation Updated?
Under Feature Flag
Database Changes
Breaking Changes
Development Tested?
Screenshots
Added screenshot of working proof
Post updating the description of discord group

Test Coverage
Additional Notes