mirror of
https://github.com/immich-app/immich.git
synced 2024-12-25 10:43:13 +02:00
feat(server,web): update email address (#1186)
* feat: change email * test: change email
This commit is contained in:
parent
fdf51a8855
commit
380f719fd8
BIN
mobile/openapi/doc/UpdateUserDto.md
generated
BIN
mobile/openapi/doc/UpdateUserDto.md
generated
Binary file not shown.
BIN
mobile/openapi/lib/model/update_user_dto.dart
generated
BIN
mobile/openapi/lib/model/update_user_dto.dart
generated
Binary file not shown.
BIN
mobile/openapi/test/update_user_dto_test.dart
generated
BIN
mobile/openapi/test/update_user_dto_test.dart
generated
Binary file not shown.
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -2400,6 +2400,9 @@
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
|
6
web/src/api/open-api/api.ts
generated
6
web/src/api/open-api/api.ts
generated
@ -1779,6 +1779,12 @@ export interface UpdateUserDto {
|
||||
* @memberof UpdateUserDto
|
||||
*/
|
||||
'id': string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof UpdateUserDto
|
||||
*/
|
||||
'email'?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
|
@ -1,5 +1,6 @@
|
||||
<script lang="ts" context="module">
|
||||
export enum SettingInputFieldType {
|
||||
EMAIL = 'email',
|
||||
TEXT = 'text',
|
||||
NUMBER = 'number',
|
||||
PASSWORD = 'password'
|
||||
|
@ -5,6 +5,7 @@
|
||||
} from '$lib/components/shared-components/notification/notification';
|
||||
import { api, UserResponseDto } from '@api';
|
||||
import { fade } from 'svelte/transition';
|
||||
import { handleError } from '../../utils/handle-error';
|
||||
import SettingInputField, {
|
||||
SettingInputFieldType
|
||||
} from '../admin-page/settings/setting-input-field.svelte';
|
||||
@ -15,6 +16,7 @@
|
||||
try {
|
||||
const { data } = await api.userApi.updateUser({
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
firstName: user.firstName,
|
||||
lastName: user.lastName
|
||||
});
|
||||
@ -26,11 +28,7 @@
|
||||
type: NotificationType.Info
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error [user-profile] [updateProfile]', error);
|
||||
notificationController.show({
|
||||
message: 'Unable to save profile',
|
||||
type: NotificationType.Error
|
||||
});
|
||||
handleError(error, 'Unable to save profile');
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@ -47,10 +45,9 @@
|
||||
/>
|
||||
|
||||
<SettingInputField
|
||||
inputType={SettingInputFieldType.TEXT}
|
||||
inputType={SettingInputFieldType.EMAIL}
|
||||
label="Email"
|
||||
bind:value={user.email}
|
||||
disabled={true}
|
||||
/>
|
||||
|
||||
<SettingInputField
|
||||
|
Loading…
Reference in New Issue
Block a user