From cdd1ca46d32d88087d5b3cfadb9333e3ad8536b3 Mon Sep 17 00:00:00 2001 From: swve Date: Sun, 14 May 2023 14:00:32 +0000 Subject: [PATCH] feat: add external video endpoint --- src/routers/courses/activities.py | 87 +++++++++++++--- src/services/courses/activities/video.py | 123 +++++++++++++++++++---- 2 files changed, 180 insertions(+), 30 deletions(-) diff --git a/src/routers/courses/activities.py b/src/routers/courses/activities.py index 292403be..c7ee127c 100644 --- a/src/routers/courses/activities.py +++ b/src/routers/courses/activities.py @@ -2,21 +2,37 @@ from fastapi import APIRouter, Depends, UploadFile, Form, Request from src.services.courses.activities.activities import * from src.security.auth import get_current_user from src.services.courses.activities.pdf import create_documentpdf_activity -from src.services.courses.activities.video import create_video_activity +from src.services.courses.activities.video import ( + ExternalVideo, + create_external_video_activity, + create_video_activity, +) router = APIRouter() @router.post("/") -async def api_create_activity(request: Request, activity_object: Activity, org_id: str, coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)): +async def api_create_activity( + request: Request, + activity_object: Activity, + org_id: str, + coursechapter_id: str, + current_user: PublicUser = Depends(get_current_user), +): """ Create new activity """ - return await create_activity(request, activity_object, org_id, coursechapter_id, current_user) + return await create_activity( + request, activity_object, org_id, coursechapter_id, current_user + ) @router.get("/{activity_id}") -async def api_get_activity(request: Request, activity_id: str, current_user: PublicUser = Depends(get_current_user)): +async def api_get_activity( + request: Request, + activity_id: str, + current_user: PublicUser = Depends(get_current_user), +): """ Get single activity by activity_id """ @@ -24,15 +40,24 @@ async def api_get_activity(request: Request, activity_id: str, current_user: Pu @router.get("/coursechapter/{coursechapter_id}") -async def api_get_activities(request: Request, coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)): +async def api_get_activities( + request: Request, + coursechapter_id: str, + current_user: PublicUser = Depends(get_current_user), +): """ - Get CourseChapter activities + Get CourseChapter activities """ return await get_activities(request, coursechapter_id, current_user) @router.put("/{activity_id}") -async def api_update_activity(request: Request, activity_object: Activity, activity_id: str, current_user: PublicUser = Depends(get_current_user)): +async def api_update_activity( + request: Request, + activity_object: Activity, + activity_id: str, + current_user: PublicUser = Depends(get_current_user), +): """ Update activity by activity_id """ @@ -40,25 +65,63 @@ async def api_update_activity(request: Request, activity_object: Activity, activ @router.delete("/{activity_id}") -async def api_delete_activity(request: Request, activity_id: str, org_id: str, current_user: PublicUser = Depends(get_current_user)): +async def api_delete_activity( + request: Request, + activity_id: str, + current_user: PublicUser = Depends(get_current_user), +): """ Delete activity by activity_id """ return await delete_activity(request, activity_id, current_user) + # Video activity @router.post("/video") -async def api_create_video_activity(request: Request, org_id: str, name: str = Form(), coursechapter_id: str = Form(), current_user: PublicUser = Depends(get_current_user), video_file: UploadFile | None = None): +async def api_create_video_activity( + request: Request, + name: str = Form(), + coursechapter_id: str = Form(), + current_user: PublicUser = Depends(get_current_user), + video_file: UploadFile | None = None, +): """ Create new activity """ - return await create_video_activity(request, name, coursechapter_id, current_user, video_file) + return await create_video_activity( + request, name, coursechapter_id, current_user, video_file + ) + + +@router.post("/external_video") +async def api_create_external_video_activity( + request: Request, + external_video: ExternalVideo, + coursechapter_id: str = Form(), + current_user: PublicUser = Depends(get_current_user), +): + """ + Create new activity + """ + return await create_external_video_activity( + request, coursechapter_id, current_user, external_video + ) + @router.post("/documentpdf") -async def api_create_documentpdf_activity(request: Request, org_id: str, name: str = Form(), coursechapter_id: str = Form(), current_user: PublicUser = Depends(get_current_user), pdf_file: UploadFile | None = None): +async def api_create_documentpdf_activity( + request: Request, + org_id: str, + name: str = Form(), + coursechapter_id: str = Form(), + current_user: PublicUser = Depends(get_current_user), + pdf_file: UploadFile | None = None, +): """ Create new activity """ - return await create_documentpdf_activity(request, name, coursechapter_id, current_user, pdf_file) + return await create_documentpdf_activity( + request, name, coursechapter_id, current_user, pdf_file + ) diff --git a/src/services/courses/activities/video.py b/src/services/courses/activities/video.py index 4abdceac..61ccfef5 100644 --- a/src/services/courses/activities/video.py +++ b/src/services/courses/activities/video.py @@ -1,3 +1,6 @@ +from typing import Literal + +from pydantic import BaseModel from src.security.security import verify_user_rights_with_roles from src.services.courses.activities.uploads.videos import upload_video from src.services.users.users import PublicUser @@ -7,37 +10,48 @@ from uuid import uuid4 from datetime import datetime -async def create_video_activity(request: Request,name: str, coursechapter_id: str, current_user: PublicUser, video_file: UploadFile | None = None): +async def create_video_activity( + request: Request, + name: str, + coursechapter_id: str, + current_user: PublicUser, + video_file: UploadFile | None = None, +): activities = request.app.db["activities"] courses = request.app.db["courses"] # generate activity_id activity_id = str(f"activity_{uuid4()}") - # get org_id from course + # get org_id from course coursechapter = await courses.find_one( - {"chapters_content.coursechapter_id": coursechapter_id}) - - org_id = coursechapter["org_id"] + {"chapters_content.coursechapter_id": coursechapter_id} + ) + org_id = coursechapter["org_id"] # check if video_file is not None if not video_file: raise HTTPException( - status_code=status.HTTP_409_CONFLICT, detail="Video : No video file provided") + status_code=status.HTTP_409_CONFLICT, + detail="Video : No video file provided", + ) if video_file.content_type not in ["video/mp4", "video/webm"]: raise HTTPException( - status_code=status.HTTP_409_CONFLICT, detail="Video : Wrong video format") - + status_code=status.HTTP_409_CONFLICT, detail="Video : Wrong video format" + ) + # get video format - if video_file.filename: + if video_file.filename: video_format = video_file.filename.split(".")[-1] - else: + else: raise HTTPException( - status_code=status.HTTP_409_CONFLICT, detail="Video : No video file provided") - + status_code=status.HTTP_409_CONFLICT, + detail="Video : No video file provided", + ) + activity_object = ActivityInDB( org_id=org_id, activity_id=activity_id, @@ -46,7 +60,7 @@ async def create_video_activity(request: Request,name: str, coursechapter_id: s type="video", content={ "video": { - "filename": "video."+video_format, + "filename": "video." + video_format, "activity_id": activity_id, } }, @@ -54,11 +68,15 @@ async def create_video_activity(request: Request,name: str, coursechapter_id: s updateDate=str(datetime.now()), ) - hasRoleRights = await verify_user_rights_with_roles(request,"create", current_user.user_id, activity_id, element_org_id=org_id) + hasRoleRights = await verify_user_rights_with_roles( + request, "create", current_user.user_id, activity_id, element_org_id=org_id + ) if not hasRoleRights: raise HTTPException( - status_code=status.HTTP_409_CONFLICT, detail="Roles : Insufficient rights to perform this action") + status_code=status.HTTP_409_CONFLICT, + detail="Roles : Insufficient rights to perform this action", + ) # create activity activity = ActivityInDB(**activity_object.dict()) @@ -67,11 +85,80 @@ async def create_video_activity(request: Request,name: str, coursechapter_id: s # upload video if video_file: # get videofile format - await upload_video(video_file, activity_id) + await upload_video(video_file, activity_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}}) + await courses.update_one( + {"chapters_content.coursechapter_id": coursechapter_id}, + {"$addToSet": {"chapters_content.$.activities": activity_id}}, + ) + + return activity + + +class ExternalVideo(BaseModel): + name: str + uri: str + type: Literal["youtube", "vimeo"] + activity_id: str + + +async def create_external_video_activity( + request: Request, + coursechapter_id: str, + current_user: PublicUser, + data: ExternalVideo, +): + activities = request.app.db["activities"] + courses = request.app.db["courses"] + + # 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} + ) + + org_id = coursechapter["org_id"] + + activity_object = ActivityInDB( + org_id=org_id, + activity_id=activity_id, + coursechapter_id=coursechapter_id, + name=data.name, + type="video", + content={ + "external_video": { + "uri": data.uri, + "activity_id": activity_id, + "type": data.type, + } + }, + creationDate=str(datetime.now()), + updateDate=str(datetime.now()), + ) + + hasRoleRights = await verify_user_rights_with_roles( + request, "create", current_user.user_id, activity_id, element_org_id=org_id + ) + + if not hasRoleRights: + raise HTTPException( + status_code=status.HTTP_409_CONFLICT, + detail="Roles : Insufficient rights to perform this action", + ) + + # create activity + activity = ActivityInDB(**activity_object.dict()) + await activities.insert_one(activity.dict()) + + # 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}}, + ) return activity