Pārlūkot izejas kodu

chore(server): cleanup controllers (#2065)

Jason Rasmussen 2 gadi atpakaļ
vecāks
revīzija
54f98053a8

+ 9 - 10
server/apps/immich/src/controllers/auth.controller.ts

@@ -22,7 +22,7 @@ import { Authenticated } from '../decorators/authenticated.decorator';
 @ApiTags('Authentication')
 @Controller('auth')
 export class AuthController {
-  constructor(private readonly authService: AuthService) {}
+  constructor(private readonly service: AuthService) {}
 
   @Post('login')
   async login(
@@ -31,8 +31,8 @@ export class AuthController {
     @Req() req: Request,
     @Res({ passthrough: true }) res: Response,
   ): Promise<LoginResponseDto> {
-    const { response, cookie } = await this.authService.login(loginCredential, clientIp, req.secure);
-    res.setHeader('Set-Cookie', cookie);
+    const { response, cookie } = await this.service.login(loginCredential, clientIp, req.secure);
+    res.header('Set-Cookie', cookie);
     return response;
   }
 
@@ -41,25 +41,24 @@ export class AuthController {
   adminSignUp(
     @Body(new ValidationPipe({ transform: true })) signUpCredential: SignUpDto,
   ): Promise<AdminSignupResponseDto> {
-    return this.authService.adminSignUp(signUpCredential);
+    return this.service.adminSignUp(signUpCredential);
   }
 
   @Authenticated()
   @Post('validateToken')
-  // eslint-disable-next-line @typescript-eslint/no-unused-vars
-  validateAccessToken(@GetAuthUser() authUser: AuthUserDto): ValidateAccessTokenResponseDto {
+  validateAccessToken(): ValidateAccessTokenResponseDto {
     return { authStatus: true };
   }
 
   @Authenticated()
   @Post('change-password')
-  async changePassword(@GetAuthUser() authUser: AuthUserDto, @Body() dto: ChangePasswordDto): Promise<UserResponseDto> {
-    return this.authService.changePassword(authUser, dto);
+  changePassword(@GetAuthUser() authUser: AuthUserDto, @Body() dto: ChangePasswordDto): Promise<UserResponseDto> {
+    return this.service.changePassword(authUser, dto);
   }
 
   @Authenticated()
   @Post('logout')
-  async logout(
+  logout(
     @Req() req: Request,
     @Res({ passthrough: true }) res: Response,
     @GetAuthUser() authUser: AuthUserDto,
@@ -69,6 +68,6 @@ export class AuthController {
     res.clearCookie(IMMICH_ACCESS_COOKIE);
     res.clearCookie(IMMICH_AUTH_TYPE_COOKIE);
 
-    return this.authService.logout(authUser, authType);
+    return this.service.logout(authUser, authType);
   }
 }

+ 1 - 1
server/apps/immich/src/controllers/device-info.controller.ts

@@ -9,9 +9,9 @@ import { ApiTags } from '@nestjs/swagger';
 import { GetAuthUser } from '../decorators/auth-user.decorator';
 import { Authenticated } from '../decorators/authenticated.decorator';
 
-@Authenticated()
 @ApiTags('Device Info')
 @Controller('device-info')
+@Authenticated()
 export class DeviceInfoController {
   constructor(private readonly service: DeviceInfoService) {}
 

+ 4 - 4
server/apps/immich/src/controllers/job.controller.ts

@@ -3,19 +3,19 @@ import { Body, Controller, Get, Param, Put, ValidationPipe } from '@nestjs/commo
 import { ApiTags } from '@nestjs/swagger';
 import { Authenticated } from '../decorators/authenticated.decorator';
 
-@Authenticated({ admin: true })
 @ApiTags('Job')
 @Controller('jobs')
+@Authenticated({ admin: true })
 export class JobController {
-  constructor(private readonly jobService: JobService) {}
+  constructor(private service: JobService) {}
 
   @Get()
   getAllJobsStatus(): Promise<AllJobStatusResponseDto> {
-    return this.jobService.getAllJobsStatus();
+    return this.service.getAllJobsStatus();
   }
 
   @Put('/:jobId')
   sendJobCommand(@Param(ValidationPipe) { jobId }: JobIdDto, @Body(ValidationPipe) dto: JobCommandDto): Promise<void> {
-    return this.jobService.handleCommand(jobId, dto);
+    return this.service.handleCommand(jobId, dto);
   }
 }

+ 15 - 17
server/apps/immich/src/controllers/oauth.controller.ts

@@ -1,7 +1,6 @@
 import {
   AuthUserDto,
   LoginResponseDto,
-  MOBILE_REDIRECT,
   OAuthCallbackDto,
   OAuthConfigDto,
   OAuthConfigResponseDto,
@@ -17,43 +16,42 @@ import { Authenticated } from '../decorators/authenticated.decorator';
 @ApiTags('OAuth')
 @Controller('oauth')
 export class OAuthController {
-  constructor(private readonly oauthService: OAuthService) {}
+  constructor(private service: OAuthService) {}
 
   @Get('mobile-redirect')
   @Redirect()
-  public mobileRedirect(@Req() req: Request) {
-    const url = `${MOBILE_REDIRECT}?${req.url.split('?')[1] || ''}`;
-    return { url, statusCode: HttpStatus.TEMPORARY_REDIRECT };
+  mobileRedirect(@Req() req: Request) {
+    return {
+      url: this.service.getMobileRedirect(req.url),
+      statusCode: HttpStatus.TEMPORARY_REDIRECT,
+    };
   }
 
   @Post('config')
-  public generateConfig(@Body(ValidationPipe) dto: OAuthConfigDto): Promise<OAuthConfigResponseDto> {
-    return this.oauthService.generateConfig(dto);
+  generateConfig(@Body(ValidationPipe) dto: OAuthConfigDto): Promise<OAuthConfigResponseDto> {
+    return this.service.generateConfig(dto);
   }
 
   @Post('callback')
-  public async callback(
+  async callback(
     @Res({ passthrough: true }) res: Response,
     @Body(ValidationPipe) dto: OAuthCallbackDto,
     @Req() req: Request,
   ): Promise<LoginResponseDto> {
-    const { response, cookie } = await this.oauthService.login(dto, req.secure);
-    res.setHeader('Set-Cookie', cookie);
+    const { response, cookie } = await this.service.login(dto, req.secure);
+    res.header('Set-Cookie', cookie);
     return response;
   }
 
   @Authenticated()
   @Post('link')
-  public async link(
-    @GetAuthUser() authUser: AuthUserDto,
-    @Body(ValidationPipe) dto: OAuthCallbackDto,
-  ): Promise<UserResponseDto> {
-    return this.oauthService.link(authUser, dto);
+  link(@GetAuthUser() authUser: AuthUserDto, @Body(ValidationPipe) dto: OAuthCallbackDto): Promise<UserResponseDto> {
+    return this.service.link(authUser, dto);
   }
 
   @Authenticated()
   @Post('unlink')
-  public async unlink(@GetAuthUser() authUser: AuthUserDto): Promise<UserResponseDto> {
-    return this.oauthService.unlink(authUser);
+  unlink(@GetAuthUser() authUser: AuthUserDto): Promise<UserResponseDto> {
+    return this.service.unlink(authUser);
   }
 }

+ 6 - 6
server/apps/immich/src/controllers/search.controller.ts

@@ -12,26 +12,26 @@ import { GetAuthUser } from '../decorators/auth-user.decorator';
 import { Authenticated } from '../decorators/authenticated.decorator';
 
 @ApiTags('Search')
-@Authenticated()
 @Controller('search')
+@Authenticated()
 export class SearchController {
-  constructor(private readonly searchService: SearchService) {}
+  constructor(private service: SearchService) {}
 
   @Get()
-  async search(
+  search(
     @GetAuthUser() authUser: AuthUserDto,
     @Query(new ValidationPipe({ transform: true })) dto: SearchDto,
   ): Promise<SearchResponseDto> {
-    return this.searchService.search(authUser, dto);
+    return this.service.search(authUser, dto);
   }
 
   @Get('config')
   getSearchConfig(): SearchConfigResponseDto {
-    return this.searchService.getConfig();
+    return this.service.getConfig();
   }
 
   @Get('explore')
   getExploreData(@GetAuthUser() authUser: AuthUserDto): Promise<SearchExploreResponseDto[]> {
-    return this.searchService.getExploreData(authUser) as Promise<SearchExploreResponseDto[]>;
+    return this.service.getExploreData(authUser) as Promise<SearchExploreResponseDto[]>;
   }
 }

+ 1 - 1
server/apps/immich/src/controllers/server-info.controller.ts

@@ -12,7 +12,7 @@ import { Authenticated } from '../decorators/authenticated.decorator';
 @ApiTags('Server Info')
 @Controller('server-info')
 export class ServerInfoController {
-  constructor(private readonly service: ServerInfoService) {}
+  constructor(private service: ServerInfoService) {}
 
   @Get()
   getServerInfo(): Promise<ServerInfoResponseDto> {

+ 9 - 8
server/apps/immich/src/controllers/share.controller.ts

@@ -1,35 +1,36 @@
+import { AuthUserDto, EditSharedLinkDto, SharedLinkResponseDto, ShareService } from '@app/domain';
 import { Body, Controller, Delete, Get, Param, Patch, ValidationPipe } from '@nestjs/common';
 import { ApiTags } from '@nestjs/swagger';
 import { GetAuthUser } from '../decorators/auth-user.decorator';
 import { Authenticated } from '../decorators/authenticated.decorator';
-import { AuthUserDto, EditSharedLinkDto, SharedLinkResponseDto, ShareService } from '@app/domain';
 
 @ApiTags('share')
 @Controller('share')
 export class ShareController {
-  constructor(private readonly shareService: ShareService) {}
+  constructor(private readonly service: ShareService) {}
+
   @Authenticated()
   @Get()
   getAllSharedLinks(@GetAuthUser() authUser: AuthUserDto): Promise<SharedLinkResponseDto[]> {
-    return this.shareService.getAll(authUser);
+    return this.service.getAll(authUser);
   }
 
   @Authenticated({ isShared: true })
   @Get('me')
   getMySharedLink(@GetAuthUser() authUser: AuthUserDto): Promise<SharedLinkResponseDto> {
-    return this.shareService.getMine(authUser);
+    return this.service.getMine(authUser);
   }
 
   @Authenticated()
   @Get(':id')
   getSharedLinkById(@GetAuthUser() authUser: AuthUserDto, @Param('id') id: string): Promise<SharedLinkResponseDto> {
-    return this.shareService.getById(authUser, id, true);
+    return this.service.getById(authUser, id, true);
   }
 
   @Authenticated()
   @Delete(':id')
   removeSharedLink(@GetAuthUser() authUser: AuthUserDto, @Param('id') id: string): Promise<void> {
-    return this.shareService.remove(authUser, id);
+    return this.service.remove(authUser, id);
   }
 
   @Authenticated()
@@ -37,8 +38,8 @@ export class ShareController {
   editSharedLink(
     @GetAuthUser() authUser: AuthUserDto,
     @Param('id') id: string,
-    @Body(new ValidationPipe()) dto: EditSharedLinkDto,
+    @Body(ValidationPipe) dto: EditSharedLinkDto,
   ): Promise<SharedLinkResponseDto> {
-    return this.shareService.edit(authUser, id, dto);
+    return this.service.edit(authUser, id, dto);
   }
 }

+ 10 - 10
server/apps/immich/src/controllers/system-config.controller.ts

@@ -4,28 +4,28 @@ import { ApiTags } from '@nestjs/swagger';
 import { Authenticated } from '../decorators/authenticated.decorator';
 
 @ApiTags('System Config')
-@Authenticated({ admin: true })
 @Controller('system-config')
+@Authenticated({ admin: true })
 export class SystemConfigController {
-  constructor(private readonly systemConfigService: SystemConfigService) {}
+  constructor(private readonly service: SystemConfigService) {}
 
   @Get()
-  public getConfig(): Promise<SystemConfigDto> {
-    return this.systemConfigService.getConfig();
+  getConfig(): Promise<SystemConfigDto> {
+    return this.service.getConfig();
   }
 
   @Get('defaults')
-  public getDefaults(): SystemConfigDto {
-    return this.systemConfigService.getDefaults();
+  getDefaults(): SystemConfigDto {
+    return this.service.getDefaults();
   }
 
   @Put()
-  public updateConfig(@Body(ValidationPipe) dto: SystemConfigDto): Promise<SystemConfigDto> {
-    return this.systemConfigService.updateConfig(dto);
+  updateConfig(@Body(ValidationPipe) dto: SystemConfigDto): Promise<SystemConfigDto> {
+    return this.service.updateConfig(dto);
   }
 
   @Get('storage-template-options')
-  public getStorageTemplateOptions(): SystemConfigTemplateStorageOptionDto {
-    return this.systemConfigService.getStorageTemplateOptions();
+  getStorageTemplateOptions(): SystemConfigTemplateStorageOptionDto {
+    return this.service.getStorageTemplateOptions();
   }
 }

+ 21 - 25
server/apps/immich/src/controllers/user.controller.ts

@@ -33,60 +33,58 @@ import { UserCountDto } from '@app/domain';
 @ApiTags('User')
 @Controller('user')
 export class UserController {
-  constructor(private readonly userService: UserService) {}
+  constructor(private service: UserService) {}
 
   @Authenticated()
   @Get()
-  async getAllUsers(
+  getAllUsers(
     @GetAuthUser() authUser: AuthUserDto,
     @Query('isAll', ParseBoolPipe) isAll: boolean,
   ): Promise<UserResponseDto[]> {
-    return await this.userService.getAllUsers(authUser, isAll);
+    return this.service.getAllUsers(authUser, isAll);
   }
 
   @Get('/info/:userId')
-  async getUserById(@Param('userId') userId: string): Promise<UserResponseDto> {
-    return await this.userService.getUserById(userId);
+  getUserById(@Param('userId') userId: string): Promise<UserResponseDto> {
+    return this.service.getUserById(userId);
   }
 
   @Authenticated()
   @Get('me')
-  async getMyUserInfo(@GetAuthUser() authUser: AuthUserDto): Promise<UserResponseDto> {
-    return await this.userService.getUserInfo(authUser);
+  getMyUserInfo(@GetAuthUser() authUser: AuthUserDto): Promise<UserResponseDto> {
+    return this.service.getUserInfo(authUser);
   }
 
   @Authenticated({ admin: true })
   @Post()
-  async createUser(
-    @Body(new ValidationPipe({ transform: true })) createUserDto: CreateUserDto,
-  ): Promise<UserResponseDto> {
-    return await this.userService.createUser(createUserDto);
+  createUser(@Body(new ValidationPipe({ transform: true })) createUserDto: CreateUserDto): Promise<UserResponseDto> {
+    return this.service.createUser(createUserDto);
   }
 
   @Get('/count')
-  async getUserCount(@Query(new ValidationPipe({ transform: true })) dto: UserCountDto): Promise<UserCountResponseDto> {
-    return await this.userService.getUserCount(dto);
+  getUserCount(@Query(new ValidationPipe({ transform: true })) dto: UserCountDto): Promise<UserCountResponseDto> {
+    return this.service.getUserCount(dto);
   }
 
   @Authenticated({ admin: true })
   @Delete('/:userId')
-  async deleteUser(@GetAuthUser() authUser: AuthUserDto, @Param('userId') userId: string): Promise<UserResponseDto> {
-    return await this.userService.deleteUser(authUser, userId);
+  deleteUser(@GetAuthUser() authUser: AuthUserDto, @Param('userId') userId: string): Promise<UserResponseDto> {
+    return this.service.deleteUser(authUser, userId);
   }
 
   @Authenticated({ admin: true })
   @Post('/:userId/restore')
-  async restoreUser(@GetAuthUser() authUser: AuthUserDto, @Param('userId') userId: string): Promise<UserResponseDto> {
-    return await this.userService.restoreUser(authUser, userId);
+  restoreUser(@GetAuthUser() authUser: AuthUserDto, @Param('userId') userId: string): Promise<UserResponseDto> {
+    return this.service.restoreUser(authUser, userId);
   }
 
   @Authenticated()
   @Put()
-  async updateUser(
+  updateUser(
     @GetAuthUser() authUser: AuthUserDto,
     @Body(ValidationPipe) updateUserDto: UpdateUserDto,
   ): Promise<UserResponseDto> {
-    return await this.userService.updateUser(authUser, updateUserDto);
+    return this.service.updateUser(authUser, updateUserDto);
   }
 
   @UseInterceptors(FileInterceptor('file', profileImageUploadOption))
@@ -97,20 +95,18 @@ export class UserController {
     type: CreateProfileImageDto,
   })
   @Post('/profile-image')
-  async createProfileImage(
+  createProfileImage(
     @GetAuthUser() authUser: AuthUserDto,
     @UploadedFile() fileInfo: Express.Multer.File,
   ): Promise<CreateProfileImageResponseDto> {
-    return await this.userService.createProfileImage(authUser, fileInfo);
+    return this.service.createProfileImage(authUser, fileInfo);
   }
 
   @Get('/profile-image/:userId')
   @Header('Cache-Control', 'max-age=600')
   async getProfileImage(@Param('userId') userId: string, @Response({ passthrough: true }) res: Res): Promise<any> {
-    const readableStream = await this.userService.getUserProfileImage(userId);
-    res.set({
-      'Content-Type': 'image/jpeg',
-    });
+    const readableStream = await this.service.getUserProfileImage(userId);
+    res.header('Content-Type', 'image/jpeg');
     return new StreamableFile(readableStream);
   }
 }

+ 10 - 0
server/libs/domain/src/oauth/oauth.service.spec.ts

@@ -63,6 +63,16 @@ describe('OAuthService', () => {
     expect(sut).toBeDefined();
   });
 
+  describe('getMobileRedirect', () => {
+    it('should pass along the query params', () => {
+      expect(sut.getMobileRedirect('http://immich.app?code=123&state=456')).toEqual('app.immich:/?code=123&state=456');
+    });
+
+    it('should work if called without query params', () => {
+      expect(sut.getMobileRedirect('http://immich.app')).toEqual('app.immich:/?');
+    });
+  });
+
   describe('generateConfig', () => {
     it('should work when oauth is not configured', async () => {
       await expect(sut.generateConfig({ redirectUri: 'http://callback' })).resolves.toEqual({

+ 7 - 2
server/libs/domain/src/oauth/oauth.service.ts

@@ -1,14 +1,15 @@
 import { SystemConfig } from '@app/infra/db/entities';
 import { BadRequestException, Inject, Injectable, Logger } from '@nestjs/common';
 import { AuthType, AuthUserDto, LoginResponseDto } from '../auth';
-import { ICryptoRepository } from '../crypto';
 import { AuthCore } from '../auth/auth.core';
+import { ICryptoRepository } from '../crypto';
 import { INITIAL_SYSTEM_CONFIG, ISystemConfigRepository } from '../system-config';
 import { IUserRepository, UserCore, UserResponseDto } from '../user';
+import { IUserTokenRepository } from '../user-token';
 import { OAuthCallbackDto, OAuthConfigDto } from './dto';
+import { MOBILE_REDIRECT } from './oauth.constants';
 import { OAuthCore } from './oauth.core';
 import { OAuthConfigResponseDto } from './response-dto';
-import { IUserTokenRepository } from '../user-token';
 
 @Injectable()
 export class OAuthService {
@@ -30,6 +31,10 @@ export class OAuthService {
     this.oauthCore = new OAuthCore(configRepository, initialConfig);
   }
 
+  getMobileRedirect(url: string) {
+    return `${MOBILE_REDIRECT}?${url.split('?')[1] || ''}`;
+  }
+
   generateConfig(dto: OAuthConfigDto): Promise<OAuthConfigResponseDto> {
     return this.oauthCore.generateConfig(dto);
   }