generated from Real-Dev-Squad/website-template
-
Notifications
You must be signed in to change notification settings - Fork 54
Create an api to delete a role from the discord server #282
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
Merged
prakashchoudhary07
merged 12 commits into
Real-Dev-Squad:develop
from
pankajjs:feat/delete-guild-role-api
Nov 12, 2024
Merged
Changes from 10 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
369ff64
feat: add deleteGuildRole api route definition and handler
pankajjs 55fe580
fix: fix deleteGuildRole util and tests
pankajjs 1075e40
fix: return success and error message
pankajjs fc3fd55
fix: clear mocks before each test and refactor tests
pankajjs 4fd48bf
refactor: refactor deleteGuildRole util and tests in separate file
pankajjs 9a2f4d3
refactor: refactor deleteGuildRoleHandler and tests
pankajjs 6989c74
fix: import deleteGuildRoleHandler from correct file
pankajjs 5cc429d
fix: remove ternary condition
pankajjs f2cabae
fix: change api name to /roles/:roleId
pankajjs df52b33
refactor: change variable name for better readability
pankajjs 0d1d4ac
fix: log error messages for debugging
pankajjs d28042b
fix: change error response and validation order
pankajjs File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { IRequest } from "itty-router"; | ||
import JSONResponse from "../utils/JsonResponse"; | ||
import { env } from "../typeDefinitions/default.types"; | ||
import * as response from "../constants/responses"; | ||
import { verifyNodejsBackendAuthToken } from "../utils/verifyAuthToken"; | ||
import { deleteGuildRole } from "../utils/deleteGuildRole"; | ||
|
||
export async function deleteGuildRoleHandler(request: IRequest, env: env) { | ||
const authHeader = request.headers.get("Authorization"); | ||
const reason = request.headers.get("X-Audit-Log-Reason"); | ||
const roleId = decodeURI(request.params?.roleId ?? ""); | ||
const { dev } = request.query; | ||
const devFlag = dev === "true"; | ||
|
||
if (!devFlag) { | ||
return new JSONResponse(response.NOT_FOUND, { status: 404 }); | ||
} | ||
|
||
if (!authHeader) { | ||
joyguptaa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return new JSONResponse(response.BAD_SIGNATURE, { status: 401 }); | ||
} | ||
if (!roleId) { | ||
return new JSONResponse(response.BAD_REQUEST, { status: 400 }); | ||
} | ||
|
||
try { | ||
await verifyNodejsBackendAuthToken(authHeader, env); | ||
const result = await deleteGuildRole(env, roleId, reason); | ||
|
||
if (result === response.ROLE_REMOVED) { | ||
return new Response(null, { status: 204 }); | ||
} else { | ||
return new JSONResponse(response.INTERNAL_SERVER_ERROR, { | ||
status: 500, | ||
}); | ||
} | ||
} catch (err) { | ||
return new JSONResponse(response.INTERNAL_SERVER_ERROR, { | ||
status: 500, | ||
}); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { INTERNAL_SERVER_ERROR, ROLE_REMOVED } from "../constants/responses"; | ||
import { DISCORD_BASE_URL } from "../constants/urls"; | ||
import { env } from "../typeDefinitions/default.types"; | ||
import createDiscordHeaders from "./createDiscordHeaders"; | ||
|
||
export async function deleteGuildRole( | ||
env: env, | ||
roleId: string, | ||
reason?: string | ||
) { | ||
const deleteGuildRoleUrl = `${DISCORD_BASE_URL}/guilds/${env.DISCORD_GUILD_ID}/roles/${roleId}`; | ||
const headers: HeadersInit = createDiscordHeaders({ | ||
token: env.DISCORD_TOKEN, | ||
reason: reason, | ||
pankajjs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}); | ||
try { | ||
const response = await fetch(deleteGuildRoleUrl, { | ||
method: "DELETE", | ||
headers, | ||
}); | ||
if (response.ok) { | ||
return ROLE_REMOVED; | ||
} else { | ||
return INTERNAL_SERVER_ERROR; | ||
} | ||
} catch (err) { | ||
return INTERNAL_SERVER_ERROR; | ||
pankajjs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
import { generateDummyRequestObject, guildEnv } from "../../fixtures/fixture"; | ||
import * as responseConstants from "../../../src/constants/responses"; | ||
import * as verifyTokenUtils from "../../../src/utils/verifyAuthToken"; | ||
import { deleteGuildRoleHandler } from "../../../src/controllers/deleteGuildRoleHandler"; | ||
import * as deleteGuildRoleUtils from "../../../src/utils/deleteGuildRole"; | ||
|
||
describe("deleteGuildRoleHandler", () => { | ||
afterEach(() => { | ||
jest.restoreAllMocks(); | ||
}); | ||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
const roleId = "1A32BEX04"; | ||
it("should return NOT_FOUND when dev is false", async () => { | ||
const mockRequest = generateDummyRequestObject({ | ||
url: "/roles", | ||
params: { | ||
roleId: roleId, | ||
}, | ||
query: { | ||
dev: "false", | ||
}, | ||
method: "DELETE", | ||
}); | ||
const response = await deleteGuildRoleHandler(mockRequest, guildEnv); | ||
const jsonResponse = await response.json(); | ||
expect(jsonResponse).toEqual(responseConstants.NOT_FOUND); | ||
}); | ||
it("should return BAD_REQUEST when roleId is not valid", async () => { | ||
const mockRequest = generateDummyRequestObject({ | ||
url: "/roles", | ||
params: { | ||
roleId: "", | ||
}, | ||
query: { | ||
dev: "true", | ||
}, | ||
method: "DELETE", | ||
headers: { Authorization: "Bearer testtoken" }, | ||
}); | ||
const response = await deleteGuildRoleHandler(mockRequest, guildEnv); | ||
const jsonResponse = await response.json(); | ||
expect(jsonResponse).toEqual(responseConstants.BAD_REQUEST); | ||
}); | ||
it("should return BAD_SIGNATURE when authorization header is not provided", async () => { | ||
const mockRequest = generateDummyRequestObject({ | ||
url: "/roles", | ||
params: { | ||
roleId: roleId, | ||
}, | ||
query: { | ||
dev: "true", | ||
}, | ||
method: "DELETE", | ||
}); | ||
const response = await deleteGuildRoleHandler(mockRequest, guildEnv); | ||
const jsonResponse = await response.json(); | ||
expect(jsonResponse).toEqual(responseConstants.BAD_SIGNATURE); | ||
}); | ||
it("should return INTERNAL_SERVER_ERROR when response is not ok", async () => { | ||
const expectedResponse = responseConstants.INTERNAL_SERVER_ERROR; | ||
const mockRequest = generateDummyRequestObject({ | ||
url: "/roles", | ||
params: { | ||
roleId: roleId, | ||
}, | ||
query: { | ||
dev: "true", | ||
}, | ||
method: "DELETE", | ||
headers: { Authorization: "Bearer testtoken" }, | ||
}); | ||
jest | ||
.spyOn(deleteGuildRoleUtils, "deleteGuildRole") | ||
.mockResolvedValue(expectedResponse); | ||
const response = await deleteGuildRoleHandler(mockRequest, guildEnv); | ||
const jsonResponse = await response.json(); | ||
expect(jsonResponse).toEqual(expectedResponse); | ||
}); | ||
it("should return INTERNAL_SERVER_ERROR when token is not verified", async () => { | ||
const expectedResponse = responseConstants.INTERNAL_SERVER_ERROR; | ||
const mockRequest = generateDummyRequestObject({ | ||
url: "/roles", | ||
method: "DELETE", | ||
params: { | ||
roleId: roleId, | ||
}, | ||
query: { | ||
dev: "true", | ||
}, | ||
headers: { Authorization: "Bearer testtoken" }, | ||
}); | ||
jest | ||
.spyOn(verifyTokenUtils, "verifyNodejsBackendAuthToken") | ||
.mockRejectedValue(expectedResponse); | ||
const response = await deleteGuildRoleHandler(mockRequest, guildEnv); | ||
const jsonResponse = await response.json(); | ||
expect(jsonResponse).toEqual(expectedResponse); | ||
}); | ||
it("should return ok response", async () => { | ||
const expectedResponse = new Response(null, { | ||
status: 204, | ||
}); | ||
const mockRequest = generateDummyRequestObject({ | ||
url: "/roles", | ||
method: "DELETE", | ||
params: { | ||
roleId: roleId, | ||
}, | ||
query: { | ||
dev: "true", | ||
}, | ||
headers: { Authorization: "Bearer testtoken" }, | ||
}); | ||
const verifyTokenSpy = jest | ||
.spyOn(verifyTokenUtils, "verifyNodejsBackendAuthToken") | ||
.mockResolvedValueOnce(); | ||
const deleteGuildRoleSpy = jest | ||
.spyOn(deleteGuildRoleUtils, "deleteGuildRole") | ||
.mockResolvedValueOnce(responseConstants.ROLE_REMOVED); | ||
const response = await deleteGuildRoleHandler(mockRequest, guildEnv); | ||
expect(verifyTokenSpy).toHaveBeenCalledTimes(1); | ||
expect(deleteGuildRoleSpy).toHaveBeenCalledTimes(1); | ||
expect(response).toEqual(expectedResponse); | ||
expect(response.status).toEqual(expectedResponse.status); | ||
}); | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { DISCORD_BASE_URL } from "../../../src/constants/urls"; | ||
import { deleteGuildRole } from "../../../src/utils/deleteGuildRole"; | ||
import JSONResponse from "../../../src/utils/JsonResponse"; | ||
import { guildEnv } from "../../fixtures/fixture"; | ||
import * as response from "../../../src/constants/responses"; | ||
|
||
describe("deleteGuildRole", () => { | ||
const roleId = "1A32BEX04"; | ||
const deleteGuildRoleUrl = `${DISCORD_BASE_URL}/guilds/${guildEnv.DISCORD_GUILD_ID}/roles/${roleId}`; | ||
const mockRequestInit = { | ||
method: "DELETE", | ||
headers: { | ||
"Content-Type": "application/json", | ||
Authorization: `Bot ${guildEnv.DISCORD_TOKEN}`, | ||
"X-Audit-Log-Reason": "This is reason for this action", | ||
}, | ||
}; | ||
|
||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
afterEach(() => { | ||
jest.restoreAllMocks(); | ||
}); | ||
|
||
it("should pass the reason to discord as a X-Audit-Log-Reason header if provided", async () => { | ||
jest | ||
.spyOn(global, "fetch") | ||
.mockImplementation((inp) => Promise.resolve(new JSONResponse(inp))); | ||
|
||
await deleteGuildRole(guildEnv, roleId, "This is reason for this action"); | ||
|
||
expect(global.fetch).toHaveBeenCalledWith( | ||
deleteGuildRoleUrl, | ||
mockRequestInit | ||
); | ||
}); | ||
|
||
it("should return ROLE_REMOVED when response is ok", async () => { | ||
const expectedResponse = new Response(null, { | ||
status: 204, | ||
}); | ||
jest.spyOn(global, "fetch").mockResolvedValue(expectedResponse); | ||
const result = await deleteGuildRole(guildEnv, roleId); | ||
expect(result).toEqual(response.ROLE_REMOVED); | ||
expect(global.fetch).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it("should return INTERNAL_SERVER_ERROR when response is not ok", async () => { | ||
const expectedErrorResponse = new Response(response.INTERNAL_SERVER_ERROR); | ||
jest.spyOn(global, "fetch").mockRejectedValue(expectedErrorResponse); | ||
const result = await deleteGuildRole(guildEnv, roleId); | ||
expect(result).toEqual(response.INTERNAL_SERVER_ERROR); | ||
expect(global.fetch).toHaveBeenCalledTimes(1); | ||
}); | ||
}); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.