maleo-identity 0.0.85__py3-none-any.whl → 0.1.24__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. maleo/identity/constants/api_key.py +13 -0
  2. maleo/identity/constants/organization.py +3 -10
  3. maleo/identity/constants/organization_registration_code.py +5 -17
  4. maleo/identity/constants/organization_relation.py +13 -0
  5. maleo/identity/constants/patient.py +7 -0
  6. maleo/identity/constants/user.py +3 -20
  7. maleo/identity/constants/user_medical_role.py +13 -0
  8. maleo/identity/constants/user_organization_role.py +5 -39
  9. maleo/identity/constants/user_profile.py +3 -21
  10. maleo/identity/constants/user_system_role.py +9 -8
  11. maleo/identity/enums/api_key.py +25 -0
  12. maleo/identity/enums/organization.py +16 -3
  13. maleo/identity/enums/organization_registration_code.py +9 -0
  14. maleo/identity/enums/organization_relation.py +22 -0
  15. maleo/identity/enums/patient.py +29 -0
  16. maleo/identity/enums/user.py +16 -7
  17. maleo/identity/enums/user_medical_role.py +22 -0
  18. maleo/identity/enums/user_organization_role.py +19 -12
  19. maleo/identity/enums/user_profile.py +7 -9
  20. maleo/identity/enums/user_system_role.py +30 -0
  21. maleo/identity/mixins/api_key.py +72 -0
  22. maleo/identity/mixins/common.py +29 -0
  23. maleo/identity/mixins/organization.py +68 -8
  24. maleo/identity/mixins/organization_registration_code.py +126 -9
  25. maleo/identity/mixins/organization_relation.py +80 -0
  26. maleo/identity/mixins/patient.py +65 -0
  27. maleo/identity/mixins/user.py +86 -24
  28. maleo/identity/mixins/user_medical_role.py +68 -0
  29. maleo/identity/mixins/user_organization_role.py +68 -4
  30. maleo/identity/mixins/user_profile.py +84 -53
  31. maleo/identity/mixins/user_system_role.py +72 -4
  32. maleo/identity/schemas/api_key.py +171 -0
  33. maleo/identity/schemas/common.py +335 -0
  34. maleo/identity/schemas/organization.py +311 -0
  35. maleo/identity/schemas/organization_registration_code.py +314 -0
  36. maleo/identity/schemas/organization_relation.py +315 -0
  37. maleo/identity/schemas/patient.py +349 -0
  38. maleo/identity/schemas/user.py +318 -0
  39. maleo/identity/schemas/user_medical_role.py +316 -0
  40. maleo/identity/schemas/user_organization_role.py +317 -0
  41. maleo/identity/schemas/user_profile.py +362 -0
  42. maleo/identity/schemas/user_system_role.py +339 -0
  43. maleo/identity/types/api_key.py +7 -0
  44. maleo/identity/types/organization.py +4 -0
  45. maleo/identity/types/organization_registration_code.py +4 -0
  46. maleo/identity/types/organization_relation.py +7 -0
  47. maleo/identity/types/patient.py +4 -0
  48. maleo/identity/types/user.py +4 -0
  49. maleo/identity/types/user_medical_role.py +7 -0
  50. maleo/identity/types/user_organization_role.py +7 -0
  51. maleo/identity/types/user_profile.py +4 -0
  52. maleo/identity/types/user_system_role.py +8 -0
  53. maleo/identity/utils/organization.py +32 -0
  54. maleo/identity/utils/user.py +32 -0
  55. maleo_identity-0.1.24.dist-info/METADATA +119 -0
  56. maleo_identity-0.1.24.dist-info/RECORD +66 -0
  57. maleo_identity-0.1.24.dist-info/licenses/LICENSE +57 -0
  58. maleo/identity/client/manager.py +0 -157
  59. maleo/identity/client/services/__init__.py +0 -0
  60. maleo/identity/client/services/organization.py +0 -1944
  61. maleo/identity/client/services/organization_registration_code.py +0 -470
  62. maleo/identity/client/services/organization_role.py +0 -276
  63. maleo/identity/client/services/user.py +0 -1559
  64. maleo/identity/client/services/user_organization.py +0 -276
  65. maleo/identity/client/services/user_organization_role.py +0 -278
  66. maleo/identity/client/services/user_profile.py +0 -276
  67. maleo/identity/client/services/user_system_role.py +0 -276
  68. maleo/identity/constants/organization_role.py +0 -35
  69. maleo/identity/constants/user_organization.py +0 -58
  70. maleo/identity/db.py +0 -4
  71. maleo/identity/dtos/__init__.py +0 -0
  72. maleo/identity/dtos/configuration.py +0 -15
  73. maleo/identity/dtos/data/__init__.py +0 -0
  74. maleo/identity/dtos/data/organization_registration_code.py +0 -15
  75. maleo/identity/dtos/data/user_profile.py +0 -29
  76. maleo/identity/dtos/settings.py +0 -17
  77. maleo/identity/enums/general.py +0 -5
  78. maleo/identity/enums/organization_role.py +0 -7
  79. maleo/identity/enums/user_organization.py +0 -14
  80. maleo/identity/mixins/organization_role.py +0 -15
  81. maleo/identity/mixins/user_organization.py +0 -6
  82. maleo/identity/models/__init__.py +0 -0
  83. maleo/identity/models/organization.py +0 -62
  84. maleo/identity/models/organization_registration_code.py +0 -33
  85. maleo/identity/models/organization_role.py +0 -37
  86. maleo/identity/models/user.py +0 -39
  87. maleo/identity/models/user_organization.py +0 -48
  88. maleo/identity/models/user_organization_role.py +0 -61
  89. maleo/identity/models/user_profile.py +0 -33
  90. maleo/identity/models/user_system_role.py +0 -26
  91. maleo/identity/schemas/data/__init__.py +0 -0
  92. maleo/identity/schemas/data/organization.py +0 -36
  93. maleo/identity/schemas/data/organization_registration_code.py +0 -27
  94. maleo/identity/schemas/data/organization_role.py +0 -32
  95. maleo/identity/schemas/data/user.py +0 -33
  96. maleo/identity/schemas/data/user_organization.py +0 -23
  97. maleo/identity/schemas/data/user_organization_role.py +0 -13
  98. maleo/identity/schemas/data/user_profile.py +0 -59
  99. maleo/identity/schemas/data/user_system_role.py +0 -25
  100. maleo/identity/schemas/metadata/__init__.py +0 -0
  101. maleo/identity/schemas/metadata/user.py +0 -6
  102. maleo/identity/schemas/parameter/__init__.py +0 -0
  103. maleo/identity/schemas/parameter/client/__init__.py +0 -0
  104. maleo/identity/schemas/parameter/client/organization.py +0 -74
  105. maleo/identity/schemas/parameter/client/organization_registration_code.py +0 -24
  106. maleo/identity/schemas/parameter/client/organization_role.py +0 -42
  107. maleo/identity/schemas/parameter/client/user.py +0 -44
  108. maleo/identity/schemas/parameter/client/user_organization.py +0 -62
  109. maleo/identity/schemas/parameter/client/user_organization_role.py +0 -49
  110. maleo/identity/schemas/parameter/client/user_profile.py +0 -28
  111. maleo/identity/schemas/parameter/client/user_system_role.py +0 -43
  112. maleo/identity/schemas/parameter/general/__init__.py +0 -0
  113. maleo/identity/schemas/parameter/general/organization.py +0 -43
  114. maleo/identity/schemas/parameter/general/organization_registration_code.py +0 -54
  115. maleo/identity/schemas/parameter/general/organization_role.py +0 -14
  116. maleo/identity/schemas/parameter/general/user.py +0 -101
  117. maleo/identity/schemas/parameter/general/user_organization.py +0 -18
  118. maleo/identity/schemas/parameter/general/user_organization_role.py +0 -15
  119. maleo/identity/schemas/parameter/general/user_profile.py +0 -70
  120. maleo/identity/schemas/parameter/general/user_system_role.py +0 -30
  121. maleo/identity/schemas/parameter/service/__init__.py +0 -0
  122. maleo/identity/schemas/parameter/service/organization.py +0 -60
  123. maleo/identity/schemas/parameter/service/organization_registration_code.py +0 -24
  124. maleo/identity/schemas/parameter/service/organization_role.py +0 -35
  125. maleo/identity/schemas/parameter/service/user.py +0 -47
  126. maleo/identity/schemas/parameter/service/user_organization_role.py +0 -36
  127. maleo/identity/schemas/parameter/service/user_profile.py +0 -28
  128. maleo/identity/schemas/parameter/service/user_system_role.py +0 -31
  129. maleo/identity/types/base/__init__.py +0 -0
  130. maleo/identity/types/base/organization.py +0 -5
  131. maleo/identity/types/base/organization_registration_code.py +0 -4
  132. maleo/identity/types/base/user.py +0 -5
  133. maleo/identity/types/base/user_profile.py +0 -5
  134. maleo_identity-0.0.85.dist-info/METADATA +0 -40
  135. maleo_identity-0.0.85.dist-info/RECORD +0 -105
  136. /maleo/identity/{client → utils}/__init__.py +0 -0
  137. {maleo_identity-0.0.85.dist-info → maleo_identity-0.1.24.dist-info}/WHEEL +0 -0
  138. {maleo_identity-0.0.85.dist-info → maleo_identity-0.1.24.dist-info}/top_level.txt +0 -0
@@ -1,15 +1,75 @@
1
1
  from pydantic import BaseModel, Field
2
- from maleo.soma.mixins.parameter import Expand as BaseExpand
3
- from maleo.identity.enums.organization import ExpandableField
2
+ from typing import Annotated, Generic, Literal, TypeGuard
3
+ from uuid import UUID
4
+ from maleo.schemas.mixins.identity import Identifier, Key as BaseKey, Name as BaseName
5
+ from maleo.types.string import OptStrT
6
+ from maleo.types.uuid import OptUUIDT
7
+ from ..enums.organization import IdentifierType
8
+ from ..types.organization import IdentifierValueType
4
9
 
5
10
 
6
- class Expand(BaseExpand[ExpandableField]):
7
- pass
11
+ class Key(BaseKey, Generic[OptStrT]):
12
+ key: Annotated[OptStrT, Field(..., description="Key", max_length=255)]
8
13
 
9
14
 
10
- class Key(BaseModel):
11
- key: str = Field(..., max_length=255, description="Organization's key")
15
+ class Name(BaseName, Generic[OptStrT]):
16
+ name: Annotated[OptStrT, Field(..., description="Name", max_length=255)]
12
17
 
13
18
 
14
- class Name(BaseModel):
15
- name: str = Field(..., max_length=255, description="Organization's name")
19
+ class Secret(BaseModel, Generic[OptUUIDT]):
20
+ secret: Annotated[OptUUIDT, Field(..., description="Secret")]
21
+
22
+
23
+ class OrganizationIdentifier(Identifier[IdentifierType, IdentifierValueType]):
24
+ @property
25
+ def column_and_value(self) -> tuple[str, IdentifierValueType]:
26
+ return self.type.column, self.value
27
+
28
+
29
+ class IdOrganizationIdentifier(Identifier[Literal[IdentifierType.ID], int]):
30
+ type: Annotated[
31
+ Literal[IdentifierType.ID],
32
+ Field(IdentifierType.ID, description="Identifier's type"),
33
+ ] = IdentifierType.ID
34
+ value: Annotated[int, Field(..., description="Identifier's value", ge=1)]
35
+
36
+
37
+ class UUIDOrganizationIdentifier(Identifier[Literal[IdentifierType.UUID], UUID]):
38
+ type: Annotated[
39
+ Literal[IdentifierType.UUID],
40
+ Field(IdentifierType.UUID, description="Identifier's type"),
41
+ ] = IdentifierType.UUID
42
+
43
+
44
+ class KeyOrganizationIdentifier(Identifier[Literal[IdentifierType.KEY], str]):
45
+ type: Annotated[
46
+ Literal[IdentifierType.KEY],
47
+ Field(IdentifierType.KEY, description="Identifier's type"),
48
+ ] = IdentifierType.KEY
49
+ value: Annotated[str, Field(..., description="Identifier's value", max_length=255)]
50
+
51
+
52
+ AnyOrganizationIdentifier = (
53
+ OrganizationIdentifier
54
+ | IdOrganizationIdentifier
55
+ | UUIDOrganizationIdentifier
56
+ | KeyOrganizationIdentifier
57
+ )
58
+
59
+
60
+ def is_id_identifier(
61
+ identifier: AnyOrganizationIdentifier,
62
+ ) -> TypeGuard[IdOrganizationIdentifier]:
63
+ return identifier.type is IdentifierType.ID and isinstance(identifier.value, int)
64
+
65
+
66
+ def is_uuid_identifier(
67
+ identifier: AnyOrganizationIdentifier,
68
+ ) -> TypeGuard[UUIDOrganizationIdentifier]:
69
+ return identifier.type is IdentifierType.UUID and isinstance(identifier.value, UUID)
70
+
71
+
72
+ def is_key_identifier(
73
+ identifier: AnyOrganizationIdentifier,
74
+ ) -> TypeGuard[KeyOrganizationIdentifier]:
75
+ return identifier.type is IdentifierType.KEY and isinstance(identifier.value, str)
@@ -1,19 +1,136 @@
1
- from pydantic import BaseModel, Field
1
+ from pydantic import BaseModel, Field, model_validator
2
+ from typing import Annotated, Generic, Literal, Self, TypeGuard
2
3
  from uuid import UUID
3
- from maleo.soma.types.base import OptionalInteger
4
+ from maleo.schemas.mixins.identity import Identifier
5
+ from maleo.types.integer import OptIntT
6
+ from maleo.types.misc import OptIntOrStr
7
+ from maleo.types.string import OptStrT
8
+ from ..enums.organization_registration_code import IdentifierType
9
+ from ..types.organization_registration_code import IdentifierValueType
4
10
 
5
11
 
6
- class Code(BaseModel):
7
- code: UUID = Field(..., description="Registration code")
12
+ class CodeOrLength(BaseModel):
13
+ code_or_length: Annotated[
14
+ OptIntOrStr,
15
+ Field(
16
+ None,
17
+ description=(
18
+ "Code (str) or length (int). "
19
+ "If code is given, the length must be between 6 and 36 inclusive. "
20
+ "If length is given, the value must be between 6 and 36 inclusive. "
21
+ "Will generate random 6 char string if omitted"
22
+ ),
23
+ ),
24
+ ]
8
25
 
26
+ @model_validator(mode="after")
27
+ def validate_code_or_length(self) -> Self:
28
+ code_or_length = self.code_or_length
29
+ if code_or_length is None:
30
+ return self
31
+ print(code_or_length)
32
+ if isinstance(code_or_length, int):
33
+ length = code_or_length
34
+ elif isinstance(code_or_length, str):
35
+ length = len(code_or_length)
36
+ else:
37
+ raise ValueError("Code or Length must be either int or str")
38
+ if length < 6 or length > 36:
39
+ raise ValueError("Code or Length must be between 6 and 36 inclusive")
40
+ return self
9
41
 
10
- class MaxUses(BaseModel):
11
- max_uses: int = Field(1, ge=1, description="Max code uses")
12
42
 
43
+ class Code(BaseModel, Generic[OptStrT]):
44
+ code: Annotated[
45
+ OptStrT, Field(..., description="Code", min_length=6, max_length=36)
46
+ ]
13
47
 
14
- class OptionalMaxUses(BaseModel):
15
- max_uses: OptionalInteger = Field(None, ge=1, description="Max code uses")
48
+
49
+ class MaxUses(BaseModel, Generic[OptIntT]):
50
+ max_uses: Annotated[OptIntT, Field(..., description="Max Uses", ge=1)]
16
51
 
17
52
 
18
53
  class CurrentUses(BaseModel):
19
- current_uses: int = Field(0, ge=0, description="Current code uses")
54
+ current_uses: Annotated[int, Field(0, description="Current Uses", ge=0)] = 0
55
+
56
+
57
+ class OrganizationRegistrationCodeIdentifier(
58
+ Identifier[IdentifierType, IdentifierValueType]
59
+ ):
60
+ @property
61
+ def column_and_value(self) -> tuple[str, IdentifierValueType]:
62
+ return self.type.column, self.value
63
+
64
+
65
+ class IdOrganizationRegistrationCodeIdentifier(
66
+ Identifier[Literal[IdentifierType.ID], int]
67
+ ):
68
+ type: Annotated[
69
+ Literal[IdentifierType.ID],
70
+ Field(IdentifierType.ID, description="Identifier's type"),
71
+ ] = IdentifierType.ID
72
+ value: Annotated[int, Field(..., description="Identifier's value", ge=1)]
73
+
74
+
75
+ class OrgIdOrganizationRegistrationCodeIdentifier(
76
+ Identifier[Literal[IdentifierType.ORGANIZATION_ID], int]
77
+ ):
78
+ type: Annotated[
79
+ Literal[IdentifierType.ORGANIZATION_ID],
80
+ Field(IdentifierType.ORGANIZATION_ID, description="Identifier's type"),
81
+ ] = IdentifierType.ORGANIZATION_ID
82
+ value: Annotated[int, Field(..., description="Identifier's value", ge=1)]
83
+
84
+
85
+ class UUIDOrganizationRegistrationCodeIdentifier(
86
+ Identifier[Literal[IdentifierType.UUID], UUID]
87
+ ):
88
+ type: Annotated[
89
+ Literal[IdentifierType.UUID],
90
+ Field(IdentifierType.UUID, description="Identifier's type"),
91
+ ] = IdentifierType.UUID
92
+
93
+
94
+ class CodeOrganizationRegistrationCodeIdentifier(
95
+ Identifier[Literal[IdentifierType.CODE], str]
96
+ ):
97
+ type: Annotated[
98
+ Literal[IdentifierType.CODE],
99
+ Field(IdentifierType.CODE, description="Identifier's type"),
100
+ ] = IdentifierType.CODE
101
+ value: Annotated[str, Field(..., description="Identifier's value", max_length=36)]
102
+
103
+
104
+ AnyOrganizationRegistrationCodeIdentifier = (
105
+ OrganizationRegistrationCodeIdentifier
106
+ | IdOrganizationRegistrationCodeIdentifier
107
+ | OrgIdOrganizationRegistrationCodeIdentifier
108
+ | UUIDOrganizationRegistrationCodeIdentifier
109
+ | CodeOrganizationRegistrationCodeIdentifier
110
+ )
111
+
112
+
113
+ def is_id_identifier(
114
+ identifier: AnyOrganizationRegistrationCodeIdentifier,
115
+ ) -> TypeGuard[IdOrganizationRegistrationCodeIdentifier]:
116
+ return identifier.type is IdentifierType.ID and isinstance(identifier.value, int)
117
+
118
+
119
+ def is_org_id_identifier(
120
+ identifier: AnyOrganizationRegistrationCodeIdentifier,
121
+ ) -> TypeGuard[OrgIdOrganizationRegistrationCodeIdentifier]:
122
+ return identifier.type is IdentifierType.ORGANIZATION_ID and isinstance(
123
+ identifier.value, int
124
+ )
125
+
126
+
127
+ def is_uuid_identifier(
128
+ identifier: AnyOrganizationRegistrationCodeIdentifier,
129
+ ) -> TypeGuard[UUIDOrganizationRegistrationCodeIdentifier]:
130
+ return identifier.type is IdentifierType.UUID and isinstance(identifier.value, UUID)
131
+
132
+
133
+ def is_code_identifier(
134
+ identifier: AnyOrganizationRegistrationCodeIdentifier,
135
+ ) -> TypeGuard[CodeOrganizationRegistrationCodeIdentifier]:
136
+ return identifier.type is IdentifierType.CODE and isinstance(identifier.value, str)
@@ -0,0 +1,80 @@
1
+ from pydantic import BaseModel, Field
2
+ from typing import Annotated, Generic, Literal, TypeGuard
3
+ from uuid import UUID
4
+ from maleo.schemas.mixins.identity import Identifier
5
+ from maleo.types.any import ManyAny
6
+ from maleo.types.boolean import OptBoolT
7
+ from maleo.types.misc import OptListOfAnyOrStrToAnyDict
8
+ from maleo.types.string import ManyStrs
9
+ from ..enums.organization_relation import IdentifierType
10
+ from ..types.organization_relation import CompositeIdentifierType, IdentifierValueType
11
+
12
+
13
+ class IsBidirectional(BaseModel, Generic[OptBoolT]):
14
+ is_bidirectional: Annotated[OptBoolT, Field(..., description="Is Bidirectional")]
15
+
16
+
17
+ class Meta(BaseModel):
18
+ meta: Annotated[OptListOfAnyOrStrToAnyDict, Field(None, description="Meta")] = None
19
+
20
+
21
+ class OrganizationRelationIdentifier(Identifier[IdentifierType, IdentifierValueType]):
22
+ @property
23
+ def columns_and_values(self) -> tuple[ManyStrs, ManyAny]:
24
+ values = self.value if isinstance(self.value, tuple) else (self.value,)
25
+ return self.type.columns, values
26
+
27
+
28
+ class IdOrganizationRelationIdentifier(Identifier[Literal[IdentifierType.ID], int]):
29
+ type: Annotated[
30
+ Literal[IdentifierType.ID],
31
+ Field(IdentifierType.ID, description="Identifier's type"),
32
+ ] = IdentifierType.ID
33
+ value: Annotated[int, Field(..., description="Identifier's value", ge=1)]
34
+
35
+
36
+ class UUIDOrganizationRelationIdentifier(
37
+ Identifier[Literal[IdentifierType.UUID], UUID]
38
+ ):
39
+ type: Annotated[
40
+ Literal[IdentifierType.UUID],
41
+ Field(IdentifierType.UUID, description="Identifier's type"),
42
+ ] = IdentifierType.UUID
43
+
44
+
45
+ class CompositeOrganizationRelationIdentifier(
46
+ Identifier[Literal[IdentifierType.COMPOSITE], CompositeIdentifierType]
47
+ ):
48
+ type: Annotated[
49
+ Literal[IdentifierType.COMPOSITE],
50
+ Field(IdentifierType.COMPOSITE, description="Identifier's type"),
51
+ ] = IdentifierType.COMPOSITE
52
+ value: Annotated[CompositeIdentifierType, Field(..., description="Identifier's value")]
53
+
54
+
55
+ AnyOrganizationRelationIdentifier = (
56
+ OrganizationRelationIdentifier
57
+ | IdOrganizationRelationIdentifier
58
+ | UUIDOrganizationRelationIdentifier
59
+ | CompositeOrganizationRelationIdentifier
60
+ )
61
+
62
+
63
+ def is_id_identifier(
64
+ identifier: AnyOrganizationRelationIdentifier,
65
+ ) -> TypeGuard[IdOrganizationRelationIdentifier]:
66
+ return identifier.type is IdentifierType.ID and isinstance(identifier.value, int)
67
+
68
+
69
+ def is_uuid_identifier(
70
+ identifier: AnyOrganizationRelationIdentifier,
71
+ ) -> TypeGuard[UUIDOrganizationRelationIdentifier]:
72
+ return identifier.type is IdentifierType.UUID and isinstance(identifier.value, UUID)
73
+
74
+
75
+ def is_composite_identifier(
76
+ identifier: AnyOrganizationRelationIdentifier,
77
+ ) -> TypeGuard[CompositeOrganizationRelationIdentifier]:
78
+ return identifier.type is IdentifierType.COMPOSITE and isinstance(
79
+ identifier.value, tuple
80
+ )
@@ -0,0 +1,65 @@
1
+ from pydantic import BaseModel, Field, model_validator
2
+ from typing import Annotated, Generic, Literal, Self, TypeGuard
3
+ from uuid import UUID
4
+ from maleo.schemas.mixins.identity import Identifier, Passport as BasePassport
5
+ from maleo.types.string import OptStr, OptStrT
6
+ from ..enums.patient import IdentifierType, OptListOfExpandableFields
7
+ from ..types.patient import IdentifierValueType
8
+ from .common import IdCard
9
+
10
+
11
+ class Passport(BasePassport, Generic[OptStrT]):
12
+ passport: Annotated[OptStrT, Field(..., description="Passport", max_length=9)]
13
+
14
+
15
+ class PatientIdentity(
16
+ Passport[OptStr],
17
+ IdCard[OptStr],
18
+ ):
19
+ @model_validator(mode="after")
20
+ def chk_id_card_or_passport(self) -> Self:
21
+ if self.id_card is None and self.passport is None:
22
+ raise ValueError("Either ID Card or Passport must exist")
23
+ return self
24
+
25
+
26
+ class Expand(BaseModel):
27
+ expand: Annotated[
28
+ OptListOfExpandableFields, Field(None, description="Expanded field(s)")
29
+ ] = None
30
+
31
+
32
+ class PatientIdentifier(Identifier[IdentifierType, IdentifierValueType]):
33
+ @property
34
+ def column_and_value(self) -> tuple[str, IdentifierValueType]:
35
+ return self.type.column, self.value
36
+
37
+
38
+ class IdPatientIdentifier(Identifier[Literal[IdentifierType.ID], int]):
39
+ type: Annotated[
40
+ Literal[IdentifierType.ID],
41
+ Field(IdentifierType.ID, description="Identifier's type"),
42
+ ] = IdentifierType.ID
43
+ value: Annotated[int, Field(..., description="Identifier's value", ge=1)]
44
+
45
+
46
+ class UUIDPatientIdentifier(Identifier[Literal[IdentifierType.UUID], UUID]):
47
+ type: Annotated[
48
+ Literal[IdentifierType.UUID],
49
+ Field(IdentifierType.UUID, description="Identifier's type"),
50
+ ] = IdentifierType.UUID
51
+
52
+
53
+ AnyPatientIdentifier = PatientIdentifier | IdPatientIdentifier | UUIDPatientIdentifier
54
+
55
+
56
+ def is_id_identifier(
57
+ identifier: AnyPatientIdentifier,
58
+ ) -> TypeGuard[IdPatientIdentifier]:
59
+ return identifier.type is IdentifierType.ID and isinstance(identifier.value, int)
60
+
61
+
62
+ def is_uuid_identifier(
63
+ identifier: AnyPatientIdentifier,
64
+ ) -> TypeGuard[UUIDPatientIdentifier]:
65
+ return identifier.type is IdentifierType.UUID and isinstance(identifier.value, UUID)
@@ -1,47 +1,109 @@
1
1
  from pydantic import BaseModel, Field
