Skip to content

Commit 43e600c

Browse files
committed
feat: routes standarized and cookie parser added
1 parent 4467a37 commit 43e600c

File tree

10 files changed

+80
-68
lines changed

10 files changed

+80
-68
lines changed

package-lock.json

Lines changed: 41 additions & 30 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
{
22
"name": "user-management",
3-
"version": "1.5.0",
3+
"version": "2.0.0",
44
"description": "Microservicio de administración de usuario con public key",
55
"main": "./src/index.js",
66
"type": "module",
77
"scripts": {
88
"test": "echo \"Error: no test specified\" && exit 1",
9+
"start": "node --env-file .env dist/index.js",
910
"dev": "nodemon --env-file .env dist/index.js",
1011
"build": "tsc --watch"
1112
},
@@ -18,20 +19,21 @@
1819
"license": "MIT",
1920
"dependencies": {
2021
"bcrypt": "5.1.1",
22+
"cookie-parser": "^1.4.6",
2123
"cors": "2.8.5",
24+
"crypto": "^1.0.1",
2225
"express": "4.18.2",
2326
"joi": "17.10.2",
2427
"jsonwebtoken": "9.0.2",
25-
"mysql2": "3.6.1",
26-
"node-rsa": "1.1.1"
28+
"mysql2": "3.6.1"
2729
},
2830
"devDependencies": {
2931
"@types/bcrypt": "^5.0.0",
32+
"@types/cookie-parser": "^1.4.5",
3033
"@types/cors": "2.8.14",
3134
"@types/express": "4.17.17",
3235
"@types/jsonwebtoken": "^9.0.3",
3336
"@types/mysql2": "github:types/mysql2",
34-
"@types/node-rsa": "^1.1.2",
3537
"@typescript-eslint/eslint-plugin": "6.7.2",
3638
"eslint": "8.50.0",
3739
"eslint-config-prettier": "9.0.0",

src/app.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import express, { type Request, type Application, type Response, type IRouter } from 'express'
22
import cors, { type CorsOptions } from 'cors'
3+
import cookieParser from 'cookie-parser'
34
import * as routes from './routes/routes.js'
45
import { HttpStatusCode } from './enums/httpStatusCodes.enums.js'
56

@@ -16,6 +17,8 @@ app.use(cors(options))
1617

1718
app.use(express.json())
1819

20+
app.use(cookieParser())
21+
1922
const appRoutes: IRouter[] = Object.values(routes)
2023

2124
const API = '/api'
Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,20 @@
11
import { type Request, type Response } from 'express'
22
import { httpErrorCatch } from '../errors/errorHandler.js'
3-
import NodeRSA from 'node-rsa'
43
import { HttpStatusCode } from '../enums/httpStatusCodes.enums.js'
54
import { pool } from '../config/dbconection.js'
65
import { APIError } from '../errors/customErrorClasses.js'
76

8-
export const createPublicKey = async (_: Request, res: Response): Promise<Response> => {
7+
export const saveKeyToDatabase = async (req: Request, res: Response): Promise<string | Response> => {
8+
const publicKey = req.headers['x-public-key']
99
try {
10-
const key = new NodeRSA({ b: 128 })
11-
key.generateKeyPair()
12-
const publicKey = key.exportKey('public').replace('-----BEGIN PUBLIC KEY-----\n', '').replace('\n-----END PUBLIC KEY-----', '').replaceAll('\n', '')
13-
await saveKeyToDatabase(publicKey)
10+
const [query] = await pool.query('INSERT INTO user_api_keys (user_api_key) VALUES (?)', [publicKey])
11+
if (Array.isArray(query) && query.length === 0) throw new APIError('Error al almacenar la llave pública')
1412
return res.status(HttpStatusCode.OK).json({ key: publicKey })
1513
} catch (error: any) {
16-
console.error(error)
1714
return httpErrorCatch(res, error)
1815
}
1916
}
2017

21-
const saveKeyToDatabase = async (publicKey: string): Promise<string | boolean> => {
22-
try {
23-
const [query] = await pool.query('INSERT INTO user_api_keys (api_key) VALUES (?)', [publicKey])
24-
if (Array.isArray(query) && query.length === 0) throw new APIError('Error al almacenar la llave pública')
25-
return true
26-
} catch (error) {
27-
throw new APIError('Error al almacenar los datos')
28-
}
29-
}
30-
3118
export const checkDone = (_req: Request, res: Response): Response => {
3219
return res.status(HttpStatusCode.OK).json({ check: true })
3320
}

src/controllers/user.controllers.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import jwt from 'jsonwebtoken'
99
export const createUserByEmail = async (req: Request, res: Response): Promise<Response> => {
1010
const { userName, userEmail, dbNameSpace, userPassword, userRole, IDKey } = req.body as user
1111
try {
12-
const [query] = await pool.query('INSERT INTO users (id_user_api_key, user_full_name, user_email, user_password, id_user_role_fk, db_namespace) VALUES (?, ?, ?, ?, ?, ?)', [IDKey, userName, userEmail, userPassword, userRole, dbNameSpace])
12+
const [query] = await pool.query('INSERT INTO users (id_user_api_key_fk, user_full_name, user_email, user_password, id_user_role_fk, db_namespace) VALUES (?, ?, ?, ?, ?, ?)', [IDKey, userName, userEmail, userPassword, userRole, dbNameSpace])
1313
if (Array.isArray(query) && query.length === 0) throw new APIError('Ha ocurrido un error al ingresar los datos')
1414
return res.status(HttpStatusCode.OK).json({ msg: 'User created!' })
1515
} catch (error: any) {
@@ -20,8 +20,7 @@ export const createUserByEmail = async (req: Request, res: Response): Promise<Re
2020
export const getDBUsers = async (req: Request, res: Response): Promise<Response> => {
2121
const { IDKey, dbNameSpace } = req.query
2222
try {
23-
const [query] = await pool.query('SELECT users.user_email, users.user_password, users.db_namespace, roles.role_name, COUNT(*) AS total_users FROM users INNER JOIN roles ON users.id_user_role_fk = roles.id_role WHERE users.db_namespace = ? AND id_user_api_key = ? GROUP BY users.user_email, users.user_password, users.db_namespace, roles.role_name', [dbNameSpace, IDKey])
24-
if (Array.isArray(query) && query.length === 0) throw new APIError('Error al buscar los usuarios')
23+
const [query] = await pool.query('SELECT users.user_email, users.user_password, users.db_namespace, roles.role_name, COUNT(*) AS total_users FROM users INNER JOIN roles ON users.id_user_role_fk = roles.id_role WHERE users.db_namespace = ? AND users.id_user_api_key_fk = ? GROUP BY users.user_email, users.user_password, users.db_namespace, roles.role_name', [dbNameSpace, IDKey])
2524
return res.status(HttpStatusCode.OK).json(query)
2625
} catch (error: any) {
2726
return httpErrorCatch(res, error)
@@ -36,7 +35,7 @@ export const generateToken = async (req: Request, res: Response): Promise<Respon
3635
const secretKey = process.env.PRIVATE_KEY ?? 'foo'
3736
const token = jwt.sign({ payload: { userEmail, DBPayload, userName } }, secretKey, { algorithm: 'HS256', expiresIn: expiresInTime })
3837
if (token === undefined) throw new APIError('Error al crear el token')
39-
return res.status(HttpStatusCode.OK).json(token)
38+
return res.status(HttpStatusCode.OK).cookie('jwt_token', token, { httpOnly: true, secure: true }).json('Done.')
4039
} catch (error: any) {
4140
return httpErrorCatch(res, error)
4241
}

src/errors/errorHandler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ import { HttpStatusCode } from '../enums/httpStatusCodes.enums.js'
33
import { type CustomError } from './customErrorClasses.js'
44

55
export const httpErrorCatch = (res: Response, error: CustomError): Response => {
6-
return res.status(HttpStatusCode.InternalServerError).json({ message: error.message, code: error.statusCode, header: error.header })
6+
return res.status(HttpStatusCode.InternalServerError).json({ message: error.message ?? 'Error con la API', code: error.statusCode ?? HttpStatusCode.InternalServerError, header: error.header ?? 'Error' })
77
}

src/middlewares/publicKey.middlewares.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { pool } from '../config/dbconection.js'
33
import { APIError } from '../errors/customErrorClasses.js'
44
import { httpErrorCatch } from '../errors/errorHandler.js'
55
import { type RowDataPacket } from 'mysql2'
6+
import crypto from 'crypto'
67

78
export const checkPublicKey = async (req: Request<any>, res: Response, next: NextFunction): Promise<void> => {
89
const publicKey = req.headers['x-public-key']
@@ -16,9 +17,19 @@ export const checkPublicKey = async (req: Request<any>, res: Response, next: Nex
1617
}
1718
}
1819

20+
export const createPublicKey = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
21+
try {
22+
const publicKey = crypto.randomBytes(16).toString('hex')
23+
req.headers['x-public-key'] = publicKey
24+
next()
25+
} catch (error: any) {
26+
httpErrorCatch(res, error)
27+
}
28+
}
29+
1930
const getDBPublicKey = async (payload: string): Promise<void> => {
2031
try {
21-
const [query] = await pool.query('SELECT api_key, true FROM user_api_keys WHERE api_key = ?', [payload])
32+
const [query] = await pool.query('SELECT user_api_key, true FROM user_api_keys WHERE user_api_key = ?', [payload])
2233
if (Array.isArray(query) && query.length === 0) throw new APIError('Error al buscar la api key.')
2334
} catch (error: any) {
2435
throw new APIError(error)
@@ -28,10 +39,9 @@ const getDBPublicKey = async (payload: string): Promise<void> => {
2839
export const getDBIDKey = async (req: Request, _res: Response, next: NextFunction): Promise<void> => {
2940
const publicKey = req.headers['x-public-key']
3041
try {
31-
const [query] = await pool.query<RowDataPacket[]>('SELECT id_user_api_key FROM user_api_keys WHERE api_key = ?', [publicKey])
42+
const [query] = await pool.query<RowDataPacket[]>('SELECT id FROM user_api_keys WHERE user_api_key = ?', [publicKey])
3243
if (Array.isArray(query) && query.length === 0) throw new APIError('Error al traer el ID la api key.')
33-
req.body.IDKey = query[0].id_user_api_key
34-
req.query.IDKey = query[0].id_user_api_key
44+
req.body.IDKey = query[0].id
3545
next()
3646
} catch (error: any) {
3747
throw new APIError(error)

src/routes/publicKey.routes.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { Router } from 'express'
2-
import { checkDone, createPublicKey } from '../controllers/publicKey.controllers.js'
3-
import { checkPublicKey } from '../middlewares/publicKey.middlewares.js'
2+
import { checkDone, saveKeyToDatabase } from '../controllers/publicKey.controllers.js'
3+
import { checkPublicKey, createPublicKey } from '../middlewares/publicKey.middlewares.js'
44

55
const keyRoute: Router = Router()
66

7-
keyRoute.get('/check-public-key', checkPublicKey, checkDone)
7+
keyRoute.get('/public-key', checkPublicKey, checkDone)
88

9-
keyRoute.post('/create-public-key', createPublicKey)
9+
keyRoute.post('/public-key', createPublicKey, saveKeyToDatabase)
1010

1111
export { keyRoute }

src/routes/routes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ routes.get('/test', async (_req: Request, res: Response): Promise<void> => {
1313
const [testPool] = await pool.query('SELECT 1+1')
1414
res.status(HttpStatusCode.OK).json({ msg: testPool, status: 200, db: process.env.DB_DATABASE })
1515
} catch (error) {
16-
res.status(HttpStatusCode.InternalServerError).json({ msg: 'Error en la consulta a la base de datos' })
16+
res.status(HttpStatusCode.InternalServerError).json({ msg: 'Error en la consulta a la base de datos', error })
1717
}
1818
})
1919

src/routes/user.routes.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import { createUserByEmail, generateToken, getDBUsers } from '../controllers/use
55

66
const userRoute = Router()
77

8-
userRoute.get('/show-db-users', checkPublicKey, getDBIDKey, checkDBNameSpace, getDBUsers)
8+
userRoute.get('/users', checkPublicKey, getDBIDKey, checkDBNameSpace, getDBUsers)
99

10-
userRoute.post('/register-user/email', checkPublicKey, checkUserData, cryptUserPassword, getDBIDKey, createUserByEmail)
11-
userRoute.post('/login-user/email', checkPublicKey, checkLoginData, getUserPassword, comparePassword, generateToken)
10+
userRoute.post('/users/register', checkPublicKey, checkUserData, cryptUserPassword, getDBIDKey, createUserByEmail)
11+
userRoute.post('/users/login', checkPublicKey, checkLoginData, getUserPassword, comparePassword, generateToken)
1212

1313
export { userRoute }

0 commit comments

Comments
 (0)