/[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 349 - (hide annotations)
Mon Jul 29 17:29:43 2024 UTC (8 months, 2 weeks ago) by rakin
File MIME type: application/typescript
File size: 4663 byte(s)
feat(api): auth middleware
1 rakin 326 import { Request } from "express";
2 rakin 348 import User from "../../models/User";
3 rakin 326 import Controller from "../Controller";
4 rakin 349 import { body } from 'express-validator';
5 rakin 348 import bcrypt from 'bcrypt';
6     import jwt from 'jsonwebtoken';
7     import KeyValuePair from "../../types/KeyValuePair";
8     import Response from "../Response";
9 rakin 349 import ValidatorError from "../middleware/ValidatorError";
10     import RequireAuth from "../middleware/RequireAuth";
11 rakin 326
12     export default class UserController extends Controller {
13 rakin 348 middleware(): KeyValuePair<Function[]> {
14     return {
15     create: [
16     body(["password"]).isLength({ min: 2 }),
17     body(["username"]).custom(async username => {
18     const user = await User.findOne({ username });
19    
20     if (user) {
21     return Promise.reject("Username is already in use");
22     }
23    
24     return username;
25     }),
26     body(["discord_id"]).custom(value => /\d+/g.test(value) ? value : Promise.reject("Invalid Snowflake Given"))
27 rakin 349 ],
28     login: [
29     body(["username", "password"]).isLength({ min: 2 }),
30     ],
31     delete: [
32     RequireAuth,
33     body(["username", "password"]).isLength({ min: 2 }),
34 rakin 348 ]
35     };
36 rakin 326 }
37 rakin 348
38 rakin 349 globalMiddleware(): Function[] {
39     return [ValidatorError];
40     }
41    
42 rakin 348 public async index() {
43 rakin 349 return new Response(403);
44     return await User.find().select(["_id", "username", "createdAt"]).limit(30);
45 rakin 348 }
46    
47     public async create(request: Request) {
48     return new Response(403);
49    
50     const user = new User();
51    
52     user.username = request.body.username;
53     user.discord_id = request.body.discord_id;
54     user.createdAt = new Date();
55 rakin 349 user.tokenUpdatedAt = new Date();
56 rakin 348
57     try {
58     await user.save();
59     }
60     catch (e) {
61     return { error: "DB validation error", error_type: 'db_validation' };
62     }
63    
64     const salt = await bcrypt.genSalt();
65     user.password = await bcrypt.hash(request.body.password, salt);
66    
67     const token = await jwt.sign({
68     username: user.username,
69     discord_id: user.discord_id,
70     _id: user.id
71     }, process.env.JWT_SECRET!, {
72     expiresIn: "2 days",
73     issuer: "SudoBot API",
74     });
75    
76     user.token = token;
77    
78     try {
79     await user.save();
80     }
81     catch (e) {
82     return { error: "Token signing error", error_type: 'token_signing' };
83     }
84    
85     user.password = undefined;
86     return user;
87     }
88 rakin 349
89     public async delete(request: Request) {
90     const { username, password } = request.body;
91     const user = await User.findOne({ username });
92    
93     if (!user) {
94     return { error: "Username is incorrect." };
95     }
96    
97     if (!(await bcrypt.compare(password, user.password!))) {
98     return { error: "Password is incorrect." };
99     }
100    
101     await user.delete();
102    
103     user.password = undefined;
104     user.token = undefined;
105     user.tokenUpdatedAt = undefined;
106    
107     return {
108     message: "Account deletion successful",
109     user
110     };
111     }
112    
113     public async login(request: Request) {
114     const { username, password } = request.body;
115     const user = await User.findOne({ username });
116    
117     if (!user) {
118     return { error: "Username is incorrect." };
119     }
120    
121     if (!(await bcrypt.compare(password, user.password!))) {
122     return { error: "Password is incorrect." };
123     }
124    
125     let { token } = user;
126    
127     try {
128     if (!token) {
129     throw new Error("Token is not set");
130     }
131    
132     if (!jwt.verify(token, process.env.JWT_SECRET!)) {
133     throw new Error("Token is not valid");
134     }
135     }
136     catch (e) {
137     console.log(e);
138    
139     const newToken = await jwt.sign({
140     username: user.username,
141     discord_id: user.discord_id,
142     _id: user.id
143     }, process.env.JWT_SECRET!, {
144     expiresIn: "2 days",
145     issuer: "SudoBot API",
146     });
147    
148     token = newToken;
149     user.tokenUpdatedAt = new Date();
150     user.token = newToken;
151     await user.save();
152     }
153    
154     return {
155     message: "Login successful",
156     username,
157     token,
158     expires: new Date(user.tokenUpdatedAt!.getTime() + (2 * 24 * 60 * 60 * 1000))
159     };
160     }
161 rakin 326 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26