Skip to content

Commit e4fbc17

Browse files
authored
Merge pull request #10 from nicolelim02/feat/users
Add user profile page
2 parents 6ea317a + 4e94624 commit e4fbc17

File tree

17 files changed

+721
-67
lines changed

17 files changed

+721
-67
lines changed

backend/user-service/.env.sample

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ JWT_SECRET=you-can-replace-this-with-your-own-secret
88
ADMIN_USERNAME=administrator
99
ADMIN_EMAIL=[email protected]
1010
ADMIN_PASSWORD=Admin@123
11+
12+
# origins for cors
13+
ORIGINS=["http://localhost:5173", "http://127.0.0.1:5173"]

backend/user-service/app.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,42 @@
11
import express, { Request, Response, NextFunction } from "express";
22
import cors from "cors";
3+
import dotenv from "dotenv";
4+
import fs from "fs";
5+
import yaml from "yaml";
6+
import swaggerUi from "swagger-ui-express";
37

48
import userRoutes from "./routes/user-routes.js";
59
import authRoutes from "./routes/auth-routes.js";
610

11+
dotenv.config();
12+
13+
const file = fs.readFileSync("./swagger.yml", "utf-8");
14+
const swaggerDocument = yaml.parse(file);
15+
const origin = process.env.ORIGINS
16+
? process.env.ORIGINS.split(",")
17+
: ["http://localhost:5173", "http://127.0.0.1:5173"];
18+
719
const app = express();
820

921
app.use(express.urlencoded({ extended: true }));
1022
app.use(express.json());
11-
app.use(cors()); // config cors so that front-end can use
12-
app.options("*", cors());
23+
app.use(
24+
cors({
25+
origin: origin,
26+
credentials: true,
27+
})
28+
); // config cors so that front-end can use
29+
app.options(
30+
"*",
31+
cors({
32+
origin: ["http://localhost:5173", "http://127.0.0.1:5173"],
33+
credentials: true,
34+
})
35+
);
1336