2
+ from typing import Annotated, Generic, Literal, TypeGuard
2
3
  from uuid import UUID
3
- from maleo.soma.mixins.parameter import Expand as BaseExpand
4
- from maleo.soma.types.base import OptionalListOfStrings
5
- from maleo.identity.enums.user import ExpandableField
4
+ from maleo.schemas.mixins.identity import Identifier
5
+ from maleo.types.string import OptStrT, OptListOfStrsT
6
+ from ..enums.user import IdentifierType
7
+ from ..types.user import IdentifierValueType
6
8
 
7
9
 
8
- class Expand(BaseExpand[ExpandableField]):
9
- pass
10
+ class Username(BaseModel, Generic[OptStrT]):
11
+ username: Annotated[
12
+ OptStrT, Field(..., description="User's username", max_length=50)
13
+ ]
10
14
 
11
15
 
12
- class Username(BaseModel):
13
- username: str = Field(..., max_length=50, description="User's username")
16
+ class Usernames(BaseModel, Generic[OptListOfStrsT]):
17
+ usernames: Annotated[OptListOfStrsT, Field(..., description="User's Usernames")]
14
18
 
15
19
 
16
- class OptionalListOfUsernames(BaseModel):
17
- usernames: OptionalListOfStrings = Field(None, description="Specific usernames")
20
+ class Email(BaseModel, Generic[OptStrT]):
21
+ email: Annotated[OptStrT, Field(..., description="User's email", max_length=255)]
18
22
 
