Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

documentation done for the clubs #18

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.venv/
*venv/
.vscode/
.in
.out
__pycache__/
build/
17 changes: 17 additions & 0 deletions db.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
"""
MongoDB Initialization Module.

This module sets up the connection to the MongoDB database.
It ensures that the required indexes are created.

Attributes:
MONGO_USERNAME (str): An environment variable having MongoDB username. Defaults to "username".
MONGO_PASSWORD (str): An environment variable having MongoDB password. Defaults to "password".
MONGO_PORT (str): MongoDB port. Defaults to "27017".
MONGO_URI (str): MongoDB URI.
MONGO_DATABASE (str): MongoDB database name.
client (MongoClient): MongoDB client.
db (Database): MongoDB database.
clubsdb (Collection): MongoDB collection for clubs.
"""

from os import getenv

from pymongo import MongoClient
Expand Down
15 changes: 14 additions & 1 deletion main.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
"""
Main module for the Clubs Microservice.

This module sets up the FastAPI application and integrates the Strawberry GraphQL schema.
It includes the configuration for queries, mutations, and context.

Attributes:
GLOBAL_DEBUG (str): Environment variable that Enables or Disables debug mode. Defaults to "False".
DEBUG (bool): Indicates whether the application is running in debug mode.
gql_app (GraphQLRouter): The GraphQL router for handling GraphQL requests.
app (FastAPI): The FastAPI application instance.
"""

from os import getenv

import strawberry
Expand All @@ -20,7 +33,7 @@
Mutation = create_type("Mutation", mutations)


# override context getter
# Returns The custom context by overriding the context getter.
async def get_context() -> Context:
return Context()

Expand Down
64 changes: 64 additions & 0 deletions models.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
from pydantic_core import core_schema
from pytz import timezone

