This commit is contained in:
Николай Вигдоров
2025-03-02 12:13:01 +03:00
parent 12b3d5b23c
commit 5e91f028d9
7 changed files with 200 additions and 12 deletions

57
.http Normal file
View File

@ -0,0 +1,57 @@
### use REST Client plugin for VSCode https://marketplace.visualstudio.com/items?itemName=humao.rest-client
@host = http://localhost:4005
@user = test_user
@auth = 7b5da8a1-b64c-43ea-90f3-cdd3da507504
@storage_id = 67c420ab38fafe445411e76a
### Auth
POST {{host}}/auth HTTP/1.1
content-type: application/json
{
"login": "{{user}}"
}
### Get storages list
GET {{host}}/storages HTTP/1.1
content-type: application/json
Authorization: {{auth}}
{
"login": "test_user"
}
### Create storage
POST {{host}}/storages HTTP/1.1
content-type: application/json
Authorization: {{auth}}
{
"data": {
"users": ["ivan", "maria"],
"count": 2
},
"storageName": "users"
}
### Get storage
GET {{host}}/storages/{{storage_id}} HTTP/1.1
content-type: application/json
Authorization: {{auth}}
### Update storage
PUT {{host}}/storages/{{storage_id}} HTTP/1.1
content-type: application/json
Authorization: {{auth}}
{
"data": {
"users": ["ivan", "maria", "fedor"],
"count": 3
}
}
### Remove image
DELETE {{host}}/storages/{{storage_id}} HTTP/1.1
content-type: application/json
Authorization: {{auth}}

View File

