Commit ca2b7957 authored by Pavel Mishakov's avatar Pavel Mishakov

new fitches

parent 8c49b3f3
This diff is collapsed.
......@@ -10,25 +10,31 @@
"author": "",
"license": "ISC",
"dependencies": {
"bcrypt": "^5.1.0",
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"mongodb": "^5.1.0",
"mongoose": "^7.0.3",
"multer": "^1.4.5-lts.1",
"nanoid": "^4.0.1",
"pg": "^8.9.0",
"pg-hstore": "^2.3.4",
"sequelize": "^6.29.0",
"sequelize-typescript": "^2.1.5",
"shortid": "^2.2.16",
"uuidv4": "^6.2.13"
},
"devDependencies": {
"@types/bcrypt": "^5.0.0",
"@types/cors": "^2.8.13",
"@types/dotenv": "^8.2.0",
"@types/express": "^4.17.17",
"@types/mongodb": "^4.0.7",
"@types/mongoose": "^5.11.97",
"@types/multer": "^1.4.7",
"@types/nanoid": "^3.0.0",
"@types/shortid": "^0.0.29",
"@types/uuidv4": "^5.0.0",
"@types/validator": "^13.7.12",
"ts-node-dev": "^2.0.0"
......
import express, { Router, Request, Response } from 'express'
import { ProductService, productService } from '../services/products'
import { ProductServicePg, productServicePg } from '../services/productsPg'
import multer from 'multer'
// import {nanoid} from 'nanoid'
// const {nanoid} = require('nanoid')
import { config } from '../index.config'
import { productServiceMongo } from '../services/productsMongo'
// import path from 'path'
import { productService, ProductService } from '../services/products'
const storage = multer.diskStorage({
destination(req, file, callback) {
......@@ -23,26 +18,14 @@ const upload = multer({storage})
export class ProductsController {
private router: Router
private service: ProductService | ProductServicePg
private service: ProductService
constructor() {
this.router = express.Router()
this.router.get('/', this.getProducts)
this.router.get('/:id', this.getProductById)
this.router.post('/', upload.single('image'), this.addProduct)
switch(process.env.DB) {
case 'file':
this.service = productService
break
case 'postgres':
this.service = productServicePg
break
case 'mongoDBCLient':
this.service = productServiceMongo
break
default:
this.service = productServicePg
}
this.service = productService
}
public getRouter = (): Router => {
......
import express, { Router, Request, Response } from 'express'
import { supplierService, SupplierService } from '../services/suppliers'
export class SuppliersController {
private router: Router
private service: SupplierService
constructor() {
this.router = express.Router()
this.router.get('/', this.getSuppliers)
this.router.get('/:id', this.getSupplierById)
this.router.post('/', this.addSupplier)
this.router.delete('/:id', this.deleteSupplierById)
this.router.post('/:id', this.updateSupplierById)
this.service = supplierService
}
public getRouter = (): Router => {
return this.router
}
private getSuppliers = async (req: Request, res: Response): Promise<void> => {
const response = await this.service.getSuppliers()
res.send(response)
}
private getSupplierById = async (req: Request, res: Response): Promise<void> => {
const response = await this.service.getSupplierById(req.params.id)
res.send(response)
}
private deleteSupplierById = async (req: Request, res: Response): Promise<void> => {
const response = await this.service.deleteSupplierById(req.params.id)
res.send(response)
}
private updateSupplierById = async (req: Request, res: Response): Promise<void> => {
const response = await this.service.updateSupplierById(req.params.id, req.body)
res.send(response)
}
private addSupplier = async (req: Request, res: Response): Promise<void> => {
const response = await this.service.addSupplier(req.body)
res.send(response)
}
}
\ No newline at end of file
import { userService, UserService } from "../services/user"
import express, {Request, Response, Router} from 'express'
import IResponse from "../interfaces/IResponse"
import IUser from "../interfaces/IUser"
import { User } from "../models/mongo/User"
export class UserController {
private service: UserService
private router: Router
constructor() {
this.service = userService
this.router = express.Router()
this.router.get('/', this.getUsers)
this.router.post('/', this.createUser)
this.router.post('/login', this.login)
this.router.get('/token', this.checkToken)
}
public getRouter = (): Router => {
return this.router
}
private createUser = async (req: Request, res: Response): Promise<void> => {
const response: IResponse<IUser | undefined> = await this.service.createUser(req.body)
res.status(200).send(response)
}
public login = async (req: Request, res: Response): Promise<void> => {
const response: IResponse<IUser | undefined> = await this.service.login(req.body)
res.status(200).send(response)
}
public getUsers = async (req: Request, res: Response): Promise<void> => {
const user = await User.findOne({token: req.get('Authorization')})
if(!user) {
res.status(200).send({
isStatusOk: false,
result: undefined,
message: 'Not authorized'
})
} else {
const response: IResponse<IUser[] | undefined> = await this.service.getUsers()
res.status(200).send(response)
}
}
public checkToken = async (req: Request, res: Response): Promise<void> => {
const user = await User.findOne({token: req.get('Authorization')})
console.log(user)
if(!user) {
res.status(200).send({
isStatusOk: false,
result: undefined,
message: 'Not authorized'
})
} else {
const response: IResponse<IUser | undefined> = {
isStatusOK: true,
result: user,
message: 'Token is ok'
}
res.status(200).send(response)
}
}
}
export const userController = new UserController()
\ No newline at end of file
......@@ -7,6 +7,9 @@ import dotenv from 'dotenv'
import { postgresDB } from './repository/postgresDB'
import { mongoDBClient } from './repository/mongoDBClient'
import IDataBase from './interfaces/IDataBase'
import { SuppliersController } from './controllers/suppliers'
import { UserController } from './controllers/user'
import { mongo } from './repository/mongo'
dotenv.config()
......@@ -22,26 +25,33 @@ class App {
public init = async (): Promise<void> => {
try {
let currentDb: IDataBase
switch(process.env.DB) {
case 'file':
currentDb = db
break
case 'postgres':
currentDb = postgresDB
break
case 'mongoDBCLient':
currentDb = mongoDBClient
break
default:
currentDb = postgresDB
}
await currentDb.init()
// let currentDb: IDataBase
// switch(process.env.DB) {
// case 'file':
// currentDb = db
// break
// case 'postgres':
// currentDb = postgresDB
// break
// case 'mongoDBCLient':
// currentDb = mongoDBClient
// break
// default:
// currentDb = postgresDB
// }
// await currentDb.init()
// process.on('exit', () => {
// currentDb.close()
// })
mongo.init()
process.on('exit', () => {
currentDb.close()
mongo.close()
})
this.app.use('/health-check', new HealthCheckController().getRouter())
this.app.use('/products', new ProductsController().getRouter())
this.app.use('/suppliers', new SuppliersController().getRouter())
this.app.use('/users', new UserController().getRouter())
this.app.listen(process.env.APP_PORT, () => {
console.log(`Server is running on port ${process.env.APP_PORT}`)
})
......
import { EStatuses } from "../enums/EStatuses";
import IProduct from "./IProduct";
export default interface IResponse {
result: IProduct[] | IProduct | undefined | null
export default interface IResponse<T> {
result: T
message: string
status: EStatuses
}
\ No newline at end of file
import {Document} from 'mongoose'
export default interface IUser extends Document {
_id: string
username: string
password: string
active: boolean
token: string
}
\ No newline at end of file
import IUSer from "./IUser";
export default interface IUserDto {
username: IUSer['username']
password: IUSer['password']
}
\ No newline at end of file
import mongoose, { Schema } from 'mongoose'
import IProduct from '../interfaces/IProduct'
const ProductSchema: Schema = new Schema<IProduct>({
product: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
description: {
type: String,
required: true
},
category_id: String,
brand_id: String,
image: String,
suppliers: [
{
type: Schema.Types.ObjectId,
ref: 'Supplier'
}
]
}, {
versionKey: false,
timestamps: true
})
export const Product = mongoose.model<IProduct>('Product', ProductSchema)
\ No newline at end of file
import mongoose, { Schema } from 'mongoose'
import ISupplier from '../interfaces/ISupplier'
const SupplierSchema: Schema = new Schema<ISupplier>({
supplier: {
type: String,
required: true
},
address: {
type: String,
required: true
},
contacts: String,
products: [
{
type: Schema.Types.ObjectId,
ref: 'Product'
}
]
}, {
versionKey: false
})
export const Supplier = mongoose.model<ISupplier>('Supplier', SupplierSchema)
\ No newline at end of file
import mongoose, { Schema } from 'mongoose'
import IUser from '../../interfaces/IUser'
import bcrypt from 'bcrypt'
import shortid from 'shortid'
const UserSchema: Schema = new Schema<IUser>({
username: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
token: {
type: String,
required: true
}
})
UserSchema.pre('save', async function(next) {
if (!this.isModified('password')) return next()
const salt = await bcrypt.genSalt(parseInt(process.env.BCRYPT_SALT || '') || 10)
const hash = await bcrypt.hash(this.password, salt)
this.password = hash
next()
})
UserSchema.set('toJSON', {
transform(doc, ret, options) {
delete ret.password
return ret
},
})
UserSchema.methods.checkPassword = async function(password: string) {
return await bcrypt.compare(password, this.password);
};
UserSchema.methods.generateToken = async function() {
this.token = shortid.generate()
};
export const User = mongoose.model<IUser>('User', UserSchema)
\ No newline at end of file
import mongoose, { Mongoose } from 'mongoose'
import dotenv from 'dotenv'
import IDataBase from '../interfaces/IDataBase'
import { EStatuses } from "../enums/EStatuses"
import IProduct from "../interfaces/IProduct"
import IProductDto from "../interfaces/IProductDto"
import IResponse from "../interfaces/IResponse"
import { Product } from "../models/mongo/Product"
import { Supplier } from '../models/mongo/Supplier'
import ISupplierDto from '../interfaces/ISupplierDto'
import ISupplier from '../interfaces/ISupplier'
import { User } from '../models/mongo/User'
import IUserDto from '../interfaces/IUserDto'
import IUser from '../interfaces/IUser'
dotenv.config()
export class Mongo implements IDataBase {
private client: Mongoose | null = null
public close = async(): Promise<void> => {
if (!this.client) return
await this.client.disconnect()
}
public init = async (): Promise<void> => {
this.client = await mongoose.connect(process.env.MONGO_CLIENT_URL || 'mongodb://localhost/myStore')
console.log('Mongo mongoose is connected')
}
public getProducts = async (): Promise<IResponse<IProduct[] | undefined>> => {
try {
const data = await Product.find().populate('suppliers', 'supplier')
const response: IResponse<IProduct[]> = {
status: EStatuses.OK,
result: data as any,
message: 'Products found'
}
return response
} catch (err: unknown) {
const error = err as Error
const response: IResponse<undefined> = {
status: EStatuses.NOT_OK,
result: undefined,
message: error.message
}
return response
}
}
public getProductById = async (id: string): Promise<IResponse<IProduct | undefined>> => {
try {
// const isExist = await Product.exists({_id: id})
const data = await Product.findById(id)
const response: IResponse<IProduct> = {
status: EStatuses.OK,
result: data as any,
message: ''
}
return response
} catch (err: unknown) {
const error = err as Error
const response: IResponse<undefined> = {
status: EStatuses.NOT_OK,
result: undefined,
message: error.message
}
return response
}
}
public addProduct = async (productDto: IProductDto): Promise<IResponse<IProduct | undefined>> => {
try {
const product = new Product(productDto)
const data = await product.save()
const response: IResponse<IProduct> = {
status: EStatuses.OK,
result: data as any,
message: ''
}
return response
} catch (err: unknown) {
const error = err as Error
const response: IResponse<undefined> = {
status: EStatuses.NOT_OK,
result: undefined,
message: error.message
}
return response
}
}
public deleteProductById = async (id: string): Promise<IResponse<IProduct | undefined>> => {
try {
const data = await Product.findOneAndDelete({_id: id})
const response: IResponse<IProduct> = {
status: EStatuses.OK,
result: data as any,
message: ''
}
return response
} catch (err: unknown) {
const error = err as Error
const response: IResponse<undefined> = {
status: EStatuses.NOT_OK,
result: undefined,
message: error.message
}
return response
}
}
public updateProductById = async (id: string, productDto: IProductDto): Promise<IResponse<IProduct | undefined>> => {
try {
const data = await Product.findOneAndUpdate({_id: id}, productDto)
// const data = await Product.findOneAndUpdate({_id: id}, {
// ...productDto,
// $pull: {suppliers: '6411a3cb02256125afc764fa'}
// })
// const data = await Product.findOneAndUpdate({_id: id}, {
// ...productDto,
// $push: {suppliers: '6411a11b8a6d2e3395c9a34a'}
// })
const response: IResponse<IProduct> = {
status: EStatuses.OK,
result: data as any,
message: ''
}
return response
} catch (err: unknown) {
const error = err as Error
const response: IResponse<undefined> = {
status: EStatuses.NOT_OK,
result: undefined,
message: error.message
}
return response
}
}
public getSuppliers = async (): Promise<IResponse<ISupplier[] | undefined>> => {
try {
const data = await Supplier.find().populate('products', 'product')
const response: IResponse<ISupplier[]> = {
status: EStatuses.OK,
result: data as any,
message: 'Suppliers found'
}
return response
} catch (err: unknown) {
const error = err as Error
const response: IResponse<undefined> = {
status: EStatuses.NOT_OK,
result: undefined,
message: error.message
}
return response
}
}
public getSupplierById = async (id: string): Promise<IResponse<ISupplier | undefined>> => {
try {
const data = await Supplier.findById(id)
const response: IResponse<ISupplier> = {
status: EStatuses.OK,
result: data as any,
message: ''
}
return response
} catch (err: unknown) {
const error = err as Error
const response: IResponse<undefined> = {
status: EStatuses.NOT_OK,
result: undefined,
message: error.message
}
return response
}
}
public addSupplier = async (supplierDto: ISupplierDto): Promise<IResponse<ISupplier | undefined>> => {
try {
const supplier = new Supplier(supplierDto)
const data = await supplier.save()
const response: IResponse<ISupplier> = {
status: EStatuses.OK,
result: data as any,
message: ''
}
return response
} catch (err: unknown) {
const error = err as Error
const response: IResponse<undefined> = {
status: EStatuses.NOT_OK,
result: undefined,
message: error.message
}
return response
}
}
public deleteSupplierById = async (id: string): Promise<IResponse<ISupplier | undefined>> => {
try {
const data = await Supplier.findOneAndDelete({_id: id})
const response: IResponse<ISupplier> = {
status: EStatuses.OK,
result: data as any,
message: ''
}
return response
} catch (err: unknown) {
const error = err as Error
const response: IResponse<undefined> = {
status: EStatuses.NOT_OK,
result: undefined,
message: error.message
}
return response
}
}
public updateSupplierById = async (id: string, supplierDto: ISupplierDto): Promise<IResponse<ISupplier | undefined>> => {
try {
const data = await Supplier.findOneAndUpdate({_id: id}, supplierDto)
const response: IResponse<ISupplier> = {
status: EStatuses.OK,
result: data as any,
message: ''
}
return response
} catch (err: unknown) {
const error = err as Error
const response: IResponse<undefined> = {
status: EStatuses.NOT_OK,
result: undefined,
message: error.message
}
return response
}
}
public createUser = async (userDto: IUserDto): Promise<IResponse<IUser | undefined>> => {
try {
const user = new User(userDto)
// @ts-ignore
user.generateToken()
const data = await user.save()
return {
status: EStatuses.OK,
result: data,
message: 'User was created'
}
} catch(err: unknown) {
return {
status: EStatuses.NOT_OK,
result: undefined,
message: '[ERROR] Cannot create user'
}
}
}
public login = async (userDto: IUserDto): Promise<IResponse<IUser | undefined>> => {
try {
const user = await User.findOne({username: userDto.username})
if (!user) {
throw new Error('Not found')
}
//@ts-ignore
const isMatch: boolean = await user.checkPassword(userDto.password)
if (!isMatch) {
throw new Error('Wrong password')
}
// @ts-ignore
user.generateToken()
await user.save()
return {
status: EStatuses.OK,
result: user,
message: 'Access granted'
}
} catch(err: unknown) {
return {
status: EStatuses.NOT_OK,
result: undefined,
message: '[ERROR] Access denied'
}
}
}
public getUsers = async (): Promise<IResponse<IUser[] | undefined>> => {
try {
const data = await User.find()
return {
status: EStatuses.OK,
result: data,
message: 'Users found'
}
} catch(err: unknown) {
return {
status: EStatuses.NOT_OK,
result: undefined,
message: '[ERROR] Cannot find users'
}
}
}
}
export const mongo = new Mongo()
\ No newline at end of file
import { EStatuses } from "../enums/EStatuses"
import IProduct from "../interfaces/IProduct"
import IProductDto from "../interfaces/IProductDto"
import IResponse from "../interfaces/IResponse"
import { db } from "../repository/fileDB"
import { Mongo, mongo } from "../repository/mongo"
export class ProductService {
public getProducts = (): IResponse => {
try {
const data = db.getItems()
const response: IResponse = {
status: EStatuses.OK,
result: data,
message: 'Products found'
}
return response
} catch (err: unknown) {
const error = err as Error
const response: IResponse = {
status: EStatuses.NOT_OK,
result: undefined,
message: error.message
}
return response
}
private repository: Mongo
constructor() {
this.repository = mongo
}
public getProductById = (id: string): IResponse => {
try {
const data: IProduct | undefined = db.getItemById(id)
const response: IResponse = {
status: EStatuses.OK,
result: data,
message: ''
}
return response
} catch (err: unknown) {
const error = err as Error
const response: IResponse = {
status: EStatuses.NOT_OK,
result: undefined,
message: error.message
}
return response
}
public getProducts = async (): Promise<IResponse<IProduct[] | undefined>> => {
return await this.repository.getProducts()
}
public addProduct = (product: IProductDto): IResponse => {
try {
const data: IProduct | undefined = db.addItem(product)
const response: IResponse = {
status: EStatuses.OK,
result: data,
message: ''
}
return response
} catch (err: unknown) {
const error = err as Error
const response: IResponse = {
status: EStatuses.NOT_OK,
result: undefined,
message: error.message
}
return response
}
public getProductById = async (id: string): Promise<IResponse<IProduct | undefined>> => {
return await this.repository.getProductById(id)
}
public addProduct = async (productDto: IProductDto): Promise<IResponse<IProduct | undefined>> => {
return await this.repository.addProduct(productDto)
}
public deleteProductById = async (id: string): Promise<IResponse<IProduct | undefined>> => {
return await this.repository.deleteProductById(id)
}
public updateProductById = async (id: string, productDto: IProductDto): Promise<IResponse<IProduct | undefined>> => {
return await this.repository.updateProductById(id, productDto)
}
}
......
import ISupplier from "../interfaces/ISupplier"
import ISupplierDto from "../interfaces/ISupplierDto"
import IResponse from "../interfaces/IResponse"
import { mongo, Mongo } from "../repository/mongo"
export class SupplierService {
private repository: Mongo
constructor() {
this.repository = mongo
}
public getSuppliers = async (): Promise<IResponse<ISupplier[] | undefined>> => {
return await this.repository.getSuppliers()
}
public getSupplierById = async (id: string): Promise<IResponse<ISupplier | undefined>> => {
return await this.repository.getSupplierById(id)
}
public addSupplier = async (supplierDto: ISupplierDto): Promise<IResponse<ISupplier | undefined>> => {
return await this.repository.addSupplier(supplierDto)
}
public deleteSupplierById = async (id: string): Promise<IResponse<ISupplier | undefined>> => {
return await this.repository.deleteSupplierById(id)
}
public updateSupplierById = async (id: string, supplierDto: ISupplierDto): Promise<IResponse<ISupplier | undefined>> => {
return await this.repository.updateSupplierById(id, supplierDto)
}
}
export const supplierService = new SupplierService()
\ No newline at end of file
import IResponse from "../interfaces/IResponse";
import IUser from "../interfaces/IUser";
import IUserDto from "../interfaces/IUserDto";
import { mongo, Mongo } from "../repository/mongo";
export class UserService {
private repository: Mongo
constructor() {
this.repository = mongo
}
public createUser = async (userDto: IUserDto): Promise<IResponse<IUser | undefined>> => {
return await this.repository.createUser(userDto)
}
public login = async (userDto: IUserDto): Promise<IResponse<IUser | undefined>> => {
return await this.repository.login(userDto)
}
public getUsers = async (): Promise<IResponse<IUser[] | undefined>> => {
return await this.repository.getUsers()
}
}
export const userService = new UserService()
\ No newline at end of file
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