"""
Annotated type and validator for HTTP URLs to be stored as strings.
"""
http_url_adapter = TypeAdapter(HttpUrl)
HttpUrlString = Annotated[
str,
Expand All @@ -27,11 +30,18 @@


def create_utc_time():
"""
Returns the current time according to UTC timezone.
"""
return datetime.now(timezone("UTC"))


# for handling mongo ObjectIds
class PyObjectId(ObjectId):
"""
Class for handling MongoDB document ObjectIds for 'id' fields in Models.
"""

@classmethod
def __get_pydantic_core_schema__(cls, source_type: Any, handler):
return core_schema.union_schema(
Expand All @@ -55,6 +65,18 @@ def __get_pydantic_json_schema__(cls, field_schema):


def iiit_email_only(v: str) -> str:
"""
Validates emails according to the valid forms.

Args:
v (str): The Email to be validated.

Raises:
ValueError: If email is not valid.

Returns:
str: Valid Email.
"""
valid_domains = [
"@iiit.ac.in",
"@students.iiit.ac.in",
Expand All @@ -67,17 +89,22 @@ def iiit_email_only(v: str) -> str:


def current_year() -> int:
"""Returns the current year."""
return datetime.now().year


@strawberry.enum
class EnumStates(str, Enum):
"""Enum for state of the club."""

active = "active"
deleted = "deleted"


@strawberry.enum
class EnumCategories(str, Enum):
"""Enum for category of the club."""

cultural = "cultural"
technical = "technical"
affinity = "affinity"
Expand All @@ -87,6 +114,21 @@ class EnumCategories(str, Enum):


class Social(BaseModel):
"""
Model for storing social handles of a Club

Attributes:
website (HttpUrlString | None): Club Website URL. Defaults to None.
instagram (HttpUrlString | None): Club Instagram handle. Defaults to None.
facebook (HttpUrlString | None): Club Facebook. Defaults to None.
youtube (HttpUrlString | None): Club YouTube handle. Defaults to None.
twitter (HttpUrlString | None): Club Twitter handle. Defaults to None.
linkedin (HttpUrlString | None): Club LinkedIn handle. Defaults to None.
discord (HttpUrlString | None): Club Discord handle. Defaults to None.
whatsapp (HttpUrlString | None): Club WhatsApp handle. Defaults to None.
other_links (List[HttpUrlString]): List of other social handles and URLs
"""

website: HttpUrlString | None = None
instagram: HttpUrlString | None = None
facebook: HttpUrlString | None = None
Expand All @@ -106,6 +148,28 @@ def validate_unique_links(cls, value):


class Club(BaseModel):
"""
Model for storing Club details.

Attributes:
id (PyObjectId): Unique ObjectId of the document of the Club.
cid (str): the Club ID.
code (str): Unique Short Code of Club.
state (EnumStates): State of the Club.
category (EnumCategories): Category of the Club.
student_body (bool): Is this a Student Body?
name (str): Name of the Club.
email (EmailStr): Email of the Club.
logo (str | None): Club Official Logo. Defaults to None.
banner (str | None): Club Long Banner. Defaults to None.
banner_square (str | None): Club Square Banner. Defaults to None.
tagline (str | None): Tagline of the Club. Defaults to None.
description (str | None): Club Description. Defaults to None.
socials (Social): Social Handles of the Club.
created_time (datetime): Time of creation of the Club.
updated_time (datetime): Time of last update to the Club.
"""

id: PyObjectId = Field(default_factory=PyObjectId, alias="_id")
cid: str = Field(..., description="Club ID")
code: str = Field(
Expand Down
75 changes: 70 additions & 5 deletions mutations.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
Mutations for Clubs
"""

import strawberry
from fastapi.encoders import jsonable_encoder

Expand All @@ -23,9 +27,22 @@
@strawberry.mutation
def createClub(clubInput: FullClubInput, info: Info) -> SimpleClubType:
"""
Create a new Club.
Checks for the 'cc' role, else raises an Error.
Checks for uniqueness of the club code.
Mutation for creation of a new club by CC.

Args:
clubInput (FullClubInput): Full details of the club.
info (Info): User metadata and cookies.

Returns:
SimpleClubType: Details of the created club.

Raises:
Exception: Not Authenticated
Exception: A club with this cid already exists
Exception: A club with this short code already exists
Exception: Invalid Club ID/Club Email
Exception: Error in updating the role for the club
Exception: Not Authenticated to access this API
"""
user = info.context.user
if user is None:
Expand Down Expand Up @@ -67,7 +84,29 @@ def createClub(clubInput: FullClubInput, info: Info) -> SimpleClubType:
@strawberry.mutation
def editClub(clubInput: FullClubInput, info: Info) -> FullClubType:
"""
Mutation for editing of the club details either by that specific club or the cc.
Mutation for editing of the club details either by that specific club or the cc

This method is used for editing the club details.
CC can edit any club details, but the club can only edit its own details.
Only CC can change a clubs name/email and category.


Args:
clubInput (FullClubInput): Full details of the club to be updated to.
Info (Info): User metadata and cookies.

Returns:
FullClubType: Full Details of the edited club.

Raises:
Exception: Not Authenticated.
Exception: A club with this code does not exist.
Exception: Invalid Club ID/Club Email.
Exception: Error in updating the role/cid.
Exception: Authentication Error! (CLUB ID CHANGED).
Exception: You dont have permission to change the name/email of the club. Please contact CC for it.
Exception: Only CC is allowed to change the category of club.
Exception: Not Authenticated to access this API.
""" # noqa: E501
user = info.context.user
if user is None:
Expand Down Expand Up @@ -195,6 +234,8 @@ def editClub(clubInput: FullClubInput, info: Info) -> FullClubType:
}
},
)

# also autofills the updated time
clubsdb.update_one(
{"cid": club_input["cid"]},
{
Expand All @@ -218,6 +259,17 @@ def editClub(clubInput: FullClubInput, info: Info) -> FullClubType:
def deleteClub(clubInput: SimpleClubInput, info: Info) -> SimpleClubType:
"""
Mutation for the cc to move a club to deleted state.

Args:
clubInput (SimpleClubInput): The club cid.
info (Info): User metadata and cookies.

Returns:
SimpleClubType: Details of the deleted club.

Raises:
Exception: Not Authenticated.
Exception: Not Authenticated to access this API.
"""
user = info.context.user
if user is None:
Expand All @@ -229,6 +281,7 @@ def deleteClub(clubInput: SimpleClubInput, info: Info) -> SimpleClubType:
if role not in ["cc"]:
raise Exception("Not Authenticated to access this API")

# also autofills the updated time
clubsdb.update_one(
{"cid": club_input["cid"]},
{"$set": {"state": "deleted", "updated_time": create_utc_time()}},
Expand All @@ -246,7 +299,18 @@ def deleteClub(clubInput: SimpleClubInput, info: Info) -> SimpleClubType:
@strawberry.mutation
def restartClub(clubInput: SimpleClubInput, info: Info) -> SimpleClubType:
"""
Mutation for cc to move a club from deleted state to asctive state.
Mutation for cc to move a club from deleted state to active state.

Args:
clubInput (SimpleClubInput): The club cid.
info (Info): User metadata and cookies.

Returns:
SimpleClubType: Details of the restarted clubs cid.

Raises:
Exception: Not Authenticated.
Exception: Not Authenticated to access this API.
"""
user = info.context.user
if user is None:
Expand All @@ -258,6 +322,7 @@ def restartClub(clubInput: SimpleClubInput, info: Info) -> SimpleClubType:
if role not in ["cc"]:
raise Exception("Not Authenticated to access this API")

# also autofills the updated time
clubsdb.update_one(
{"cid": club_input["cid"]},
{"$set": {"state": "active", "updated_time": create_utc_time()}},
Expand Down
Loading
Loading