diff --git a/server/src/domain/auth/dto/login-credential.dto.spec.ts b/server/src/domain/auth/dto/login-credential.dto.spec.ts index 2caaefcd99..7682db4c4e 100644 --- a/server/src/domain/auth/dto/login-credential.dto.spec.ts +++ b/server/src/domain/auth/dto/login-credential.dto.spec.ts @@ -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); diff --git a/server/src/domain/auth/dto/login-credential.dto.ts b/server/src/domain/auth/dto/login-credential.dto.ts index e13badafa3..dfb9da873b 100644 --- a/server/src/domain/auth/dto/login-credential.dto.ts +++ b/server/src/domain/auth/dto/login-credential.dto.ts @@ -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; diff --git a/server/src/domain/auth/dto/sign-up.dto.spec.ts b/server/src/domain/auth/dto/sign-up.dto.spec.ts index c2e9d7f479..de708fe2ee 100644 --- a/server/src/domain/auth/dto/sign-up.dto.spec.ts +++ b/server/src/domain/auth/dto/sign-up.dto.spec.ts @@ -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', diff --git a/server/src/domain/auth/dto/sign-up.dto.ts b/server/src/domain/auth/dto/sign-up.dto.ts index 353e9cd8d3..b6c6175871 100644 --- a/server/src/domain/auth/dto/sign-up.dto.ts +++ b/server/src/domain/auth/dto/sign-up.dto.ts @@ -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; diff --git a/server/src/domain/user/dto/create-user.dto.spec.ts b/server/src/domain/user/dto/create-user.dto.spec.ts index 45f3335674..492d44c36f 100644 --- a/server/src/domain/user/dto/create-user.dto.spec.ts +++ b/server/src/domain/user/dto/create-user.dto.spec.ts @@ -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); + }); }); diff --git a/server/src/domain/user/dto/create-user.dto.ts b/server/src/domain/user/dto/create-user.dto.ts index 4fea6eddc6..ef857ffe21 100644 --- a/server/src/domain/user/dto/create-user.dto.ts +++ b/server/src/domain/user/dto/create-user.dto.ts @@ -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; diff --git a/server/src/domain/user/dto/update-user.dto.spec.ts b/server/src/domain/user/dto/update-user.dto.spec.ts new file mode 100644 index 0000000000..8e9013f291 --- /dev/null +++ b/server/src/domain/user/dto/update-user.dto.spec.ts @@ -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); + }); +}); diff --git a/server/src/domain/user/dto/update-user.dto.ts b/server/src/domain/user/dto/update-user.dto.ts index 0c23ad7d3c..c17abcbdb0 100644 --- a/server/src/domain/user/dto/update-user.dto.ts +++ b/server/src/domain/user/dto/update-user.dto.ts @@ -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;