Merge pull request #37 from learnhouse/chore/better-mongodb-code

chore: use lectures naming + better mongodb code
This commit is contained in:
Badr B 2023-01-18 23:02:09 +01:00 committed by GitHub
commit 2c782c7af8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
60 changed files with 852 additions and 937 deletions

24
app.py
View file

@ -1,5 +1,7 @@
from urllib.request import Request import logging
from fastapi import FastAPI from fastapi import FastAPI, Request
from src.core.config.config import Settings, get_settings
from src.core.events.events import shutdown_app, startup_app
from src.main import global_router from src.main import global_router
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
@ -13,7 +15,6 @@ from src.services.mocks.initial import create_initial_data
# (c) LearnHouse 2022 # (c) LearnHouse 2022
######################## ########################
# Global Config # Global Config
app = FastAPI( app = FastAPI(
title="LearnHouse", title="LearnHouse",
@ -22,19 +23,25 @@ app = FastAPI(
root_path="/" root_path="/"
) )
app.add_middleware( app.add_middleware(
CORSMiddleware, CORSMiddleware,
allow_origins=["http://localhost:3000"], allow_origins=["http://localhost:3000", "http://localhost:3001"],
allow_methods=["*"], allow_methods=["*"],
allow_credentials=True, allow_credentials=True,
allow_headers=["*"] allow_headers=["*"]
) )
# Static Files
app.mount("/content", StaticFiles(directory="content"), name="content") app.mount("/content", StaticFiles(directory="content"), name="content")
# Exception Handler
# Events
app.add_event_handler("startup", startup_app(app))
app.add_event_handler("shutdown", shutdown_app(app))
# JWT Exception Handler
@app.exception_handler(AuthJWTException) @app.exception_handler(AuthJWTException)
def authjwt_exception_handler(request: Request, exc: AuthJWTException): def authjwt_exception_handler(request: Request, exc: AuthJWTException):
return JSONResponse( return JSONResponse(
@ -43,8 +50,11 @@ def authjwt_exception_handler(request: Request, exc: AuthJWTException):
) )
# Global Routes
app.include_router(global_router) app.include_router(global_router)
# General Routes
@app.get("/") @app.get("/")
async def root(): async def root():
@ -52,7 +62,7 @@ async def root():
@app.get("/initial_data") @app.get("/initial_data")
async def initial_data(): async def initial_data(request: Request):
await create_initial_data() await create_initial_data(request)
return {"Message": "Initial data created 🤖"} return {"Message": "Initial data created 🤖"}

View file

@ -9,7 +9,7 @@ services:
frontend: frontend:
build: ./front build: ./front
ports: ports:
- "3000:3000" - "3001:3000"
volumes: volumes:
- ./front:/usr/learnhouse/front - ./front:/usr/learnhouse/front
mongo: mongo:

View file

@ -11,8 +11,8 @@ import Chapter from "../../../../../../components/Drags/Chapter";
import { createChapter, deleteChapter, getCourseChaptersMetadata, updateChaptersMetadata } from "../../../../../../services/courses/chapters"; import { createChapter, deleteChapter, getCourseChaptersMetadata, updateChaptersMetadata } from "../../../../../../services/courses/chapters";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import NewChapterModal from "../../../../../../components/Modals/CourseEdit/NewChapter"; import NewChapterModal from "../../../../../../components/Modals/CourseEdit/NewChapter";
import NewElementModal from "../../../../../../components/Modals/CourseEdit/NewElement"; import NewLectureModal from "../../../../../../components/Modals/CourseEdit/NewLecture";
import { createElement, createFileElement } from "../../../../../../services/courses/elements"; import { createLecture, createFileLecture } from "../../../../../../services/courses/lectures";
function CourseEdit(params: any) { function CourseEdit(params: any) {
const router = useRouter(); const router = useRouter();
@ -22,9 +22,9 @@ function CourseEdit(params: any) {
// New Chapter Modal State // New Chapter Modal State
const [newChapterModal, setNewChapterModal] = useState(false) as any; const [newChapterModal, setNewChapterModal] = useState(false) as any;
// New Element Modal State // New Lecture Modal State
const [newElementModal, setNewElementModal] = useState(false) as any; const [newLectureModal, setNewLectureModal] = useState(false) as any;
const [newElementModalData, setNewElementModalData] = useState("") as any; const [newLectureModalData, setNewLectureModalData] = useState("") as any;
// Check window availability // Check window availability
const [winReady, setwinReady] = useState(false); const [winReady, setwinReady] = useState(false);
@ -50,16 +50,16 @@ function CourseEdit(params: any) {
const chapterOrder = data.chapterOrder ? data.chapterOrder : []; const chapterOrder = data.chapterOrder ? data.chapterOrder : [];
return chapterOrder.map((chapterId: any) => { return chapterOrder.map((chapterId: any) => {
const chapter = data.chapters[chapterId]; const chapter = data.chapters[chapterId];
let elements = []; let lectures = [];
if (data.elements) { if (data.lectures) {
elements = chapter.elementIds.map((elementId: any) => data.elements[elementId]) lectures = chapter.lectureIds.map((lectureId: any) => data.lectures[lectureId])
? chapter.elementIds.map((elementId: any) => data.elements[elementId]) ? chapter.lectureIds.map((lectureId: any) => data.lectures[lectureId])
: []; : [];
} }
return { return {
list: { list: {
chapter: chapter, chapter: chapter,
elements: elements, lectures: lectures,
}, },
}; };
}); });
@ -72,22 +72,22 @@ function CourseEdit(params: any) {
setNewChapterModal(false); setNewChapterModal(false);
}; };
// Submit new element // Submit new lecture
const submitElement = async (element: any) => { const submitLecture = async (lecture: any) => {
console.log("submitElement", element); console.log("submitLecture", lecture);
await updateChaptersMetadata(courseid, data); await updateChaptersMetadata(courseid, data);
await createElement(element, element.chapterId); await createLecture(lecture, lecture.chapterId);
await getCourseChapters(); await getCourseChapters();
setNewElementModal(false); setNewLectureModal(false);
}; };
// Submit File Upload // Submit File Upload
const submitFileElement = async (file: any, type: any, element: any, chapterId: string) => { const submitFileLecture = async (file: any, type: any, lecture: any, chapterId: string) => {
console.log("submitFileElement", file); console.log("submitFileLecture", file);
await updateChaptersMetadata(courseid, data); await updateChaptersMetadata(courseid, data);
await createFileElement(file, type, element, chapterId); await createFileLecture(file, type, lecture, chapterId);
await getCourseChapters(); await getCourseChapters();
setNewElementModal(false); setNewLectureModal(false);
}; };
const deleteChapterUI = async (chapterId: any) => { const deleteChapterUI = async (chapterId: any) => {
@ -107,10 +107,10 @@ function CourseEdit(params: any) {
*/ */
const openNewElementModal = async (chapterId: any) => { const openNewLectureModal = async (chapterId: any) => {
console.log("openNewElementModal", chapterId); console.log("openNewLectureModal", chapterId);
setNewElementModal(true); setNewLectureModal(true);
setNewElementModalData(chapterId); setNewLectureModalData(chapterId);
}; };
// Close new chapter modal // Close new chapter modal
@ -118,8 +118,8 @@ function CourseEdit(params: any) {
setNewChapterModal(false); setNewChapterModal(false);
}; };
const closeNewElementModal = () => { const closeNewLectureModal = () => {
setNewElementModal(false); setNewLectureModal(false);
}; };
/* /*
@ -130,12 +130,12 @@ function CourseEdit(params: any) {
const { destination, source, draggableId, type } = result; const { destination, source, draggableId, type } = result;
console.log(result); console.log(result);
// check if the element is dropped outside the droppable area // check if the lecture is dropped outside the droppable area
if (!destination) { if (!destination) {
return; return;
} }
// check if the element is dropped in the same place // check if the lecture is dropped in the same place
if (destination.droppableId === source.droppableId && destination.index === source.index) { if (destination.droppableId === source.droppableId && destination.index === source.index) {
return; return;
} }
@ -155,26 +155,26 @@ function CourseEdit(params: any) {
return; return;
} }
//////////////////////// ELEMENTS IN SAME CHAPTERS //////////////////////////// //////////////////////// LECTURES IN SAME CHAPTERS ////////////////////////////
// check if the element is dropped in the same chapter // check if the lecture is dropped in the same chapter
const start = data.chapters[source.droppableId]; const start = data.chapters[source.droppableId];
const finish = data.chapters[destination.droppableId]; const finish = data.chapters[destination.droppableId];
// check if the element is dropped in the same chapter // check if the lecture is dropped in the same chapter
if (start === finish) { if (start === finish) {
// create new arrays for chapters and elements // create new arrays for chapters and lectures
const chapter = data.chapters[source.droppableId]; const chapter = data.chapters[source.droppableId];
const newElementIds = Array.from(chapter.elementIds); const newLectureIds = Array.from(chapter.lectureIds);
// remove the element from the old position // remove the lecture from the old position
newElementIds.splice(source.index, 1); newLectureIds.splice(source.index, 1);
// add the element to the new position // add the lecture to the new position
newElementIds.splice(destination.index, 0, draggableId); newLectureIds.splice(destination.index, 0, draggableId);
const newChapter = { const newChapter = {
...chapter, ...chapter,
elementIds: newElementIds, lectureIds: newLectureIds,
}; };
const newState = { const newState = {
@ -189,25 +189,25 @@ function CourseEdit(params: any) {
return; return;
} }
//////////////////////// ELEMENTS IN DIFF CHAPTERS //////////////////////////// //////////////////////// LECTURES IN DIFF CHAPTERS ////////////////////////////
// check if the element is dropped in a different chapter // check if the lecture is dropped in a different chapter
if (start !== finish) { if (start !== finish) {
// create new arrays for chapters and elements // create new arrays for chapters and lectures
const startChapterElementIds = Array.from(start.elementIds); const startChapterLectureIds = Array.from(start.lectureIds);
// remove the element from the old position // remove the lecture from the old position
startChapterElementIds.splice(source.index, 1); startChapterLectureIds.splice(source.index, 1);
const newStart = { const newStart = {
...start, ...start,
elementIds: startChapterElementIds, lectureIds: startChapterLectureIds,
}; };
// add the element to the new position within the chapter // add the lecture to the new position within the chapter
const finishChapterElementIds = Array.from(finish.elementIds); const finishChapterLectureIds = Array.from(finish.lectureIds);
finishChapterElementIds.splice(destination.index, 0, draggableId); finishChapterLectureIds.splice(destination.index, 0, draggableId);
const newFinish = { const newFinish = {
...finish, ...finish,
elementIds: finishChapterElementIds, lectureIds: finishChapterLectureIds,
}; };
const newState = { const newState = {
@ -245,13 +245,13 @@ function CourseEdit(params: any) {
</button> </button>
</Title> </Title>
{newChapterModal && <NewChapterModal closeModal={closeNewChapterModal} submitChapter={submitChapter}></NewChapterModal>} {newChapterModal && <NewChapterModal closeModal={closeNewChapterModal} submitChapter={submitChapter}></NewChapterModal>}
{newElementModal && ( {newLectureModal && (
<NewElementModal <NewLectureModal
closeModal={closeNewElementModal} closeModal={closeNewLectureModal}
submitFileElement={submitFileElement} submitFileLecture={submitFileLecture}
submitElement={submitElement} submitLecture={submitLecture}
chapterId={newElementModalData} chapterId={newLectureModalData}
></NewElementModal> ></NewLectureModal>
)} )}
<br /> <br />
@ -267,7 +267,7 @@ function CourseEdit(params: any) {
<Chapter <Chapter
orgslug={orgslug} orgslug={orgslug}
courseid={courseid} courseid={courseid}
openNewElementModal={openNewElementModal} openNewLectureModal={openNewLectureModal}
deleteChapter={deleteChapterUI} deleteChapter={deleteChapterUI}
key={index} key={index}
info={info} info={info}

View file

@ -4,23 +4,23 @@ import { default as React, useEffect, useRef } from "react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { getElement } from "../../../../../../../../services/courses/elements"; import { getLecture } from "../../../../../../../../services/courses/lectures";
import AuthProvider from "../../../../../../../../components/Security/AuthProvider"; import AuthProvider from "../../../../../../../../components/Security/AuthProvider";
import EditorWrapper from "../../../../../../../../components/Editor/EditorWrapper"; import EditorWrapper from "../../../../../../../../components/Editor/EditorWrapper";
import { getCourseMetadata } from "../../../../../../../../services/courses/courses"; import { getCourseMetadata } from "../../../../../../../../services/courses/courses";
function EditElement(params: any) { function EditLecture(params: any) {
const router = useRouter(); const router = useRouter();
const elementid = params.params.elementid; const lectureid = params.params.lectureid;
const courseid = params.params.courseid; const courseid = params.params.courseid;
const [element, setElement] = React.useState<any>({}); const [lecture, setLecture] = React.useState<any>({});
const [courseInfo, setCourseInfo] = React.useState({}) as any; const [courseInfo, setCourseInfo] = React.useState({}) as any;
const [isLoading, setIsLoading] = React.useState(true); const [isLoading, setIsLoading] = React.useState(true);
async function fetchElementData() { async function fetchLectureData() {
const element = await getElement("element_" + elementid); const lecture = await getLecture("lecture_" + lectureid);
setElement(element); setLecture(lecture);
} }
async function fetchCourseInfo() { async function fetchCourseInfo() {
@ -29,24 +29,24 @@ function EditElement(params: any) {
} }
async function fetchAllData() { async function fetchAllData() {
await fetchElementData(); await fetchLectureData();
await fetchCourseInfo(); await fetchCourseInfo();
setIsLoading(false); setIsLoading(false);
} }
React.useEffect(() => { React.useEffect(() => {
if (elementid && courseid) { if (lectureid && courseid) {
fetchAllData(); fetchAllData();
} }
return () => {}; return () => {};
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [elementid, courseid ]); }, [lectureid, courseid ]);
return ( return (
<AuthProvider> <AuthProvider>
{isLoading ? <div>Loading...</div> : <EditorWrapper course={courseInfo} element={element} content={element.content}></EditorWrapper>} {isLoading ? <div>Loading...</div> : <EditorWrapper course={courseInfo} lecture={lecture} content={lecture.content}></EditorWrapper>}
</AuthProvider> </AuthProvider>
); );
} }
export default EditElement; export default EditLecture;

View file

@ -3,26 +3,26 @@ import { useRouter } from "next/navigation";
import Link from "next/link"; import Link from "next/link";
import React, { useMemo } from "react"; import React, { useMemo } from "react";
import Layout from "../../../../../../../components/UI/Layout"; import Layout from "../../../../../../../components/UI/Layout";
import { getElement } from "../../../../../../../services/courses/elements"; import { getLecture } from "../../../../../../../services/courses/lectures";
import { getBackendUrl } from "../../../../../../../services/config"; import { getBackendUrl } from "../../../../../../../services/config";
import Canva from "../../../../../../../components/LectureViews/DynamicCanva/DynamicCanva"; import Canva from "../../../../../../../components/LectureViews/DynamicCanva/DynamicCanva";
import styled from "styled-components"; import styled from "styled-components";
import { getCourse, getCourseMetadata } from "../../../../../../../services/courses/courses"; import { getCourse, getCourseMetadata } from "../../../../../../../services/courses/courses";
import VideoLecture from "@components/LectureViews/Video/Video"; import VideoLecture from "@components/LectureViews/Video/Video";
function ElementPage(params: any) { function LecturePage(params: any) {
const router = useRouter(); const router = useRouter();
const elementid = params.params.elementid; const lectureid = params.params.lectureid;
const courseid = params.params.courseid; const courseid = params.params.courseid;
const orgslug = params.params.orgslug; const orgslug = params.params.orgslug;
const [element, setElement] = React.useState<any>({}); const [lecture, setLecture] = React.useState<any>({});
const [course, setCourse] = React.useState<any>({}); const [course, setCourse] = React.useState<any>({});
const [isLoading, setIsLoading] = React.useState(true); const [isLoading, setIsLoading] = React.useState(true);
async function fetchElementData() { async function fetchLectureData() {
setIsLoading(true); setIsLoading(true);
const element = await getElement("element_" + elementid); const lecture = await getLecture("lecture_" + lectureid);
setElement(element); setLecture(lecture);
} }
async function fetchCourseData() { async function fetchCourseData() {
@ -32,13 +32,13 @@ function ElementPage(params: any) {
} }
React.useEffect(() => { React.useEffect(() => {
if (elementid) { if (lectureid) {
fetchElementData(); fetchLectureData();
fetchCourseData(); fetchCourseData();
} }
return () => {}; return () => {};
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [elementid]); }, [lectureid]);
return ( return (
<> <>
@ -62,11 +62,11 @@ function ElementPage(params: any) {
return ( return (
<> <>
<div style={{ display: "flex", flexDirection: "row" }} key={chapter.chapter_id}> <div style={{ display: "flex", flexDirection: "row" }} key={chapter.chapter_id}>
{chapter.elements.map((element: any) => { {chapter.lectures.map((lecture: any) => {
return ( return (
<> <>
<Link href={`/org/${orgslug}/course/${courseid}/element/${element.id.replace("element_", "")}`}> <Link href={`/org/${orgslug}/course/${courseid}/lecture/${lecture.id.replace("lecture_", "")}`}>
<ChapterIndicator key={element.id} /> <ChapterIndicator key={lecture.id} />
</Link>{" "} </Link>{" "}
</> </>
); );
@ -79,9 +79,9 @@ function ElementPage(params: any) {
</ChaptersWrapper> </ChaptersWrapper>
<CourseContent> <CourseContent>
{element.type == "dynamic" && <Canva content={element.content} element={element} />} {lecture.type == "dynamic" && <Canva content={lecture.content} lecture={lecture} />}
{/* todo : use apis & streams instead of this */} {/* todo : use apis & streams instead of this */}
{element.type == "video" && <VideoLecture course={course} element={element} />} {lecture.type == "video" && <VideoLecture course={course} lecture={lecture} />}
</CourseContent> </CourseContent>
</LectureLayout> </LectureLayout>
)} )}
@ -154,4 +154,4 @@ const CourseContent = styled.div`
background-color: white; background-color: white;
min-height: 600px; min-height: 600px;
`; `;
export default ElementPage; export default LecturePage;

View file

@ -50,10 +50,10 @@ const CourseIdPage = (params: any) => {
{courseInfo.chapters.map((chapter: any) => { {courseInfo.chapters.map((chapter: any) => {
return ( return (
<> <>
{chapter.elements.map((element: any) => { {chapter.lectures.map((lecture: any) => {
return ( return (
<> <>
<Link href={`/org/${orgslug}/course/${courseid}/element/${element.id.replace("element_", "")}`}> <Link href={`/org/${orgslug}/course/${courseid}/lecture/${lecture.id.replace("lecture_", "")}`}>
<ChapterIndicator /> <ChapterIndicator />
</Link>{" "} </Link>{" "}
</> </>
@ -87,12 +87,12 @@ const CourseIdPage = (params: any) => {
return ( return (
<> <>
<h3>Chapter : {chapter.name}</h3> <h3>Chapter : {chapter.name}</h3>
{chapter.elements.map((element: any) => { {chapter.lectures.map((lecture: any) => {
return ( return (
<> <>
<p> <p>
Element {element.name} Lecture {lecture.name}
<Link href={`/org/${orgslug}/course/${courseid}/element/${element.id.replace("element_", "")}`} rel="noopener noreferrer"> <Link href={`/org/${orgslug}/course/${courseid}/lecture/${lecture.id.replace("lecture_", "")}`} rel="noopener noreferrer">
<EyeOpenIcon /> <EyeOpenIcon />
</Link>{" "} </Link>{" "}
</p> </p>

View file

@ -1,7 +1,8 @@
"use client";
import React from "react"; import React from "react";
import Layout from "../../components/UI/Layout"; import Layout from "../../../components/UI/Layout";
import { Title } from "../../components/UI/Elements/Styles/Title"; import { Title } from "../../../components/UI/Elements/Styles/Title";
import { createNewOrganization } from "../../services/orgs"; import { createNewOrganization } from "../../../services/orgs";
const Organizations = () => { const Organizations = () => {
const [name, setName] = React.useState(""); const [name, setName] = React.useState("");

View file

@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import styled from "styled-components"; import styled from "styled-components";
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
import Element, { ElementWrapper } from "./Element"; import Lecture, { LectureWrapper } from "./Lecture";
function Chapter(props: any) { function Chapter(props: any) {
return ( return (
@ -18,10 +18,10 @@ function Chapter(props: any) {
{props.info.list.chapter.name}{" "} {props.info.list.chapter.name}{" "}
<button <button
onClick={() => { onClick={() => {
props.openNewElementModal(props.info.list.chapter.id); props.openNewLectureModal(props.info.list.chapter.id);
}} }}
> >
Create Element Create Lecture
</button> </button>
<button <button
onClick={() => { onClick={() => {
@ -31,14 +31,14 @@ function Chapter(props: any) {
X X
</button> </button>
</h3> </h3>
<Droppable key={props.info.list.chapter.id} droppableId={props.info.list.chapter.id} type="element"> <Droppable key={props.info.list.chapter.id} droppableId={props.info.list.chapter.id} type="lecture">
{(provided) => ( {(provided) => (
<ElementsList {...provided.droppableProps} ref={provided.innerRef}> <LecturesList {...provided.droppableProps} ref={provided.innerRef}>
{props.info.list.elements.map((element: any, index: any) => ( {props.info.list.lectures.map((lecture: any, index: any) => (
<Element orgslug={props.orgslug} courseid={props.courseid} key={element.id} element={element} index={index}></Element> <Lecture orgslug={props.orgslug} courseid={props.courseid} key={lecture.id} lecture={lecture} index={index}></Lecture>
))} ))}
{provided.placeholder} {provided.placeholder}
</ElementsList> </LecturesList>
)} )}
</Droppable> </Droppable>
</ChapterWrapper> </ChapterWrapper>
@ -59,7 +59,7 @@ const ChapterWrapper = styled.div`
transition: all 0.2s ease; transition: all 0.2s ease;
`; `;
const ElementsList = styled.div` const LecturesList = styled.div`
padding: 10px; padding: 10px;
`; `;

View file

@ -4,31 +4,31 @@ import { Draggable } from "react-beautiful-dnd";
import { EyeOpenIcon, Pencil2Icon } from '@radix-ui/react-icons' import { EyeOpenIcon, Pencil2Icon } from '@radix-ui/react-icons'
import styled from "styled-components"; import styled from "styled-components";
function Element(props: any) { function Lecture(props: any) {
return ( return (
<Draggable key={props.element.id} draggableId={props.element.id} index={props.index}> <Draggable key={props.lecture.id} draggableId={props.lecture.id} index={props.index}>
{(provided) => ( {(provided) => (
<ElementWrapper key={props.element.id} {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef}> <LectureWrapper key={props.lecture.id} {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef}>
<p>{props.element.name} </p> <p>{props.lecture.name} </p>
<Link <Link
href={`/org/${props.orgslug}/course/${props.courseid}/element/${props.element.id.replace("element_", "")}`} href={`/org/${props.orgslug}/course/${props.courseid}/lecture/${props.lecture.id.replace("lecture_", "")}`}
rel="noopener noreferrer"> rel="noopener noreferrer">
&nbsp; <EyeOpenIcon/> &nbsp; <EyeOpenIcon/>
</Link> </Link>
<Link <Link
href={`/org/${props.orgslug}/course/${props.courseid}/element/${props.element.id.replace("element_", "")}/edit`} href={`/org/${props.orgslug}/course/${props.courseid}/lecture/${props.lecture.id.replace("lecture_", "")}/edit`}
rel="noopener noreferrer"> rel="noopener noreferrer">
&nbsp; <Pencil2Icon/> &nbsp; <Pencil2Icon/>
</Link> </Link>
</ElementWrapper> </LectureWrapper>
)} )}
</Draggable> </Draggable>
); );
} }
export const ElementWrapper = styled.div` export const LectureWrapper = styled.div`
padding: 10px; padding: 10px;
padding-left: 17px; padding-left: 17px;
list-style: none; list-style: none;
@ -42,4 +42,4 @@ export const ElementWrapper = styled.div`
} }
`; `;
export default Element; export default Lecture;

View file

@ -1,15 +1,15 @@
export const initialData = { export const initialData = {
elements: { lectures: {
"element-1": { id: "element-1", content: "First element" }, "lecture-1": { id: "lecture-1", content: "First lecture" },
"element-2": { id: "element-2", content: "Second element" }, "lecture-2": { id: "lecture-2", content: "Second lecture" },
"element-3": { id: "element-3", content: "Third element" }, "lecture-3": { id: "lecture-3", content: "Third lecture" },
"element-4": { id: "element-4", content: "Fourth element" }, "lecture-4": { id: "lecture-4", content: "Fourth lecture" },
"element-5": { id: "element-5", content: "Fifth element" }, "lecture-5": { id: "lecture-5", content: "Fifth lecture" },
}, },
chapters: { chapters: {
"chapter-1": { id: "chapter-1", name: "Chapter 1", elementIds: ["element-1", "element-2", "element-3"] }, "chapter-1": { id: "chapter-1", name: "Chapter 1", lectureIds: ["lecture-1", "lecture-2", "lecture-3"] },
"chapter-2": { id: "chapter-2", name: "Chapter 2", elementIds: ["element-4"] }, "chapter-2": { id: "chapter-2", name: "Chapter 2", lectureIds: ["lecture-4"] },
"chapter-3": { id: "chapter-3", name: "Chapter 3", elementIds: ["element-5"] }, "chapter-3": { id: "chapter-3", name: "Chapter 3", lectureIds: ["lecture-5"] },
}, },
chapterOrder: ["chapter-1", "chapter-2", "chapter-3"], chapterOrder: ["chapter-1", "chapter-2", "chapter-3"],

View file

@ -24,7 +24,7 @@ interface Editor {
content: string; content: string;
ydoc: any; ydoc: any;
provider: any; provider: any;
element: any; lecture: any;
course: any; course: any;
setContent: (content: string) => void; setContent: (content: string) => void;
} }
@ -48,11 +48,11 @@ function Editor(props: Editor) {
}), }),
ImageBlock.configure({ ImageBlock.configure({
editable: true, editable: true,
element: props.element, lecture: props.lecture,
}), }),
VideoBlock.configure({ VideoBlock.configure({
editable: true, editable: true,
element: props.element, lecture: props.lecture,
}), }),
Youtube.configure({ Youtube.configure({
controls: true, controls: true,
@ -96,7 +96,7 @@ function Editor(props: Editor) {
<EditorInfoThumbnail src={`${getBackendUrl()}content/uploads/img/${props.course.course.thumbnail}`} alt=""></EditorInfoThumbnail> <EditorInfoThumbnail src={`${getBackendUrl()}content/uploads/img/${props.course.course.thumbnail}`} alt=""></EditorInfoThumbnail>
<EditorInfoDocName> <EditorInfoDocName>
{" "} {" "}
<b>{props.course.course.name}</b> <SlashIcon /> {props.element.name}{" "} <b>{props.course.course.name}</b> <SlashIcon /> {props.lecture.name}{" "}
</EditorInfoDocName> </EditorInfoDocName>
<EditorSaveButton onClick={() => props.setContent(editor.getJSON())}> <EditorSaveButton onClick={() => props.setContent(editor.getJSON())}>
Save <Save size={12} /> Save <Save size={12} />

View file

@ -2,11 +2,11 @@ import { default as React, } from "react";
import * as Y from "yjs"; import * as Y from "yjs";
import { WebrtcProvider } from "y-webrtc"; import { WebrtcProvider } from "y-webrtc";
import Editor from "./Editor"; import Editor from "./Editor";
import { updateElement } from "../../services/courses/elements"; import { updateLecture } from "../../services/courses/lectures";
interface EditorWrapperProps { interface EditorWrapperProps {
content: string; content: string;
element: any; lecture: any;
course:any course:any
} }
@ -18,16 +18,16 @@ function EditorWrapper(props: EditorWrapperProps) : JSX.Element {
const [isLoading, setIsLoading] = React.useState(true); const [isLoading, setIsLoading] = React.useState(true);
function createRTCProvider() { function createRTCProvider() {
// const provider = new WebrtcProvider(props.element.element_id, ydoc); // const provider = new WebrtcProvider(props.lecture.lecture_id, ydoc);
// setYdocState(ydoc); // setYdocState(ydoc);
// setProviderState(provider); // setProviderState(provider);
setIsLoading(false); setIsLoading(false);
} }
async function setContent(content: any) { async function setContent(content: any) {
let element = props.element; let lecture = props.lecture;
element.content = content; lecture.content = content;
const res = await updateElement(element, element.element_id); const res = await updateLecture(lecture, lecture.lecture_id);
alert(JSON.stringify(res)); alert(JSON.stringify(res));
} }
@ -35,7 +35,7 @@ function EditorWrapper(props: EditorWrapperProps) : JSX.Element {
createRTCProvider(); createRTCProvider();
return <div>Loading...</div>; return <div>Loading...</div>;
} else { } else {
return <Editor course={props.course} element={props.element} content={props.content} setContent={setContent} provider={providerState} ydoc={ydocState}></Editor>; return <Editor course={props.course} lecture={props.lecture} content={props.content} setContent={setContent} provider={providerState} ydoc={ydocState}></Editor>;
} }
} }

View file

@ -17,7 +17,7 @@ function ImageBlockComponent(props: any) {
const handleSubmit = async (e: any) => { const handleSubmit = async (e: any) => {
e.preventDefault(); e.preventDefault();
setIsLoading(true); setIsLoading(true);
let object = await uploadNewImageFile(image, props.extension.options.element.element_id); let object = await uploadNewImageFile(image, props.extension.options.lecture.lecture_id);
setIsLoading(false); setIsLoading(false);
setfileObject(object); setfileObject(object);
props.updateAttributes({ props.updateAttributes({
@ -41,7 +41,7 @@ function ImageBlockComponent(props: any) {
{fileObject && ( {fileObject && (
<BlockImage> <BlockImage>
<img <img
src={`${getBackendUrl()}content/uploads/files/pictures/${props.extension.options.element.element_id}/${fileObject.file_id}.${ src={`${getBackendUrl()}content/uploads/files/pictures/${props.extension.options.lecture.lecture_id}/${fileObject.file_id}.${
fileObject.file_format fileObject.file_format
}`} }`}
alt="" alt=""

View file

@ -17,7 +17,7 @@ function VideoBlockComponents(props: any) {
const handleSubmit = async (e: any) => { const handleSubmit = async (e: any) => {
e.preventDefault(); e.preventDefault();
setIsLoading(true); setIsLoading(true);
let object = await uploadNewVideoFile(video, props.extension.options.element.element_id); let object = await uploadNewVideoFile(video, props.extension.options.lecture.lecture_id);
setIsLoading(false); setIsLoading(false);
setfileObject(object); setfileObject(object);
props.updateAttributes({ props.updateAttributes({
@ -42,7 +42,7 @@ function VideoBlockComponents(props: any) {
<BlockVideo> <BlockVideo>
<video <video
controls controls
src={`${getBackendUrl()}content/uploads/files/videos/${props.extension.options.element.element_id}/${fileObject.file_id}.${ src={`${getBackendUrl()}content/uploads/files/videos/${props.extension.options.lecture.lecture_id}/${fileObject.file_id}.${
fileObject.file_format fileObject.file_format
}`} }`}
></video> ></video>

View file

@ -12,7 +12,7 @@ import { styled } from "styled-components";
interface Editor { interface Editor {
content: string; content: string;
element: any; lecture: any;
//course: any; //course: any;
} }
@ -31,11 +31,11 @@ function Canva(props: Editor) {
}), }),
ImageBlock.configure({ ImageBlock.configure({
editable: isEditable, editable: isEditable,
element: props.element, lecture: props.lecture,
}), }),
VideoBlock.configure({ VideoBlock.configure({
editable: true, editable: true,
element: props.element, lecture: props.lecture,
}), }),
Youtube.configure({ Youtube.configure({
controls: true, controls: true,

View file

@ -2,10 +2,10 @@ import { getBackendUrl } from "@services/config";
import React from "react"; import React from "react";
import styled from "styled-components"; import styled from "styled-components";
function VideoLecture({ element, course }: { element: any; course: any }) { function VideoLecture({ lecture, course }: { lecture: any; course: any }) {
function getChapterName() { function getChapterName() {
let chapterName = ""; let chapterName = "";
let chapterId = element.chapter_id; let chapterId = lecture.chapter_id;
course.chapters.forEach((chapter: any) => { course.chapters.forEach((chapter: any) => {
if (chapter.chapter_id === chapterId) { if (chapter.chapter_id === chapterId) {
chapterName = chapter.name; chapterName = chapter.name;
@ -18,10 +18,10 @@ function VideoLecture({ element, course }: { element: any; course: any }) {
<VideoLectureLayout> <VideoLectureLayout>
<VideoTitle> <VideoTitle>
<p>Chapter : {getChapterName()}</p> <p>Chapter : {getChapterName()}</p>
{element.name} {lecture.name}
</VideoTitle> </VideoTitle>
<VideoPlayerWrapper> <VideoPlayerWrapper>
<video controls src={`${getBackendUrl()}content/uploads/video/${element.content.video.element_id}/${element.content.video.filename}`}></video> <video controls src={`${getBackendUrl()}content/uploads/video/${lecture.content.video.lecture_id}/${lecture.content.video.filename}`}></video>
</VideoPlayerWrapper> </VideoPlayerWrapper>
</VideoLectureLayout> </VideoLectureLayout>
); );

View file

@ -16,7 +16,7 @@ function NewChapterModal({ submitChapter , closeModal }: any) {
const handleSubmit = async (e: any) => { const handleSubmit = async (e: any) => {
e.preventDefault(); e.preventDefault();
console.log({ chapterName, chapterDescription }); console.log({ chapterName, chapterDescription });
submitChapter({ name : chapterName, description : chapterDescription , elements : [] }); submitChapter({ name : chapterName, description : chapterDescription , lectures : [] });
}; };
return ( return (

View file

@ -1,36 +0,0 @@
import React, { useState } from "react";
function DynamicCanvaModal({ submitElement, chapterId }: any) {
const [elementName, setElementName] = useState("");
const [elementDescription, setElementDescription] = useState("");
const handleElementNameChange = (e: any) => {
setElementName(e.target.value);
};
const handleElementDescriptionChange = (e: any) => {
setElementDescription(e.target.value);
};
const handleSubmit = async (e: any) => {
e.preventDefault();
console.log({ elementName, elementDescription, chapterId });
submitElement({
name: elementName,
chapterId: chapterId,
type: "dynamic",
});
};
return (
<div>
<div>
<input type="text" onChange={handleElementNameChange} placeholder="Element Name" /> <br />
<input type="text" onChange={handleElementDescriptionChange} placeholder="Element Description" />
<br />
<button onClick={handleSubmit}>Add Element</button>
</div>
</div>
);
}
export default DynamicCanvaModal;

View file

@ -2,10 +2,10 @@ import React, { useState } from "react";
import { ArrowLeftIcon, Cross1Icon } from "@radix-ui/react-icons"; import { ArrowLeftIcon, Cross1Icon } from "@radix-ui/react-icons";
import Modal from "../Modal"; import Modal from "../Modal";
import styled from "styled-components"; import styled from "styled-components";
import DynamicCanvaModal from "./NewElementModal/DynamicCanva"; import DynamicCanvaModal from "./NewLectureModal/DynamicCanva";
import VideoModal from "./NewElementModal/Video"; import VideoModal from "./NewLectureModal/Video";
function NewElementModal({ closeModal, submitElement, submitFileElement, chapterId }: any) { function NewLectureModal({ closeModal, submitLecture, submitFileLecture, chapterId }: any) {
const [selectedView, setSelectedView] = useState("home"); const [selectedView, setSelectedView] = useState("home");
return ( return (
@ -16,29 +16,29 @@ function NewElementModal({ closeModal, submitElement, submitFileElement, chapter
<button onClick={closeModal}> <button onClick={closeModal}>
<Cross1Icon /> <Cross1Icon />
</button> </button>
<h1>Add New Element</h1> <h1>Add New Lecture</h1>
<br /> <br />
{selectedView === "home" && ( {selectedView === "home" && (
<ElementChooserWrapper> <LectureChooserWrapper>
<ElementButton onClick={() => {setSelectedView("dynamic")}}>📄</ElementButton> <LectureButton onClick={() => {setSelectedView("dynamic")}}>📄</LectureButton>
<ElementButton onClick={() => {setSelectedView("video")}}>📹</ElementButton> <LectureButton onClick={() => {setSelectedView("video")}}>📹</LectureButton>
</ElementChooserWrapper> </LectureChooserWrapper>
)} )}
{selectedView === "dynamic" && ( {selectedView === "dynamic" && (
<DynamicCanvaModal submitElement={submitElement} chapterId={chapterId} /> <DynamicCanvaModal submitLecture={submitLecture} chapterId={chapterId} />
)} )}
{selectedView === "video" && ( {selectedView === "video" && (
<VideoModal submitFileElement={submitFileElement} chapterId={chapterId} /> <VideoModal submitFileLecture={submitFileLecture} chapterId={chapterId} />
)} )}
</Modal> </Modal>
); );
} }
const ElementChooserWrapper = styled.div` const LectureChooserWrapper = styled.div`
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
@ -46,7 +46,7 @@ const ElementChooserWrapper = styled.div`
gap: 20px; gap: 20px;
`; `;
const ElementButton = styled.button` const LectureButton = styled.button`
padding: 20px; padding: 20px;
border-radius: 10px; border-radius: 10px;
border: none; border: none;
@ -58,4 +58,4 @@ const ElementButton = styled.button`
} }
`; `;
export default NewElementModal; export default NewLectureModal;

View file

@ -0,0 +1,36 @@
import React, { useState } from "react";
function DynamicCanvaModal({ submitLecture, chapterId }: any) {
const [lectureName, setLectureName] = useState("");
const [lectureDescription, setLectureDescription] = useState("");
const handleLectureNameChange = (e: any) => {
setLectureName(e.target.value);
};
const handleLectureDescriptionChange = (e: any) => {
setLectureDescription(e.target.value);
};
const handleSubmit = async (e: any) => {
e.preventDefault();
console.log({ lectureName, lectureDescription, chapterId });
submitLecture({
name: lectureName,
chapterId: chapterId,
type: "dynamic",
});
};
return (
<div>
<div>
<input type="text" onChange={handleLectureNameChange} placeholder="Lecture Name" /> <br />
<input type="text" onChange={handleLectureDescriptionChange} placeholder="Lecture Description" />
<br />
<button onClick={handleSubmit}>Add Lecture</button>
</div>
</div>
);
}
export default DynamicCanvaModal;

View file

@ -1,6 +1,6 @@
import React from "react"; import React from "react";
function VideoModal({ submitFileElement, chapterId }: any) { function VideoModal({ submitFileLecture, chapterId }: any) {
const [video, setVideo] = React.useState(null) as any; const [video, setVideo] = React.useState(null) as any;
const [name, setName] = React.useState(""); const [name, setName] = React.useState("");
@ -14,11 +14,11 @@ function VideoModal({ submitFileElement, chapterId }: any) {
const handleSubmit = async (e: any) => { const handleSubmit = async (e: any) => {
e.preventDefault(); e.preventDefault();
let status = await submitFileElement(video, "video", { name, type: "video" }, chapterId); let status = await submitFileLecture(video, "video", { name, type: "video" }, chapterId);
}; };
/* TODO : implement some sort of progress bar for file uploads, it is not possible yet because i'm not using axios. /* TODO : implement some sort of progress bar for file uploads, it is not possible yet because i'm not using axios.
and the actual upload isn't happening here anyway, it's in the submitFileElement function */ and the actual upload isn't happening here anyway, it's in the submitFileLecture function */
return ( return (
<div> <div>

View file

@ -1,6 +1,6 @@
import { getAPIUrl } from "../config"; import { getAPIUrl } from "../config";
export async function createElement(data: any, chapter_id: any) { export async function createLecture(data: any, chapter_id: any) {
data.content = {}; data.content = {};
console.log("data", data, chapter_id); console.log("data", data, chapter_id);
@ -17,7 +17,7 @@ export async function createElement(data: any, chapter_id: any) {
body: JSON.stringify(data), body: JSON.stringify(data),
}; };
const result: any = await fetch(`${getAPIUrl()}elements/?coursechapter_id=${chapter_id}`, requestOptions) const result: any = await fetch(`${getAPIUrl()}lectures/?coursechapter_id=${chapter_id}`, requestOptions)
.then((result) => result.json()) .then((result) => result.json())
.catch((error) => console.log("error", error)); .catch((error) => console.log("error", error));
@ -26,7 +26,7 @@ export async function createElement(data: any, chapter_id: any) {
return result; return result;
} }
export async function createFileElement(file: File, type: string, data: any, chapter_id: any) { export async function createFileLecture(file: File, type: string, data: any, chapter_id: any) {
const HeadersConfig = new Headers(); const HeadersConfig = new Headers();
@ -37,12 +37,12 @@ export async function createFileElement(file: File, type: string, data: any, cha
console.log("type" , type); console.log("type" , type);
let endpoint = `${getAPIUrl()}elements/video`; let endpoint = `${getAPIUrl()}lectures/video`;
if (type === "video") { if (type === "video") {
formData.append("name", data.name); formData.append("name", data.name);
formData.append("video_file", file); formData.append("video_file", file);
endpoint = `${getAPIUrl()}elements/video`; endpoint = `${getAPIUrl()}lectures/video`;
} }
console.log(); console.log();
@ -67,21 +67,21 @@ export async function createFileElement(file: File, type: string, data: any, cha
return result; return result;
} }
export async function getElement(element_id: any) { export async function getLecture(lecture_id: any) {
const requestOptions: any = { const requestOptions: any = {
method: "GET", method: "GET",
redirect: "follow", redirect: "follow",
credentials: "include", credentials: "include",
}; };
const result: any = await fetch(`${getAPIUrl()}elements/${element_id}`, requestOptions) const result: any = await fetch(`${getAPIUrl()}lectures/${lecture_id}`, requestOptions)
.then((result) => result.json()) .then((result) => result.json())
.catch((error) => console.log("error", error)); .catch((error) => console.log("error", error));
return result; return result;
} }
export async function updateElement(data: any, element_id: any) { export async function updateLecture(data: any, lecture_id: any) {
const HeadersConfig = new Headers({ "Content-Type": "application/json" }); const HeadersConfig = new Headers({ "Content-Type": "application/json" });
const requestOptions: any = { const requestOptions: any = {
@ -92,7 +92,7 @@ export async function updateElement(data: any, element_id: any) {
body: JSON.stringify(data), body: JSON.stringify(data),
}; };
const result: any = await fetch(`${getAPIUrl()}elements/${element_id}`, requestOptions) const result: any = await fetch(`${getAPIUrl()}lectures/${lecture_id}`, requestOptions)
.then((result) => result.json()) .then((result) => result.json())
.catch((error) => console.log("error", error)); .catch((error) => console.log("error", error));

View file

@ -1,12 +1,12 @@
import { getAPIUrl } from "../config"; import { getAPIUrl } from "../config";
export async function uploadNewImageFile(file: any, element_id: string) { export async function uploadNewImageFile(file: any, lecture_id: string) {
const HeadersConfig = new Headers(); const HeadersConfig = new Headers();
// Send file thumbnail as form data // Send file thumbnail as form data
const formData = new FormData(); const formData = new FormData();
formData.append("file_object", file); formData.append("file_object", file);
formData.append("element_id", element_id); formData.append("lecture_id", lecture_id);
const requestOptions: any = { const requestOptions: any = {
method: "POST", method: "POST",

View file

@ -1,12 +1,12 @@
import { getAPIUrl } from "../config"; import { getAPIUrl } from "../config";
export async function uploadNewVideoFile(file: any, element_id: string) { export async function uploadNewVideoFile(file: any, lecture_id: string) {
const HeadersConfig = new Headers(); const HeadersConfig = new Headers();
// Send file thumbnail as form data // Send file thumbnail as form data
const formData = new FormData(); const formData = new FormData();
formData.append("file_object", file); formData.append("file_object", file);
formData.append("element_id", element_id); formData.append("lecture_id", lecture_id);
const requestOptions: any = { const requestOptions: any = {
method: "POST", method: "POST",

View file

@ -1,6 +1,6 @@
fastapi==0.78.0 fastapi==0.89.1
pydantic>=1.8.0,<2.0.0 pydantic>=1.8.0,<2.0.0
uvicorn>=0.15.0,<0.16.0 uvicorn==0.20.0
pymongo==4.1.1 pymongo==4.1.1
python-multipart python-multipart
python-jose python-jose

0
src/core/__init__.py Normal file
View file

View file

11
src/core/config/config.py Normal file
View file

@ -0,0 +1,11 @@
from fastapi import FastAPI
class Settings(FastAPI):
title="LearnHousse",
description="LearnHouse is a new open-source platform tailored for learning experiences.",
version="0.1.0",
root_path="/"
docs_url="/docs"
async def get_settings() -> Settings:
return Settings()

View file

View file

@ -0,0 +1,18 @@
import logging
from fastapi import FastAPI
import pymongo
async def connect_to_db(app: FastAPI) :
logging.info("Connecting to database...")
try:
app.mongodb_client = pymongo.MongoClient("mongodb://learnhouse:learnhouse@mongo:27017/") # type: ignore
app.db = app.mongodb_client["learnhouse"] # type: ignore
logging.info("Connected to database!")
except Exception as e:
logging.error("Failed to connect to database!")
logging.error(e)
async def close_database(app: FastAPI):
app.mongodb_client.close() # type: ignore
logging.info("LearnHouse has been shut down.")
return app

17
src/core/events/events.py Normal file
View file

@ -0,0 +1,17 @@
from typing import Callable
from fastapi import FastAPI
from src.core.events.database import close_database, connect_to_db
def startup_app(app: FastAPI) -> Callable:
async def start_app() -> None:
# Connect to database
await connect_to_db(app)
return start_app
def shutdown_app(app: FastAPI) -> Callable:
async def close_app() -> None:
await close_database(app)
return close_app

View file

@ -44,8 +44,8 @@ class TokenData(BaseModel):
#### Classes #################################################### #### Classes ####################################################
async def authenticate_user(email: str, password: str): async def authenticate_user(request: Request,email: str, password: str):
user = await security_get_user(email) user = await security_get_user(request, email)
if not user: if not user:
return False return False
if not await security_verify_password(password, user.password): if not await security_verify_password(password, user.password):
@ -63,28 +63,10 @@ def create_access_token(data: dict, expires_delta: timedelta | None = None):
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt return encoded_jwt
# DEPRECATED
async def get_current_user_old(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub") # type: ignore
if username is None:
raise credentials_exception
token_data = TokenData(username=username)
except JWTError:
raise credentials_exception
user = await security_get_user(email=token_data.username) # type: ignore
if user is None:
raise credentials_exception
return PublicUser(**user.dict())
async def get_current_user(Authorize: AuthJWT = Depends()):
async def get_current_user(request: Request, Authorize: AuthJWT = Depends()):
credentials_exception = HTTPException( credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials", detail="Could not validate credentials",
@ -97,7 +79,7 @@ async def get_current_user(Authorize: AuthJWT = Depends()):
token_data = TokenData(username=username) # type: ignore token_data = TokenData(username=username) # type: ignore
except JWTError: except JWTError:
raise credentials_exception raise credentials_exception
user = await security_get_user(email=token_data.username) # type: ignore # treated as an email user = await security_get_user(request, email=token_data.username) # type: ignore # treated as an email
if user is None: if user is None:
raise credentials_exception raise credentials_exception
return PublicUser(**user.dict()) return PublicUser(**user.dict())

View file

@ -1,6 +1,6 @@
from fastapi import APIRouter from fastapi import APIRouter
from src.routers import users, auth, houses, orgs, roles, files from src.routers import users, auth, houses, orgs, roles, files
from src.routers.courses import chapters, collections, courses,elements from src.routers.courses import chapters, collections, courses,lectures
global_router = APIRouter(prefix="/api") global_router = APIRouter(prefix="/api")
@ -15,6 +15,6 @@ global_router.include_router(roles.router, prefix="/roles", tags=["roles"])
global_router.include_router(files.router, prefix="/files", tags=["files"]) global_router.include_router(files.router, prefix="/files", tags=["files"])
global_router.include_router(courses.router, prefix="/courses", tags=["courses"]) global_router.include_router(courses.router, prefix="/courses", tags=["courses"])
global_router.include_router(chapters.router, prefix="/chapters", tags=["chapters"]) global_router.include_router(chapters.router, prefix="/chapters", tags=["chapters"])
global_router.include_router(elements.router, prefix="/elements", tags=["elements"]) global_router.include_router(lectures.router, prefix="/lectures", tags=["lectures"])
global_router.include_router(collections.router, prefix="/collections", tags=["collections"]) global_router.include_router(collections.router, prefix="/collections", tags=["collections"])

View file

@ -1,5 +1,5 @@
from urllib.request import Request from urllib.request import Request
from fastapi import Depends, APIRouter, HTTPException, status from fastapi import Depends, APIRouter, HTTPException, status, Request
from fastapi.security import OAuth2PasswordRequestForm from fastapi.security import OAuth2PasswordRequestForm
from src.dependencies.auth import * from src.dependencies.auth import *
from src.services.users import * from src.services.users import *
@ -11,11 +11,11 @@ router = APIRouter()
# DEPRECATED # DEPRECATED
@router.post("/token", response_model=Token) @router.post("/token", response_model=Token)
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()): async def login_for_access_token(request: Request, form_data: OAuth2PasswordRequestForm = Depends()):
""" """
OAuth2 compatible token login, get access token for future requests OAuth2 compatible token login, get access token for future requests
""" """
user = await authenticate_user(form_data.username, form_data.password) user = await authenticate_user(request, form_data.username, form_data.password)
if not user: if not user:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, status_code=status.HTTP_401_UNAUTHORIZED,
@ -47,8 +47,8 @@ def refresh(Authorize: AuthJWT = Depends()):
return {"access_token": new_access_token} return {"access_token": new_access_token}
@router.post('/login') @router.post('/login')
async def login(Authorize: AuthJWT = Depends(), form_data: OAuth2PasswordRequestForm = Depends()): async def login(request: Request,Authorize: AuthJWT = Depends(), form_data: OAuth2PasswordRequestForm = Depends()):
user = await authenticate_user(form_data.username, form_data.password) user = await authenticate_user(request, form_data.username, form_data.password)
if not user: if not user:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, status_code=status.HTTP_401_UNAUTHORIZED,

View file

@ -1,4 +1,4 @@
from fastapi import APIRouter, Depends, UploadFile, Form from fastapi import APIRouter, Depends, Request, UploadFile, Form
from src.services.courses.chapters import CourseChapter, CourseChapterMetaData, create_coursechapter, delete_coursechapter, get_coursechapter, get_coursechapters, get_coursechapters_meta, update_coursechapter, update_coursechapters_meta from src.services.courses.chapters import CourseChapter, CourseChapterMetaData, create_coursechapter, delete_coursechapter, get_coursechapter, get_coursechapters, get_coursechapters_meta, update_coursechapter, update_coursechapters_meta
from src.services.users import PublicUser from src.services.users import PublicUser
@ -8,57 +8,57 @@ router = APIRouter()
@router.post("/") @router.post("/")
async def api_create_coursechapter(coursechapter_object: CourseChapter, course_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_create_coursechapter(request: Request,coursechapter_object: CourseChapter, course_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Create new CourseChapter Create new CourseChapter
""" """
return await create_coursechapter(coursechapter_object, course_id, current_user) return await create_coursechapter(request, coursechapter_object, course_id, current_user)
@router.get("/{coursechapter_id}") @router.get("/{coursechapter_id}")
async def api_get_coursechapter(coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_get_coursechapter(request: Request,coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Get single CourseChapter by coursechapter_id Get single CourseChapter by coursechapter_id
""" """
return await get_coursechapter(coursechapter_id, current_user=current_user) return await get_coursechapter(request, coursechapter_id, current_user=current_user)
@router.get("/meta/{course_id}") @router.get("/meta/{course_id}")
async def api_get_coursechapter_meta(course_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_get_coursechapter_meta(request: Request,course_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Get coursechapter metadata Get coursechapter metadata
""" """
return await get_coursechapters_meta(course_id, current_user=current_user) return await get_coursechapters_meta(request, course_id, current_user=current_user)
@router.put("/meta/{course_id}") @router.put("/meta/{course_id}")
async def api_update_coursechapter_meta(course_id: str, coursechapters_metadata: CourseChapterMetaData, current_user: PublicUser = Depends(get_current_user)): async def api_update_coursechapter_meta(request: Request,course_id: str, coursechapters_metadata: CourseChapterMetaData, current_user: PublicUser = Depends(get_current_user)):
""" """
Update coursechapter metadata Update coursechapter metadata
""" """
return await update_coursechapters_meta(course_id, coursechapters_metadata, current_user=current_user) return await update_coursechapters_meta(request, course_id, coursechapters_metadata, current_user=current_user)
@router.get("/{course_id}/page/{page}/limit/{limit}") @router.get("/{course_id}/page/{page}/limit/{limit}")
async def api_get_coursechapter_by(course_id: str, page: int, limit: int): async def api_get_coursechapter_by(request: Request,course_id: str, page: int, limit: int):
""" """
Get CourseChapters by page and limit Get CourseChapters by page and limit
""" """
return await get_coursechapters(course_id, page, limit) return await get_coursechapters(request, course_id, page, limit)
@router.put("/{coursechapter_id}") @router.put("/{coursechapter_id}")
async def api_update_coursechapter(coursechapter_object: CourseChapter, coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_update_coursechapter(request: Request,coursechapter_object: CourseChapter, coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Update CourseChapters by course_id Update CourseChapters by course_id
""" """
return await update_coursechapter(coursechapter_object, coursechapter_id, current_user) return await update_coursechapter(request, coursechapter_object, coursechapter_id, current_user)
@router.delete("/{coursechapter_id}") @router.delete("/{coursechapter_id}")
async def api_delete_coursechapter(coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_delete_coursechapter(request: Request,coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Delete CourseChapters by ID Delete CourseChapters by ID
""" """
return await delete_coursechapter(coursechapter_id, current_user) return await delete_coursechapter(request,coursechapter_id, current_user)

View file

@ -1,4 +1,4 @@
from fastapi import APIRouter, Depends from fastapi import APIRouter, Depends, Request
from src.dependencies.auth import get_current_user from src.dependencies.auth import get_current_user
from src.services.users import PublicUser, User from src.services.users import PublicUser, User
from src.services.courses.collections import Collection, create_collection, get_collection, get_collections, update_collection, delete_collection from src.services.courses.collections import Collection, create_collection, get_collection, get_collections, update_collection, delete_collection
@ -8,41 +8,41 @@ router = APIRouter()
@router.post("/") @router.post("/")
async def api_create_collection(collection_object: Collection, current_user: PublicUser = Depends(get_current_user)): async def api_create_collection(request: Request,collection_object: Collection, current_user: PublicUser = Depends(get_current_user)):
""" """
Create new Collection Create new Collection
""" """
return await create_collection(collection_object, current_user) return await create_collection(request, collection_object, current_user)
@router.get("/{collection_id}") @router.get("/{collection_id}")
async def api_get_collection(collection_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_get_collection(request: Request,collection_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Get single collection by ID Get single collection by ID
""" """
return await get_collection(collection_id, current_user) return await get_collection(request, collection_id, current_user)
@router.get("/page/{page}/limit/{limit}") @router.get("/page/{page}/limit/{limit}")
async def api_get_collections_by(page: int, limit: int, current_user: PublicUser = Depends(get_current_user)): async def api_get_collections_by(request: Request,page: int, limit: int, current_user: PublicUser = Depends(get_current_user)):
""" """
Get collections by page and limit Get collections by page and limit
""" """
return await get_collections(page, limit) return await get_collections(request, page, limit)
@router.put("/{collection_id}") @router.put("/{collection_id}")
async def api_update_collection(collection_object: Collection, collection_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_update_collection(request: Request,collection_object: Collection, collection_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Update collection by ID Update collection by ID
""" """
return await update_collection(collection_object, collection_id, current_user) return await update_collection(request, collection_object, collection_id, current_user)
@router.delete("/{collection_id}") @router.delete("/{collection_id}")
async def api_delete_collection(collection_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_delete_collection(request: Request,collection_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Delete collection by ID Delete collection by ID
""" """
return await delete_collection(collection_id, current_user) return await delete_collection(request, collection_id, current_user)

View file

@ -1,4 +1,4 @@
from fastapi import APIRouter, Depends, UploadFile, Form from fastapi import APIRouter, Depends, UploadFile, Form, Request
from src.dependencies.auth import get_current_user from src.dependencies.auth import get_current_user
from src.services.courses.courses import Course, create_course, get_course, get_course_meta, get_courses, update_course, delete_course, update_course_thumbnail from src.services.courses.courses import Course, create_course, get_course, get_course_meta, get_courses, update_course, delete_course, update_course_thumbnail
@ -9,59 +9,59 @@ router = APIRouter()
@router.post("/") @router.post("/")
async def api_create_course(org_id: str, name: str = Form(), mini_description: str = Form(), description: str = Form(), public: bool = Form(), current_user: PublicUser = Depends(get_current_user), thumbnail: UploadFile | None = None): async def api_create_course(request: Request,org_id: str, name: str = Form(), mini_description: str = Form(), description: str = Form(), public: bool = Form(), current_user: PublicUser = Depends(get_current_user), thumbnail: UploadFile | None = None):
""" """
Create new Course Create new Course
""" """
course = Course(name=name, mini_description=mini_description, description=description, course = Course(name=name, mini_description=mini_description, description=description,
org_id=org_id, public=public, thumbnail="", chapters=[], learnings=[]) org_id=org_id, public=public, thumbnail="", chapters=[], learnings=[])
return await create_course(course, org_id, current_user, thumbnail) return await create_course(request, course, org_id, current_user, thumbnail)
@router.put("/thumbnail/{course_id}") @router.put("/thumbnail/{course_id}")
async def api_create_course_thumbnail(course_id: str, thumbnail: UploadFile | None = None, current_user: PublicUser = Depends(get_current_user)): async def api_create_course_thumbnail(request: Request,course_id: str, thumbnail: UploadFile | None = None, current_user: PublicUser = Depends(get_current_user)):
""" """
Update new Course Thumbnail Update new Course Thumbnail
""" """
return await update_course_thumbnail(course_id, current_user, thumbnail) return await update_course_thumbnail(request, course_id, current_user, thumbnail)
@router.get("/{course_id}") @router.get("/{course_id}")
async def api_get_course(course_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_get_course(request: Request,course_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Get single Course by course_id Get single Course by course_id
""" """
return await get_course(course_id, current_user=current_user) return await get_course(request, course_id, current_user=current_user)
@router.get("/meta/{course_id}") @router.get("/meta/{course_id}")
async def api_get_course_meta(course_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_get_course_meta(request: Request,course_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Get single Course Metadata (chapters, elements) by course_id Get single Course Metadata (chapters, lectures) by course_id
""" """
return await get_course_meta(course_id, current_user=current_user) return await get_course_meta(request, course_id, current_user=current_user)
@router.get("/{org_id}/page/{page}/limit/{limit}") @router.get("/{org_id}/page/{page}/limit/{limit}")
async def api_get_course_by(page: int, limit: int, org_id: str): async def api_get_course_by(request: Request,page: int, limit: int, org_id: str):
""" """
Get houses by page and limit Get houses by page and limit
""" """
return await get_courses(page, limit, org_id) return await get_courses(request,page, limit, org_id)
@router.put("/{course_id}") @router.put("/{course_id}")
async def api_update_course(course_object: Course, course_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_update_course(request: Request,course_object: Course, course_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Update Course by course_id Update Course by course_id
""" """
return await update_course(course_object, course_id, current_user) return await update_course(request,course_object, course_id, current_user)
@router.delete("/{course_id}") @router.delete("/{course_id}")
async def api_delete_course(course_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_delete_course(request: Request,course_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Delete Course by ID Delete Course by ID
""" """
return await delete_course(course_id, current_user) return await delete_course(request, course_id, current_user)

View file

@ -1,55 +0,0 @@
from fastapi import APIRouter, Depends, UploadFile, Form
from src.services.courses.elements.elements import *
from src.dependencies.auth import get_current_user
from src.services.courses.elements.video import create_video_element
router = APIRouter()
@router.post("/")
async def api_create_element(element_object: Element, coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Create new Element
"""
return await create_element(element_object, coursechapter_id, current_user)
@router.get("/{element_id}")
async def api_get_element(element_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Get single Element by element_id
"""
return await get_element(element_id, current_user=current_user)
@router.get("/coursechapter/{coursechapter_id}")
async def api_get_elements(coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Get CourseChapter Elements
"""
return await get_elements(coursechapter_id, current_user)
@router.put("/{element_id}")
async def api_update_element(element_object: Element, element_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Update Element by element_id
"""
return await update_element(element_object, element_id, current_user)
@router.delete("/{element_id}")
async def api_delete_element(element_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Delete Element by element_id
"""
return await delete_element(element_id, current_user)
# Video Element
@router.post("/video")
async def api_create_video_element(name: str = Form() , coursechapter_id: str = Form(), current_user: PublicUser = Depends(get_current_user), video_file: UploadFile | None = None):
"""
Create new Element
"""
return await create_video_element(name, coursechapter_id, current_user, video_file)

View file

@ -0,0 +1,54 @@
from fastapi import APIRouter, Depends, UploadFile, Form, Request
from src.services.courses.lectures.lectures import *
from src.dependencies.auth import get_current_user
from src.services.courses.lectures.video import create_video_lecture
router = APIRouter()
@router.post("/")
async def api_create_lecture(request: Request,lecture_object: Lecture, coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Create new lecture
"""
return await create_lecture(request,lecture_object, coursechapter_id, current_user)
@router.get("/{lecture_id}")
async def api_get_lecture(request: Request,lecture_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Get single lecture by lecture_id
"""
return await get_lecture(request, lecture_id, current_user=current_user)
@router.get("/coursechapter/{coursechapter_id}")
async def api_get_lectures(request: Request,coursechapter_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Get CourseChapter lectures
"""
return await get_lectures(request,coursechapter_id, current_user)
@router.put("/{lecture_id}")
async def api_update_lecture(request: Request,lecture_object: Lecture, lecture_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Update lecture by lecture_id
"""
return await update_lecture(request,lecture_object, lecture_id, current_user)
@router.delete("/{lecture_id}")
async def api_delete_lecture(request: Request,lecture_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Delete lecture by lecture_id
"""
return await delete_lecture(request,lecture_id, current_user)
# Video play
@router.post("/video")
async def api_create_video_lecture(request: Request,name: str = Form(), coursechapter_id: str = Form(), current_user: PublicUser = Depends(get_current_user), video_file: UploadFile | None = None):
"""
Create new lecture
"""
return await create_video_lecture(request,name, coursechapter_id, current_user, video_file)

View file

@ -1,4 +1,4 @@
from fastapi import APIRouter, Depends, UploadFile, Form from fastapi import APIRouter, Depends, UploadFile, Form, Request
from src.dependencies.auth import get_current_user from src.dependencies.auth import get_current_user
from fastapi import HTTPException, status, UploadFile from fastapi import HTTPException, status, UploadFile
@ -10,32 +10,32 @@ router = APIRouter()
@router.post("/picture") @router.post("/picture")
async def api_create_picture_file(file_object: UploadFile, element_id: str = Form(), current_user: PublicUser = Depends(get_current_user)): async def api_create_picture_file(request: Request,file_object: UploadFile, lecture_id: str = Form(), current_user: PublicUser = Depends(get_current_user)):
""" """
Create new picture file Create new picture file
""" """
return await create_picture_file(file_object, element_id) return await create_picture_file(request,file_object, lecture_id)
@router.post("/video") @router.post("/video")
async def api_create_video_file(file_object: UploadFile,element_id: str = Form(), current_user: PublicUser = Depends(get_current_user)): async def api_create_video_file(request: Request,file_object: UploadFile,lecture_id: str = Form(), current_user: PublicUser = Depends(get_current_user)):
""" """
Create new video file Create new video file
""" """
return await create_video_file(file_object, element_id) return await create_video_file(request, file_object, lecture_id)
@router.get("/picture") @router.get("/picture")
async def api_get_picture_file(file_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_get_picture_file(request: Request,file_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Get picture file Get picture file
""" """
return await get_picture_file(file_id, current_user) return await get_picture_file(request, file_id, current_user)
@router.get("/video") @router.get("/video")
async def api_get_video_file(file_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_get_video_file(request: Request,file_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Get video file Get video file
""" """
return await get_video_file(file_id, current_user) return await get_video_file(request, file_id, current_user)

View file

@ -1,4 +1,4 @@
from fastapi import APIRouter, Depends from fastapi import APIRouter, Depends, Request
from src.dependencies.auth import get_current_user from src.dependencies.auth import get_current_user
from src.services.houses import House, HouseInDB, create_house, get_house, get_houses, update_house, delete_house from src.services.houses import House, HouseInDB, create_house, get_house, get_houses, update_house, delete_house
@ -9,41 +9,41 @@ router = APIRouter()
@router.post("/") @router.post("/")
async def api_create_house(house_object: House, current_user: PublicUser = Depends(get_current_user)): async def api_create_house(request: Request,house_object: House, current_user: PublicUser = Depends(get_current_user)):
""" """
Create new house Create new house
""" """
return await create_house(house_object, current_user) return await create_house(request, house_object, current_user)
@router.get("/{house_id}") @router.get("/{house_id}")
async def api_get_house(house_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_get_house(request: Request,house_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Get single House by house_id Get single House by house_id
""" """
return await get_house(house_id, current_user=current_user) return await get_house(request, house_id, current_user=current_user)
@router.get("/page/{page}/limit/{limit}") @router.get("/page/{page}/limit/{limit}")
async def api_get_house_by(page: int, limit: int): async def api_get_house_by(request: Request,page: int, limit: int):
""" """
Get houses by page and limit Get houses by page and limit
""" """
return await get_houses(page, limit) return await get_houses(request, page, limit)
@router.put("/{house_id}") @router.put("/{house_id}")
async def api_update_house(house_object: House, house_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_update_house(request: Request,house_object: House, house_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Update House by house_id Update House by house_id
""" """
return await update_house(house_object, house_id, current_user) return await update_house(request, house_object, house_id, current_user)
@router.delete("/{house_id}") @router.delete("/{house_id}")
async def api_delete_house(house_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_delete_house(request: Request,house_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Delete House by ID Delete House by ID
""" """
return await delete_house(house_id, current_user) return await delete_house(request, house_id, current_user)

View file

@ -1,6 +1,7 @@
from fastapi import APIRouter, Depends
from fastapi import APIRouter, Depends, Request
from src.dependencies.auth import get_current_user from src.dependencies.auth import get_current_user
from src.services.orgs import Organization, create_org, delete_org, get_organization, get_organization_by_slug, get_orgs, get_orgs_by_user, update_org from src.services.orgs import Organization, create_org, delete_org, get_organization, get_organization_by_slug, get_orgs_by_user, update_org
from src.services.users import PublicUser, User from src.services.users import PublicUser, User
@ -8,55 +9,49 @@ router = APIRouter()
@router.post("/") @router.post("/")
async def api_create_org(org_object: Organization, current_user: PublicUser = Depends(get_current_user)): async def api_create_org(request: Request, org_object: Organization, current_user: PublicUser = Depends(get_current_user)):
""" """
Create new organization Create new organization
""" """
return await create_org(org_object, current_user) return await create_org(request, org_object, current_user)
@router.get("/{org_id}") @router.get("/{org_id}")
async def api_get_org(org_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_get_org(request: Request, org_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Get single Org by ID Get single Org by ID
""" """
return await get_organization(org_id) return await get_organization(request, org_id)
@router.get("/slug/{org_slug}") @router.get("/slug/{org_slug}")
async def api_get_org_by_slug(org_slug: str, current_user: User = Depends(get_current_user)): async def api_get_org_by_slug(request: Request, org_slug: str, current_user: User = Depends(get_current_user)):
""" """
Get single Org by Slug Get single Org by Slug
""" """
return await get_organization_by_slug(org_slug) return await get_organization_by_slug(request, org_slug)
@router.get("/page/{page}/limit/{limit}")
async def api_get_org_by(page: int, limit: int):
"""
Get orgs by page and limit
"""
return await get_orgs(page, limit)
@router.get("/user/page/{page}/limit/{limit}") @router.get("/user/page/{page}/limit/{limit}")
async def api_user_orgs(page: int, limit: int, current_user: PublicUser = Depends(get_current_user)): async def api_user_orgs(request: Request, page: int, limit: int, current_user: PublicUser = Depends(get_current_user)):
""" """
Get orgs by page and limit by user Get orgs by page and limit by user
""" """
return await get_orgs_by_user(current_user.user_id, page, limit) return await get_orgs_by_user(request, current_user.user_id, page, limit)
@router.put("/{org_id}") @router.put("/{org_id}")
async def api_update_org(org_object: Organization, org_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_update_org(request: Request, org_object: Organization, org_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Update Org by ID Update Org by ID
""" """
return await update_org(org_object, org_id, current_user) return await update_org(request, org_object, org_id, current_user)
@router.delete("/{org_id}") @router.delete("/{org_id}")
async def api_delete_org(org_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_delete_org(request: Request, org_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Delete Org by ID Delete Org by ID
""" """
return await delete_org(org_id, current_user) return await delete_org(request, org_id, current_user)

View file

@ -1,6 +1,5 @@
from fastapi import APIRouter, Depends from fastapi import APIRouter, Depends, Request
from src.dependencies.auth import get_current_user from src.dependencies.auth import get_current_user
from src.services.roles import Role, create_role, delete_role, get_role, get_roles, update_role from src.services.roles import Role, create_role, delete_role, get_role, get_roles, update_role
from src.services.users import PublicUser, User from src.services.users import PublicUser, User
@ -9,41 +8,41 @@ router = APIRouter()
@router.post("/") @router.post("/")
async def api_create_role(role_object: Role, current_user: PublicUser = Depends(get_current_user)): async def api_create_role(request: Request,role_object: Role, current_user: PublicUser = Depends(get_current_user)):
""" """
Create new role Create new role
""" """
return await create_role(role_object, current_user) return await create_role(request, role_object, current_user)
@router.get("/{role_id}") @router.get("/{role_id}")
async def api_get_role(role_id: str): async def api_get_role(request: Request,role_id: str):
""" """
Get single role by role_id Get single role by role_id
""" """
return await get_role(role_id) return await get_role(request, role_id)
@router.get("/page/{page}/limit/{limit}") @router.get("/page/{page}/limit/{limit}")
async def api_get_role_by(page: int, limit: int): async def api_get_role_by(request: Request,page: int, limit: int):
""" """
Get roles by page and limit Get roles by page and limit
""" """
return await get_roles(page, limit) return await get_roles(request, page, limit)
@router.put("/{role_id}") @router.put("/{role_id}")
async def api_update_role(role_object: Role, role_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_update_role(request: Request,role_object: Role, role_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Update role by role_id Update role by role_id
""" """
return await update_role(role_object, role_id, current_user) return await update_role(request, role_object, role_id, current_user)
@router.delete("/{role_id}") @router.delete("/{role_id}")
async def api_delete_role(role_id: str, current_user: PublicUser = Depends(get_current_user)): async def api_delete_role(request: Request,role_id: str, current_user: PublicUser = Depends(get_current_user)):
""" """
Delete role by ID Delete role by ID
""" """
return await delete_role(role_id, current_user) return await delete_role(request, role_id, current_user)

View file

@ -9,13 +9,6 @@ from src.services.users import *
router = APIRouter() router = APIRouter()
# DEPRECATED
@router.get("/me")
async def api_get_current_user_old(current_user: User = Depends(get_current_user)):
"""
Get current user
"""
return current_user.dict()
@router.get("/profile") @router.get("/profile")
async def api_get_current_user(current_user: User = Depends(get_current_user)): async def api_get_current_user(current_user: User = Depends(get_current_user)):
@ -25,49 +18,49 @@ async def api_get_current_user(current_user: User = Depends(get_current_user)):
return current_user.dict() return current_user.dict()
@router.get("/profile_metadata") @router.get("/profile_metadata")
async def api_get_current_user_metadata(current_user: User = Depends(get_current_user)): async def api_get_current_user_metadata(request: Request,current_user: User = Depends(get_current_user)):
""" """
Get current user Get current user
""" """
return await get_profile_metadata(current_user.dict()) return await get_profile_metadata(request , current_user.dict())
@router.get("/username/{username}") @router.get("/username/{username}")
async def api_get_user_by_username(username: str): async def api_get_user_by_username(request: Request, username: str):
""" """
Get single user by username Get single user by username
""" """
return await get_user(username) return await get_user(request, username)
@router.get("/user_id/{user_id}") @router.get("/user_id/{user_id}")
async def api_get_user_by_userid(user_id: str): async def api_get_user_by_userid(request: Request,user_id: str):
""" """
Get single user by user_id Get single user by user_id
""" """
return await get_user_by_userid(user_id) return await get_user_by_userid(request, user_id)
@router.post("/") @router.post("/")
async def api_create_user(user_object: UserWithPassword): async def api_create_user(request: Request,user_object: UserWithPassword):
""" """
Create new user Create new user
""" """
return await create_user(user_object) return await create_user(request, user_object)
@router.delete("/user_id/{user_id}") @router.delete("/user_id/{user_id}")
async def api_delete_user(user_id: str): async def api_delete_user(request: Request, user_id: str):
""" """
Delete user by ID Delete user by ID
""" """
return await delete_user(user_id) return await delete_user(request, user_id)
@router.put("/user_id/{user_id}") @router.put("/user_id/{user_id}")
async def api_update_user(user_object: UserWithPassword, user_id: str): async def api_update_user(request: Request, user_object: UserWithPassword, user_id: str):
""" """
Update user by ID Update user by ID
""" """
return await update_user(user_id, user_object) return await update_user(request, user_id, user_object)

View file

@ -4,17 +4,16 @@ from typing import List
from uuid import uuid4 from uuid import uuid4
from pydantic import BaseModel from pydantic import BaseModel
from src.services.courses.courses import Course, CourseInDB from src.services.courses.courses import Course, CourseInDB
from src.services.courses.elements.elements import Element, ElementInDB from src.services.courses.lectures.lectures import Lecture, LectureInDB
from src.services.database import create_config_collection, check_database, create_database, learnhouseDB, learnhouseDB
from src.services.security import verify_user_rights_with_roles from src.services.security import verify_user_rights_with_roles
from src.services.users import PublicUser from src.services.users import PublicUser
from fastapi import FastAPI, HTTPException, status, Request, Response, BackgroundTasks, UploadFile, File from fastapi import HTTPException, status, Request, Response, BackgroundTasks, UploadFile, File
class CourseChapter(BaseModel): class CourseChapter(BaseModel):
name: str name: str
description: str description: str
elements: list lectures: list
class CourseChapterInDB(CourseChapter): class CourseChapterInDB(CourseChapter):
@ -28,7 +27,7 @@ class CourseChapterInDB(CourseChapter):
class CourseChapterMetaData(BaseModel): class CourseChapterMetaData(BaseModel):
chapterOrder: List[str] chapterOrder: List[str]
chapters: object chapters: object
elements: object lectures: object
#### Classes #################################################### #### Classes ####################################################
@ -37,15 +36,14 @@ class CourseChapterMetaData(BaseModel):
#################################################### ####################################################
async def create_coursechapter(coursechapter_object: CourseChapter, course_id: str, current_user: PublicUser): async def create_coursechapter(request: Request,coursechapter_object: CourseChapter, course_id: str, current_user: PublicUser):
await check_database() coursechapters = request.app.db["coursechapters"]
coursechapters = learnhouseDB["coursechapters"] courses = request.app.db["courses"]
courses = learnhouseDB["courses"]
# generate coursechapter_id with uuid4 # generate coursechapter_id with uuid4
coursechapter_id = str(f"coursechapter_{uuid4()}") coursechapter_id = str(f"coursechapter_{uuid4()}")
hasRoleRights = await verify_user_rights_with_roles("create", current_user.user_id, coursechapter_id) hasRoleRights = await verify_user_rights_with_roles(request, "create", current_user.user_id, coursechapter_id)
if not hasRoleRights: if not hasRoleRights:
raise HTTPException( raise HTTPException(
@ -65,16 +63,15 @@ async def create_coursechapter(coursechapter_object: CourseChapter, course_id: s
return coursechapter.dict() return coursechapter.dict()
async def get_coursechapter(coursechapter_id: str, current_user: PublicUser): async def get_coursechapter(request: Request,coursechapter_id: str, current_user: PublicUser):
await check_database() coursechapters = request.app.db["coursechapters"]
coursechapters = learnhouseDB["coursechapters"]
coursechapter = coursechapters.find_one( coursechapter = coursechapters.find_one(
{"coursechapter_id": coursechapter_id}) {"coursechapter_id": coursechapter_id})
if coursechapter: if coursechapter:
# verify course rights # verify course rights
await verify_rights(coursechapter["course_id"], current_user, "read") await verify_rights(request, coursechapter["course_id"], current_user, "read")
coursechapter = CourseChapter(**coursechapter) coursechapter = CourseChapter(**coursechapter)
return coursechapter return coursechapter
@ -84,16 +81,15 @@ async def get_coursechapter(coursechapter_id: str, current_user: PublicUser):
status_code=status.HTTP_409_CONFLICT, detail="CourseChapter does not exist") status_code=status.HTTP_409_CONFLICT, detail="CourseChapter does not exist")
async def update_coursechapter(coursechapter_object: CourseChapter, coursechapter_id: str, current_user: PublicUser): async def update_coursechapter(request: Request,coursechapter_object: CourseChapter, coursechapter_id: str, current_user: PublicUser):
await check_database() coursechapters = request.app.db["coursechapters"]
coursechapters = learnhouseDB["coursechapters"]
coursechapter = coursechapters.find_one( coursechapter = coursechapters.find_one(
{"coursechapter_id": coursechapter_id}) {"coursechapter_id": coursechapter_id})
if coursechapter: if coursechapter:
# verify course rights # verify course rights
await verify_rights(coursechapter["course_id"], current_user, "update") await verify_rights(request, coursechapter["course_id"], current_user, "update")
creationDate = coursechapter["creationDate"] creationDate = coursechapter["creationDate"]
# get today's date # get today's date
@ -112,18 +108,17 @@ async def update_coursechapter(coursechapter_object: CourseChapter, coursechapt
status_code=status.HTTP_409_CONFLICT, detail="Coursechapter does not exist") status_code=status.HTTP_409_CONFLICT, detail="Coursechapter does not exist")
async def delete_coursechapter(coursechapter_id: str, current_user: PublicUser): async def delete_coursechapter(request: Request,coursechapter_id: str, current_user: PublicUser):
await check_database()
coursechapters = learnhouseDB["coursechapters"] coursechapters = request.app.db["coursechapters"]
courses = learnhouseDB["courses"] courses = request.app.db["courses"]
coursechapter = coursechapters.find_one( coursechapter = coursechapters.find_one(
{"coursechapter_id": coursechapter_id}) {"coursechapter_id": coursechapter_id})
if coursechapter: if coursechapter:
# verify course rights # verify course rights
await verify_rights(coursechapter["course_id"], current_user, "delete") await verify_rights(request, coursechapter["course_id"], current_user, "delete")
isDeleted = coursechapters.delete_one( isDeleted = coursechapters.delete_one(
{"coursechapter_id": coursechapter_id}) {"coursechapter_id": coursechapter_id})
@ -147,9 +142,8 @@ async def delete_coursechapter(coursechapter_id: str, current_user: PublicUser)
#################################################### ####################################################
async def get_coursechapters(course_id: str, page: int = 1, limit: int = 10): async def get_coursechapters(request: Request,course_id: str, page: int = 1, limit: int = 10):
await check_database() courses = request.app.db["coursechapters"]
courses = learnhouseDB["coursechapters"]
# TODO : Get only courses that user is admin/has roles of # TODO : Get only courses that user is admin/has roles of
# get all courses from database # get all courses from database
all_coursechapters = courses.find({"course_id": course_id}).sort( all_coursechapters = courses.find({"course_id": course_id}).sort(
@ -158,11 +152,10 @@ async def get_coursechapters(course_id: str, page: int = 1, limit: int = 10):
return [json.loads(json.dumps(coursechapter, default=str)) for coursechapter in all_coursechapters] return [json.loads(json.dumps(coursechapter, default=str)) for coursechapter in all_coursechapters]
async def get_coursechapters_meta(course_id: str, current_user: PublicUser): async def get_coursechapters_meta(request: Request,course_id: str, current_user: PublicUser):
await check_database() coursechapters = request.app.db["coursechapters"]
coursechapters = learnhouseDB["coursechapters"] courses = request.app.db["courses"]
courses = learnhouseDB["courses"] lectures = request.app.db["lectures"]
elements = learnhouseDB["elements"]
coursechapters = coursechapters.find( coursechapters = coursechapters.find(
{"course_id": course_id}).sort("name", 1) {"course_id": course_id}).sort("name", 1)
@ -170,63 +163,61 @@ async def get_coursechapters_meta(course_id: str, current_user: PublicUser):
course = courses.find_one({"course_id": course_id}) course = courses.find_one({"course_id": course_id})
course = Course(**course) # type: ignore course = Course(**course) # type: ignore
# elements # lectures
coursechapter_elementIds_global = [] coursechapter_lectureIds_global = []
# chapters # chapters
chapters = {} chapters = {}
for coursechapter in coursechapters: for coursechapter in coursechapters:
coursechapter = CourseChapterInDB(**coursechapter) coursechapter = CourseChapterInDB(**coursechapter)
coursechapter_elementIds = [] coursechapter_lectureIds = []
for element in coursechapter.elements: for lecture in coursechapter.lectures:
coursechapter_elementIds.append(element) coursechapter_lectureIds.append(lecture)
coursechapter_elementIds_global.append(element) coursechapter_lectureIds_global.append(lecture)
chapters[coursechapter.coursechapter_id] = { chapters[coursechapter.coursechapter_id] = {
"id": coursechapter.coursechapter_id, "name": coursechapter.name, "elementIds": coursechapter_elementIds "id": coursechapter.coursechapter_id, "name": coursechapter.name, "lectureIds": coursechapter_lectureIds
} }
# elements # lectures
elements_list = {} lectures_list = {}
for element in elements.find({"element_id": {"$in": coursechapter_elementIds_global}}): for lecture in lectures.find({"lecture_id": {"$in": coursechapter_lectureIds_global}}):
element = ElementInDB(**element) lecture = LectureInDB(**lecture)
elements_list[element.element_id] = { lectures_list[lecture.lecture_id] = {
"id": element.element_id, "name": element.name, "type": element.type, "content": element.content "id": lecture.lecture_id, "name": lecture.name, "type": lecture.type, "content": lecture.content
} }
final = { final = {
"chapters": chapters, "chapters": chapters,
"chapterOrder": course.chapters, "chapterOrder": course.chapters,
"elements": elements_list "lectures": lectures_list
} }
return final return final
async def update_coursechapters_meta(course_id: str, coursechapters_metadata: CourseChapterMetaData, current_user: PublicUser): async def update_coursechapters_meta(request: Request,course_id: str, coursechapters_metadata: CourseChapterMetaData, current_user: PublicUser):
await check_database() coursechapters = request.app.db["coursechapters"]
coursechapters = learnhouseDB["coursechapters"] courses = request.app.db["courses"]
courses = learnhouseDB["courses"]
# update chapters in course # update chapters in course
courseInDB = courses.update_one({"course_id": course_id}, { courseInDB = courses.update_one({"course_id": course_id}, {
"$set": {"chapters": coursechapters_metadata.chapterOrder}}) "$set": {"chapters": coursechapters_metadata.chapterOrder}})
# update elements in coursechapters # update lectures in coursechapters
# TODO : performance/optimization improvement # TODO : performance/optimization improvement
for coursechapter in coursechapters_metadata.chapters.__dict__.items(): for coursechapter in coursechapters_metadata.chapters.__dict__.items():
coursechapters.update_one({"coursechapter_id": coursechapter}, { coursechapters.update_one({"coursechapter_id": coursechapter}, {
"$set": {"elements": coursechapters_metadata.chapters[coursechapter]["elementIds"]}}) "$set": {"lectures": coursechapters_metadata.chapters[coursechapter]["lectureIds"]}}) # type: ignore
return {"detail": "coursechapters metadata updated"} return {"detail": "coursechapters metadata updated"}
#### Security #################################################### #### Security ####################################################
async def verify_rights(course_id: str, current_user: PublicUser, action: str): async def verify_rights(request: Request,course_id: str, current_user: PublicUser, action: str):
await check_database() courses = request.app.db["courses"]
courses = learnhouseDB["courses"]
course = courses.find_one({"course_id": course_id}) course = courses.find_one({"course_id": course_id})
@ -234,7 +225,7 @@ async def verify_rights(course_id: str, current_user: PublicUser, action: str):
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail=f"Course does not exist") status_code=status.HTTP_409_CONFLICT, detail=f"Course does not exist")
hasRoleRights = await verify_user_rights_with_roles(action, current_user.user_id, course_id) hasRoleRights = await verify_user_rights_with_roles(request, action, current_user.user_id, course_id)
isAuthor = current_user.user_id in course["authors"] isAuthor = current_user.user_id in course["authors"]
if not hasRoleRights and not isAuthor: if not hasRoleRights and not isAuthor:

View file

@ -3,7 +3,6 @@ from typing import List
from uuid import uuid4 from uuid import uuid4
from pydantic import BaseModel from pydantic import BaseModel
from src.services.users import PublicUser, User from src.services.users import PublicUser, User
from src.services.database import create_config_collection, check_database, create_database, learnhouseDB, learnhouseDB
from src.services.security import * from src.services.security import *
from fastapi import FastAPI, HTTPException, status, Request, Response, BackgroundTasks from fastapi import FastAPI, HTTPException, status, Request, Response, BackgroundTasks
from datetime import datetime from datetime import datetime
@ -28,14 +27,13 @@ class CollectionInDB(Collection):
# CRUD # CRUD
#################################################### ####################################################
async def get_collection(collection_id: str, current_user: PublicUser): async def get_collection(request: Request,collection_id: str, current_user: PublicUser):
await check_database() collections = request.app.db["collections"]
collections = learnhouseDB["collections"]
collection = collections.find_one({"collection_id": collection_id}) collection = collections.find_one({"collection_id": collection_id})
# verify collection rights # verify collection rights
await verify_collection_rights(collection_id, current_user, "read") await verify_collection_rights(request, collection_id, current_user, "read")
if not collection: if not collection:
raise HTTPException( raise HTTPException(
@ -45,9 +43,8 @@ async def get_collection(collection_id: str, current_user: PublicUser):
return collection return collection
async def create_collection(collection_object: Collection, current_user: PublicUser): async def create_collection(request: Request,collection_object: Collection, current_user: PublicUser):
await check_database() collections = request.app.db["collections"]
collections = learnhouseDB["collections"]
# find if collection already exists using name # find if collection already exists using name
isCollectionNameAvailable = collections.find_one( isCollectionNameAvailable = collections.find_one(
@ -75,13 +72,12 @@ async def create_collection(collection_object: Collection, current_user: PublicU
return collection.dict() return collection.dict()
async def update_collection(collection_object: Collection, collection_id: str, current_user: PublicUser): async def update_collection(request: Request,collection_object: Collection, collection_id: str, current_user: PublicUser):
await check_database()
# verify collection rights # verify collection rights
await verify_collection_rights(collection_id, current_user, "update") await verify_collection_rights(request, collection_id, current_user, "update")
collections = learnhouseDB["collections"] collections = request.app.db["collections"]
collection = collections.find_one({"collection_id": collection_id}) collection = collections.find_one({"collection_id": collection_id})
@ -98,12 +94,11 @@ async def update_collection(collection_object: Collection, collection_id: str, c
return Collection(**updated_collection.dict()) return Collection(**updated_collection.dict())
async def delete_collection(collection_id: str, current_user: PublicUser): async def delete_collection(request: Request,collection_id: str, current_user: PublicUser):
await check_database()
await verify_collection_rights(collection_id, current_user, "delete") await verify_collection_rights(request, collection_id, current_user, "delete")
collections = learnhouseDB["collections"] collections = request.app.db["collections"]
collection = collections.find_one({"collection_id": collection_id}) collection = collections.find_one({"collection_id": collection_id})
@ -124,10 +119,9 @@ async def delete_collection(collection_id: str, current_user: PublicUser):
#################################################### ####################################################
async def get_collections(page: int = 1, limit: int = 10): async def get_collections(request: Request,page: int = 1, limit: int = 10):
## TODO : auth ## TODO : auth
await check_database() collections = request.app.db["collections"]
collections = learnhouseDB["collections"]
# get all collections from database without ObjectId # get all collections from database without ObjectId
all_collections = collections.find({}).sort( all_collections = collections.find({}).sort(
@ -141,7 +135,7 @@ async def get_collections(page: int = 1, limit: int = 10):
collection_courses = [course for course in collection.courses] collection_courses = [course for course in collection.courses]
# add courses to collection # add courses to collection
courses = learnhouseDB["courses"] courses = request.app.db["courses"]
collection.courses = [] collection.courses = []
collection.courses = courses.find( collection.courses = courses.find(
{"course_id": {"$in": collection_courses}}, {'_id': 0}) {"course_id": {"$in": collection_courses}}, {'_id': 0})
@ -153,9 +147,8 @@ async def get_collections(page: int = 1, limit: int = 10):
#### Security #################################################### #### Security ####################################################
async def verify_collection_rights(collection_id: str, current_user: PublicUser, action: str): async def verify_collection_rights(request: Request,collection_id: str, current_user: PublicUser, action: str):
await check_database() collections = request.app.db["collections"]
collections = learnhouseDB["collections"]
collection = collections.find_one({"collection_id": collection_id}) collection = collections.find_one({"collection_id": collection_id})
@ -163,7 +156,7 @@ async def verify_collection_rights(collection_id: str, current_user: PublicUser
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Collection does not exist") status_code=status.HTTP_409_CONFLICT, detail="Collection does not exist")
hasRoleRights = await verify_user_rights_with_roles(action, current_user.user_id, collection_id) hasRoleRights = await verify_user_rights_with_roles(request, action, current_user.user_id, collection_id)
if not hasRoleRights: if not hasRoleRights:
raise HTTPException( raise HTTPException(

View file

@ -2,10 +2,9 @@ import json
from typing import List from typing import List
from uuid import uuid4 from uuid import uuid4
from pydantic import BaseModel from pydantic import BaseModel
from src.services.courses.elements.elements import ElementInDB from src.services.courses.lectures.lectures import LectureInDB
from src.services.courses.thumbnails import upload_thumbnail from src.services.courses.thumbnails import upload_thumbnail
from src.services.users import PublicUser from src.services.users import PublicUser
from src.services.database import check_database, learnhouseDB
from src.services.security import * from src.services.security import *
from fastapi import HTTPException, status, UploadFile from fastapi import HTTPException, status, UploadFile
from datetime import datetime from datetime import datetime
@ -36,7 +35,7 @@ class CourseInDB(Course):
class CourseChapter(BaseModel): class CourseChapter(BaseModel):
name: str name: str
description: str description: str
elements: list lectures: list
class CourseChapterInDB(CourseChapter): class CourseChapterInDB(CourseChapter):
@ -54,14 +53,13 @@ class CourseChapterInDB(CourseChapter):
# CRUD # CRUD
#################################################### ####################################################
async def get_course(course_id: str, current_user: PublicUser): async def get_course(request: Request,course_id: str, current_user: PublicUser):
await check_database() courses = request.app.db["courses"]
courses = learnhouseDB["courses"]
course = courses.find_one({"course_id": course_id}) course = courses.find_one({"course_id": course_id})
# verify course rights # verify course rights
await verify_rights(course_id, current_user, "read") await verify_rights(request,course_id, current_user, "read")
if not course: if not course:
raise HTTPException( raise HTTPException(
@ -71,15 +69,14 @@ async def get_course(course_id: str, current_user: PublicUser):
return course return course
async def get_course_meta(course_id: str, current_user: PublicUser): async def get_course_meta(request: Request,course_id: str, current_user: PublicUser):
await check_database() courses = request.app.db["courses"]
courses = learnhouseDB["courses"] coursechapters = request.app.db["coursechapters"]
coursechapters = learnhouseDB["coursechapters"]
course = courses.find_one({"course_id": course_id}) course = courses.find_one({"course_id": course_id})
elements = learnhouseDB["elements"] lectures = request.app.db["lectures"]
# verify course rights # verify course rights
await verify_rights(course_id, current_user, "read") await verify_rights(request,course_id, current_user, "read")
if not course: if not course:
raise HTTPException( raise HTTPException(
@ -88,52 +85,51 @@ async def get_course_meta(course_id: str, current_user: PublicUser):
coursechapters = coursechapters.find( coursechapters = coursechapters.find(
{"course_id": course_id}).sort("name", 1) {"course_id": course_id}).sort("name", 1)
# elements # lectures
coursechapter_elementIds_global = [] coursechapter_lectureIds_global = []
# chapters # chapters
chapters = {} chapters = {}
for coursechapter in coursechapters: for coursechapter in coursechapters:
coursechapter = CourseChapterInDB(**coursechapter) coursechapter = CourseChapterInDB(**coursechapter)
coursechapter_elementIds = [] coursechapter_lectureIds = []
for element in coursechapter.elements: for lecture in coursechapter.lectures:
coursechapter_elementIds.append(element) coursechapter_lectureIds.append(lecture)
coursechapter_elementIds_global.append(element) coursechapter_lectureIds_global.append(lecture)
chapters[coursechapter.coursechapter_id] = { chapters[coursechapter.coursechapter_id] = {
"id": coursechapter.coursechapter_id, "name": coursechapter.name, "elementIds": coursechapter_elementIds "id": coursechapter.coursechapter_id, "name": coursechapter.name, "lectureIds": coursechapter_lectureIds
} }
# elements # lectures
elements_list = {} lectures_list = {}
for element in elements.find({"element_id": {"$in": coursechapter_elementIds_global}}): for lecture in lectures.find({"lecture_id": {"$in": coursechapter_lectureIds_global}}):
element = ElementInDB(**element) lecture = LectureInDB(**lecture)
elements_list[element.element_id] = { lectures_list[lecture.lecture_id] = {
"id": element.element_id, "name": element.name, "type": element.type, "content": element.content "id": lecture.lecture_id, "name": lecture.name, "type": lecture.type, "content": lecture.content
} }
chapters_list_with_elements = [] chapters_list_with_lectures = []
for chapter in chapters: for chapter in chapters:
chapters_list_with_elements.append( chapters_list_with_lectures.append(
{"id": chapters[chapter]["id"], "name": chapters[chapter]["name"], "elements": [elements_list[element] for element in chapters[chapter]["elementIds"]]}) {"id": chapters[chapter]["id"], "name": chapters[chapter]["name"], "lectures": [lectures_list[lecture] for lecture in chapters[chapter]["lectureIds"]]})
course = Course(**course) course = Course(**course)
return { return {
"course": course, "course": course,
"chapters": chapters_list_with_elements, "chapters": chapters_list_with_lectures,
} }
async def create_course(course_object: Course, org_id: str, current_user: PublicUser, thumbnail_file: UploadFile | None = None): async def create_course(request: Request,course_object: Course, org_id: str, current_user: PublicUser, thumbnail_file: UploadFile | None = None):
await check_database() courses = request.app.db["courses"]
courses = learnhouseDB["courses"]
# generate course_id with uuid4 # generate course_id with uuid4
course_id = str(f"course_{uuid4()}") course_id = str(f"course_{uuid4()}")
# TODO(fix) : the implementation here is clearly not the best one (this entire function) # TODO(fix) : the implementation here is clearly not the best one (this entire function)
course_object.org_id = org_id course_object.org_id = org_id
hasRoleRights = await verify_user_rights_with_roles("create", current_user.user_id, course_id) hasRoleRights = await verify_user_rights_with_roles(request, "create", current_user.user_id, course_id)
if not hasRoleRights: if not hasRoleRights:
raise HTTPException( raise HTTPException(
@ -156,13 +152,12 @@ async def create_course(course_object: Course, org_id: str, current_user: Public
return course.dict() return course.dict()
async def update_course_thumbnail(course_id: str, current_user: PublicUser, thumbnail_file: UploadFile | None = None): async def update_course_thumbnail(request: Request,course_id: str, current_user: PublicUser, thumbnail_file: UploadFile | None = None):
await check_database()
# verify course rights # verify course rights
await verify_rights(course_id, current_user, "update") await verify_rights(request, course_id, current_user, "update")
courses = learnhouseDB["courses"] courses = request.app.db["courses"]
course = courses.find_one({"course_id": course_id}) course = courses.find_one({"course_id": course_id})
# TODO(fix) : the implementation here is clearly not the best one # TODO(fix) : the implementation here is clearly not the best one
@ -187,13 +182,12 @@ async def update_course_thumbnail(course_id: str, current_user: PublicUser, thum
status_code=status.HTTP_409_CONFLICT, detail="Course does not exist") status_code=status.HTTP_409_CONFLICT, detail="Course does not exist")
async def update_course(course_object: Course, course_id: str, current_user: PublicUser): async def update_course(request: Request,course_object: Course, course_id: str, current_user: PublicUser):
await check_database()
# verify course rights # verify course rights
await verify_rights(course_id, current_user, "update") await verify_rights(request, course_id, current_user, "update")
courses = learnhouseDB["courses"] courses = request.app.db["courses"]
course = courses.find_one({"course_id": course_id}) course = courses.find_one({"course_id": course_id})
@ -217,13 +211,12 @@ async def update_course(course_object: Course, course_id: str, current_user: Pub
status_code=status.HTTP_409_CONFLICT, detail="Course does not exist") status_code=status.HTTP_409_CONFLICT, detail="Course does not exist")
async def delete_course(course_id: str, current_user: PublicUser): async def delete_course(request: Request,course_id: str, current_user: PublicUser):
await check_database()
# verify course rights # verify course rights
await verify_rights(course_id, current_user, "delete") await verify_rights(request, course_id, current_user, "delete")
courses = learnhouseDB["courses"] courses = request.app.db["courses"]
course = courses.find_one({"course_id": course_id}) course = courses.find_one({"course_id": course_id})
@ -244,9 +237,8 @@ async def delete_course(course_id: str, current_user: PublicUser):
#################################################### ####################################################
async def get_courses(page: int = 1, limit: int = 10, org_id: str | None = None): async def get_courses(request: Request,page: int = 1, limit: int = 10, org_id: str | None = None):
await check_database() courses = request.app.db["courses"]
courses = learnhouseDB["courses"]
# TODO : Get only courses that user is admin/has roles of # TODO : Get only courses that user is admin/has roles of
# get all courses from database # get all courses from database
all_courses = courses.find({"org_id": org_id}).sort( all_courses = courses.find({"org_id": org_id}).sort(
@ -258,9 +250,8 @@ async def get_courses(page: int = 1, limit: int = 10, org_id: str | None = None)
#### Security #################################################### #### Security ####################################################
async def verify_rights(course_id: str, current_user: PublicUser, action: str): async def verify_rights(request: Request,course_id: str, current_user: PublicUser, action: str):
await check_database() courses = request.app.db["courses"]
courses = learnhouseDB["courses"]
course = courses.find_one({"course_id": course_id}) course = courses.find_one({"course_id": course_id})
@ -268,7 +259,7 @@ async def verify_rights(course_id: str, current_user: PublicUser, action: str):
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail=f"Course/CourseChapter does not exist") status_code=status.HTTP_409_CONFLICT, detail=f"Course/CourseChapter does not exist")
hasRoleRights = await verify_user_rights_with_roles(action, current_user.user_id, course_id) hasRoleRights = await verify_user_rights_with_roles(request, action, current_user.user_id, course_id)
isAuthor = current_user.user_id in course["authors"] isAuthor = current_user.user_id in course["authors"]
if not hasRoleRights and not isAuthor: if not hasRoleRights and not isAuthor:

View file

@ -1,153 +0,0 @@
from pydantic import BaseModel
from src.services.database import create_config_collection, check_database, create_database, learnhouseDB
from src.services.security import verify_user_rights_with_roles
from src.services.users import PublicUser, User
from fastapi import FastAPI, HTTPException, status, Request, Response, BackgroundTasks, UploadFile, File
from uuid import uuid4
from datetime import datetime
#### Classes ####################################################
class Element(BaseModel):
name: str
type: str
content: object
class ElementInDB(Element):
element_id: str
coursechapter_id: str
creationDate: str
updateDate: str
#### Classes ####################################################
####################################################
# CRUD
####################################################
async def create_element(element_object: Element, coursechapter_id: str, current_user: PublicUser):
await check_database()
elements = learnhouseDB["elements"]
coursechapters = learnhouseDB["coursechapters"]
# generate element_id
element_id = str(f"element_{uuid4()}")
hasRoleRights = await verify_user_rights_with_roles("create", current_user.user_id, element_id)
if not hasRoleRights:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Roles : Insufficient rights to perform this action")
# create element
element = ElementInDB(**element_object.dict(), creationDate=str(
datetime.now()), coursechapter_id=coursechapter_id, updateDate=str(datetime.now()), element_id=element_id)
elements.insert_one(element.dict())
# update chapter
coursechapters.update_one({"coursechapter_id": coursechapter_id}, {
"$addToSet": {"elements": element_id}})
return element
async def get_element(element_id: str, current_user: PublicUser):
await check_database()
elements = learnhouseDB["elements"]
element = elements.find_one({"element_id": element_id})
# verify course rights
hasRoleRights = await verify_user_rights_with_roles("read", current_user.user_id, element_id)
if not hasRoleRights:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Roles : Insufficient rights to perform this action")
if not element:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Course does not exist")
element = ElementInDB(**element)
return element
async def update_element(element_object: Element, element_id: str, current_user: PublicUser):
await check_database()
# verify course rights
await verify_user_rights_with_roles("update", current_user.user_id, element_id)
elements = learnhouseDB["elements"]
element = elements.find_one({"element_id": element_id})
if element:
creationDate = element["creationDate"]
# get today's date
datetime_object = datetime.now()
updated_course = ElementInDB(
element_id=element_id, coursechapter_id=element["coursechapter_id"], creationDate=creationDate, updateDate=str(datetime_object), **element_object.dict())
elements.update_one({"element_id": element_id}, {
"$set": updated_course.dict()})
return ElementInDB(**updated_course.dict())
else:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Element does not exist")
async def delete_element(element_id: str, current_user: PublicUser):
await check_database()
# verify course rights
await verify_user_rights_with_roles("delete", current_user.user_id, element_id)
elements = learnhouseDB["elements"]
element = elements.find_one({"element_id": element_id})
if not element:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Element does not exist")
isDeleted = elements.delete_one({"element_id": element_id})
if isDeleted:
return {"detail": "Element deleted"}
else:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Unavailable database")
####################################################
# Misc
####################################################
async def get_elements(coursechapter_id: str, current_user: PublicUser):
await check_database()
elements = learnhouseDB["elements"]
# verify course rights
await verify_user_rights_with_roles("read", current_user.user_id, coursechapter_id)
elements = elements.find({"coursechapter_id": coursechapter_id})
if not elements:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="No elements found")
elements_list = []
for element in elements:
elements_list.append(Element(**element))
return elements_list

View file

@ -0,0 +1,147 @@
from pydantic import BaseModel
from src.services.security import verify_user_rights_with_roles
from src.services.users import PublicUser, User
from fastapi import FastAPI, HTTPException, status, Request, Response, BackgroundTasks, UploadFile, File
from uuid import uuid4
from datetime import datetime
#### Classes ####################################################
class Lecture(BaseModel):
name: str
type: str
content: object
class LectureInDB(Lecture):
lecture_id: str
coursechapter_id: str
creationDate: str
updateDate: str
#### Classes ####################################################
####################################################
# CRUD
####################################################
async def create_lecture(request: Request,lecture_object: Lecture, coursechapter_id: str, current_user: PublicUser):
lectures = request.app.db["lectures"]
coursechapters = request.app.db["coursechapters"]
# generate lecture_id
lecture_id = str(f"lecture_{uuid4()}")
hasRoleRights = await verify_user_rights_with_roles(request, "create", current_user.user_id, lecture_id)
if not hasRoleRights:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Roles : Insufficient rights to perform this action")
# create lecture
lecture = LectureInDB(**lecture_object.dict(), creationDate=str(
datetime.now()), coursechapter_id=coursechapter_id, updateDate=str(datetime.now()), lecture_id=lecture_id)
lectures.insert_one(lecture.dict())
# update chapter
coursechapters.update_one({"coursechapter_id": coursechapter_id}, {
"$addToSet": {"lectures": lecture_id}})
return lecture
async def get_lecture(request: Request,lecture_id: str, current_user: PublicUser):
lectures = request.app.db["lectures"]
lecture = lectures.find_one({"lecture_id": lecture_id})
# verify course rights
hasRoleRights = await verify_user_rights_with_roles(request,"read", current_user.user_id, lecture_id)
if not hasRoleRights:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Roles : Insufficient rights to perform this action")
if not lecture:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Course does not exist")
lecture = LectureInDB(**lecture)
return lecture
async def update_lecture(request: Request,lecture_object: Lecture, lecture_id: str, current_user: PublicUser):
# verify course rights
await verify_user_rights_with_roles(request, "update", current_user.user_id, lecture_id)
lectures = request.app.db["lectures"]
lecture = lectures.find_one({"lecture_id": lecture_id})
if lecture:
creationDate = lecture["creationDate"]
# get today's date
datetime_object = datetime.now()
updated_course = LectureInDB(
lecture_id=lecture_id, coursechapter_id=lecture["coursechapter_id"], creationDate=creationDate, updateDate=str(datetime_object), **lecture_object.dict())
lectures.update_one({"lecture_id": lecture_id}, {
"$set": updated_course.dict()})
return LectureInDB(**updated_course.dict())
else:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="lecture does not exist")
async def delete_lecture(request: Request,lecture_id: str, current_user: PublicUser):
# verify course rights
await verify_user_rights_with_roles(request,"delete", current_user.user_id, lecture_id)
lectures = request.app.db["lectures"]
lecture = lectures.find_one({"lecture_id": lecture_id})
if not lecture:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="lecture does not exist")
isDeleted = lectures.delete_one({"lecture_id": lecture_id})
if isDeleted:
return {"detail": "lecture deleted"}
else:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Unavailable database")
####################################################
# Misc
####################################################
async def get_lectures(request: Request,coursechapter_id: str, current_user: PublicUser):
lectures = request.app.db["lectures"]
# verify course rights
await verify_user_rights_with_roles(request,"read", current_user.user_id, coursechapter_id)
lectures = lectures.find({"coursechapter_id": coursechapter_id})
if not lectures:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="No lectures found")
lectures_list = []
for lecture in lectures:
lectures_list.append(Lecture(**lecture))
return lectures_list

View file

@ -1,14 +1,14 @@
import os import os
async def upload_video(video_file, element_id): async def upload_video(video_file, lecture_id):
contents = video_file.file.read() contents = video_file.file.read()
video_format = video_file.filename.split(".")[-1] video_format = video_file.filename.split(".")[-1]
# create folder # create folder
os.mkdir(f"content/uploads/video/{element_id}") os.mkdir(f"content/uploads/video/{lecture_id}")
try: try:
with open(f"content/uploads/video/{element_id}/video.{video_format}", 'wb') as f: with open(f"content/uploads/video/{lecture_id}/video.{video_format}", 'wb') as f:
f.write(contents) f.write(contents)
f.close() f.close()

View file

@ -1,21 +1,19 @@
from pydantic import BaseModel from pydantic import BaseModel
from src.services.database import check_database, learnhouseDB
from src.services.security import verify_user_rights_with_roles from src.services.security import verify_user_rights_with_roles
from src.services.courses.elements.uploads.videos import upload_video from src.services.courses.lectures.uploads.videos import upload_video
from src.services.users import PublicUser from src.services.users import PublicUser
from src.services.courses.elements.elements import ElementInDB from src.services.courses.lectures.lectures import LectureInDB
from fastapi import HTTPException, status, UploadFile from fastapi import HTTPException, status, UploadFile, Request
from uuid import uuid4 from uuid import uuid4
from datetime import datetime from datetime import datetime
async def create_video_element(name: str, coursechapter_id: str, current_user: PublicUser, video_file: UploadFile | None = None): async def create_video_lecture(request: Request,name: str, coursechapter_id: str, current_user: PublicUser, video_file: UploadFile | None = None):
await check_database() lectures = request.app.db["lectures"]
elements = learnhouseDB["elements"] coursechapters = request.app.db["coursechapters"]
coursechapters = learnhouseDB["coursechapters"]
# generate element_id # generate lecture_id
element_id = str(f"element_{uuid4()}") lecture_id = str(f"lecture_{uuid4()}")
# check if video_file is not None # check if video_file is not None
if not video_file: if not video_file:
@ -23,41 +21,41 @@ async def create_video_element(name: str, coursechapter_id: str, current_user:
status_code=status.HTTP_409_CONFLICT, detail="Video : No video file provided") status_code=status.HTTP_409_CONFLICT, detail="Video : No video file provided")
video_format = video_file.filename.split(".")[-1] video_format = video_file.filename.split(".")[-1]
element_object = ElementInDB( lecture_object = LectureInDB(
element_id=element_id, lecture_id=lecture_id,
coursechapter_id=coursechapter_id, coursechapter_id=coursechapter_id,
name=name, name=name,
type="video", type="video",
content={ content={
"video": { "video": {
"filename": "video."+video_format, "filename": "video."+video_format,
"element_id": element_id, "lecture_id": lecture_id,
} }
}, },
creationDate=str(datetime.now()), creationDate=str(datetime.now()),
updateDate=str(datetime.now()), updateDate=str(datetime.now()),
) )
hasRoleRights = await verify_user_rights_with_roles("create", current_user.user_id, element_id) hasRoleRights = await verify_user_rights_with_roles(request,"create", current_user.user_id, lecture_id)
if not hasRoleRights: if not hasRoleRights:
raise HTTPException( 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 element # create lecture
element = ElementInDB(**element_object.dict()) lecture = LectureInDB(**lecture_object.dict())
elements.insert_one(element.dict()) lectures.insert_one(lecture.dict())
# upload video # upload video
if video_file: if video_file:
print("uploading video") print("uploading video")
# get videofile format # get videofile format
await upload_video(video_file, element_id) await upload_video(video_file, lecture_id)
# todo : choose whether to update the chapter or not # todo : choose whether to update the chapter or not
# update chapter # update chapter
coursechapters.update_one({"coursechapter_id": coursechapter_id}, { coursechapters.update_one({"coursechapter_id": coursechapter_id}, {
"$addToSet": {"elements": element_id}}) "$addToSet": {"lectures": lecture_id}})
return element return lecture

View file

@ -1,27 +0,0 @@
import pymongo
# MongoDB
client = pymongo.MongoClient("mongodb://learnhouse:learnhouse@mongo:27017/") # type: ignore
learnhouseDB = client["learnhouse"]
async def create_database():
learnhouseDB = client["learnhouse"]
async def check_database():
# Check if database learnhouse exists
if "learnhouse" in client.list_database_names():
return True
else:
await create_database()
async def create_config_collection():
# Create config collection if it doesn't exist
learnhouseDB = client["learnhouse"]
config = learnhouseDB["config"]
config.insert_one({"name": "LearnHouse", "date": "2022"})
return config.find_one()

View file

@ -1,7 +1,6 @@
from uuid import uuid4 from uuid import uuid4
from pydantic import BaseModel from pydantic import BaseModel
from src.services.database import check_database, learnhouseDB, learnhouseDB from fastapi import HTTPException, status, UploadFile, Request
from fastapi import HTTPException, status, UploadFile
from fastapi.responses import StreamingResponse from fastapi.responses import StreamingResponse
import os import os
@ -14,12 +13,11 @@ class PhotoFile(BaseModel):
file_name: str file_name: str
file_size: int file_size: int
file_type: str file_type: str
element_id: str lecture_id: str
async def create_picture_file(picture_file: UploadFile, element_id: str): async def create_picture_file(request: Request,picture_file: UploadFile, lecture_id: str):
await check_database() photos = request.app.db["files"]
photos = learnhouseDB["files"]
# generate file_id # generate file_id
file_id = str(f"file_{uuid4()}") file_id = str(f"file_{uuid4()}")
@ -51,15 +49,15 @@ async def create_picture_file(picture_file: UploadFile, element_id: str):
file_name=file_name, file_name=file_name,
file_size=file_size, file_size=file_size,
file_type=file_type, file_type=file_type,
element_id=element_id lecture_id=lecture_id
) )
# create folder for element # create folder for lecture
if not os.path.exists(f"content/uploads/files/pictures/{element_id}"): if not os.path.exists(f"content/uploads/files/pictures/{lecture_id}"):
os.mkdir(f"content/uploads/files/pictures/{element_id}") os.mkdir(f"content/uploads/files/pictures/{lecture_id}")
# upload file to server # upload file to server
with open(f"content/uploads/files/pictures/{element_id}/{file_id}.{file_format}", 'wb') as f: with open(f"content/uploads/files/pictures/{lecture_id}/{file_id}.{file_format}", 'wb') as f:
f.write(file) f.write(file)
f.close() f.close()
@ -73,9 +71,8 @@ async def create_picture_file(picture_file: UploadFile, element_id: str):
return uploadable_file return uploadable_file
async def get_picture_object(file_id: str): async def get_picture_object(request: Request,file_id: str):
await check_database() photos = request.app.db["files"]
photos = learnhouseDB["files"]
photo_file = photos.find_one({"file_id": file_id}) photo_file = photos.find_one({"file_id": file_id})
@ -88,9 +85,8 @@ async def get_picture_object(file_id: str):
status_code=status.HTTP_409_CONFLICT, detail="Photo file does not exist") status_code=status.HTTP_409_CONFLICT, detail="Photo file does not exist")
async def get_picture_file(file_id: str, current_user: PublicUser): async def get_picture_file(request: Request,file_id: str, current_user: PublicUser):
await check_database() photos = request.app.db["files"]
photos = learnhouseDB["files"]
photo_file = photos.find_one({"file_id": file_id}) photo_file = photos.find_one({"file_id": file_id})
@ -106,9 +102,9 @@ async def get_picture_file(file_id: str, current_user: PublicUser):
# stream file # stream file
photo_file = PhotoFile(**photo_file) photo_file = PhotoFile(**photo_file)
file_format = photo_file.file_format file_format = photo_file.file_format
element_id = photo_file.element_id lecture_id = photo_file.lecture_id
file = open( file = open(
f"content/uploads/files/pictures/{element_id}/{file_id}.{file_format}", 'rb') f"content/uploads/files/pictures/{lecture_id}/{file_id}.{file_format}", 'rb')
return StreamingResponse(file, media_type=photo_file.file_type) return StreamingResponse(file, media_type=photo_file.file_type)
else: else:

View file

@ -1,8 +1,7 @@
from uuid import uuid4 from uuid import uuid4
from pydantic import BaseModel from pydantic import BaseModel
import os import os
from src.services.database import check_database, learnhouseDB, learnhouseDB from fastapi import HTTPException, status, UploadFile,Request
from fastapi import HTTPException, status, UploadFile
from fastapi.responses import StreamingResponse from fastapi.responses import StreamingResponse
from src.services.users import PublicUser from src.services.users import PublicUser
@ -14,12 +13,11 @@ class VideoFile(BaseModel):
file_name: str file_name: str
file_size: int file_size: int
file_type: str file_type: str
element_id: str lecture_id: str
async def create_video_file(video_file: UploadFile, element_id: str): async def create_video_file(request: Request,video_file: UploadFile, lecture_id: str):
await check_database() files = request.app.db["files"]
files = learnhouseDB["files"]
# generate file_id # generate file_id
file_id = str(f"file_{uuid4()}") file_id = str(f"file_{uuid4()}")
@ -51,15 +49,15 @@ async def create_video_file(video_file: UploadFile, element_id: str):
file_name=file_name, file_name=file_name,
file_size=file_size, file_size=file_size,
file_type=file_type, file_type=file_type,
element_id=element_id lecture_id=lecture_id
) )
# create folder for element # create folder for lecture
if not os.path.exists(f"content/uploads/files/videos/{element_id}"): if not os.path.exists(f"content/uploads/files/videos/{lecture_id}"):
os.mkdir(f"content/uploads/files/videos/{element_id}") os.mkdir(f"content/uploads/files/videos/{lecture_id}")
# upload file to server # upload file to server
with open(f"content/uploads/files/videos/{element_id}/{file_id}.{file_format}", 'wb') as f: with open(f"content/uploads/files/videos/{lecture_id}/{file_id}.{file_format}", 'wb') as f:
f.write(file) f.write(file)
f.close() f.close()
@ -73,9 +71,8 @@ async def create_video_file(video_file: UploadFile, element_id: str):
return uploadable_file return uploadable_file
async def get_video_object(file_id: str, current_user: PublicUser): async def get_video_object(request: Request,file_id: str, current_user: PublicUser):
await check_database() photos = request.app.db["files"]
photos = learnhouseDB["files"]
video_file = photos.find_one({"file_id": file_id}) video_file = photos.find_one({"file_id": file_id})
@ -88,9 +85,8 @@ async def get_video_object(file_id: str, current_user: PublicUser):
status_code=status.HTTP_409_CONFLICT, detail="Photo file does not exist") status_code=status.HTTP_409_CONFLICT, detail="Photo file does not exist")
async def get_video_file(file_id: str, current_user: PublicUser): async def get_video_file(request: Request,file_id: str, current_user: PublicUser):
await check_database() photos = request.app.db["files"]
photos = learnhouseDB["files"]
video_file = photos.find_one({"file_id": file_id}) video_file = photos.find_one({"file_id": file_id})
@ -106,11 +102,11 @@ async def get_video_file(file_id: str, current_user: PublicUser):
# stream file # stream file
video_file = VideoFile(**video_file) video_file = VideoFile(**video_file)
file_format = video_file.file_format file_format = video_file.file_format
element_id = video_file.element_id lecture_id = video_file.lecture_id
def iterfile(): # def iterfile(): #
# #
with open(f"content/uploads/files/videos/{element_id}/{file_id}.{file_format}", mode="rb") as file_like: with open(f"content/uploads/files/videos/{lecture_id}/{file_id}.{file_format}", mode="rb") as file_like:
yield from file_like yield from file_like
return StreamingResponse(iterfile(), media_type=video_file.file_type) return StreamingResponse(iterfile(), media_type=video_file.file_type)

View file

@ -3,7 +3,6 @@ from typing import List
from uuid import uuid4 from uuid import uuid4
from pydantic import BaseModel from pydantic import BaseModel
from src.services.users import PublicUser, User from src.services.users import PublicUser, User
from src.services.database import create_config_collection, check_database, create_database, learnhouseDB, learnhouseDB
from src.services.security import * from src.services.security import *
from fastapi import FastAPI, HTTPException, status, Request, Response, BackgroundTasks from fastapi import FastAPI, HTTPException, status, Request, Response, BackgroundTasks
from datetime import datetime from datetime import datetime
@ -28,14 +27,13 @@ class HouseInDB(House):
# TODO : Add house photo upload and delete # TODO : Add house photo upload and delete
async def get_house(house_id: str, current_user: PublicUser): async def get_house(request: Request, house_id: str, current_user: PublicUser):
await check_database() houses = request.app.db["houses"]
houses = learnhouseDB["houses"]
house = houses.find_one({"house_id": house_id}) house = houses.find_one({"house_id": house_id})
# verify house rights # verify house rights
await verify_house_rights(house_id, current_user, "read") await verify_house_rights(request,house_id, current_user, "read")
if not house: if not house:
raise HTTPException( raise HTTPException(
@ -45,9 +43,8 @@ async def get_house(house_id: str, current_user: PublicUser):
return house return house
async def create_house(house_object: House, current_user: PublicUser): async def create_house(request: Request,house_object: House, current_user: PublicUser):
await check_database() houses = request.app.db["houses"]
houses = learnhouseDB["houses"]
# find if house already exists using name # find if house already exists using name
isHouseAvailable = houses.find_one({"name": house_object.name}) isHouseAvailable = houses.find_one({"name": house_object.name})
@ -59,7 +56,7 @@ async def create_house(house_object: House, current_user: PublicUser):
# generate house_id with uuid4 # generate house_id with uuid4
house_id = str(f"house_{uuid4()}") house_id = str(f"house_{uuid4()}")
hasRoleRights = await verify_user_rights_with_roles("create", current_user.user_id, house_id) hasRoleRights = await verify_user_rights_with_roles(request, "create", current_user.user_id, house_id)
if not hasRoleRights: if not hasRoleRights:
raise HTTPException( raise HTTPException(
@ -78,13 +75,12 @@ async def create_house(house_object: House, current_user: PublicUser):
return house.dict() return house.dict()
async def update_house(house_object: House, house_id: str, current_user: PublicUser): async def update_house(request: Request,house_object: House, house_id: str, current_user: PublicUser):
await check_database()
# verify house rights # verify house rights
await verify_house_rights(house_id, current_user, "update") await verify_house_rights(request,house_id, current_user, "update")
houses = learnhouseDB["houses"] houses = request.app.db["houses"]
house = houses.find_one({"house_id": house_id}) house = houses.find_one({"house_id": house_id})
@ -107,13 +103,12 @@ async def update_house(house_object: House, house_id: str, current_user: PublicU
async def delete_house(house_id: str, current_user: PublicUser): async def delete_house(request: Request,house_id: str, current_user: PublicUser):
await check_database()
# verify house rights # verify house rights
await verify_house_rights(house_id, current_user, "delete") await verify_house_rights(request,house_id, current_user, "delete")
houses = learnhouseDB["houses"] houses = request.app.db["houses"]
house = houses.find_one({"house_id": house_id}) house = houses.find_one({"house_id": house_id})
@ -130,9 +125,8 @@ async def delete_house(house_id: str, current_user: PublicUser):
status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Unavailable database") status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Unavailable database")
async def get_houses(page: int = 1, limit: int = 10): async def get_houses(request: Request,page: int = 1, limit: int = 10):
await check_database() houses = request.app.db["houses"]
houses = learnhouseDB["houses"]
# TODO : Get only houses that user is admin/has roles of # TODO : Get only houses that user is admin/has roles of
# get all houses from database # get all houses from database
all_houses = houses.find().sort("name", 1).skip(10 * (page - 1)).limit(limit) all_houses = houses.find().sort("name", 1).skip(10 * (page - 1)).limit(limit)
@ -142,9 +136,8 @@ async def get_houses(page: int = 1, limit: int = 10):
#### Security #################################################### #### Security ####################################################
async def verify_house_rights(house_id: str, current_user: PublicUser, action: str): async def verify_house_rights(request: Request,house_id: str, current_user: PublicUser, action: str):
await check_database() houses = request.app.db["houses"]
houses = learnhouseDB["houses"]
house = houses.find_one({"house_id": house_id}) house = houses.find_one({"house_id": house_id})
@ -152,7 +145,7 @@ async def verify_house_rights(house_id: str, current_user: PublicUser, action: s
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="House does not exist") status_code=status.HTTP_409_CONFLICT, detail="House does not exist")
hasRoleRights = await verify_user_rights_with_roles(action, current_user.user_id, house_id) hasRoleRights = await verify_user_rights_with_roles(request,action, current_user.user_id, house_id)
isOwner = current_user.user_id in house["owners"] isOwner = current_user.user_id in house["owners"]
if not hasRoleRights and not isOwner: if not hasRoleRights and not isOwner:

View file

@ -1,14 +1,14 @@
import requests
from datetime import datetime from datetime import datetime
from fileinput import filename from fileinput import filename
from pprint import pprint from pprint import pprint
from uuid import uuid4 from uuid import uuid4
import requests from fastapi import File, UploadFile, Request
from fastapi import File, UploadFile
from src.services.courses.chapters import CourseChapter, create_coursechapter from src.services.courses.chapters import CourseChapter, create_coursechapter
from src.services.courses.elements.elements import Element, create_element from src.services.courses.lectures.lectures import Lecture, create_lecture
from src.services.courses.thumbnails import upload_thumbnail from src.services.courses.thumbnails import upload_thumbnail
from src.services.users import PublicUser, User, UserInDB, UserWithPassword from src.services.users import PublicUser, User, UserInDB, UserWithPassword
from src.services.database import learnhouseDB
from src.services.orgs import OrganizationInDB, Organization, create_org from src.services.orgs import OrganizationInDB, Organization, create_org
from src.services.roles import Permission, Elements, create_role from src.services.roles import Permission, Elements, create_role
from src.services.users import create_user from src.services.users import create_user
@ -17,7 +17,7 @@ from src.services.roles import Role
from faker import Faker from faker import Faker
async def create_initial_data(): async def create_initial_data(request: Request):
fake = Faker(['en_US']) fake = Faker(['en_US'])
fake_multilang = Faker( fake_multilang = Faker(
['en_US', 'de_DE', 'ja_JP', 'es_ES', 'it_IT', 'pt_BR', 'ar_PS']) ['en_US', 'de_DE', 'ja_JP', 'es_ES', 'it_IT', 'pt_BR', 'ar_PS'])
@ -25,7 +25,7 @@ async def create_initial_data():
# Create users # Create users
######################################## ########################################
database_users = learnhouseDB["users"] database_users = request.app.db["users"]
database_users.delete_many({}) database_users.delete_many({})
users = [] users = []
@ -36,7 +36,7 @@ async def create_initial_data():
user_type="isOwner", user_type="isOwner",
) )
admin_user = await create_user(admin_user) admin_user = await create_user(request, admin_user)
for i in range(0, 20): for i in range(0, 20):
user = UserWithPassword( user = UserWithPassword(
@ -49,10 +49,10 @@ async def create_initial_data():
users.append(user) users.append(user)
for user in users: for user in users:
await create_user(user) await create_user(request, user)
# find admin user # find admin user
users = learnhouseDB["users"] users = request.app.db["users"]
admin_user = users.find_one({"username": "admin"}) admin_user = users.find_one({"username": "admin"})
if admin_user: if admin_user:
@ -64,7 +64,7 @@ async def create_initial_data():
# Create organizations # Create organizations
######################################## ########################################
database_orgs = learnhouseDB["organizations"] database_orgs = request.app.db["organizations"]
database_orgs.delete_many({}) database_orgs.delete_many({})
organizations = [] organizations = []
@ -79,12 +79,12 @@ async def create_initial_data():
slug=slug, slug=slug,
) )
organizations.append(org) organizations.append(org)
await create_org(org, current_user) await create_org(request, org, current_user)
# Create roles # Create roles
######################################## ########################################
database_roles = learnhouseDB["roles"] database_roles = request.app.db["roles"]
database_roles.delete_many({}) database_roles.delete_many({})
roles = [] roles = []
@ -104,24 +104,24 @@ async def create_initial_data():
collections=["*"], collections=["*"],
organizations=["*"], organizations=["*"],
coursechapters=["*"], coursechapters=["*"],
elements=["*"], lectures=["*"],
), ),
linked_users=[admin_user.user_id], linked_users=[admin_user.user_id],
) )
roles.append(admin_role) roles.append(admin_role)
await create_role(admin_role, current_user) await create_role(request, admin_role, current_user)
# Generate Courses and CourseChapters # Generate Courses and CourseChapters
######################################## ########################################
database_courses = learnhouseDB["courses"] database_courses = request.app.db["courses"]
database_chapters = learnhouseDB["coursechapters"] database_chapters = request.app.db["coursechapters"]
database_courses.delete_many({}) database_courses.delete_many({})
database_chapters.delete_many({}) database_chapters.delete_many({})
courses = [] courses = []
orgs = learnhouseDB["organizations"] orgs = request.app.db["organizations"]
if orgs.count_documents({}) > 0: if orgs.count_documents({}) > 0:
for org in orgs.find(): for org in orgs.find():
@ -150,7 +150,7 @@ async def create_initial_data():
authors=[current_user.user_id], authors=[current_user.user_id],
) )
courses = learnhouseDB["courses"] courses = request.app.db["courses"]
name_in_disk = f"test_mock{course_id}.jpeg" name_in_disk = f"test_mock{course_id}.jpeg"
image = requests.get( image = requests.get(
@ -168,16 +168,16 @@ async def create_initial_data():
coursechapter = CourseChapter( coursechapter = CourseChapter(
name=fake_multilang.unique.sentence(), name=fake_multilang.unique.sentence(),
description=fake_multilang.unique.text(), description=fake_multilang.unique.text(),
elements=[], lectures=[],
) )
coursechapter = await create_coursechapter(coursechapter, course_id, current_user) coursechapter = await create_coursechapter(request,coursechapter, course_id, current_user)
pprint(coursechapter) pprint(coursechapter)
if coursechapter: if coursechapter:
# create elements # create lectures
for i in range(0, 5): for i in range(0, 5):
element = Element( lecture = Lecture(
name=fake_multilang.unique.sentence(), name=fake_multilang.unique.sentence(),
type="dynamic", type="dynamic",
content={}, content={},
) )
element = await create_element(element, coursechapter['coursechapter_id'], current_user) lecture = await create_lecture(request,lecture, coursechapter['coursechapter_id'], current_user)

View file

@ -3,7 +3,6 @@ from typing import List
from uuid import uuid4 from uuid import uuid4
from pydantic import BaseModel from pydantic import BaseModel
from src.services.users import PublicUser, User from src.services.users import PublicUser, User
from src.services.database import create_config_collection, check_database, create_database, learnhouseDB, learnhouseDB
from src.services.security import * from src.services.security import *
from fastapi import FastAPI, HTTPException, status, Request, Response, BackgroundTasks from fastapi import FastAPI, HTTPException, status, Request, Response, BackgroundTasks
from datetime import datetime from datetime import datetime
@ -15,7 +14,7 @@ class Organization(BaseModel):
name: str name: str
description: str description: str
email: str email: str
slug :str slug: str
class OrganizationInDB(Organization): class OrganizationInDB(Organization):
@ -23,6 +22,7 @@ class OrganizationInDB(Organization):
owners: List[str] owners: List[str]
admins: List[str] admins: List[str]
class PublicOrganization(Organization): class PublicOrganization(Organization):
name: str name: str
description: str description: str
@ -34,9 +34,8 @@ class PublicOrganization(Organization):
#### Classes #################################################### #### Classes ####################################################
async def get_organization(org_id: str): async def get_organization(request: Request, org_id: str):
await check_database() orgs = request.app.db["organizations"]
orgs = learnhouseDB["organizations"]
org = orgs.find_one({"org_id": org_id}) org = orgs.find_one({"org_id": org_id})
@ -47,9 +46,9 @@ async def get_organization(org_id: str):
org = PublicOrganization(**org) org = PublicOrganization(**org)
return org return org
async def get_organization_by_slug(org_slug: str):
await check_database() async def get_organization_by_slug(request: Request, org_slug: str):
orgs = learnhouseDB["organizations"] orgs = request.app.db["organizations"]
org = orgs.find_one({"slug": org_slug}) org = orgs.find_one({"slug": org_slug})
@ -61,9 +60,8 @@ async def get_organization_by_slug(org_slug: str):
return org return org
async def create_org(org_object: Organization, current_user: PublicUser): async def create_org(request: Request, org_object: Organization, current_user: PublicUser):
await check_database() orgs = request.app.db["organizations"]
orgs = learnhouseDB["organizations"]
# find if org already exists using name # find if org already exists using name
isOrgAvailable = orgs.find_one({"slug": org_object.slug}) isOrgAvailable = orgs.find_one({"slug": org_object.slug})
@ -88,13 +86,12 @@ async def create_org(org_object: Organization, current_user: PublicUser):
return org.dict() return org.dict()
async def update_org(org_object: Organization, org_id: str, current_user: PublicUser): async def update_org(request: Request, org_object: Organization, org_id: str, current_user: PublicUser):
await check_database()
# verify org rights # verify org rights
await verify_org_rights(org_id, current_user,"update") await verify_org_rights(request, org_id, current_user, "update")
orgs = learnhouseDB["organizations"] orgs = request.app.db["organizations"]
org = orgs.find_one({"org_id": org_id}) org = orgs.find_one({"org_id": org_id})
@ -114,12 +111,11 @@ async def update_org(org_object: Organization, org_id: str, current_user: Public
return Organization(**updated_org.dict()) return Organization(**updated_org.dict())
async def delete_org(org_id: str, current_user: PublicUser): async def delete_org(request: Request, org_id: str, current_user: PublicUser):
await check_database()
await verify_org_rights(org_id, current_user,"delete") await verify_org_rights(request, org_id, current_user, "delete")
orgs = learnhouseDB["organizations"] orgs = request.app.db["organizations"]
org = orgs.find_one({"org_id": org_id}) org = orgs.find_one({"org_id": org_id})
@ -136,33 +132,21 @@ async def delete_org(org_id: str, current_user: PublicUser):
status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Unavailable database") status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Unavailable database")
async def get_orgs(page: int = 1, limit: int = 10): async def get_orgs_by_user(request: Request, user_id: str, page: int = 1, limit: int = 10):
## TODO : Deprecated orgs = request.app.db["organizations"]
await check_database()
orgs = learnhouseDB["organizations"]
# get all orgs from database
all_orgs = orgs.find().sort("name", 1).skip(10 * (page - 1)).limit(limit)
return [json.loads(json.dumps(org, default=str)) for org in all_orgs]
async def get_orgs_by_user(user_id: str, page: int = 1, limit: int = 10):
await check_database()
orgs = learnhouseDB["organizations"]
print(user_id) print(user_id)
# find all orgs where user_id is in owners or admins arrays # find all orgs where user_id is in owners or admins arrays
all_orgs = orgs.find({"$or": [{"owners": user_id}, {"admins": user_id}]}).sort("name", 1).skip(10 * (page - 1)).limit(limit) all_orgs = orgs.find({"$or": [{"owners": user_id}, {"admins": user_id}]}).sort(
"name", 1).skip(10 * (page - 1)).limit(limit)
return [json.loads(json.dumps(org, default=str)) for org in all_orgs] return [json.loads(json.dumps(org, default=str)) for org in all_orgs]
#### Security #################################################### #### Security ####################################################
async def verify_org_rights(org_id: str, current_user: PublicUser, action: str,): async def verify_org_rights(request: Request, org_id: str, current_user: PublicUser, action: str,):
await check_database() orgs = request.app.db["organizations"]
orgs = learnhouseDB["organizations"]
org = orgs.find_one({"org_id": org_id}) org = orgs.find_one({"org_id": org_id})

View file

@ -3,10 +3,9 @@ from typing import List
from uuid import uuid4 from uuid import uuid4
from pydantic import BaseModel from pydantic import BaseModel
from src.services.users import PublicUser, User from src.services.users import PublicUser, User
from src.services.database import check_database, learnhouseDB, learnhouseDB
from src.services.security import * from src.services.security import *
from src.services.houses import House from src.services.houses import House
from fastapi import HTTPException, status from fastapi import HTTPException, status, Request
from datetime import datetime from datetime import datetime
#### Classes #################################################### #### Classes ####################################################
@ -26,7 +25,7 @@ class Elements(BaseModel):
collections: List[str] collections: List[str]
organizations: List[str] organizations: List[str]
coursechapters: List[str] coursechapters: List[str]
elements : List[str] lectures : List[str]
class Role(BaseModel): class Role(BaseModel):
@ -45,9 +44,8 @@ class RoleInDB(Role):
#### Classes #################################################### #### Classes ####################################################
async def get_role(role_id: str): async def get_role(request: Request,role_id: str):
await check_database() roles = request.app.db["roles"]
roles = learnhouseDB["roles"]
role = roles.find_one({"role_id": role_id}) role = roles.find_one({"role_id": role_id})
@ -59,9 +57,8 @@ async def get_role(role_id: str):
return role return role
async def create_role(role_object: Role, current_user: PublicUser): async def create_role(request: Request,role_object: Role, current_user: PublicUser):
await check_database() roles = request.app.db["roles"]
roles = learnhouseDB["roles"]
# find if house already exists using name # find if house already exists using name
isRoleAvailable = roles.find_one({"name": role_object.name}) isRoleAvailable = roles.find_one({"name": role_object.name})
@ -70,7 +67,7 @@ async def create_role(role_object: Role, current_user: PublicUser):
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Role name already exists") status_code=status.HTTP_409_CONFLICT, detail="Role name already exists")
await verify_user_permissions_on_roles("create", current_user) await verify_user_permissions_on_roles(request, "create", current_user)
# generate house_id with uuid4 # generate house_id with uuid4
role_id = str(f"role_{uuid4()}") role_id = str(f"role_{uuid4()}")
@ -87,13 +84,12 @@ async def create_role(role_object: Role, current_user: PublicUser):
return role.dict() return role.dict()
async def update_role(role_object: Role, role_id: str, current_user: PublicUser): async def update_role(request: Request,role_object: Role, role_id: str, current_user: PublicUser):
await check_database()
# verify house rights # verify house rights
await verify_user_permissions_on_roles("update", current_user) await verify_user_permissions_on_roles(request, "update", current_user)
roles = learnhouseDB["roles"] roles = request.app.db["roles"]
role = roles.find_one({"role_id": role_id}) role = roles.find_one({"role_id": role_id})
@ -109,13 +105,12 @@ async def update_role(role_object: Role, role_id: str, current_user: PublicUser)
return RoleInDB(**updated_role.dict()) return RoleInDB(**updated_role.dict())
async def delete_role(role_id: str, current_user: PublicUser): async def delete_role(request: Request,role_id: str, current_user: PublicUser):
await check_database()
# verify house rights # verify house rights
await verify_user_permissions_on_roles("delete", current_user) await verify_user_permissions_on_roles(request, "delete", current_user)
roles = learnhouseDB["roles"] roles = request.app.db["roles"]
role = roles.find_one({"role_id": role_id}) role = roles.find_one({"role_id": role_id})
@ -132,9 +127,8 @@ async def delete_role(role_id: str, current_user: PublicUser):
status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Unavailable database") status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Unavailable database")
async def get_roles(page: int = 1, limit: int = 10): async def get_roles(request: Request,page: int = 1, limit: int = 10):
await check_database() roles = request.app.db["roles"]
roles = learnhouseDB["roles"]
# get all roles from database # get all roles from database
all_roles = roles.find().sort("name", 1).skip(10 * (page - 1)).limit(limit) all_roles = roles.find().sort("name", 1).skip(10 * (page - 1)).limit(limit)
@ -144,9 +138,8 @@ async def get_roles(page: int = 1, limit: int = 10):
#### Security #################################################### #### Security ####################################################
async def verify_user_permissions_on_roles(action: str, current_user: PublicUser): async def verify_user_permissions_on_roles(request: Request,action: str, current_user: PublicUser):
await check_database() users = request.app.db["users"]
users = learnhouseDB["users"]
user = users.find_one({"user_id": current_user.user_id}) user = users.find_one({"user_id": current_user.user_id})

View file

@ -1,10 +1,6 @@
from fastapi import HTTPException, status from fastapi import HTTPException, status, Request
from passlib.context import CryptContext from passlib.context import CryptContext
from jose import JWTError, jwt
import logging
from passlib.hash import pbkdf2_sha256 from passlib.hash import pbkdf2_sha256
from src.services.database import check_database
from src.services.database import check_database, learnhouseDB, learnhouseDB
### 🔒 JWT ############################################################## ### 🔒 JWT ##############################################################
@ -31,12 +27,11 @@ async def security_verify_password(plain_password: str, hashed_password: str):
### 🔒 Roles checking ############################################################## ### 🔒 Roles checking ##############################################################
async def verify_user_rights_with_roles(action: str, user_id: str, element_id: str): async def verify_user_rights_with_roles(request: Request,action: str, user_id: str, element_id: str):
""" """
Check if the user has the right to perform the action on the element Check if the user has the right to perform the action on the element
""" """
await check_database() roles = request.app.db["roles"]
roles = learnhouseDB["roles"]
# find data where user_id is in linked_users or * is in linked_users # find data where user_id is in linked_users or * is in linked_users
user_roles_cursor = roles.find({"$or": [{"linked_users": user_id}, {"linked_users": "*"}]}) user_roles_cursor = roles.find({"$or": [{"linked_users": user_id}, {"linked_users": "*"}]})
@ -77,8 +72,8 @@ async def check_element_type(element_id):
return "coursechapters" return "coursechapters"
elif element_id.startswith("collection_"): elif element_id.startswith("collection_"):
return "collections" return "collections"
elif element_id.startswith("element_"): elif element_id.startswith("lecture_"):
return "elements" return "lectures"
else: else:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Issue verifying element nature") status_code=status.HTTP_409_CONFLICT, detail="Issue verifying element nature")

View file

@ -1,8 +1,7 @@
from uuid import uuid4 from uuid import uuid4
from pydantic import BaseModel from pydantic import BaseModel
from src.services.database import check_database, learnhouseDB, learnhouseDB
from src.services.security import * from src.services.security import *
from fastapi import HTTPException, status from fastapi import HTTPException, status, Request
from datetime import datetime from datetime import datetime
#### Classes #################################################### #### Classes ####################################################
@ -41,6 +40,8 @@ class UserProfileMetadata(BaseModel):
roles = list roles = list
# TODO : terrible, export role classes from one single source of truth # TODO : terrible, export role classes from one single source of truth
class Role(BaseModel): class Role(BaseModel):
name: str name: str
description: str description: str
@ -53,9 +54,8 @@ class Role(BaseModel):
# TODO : avatar upload and update # TODO : avatar upload and update
async def get_user(username: str): async def get_user(request: Request, username: str):
await check_database() users = request.app.db["users"]
users = learnhouseDB["users"]
user = users.find_one({"username": username}) user = users.find_one({"username": username})
@ -67,10 +67,9 @@ async def get_user(username: str):
return user return user
async def get_profile_metadata(user): async def get_profile_metadata(request: Request, user):
await check_database() users = request.app.db["users"]
users = learnhouseDB["users"] roles = request.app.db["roles"]
roles = learnhouseDB["roles"]
user = users.find_one({"user_id": user['user_id']}) user = users.find_one({"user_id": user['user_id']})
@ -92,9 +91,8 @@ async def get_profile_metadata(user):
} }
async def get_user_by_userid(user_id: str): async def get_user_by_userid(request: Request, user_id: str):
await check_database() users = request.app.db["users"]
users = learnhouseDB["users"]
user = users.find_one({"user_id": user_id}) user = users.find_one({"user_id": user_id})
@ -106,9 +104,8 @@ async def get_user_by_userid(user_id: str):
return user return user
async def security_get_user(email: str): async def security_get_user(request: Request, email: str):
await check_database() users = request.app.db["users"]
users = learnhouseDB["users"]
user = users.find_one({"email": email}) user = users.find_one({"email": email})
@ -119,9 +116,8 @@ async def security_get_user(email: str):
return UserInDB(**user) return UserInDB(**user)
async def get_userid_by_username(username: str): async def get_userid_by_username(request: Request, username: str):
await check_database() users = request.app.db["users"]
users = learnhouseDB["users"]
user = users.find_one({"username": username}) user = users.find_one({"username": username})
@ -132,9 +128,8 @@ async def get_userid_by_username(username: str):
return user["user_id"] return user["user_id"]
async def update_user(user_id: str, user_object: UserWithPassword): async def update_user(request: Request, user_id: str, user_object: UserWithPassword):
await check_database() users = request.app.db["users"]
users = learnhouseDB["users"]
isUserExists = users.find_one({"user_id": user_id}) isUserExists = users.find_one({"user_id": user_id})
isUsernameAvailable = users.find_one({"username": user_object.username}) isUsernameAvailable = users.find_one({"username": user_object.username})
@ -155,9 +150,8 @@ async def update_user(user_id: str, user_object: UserWithPassword):
return User(**user_object.dict()) return User(**user_object.dict())
async def delete_user(user_id: str): async def delete_user(request: Request, user_id: str):
await check_database() users = request.app.db["users"]
users = learnhouseDB["users"]
isUserAvailable = users.find_one({"user_id": user_id}) isUserAvailable = users.find_one({"user_id": user_id})
@ -170,9 +164,8 @@ async def delete_user(user_id: str):
return {"detail": "User deleted"} return {"detail": "User deleted"}
async def create_user(user_object: UserWithPassword): async def create_user(request: Request, user_object: UserWithPassword):
await check_database() users = request.app.db["users"]
users = learnhouseDB["users"]
isUserAvailable = users.find_one({"username": user_object.username}) isUserAvailable = users.find_one({"username": user_object.username})