From 380f719fd86b306cc77f2890ba58408f0ecf96dd Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Tue, 27 Dec 2022 11:36:31 -0500 Subject: [PATCH] feat(server,web): update email address (#1186) * feat: change email * test: change email --- mobile/openapi/doc/UpdateUserDto.md | Bin 679 -> 719 bytes mobile/openapi/lib/model/update_user_dto.dart | Bin 7550 -> 8180 bytes mobile/openapi/test/update_user_dto_test.dart | Bin 1193 -> 1288 bytes .../src/api-v1/user/dto/update-user.dto.ts | 6 ++++- .../apps/immich/src/api-v1/user/user.core.ts | 7 ++++++ .../src/api-v1/user/user.service.spec.ts | 22 ++++++++++++++++++ server/immich-openapi-specs.json | 3 +++ web/src/api/open-api/api.ts | 6 +++++ .../settings/setting-input-field.svelte | 1 + .../user-profile-settings.svelte | 11 ++++----- 10 files changed, 48 insertions(+), 8 deletions(-) diff --git a/mobile/openapi/doc/UpdateUserDto.md b/mobile/openapi/doc/UpdateUserDto.md index 1bdb496c5ab1dfe127bce47b4b4e24cf2b98458a..043f2e6ab8a845f3c31fd64000494fd1dc796fa9 100644 GIT binary patch delta 20 ccmZ3^dY*N{C)U*5#LS$@fsD!&54h7o>vjz=N0keV*i2<`25Dfvdj}eRpvr-tM2XDg< AC;$Ke diff --git a/mobile/openapi/test/update_user_dto_test.dart b/mobile/openapi/test/update_user_dto_test.dart index 3010100d8ecf15d44573b8ffbca6eb53e1d45232..5055f5fa9be72823c5c0b18226367f46d6951a96 100644 GIT binary patch delta 32 icmZ3<*}=6zn~60wH!(A3aw4-Lloi8dvRRv{jtKy#s0rBs delta 12 TcmeC+TFJRVn`v_wQymik8z}?f diff --git a/server/apps/immich/src/api-v1/user/dto/update-user.dto.ts b/server/apps/immich/src/api-v1/user/dto/update-user.dto.ts index 424e08e1a..73bcdf199 100644 --- a/server/apps/immich/src/api-v1/user/dto/update-user.dto.ts +++ b/server/apps/immich/src/api-v1/user/dto/update-user.dto.ts @@ -1,9 +1,13 @@ -import { IsNotEmpty, IsOptional } from 'class-validator'; +import { IsEmail, IsNotEmpty, IsOptional } from 'class-validator'; export class UpdateUserDto { @IsNotEmpty() id!: string; + @IsEmail() + @IsOptional() + email?: string; + @IsOptional() password?: string; diff --git a/server/apps/immich/src/api-v1/user/user.core.ts b/server/apps/immich/src/api-v1/user/user.core.ts index 788c21889..a2dec23a4 100644 --- a/server/apps/immich/src/api-v1/user/user.core.ts +++ b/server/apps/immich/src/api-v1/user/user.core.ts @@ -28,6 +28,13 @@ export class UserCore { throw new BadRequestException('Admin user exists'); } + if (dto.email) { + const duplicate = await this.userRepository.getByEmail(dto.email); + if (duplicate && duplicate.id !== id) { + throw new BadRequestException('Email already in user by another account'); + } + } + try { if (dto.password) { dto.password = await hash(dto.password, SALT_ROUNDS); diff --git a/server/apps/immich/src/api-v1/user/user.service.spec.ts b/server/apps/immich/src/api-v1/user/user.service.spec.ts index 0db9c9f5e..399fff209 100644 --- a/server/apps/immich/src/api-v1/user/user.service.spec.ts +++ b/server/apps/immich/src/api-v1/user/user.service.spec.ts @@ -102,6 +102,28 @@ describe('UserService', () => { await expect(result).rejects.toBeInstanceOf(ForbiddenException); }); + it('should let a user change their email', async () => { + const dto = { id: immichUser.id, email: 'updated@test.com' }; + + userRepositoryMock.get.mockResolvedValue(immichUser); + userRepositoryMock.update.mockResolvedValue(immichUser); + + await sut.updateUser(immichUser, dto); + + expect(userRepositoryMock.update).toHaveBeenCalledWith(immichUser.id, { email: 'updated@test.com' }); + }); + + it('should not let a user change their email to one already in use', async () => { + const dto = { id: immichUser.id, email: 'updated@test.com' }; + + userRepositoryMock.get.mockResolvedValue(immichUser); + userRepositoryMock.getByEmail.mockResolvedValue(adminUser); + + await expect(sut.updateUser(immichUser, dto)).rejects.toBeInstanceOf(BadRequestException); + + expect(userRepositoryMock.update).not.toHaveBeenCalled(); + }); + it('admin can update any user information', async () => { const update: UpdateUserDto = { id: immichUser.id, diff --git a/server/immich-openapi-specs.json b/server/immich-openapi-specs.json index 866b27576..18c89a968 100644 --- a/server/immich-openapi-specs.json +++ b/server/immich-openapi-specs.json @@ -2400,6 +2400,9 @@ "id": { "type": "string" }, + "email": { + "type": "string" + }, "password": { "type": "string" }, diff --git a/web/src/api/open-api/api.ts b/web/src/api/open-api/api.ts index 4fed33138..ebca7211b 100644 --- a/web/src/api/open-api/api.ts +++ b/web/src/api/open-api/api.ts @@ -1779,6 +1779,12 @@ export interface UpdateUserDto { * @memberof UpdateUserDto */ 'id': string; + /** + * + * @type {string} + * @memberof UpdateUserDto + */ + 'email'?: string; /** * * @type {string} diff --git a/web/src/lib/components/admin-page/settings/setting-input-field.svelte b/web/src/lib/components/admin-page/settings/setting-input-field.svelte index 5319d7cf5..4fde6f000 100644 --- a/web/src/lib/components/admin-page/settings/setting-input-field.svelte +++ b/web/src/lib/components/admin-page/settings/setting-input-field.svelte @@ -1,5 +1,6 @@ @@ -47,10 +45,9 @@ />