add service and first method to controller
This commit is contained in:
22
src/api.responses.ts
Normal file
22
src/api.responses.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { ApiResponseOptions } from '@nestjs/swagger';
|
||||
import { StorageResponse } from './schemas';
|
||||
|
||||
export const AUTH_SUCCESS: ApiResponseOptions = {
|
||||
status: 200,
|
||||
description: 'Токен пользователя',
|
||||
type: String,
|
||||
};
|
||||
|
||||
export const AUTH_ERROR: ApiResponseOptions = {
|
||||
status: 406,
|
||||
description:
|
||||
'Ошибка, при попытке получить доступ к данным без токена или с не корректным токеном',
|
||||
type: Error,
|
||||
};
|
||||
|
||||
export const GET_STORAGES_LIST_SUCCESS: ApiResponseOptions = {
|
||||
status: 200,
|
||||
description: 'Список всех картинок',
|
||||
type: StorageResponse,
|
||||
isArray: true,
|
||||
};
|
||||
@ -1,12 +1,68 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Header,
|
||||
HttpCode,
|
||||
Options,
|
||||
Post,
|
||||
Req,
|
||||
} from '@nestjs/common';
|
||||
import { Request } from 'express';
|
||||
import { AppService } from './app.service';
|
||||
import { ApiBody, ApiResponse, ApiSecurity, ApiTags } from '@nestjs/swagger';
|
||||
import {
|
||||
ALLOW_CREDENTIALS,
|
||||
ALLOW_HEADERS,
|
||||
ALLOW_METHOD,
|
||||
ALLOW_ORIGIN_ALL,
|
||||
CONTENT_LENGTH,
|
||||
} from './consts';
|
||||
import {
|
||||
AUTH_ERROR,
|
||||
AUTH_SUCCESS,
|
||||
GET_STORAGES_LIST_SUCCESS,
|
||||
} from './api.responses';
|
||||
import { AuthRequest } from './schemas';
|
||||
import { Storage } from './types';
|
||||
|
||||
@Controller()
|
||||
@ApiTags('storage-app')
|
||||
export class AppController {
|
||||
constructor(private readonly appService: AppService) {}
|
||||
|
||||
@Get()
|
||||
getHello(): string {
|
||||
return this.appService.getHello();
|
||||
@Post('/auth')
|
||||
@ApiBody({
|
||||
type: AuthRequest,
|
||||
description: 'Объект с логином пользователя',
|
||||
})
|
||||
@Header(...ALLOW_ORIGIN_ALL)
|
||||
@ApiResponse(AUTH_SUCCESS)
|
||||
authUser(
|
||||
@Req() request: Request<null, null, { login: string }>,
|
||||
): Promise<string> {
|
||||
return this.appService.authUser(request.body.login);
|
||||
}
|
||||
|
||||
@Get('/storages')
|
||||
@ApiSecurity('apiKey')
|
||||
@Header(...ALLOW_ORIGIN_ALL)
|
||||
@ApiResponse(GET_STORAGES_LIST_SUCCESS)
|
||||
@ApiResponse(AUTH_ERROR)
|
||||
async getStorageList(@Req() request: Request): Promise<Storage[]> {
|
||||
const { login } = await this.appService.checkRequest(
|
||||
request.headers.authorization,
|
||||
);
|
||||
return this.appService.getStorageList(login);
|
||||
}
|
||||
|
||||
@Options(['', '/auth'])
|
||||
@Header(...ALLOW_ORIGIN_ALL)
|
||||
@Header(...ALLOW_METHOD)
|
||||
@Header(...ALLOW_CREDENTIALS)
|
||||
@Header(...CONTENT_LENGTH)
|
||||
@Header(...ALLOW_HEADERS)
|
||||
@HttpCode(204)
|
||||
async options(): Promise<string> {
|
||||
return await Promise.resolve('');
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,32 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
import { MongooseModule } from '@nestjs/mongoose';
|
||||
import { DB_STORAGES, DB_USERS, MONGO_URL } from './consts';
|
||||
import {
|
||||
StorageDocument,
|
||||
StorageScheme,
|
||||
UserDocument,
|
||||
UserScheme,
|
||||
} from './schemas';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
imports: [
|
||||
MongooseModule.forRoot(`${MONGO_URL}/${DB_USERS}`, {
|
||||
connectionName: DB_USERS,
|
||||
}),
|
||||
MongooseModule.forRoot(`${MONGO_URL}/${DB_STORAGES}`, {
|
||||
connectionName: DB_STORAGES,
|
||||
}),
|
||||
MongooseModule.forFeature(
|
||||
[{ name: UserDocument.name, schema: UserScheme }],
|
||||
DB_USERS,
|
||||
),
|
||||
MongooseModule.forFeature(
|
||||
[{ name: StorageDocument.name, schema: StorageScheme }],
|
||||
DB_STORAGES,
|
||||
),
|
||||
],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
})
|
||||
|
||||
@ -1,8 +1,130 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import {
|
||||
BadRequestException,
|
||||
Injectable,
|
||||
NotAcceptableException,
|
||||
} from '@nestjs/common';
|
||||
import { InjectModel } from '@nestjs/mongoose';
|
||||
import { StorageDocument, UserDocument } from './schemas';
|
||||
import { Model } from 'mongoose';
|
||||
import { User, Storage, StorageCreate, StorageUpdate } from './types';
|
||||
import { v4 } from 'uuid';
|
||||
import { DB_STORAGES, DB_USERS } from './consts';
|
||||
|
||||
@Injectable()
|
||||
export class AppService {
|
||||
getHello(): string {
|
||||
return 'Hello World!';
|
||||
constructor(
|
||||
@InjectModel(UserDocument.name, DB_USERS)
|
||||
private userModel: Model<UserDocument>,
|
||||
@InjectModel(StorageDocument.name, DB_STORAGES)
|
||||
private storageModel: Model<StorageDocument>,
|
||||
) {}
|
||||
|
||||
async checkRequest(token?: string): Promise<User> {
|
||||
const userList = await this.userModel.find().exec();
|
||||
const searchUser = userList.find((user) => user.token === token);
|
||||
if (searchUser) {
|
||||
return {
|
||||
login: searchUser.login,
|
||||
token: searchUser.token,
|
||||
};
|
||||
}
|
||||
throw new NotAcceptableException(`Доступ запрещен`);
|
||||
}
|
||||
|
||||
async authUser(login: string): Promise<string> {
|
||||
const userList = await this.userModel.find().exec();
|
||||
const searchUser = userList.find((user) => user.login === login);
|
||||
if (searchUser) {
|
||||
return searchUser.token;
|
||||
}
|
||||
const Model = this.userModel;
|
||||
const userModel = new Model({
|
||||
login,
|
||||
token: v4(),
|
||||
});
|
||||
const newUser = await userModel.save();
|
||||
return newUser.token;
|
||||
}
|
||||
|
||||
async getStorageList(login: string): Promise<Storage[]> {
|
||||
const storageList = await this.storageModel.find().exec();
|
||||
const preparedList = storageList.map(({ data, _id, user }) => ({
|
||||
data,
|
||||
id: _id as string,
|
||||
user,
|
||||
}));
|
||||
|
||||
return preparedList.filter(({ user }) => user === login);
|
||||
}
|
||||
|
||||
async getStorageById(login: string, id: string): Promise<Storage> {
|
||||
const searchStorage = await this.storageModel.findById(id);
|
||||
if (searchStorage && searchStorage.user === login) {
|
||||
return {
|
||||
data: searchStorage.data,
|
||||
id: searchStorage._id as string,
|
||||
user: searchStorage.user,
|
||||
};
|
||||
}
|
||||
throw new BadRequestException(`Storage с id - "${id}" не найдена`);
|
||||
}
|
||||
|
||||
async addStorage(login: string, storage: StorageCreate): Promise<Storage> {
|
||||
const Model = this.storageModel;
|
||||
const storageModel = new Model({
|
||||
data: storage.data,
|
||||
user: login,
|
||||
});
|
||||
try {
|
||||
await storageModel.validate();
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
throw new BadRequestException(e.message);
|
||||
}
|
||||
|
||||
const newStorage = await storageModel.save();
|
||||
return {
|
||||
data: newStorage.data,
|
||||
user: newStorage.user,
|
||||
id: newStorage._id as string,
|
||||
};
|
||||
}
|
||||
|
||||
async updateStorage(
|
||||
login: string,
|
||||
id: string,
|
||||
storage: StorageUpdate,
|
||||
): Promise<Storage> {
|
||||
const searchStorage = await this.storageModel.findById(id);
|
||||
|
||||
if (!searchStorage || searchStorage.user !== login) {
|
||||
throw new BadRequestException(`Storage с id - "${id}" не найден`);
|
||||
}
|
||||
|
||||
await searchStorage.updateOne({
|
||||
data: storage.data,
|
||||
});
|
||||
|
||||
return {
|
||||
data: storage.data,
|
||||
user: searchStorage.user,
|
||||
id: searchStorage._id as string,
|
||||
};
|
||||
}
|
||||
|
||||
async deleteStorageById(login: string, id: string): Promise<Storage> {
|
||||
const searchStorage = await this.storageModel.findById(id);
|
||||
if (!searchStorage || searchStorage.user !== login) {
|
||||
throw new BadRequestException(`Storage с id - "${id}" не найден`);
|
||||
}
|
||||
const Model = this.storageModel;
|
||||
|
||||
await Model.findByIdAndDelete(id);
|
||||
|
||||
return {
|
||||
data: searchStorage.data,
|
||||
user: searchStorage.user,
|
||||
id: searchStorage._id as string,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
24
src/consts.ts
Normal file
24
src/consts.ts
Normal file
@ -0,0 +1,24 @@
|
||||
export const MONGO_URL = 'mongodb://localhost:27017';
|
||||
|
||||
export const APP_CONTROLLER = 'storage-app';
|
||||
|
||||
export const DB_USERS = 'storage-back-users';
|
||||
export const DB_STORAGES = 'storage-back-storages';
|
||||
|
||||
export const ALLOW_ORIGIN_ALL: [string, string] = [
|
||||
'Access-Control-Allow-Origin',
|
||||
'*',
|
||||
];
|
||||
export const ALLOW_CREDENTIALS: [string, string] = [
|
||||
'Access-Control-Allow-Credentials',
|
||||
'true',
|
||||
];
|
||||
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_HEADERS: [string, string] = [
|
||||
'Access-Control-Allow-Headers',
|
||||
'Version, Authorization, Content-Type, Api-Name, x-turbo-id, x-turbo-compression, chrome-proxy, chrome-proxy-ect',
|
||||
];
|
||||
22
src/main.ts
22
src/main.ts
@ -1,8 +1,28 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { AppModule } from './app.module';
|
||||
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
||||
import { APP_CONTROLLER } from './consts';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule);
|
||||
|
||||
const options = new DocumentBuilder()
|
||||
.addSecurity('apiKey', {
|
||||
type: 'apiKey',
|
||||
in: 'header',
|
||||
name: 'Authorization',
|
||||
})
|
||||
.setTitle('Storage API')
|
||||
.setDescription('API для работы с хранилищами')
|
||||
.setVersion('1.0.0')
|
||||
.addTag(APP_CONTROLLER)
|
||||
.build();
|
||||
|
||||
const document = SwaggerModule.createDocument(app, options);
|
||||
|
||||
SwaggerModule.setup('api', app, document);
|
||||
|
||||
await app.listen(process.env.PORT ?? 3000);
|
||||
}
|
||||
bootstrap();
|
||||
|
||||
void bootstrap();
|
||||
|
||||
53
src/schemas.ts
Normal file
53
src/schemas.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Document } from 'mongoose';
|
||||
import { Storage } from './types';
|
||||
|
||||
export class AuthRequest {
|
||||
@ApiProperty()
|
||||
login: string;
|
||||
}
|
||||
|
||||
@Schema()
|
||||
export class UserDocument extends Document {
|
||||
@Prop({
|
||||
type: String,
|
||||
required: true,
|
||||
})
|
||||
login: string;
|
||||
|
||||
@Prop({
|
||||
type: String,
|
||||
required: true,
|
||||
})
|
||||
token: string;
|
||||
}
|
||||
|
||||
@Schema()
|
||||
export class StorageDocument extends Document {
|
||||
@Prop({
|
||||
type: Object,
|
||||
required: true,
|
||||
})
|
||||
data: object;
|
||||
|
||||
@Prop({
|
||||
type: String,
|
||||
required: true,
|
||||
})
|
||||
user: string;
|
||||
}
|
||||
|
||||
export const StorageScheme = SchemaFactory.createForClass(StorageDocument);
|
||||
export const UserScheme = SchemaFactory.createForClass(UserDocument);
|
||||
|
||||
export class StorageResponse implements Storage {
|
||||
@ApiProperty()
|
||||
data: object;
|
||||
|
||||
@ApiProperty()
|
||||
user: string;
|
||||
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
}
|
||||
18
src/types.ts
Normal file
18
src/types.ts
Normal file
@ -0,0 +1,18 @@
|
||||
export type User = {
|
||||
login: string;
|
||||
token: string;
|
||||
};
|
||||
|
||||
export type Storage = {
|
||||
data: object;
|
||||
user: string;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export type StorageCreate = {
|
||||
data: object;
|
||||
};
|
||||
|
||||
export type StorageUpdate = {
|
||||
data: object;
|
||||
};
|
||||
Reference in New Issue
Block a user