1437
// To handle CORS Errors
1538
app.use((req: Request, res: Response, next: NextFunction) => {
16-
res.header("Access-Control-Allow-Origin", "*"); // "*" -> Allow all links to access
39+
res.header("Access-Control-Allow-Origin", req.headers.origin); // "*" -> Allow all links to access
1740

1841
res.header(
1942
"Access-Control-Allow-Headers",
@@ -30,9 +53,9 @@ app.use((req: Request, res: Response, next: NextFunction) => {
3053
next();
3154
});
3255

33-
app.use("/users", userRoutes);
34-
app.use("/auth", authRoutes);
35-
56+
app.use("/api/users", userRoutes);
57+
app.use("/api/auth", authRoutes);
58+
app.use("/docs", swaggerUi.serve, swaggerUi.setup(swaggerDocument));
3659
app.get("/", (req: Request, res: Response, next: NextFunction) => {
3760
console.log("Sending Greetings!");
3861
res.json({

backend/user-service/controller/auth-controller.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import { findUserByEmail as _findUserByEmail } from "../model/repository.js";
55
import { formatUserResponse } from "./user-controller.js";
66
import { AuthenticatedRequest } from "../types/request.js";
77

8-
export async function handleLogin(req: AuthenticatedRequest, res: Response): Promise<Response> {
8+
export async function handleLogin(
9+
req: AuthenticatedRequest,
10+
res: Response
11+
): Promise<Response> {
912
const { email, password } = req.body;
1013
if (email && password) {
1114
try {
@@ -28,9 +31,10 @@ export async function handleLogin(req: AuthenticatedRequest, res: Response): Pro
2831
expiresIn: "7d",
2932
}
3033
);
31-
return res
32-
.status(200)
33-
.json({ message: "User logged in", data: { accessToken, ...formatUserResponse(user) } });
34+
return res.status(200).json({
35+
message: "User logged in",
36+
data: { accessToken, user: formatUserResponse(user) },
37+
});
3438
} catch (err) {
3539
return res.status(500).json({ message: "Server error", err });
3640
}
@@ -45,7 +49,9 @@ export async function handleVerifyToken(
4549
): Promise<Response> {
4650
try {
4751
const verifiedUser = req.user;
48-
return res.status(200).json({ message: "Token verified", data: verifiedUser });
52+
return res
53+
.status(200)
54+
.json({ message: "Token verified", data: verifiedUser });
4955
} catch (err) {
5056
return res.status(500).json({ message: "Server error", err });
5157
}

backend/user-service/controller/user-controller.ts

Lines changed: 91 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,34 @@ import {
2121
} from "../utils/validators";
2222
import { IUser } from "../model/user-model";
2323

24-
export async function createUser(req: Request, res: Response): Promise<Response> {
24+
export async function createUser(
25+
req: Request,
26+
res: Response
27+
): Promise<Response> {
2528
try {
2629
const { username, email, password } = req.body;
2730
const existingUser = await _findUserByUsernameOrEmail(username, email);
2831
if (existingUser) {
29-
return res.status(409).json({ message: "username or email already exists" });
32+
return res
33+
.status(409)
34+
.json({ message: "username or email already exists" });
3035
}
3136

3237
if (username && email && password) {
33-
const { isValid: isValidUsername, message: usernameMessage } = validateUsername(username);
38+
const { isValid: isValidUsername, message: usernameMessage } =
39+
validateUsername(username);
3440
if (!isValidUsername) {
3541
return res.status(400).json({ message: usernameMessage });
3642
}
3743

38-
const { isValid: isValidEmail, message: emailMessage } = validateEmail(email);
44+
const { isValid: isValidEmail, message: emailMessage } =
45+
validateEmail(email);
3946
if (!isValidEmail) {
4047
return res.status(400).json({ message: emailMessage });
4148
}
4249

43-
const { isValid: isValidPassword, message: passwordMessage } = validatePassword(password);
50+
const { isValid: isValidPassword, message: passwordMessage } =
51+
validatePassword(password);
4452
if (!isValidPassword) {
4553
return res.status(400).json({ message: passwordMessage });
4654
}
@@ -53,11 +61,15 @@ export async function createUser(req: Request, res: Response): Promise<Response>
5361
data: formatUserResponse(createdUser),
5462
});
5563
} else {
56-
return res.status(400).json({ message: "username and/or email and/or password are missing" });
64+
return res
65+
.status(400)
66+
.json({ message: "username and/or email and/or password are missing" });
5767
}
5868
} catch (err) {
5969
console.error(err);
60-
return res.status(500).json({ message: "Unknown error when creating new user!" });
70+
return res
71+
.status(500)
72+
.json({ message: "Unknown error when creating new user!" });
6173
}
6274
}
6375

@@ -72,30 +84,59 @@ export async function getUser(req: Request, res: Response): Promise<Response> {
7284
if (!user) {
7385
return res.status(404).json({ message: `User ${userId} not found` });
7486
} else {
75-
return res.status(200).json({ message: `Found user`, data: formatUserResponse(user) });
87+
return res
88+
.status(200)
89+
.json({ message: `Found user`, data: formatUserResponse(user) });
7690
}
7791
} catch (err) {
7892
console.error(err);
79-
return res.status(500).json({ message: "Unknown error when getting user!" });
93+
return res
94+
.status(500)
95+
.json({ message: "Unknown error when getting user!" });
8096
}
8197
}
8298

83-
export async function getAllUsers(req: Request, res: Response): Promise<Response> {
99+
export async function getAllUsers(
100+
req: Request,
101+
res: Response
102+
): Promise<Response> {
84103
try {
85104
const users = await _findAllUsers();
86105

87-
return res.status(200).json({ message: `Found users`, data: users.map(formatUserResponse) });
106+
return res
107+
.status(200)
108+
.json({ message: `Found users`, data: users.map(formatUserResponse) });
88109
} catch (err) {
89110
console.error(err);
90-
return res.status(500).json({ message: "Unknown error when getting all users!" });
111+
return res
112+
.status(500)
113+
.json({ message: "Unknown error when getting all users!" });
91114
}
92115
}
93116

94-
export async function updateUser(req: Request, res: Response): Promise<Response> {
117+
export async function updateUser(
118+
req: Request,
119+
res: Response
120+
): Promise<Response> {
95121
try {
96-
const { username, email, password, profilePictureUrl, firstName, lastName, biography } =
97-
req.body;
98-
if (username || email || password || profilePictureUrl || firstName || lastName || biography) {
122+
const {
123+
username,
124+
email,
125+
password,
126+
profilePictureUrl,
127+
firstName,
128+
lastName,
129+
biography,
130+
} = req.body;
131+
if (
132+
username ||
133+
email ||
134+
password ||
135+
profilePictureUrl ||
136+
firstName ||
137+
lastName ||
138+
biography
139+
) {
99140
const userId = req.params.id;
100141

101142
if (!isValidObjectId(userId)) {
@@ -108,7 +149,8 @@ export async function updateUser(req: Request, res: Response): Promise<Response>
108149
}
109150

110151
if (username) {
111-
const { isValid: isValidUsername, message: usernameMessage } = validateUsername(username);
152+
const { isValid: isValidUsername, message: usernameMessage } =
153+
validateUsername(username);
112154
if (!isValidUsername) {
113155
return res.status(400).json({ message: usernameMessage });
114156
}
@@ -120,7 +162,8 @@ export async function updateUser(req: Request, res: Response): Promise<Response>
120162
}
121163

122164
if (email) {
123-
const { isValid: isValidEmail, message: emailMessage } = validateEmail(email);
165+
const { isValid: isValidEmail, message: emailMessage } =
166+
validateEmail(email);
124167
if (!isValidEmail) {
125168
return res.status(400).json({ message: emailMessage });
126169
}
@@ -133,7 +176,8 @@ export async function updateUser(req: Request, res: Response): Promise<Response>
133176

134177
let hashedPassword: string | undefined;
135178
if (password) {
136-
const { isValid: isValidPassword, message: passwordMessage } = validatePassword(password);
179+
const { isValid: isValidPassword, message: passwordMessage } =
180+
validatePassword(password);
137181
if (!isValidPassword) {
138182
return res.status(400).json({ message: passwordMessage });
139183
}
@@ -143,20 +187,16 @@ export async function updateUser(req: Request, res: Response): Promise<Response>
143187
}
144188

145189
if (firstName) {
146-
const { isValid: isValidFirstName, message: firstNameMessage } = validateName(
147-
firstName,
148-
"first name"
149-
);
190+
const { isValid: isValidFirstName, message: firstNameMessage } =
191+
validateName(firstName, "first name");
150192
if (!isValidFirstName) {
151193
return res.status(400).json({ message: firstNameMessage });
152194
}
153195
}
154196

155197
if (lastName) {
156-
const { isValid: isValidLastName, message: lastNameMessage } = validateName(
157-
lastName,
158-
"last name"
159-
);
198+
const { isValid: isValidLastName, message: lastNameMessage } =
199+
validateName(lastName, "last name");
160200
if (!isValidLastName) {
161201
return res.status(400).json({ message: lastNameMessage });
162202
}
@@ -192,11 +232,16 @@ export async function updateUser(req: Request, res: Response): Promise<Response>
192232
}
193233
} catch (err) {
194234
console.error(err);
195-
return res.status(500).json({ message: "Unknown error when updating user!" });
235+
return res
236+
.status(500)
237+
.json({ message: "Unknown error when updating user!" });
196238
}
197239
}
198240

199-
export async function updateUserPrivilege(req: Request, res: Response): Promise<Response> {
241+
export async function updateUserPrivilege(
242+
req: Request,
243+
res: Response
244+
): Promise<Response> {
200245
try {
201246
const { isAdmin } = req.body;
202247

@@ -211,7 +256,10 @@ export async function updateUserPrivilege(req: Request, res: Response): Promise<
211256
return res.status(404).json({ message: `User ${userId} not found` });
212257
}
213258

214-
const updatedUser = await _updateUserPrivilegeById(userId, isAdmin === true);
259+
const updatedUser = await _updateUserPrivilegeById(
260+
userId,
261+
isAdmin === true
262+
);
215263
return res.status(200).json({
216264
message: `Updated privilege for user ${userId}`,
217265
data: formatUserResponse(updatedUser as IUser),
@@ -221,11 +269,16 @@ export async function updateUserPrivilege(req: Request, res: Response): Promise<
221269
}
222270
} catch (err) {
223271
console.error(err);
224-
return res.status(500).json({ message: "Unknown error when updating user privilege!" });
272+
return res
273+
.status(500)
274+
.json({ message: "Unknown error when updating user privilege!" });
225275
}
226276
}
227277

228-
export async function deleteUser(req: Request, res: Response): Promise<Response> {
278+
export async function deleteUser(
279+
req: Request,
280+
res: Response
281+
): Promise<Response> {
229282
try {
230283
const userId = req.params.id;
231284
if (!isValidObjectId(userId)) {
@@ -237,10 +290,14 @@ export async function deleteUser(req: Request, res: Response): Promise<Response>
237290
}
238291

239292
await _deleteUserById(userId);
240-
return res.status(200).json({ message: `Deleted user ${userId} successfully` });
293+
return res
294+
.status(200)
295+
.json({ message: `Deleted user ${userId} successfully` });
241296
} catch (err) {
242297
console.error(err);
243-
return res.status(500).json({ message: "Unknown error when deleting user!" });
298+
return res
299+
.status(500)
300+
.json({ message: "Unknown error when deleting user!" });
244301
}
245302
}
246303

backend/user-service/model/repository.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ export async function findUserById(userId: string): Promise<IUser | null> {
3737
return UserModel.findById(userId);
3838
}
3939

40-
export async function findUserByUsername(username: string): Promise<IUser | null> {
40+
export async function findUserByUsername(
41+
username: string
42+
): Promise<IUser | null> {
4143
return UserModel.findOne({ username });
4244
}
4345

0 commit comments

Comments
 (0)