19
23
 
20
- class Email(BaseModel):
21
- email: str = Field(..., max_length=255, description="User's email")
24
+ class Emails(BaseModel, Generic[OptListOfStrsT]):
25
+ emails: Annotated[OptListOfStrsT, Field(..., description="User's Emails")]
22
26
 
23
27
 
24
- class OptionalListOfEmails(BaseModel):
25
- emails: OptionalListOfStrings = Field(None, description="Specific emails")
28
+ class Phone(BaseModel, Generic[OptStrT]):
29
+ phone: Annotated[OptStrT, Field(..., description="User's phone", max_length=15)]
26
30
 
27
31
 
28
- class Phone(BaseModel):
29
- phone: str = Field(..., min_length=4, max_length=15, description="User's phone")
32
+ class Phones(BaseModel, Generic[OptListOfStrsT]):
33
+ phones: Annotated[OptListOfStrsT, Field(..., description="User's Phones")]
30
34
 
31
35
 
32
- class OptionalListOfPhones(BaseModel):
33
- phones: OptionalListOfStrings = Field(None, description="Specific phones")
36
+ class Password(BaseModel):
37
+ password: Annotated[str, Field(..., description="Password", max_length=255)]
34
38
 
35
39
 
36
- class Password(BaseModel):
37
- password: str = Field(..., max_length=255, description="User's password")
40
+ class UserIdentifier(Identifier[IdentifierType, IdentifierValueType]):
41
+ @property
42
+ def column_and_value(self) -> tuple[str, IdentifierValueType]:
43
+ return self.type.column, self.value
44
+
45
+
46
+ class IdUserIdentifier(Identifier[Literal[IdentifierType.ID], int]):
47
+ type: Annotated[
48
+ Literal[IdentifierType.ID],
49
+ Field(IdentifierType.ID, description="Identifier's type"),
50
+ ] = IdentifierType.ID
51
+ value: Annotated[int, Field(..., description="Identifier's value", ge=1)]
52
+
53
+
54
+ class UUIDUserIdentifier(Identifier[Literal[IdentifierType.UUID], UUID]):
55
+ type: Annotated[
56
+ Literal[IdentifierType.UUID],
57
+ Field(IdentifierType.UUID, description="Identifier's type"),
58
+ ] = IdentifierType.UUID
59
+
60
+
61
+ class UsernameUserIdentifier(Identifier[Literal[IdentifierType.USERNAME], str]):
62
+ type: Annotated[
63
+ Literal[IdentifierType.USERNAME],
64
+ Field(IdentifierType.USERNAME, description="Identifier's type"),
65
+ ] = IdentifierType.USERNAME
66
+ value: Annotated[str, Field(..., description="Identifier's value", max_length=50)]
67
+
68
+
69
+ class EmailUserIdentifier(Identifier[Literal[IdentifierType.EMAIL], str]):
70
+ type: Annotated[
71
+ Literal[IdentifierType.EMAIL],
72
+ Field(IdentifierType.EMAIL, description="Identifier's type"),
73
+ ] = IdentifierType.EMAIL
74
+ value: Annotated[str, Field(..., description="Identifier's value", max_length=255)]
75
+
76
+
77
+ AnyUserIdentifier = (
78
+ UserIdentifier
79
+ | IdUserIdentifier
80
+ | UUIDUserIdentifier
81
+ | UsernameUserIdentifier
82
+ | EmailUserIdentifier
83
+ )
84
+
85
+
86
+ def is_id_identifier(
87
+ identifier: AnyUserIdentifier,
88
+ ) -> TypeGuard[IdUserIdentifier]:
89
+ return identifier.type is IdentifierType.ID and isinstance(identifier.value, int)
90
+
91
+
92
+ def is_uuid_identifier(
93
+ identifier: AnyUserIdentifier,
94
+ ) -> TypeGuard[UUIDUserIdentifier]:
95
+ return identifier.type is IdentifierType.UUID and isinstance(identifier.value, UUID)
38
96
 
