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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 326 by rakin, Mon Jul 29 17:29:33 2024 UTC revision 393 by rakin, Mon Jul 29 17:29:59 2024 UTC
# Line 1  Line 1 
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";  import { Request } from "express";
21    import User from "../../models/User";
22  import Controller from "../Controller";  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 {  export default class UserController extends Controller {
32      public async index(request: Request) {      middleware(): KeyValuePair<Function[]> {
33          return { message: "Server is up." };          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  }  }

Legend:
Removed from v.326  
changed lines
  Added in v.393

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26