Skip to content

Commit b6d31c6

Browse files
authored
Merge pull request #42 from Capstone-C2SE02-TI/user-settings
login and update db user
2 parents 82dd35e + 85cb28f commit b6d31c6

File tree

12 files changed

+769
-383
lines changed

12 files changed

+769
-383
lines changed

package-lock.json

+605-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+7-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
"type": "module",
77
"scripts": {
88
"start": "nodemon src/index.js",
9-
"update-deps": "npx npm-check-updates -u && npm install"
9+
"update-deps": "npx npm-check-updates -u && npm install",
10+
"lint": "eslint",
11+
"test": "echo \"Error: no test specified\" && exit 1"
1012
},
1113
"keywords": [
1214
"capstone-project",
@@ -16,16 +18,19 @@
1618
"license": "MIT",
1719
"homepage": "https://github.com/Capstone-C2SE02-TI/backend-node-mongodb#readme",
1820
"dependencies": {
21+
"and": "^0.0.3",
1922
"bcrypt": "^5.1.0",
23+
"build": "^0.1.4",
2024
"cookie-parser": "^1.4.6",
2125
"cors": "^2.8.5",
26+
"crypto": "^1.0.1",
2227
"dotenv": "^16.0.3",
2328
"express": "^4.18.2",
2429
"express-validator": "^6.15.0",
2530
"google-auth-library": "^8.7.0",
2631
"jsonwebtoken": "^9.0.0",
2732
"lodash": "^4.17.21",
28-
"mongoose": "^7.0.2",
33+
"mongoose": "^7.0.3",
2934
"mongoose-sequence": "^5.3.1",
3035
"morgan": "^1.10.0",
3136
"nodemailer": "^6.9.1",

src/controllers/Auth.js

+17-134
Original file line numberDiff line numberDiff line change
@@ -1,149 +1,32 @@
11
import dotenv from "dotenv";
22
dotenv.config();
33

4+
import { createNewUser } from "../services/crudDatabase/user.js";
45
import {
5-
createNewUser,
6-
checkExistedUsername,
7-
checkExistedEmail,
8-
getPasswordByUsername,
9-
getUserByUsername
10-
} from "../services/crudDatabase/user.js";
11-
import {
12-
isAuthed,
13-
generateAccessToken
14-
} from "../services/authentication/index.js";
15-
import { cryptPassword, comparePassword } from "../helpers/index.js";
16-
import { validateSignUpBody, validateSignInBody } from "../validators/user.js";
6+
cryptWalletAddress,
7+
decryptWalletAddress,
8+
encryptWalletAddress
9+
} from "../helpers/index.js";
1710

1811
const TI_AUTH_COOKIE = process.env.TI_AUTH_COOKIE;
1912

2013
function AuthController() {
2114
this.signup = async (req, res, next) => {
22-
const { username, email, phoneNumber, password } = req.body;
23-
const { status, error } = await validateSignUpBody(req, res, next);
24-
25-
if (status === "failed")
26-
return res.status(400).json({ message: error, error: error });
27-
28-
if (await checkExistedUsername(username))
29-
return res.status(400).json({
30-
message: "username-existed",
31-
error: "username-existed"
32-
});
33-
34-
if (await checkExistedEmail(email))
35-
return res
36-
.status(400)
37-
.json({ message: "email-existed", error: "email-existed" });
38-
39-
cryptPassword(password, async (error, hashPassword) => {
40-
const isCreated = await createNewUser({
41-
username,
42-
email,
43-
phoneNumber,
44-
hashPassword
45-
});
46-
47-
isCreated
48-
? res.status(200).json({
49-
message: "successfully",
50-
error: null
51-
})
52-
: res.status(400).json({
53-
message: "failed",
54-
error: error
55-
});
56-
});
57-
};
15+
const { walletAddress } = req.body;
5816

59-
this.signin = async (req, res, next) => {
60-
const { username, password } = req.body;
61-
const { status, error } = await validateSignInBody(req, res, next);
62-
63-
if (status === "failed")
64-
return res.status(400).json({
65-
message: error,
66-
error: error,
67-
user: null
68-
});
69-
70-
if (!(await checkExistedUsername(username))) {
71-
return res.status(404).json({
72-
message: "username-notfound",
73-
error: "username-notfound",
74-
user: null
75-
});
76-
} else {
77-
const hashPassword = await getPasswordByUsername(username);
78-
comparePassword(
79-
password,
80-
hashPassword,
81-
async (error, isPasswordMatch) => {
82-
if (isPasswordMatch) {
83-
const user = await getUserByUsername(username);
84-
const cookie = req.cookies[TI_AUTH_COOKIE];
85-
86-
if (!cookie) {
87-
const accessToken = await generateAccessToken({
88-
username
89-
});
90-
91-
res.cookie(TI_AUTH_COOKIE, accessToken, {
92-
// Expire in 1 week
93-
maxAge: 604800000
94-
});
95-
96-
return res.status(200).json({
97-
message: "successfully",
98-
error: null,
99-
user: {
100-
role: "user",
101-
username: user.username,
102-
userId: user.userId,
103-
email: user.email
104-
}
105-
});
106-
} else {
107-
if (await isAuthed(req)) {
108-
return res.status(200).json({
109-
message: "successfully",
110-
error: null,
111-
user: {
112-
role: "user",
113-
username: user.username,
114-
userId: user.userId,
115-
email: user.email
116-
}
117-
});
118-
} else {
119-
return res.status(401).json({
120-
message: "failed-unauthorized",
121-
error: "failed-unauthorized",
122-
user: null
123-
});
124-
}
125-
}
126-
} else {
127-
return res.status(400).json({
128-
message: "incorrect-password",
129-
error: "incorrect-password",
130-
user: null
131-
});
132-
}
133-
}
134-
);
135-
}
136-
};
17+
const hashWallet = encryptWalletAddress(walletAddress);
13718

138-
this.signout = (req, res, next) => {
139-
try {
140-
req.user = null;
141-
req.session = null;
19+
const detailCreated = await createNewUser(hashWallet.encryptedData);
14220

143-
return res.status(200).json({ message: "successfully", error: null });
144-
} catch (error) {
145-
return res.status(400).json({ message: "failed", error: error });
146-
}
21+
detailCreated.created
22+
? res.status(200).json({
23+
message: detailCreated.message,
24+
error: null
25+
})
26+
: res.status(400).json({
27+
message: detailCreated.message,
28+
error: detailCreated.error
29+
});
14730
};
14831
}
14932

src/controllers/User.js

+9-55
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
import _ from "lodash";
22
import {
3-
getUserByEmail,
4-
updateUserPassword,
5-
getPasswordByEmail,
63
followWalletOfShark,
74
unfollowWalletOfShark,
85
getListOfSharkFollowed,
@@ -16,28 +13,25 @@ import {
1613
} from "../services/crudDatabase/admin.js";
1714
import {
1815
validateUpdateProfileBody,
19-
validateChangePasswordBody
2016
} from "../validators/user.js";
21-
import { cryptPassword, comparePassword } from "../helpers/index.js";
2217

2318
function UserController() {
2419
this.getUserProfile = async (req, res, next) => {
25-
let userId = req.query.userId;
20+
let walletAddress = req.query.walletAddress;
2621

27-
if (!userId) userId = null;
22+
if (!walletAddress) walletAddress = null;
2823
else {
29-
const userIdCheck = _.toString(userId);
30-
if (_.isNaN(userIdCheck)) userId = undefined;
31-
else userId = Number(userIdCheck);
24+
const walletAddressCheck = _.toString(walletAddress);
25+
if (_.isNaN(walletAddressCheck)) walletAddress = undefined;
3226
}
3327

34-
await getUserProfile(userId)
28+
await getUserProfile(walletAddress)
3529
.then((data) =>
3630
Object.entries(data).length === 0
3731
? res.status(400).json({
38-
message: "failed-userid-invalid",
39-
error: "userid-invalid",
40-
data: {}
32+
message: "failed-wallet-address-invalid",
33+
error: "wallet-address-invalid",
34+
data: data
4135
})
4236
: res.status(200).json({
4337
message: "successfully",
@@ -91,48 +85,8 @@ function UserController() {
9185
}
9286
};
9387

94-
this.changePassword = async (req, res, next) => {
95-
const { status, error } = await validateChangePasswordBody(req, res, next);
96-
97-
if (status === "failed")
98-
return res.status(400).json({ message: error, error: error });
99-
else {
100-
const { email, oldPassword, newPassword } = req.body;
101-
const user = await getUserByEmail(email);
102-
103-
if (user) {
104-
// Check correct old password
105-
const password = await getPasswordByEmail(email);
106-
comparePassword(oldPassword, password, (error, isPasswordMatch) => {
107-
if (isPasswordMatch) {
108-
cryptPassword(newPassword, async (error, hashPassword) =>
109-
(await updateUserPassword(user.userId, hashPassword)) === true
110-
? res.status(200).json({
111-
message: "successfully",
112-
error: null
113-
})
114-
: res.status(400).json({
115-
message: "failed",
116-
error: error
117-
})
118-
);
119-
} else {
120-
return res.status(400).json({
121-
message: "incorrect-oldpassword",
122-
error: "incorrect-oldpassword"
123-
});
124-
}
125-
});
126-
} else {
127-
return res
128-
.status(400)
129-
.json({ message: "user-notfound", error: "user-notfound" });
130-
}
131-
}
132-
};
133-
13488
this.upgradePremiumAccount = async (req, res, next) => {
135-
let userId = req.body.userId;
89+
let userId = req.body.userId;
13690

13791
if (!userId) userId = null;
13892
else {

src/helpers/index.js

+42
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,53 @@
11
import _ from "lodash";
22
import bcrypt from "bcrypt";
3+
import crypto from "crypto";
4+
5+
const algorithm = "aes-256-cbc";
6+
7+
const key = crypto.randomBytes(32);
8+
9+
const iv = crypto.randomBytes(16);
310

411
export const randomConfirmationCode = () => {
512
const code = Math.floor(100000 + Math.random() * 900000);
613
return code.toString();
714
};
815

16+
export const encryptWalletAddress = (walletAddress) => {
17+
const cipher = crypto.createCipheriv(algorithm, Buffer.from(key), iv);
18+
let encrypted = cipher.update(walletAddress);
19+
encrypted = Buffer.concat([encrypted, cipher.final()]);
20+
return { iv: iv.toString("hex"), encryptedData: encrypted.toString("hex") };
21+
};
22+
23+
export const decryptWalletAddress = (encryptedData) => {
24+
const ivDecrypt = Buffer.from(iv.toString("hex"), "hex");
25+
const encryptedText = Buffer.from(encryptedData, "hex");
26+
27+
const decipher = crypto.createDecipheriv(algorithm, Buffer.from(key), ivDecrypt);
28+
29+
let decrypted = decipher.update(encryptedText);
30+
decrypted = Buffer.concat([decrypted, decipher.final()]);
31+
32+
return decrypted;
33+
};
34+
35+
export const compareWalletAddress = (plainAddress, hashAddress, callback) => {
36+
bcrypt.compare(plainAddress, hashAddress, (error, isAddressMatch) => {
37+
return error == null ? callback(null, isAddressMatch) : callback(error);
38+
});
39+
};
40+
41+
export const cryptWalletAddress = (password, callback) => {
42+
bcrypt.genSalt(10, (error, salt) => {
43+
if (error) return callback(error);
44+
45+
bcrypt.hash(password, salt, (error, hashPassword) => {
46+
return callback(error, hashPassword);
47+
});
48+
});
49+
};
50+
951
export const cryptPassword = (password, callback) => {
1052
bcrypt.genSalt(10, (error, salt) => {
1153
if (error) return callback(error);

src/models/User.js

+2-13
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,18 @@
11
import mongoose from "mongoose";
2-
import Inc from "mongoose-sequence";
3-
const AutoIncrement = Inc(mongoose);
42

53
const UserSchema = new mongoose.Schema(
64
{
75
walletAddress: {
86
type: String,
97
trim: true,
10-
default: null
8+
required: true,
9+
unique: true
1110
},
1211
fullName: {
1312
type: String,
1413
trim: true,
1514
default: ""
1615
},
17-
confirmationCode: {
18-
type: String,
19-
trim: true,
20-
default: ""
21-
},
22-
isCodeConfirmed: {
23-
type: Boolean,
24-
default: false
25-
},
2616
avatar: {
2717
type: String,
2818
trim: true,
@@ -50,7 +40,6 @@ const UserSchema = new mongoose.Schema(
5040
{ timestamps: true, versionKey: false }
5141
);
5242

53-
UserSchema.plugin(AutoIncrement, { inc_field: "userId" });
5443

5544
const UserModel = mongoose.model("User", UserSchema);
5645
export default UserModel;

src/routes/auth.js

-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,5 @@ const router = express.Router();
33
import AuthController from "../controllers/Auth.js";
44

55
router.post("/signup", AuthController.signup);
6-
router.post("/signin", AuthController.signin);
7-
router.post("/signout", AuthController.signout);
86

97
export default router;

0 commit comments

Comments
 (0)