Skip to content

Commit 2b05763

Browse files
authored
Merge pull request #293 from Real-Dev-Squad/develop
Dev to main sync
2 parents e14a179 + 0aef740 commit 2b05763

18 files changed

+591
-3
lines changed

.github/workflows/register-commands-production.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ jobs:
2525
RDS_SERVERLESS_PUBLIC_KEY: ${{secrets.RDS_SERVERLESS_PUBLIC_KEY}}
2626
CRON_JOBS_PUBLIC_KEY: ${{secrets.CRON_JOBS_PUBLIC_KEY}}
2727
IDENTITY_SERVICE_PUBLIC_KEY: ${{secrets.IDENTITY_SERVICE_PUBLIC_KEY}}
28+
AWS_READ_ACCESS_GROUP_ID: ${{secrets.AWS_READ_ACCESS_GROUP_ID}}
2829

2930
Register-Commands:
3031
needs: [Environment-Variables-Check]
@@ -41,6 +42,7 @@ jobs:
4142
DISCORD_TOKEN: ${{secrets.DISCORD_TOKEN}}
4243
DISCORD_APPLICATION_ID: ${{secrets.DISCORD_APPLICATION_ID}}
4344
DISCORD_GUILD_ID: ${{secrets.DISCORD_GUILD_ID}}
45+
AWS_READ_ACCESS_GROUP_ID: ${{secrets.AWS_READ_ACCESS_GROUP_ID}}
4446
Deploy-to-Cloudflare:
4547
needs: [Register-Commands]
4648
runs-on: ubuntu-latest
@@ -61,6 +63,7 @@ jobs:
6163
RDS_SERVERLESS_PUBLIC_KEY
6264
CRON_JOBS_PUBLIC_KEY
6365
IDENTITY_SERVICE_PUBLIC_KEY
66+
AWS_READ_ACCESS_GROUP_ID
6467
env:
6568
CURRENT_ENVIRONMENT: production
6669
CLOUDFLARE_API_TOKEN: ${{secrets.CLOUDFLARE_API_TOKEN}}
@@ -71,3 +74,4 @@ jobs:
7174
RDS_SERVERLESS_PUBLIC_KEY: ${{secrets.RDS_SERVERLESS_PUBLIC_KEY}}
7275
CRON_JOBS_PUBLIC_KEY: ${{secrets.CRON_JOBS_PUBLIC_KEY}}
7376
IDENTITY_SERVICE_PUBLIC_KEY: ${{secrets.IDENTITY_SERVICE_PUBLIC_KEY}}
77+
AWS_READ_ACCESS_GROUP_ID: ${{secrets.AWS_READ_ACCESS_GROUP_ID}}

.github/workflows/register-commands-staging.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ jobs:
2525
RDS_SERVERLESS_PUBLIC_KEY: ${{secrets.RDS_SERVERLESS_PUBLIC_KEY}}
2626
CRON_JOBS_PUBLIC_KEY: ${{secrets.CRON_JOBS_PUBLIC_KEY}}
2727
IDENTITY_SERVICE_PUBLIC_KEY: ${{secrets.IDENTITY_SERVICE_PUBLIC_KEY}}
28+
AWS_READ_ACCESS_GROUP_ID: ${{secrets.AWS_READ_ACCESS_GROUP_ID}}
2829

2930
Register-Commands:
3031
needs: [Environment-Variables-Check]
@@ -41,6 +42,7 @@ jobs:
4142
DISCORD_TOKEN: ${{secrets.DISCORD_TOKEN}}
4243
DISCORD_APPLICATION_ID: ${{secrets.DISCORD_APPLICATION_ID}}
4344
DISCORD_GUILD_ID: ${{secrets.DISCORD_GUILD_ID}}
45+
AWS_READ_ACCESS_GROUP_ID: ${{secrets.AWS_READ_ACCESS_GROUP_ID}}
4446
Deploy-to-Cloudflare:
4547
needs: [Register-Commands]
4648
runs-on: ubuntu-latest
@@ -61,6 +63,7 @@ jobs:
6163
RDS_SERVERLESS_PUBLIC_KEY
6264
CRON_JOBS_PUBLIC_KEY
6365
IDENTITY_SERVICE_PUBLIC_KEY
66+
AWS_READ_ACCESS_GROUP_ID
6467
env:
6568
CURRENT_ENVIRONMENT: staging
6669
CLOUDFLARE_API_TOKEN: ${{secrets.CLOUDFLARE_API_TOKEN}}
@@ -71,3 +74,4 @@ jobs:
7174
RDS_SERVERLESS_PUBLIC_KEY: ${{secrets.RDS_SERVERLESS_PUBLIC_KEY}}
7275
CRON_JOBS_PUBLIC_KEY: ${{secrets.CRON_JOBS_PUBLIC_KEY}}
7376
IDENTITY_SERVICE_PUBLIC_KEY: ${{secrets.IDENTITY_SERVICE_PUBLIC_KEY}}
77+
AWS_READ_ACCESS_GROUP_ID: ${{secrets.AWS_READ_ACCESS_GROUP_ID}}

