feat: init activities

This commit is contained in:
swve 2023-11-14 22:30:39 +01:00
parent ee07f49139
commit 727f17ba7c
9 changed files with 358 additions and 370 deletions

View file

@ -1,55 +1,69 @@
from typing import Literal, Optional
from click import Option
from sqlalchemy import JSON, Column
from sqlmodel import Field, Session, SQLModel, create_engine, select
from enum import Enum
class ActivityTypeEnum(str, Enum):
VIDEO = "VIDEO"
DOCUMENT = "DOCUMENT"
DYNAMIC = "DYNAMIC"
ASSESSMENT = "ASSESSMENT"
CUSTOM = "CUSTOM"
TYPE_VIDEO = "TYPE_VIDEO"
TYPE_DOCUMENT = "TYPE_DOCUMENT"
TYPE_DYNAMIC = "TYPE_DYNAMIC"
TYPE_ASSESSMENT = "TYPE_ASSESSMENT"
TYPE_CUSTOM = "TYPE_CUSTOM"
class ActivitySubTypeEnum(str, Enum):
# Dynamic
DYNAMIC_PAGE = "DYNAMIC_PAGE"
SUBTYPE_DYNAMIC_PAGE = "SUBTYPE_DYNAMIC_PAGE"
# Video
VIDEO_YOUTUBE = "VIDEO_YOUTUBE"
VIDEO_HOSTED = "VIDEO_HOSTED"
SUBTYPE_VIDEO_YOUTUBE = "SUBTYPE_VIDEO_YOUTUBE"
SUBTYPE_VIDEO_HOSTED = "SUBTYPE_VIDEO_HOSTED"
# Document
DOCUMENT_PDF = "DOCUMENT_PDF"
DOCUMENT_DOC = "DOCUMENT_GDOC"
SUBTYPE_DOCUMENT_PDF = "SUBTYPE_DOCUMENT_PDF"
SUBTYPE_DOCUMENT_DOC = "SUBTYPE_DOCUMENT_DOC"
# Assessment
ASSESSMENT_QUIZ = "ASSESSMENT_QUIZ"
SUBTYPE_ASSESSMENT_QUIZ = "SUBTYPE_ASSESSMENT_QUIZ"
# Custom
CUSTOM = "CUSTOM"
SUBTYPE_CUSTOM = "SUBTYPE_CUSTOM"
class ActivityBase(SQLModel):
name: str
activity_type: ActivityTypeEnum = ActivityTypeEnum.CUSTOM
activity_sub_type: ActivitySubTypeEnum = ActivitySubTypeEnum.CUSTOM
slug: str
activity_type: ActivityTypeEnum = ActivityTypeEnum.TYPE_CUSTOM
activity_sub_type: ActivitySubTypeEnum = ActivitySubTypeEnum.SUBTYPE_CUSTOM
content: dict = Field(default={}, sa_column=Column(JSON))
published_version: int
version: int
org_id: int = Field(default=None, foreign_key="organization.id")
course_id: int = Field(default=None, foreign_key="course.id")
class Activity(ActivityBase, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
activity_uuid: str
creation_date: str
update_date: str
org_id: int = Field(default=None, foreign_key="organization.id")
activity_uuid: str = ""
creation_date: str = ""
update_date: str = ""
class ActivityCreate(ActivityBase):
order: int
org_id: int = Field(default=None, foreign_key="organization.id")
course_id: int = Field(default=None, foreign_key="course.id")
chapter_id : int
pass
class ActivityUpdate(ActivityBase):
activity_id: int
name: Optional[str]
activity_type: Optional[ActivityTypeEnum]
activity_sub_type: Optional[ActivitySubTypeEnum]
content: dict = Field(default={}, sa_column=Column(JSON))
published_version: Optional[int]
version: Optional[int]
class ActivityRead(ActivityBase):
id: int
activity_uuid: str

View file

@ -4,10 +4,10 @@ from sqlmodel import Field, SQLModel
class OrganizationBase(SQLModel):
name: str
description: Optional[str] = ""
description: Optional[str]
slug: str
email: str
logo_image: Optional[str] = ""
logo_image: Optional[str]
class Organization(OrganizationBase, table=True):

View file

@ -5,9 +5,9 @@ from sqlmodel import Field, SQLModel
class RoleTypeEnum(str, Enum):
ORGANIZATION = "ORGANIZATION"
ORGANIZATION_API_TOKEN = "ORGANIZATION_API_TOKEN"
GLOBAL = "GLOBAL"
TYPE_ORGANIZATION = "TYPE_ORGANIZATION"
TYPE_ORGANIZATION_API_TOKEN = "TYPE_ORGANIZATION_API_TOKEN"
TYPE_GLOBAL = "TYPE_GLOBAL"
class RoleBase(SQLModel):
@ -19,7 +19,7 @@ class RoleBase(SQLModel):
class Role(RoleBase, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
org_id: int = Field(default=None, foreign_key="organization.id")
role_type: RoleTypeEnum = RoleTypeEnum.ORGANIZATION
role_type: RoleTypeEnum = RoleTypeEnum.TYPE_GLOBAL
role_uuid: str = ""
creation_date: str = ""
update_date: str = ""

View file

@ -1,4 +1,7 @@
from fastapi import APIRouter, Depends, UploadFile, Form, Request
from src.db.activities import ActivityCreate, ActivityUpdate
from src.db.users import PublicUser
from src.core.events.database import get_db_session
from src.services.courses.activities.activities import (
Activity,
create_activity,
@ -14,7 +17,6 @@ from src.services.courses.activities.video import (
create_external_video_activity,
create_video_activity,
)
from src.services.users.schemas.users import PublicUser
router = APIRouter()
@ -22,17 +24,14 @@ router = APIRouter()
@router.post("/")
async def api_create_activity(
request: Request,
activity_object: Activity,
org_id: str,
coursechapter_id: str,
activity_object: ActivityCreate,
current_user: PublicUser = Depends(get_current_user),
db_session=Depends(get_db_session),
):
"""
Create new activity
"""
return await create_activity(
request, activity_object, org_id, coursechapter_id, current_user
)
return await create_activity(request, activity_object, current_user, db_session)
@router.get("/{activity_id}")
@ -40,11 +39,14 @@ async def api_get_activity(
request: Request,
activity_id: str,
current_user: PublicUser = Depends(get_current_user),
db_session=Depends(get_db_session),
):
"""
Get single activity by activity_id
"""
return await get_activity(request, activity_id, current_user=current_user)
return await get_activity(
request, activity_id, current_user=current_user, db_session=db_session
)
@router.get("/coursechapter/{coursechapter_id}")
@ -52,24 +54,25 @@ async def api_get_activities(
request: Request,
coursechapter_id: str,
current_user: PublicUser = Depends(get_current_user),
db_session=Depends(get_db_session),
):
"""
Get CourseChapter activities
"""
return await get_activities(request, coursechapter_id, current_user)
return await get_activities(request, coursechapter_id, current_user, db_session)
@router.put("/{activity_id}")
@router.put("/")
async def api_update_activity(
request: Request,
activity_object: Activity,
activity_id: str,
activity_object: ActivityUpdate,
current_user: PublicUser = Depends(get_current_user),
db_session=Depends(get_db_session),
):
"""
Update activity by activity_id
"""
return await update_activity(request, activity_object, activity_id, current_user)
return await update_activity(request, activity_object, current_user, db_session)
@router.delete("/{activity_id}")
@ -77,11 +80,12 @@ async def api_delete_activity(
request: Request,
activity_id: str,
current_user: PublicUser = Depends(get_current_user),
db_session=Depends(get_db_session),
):
"""
Delete activity by activity_id
"""
return await delete_activity(request, activity_id, current_user)
return await delete_activity(request, activity_id, current_user, db_session)
# Video activity
@ -91,15 +95,21 @@ async def api_delete_activity(
async def api_create_video_activity(
request: Request,
name: str = Form(),
coursechapter_id: str = Form(),
chapter_id: str = Form(),
current_user: PublicUser = Depends(get_current_user),
video_file: UploadFile | None = None,
db_session=Depends(get_db_session),
):
"""
Create new activity
"""
return await create_video_activity(
request, name, coursechapter_id, current_user, video_file
request,
name,
chapter_id,
current_user,
db_session,
video_file,
)
@ -108,24 +118,28 @@ async def api_create_external_video_activity(
request: Request,
external_video: ExternalVideo,
current_user: PublicUser = Depends(get_current_user),
db_session=Depends(get_db_session),
):
"""
Create new activity
"""
return await create_external_video_activity(request, current_user, external_video)
return await create_external_video_activity(
request, current_user, external_video, db_session
)
@router.post("/documentpdf")
async def api_create_documentpdf_activity(
request: Request,
name: str = Form(),
coursechapter_id: str = Form(),
chapter_id: str = Form(),
current_user: PublicUser = Depends(get_current_user),
pdf_file: UploadFile | None = None,
db_session=Depends(get_db_session),
):
"""
Create new activity
"""
return await create_documentpdf_activity(
request, name, coursechapter_id, current_user, pdf_file
request, name, chapter_id, current_user, db_session, pdf_file
)

View file

@ -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 ####################################################

View file

@ -1,7 +1,16 @@
from sqlmodel import Session, select
from src.db.chapters import Chapter
from src.db.activities import (
Activity,
ActivityRead,
ActivitySubTypeEnum,
ActivityTypeEnum,
)
from src.db.chapter_activities import ChapterActivity
from src.db.course_chapters import CourseChapter
from src.db.users import PublicUser
from src.security.rbac.rbac import authorization_verify_based_on_roles
from src.services.courses.activities.uploads.pdfs import upload_pdf
from src.services.users.users import PublicUser
from src.services.courses.activities.activities import ActivityInDB
from fastapi import HTTPException, status, UploadFile, Request
from uuid import uuid4
from datetime import datetime
@ -10,26 +19,35 @@ from datetime import datetime
async def create_documentpdf_activity(
request: Request,
name: str,
coursechapter_id: str,
chapter_id: str,
current_user: PublicUser,
db_session: Session,
pdf_file: UploadFile | None = None,
):
activities = request.app.db["activities"]
courses = request.app.db["courses"]
users = request.app.db["users"]
# get chapter_id
statement = select(Chapter).where(Chapter.id == chapter_id)
chapter = db_session.exec(statement).first()
# get user
user = await users.find_one({"user_id": current_user.user_id})
if not chapter:
raise HTTPException(
status_code=404,
detail="Chapter not found",
)
# generate activity_id
activity_id = str(f"activity_{uuid4()}")
statement = select(CourseChapter).where(CourseChapter.chapter_id == chapter_id)
coursechapter = db_session.exec(statement).first()
# get org_id from course
coursechapter = await courses.find_one(
{"chapters_content.coursechapter_id": coursechapter_id}
)
if not coursechapter:
raise HTTPException(
status_code=404,
detail="CourseChapter not found",
)
org_id = coursechapter["org_id"]
# get org_id
org_id = coursechapter.id
# create activity uuid
activity_uuid = f"activity_{uuid4()}"
# check if pdf_file is not None
if not pdf_file:
@ -51,45 +69,48 @@ async def create_documentpdf_activity(
status_code=status.HTTP_409_CONFLICT, detail="Pdf : No pdf file provided"
)
activity_object = ActivityInDB(
org_id=org_id,
activity_id=activity_id,
coursechapter_id=coursechapter_id,
# Create activity
activity = Activity(
name=name,
type="documentpdf",
course_id=coursechapter["course_id"],
activity_type=ActivityTypeEnum.TYPE_DOCUMENT,
activity_sub_type=ActivitySubTypeEnum.SUBTYPE_DOCUMENT_PDF,
content={
"documentpdf": {
"filename": "documentpdf." + pdf_format,
"activity_id": activity_id,
}
"filename": "documentpdf." + pdf_format,
"activity_uuid": activity_uuid,
},
creationDate=str(datetime.now()),
updateDate=str(datetime.now()),
published_version=1,
version=1,
org_id=org_id is not None,
course_id=coursechapter.course_id,
activity_uuid=activity_uuid,
creation_date=str(datetime.now()),
update_date=str(datetime.now()),
)
await authorization_verify_based_on_roles(
request,
current_user.user_id,
"create",
user["roles"],
activity_id,
)
# Insert Activity in DB
db_session.add(activity)
db_session.commit()
db_session.refresh(activity)
# create activity
activity = ActivityInDB(**activity_object.dict())
await activities.insert_one(activity.dict())
# Add activity to chapter
activity_chapter = ChapterActivity(
chapter_id=(int(chapter_id)),
activity_id=activity.id is not None,
course_id=coursechapter.course_id,
org_id=coursechapter.org_id,
creation_date=str(datetime.now()),
update_date=str(datetime.now()),
order=1,
)
# upload pdf
if pdf_file:
# get pdffile format
await upload_pdf(pdf_file, activity_id, org_id, coursechapter["course_id"])
await upload_pdf(pdf_file, activity.id, org_id, coursechapter.course_id)
# todo : choose whether to update the chapter or not
# update chapter
await courses.update_one(
{"chapters_content.coursechapter_id": coursechapter_id},
{"$addToSet": {"chapters_content.$.activities": activity_id}},
)
# Insert ChapterActivity link in DB
db_session.add(activity_chapter)
db_session.commit()
db_session.refresh(activity_chapter)
return activity
return ActivityRead.from_orm(activity)

View file

@ -1,12 +1,16 @@
from typing import Literal
from pydantic import BaseModel
from sqlmodel import Session, select
from src.db.chapters import Chapter
from src.db.activities import Activity, ActivityRead, ActivitySubTypeEnum, ActivityTypeEnum
from src.db.chapter_activities import ChapterActivity
from src.db.course_chapters import CourseChapter
from src.db.users import PublicUser
from src.security.rbac.rbac import (
authorization_verify_based_on_roles,
)
from src.services.courses.activities.uploads.videos import upload_video
from src.services.users.users import PublicUser
from src.services.courses.activities.activities import ActivityInDB
from fastapi import HTTPException, status, UploadFile, Request
from uuid import uuid4
from datetime import datetime
@ -15,32 +19,32 @@ from datetime import datetime
async def create_video_activity(
request: Request,
name: str,
coursechapter_id: str,
chapter_id: str,
current_user: PublicUser,
db_session: Session,
video_file: UploadFile | None = None,
):
activities = request.app.db["activities"]
courses = request.app.db["courses"]
users = request.app.db["users"]
# get chapter_id
statement = select(Chapter).where(Chapter.id == chapter_id)
chapter = db_session.exec(statement).first()
# get user
user = await users.find_one({"user_id": current_user.user_id})
if not chapter:
raise HTTPException(
status_code=404,
detail="Chapter not found",
)
# generate activity_id
activity_id = str(f"activity_{uuid4()}")
# get org_id from course
coursechapter = await courses.find_one(
{"chapters_content.coursechapter_id": coursechapter_id}
)
statement = select(CourseChapter).where(CourseChapter.chapter_id == chapter_id)
coursechapter = db_session.exec(statement).first()
if not coursechapter:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail="CourseChapter : No coursechapter found",
status_code=404,
detail="CourseChapter not found",
)
org_id = coursechapter["org_id"]
# generate activity_uuid
activity_uuid = str(f"activity_{uuid4()}")
# check if video_file is not None
if not video_file:
@ -64,55 +68,57 @@ async def create_video_activity(
detail="Video : No video file provided",
)
activity_object = ActivityInDB(
org_id=org_id,
activity_id=activity_id,
coursechapter_id=coursechapter_id,
course_id=coursechapter["course_id"],
activity_object = Activity(
name=name,
type="video",
activity_type=ActivityTypeEnum.TYPE_VIDEO,
activity_sub_type=ActivitySubTypeEnum.SUBTYPE_VIDEO_HOSTED,
activity_uuid=activity_uuid,
published_version=1,
content={
"video": {
"filename": "video." + video_format,
"activity_id": activity_id,
}
"filename": "video." + video_format,
"activity_uuid": activity_uuid,
},
creationDate=str(datetime.now()),
updateDate=str(datetime.now()),
)
await authorization_verify_based_on_roles(
request,
current_user.user_id,
"create",
user["roles"],
activity_id,
version=1,
creation_date=str(datetime.now()),
update_date=str(datetime.now()),
)
# create activity
activity = ActivityInDB(**activity_object.dict())
await activities.insert_one(activity.dict())
activity = Activity.from_orm(activity_object)
db_session.add(activity)
db_session.commit()
db_session.refresh(activity)
# upload video
if video_file:
# get videofile format
await upload_video(video_file, activity_id, org_id, coursechapter["course_id"])
await upload_video(
video_file, activity.id, coursechapter.org_id, coursechapter.course_id
)
# todo : choose whether to update the chapter or not
# update chapter
await courses.update_one(
{"chapters_content.coursechapter_id": coursechapter_id},
{"$addToSet": {"chapters_content.$.activities": activity_id}},
chapter_activity_object = ChapterActivity(
chapter_id=coursechapter.id is not None,
activity_id=activity.id is not None,
course_id=coursechapter.course_id,
org_id=coursechapter.org_id,
creation_date=str(datetime.now()),
update_date=str(datetime.now()),
order=1,
)
return activity
# Insert ChapterActivity link in DB
db_session.add(chapter_activity_object)
db_session.commit()
db_session.refresh(chapter_activity_object)
return ActivityRead.from_orm(activity)
class ExternalVideo(BaseModel):
name: str
uri: str
type: Literal["youtube", "vimeo"]
coursechapter_id: str
chapter_id: str
class ExternalVideoInDB(BaseModel):
@ -123,65 +129,63 @@ async def create_external_video_activity(
request: Request,
current_user: PublicUser,
data: ExternalVideo,
db_session: Session,
):
activities = request.app.db["activities"]
courses = request.app.db["courses"]
users = request.app.db["users"]
# get chapter_id
statement = select(Chapter).where(Chapter.id == data.chapter_id)
chapter = db_session.exec(statement).first()
# get user
user = await users.find_one({"user_id": current_user.user_id})
if not chapter:
raise HTTPException(
status_code=404,
detail="Chapter not found",
)
# generate activity_id
activity_id = str(f"activity_{uuid4()}")
# get org_id from course
coursechapter = await courses.find_one(
{"chapters_content.coursechapter_id": data.coursechapter_id}
)
statement = select(CourseChapter).where(CourseChapter.chapter_id == data.chapter_id)
coursechapter = db_session.exec(statement).first()
if not coursechapter:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail="CourseChapter : No coursechapter found",
status_code=404,
detail="CourseChapter not found",
)
org_id = coursechapter["org_id"]
# generate activity_uuid
activity_uuid = str(f"activity_{uuid4()}")
activity_object = ActivityInDB(
org_id=org_id,
activity_id=activity_id,
coursechapter_id=data.coursechapter_id,
activity_object = Activity(
name=data.name,
type="video",
activity_type=ActivityTypeEnum.TYPE_VIDEO,
activity_sub_type=ActivitySubTypeEnum.SUBTYPE_VIDEO_YOUTUBE,
activity_uuid=activity_uuid,
published_version=1,
content={
"external_video": {
"uri": data.uri,
"activity_id": activity_id,
"type": data.type,
}
"uri": data.uri,
"type": data.type,
"activity_uuid": activity_uuid,
},
course_id=coursechapter["course_id"],
creationDate=str(datetime.now()),
updateDate=str(datetime.now()),
)
await authorization_verify_based_on_roles(
request,
current_user.user_id,
"create",
user["roles"],
activity_id,
version=1,
creation_date=str(datetime.now()),
update_date=str(datetime.now()),
)
# create activity
activity = ActivityInDB(**activity_object.dict())
await activities.insert_one(activity.dict())
activity = Activity.from_orm(activity_object)
db_session.add(activity)
db_session.commit()
db_session.refresh(activity)
# todo : choose whether to update the chapter or not
# update chapter
await courses.update_one(
{"chapters_content.coursechapter_id": data.coursechapter_id},
{"$addToSet": {"chapters_content.$.activities": activity_id}},
chapter_activity_object = ChapterActivity(
chapter_id=coursechapter.id is not None,
activity_id=activity.id is not None,
creation_date=str(datetime.now()),
update_date=str(datetime.now()),
order=1,
)
return activity
# Insert ChapterActivity link in DB
db_session.add(chapter_activity_object)
db_session.commit()
return ActivityRead.from_orm(activity)

View file

@ -10,11 +10,23 @@ from src.security.rbac.rbac import (
authorization_verify_if_user_is_anon,
)
from src.services.courses.courses import Course
from src.services.courses.activities.activities import ActivityInDB
from src.services.users.users import PublicUser
from fastapi import HTTPException, status, Request
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
class CourseChapter(BaseModel):
name: str
description: str

View file

@ -12,7 +12,6 @@ from src.security.rbac.rbac import (
authorization_verify_if_element_is_public,
authorization_verify_if_user_is_anon,
)
from src.services.courses.activities.activities import ActivityInDB
from src.services.courses.thumbnails import upload_thumbnail
from fastapi import HTTPException, Request, status, UploadFile
from datetime import datetime