11import  re 
22from  datetime  import  date , datetime 
33from  enum  import  Enum 
4- from  typing  import  Annotated , Any , Literal , Self 
4+ from  typing  import  Annotated , Any , Literal , Self ,  TypeAlias 
55
66import  annotated_types 
77from  common_library .basic_types  import  DEFAULT_FACTORY 
1818    StringConstraints ,
1919    ValidationInfo ,
2020    field_validator ,
21+     model_validator ,
2122)
2223from  pydantic .config  import  JsonDict 
2324
@@ -83,7 +84,14 @@ class MyProfileRestGet(OutputSchemaWithoutCamelCase):
8384    login : LowerCaseEmailStr 
8485    phone : str  |  None  =  None 
8586
86-     role : Literal ["ANONYMOUS" , "GUEST" , "USER" , "TESTER" , "PRODUCT_OWNER" , "ADMIN" ]
87+     role : Literal [
88+         "ANONYMOUS" ,
89+         "GUEST" ,
90+         "USER" ,
91+         "TESTER" ,
92+         "PRODUCT_OWNER" ,
93+         "ADMIN" ,
94+     ]
8795    groups : MyGroupsGet  |  None  =  None 
8896    gravatar_id : Annotated [str  |  None , Field (deprecated = True )] =  None 
8997
@@ -306,15 +314,41 @@ class UserAccountReject(InputSchema):
306314    email : EmailStr 
307315
308316
317+ GlobString : TypeAlias  =  Annotated [
318+     str ,
319+     StringConstraints (
320+         min_length = 3 , max_length = 200 , strip_whitespace = True , pattern = r"^[^%]*$" 
321+     ),
322+ ]
323+ 
324+ 
309325class  UserAccountSearchQueryParams (RequestParameters ):
310326    email : Annotated [
311-         str ,
327+         GlobString   |   None ,
312328        Field (
313-             min_length = 3 ,
314-             max_length = 200 ,
315329            description = "complete or glob pattern for an email" ,
316330        ),
317-     ]
331+     ] =  None 
332+     primary_group_id : Annotated [
333+         GroupID  |  None ,
334+         Field (
335+             description = "Filter by primary group ID" ,
336+         ),
337+     ] =  None 
338+     user_name : Annotated [
339+         GlobString  |  None ,
340+         Field (
341+             description = "complete or glob pattern for a username" ,
342+         ),
343+     ] =  None 
344+ 
345+     @model_validator (mode = "after" ) 
346+     def  _validate_at_least_one_filter (self ) ->  Self :
347+         field_names  =  list (self .__class__ .model_fields )
348+         if  not  any (getattr (self , field_name , None ) for  field_name  in  field_names ):
349+             msg  =  f"At least one filter { field_names }   must be provided" 
350+             raise  ValueError (msg )
351+         return  self 
318352
319353
320354class  UserAccountGet (OutputSchema ):
@@ -340,9 +374,9 @@ class UserAccountGet(OutputSchema):
340374    # pre-registration NOTE: that some users have no pre-registartion and therefore all options here can be none 
341375    pre_registration_id : int  |  None 
342376    pre_registration_created : datetime  |  None 
343-     invited_by : str  |  None  =  None 
377+     invited_by : UserNameID  |  None  =  None 
344378    account_request_status : AccountRequestStatus  |  None 
345-     account_request_reviewed_by : UserID  |  None  =  None 
379+     account_request_reviewed_by : UserNameID  |  None  =  None 
346380    account_request_reviewed_at : datetime  |  None  =  None 
347381
348382    # user status 
0 commit comments