config/config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ export function loadEnv(env: env, fromWorkerEnv: boolean): env {
5656
IDENTITY_SERVICE_PUBLIC_KEY: fromWorkerEnv
5757
? env.IDENTITY_SERVICE_PUBLIC_KEY
5858
: process.env.IDENTITY_SERVICE_PUBLIC_KEY || "",
59+
AWS_READ_ACCESS_GROUP_ID: fromWorkerEnv
60+
? env.AWS_READ_ACCESS_GROUP_ID
61+
: process.env.AWS_READ_ACCESS_GROUP_ID || "",
5962
};
6063
return Env;
6164
}

src/constants/commands.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import { config } from "dotenv";
2+
3+
config();
4+
15
export const HELLO = {
26
name: "hello",
37
description: "Replies with hello in the channel",
@@ -27,6 +31,36 @@ export const GROUP_INVITE = {
2731
},
2832
],
2933
};
34+
export const GRANT_AWS_ACCESS = {
35+
name: "grant-aws-access",
36+
description: "This command is to grant AWS access to the discord users.",
37+
options: [
38+
{
39+
name: "user-name",
40+
description: "User to be granted the AWS access",
41+
type: 6, //user Id to be grant the access
42+
required: true,
43+
},
44+
{
45+
name: "aws-group-name",
46+
description: "AWS group name",
47+
type: 3,
48+
required: true,
49+
choices: [
50+
{
51+
name: "AWS read access",
52+
value: process.env.AWS_READ_ACCESS_GROUP_ID,
53+
},
54+
],
55+
},
56+
{
57+
name: "dev",
58+
description: "Feature flag",
59+
type: 5,
60+
required: true,
61+
},
62+
],
63+
};
3064

