208 lines
4.9 KiB
TypeScript
208 lines
4.9 KiB
TypeScript
import { IsEmail, IsString, MinLength, IsOptional, ValidateNested, IsEnum, MaxLength, Matches } from 'class-validator';
|
|
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
|
import { Type } from 'class-transformer';
|
|
import { OrganizationType } from '@domain/entities/organization.entity';
|
|
|
|
export class LoginDto {
|
|
@ApiProperty({
|
|
example: 'john.doe@acme.com',
|
|
description: 'Email address',
|
|
})
|
|
@IsEmail({}, { message: 'Invalid email format' })
|
|
email: string;
|
|
|
|
@ApiProperty({
|
|
example: 'SecurePassword123!',
|
|
description: 'Password (minimum 12 characters)',
|
|
minLength: 12,
|
|
})
|
|
@IsString()
|
|
@MinLength(12, { message: 'Password must be at least 12 characters' })
|
|
password: string;
|
|
}
|
|
|
|
/**
|
|
* Organization data for registration (nested in RegisterDto)
|
|
*/
|
|
export class RegisterOrganizationDto {
|
|
@ApiProperty({
|
|
example: 'Acme Freight Forwarding',
|
|
description: 'Organization name',
|
|
minLength: 2,
|
|
maxLength: 200,
|
|
})
|
|
@IsString()
|
|
@MinLength(2)
|
|
@MaxLength(200)
|
|
name: string;
|
|
|
|
@ApiProperty({
|
|
example: OrganizationType.FREIGHT_FORWARDER,
|
|
description: 'Organization type',
|
|
enum: OrganizationType,
|
|
})
|
|
@IsEnum(OrganizationType)
|
|
type: OrganizationType;
|
|
|
|
@ApiProperty({
|
|
example: '123 Main Street',
|
|
description: 'Street address',
|
|
})
|
|
@IsString()
|
|
street: string;
|
|
|
|
@ApiProperty({
|
|
example: 'Rotterdam',
|
|
description: 'City',
|
|
})
|
|
@IsString()
|
|
city: string;
|
|
|
|
@ApiPropertyOptional({
|
|
example: 'South Holland',
|
|
description: 'State or province',
|
|
})
|
|
@IsString()
|
|
@IsOptional()
|
|
state?: string;
|
|
|
|
@ApiProperty({
|
|
example: '3000 AB',
|
|
description: 'Postal code',
|
|
})
|
|
@IsString()
|
|
postalCode: string;
|
|
|
|
@ApiProperty({
|
|
example: 'NL',
|
|
description: 'Country code (ISO 3166-1 alpha-2)',
|
|
minLength: 2,
|
|
maxLength: 2,
|
|
})
|
|
@IsString()
|
|
@MinLength(2)
|
|
@MaxLength(2)
|
|
@Matches(/^[A-Z]{2}$/, { message: 'Country must be a 2-letter ISO code (e.g., NL, US, CN)' })
|
|
country: string;
|
|
|
|
@ApiPropertyOptional({
|
|
example: 'MAEU',
|
|
description: 'Standard Carrier Alpha Code (4 uppercase letters, required for carriers only)',
|
|
minLength: 4,
|
|
maxLength: 4,
|
|
})
|
|
@IsString()
|
|
@IsOptional()
|
|
@MinLength(4)
|
|
@MaxLength(4)
|
|
@Matches(/^[A-Z]{4}$/, { message: 'SCAC must be 4 uppercase letters' })
|
|
scac?: string;
|
|
}
|
|
|
|
export class RegisterDto {
|
|
@ApiProperty({
|
|
example: 'john.doe@acme.com',
|
|
description: 'Email address',
|
|
})
|
|
@IsEmail({}, { message: 'Invalid email format' })
|
|
email: string;
|
|
|
|
@ApiProperty({
|
|
example: 'SecurePassword123!',
|
|
description: 'Password (minimum 12 characters)',
|
|
minLength: 12,
|
|
})
|
|
@IsString()
|
|
@MinLength(12, { message: 'Password must be at least 12 characters' })
|
|
password: string;
|
|
|
|
@ApiPropertyOptional({
|
|
example: 'John',
|
|
description: 'First name (optional if using invitation token)',
|
|
})
|
|
@IsString()
|
|
@IsOptional()
|
|
@MinLength(2, { message: 'First name must be at least 2 characters' })
|
|
firstName: string;
|
|
|
|
@ApiPropertyOptional({
|
|
example: 'Doe',
|
|
description: 'Last name (optional if using invitation token)',
|
|
})
|
|
@IsString()
|
|
@IsOptional()
|
|
@MinLength(2, { message: 'Last name must be at least 2 characters' })
|
|
lastName: string;
|
|
|
|
@ApiPropertyOptional({
|
|
example: 'abc123def456',
|
|
description: 'Invitation token (for invited users)',
|
|
required: false,
|
|
})
|
|
@IsString()
|
|
@IsOptional()
|
|
invitationToken?: string;
|
|
|
|
@ApiPropertyOptional({
|
|
example: '550e8400-e29b-41d4-a716-446655440000',
|
|
description: 'Organization ID (optional - for invited users). If not provided, organization data must be provided.',
|
|
required: false,
|
|
})
|
|
@IsString()
|
|
@IsOptional()
|
|
organizationId?: string;
|
|
|
|
@ApiPropertyOptional({
|
|
description: 'Organization data (required if organizationId and invitationToken are not provided)',
|
|
type: RegisterOrganizationDto,
|
|
required: false,
|
|
})
|
|
@ValidateNested()
|
|
@Type(() => RegisterOrganizationDto)
|
|
@IsOptional()
|
|
organization?: RegisterOrganizationDto;
|
|
}
|
|
|
|
export class AuthResponseDto {
|
|
@ApiProperty({
|
|
example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
|
|
description: 'JWT access token (valid 15 minutes)',
|
|
})
|
|
accessToken: string;
|
|
|
|
@ApiProperty({
|
|
example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
|
|
description: 'JWT refresh token (valid 7 days)',
|
|
})
|
|
refreshToken: string;
|
|
|
|
@ApiProperty({
|
|
example: {
|
|
id: '550e8400-e29b-41d4-a716-446655440000',
|
|
email: 'john.doe@acme.com',
|
|
firstName: 'John',
|
|
lastName: 'Doe',
|
|
role: 'user',
|
|
organizationId: '550e8400-e29b-41d4-a716-446655440001',
|
|
},
|
|
description: 'User information',
|
|
})
|
|
user: {
|
|
id: string;
|
|
email: string;
|
|
firstName: string;
|
|
lastName: string;
|
|
role: string;
|
|
organizationId: string;
|
|
};
|
|
}
|
|
|
|
export class RefreshTokenDto {
|
|
@ApiProperty({
|
|
example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
|
|
description: 'Refresh token',
|
|
})
|
|
@IsString()
|
|
refreshToken: string;
|
|
}
|