generated from csc301-2023-fall/deliverable-documents
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathaccountService.js
148 lines (136 loc) · 5.08 KB
/
accountService.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/**
* This module implements the use case operations for the account service.
*
* @module api/service/accountService
*
* @requires api/db/psqlDbPlugin
* @requires crypto
* @requires bcrypt
* @requires api/entities/ServiceErrors
* @requires config
* @requires jsonwebtoken
*/
const db = require('../db/accountDbPlugin');
const activityDB = require('../db/activityDbPlugin');
const counselorDB = require('../db/counselorDbPlugin');
const roomDB = require('../db/roomDbPlugin');
const scheduleDB = require('../db/scheduleDbPlugin');
const studentDB = require('../db/studentDbPlugin');
const groupDB = require('../db/groupDbPlugin');
const blockDB = require('../db/blockDbPlugin');
const bcrypt = require('bcrypt');
const {AccountServiceError, STATUS_CODES} = require('../entities/ServiceErrors');
const config = require('config');
const jwt = require('jsonwebtoken');
const saveJson = require('../utils/jsonToFile.js');
const AdminUser = require('../entities/AdminUser');
/**
* Authorisation token config.
* @const {string} [AUTH_TOKEN_SECRET] Secret for JWT signatures.
* @const {number} [AUTH_TOKEN_EXPIRATION] Number of days until JWT expires.
* @const {number} [AUTH_HASHING_SALT_ROUNDS] Number of salt rounds for password hashing.
*/
const AUTH_TOKEN_SECRET = process.env.AUTH_SECRET || config.get('auth.SECRET');
const AUTH_TOKEN_EXPIRATION = process.env.AUTH_EXPIRATION || config.get('auth.EXPIRATION');
const AUTH_HASHING_SALT_ROUNDS = process.env.SALT_ROUNDS || config.get('auth.SALT_ROUNDS');
/**
* Generates token for admin user session if login credentials are valid.
*
* @param {string} username Username for logging on user
* @param {string} password Plaintext password for loggin on user
* @returns {token} JWT for login session if credentials are valid
*/
async function login(username, password) {
if (!(await db.checkLogin(username, password))) {
throw new AccountServiceError(
"Invalid login credentials",
STATUS_CODES.UNAUTHORISED
);
} else {
const curr_user = await db.getAdminUserByName(username);
const token = jwt.sign({user_id: curr_user.user_id}, AUTH_TOKEN_SECRET, {
expiresIn: AUTH_TOKEN_EXPIRATION
});
return token;
}
}
/**
* Registers a new admin user with the provided credentials and logs
* them in.
*
* @param {string} username Username for logging on user
* @param {string} password Plaintext password for loggin on user
* @returns {token} JWT for login session for newly-registered user
*/
async function signup(username, password) {
if (await db.existsUser(username)) {
throw new AccountServiceError(
`User already exists for username '${username}'`,
STATUS_CODES.CONFLICT
);
}
else {
const password_hash = await bcrypt.hash(password, AUTH_HASHING_SALT_ROUNDS);
if(!(await db.createAdminUser(username, password_hash))) {
throw new AccountServiceError(
`Failed to create new admin user resource in DB for '${username}'`,
STATUS_CODES.FAILED
);
}
return login(username, password);
}
}
/**
* Returns whether the user is logged in or not.
*
* @param {token} token JWT for user session (may be null).
* @returns {boolean} Whether user is logged in or not
*/
async function getLoginStatus(token) {
if (token == null) {
return false;
} else {
try {
const decoded = jwt.verify(token, AUTH_TOKEN_SECRET);
return true;
} catch(err) {
// Error indicates token is invalid
return false;
}
}
}
/**
* Delete all non campus/camp/account entities in the database.
*
* @returns {boolean} - Whether operation succeeded
*/
async function clearDatabase() {
try {
var status = await blockDB.deleteAllBlocks();
status = await activityDB.deleteAllActivities() && status;
status = await counselorDB.deleteAllCounselors() && status;
status = await roomDB.deleteAllRooms() && status;
status = await scheduleDB.deleteAllSchedules() && status;
status = await studentDB.deleteAllStudents() && status;
status = await groupDB.deleteAllGroups() && status;
saveJson.saveJsonToFile("[[]]", './api/res/private/saved_scheduled.json');
status = await activityDB.resetActivityIds() && status;
status = await counselorDB.resetCounselorIds() && status;
status = await roomDB.resetRoomIds() && status;
status = await scheduleDB.resetScheduleIds() && status;
status = await studentDB.resetStudentIds() && status;
status = await groupDB.resetGroupIds() && status;
return await blockDB.resetBlockIds() && status;
} catch(err) {
throw new AccountServiceError(
`DB Operation Failure: ${err}`,
STATUS_CODES.FAILED
);
}
}
module.exports = {
login,
signup,
getLoginStatus,
clearDatabase
}