HM-45. Добавлена возможность использования тестового api с помощью заголовка
This commit is contained in:
@ -1,16 +1,24 @@
|
|||||||
import {Module} from '@nestjs/common';
|
import {Module} from '@nestjs/common';
|
||||||
import {MongooseModule} from '@nestjs/mongoose';
|
import {MongooseModule} from '@nestjs/mongoose';
|
||||||
import {MONGO_URL} from './consts';
|
import {MONGO_URL, DB_NAME, DB_TEST_NAME} from './consts';
|
||||||
import {StoreService} from './store/store.service';
|
import {StoreService} from './store/store.service';
|
||||||
import {Store, StoreSchema} from './store/store.schema';
|
import {Store, StoreSchema} from './store/store.schema';
|
||||||
import {StoreController} from './store/store.controller';
|
import {StoreController} from './store/store.controller';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
MongooseModule.forRoot(MONGO_URL),
|
MongooseModule.forRoot(`${MONGO_URL}/${DB_NAME}`, {
|
||||||
|
connectionName: DB_NAME,
|
||||||
|
}),
|
||||||
|
MongooseModule.forRoot(`${MONGO_URL}/${DB_TEST_NAME}`, {
|
||||||
|
connectionName: DB_TEST_NAME,
|
||||||
|
}),
|
||||||
MongooseModule.forFeature([
|
MongooseModule.forFeature([
|
||||||
{name: Store.name, schema: StoreSchema},
|
{name: Store.name, schema: StoreSchema},
|
||||||
]),
|
], DB_NAME),
|
||||||
|
MongooseModule.forFeature([
|
||||||
|
{name: Store.name, schema: StoreSchema},
|
||||||
|
], DB_TEST_NAME),
|
||||||
],
|
],
|
||||||
controllers: [
|
controllers: [
|
||||||
StoreController,
|
StoreController,
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
export const DB_NAME = '/store-service';
|
export const DB_NAME = 'store-service';
|
||||||
export const MONGO_URL = `mongodb://localhost:27017${DB_NAME}`;
|
export const DB_TEST_NAME = 'store-service-test';
|
||||||
|
export const MONGO_URL = 'mongodb://localhost:27017';
|
||||||
|
export const COOLECTION_STORE = 'store';
|
||||||
export const ALLOW_ORIGIN_ALL: [string, string] = ['Access-Control-Allow-Origin', '*'];
|
export const ALLOW_ORIGIN_ALL: [string, string] = ['Access-Control-Allow-Origin', '*'];
|
||||||
export const ALLOW_CREDENTIALS: [string, string] = ['Access-Control-Allow-Credentials', 'true'];
|
export const ALLOW_CREDENTIALS: [string, string] = ['Access-Control-Allow-Credentials', 'true'];
|
||||||
export const CONTENT_LENGTH: [string, string] = ['Content-Length', '0'];
|
export const CONTENT_LENGTH: [string, string] = ['Content-Length', '0'];
|
||||||
export const ALLOW_METHOD: [string, string] = ['Access-Control-Allow-Methods', 'GET,HEAD,PUT,PATCH,POST,DELETE'];
|
export const ALLOW_METHOD: [string, string] = ['Access-Control-Allow-Methods', 'GET,HEAD,PUT,PATCH,POST,DELETE'];
|
||||||
export const ALLOW_HEADERS: [string, string] = ['Access-Control-Allow-Headers', 'Version, Authorization, Content-Type'];
|
export const ALLOW_HEADERS: [string, string] = ['Access-Control-Allow-Headers', 'Version, Authorization, Content-Type, Api-Name'];
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import { Controller, Get, Post, Body, Param, Options, Header, Delete, HttpCode, Put } from '@nestjs/common';
|
import {Controller, Get, Req, Post, Options, Header, Delete, HttpCode, Put} from '@nestjs/common';
|
||||||
import {StoreService} from './store.service';
|
import {StoreService} from './store.service';
|
||||||
import {Store, StoreRequest} from './store.schema';
|
import {Store, StoreRequest} from './store.schema';
|
||||||
import {ApiResponse, ApiTags, ApiParam, ApiBody} from '@nestjs/swagger';
|
import {ApiResponse, ApiTags, ApiParam, ApiBody} from '@nestjs/swagger';
|
||||||
import {ALLOW_ORIGIN_ALL, ALLOW_METHOD, ALLOW_CREDENTIALS, CONTENT_LENGTH, ALLOW_HEADERS} from 'src/consts';
|
import {ALLOW_ORIGIN_ALL, ALLOW_METHOD, ALLOW_CREDENTIALS, CONTENT_LENGTH, ALLOW_HEADERS, COOLECTION_STORE} from 'src/consts';
|
||||||
|
import {Request} from 'express';
|
||||||
|
|
||||||
const prepareStoreToStoreRequest = ({
|
const prepareStoreToStoreRequest = ({
|
||||||
key, value, description, service_name, author
|
key, value, description, service_name, author
|
||||||
@ -10,8 +11,13 @@ const prepareStoreToStoreRequest = ({
|
|||||||
key, value, description, service_name, author,
|
key, value, description, service_name, author,
|
||||||
});
|
});
|
||||||
|
|
||||||
@Controller('store')
|
const makeApiHeader = (request: Request): string => {
|
||||||
@ApiTags('store')
|
const apiHeader = request.headers?.['api-name'];
|
||||||
|
return typeof apiHeader === 'string' ? apiHeader : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
@Controller(COOLECTION_STORE)
|
||||||
|
@ApiTags(COOLECTION_STORE)
|
||||||
export class StoreController {
|
export class StoreController {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly storeService: StoreService
|
private readonly storeService: StoreService
|
||||||
@ -24,8 +30,9 @@ export class StoreController {
|
|||||||
description: 'Список всех пар ключ-значение',
|
description: 'Список всех пар ключ-значение',
|
||||||
type: [StoreRequest],
|
type: [StoreRequest],
|
||||||
})
|
})
|
||||||
async findAll(): Promise<StoreRequest[]> {
|
async findAll(@Req() request: Request): Promise<StoreRequest[]> {
|
||||||
const storeList = await this.storeService.findAll();
|
const api = makeApiHeader(request);
|
||||||
|
const storeList = await this.storeService.findAll(api);
|
||||||
return storeList.map(prepareStoreToStoreRequest);
|
return storeList.map(prepareStoreToStoreRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,8 +47,10 @@ export class StoreController {
|
|||||||
name: 'key',
|
name: 'key',
|
||||||
description: 'Уникальный ключ для получения api',
|
description: 'Уникальный ключ для получения api',
|
||||||
})
|
})
|
||||||
async findOne(@Param() {key}: {key: string}): Promise<StoreRequest> {
|
async findOne(@Req() request: Request<{key: string}>): Promise<StoreRequest> {
|
||||||
const store = await this.storeService.findOne(key);
|
const {key} = request.params;
|
||||||
|
const api = makeApiHeader(request);
|
||||||
|
const store = await this.storeService.findOne(api, key);
|
||||||
return prepareStoreToStoreRequest(store);
|
return prepareStoreToStoreRequest(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,8 +65,9 @@ export class StoreController {
|
|||||||
type: StoreRequest,
|
type: StoreRequest,
|
||||||
description: 'Принимает объект для создания api'
|
description: 'Принимает объект для создания api'
|
||||||
})
|
})
|
||||||
async create(@Body() createStoreClass: StoreRequest): Promise<StoreRequest> {
|
async create(@Req() request: Request<null, StoreRequest>): Promise<StoreRequest> {
|
||||||
const store = await this.storeService.create(createStoreClass);
|
const api = makeApiHeader(request);
|
||||||
|
const store = await this.storeService.create(api, request.body);
|
||||||
return prepareStoreToStoreRequest(store);
|
return prepareStoreToStoreRequest(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,8 +82,9 @@ export class StoreController {
|
|||||||
type: StoreRequest,
|
type: StoreRequest,
|
||||||
description: 'Принимает объект для обновления api'
|
description: 'Принимает объект для обновления api'
|
||||||
})
|
})
|
||||||
async update(@Body() updateStoreClass: StoreRequest): Promise<StoreRequest> {
|
async update(@Req() request: Request<null, StoreRequest>): Promise<StoreRequest> {
|
||||||
const store = await this.storeService.update(updateStoreClass);
|
const api = makeApiHeader(request);
|
||||||
|
const store = await this.storeService.update(api, request.body);
|
||||||
return prepareStoreToStoreRequest(store);
|
return prepareStoreToStoreRequest(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,8 +99,10 @@ export class StoreController {
|
|||||||
name: 'key',
|
name: 'key',
|
||||||
description: 'Уникальный ключ для удаления api',
|
description: 'Уникальный ключ для удаления api',
|
||||||
})
|
})
|
||||||
async removeOne(@Param() {key}: {key: string}): Promise<StoreRequest> {
|
async removeOne(@Req() request: Request<{key: string}>): Promise<StoreRequest> {
|
||||||
const store = await this.storeService.removeOne(key);
|
const {key} = request.params;
|
||||||
|
const api = makeApiHeader(request);
|
||||||
|
const store = await this.storeService.removeOne(api, key);
|
||||||
return prepareStoreToStoreRequest(store);
|
return prepareStoreToStoreRequest(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import {Model} from 'mongoose';
|
import {Model, Connection} from 'mongoose';
|
||||||
import {Injectable, NotFoundException, BadGatewayException} from '@nestjs/common';
|
import {Injectable, NotFoundException, BadGatewayException} from '@nestjs/common';
|
||||||
import {InjectModel} from '@nestjs/mongoose';
|
import {InjectConnection} from '@nestjs/mongoose';
|
||||||
import {Store, StoreRequest} from './store.schema';
|
import {Store, StoreRequest, StoreSchema} from './store.schema';
|
||||||
|
import {DB_TEST_NAME, DB_NAME, COOLECTION_STORE} from 'src/consts';
|
||||||
|
|
||||||
const validateModel = async (store: Store) => {
|
const validateModel = async (store: Store) => {
|
||||||
try {
|
try {
|
||||||
@ -13,20 +14,30 @@ const validateModel = async (store: Store) => {
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class StoreService {
|
export class StoreService {
|
||||||
constructor(@InjectModel(Store.name) private storeModel: Model<Store>) {}
|
constructor(
|
||||||
|
@InjectConnection(DB_NAME) private dbConnection: Connection,
|
||||||
|
@InjectConnection(DB_TEST_NAME) private dbTestConnection: Connection,
|
||||||
|
) {}
|
||||||
|
|
||||||
async findAll(): Promise<Store[]> {
|
storeModel(api: string): Model<Store> {
|
||||||
return this.storeModel.find().exec();
|
if (api === DB_TEST_NAME) {
|
||||||
|
return this.dbTestConnection.model<Store>(COOLECTION_STORE, StoreSchema);
|
||||||
|
}
|
||||||
|
return this.dbConnection.model<Store>(COOLECTION_STORE, StoreSchema);
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(store: StoreRequest): Promise<Store> {
|
async findAll(api: string): Promise<Store[]> {
|
||||||
const searchStore = await this.findOne(store.key);
|
return this.storeModel(api).find().exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(api: string, store: StoreRequest): Promise<Store> {
|
||||||
|
const searchStore = await this.findOne(api, store.key);
|
||||||
|
|
||||||
if (searchStore) {
|
if (searchStore) {
|
||||||
throw new NotFoundException(`Api key ${store.key} is already taken`);
|
throw new NotFoundException(`Api key ${store.key} is already taken`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const createdStore = new this.storeModel(store);
|
const createdStore = new (this.storeModel(api))(store);
|
||||||
|
|
||||||
await validateModel(createdStore);
|
await validateModel(createdStore);
|
||||||
|
|
||||||
@ -37,15 +48,15 @@ export class StoreService {
|
|||||||
return savedStore;
|
return savedStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
async update({author, ...omitProps}: StoreRequest): Promise<Store> {
|
async update(api: string, {author, ...omitProps}: StoreRequest): Promise<Store> {
|
||||||
const searchStore = await this.findOne(omitProps.key);
|
const searchStore = await this.findOne(api, omitProps.key);
|
||||||
|
|
||||||
if (searchStore) {
|
if (searchStore) {
|
||||||
const store = {
|
const store = {
|
||||||
...omitProps,
|
...omitProps,
|
||||||
author: searchStore.author,
|
author: searchStore.author,
|
||||||
};
|
};
|
||||||
const updateStore = new this.storeModel(store);
|
const updateStore = new (this.storeModel(api))(store);
|
||||||
await validateModel(updateStore);
|
await validateModel(updateStore);
|
||||||
|
|
||||||
await searchStore.updateOne({
|
await searchStore.updateOne({
|
||||||
@ -59,15 +70,15 @@ export class StoreService {
|
|||||||
throw new NotFoundException(`Not Found api key - ${omitProps.key}`);
|
throw new NotFoundException(`Not Found api key - ${omitProps.key}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOne(key: string): Promise<Store> {
|
async findOne(api: string, key: string): Promise<Store> {
|
||||||
return this.storeModel.findOne({key})
|
return this.storeModel(api).findOne({key})
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeOne(key: string): Promise<Store> {
|
async removeOne(api: string, key: string): Promise<Store> {
|
||||||
const searchStore = await this.findOne(key);
|
const searchStore = await this.findOne(api, key);
|
||||||
|
|
||||||
if (searchStore) {
|
if (searchStore) {
|
||||||
await this.storeModel.deleteOne({key});
|
await this.storeModel(api).deleteOne({key});
|
||||||
|
|
||||||
return searchStore;
|
return searchStore;
|
||||||
}
|
}
|
||||||
|
|||||||
11
store.http
11
store.http
@ -1,13 +1,16 @@
|
|||||||
GET http://localhost:4001/store HTTP/1.1
|
GET http://localhost:4001/store HTTP/1.1
|
||||||
|
Api-Name: store-service-test
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|
||||||
GET http://localhost:4001/store/testApi22 HTTP/1.1
|
GET http://localhost:4001/store/testApi-4 HTTP/1.1
|
||||||
|
Api-Name: store-service-test
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|
||||||
POST http://localhost:4001/store HTTP/1.1
|
POST http://localhost:4001/store HTTP/1.1
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
|
Api-Name: store-service-test
|
||||||
|
|
||||||
{
|
{
|
||||||
"key": "testApi-4",
|
"key": "testApi-4",
|
||||||
@ -23,17 +26,19 @@ content-type: application/json
|
|||||||
|
|
||||||
PUT http://localhost:4001/store HTTP/1.1
|
PUT http://localhost:4001/store HTTP/1.1
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
|
Api-Name: store-service-test
|
||||||
|
|
||||||
{
|
{
|
||||||
"key": "testApi-4",
|
"key": "testApi-4",
|
||||||
"value": {
|
"value": {
|
||||||
|
|
||||||
},
|
},
|
||||||
"description": "тестовое апи",
|
"description": "тестовое апи22",
|
||||||
"service_name": "test-api",
|
"service_name": "test-api",
|
||||||
"author": "vigdorov23422"
|
"author": "vigdorov23422"
|
||||||
}
|
}
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|
||||||
DELETE http://localhost:4001/store/testApi22 HTTP/1.1
|
DELETE http://localhost:4001/store/testApi-4 HTTP/1.1
|
||||||
|
Api-Name: store-service-test
|
||||||
Reference in New Issue
Block a user