From 9471930e4ee8137ba28cb530fb168d9fef36ac3b Mon Sep 17 00:00:00 2001 From: Michael Liendo Date: Mon, 15 Jul 2024 21:53:21 -0400 Subject: [PATCH] feat: install types and create a login services and use in the register services --- package-lock.json | 58 ++++++++++++++++++++++--- server/package.json | 4 +- server/src/controllers/Auth/register.ts | 2 +- server/src/services/Auth.ts | 33 +++++++++++--- server/src/utils/jwt.ts | 6 +-- 5 files changed, 85 insertions(+), 18 deletions(-) diff --git a/package-lock.json b/package-lock.json index 157521a..8479b76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1316,11 +1316,19 @@ "@types/node": "*" } }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz", + "integrity": "sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "20.14.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", - "dev": true, "license": "MIT", "dependencies": { "undici-types": "~5.26.4" @@ -1330,14 +1338,14 @@ "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/@types/react": { "version": "18.3.3", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -1956,7 +1964,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/debug": { @@ -4566,7 +4574,6 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true, "license": "MIT" }, "node_modules/update-browserslist-db": { @@ -4609,6 +4616,15 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -4823,6 +4839,34 @@ "node": ">=6" } }, + "node_modules/zustand": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.4.tgz", + "integrity": "sha512-/BPMyLKJPtFEvVL0E9E9BTUM63MNyhPGlvxk1XjrfWTUlV+BR8jufjsovHzrtR6YNcBEcL7cMHovL1n9xHawEg==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "1.2.0" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + }, "server": { "name": "@linx/server", "version": "0.0.1", @@ -4830,6 +4874,7 @@ "dependencies": { "@fastify/cors": "^8.4.1", "@linx/shared": "^0.0.1", + "@types/jsonwebtoken": "^9.0.6", "bcrypt": "^5.1.1", "dotenv": "^16.3.1", "fastify": "^4.24.3", @@ -4838,7 +4883,8 @@ "jsonwebtoken": "^9.0.2", "knex": "^3.0.1", "pg": "^8.11.3", - "validator": "^13.11.0" + "validator": "^13.11.0", + "zustand": "^4.5.4" }, "devDependencies": { "@biomejs/biome": "^1.3.3", diff --git a/server/package.json b/server/package.json index 6ba78f8..53a2ad2 100644 --- a/server/package.json +++ b/server/package.json @@ -30,6 +30,7 @@ "dependencies": { "@fastify/cors": "^8.4.1", "@linx/shared": "^0.0.1", + "@types/jsonwebtoken": "^9.0.6", "bcrypt": "^5.1.1", "dotenv": "^16.3.1", "fastify": "^4.24.3", @@ -38,7 +39,8 @@ "jsonwebtoken": "^9.0.2", "knex": "^3.0.1", "pg": "^8.11.3", - "validator": "^13.11.0" + "validator": "^13.11.0", + "zustand": "^4.5.4" }, "devDependencies": { "@biomejs/biome": "^1.3.3", diff --git a/server/src/controllers/Auth/register.ts b/server/src/controllers/Auth/register.ts index d532bb1..ffd6a4c 100644 --- a/server/src/controllers/Auth/register.ts +++ b/server/src/controllers/Auth/register.ts @@ -30,7 +30,7 @@ export default async function register(request: Request, reply: Reply) { password, }); - return reply.code(201).send({ message: 'User created', data: { user } }); + return reply.code(201).send({ message: 'User created', data: { ...user } }); } catch (error) { return reply.code(500).send({ message: 'Internal server error', diff --git a/server/src/services/Auth.ts b/server/src/services/Auth.ts index 58f0b23..47f5f39 100644 --- a/server/src/services/Auth.ts +++ b/server/src/services/Auth.ts @@ -1,20 +1,34 @@ -import { User } from '../repository/User'; -import { hashPassword } from '../utils/password'; +import { comparePassword, hashPassword } from '../utils/password'; import Repository from '../repository'; -import { BadRequestError } from '../utils/errorHandler'; +import { BadRequestError, UnauthorizedError } from '../utils/errorHandler'; import type { IUserForLogin, IUserForRegister } from '@linx/shared'; +import { Jwt } from '../utils/jwt'; export default class Auth { - // biome-ignore lint/correctness/noUnusedVariables: todo: remove this static async login(data: IUserForLogin) { - // todo: implement login + const { password, ...user } = await Repository.user.getUserByEmail( + data.email, + ); + + if (!user) { + throw new UnauthorizedError('UnauthorizedError'); + } + + const isCorrectPassword = await comparePassword(data.password, password); + + if (!isCorrectPassword) { + throw new UnauthorizedError('UnauthorizedError'); + } + + const jwt = await Jwt.createToken(user); + return jwt; } static async register(data: IUserForRegister) { const { first_name, last_name, email, password } = data; - const user = await User.getUserByEmail(email); + const user = await Repository.user.getUserByEmail(email); if (user) { throw new BadRequestError('Select another email'); @@ -31,6 +45,11 @@ export default class Auth { const id = await Repository.user.createUser(registeredUser); - return id; + const token = await this.login({ + email: data.email, + password: data.password, + }); + + return { id, token }; } } diff --git a/server/src/utils/jwt.ts b/server/src/utils/jwt.ts index eccb0b3..acfeed2 100644 --- a/server/src/utils/jwt.ts +++ b/server/src/utils/jwt.ts @@ -2,11 +2,11 @@ import jwt from 'jsonwebtoken'; import { UnauthorizedError } from './errorHandler'; export class Jwt { - static createToken(payload: string) { + static createToken(payload: object): Promise { return new Promise((resolve, reject) => { - jwt.sign(payload, process.env.JWT_PRIVATE_KEY, (error, token) => { + jwt.sign(payload, process.env.JWT_PRIVATE_KEY, (error, token: string) => { if (error) { - reject('error when creating token'); + reject(error); } else { resolve(token); }