Skip to content

Commit 57b92e0

Browse files
committed
Merge branch 'development' into feat/questions
2 parents ed60d0b + afa9755 commit 57b92e0

File tree

47 files changed

+2421
-337
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2421
-337
lines changed

backend/question-service/src/models/Question.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,6 @@ const questionSchema: Schema<IQuestion> = new mongoose.Schema(
2020
},
2121
category: {
2222
type: [String],
23-
enum: [
24-
"Strings",
25-
"Algorithms",
26-
"Data Structures",
27-
"Bit Manipulation",
28-
"Recursion",
29-
"Databases",
30-
"Arrays",
31-
"Brainteaser",
32-
],
3323
required: true,
3424
},
3525
},

backend/user-service/.env.sample

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ PORT=3001
55
JWT_SECRET=you-can-replace-this-with-your-own-secret
66

77
# admin default credentials
8+
ADMIN_FIRST_NAME=Admin
9+
ADMIN_LAST_NAME=User
810
ADMIN_USERNAME=administrator
911
ADMIN_EMAIL=[email protected]
1012
ADMIN_PASSWORD=Admin@123

backend/user-service/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,12 @@
4848

4949
- Body
5050

51-
- Required: `username` (string), `email` (string), `password` (string)
51+
- Required: `firstName` (string), `lastName` (string), `username` (string), `email` (string), `password` (string)
5252

