Skip to content
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

Merge master into integrate-grading-service-3 #2

Merged
merged 49 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
a0b50b7
Add files for service containerization
hhchinh2002 Apr 2, 2024
e082a86
Merge branch 'master' of https://github.com/tryyang2001/CS3213-Fronte…
hhchinh2002 Apr 2, 2024
b3f2631
Fix Dockerfile for grading service and frontend
hhchinh2002 Apr 5, 2024
c1ca40c
Add kubernetes .yaml file for deployment
hhchinh2002 Apr 5, 2024
a349b50
Add middleware on frontend to redirect user without authentication ac…
hhchinh2002 Apr 7, 2024
3454cbc
Fixing middleware.ts in frontend
hhchinh2002 Apr 7, 2024
4d7b343
Merge branch 'User-Microservice-temp' into User-Microservice
hhchinh2002 Apr 7, 2024
0bad0a1
Add middleware for frontend to redierct user if they are not logging …
hhchinh2002 Apr 8, 2024
2e69079
Remove some console.log on frontend and fix build eslint error
hhchinh2002 Apr 8, 2024
0768612
Fix frontend build errors
hhchinh2002 Apr 8, 2024
c544f5c
Fix user-service unit tests, remove middleware from frontend
hhchinh2002 Apr 9, 2024
d236936
Merge branch 'master' into User-Microservice
hhchinh2002 Apr 9, 2024
1ec00fe
Fix unit test
hhchinh2002 Apr 9, 2024
9e35011
Add homepage link to sidebar, sign in button if user is not logged in…
hhchinh2002 Apr 9, 2024
29e57b9
Update user service to use HttpsStatusCode enum
hhchinh2002 Apr 9, 2024
a9a81f2
Fix yarn build error for user service
hhchinh2002 Apr 9, 2024
b08a9cf
Merge branch 'master' into User-Microservice
hhchinh2002 Apr 10, 2024
d4ac36c
Resolve conflict
hhchinh2002 Apr 10, 2024
7c921d7
Ensure assignment page/component behave correctly after change
hhchinh2002 Apr 10, 2024
b87858a
Fix build error
hhchinh2002 Apr 10, 2024
532642f
Fix build error
hhchinh2002 Apr 10, 2024
2bcccb6
Fix build error
hhchinh2002 Apr 10, 2024
0a9a337
Fix ESlint rule violations
hhchinh2002 Apr 10, 2024
e7d1331
Fix build error, middleware since I'm not storing user in cookies
hhchinh2002 Apr 10, 2024
ee7f73e
Merge branch 'User-Microservice' into HEAD
hhchinh2002 Apr 10, 2024
ca9c80e
Resolve conflict
hhchinh2002 Apr 10, 2024
3b2e7d2
Fix build error
hhchinh2002 Apr 10, 2024
eda8de8
Fix build error
hhchinh2002 Apr 10, 2024
4682ada
Fix user logging in condition checking in Userpage
hhchinh2002 Apr 10, 2024
2520be7
Fix frontend unit test behaviour after changes
hhchinh2002 Apr 10, 2024
39c7055
Integration for user profile update
hhchinh2002 Apr 10, 2024
652ca98
Fix user table email field to be unique, delete Sidebar login logout …
hhchinh2002 Apr 11, 2024
4d1055e
Merge branch 'master' into User-Microservice
hhchinh2002 Apr 11, 2024
fb06518
Fix InputPassword label is not set appropriately on /user/page.tsx
hhchinh2002 Apr 11, 2024
12c8e14
Fix user table field to store avatar url to be named as "avatarUrl" i…
hhchinh2002 Apr 11, 2024
ddc4551
fix assignment table authors being changed from number[] to text[], a…
Apr 11, 2024
636f10c
delete unused interface definition
Apr 11, 2024
130013b
remove course attribute from the user schema
Apr 11, 2024
45e7f83
Merge pull request #78 from tryyang2001/tryyang/fix_db_issues_and_get…
tryyang2001 Apr 11, 2024
c1f3319
Merge branch 'master' into User-Microservice
hhchinh2002 Apr 11, 2024
5f81fd3
Merge branch 'User-Microservice' into deployment-local
hhchinh2002 Apr 11, 2024
fecdba2
Fix SideBar behaviours, logging in, signing up, profile update error …
hhchinh2002 Apr 11, 2024
d3f6e99
Merge branch 'deployment-local' into User-Microservice
hhchinh2002 Apr 11, 2024
eb038bf
Fix user package misdeleting dependencies
hhchinh2002 Apr 11, 2024
bc73f61
Remove console.log in frontend
hhchinh2002 Apr 11, 2024
6d90dfe
remove console.log in frontend (2)
hhchinh2002 Apr 11, 2024
5a34543
Fix build error
hhchinh2002 Apr 11, 2024
0ce6178
Merge pull request #76 from tryyang2001/User-Microservice
hhchinh2002 Apr 11, 2024
f9b4cac
Merge branch 'integrate-grading-service-3' into master
vivienherq Apr 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions backend/assignment-service/src/models/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,11 @@ model ReferenceSolution {
model User {
uid Int @id @default(autoincrement())

name String
email String @unique
major String
course String?
name String
email String @unique
major String
avatarUrl String?
bio String?

password String

Expand Down
116 changes: 68 additions & 48 deletions backend/user-service/controllers/user-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,24 @@ import { Request, Response } from "express";
import jwt, { Secret } from "jsonwebtoken";
import bcrypt from "bcrypt";
import db from "../models/user-model";
import HttpStatusCode from "../libs/enums/HttpStatusCode";

async function registerUser(req: Request, res: Response) {
const { email, password, name, major, course, role } = req.body;
const { email, password, name, major, role } = req.body;

console.log("registering new user", req.body);
try {
const emailSearch = await db.getUserByEmail(email);

if (emailSearch.rows.length > 0) {
console.log("Email already exists.");
return res.json({
error: "Email already exists.",
return res.status(HttpStatusCode.BAD_REQUEST.valueOf()).json({
message: "Email already exists.",
});
} else if (password.length < 10) {
console.log("Password not long enough.");
return res.json({
error: "Password not long enough.",
return res.status(HttpStatusCode.BAD_REQUEST.valueOf()).json({
message: "Password not long enough.",
});
}
bcrypt
Expand All @@ -29,39 +30,37 @@ async function registerUser(req: Request, res: Response) {
const uid = await db.createNewUser(
name,
major,
course,
email,
hash,
role
);
return res.json({ uid });
} catch (err) {
console.log(err);
return res.json({
error: "Failed to create user.",
return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR.valueOf()).json({
message: "Failed to create user.",
});
}
})
.catch((err) => {
console.log(err);
return res.send({ message: "Error crypting password." });
return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR.valueOf()).json({ message: "Error crypting password." });
});
} catch (err) {
console.log(err);
return res.json({
error: "Undefined error creating users.",
return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR.valueOf()).json({
message: "Undefined error creating users.",
});
}
}

async function loginUser(req: Request, res: Response) {
const { email, password } = req.body;

const emailSearch = await db.getUserByEmail(email);
if (emailSearch.rows.length == 0) {
console.log("User does not exist.");
return res.json({
error: "User does not exist.",
return res.status(HttpStatusCode.BAD_REQUEST.valueOf()).json({
message: "User does not exist.",
});
} else if (emailSearch.rows.length > 0) {
const user = emailSearch.rows[0];
Expand All @@ -72,31 +71,35 @@ async function loginUser(req: Request, res: Response) {
.then((result) => {
if (!result) {
console.log("Incorrect password.");
return res.json({
error: "Incorrect password.",
return res.status(HttpStatusCode.FORBIDDEN.valueOf()).json({
message: "Incorrect password.",
});
} else {
const jwtSecretKey: Secret | undefined = process.env.JWT_SECRET_KEY;
if (!jwtSecretKey) {
console.error("JWT secret key is not defined.");
return res.status(500).json({
error: "Internal server error.",
return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR.valueOf()).json({
message: "Internal server error.",
});
}

const data = {
const payload = {
email: email,
password: hash,
uid: user.uid,
};

const token = jwt.sign(data, jwtSecretKey, { expiresIn: "5d" });
const token = jwt.sign(payload, jwtSecretKey, { expiresIn: "5d" });
const responseData = {
uid: user.uid,
role: user.role,
}
res
.cookie("token", token, {
path: "/",
httpOnly: true,
maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days expiry
})
.json({ user });
.json(responseData);
}
})
.catch((err) => {
Expand All @@ -106,22 +109,29 @@ async function loginUser(req: Request, res: Response) {
}
}

async function getUserByUserId(req: Request, res: Response) {
const { uid } = req.body;
async function getUserInfo(req: Request, res: Response) {
const queryUidString = req.query.uid;
console.log(queryUidString);
if (typeof queryUidString !== 'string') {
return res.status(HttpStatusCode.BAD_REQUEST.valueOf()).json({ message: 'Invalid uid.' });
}

try {
const uid = parseInt(queryUidString, 10);
console.log(uid);
const userIdSearch = await db.getUserByUserId(uid);
if (userIdSearch.rows.length == 0) {
console.log("User does not exist.");
return res.json({
error: "User does not exist.",
return res.status(HttpStatusCode.BAD_REQUEST.valueOf()).json({
message: "User does not exist.",
});
} else if (userIdSearch.rows.length > 0) {
const user = userIdSearch.rows[0];
return res.json(user);
}
} catch (err) {
console.log(err);
return res.send({
return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR.valueOf()).json({
message: "Error getting user by uid.",
});
}
Expand All @@ -133,16 +143,16 @@ async function getUserByEmail(req: Request, res: Response) {
const emailSearch = await db.getUserByEmail(email);
if (emailSearch.rows.length == 0) {
console.log("User does not exist.");
return res.json({
error: "User does not exist.",
return res.status(HttpStatusCode.BAD_REQUEST.valueOf()).json({
message: "User does not exist.",
});
} else if (emailSearch.rows.length > 0) {
const user = emailSearch.rows[0];
return res.json(user);
}
} catch (err) {
console.log(err);
return res.send({
return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR.valueOf()).json({
message: "Error getting user by email.",
});
}
Expand All @@ -154,7 +164,7 @@ async function getAllUsers(req: Request, res: Response) {
return res.json(allUsers);
} catch (err) {
console.log(err);
return res.send({ message: "Error getting all users." });
return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR.valueOf()).send({ message: "Error getting all users." });
}
}

Expand All @@ -164,8 +174,8 @@ async function updateUserPassword(req: Request, res: Response) {
const userIdSearch = await db.getUserByUserId(uid);
if (userIdSearch.rows.length == 0) {
console.log("User does not exist.");
return res.json({
error: "User does not exist.",
return res.status(HttpStatusCode.FORBIDDEN.valueOf()).json({
message: "User does not exist.",
});
} else if (userIdSearch.rows.length > 0) {
const hash = userIdSearch.rows[0].password;
Expand All @@ -175,8 +185,8 @@ async function updateUserPassword(req: Request, res: Response) {
.then((result) => {
if (!result) {
console.log("Incorrect password.");
return res.json({
error: "Incorrect password.",
return res.status(HttpStatusCode.BAD_REQUEST.valueOf()).json({
message: "Incorrect password.",
});
} else {
bcrypt
Expand All @@ -188,45 +198,55 @@ async function updateUserPassword(req: Request, res: Response) {
message: "Update password successfully.",
});
} catch (err) {
return res.json({
error: "Failed to update user password.",
return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR.valueOf()).json({
message: "Failed to update user password.",
});
}
})
.catch((err) => {
console.log(err);
return res.send({
return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR.valueOf()).send({
message: "Error crypting password.",
});
});
}
})
.catch((err) => {
console.log(err);
return res.send({
return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR.valueOf()).send({
message: "Error checking password.",
});
});
}
} catch (err) {
console.log(err);
return res.send({
return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR.valueOf()).send({
message: "Error getting user by uid.",
});
}
}

async function updateUserInfo(req: Request, res: Response) {
const { uid, email, name, major, course, role } = req.body;
const queryUidString = req.query.uid;
if (typeof queryUidString !== 'string') {
return res.status(HttpStatusCode.BAD_REQUEST.valueOf()).json({ message: 'Invalid uid.' });
}
const uid = parseInt(queryUidString);
const updateFields = req.body;

try {
await db.updateUserInfo(uid, email, name, major, course, role);
if (Object.keys(updateFields).length === 0) {
return res.status(HttpStatusCode.BAD_REQUEST.valueOf()).json({ message: 'No fields provided for update.' });
}

await db.updateUserInfo(uid, updateFields);

return res.json({
message: "User info updated.",
message: 'User info updated.',
});
} catch (err) {
return res.json({
error: "Failed to update user info.",
});
console.error('Error updating user info:', err);
return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR.valueOf()).json({ message: 'Failed to update user info.' });
}
}

Expand All @@ -242,7 +262,7 @@ async function deleteUser(req: Request, res: Response) {
} catch (err) {
console.log(err);
return res.send({
error: "Undefined error deleting account.",
message: "Undefined error deleting account.",
});
}
}
Expand All @@ -257,7 +277,7 @@ async function clearCookie(req: Request, res: Response) {
export default {
registerUser,
loginUser,
getUserByUserId,
getUserInfo,
getUserByEmail,
getAllUsers,
updateUserPassword,
Expand Down
1 change: 1 addition & 0 deletions backend/user-service/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import express from 'express';
import cookieParser from 'cookie-parser';
import cors from 'cors';
import userRoute from './routes/user-route';
import HttpStatusCode from "./libs/enums/HttpStatusCode";

const app = express();

Expand Down
Loading
Loading