Files
storage-service/src/store/store.service.ts

137 lines
4.4 KiB
TypeScript

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<Store> {
if (api === DB_TEST_NAME) {
return this.dbTestConnection.model<Store>(COLLECTION_STORE, StoreSchema);
}
return this.dbConnection.model<Store>(COLLECTION_STORE, StoreSchema);
}
async findAll(api: string): Promise<Store[]> {
return this.storeModel(api).find().exec();
}
async create(api: string, store: StoreRequest, access_token: string): Promise<Store> {
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<Store> {
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<Store> {
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<Store> {
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}"`);
}
}