Skip to content

Instantly share code, notes, and snippets.

@masterr115
Created March 4, 2024 20:06
Show Gist options
  • Save masterr115/799424fd6be54f0a239243d9e9dd89e8 to your computer and use it in GitHub Desktop.
Save masterr115/799424fd6be54f0a239243d9e9dd89e8 to your computer and use it in GitHub Desktop.
import core, { TypedBody, TypedRoute } from '@nestia/core';
import {
BadRequestException,
Controller,
Req,
UseGuards,
} from '@nestjs/common';
import { TypeGuardError } from 'typia';
import { IError } from '@utils/exceptions/IError';
import { AuthService } from '@services/auth/auth.service';
import { ILoginUser } from '@modules/auth/dto/ILoginUser';
import { ILogoutUser } from '@modules/auth/dto/ILogoutUser';
import { IRefreshToken } from '@modules/auth/dto/IRefreshToken';
import { JwtAuthGuard } from '@modules/auth/guards/jwt-auth.guard';
import { RefreshTokenGuard } from '@modules/auth/guards/refreshToken.guard';
import { UserJwtPayload } from '@modules/auth/strategy/user-jwt-payload';
@Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
/**
* Login User
*
* Login user with credentials
*
* @assignHeaders authorization
* @returns {ILoginUser.ILoginResponse} - Login response
*
* @summary Authorization api to login
* @tag Auth
*/
@TypedRoute.Post('/login')
@core.TypedException<TypeGuardError.IProps>(400, 'Invalid request')
@core.TypedException<IError>(401, 'Invalid credentials')
@core.TypedException<IError>(404, 'User not found')
async login(
@TypedBody() body: ILoginUser.ILogin,
): Promise<ILoginUser.ILoginResponse> {
return await this.authService.login(body);
}
/**
* Logout User
*
* Logout user from all devices
* @setHeader authorization.access_token Authorization
*
* @returns {ILogoutUser.ILogoutResponse} - Logout response
*
* @summary Authorization api to logout
* @security bearer
* @tag Auth
*/
@TypedRoute.Post('/logout')
@core.TypedException<IError>(404, 'User not found')
@core.TypedException<IError>(403, 'Unauthorized')
@UseGuards(JwtAuthGuard)
async logout(
@Req() req,
@TypedBody() body: ILogoutUser.ILogout,
): Promise<ILogoutUser.ILogoutResponse> {
const user: UserJwtPayload = req.user;
return await this.authService.logout(user.id, body.deviceId);
}
/**
* Refresh Token
*
* Refresh token for user
*
* @assignHeaders authorization
* @setHeader authorization.refresh_token Authorization
* @param {IRefreshToken.IRefreshTokenHeaders} headers - Refresh token headers
* @returns {IRefreshToken.IRefreshResponse} - Refresh response
*
* @summary Authorization api to refresh token
* @security bearer
* @tag Auth
*/
@TypedRoute.Post('/refresh')
@core.TypedException<IError>(404, 'User not found')
@core.TypedException<IError>(403, 'Unauthorized')
@UseGuards(RefreshTokenGuard)
async refresh(
@Req() req,
@core.TypedHeaders()
headers: IRefreshToken.IRefreshTokenHeaders,
): Promise<IRefreshToken.IRefreshResponse> {
const user: UserJwtPayload = req.user;
const refreshToken = req.user['refreshToken'];
const device = headers.deviceId;
if (!device) throw new BadRequestException('Device not found');
return await this.authService.refreshTokens(user, device, refreshToken);
}
}
import {
Controller,
Req,
UseGuards,
Param,
BadRequestException,
} from '@nestjs/common';
import core, {
TypedBody,
TypedFormData,
TypedParam,
TypedQuery,
TypedRoute,
} from '@nestia/core';
import { JwtAuthGuard } from '@modules/auth/guards/jwt-auth.guard';
import { UserJwtPayload } from '@modules/auth/strategy/user-jwt-payload';
import { CreateGroupService } from '@services/group/create-group.service';
import { FindGroupService } from '@services/group/find-group.service';
import GroupAdminGuard from '@modules/group/guards/group-admin.guard';
import { PictureGroupService } from '@services/group/picture-group.service';
import { UpdateGroupService } from '@services/group/update-group.service';
import GroupMemberGuard from '@modules/group/guards/group-member.guard';
import { ICreateGroup } from '@modules/group/dto/ICreateGroup';
import { IPage } from '@utils/pagination';
import { IFindGroup } from '@modules/group/dto/IFindGroup';
import { IPictureGroup } from '@modules/group/dto/IPictureGroup';
import { IUpdateGroup } from '@modules/group/dto/IUpdateGroup';
import { IError } from '@utils/exceptions/IError';
import { TypeGuardError } from 'typia';
@Controller('group')
export class GroupController {
constructor(
private readonly findGroupService: FindGroupService,
private readonly createGroupService: CreateGroupService,
private readonly pictureGroupService: PictureGroupService,
private readonly updateGroupService: UpdateGroupService,
) {}
/**
* Get recommended groups
*
* Get recommended groups to user
*
* @setHeader authorization.access_token Authorization
* @returns {IFindGroup.IFindRecommendedGroups} - Recommended groups
*
* @summary Get recommended groups to user
* @tag Groups
* @security bearer
*/
@TypedRoute.Get('/recommended')
@core.TypedException<IError>(401, 'Unauthorized')
@UseGuards(JwtAuthGuard)
async getRecommendedGroups(
@Req() req,
@TypedQuery() pageOptionsDto: IPage.IPageOptions,
): Promise<IFindGroup.IFindRecommendedGroups> {
const user: UserJwtPayload = req.user;
return await this.findGroupService.getRecommendedGroups(
user,
pageOptionsDto,
);
}
/**
* Create a group
*
* Create a group
*
* @setHeader authorization.access_token Authorization
* @returns {ICreateGroup.ICreateResponse} - Create response
*
* @summary Create a group
* @tag Groups
* @security bearer
*/
@TypedRoute.Post('/create')
@core.TypedException<TypeGuardError.IProps>(400, 'Invalid request body')
@core.TypedException<IError>(401, 'Unauthorized')
@core.TypedException<IError>(404, 'Interest not found')
@UseGuards(JwtAuthGuard)
async createGroup(
@Req() req,
@TypedBody() body: ICreateGroup.ICreate,
): Promise<ICreateGroup.ICreateResponse> {
const user: UserJwtPayload = req.user;
return await this.createGroupService.create(user, body);
}
/**
* Change group picture
*
* Change group picture
*
* @setHeader authorization.access_token Authorization
* @returns {IPictureGroup.IUploadGroupPictureResponse} - Upload picture response
*
* @summary Change group picture
* @tag Groups
* @security bearer
*/
@TypedRoute.Patch('/picture/:id')
@core.TypedException<TypeGuardError.IProps>(400, 'Invalid request body')
@core.TypedException<TypeGuardError.IProps>(404, 'Group not found')
@core.TypedException<IError>(401, 'Unauthorized')
@UseGuards(JwtAuthGuard, GroupAdminGuard())
async changeGroupPicture(
@Param('id') id: string,
@TypedFormData.Body()
file: IPictureGroup.IUploadGroupPicture,
): Promise<IPictureGroup.IUploadGroupPictureResponse> {
if (
file.file.type !== 'image/jpeg' &&
file.file.type !== 'image/png' &&
file.file.type !== 'image/gif'
) {
throw new BadRequestException('Only image files are allowed!');
}
const fileBuffer = Buffer.from(await file.file.arrayBuffer());
const filePayload = {
file: fileBuffer,
originalname: file.file.name,
filename: file.file.name,
mimeType: file.file.type,
size: file.file.size,
};
return await this.pictureGroupService.uploadGroupPicture(id, filePayload);
}
/**
* Remove group picture
*
* Remove group picture
*
* @setHeader authorization.access_token Authorization
* @returns {IPictureGroup.IDeleteGroupPictureResponse} - Delete picture response
*
* @summary Remove group picture
* @tag Groups
* @security bearer
*/
@TypedRoute.Delete('/picture/:id')
@core.TypedException<TypeGuardError.IProps>(400, 'Invalid request body')
@core.TypedException<TypeGuardError.IProps>(404, 'Group not found')
@core.TypedException<IError>(401, 'Unauthorized')
@UseGuards(JwtAuthGuard, GroupAdminGuard())
async deleteGroupAvatar(
@Param('id') id: string,
): Promise<IPictureGroup.IDeleteGroupPictureResponse> {
return await this.pictureGroupService.deleteGroupAvatar(id);
}
/**
* Update a group
*
* Update a group
*
* @setHeader authorization.access_token Authorization
* @returns {IUpdateGroup.IUpdateResponse} - Update response
*
* @summary Update a group
* @tag Groups
* @security bearer
*/
@TypedRoute.Patch('/update/:id')
@core.TypedException<TypeGuardError.IProps>(400, 'Invalid request body')
@core.TypedException<TypeGuardError.IProps>(
409,
'Group username already exists',
)
@core.TypedException<TypeGuardError.IProps>(404, 'Group not found')
@core.TypedException<IError>(401, 'Unauthorized')
@UseGuards(JwtAuthGuard, GroupAdminGuard())
async updateGroup(
@Req() req,
@TypedParam('id') id: string,
@TypedBody() body: IUpdateGroup.IUpdate,
): Promise<IUpdateGroup.IUpdateResponse> {
return await this.updateGroupService.updateGroupReq(id, body);
}
/**
*
*
* Get group members
*
* @setHeader authorization.access_token Authorization
* @returns {IFindGroup.IFindGroupMembers} - Group members
*
* @summary Get group members
* @tag Groups
* @security bearer
*/
@TypedRoute.Get('/members/:id')
@core.TypedException<TypeGuardError.IProps>(404, 'Group not found')
@core.TypedException<IError>(401, 'Unauthorized')
@UseGuards(JwtAuthGuard, GroupMemberGuard())
async getGroupMembers(
@Req() req,
@TypedParam('id') id: string,
@TypedQuery() pageOptionsDto: IPage.IPageOptions,
): Promise<IFindGroup.IFindGroupMembers> {
return await this.findGroupService.findGroupMembers(id, pageOptionsDto);
}
/**
* Get group by id
*
* Get group by id
*
* @setHeader authorization.access_token Authorization
* @returns {IFindGroup.IFindGroupById} - Group by id
*
* @summary Get group by id
* @tag Groups
* @security bearer
*/
@TypedRoute.Get('/byId/:id')
@core.TypedException<TypeGuardError.IProps>(404, 'Group not found')
@core.TypedException<IError>(401, 'Unauthorized')
@UseGuards(JwtAuthGuard, GroupMemberGuard())
async getGroupById(
@Req() req,
@TypedParam('id') id: string,
): Promise<IFindGroup.IFindGroupById> {
return await this.findGroupService.getGroupById(id);
}
}
import { tags } from 'typia';
import { GroupRecurrenceEnum } from '@models/group_info.entity';
export interface ICreateGroup
extends ICreateGroup.ICreate,
ICreateGroup.ICreateResponse {}
export namespace ICreateGroup {
export interface ICreate {
name: string;
description?: string;
username: string;
idInterest: string & tags.Format<'uuid'>;
info: CreateGroupInfo;
}
export interface CreateGroupInfo {
notifications: boolean;
welcomeMessage: boolean;
welcomeMessageText?: string;
private: boolean;
isPaid?: boolean;
price?: number;
recurrence?: GroupRecurrenceEnum;
}
export interface ICreateResponse {
success: boolean;
id: string & tags.Format<'uuid'>;
}
}
import { tags } from 'typia';
export interface LoginUser {
id: string & tags.Format<'uuid'>;
username: string;
firstName: string;
lastName: string;
picture: (string & tags.Format<'url'>) | null | undefined;
}
export interface ILoginUser
extends ILoginUser.ILogin,
ILoginUser.ILoginResponse {}
export namespace ILoginUser {
export interface ILogin {
ddi: string;
ddd: string;
phone: string;
passCode: string;
deviceId: string;
ipAddress: (string & tags.Format<'ipv4'>) | (string & tags.Format<'ipv6'>);
}
export interface ILoginResponse {
authorization: {
access_token: string;
refresh_token: string;
};
user: LoginUser;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment