-
Notifications
You must be signed in to change notification settings - Fork 0
/
models.py
159 lines (131 loc) · 4.34 KB
/
models.py
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
from datetime import datetime
from enum import Enum
from typing import Annotated, Any, List
import strawberry
from bson import ObjectId
from pydantic import (
BaseModel,
BeforeValidator,
ConfigDict,
EmailStr,
Field,
HttpUrl,
TypeAdapter,
field_validator,
)
from pydantic_core import core_schema
from pytz import timezone
http_url_adapter = TypeAdapter(HttpUrl)
HttpUrlString = Annotated[
str,
BeforeValidator(
lambda value: str(http_url_adapter.validate_python(value))
),
]
def create_utc_time():
return datetime.now(timezone("UTC"))
# for handling mongo ObjectIds
class PyObjectId(ObjectId):
@classmethod
def __get_pydantic_core_schema__(cls, source_type: Any, handler):
return core_schema.union_schema(
[
# check if it's an instance first before doing any further work
core_schema.is_instance_schema(ObjectId),
core_schema.no_info_plain_validator_function(cls.validate),
],
serialization=core_schema.to_string_ser_schema(),
)
@classmethod
def validate(cls, v):
if not ObjectId.is_valid(v):
raise ValueError("Invalid ObjectId")
return ObjectId(v)
@classmethod
def __get_pydantic_json_schema__(cls, field_schema):
field_schema.update(type="string")
def iiit_email_only(v: str) -> str:
valid_domains = [
"@iiit.ac.in",
"@students.iiit.ac.in",
"@research.iiit.ac.in",
]
if any(valid_domain in v for valid_domain in valid_domains):
return v.lower()
raise ValueError("Official iiit emails only.")
def current_year() -> int:
return datetime.now().year
@strawberry.enum
class EnumStates(str, Enum):
active = "active"
deleted = "deleted"
@strawberry.enum
class EnumCategories(str, Enum):
cultural = "cultural"
technical = "technical"
affinity = "affinity"
admin = "admin"
body = "body"
other = "other"
class Social(BaseModel):
website: HttpUrlString | None = None
instagram: HttpUrlString | None = None
facebook: HttpUrlString | None = None
youtube: HttpUrlString | None = None
twitter: HttpUrlString | None = None
linkedin: HttpUrlString | None = None
discord: HttpUrlString | None = None
whatsapp: HttpUrlString | None = None
other_links: List[HttpUrlString] = Field([]) # Type and URL
@field_validator("other_links")
@classmethod
def validate_unique_links(cls, value):
if len(value) != len(set(value)):
raise ValueError("Duplicate URLs are not allowed in 'other_links'")
return value
class Club(BaseModel):
id: PyObjectId = Field(default_factory=PyObjectId, alias="_id")
cid: str = Field(..., description="Club ID")
code: str = Field(
...,
description="Unique Short Code of Club",
max_length=15,
min_length=2,
) # equivalent to club id = short name
state: EnumStates = EnumStates.active
category: EnumCategories = EnumCategories.other
name: str = Field(..., min_length=5, max_length=100)
email: EmailStr = Field(...) # Optional but required
logo: str | None = Field(None, description="Club Official Logo pic URL")
banner: str | None = Field(None, description="Club Long Banner pic URL")
banner_square: str | None = Field(
None, description="Club Square Banner pic URL"
)
tagline: str | None = Field(None, min_length=2, max_length=200)
description: str | None = Field(
"No Description Provided!",
max_length=9999,
description="Club Description",
)
socials: Social = Field({}, description="Social Profile Links")
created_time: datetime = Field(
default_factory=create_utc_time, frozen=True
)
updated_time: datetime = Field(default_factory=create_utc_time)
# Validator
@field_validator("email", mode="before")
def _check_email(cls, v):
return iiit_email_only(v)
model_config = ConfigDict(
populate_by_name=True,
arbitrary_types_allowed=True,
json_encoders={ObjectId: str},
str_max_length=10000,
validate_assignment=True,
validate_default=True,
validate_return=True,
extra="forbid",
str_strip_whitespace=True,
)
# TODO: ADD CLUB SUBSCRIPTION MODEL - v2
# ADD Descriptions for non-direct fields