/[sudobot]/trunk/src/api/controllers/UserController.ts
ViewVC logotype

Contents of /trunk/src/api/controllers/UserController.ts

Parent Directory Parent Directory | Revision Log Revision Log


Revision 393 - (show annotations)
Mon Jul 29 17:29:59 2024 UTC (8 months, 1 week ago) by rakin
File MIME type: application/typescript
File size: 5482 byte(s)
style: add license comments (#77)

* style: add license commits

* fix: shebang errors
1 /**
2 * This file is part of SudoBot.
3 *
4 * Copyright (C) 2021-2022 OSN Inc.
5 *
6 * SudoBot is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * SudoBot is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with SudoBot. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 import { Request } from "express";
21 import User from "../../models/User";
22 import Controller from "../Controller";
23 import { body } from 'express-validator';
24 import bcrypt from 'bcrypt';
25 import jwt from 'jsonwebtoken';
26 import KeyValuePair from "../../types/KeyValuePair";
27 import Response from "../Response";
28 import ValidatorError from "../middleware/ValidatorError";
29 import RequireAuth from "../middleware/RequireAuth";
30
31 export default class UserController extends Controller {
32 middleware(): KeyValuePair<Function[]> {
33 return {
34 create: [
35 body(["password"]).isLength({ min: 2 }),
36 body(["username"]).custom(async username => {
37 const user = await User.findOne({ username });
38
39 if (user) {
40 return Promise.reject("Username is already in use");
41 }
42
43 return username;
44 }),
45 body(["discord_id"]).custom(value => /\d+/g.test(value) ? value : Promise.reject("Invalid Snowflake Given"))
46 ],
47 login: [
48 body(["username", "password"]).isLength({ min: 2 }),
49 ],
50 delete: [
51 RequireAuth,
52 body(["username", "password"]).isLength({ min: 2 }),
53 ]
54 };
55 }
56
57 globalMiddleware(): Function[] {
58 return [ValidatorError];
59 }
60
61 public async index() {
62 return new Response(403);
63 return await User.find().select(["_id", "username", "createdAt"]).limit(30);
64 }
65
66 public async create(request: Request) {
67 return new Response(403);
68
69 const user = new User();
70
71 user.username = request.body.username;
72 user.discord_id = request.body.discord_id;
73 user.createdAt = new Date();
74 user.tokenUpdatedAt = new Date();
75
76 try {
77 await user.save();
78 }
79 catch (e) {
80 return { error: "DB validation error", error_type: 'db_validation' };
81 }
82
83 const salt = await bcrypt.genSalt();
84 user.password = await bcrypt.hash(request.body.password, salt);
85
86 const token = await jwt.sign({
87 username: user.username,
88 discord_id: user.discord_id,
89 _id: user.id
90 }, process.env.JWT_SECRET!, {
91 expiresIn: "2 days",
92 issuer: "SudoBot API",
93 });
94
95 user.token = token;
96
97 try {
98 await user.save();
99 }
100 catch (e) {
101 return { error: "Token signing error", error_type: 'token_signing' };
102 }
103
104 user.password = undefined;
105 return user;
106 }
107
108 public async delete(request: Request) {
109 const { username, password } = request.body;
110 const user = await User.findOne({ username });
111
112 if (!user) {
113 return { error: "Username is incorrect." };
114 }
115
116 if (!(await bcrypt.compare(password, user.password!))) {
117 return { error: "Password is incorrect." };
118 }
119
120 await user.delete();
121
122 user.password = undefined;
123 user.token = undefined;
124 user.tokenUpdatedAt = undefined;
125
126 return {
127 message: "Account deletion successful",
128 user
129 };
130 }
131
132 public async login(request: Request) {
133 const { username, password } = request.body;
134 const user = await User.findOne({ username });
135
136 if (!user) {
137 return { error: "Username is incorrect." };
138 }
139
140 if (!(await bcrypt.compare(password, user.password!))) {
141 return { error: "Password is incorrect." };
142 }
143
144 let { token } = user;
145
146 try {
147 if (!token) {
148 throw new Error("Token is not set");
149 }
150
151 if (!jwt.verify(token, process.env.JWT_SECRET!)) {
152 throw new Error("Token is not valid");
153 }
154 }
155 catch (e) {
156 console.log(e);
157
158 const newToken = await jwt.sign({
159 username: user.username,
160 discord_id: user.discord_id,
161 _id: user.id
162 }, process.env.JWT_SECRET!, {
163 expiresIn: "2 days",
164 issuer: "SudoBot API",
165 });
166
167 token = newToken;
168 user.tokenUpdatedAt = new Date();
169 user.token = newToken;
170 await user.save();
171 }
172
173 return {
174 message: "Login successful",
175 username,
176 token,
177 expires: new Date(user.tokenUpdatedAt!.getTime() + (2 * 24 * 60 * 60 * 1000)),
178 guilds: this.client.guilds.cache.filter(g => user.guilds.includes(g.id) ?? false)
179 };
180 }
181 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26