@ -16,7 +16,13 @@ export const AUTH_ERROR: ApiResponseOptions = {
export const GET_STORAGES_LIST_SUCCESS: ApiResponseOptions = { export const GET_STORAGES_LIST_SUCCESS: ApiResponseOptions = {
status: 200, status: 200,
description: 'Список всех картинок', description: 'Список всех storage пользователя',
type: StorageResponse, type: StorageResponse,
isArray: true, isArray: true,
}; };
export const MANIPULATE_STORAGE_SUCCESS: ApiResponseOptions = {
status: 200,
description: 'Storage',
type: StorageResponse,
};

View File

@ -1,15 +1,24 @@
import { import {
Controller, Controller,
Delete,
Get, Get,
Header, Header,
HttpCode, HttpCode,
Options, Options,
Post, Post,
Put,
Req, Req,
} from '@nestjs/common'; } from '@nestjs/common';
import { Request } from 'express'; import { Request } from 'express';
import { AppService } from './app.service'; import { AppService } from './app.service';
import { ApiBody, ApiResponse, ApiSecurity, ApiTags } from '@nestjs/swagger'; import {
ApiBody,
ApiExcludeEndpoint,
ApiParam,
ApiResponse,
ApiSecurity,
ApiTags,
} from '@nestjs/swagger';
import { import {
ALLOW_CREDENTIALS, ALLOW_CREDENTIALS,
ALLOW_HEADERS, ALLOW_HEADERS,
@ -20,10 +29,11 @@ import {
import { import {
AUTH_ERROR, AUTH_ERROR,
AUTH_SUCCESS, AUTH_SUCCESS,
MANIPULATE_STORAGE_SUCCESS,
GET_STORAGES_LIST_SUCCESS, GET_STORAGES_LIST_SUCCESS,
} from './api.responses'; } from './api.responses';
import { AuthRequest } from './schemas'; import { AuthRequest, StorageCreateRequest } from './schemas';
import { Storage } from './types'; import { Storage, StorageCreate, StorageList, StorageUpdate } from './types';
@Controller() @Controller()
@ApiTags('storage-app') @ApiTags('storage-app')
@ -48,14 +58,89 @@ export class AppController {
@Header(...ALLOW_ORIGIN_ALL) @Header(...ALLOW_ORIGIN_ALL)
@ApiResponse(GET_STORAGES_LIST_SUCCESS) @ApiResponse(GET_STORAGES_LIST_SUCCESS)
@ApiResponse(AUTH_ERROR) @ApiResponse(AUTH_ERROR)
async getStorageList(@Req() request: Request): Promise<Storage[]> { async getStorageList(@Req() request: Request): Promise<StorageList> {
const { login } = await this.appService.checkRequest( const { login } = await this.appService.checkRequest(
request.headers.authorization, request.headers.authorization,
); );
return this.appService.getStorageList(login); return this.appService.getStorageList(login);
} }
@Options(['', '/auth']) @Get('/storages/:id')
@ApiSecurity('apiKey')
@ApiParam({
name: 'id',
description: 'id storage',
})
@Header(...ALLOW_ORIGIN_ALL)
@ApiResponse(MANIPULATE_STORAGE_SUCCESS)
@ApiResponse(AUTH_ERROR)
async getImageById(
@Req() request: Request<{ id: string }>,
): Promise<Storage> {
const { login } = await this.appService.checkRequest(
request.headers.authorization,
);
return this.appService.getStorageById(login, request.params.id);
}
@Post('/storages')
@ApiSecurity('apiKey')
@ApiBody({
type: StorageCreateRequest,
description: 'Объект создания storage',
})
@Header(...ALLOW_ORIGIN_ALL)
@ApiResponse(MANIPULATE_STORAGE_SUCCESS)
@ApiResponse(AUTH_ERROR)
async createImage(
@Req() request: Request<null, null, StorageCreate>,
): Promise<Storage> {
const { login } = await this.appService.checkRequest(
request.headers.authorization,
);
return this.appService.addStorage(login, request.body);
}
@Put('/storages/:id')
@ApiSecurity('apiKey')
@ApiParam({
name: 'id',
description: 'id storage',
})
@Header(...ALLOW_ORIGIN_ALL)
@ApiResponse(MANIPULATE_STORAGE_SUCCESS)
@ApiResponse(AUTH_ERROR)
async toggleLike(
@Req() request: Request<{ id: string }, null, StorageUpdate>,
): Promise<Storage> {
const { login } = await this.appService.checkRequest(
request.headers.authorization,
);
return this.appService.updateStorage(
login,
request.params.id,
request.body,
);
}
@Delete('/storages/:id')
@ApiSecurity('apiKey')
@ApiParam({
name: 'id',
description: 'id картинки',
})
@Header(...ALLOW_ORIGIN_ALL)
@ApiResponse(MANIPULATE_STORAGE_SUCCESS)
@ApiResponse(AUTH_ERROR)
async deleteImage(@Req() request: Request<{ id: string }>): Promise<Storage> {
const { login } = await this.appService.checkRequest(
request.headers.authorization,
);
return this.appService.deleteStorageById(login, request.params.id);
}
@ApiExcludeEndpoint()
@Options(['', '/auth', '/storages', '/storages/:id'])
@Header(...ALLOW_ORIGIN_ALL) @Header(...ALLOW_ORIGIN_ALL)
@Header(...ALLOW_METHOD) @Header(...ALLOW_METHOD)
@Header(...ALLOW_CREDENTIALS) @Header(...ALLOW_CREDENTIALS)

View File

@ -6,7 +6,13 @@ import {
import { InjectModel } from '@nestjs/mongoose'; import { InjectModel } from '@nestjs/mongoose';
import { StorageDocument, UserDocument } from './schemas'; import { StorageDocument, UserDocument } from './schemas';
import { Model } from 'mongoose'; import { Model } from 'mongoose';
import { User, Storage, StorageCreate, StorageUpdate } from './types'; import {
User,
Storage,
StorageCreate,
StorageUpdate,
StorageList,
} from './types';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
import { DB_STORAGES, DB_USERS } from './consts'; import { DB_STORAGES, DB_USERS } from './consts';
@ -46,12 +52,12 @@ export class AppService {
return newUser.token; return newUser.token;
} }
async getStorageList(login: string): Promise<Storage[]> { async getStorageList(login: string): Promise<StorageList> {
const storageList = await this.storageModel.find().exec(); const storageList = await this.storageModel.find().exec();
const preparedList = storageList.map(({ data, _id, user }) => ({ const preparedList = storageList.map(({ _id, user, storageName }) => ({
data,
id: _id as string, id: _id as string,
user, user,
storageName,
})); }));
return preparedList.filter(({ user }) => user === login); return preparedList.filter(({ user }) => user === login);
@ -63,6 +69,7 @@ export class AppService {
return { return {
data: searchStorage.data, data: searchStorage.data,
id: searchStorage._id as string, id: searchStorage._id as string,
storageName: searchStorage.storageName,
user: searchStorage.user, user: searchStorage.user,
}; };
} }
@ -73,6 +80,7 @@ export class AppService {
const Model = this.storageModel; const Model = this.storageModel;
const storageModel = new Model({ const storageModel = new Model({
data: storage.data, data: storage.data,
storageName: storage.storageName,
user: login, user: login,
}); });
try { try {
@ -86,6 +94,7 @@ export class AppService {
return { return {
data: newStorage.data, data: newStorage.data,
user: newStorage.user, user: newStorage.user,
storageName: newStorage.storageName,
id: newStorage._id as string, id: newStorage._id as string,
}; };
} }
@ -101,13 +110,17 @@ export class AppService {
throw new BadRequestException(`Storage с id - "${id}" не найден`); throw new BadRequestException(`Storage с id - "${id}" не найден`);
} }
const updatedStorageName = storage.storageName ?? searchStorage.storageName;
await searchStorage.updateOne({ await searchStorage.updateOne({
data: storage.data, data: storage.data,
storageName: updatedStorageName,
}); });
return { return {
data: storage.data, data: storage.data,
user: searchStorage.user, user: searchStorage.user,
storageName: updatedStorageName,
id: searchStorage._id as string, id: searchStorage._id as string,
}; };
} }
@ -124,6 +137,7 @@ export class AppService {
return { return {
data: searchStorage.data, data: searchStorage.data,
user: searchStorage.user, user: searchStorage.user,
storageName: searchStorage.storageName,
id: searchStorage._id as string, id: searchStorage._id as string,
}; };
} }

View File

@ -22,7 +22,7 @@ async function bootstrap() {
SwaggerModule.setup('api', app, document); SwaggerModule.setup('api', app, document);
await app.listen(process.env.PORT ?? 3000); await app.listen(4005);
} }
void bootstrap(); void bootstrap();

View File

@ -1,7 +1,7 @@
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
import { Document } from 'mongoose'; import { Document } from 'mongoose';
import { Storage } from './types'; import { Storage, StorageCreate } from './types';
export class AuthRequest { export class AuthRequest {
@ApiProperty() @ApiProperty()
@ -31,6 +31,12 @@ export class StorageDocument extends Document {
}) })
data: object; data: object;
@Prop({
type: String,
required: true,
})
storageName: string;
@Prop({ @Prop({
type: String, type: String,
required: true, required: true,
@ -48,6 +54,17 @@ export class StorageResponse implements Storage {
@ApiProperty() @ApiProperty()
user: string; user: string;
@ApiProperty()
storageName: string;
@ApiProperty() @ApiProperty()
id: string; id: string;
} }
export class StorageCreateRequest implements StorageCreate {
@ApiProperty()
data: object;
@ApiProperty()
storageName: string;
}

View File

@ -5,14 +5,23 @@ export type User = {
export type Storage = { export type Storage = {
data: object; data: object;
storageName: string;
user: string; user: string;
id: string; id: string;
}; };
export type StorageList = Array<{
user: string;
storageName: string;
id: string;
}>;
export type StorageCreate = { export type StorageCreate = {
data: object; data: object;
storageName: string;
}; };
export type StorageUpdate = { export type StorageUpdate = {
data: object; data: object;
storageName?: string;
}; };