5353
```json
5454
{
55+
"firstName": "SampleFirstName",
56+
"lastName": "SampleLastName",
5557
"username": "SampleUserName",
5658
"email": "[email protected]",
5759
"password": "SecurePassword"

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

Lines changed: 39 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,27 @@ export async function createUser(
2626
res: Response
2727
): Promise<Response> {
2828
try {
29-
const { username, email, password } = req.body;
29+
const { firstName, lastName, username, email, password } = req.body;
3030
const existingUser = await _findUserByUsernameOrEmail(username, email);
3131
if (existingUser) {
3232
return res
3333
.status(409)
34-
.json({ message: "username or email already exists" });
34+
.json({ message: "Username or email already exists" });
3535
}
3636

37-
if (username && email && password) {
37+
if (firstName && lastName && username && email && password) {
38+
const { isValid: isValidFirstName, message: firstNameMessage } =
39+
validateName(firstName, "first name");
40+
if (!isValidFirstName) {
41+
return res.status(400).json({ message: firstNameMessage });
42+
}
43+
44+
const { isValid: isValidLastName, message: lastNameMessage } =
45+
validateName(lastName, "last name");
46+
if (!isValidLastName) {
47+
return res.status(400).json({ message: lastNameMessage });
48+
}
49+
3850
const { isValid: isValidUsername, message: usernameMessage } =
3951
validateUsername(username);
4052
if (!isValidUsername) {
@@ -55,15 +67,23 @@ export async function createUser(
5567

5668
const salt = bcrypt.genSaltSync(10);
5769
const hashedPassword = bcrypt.hashSync(password, salt);
58-
const createdUser = await _createUser(username, email, hashedPassword);
70+
71+
const createdUser = await _createUser(
72+
firstName,
73+
lastName,
74+
username,
75+
email,
76+
hashedPassword,
77+
);
5978
return res.status(201).json({
6079
message: `Created new user ${username} successfully`,
6180
data: formatUserResponse(createdUser),
6281
});
6382
} else {
64-
return res
65-
.status(400)
66-
.json({ message: "username and/or email and/or password are missing" });
83+
return res.status(400).json({
84+
message:
85+
"At least one of first name, last name, username, email and password are missing",
86+
});
6787
}
6888
} catch (err) {
6989
console.error(err);
@@ -120,18 +140,15 @@ export async function updateUser(
120140
): Promise<Response> {
121141
try {
122142
const {
123-
username,
124-
email,
125-
password,
143+
oldPassword,
144+
newPassword,
126145
profilePictureUrl,
127146
firstName,
128147
lastName,
129148
biography,
130149
} = req.body;
131150
if (
132-
username ||
133-
email ||
134-
password ||
151+
(oldPassword && newPassword) ||
135152
profilePictureUrl ||
136153
firstName ||
137154
lastName ||
@@ -148,42 +165,23 @@ export async function updateUser(
148165
return res.status(404).json({ message: `User ${userId} not found` });
149166
}
150167

151-
if (username) {
152-
const { isValid: isValidUsername, message: usernameMessage } =
153-
validateUsername(username);
154-
if (!isValidUsername) {
155-
return res.status(400).json({ message: usernameMessage });
156-
}
157-
158-
const existingUser = await _findUserByUsername(username);
159-
if (existingUser && existingUser.id !== userId) {
160-
return res.status(409).json({ message: "username already exists" });
161-
}
162-
}
163-
164-
if (email) {
165-
const { isValid: isValidEmail, message: emailMessage } =
166-
validateEmail(email);
167-
if (!isValidEmail) {
168-
return res.status(400).json({ message: emailMessage });
169-
}
170-
171-
const existingUser = await _findUserByEmail(email);
172-
if (existingUser && existingUser.id !== userId) {
173-
return res.status(409).json({ message: "email already exists" });
168+
let hashedPassword: string | undefined;
169+
if (oldPassword && newPassword) {
170+
const match = await bcrypt.compare(oldPassword, user.password);
171+
if (!match) {
172+
return res
173+
.status(403)
174+
.json({ message: "Wrong current password given" });
174175
}
175-
}
176176

177-
let hashedPassword: string | undefined;
178-
if (password) {
179177
const { isValid: isValidPassword, message: passwordMessage } =
180-
validatePassword(password);
178+
validatePassword(newPassword);
181179
if (!isValidPassword) {
182180
return res.status(400).json({ message: passwordMessage });
183181
}
184182

185183
const salt = bcrypt.genSaltSync(10);
186-
hashedPassword = bcrypt.hashSync(password, salt);
184+
hashedPassword = bcrypt.hashSync(newPassword, salt);
187185
}
188186

189187
if (firstName) {
@@ -212,8 +210,6 @@ export async function updateUser(
212210

213211
const updatedUser = await _updateUserById(
214212
userId,
215-
username,
216-
email,
217213
hashedPassword,
218214
profilePictureUrl,
219215
firstName,

backend/user-service/model/repository.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import UserModel, { IUser } from "./user-model";
22
import "dotenv/config";
33
import { connect } from "mongoose";
4-
import { faker } from "@faker-js/faker";
54

65
export async function connectToDB() {
76
const mongoDBUri: string | undefined = process.env.DB_CLOUD_URI;
@@ -14,17 +13,19 @@ export async function connectToDB() {
1413
}
1514

1615
export async function createUser(
16+
firstName: string,
17+
lastName: string,
1718
username: string,
1819
email: string,
1920
password: string,
2021
isAdmin: boolean = false
2122
): Promise<IUser> {
2223
return new UserModel({
24+
firstName,
25+
lastName,
2326
username,
2427
email,
2528
password,
26-
firstName: faker.person.firstName(),
27-
lastName: faker.person.lastName(),
2829
isAdmin,
2930
}).save();
3031
}
@@ -58,8 +59,6 @@ export async function findAllUsers(): Promise<IUser[]> {
5859

5960
export async function updateUserById(
6061
userId: string,
61-
username: string,
62-
email: string,
6362
password: string | undefined,
6463
profilePictureUrl: string,
6564
firstName: string,
@@ -70,8 +69,6 @@ export async function updateUserById(
7069
userId,
7170
{
7271
$set: {
73-
username,
74-
email,
7572
password,
7673
profilePictureUrl,
7774
firstName,

backend/user-service/model/user-model.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ export interface IUser extends Document {
88
isAdmin: boolean;
99

1010
profilePictureUrl?: string;
11-
firstName?: string;
12-
lastName?: string;
11+
firstName: string;
12+
lastName: string;
1313
biography?: string;
1414
}
1515

@@ -43,11 +43,11 @@ const UserModelSchema: Schema<IUser> = new mongoose.Schema({
4343
},
4444
firstName: {
4545
type: String,
46-
required: false,
46+
required: true,
4747
},
4848
lastName: {
4949
type: String,
50-
required: false,
50+
required: true,
5151
},
5252
biography: {
5353
type: String,

backend/user-service/scripts/seed.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,21 @@ import { connectToDB, createUser, findUserByEmail } from "../model/repository";
44
export async function seedAdminAccount() {
55
await connectToDB();
66

7+
const adminFirstName = process.env.ADMIN_FIRST_NAME || "Admin";
8+
const adminLastName = process.env.ADMIN_LAST_NAME || "User";
79
const adminUsername = process.env.ADMIN_USERNAME || "administrator";
810
const adminEmail = process.env.ADMIN_EMAIL || "[email protected]";
911
const adminPassword = process.env.ADMIN_PASSWORD || "Admin@123";
1012

1113
if (
14+
!process.env.ADMIN_FIRST_NAME ||
15+
!process.env.ADMIN_LAST_NAME ||
1216
!process.env.ADMIN_USERNAME ||
1317
!process.env.ADMIN_EMAIL ||
1418
!process.env.ADMIN_PASSWORD
1519
) {
1620
console.error(
17-
"Admin account not seeded in .env. Using default admin account credentials (username: administrator, email: [email protected], password: Admin@123)"
21+
"Admin account not seeded in .env. Using default admin account credentials (first name: Admin, last name: User, username: administrator, email: [email protected], password: Admin@123)"
1822
);
1923
}
2024

@@ -28,7 +32,7 @@ export async function seedAdminAccount() {
2832
const salt = bcrypt.genSaltSync(10);
2933
const hashedPassword = bcrypt.hashSync(adminPassword, salt);
3034

31-
await createUser(adminUsername, adminEmail, hashedPassword, true);
35+
await createUser(adminFirstName, adminLastName, adminUsername, adminEmail, hashedPassword, true);
3236

3337
console.log("Admin account created successfully.");
3438
process.exit(0);

0 commit comments

Comments
 (0)