mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
feat: init activities
This commit is contained in:
parent
ee07f49139
commit
727f17ba7c
9 changed files with 358 additions and 370 deletions
|
|
@ -1,35 +1,21 @@
|
|||
import stat
|
||||
from typing import Literal
|
||||
from pydantic import BaseModel
|
||||
from sqlmodel import Session, select
|
||||
from src.db.organizations import Organization
|
||||
from src import db
|
||||
from src.db.activities import ActivityCreate, Activity, ActivityRead, ActivityUpdate
|
||||
from src.db.chapter_activities import ChapterActivity
|
||||
from src.security.rbac.rbac import (
|
||||
authorization_verify_based_on_roles,
|
||||
authorization_verify_if_element_is_public,
|
||||
authorization_verify_if_user_is_anon,
|
||||
)
|
||||
from src.services.users.schemas.users import AnonymousUser, PublicUser
|
||||
from src.db.users import AnonymousUser, PublicUser
|
||||
from fastapi import HTTPException, status, Request
|
||||
from uuid import uuid4
|
||||
from datetime import datetime
|
||||
|
||||
#### Classes ####################################################
|
||||
|
||||
|
||||
class Activity(BaseModel):
|
||||
name: str
|
||||
type: str
|
||||
content: object
|
||||
|
||||
|
||||
class ActivityInDB(Activity):
|
||||
activity_id: str
|
||||
course_id: str
|
||||
coursechapter_id: str
|
||||
org_id: str
|
||||
creationDate: str
|
||||
updateDate: str
|
||||
|
||||
|
||||
#### Classes ####################################################
|
||||
|
||||
|
||||
####################################################
|
||||
# CRUD
|
||||
|
|
@ -38,148 +24,130 @@ class ActivityInDB(Activity):
|
|||
|
||||
async def create_activity(
|
||||
request: Request,
|
||||
activity_object: Activity,
|
||||
org_id: str,
|
||||
coursechapter_id: str,
|
||||
activity_object: ActivityCreate,
|
||||
current_user: PublicUser,
|
||||
db_session: Session,
|
||||
):
|
||||
activities = request.app.db["activities"]
|
||||
courses = request.app.db["courses"]
|
||||
users = request.app.db["users"]
|
||||
activity = Activity.from_orm(activity_object)
|
||||
|
||||
# get user
|
||||
user = await users.find_one({"user_id": current_user.user_id})
|
||||
# CHeck if org exists
|
||||
statement = select(Organization).where(Organization.id == activity_object.org_id)
|
||||
org = db_session.exec(statement).first()
|
||||
|
||||
# generate activity_id
|
||||
activity_id = str(f"activity_{uuid4()}")
|
||||
if not org:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Organization not found",
|
||||
)
|
||||
|
||||
# verify activity rights
|
||||
await authorization_verify_based_on_roles(
|
||||
request,
|
||||
current_user.user_id,
|
||||
"create",
|
||||
user["roles"],
|
||||
activity_id,
|
||||
activity.activity_uuid = str(f"activity_{uuid4()}")
|
||||
activity.creation_date = str(datetime.now())
|
||||
activity.update_date = str(datetime.now())
|
||||
|
||||
# Insert Activity in DB
|
||||
db_session.add(activity)
|
||||
db_session.commit()
|
||||
db_session.refresh(activity)
|
||||
|
||||
# Add activity to chapter
|
||||
activity_chapter = ChapterActivity(
|
||||
chapter_id=activity_object.chapter_id,
|
||||
activity_id=activity.id is not None,
|
||||
course_id=activity_object.course_id,
|
||||
org_id=activity_object.org_id,
|
||||
creation_date=str(datetime.now()),
|
||||
update_date=str(datetime.now()),
|
||||
order=activity_object.order,
|
||||
)
|
||||
|
||||
# get course_id from activity
|
||||
course = await courses.find_one({"chapters": coursechapter_id})
|
||||
# Insert ChapterActivity link in DB
|
||||
db_session.add(activity_chapter)
|
||||
db_session.commit()
|
||||
db_session.refresh(activity_chapter)
|
||||
|
||||
# create activity
|
||||
activity = ActivityInDB(
|
||||
**activity_object.dict(),
|
||||
creationDate=str(datetime.now()),
|
||||
coursechapter_id=coursechapter_id,
|
||||
updateDate=str(datetime.now()),
|
||||
activity_id=activity_id,
|
||||
org_id=org_id,
|
||||
course_id=course["course_id"],
|
||||
)
|
||||
await activities.insert_one(activity.dict())
|
||||
|
||||
# update chapter
|
||||
await courses.update_one(
|
||||
{"chapters_content.coursechapter_id": coursechapter_id},
|
||||
{"$addToSet": {"chapters_content.$.activities": activity_id}},
|
||||
)
|
||||
|
||||
return activity
|
||||
return ActivityRead.from_orm(activity)
|
||||
|
||||
|
||||
async def get_activity(request: Request, activity_id: str, current_user: PublicUser):
|
||||
activities = request.app.db["activities"]
|
||||
courses = request.app.db["courses"]
|
||||
|
||||
activity = await activities.find_one({"activity_id": activity_id})
|
||||
|
||||
# get course_id from activity
|
||||
coursechapter_id = activity["coursechapter_id"]
|
||||
await courses.find_one({"chapters": coursechapter_id})
|
||||
|
||||
# verify course rights
|
||||
await verify_rights(request, activity["course_id"], current_user, "read")
|
||||
async def get_activity(
|
||||
request: Request,
|
||||
activity_id: str,
|
||||
current_user: PublicUser,
|
||||
db_session: Session,
|
||||
):
|
||||
statement = select(Activity).where(Activity.id == activity_id)
|
||||
activity = db_session.exec(statement).first()
|
||||
|
||||
if not activity:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT, detail="Course does not exist"
|
||||
status_code=404,
|
||||
detail="Activity not found",
|
||||
)
|
||||
|
||||
activity = ActivityInDB(**activity)
|
||||
return activity
|
||||
|
||||
|
||||
async def update_activity(
|
||||
request: Request,
|
||||
activity_object: Activity,
|
||||
activity_id: str,
|
||||
activity_object: ActivityUpdate,
|
||||
current_user: PublicUser,
|
||||
db_session: Session,
|
||||
):
|
||||
activities = request.app.db["activities"]
|
||||
|
||||
activity = await activities.find_one({"activity_id": activity_id})
|
||||
|
||||
# verify course rights
|
||||
await verify_rights(request, activity_id, current_user, "update")
|
||||
|
||||
if activity:
|
||||
creationDate = activity["creationDate"]
|
||||
|
||||
# get today's date
|
||||
datetime_object = datetime.now()
|
||||
|
||||
updated_course = ActivityInDB(
|
||||
activity_id=activity_id,
|
||||
coursechapter_id=activity["coursechapter_id"],
|
||||
creationDate=creationDate,
|
||||
updateDate=str(datetime_object),
|
||||
course_id=activity["course_id"],
|
||||
org_id=activity["org_id"],
|
||||
**activity_object.dict(),
|
||||
)
|
||||
|
||||
await activities.update_one(
|
||||
{"activity_id": activity_id}, {"$set": updated_course.dict()}
|
||||
)
|
||||
|
||||
return ActivityInDB(**updated_course.dict())
|
||||
|
||||
else:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT, detail="activity does not exist"
|
||||
)
|
||||
|
||||
|
||||
async def delete_activity(request: Request, activity_id: str, current_user: PublicUser):
|
||||
activities = request.app.db["activities"]
|
||||
|
||||
activity = await activities.find_one({"activity_id": activity_id})
|
||||
|
||||
# verify course rights
|
||||
await verify_rights(request, activity_id, current_user, "delete")
|
||||
statement = select(Activity).where(Activity.id == activity_object.activity_id)
|
||||
activity = db_session.exec(statement).first()
|
||||
|
||||
if not activity:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT, detail="activity does not exist"
|
||||
status_code=404,
|
||||
detail="Activity not found",
|
||||
)
|
||||
|
||||
# Remove Activity
|
||||
isDeleted = await activities.delete_one({"activity_id": activity_id})
|
||||
del activity_object.activity_id
|
||||
|
||||
# Remove Activity from chapter
|
||||
courses = request.app.db["courses"]
|
||||
isDeletedFromChapter = await courses.update_one(
|
||||
{"chapters_content.activities": activity_id},
|
||||
{"$pull": {"chapters_content.$.activities": activity_id}},
|
||||
)
|
||||
# Update only the fields that were passed in
|
||||
for var, value in vars(activity_object).items():
|
||||
if value is not None:
|
||||
setattr(activity, var, value)
|
||||
|
||||
if isDeleted and isDeletedFromChapter:
|
||||
return {"detail": "Activity deleted"}
|
||||
else:
|
||||
db_session.add(activity)
|
||||
db_session.commit()
|
||||
db_session.refresh(activity)
|
||||
|
||||
return activity
|
||||
|
||||
|
||||
async def delete_activity(
|
||||
request: Request,
|
||||
activity_id: str,
|
||||
current_user: PublicUser,
|
||||
db_session: Session,
|
||||
):
|
||||
statement = select(Activity).where(Activity.id == activity_id)
|
||||
activity = db_session.exec(statement).first()
|
||||
|
||||
if not activity:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
detail="Unavailable database",
|
||||
status_code=404,
|
||||
detail="Activity not found",
|
||||
)
|
||||
|
||||
# Delete activity from chapter
|
||||
statement = select(ChapterActivity).where(
|
||||
ChapterActivity.activity_id == activity_id
|
||||
)
|
||||
activity_chapter = db_session.exec(statement).first()
|
||||
|
||||
if not activity_chapter:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Activity not found in chapter",
|
||||
)
|
||||
|
||||
db_session.delete(activity_chapter)
|
||||
db_session.delete(activity)
|
||||
db_session.commit()
|
||||
|
||||
return {"detail": "Activity deleted"}
|
||||
|
||||
|
||||
####################################################
|
||||
# Misc
|
||||
|
|
@ -187,64 +155,20 @@ async def delete_activity(request: Request, activity_id: str, current_user: Publ
|
|||
|
||||
|
||||
async def get_activities(
|
||||
request: Request, coursechapter_id: str, current_user: PublicUser
|
||||
request: Request,
|
||||
coursechapter_id: str,
|
||||
current_user: PublicUser,
|
||||
db_session: Session,
|
||||
):
|
||||
activities = request.app.db["activities"]
|
||||
|
||||
activities = activities.find({"coursechapter_id": coursechapter_id})
|
||||
statement = select(ChapterActivity).where(
|
||||
ChapterActivity.chapter_id == coursechapter_id
|
||||
)
|
||||
activities = db_session.exec(statement).all()
|
||||
|
||||
if not activities:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT, detail="Course does not exist"
|
||||
status_code=404,
|
||||
detail="No activities found",
|
||||
)
|
||||
|
||||
activities = [
|
||||
ActivityInDB(**activity) for activity in await activities.to_list(length=100)
|
||||
]
|
||||
|
||||
return activities
|
||||
|
||||
|
||||
#### Security ####################################################
|
||||
|
||||
|
||||
async def verify_rights(
|
||||
request: Request,
|
||||
activity_id: str, # course_id in case of read
|
||||
current_user: PublicUser | AnonymousUser,
|
||||
action: Literal["create", "read", "update", "delete"],
|
||||
):
|
||||
if action == "read":
|
||||
if current_user.user_id == "anonymous":
|
||||
await authorization_verify_if_element_is_public(
|
||||
request, activity_id, current_user.user_id, action
|
||||
)
|
||||
else:
|
||||
users = request.app.db["users"]
|
||||
user = await users.find_one({"user_id": current_user.user_id})
|
||||
|
||||
await authorization_verify_if_user_is_anon(current_user.user_id)
|
||||
|
||||
await authorization_verify_based_on_roles(
|
||||
request,
|
||||
current_user.user_id,
|
||||
action,
|
||||
user["roles"],
|
||||
activity_id,
|
||||
)
|
||||
else:
|
||||
users = request.app.db["users"]
|
||||
user = await users.find_one({"user_id": current_user.user_id})
|
||||
|
||||
await authorization_verify_if_user_is_anon(current_user.user_id)
|
||||
|
||||
await authorization_verify_based_on_roles(
|
||||
request,
|
||||
current_user.user_id,
|
||||
action,
|
||||
user["roles"],
|
||||
activity_id,
|
||||
)
|
||||
|
||||
|
||||
#### Security ####################################################
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue