Commit f9c35d8a authored by Pavel Mishakov's avatar Pavel Mishakov

webinar done BACK

parent 7c83f8b0
......@@ -13,6 +13,7 @@
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.0",
"mongodb": "^5.1.0",
"mongoose": "^7.0.3",
"multer": "^1.4.5-lts.1",
......@@ -29,6 +30,7 @@
"@types/cors": "^2.8.13",
"@types/dotenv": "^8.2.0",
"@types/express": "^4.17.17",
"@types/jsonwebtoken": "^9.0.1",
"@types/mongodb": "^4.0.7",
"@types/mongoose": "^5.11.97",
"@types/multer": "^1.4.7",
......@@ -211,6 +213,15 @@
"@types/range-parser": "*"
}
},
"node_modules/@types/jsonwebtoken": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz",
"integrity": "sha512-c5ltxazpWabia/4UzhIoaDcIza4KViOQhdbjRlfcIGVnsE3c3brkz9Z+F/EeJIECOQP7W7US2hNE930cWWkPiw==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/mime": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
......@@ -551,6 +562,11 @@
"node": ">=14.20.1"
}
},
"node_modules/buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
},
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
......@@ -786,6 +802,14 @@
"xtend": "^4.0.0"
}
},
"node_modules/ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"dependencies": {
"safe-buffer": "^5.0.1"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
......@@ -1200,6 +1224,45 @@
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"node_modules/jsonwebtoken": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz",
"integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==",
"dependencies": {
"jws": "^3.2.2",
"lodash": "^4.17.21",
"ms": "^2.1.1",
"semver": "^7.3.8"
},
"engines": {
"node": ">=12",
"npm": ">=6"
}
},
"node_modules/jsonwebtoken/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
"dependencies": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/jws": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"dependencies": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
}
},
"node_modules/kareem": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz",
......@@ -2835,6 +2898,15 @@
"@types/range-parser": "*"
}
},
"@types/jsonwebtoken": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz",
"integrity": "sha512-c5ltxazpWabia/4UzhIoaDcIza4KViOQhdbjRlfcIGVnsE3c3brkz9Z+F/EeJIECOQP7W7US2hNE930cWWkPiw==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/mime": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
......@@ -3123,6 +3195,11 @@
"resolved": "https://registry.npmjs.org/bson/-/bson-5.0.1.tgz",
"integrity": "sha512-y09gBGusgHtinMon/GVbv1J6FrXhnr/+6hqLlSmEFzkz6PodqF6TxjyvfvY3AfO+oG1mgUtbC86xSbOlwvM62Q=="
},
"buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
},
"buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
......@@ -3298,6 +3375,14 @@
"xtend": "^4.0.0"
}
},
"ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"requires": {
"safe-buffer": "^5.0.1"
}
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
......@@ -3617,6 +3702,43 @@
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"jsonwebtoken": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz",
"integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==",
"requires": {
"jws": "^3.2.2",
"lodash": "^4.17.21",
"ms": "^2.1.1",
"semver": "^7.3.8"
},
"dependencies": {
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
}
}
},
"jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
"requires": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"jws": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"requires": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
}
},
"kareem": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz",
......
......@@ -14,6 +14,7 @@
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.0",
"mongodb": "^5.1.0",
"mongoose": "^7.0.3",
"multer": "^1.4.5-lts.1",
......@@ -30,6 +31,7 @@
"@types/cors": "^2.8.13",
"@types/dotenv": "^8.2.0",
"@types/express": "^4.17.17",
"@types/jsonwebtoken": "^9.0.1",
"@types/mongodb": "^4.0.7",
"@types/mongoose": "^5.11.97",
"@types/multer": "^1.4.7",
......
import express, { Router, Request, Response } from 'express'
import multer from 'multer'
import { config } from '../index.config'
import { auth } from '../middlewares/auth'
import { productService, ProductService } from '../services/products'
const storage = multer.diskStorage({
......@@ -22,10 +23,10 @@ export class ProductsController {
constructor() {
this.router = express.Router()
this.router.get('/', this.getProducts)
this.router.get('/:id', this.getProductById)
this.router.post('/', upload.single('image'), this.addProduct)
this.router.delete('/:id', this.deleteProductById)
this.router.get('/', auth, this.getProducts)
this.router.get('/:id', auth, this.getProductById)
this.router.post('/', [auth, upload.single('image')], this.addProduct)
this.router.delete('/:id', auth, this.deleteProductById)
this.service = productService
}
......@@ -44,7 +45,6 @@ export class ProductsController {
}
private addProduct = async (req: Request, res: Response): Promise<void> => {
console.log('REQ FILE****: ', req.file)
const product = req.body
product.image = req.file ? req.file.filename : ''
const response = await this.service.addProduct(product)
......
......@@ -2,8 +2,9 @@ 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"
import { EStatuses } from "../enums/EStatuses"
import IUserGetDto from "../interfaces/IUserGetDto"
import { auth } from "../middlewares/auth"
......@@ -13,10 +14,10 @@ export class UserController {
constructor() {
this.service = userService
this.router = express.Router()
this.router.get('/', this.getUsers)
this.router.get('/', auth, this.getUsers)
this.router.post('/', this.createUser)
this.router.post('/login', this.login)
this.router.get('/token', this.checkToken)
this.router.get('/token', auth, this.checkToken)
}
......@@ -24,46 +25,28 @@ export class UserController {
return this.router
}
private createUser = async (req: Request, res: Response): Promise<void> => {
const response: IResponse<IUser | undefined> = await this.service.createUser(req.body)
const response: IResponse<IUserGetDto | 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)
const response: IResponse<IUserGetDto | 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)
}
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')})
if(!user) {
res.status(200).send({
status: EStatuses.OK,
result: undefined,
message: 'Not authorized'
})
} else {
const response: IResponse<IUser | undefined> = {
status: EStatuses.NOT_OK,
result: user,
message: 'Token is ok'
}
res.status(200).send(response)
public checkToken = async (req: Request, res: Response): Promise<void> => {
const response: IResponse<IUserGetDto | undefined> = {
status: EStatuses.NOT_OK,
//@ts-ignore
result: req.dataFromToken as IUserGetDto,
message: 'Token is ok'
}
res.status(200).send(response)
}
}
......
import jwt from 'jsonwebtoken'
export const generateJWT = (payload: {[key: string]: string | number | boolean}) => {
return jwt.sign(payload, process.env.SECRET_KEY || '', {expiresIn: '2m'})
}
\ No newline at end of file
......@@ -5,5 +5,4 @@ export default interface IUser extends Document {
username: string
password: string
active: boolean
token: string
}
\ No newline at end of file
import IUSer from "./IUser";
export default interface IUserDto {
export default interface IUserCreateDto {
username: IUSer['username']
password: IUSer['password']
}
\ No newline at end of file
import IUSer from "./IUser";
export default interface IUserGetDto {
_id: string
username: IUSer['username']
token: string
}
\ No newline at end of file
import { NextFunction, Request, Response } from "express";
import { EStatuses } from "../enums/EStatuses";
import IResponse from "../interfaces/IResponse";
import jwt from 'jsonwebtoken'
export const auth = (req: Request, res: Response, next: NextFunction) => {
if (req.method === 'OPTIONS') {
next()
}
try {
const data = jwt.verify(req.get('Authorization') || '', process.env.SECRET_KEY || '')
if (data) {
//@ts-ignore
req.dataFromToken = data
next()
} else {
const response: IResponse<undefined> = {
status: EStatuses.NOT_OK,
result: undefined,
message: 'Not authorized'
}
res.status(200).send(response)
}
} catch {
const response: IResponse<undefined> = {
status: EStatuses.NOT_OK,
result: undefined,
message: 'Not authorized'
}
res.status(200).send(response)
}
}
\ 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: {
......@@ -12,10 +11,6 @@ const UserSchema: Schema = new Schema<IUser>({
password: {
type: String,
required: true
},
token: {
type: String,
required: true
}
})
......@@ -38,9 +33,6 @@ 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
......@@ -11,8 +11,10 @@ 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 IUserCreateDto from '../interfaces/IUserCreateDto'
import IUser from '../interfaces/IUser'
import IUserGetDto from '../interfaces/IUserGetDto'
import { generateJWT } from '../helpers/generateJWT'
dotenv.config()
export class Mongo implements IDataBase {
......@@ -98,7 +100,7 @@ export class Mongo implements IDataBase {
const response: IResponse<IProduct> = {
status: EStatuses.OK,
result: data,
message: ''
message: 'Product is deleted'
}
return response
} catch (err: unknown) {
......@@ -242,7 +244,7 @@ export class Mongo implements IDataBase {
}
}
public createUser = async (userDto: IUserDto): Promise<IResponse<IUser | undefined>> => {
public createUser = async (userDto: IUserCreateDto): Promise<IResponse<IUserGetDto | undefined>> => {
try {
const exists = await User.exists({username: userDto.username})
if (exists) {
......@@ -253,10 +255,12 @@ export class Mongo implements IDataBase {
}
}
const user = new User(userDto)
// @ts-ignore
user.generateToken()
// user.token = '1234'
const data = await user.save()
await user.save()
const data = {
_id: user._id,
username: user.username,
token: generateJWT({_id: user._id, username: user.username})
}
return {
status: EStatuses.OK,
result: data,
......@@ -271,7 +275,7 @@ export class Mongo implements IDataBase {
}
}
public login = async (userDto: IUserDto): Promise<IResponse<IUser | undefined>> => {
public login = async (userDto: IUserCreateDto): Promise<IResponse<IUserGetDto | undefined>> => {
try {
const user = await User.findOne({username: userDto.username})
if (!user) {
......@@ -283,12 +287,15 @@ export class Mongo implements IDataBase {
if (!isMatch) {
throw new Error('Wrong password')
}
// @ts-ignore
user.generateToken()
const data = {
_id: user._id,
username: user.username,
token: generateJWT({_id: user._id, username: user.username})
}
await user.save()
return {
status: EStatuses.OK,
result: user,
result: data,
message: 'Access granted'
}
} catch(err: unknown) {
......
import IResponse from "../interfaces/IResponse";
import IUser from "../interfaces/IUser";
import IUserDto from "../interfaces/IUserDto";
import IUserCreateDto from "../interfaces/IUserCreateDto";
import IUserGetDto from "../interfaces/IUserGetDto";
import { mongo, Mongo } from "../repository/mongo";
......@@ -10,11 +11,11 @@ export class UserService {
this.repository = mongo
}
public createUser = async (userDto: IUserDto): Promise<IResponse<IUser | undefined>> => {
public createUser = async (userDto: IUserCreateDto): Promise<IResponse<IUserGetDto | undefined>> => {
return await this.repository.createUser(userDto)
}
public login = async (userDto: IUserDto): Promise<IResponse<IUser | undefined>> => {
public login = async (userDto: IUserCreateDto): Promise<IResponse<IUserGetDto | undefined>> => {
return await this.repository.login(userDto)
}
......
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