Skip to content

Commit 5c5ba3d

Browse files
authored
Merge pull request #89 from CS3219-AY2425S1/room-fetching-rest
Add Room Fetching Based on Rest
2 parents 93e0c52 + df68358 commit 5c5ba3d

File tree

17 files changed

+271
-43
lines changed

17 files changed

+271
-43
lines changed

backend/api-gateway/nginx.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ http {
6363
proxy_send_timeout 60s;
6464
}
6565

66-
# Proxy for /api/categories to service running on port 3002
66+
# Proxy for /api/history to service running on port 3002
6767
location /api/history/ {
6868
proxy_pass http://host.docker.internal:3002/api/history/;
6969
proxy_set_header Host $host;

backend/matching-service/.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ RELAXATION_INTERVAL=3000
1818
MATCH_TIMEOUT=30000
1919
CLEANUP_INTERVAL=75000
2020

21+
JWT_ACCESS_TOKEN_SECRET=<your-jwt-accecss-token>
22+
2123
# Copy root .env
2224
# If using mongoDB containerization, set to true. Else set to false (i.e local testing)
2325
DB_REQUIRE_AUTH=true

backend/matching-service/app.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,12 @@ initSocket(server);
2727

2828
app.use(express.json());
2929

30-
app.use("/api/match", matchingRoutes);
30+
app.use(cors({
31+
origin: true,
32+
credentials: true,
33+
}));
3134

32-
app.use(
33-
cors({
34-
origin: "*",
35-
credentials: true,
36-
})
37-
);
35+
app.use("/api/match", matchingRoutes);
3836

3937
app.use(errorHandler);
4038

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import roomModel from "../models/RoomSchema";
2+
import { Request, Response, NextFunction } from "express";
3+
4+
export async function getRoomDetails(
5+
request: Request,
6+
response: Response,
7+
next: NextFunction
8+
) {
9+
const { roomId } = request.params
10+
try {
11+
console.log(roomId)
12+
const room = await roomModel.findOne({ roomId });
13+
if (!room) {
14+
throw new Error("Room not found");
15+
}
16+
response.status(200).json({
17+
roomId,
18+
attemptStartedAt: room.createdAt.getTime(),
19+
userIdOne: room.participants[0],
20+
userIdTwo: room.participants[1],
21+
questionId: room.questionId,
22+
});
23+
} catch (error) {
24+
next(error);
25+
}
26+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Request, Response, NextFunction } from "express";
2+
import jwt from "jsonwebtoken";
3+
4+
export interface AuthenticatedRequest extends Request {
5+
userId?: string;
6+
}
7+
8+
export const authenticateToken = (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
9+
const authHeader = req.headers["authorization"];
10+
11+
if (!authHeader) return res.status(401).json({ error: "Authorization header missing" });
12+
13+
const token = authHeader.split(" ")[1];
14+
15+
if (!token) return res.status(401).json({ error: "Token missing" });
16+
17+
jwt.verify(token, process.env.JWT_ACCESS_TOKEN_SECRET as string, (err, decoded: any) => {
18+
console.log(err);
19+
if (err) return res.status(403).json({ error: "Invalid token" });
20+
21+
req.userId = decoded.id;
22+
next();
23+
});
24+
};
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import jwt from "jsonwebtoken";
2+
export function verifyIsAdmin(req: any, res: any, next: any) {
3+
if (req.isAdmin) {
4+
next();
5+
} else {
6+
return res.status(403).json({ message: "Not authorized to access this resource" });
7+
}
8+
}
9+
export function verifyAccessToken(req: any, res: any, next: any) {
10+
const authHeader = req.headers.authorization || req.header.Authorization;
11+
if (!authHeader) {
12+
return res.status(401).json({ message: "Authentication failed" });
13+
}
14+
15+
if (!authHeader?.startsWith("Bearer ")) {
16+
return res.status(401).json({ message: "Unauthorized: no token" });
17+
}
18+
const token = authHeader.split(" ")[1];
19+
20+
const secret = process.env.JWT_ACCESS_TOKEN_SECRET;
21+
if (!secret) {
22+
return res.status(500).json({ message: "Internal server error" });
23+
}
24+
jwt.verify(token, secret, async (err: any, user: any) => {
25+
if (err) {
26+
return res.status(401).json({ message: `Unauthorized: ${err.message}` });
27+
}
28+
req.isAdmin = user.isAdmin;
29+
next();
30+
});
31+
}
Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
1-
import mongoose from "mongoose";
1+
import mongoose, { Schema, Types } from "mongoose";
22

3-
const roomSchema = new mongoose.Schema({
3+
export interface Room extends mongoose.Document {
4+
_id: Types.ObjectId;
5+
participants: string[];
6+
category: string;
7+
difficulty: string;
8+
roomId: string;
9+
questionId: string;
10+
createdAt: Date;
11+
}
12+
13+
14+
const roomSchema: Schema<Room> = new mongoose.Schema<Room>({
415
participants: [{ userId: String }],
516
category: { type: String, default: 'Any' },
617
difficulty: { type: String, default: 'Any' },
@@ -9,6 +20,6 @@ const roomSchema = new mongoose.Schema({
920
createdAt: { type: Date, default: Date.now }
1021
});
1122

12-
const Room = mongoose.model('Room', roomSchema);
23+
const roomModel = mongoose.model<Room>('Room', roomSchema);
1324

14-
export default Room;
25+
export default roomModel;
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
import { getRoomDetails } from '../controllers/roomController';
12
import { cancelMatch, startMatching } from '../controllers/matchingController';
23
import express from 'express';
4+
import { authenticateToken } from '../middlewares/auth';
35

46
const router = express.Router();
57

6-
router.post('/', startMatching);
7-
router.delete('/:socketId', cancelMatch)
8+
router.post("/", authenticateToken, startMatching);
9+
router.delete("/:socketId", authenticateToken, cancelMatch);
10+
router.get("/room/:roomId", authenticateToken, getRoomDetails);
811

9-
export default router;
12+
export default router;

frontend/src/data/repositories/HistoryRemoteDataSource.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ export class HistoryRemoteDataSource extends BaseApi {
1818
}
1919

2020
async deleteSelectedHistories(selectedHistoryIds: string[]): Promise<void> {
21-
console.log("Delete")
2221
selectedHistoryIds.forEach(async (id) => {
2322
console.log(id);
2423
await this.protectedDelete<void>(`/user/${id}`);
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { BaseApi } from "../../infrastructure/Api/BaseApi";
2+
import { Room } from "../../domain/entities/Room";
3+
4+
const API_URL = "/api/match";
5+
6+
export class RoomRemoteDataSource extends BaseApi {
7+
constructor() {
8+
super(API_URL);
9+
}
10+
11+
async getRoomDetails(roomId: string): Promise<Room> {
12+
return await this.protectedGet<Room>(`/room/${roomId}`);
13+
}
14+
}
15+
16+
export const roomRemoteDataSource = new RoomRemoteDataSource();

0 commit comments

Comments
 (0)