import {Model, Connection} from 'mongoose'; import {Injectable, NotFoundException, BadGatewayException, ConflictException, BadRequestException, HttpException, HttpService} from '@nestjs/common'; import {InjectConnection} from '@nestjs/mongoose'; import {Store, StoreRequest, StoreSchema} from './store.schema'; import {DB_TEST_NAME, DB_NAME, COLLECTION_STORE} from 'src/consts'; import * as jwt from 'jsonwebtoken'; interface Token { login: string; agent: string; iat: number; exp: number; } const validateModel = async (store: Store) => { try { await store.validate(); } catch (e) { throw new BadGatewayException(e); } }; @Injectable() export class StoreService { constructor( @InjectConnection(DB_NAME) private dbConnection: Connection, @InjectConnection(DB_TEST_NAME) private dbTestConnection: Connection, private http: HttpService, ) {} storeModel(api: string): Model { if (api === DB_TEST_NAME) { return this.dbTestConnection.model(COLLECTION_STORE, StoreSchema); } return this.dbConnection.model(COLLECTION_STORE, StoreSchema); } async findAll(api: string): Promise { return this.storeModel(api).find().exec(); } async create(api: string, store: StoreRequest, access_token: string): Promise { const searchStore = await this.storeModel(api).findOne({key: store.key}); if (searchStore) { throw new ConflictException(`Api key "${store.key}" is already taken`); } const {login, agent} = jwt.decode(access_token) as Token; const apiPath = 'http://api.auth.vigdorov.ru/users/search/'; const headers = { Authorization: access_token, 'user-agent': agent }; try { const {data: currentUser} = await this.http.get(`${apiPath}${login}`, {headers}).toPromise(); await this.http.get(`${apiPath}${store.author}`, {headers}).toPromise(); const author = currentUser.is_admin ? store.author : login; const createdStore = new (this.storeModel(api))({ ...store, author, }); try { await validateModel(createdStore); } catch (e) { if (e?.message?.includes('validation failed')) { throw new BadRequestException(e.message); } throw e; } const savedStore = await createdStore.save(); if (!Object.keys(savedStore.value).length) { await savedStore.updateOne({value: {}}); } return savedStore; } catch (e) { if (e?.response?.data?.statusCode === 404) { throw new NotFoundException(e.response.data.message); } throw new BadRequestException(e.message); } } async update(api: string, {author, ...omitProps}: StoreRequest): Promise { const searchStore = await this.findOne(api, omitProps.key); if (searchStore) { const store = { ...omitProps, author: searchStore.author, }; const updateStore = new (this.storeModel(api))(store); try { await validateModel(updateStore); } catch (e) { if (e?.message?.includes('validation failed')) { throw new BadRequestException(e.message); } throw e; } await searchStore.updateOne({ ...store, author: searchStore.author, }); return updateStore; } throw new NotFoundException(`Not found api key "${omitProps.key}"`); } async findOne(api: string, key: string): Promise { const searchStore = await this.storeModel(api).findOne({key}); if (!searchStore) { throw new NotFoundException(`Not found api key "${key}"`); } return searchStore; } async removeOne(api: string, key: string): Promise { const searchStore = await this.findOne(api, key); if (searchStore) { await this.storeModel(api).deleteOne({key}); return searchStore; } throw new NotFoundException(`Not found api key "${key}"`); } }