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
from fastapi import FastAPI
import logging
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 fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
@ -13,7 +15,6 @@ from src.services.mocks.initial import create_initial_data
# (c) LearnHouse 2022
########################
# Global Config
app = FastAPI(
title="LearnHouse",
@ -22,19 +23,25 @@ app = FastAPI(
root_path="/"
)
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"],
allow_origins=["http://localhost:3000", "http://localhost:3001"],
allow_methods=["*"],
allow_credentials=True,
allow_headers=["*"]
)
# Static Files
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)
def authjwt_exception_handler(request: Request, exc: AuthJWTException):
return JSONResponse(
@ -43,8 +50,11 @@ def authjwt_exception_handler(request: Request, exc: AuthJWTException):
)
# Global Routes
app.include_router(global_router)
# General Routes
@app.get("/")
async def root():
@ -52,7 +62,7 @@ async def root():
@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 🤖"}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -4,31 +4,31 @@ import { Draggable } from "react-beautiful-dnd";
import { EyeOpenIcon, Pencil2Icon } from '@radix-ui/react-icons'
import styled from "styled-components";
function Element(props: any) {
function Lecture(props: any) {
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) => (
<ElementWrapper key={props.element.id} {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef}>
<p>{props.element.name} </p>
<LectureWrapper key={props.lecture.id} {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef}>
<p>{props.lecture.name} </p>
<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">
&nbsp; <EyeOpenIcon/>
</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">
&nbsp; <Pencil2Icon/>
</Link>
</ElementWrapper>
</LectureWrapper>
)}
</Draggable>
);
}
export const ElementWrapper = styled.div`
export const LectureWrapper = styled.div`
padding: 10px;
padding-left: 17px;
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 = {
elements: {
"element-1": { id: "element-1", content: "First element" },
"element-2": { id: "element-2", content: "Second element" },
"element-3": { id: "element-3", content: "Third element" },
"element-4": { id: "element-4", content: "Fourth element" },
"element-5": { id: "element-5", content: "Fifth element" },
lectures: {
"lecture-1": { id: "lecture-1", content: "First lecture" },
"lecture-2": { id: "lecture-2", content: "Second lecture" },
"lecture-3": { id: "lecture-3", content: "Third lecture" },
"lecture-4": { id: "lecture-4", content: "Fourth lecture" },
"lecture-5": { id: "lecture-5", content: "Fifth lecture" },
},
chapters: {
"chapter-1": { id: "chapter-1", name: "Chapter 1", elementIds: ["element-1", "element-2", "element-3"] },
"chapter-2": { id: "chapter-2", name: "Chapter 2", elementIds: ["element-4"] },
"chapter-3": { id: "chapter-3", name: "Chapter 3", elementIds: ["element-5"] },
"chapter-1": { id: "chapter-1", name: "Chapter 1", lectureIds: ["lecture-1", "lecture-2", "lecture-3"] },
"chapter-2": { id: "chapter-2", name: "Chapter 2", lectureIds: ["lecture-4"] },
"chapter-3": { id: "chapter-3", name: "Chapter 3", lectureIds: ["lecture-5"] },
},
chapterOrder: ["chapter-1", "chapter-2", "chapter-3"],

View file

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

View file

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

View file

@ -17,7 +17,7 @@ function VideoBlockComponents(props: any) {
const handleSubmit = async (e: any) => {
e.preventDefault();
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);
setfileObject(object);
props.updateAttributes({
@ -42,7 +42,7 @@ function VideoBlockComponents(props: any) {
<BlockVideo>
<video
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
}`}
></video>

View file

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

View file

@ -2,10 +2,10 @@ import { getBackendUrl } from "@services/config";
import React from "react";
import styled from "styled-components";
function VideoLecture({ element, course }: { element: any; course: any }) {
function VideoLecture({ lecture, course }: { lecture: any; course: any }) {
function getChapterName() {
let chapterName = "";
let chapterId = element.chapter_id;
let chapterId = lecture.chapter_id;
course.chapters.forEach((chapter: any) => {
if (chapter.chapter_id === chapterId) {
chapterName = chapter.name;
@ -18,10 +18,10 @@ function VideoLecture({ element, course }: { element: any; course: any }) {
<VideoLectureLayout>
<VideoTitle>
<p>Chapter : {getChapterName()}</p>
{element.name}
{lecture.name}
</VideoTitle>
<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>
</VideoLectureLayout>
);

View file

@ -16,7 +16,7 @@ function NewChapterModal({ submitChapter , closeModal }: any) {
const handleSubmit = async (e: any) => {
e.preventDefault();
console.log({ chapterName, chapterDescription });
submitChapter({ name : chapterName, description : chapterDescription , elements : [] });
submitChapter({ name : chapterName, description : chapterDescription , lectures : [] });
};
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 Modal from "../Modal";
import styled from "styled-components";
import DynamicCanvaModal from "./NewElementModal/DynamicCanva";
import VideoModal from "./NewElementModal/Video";
import DynamicCanvaModal from "./NewLectureModal/DynamicCanva";
import VideoModal from "./NewLectureModal/Video";
function NewElementModal({ closeModal, submitElement, submitFileElement, chapterId }: any) {
function NewLectureModal({ closeModal, submitLecture, submitFileLecture, chapterId }: any) {
const [selectedView, setSelectedView] = useState("home");
return (
@ -16,29 +16,29 @@ function NewElementModal({ closeModal, submitElement, submitFileElement, chapter
<button onClick={closeModal}>
<Cross1Icon />
</button>
<h1>Add New Element</h1>
<h1>Add New Lecture</h1>
<br />
{selectedView === "home" && (
<ElementChooserWrapper>
<ElementButton onClick={() => {setSelectedView("dynamic")}}>📄</ElementButton>
<ElementButton onClick={() => {setSelectedView("video")}}>📹</ElementButton>
</ElementChooserWrapper>
<LectureChooserWrapper>
<LectureButton onClick={() => {setSelectedView("dynamic")}}>📄</LectureButton>
<LectureButton onClick={() => {setSelectedView("video")}}>📹</LectureButton>
</LectureChooserWrapper>
)}
{selectedView === "dynamic" && (
<DynamicCanvaModal submitElement={submitElement} chapterId={chapterId} />
<DynamicCanvaModal submitLecture={submitLecture} chapterId={chapterId} />
)}
{selectedView === "video" && (
<VideoModal submitFileElement={submitFileElement} chapterId={chapterId} />
<VideoModal submitFileLecture={submitFileLecture} chapterId={chapterId} />
)}
</Modal>
);
}
const ElementChooserWrapper = styled.div`
const LectureChooserWrapper = styled.div`
display: flex;
flex-direction: row;
align-items: center;
@ -46,7 +46,7 @@ const ElementChooserWrapper = styled.div`
gap: 20px;
`;
const ElementButton = styled.button`
const LectureButton = styled.button`
padding: 20px;
border-radius: 10px;
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";
function VideoModal({ submitFileElement, chapterId }: any) {
function VideoModal({ submitFileLecture, chapterId }: any) {
const [video, setVideo] = React.useState(null) as any;
const [name, setName] = React.useState("");
@ -14,11 +14,11 @@ function VideoModal({ submitFileElement, chapterId }: any) {
const handleSubmit = async (e: any) => {
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.
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 (
<div>

View file

@ -1,6 +1,6 @@
import { getAPIUrl } from "../config";
export async function createElement(data: any, chapter_id: any) {
export async function createLecture(data: any, chapter_id: any) {
data.content = {};
console.log("data", data, chapter_id);
@ -17,7 +17,7 @@ export async function createElement(data: any, chapter_id: any) {
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())
.catch((error) => console.log("error", error));
@ -26,7 +26,7 @@ export async function createElement(data: any, chapter_id: any) {
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();
@ -37,12 +37,12 @@ export async function createFileElement(file: File, type: string, data: any, cha
console.log("type" , type);
let endpoint = `${getAPIUrl()}elements/video`;
let endpoint = `${getAPIUrl()}lectures/video`;
if (type === "video") {
formData.append("name", data.name);
formData.append("video_file", file);
endpoint = `${getAPIUrl()}elements/video`;
endpoint = `${getAPIUrl()}lectures/video`;
}
console.log();
@ -67,21 +67,21 @@ export async function createFileElement(file: File, type: string, data: any, cha
return result;
}
export async function getElement(element_id: any) {
export async function getLecture(lecture_id: any) {
const requestOptions: any = {
method: "GET",
redirect: "follow",
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())
.catch((error) => console.log("error", error));
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 requestOptions: any = {
@ -92,7 +92,7 @@ export async function updateElement(data: any, element_id: any) {
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())
.catch((error) => console.log("error", error));

View file

@ -1,12 +1,12 @@
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();
// Send file thumbnail as form data
const formData = new FormData();
formData.append("file_object", file);
formData.append("element_id", element_id);
formData.append("lecture_id", lecture_id);
const requestOptions: any = {
method: "POST",

View file

@ -1,12 +1,12 @@
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();
// Send file thumbnail as form data
const formData = new FormData();
formData.append("file_object", file);
formData.append("element_id", element_id);
formData.append("lecture_id", lecture_id);
const requestOptions: any = {
method: "POST",

View file

@ -1,6 +1,6 @@
fastapi==0.78.0
fastapi==0.89.1
pydantic>=1.8.0,<2.0.0
uvicorn>=0.15.0,<0.16.0
uvicorn==0.20.0
pymongo==4.1.1
python-multipart
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 ####################################################
async def authenticate_user(email: str, password: str):
user = await security_get_user(email)
async def authenticate_user(request: Request,email: str, password: str):
user = await security_get_user(request, email)
if not user:
return False
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)
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(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
@ -97,7 +79,7 @@ async def get_current_user(Authorize: AuthJWT = Depends()):
token_data = TokenData(username=username) # type: ignore
except JWTError:
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:
raise credentials_exception
return PublicUser(**user.dict())

View file

@ -1,6 +1,6 @@
from fastapi import APIRouter
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")
@ -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(courses.router, prefix="/courses", tags=["courses"])
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"])

View file

@ -1,5 +1,5 @@
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 src.dependencies.auth import *
from src.services.users import *
@ -11,11 +11,11 @@ router = APIRouter()
# DEPRECATED
@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
"""
user = await authenticate_user(form_data.username, form_data.password)
user = await authenticate_user(request, form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
@ -47,8 +47,8 @@ def refresh(Authorize: AuthJWT = Depends()):
return {"access_token": new_access_token}
@router.post('/login')
async def login(Authorize: AuthJWT = Depends(), form_data: OAuth2PasswordRequestForm = Depends()):
user = await authenticate_user(form_data.username, form_data.password)
async def login(request: Request,Authorize: AuthJWT = Depends(), form_data: OAuth2PasswordRequestForm = Depends()):
user = await authenticate_user(request, form_data.username, form_data.password)
if not user:
raise HTTPException(
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.users import PublicUser
@ -8,57 +8,57 @@ router = APIRouter()
@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
"""
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}")
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
"""
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}")
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
"""
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}")
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
"""
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}")
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
"""
return await get_coursechapters(course_id, page, limit)
return await get_coursechapters(request, course_id, page, limit)
@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
"""
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}")
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
"""
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.services.users import PublicUser, User
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("/")
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
"""
return await create_collection(collection_object, current_user)
return await create_collection(request, collection_object, current_user)
@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
"""
return await get_collection(collection_id, current_user)
return await get_collection(request, collection_id, current_user)
@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
"""
return await get_collections(page, limit)
return await get_collections(request, page, limit)
@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
"""
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}")
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
"""
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.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("/")
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
"""
course = Course(name=name, mini_description=mini_description, description=description,
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}")
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
"""
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}")
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
"""
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}")
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}")
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
"""
return await get_courses(page, limit, org_id)
return await get_courses(request,page, limit, org_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
"""
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}")
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
"""
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 fastapi import HTTPException, status, UploadFile
@ -10,32 +10,32 @@ router = APIRouter()
@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
"""
return await create_picture_file(file_object, element_id)
return await create_picture_file(request,file_object, lecture_id)
@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
"""
return await create_video_file(file_object, element_id)
return await create_video_file(request, file_object, lecture_id)
@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
"""
return await get_picture_file(file_id, current_user)
return await get_picture_file(request, file_id, current_user)
@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
"""
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.services.houses import House, HouseInDB, create_house, get_house, get_houses, update_house, delete_house
@ -9,41 +9,41 @@ router = APIRouter()
@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
"""
return await create_house(house_object, current_user)
return await create_house(request, house_object, current_user)
@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
"""
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}")
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
"""
return await get_houses(page, limit)
return await get_houses(request, page, limit)
@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
"""
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}")
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
"""
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.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
@ -8,55 +9,49 @@ router = APIRouter()
@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
"""
return await create_org(org_object, current_user)
return await create_org(request, org_object, current_user)
@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
"""
return await get_organization(org_id)
return await get_organization(request, org_id)
@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
"""
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}")
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
"""
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}")
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
"""
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}")
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
"""
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.services.roles import Role, create_role, delete_role, get_role, get_roles, update_role
from src.services.users import PublicUser, User
@ -9,41 +8,41 @@ router = APIRouter()
@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
"""
return await create_role(role_object, current_user)
return await create_role(request, role_object, current_user)
@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
"""
return await get_role(role_id)
return await get_role(request, role_id)
@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
"""
return await get_roles(page, limit)
return await get_roles(request, page, limit)
@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
"""
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}")
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
"""
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()
# 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")
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()
@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
"""
return await get_profile_metadata(current_user.dict())
return await get_profile_metadata(request , current_user.dict())
@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
"""
return await get_user(username)
return await get_user(request, username)
@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
"""
return await get_user_by_userid(user_id)
return await get_user_by_userid(request, user_id)
@router.post("/")
async def api_create_user(user_object: UserWithPassword):
async def api_create_user(request: Request,user_object: UserWithPassword):
"""
Create new user
"""
return await create_user(user_object)
return await create_user(request, user_object)
@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
"""
return await delete_user(user_id)
return await delete_user(request, 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
"""
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 pydantic import BaseModel
from src.services.courses.courses import Course, CourseInDB
from src.services.courses.elements.elements import Element, ElementInDB
from src.services.database import create_config_collection, check_database, create_database, learnhouseDB, learnhouseDB
from src.services.courses.lectures.lectures import Lecture, LectureInDB
from src.services.security import verify_user_rights_with_roles
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):
name: str
description: str
elements: list
lectures: list
class CourseChapterInDB(CourseChapter):
@ -28,7 +27,7 @@ class CourseChapterInDB(CourseChapter):
class CourseChapterMetaData(BaseModel):
chapterOrder: List[str]
chapters: object
elements: object
lectures: object
#### Classes ####################################################
@ -37,15 +36,14 @@ class CourseChapterMetaData(BaseModel):
####################################################
async def create_coursechapter(coursechapter_object: CourseChapter, course_id: str, current_user: PublicUser):
await check_database()
coursechapters = learnhouseDB["coursechapters"]
courses = learnhouseDB["courses"]
async def create_coursechapter(request: Request,coursechapter_object: CourseChapter, course_id: str, current_user: PublicUser):
coursechapters = request.app.db["coursechapters"]
courses = request.app.db["courses"]
# generate coursechapter_id with 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:
raise HTTPException(
@ -65,16 +63,15 @@ async def create_coursechapter(coursechapter_object: CourseChapter, course_id: s
return coursechapter.dict()
async def get_coursechapter(coursechapter_id: str, current_user: PublicUser):
await check_database()
coursechapters = learnhouseDB["coursechapters"]
async def get_coursechapter(request: Request,coursechapter_id: str, current_user: PublicUser):
coursechapters = request.app.db["coursechapters"]
coursechapter = coursechapters.find_one(
{"coursechapter_id": coursechapter_id})
if coursechapter:
# 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)
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")
async def update_coursechapter(coursechapter_object: CourseChapter, coursechapter_id: str, current_user: PublicUser):
await check_database()
coursechapters = learnhouseDB["coursechapters"]
async def update_coursechapter(request: Request,coursechapter_object: CourseChapter, coursechapter_id: str, current_user: PublicUser):
coursechapters = request.app.db["coursechapters"]
coursechapter = coursechapters.find_one(
{"coursechapter_id": coursechapter_id})
if coursechapter:
# 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"]
# 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")
async def delete_coursechapter(coursechapter_id: str, current_user: PublicUser):
await check_database()
async def delete_coursechapter(request: Request,coursechapter_id: str, current_user: PublicUser):
coursechapters = learnhouseDB["coursechapters"]
courses = learnhouseDB["courses"]
coursechapters = request.app.db["coursechapters"]
courses = request.app.db["courses"]
coursechapter = coursechapters.find_one(
{"coursechapter_id": coursechapter_id})
if coursechapter:
# 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(
{"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):
await check_database()
courses = learnhouseDB["coursechapters"]
async def get_coursechapters(request: Request,course_id: str, page: int = 1, limit: int = 10):
courses = request.app.db["coursechapters"]
# TODO : Get only courses that user is admin/has roles of
# get all courses from database
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]
async def get_coursechapters_meta(course_id: str, current_user: PublicUser):
await check_database()
coursechapters = learnhouseDB["coursechapters"]
courses = learnhouseDB["courses"]
elements = learnhouseDB["elements"]
async def get_coursechapters_meta(request: Request,course_id: str, current_user: PublicUser):
coursechapters = request.app.db["coursechapters"]
courses = request.app.db["courses"]
lectures = request.app.db["lectures"]
coursechapters = coursechapters.find(
{"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 = Course(**course) # type: ignore
# elements
coursechapter_elementIds_global = []
# lectures
coursechapter_lectureIds_global = []
# chapters
chapters = {}
for coursechapter in coursechapters:
coursechapter = CourseChapterInDB(**coursechapter)
coursechapter_elementIds = []
coursechapter_lectureIds = []
for element in coursechapter.elements:
coursechapter_elementIds.append(element)
coursechapter_elementIds_global.append(element)
for lecture in coursechapter.lectures:
coursechapter_lectureIds.append(lecture)
coursechapter_lectureIds_global.append(lecture)
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
elements_list = {}
for element in elements.find({"element_id": {"$in": coursechapter_elementIds_global}}):
element = ElementInDB(**element)
elements_list[element.element_id] = {
"id": element.element_id, "name": element.name, "type": element.type, "content": element.content
# lectures
lectures_list = {}
for lecture in lectures.find({"lecture_id": {"$in": coursechapter_lectureIds_global}}):
lecture = LectureInDB(**lecture)
lectures_list[lecture.lecture_id] = {
"id": lecture.lecture_id, "name": lecture.name, "type": lecture.type, "content": lecture.content
}
final = {
"chapters": chapters,
"chapterOrder": course.chapters,
"elements": elements_list
"lectures": lectures_list
}
return final
async def update_coursechapters_meta(course_id: str, coursechapters_metadata: CourseChapterMetaData, current_user: PublicUser):
await check_database()
coursechapters = learnhouseDB["coursechapters"]
courses = learnhouseDB["courses"]
async def update_coursechapters_meta(request: Request,course_id: str, coursechapters_metadata: CourseChapterMetaData, current_user: PublicUser):
coursechapters = request.app.db["coursechapters"]
courses = request.app.db["courses"]
# update chapters in course
courseInDB = courses.update_one({"course_id": course_id}, {
"$set": {"chapters": coursechapters_metadata.chapterOrder}})
# update elements in coursechapters
# update lectures in coursechapters
# TODO : performance/optimization improvement
for coursechapter in coursechapters_metadata.chapters.__dict__.items():
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"}
#### Security ####################################################
async def verify_rights(course_id: str, current_user: PublicUser, action: str):
await check_database()
courses = learnhouseDB["courses"]
async def verify_rights(request: Request,course_id: str, current_user: PublicUser, action: str):
courses = request.app.db["courses"]
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(
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"]
if not hasRoleRights and not isAuthor:

View file

@ -3,7 +3,6 @@ from typing import List
from uuid import uuid4
from pydantic import BaseModel
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 fastapi import FastAPI, HTTPException, status, Request, Response, BackgroundTasks
from datetime import datetime
@ -28,14 +27,13 @@ class CollectionInDB(Collection):
# CRUD
####################################################
async def get_collection(collection_id: str, current_user: PublicUser):
await check_database()
collections = learnhouseDB["collections"]
async def get_collection(request: Request,collection_id: str, current_user: PublicUser):
collections = request.app.db["collections"]
collection = collections.find_one({"collection_id": collection_id})
# 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:
raise HTTPException(
@ -45,9 +43,8 @@ async def get_collection(collection_id: str, current_user: PublicUser):
return collection
async def create_collection(collection_object: Collection, current_user: PublicUser):
await check_database()
collections = learnhouseDB["collections"]
async def create_collection(request: Request,collection_object: Collection, current_user: PublicUser):
collections = request.app.db["collections"]
# find if collection already exists using name
isCollectionNameAvailable = collections.find_one(
@ -75,13 +72,12 @@ async def create_collection(collection_object: Collection, current_user: PublicU
return collection.dict()
async def update_collection(collection_object: Collection, collection_id: str, current_user: PublicUser):
await check_database()
async def update_collection(request: Request,collection_object: Collection, collection_id: str, current_user: PublicUser):
# 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})
@ -98,12 +94,11 @@ async def update_collection(collection_object: Collection, collection_id: str, c
return Collection(**updated_collection.dict())
async def delete_collection(collection_id: str, current_user: PublicUser):
await check_database()
async def delete_collection(request: Request,collection_id: str, current_user: PublicUser):
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})
@ -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
await check_database()
collections = learnhouseDB["collections"]
collections = request.app.db["collections"]
# get all collections from database without ObjectId
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]
# add courses to collection
courses = learnhouseDB["courses"]
courses = request.app.db["courses"]
collection.courses = []
collection.courses = courses.find(
{"course_id": {"$in": collection_courses}}, {'_id': 0})
@ -153,9 +147,8 @@ async def get_collections(page: int = 1, limit: int = 10):
#### Security ####################################################
async def verify_collection_rights(collection_id: str, current_user: PublicUser, action: str):
await check_database()
collections = learnhouseDB["collections"]
async def verify_collection_rights(request: Request,collection_id: str, current_user: PublicUser, action: str):
collections = request.app.db["collections"]
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(
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:
raise HTTPException(

View file

@ -2,10 +2,9 @@ import json
from typing import List
from uuid import uuid4
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.users import PublicUser
from src.services.database import check_database, learnhouseDB
from src.services.security import *
from fastapi import HTTPException, status, UploadFile
from datetime import datetime
@ -36,7 +35,7 @@ class CourseInDB(Course):
class CourseChapter(BaseModel):
name: str
description: str
elements: list
lectures: list
class CourseChapterInDB(CourseChapter):
@ -54,14 +53,13 @@ class CourseChapterInDB(CourseChapter):
# CRUD
####################################################
async def get_course(course_id: str, current_user: PublicUser):
await check_database()
courses = learnhouseDB["courses"]
async def get_course(request: Request,course_id: str, current_user: PublicUser):
courses = request.app.db["courses"]
course = courses.find_one({"course_id": course_id})
# verify course rights
await verify_rights(course_id, current_user, "read")
await verify_rights(request,course_id, current_user, "read")
if not course:
raise HTTPException(
@ -71,15 +69,14 @@ async def get_course(course_id: str, current_user: PublicUser):
return course
async def get_course_meta(course_id: str, current_user: PublicUser):
await check_database()
courses = learnhouseDB["courses"]
coursechapters = learnhouseDB["coursechapters"]
async def get_course_meta(request: Request,course_id: str, current_user: PublicUser):
courses = request.app.db["courses"]
coursechapters = request.app.db["coursechapters"]
course = courses.find_one({"course_id": course_id})
elements = learnhouseDB["elements"]
lectures = request.app.db["lectures"]
# verify course rights
await verify_rights(course_id, current_user, "read")
await verify_rights(request,course_id, current_user, "read")
if not course:
raise HTTPException(
@ -88,52 +85,51 @@ async def get_course_meta(course_id: str, current_user: PublicUser):
coursechapters = coursechapters.find(
{"course_id": course_id}).sort("name", 1)
# elements
coursechapter_elementIds_global = []
# lectures
coursechapter_lectureIds_global = []
# chapters
chapters = {}
for coursechapter in coursechapters:
coursechapter = CourseChapterInDB(**coursechapter)
coursechapter_elementIds = []
coursechapter_lectureIds = []
for element in coursechapter.elements:
coursechapter_elementIds.append(element)
coursechapter_elementIds_global.append(element)
for lecture in coursechapter.lectures:
coursechapter_lectureIds.append(lecture)
coursechapter_lectureIds_global.append(lecture)
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
elements_list = {}
for element in elements.find({"element_id": {"$in": coursechapter_elementIds_global}}):
element = ElementInDB(**element)
elements_list[element.element_id] = {
"id": element.element_id, "name": element.name, "type": element.type, "content": element.content
# lectures
lectures_list = {}
for lecture in lectures.find({"lecture_id": {"$in": coursechapter_lectureIds_global}}):
lecture = LectureInDB(**lecture)
lectures_list[lecture.lecture_id] = {
"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:
chapters_list_with_elements.append(
{"id": chapters[chapter]["id"], "name": chapters[chapter]["name"], "elements": [elements_list[element] for element in chapters[chapter]["elementIds"]]})
chapters_list_with_lectures.append(
{"id": chapters[chapter]["id"], "name": chapters[chapter]["name"], "lectures": [lectures_list[lecture] for lecture in chapters[chapter]["lectureIds"]]})
course = Course(**course)
return {
"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):
await check_database()
courses = learnhouseDB["courses"]
async def create_course(request: Request,course_object: Course, org_id: str, current_user: PublicUser, thumbnail_file: UploadFile | None = None):
courses = request.app.db["courses"]
# generate course_id with uuid4
course_id = str(f"course_{uuid4()}")
# TODO(fix) : the implementation here is clearly not the best one (this entire function)
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:
raise HTTPException(
@ -156,13 +152,12 @@ async def create_course(course_object: Course, org_id: str, current_user: Public
return course.dict()
async def update_course_thumbnail(course_id: str, current_user: PublicUser, thumbnail_file: UploadFile | None = None):
await check_database()
async def update_course_thumbnail(request: Request,course_id: str, current_user: PublicUser, thumbnail_file: UploadFile | None = None):
# 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})
# 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")
async def update_course(course_object: Course, course_id: str, current_user: PublicUser):
await check_database()
async def update_course(request: Request,course_object: Course, course_id: str, current_user: PublicUser):
# 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})
@ -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")
async def delete_course(course_id: str, current_user: PublicUser):
await check_database()
async def delete_course(request: Request,course_id: str, current_user: PublicUser):
# 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})
@ -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):
await check_database()
courses = learnhouseDB["courses"]
async def get_courses(request: Request,page: int = 1, limit: int = 10, org_id: str | None = None):
courses = request.app.db["courses"]
# TODO : Get only courses that user is admin/has roles of
# get all courses from database
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 ####################################################
async def verify_rights(course_id: str, current_user: PublicUser, action: str):
await check_database()
courses = learnhouseDB["courses"]
async def verify_rights(request: Request,course_id: str, current_user: PublicUser, action: str):
courses = request.app.db["courses"]
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(
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"]
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
async def upload_video(video_file, element_id):
async def upload_video(video_file, lecture_id):
contents = video_file.file.read()
video_format = video_file.filename.split(".")[-1]
# create folder
os.mkdir(f"content/uploads/video/{element_id}")
os.mkdir(f"content/uploads/video/{lecture_id}")
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.close()

View file

@ -1,21 +1,19 @@
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.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.courses.elements.elements import ElementInDB
from fastapi import HTTPException, status, UploadFile
from src.services.courses.lectures.lectures import LectureInDB
from fastapi import HTTPException, status, UploadFile, Request
from uuid import uuid4
from datetime import datetime
async def create_video_element(name: str, coursechapter_id: str, current_user: PublicUser, video_file: UploadFile | None = None):
await check_database()
elements = learnhouseDB["elements"]
coursechapters = learnhouseDB["coursechapters"]
async def create_video_lecture(request: Request,name: str, coursechapter_id: str, current_user: PublicUser, video_file: UploadFile | None = None):
lectures = request.app.db["lectures"]
coursechapters = request.app.db["coursechapters"]
# generate element_id
element_id = str(f"element_{uuid4()}")
# generate lecture_id
lecture_id = str(f"lecture_{uuid4()}")
# check if video_file is not None
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")
video_format = video_file.filename.split(".")[-1]
element_object = ElementInDB(
element_id=element_id,
lecture_object = LectureInDB(
lecture_id=lecture_id,
coursechapter_id=coursechapter_id,
name=name,
type="video",
content={
"video": {
"filename": "video."+video_format,
"element_id": element_id,
"lecture_id": lecture_id,
}
},
creationDate=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:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Roles : Insufficient rights to perform this action")
# create element
element = ElementInDB(**element_object.dict())
elements.insert_one(element.dict())
# create lecture
lecture = LectureInDB(**lecture_object.dict())
lectures.insert_one(lecture.dict())
# upload video
if video_file:
print("uploading video")
# 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
# update chapter
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 pydantic import BaseModel
from src.services.database import check_database, learnhouseDB, learnhouseDB
from fastapi import HTTPException, status, UploadFile
from fastapi import HTTPException, status, UploadFile, Request
from fastapi.responses import StreamingResponse
import os
@ -14,12 +13,11 @@ class PhotoFile(BaseModel):
file_name: str
file_size: int
file_type: str
element_id: str
lecture_id: str
async def create_picture_file(picture_file: UploadFile, element_id: str):
await check_database()
photos = learnhouseDB["files"]
async def create_picture_file(request: Request,picture_file: UploadFile, lecture_id: str):
photos = request.app.db["files"]
# generate file_id
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_size=file_size,
file_type=file_type,
element_id=element_id
lecture_id=lecture_id
)
# create folder for element
if not os.path.exists(f"content/uploads/files/pictures/{element_id}"):
os.mkdir(f"content/uploads/files/pictures/{element_id}")
# create folder for lecture
if not os.path.exists(f"content/uploads/files/pictures/{lecture_id}"):
os.mkdir(f"content/uploads/files/pictures/{lecture_id}")
# 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.close()
@ -73,9 +71,8 @@ async def create_picture_file(picture_file: UploadFile, element_id: str):
return uploadable_file
async def get_picture_object(file_id: str):
await check_database()
photos = learnhouseDB["files"]
async def get_picture_object(request: Request,file_id: str):
photos = request.app.db["files"]
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")
async def get_picture_file(file_id: str, current_user: PublicUser):
await check_database()
photos = learnhouseDB["files"]
async def get_picture_file(request: Request,file_id: str, current_user: PublicUser):
photos = request.app.db["files"]
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
photo_file = PhotoFile(**photo_file)
file_format = photo_file.file_format
element_id = photo_file.element_id
lecture_id = photo_file.lecture_id
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)
else:

View file

@ -1,8 +1,7 @@
from uuid import uuid4
from pydantic import BaseModel
import os
from src.services.database import check_database, learnhouseDB, learnhouseDB
from fastapi import HTTPException, status, UploadFile
from fastapi import HTTPException, status, UploadFile,Request
from fastapi.responses import StreamingResponse
from src.services.users import PublicUser
@ -14,12 +13,11 @@ class VideoFile(BaseModel):
file_name: str
file_size: int
file_type: str
element_id: str
lecture_id: str
async def create_video_file(video_file: UploadFile, element_id: str):
await check_database()
files = learnhouseDB["files"]
async def create_video_file(request: Request,video_file: UploadFile, lecture_id: str):
files = request.app.db["files"]
# generate file_id
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_size=file_size,
file_type=file_type,
element_id=element_id
lecture_id=lecture_id
)
# create folder for element
if not os.path.exists(f"content/uploads/files/videos/{element_id}"):
os.mkdir(f"content/uploads/files/videos/{element_id}")
# create folder for lecture
if not os.path.exists(f"content/uploads/files/videos/{lecture_id}"):
os.mkdir(f"content/uploads/files/videos/{lecture_id}")
# 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.close()
@ -73,9 +71,8 @@ async def create_video_file(video_file: UploadFile, element_id: str):
return uploadable_file
async def get_video_object(file_id: str, current_user: PublicUser):
await check_database()
photos = learnhouseDB["files"]
async def get_video_object(request: Request,file_id: str, current_user: PublicUser):
photos = request.app.db["files"]
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")
async def get_video_file(file_id: str, current_user: PublicUser):
await check_database()
photos = learnhouseDB["files"]
async def get_video_file(request: Request,file_id: str, current_user: PublicUser):
photos = request.app.db["files"]
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
video_file = VideoFile(**video_file)
file_format = video_file.file_format
element_id = video_file.element_id
lecture_id = video_file.lecture_id
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
return StreamingResponse(iterfile(), media_type=video_file.file_type)

View file

@ -3,7 +3,6 @@ from typing import List
from uuid import uuid4
from pydantic import BaseModel
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 fastapi import FastAPI, HTTPException, status, Request, Response, BackgroundTasks
from datetime import datetime
@ -28,14 +27,13 @@ class HouseInDB(House):
# TODO : Add house photo upload and delete
async def get_house(house_id: str, current_user: PublicUser):
await check_database()
houses = learnhouseDB["houses"]
async def get_house(request: Request, house_id: str, current_user: PublicUser):
houses = request.app.db["houses"]
house = houses.find_one({"house_id": house_id})
# 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:
raise HTTPException(
@ -45,9 +43,8 @@ async def get_house(house_id: str, current_user: PublicUser):
return house
async def create_house(house_object: House, current_user: PublicUser):
await check_database()
houses = learnhouseDB["houses"]
async def create_house(request: Request,house_object: House, current_user: PublicUser):
houses = request.app.db["houses"]
# find if house already exists using 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
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:
raise HTTPException(
@ -78,13 +75,12 @@ async def create_house(house_object: House, current_user: PublicUser):
return house.dict()
async def update_house(house_object: House, house_id: str, current_user: PublicUser):
await check_database()
async def update_house(request: Request,house_object: House, house_id: str, current_user: PublicUser):
# 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})
@ -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):
await check_database()
async def delete_house(request: Request,house_id: str, current_user: PublicUser):
# 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})
@ -130,9 +125,8 @@ async def delete_house(house_id: str, current_user: PublicUser):
status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Unavailable database")
async def get_houses(page: int = 1, limit: int = 10):
await check_database()
houses = learnhouseDB["houses"]
async def get_houses(request: Request,page: int = 1, limit: int = 10):
houses = request.app.db["houses"]
# TODO : Get only houses that user is admin/has roles of
# get all houses from database
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 ####################################################
async def verify_house_rights(house_id: str, current_user: PublicUser, action: str):
await check_database()
houses = learnhouseDB["houses"]
async def verify_house_rights(request: Request,house_id: str, current_user: PublicUser, action: str):
houses = request.app.db["houses"]
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(
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"]
if not hasRoleRights and not isOwner:

View file

@ -1,14 +1,14 @@
import requests
from datetime import datetime
from fileinput import filename
from pprint import pprint
from uuid import uuid4
import requests
from fastapi import File, UploadFile
from fastapi import File, UploadFile, Request
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.users import PublicUser, User, UserInDB, UserWithPassword
from src.services.database import learnhouseDB
from src.services.orgs import OrganizationInDB, Organization, create_org
from src.services.roles import Permission, Elements, create_role
from src.services.users import create_user
@ -17,7 +17,7 @@ from src.services.roles import Role
from faker import Faker
async def create_initial_data():
async def create_initial_data(request: Request):
fake = Faker(['en_US'])
fake_multilang = Faker(
['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
########################################
database_users = learnhouseDB["users"]
database_users = request.app.db["users"]
database_users.delete_many({})
users = []
@ -36,7 +36,7 @@ async def create_initial_data():
user_type="isOwner",
)
admin_user = await create_user(admin_user)
admin_user = await create_user(request, admin_user)
for i in range(0, 20):
user = UserWithPassword(
@ -49,10 +49,10 @@ async def create_initial_data():
users.append(user)
for user in users:
await create_user(user)
await create_user(request, user)
# find admin user
users = learnhouseDB["users"]
users = request.app.db["users"]
admin_user = users.find_one({"username": "admin"})
if admin_user:
@ -64,7 +64,7 @@ async def create_initial_data():
# Create organizations
########################################
database_orgs = learnhouseDB["organizations"]
database_orgs = request.app.db["organizations"]
database_orgs.delete_many({})
organizations = []
@ -79,12 +79,12 @@ async def create_initial_data():
slug=slug,
)
organizations.append(org)
await create_org(org, current_user)
await create_org(request, org, current_user)
# Create roles
########################################
database_roles = learnhouseDB["roles"]
database_roles = request.app.db["roles"]
database_roles.delete_many({})
roles = []
@ -104,24 +104,24 @@ async def create_initial_data():
collections=["*"],
organizations=["*"],
coursechapters=["*"],
elements=["*"],
lectures=["*"],
),
linked_users=[admin_user.user_id],
)
roles.append(admin_role)
await create_role(admin_role, current_user)
await create_role(request, admin_role, current_user)
# Generate Courses and CourseChapters
########################################
database_courses = learnhouseDB["courses"]
database_chapters = learnhouseDB["coursechapters"]
database_courses = request.app.db["courses"]
database_chapters = request.app.db["coursechapters"]
database_courses.delete_many({})
database_chapters.delete_many({})
courses = []
orgs = learnhouseDB["organizations"]
orgs = request.app.db["organizations"]
if orgs.count_documents({}) > 0:
for org in orgs.find():
@ -150,7 +150,7 @@ async def create_initial_data():
authors=[current_user.user_id],
)
courses = learnhouseDB["courses"]
courses = request.app.db["courses"]
name_in_disk = f"test_mock{course_id}.jpeg"
image = requests.get(
@ -168,16 +168,16 @@ async def create_initial_data():
coursechapter = CourseChapter(
name=fake_multilang.unique.sentence(),
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)
if coursechapter:
# create elements
# create lectures
for i in range(0, 5):
element = Element(
lecture = Lecture(
name=fake_multilang.unique.sentence(),
type="dynamic",
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 pydantic import BaseModel
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 fastapi import FastAPI, HTTPException, status, Request, Response, BackgroundTasks
from datetime import datetime
@ -15,7 +14,7 @@ class Organization(BaseModel):
name: str
description: str
email: str
slug :str
slug: str
class OrganizationInDB(Organization):
@ -23,6 +22,7 @@ class OrganizationInDB(Organization):
owners: List[str]
admins: List[str]
class PublicOrganization(Organization):
name: str
description: str
@ -34,9 +34,8 @@ class PublicOrganization(Organization):
#### Classes ####################################################
async def get_organization(org_id: str):
await check_database()
orgs = learnhouseDB["organizations"]
async def get_organization(request: Request, org_id: str):
orgs = request.app.db["organizations"]
org = orgs.find_one({"org_id": org_id})
@ -47,9 +46,9 @@ async def get_organization(org_id: str):
org = PublicOrganization(**org)
return org
async def get_organization_by_slug(org_slug: str):
await check_database()
orgs = learnhouseDB["organizations"]
async def get_organization_by_slug(request: Request, org_slug: str):
orgs = request.app.db["organizations"]
org = orgs.find_one({"slug": org_slug})
@ -61,9 +60,8 @@ async def get_organization_by_slug(org_slug: str):
return org
async def create_org(org_object: Organization, current_user: PublicUser):
await check_database()
orgs = learnhouseDB["organizations"]
async def create_org(request: Request, org_object: Organization, current_user: PublicUser):
orgs = request.app.db["organizations"]
# find if org already exists using name
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()
async def update_org(org_object: Organization, org_id: str, current_user: PublicUser):
await check_database()
async def update_org(request: Request, org_object: Organization, org_id: str, current_user: PublicUser):
# 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})
@ -114,12 +111,11 @@ async def update_org(org_object: Organization, org_id: str, current_user: Public
return Organization(**updated_org.dict())
async def delete_org(org_id: str, current_user: PublicUser):
await check_database()
async def delete_org(request: Request, org_id: str, current_user: PublicUser):
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})
@ -136,33 +132,21 @@ async def delete_org(org_id: str, current_user: PublicUser):
status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Unavailable database")
async def get_orgs(page: int = 1, limit: int = 10):
## TODO : Deprecated
await check_database()
orgs = learnhouseDB["organizations"]
async def get_orgs_by_user(request: Request, user_id: str, page: int = 1, limit: int = 10):
orgs = request.app.db["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)
# 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]
#### Security ####################################################
async def verify_org_rights(org_id: str, current_user: PublicUser, action: str,):
await check_database()
orgs = learnhouseDB["organizations"]
async def verify_org_rights(request: Request, org_id: str, current_user: PublicUser, action: str,):
orgs = request.app.db["organizations"]
org = orgs.find_one({"org_id": org_id})

View file

@ -3,10 +3,9 @@ from typing import List
from uuid import uuid4
from pydantic import BaseModel
from src.services.users import PublicUser, User
from src.services.database import check_database, learnhouseDB, learnhouseDB
from src.services.security import *
from src.services.houses import House
from fastapi import HTTPException, status
from fastapi import HTTPException, status, Request
from datetime import datetime
#### Classes ####################################################
@ -26,7 +25,7 @@ class Elements(BaseModel):
collections: List[str]
organizations: List[str]
coursechapters: List[str]
elements : List[str]
lectures : List[str]
class Role(BaseModel):
@ -45,9 +44,8 @@ class RoleInDB(Role):
#### Classes ####################################################
async def get_role(role_id: str):
await check_database()
roles = learnhouseDB["roles"]
async def get_role(request: Request,role_id: str):
roles = request.app.db["roles"]
role = roles.find_one({"role_id": role_id})
@ -59,9 +57,8 @@ async def get_role(role_id: str):
return role
async def create_role(role_object: Role, current_user: PublicUser):
await check_database()
roles = learnhouseDB["roles"]
async def create_role(request: Request,role_object: Role, current_user: PublicUser):
roles = request.app.db["roles"]
# find if house already exists using 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(
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
role_id = str(f"role_{uuid4()}")
@ -87,13 +84,12 @@ async def create_role(role_object: Role, current_user: PublicUser):
return role.dict()
async def update_role(role_object: Role, role_id: str, current_user: PublicUser):
await check_database()
async def update_role(request: Request,role_object: Role, role_id: str, current_user: PublicUser):
# 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})
@ -109,13 +105,12 @@ async def update_role(role_object: Role, role_id: str, current_user: PublicUser)
return RoleInDB(**updated_role.dict())
async def delete_role(role_id: str, current_user: PublicUser):
await check_database()
async def delete_role(request: Request,role_id: str, current_user: PublicUser):
# 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})
@ -132,9 +127,8 @@ async def delete_role(role_id: str, current_user: PublicUser):
status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Unavailable database")
async def get_roles(page: int = 1, limit: int = 10):
await check_database()
roles = learnhouseDB["roles"]
async def get_roles(request: Request,page: int = 1, limit: int = 10):
roles = request.app.db["roles"]
# get all roles from database
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 ####################################################
async def verify_user_permissions_on_roles(action: str, current_user: PublicUser):
await check_database()
users = learnhouseDB["users"]
async def verify_user_permissions_on_roles(request: Request,action: str, current_user: PublicUser):
users = request.app.db["users"]
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 jose import JWTError, jwt
import logging
from passlib.hash import pbkdf2_sha256
from src.services.database import check_database
from src.services.database import check_database, learnhouseDB, learnhouseDB
### 🔒 JWT ##############################################################
@ -31,12 +27,11 @@ async def security_verify_password(plain_password: str, hashed_password: str):
### 🔒 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
"""
await check_database()
roles = learnhouseDB["roles"]
roles = request.app.db["roles"]
# 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": "*"}]})
@ -77,8 +72,8 @@ async def check_element_type(element_id):
return "coursechapters"
elif element_id.startswith("collection_"):
return "collections"
elif element_id.startswith("element_"):
return "elements"
elif element_id.startswith("lecture_"):
return "lectures"
else:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Issue verifying element nature")

View file

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