File size: 3,036 Bytes
79ef7e1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# ============================================================
# app/schemas/auth.py - Authentication DTOs
# ============================================================

from pydantic import BaseModel, EmailStr, Field, field_validator
from typing import Optional
import re

class SignupDto(BaseModel):
    """Signup request DTO"""
    first_name: str = Field(..., min_length=1, max_length=50)
    last_name: str = Field(..., min_length=1, max_length=50)
    email: Optional[EmailStr] = None
    phone: Optional[str] = None
    password: str = Field(..., min_length=8, max_length=100)
    role: str = Field(..., pattern="^(renter|landlord)$")
    
    @field_validator("password")
    @classmethod
    def validate_password(cls, v):
        """Validate password strength"""
        if not re.search(r"[A-Z]", v):
            raise ValueError("Must contain uppercase letter")
        if not re.search(r"[a-z]", v):
            raise ValueError("Must contain lowercase letter")
        if not re.search(r"[0-9]", v):
            raise ValueError("Must contain digit")
        if not re.search(r"[!@#$%^&*(),.?\":{}|<>]", v):
            raise ValueError("Must contain special character")
        return v
    
    @field_validator("email", "phone")
    @classmethod
    def validate_contact(cls, v, info):
        """At least email or phone required"""
        if info.data.get("email") or info.data.get("phone"):
            return v
        raise ValueError("Email or phone is required")

class VerifySignupOtpDto(BaseModel):
    """Verify signup OTP DTO"""
    identifier: str = Field(..., min_length=1)
    code: str = Field(..., min_length=4, max_length=4)

class LoginDto(BaseModel):
    """Login request DTO"""
    identifier: str = Field(..., min_length=1)
    password: str = Field(..., min_length=1)

class SendPasswordResetOtpDto(BaseModel):
    """Send password reset OTP DTO"""
    identifier: str = Field(..., min_length=1)

class VerifyPasswordResetOtpDto(BaseModel):
    """Verify password reset OTP DTO"""
    identifier: str = Field(..., min_length=1)
    code: str = Field(..., min_length=4, max_length=4)

class ResetPasswordDto(BaseModel):
    """Reset password DTO"""
    identifier: str = Field(..., min_length=1)
    new_password: str = Field(..., min_length=8, max_length=100)
    
    @field_validator("new_password")
    @classmethod
    def validate_password(cls, v):
        """Validate password strength"""
        if not re.search(r"[A-Z]", v):
            raise ValueError("Must contain uppercase letter")
        if not re.search(r"[a-z]", v):
            raise ValueError("Must contain lowercase letter")
        if not re.search(r"[0-9]", v):
            raise ValueError("Must contain digit")
        if not re.search(r"[!@#$%^&*(),.?\":{}|<>]", v):
            raise ValueError("Must contain special character")
        return v

class ResendOtpDto(BaseModel):
    """Resend OTP DTO"""
    identifier: str = Field(..., min_length=1)
    purpose: str = Field(..., pattern="^(signup|password_reset)$")