3165
export const MENTION_EACH = {
3266
name: "mention-each",

src/constants/responses.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,4 @@ export const INVALID_TOKEN_FORMAT =
8282
export const AUTHENTICATION_ERROR = "Invalid Authentication token";
8383
export const TASK_UPDATE_SENT_MESSAGE =
8484
"Task update sent on Discord's tracking-updates channel.";
85+
export const NOT_IMPLEMENTED = "Feature not implemented";

src/constants/urls.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export const RDS_BASE_STAGING_API_URL = "https://staging-api.realdevsquad.com";
33
export const RDS_BASE_DEVELOPMENT_API_URL = "http://localhost:3000"; // If needed, modify the URL to your local API server run through ngrok
44

55
export const DISCORD_BASE_URL = "https://discord.com/api/v10";
6+
export const AWS_IAM_SIGNIN_URL = "https://realdevsquad.awsapps.com/start#/";
67
export const DISCORD_AVATAR_BASE_URL = "https://cdn.discordapp.com/avatars";
78

89
export const VERIFICATION_SITE_URL = "https://my.realdevsquad.com";

src/controllers/baseHandler.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
USER,
3030
REMOVE,
3131
GROUP_INVITE,
32+
GRANT_AWS_ACCESS,
3233
} from "../constants/commands";
3334
import { updateNickName } from "../utils/updateNickname";
3435
import { discordEphemeralResponse } from "../utils/discordEphemeralResponse";
@@ -44,6 +45,7 @@ import {
4445
import { DevFlag } from "../typeDefinitions/filterUsersByRole";
4546
import { kickEachUser } from "./kickEachUser";
4647
import { groupInvite } from "./groupInvite";
48+
import { grantAWSAccessCommand } from "./grantAWSAccessCommand";
4749

4850
export async function baseHandler(
4951
message: discordMessageRequest,
@@ -82,6 +84,19 @@ export async function baseHandler(
8284
return await mentionEachUser(transformedArgument, env, ctx);
8385
}
8486

87+
case getCommandName(GRANT_AWS_ACCESS): {
88+
const data = message.data?.options as Array<messageRequestDataOptions>;
89+
const transformedArgument = {
90+
member: message.member,
91+
userDetails: data[0],
92+
awsGroupDetails: data[1],
93+
channelId: message.channel_id,
94+
dev: data.find((item) => item.name === "dev") as unknown as DevFlag,
95+
};
96+
97+
return await grantAWSAccessCommand(transformedArgument, env, ctx);
98+
}
99+
85100
case getCommandName(REMOVE): {
86101
const data = message.data?.options as Array<messageRequestDataOptions>;
87102
const transformedArgument = {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { IRequest } from "itty-router";
2+
import JSONResponse from "../utils/JsonResponse";
3+
import { env } from "../typeDefinitions/default.types";
4+
import * as response from "../constants/responses";
5+
import { verifyNodejsBackendAuthToken } from "../utils/verifyAuthToken";
6+
import { deleteGuildRole } from "../utils/deleteGuildRole";
7+
8+
export async function deleteGuildRoleHandler(request: IRequest, env: env) {
9+
const authHeader = request.headers.get("Authorization");
10+
const reason = request.headers.get("X-Audit-Log-Reason");
11+
const roleId = decodeURI(request.params?.roleId ?? "");
12+
const { dev } = request.query;
13+
const devFlag = dev === "true";
14+
15+
if (!authHeader) {
16+
return new JSONResponse(response.BAD_SIGNATURE, { status: 401 });
17+
}
18+
19+
if (!devFlag) {
20+
return new JSONResponse(response.NOT_IMPLEMENTED, { status: 501 });
21+
}
22+
23+
if (!roleId) {
24+
return new JSONResponse(response.BAD_REQUEST, { status: 400 });
25+
}
26+
27+
try {
28+
await verifyNodejsBackendAuthToken(authHeader, env);
29+
const result = await deleteGuildRole(env, roleId, reason);
30+
31+
if (result === response.ROLE_REMOVED) {
32+
return new Response(null, { status: 204 });
33+
} else {
34+
return new JSONResponse(response.INTERNAL_SERVER_ERROR, {
35+
status: 500,
36+
});
37+
}
38+
} catch (err) {
39+
console.error("An error occurred while deleting discord role:", err);
40+
return new JSONResponse(response.INTERNAL_SERVER_ERROR, {
41+
status: 500,
42+
});
43+
}
44+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { discordTextResponse } from "../utils/discordResponse";
2+
import { SUPER_USER_ONE, SUPER_USER_TWO } from "../constants/variables";
3+
import { env } from "../typeDefinitions/default.types";
4+
import {
5+
messageRequestMember,
6+
messageRequestDataOptions,
7+
} from "../typeDefinitions/discordMessage.types";
8+
import { grantAWSAccess } from "../utils/awsAccess";
9+
import { DevFlag } from "../typeDefinitions/filterUsersByRole";
10+
11+
export async function grantAWSAccessCommand(
12+
transformedArgument: {
13+
member: messageRequestMember;
14+
userDetails: messageRequestDataOptions;
15+
awsGroupDetails: messageRequestDataOptions;
16+
channelId: number;
17+
dev?: DevFlag;
18+
},
19+
env: env,
20+
ctx: ExecutionContext
21+
) {
22+
const dev = transformedArgument?.dev?.value || false;
23+
if (!dev) {
24+
return discordTextResponse("Please enable feature flag to make this work");
25+
}
26+
const isUserSuperUser = [SUPER_USER_ONE, SUPER_USER_TWO].includes(
27+
transformedArgument.member.user.id.toString()
28+
);
29+
if (!isUserSuperUser) {
30+
const responseText = `You're not authorized to make this request.`;
31+
return discordTextResponse(responseText);
32+
}
33+
const roleId = transformedArgument.userDetails.value;
34+
const groupId = transformedArgument.awsGroupDetails.value;
35+
const channelId = transformedArgument.channelId;
36+
37+
return grantAWSAccess(roleId, groupId, env, ctx, channelId);
38+
}

src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { sendProfileBlockedMessage } from "./controllers/profileHandler";
2323
import { sendTaskUpdatesHandler } from "./controllers/taskUpdatesHandler";
2424

2525
import config, { loadEnv } from "./../config/config";
26+
import { deleteGuildRoleHandler } from "./controllers/deleteGuildRoleHandler";
2627

2728
const router = Router();
2829

@@ -34,6 +35,8 @@ router.get("/", async () => {
3435

3536
router.patch("/guild/member", changeNickname);
3637

38+
router.delete("/roles/:roleId", deleteGuildRoleHandler);
39+
3740
router.put("/roles/create", createGuildRoleHandler);
3841

3942
router.put("/roles/add", addGroupRoleHandler);

0 commit comments

Comments
 (0)