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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 393 - (hide annotations)
Mon Jul 29 17:29:59 2024 UTC (8 months, 3 weeks 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 rakin 393 /**
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 rakin 326 import { Request } from "express";
21 rakin 348 import User from "../../models/User";
22 rakin 326 import Controller from "../Controller";
23 rakin 349 import { body } from 'express-validator';
24 rakin 348 import bcrypt from 'bcrypt';
25     import jwt from 'jsonwebtoken';
26     import KeyValuePair from "../../types/KeyValuePair";
27     import Response from "../Response";
28 rakin 349 import ValidatorError from "../middleware/ValidatorError";
29     import RequireAuth from "../middleware/RequireAuth";
30 rakin 326
31     export default class UserController extends Controller {
32 rakin 348 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 rakin 349 ],
47     login: [
48     body(["username", "password"]).isLength({ min: 2 }),
49     ],
50     delete: [
51     RequireAuth,
52     body(["username", "password"]).isLength({ min: 2 }),
53 rakin 348 ]
54     };
55 rakin 326 }
56 rakin 348
57 rakin 349 globalMiddleware(): Function[] {
58     return [ValidatorError];
59     }
60    
61 rakin 348 public async index() {
62 rakin 349 return new Response(403);
63     return await User.find().select(["_id", "username", "createdAt"]).limit(30);
64 rakin 348 }
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 rakin 349 user.tokenUpdatedAt = new Date();
75 rakin 348
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 rakin 349
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 rakin 379 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 rakin 349 };
180     }
181 rakin 326 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26