From be88a7ff28587083cb863cd4382c39701870df7a Mon Sep 17 00:00:00 2001 From: Netcup Gituser Date: Mon, 4 Dec 2023 22:50:25 +0100 Subject: [PATCH] login and sign up --- index.ts | 4 +- src/controllers/userController.ts | 85 ++++++++++++++--- src/models/session.ts | 10 ++ src/routes/routes.ts | 152 +++++++++++++++++++++--------- 4 files changed, 194 insertions(+), 57 deletions(-) create mode 100644 src/models/session.ts diff --git a/index.ts b/index.ts index 996e41d..fcd7663 100644 --- a/index.ts +++ b/index.ts @@ -30,12 +30,12 @@ const options = { servers: [ { - url: "http://localhost:3000", + url: "http://localhost:3000/api/v1", //description: "PartyApp API Documentation", }, ], }, - apis: ["./src/routes/api/v1/router/*.ts"], + apis: ["./src/routes/*.ts"], }; app.use(bodyParser.json()); diff --git a/src/controllers/userController.ts b/src/controllers/userController.ts index 9eca88a..181c88d 100644 --- a/src/controllers/userController.ts +++ b/src/controllers/userController.ts @@ -1,33 +1,92 @@ -import { Request } from "express"; +import { Request, Response } from "express"; import bcrypt from "bcrypt"; import { User } from "../models/user"; +import crypto from "crypto"; +import { Session } from "../models/session"; -export async function SignUp(req: Request, res: any) { +export async function SignUp(req: Request, res: Response) { if (!req.body.accountName || !req.body.username || !req.body.password) { - res.status(400).json({ error: "invalid body" }); - return; + return res.status(400).json({ status: "err" }); } - const decodedPassword = Buffer.from(req.body.password, "base64").toString( - "utf-8" - ); + const { accountName, username, password } = req.body; + + const existingUser = await User.findOne({ accountName }); + + if (existingUser) { + return res.status(400).json({ status: "err" }); + } + + const isBase64Password = + /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$/.test( + password + ); + + if (!isBase64Password) { + return res.status(400).json({ status: "err" }); + } + + const decodedPassword = Buffer.from(password, "base64").toString("utf-8"); const hashedPassword = await bcrypt.hash(decodedPassword, 10); const user = new User({ - accountName: req.body.accountName, - username: req.body.username, + accountName: accountName, + username: username, password: hashedPassword, }); user .save() - .then(() => { - console.log("test"); - res.status(200).json({ status: "ok" }); - }) + .then(() => res.status(200).json({ status: "ok" })) .catch((err) => { console.log(err); res.status(500).json({ status: "err" }); }); } + +export async function Login(req: Request, res: Response) { + try { + if (!req.body.accountName || !req.body.password) { + return res.status(400).json({ status: "err" }); + } + + const { accountName, password } = req.body; + + const user = await User.findOne({ accountName }); + + if (!user) { + return res.status(401).json({ status: "err" }); + } + + if (user.password === undefined || user.password === null) { + return res.status(401).json({ status: "err" }); + } + + const decodedPassword = Buffer.from(password, "base64").toString("utf-8"); + + const isPasswordValid = await bcrypt.compare( + decodedPassword, + user.password + ); + + if (!isPasswordValid) { + return res.status(401).json({ status: "err" }); + } + + const sessionId = crypto.randomBytes(32).toString("hex"); + + const session = new Session({ + sessionId: sessionId, + accountName: user.accountName, + }); + + session + .save() + .then(() => res.status(200).json({ sessionId })) + .catch(() => res.status(500).json({ status: "err" })); + } catch (error) { + console.error("error on login:", error); + res.status(500).json({ status: "err" }); + } +} diff --git a/src/models/session.ts b/src/models/session.ts new file mode 100644 index 0000000..72ec7cc --- /dev/null +++ b/src/models/session.ts @@ -0,0 +1,10 @@ +import mongoose, { InferSchemaType, Schema } from "mongoose"; + +export const sessionSchema = new Schema({ + sessionId: String, + accountName: String, +}); + +export type Session = InferSchemaType; + +export const Session = mongoose.model("Session", sessionSchema); diff --git a/src/routes/routes.ts b/src/routes/routes.ts index a4197d9..a6fe10d 100644 --- a/src/routes/routes.ts +++ b/src/routes/routes.ts @@ -4,58 +4,126 @@ import * as userController from "../controllers/userController"; /** * @swagger - * components: - * schemas: - * Post: - * type: object - * required: - * - userId - * - title - * - body - * properties: - * id: - * type: integer - * description: The Auto-generated id of a post - * userId: - * type: integer - * description: id of author - * title: - * type: string - * description: title of post - * body: - * type: string - * descripton: content of post * - * example: - * id: 1 - * userId: 1 - * title: my title - * body: my article - * + * tags: + * name: users + * description: User-related operations */ /** * @swagger - * tags: - * name: Posts - * description: posts of users - */ - -/** - * @swagger - * /posts: - * get: - * summary: Returns all posts - * tags: [Posts] + * /signup: + * post: + * summary: Sign up a new user + * description: Create a new user account with accountName, username, and password + * tags: + * - users + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * accountName: + * type: string + * username: + * type: string + * password: + * type: string * responses: * 200: - * description: the list of the posts + * description: Successful user registration * content: * application/json: * schema: - * type: array - * items: - * $ref: '#/components/schemas/Post' + * type: object + * properties: + * status: + * type: string + * example: 'ok' + * 400: + * description: Invalid request body or account already exists + * content: + * application/json: + * schema: + * type: object + * properties: + * status: + * type: string + * example: 'err' + * 500: + * description: Internal server error + * content: + * application/json: + * schema: + * type: object + * properties: + * status: + * type: string + * example: 'err' */ router.post("/user/signup", userController.SignUp); +/** + * @swagger + * /user/login: + * post: + * summary: Log in a user + * description: Log in a user by checking accountName and password + * tags: + * - users + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * accountName: + * type: string + * password: + * type: string + * responses: + * 200: + * description: Successful login + * content: + * application/json: + * schema: + * type: object + * properties: + * sessionId: + * type: string + * 400: + * description: Invalid request body + * content: + * application/json: + * schema: + * type: object + * properties: + * status: + * type: string + * example: 'err' + * 401: + * description: Authentication failed + * content: + * application/json: + * schema: + * type: object + * properties: + * status: + * type: string + * example: 'err' + * 500: + * description: Internal server error + * content: + * application/json: + * schema: + * type: object + * properties: + * status: + * type: string + * example: 'err' + */ +router.post("/user/login", userController.Login); + export default router;