Skip to content

Commit a6ea205

Browse files
authored
Merge pull request #78 from CS3219-AY2425S1/d7/interview-auth
Authenticate User On Entering Interview Room
2 parents 845c555 + 0232ce1 commit a6ea205

37 files changed

+1555
-186
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { defineConfig } from 'drizzle-kit';
2+
3+
const config = {
4+
host: process.env.EXPRESS_DB_HOST!,
5+
port: Number.parseInt(process.env.EXPRESS_DB_PORT!),
6+
database: process.env.POSTGRES_DB!,
7+
user: process.env.POSTGRES_USER,
8+
password: process.env.POSTGRES_PASSWORD,
9+
};
10+
11+
export default defineConfig({
12+
schema: './src/lib/db/schema.ts',
13+
out: './drizzle',
14+
dialect: 'postgresql',
15+
dbCredentials: config,
16+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CREATE TYPE "public"."action" AS ENUM('SEED');--> statement-breakpoint
2+
CREATE TABLE IF NOT EXISTS "admin" (
3+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
4+
"created_at" timestamp DEFAULT now(),
5+
"action" "action" NOT NULL
6+
);
7+
--> statement-breakpoint
8+
CREATE TABLE IF NOT EXISTS "rooms" (
9+
"room_id" varchar(255) PRIMARY KEY NOT NULL,
10+
"user_id_1" uuid NOT NULL,
11+
"user_id_2" uuid NOT NULL,
12+
"question_id" serial NOT NULL,
13+
"created_at" timestamp DEFAULT now()
14+
);
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
{
2+
"id": "0fa8a8f0-f2e1-432e-890f-4a1da22f1a18",
3+
"prevId": "00000000-0000-0000-0000-000000000000",
4+
"version": "7",
5+
"dialect": "postgresql",
6+
"tables": {
7+
"public.admin": {
8+
"name": "admin",
9+
"schema": "",
10+
"columns": {
11+
"id": {
12+
"name": "id",
13+
"type": "uuid",
14+
"primaryKey": true,
15+
"notNull": true,
16+
"default": "gen_random_uuid()"
17+
},
18+
"created_at": {
19+
"name": "created_at",
20+
"type": "timestamp",
21+
"primaryKey": false,
22+
"notNull": false,
23+
"default": "now()"
24+
},
25+
"action": {
26+
"name": "action",
27+
"type": "action",
28+
"typeSchema": "public",
29+
"primaryKey": false,
30+
"notNull": true
31+
}
32+
},
33+
"indexes": {},
34+
"foreignKeys": {},
35+
"compositePrimaryKeys": {},
36+
"uniqueConstraints": {},
37+
"policies": {},
38+
"checkConstraints": {},
39+
"isRLSEnabled": false
40+
},
41+
"public.rooms": {
42+
"name": "rooms",
43+
"schema": "",
44+
"columns": {
45+
"room_id": {
46+
"name": "room_id",
47+
"type": "varchar(255)",
48+
"primaryKey": true,
49+
"notNull": true
50+
},
51+
"user_id_1": {
52+
"name": "user_id_1",
53+
"type": "uuid",
54+
"primaryKey": false,
55+
"notNull": true
56+
},
57+
"user_id_2": {
58+
"name": "user_id_2",
59+
"type": "uuid",
60+
"primaryKey": false,
61+
"notNull": true
62+
},
63+
"question_id": {
64+
"name": "question_id",
65+
"type": "serial",
66+
"primaryKey": false,
67+
"notNull": true
68+
},
69+
"created_at": {
70+
"name": "created_at",
71+
"type": "timestamp",
72+
"primaryKey": false,
73+
"notNull": false,
74+
"default": "now()"
75+
}
76+
},
77+
"indexes": {},
78+
"foreignKeys": {},
79+
"compositePrimaryKeys": {},
80+
"uniqueConstraints": {},
81+
"policies": {},
82+
"checkConstraints": {},
83+
"isRLSEnabled": false
84+
}
85+
},
86+
"enums": {
87+
"public.action": {
88+
"name": "action",
89+
"schema": "public",
90+
"values": [
91+
"SEED"
92+
]
93+
}
94+
},
95+
"schemas": {},
96+
"sequences": {},
97+
"roles": {},
98+
"policies": {},
99+
"views": {},
100+
"_meta": {
101+
"columns": {},
102+
"schemas": {},
103+
"tables": {}
104+
}
105+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"version": "7",
3+
"dialect": "postgresql",
4+
"entries": [
5+
{
6+
"idx": 0,
7+
"version": "7",
8+
"when": 1731050544004,
9+
"tag": "0000_initial_schema",
10+
"breakpoints": true
11+
}
12+
]
13+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,13 @@
11
#!/bin/sh
2+
3+
# Drizzle will handle its own logic to remove conflicts
4+
npm run db:prod:migrate
5+
6+
# Checks admin table and will not seed if data exists
7+
npm run db:prod:seed
8+
9+
rm -rf drizzle src tsconfig.json
10+
11+
npm uninstall tsx drizzle-kit
12+
213
npm run start

backend/collaboration/express.Dockerfile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ RUN npm ci --omit=dev
1515

1616
RUN sed -i 's|./ws|ws|g' ./dist/ws.js
1717

18+
# For migration
19+
RUN npm install tsx drizzle-kit
20+
COPY drizzle ./drizzle
21+
COPY src/lib/db/ ./src/lib/db
22+
COPY src/config.ts ./src
23+
COPY tsconfig.json .
1824
COPY entrypoint.sh .
1925

2026
ARG port

backend/collaboration/package.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88
"start": "node dist/index.js",
99
"build:local": "env-cmd -f .env.local tsc && tsc-alias",
1010
"start:local": "env-cmd -f .env.local node dist/index.js",
11+
"db:generate": "env-cmd -f .env.local drizzle-kit generate",
12+
"db:migrate": "env-cmd -f .env.local tsx ./src/lib/db/migrate.ts",
13+
"db:prod:migrate": "tsx ./src/lib/db/migrate.ts",
14+
"db:prod:seed": "tsx ./src/lib/db/seed.ts",
15+
"db:seed": "env-cmd -f .env.local tsx src/lib/db/seed.ts",
16+
"db:seed:prod": "tsx src/lib/db/seed.ts",
1117
"fmt": "prettier --config .prettierrc src --write",
1218
"test": "echo \"Error: no test specified\" && exit 1"
1319
},
@@ -18,6 +24,7 @@
1824
"dependencies": {
1925
"cors": "^2.8.5",
2026
"dotenv": "^16.4.5",
27+
"drizzle-orm": "^0.36.1",
2128
"env-cmd": "^10.1.0",
2229
"express": "^4.21.1",
2330
"http-status-codes": "^2.3.0",
@@ -33,6 +40,7 @@
3340
"yjs": "^13.6.19"
3441
},
3542
"devDependencies": {
43+
"drizzle-kit": "^0.28.0",
3644
"@types/cors": "^2.8.17",
3745
"@types/express": "^4.17.21",
3846
"@types/node": "^22.5.5",
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import type { Request, Response } from 'express';
2+
import { StatusCodes } from 'http-status-codes';
3+
4+
import { getRoomsService } from '@/service/get/rooms-get-service';
5+
6+
type QueryParams = {
7+
userId: string;
8+
offset?: number;
9+
limit?: number;
10+
};
11+
12+
export async function getRoomsController(
13+
req: Request<unknown, unknown, unknown, Partial<QueryParams>>,
14+
res: Response
15+
) {
16+
const { userId, ...rest } = req.query;
17+
18+
if (!userId) {
19+
return res.status(StatusCodes.UNPROCESSABLE_ENTITY).json('Malformed Request');
20+
}
21+
22+
const response = await getRoomsService({ userId, ...rest });
23+
24+
if (response.data) {
25+
return res.status(response.code).json(response.data);
26+
}
27+
28+
return res
29+
.status(response.code)
30+
.json({ error: response.error || { message: 'An error occurred' } });
31+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import type { Request, Response } from 'express';
2+
import { StatusCodes } from 'http-status-codes';
3+
4+
import { logger } from '@/lib/utils';
5+
import { roomAuthService } from '@/service/get/room-auth-service';
6+
7+
type QueryParams = {
8+
roomId: string;
9+
userId: string;
10+
};
11+
12+
// Returns the questionId if valid.
13+
export async function authCheck(
14+
req: Request<unknown, unknown, unknown, Partial<QueryParams>>,
15+
res: Response
16+
) {
17+
const { roomId, userId } = req.query;
18+
19+
if (!roomId || !userId) {
20+
return res.status(StatusCodes.UNPROCESSABLE_ENTITY).json('Malformed request');
21+
}
22+
23+
try {
24+
const response = await roomAuthService({
25+
roomId,
26+
userId,
27+
});
28+
29+
if (response.data) {
30+
return res.status(response.code).json(response.data);
31+
}
32+
33+
return res
34+
.status(response.code)
35+
.json({ error: response.error || { message: 'An error occurred.' } });
36+
} catch (error) {
37+
const { name, stack, cause, message } = error as Error;
38+
logger.error('Error authenticating room: ' + JSON.stringify({ name, stack, message, cause }));
39+
return res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
40+
error: { message: 'An error occurred while authenticating the room' },
41+
});
42+
}
43+
}

backend/collaboration/src/lib/db/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { drizzle } from 'drizzle-orm/postgres-js';
12
import postgres from 'postgres';
23

34
export const config = {
@@ -8,4 +9,8 @@ export const config = {
89
password: process.env.POSTGRES_PASSWORD,
910
};
1011

11-
export const db = postgres(config);
12+
const queryClient = postgres(config);
13+
14+
export const db = drizzle(queryClient);
15+
16+
export * from './schema';

0 commit comments

Comments
 (0)