From f4c056c246ab04295ab97901bae75ec9d39b85f4 Mon Sep 17 00:00:00 2001 From: Lakshay Manchanda <45519620+lakshayman@users.noreply.github.com> Date: Sun, 3 Mar 2024 04:50:54 +0530 Subject: [PATCH] Dev to main (#204) * Added a route to send Profile Blocked Messages (#198) * Added a route to sent Profile Blocked Messages * Modification to the message bot is sending * Authentication Added * Fixed Lint issues * Code Cleaning * Update variables.ts * Code Cleaning * Added a re-usable function for Auth (#199) * Added Auth for Identity Service (#200) * Added a route to sent Profile Blocked Messages * Modification to the message bot is sending * Authentication Added * Fixed Lint issues * Code Cleaning * Update variables.ts * Code Cleaning * Added a re-usable function for auth token * Added Auth for Identity Service * Set IDENTITY_SERVICE_PUBLIC_KEY environment while deploying (#201) --- .../register-commands-production.yaml | 2 + .../workflows/register-commands-staging.yaml | 2 + config/config.ts | 9 ++ src/constants/variables.ts | 5 + src/controllers/changeNickname.ts | 4 +- src/controllers/generateDiscordInvite.ts | 4 +- .../getGuildMemberDetailsHandler.ts | 4 +- src/controllers/getMembersInServer.ts | 4 +- src/controllers/guildRoleHandler.ts | 17 +-- src/controllers/profileHandler.ts | 22 ++++ src/index.ts | 5 +- src/typeDefinitions/default.types.d.ts | 1 + src/utils/sendProfileServiceBlockedMessage.ts | 40 ++++++ src/utils/verifyAuthToken.ts | 62 +++++++--- .../handlers/generateDiscordInvite.test.ts | 2 +- tests/unit/handlers/guildRoleHandler.test.ts | 2 +- .../sendProfileServiceBlockedMessage.test.ts | 115 ++++++++++++++++++ tests/unit/utils/verifyToken.test.ts | 26 ++-- 18 files changed, 276 insertions(+), 50 deletions(-) create mode 100644 src/controllers/profileHandler.ts create mode 100644 src/utils/sendProfileServiceBlockedMessage.ts create mode 100644 tests/unit/utils/sendProfileServiceBlockedMessage.test.ts diff --git a/.github/workflows/register-commands-production.yaml b/.github/workflows/register-commands-production.yaml index f0d161aa..161dffdb 100644 --- a/.github/workflows/register-commands-production.yaml +++ b/.github/workflows/register-commands-production.yaml @@ -36,6 +36,7 @@ jobs: BOT_PRIVATE_KEY RDS_SERVERLESS_PUBLIC_KEY CRON_JOBS_PUBLIC_KEY + IDENTITY_SERVICE_PUBLIC_KEY env: CURRENT_ENVIRONMENT: production CLOUDFLARE_API_TOKEN: ${{secrets.CLOUDFLARE_API_TOKEN}} @@ -45,3 +46,4 @@ jobs: DISCORD_GUILD_ID: ${{secrets.DISCORD_GUILD_ID}} RDS_SERVERLESS_PUBLIC_KEY: ${{secrets.RDS_SERVERLESS_PUBLIC_KEY}} CRON_JOBS_PUBLIC_KEY: ${{secrets.CRON_JOBS_PUBLIC_KEY}} + IDENTITY_SERVICE_PUBLIC_KEY: ${{secrets.IDENTITY_SERVICE_PUBLIC_KEY}} diff --git a/.github/workflows/register-commands-staging.yaml b/.github/workflows/register-commands-staging.yaml index d5d26209..41384440 100644 --- a/.github/workflows/register-commands-staging.yaml +++ b/.github/workflows/register-commands-staging.yaml @@ -35,6 +35,7 @@ jobs: CURRENT_ENVIRONMENT BOT_PRIVATE_KEY CRON_JOBS_PUBLIC_KEY + IDENTITY_SERVICE_PUBLIC_KEY env: CURRENT_ENVIRONMENT: staging CLOUDFLARE_API_TOKEN: ${{secrets.CLOUDFLARE_API_TOKEN}} @@ -43,3 +44,4 @@ jobs: BOT_PRIVATE_KEY: ${{secrets.BOT_PRIVATE_KEY}} DISCORD_GUILD_ID: ${{secrets.DISCORD_GUILD_ID}} CRON_JOBS_PUBLIC_KEY: ${{secrets.CRON_JOBS_PUBLIC_KEY}} + IDENTITY_SERVICE_PUBLIC_KEY: ${{secrets.IDENTITY_SERVICE_PUBLIC_KEY}} diff --git a/config/config.ts b/config/config.ts index 7c1f2a7a..0b6347c9 100644 --- a/config/config.ts +++ b/config/config.ts @@ -10,6 +10,11 @@ import { DEVELOPMENT_RDS_TRACKING_CHANNEL_URL, STAGING_RDS_TRACKING_CHANNEL_URL, } from "../src/constants/urls"; +import { + DISCORD_PROFILE_SERVICE_HELP_GROUP, + DISCORD_PROFILE_SERVICE_STAGING_HELP_GROUP, + DISCORD_PROFILE_SERVICE_DEVELOPMENT_HELP_GROUP, +} from "../src/constants/variables"; const config = (env: env) => { const environment: environment = { @@ -17,16 +22,20 @@ const config = (env: env) => { RDS_BASE_API_URL: RDS_BASE_API_URL, VERIFICATION_SITE_URL: VERIFICATION_SITE_URL, TRACKING_CHANNEL_URL: RDS_TRACKING_CHANNEL_URL, + PROFILE_SERVICE_HELP_GROUP_ID: DISCORD_PROFILE_SERVICE_HELP_GROUP, }, staging: { RDS_BASE_API_URL: RDS_BASE_STAGING_API_URL, VERIFICATION_SITE_URL: STAGING_VERIFICATION_SITE_URL, TRACKING_CHANNEL_URL: STAGING_RDS_TRACKING_CHANNEL_URL, + PROFILE_SERVICE_HELP_GROUP_ID: DISCORD_PROFILE_SERVICE_STAGING_HELP_GROUP, }, default: { RDS_BASE_API_URL: RDS_BASE_DEVELOPMENT_API_URL, VERIFICATION_SITE_URL: DEVELOPMENT_VERIFICATION_SITE_URL, TRACKING_CHANNEL_URL: DEVELOPMENT_RDS_TRACKING_CHANNEL_URL, + PROFILE_SERVICE_HELP_GROUP_ID: + DISCORD_PROFILE_SERVICE_DEVELOPMENT_HELP_GROUP, }, }; diff --git a/src/constants/variables.ts b/src/constants/variables.ts index 209cc38c..dfc456f8 100644 --- a/src/constants/variables.ts +++ b/src/constants/variables.ts @@ -1,2 +1,7 @@ export const SUPER_USER_ONE = "154585730465660929"; export const SUPER_USER_TWO = "1040700289348542566"; + +export const DISCORD_PROFILE_SERVICE_HELP_GROUP = "1209244798557360138"; +export const DISCORD_PROFILE_SERVICE_STAGING_HELP_GROUP = "1209248671170953236"; +export const DISCORD_PROFILE_SERVICE_DEVELOPMENT_HELP_GROUP = + "1209237447083303014"; //Change this for your local environment diff --git a/src/controllers/changeNickname.ts b/src/controllers/changeNickname.ts index 61358708..0128796d 100644 --- a/src/controllers/changeNickname.ts +++ b/src/controllers/changeNickname.ts @@ -2,7 +2,7 @@ import { IRequest } from "itty-router"; import { env } from "../typeDefinitions/default.types"; import JSONResponse from "../utils/JsonResponse"; import * as response from "../constants/responses"; -import { verifyAuthToken } from "../utils/verifyAuthToken"; +import { verifyNodejsBackendAuthToken } from "../utils/verifyAuthToken"; import { updateNickName } from "../utils/updateNickname"; export async function changeNickname(request: IRequest, env: env) { @@ -14,7 +14,7 @@ export async function changeNickname(request: IRequest, env: env) { } try { - await verifyAuthToken(authHeader, env); + await verifyNodejsBackendAuthToken(authHeader, env); const { discordId, userName } = await request.json(); const res = await updateNickName(discordId, userName, env, reason); return new JSONResponse(res); diff --git a/src/controllers/generateDiscordInvite.ts b/src/controllers/generateDiscordInvite.ts index a7533b91..98d1dff8 100644 --- a/src/controllers/generateDiscordInvite.ts +++ b/src/controllers/generateDiscordInvite.ts @@ -2,7 +2,7 @@ import { IRequest } from "itty-router"; import * as response from "../constants/responses"; import { env } from "../typeDefinitions/default.types"; import JSONResponse from "../utils/JsonResponse"; -import { verifyAuthToken } from "../utils/verifyAuthToken"; +import { verifyNodejsBackendAuthToken } from "../utils/verifyAuthToken"; import { generateDiscordLink } from "../utils/generateDiscordInvite"; import { inviteLinkBody } from "../typeDefinitions/discordLink.types"; @@ -12,7 +12,7 @@ export async function generateInviteLink(request: IRequest, env: env) { return new JSONResponse(response.BAD_SIGNATURE); } try { - await verifyAuthToken(authHeader, env); + await verifyNodejsBackendAuthToken(authHeader, env); const reason = request.headers.get("X-Audit-Log-Reason"); const body: inviteLinkBody = await request.json(); diff --git a/src/controllers/getGuildMemberDetailsHandler.ts b/src/controllers/getGuildMemberDetailsHandler.ts index c14e86ce..7c7adf92 100644 --- a/src/controllers/getGuildMemberDetailsHandler.ts +++ b/src/controllers/getGuildMemberDetailsHandler.ts @@ -2,7 +2,7 @@ import * as response from "../constants/responses"; import { env } from "../typeDefinitions/default.types"; import JSONResponse from "../utils/JsonResponse"; import { IRequest } from "itty-router"; -import { verifyAuthToken } from "../utils/verifyAuthToken"; +import { verifyNodejsBackendAuthToken } from "../utils/verifyAuthToken"; import { getGuildMemberDetails } from "../utils/getGuildMemberDetails"; export async function getGuildMemberDetailsHandler( @@ -14,7 +14,7 @@ export async function getGuildMemberDetailsHandler( return new JSONResponse(response.BAD_SIGNATURE); } try { - await verifyAuthToken(authHeader, env); + await verifyNodejsBackendAuthToken(authHeader, env); const { id: discordId } = request.params; diff --git a/src/controllers/getMembersInServer.ts b/src/controllers/getMembersInServer.ts index d82dc673..2e8eb055 100644 --- a/src/controllers/getMembersInServer.ts +++ b/src/controllers/getMembersInServer.ts @@ -5,7 +5,7 @@ import { env } from "../typeDefinitions/default.types"; import JSONResponse from "../utils/JsonResponse"; import { User } from "../typeDefinitions/user.types"; import { getMembersInServer } from "../utils/getMembersInServer"; -import { verifyAuthToken } from "../utils/verifyAuthToken"; +import { verifyNodejsBackendAuthToken } from "../utils/verifyAuthToken"; export const getMembersInServerHandler = async ( request: IRequest, @@ -17,7 +17,7 @@ export const getMembersInServerHandler = async ( return new JSONResponse(response.BAD_SIGNATURE); } try { - await verifyAuthToken(authHeader, env); + await verifyNodejsBackendAuthToken(authHeader, env); const users = (await getMembersInServer(env)) as User[]; diff --git a/src/controllers/guildRoleHandler.ts b/src/controllers/guildRoleHandler.ts index 43724150..a165fb06 100644 --- a/src/controllers/guildRoleHandler.ts +++ b/src/controllers/guildRoleHandler.ts @@ -13,7 +13,10 @@ import { createNewRole, memberGroupRole, } from "../typeDefinitions/discordMessage.types"; -import { verifyAuthToken, verifyCronJobsToken } from "../utils/verifyAuthToken"; +import { + verifyNodejsBackendAuthToken, + verifyCronJobsToken, +} from "../utils/verifyAuthToken"; import { batchDiscordRequests } from "../utils/batchDiscordRequests"; import { DISCORD_BASE_URL } from "../constants/urls"; import { GROUP_ROLE_ADD } from "../constants/requestsActions"; @@ -25,7 +28,7 @@ export async function createGuildRoleHandler(request: IRequest, env: env) { return new JSONResponse(response.BAD_SIGNATURE); } try { - await verifyAuthToken(authHeader, env); + await verifyNodejsBackendAuthToken(authHeader, env); const body: createNewRole = await request.json(); const reason = request.headers.get("X-Audit-Log-Reason"); const res = await createGuildRole(body, env, reason); @@ -40,7 +43,7 @@ export async function addGroupRoleHandler(request: IRequest, env: env) { return new JSONResponse(response.BAD_SIGNATURE); } try { - await verifyAuthToken(authHeader, env); + await verifyNodejsBackendAuthToken(authHeader, env); const body: memberGroupRole = await request.json(); const reason = request.headers.get("X-Audit-Log-Reason"); @@ -64,7 +67,7 @@ export async function getGuildRolesPostHandler(request: IRequest, env: env) { if (dev === "true") { await verifyCronJobsToken(authHeader, env); } else { - await verifyAuthToken(authHeader, env); + await verifyNodejsBackendAuthToken(authHeader, env); } switch (action) { @@ -161,7 +164,7 @@ export async function removeGuildRoleHandler(request: IRequest, env: env) { return new JSONResponse(response.BAD_SIGNATURE, { status: 401 }); } try { - await verifyAuthToken(authHeader, env); + await verifyNodejsBackendAuthToken(authHeader, env); const body: memberGroupRole = await request.json(); const res = await removeGuildRole(body, env, reason); return new JSONResponse(res, { @@ -186,7 +189,7 @@ export async function getGuildRolesHandler(request: IRequest, env: env) { return new JSONResponse(response.BAD_SIGNATURE, { status: 401 }); } try { - await verifyAuthToken(authHeader, env); + await verifyNodejsBackendAuthToken(authHeader, env); const roles = await getGuildRoles(env); return new JSONResponse({ roles }); } catch (err: any) { @@ -223,7 +226,7 @@ export async function getGuildRoleByRoleNameHandler( return new JSONResponse(response.BAD_REQUEST, { status: 404 }); } try { - await verifyAuthToken(authHeader, env); + await verifyNodejsBackendAuthToken(authHeader, env); const role = await getGuildRoleByName(roleName, env); if (!role) { return new JSONResponse(response.NOT_FOUND, { diff --git a/src/controllers/profileHandler.ts b/src/controllers/profileHandler.ts new file mode 100644 index 00000000..8891d052 --- /dev/null +++ b/src/controllers/profileHandler.ts @@ -0,0 +1,22 @@ +import { env } from "../typeDefinitions/default.types"; +import { sendProfileServiceBlockedMessage } from "../utils/sendProfileServiceBlockedMessage"; +import JSONResponse from "../utils/JsonResponse"; +import * as response from "../constants/responses"; +import { verifyIdentityServiceAuthToken } from "../utils/verifyAuthToken"; + +export const sendProfileBlockedMessage = async (request: any, env: env) => { + const authHeader = request.headers.get("Authorization"); + if (!authHeader) { + return new JSONResponse(response.BAD_SIGNATURE); + } + try { + await verifyIdentityServiceAuthToken(authHeader, env); + const messageRequest: { userId: string; reason: string } = + await request.json(); + const { userId, reason } = messageRequest; + await sendProfileServiceBlockedMessage(userId, reason, env); + return new JSONResponse("Message sent in tracking channel on discord"); + } catch (e) { + return new JSONResponse(response.BAD_SIGNATURE); + } +}; diff --git a/src/index.ts b/src/index.ts index 3f5b4ca0..c3a5881a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -19,6 +19,7 @@ import { changeNickname } from "./controllers/changeNickname"; import { getGuildMemberDetailsHandler } from "./controllers/getGuildMemberDetailsHandler"; import { send } from "./handlers/scheduledEventHandler"; import { generateInviteLink } from "./controllers/generateDiscordInvite"; +import { sendProfileBlockedMessage } from "./controllers/profileHandler"; const router = Router(); @@ -54,6 +55,8 @@ router.put("/roles/add", addGroupRoleHandler); router.delete("/roles", removeGuildRoleHandler); +router.post("/profile/blocked", sendProfileBlockedMessage); + router.post("/", async (request, env) => { const message: discordMessageRequest = await request.json(); @@ -76,7 +79,7 @@ router.all("*", async () => { export default { async fetch(request: Request, env: env): Promise { - const apiUrls = ["/invite", "/roles"]; + const apiUrls = ["/invite", "/roles", "/profile/blocked"]; const url = new URL(request.url); if (request.method === "POST" && !apiUrls.includes(url.pathname)) { const isVerifiedRequest = await verifyBot(request, env); diff --git a/src/typeDefinitions/default.types.d.ts b/src/typeDefinitions/default.types.d.ts index 419652d3..856a459f 100644 --- a/src/typeDefinitions/default.types.d.ts +++ b/src/typeDefinitions/default.types.d.ts @@ -10,6 +10,7 @@ export interface variables { RDS_BASE_API_URL: string; VERIFICATION_SITE_URL: string; TRACKING_CHANNEL_URL: string; + PROFILE_SERVICE_HELP_GROUP_ID: string; } export interface discordCommand { diff --git a/src/utils/sendProfileServiceBlockedMessage.ts b/src/utils/sendProfileServiceBlockedMessage.ts new file mode 100644 index 00000000..6ac6a64f --- /dev/null +++ b/src/utils/sendProfileServiceBlockedMessage.ts @@ -0,0 +1,40 @@ +import { env } from "../typeDefinitions/default.types"; +import config from "../../config/config"; + +export const generateStringToBeSent = ( + userId: string, + reason: string, + env: env +) => { + const helpGroupRoleId = config(env).PROFILE_SERVICE_HELP_GROUP_ID; + return `Hello${userId ? ` <@${userId}>` : ""},\n${ + userId ? "Your" : "Someone's" + } Profile Service is **BLOCKED** because of the below-mentioned reason.${ + userId + ? ` Please visit the [MY SITE](https://my.realdevsquad.com/identity) to fix this.\nIf you have any issue related to profile service, you can tag <@&${helpGroupRoleId}> and ask for help.` + : "" + }\n\n**Reason:** \`${reason ? reason : "No reason provided"}\``; +}; + +export async function sendProfileServiceBlockedMessage( + userId: string, + reason: string, + env: env +): Promise { + const stringToBeSent = generateStringToBeSent(userId, reason, env); + + const bodyObj = { + content: stringToBeSent, + }; + + const url = config(env).TRACKING_CHANNEL_URL; + + await fetch(url, { + method: "POST", + body: JSON.stringify(bodyObj), + headers: { + "Content-Type": "application/json", + Authorization: `Bot ${env.DISCORD_TOKEN}`, + }, + }); +} diff --git a/src/utils/verifyAuthToken.ts b/src/utils/verifyAuthToken.ts index 859b587e..2d599bc7 100644 --- a/src/utils/verifyAuthToken.ts +++ b/src/utils/verifyAuthToken.ts @@ -5,19 +5,16 @@ import { import { env } from "../typeDefinitions/default.types"; import jwt from "@tsndr/cloudflare-worker-jwt"; -/** - * - * @param authHeader { string } : the auth header of request - * @param env { env }: the ctx (context) which contains the secrets put in as wrangler secrets. - */ - -export async function verifyAuthToken(authHeader: string, env: env) { +async function verifyAuthToken(authHeader: string, public_key: string) { + if (!authHeader) { + throw new Error(INVALID_TOKEN_FORMAT); + } const parts = authHeader.split(" "); if (parts.length !== 2 || parts[0] !== "Bearer") { throw new Error(INVALID_TOKEN_FORMAT); } const authToken = parts[1]; - const isValid = await jwt.verify(authToken, env.RDS_SERVERLESS_PUBLIC_KEY, { + const isValid = await jwt.verify(authToken, public_key, { algorithm: "RS256", }); if (!isValid) { @@ -30,19 +27,44 @@ export async function verifyAuthToken(authHeader: string, env: env) { * @param authHeader { string } : the auth header of request * @param env { env }: the ctx (context) which contains the secrets put in as wrangler secrets. */ -export async function verifyCronJobsToken(authHeader: string, env: env) { - if (!authHeader) { - throw new Error(INVALID_TOKEN_FORMAT); + +export async function verifyNodejsBackendAuthToken( + authHeader: string, + env: env +) { + try { + await verifyAuthToken(authHeader, env.RDS_SERVERLESS_PUBLIC_KEY); + } catch (err: any) { + throw new Error(err.message); } - const authHeaderParts = authHeader.split(" "); - if (authHeaderParts.length !== 2 || authHeaderParts[0] !== "Bearer") { - throw new Error(INVALID_TOKEN_FORMAT); +} + +/** + * + * @param authHeader { string } : the auth header of request + * @param env { env }: the ctx (context) which contains the secrets put in as wrangler secrets. + */ + +export async function verifyIdentityServiceAuthToken( + authHeader: string, + env: env +) { + try { + await verifyAuthToken(authHeader, env.IDENTITY_SERVICE_PUBLIC_KEY); + } catch (err: any) { + throw new Error(err.message); } - const authToken = authHeaderParts[1]; - const isValid = await jwt.verify(authToken, env.CRON_JOBS_PUBLIC_KEY, { - algorithm: "RS256", - }); - if (!isValid) { - throw new Error(AUTHENTICATION_ERROR); +} + +/** + * + * @param authHeader { string } : the auth header of request + * @param env { env }: the ctx (context) which contains the secrets put in as wrangler secrets. + */ +export async function verifyCronJobsToken(authHeader: string, env: env) { + try { + await verifyAuthToken(authHeader, env.CRON_JOBS_PUBLIC_KEY); + } catch (err: any) { + throw new Error(err.message); } } diff --git a/tests/unit/handlers/generateDiscordInvite.test.ts b/tests/unit/handlers/generateDiscordInvite.test.ts index c125b269..68d14b7d 100644 --- a/tests/unit/handlers/generateDiscordInvite.test.ts +++ b/tests/unit/handlers/generateDiscordInvite.test.ts @@ -11,7 +11,7 @@ import * as responseConstants from "../../../src/constants/responses"; import { inviteResponseType } from "../../../src/typeDefinitions/discordLink.types"; jest.mock("../../../src/utils/verifyAuthToken", () => ({ - verifyAuthToken: jest.fn().mockReturnValue(true), + verifyNodejsBackendAuthToken: jest.fn().mockReturnValue(true), })); describe("generate discord link", () => { diff --git a/tests/unit/handlers/guildRoleHandler.test.ts b/tests/unit/handlers/guildRoleHandler.test.ts index 581b693d..5f205610 100644 --- a/tests/unit/handlers/guildRoleHandler.test.ts +++ b/tests/unit/handlers/guildRoleHandler.test.ts @@ -17,7 +17,7 @@ import * as guildRoleUtils from "../../../src/utils/guildRole"; import { GROUP_ROLE_ADD } from "../../../src/constants/requestsActions"; jest.mock("../../../src/utils/verifyAuthToken", () => ({ - verifyAuthToken: jest.fn().mockReturnValue(true), + verifyNodejsBackendAuthToken: jest.fn().mockReturnValue(true), verifyCronJobsToken: jest.fn().mockReturnValue(true), })); diff --git a/tests/unit/utils/sendProfileServiceBlockedMessage.test.ts b/tests/unit/utils/sendProfileServiceBlockedMessage.test.ts new file mode 100644 index 00000000..f47df89f --- /dev/null +++ b/tests/unit/utils/sendProfileServiceBlockedMessage.test.ts @@ -0,0 +1,115 @@ +import config from "../../../config/config"; +import JSONResponse from "../../../src/utils/JsonResponse"; +import { + generateStringToBeSent, + sendProfileServiceBlockedMessage, +} from "../../../src/utils/sendProfileServiceBlockedMessage"; + +describe("Send Profile Service Blocked Message", () => { + const mockEnv = { + BOT_PUBLIC_KEY: "xyz", + DISCORD_GUILD_ID: "123", + DISCORD_TOKEN: "abc", + }; + + const mockData = { + discordId: "12345678910111213", + reason: "Unauthenticated access to profile service", + }; + + test("should send the message if both userId and reason provided", async () => { + const url = config(mockEnv).TRACKING_CHANNEL_URL; + const data = { + content: generateStringToBeSent( + mockData.discordId, + mockData.reason, + mockEnv + ), + }; + + jest + .spyOn(global, "fetch") + .mockImplementation(() => Promise.resolve(new JSONResponse(""))); + + await sendProfileServiceBlockedMessage( + mockData.discordId, + mockData.reason, + mockEnv + ); + + expect(global.fetch).toHaveBeenCalledWith(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bot ${mockEnv.DISCORD_TOKEN}`, + }, + body: JSON.stringify(data), + }); + }); + + test("should send the message if userId not present", async () => { + const data = { + content: generateStringToBeSent("", mockData.reason, mockEnv), + }; + const url = config(mockEnv).TRACKING_CHANNEL_URL; + + jest + .spyOn(global, "fetch") + .mockImplementation(() => Promise.resolve(new JSONResponse(""))); + + await sendProfileServiceBlockedMessage("", mockData.reason, mockEnv); + + expect(global.fetch).toHaveBeenCalledWith(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bot ${mockEnv.DISCORD_TOKEN}`, + }, + body: JSON.stringify(data), + }); + }); + + test("should send the message if both are not present", async () => { + const data = { + content: generateStringToBeSent("", "", mockEnv), + }; + const url = config(mockEnv).TRACKING_CHANNEL_URL; + + jest + .spyOn(global, "fetch") + .mockImplementation(() => Promise.resolve(new JSONResponse(""))); + + await sendProfileServiceBlockedMessage("", "", mockEnv); + + expect(global.fetch).toHaveBeenCalledWith(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bot ${mockEnv.DISCORD_TOKEN}`, + }, + body: JSON.stringify(data), + }); + }); + + test("should send the message if reason is not present", async () => { + const data = { + content: generateStringToBeSent(mockData.discordId, "", mockEnv), + }; + const url = config(mockEnv).TRACKING_CHANNEL_URL; + + jest + .spyOn(global, "fetch") + .mockImplementation(() => Promise.resolve(new JSONResponse(""))); + + await sendProfileServiceBlockedMessage(mockData.discordId, "", mockEnv); + + expect(global.fetch).toHaveBeenCalledWith(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bot ${mockEnv.DISCORD_TOKEN}`, + }, + body: JSON.stringify(data), + }); + }); +}); diff --git a/tests/unit/utils/verifyToken.test.ts b/tests/unit/utils/verifyToken.test.ts index c533b268..c37d14b5 100644 --- a/tests/unit/utils/verifyToken.test.ts +++ b/tests/unit/utils/verifyToken.test.ts @@ -1,6 +1,6 @@ import jwt from "@tsndr/cloudflare-worker-jwt"; import { - verifyAuthToken, + verifyNodejsBackendAuthToken, verifyCronJobsToken, } from "../../../src/utils/verifyAuthToken"; import { @@ -8,7 +8,7 @@ import { INVALID_TOKEN_FORMAT, } from "../../../src/constants/responses"; -describe("verifyAuthToken", () => { +describe("verifyNodejsBackendAuthToken", () => { const authToken = "validToken"; const mockEnv = { RDS_SERVERLESS_PUBLIC_KEY: "publicKey" }; @@ -19,7 +19,9 @@ describe("verifyAuthToken", () => { it("should verify a valid token successfully", async () => { jwt.verify = jest.fn().mockResolvedValue(true); const authHeader = `Bearer ${authToken}`; - await expect(verifyAuthToken(authHeader, mockEnv)).resolves.not.toThrow(); + await expect( + verifyNodejsBackendAuthToken(authHeader, mockEnv) + ).resolves.not.toThrow(); expect(jwt.verify).toHaveBeenCalledWith( authToken, mockEnv.RDS_SERVERLESS_PUBLIC_KEY, @@ -30,22 +32,22 @@ describe("verifyAuthToken", () => { it("should throw an error for an invalid token", async () => { const authHeader = "Bearer invalidToken"; jwt.verify = jest.fn().mockResolvedValue(false); - await expect(verifyAuthToken(authHeader, mockEnv)).rejects.toThrow( - AUTHENTICATION_ERROR - ); + await expect( + verifyNodejsBackendAuthToken(authHeader, mockEnv) + ).rejects.toThrow(AUTHENTICATION_ERROR); }); it("should throw an error when Bearer is not passed", async () => { const authHeader = "Beaer invalidToken"; - await expect(verifyAuthToken(authHeader, mockEnv)).rejects.toThrow( - INVALID_TOKEN_FORMAT - ); + await expect( + verifyNodejsBackendAuthToken(authHeader, mockEnv) + ).rejects.toThrow(INVALID_TOKEN_FORMAT); }); it("should throw an error for a malformed auth header", async () => { const malformedHeader = "invalidformat"; - await expect(verifyAuthToken(malformedHeader, mockEnv)).rejects.toThrow( - INVALID_TOKEN_FORMAT - ); + await expect( + verifyNodejsBackendAuthToken(malformedHeader, mockEnv) + ).rejects.toThrow(INVALID_TOKEN_FORMAT); }); });