refactor(server): auth decorator (#2588)
This commit is contained in:
parent
e7ad622c02
commit
ffe397247e
11 changed files with 62 additions and 71 deletions
|
@ -1,7 +1,7 @@
|
|||
import { Controller, Get, Post, Body, Param, Delete, Put, Query, Response } from '@nestjs/common';
|
||||
import { ParseMeUUIDPipe } from '../validation/parse-me-uuid-pipe';
|
||||
import { AlbumService } from './album.service';
|
||||
import { Authenticated } from '../../decorators/authenticated.decorator';
|
||||
import { Authenticated, SharedLinkRoute } from '../../decorators/authenticated.decorator';
|
||||
import { AuthUserDto, GetAuthUser } from '../../decorators/auth-user.decorator';
|
||||
import { AddAssetsDto } from './dto/add-assets.dto';
|
||||
import { AddUsersDto } from './dto/add-users.dto';
|
||||
|
@ -32,24 +32,23 @@ const handleDownload = (download: DownloadArchive, res: Res) => {
|
|||
|
||||
@ApiTags('Album')
|
||||
@Controller('album')
|
||||
@Authenticated()
|
||||
@UseValidation()
|
||||
export class AlbumController {
|
||||
constructor(private readonly service: AlbumService) {}
|
||||
|
||||
@Authenticated()
|
||||
@Get('count-by-user-id')
|
||||
getAlbumCountByUserId(@GetAuthUser() authUser: AuthUserDto): Promise<AlbumCountResponseDto> {
|
||||
return this.service.getCountByUserId(authUser);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Put(':id/users')
|
||||
addUsersToAlbum(@GetAuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto, @Body() dto: AddUsersDto) {
|
||||
// TODO: Handle nonexistent sharedUserIds.
|
||||
return this.service.addUsers(authUser, id, dto);
|
||||
}
|
||||
|
||||
@Authenticated({ isShared: true })
|
||||
@SharedLinkRoute()
|
||||
@Put(':id/assets')
|
||||
addAssetsToAlbum(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
|
@ -61,13 +60,12 @@ export class AlbumController {
|
|||
return this.service.addAssets(authUser, id, dto);
|
||||
}
|
||||
|
||||
@Authenticated({ isShared: true })
|
||||
@SharedLinkRoute()
|
||||
@Get(':id')
|
||||
getAlbumInfo(@GetAuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto) {
|
||||
return this.service.get(authUser, id);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Delete(':id/assets')
|
||||
removeAssetFromAlbum(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
|
@ -77,7 +75,6 @@ export class AlbumController {
|
|||
return this.service.removeAssets(authUser, id, dto);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Delete(':id/user/:userId')
|
||||
removeUserFromAlbum(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
|
@ -87,7 +84,7 @@ export class AlbumController {
|
|||
return this.service.removeUser(authUser, id, userId);
|
||||
}
|
||||
|
||||
@Authenticated({ isShared: true })
|
||||
@SharedLinkRoute()
|
||||
@Get(':id/download')
|
||||
@ApiOkResponse({ content: { 'application/zip': { schema: { type: 'string', format: 'binary' } } } })
|
||||
downloadArchive(
|
||||
|
@ -100,7 +97,6 @@ export class AlbumController {
|
|||
return this.service.downloadArchive(authUser, id, dto).then((download) => handleDownload(download, res));
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Post('create-shared-link')
|
||||
createAlbumSharedLink(@GetAuthUser() authUser: AuthUserDto, @Body() dto: CreateAlbumSharedLinkDto) {
|
||||
return this.service.createSharedLink(authUser, dto);
|
||||
|
|
|
@ -19,7 +19,7 @@ import {
|
|||
StreamableFile,
|
||||
ParseFilePipe,
|
||||
} from '@nestjs/common';
|
||||
import { Authenticated } from '../../decorators/authenticated.decorator';
|
||||
import { Authenticated, SharedLinkRoute } from '../../decorators/authenticated.decorator';
|
||||
import { AssetService } from './asset.service';
|
||||
import { FileFieldsInterceptor } from '@nestjs/platform-express';
|
||||
import { AuthUserDto, GetAuthUser } from '../../decorators/auth-user.decorator';
|
||||
|
@ -68,10 +68,11 @@ function asStreamableFile({ stream, type, length }: ImmichReadStream) {
|
|||
|
||||
@ApiTags('Asset')
|
||||
@Controller('asset')
|
||||
@Authenticated()
|
||||
export class AssetController {
|
||||
constructor(private assetService: AssetService) {}
|
||||
|
||||
@Authenticated({ isShared: true })
|
||||
@SharedLinkRoute()
|
||||
@Post('upload')
|
||||
@UseInterceptors(
|
||||
FileFieldsInterceptor(
|
||||
|
@ -116,7 +117,7 @@ export class AssetController {
|
|||
return responseDto;
|
||||
}
|
||||
|
||||
@Authenticated({ isShared: true })
|
||||
@SharedLinkRoute()
|
||||
@Get('/download/:assetId')
|
||||
@ApiOkResponse({ content: { 'application/octet-stream': { schema: { type: 'string', format: 'binary' } } } })
|
||||
async downloadFile(
|
||||
|
@ -127,7 +128,7 @@ export class AssetController {
|
|||
return this.assetService.downloadFile(authUser, assetId).then(asStreamableFile);
|
||||
}
|
||||
|
||||
@Authenticated({ isShared: true })
|
||||
@SharedLinkRoute()
|
||||
@Post('/download-files')
|
||||
@ApiOkResponse({ content: { 'application/octet-stream': { schema: { type: 'string', format: 'binary' } } } })
|
||||
async downloadFiles(
|
||||
|
@ -148,7 +149,7 @@ export class AssetController {
|
|||
/**
|
||||
* Current this is not used in any UI element
|
||||
*/
|
||||
@Authenticated({ isShared: true })
|
||||
@SharedLinkRoute()
|
||||
@Get('/download-library')
|
||||
@ApiOkResponse({ content: { 'application/octet-stream': { schema: { type: 'string', format: 'binary' } } } })
|
||||
async downloadLibrary(
|
||||
|
@ -165,7 +166,7 @@ export class AssetController {
|
|||
return stream;
|
||||
}
|
||||
|
||||
@Authenticated({ isShared: true })
|
||||
@SharedLinkRoute()
|
||||
@Get('/file/:assetId')
|
||||
@Header('Cache-Control', 'max-age=31536000')
|
||||
@ApiOkResponse({ content: { 'application/octet-stream': { schema: { type: 'string', format: 'binary' } } } })
|
||||
|
@ -180,7 +181,7 @@ export class AssetController {
|
|||
return this.assetService.serveFile(authUser, assetId, query, res, headers);
|
||||
}
|
||||
|
||||
@Authenticated({ isShared: true })
|
||||
@SharedLinkRoute()
|
||||
@Get('/thumbnail/:assetId')
|
||||
@Header('Cache-Control', 'max-age=31536000')
|
||||
@ApiOkResponse({ content: { 'application/octet-stream': { schema: { type: 'string', format: 'binary' } } } })
|
||||
|
@ -195,25 +196,21 @@ export class AssetController {
|
|||
return this.assetService.getAssetThumbnail(assetId, query, res, headers);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Get('/curated-objects')
|
||||
async getCuratedObjects(@GetAuthUser() authUser: AuthUserDto): Promise<CuratedObjectsResponseDto[]> {
|
||||
return this.assetService.getCuratedObject(authUser);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Get('/curated-locations')
|
||||
async getCuratedLocations(@GetAuthUser() authUser: AuthUserDto): Promise<CuratedLocationsResponseDto[]> {
|
||||
return this.assetService.getCuratedLocation(authUser);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Get('/search-terms')
|
||||
async getAssetSearchTerms(@GetAuthUser() authUser: AuthUserDto): Promise<string[]> {
|
||||
return this.assetService.getAssetSearchTerm(authUser);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Post('/search')
|
||||
async searchAsset(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
|
@ -222,7 +219,6 @@ export class AssetController {
|
|||
return this.assetService.searchAsset(authUser, searchAssetDto);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Post('/count-by-time-bucket')
|
||||
async getAssetCountByTimeBucket(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
|
@ -231,13 +227,11 @@ export class AssetController {
|
|||
return this.assetService.getAssetCountByTimeBucket(authUser, getAssetCountByTimeGroupDto);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Get('/count-by-user-id')
|
||||
async getAssetCountByUserId(@GetAuthUser() authUser: AuthUserDto): Promise<AssetCountByUserIdResponseDto> {
|
||||
return this.assetService.getAssetCountByUserId(authUser);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Get('/stat/archive')
|
||||
async getArchivedAssetCountByUserId(@GetAuthUser() authUser: AuthUserDto): Promise<AssetCountByUserIdResponseDto> {
|
||||
return this.assetService.getArchivedAssetCountByUserId(authUser);
|
||||
|
@ -245,7 +239,6 @@ export class AssetController {
|
|||
/**
|
||||
* Get all AssetEntity belong to the user
|
||||
*/
|
||||
@Authenticated()
|
||||
@Get('/')
|
||||
@ApiHeader({
|
||||
name: 'if-none-match',
|
||||
|
@ -260,7 +253,6 @@ export class AssetController {
|
|||
return this.assetService.getAllAssets(authUser, dto);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Post('/time-bucket')
|
||||
async getAssetByTimeBucket(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
|
@ -272,7 +264,6 @@ export class AssetController {
|
|||
/**
|
||||
* Get all asset of a device that are in the database, ID only.
|
||||
*/
|
||||
@Authenticated()
|
||||
@Get('/:deviceId')
|
||||
async getUserAssetsByDeviceId(@GetAuthUser() authUser: AuthUserDto, @Param() { deviceId }: DeviceIdDto) {
|
||||
return await this.assetService.getUserAssetsByDeviceId(authUser, deviceId);
|
||||
|
@ -281,7 +272,7 @@ export class AssetController {
|
|||
/**
|
||||
* Get a single asset's information
|
||||
*/
|
||||
@Authenticated({ isShared: true })
|
||||
@SharedLinkRoute()
|
||||
@Get('/assetById/:assetId')
|
||||
async getAssetById(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
|
@ -294,7 +285,6 @@ export class AssetController {
|
|||
/**
|
||||
* Update an asset
|
||||
*/
|
||||
@Authenticated()
|
||||
@Put('/:assetId')
|
||||
async updateAsset(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
|
@ -305,7 +295,6 @@ export class AssetController {
|
|||
return await this.assetService.updateAsset(authUser, assetId, dto);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Delete('/')
|
||||
async deleteAsset(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
|
@ -318,7 +307,7 @@ export class AssetController {
|
|||
/**
|
||||
* Check duplicated asset before uploading - for Web upload used
|
||||
*/
|
||||
@Authenticated({ isShared: true })
|
||||
@SharedLinkRoute()
|
||||
@Post('/check')
|
||||
@HttpCode(200)
|
||||
async checkDuplicateAsset(
|
||||
|
@ -331,7 +320,6 @@ export class AssetController {
|
|||
/**
|
||||
* Checks if multiple assets exist on the server and returns all existing - used by background backup
|
||||
*/
|
||||
@Authenticated()
|
||||
@Post('/exist')
|
||||
@HttpCode(200)
|
||||
async checkExistingAssets(
|
||||
|
@ -344,7 +332,6 @@ export class AssetController {
|
|||
/**
|
||||
* Checks if assets exist by checksums
|
||||
*/
|
||||
@Authenticated()
|
||||
@Post('/bulk-upload-check')
|
||||
@HttpCode(200)
|
||||
bulkUploadCheck(
|
||||
|
@ -354,7 +341,6 @@ export class AssetController {
|
|||
return this.assetService.bulkUploadCheck(authUser, dto);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Post('/shared-link')
|
||||
async createAssetsSharedLink(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
|
@ -363,7 +349,7 @@ export class AssetController {
|
|||
return await this.assetService.createAssetsSharedLink(authUser, dto);
|
||||
}
|
||||
|
||||
@Authenticated({ isShared: true })
|
||||
@SharedLinkRoute()
|
||||
@Patch('/shared-link/add')
|
||||
async addAssetsToSharedLink(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
|
@ -372,7 +358,7 @@ export class AssetController {
|
|||
return await this.assetService.addAssetsToSharedLink(authUser, dto);
|
||||
}
|
||||
|
||||
@Authenticated({ isShared: true })
|
||||
@SharedLinkRoute()
|
||||
@Patch('/shared-link/remove')
|
||||
async removeAssetsFromSharedLink(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
|
|
|
@ -8,9 +8,9 @@ import { AuthUserDto, GetAuthUser } from '../../decorators/auth-user.decorator';
|
|||
import { mapTag, TagResponseDto } from '@app/domain';
|
||||
import { UUIDParamDto } from '../../controllers/dto/uuid-param.dto';
|
||||
|
||||
@Authenticated()
|
||||
@ApiTags('Tag')
|
||||
@Controller('tag')
|
||||
@Authenticated()
|
||||
export class TagController {
|
||||
constructor(private readonly tagService: TagService) {}
|
||||
|
||||
|
|
|
@ -19,16 +19,18 @@ import { Body, Controller, Delete, Get, Param, Post, Req, Res } from '@nestjs/co
|
|||
import { ApiBadRequestResponse, ApiTags } from '@nestjs/swagger';
|
||||
import { Request, Response } from 'express';
|
||||
import { GetAuthUser, GetLoginDetails } from '../decorators/auth-user.decorator';
|
||||
import { Authenticated } from '../decorators/authenticated.decorator';
|
||||
import { Authenticated, PublicRoute } from '../decorators/authenticated.decorator';
|
||||
import { UseValidation } from '../decorators/use-validation.decorator';
|
||||
import { UUIDParamDto } from './dto/uuid-param.dto';
|
||||
|
||||
@ApiTags('Authentication')
|
||||
@Controller('auth')
|
||||
@Authenticated()
|
||||
@UseValidation()
|
||||
export class AuthController {
|
||||
constructor(private readonly service: AuthService) {}
|
||||
|
||||
@PublicRoute()
|
||||
@Post('login')
|
||||
async login(
|
||||
@Body() loginCredential: LoginCredentialDto,
|
||||
|
@ -40,43 +42,38 @@ export class AuthController {
|
|||
return response;
|
||||
}
|
||||
|
||||
@PublicRoute()
|
||||
@Post('admin-sign-up')
|
||||
@ApiBadRequestResponse({ description: 'The server already has an admin' })
|
||||
adminSignUp(@Body() signUpCredential: SignUpDto): Promise<AdminSignupResponseDto> {
|
||||
return this.service.adminSignUp(signUpCredential);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Get('devices')
|
||||
getAuthDevices(@GetAuthUser() authUser: AuthUserDto): Promise<AuthDeviceResponseDto[]> {
|
||||
return this.service.getDevices(authUser);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Delete('devices')
|
||||
logoutAuthDevices(@GetAuthUser() authUser: AuthUserDto): Promise<void> {
|
||||
return this.service.logoutDevices(authUser);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Delete('devices/:id')
|
||||
logoutAuthDevice(@GetAuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
||||
return this.service.logoutDevice(authUser, id);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Post('validateToken')
|
||||
validateAccessToken(): ValidateAccessTokenResponseDto {
|
||||
return { authStatus: true };
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Post('change-password')
|
||||
changePassword(@GetAuthUser() authUser: AuthUserDto, @Body() dto: ChangePasswordDto): Promise<UserResponseDto> {
|
||||
return this.service.changePassword(authUser, dto);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Post('logout')
|
||||
logout(
|
||||
@Req() req: Request,
|
||||
|
|
|
@ -12,15 +12,17 @@ import { Body, Controller, Get, HttpStatus, Post, Redirect, Req, Res } from '@ne
|
|||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { Request, Response } from 'express';
|
||||
import { GetAuthUser, GetLoginDetails } from '../decorators/auth-user.decorator';
|
||||
import { Authenticated } from '../decorators/authenticated.decorator';
|
||||
import { Authenticated, PublicRoute } from '../decorators/authenticated.decorator';
|
||||
import { UseValidation } from '../decorators/use-validation.decorator';
|
||||
|
||||
@ApiTags('OAuth')
|
||||
@Controller('oauth')
|
||||
@Authenticated()
|
||||
@UseValidation()
|
||||
export class OAuthController {
|
||||
constructor(private service: OAuthService) {}
|
||||
|
||||
@PublicRoute()
|
||||
@Get('mobile-redirect')
|
||||
@Redirect()
|
||||
mobileRedirect(@Req() req: Request) {
|
||||
|
@ -30,11 +32,13 @@ export class OAuthController {
|
|||
};
|
||||
}
|
||||
|
||||
@PublicRoute()
|
||||
@Post('config')
|
||||
generateConfig(@Body() dto: OAuthConfigDto): Promise<OAuthConfigResponseDto> {
|
||||
return this.service.generateConfig(dto);
|
||||
}
|
||||
|
||||
@PublicRoute()
|
||||
@Post('callback')
|
||||
async callback(
|
||||
@Res({ passthrough: true }) res: Response,
|
||||
|
@ -46,13 +50,11 @@ export class OAuthController {
|
|||
return response;
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Post('link')
|
||||
link(@GetAuthUser() authUser: AuthUserDto, @Body() dto: OAuthCallbackDto): Promise<UserResponseDto> {
|
||||
return this.service.link(authUser, dto);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Post('unlink')
|
||||
unlink(@GetAuthUser() authUser: AuthUserDto): Promise<UserResponseDto> {
|
||||
return this.service.unlink(authUser);
|
||||
|
|
|
@ -8,11 +8,11 @@ import { UUIDParamDto } from './dto/uuid-param.dto';
|
|||
|
||||
@ApiTags('Partner')
|
||||
@Controller('partner')
|
||||
@Authenticated()
|
||||
@UseValidation()
|
||||
export class PartnerController {
|
||||
constructor(private service: PartnerService) {}
|
||||
|
||||
@Authenticated()
|
||||
@Get()
|
||||
@ApiQuery({ name: 'direction', type: 'string', enum: PartnerDirection, required: true })
|
||||
getPartners(
|
||||
|
@ -22,13 +22,11 @@ export class PartnerController {
|
|||
return this.service.getAll(authUser, direction);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Post(':id')
|
||||
createPartner(@GetAuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto): Promise<UserResponseDto> {
|
||||
return this.service.create(authUser, id);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Delete(':id')
|
||||
removePartner(@GetAuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
||||
return this.service.remove(authUser, id);
|
||||
|
|
|
@ -7,32 +7,34 @@ import {
|
|||
} from '@app/domain';
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { Authenticated } from '../decorators/authenticated.decorator';
|
||||
import { AdminRoute, Authenticated, PublicRoute } from '../decorators/authenticated.decorator';
|
||||
import { UseValidation } from '../decorators/use-validation.decorator';
|
||||
|
||||
@ApiTags('Server Info')
|
||||
@Controller('server-info')
|
||||
@Authenticated()
|
||||
@UseValidation()
|
||||
export class ServerInfoController {
|
||||
constructor(private service: ServerInfoService) {}
|
||||
|
||||
@Authenticated()
|
||||
@Get()
|
||||
getServerInfo(): Promise<ServerInfoResponseDto> {
|
||||
return this.service.getInfo();
|
||||
}
|
||||
|
||||
@PublicRoute()
|
||||
@Get('/ping')
|
||||
pingServer(): ServerPingResponse {
|
||||
return this.service.ping();
|
||||
}
|
||||
|
||||
@PublicRoute()
|
||||
@Get('/version')
|
||||
getServerVersion(): ServerVersionReponseDto {
|
||||
return this.service.getVersion();
|
||||
}
|
||||
|
||||
@Authenticated({ admin: true })
|
||||
@AdminRoute()
|
||||
@Get('/stats')
|
||||
getStats(): Promise<ServerStatsResponseDto> {
|
||||
return this.service.getStats();
|
||||
|
|
|
@ -2,29 +2,28 @@ import { AuthUserDto, EditSharedLinkDto, SharedLinkResponseDto, ShareService } f
|
|||
import { Body, Controller, Delete, Get, Param, Patch } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { GetAuthUser } from '../decorators/auth-user.decorator';
|
||||
import { Authenticated } from '../decorators/authenticated.decorator';
|
||||
import { Authenticated, SharedLinkRoute } from '../decorators/authenticated.decorator';
|
||||
import { UseValidation } from '../decorators/use-validation.decorator';
|
||||
import { UUIDParamDto } from './dto/uuid-param.dto';
|
||||
|
||||
@ApiTags('share')
|
||||
@Controller('share')
|
||||
@Authenticated()
|
||||
@UseValidation()
|
||||
export class SharedLinkController {
|
||||
constructor(private readonly service: ShareService) {}
|
||||
|
||||
@Authenticated()
|
||||
@Get()
|
||||
getAllSharedLinks(@GetAuthUser() authUser: AuthUserDto): Promise<SharedLinkResponseDto[]> {
|
||||
return this.service.getAll(authUser);
|
||||
}
|
||||
|
||||
@Authenticated({ isShared: true })
|
||||
@SharedLinkRoute()
|
||||
@Get('me')
|
||||
getMySharedLink(@GetAuthUser() authUser: AuthUserDto): Promise<SharedLinkResponseDto> {
|
||||
return this.service.getMine(authUser);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Get(':id')
|
||||
getSharedLinkById(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
|
@ -33,13 +32,11 @@ export class SharedLinkController {
|
|||
return this.service.getById(authUser, id, true);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Delete(':id')
|
||||
removeSharedLink(@GetAuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
||||
return this.service.remove(authUser, id);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Patch(':id')
|
||||
editSharedLink(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
|
|
|
@ -14,7 +14,7 @@ import {
|
|||
Header,
|
||||
} from '@nestjs/common';
|
||||
import { UserService } from '@app/domain';
|
||||
import { Authenticated } from '../decorators/authenticated.decorator';
|
||||
import { AdminRoute, Authenticated, PublicRoute } from '../decorators/authenticated.decorator';
|
||||
import { AuthUserDto, GetAuthUser } from '../decorators/auth-user.decorator';
|
||||
import { CreateUserDto } from '@app/domain';
|
||||
import { UpdateUserDto } from '@app/domain';
|
||||
|
@ -32,58 +32,55 @@ import { UserIdDto } from '@app/domain/user/dto/user-id.dto';
|
|||
|
||||
@ApiTags('User')
|
||||
@Controller('user')
|
||||
@Authenticated()
|
||||
@UseValidation()
|
||||
export class UserController {
|
||||
constructor(private service: UserService) {}
|
||||
|
||||
@Authenticated()
|
||||
@Get()
|
||||
getAllUsers(@GetAuthUser() authUser: AuthUserDto, @Query('isAll') isAll: boolean): Promise<UserResponseDto[]> {
|
||||
return this.service.getAllUsers(authUser, isAll);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Get('/info/:userId')
|
||||
getUserById(@Param() { userId }: UserIdDto): Promise<UserResponseDto> {
|
||||
return this.service.getUserById(userId);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Get('me')
|
||||
getMyUserInfo(@GetAuthUser() authUser: AuthUserDto): Promise<UserResponseDto> {
|
||||
return this.service.getUserInfo(authUser);
|
||||
}
|
||||
|
||||
@Authenticated({ admin: true })
|
||||
@AdminRoute()
|
||||
@Post()
|
||||
createUser(@Body() createUserDto: CreateUserDto): Promise<UserResponseDto> {
|
||||
return this.service.createUser(createUserDto);
|
||||
}
|
||||
|
||||
@PublicRoute()
|
||||
@Get('/count')
|
||||
getUserCount(@Query() dto: UserCountDto): Promise<UserCountResponseDto> {
|
||||
return this.service.getUserCount(dto);
|
||||
}
|
||||
|
||||
@Authenticated({ admin: true })
|
||||
@AdminRoute()
|
||||
@Delete('/:userId')
|
||||
deleteUser(@GetAuthUser() authUser: AuthUserDto, @Param() { userId }: UserIdDto): Promise<UserResponseDto> {
|
||||
return this.service.deleteUser(authUser, userId);
|
||||
}
|
||||
|
||||
@Authenticated({ admin: true })
|
||||
@AdminRoute()
|
||||
@Post('/:userId/restore')
|
||||
restoreUser(@GetAuthUser() authUser: AuthUserDto, @Param() { userId }: UserIdDto): Promise<UserResponseDto> {
|
||||
return this.service.restoreUser(authUser, userId);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Put()
|
||||
updateUser(@GetAuthUser() authUser: AuthUserDto, @Body() updateUserDto: UpdateUserDto): Promise<UserResponseDto> {
|
||||
return this.service.updateUser(authUser, updateUserDto);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@UseInterceptors(FileInterceptor('file', profileImageUploadOption))
|
||||
@ApiConsumes('multipart/form-data')
|
||||
@ApiBody({
|
||||
|
@ -98,7 +95,6 @@ export class UserController {
|
|||
return this.service.createProfileImage(authUser, fileInfo);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Get('/profile-image/:userId')
|
||||
@Header('Cache-Control', 'max-age=600')
|
||||
async getProfileImage(@Param() { userId }: UserIdDto, @Response({ passthrough: true }) res: Res): Promise<any> {
|
||||
|
|
|
@ -11,8 +11,16 @@ export enum Metadata {
|
|||
AUTH_ROUTE = 'auth_route',
|
||||
ADMIN_ROUTE = 'admin_route',
|
||||
SHARED_ROUTE = 'shared_route',
|
||||
PUBLIC_SECURITY = 'public_security',
|
||||
}
|
||||
|
||||
const adminDecorator = SetMetadata(Metadata.ADMIN_ROUTE, true);
|
||||
|
||||
const sharedLinkDecorators = [
|
||||
SetMetadata(Metadata.SHARED_ROUTE, true),
|
||||
ApiQuery({ name: 'key', type: String, required: false }),
|
||||
];
|
||||
|
||||
export const Authenticated = (options: AuthenticatedOptions = {}) => {
|
||||
const decorators: MethodDecorator[] = [
|
||||
ApiBearerAuth(),
|
||||
|
@ -22,13 +30,17 @@ export const Authenticated = (options: AuthenticatedOptions = {}) => {
|
|||
];
|
||||
|
||||
if (options.admin) {
|
||||
decorators.push(SetMetadata(Metadata.ADMIN_ROUTE, true));
|
||||
decorators.push(adminDecorator);
|
||||
}
|
||||
|
||||
if (options.isShared) {
|
||||
decorators.push(SetMetadata(Metadata.SHARED_ROUTE, true));
|
||||
decorators.push(ApiQuery({ name: 'key', type: String, required: false }));
|
||||
decorators.push(...sharedLinkDecorators);
|
||||
}
|
||||
|
||||
return applyDecorators(...decorators);
|
||||
};
|
||||
|
||||
export const PublicRoute = () =>
|
||||
applyDecorators(SetMetadata(Metadata.AUTH_ROUTE, false), ApiSecurity(Metadata.PUBLIC_SECURITY));
|
||||
export const SharedLinkRoute = () => applyDecorators(...sharedLinkDecorators);
|
||||
export const AdminRoute = () => adminDecorator;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { OpenAPIObject } from '@nestjs/swagger';
|
||||
import { Metadata } from '../decorators/authenticated.decorator';
|
||||
|
||||
export function patchOpenAPI(document: OpenAPIObject) {
|
||||
for (const path of Object.values(document.paths)) {
|
||||
|
@ -18,6 +19,10 @@ export function patchOpenAPI(document: OpenAPIObject) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if ((operation.security || []).find((item) => !!item[Metadata.PUBLIC_SECURITY])) {
|
||||
delete operation.security;
|
||||
}
|
||||
|
||||
if (operation.summary === '') {
|
||||
delete operation.summary;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue