11from datetime import UTC , datetime
2+ from enum import Enum
23from typing import Any , Optional
34from uuid import uuid4
45
5- from pydantic import BaseModel , Field
6+ from pydantic import BaseModel , Field , field_validator
67
78from ..core .schemas .timestamp import TimestampSchema
89
910
10- class SessionData ( BaseModel ):
11- """Common base data for any user session. """
11+ class DeviceType ( str , Enum ):
12+ """Device type enumeration """
1213
13- user_id : int
14- session_id : str = Field (default_factory = lambda : str (uuid4 ()))
15- ip_address : str
16- user_agent : str
17- device_info : dict [str , Any ] = Field (default_factory = dict )
18- created_at : datetime = Field (default_factory = lambda : datetime .now (UTC ))
19- last_activity : datetime = Field (default_factory = lambda : datetime .now (UTC ))
20- is_active : bool = True
21- metadata : dict [str , Any ] = Field (default_factory = dict )
14+ MOBILE = "mobile"
15+ TABLET = "tablet"
16+ DESKTOP = "desktop"
17+ UNKNOWN = "unknown"
18+
19+
20+ class BaseSession (BaseModel ):
21+ """Common base fields for all session types."""
22+
23+ user_id : int = Field (
24+ ..., description = "The ID of the user associated with the session."
25+ )
26+
27+ session_id : str = Field (
28+ default_factory = lambda : str (uuid4 ()), description = "Unique session identifier"
29+ )
30+ ip_address : str = Field (..., description = "Client IP address" )
31+ user_agent : str = Field (..., description = "Client user agent string" )
32+ device_info : dict [str , Any ] = Field (
33+ default_factory = dict , description = "Additional device information"
34+ )
35+ is_active : bool = Field (default = True , description = "Whether session is active" )
36+
37+ @field_validator ("ip_address" )
38+ @classmethod
39+ def validate_ip_address (cls , ip : str ) -> str :
40+ """Validate IP address format."""
41+ import ipaddress
42+
43+ try :
44+ ipaddress .ip_address (ip )
45+ except ValueError as err :
46+ raise ValueError ("Invalid IP Address format" ) from err
47+ return ip
48+
49+
50+ class SessionData (BaseSession ):
51+ """Common session data for any user session."""
52+
53+ metadata : dict [str , Any ] = Field (
54+ default_factory = dict , description = "Additional session metadata"
55+ )
56+ created_at : datetime = Field (
57+ default_factory = lambda : datetime .now (UTC ),
58+ description = "Session creation timestamp" ,
59+ )
60+ last_activity : datetime = Field (
61+ default_factory = lambda : datetime .now (UTC ), description = "Last activity timestamp"
62+ )
2263
2364
2465class SessionCreate (SessionData ):
@@ -38,9 +79,9 @@ class SessionUpdate(BaseModel):
3879class UserAgentInfo (BaseModel ):
3980 """User agent information parsed from the User-Agent header."""
4081
41- browser : str
42- browser_version : str
43- os : str
82+ browser : str = Field (..., description = "Browser name" )
83+ browser_version : str = Field (..., description = "Browser version" )
84+ os : str = Field (..., description = "Operating System" )
4485 device : str
4586 is_mobile : bool
4687 is_tablet : bool
@@ -57,46 +98,32 @@ class CSRFToken(BaseModel):
5798 expires_at : datetime
5899
59100
60- class AdminSessionBase (BaseModel ):
61- """Base schema for AdminSession."""
62-
63- user_id : int
64- session_id : str
65- ip_address : str
66- user_agent : str
67- device_info : dict [str , Any ] = Field (default_factory = dict )
68- session_metadata : dict [str , Any ] = Field (default_factory = dict )
69- is_active : bool = True
70-
71-
72- class AdminSession (TimestampSchema , AdminSessionBase ):
101+ class AdminSession (TimestampSchema , BaseSession ):
73102 """Full AdminSession schema with all fields."""
74103
75104 id : int
76- created_at : datetime
77- last_activity : datetime
105+ session_metadata : dict [str , Any ] = Field (
106+ default_factory = dict , description = "admin specific session metadata"
107+ )
108+ # remove redundant timestamp fields - let TimestampSchema handle them
78109
79110
80- class AdminSessionRead (BaseModel ):
111+ class AdminSessionRead (BaseSession ):
81112 """Schema for reading AdminSession data."""
82113
83114 id : int
84- user_id : int
85- session_id : str
86- ip_address : str
87- user_agent : str
88- device_info : dict [str , Any ]
89115 session_metadata : dict [str , Any ]
90116 created_at : datetime
91117 last_activity : datetime
92118 is_active : bool
93119
94120
95- class AdminSessionCreate (AdminSessionBase ):
121+ class AdminSessionCreate (BaseSession ):
96122 """Schema for creating AdminSession in database."""
97123
98124 created_at : datetime = Field (default_factory = lambda : datetime .now (UTC ))
99125 last_activity : datetime = Field (default_factory = lambda : datetime .now (UTC ))
126+ session_metadata : dict [str , Any ] = Field (default_factory = dict )
100127
101128
102129class AdminSessionUpdate (BaseModel ):
@@ -119,7 +146,6 @@ class AdminSessionUpdateInternal(AdminSessionUpdate):
119146 "SessionUpdate" ,
120147 "UserAgentInfo" ,
121148 "CSRFToken" ,
122- "AdminSessionBase" ,
123149 "AdminSession" ,
124150 "AdminSessionRead" ,
125151 "AdminSessionCreate" ,
0 commit comments