forked from Mintplex-Labs/anything-llm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathuser.js
157 lines (140 loc) · 4.51 KB
/
user.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
149
150
151
152
153
154
155
156
157
const prisma = require("../utils/prisma");
const { EventLogs } = require("./eventLogs");
const User = {
create: async function ({ username, password, role = "default" }) {
const passwordCheck = this.checkPasswordComplexity(password);
if (!passwordCheck.checkedOK) {
return { user: null, error: passwordCheck.error };
}
try {
const bcrypt = require("bcrypt");
const hashedPassword = bcrypt.hashSync(password, 10);
const user = await prisma.users.create({
data: {
username,
password: hashedPassword,
role,
},
});
return { user, error: null };
} catch (error) {
console.error("FAILED TO CREATE USER.", error.message);
return { user: null, error: error.message };
}
},
// Log the changes to a user object, but omit sensitive fields
// that are not meant to be logged.
loggedChanges: function (updates, prev = {}) {
const changes = {};
const sensitiveFields = ["password"];
Object.keys(updates).forEach((key) => {
if (!sensitiveFields.includes(key) && updates[key] !== prev[key]) {
changes[key] = `${prev[key]} => ${updates[key]}`;
}
});
return changes;
},
update: async function (userId, updates = {}) {
try {
const currentUser = await prisma.users.findUnique({
where: { id: parseInt(userId) },
});
if (!currentUser) {
return { success: false, error: "User not found" };
}
if (updates.hasOwnProperty("password")) {
const passwordCheck = this.checkPasswordComplexity(updates.password);
if (!passwordCheck.checkedOK) {
return { success: false, error: passwordCheck.error };
}
const bcrypt = require("bcrypt");
updates.password = bcrypt.hashSync(updates.password, 10);
}
const user = await prisma.users.update({
where: { id: parseInt(userId) },
data: updates,
});
await EventLogs.logEvent(
"user_updated",
{
username: user.username,
changes: this.loggedChanges(updates, currentUser),
},
userId
);
return { success: true, error: null };
} catch (error) {
console.error(error.message);
return { success: false, error: error.message };
}
},
get: async function (clause = {}) {
try {
const user = await prisma.users.findFirst({ where: clause });
return user ? { ...user } : null;
} catch (error) {
console.error(error.message);
return null;
}
},
count: async function (clause = {}) {
try {
const count = await prisma.users.count({ where: clause });
return count;
} catch (error) {
console.error(error.message);
return 0;
}
},
delete: async function (clause = {}) {
try {
await prisma.users.deleteMany({ where: clause });
return true;
} catch (error) {
console.error(error.message);
return false;
}
},
where: async function (clause = {}, limit = null) {
try {
const users = await prisma.users.findMany({
where: clause,
...(limit !== null ? { take: limit } : {}),
});
return users;
} catch (error) {
console.error(error.message);
return [];
}
},
checkPasswordComplexity: function (passwordInput = "") {
const passwordComplexity = require("joi-password-complexity");
// Can be set via ENV variable on boot. No frontend config at this time.
// Docs: https://www.npmjs.com/package/joi-password-complexity
const complexityOptions = {
min: process.env.PASSWORDMINCHAR || 8,
max: process.env.PASSWORDMAXCHAR || 250,
lowerCase: process.env.PASSWORDLOWERCASE || 0,
upperCase: process.env.PASSWORDUPPERCASE || 0,
numeric: process.env.PASSWORDNUMERIC || 0,
symbol: process.env.PASSWORDSYMBOL || 0,
// reqCount should be equal to how many conditions you are testing for (1-4)
requirementCount: process.env.PASSWORDREQUIREMENTS || 0,
};
const complexityCheck = passwordComplexity(
complexityOptions,
"password"
).validate(passwordInput);
if (complexityCheck.hasOwnProperty("error")) {
let myError = "";
let prepend = "";
for (let i = 0; i < complexityCheck.error.details.length; i++) {
myError += prepend + complexityCheck.error.details[i].message;
prepend = ", ";
}
return { checkedOK: false, error: myError };
}
return { checkedOK: true, error: "No error." };
},
};
module.exports = { User };