update

parent 3144fc0a
This diff is collapsed.
...@@ -13,11 +13,14 @@ ...@@ -13,11 +13,14 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@types/lodash": "^4.17.7",
"@types/multer": "^1.4.11", "@types/multer": "^1.4.11",
"bcrypt": "^5.1.1",
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.14.1", "class-validator": "^0.14.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^4.18.2", "express": "^4.18.2",
"lodash": "^4.17.21",
"multer": "^1.4.5-lts.1", "multer": "^1.4.5-lts.1",
"mysql": "^2.18.1", "mysql": "^2.18.1",
"nanoid": "^3.3.6", "nanoid": "^3.3.6",
...@@ -31,6 +34,7 @@ ...@@ -31,6 +34,7 @@
"typescript": "^5.1.6" "typescript": "^5.1.6"
}, },
"devDependencies": { "devDependencies": {
"@types/bcrypt": "^5.0.2",
"@types/cors": "^2.8.17", "@types/cors": "^2.8.17",
"@types/express": "^4.17.17", "@types/express": "^4.17.17",
"@types/node": "^20.4.2", "@types/node": "^20.4.2",
......
import { DataSource } from "typeorm"; import { DataSource } from "typeorm";
import { Product } from "./entities/product.entity"; import { Product } from "./entities/product.entity";
import { Category } from "./entities/category.entity"; import { Category } from "./entities/category.entity";
import { User } from "./entities/user.entity";
export const AppDataSource = new DataSource({ export const AppDataSource = new DataSource({
type: "postgres", type: "postgres",
...@@ -11,5 +12,5 @@ export const AppDataSource = new DataSource({ ...@@ -11,5 +12,5 @@ export const AppDataSource = new DataSource({
database: "postgres", database: "postgres",
schema: "public", schema: "public",
synchronize: true, synchronize: true,
entities: [Product, Category] entities: [Product, Category, User]
}) })
\ No newline at end of file
import { UserService } from "@/services/user.service";
import { RequestHandler } from "express";
import { plainToInstance } from 'class-transformer';
// import { SignInUserDto } from "@/dto/sign-in-user.dto";
import { RegistrationUserDto } from "@/dto/registration-user.dto";
export class UserController {
private service: UserService;
constructor() {
this.service = new UserService();
}
signIn: RequestHandler = async (req, res): Promise<void> => {
res.send(req.headers.authorization)
// try {
// const signInDto = plainToInstance(SignInUserDto, req.body)
// const user = await this.service.signIn(signInDto)
// res.send(user)
// } catch (e) {
// res.status(401).send((e as Error).message)
// }
}
registration: RequestHandler = async (req, res): Promise<void> => {
const registrationInDto = plainToInstance(RegistrationUserDto, req.body)
const user = await this.service.registration(registrationInDto)
res.send(user)
}
}
import { Expose } from 'class-transformer';
import { IsNotEmpty, IsString, IsOptional } from 'class-validator';
export class RegistrationUserDto {
@Expose()
@IsNotEmpty({message: 'Логин не должен быть пустым'})
@IsString({message: 'Логин должен быть строкой'})
username!: string;
@Expose()
@IsNotEmpty({message: 'Пароль не должен быть пустым'})
@IsString({message: 'Пароль должен быть строкой'})
password!: string;
@Expose()
@IsOptional()
displayName?: string
}
import { Expose } from 'class-transformer';
import { IsNotEmpty, IsString } from 'class-validator';
export class SignInUserDto {
@Expose()
@IsNotEmpty({message: 'Логин не должен быть пустым'})
@IsString({message: 'Логин должен быть строкой'})
username!: string;
@Expose()
@IsNotEmpty({message: 'Пароль не должен быть пустым'})
@IsString({message: 'Пароль должен быть строкой'})
password!: string;
}
import { Entity, PrimaryGeneratedColumn, Column, Unique } from "typeorm";
import bcrypt from 'bcrypt';
@Entity()
@Unique(['username'])
export class User {
@PrimaryGeneratedColumn()
id!: number;
@Column()
username!: string
@Column()
password!: string
@Column({nullable: true})
token!: string
@Column({nullable: true})
displayName!: string
async comparePassword(password: string): Promise<boolean> {
return await bcrypt.compare(password, this.password);
}
generateToken() {
this.token = crypto.randomUUID();
}
}
\ No newline at end of file
...@@ -4,11 +4,12 @@ import App from './app'; ...@@ -4,11 +4,12 @@ import App from './app';
import logger from './middlewares/logger'; import logger from './middlewares/logger';
import { ArticleRoute } from './routes/article.route'; import { ArticleRoute } from './routes/article.route';
import { ProductRoute } from './routes/product.route'; import { ProductRoute } from './routes/product.route';
import { UserRoute } from './routes/user.route';
const app = new App({ const app = new App({
port: 8000, port: 8000,
middlewares: [logger(), cors()], middlewares: [logger(), cors()],
controllers: [new ArticleRoute(), new ProductRoute(), new CategoryRoute()], controllers: [new ArticleRoute(), new ProductRoute(), new CategoryRoute(), new UserRoute()],
}); });
app.listen(); app.listen();
export interface IUser {
id: number
username: string
password?: string
displayName?: string
}
\ No newline at end of file
import { AppDataSource } from "@/appDataSource";
import { Repository } from "typeorm";
import { User } from "@/entities/user.entity";
import { IUser } from "@/interfaces/IUser.interface";
import { SignInUserDto } from "@/dto/sign-in-user.dto";
import { RegistrationUserDto } from "@/dto/registration-user.dto";
import bcrypt from 'bcrypt';
import _ from "lodash";
const SALT_WORK_FACTOR = 10;
export class UserRepo {
private repo: Repository<User>
constructor() {
this.repo = AppDataSource.getRepository(User)
}
async signIn(signInUserDto: SignInUserDto): Promise<IUser> {
const userData = await this.repo.findOne({where: {username: signInUserDto.username}})
if(!userData) throw new Error('Invalid username or password')
const isCorrect = await userData.comparePassword(signInUserDto.password)
if(!isCorrect) throw new Error('Invalid username or password')
userData.generateToken()
const user = await this.repo.save(userData)
const userWithoutPass = _.omit(user, 'password')
return userWithoutPass
}
async registration(registrationUserDto: RegistrationUserDto): Promise<IUser> {
const salt = await bcrypt.genSalt(SALT_WORK_FACTOR)
registrationUserDto.password = await bcrypt.hash(registrationUserDto.password, salt)
const user = await this.repo.save(registrationUserDto)
const userWithoutPass = _.omit(user, 'password')
return userWithoutPass
}
}
export const userRepo = new UserRepo()
\ No newline at end of file
import { Router } from 'express';
import { IRoute } from '../interfaces/IRoute.interface';
import { UserController } from '@/controllers/user.controller';
export class UserRoute implements IRoute {
public path = '/user';
public router = Router();
private controller: UserController;
constructor() {
this.controller = new UserController();
this.init();
}
private init() {
this.router.post('/registration', this.controller.registration);
this.router.post('/signIn', this.controller.signIn);
}
}
...@@ -2,7 +2,6 @@ import { CategoryDto } from "@/dto/category.dto"; ...@@ -2,7 +2,6 @@ import { CategoryDto } from "@/dto/category.dto";
import { Category } from "@/entities/category.entity"; import { Category } from "@/entities/category.entity";
import { categoryRepo } from "@/repositories/category.repository"; import { categoryRepo } from "@/repositories/category.repository";
export class CategoryService { export class CategoryService {
getAllCategories = async (): Promise<Category[]> => { getAllCategories = async (): Promise<Category[]> => {
return await categoryRepo.getAll() return await categoryRepo.getAll()
......
import { SignInUserDto } from "@/dto/sign-in-user.dto"
import { RegistrationUserDto } from "@/dto/registration-user.dto"
import { userRepo } from "@/repositories/user.repository"
export class UserService {
async signIn(signInUserDto: SignInUserDto) {
return await userRepo.signIn(signInUserDto)
}
async registration(registrationUserDto: RegistrationUserDto) {
return await userRepo.registration(registrationUserDto)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment