users api

This commit is contained in:
vigdorov
2020-07-26 16:42:00 +03:00
parent 7c62c57f2d
commit baeded4a7a
6 changed files with 250 additions and 21 deletions

View File

@ -8,4 +8,4 @@ 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'];
export const ALLOW_HEADERS: [string, string] = ['Access-Control-Allow-Headers', 'Version, Authorization, Content-Type'];

View File

@ -1,9 +1,10 @@
import {Controller, Get, Req, Post, Options, Header, Delete, HttpCode, Put, UseInterceptors, All} from '@nestjs/common';
import {Controller, Get, Req, Post, Options, Header, Delete, HttpCode, Put} from '@nestjs/common';
import {ApiResponse, ApiTags, ApiParam, ApiBody} from '@nestjs/swagger';
import {ALLOW_ORIGIN_ALL, ALLOW_METHOD, ALLOW_CREDENTIALS, CONTENT_LENGTH, ALLOW_HEADERS, USERS_CONTROLLER} from '../consts';
import {UserService} from './users.service';
import {UserRequest} from './users.schema';
import {UserResponse, CreateUserRequest, UpdateUserRequest} from './users.schema';
import {Request} from 'express';
@Controller(USERS_CONTROLLER)
@ApiTags(USERS_CONTROLLER)
@ -17,12 +18,71 @@ export class UsersController {
@ApiResponse({
status: 200,
description: 'Список всех пользователей',
type: [UserRequest]
type: [UserResponse]
})
async findAll(): Promise<UserRequest[]> {
async findAll(): Promise<UserResponse[]> {
return this.userService.findAll();
}
@Get(':login')
@Header(...ALLOW_ORIGIN_ALL)
@ApiResponse({
status: 200,
description: 'Получить пользователя по логину'
})
@ApiParam({
name: 'login',
description: 'Логин пользователя',
})
async findOne(@Req() request: Request<{login: string}>): Promise<UserResponse> {
return await this.userService.findOne(request.params.login);
}
@Post()
@Header(...ALLOW_ORIGIN_ALL)
@ApiResponse({
status: 201,
description: 'Создает пользователя в системе',
type: UserResponse,
})
@ApiBody({
type: CreateUserRequest,
description: 'Принимает объект для создания пользователя'
})
async createUser(@Req() request: Request<null, CreateUserRequest>): Promise<UserResponse> {
return await this.userService.create(request.body);
}
@Put()
@Header(...ALLOW_ORIGIN_ALL)
@ApiResponse({
status: 200,
description: 'Обновляет данные пользователя',
type: UpdateUserRequest
})
@ApiBody({
type: UpdateUserRequest,
description: 'Принимает объект для обновления данных пользователя'
})
async updateUser(@Req() request: Request<null, UpdateUserRequest>): Promise<UserResponse> {
return await this.userService.update(request.body);
}
@Delete(':login')
@Header(...ALLOW_ORIGIN_ALL)
@ApiResponse({
status: 200,
description: 'Удаляет пользователя',
type: UpdateUserRequest,
})
@ApiParam({
name: 'login',
description: 'Логин пользователя',
})
async removeUser(@Req() request: Request<{login: string}>): Promise<UpdateUserRequest> {
return await this.userService.removeOne(request.params.login);
}
@Options()
@Header(...ALLOW_ORIGIN_ALL)
@Header(...ALLOW_METHOD)

View File

@ -1,13 +1,13 @@
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';
import {ApiProperty} from '@nestjs/swagger';
import { Document } from 'mongoose';
interface Token {
token: string;
expired_at: string;
}
export class UserRequest {
export class CreateUserRequest {
@ApiProperty()
login: string;
@ -15,7 +15,46 @@ export class UserRequest {
avatar: string;
@ApiProperty()
is_admin: string;
password: string;
}
export class UpdateUserRequest {
@ApiProperty()
login: string;
@ApiProperty()
avatar: string;
}
export class UserResponse {
@ApiProperty()
login: string;
@ApiProperty()
avatar: string;
@ApiProperty()
is_admin: boolean;
}
export class UserModel {
@ApiProperty()
login: string;
@ApiProperty()
avatar: string;
@ApiProperty()
password: string;
@ApiProperty()
is_admin: boolean;
@ApiProperty()
access_token: Token[];
@ApiProperty()
refresh_token: Token[];
}
@Schema()
@ -44,20 +83,40 @@ export class User extends Document {
is_admin: boolean;
@Prop({
type: {
type: [{
token: String,
expired_at: String,
}
}]
})
access_token: Token;
access_token: Token[];
@Prop({
type: {
type: [{
token: String,
expired_at: String,
}
}]
})
refresh_token: Token;
refresh_token: Token[];
}
@Schema()
export class UserUpdate extends Document {
@Prop({
required: true,
type: String,
})
login: string;
@Prop({
type: String,
})
avatar: string;
@Prop({
type: Boolean,
})
is_admin: boolean;
}
export const UserUpdateSchema = SchemaFactory.createForClass(UserUpdate);
export const UserSchema = SchemaFactory.createForClass(User);

View File

@ -1,20 +1,100 @@
import {Model, Connection} from 'mongoose';
import {Injectable} from '@nestjs/common';
import {Model, Connection, Document} from 'mongoose';
import {Injectable, NotFoundException, BadGatewayException} from '@nestjs/common';
import {InjectConnection} from '@nestjs/mongoose';
import {DB_NAME, USERS_CONTROLLER} from 'src/consts';
import {User, UserSchema} from './users.schema';
import {User, UserSchema, CreateUserRequest, UserResponse, UserModel, UpdateUserRequest} from './users.schema';
const validateModel = async (user: Document) => {
try {
await user.validate();
} catch (e) {
throw new BadGatewayException(e);
}
};
const prepareUserToUserModel = (user: User): UserModel => ({
login: user.login,
avatar: user.avatar,
password: user.password,
is_admin: user.is_admin,
access_token: user.access_token,
refresh_token: user.refresh_token,
});
const prepareUserToUserResponse = (user: User): UserResponse => ({
login: user.login,
avatar: user.avatar,
is_admin: user.is_admin,
});
@Injectable()
export class UserService {
constructor(
@InjectConnection(DB_NAME) private dbConnection: Connection,
) {}
get userModel(): Model<User> {
userModel(): Model<User> {
return this.dbConnection.model<User>(USERS_CONTROLLER, UserSchema);
}
findAll(): any {
return this.userModel.find().exec();
async findUser(login: string): Promise<UserModel> {
const user = await this.userModel().findOne({login});
return user ? prepareUserToUserModel(user) : user;
}
async findOne(login: string): Promise<UserResponse> {
const user = await this.userModel().findOne({login});
if (!user) {
throw new NotFoundException(`Пользователь с логином ${login} не найден`);
}
return prepareUserToUserResponse(user);
}
async findAll(): Promise<UserResponse[]> {
const users = await this.userModel().find().exec();
return users.map(prepareUserToUserResponse);
}
async create(user: CreateUserRequest): Promise<UserResponse> {
const searchUser = await this.findUser(user.login);
if (searchUser) {
throw new NotFoundException(`Пользователь с логином ${user.login} уже существует`);
}
const Model = await this.userModel();
const createUser = new Model(user);
await validateModel(createUser);
const savedUser = await createUser.save();
return prepareUserToUserResponse(savedUser);
}
async update(user: UpdateUserRequest): Promise<UserResponse> {
const searchUser = await this.userModel().findOne({login: user.login});
const Model = await this.userModel();
const updateUser = new Model({
...user,
password: searchUser.password,
});
await validateModel(updateUser);
await searchUser.updateOne({
...{
avatar: user.avatar,
},
});
return prepareUserToUserResponse(updateUser);
}
async removeOne(login: string): Promise<UserResponse> {
const searchUser = await this.userModel().findOne({login});
await this.userModel().deleteOne({login});
return prepareUserToUserResponse(searchUser);
}
}