Copy import {
Inject,
HttpException,
HttpStatus,
Controller,
UseGuards,
UsePipes,
Get,
Post,
Body,
Req,
Patch,
Query,
Param,
Delete,
} from '@nestjs/common';
import { Request } from 'express';
import { InjectQueue } from '@nestjs/bull';
import { Queue } from 'bull';
import {
queuePool,
JoiValidationPipe,
CoreService,
AppHostService,
JsonWebTokenService
} from 'niro-health';
import EmailNameJob from './jobs/constants/email/emailNameJob';
import AccountActivateProcess from './jobs/constants/email/accountActivateProcess';
import { AccountActivateType } from './jobs/types/email/accountActivate';
import { AccountActivateOptions } from './jobs/configs/email/accountActivate';
import { RolesGuard } from './guards/roles.guard';
// import { Roles } from './guards/roles.decorator';
import { TokenGuard } from './guards/token.guard';
// import { Token } from './guards/token.decorator';
import { UsersService } from './users.service';
import { UsersParser } from './parsers';
import type { CreateUserDto } from './dto/create';
import type { ActivateUserDto } from './dto/activate';
import type { LoginUserDto } from './dto/login';
import type { SessionValidateUserDto } from './dto/sessionValidate';
import type { LogoutUserDto } from './dto/logout';
import type { UpdateUserDto } from './dto/update';
import { CreateUserSchema } from './dto/schemas/create.joi';
import { ActivateUserSchema } from './dto/schemas/activate.joi';
import { LoginUserSchema } from './dto/schemas/login.joi';
import { SessionValidateUserSchema } from './dto/schemas/sessionValidate.joi';
import { LogoutUserSchema } from './dto/schemas/logout.joi';
import { UpdateUserSchema } from './dto/schemas/update.joi';
@Controller('api/users')
@UseGuards(RolesGuard, TokenGuard)
export class UsersController {
constructor(
@InjectQueue(EmailNameJob)
private readonly emailQueue: Queue<AccountActivateType>,
private readonly coreService: CoreService,
private readonly appHostService: AppHostService,
@Inject('IUsersService') private readonly usersService: UsersService,
@Inject('IUsersParser') private readonly usersParser: UsersParser,
) {
queuePool.add(emailQueue);
}
@Post()
@UsePipes(new JoiValidationPipe(CreateUserSchema))
async create(@Body() createUserDto: CreateUserDto) {
const user = await this.usersService.create(createUserDto);
if (user instanceof Error)
throw new HttpException(user.message, HttpStatus.FORBIDDEN);
try {
await this.emailQueue.add(
AccountActivateProcess,
{
email: createUserDto.email,
username: createUserDto.username,
token: this.appHostService.app
.get<JsonWebTokenService>('IJsonWebTokenService')
.save(
{
id: user.id,
username: user.username,
timestamp: new Date().getTime(),
},
null,
`7d`,
) as string,
temporarypass: null,
},
AccountActivateOptions,
);
return this.usersParser.toJSON(user);
} catch (error) {
throw new HttpException(error.message, HttpStatus.FORBIDDEN);
}
}
@Post('activate')
@UsePipes(new JoiValidationPipe(ActivateUserSchema))
async activate(@Body() activateUserDto: ActivateUserDto) {
const token = this.appHostService.app
.get<JsonWebTokenService>('IJsonWebTokenService')
.load(activateUserDto.token, null);
if (token instanceof Error)
throw new HttpException(
'Account activation token is invalid. Please try again.',
HttpStatus.FORBIDDEN,
);
const { id } = token as { id: string };
const user = await this.usersService.activate(id);
if (user instanceof Error)
throw new HttpException(user.message, HttpStatus.FORBIDDEN);
return true;
}
@Post('auth/login')
@UsePipes(new JoiValidationPipe(LoginUserSchema))
async login(@Body() loginUserDto: LoginUserDto, @Req() request: Request) {
const clientGeoIP = await this.coreService.getClientGeoIP(request);
const user = await this.usersService.login(
loginUserDto.email,
loginUserDto.password,
clientGeoIP.device_name,
{
...clientGeoIP,
token_signature: '',
},
);
if (user instanceof Error)
throw new HttpException(user.message, HttpStatus.FORBIDDEN);
return this.usersParser.toJSON(user);
}
@Post('auth/validate')
@UsePipes(new JoiValidationPipe(SessionValidateUserSchema))
async sessionValidate(
@Body() sessionValidateUserDto: SessionValidateUserDto,
@Req() request: Request,
) {
const clientGeoIP = await this.coreService.getClientGeoIP(request);
const session = await this.usersService.sessionValidate(
sessionValidateUserDto.id,
sessionValidateUserDto.token_value,
sessionValidateUserDto.token_signature,
sessionValidateUserDto.token_revalidate_value,
sessionValidateUserDto.token_revalidate_signature,
clientGeoIP.device_name,
{
...clientGeoIP,
token_signature: sessionValidateUserDto.token_signature,
},
);
if (session instanceof Error)
throw new HttpException(session.message, HttpStatus.FORBIDDEN);
return session;
}
@Post('auth/logout')
@UsePipes(new JoiValidationPipe(LogoutUserSchema))
async logout(@Body() logoutUserDto: LogoutUserDto) {
const session = await this.usersService.logout(
logoutUserDto.id,
logoutUserDto.token_value,
);
if (session instanceof Error)
throw new HttpException(session.message, HttpStatus.FORBIDDEN);
return true;
}
@Get()
async findAll(@Query('limit') limit: string, @Query('skip') skip: string) {
return (
await this.usersService.findAll(
limit && parseInt(limit),
skip && parseInt(skip),
)
).map((user) => this.usersParser.toJSON(user));
}
@Get(':id')
async findOne(@Param('id') id: string) {
const user = await this.usersService.findOne(id);
if (user instanceof Error)
throw new HttpException(user.message, HttpStatus.FORBIDDEN);
return this.usersParser.toJSON(user);
}
@Patch(':id')
async update(
@Param('id') id: string,
@Body(new JoiValidationPipe(UpdateUserSchema))
updateUserDto: UpdateUserDto,
) {
const user = await this.usersService.update(id, updateUserDto);
if (user instanceof Error)
throw new HttpException(user.message, HttpStatus.FORBIDDEN);
return this.usersParser.toJSON(user);
}
@Delete(':id')
async delete(@Param('id') id: string) {
const deleted = await this.usersService.delete(id);
if (deleted instanceof Error)
throw new HttpException(deleted.message, HttpStatus.FORBIDDEN);
return deleted;
}
}