running now
This commit is contained in:
parent
85cd083750
commit
c17bb05f0a
25 changed files with 156 additions and 114 deletions
2
.env
2
.env
|
|
@ -4,5 +4,5 @@ DB_HOST=localhost
|
||||||
DB_PORT=5432
|
DB_PORT=5432
|
||||||
DB_USERNAME=recipe-backend
|
DB_USERNAME=recipe-backend
|
||||||
DB_PASSWORD=yeshu0bue5aigaphie0eemoFey3farei
|
DB_PASSWORD=yeshu0bue5aigaphie0eemoFey3farei
|
||||||
DB_DATABASE=recipe-backend
|
DB_DATABASE=recipe-backend-dev
|
||||||
NODE_ENV=dev
|
NODE_ENV=dev
|
||||||
|
|
|
||||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
.vscode
|
||||||
|
build
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "recipe-backend",
|
"name": "recipe-backend",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"description": "Awesome project developed with TypeORM.",
|
"description": "Awesome project developed with TypeORM.",
|
||||||
"type": "commonjs",
|
"type": "module",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.13.10",
|
"@types/node": "^22.13.10",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { UserRepository } from "../repositories/UserRepository";
|
import { UserRepository } from "../repositories/UserRepository.js";
|
||||||
import { encrypt } from "../utils/encryptionUtils";
|
import { encrypt } from "../utils/encryptionUtils.js";
|
||||||
import { ValidationError, UnauthorizedError } from "../errors/httpErrors";
|
import { ValidationError, UnauthorizedError } from "../errors/httpErrors.js";
|
||||||
import { UserDtoEntityMapper } from "../mappers/UserDtoEntityMapper";
|
import { UserDtoEntityMapper } from "../mappers/UserDtoEntityMapper.js";
|
||||||
import { LoginResponseDto } from "../dtos/LoginResponseDto";
|
import { LoginResponseDto } from "../dtos/LoginResponseDto.js";
|
||||||
import { LoginRequestDto } from "../dtos/LoginRequestDto";
|
import { LoginRequestDto } from "../dtos/LoginRequestDto.js";
|
||||||
|
|
||||||
export class AuthController {
|
export class AuthController {
|
||||||
constructor(
|
constructor(
|
||||||
|
|
@ -12,25 +12,27 @@ export class AuthController {
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async login(loginRequest : LoginRequestDto): Promise<LoginResponseDto> {
|
async login(loginRequest : LoginRequestDto): Promise<LoginResponseDto> {
|
||||||
const userName :string = loginRequest.userName;
|
const userName :string|undefined = loginRequest.userName;
|
||||||
const password :string = loginRequest.password;
|
const password :string|undefined = loginRequest.password;
|
||||||
if (!userName || !password) {
|
if (!userName || !password) {
|
||||||
throw new ValidationError("Username and password are required");
|
throw new ValidationError("Username and password are required");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find user by userName
|
// Find user by userName
|
||||||
const user = await this.userRepository.findByUserName(userName);
|
const user = await this.userRepository.findByUserName(userName);
|
||||||
|
// check user before trying to access password!
|
||||||
|
if(!user){
|
||||||
|
throw new UnauthorizedError("Invalid username or password");
|
||||||
|
}
|
||||||
// Compare password
|
// Compare password
|
||||||
const passwordMatches = encrypt.comparepassword(user.password, password);
|
const passwordMatches = encrypt.comparepassword(user.password, password);
|
||||||
if (!passwordMatches || !user ) {
|
if (!passwordMatches) {
|
||||||
throw new UnauthorizedError("Invalid username or password");
|
throw new UnauthorizedError("Invalid username or password");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create JWT
|
// Create JWT
|
||||||
const token = encrypt.generateToken({
|
const token = encrypt.generateToken({
|
||||||
id: user.id,
|
id: user.id,
|
||||||
userName: user.userName,
|
|
||||||
role: user.role,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const responseDto = new LoginResponseDto();
|
const responseDto = new LoginResponseDto();
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
import { ValidationError, ConflictError } from "../errors/httpErrors";
|
import { ValidationError, ConflictError } from "../errors/httpErrors.js";
|
||||||
import { CreateUserRequestDto } from "../dtos/CreateUserRequestDto";
|
import { CreateUserRequestDto } from "../dtos/CreateUserRequestDto.js";
|
||||||
import { UserDto } from "../dtos/UserDto";
|
import { UserDto } from "../dtos/UserDto.js";
|
||||||
import { encrypt } from "../utils/encryptionUtils";
|
import { encrypt } from "../utils/encryptionUtils.js";
|
||||||
import { UserRepository } from "../repositories/UserRepository";
|
import { UserRepository } from "../repositories/UserRepository.js";
|
||||||
import { UserDtoEntityMapper } from "../mappers/UserDtoEntityMapper";
|
import { UserDtoEntityMapper } from "../mappers/UserDtoEntityMapper.js";
|
||||||
import { isNeitherNullNorEmpty } from "../utils/stringUtils";
|
|
||||||
|
|
||||||
export class UserController {
|
export class UserController {
|
||||||
constructor(
|
constructor(
|
||||||
|
|
@ -14,23 +13,30 @@ export class UserController {
|
||||||
|
|
||||||
async createUser(dto: CreateUserRequestDto): Promise<UserDto> {
|
async createUser(dto: CreateUserRequestDto): Promise<UserDto> {
|
||||||
// check mandatory fields
|
// check mandatory fields
|
||||||
if (!isNeitherNullNorEmpty(dto.userData.email)) {
|
if(!dto.userData){
|
||||||
|
throw new ValidationError("User data is required")
|
||||||
|
}
|
||||||
|
const email = dto.userData.email;
|
||||||
|
if (!email || (email && email.length == 0)) {
|
||||||
throw new ValidationError("Email is required");
|
throw new ValidationError("Email is required");
|
||||||
}
|
}
|
||||||
if (!isNeitherNullNorEmpty(dto.userData.userName)) {
|
const password = dto.password;
|
||||||
throw new ValidationError("Username is required");
|
if(!password || (password && password.length == 0)){
|
||||||
}
|
|
||||||
if(!isNeitherNullNorEmpty(dto.password){
|
|
||||||
throw new ValidationError("Password is required");
|
throw new ValidationError("Password is required");
|
||||||
}
|
}
|
||||||
// user name must be uniqu
|
const userName = dto.userData.userName;
|
||||||
const existingUser = await this.userRepository.findByUserName(dto.userData.email);
|
if (!userName|| (userName && userName.length == 0)){
|
||||||
|
throw new ValidationError("Username is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
// user name must be unique
|
||||||
|
const existingUser = await this.userRepository.findByUserName(userName);
|
||||||
if (existingUser) {
|
if (existingUser) {
|
||||||
throw new ConflictError("User with this user name already exists");
|
throw new ConflictError("User with this user name already exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
const userEntity = this.mapper.toEntity(dto.userData);
|
const userEntity = this.mapper.toEntity(dto.userData);
|
||||||
userEntity.password = await encrypt.encryptpass(dto.password);
|
userEntity.password = await encrypt.encryptpass(password);
|
||||||
|
|
||||||
const savedUser = await this.userRepository.create(userEntity);
|
const savedUser = await this.userRepository.create(userEntity);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,13 @@ import "reflect-metadata";
|
||||||
import { DataSource } from "typeorm";
|
import { DataSource } from "typeorm";
|
||||||
|
|
||||||
import * as dotenv from "dotenv";
|
import * as dotenv from "dotenv";
|
||||||
import { UserEntity } from "./entities/UserEntity";
|
import { UserEntity } from "./entities/UserEntity.js";
|
||||||
|
|
||||||
|
import { fileURLToPath } from "url";
|
||||||
|
import { dirname, join } from "path";
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = dirname(__filename);
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
|
|
@ -20,7 +26,7 @@ export const AppDataSource = new DataSource({
|
||||||
synchronize: NODE_ENV === "dev" ? false : false,
|
synchronize: NODE_ENV === "dev" ? false : false,
|
||||||
//logging logs sql command on the terminal
|
//logging logs sql command on the terminal
|
||||||
logging: NODE_ENV === "dev" ? false : false,
|
logging: NODE_ENV === "dev" ? false : false,
|
||||||
entities: [UserEntity],
|
entities: [join(__dirname, "/entities/*.{ts,js}")],
|
||||||
migrations: [__dirname + "/migration/*.ts"],
|
migrations: [join(__dirname, "/migrations/*.{ts,js}")],
|
||||||
subscribers: [],
|
subscribers: [],
|
||||||
});
|
});
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
export abstract class AbstractDto {
|
export abstract class AbstractDto {
|
||||||
id: string;
|
id?: string;
|
||||||
createdAt?: Date;
|
createdAt?: Date;
|
||||||
updatedAt?: Date;
|
updatedAt?: Date;
|
||||||
}
|
}
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { UserDto } from "./UserDto";
|
import { UserDto } from "./UserDto.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DTO used for user creation
|
* DTO used for user creation
|
||||||
*/
|
*/
|
||||||
export class CreateUserRequestDto {
|
export class CreateUserRequestDto {
|
||||||
userData: UserDto;
|
userData?: UserDto;
|
||||||
password: string;
|
password?: string;
|
||||||
}
|
}
|
||||||
|
|
@ -2,6 +2,6 @@
|
||||||
* Defines a login request
|
* Defines a login request
|
||||||
*/
|
*/
|
||||||
export class LoginRequestDto {
|
export class LoginRequestDto {
|
||||||
userName: string;
|
userName?: string;
|
||||||
password: string;
|
password?: string;
|
||||||
}
|
}
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { UserDto } from "./UserDto";
|
import { UserDto } from "./UserDto.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Response to a successful login
|
* Response to a successful login
|
||||||
*/
|
*/
|
||||||
export class LoginResponseDto {
|
export class LoginResponseDto {
|
||||||
userData: UserDto;
|
userData?: UserDto;
|
||||||
token: string;
|
token?: string;
|
||||||
}
|
}
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { AbstractDto } from "./AbstractDto";
|
import { AbstractDto } from "./AbstractDto.js";
|
||||||
|
|
||||||
export class UserDto extends AbstractDto {
|
export class UserDto extends AbstractDto {
|
||||||
firstName?: string;
|
firstName?: string;
|
||||||
lastName?: string;
|
lastName?: string;
|
||||||
userName: string;
|
userName!: string;
|
||||||
email: string;
|
email!: string;
|
||||||
role: string;
|
role?: string;
|
||||||
}
|
}
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import { Router } from "express";
|
import { Router } from "express";
|
||||||
import { AuthController } from "../controllers/AuthController";
|
import { AuthController } from "../controllers/AuthController.js";
|
||||||
import { UserRepository } from "../repositories/UserRepository";
|
import { UserRepository } from "../repositories/UserRepository.js";
|
||||||
import { UserDtoEntityMapper } from "../mappers/UserDtoEntityMapper";
|
import { UserDtoEntityMapper } from "../mappers/UserDtoEntityMapper.js";
|
||||||
import {
|
import {
|
||||||
ValidationError,
|
ValidationError,
|
||||||
UnauthorizedError,
|
UnauthorizedError,
|
||||||
InternalServerError,
|
InternalServerError,
|
||||||
} from "../errors/httpErrors";
|
} from "../errors/httpErrors.js";
|
||||||
import { LoginRequestDto } from "../dtos/LoginRequestDto";
|
import { LoginRequestDto } from "../dtos/LoginRequestDto.js";
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
|
|
@ -18,7 +18,7 @@ const authController = new AuthController(userRepository, mapper);
|
||||||
router.post("/login", async (req, res) => {
|
router.post("/login", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const requestDto: LoginRequestDto = req.body;
|
const requestDto: LoginRequestDto = req.body;
|
||||||
const responseDto = await authController.login(requestDto));
|
const responseDto = await authController.login(requestDto);
|
||||||
res.json(responseDto);
|
res.json(responseDto);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (err instanceof ValidationError || err instanceof UnauthorizedError) {
|
if (err instanceof ValidationError || err instanceof UnauthorizedError) {
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
import { Router } from "express";
|
import { Router } from "express";
|
||||||
import { UserController } from "../controllers/UserController";
|
import { UserController } from "../controllers/UserController.js";
|
||||||
import { CreateUserRequestDto } from "../dtos/CreateUserRequestDto";
|
import { CreateUserRequestDto } from "../dtos/CreateUserRequestDto.js";
|
||||||
import { UserRepository } from "../repositories/UserRepository";
|
import { UserRepository } from "../repositories/UserRepository.js";
|
||||||
import { UserDtoEntityMapper } from "../mappers/UserDtoEntityMapper";
|
import { UserDtoEntityMapper } from "../mappers/UserDtoEntityMapper.js";
|
||||||
import {
|
import {
|
||||||
ValidationError,
|
ValidationError,
|
||||||
ConflictError,
|
ConflictError,
|
||||||
NotFoundError,
|
NotFoundError,
|
||||||
InternalServerError,
|
InternalServerError,
|
||||||
} from "../errors/httpErrors";
|
} from "../errors/httpErrors.js";
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,11 @@ import {
|
||||||
|
|
||||||
export abstract class AbstractEntity {
|
export abstract class AbstractEntity {
|
||||||
@PrimaryGeneratedColumn("uuid")
|
@PrimaryGeneratedColumn("uuid")
|
||||||
id: string;
|
id?: string;
|
||||||
|
|
||||||
@CreateDateColumn()
|
@CreateDateColumn()
|
||||||
createdAt: Date;
|
createdAt?: Date;
|
||||||
|
|
||||||
@UpdateDateColumn()
|
@UpdateDateColumn()
|
||||||
updatedAt: Date;
|
updatedAt?: Date;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,23 @@
|
||||||
import { Entity, Column } from "typeorm";
|
import { Entity, Column } from "typeorm";
|
||||||
import { AbstractEntity } from "./AbstractEntity";
|
import { AbstractEntity } from "./AbstractEntity.js";
|
||||||
|
|
||||||
@Entity({ name: "user" })
|
@Entity({ name: "user" })
|
||||||
export class UserEntity extends AbstractEntity {
|
export class UserEntity extends AbstractEntity {
|
||||||
@Column({ nullable: false })
|
@Column({ nullable: false })
|
||||||
userName: string;
|
userName!: string;
|
||||||
|
|
||||||
@Column({ nullable: false })
|
@Column({ nullable: false })
|
||||||
email: string;
|
email!: string;
|
||||||
|
|
||||||
@Column({ nullable: false })
|
@Column({ nullable: false })
|
||||||
password: string;
|
password!: string;
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
firstName: string;
|
firstName?: string;
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
lastName: string;
|
lastName?: string;
|
||||||
|
|
||||||
@Column({ default: "user" })
|
@Column({ default: "user" })
|
||||||
role: string;
|
role!: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
34
src/index.ts
34
src/index.ts
|
|
@ -1,19 +1,18 @@
|
||||||
import { AppDataSource } from "./data-source"
|
|
||||||
import * as express from "express";
|
|
||||||
import * as dotenv from "dotenv";
|
|
||||||
import { Request, Response } from "express";
|
|
||||||
import authRoutes from "./endpoints/AuthPoint"
|
|
||||||
import userRoutes from "./endpoints/UserPoint";
|
|
||||||
//import { recipePoint } from "./endpoints/RecipePoint";
|
|
||||||
import {errorHandler} from "./middleware/errorHandler"
|
|
||||||
import "reflect-metadata";
|
import "reflect-metadata";
|
||||||
|
import express, { NextFunction, Request, Response } from "express";
|
||||||
|
import dotenv from "dotenv";
|
||||||
|
import { AppDataSource } from "./data-source.js";
|
||||||
|
import authRoutes from "./endpoints/AuthPoint.js";
|
||||||
|
import userRoutes from "./endpoints/UserPoint.js";
|
||||||
|
// import recipeRoutes from "./endpoints/RecipePoint.js";
|
||||||
|
import { errorHandler } from "./middleware/errorHandler.js";
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
app.use(errorHandler);
|
app.use(errorHandler);
|
||||||
|
|
||||||
|
|
||||||
async function startServer() {
|
async function startServer() {
|
||||||
try {
|
try {
|
||||||
// 1️⃣ Initialize database
|
// 1️⃣ Initialize database
|
||||||
|
|
@ -27,21 +26,26 @@ async function startServer() {
|
||||||
// 2️⃣ Setup routes
|
// 2️⃣ Setup routes
|
||||||
app.use("/auth", authRoutes);
|
app.use("/auth", authRoutes);
|
||||||
app.use("/user", userRoutes);
|
app.use("/user", userRoutes);
|
||||||
|
// app.use("/recipe", recipeRoutes);
|
||||||
|
|
||||||
app.get("*", (req: Request, res: Response) => {
|
console.log("auth and user routes added")
|
||||||
res.status(505).json({ message: "Bad Request" });
|
app.get(/(.*)/, (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
res.status(400).json({ message: "Bad Request" });
|
||||||
});
|
});
|
||||||
|
console.log("Routes set up")
|
||||||
|
|
||||||
// 3️⃣ Start listening
|
// 3️⃣ Start listening
|
||||||
const PORT = parseInt(process.env.PORT || "4000", 10);
|
const PORT = Number(process.env.PORT) || 4000;
|
||||||
const HOST = process.env.HOST || "localhost";
|
const HOST = process.env.HOST || "localhost";
|
||||||
|
|
||||||
app.listen(PORT, HOST, () => {
|
app.listen(PORT, HOST, () => {
|
||||||
console.log(`Server running on http://${HOST}:${PORT}`);
|
console.log(`✅ Server running on http://${HOST}:${PORT}`);
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Error during Data Source initialization:", err);
|
console.error("❌ Error during Data Source initialization:", err);
|
||||||
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the async start function
|
// Call the async start function
|
||||||
startServer();
|
startServer();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { AbstractDto } from "../dtos/AbstractDto";
|
import { AbstractDto } from "../dtos/AbstractDto.js";
|
||||||
import { AbstractEntity } from "../entities/AbstractEntity";
|
import { AbstractEntity } from "../entities/AbstractEntity.js";
|
||||||
|
|
||||||
export abstract class AbstractDtoEntityMapper<
|
export abstract class AbstractDtoEntityMapper<
|
||||||
E extends AbstractEntity,
|
E extends AbstractEntity,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { AbstractDtoEntityMapper } from "./AbstractDtoEntityMapper";
|
import { AbstractDtoEntityMapper } from "./AbstractDtoEntityMapper.js";
|
||||||
import { UserEntity } from "../entities/UserEntity";
|
import { UserEntity } from "../entities/UserEntity.js";
|
||||||
import { UserDto } from "../dtos/UserDto";
|
import { UserDto } from "../dtos/UserDto.js";
|
||||||
|
import { ValidationError } from "../errors/httpErrors.js";
|
||||||
|
|
||||||
export class UserDtoEntityMapper extends AbstractDtoEntityMapper<UserEntity, UserDto> {
|
export class UserDtoEntityMapper extends AbstractDtoEntityMapper<UserEntity, UserDto> {
|
||||||
toDto(entity: UserEntity): UserDto {
|
toDto(entity: UserEntity): UserDto {
|
||||||
|
|
@ -22,10 +23,11 @@ export class UserDtoEntityMapper extends AbstractDtoEntityMapper<UserEntity, Use
|
||||||
|
|
||||||
entity.userName = dto.userName;
|
entity.userName = dto.userName;
|
||||||
entity.email = dto.email;
|
entity.email = dto.email;
|
||||||
// ⚠️ Don’t forget password handling — usually set elsewhere, not exposed in DTO
|
|
||||||
entity.firstName = dto.firstName;
|
entity.firstName = dto.firstName;
|
||||||
entity.lastName = dto.lastName;
|
entity.lastName = dto.lastName;
|
||||||
entity.role = dto.role;
|
if(dto.role){
|
||||||
|
entity.role = dto.role;
|
||||||
|
}
|
||||||
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,17 @@
|
||||||
import { NextFunction, Request, Response } from "express";
|
import { NextFunction, Request, Response } from "express";
|
||||||
import * as jwt from "jsonwebtoken";
|
import * as jwt from "jsonwebtoken";
|
||||||
import * as dotenv from "dotenv";
|
import * as dotenv from "dotenv";
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
namespace Express {
|
||||||
|
interface Request {
|
||||||
|
currentUser?: string | jwt.JwtPayload;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const authentication = (
|
export const authentication = (
|
||||||
req: Request,
|
req: Request,
|
||||||
res: Response,
|
res: Response,
|
||||||
|
|
@ -12,14 +21,22 @@ export const authentication = (
|
||||||
if (!header) {
|
if (!header) {
|
||||||
return res.status(401).json({ message: "Unauthorized" });
|
return res.status(401).json({ message: "Unauthorized" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const token = header.split(" ")[1];
|
const token = header.split(" ")[1];
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return res.status(401).json({ message: "Unauthorized" });
|
return res.status(401).json({ message: "Unauthorized" });
|
||||||
}
|
}
|
||||||
const decode = jwt.verify(token, process.env.JWT_SECRET);
|
|
||||||
if (!decode) {
|
const JWT_SECRET = process.env.JWT_SECRET;
|
||||||
|
if (!JWT_SECRET) {
|
||||||
|
throw new Error("JWT_SECRET not defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const decoded = jwt.verify(token, JWT_SECRET);
|
||||||
|
req.currentUser = decoded;
|
||||||
|
next();
|
||||||
|
} catch (err) {
|
||||||
return res.status(401).json({ message: "Unauthorized" });
|
return res.status(401).json({ message: "Unauthorized" });
|
||||||
}
|
}
|
||||||
req[" currentUser"] = decode;
|
};
|
||||||
next();
|
|
||||||
};
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,16 @@
|
||||||
import { NextFunction, Request, Response } from "express";
|
/* import { NextFunction, Request, Response } from "express";
|
||||||
import { AppDataSource } from "../data-source";
|
import { AppDataSource } from "../data-source.js";
|
||||||
import { UserEntity } from "../entities/UserEntity";
|
import { UserEntity } from "../entities/UserEntity.js";
|
||||||
|
|
||||||
|
// @todo we'll need some other means to determin the user corresponding to the token here as it seems...
|
||||||
export const authorization = (roles: string[]) => {
|
export const authorization = (roles: string[]) => {
|
||||||
return async (req: Request, res: Response, next: NextFunction) => {
|
return async (req: Request, res: Response, next: NextFunction) => {
|
||||||
const userRepo = AppDataSource.getRepository(UserEntity);
|
const userRepo = AppDataSource.getRepository(UserEntity);
|
||||||
|
const currentUser = req.currentUser;
|
||||||
|
if(!currentUser){
|
||||||
|
return res.status(403).json({ message: "Forbidden - currentUser is missing" });
|
||||||
|
}
|
||||||
|
const userId = currentUser.id
|
||||||
const user = await userRepo.findOne({
|
const user = await userRepo.findOne({
|
||||||
where: { id: req[" currentUser"].id },
|
where: { id: req[" currentUser"].id },
|
||||||
});
|
});
|
||||||
|
|
@ -13,5 +19,5 @@ export const authorization = (roles: string[]) => {
|
||||||
return res.status(403).json({ message: "Forbidden" });
|
return res.status(403).json({ message: "Forbidden" });
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
};
|
};*/
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import { Repository, DeepPartial } from "typeorm";
|
import { Repository, DeepPartial, ObjectLiteral } from "typeorm";
|
||||||
import { AppDataSource } from "../data-source";
|
import { AppDataSource } from "../data-source.js";
|
||||||
|
import { AbstractEntity } from "../entities/AbstractEntity.js";
|
||||||
|
|
||||||
export abstract class AbstractRepository<T> {
|
export abstract class AbstractRepository<T extends AbstractEntity> {
|
||||||
protected repo: Repository<T>;
|
protected repo: Repository<T>;
|
||||||
|
|
||||||
constructor(entity: { new (): T }) {
|
constructor(entity: { new (): T }) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { AbstractRepository } from "./AbstractRepository";
|
import { AbstractRepository } from "./AbstractRepository.js";
|
||||||
import { UserEntity } from "../entities/UserEntity";
|
import { UserEntity } from "../entities/UserEntity.js";
|
||||||
|
|
||||||
export class UserRepository extends AbstractRepository<UserEntity> {
|
export class UserRepository extends AbstractRepository<UserEntity> {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import * as jwt from "jsonwebtoken";
|
import * as jwt from "jsonwebtoken";
|
||||||
import * as bcrypt from "bcrypt";
|
import * as bcrypt from "bcrypt";
|
||||||
import * as dotenv from "dotenv";
|
import * as dotenv from "dotenv";
|
||||||
import { payload } from "../dtos/userDto";
|
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
const { JWT_SECRET = "" } = process.env;
|
const { JWT_SECRET = "" } = process.env;
|
||||||
|
|
@ -9,11 +8,11 @@ export class encrypt {
|
||||||
static async encryptpass(password: string) {
|
static async encryptpass(password: string) {
|
||||||
return bcrypt.hashSync(password, 12);
|
return bcrypt.hashSync(password, 12);
|
||||||
}
|
}
|
||||||
static comparepassword(hashPassword: string, password: string) {
|
static comparepassword(password: string, hashPassword: string) {
|
||||||
return bcrypt.compareSync(password, hashPassword);
|
return bcrypt.compareSync(password, hashPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
static generateToken(payload: payload) {
|
static generateToken(payload: object) {
|
||||||
return jwt.sign(payload, JWT_SECRET, { expiresIn: "1d" });
|
return jwt.sign(payload, JWT_SECRET, { expiresIn: "1d" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
export function isNeitherNullNorEmpty(input : string) : boolean {
|
|
||||||
return input && input.length !==0;
|
|
||||||
}
|
|
||||||
|
|
@ -4,11 +4,12 @@
|
||||||
"es2021"
|
"es2021"
|
||||||
],
|
],
|
||||||
"target": "es2021",
|
"target": "es2021",
|
||||||
"module": "commonjs",
|
"module": "node16",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node16",
|
||||||
"outDir": "./build",
|
"outDir": "./build",
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"sourceMap": true
|
"sourceMap": true,
|
||||||
|
"strict": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue