mirror of
				https://github.com/KevinMidboe/immich.git
				synced 2025-10-29 17:40:28 +00:00 
			
		
		
		
	allow emails without a tld (#2762)
It's perfectly valid to have an email address without a TLD, for instance: - test@localhost - test@svc-in-same-k8s-namespace - test@internal-corp Fixes #2667
This commit is contained in:
		| @@ -3,6 +3,15 @@ import { validateSync } from 'class-validator'; | ||||
| import { LoginCredentialDto } from './login-credential.dto'; | ||||
|  | ||||
| describe('LoginCredentialDto', () => { | ||||
|   it('should allow emails without a tld', () => { | ||||
|     const someEmail = 'test@test'; | ||||
|  | ||||
|     const dto = plainToInstance(LoginCredentialDto, { email: someEmail, password: 'password' }); | ||||
|     const errors = validateSync(dto); | ||||
|     expect(errors).toHaveLength(0); | ||||
|     expect(dto.email).toEqual(someEmail); | ||||
|   }); | ||||
|  | ||||
|   it('should fail without an email', () => { | ||||
|     const dto = plainToInstance(LoginCredentialDto, { password: 'password' }); | ||||
|     const errors = validateSync(dto); | ||||
|   | ||||
| @@ -3,7 +3,7 @@ import { Transform } from 'class-transformer'; | ||||
| import { IsEmail, IsNotEmpty, IsString } from 'class-validator'; | ||||
|  | ||||
| export class LoginCredentialDto { | ||||
|   @IsEmail() | ||||
|   @IsEmail({ require_tld: false }) | ||||
|   @ApiProperty({ example: 'testuser@email.com' }) | ||||
|   @Transform(({ value }) => value.toLowerCase()) | ||||
|   email!: string; | ||||
|   | ||||
| @@ -30,6 +30,20 @@ describe('SignUpDto', () => { | ||||
|     expect(errors[0].property).toEqual('email'); | ||||
|   }); | ||||
|  | ||||
|   it('should allow emails without a tld', () => { | ||||
|     const someEmail = 'test@test'; | ||||
|  | ||||
|     const dto = plainToInstance(SignUpDto, { | ||||
|       email: someEmail, | ||||
|       password: 'password', | ||||
|       firstName: 'first name', | ||||
|       lastName: 'last name', | ||||
|     }); | ||||
|     const errors = validateSync(dto); | ||||
|     expect(errors).toHaveLength(0); | ||||
|     expect(dto.email).toEqual(someEmail); | ||||
|   }); | ||||
|  | ||||
|   it('should make the email all lowercase', () => { | ||||
|     const dto = plainToInstance(SignUpDto, { | ||||
|       email: 'TeSt@ImMiCh.com', | ||||
|   | ||||
| @@ -3,7 +3,7 @@ import { Transform } from 'class-transformer'; | ||||
| import { IsEmail, IsNotEmpty, IsString } from 'class-validator'; | ||||
|  | ||||
| export class SignUpDto { | ||||
|   @IsEmail() | ||||
|   @IsEmail({ require_tld: false }) | ||||
|   @ApiProperty({ example: 'testuser@email.com' }) | ||||
|   @Transform(({ value }) => value.toLowerCase()) | ||||
|   email!: string; | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import { plainToInstance } from 'class-transformer'; | ||||
| import { validate } from 'class-validator'; | ||||
| import { CreateUserDto } from './create-user.dto'; | ||||
| import { CreateAdminDto, CreateUserDto, CreateUserOAuthDto } from './create-user.dto'; | ||||
|  | ||||
| describe('create user DTO', () => { | ||||
|   it('validates the email', async () => { | ||||
| @@ -24,4 +24,51 @@ describe('create user DTO', () => { | ||||
|     errors = await validate(dto); | ||||
|     expect(errors).toHaveLength(0); | ||||
|   }); | ||||
|  | ||||
|   it('should allow emails without a tld', async () => { | ||||
|     const someEmail = 'test@test'; | ||||
|  | ||||
|     const dto = plainToInstance(CreateUserDto, { | ||||
|       email: someEmail, | ||||
|       password: 'some password', | ||||
|       firstName: 'some first name', | ||||
|       lastName: 'some last name', | ||||
|     }); | ||||
|     const errors = await validate(dto); | ||||
|     expect(errors).toHaveLength(0); | ||||
|     expect(dto.email).toEqual(someEmail); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| describe('create admin DTO', () => { | ||||
|   it('should allow emails without a tld', async () => { | ||||
|     const someEmail = 'test@test'; | ||||
|  | ||||
|     const dto = plainToInstance(CreateAdminDto, { | ||||
|       isAdmin: true, | ||||
|       email: someEmail, | ||||
|       password: 'some password', | ||||
|       firstName: 'some first name', | ||||
|       lastName: 'some last name', | ||||
|     }); | ||||
|     const errors = await validate(dto); | ||||
|     expect(errors).toHaveLength(0); | ||||
|     expect(dto.email).toEqual(someEmail); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| describe('create user oauth DTO', () => { | ||||
|   it('should allow emails without a tld', async () => { | ||||
|     const someEmail = 'test@test'; | ||||
|  | ||||
|     const dto = plainToInstance(CreateUserOAuthDto, { | ||||
|       email: someEmail, | ||||
|       oauthId: 'some oauth id', | ||||
|       firstName: 'some first name', | ||||
|       lastName: 'some last name', | ||||
|     }); | ||||
|     const errors = await validate(dto); | ||||
|     expect(errors).toHaveLength(0); | ||||
|     expect(dto.email).toEqual(someEmail); | ||||
|   }); | ||||
| }); | ||||
|   | ||||
| @@ -3,7 +3,7 @@ import { IsEmail, IsNotEmpty, IsOptional, IsString } from 'class-validator'; | ||||
| import { toEmail, toSanitized } from '@app/immich/utils/transform.util'; | ||||
|  | ||||
| export class CreateUserDto { | ||||
|   @IsEmail() | ||||
|   @IsEmail({ require_tld: false }) | ||||
|   @Transform(toEmail) | ||||
|   email!: string; | ||||
|  | ||||
| @@ -29,7 +29,7 @@ export class CreateAdminDto { | ||||
|   @IsNotEmpty() | ||||
|   isAdmin!: true; | ||||
|  | ||||
|   @IsEmail() | ||||
|   @IsEmail({ require_tld: false }) | ||||
|   @Transform(({ value }) => value?.toLowerCase()) | ||||
|   email!: string; | ||||
|  | ||||
| @@ -44,7 +44,7 @@ export class CreateAdminDto { | ||||
| } | ||||
|  | ||||
| export class CreateUserOAuthDto { | ||||
|   @IsEmail() | ||||
|   @IsEmail({ require_tld: false }) | ||||
|   @Transform(({ value }) => value?.toLowerCase()) | ||||
|   email!: string; | ||||
|  | ||||
|   | ||||
							
								
								
									
										17
									
								
								server/src/domain/user/dto/update-user.dto.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								server/src/domain/user/dto/update-user.dto.spec.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| import { plainToInstance } from 'class-transformer'; | ||||
| import { validate } from 'class-validator'; | ||||
| import { UpdateUserDto } from './update-user.dto'; | ||||
|  | ||||
| describe('update user DTO', () => { | ||||
|   it('should allow emails without a tld', async () => { | ||||
|     const someEmail = 'test@test'; | ||||
|  | ||||
|     const dto = plainToInstance(UpdateUserDto, { | ||||
|       email: someEmail, | ||||
|       id: '3fe388e4-2078-44d7-b36c-39d9dee3a657', | ||||
|     }); | ||||
|     const errors = await validate(dto); | ||||
|     expect(errors).toHaveLength(0); | ||||
|     expect(dto.email).toEqual(someEmail); | ||||
|   }); | ||||
| }); | ||||
| @@ -5,7 +5,7 @@ import { toEmail, toSanitized } from '@app/immich/utils/transform.util'; | ||||
|  | ||||
| export class UpdateUserDto { | ||||
|   @IsOptional() | ||||
|   @IsEmail() | ||||
|   @IsEmail({ require_tld: false }) | ||||
|   @Transform(toEmail) | ||||
|   email?: string; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user