39
97
 
40
- class PasswordConfirmation(BaseModel):
41
- password_confirmation: str = Field(
42
- ..., max_length=255, description="User's password confirmation"
98
+ def is_username_identifier(
99
+ identifier: AnyUserIdentifier,
100
+ ) -> TypeGuard[UsernameUserIdentifier]:
101
+ return identifier.type is IdentifierType.USERNAME and isinstance(
102
+ identifier.value, str
43
103
  )
44
104
 
45
105
 
46
- class RegistrationCode(BaseModel):
47
- registration_code: UUID = Field(..., description="Registration code")
106
+ def is_email_identifier(
107
+ identifier: AnyUserIdentifier,
108
+ ) -> TypeGuard[EmailUserIdentifier]:
109
+ return identifier.type is IdentifierType.EMAIL and isinstance(identifier.value, str)
@@ -0,0 +1,68 @@
1
+ from pydantic import Field
2
+ from typing import Annotated, Literal, TypeGuard
3
+ from uuid import UUID
4
+ from maleo.schemas.mixins.identity import Identifier
5
+ from maleo.types.any import ManyAny
6
+ from maleo.types.string import ManyStrs
7
+ from ..enums.user_medical_role import IdentifierType
8
+ from ..types.user_medical_role import CompositeIdentifierType, IdentifierValueType
9
+
10
+
11
+ class UserMedicalRoleIdentifier(Identifier[IdentifierType, IdentifierValueType]):
12
+ @property
13
+ def columns_and_values(self) -> tuple[ManyStrs, ManyAny]:
14
+ values = self.value if isinstance(self.value, tuple) else (self.value,)
15
+ return self.type.columns, values
16
+
17
+
18
+ class IdUserMedicalRoleIdentifier(Identifier[Literal[IdentifierType.ID], int]):
19
+ type: Annotated[
20
+ Literal[IdentifierType.ID],
21
+ Field(IdentifierType.ID, description="Identifier's type"),
22
+ ] = IdentifierType.ID
23
+ value: Annotated[int, Field(..., description="Identifier's value", ge=1)]
24
+
25
+
26
+ class UUIDUserMedicalRoleIdentifier(Identifier[Literal[IdentifierType.UUID], UUID]):
27
+ type: Annotated[
28
+ Literal[IdentifierType.UUID],
29
+ Field(IdentifierType.UUID, description="Identifier's type"),
30
+ ] = IdentifierType.UUID
31
+
32
+
33
+ class CompositeUserMedicalRoleIdentifier(
34
+ Identifier[Literal[IdentifierType.COMPOSITE], CompositeIdentifierType]
35
+ ):
36
+ type: Annotated[
37
+ Literal[IdentifierType.COMPOSITE],
38
+ Field(IdentifierType.COMPOSITE, description="Identifier's type"),
39
+ ] = IdentifierType.COMPOSITE
40
+ value: Annotated[CompositeIdentifierType, Field(..., description="Identifier's value")]
41
+
42
+
43
+ AnyUserMedicalRoleIdentifier = (
44
+ UserMedicalRoleIdentifier
45
+ | IdUserMedicalRoleIdentifier
46
+ | UUIDUserMedicalRoleIdentifier
47
+ | CompositeUserMedicalRoleIdentifier
48
+ )
49
+
50
+
51
+ def is_id_identifier(
52
+ identifier: AnyUserMedicalRoleIdentifier,
53
+ ) -> TypeGuard[IdUserMedicalRoleIdentifier]:
54
+ return identifier.type is IdentifierType.ID and isinstance(identifier.value, int)
55
+
56
+
57
+ def is_uuid_identifier(
58
+ identifier: AnyUserMedicalRoleIdentifier,
59
+ ) -> TypeGuard[UUIDUserMedicalRoleIdentifier]:
60
+ return identifier.type is IdentifierType.UUID and isinstance(identifier.value, UUID)
61
+
62
+
63
+ def is_composite_identifier(
64
+ identifier: AnyUserMedicalRoleIdentifier,
65
+ ) -> TypeGuard[CompositeUserMedicalRoleIdentifier]:
66
+ return identifier.type is IdentifierType.COMPOSITE and isinstance(
67
+ identifier.value, tuple
68
+ )
@@ -1,6 +1,70 @@
1
- from maleo.soma.mixins.parameter import Expand as BaseExpand
2
- from maleo.identity.enums.user_organization_role import ExpandableField
1
+ from pydantic import Field
2
+ from typing import Annotated, Literal, TypeGuard
3
+ from uuid import UUID
4
+ from maleo.schemas.mixins.identity import Identifier
5
+ from maleo.types.any import ManyAny
6
+ from maleo.types.string import ManyStrs
7
+ from ..enums.user_organization_role import IdentifierType
8
+ from ..types.user_organization_role import CompositeIdentifierType, IdentifierValueType
3
9
 
4
10
 
5
- class Expand(BaseExpand[ExpandableField]):
6
- pass
11
+ class UserOrganizationRoleIdentifier(Identifier[IdentifierType, IdentifierValueType]):
12
+ @property
13
+ def columns_and_values(self) -> tuple[ManyStrs, ManyAny]:
14
+ values = self.value if isinstance(self.value, tuple) else (self.value,)
15
+ return self.type.columns, values
16
+
17
+
18
+ class IdUserOrganizationRoleIdentifier(Identifier[Literal[IdentifierType.ID], int]):
19
+ type: Annotated[
20
+ Literal[IdentifierType.ID],
21
+ Field(IdentifierType.ID, description="Identifier's type"),
22
+ ] = IdentifierType.ID
23
+ value: Annotated[int, Field(..., description="Identifier's value", ge=1)]
24
+
25
+
26
+ class UUIDUserOrganizationRoleIdentifier(
27
+ Identifier[Literal[IdentifierType.UUID], UUID]
28
+ ):
29
+ type: Annotated[
30
+ Literal[IdentifierType.UUID],
31
+ Field(IdentifierType.UUID, description="Identifier's type"),
32
+ ] = IdentifierType.UUID
33
+
34
+
35
+ class CompositeUserOrganizationRoleIdentifier(
36
+ Identifier[Literal[IdentifierType.COMPOSITE], CompositeIdentifierType]
37
+ ):
38
+ type: Annotated[
39
+ Literal[IdentifierType.COMPOSITE],
40
+ Field(IdentifierType.COMPOSITE, description="Identifier's type"),
41
+ ] = IdentifierType.COMPOSITE
42
+ value: Annotated[CompositeIdentifierType, Field(..., description="Identifier's value")]
43
+
44
+
45
+ AnyUserOrganizationRoleIdentifier = (
46
+ UserOrganizationRoleIdentifier
47
+ | IdUserOrganizationRoleIdentifier
48
+ | UUIDUserOrganizationRoleIdentifier
49
+ | CompositeUserOrganizationRoleIdentifier
50
+ )
51
+
52
+
53
+ def is_id_identifier(
54
+ identifier: AnyUserOrganizationRoleIdentifier,
55
+ ) -> TypeGuard[IdUserOrganizationRoleIdentifier]:
56
+ return identifier.type is IdentifierType.ID and isinstance(identifier.value, int)
57
+
58
+
59
+ def is_uuid_identifier(
60
+ identifier: AnyUserOrganizationRoleIdentifier,
61
+ ) -> TypeGuard[UUIDUserOrganizationRoleIdentifier]:
62
+ return identifier.type is IdentifierType.UUID and isinstance(identifier.value, UUID)
63
+
64
+
65
+ def is_composite_identifier(
66
+ identifier: AnyUserOrganizationRoleIdentifier,
67
+ ) -> TypeGuard[CompositeUserOrganizationRoleIdentifier]:
68
+ return identifier.type is IdentifierType.COMPOSITE and isinstance(
69
+ identifier.value, tuple
70
+ )