Merge pull request #52 from learnhouse/feat/new-blocks

Feat/new blocks
This commit is contained in:
Badr B 2023-03-01 00:12:17 +01:00 committed by GitHub
commit 600bb96603
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 566 additions and 211 deletions

View file

@ -22,6 +22,7 @@ import { Save } from "lucide-react";
import MathEquationBlock from "./Extensions/MathEquation/MathEquationBlock"; import MathEquationBlock from "./Extensions/MathEquation/MathEquationBlock";
import PDFBlockComponent from "./Extensions/PDF/PDFBlockComponent"; import PDFBlockComponent from "./Extensions/PDF/PDFBlockComponent";
import PDFBlock from "./Extensions/PDF/PDFBlock"; import PDFBlock from "./Extensions/PDF/PDFBlock";
import QuizBlock from "./Extensions/Quiz/QuizBlock";
interface Editor { interface Editor {
content: string; content: string;
@ -65,6 +66,10 @@ function Editor(props: Editor) {
editable: true, editable: true,
lecture: props.lecture, lecture: props.lecture,
}), }),
QuizBlock.configure({
editable: true,
lecture: props.lecture,
}),
Youtube.configure({ Youtube.configure({
controls: true, controls: true,
modestBranding: true, modestBranding: true,
@ -114,7 +119,7 @@ function Editor(props: Editor) {
</EditorSaveButton> </EditorSaveButton>
</EditorInfoWrapper> </EditorInfoWrapper>
<EditorButtonsWrapper> <EditorButtonsWrapper>
<ToolbarButtons editor={editor} /> <ToolbarButtons editor={editor} />
</EditorButtonsWrapper> </EditorButtonsWrapper>
</EditorDocSection> </EditorDocSection>
<EditorUsersSection> <EditorUsersSection>
@ -279,8 +284,8 @@ export const EditorContentWrapper = styled.div`
padding-left: 20px; padding-left: 20px;
padding-right: 20px; padding-right: 20px;
padding-bottom: 20px; padding-bottom: 20px;
padding-top: 20px;
padding-top: 1px;
&:focus { &:focus {
outline: none !important; outline: none !important;
outline-style: none !important; outline-style: none !important;

View file

@ -41,7 +41,7 @@ function ImageBlockComponent(props: any) {
{fileObject && ( {fileObject && (
<BlockImage> <BlockImage>
<img <img
src={`${getBackendUrl()}content/uploads/files/pictures/${props.extension.options.lecture.lecture_id}/${fileObject.file_id}.${ src={`${getBackendUrl()}content/uploads/files/images/${props.extension.options.lecture.lecture_id}/${fileObject.file_id}.${
fileObject.file_format fileObject.file_format
}`} }`}
alt="" alt=""

View file

@ -0,0 +1,35 @@
import { mergeAttributes, Node } from "@tiptap/core";
import { ReactNodeViewRenderer } from "@tiptap/react";
import QuizBlockComponent from "./QuizBlockComponent";
export default Node.create({
name: "blockQuiz",
group: "block",
atom: true,
addAttributes() {
return {
quizId: {
value: null,
},
};
},
parseHTML() {
return [
{
tag: "block-quiz",
},
];
},
renderHTML({ HTMLAttributes }) {
return ["block-quiz", mergeAttributes(HTMLAttributes), 0];
},
addNodeView() {
return ReactNodeViewRenderer(QuizBlockComponent);
},
});

View file

@ -0,0 +1,164 @@
import { NodeViewWrapper } from "@tiptap/react";
import { v4 as uuidv4 } from "uuid";
import React from "react";
import styled from "styled-components";
import { submitQuizBlock } from "@services/blocks/Quiz/quiz";
function ImageBlockComponent(props: any) {
const [questions, setQuestions] = React.useState([]) as any;
const [answers, setAnswers] = React.useState([]) as any;
function addSampleQuestion() {
setQuestions([
...questions,
{
question_id: "question_" + uuidv4(),
question_value: "",
options: [
{
option_id: "option_" + uuidv4(),
option_data: "",
option_type: "text",
},
],
},
]);
}
const deleteQuestion = (index: number) => {
let modifiedQuestions = [...questions];
modifiedQuestions.splice(index, 1);
setQuestions(modifiedQuestions);
console.log(questions);
// remove the answers from the answers array
let modifiedAnswers = [...answers];
modifiedAnswers = modifiedAnswers.filter((answer: any) => answer.question_id !== questions[index].question_id);
setAnswers(modifiedAnswers);
};
const onQuestionChange = (e: any, index: number) => {
let modifiedQuestions = [...questions];
modifiedQuestions[index].question_value = e.target.value;
setQuestions(modifiedQuestions);
};
const addOption = (question_id: string) => {
// find the question index from the question_id and add the option to that question index
let modifiedQuestions = [...questions];
let questionIndex = modifiedQuestions.findIndex((question: any) => question.question_id === question_id);
modifiedQuestions[questionIndex].options.push({
option_id: "option_" + uuidv4(),
option_data: "",
option_type: "text",
});
setQuestions(modifiedQuestions);
};
const deleteOption = (question_id: string, option_id: string) => {
// find the option index from the option_id and delete the option from that option index
let modifiedQuestions = [...questions];
let questionIndex = modifiedQuestions.findIndex((question: any) => question.question_id === question_id);
let optionIndex = modifiedQuestions[questionIndex].options.findIndex((option: any) => option.option_id === option_id);
modifiedQuestions[questionIndex].options.splice(optionIndex, 1);
setQuestions(modifiedQuestions);
// remove the answer from the answers array
let answerIndex = answers.findIndex((answer: any) => answer.option_id === option_id);
if (answerIndex !== -1) {
let modifiedAnswers = [...answers];
modifiedAnswers.splice(answerIndex, 1);
setAnswers(modifiedAnswers);
}
};
const markOptionAsCorrect = (question_id: string, option_id: string) => {
// find the option index from the option_id and mark the option as correct
let answer = {
question_id: question_id,
option_id: option_id,
};
setAnswers([...answers, answer]);
console.log(answers);
};
const saveQuiz = async () => {
// save the questions and answers to the backend
console.log("saving quiz");
console.log(questions);
console.log(answers);
try {
let res = await submitQuizBlock(props.extension.options.lecture.lecture_id, {questions : questions , answers : answers})
console.log(res.block_id);
props.updateAttributes({
quizId: {
value : res.block_id
},
});
}
catch (error) {
console.log(error);
}
};
const onOptionChange = (e: any, questionIndex: number, optionIndex: number) => {
let modifiedQuestions = [...questions];
modifiedQuestions[questionIndex].options[optionIndex].option_data = e.target.value;
setQuestions(modifiedQuestions);
};
React.useEffect(() => {
// fetch the questions and options from the backend
console.log("fetching questions");
console.log(questions);
console.log(answers);
}, [questions, answers]);
return (
<NodeViewWrapper className="block-quiz">
<QuizBlockWrapper>
Questions <button onClick={addSampleQuestion}>Add Question</button> <button onClick={() => saveQuiz()}>Save</button>
<hr />
{questions.map((question: any, qIndex: number) => (
<>
<div key={qIndex} style={{ marginTop: "10px" }}>
Question : <input type="text" value={question.question} onChange={(e) => onQuestionChange(e, qIndex)} />
<button onClick={() => deleteQuestion(qIndex)}>Delete</button>
</div>
Answers : <br />
{question.options.map((option: any, oIndex: number) => (
<>
<div key={oIndex}>
<input type="text" value={option.option_data} onChange={(e) => onOptionChange(e, qIndex, oIndex)} />
<button onClick={() => deleteOption(question.question_id, option.option_id)}>Delete</button>
<input
type="checkbox"
onChange={(e) =>
// check if checkbox is checked or not
// if checked then add the answer to the answers array
// if unchecked then remove the answer from the answers array
e.target.checked ? markOptionAsCorrect(question.question_id, option.option_id) : null
}
/>
</div>
</>
))}
<button onClick={() => addOption(question.question_id)}>Add Option</button>
</>
))}
</QuizBlockWrapper>
</NodeViewWrapper>
);
}
const QuizBlockWrapper = styled.div`
background-color: #0000001d;
border-radius: 5px;
padding: 20px;
height: 100%;
`;
export default ImageBlockComponent;

View file

@ -1,8 +1,8 @@
import styled from "styled-components"; import styled from "styled-components";
import { FontBoldIcon, FontItalicIcon, StrikethroughIcon, ArrowLeftIcon, ArrowRightIcon, OpacityIcon } from "@radix-ui/react-icons"; import { FontBoldIcon, FontItalicIcon, StrikethroughIcon, ArrowLeftIcon, ArrowRightIcon, OpacityIcon } from "@radix-ui/react-icons";
import { AlertCircle, AlertTriangle, FileText, ImagePlus, Info, Sigma, Video, Youtube } from "lucide-react"; import { AlertCircle, AlertTriangle, FileText, GraduationCap, ImagePlus, Info, Sigma, Video, Youtube } from "lucide-react";
export const ToolbarButtons = ({ editor }: any) => { export const ToolbarButtons = ({ editor, props }: any) => {
if (!editor) { if (!editor) {
return null; return null;
} }
@ -116,6 +116,19 @@ export const ToolbarButtons = ({ editor }: any) => {
> >
<FileText size={15} /> <FileText size={15} />
</ToolBtn> </ToolBtn>
<ToolBtn
onClick={() =>
editor
.chain()
.focus()
.insertContent({
type: "blockQuiz",
})
.run()
}
>
<GraduationCap size={15} />
</ToolBtn>
</ToolButtonsWrapper> </ToolButtonsWrapper>
); );
}; };

View file

@ -34,6 +34,9 @@ const Overlay = styled.div`
width: 100%; width: 100%;
height: 100%; height: 100%;
z-index: 100; z-index: 100;
background-color: #00000029;
backdrop-filter: blur(1px);
`; `;
const Content = styled.div` const Content = styled.div`

View file

@ -26,6 +26,7 @@
"react-katex": "^3.0.1", "react-katex": "^3.0.1",
"styled-components": "^6.0.0-beta.9", "styled-components": "^6.0.0-beta.9",
"swr": "^2.0.1", "swr": "^2.0.1",
"uuid": "^9.0.0",
"y-indexeddb": "^9.0.9", "y-indexeddb": "^9.0.9",
"y-webrtc": "^10.2.3", "y-webrtc": "^10.2.3",
"yjs": "^13.5.42" "yjs": "^13.5.42"
@ -37,6 +38,7 @@
"@types/react-dom": "18.0.6", "@types/react-dom": "18.0.6",
"@types/react-katex": "^3.0.0", "@types/react-katex": "^3.0.0",
"@types/styled-components": "^5.1.26", "@types/styled-components": "^5.1.26",
"@types/uuid": "^9.0.0",
"autoprefixer": "^10.4.12", "autoprefixer": "^10.4.12",
"eslint": "8.23.1", "eslint": "8.23.1",
"eslint-config-next": "^13.0.6", "eslint-config-next": "^13.0.6",
@ -3058,6 +3060,12 @@
"csstype": "^3.0.2" "csstype": "^3.0.2"
} }
}, },
"node_modules/@types/uuid": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.0.tgz",
"integrity": "sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==",
"dev": true
},
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "5.46.1", "version": "5.46.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.46.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.46.1.tgz",
@ -7088,6 +7096,14 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
}, },
"node_modules/uuid": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
"integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/w3c-keyname": { "node_modules/w3c-keyname": {
"version": "2.2.6", "version": "2.2.6",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
@ -9309,6 +9325,12 @@
"csstype": "^3.0.2" "csstype": "^3.0.2"
} }
}, },
"@types/uuid": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.0.tgz",
"integrity": "sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==",
"dev": true
},
"@typescript-eslint/parser": { "@typescript-eslint/parser": {
"version": "5.46.1", "version": "5.46.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.46.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.46.1.tgz",
@ -12128,6 +12150,11 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
}, },
"uuid": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
"integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg=="
},
"w3c-keyname": { "w3c-keyname": {
"version": "2.2.6", "version": "2.2.6",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",

View file

@ -27,6 +27,7 @@
"react-katex": "^3.0.1", "react-katex": "^3.0.1",
"styled-components": "^6.0.0-beta.9", "styled-components": "^6.0.0-beta.9",
"swr": "^2.0.1", "swr": "^2.0.1",
"uuid": "^9.0.0",
"y-indexeddb": "^9.0.9", "y-indexeddb": "^9.0.9",
"y-webrtc": "^10.2.3", "y-webrtc": "^10.2.3",
"yjs": "^13.5.42" "yjs": "^13.5.42"
@ -38,6 +39,7 @@
"@types/react-dom": "18.0.6", "@types/react-dom": "18.0.6",
"@types/react-katex": "^3.0.0", "@types/react-katex": "^3.0.0",
"@types/styled-components": "^5.1.26", "@types/styled-components": "^5.1.26",
"@types/uuid": "^9.0.0",
"autoprefixer": "^10.4.12", "autoprefixer": "^10.4.12",
"eslint": "8.23.1", "eslint": "8.23.1",
"eslint-config-next": "^13.0.6", "eslint-config-next": "^13.0.6",

View file

@ -0,0 +1,10 @@
import { getAPIUrl } from "@services/config";
import { RequestBody, RequestBodyForm } from "@services/utils/requests";
export async function submitQuizBlock(lecture_id: string, data: any) {
const result: any = await fetch(`${getAPIUrl()}blocks/quiz/${lecture_id}"`, RequestBody("POST", data))
.then((result) => result.json())
.catch((error) => console.log("error", error));
return result;
}

View file

@ -7,14 +7,14 @@ export async function uploadNewPDFFile(file: any, lecture_id: string) {
formData.append("file_object", file); formData.append("file_object", file);
formData.append("lecture_id", lecture_id); formData.append("lecture_id", lecture_id);
return fetch(`${getAPIUrl()}files/document`, RequestBodyForm("POST", formData)) return fetch(`${getAPIUrl()}blocks/document`, RequestBodyForm("POST", formData))
.then((result) => result.json()) .then((result) => result.json())
.catch((error) => console.log("error", error)); .catch((error) => console.log("error", error));
} }
export async function getPDFFile(file_id: string) { export async function getPDFFile(file_id: string) {
// todo : add course id to url // todo : add course id to url
return fetch(`${getAPIUrl()}files/document?file_id=${file_id}`, RequestBody("GET", null)) return fetch(`${getAPIUrl()}blocks/document?file_id=${file_id}`, RequestBody("GET", null))
.then((result) => result.json()) .then((result) => result.json())
.catch((error) => console.log("error", error)); .catch((error) => console.log("error", error));
} }

View file

@ -7,14 +7,14 @@ export async function uploadNewImageFile(file: any, lecture_id: string) {
formData.append("file_object", file); formData.append("file_object", file);
formData.append("lecture_id", lecture_id); formData.append("lecture_id", lecture_id);
return fetch(`${getAPIUrl()}files/picture`, RequestBodyForm("POST", formData)) return fetch(`${getAPIUrl()}blocks/image`, RequestBodyForm("POST", formData))
.then((result) => result.json()) .then((result) => result.json())
.catch((error) => console.log("error", error)); .catch((error) => console.log("error", error));
} }
export async function getImageFile(file_id: string) { export async function getImageFile(file_id: string) {
// todo : add course id to url // todo : add course id to url
return fetch(`${getAPIUrl()}files/picture?file_id=${file_id}`, RequestBody("GET", null)) return fetch(`${getAPIUrl()}blocks/image?file_id=${file_id}`, RequestBody("GET", null))
.then((result) => result.json()) .then((result) => result.json())
.catch((error) => console.log("error", error)); .catch((error) => console.log("error", error));
} }

View file

@ -7,13 +7,13 @@ export async function uploadNewVideoFile(file: any, lecture_id: string) {
formData.append("file_object", file); formData.append("file_object", file);
formData.append("lecture_id", lecture_id); formData.append("lecture_id", lecture_id);
return fetch(`${getAPIUrl()}files/video`, RequestBodyForm("POST", formData)) return fetch(`${getAPIUrl()}blocks/video`, RequestBodyForm("POST", formData))
.then((result) => result.json()) .then((result) => result.json())
.catch((error) => console.log("error", error)); .catch((error) => console.log("error", error));
} }
export async function getVideoFile(file_id: string) { export async function getVideoFile(file_id: string) {
return fetch(`${getAPIUrl()}files/video?file_id=${file_id}`, RequestBody("GET", null)) return fetch(`${getAPIUrl()}blocks/video?file_id=${file_id}`, RequestBody("GET", null))
.then((result) => result.json()) .then((result) => result.json())
.catch((error) => console.log("error", error)); .catch((error) => console.log("error", error));
} }

View file

@ -1,7 +1,8 @@
fastapi==0.89.1 fastapi==0.92.0
pydantic>=1.8.0,<2.0.0 pydantic>=1.8.0,<2.0.0
uvicorn==0.20.0 uvicorn==0.20.0
pymongo==4.1.1 pymongo==4.3.3
motor==3.1.1
python-multipart python-multipart
python-jose python-jose
passlib passlib

View file

@ -1,11 +1,11 @@
import logging import logging
from fastapi import FastAPI from fastapi import FastAPI
import pymongo import motor.motor_asyncio
async def connect_to_db(app: FastAPI) : async def connect_to_db(app: FastAPI) :
logging.info("Connecting to database...") logging.info("Connecting to database...")
try: try:
app.mongodb_client = pymongo.MongoClient("mongodb://learnhouse:learnhouse@mongo:27017/") # type: ignore app.mongodb_client = motor.motor_asyncio.AsyncIOMotorClient("mongodb://learnhouse:learnhouse@mongo:27017/") # type: ignore
app.db = app.mongodb_client["learnhouse"] # type: ignore app.db = app.mongodb_client["learnhouse"] # type: ignore
logging.info("Connected to database!") logging.info("Connected to database!")
except Exception as e: except Exception as e:

View file

@ -1,5 +1,5 @@
from fastapi import APIRouter from fastapi import APIRouter
from src.routers import activity, users, auth, houses, orgs, roles, files from src.routers import activity, blocks, users, auth, houses, orgs, roles
from src.routers.courses import chapters, collections, courses,lectures from src.routers.courses import chapters, collections, courses,lectures
@ -12,7 +12,7 @@ global_router.include_router(auth.router, prefix="/auth", tags=["auth"])
global_router.include_router(houses.router, prefix="/houses", tags=["houses"]) global_router.include_router(houses.router, prefix="/houses", tags=["houses"])
global_router.include_router(orgs.router, prefix="/orgs", tags=["orgs"]) global_router.include_router(orgs.router, prefix="/orgs", tags=["orgs"])
global_router.include_router(roles.router, prefix="/roles", tags=["roles"]) global_router.include_router(roles.router, prefix="/roles", tags=["roles"])
global_router.include_router(files.router, prefix="/files", tags=["files"]) global_router.include_router(blocks.router, prefix="/blocks", tags=["blocks"])
global_router.include_router(courses.router, prefix="/courses", tags=["courses"]) global_router.include_router(courses.router, prefix="/courses", tags=["courses"])
global_router.include_router(chapters.router, prefix="/chapters", tags=["chapters"]) global_router.include_router(chapters.router, prefix="/chapters", tags=["chapters"])
global_router.include_router(lectures.router, prefix="/lectures", tags=["lectures"]) global_router.include_router(lectures.router, prefix="/lectures", tags=["lectures"])

80
src/routers/blocks.py Normal file
View file

@ -0,0 +1,80 @@
from fastapi import APIRouter, Depends, UploadFile, Form, Request
from src.dependencies.auth import get_current_user
from fastapi import HTTPException, status, UploadFile
from src.services.blocks.imageBlock.images import create_image_file, get_image_file
from src.services.blocks.videoBlock.videos import create_video_file, get_video_file
from src.services.blocks.pdfBlock.documents import create_document_file, get_document_file
from src.services.blocks.quizBlock.quizBlock import create_quiz_block, get_quiz_block_answers, get_quiz_block_options, quizBlock
from src.services.users import PublicUser
router = APIRouter()
@router.post("/image")
async def api_create_image_file_block(request: Request, file_object: UploadFile, lecture_id: str = Form(), current_user: PublicUser = Depends(get_current_user)):
"""
Create new image file
"""
return await create_image_file(request, file_object, lecture_id)
@router.get("/image")
async def api_get_image_file_block(request: Request, file_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Get image file
"""
return await get_image_file(request, file_id, current_user)
@router.post("/video")
async def api_create_video_file_block(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(request, file_object, lecture_id)
@router.get("/video")
async def api_get_video_file_block(request: Request, file_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Get video file
"""
return await get_video_file(request, file_id, current_user)
@router.post("/document")
async def api_create_document_file_block(request: Request, file_object: UploadFile, lecture_id: str = Form(), current_user: PublicUser = Depends(get_current_user)):
"""
Create new document file
"""
return await create_document_file(request, file_object, lecture_id)
@router.get("/document")
async def api_get_document_file_block(request: Request, file_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Get document file
"""
return await get_document_file(request, file_id, current_user)
@router.post("/quiz/{lecture_id}")
async def api_create_quiz_block(request: Request, quiz_block: quizBlock, lecture_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Create new document file
"""
return await create_quiz_block(request, quiz_block, lecture_id, current_user)
@router.get("/quiz/options")
async def api_get_quiz_options(request: Request, block_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Get quiz options
"""
return await get_quiz_block_options(request, block_id, current_user)
@router.get("/quiz/answers")
async def api_get_quiz_answers(request: Request, block_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Get quiz answers
"""
return await get_quiz_block_answers(request, block_id, current_user)

View file

@ -1,58 +0,0 @@
from fastapi import APIRouter, Depends, UploadFile, Form, Request
from src.dependencies.auth import get_current_user
from fastapi import HTTPException, status, UploadFile
from src.services.files.documents import create_document_file, get_document_file
from src.services.files.pictures import create_picture_file, get_picture_file
from src.services.files.videos import create_video_file, get_video_file
from src.services.users import PublicUser
router = APIRouter()
@router.post("/picture")
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(request, file_object, lecture_id)
@router.post("/video")
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(request, file_object, lecture_id)
@router.get("/picture")
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(request, file_id, current_user)
@router.get("/video")
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(request, file_id, current_user)
@router.get("/document")
async def api_get_document_file(request: Request, file_id: str, current_user: PublicUser = Depends(get_current_user)):
"""
Get document file
"""
return await get_document_file(request, file_id, current_user)
@router.post("/document")
async def api_create_document_file(request: Request, file_object: UploadFile, lecture_id: str = Form(), current_user: PublicUser = Depends(get_current_user)):
"""
Create new document file
"""
return await create_document_file(request, file_object, lecture_id)

View file

@ -35,13 +35,13 @@ async def create_activity(request: Request, user: PublicUser, activity_object: A
activities = request.app.db["activities"] activities = request.app.db["activities"]
# find if the user has already started the course # find if the user has already started the course
isActivityAlreadCreated = activities.find_one( isActivityAlreadCreated = await activities.find_one(
{"course_id": activity_object.course_id, "user_id": user.user_id}) {"course_id": activity_object.course_id, "user_id": user.user_id})
if isActivityAlreadCreated: if isActivityAlreadCreated:
if isActivityAlreadCreated['status'] == 'closed': if isActivityAlreadCreated['status'] == 'closed':
activity_object.status = 'ongoing' activity_object.status = 'ongoing'
activities.update_one( await activities.update_one(
{"activity_id": isActivityAlreadCreated['activity_id']}, {"$set": activity_object.dict()}) {"activity_id": isActivityAlreadCreated['activity_id']}, {"$set": activity_object.dict()})
return activity_object return activity_object
else: else:
@ -54,7 +54,7 @@ async def create_activity(request: Request, user: PublicUser, activity_object: A
activity = ActivityInDB(**activity_object.dict(),activity_id=activity_id, activity = ActivityInDB(**activity_object.dict(),activity_id=activity_id,
user_id=user.user_id, org_id=activity_object.course_id) user_id=user.user_id, org_id=activity_object.course_id)
activities.insert_one(activity.dict()) await activities.insert_one(activity.dict())
return activity return activity
@ -73,7 +73,7 @@ async def get_user_activities(request: Request, user: PublicUser, org_id: str):
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="No activities found") status_code=status.HTTP_409_CONFLICT, detail="No activities found")
for activity in user_activities: for activity in await user_activities.to_list(length=100):
# get number of lectures in the course # get number of lectures in the course
coursechapters = await get_coursechapters_meta(request, activity['course_id'], user) coursechapters = await get_coursechapters_meta(request, activity['course_id'], user)
@ -81,7 +81,7 @@ async def get_user_activities(request: Request, user: PublicUser, org_id: str):
progression = round( progression = round(
len(activity['lectures_marked_complete']) / len(coursechapters['lectures']) * 100, 2) len(activity['lectures_marked_complete']) / len(coursechapters['lectures']) * 100, 2)
course = courses.find_one({"course_id": activity['course_id']}, {'_id': 0}) course = await courses.find_one({"course_id": activity['course_id']}, {'_id': 0})
# add progression to the activity # add progression to the activity
one_activity = {"course": course, "activitydata": activity, "progression": progression} one_activity = {"course": course, "activitydata": activity, "progression": progression}
@ -103,7 +103,7 @@ async def get_user_activities_orgslug(request: Request, user: PublicUser, org_sl
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="No activities found") status_code=status.HTTP_409_CONFLICT, detail="No activities found")
for activity in user_activities: for activity in await user_activities.to_list(length=100):
# get number of lectures in the course # get number of lectures in the course
coursechapters = await get_coursechapters_meta(request, activity['course_id'], user) coursechapters = await get_coursechapters_meta(request, activity['course_id'], user)
@ -111,7 +111,7 @@ async def get_user_activities_orgslug(request: Request, user: PublicUser, org_sl
progression = round( progression = round(
len(activity['lectures_marked_complete']) / len(coursechapters['lectures']) * 100, 2) len(activity['lectures_marked_complete']) / len(coursechapters['lectures']) * 100, 2)
course = courses.find_one({"course_id": activity['course_id']}, {'_id': 0}) course = await courses.find_one({"course_id": activity['course_id']}, {'_id': 0})
# add progression to the activity # add progression to the activity
one_activity = {"course": course, "activitydata": activity, "progression": progression} one_activity = {"course": course, "activitydata": activity, "progression": progression}
@ -125,14 +125,14 @@ async def add_lecture_to_activity(request: Request, user: PublicUser, org_id: st
course_id = f"course_{course_id}" course_id = f"course_{course_id}"
lecture_id = f"lecture_{lecture_id}" lecture_id = f"lecture_{lecture_id}"
activity = activities.find_one( activity = await activities.find_one(
{"course_id": course_id, {"course_id": course_id,
"user_id": user.user_id "user_id": user.user_id
}, {'_id': 0}) }, {'_id': 0})
if lecture_id not in activity['lectures_marked_complete']: if lecture_id not in activity['lectures_marked_complete']:
activity['lectures_marked_complete'].append(str(lecture_id)) activity['lectures_marked_complete'].append(str(lecture_id))
activities.update_one( await activities.update_one(
{"activity_id": activity['activity_id']}, {"$set": activity}) {"activity_id": activity['activity_id']}, {"$set": activity})
return activity return activity
@ -147,7 +147,7 @@ async def add_lecture_to_activity(request: Request, user: PublicUser, org_id: st
async def close_activity(request: Request, user: PublicUser, activity_id: str, org_id: str,): async def close_activity(request: Request, user: PublicUser, activity_id: str, org_id: str,):
activities = request.app.db["activities"] activities = request.app.db["activities"]
activity = activities.find_one( activity = await activities.find_one(
{"activity_id": activity_id, "user_id": user.user_id}) {"activity_id": activity_id, "user_id": user.user_id})
if not activity: if not activity:
@ -156,7 +156,7 @@ async def close_activity(request: Request, user: PublicUser, activity_id: str,
activity['status'] = 'closed' activity['status'] = 'closed'
activities.update_one( await activities.update_one(
{"activity_id": activity['activity_id']}, {"$set": activity}) {"activity_id": activity['activity_id']}, {"$set": activity})
activity = ActivityInDB(**activity) activity = ActivityInDB(**activity)

View file

@ -0,0 +1,12 @@
from typing import Any, List, Literal
from uuid import uuid4
from fastapi import Request
from pydantic import BaseModel
class Block(BaseModel):
block_id: str
lecture_id: str
block_type: Literal["quizBlock", "videoBlock", "pdfBlock"]
block_data: Any

View file

@ -16,31 +16,31 @@ class PhotoFile(BaseModel):
lecture_id: str lecture_id: str
async def create_picture_file(request: Request,picture_file: UploadFile, lecture_id: str): async def create_image_file(request: Request,image_file: UploadFile, lecture_id: str):
photos = request.app.db["files"] photos = request.app.db["files"]
# generate file_id # generate file_id
file_id = str(f"file_{uuid4()}") file_id = str(f"file_{uuid4()}")
# get file format # get file format
file_format = picture_file.filename.split(".")[-1] file_format = image_file.filename.split(".")[-1]
# validate file format # validate file format
if file_format not in ["jpg", "jpeg", "png", "gif"]: if file_format not in ["jpg", "jpeg", "png", "gif"]:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Picture file format not supported") status_code=status.HTTP_409_CONFLICT, detail="Image file format not supported")
# create file # create file
file = await picture_file.read() file = await image_file.read()
# get file size # get file size
file_size = len(file) file_size = len(file)
# get file type # get file type
file_type = picture_file.content_type file_type = image_file.content_type
# get file name # get file name
file_name = picture_file.filename file_name = image_file.filename
# create file object # create file object
uploadable_file = PhotoFile( uploadable_file = PhotoFile(
@ -53,16 +53,16 @@ async def create_picture_file(request: Request,picture_file: UploadFile, lecture
) )
# create folder for lecture # create folder for lecture
if not os.path.exists(f"content/uploads/files/pictures/{lecture_id}"): if not os.path.exists(f"content/uploads/files/images/{lecture_id}"):
os.mkdir(f"content/uploads/files/pictures/{lecture_id}") os.mkdir(f"content/uploads/files/images/{lecture_id}")
# upload file to server # upload file to server
with open(f"content/uploads/files/pictures/{lecture_id}/{file_id}.{file_format}", 'wb') as f: with open(f"content/uploads/files/images/{lecture_id}/{file_id}.{file_format}", 'wb') as f:
f.write(file) f.write(file)
f.close() f.close()
# insert file object into database # insert file object into database
photo_file_in_db = photos.insert_one(uploadable_file.dict()) photo_file_in_db = await photos.insert_one(uploadable_file.dict())
if not photo_file_in_db: if not photo_file_in_db:
raise HTTPException( raise HTTPException(
@ -71,10 +71,10 @@ async def create_picture_file(request: Request,picture_file: UploadFile, lecture
return uploadable_file return uploadable_file
async def get_picture_object(request: Request,file_id: str): async def get_image_object(request: Request,file_id: str):
photos = request.app.db["files"] photos = request.app.db["files"]
photo_file = photos.find_one({"file_id": file_id}) photo_file = await photos.find_one({"file_id": file_id})
if photo_file: if photo_file:
photo_file = PhotoFile(**photo_file) photo_file = PhotoFile(**photo_file)
@ -85,10 +85,10 @@ async def get_picture_object(request: Request,file_id: str):
status_code=status.HTTP_409_CONFLICT, detail="Photo file does not exist") status_code=status.HTTP_409_CONFLICT, detail="Photo file does not exist")
async def get_picture_file(request: Request,file_id: str, current_user: PublicUser): async def get_image_file(request: Request,file_id: str, current_user: PublicUser):
photos = request.app.db["files"] photos = request.app.db["files"]
photo_file = photos.find_one({"file_id": file_id}) photo_file = await photos.find_one({"file_id": file_id})
# TODO : check if user has access to file # TODO : check if user has access to file
@ -104,7 +104,7 @@ async def get_picture_file(request: Request,file_id: str, current_user: PublicUs
file_format = photo_file.file_format file_format = photo_file.file_format
lecture_id = photo_file.lecture_id lecture_id = photo_file.lecture_id
file = open( file = open(
f"content/uploads/files/pictures/{lecture_id}/{file_id}.{file_format}", 'rb') f"content/uploads/files/images/{lecture_id}/{file_id}.{file_format}", 'rb')
return StreamingResponse(file, media_type=photo_file.file_type) return StreamingResponse(file, media_type=photo_file.file_type)
else: else:

View file

@ -62,7 +62,7 @@ async def create_document_file(request: Request, document_file: UploadFile, lect
f.close() f.close()
# insert file object into database # insert file object into database
document_file_in_db = documents.insert_one(uploadable_file.dict()) document_file_in_db = await documents.insert_one(uploadable_file.dict())
if not document_file_in_db: if not document_file_in_db:
raise HTTPException( raise HTTPException(
@ -74,7 +74,7 @@ async def create_document_file(request: Request, document_file: UploadFile, lect
async def get_document_object(request: Request, file_id: str): async def get_document_object(request: Request, file_id: str):
documents = request.app.db["files"] documents = request.app.db["files"]
document_file = documents.find_one({"file_id": file_id}) document_file = await documents.find_one({"file_id": file_id})
if document_file: if document_file:
document_file = DocumentFile(**document_file) document_file = DocumentFile(**document_file)
@ -88,14 +88,14 @@ async def get_document_object(request: Request, file_id: str):
async def get_document_file(request: Request, file_id: str, current_user: PublicUser): async def get_document_file(request: Request, file_id: str, current_user: PublicUser):
documents = request.app.db["files"] documents = request.app.db["files"]
document_file = documents.find_one({"file_id": file_id}) document_file = await documents.find_one({"file_id": file_id})
# TODO : check if user has access to file # TODO : check if user has access to file
if document_file: if document_file:
# check media type # check media type
if document_file.format not in ["jpg", "jpeg", "png", "gif"]: if document_file.format not in ["pdf"]:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Document file format not supported") status_code=status.HTTP_409_CONFLICT, detail="Document file format not supported")

View file

@ -0,0 +1,60 @@
from typing import List, Literal
from uuid import uuid4
from fastapi import Request
from pydantic import BaseModel
from src.services.blocks.blocks import Block
from src.services.users import PublicUser
class option(BaseModel):
option_id: str
option_type: Literal["text", "image"]
option_data: str
class answer(BaseModel):
question_id: str
option_id: str
class question(BaseModel):
question_id: str
question_value:str
options: List[option]
class quizBlock(BaseModel):
questions: List[question]
answers: List[answer]
async def create_quiz_block(request: Request, quizBlock: quizBlock, lecture_id: str, user: PublicUser):
blocks = request.app.db["blocks"]
block_id = str(f"block_{uuid4()}")
# create block
block = Block(block_id=block_id, lecture_id=lecture_id,
block_type="quizBlock", block_data=quizBlock)
# insert block
await blocks.insert_one(block.dict())
return block
async def get_quiz_block_options(request: Request, block_id: str, user: PublicUser):
blocks = request.app.db["blocks"]
# find block but get only the options
block = await blocks.find_one({"block_id": block_id, }, {
"_id": 0, "block_data.answers": 0})
return block
async def get_quiz_block_answers(request: Request, block_id: str, user: PublicUser):
blocks = request.app.db["blocks"]
# find block but get only the answers
block = await blocks.find_one({"block_id": block_id, }, {
"_id": 0, "block_data.questions": 0})
return block

View file

@ -62,7 +62,7 @@ async def create_video_file(request: Request,video_file: UploadFile, lecture_id:
f.close() f.close()
# insert file object into database # insert file object into database
video_file_in_db = files.insert_one(uploadable_file.dict()) video_file_in_db = await files.insert_one(uploadable_file.dict())
if not video_file_in_db: if not video_file_in_db:
raise HTTPException( raise HTTPException(
@ -74,7 +74,7 @@ async def create_video_file(request: Request,video_file: UploadFile, lecture_id:
async def get_video_object(request: Request,file_id: str, current_user: PublicUser): async def get_video_object(request: Request,file_id: str, current_user: PublicUser):
photos = request.app.db["files"] photos = request.app.db["files"]
video_file = photos.find_one({"file_id": file_id}) video_file = await photos.find_one({"file_id": file_id})
if video_file: if video_file:
video_file = VideoFile(**video_file) video_file = VideoFile(**video_file)
@ -88,7 +88,7 @@ async def get_video_object(request: Request,file_id: str, current_user: PublicUs
async def get_video_file(request: Request,file_id: str, current_user: PublicUser): async def get_video_file(request: Request,file_id: str, current_user: PublicUser):
photos = request.app.db["files"] photos = request.app.db["files"]
video_file = photos.find_one({"file_id": file_id}) video_file = await photos.find_one({"file_id": file_id})
# TODO : check if user has access to file # TODO : check if user has access to file

View file

@ -26,7 +26,7 @@ class CourseChapterInDB(CourseChapter):
# Frontend # Frontend
class CourseChapterMetaData(BaseModel): class CourseChapterMetaData(BaseModel):
chapterOrder: List[str] chapterOrder: List[str]
chapters: object chapters: dict
lectures: object lectures: object
#### Classes #################################################### #### Classes ####################################################
@ -52,7 +52,7 @@ async def create_coursechapter(request: Request,coursechapter_object: CourseChap
coursechapter = CourseChapterInDB(coursechapter_id=coursechapter_id, creationDate=str( coursechapter = CourseChapterInDB(coursechapter_id=coursechapter_id, creationDate=str(
datetime.now()), updateDate=str(datetime.now()), course_id=course_id, **coursechapter_object.dict()) datetime.now()), updateDate=str(datetime.now()), course_id=course_id, **coursechapter_object.dict())
coursechapter_in_db = coursechapters.insert_one(coursechapter.dict()) coursechapter_in_db = await coursechapters.insert_one(coursechapter.dict())
courses.update_one({"course_id": course_id}, { courses.update_one({"course_id": course_id}, {
"$addToSet": {"chapters": coursechapter_id}}) "$addToSet": {"chapters": coursechapter_id}})
@ -66,7 +66,7 @@ async def create_coursechapter(request: Request,coursechapter_object: CourseChap
async def get_coursechapter(request: Request,coursechapter_id: str, current_user: PublicUser): async def get_coursechapter(request: Request,coursechapter_id: str, current_user: PublicUser):
coursechapters = request.app.db["coursechapters"] coursechapters = request.app.db["coursechapters"]
coursechapter = coursechapters.find_one( coursechapter = await coursechapters.find_one(
{"coursechapter_id": coursechapter_id}) {"coursechapter_id": coursechapter_id})
if coursechapter: if coursechapter:
@ -84,7 +84,7 @@ async def get_coursechapter(request: Request,coursechapter_id: str, current_user
async def update_coursechapter(request: Request,coursechapter_object: CourseChapter, coursechapter_id: str, current_user: PublicUser): async def update_coursechapter(request: Request,coursechapter_object: CourseChapter, coursechapter_id: str, current_user: PublicUser):
coursechapters = request.app.db["coursechapters"] coursechapters = request.app.db["coursechapters"]
coursechapter = coursechapters.find_one( coursechapter = await coursechapters.find_one(
{"coursechapter_id": coursechapter_id}) {"coursechapter_id": coursechapter_id})
if coursechapter: if coursechapter:
@ -98,7 +98,7 @@ async def update_coursechapter(request: Request,coursechapter_object: CourseChap
updated_coursechapter = CourseChapterInDB( updated_coursechapter = CourseChapterInDB(
coursechapter_id=coursechapter_id, creationDate=creationDate, course_id=coursechapter["course_id"], updateDate=str(datetime_object), **coursechapter_object.dict()) coursechapter_id=coursechapter_id, creationDate=creationDate, course_id=coursechapter["course_id"], updateDate=str(datetime_object), **coursechapter_object.dict())
coursechapters.update_one({"coursechapter_id": coursechapter_id}, { await coursechapters.update_one({"coursechapter_id": coursechapter_id}, {
"$set": updated_coursechapter.dict()}) "$set": updated_coursechapter.dict()})
return CourseChapterInDB(**updated_coursechapter.dict()) return CourseChapterInDB(**updated_coursechapter.dict())
@ -113,18 +113,18 @@ async def delete_coursechapter(request: Request,coursechapter_id: str, current_
coursechapters = request.app.db["coursechapters"] coursechapters = request.app.db["coursechapters"]
courses = request.app.db["courses"] courses = request.app.db["courses"]
coursechapter = coursechapters.find_one( coursechapter = await coursechapters.find_one(
{"coursechapter_id": coursechapter_id}) {"coursechapter_id": coursechapter_id})
if coursechapter: if coursechapter:
# verify course rights # verify course rights
await verify_rights(request, coursechapter["course_id"], current_user, "delete") await verify_rights(request, coursechapter["course_id"], current_user, "delete")
isDeleted = coursechapters.delete_one( isDeleted = await coursechapters.delete_one(
{"coursechapter_id": coursechapter_id}) {"coursechapter_id": coursechapter_id})
# Remove coursechapter from course # Remove coursechapter from course
courses.update_one({"course_id": coursechapter["course_id"]}, { await courses.update_one({"course_id": coursechapter["course_id"]}, {
"$pull": {"chapters": coursechapter_id}}) "$pull": {"chapters": coursechapter_id}})
if isDeleted: if isDeleted:
@ -149,7 +149,7 @@ async def get_coursechapters(request: Request,course_id: str, page: int = 1, lim
all_coursechapters = courses.find({"course_id": course_id}).sort( all_coursechapters = courses.find({"course_id": course_id}).sort(
"name", 1).skip(10 * (page - 1)).limit(limit) "name", 1).skip(10 * (page - 1)).limit(limit)
return [json.loads(json.dumps(coursechapter, default=str)) for coursechapter in all_coursechapters] return [json.loads(json.dumps(coursechapter, default=str)) for coursechapter in await all_coursechapters.to_list(length=100)]
async def get_coursechapters_meta(request: Request, course_id: str, current_user: PublicUser): async def get_coursechapters_meta(request: Request, course_id: str, current_user: PublicUser):
@ -160,7 +160,7 @@ async def get_coursechapters_meta(request: Request, course_id: str, current_user
coursechapters = coursechapters.find( coursechapters = coursechapters.find(
{"course_id": course_id}).sort("name", 1) {"course_id": course_id}).sort("name", 1)
course = courses.find_one({"course_id": course_id}) course = await courses.find_one({"course_id": course_id})
course = Course(**course) # type: ignore course = Course(**course) # type: ignore
# lectures # lectures
@ -168,7 +168,7 @@ async def get_coursechapters_meta(request: Request, course_id: str, current_user
# chapters # chapters
chapters = {} chapters = {}
for coursechapter in coursechapters: for coursechapter in await coursechapters.to_list(length=100):
coursechapter = CourseChapterInDB(**coursechapter) coursechapter = CourseChapterInDB(**coursechapter)
coursechapter_lectureIds = [] coursechapter_lectureIds = []
@ -182,7 +182,7 @@ async def get_coursechapters_meta(request: Request, course_id: str, current_user
# lectures # lectures
lectures_list = {} lectures_list = {}
for lecture in lectures.find({"lecture_id": {"$in": coursechapter_lectureIds_global}}): for lecture in await lectures.find({"lecture_id": {"$in": coursechapter_lectureIds_global}}).to_list(length=100):
lecture = LectureInDB(**lecture) lecture = LectureInDB(**lecture)
lectures_list[lecture.lecture_id] = { lectures_list[lecture.lecture_id] = {
"id": lecture.lecture_id, "name": lecture.name, "type": lecture.type, "content": lecture.content "id": lecture.lecture_id, "name": lecture.name, "type": lecture.type, "content": lecture.content
@ -202,14 +202,18 @@ async def update_coursechapters_meta(request: Request,course_id: str, coursechap
courses = request.app.db["courses"] courses = request.app.db["courses"]
# update chapters in course # update chapters in course
courseInDB = courses.update_one({"course_id": course_id}, { courseInDB = await courses.update_one({"course_id": course_id}, {
"$set": {"chapters": coursechapters_metadata.chapterOrder}}) "$set": {"chapters": coursechapters_metadata.chapterOrder}})
# update lectures in coursechapters if coursechapters_metadata.chapters is not None:
# TODO : performance/optimization improvement, this does not work anyway. for coursechapter_id, chapter_metadata in coursechapters_metadata.chapters.items():
for coursechapter in coursechapters_metadata.chapters.__dict__.items(): filter_query = {"coursechapter_id": coursechapter_id}
coursechapters.update_one({"coursechapter_id": coursechapter}, { update_query = {"$set": {"lectures": chapter_metadata["lectureIds"]}}
"$set": {"lectures": coursechapters_metadata.chapters[coursechapter]["lectureIds"]}}) # type: ignore result = await coursechapters.update_one(filter_query, update_query)
if result.matched_count == 0:
# handle error when no documents are matched by the filter query
print(f"No documents found for course chapter ID {coursechapter_id}")
return {"detail": "coursechapters metadata updated"} return {"detail": "coursechapters metadata updated"}
@ -219,7 +223,7 @@ async def update_coursechapters_meta(request: Request,course_id: str, coursechap
async def verify_rights(request: Request,course_id: str, current_user: PublicUser, action: str): async def verify_rights(request: Request,course_id: str, current_user: PublicUser, action: str):
courses = request.app.db["courses"] courses = request.app.db["courses"]
course = courses.find_one({"course_id": course_id}) course = await courses.find_one({"course_id": course_id})
if not course: if not course:
raise HTTPException( raise HTTPException(

View file

@ -30,7 +30,7 @@ class CollectionInDB(Collection):
async def get_collection(request: Request,collection_id: str, current_user: PublicUser): async def get_collection(request: Request,collection_id: str, current_user: PublicUser):
collections = request.app.db["collections"] collections = request.app.db["collections"]
collection = collections.find_one({"collection_id": collection_id}) collection = await collections.find_one({"collection_id": collection_id})
# verify collection rights # verify collection rights
await verify_collection_rights(request, collection_id, current_user, "read") await verify_collection_rights(request, collection_id, current_user, "read")
@ -47,7 +47,7 @@ async def create_collection(request: Request,collection_object: Collection, curr
collections = request.app.db["collections"] collections = request.app.db["collections"]
# find if collection already exists using name # find if collection already exists using name
isCollectionNameAvailable = collections.find_one( isCollectionNameAvailable = await collections.find_one(
{"name": collection_object.name}) {"name": collection_object.name})
# TODO # TODO
@ -63,7 +63,7 @@ async def create_collection(request: Request,collection_object: Collection, curr
collection = CollectionInDB( collection = CollectionInDB(
collection_id=collection_id, **collection_object.dict()) collection_id=collection_id, **collection_object.dict())
collection_in_db = collections.insert_one(collection.dict()) collection_in_db = await collections.insert_one(collection.dict())
if not collection_in_db: if not collection_in_db:
raise HTTPException( raise HTTPException(
@ -79,7 +79,7 @@ async def update_collection(request: Request,collection_object: Collection, coll
collections = request.app.db["collections"] collections = request.app.db["collections"]
collection = collections.find_one({"collection_id": collection_id}) collection = await collections.find_one({"collection_id": collection_id})
if not collection: if not collection:
raise HTTPException( raise HTTPException(
@ -88,7 +88,7 @@ async def update_collection(request: Request,collection_object: Collection, coll
updated_collection = CollectionInDB( updated_collection = CollectionInDB(
collection_id=collection_id, **collection_object.dict()) collection_id=collection_id, **collection_object.dict())
collections.update_one({"collection_id": collection_id}, { await collections.update_one({"collection_id": collection_id}, {
"$set": updated_collection.dict()}) "$set": updated_collection.dict()})
return Collection(**updated_collection.dict()) return Collection(**updated_collection.dict())
@ -100,13 +100,13 @@ async def delete_collection(request: Request,collection_id: str, current_user: P
collections = request.app.db["collections"] collections = request.app.db["collections"]
collection = collections.find_one({"collection_id": collection_id}) collection = await collections.find_one({"collection_id": collection_id})
if not collection: if not collection:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Collection does not exist") status_code=status.HTTP_409_CONFLICT, detail="Collection does not exist")
isDeleted = collections.delete_one({"collection_id": collection_id}) isDeleted = await collections.delete_one({"collection_id": collection_id})
if isDeleted: if isDeleted:
return {"detail": "collection deleted"} return {"detail": "collection deleted"}
@ -129,7 +129,7 @@ async def get_collections(request: Request,page: int = 1, limit: int = 10):
# create list of collections and include courses in each collection # create list of collections and include courses in each collection
collections_list = [] collections_list = []
for collection in all_collections: for collection in await all_collections.to_list(length=100):
collection = CollectionInDB(**collection) collection = CollectionInDB(**collection)
collections_list.append(collection) collections_list.append(collection)
@ -140,7 +140,7 @@ async def get_collections(request: Request,page: int = 1, limit: int = 10):
collection.courses = courses.find( collection.courses = courses.find(
{"course_id": {"$in": collection_courses}}, {'_id': 0}) {"course_id": {"$in": collection_courses}}, {'_id': 0})
collection.courses = [course for course in collection.courses] collection.courses = [course for course in await collection.courses.to_list(length=100)]
return collections_list return collections_list
@ -150,7 +150,7 @@ async def get_collections(request: Request,page: int = 1, limit: int = 10):
async def verify_collection_rights(request: Request,collection_id: str, current_user: PublicUser, action: str): async def verify_collection_rights(request: Request,collection_id: str, current_user: PublicUser, action: str):
collections = request.app.db["collections"] collections = request.app.db["collections"]
collection = collections.find_one({"collection_id": collection_id}) collection = await collections.find_one({"collection_id": collection_id})
if not collection and action != "create": if not collection and action != "create":
raise HTTPException( raise HTTPException(

View file

@ -56,7 +56,7 @@ class CourseChapterInDB(CourseChapter):
async def get_course(request: Request, course_id: str, current_user: PublicUser): async def get_course(request: Request, course_id: str, current_user: PublicUser):
courses = request.app.db["courses"] courses = request.app.db["courses"]
course = courses.find_one({"course_id": course_id}) course = await courses.find_one({"course_id": course_id})
# verify course rights # verify course rights
await verify_rights(request, course_id, current_user, "read") await verify_rights(request, course_id, current_user, "read")
@ -74,7 +74,7 @@ async def get_course_meta(request: Request, course_id: str, current_user: Public
coursechapters = request.app.db["coursechapters"] coursechapters = request.app.db["coursechapters"]
activities = request.app.db["activities"] activities = request.app.db["activities"]
course = courses.find_one({"course_id": course_id}) course = await courses.find_one({"course_id": course_id})
lectures = request.app.db["lectures"] lectures = request.app.db["lectures"]
# verify course rights # verify course rights
@ -92,7 +92,7 @@ async def get_course_meta(request: Request, course_id: str, current_user: Public
# chapters # chapters
chapters = {} chapters = {}
for coursechapter in coursechapters: for coursechapter in await coursechapters.to_list(length=100):
coursechapter = CourseChapterInDB(**coursechapter) coursechapter = CourseChapterInDB(**coursechapter)
coursechapter_lectureIds = [] coursechapter_lectureIds = []
@ -106,7 +106,7 @@ async def get_course_meta(request: Request, course_id: str, current_user: Public
# lectures # lectures
lectures_list = {} lectures_list = {}
for lecture in lectures.find({"lecture_id": {"$in": coursechapter_lectureIds_global}}): for lecture in await lectures.find({"lecture_id": {"$in": coursechapter_lectureIds_global}}).to_list(length=100):
lecture = LectureInDB(**lecture) lecture = LectureInDB(**lecture)
lectures_list[lecture.lecture_id] = { lectures_list[lecture.lecture_id] = {
"id": lecture.lecture_id, "name": lecture.name, "type": lecture.type, "content": lecture.content "id": lecture.lecture_id, "name": lecture.name, "type": lecture.type, "content": lecture.content
@ -119,7 +119,7 @@ async def get_course_meta(request: Request, course_id: str, current_user: Public
course = Course(**course) course = Course(**course)
# Get activity by user # Get activity by user
activity = activities.find_one( activity = await activities.find_one(
{"course_id": course_id, "user_id": current_user.user_id}) {"course_id": course_id, "user_id": current_user.user_id})
if activity: if activity:
activity = json.loads(json.dumps(activity, default=str)) activity = json.loads(json.dumps(activity, default=str))
@ -155,7 +155,7 @@ async def create_course(request: Request, course_object: Course, org_id: str, cu
course = CourseInDB(course_id=course_id, authors=[ course = CourseInDB(course_id=course_id, authors=[
current_user.user_id], creationDate=str(datetime.now()), updateDate=str(datetime.now()), **course_object.dict()) current_user.user_id], creationDate=str(datetime.now()), updateDate=str(datetime.now()), **course_object.dict())
course_in_db = courses.insert_one(course.dict()) course_in_db = await courses.insert_one(course.dict())
if not course_in_db: if not course_in_db:
raise HTTPException( raise HTTPException(
@ -171,7 +171,7 @@ async def update_course_thumbnail(request: Request, course_id: str, current_user
courses = request.app.db["courses"] courses = request.app.db["courses"]
course = courses.find_one({"course_id": course_id}) course = await courses.find_one({"course_id": course_id})
# TODO(fix) : the implementation here is clearly not the best one # TODO(fix) : the implementation here is clearly not the best one
if course: if course:
creationDate = course["creationDate"] creationDate = course["creationDate"]
@ -184,7 +184,7 @@ async def update_course_thumbnail(request: Request, course_id: str, current_user
updated_course = CourseInDB(course_id=course_id, creationDate=creationDate, updated_course = CourseInDB(course_id=course_id, creationDate=creationDate,
authors=authors, updateDate=str(datetime.now()), **course.dict()) authors=authors, updateDate=str(datetime.now()), **course.dict())
courses.update_one({"course_id": course_id}, { await courses.update_one({"course_id": course_id}, {
"$set": updated_course.dict()}) "$set": updated_course.dict()})
return CourseInDB(**updated_course.dict()) return CourseInDB(**updated_course.dict())
@ -201,7 +201,7 @@ async def update_course(request: Request, course_object: Course, course_id: str,
courses = request.app.db["courses"] courses = request.app.db["courses"]
course = courses.find_one({"course_id": course_id}) course = await courses.find_one({"course_id": course_id})
if course: if course:
creationDate = course["creationDate"] creationDate = course["creationDate"]
@ -213,7 +213,7 @@ async def update_course(request: Request, course_object: Course, course_id: str,
updated_course = CourseInDB( updated_course = CourseInDB(
course_id=course_id, creationDate=creationDate, authors=authors, updateDate=str(datetime_object), **course_object.dict()) course_id=course_id, creationDate=creationDate, authors=authors, updateDate=str(datetime_object), **course_object.dict())
courses.update_one({"course_id": course_id}, { await courses.update_one({"course_id": course_id}, {
"$set": updated_course.dict()}) "$set": updated_course.dict()})
return CourseInDB(**updated_course.dict()) return CourseInDB(**updated_course.dict())
@ -230,13 +230,13 @@ async def delete_course(request: Request, course_id: str, current_user: PublicUs
courses = request.app.db["courses"] courses = request.app.db["courses"]
course = courses.find_one({"course_id": course_id}) course = await courses.find_one({"course_id": course_id})
if not course: if not course:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Course does not exist") status_code=status.HTTP_409_CONFLICT, detail="Course does not exist")
isDeleted = courses.delete_one({"course_id": course_id}) isDeleted = await courses.delete_one({"course_id": course_id})
if isDeleted: if isDeleted:
return {"detail": "Course deleted"} return {"detail": "Course deleted"}
@ -256,7 +256,7 @@ async def get_courses(request: Request, page: int = 1, limit: int = 10, org_id:
all_courses = courses.find({"org_id": org_id}).sort( all_courses = courses.find({"org_id": org_id}).sort(
"name", 1).skip(10 * (page - 1)).limit(limit) "name", 1).skip(10 * (page - 1)).limit(limit)
return [json.loads(json.dumps(course, default=str)) for course in all_courses] return [json.loads(json.dumps(course, default=str)) for course in await all_courses.to_list(length=100)]
async def get_courses_orgslug(request: Request, page: int = 1, limit: int = 10, org_slug: str | None = None): async def get_courses_orgslug(request: Request, page: int = 1, limit: int = 10, org_slug: str | None = None):
courses = request.app.db["courses"] courses = request.app.db["courses"]
@ -264,7 +264,7 @@ async def get_courses_orgslug(request: Request, page: int = 1, limit: int = 10,
# TODO : Get only courses that user is admin/has roles of # TODO : Get only courses that user is admin/has roles of
# get org_id from slug # get org_id from slug
org = orgs.find_one({"slug": org_slug}) org = await orgs.find_one({"slug": org_slug})
if not org: if not org:
raise HTTPException( raise HTTPException(
@ -274,7 +274,7 @@ async def get_courses_orgslug(request: Request, page: int = 1, limit: int = 10,
all_courses = courses.find({"org_id": org['org_id']}).sort( all_courses = courses.find({"org_id": org['org_id']}).sort(
"name", 1).skip(10 * (page - 1)).limit(limit) "name", 1).skip(10 * (page - 1)).limit(limit)
return [json.loads(json.dumps(course, default=str)) for course in all_courses] return [json.loads(json.dumps(course, default=str)) for course in await all_courses.to_list(length=100)]
@ -284,7 +284,7 @@ async def get_courses_orgslug(request: Request, page: int = 1, limit: int = 10,
async def verify_rights(request: Request, course_id: str, current_user: PublicUser, action: str): async def verify_rights(request: Request, course_id: str, current_user: PublicUser, action: str):
courses = request.app.db["courses"] courses = request.app.db["courses"]
course = courses.find_one({"course_id": course_id}) course = await courses.find_one({"course_id": course_id})
if not course: if not course:
raise HTTPException( raise HTTPException(

View file

@ -44,10 +44,10 @@ async def create_lecture(request: Request,lecture_object: Lecture, coursechapter
# create lecture # create lecture
lecture = LectureInDB(**lecture_object.dict(), creationDate=str( lecture = LectureInDB(**lecture_object.dict(), creationDate=str(
datetime.now()), coursechapter_id=coursechapter_id, updateDate=str(datetime.now()), lecture_id=lecture_id) datetime.now()), coursechapter_id=coursechapter_id, updateDate=str(datetime.now()), lecture_id=lecture_id)
lectures.insert_one(lecture.dict()) await lectures.insert_one(lecture.dict())
# update chapter # update chapter
coursechapters.update_one({"coursechapter_id": coursechapter_id}, { await coursechapters.update_one({"coursechapter_id": coursechapter_id}, {
"$addToSet": {"lectures": lecture_id}}) "$addToSet": {"lectures": lecture_id}})
return lecture return lecture
@ -56,7 +56,7 @@ async def create_lecture(request: Request,lecture_object: Lecture, coursechapter
async def get_lecture(request: Request,lecture_id: str, current_user: PublicUser): async def get_lecture(request: Request,lecture_id: str, current_user: PublicUser):
lectures = request.app.db["lectures"] lectures = request.app.db["lectures"]
lecture = lectures.find_one({"lecture_id": lecture_id}) lecture = await lectures.find_one({"lecture_id": lecture_id})
# verify course rights # verify course rights
hasRoleRights = await verify_user_rights_with_roles(request,"read", current_user.user_id, lecture_id) hasRoleRights = await verify_user_rights_with_roles(request,"read", current_user.user_id, lecture_id)
@ -80,7 +80,7 @@ async def update_lecture(request: Request,lecture_object: Lecture, lecture_id: s
lectures = request.app.db["lectures"] lectures = request.app.db["lectures"]
lecture = lectures.find_one({"lecture_id": lecture_id}) lecture = await lectures.find_one({"lecture_id": lecture_id})
if lecture: if lecture:
creationDate = lecture["creationDate"] creationDate = lecture["creationDate"]
@ -91,7 +91,7 @@ async def update_lecture(request: Request,lecture_object: Lecture, lecture_id: s
updated_course = LectureInDB( updated_course = LectureInDB(
lecture_id=lecture_id, coursechapter_id=lecture["coursechapter_id"], creationDate=creationDate, updateDate=str(datetime_object), **lecture_object.dict()) 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}, { await lectures.update_one({"lecture_id": lecture_id}, {
"$set": updated_course.dict()}) "$set": updated_course.dict()})
return LectureInDB(**updated_course.dict()) return LectureInDB(**updated_course.dict())
@ -108,13 +108,13 @@ async def delete_lecture(request: Request,lecture_id: str, current_user: PublicU
lectures = request.app.db["lectures"] lectures = request.app.db["lectures"]
lecture = lectures.find_one({"lecture_id": lecture_id}) lecture = await lectures.find_one({"lecture_id": lecture_id})
if not lecture: if not lecture:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="lecture does not exist") status_code=status.HTTP_409_CONFLICT, detail="lecture does not exist")
isDeleted = lectures.delete_one({"lecture_id": lecture_id}) isDeleted = await lectures.delete_one({"lecture_id": lecture_id})
if isDeleted: if isDeleted:
return {"detail": "lecture deleted"} return {"detail": "lecture deleted"}
@ -137,11 +137,8 @@ async def get_lectures(request: Request,coursechapter_id: str, current_user: Pub
if not lectures: if not lectures:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="No lectures found") status_code=status.HTTP_409_CONFLICT, detail="Course does not exist")
lectures = [LectureInDB(**lecture) for lecture in await lectures.to_list(length=100)]
lectures_list = [] return lectures
for lecture in lectures:
lectures_list.append(Lecture(**lecture))
return lectures_list

View file

@ -44,7 +44,7 @@ async def create_video_lecture(request: Request,name: str, coursechapter_id: st
# create lecture # create lecture
lecture = LectureInDB(**lecture_object.dict()) lecture = LectureInDB(**lecture_object.dict())
lectures.insert_one(lecture.dict()) await lectures.insert_one(lecture.dict())
# upload video # upload video
if video_file: if video_file:
@ -55,7 +55,7 @@ async def create_video_lecture(request: Request,name: str, coursechapter_id: st
# todo : choose whether to update the chapter or not # todo : choose whether to update the chapter or not
# update chapter # update chapter
coursechapters.update_one({"coursechapter_id": coursechapter_id}, { await coursechapters.update_one({"coursechapter_id": coursechapter_id}, {
"$addToSet": {"lectures": lecture_id}}) "$addToSet": {"lectures": lecture_id}})
return lecture return lecture

View file

@ -131,7 +131,7 @@ async def get_houses(request: Request,page: int = 1, limit: int = 10):
# get all houses from database # get all houses from database
all_houses = houses.find().sort("name", 1).skip(10 * (page - 1)).limit(limit) all_houses = houses.find().sort("name", 1).skip(10 * (page - 1)).limit(limit)
return [json.loads(json.dumps(house, default=str)) for house in all_houses] return [json.loads(json.dumps(house, default=str)) for house in await all_houses.to_list(length=limit)]
#### Security #################################################### #### Security ####################################################

View file

@ -26,7 +26,7 @@ async def create_initial_data(request: Request):
######################################## ########################################
database_users = request.app.db["users"] database_users = request.app.db["users"]
database_users.delete_many({}) await database_users.delete_many({})
users = [] users = []
admin_user = UserWithPassword( admin_user = UserWithPassword(
@ -53,7 +53,7 @@ async def create_initial_data(request: Request):
# find admin user # find admin user
users = request.app.db["users"] users = request.app.db["users"]
admin_user = users.find_one({"username": "admin"}) admin_user = await users.find_one({"username": "admin"})
if admin_user: if admin_user:
admin_user = UserInDB(**admin_user) admin_user = UserInDB(**admin_user)
@ -65,7 +65,7 @@ async def create_initial_data(request: Request):
######################################## ########################################
database_orgs = request.app.db["organizations"] database_orgs = request.app.db["organizations"]
database_orgs.delete_many({}) await database_orgs.delete_many({})
organizations = [] organizations = []
for i in range(0, 5): for i in range(0, 5):
@ -85,7 +85,7 @@ async def create_initial_data(request: Request):
######################################## ########################################
database_roles = request.app.db["roles"] database_roles = request.app.db["roles"]
database_roles.delete_many({}) await database_roles.delete_many({})
roles = [] roles = []
admin_role = Role( admin_role = Role(
@ -117,14 +117,14 @@ async def create_initial_data(request: Request):
database_courses = request.app.db["courses"] database_courses = request.app.db["courses"]
database_chapters = request.app.db["coursechapters"] database_chapters = request.app.db["coursechapters"]
database_courses.delete_many({}) await database_courses.delete_many({})
database_chapters.delete_many({}) await database_chapters.delete_many({})
courses = [] courses = []
orgs = request.app.db["organizations"] orgs = request.app.db["organizations"]
if orgs.count_documents({}) > 0: if await orgs.count_documents({}) > 0:
for org in orgs.find(): for org in await orgs.find().to_list(length=100):
for i in range(0, 5): for i in range(0, 5):
# get image in BinaryIO format from unsplash and save it to disk # get image in BinaryIO format from unsplash and save it to disk
@ -161,7 +161,7 @@ async def create_initial_data(request: Request):
course.thumbnail = name_in_disk course.thumbnail = name_in_disk
course = CourseInDB(**course.dict()) course = CourseInDB(**course.dict())
course_in_db = courses.insert_one(course.dict()) course_in_db = await courses.insert_one(course.dict())
# create chapters # create chapters
for i in range(0, 5): for i in range(0, 5):

View file

@ -37,7 +37,7 @@ class PublicOrganization(Organization):
async def get_organization(request: Request, org_id: str): async def get_organization(request: Request, org_id: str):
orgs = request.app.db["organizations"] orgs = request.app.db["organizations"]
org = orgs.find_one({"org_id": org_id}) org = await orgs.find_one({"org_id": org_id})
if not org: if not org:
raise HTTPException( raise HTTPException(
@ -50,7 +50,7 @@ async def get_organization(request: Request, org_id: str):
async def get_organization_by_slug(request: Request, org_slug: str): async def get_organization_by_slug(request: Request, org_slug: str):
orgs = request.app.db["organizations"] orgs = request.app.db["organizations"]
org = orgs.find_one({"slug": org_slug}) org = await orgs.find_one({"slug": org_slug})
if not org: if not org:
raise HTTPException( raise HTTPException(
@ -64,7 +64,7 @@ async def create_org(request: Request, org_object: Organization, current_user: P
orgs = request.app.db["organizations"] orgs = request.app.db["organizations"]
# find if org already exists using name # find if org already exists using name
isOrgAvailable = orgs.find_one({"slug": org_object.slug}) isOrgAvailable = await orgs.find_one({"slug": org_object.slug})
if isOrgAvailable: if isOrgAvailable:
raise HTTPException( raise HTTPException(
@ -77,7 +77,7 @@ async def create_org(request: Request, org_object: Organization, current_user: P
current_user.user_id], admins=[ current_user.user_id], admins=[
current_user.user_id], **org_object.dict()) current_user.user_id], **org_object.dict())
org_in_db = orgs.insert_one(org.dict()) org_in_db = await orgs.insert_one(org.dict())
if not org_in_db: if not org_in_db:
raise HTTPException( raise HTTPException(
@ -93,7 +93,7 @@ async def update_org(request: Request, org_object: Organization, org_id: str, cu
orgs = request.app.db["organizations"] orgs = request.app.db["organizations"]
org = orgs.find_one({"org_id": org_id}) org = await orgs.find_one({"org_id": org_id})
if org: if org:
owners = org["owners"] owners = org["owners"]
@ -106,7 +106,7 @@ async def update_org(request: Request, org_object: Organization, org_id: str, cu
updated_org = OrganizationInDB( updated_org = OrganizationInDB(
org_id=org_id, owners=owners, admins=admins, **org_object.dict()) org_id=org_id, owners=owners, admins=admins, **org_object.dict())
orgs.update_one({"org_id": org_id}, {"$set": updated_org.dict()}) await orgs.update_one({"org_id": org_id}, {"$set": updated_org.dict()})
return Organization(**updated_org.dict()) return Organization(**updated_org.dict())
@ -117,13 +117,13 @@ async def delete_org(request: Request, org_id: str, current_user: PublicUser):
orgs = request.app.db["organizations"] orgs = request.app.db["organizations"]
org = orgs.find_one({"org_id": org_id}) org = await orgs.find_one({"org_id": org_id})
if not org: if not org:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Organization does not exist") status_code=status.HTTP_409_CONFLICT, detail="Organization does not exist")
isDeleted = orgs.delete_one({"org_id": org_id}) isDeleted = await orgs.delete_one({"org_id": org_id})
if isDeleted: if isDeleted:
return {"detail": "Org deleted"} return {"detail": "Org deleted"}
@ -137,9 +137,9 @@ async def get_orgs_by_user(request: Request, user_id: str, page: int = 1, limit:
# find all orgs where user_id is in owners or admins arrays # find all orgs where user_id is in owners or admins arrays
all_orgs = orgs.find({"$or": [{"owners": user_id}, {"admins": user_id}]}).sort( all_orgs = orgs.find({"$or": [{"owners": user_id}, {"admins": user_id}]}).sort(
"name", 1).skip(10 * (page - 1)).limit(limit) "name", 1).skip(10 * (page - 1)).limit(100)
return [json.loads(json.dumps(org, default=str)) for org in all_orgs] return [json.loads(json.dumps(org, default=str)) for org in await all_orgs.to_list(length=100)]
#### Security #################################################### #### Security ####################################################
@ -147,7 +147,7 @@ async def get_orgs_by_user(request: Request, user_id: str, page: int = 1, limit:
async def verify_org_rights(request: Request, org_id: str, current_user: PublicUser, action: str,): async def verify_org_rights(request: Request, org_id: str, current_user: PublicUser, action: str,):
orgs = request.app.db["organizations"] orgs = request.app.db["organizations"]
org = orgs.find_one({"org_id": org_id}) org = await orgs.find_one({"org_id": org_id})
if not org: if not org:
raise HTTPException( raise HTTPException(

View file

@ -47,7 +47,7 @@ class RoleInDB(Role):
async def get_role(request: Request,role_id: str): async def get_role(request: Request,role_id: str):
roles = request.app.db["roles"] roles = request.app.db["roles"]
role = roles.find_one({"role_id": role_id}) role = await roles.find_one({"role_id": role_id})
if not role: if not role:
raise HTTPException( raise HTTPException(
@ -61,7 +61,7 @@ async def create_role(request: Request,role_object: Role, current_user: PublicUs
roles = request.app.db["roles"] roles = request.app.db["roles"]
# find if house already exists using name # find if house already exists using name
isRoleAvailable = roles.find_one({"name": role_object.name}) isRoleAvailable = await roles.find_one({"name": role_object.name})
if isRoleAvailable: if isRoleAvailable:
raise HTTPException( raise HTTPException(
@ -75,7 +75,7 @@ async def create_role(request: Request,role_object: Role, current_user: PublicUs
role = RoleInDB(role_id=role_id, creationDate=str(datetime.now()), role = RoleInDB(role_id=role_id, creationDate=str(datetime.now()),
updateDate=str(datetime.now()), **role_object.dict()) updateDate=str(datetime.now()), **role_object.dict())
role_in_db = roles.insert_one(role.dict()) role_in_db = await roles.insert_one(role.dict())
if not role_in_db: if not role_in_db:
raise HTTPException( raise HTTPException(
@ -91,7 +91,7 @@ async def update_role(request: Request,role_object: Role, role_id: str, current_
roles = request.app.db["roles"] roles = request.app.db["roles"]
role = roles.find_one({"role_id": role_id}) role = await roles.find_one({"role_id": role_id})
if not role: if not role:
raise HTTPException( raise HTTPException(
@ -100,7 +100,7 @@ async def update_role(request: Request,role_object: Role, role_id: str, current_
updated_role = RoleInDB( updated_role = RoleInDB(
role_id=role_id, updateDate=str(datetime.now()), creationDate=role["creationDate"], **role_object.dict()) role_id=role_id, updateDate=str(datetime.now()), creationDate=role["creationDate"], **role_object.dict())
roles.update_one({"role_id": role_id}, {"$set": updated_role.dict()}) await roles.update_one({"role_id": role_id}, {"$set": updated_role.dict()})
return RoleInDB(**updated_role.dict()) return RoleInDB(**updated_role.dict())
@ -112,13 +112,13 @@ async def delete_role(request: Request,role_id: str, current_user: PublicUser):
roles = request.app.db["roles"] roles = request.app.db["roles"]
role = roles.find_one({"role_id": role_id}) role = await roles.find_one({"role_id": role_id})
if not role: if not role:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Role does not exist") status_code=status.HTTP_409_CONFLICT, detail="Role does not exist")
isDeleted = roles.delete_one({"role_id": role_id}) isDeleted = await roles.delete_one({"role_id": role_id})
if isDeleted: if isDeleted:
return {"detail": "Role deleted"} return {"detail": "Role deleted"}
@ -133,7 +133,7 @@ async def get_roles(request: Request,page: int = 1, limit: int = 10):
# get all roles from database # get all roles from database
all_roles = roles.find().sort("name", 1).skip(10 * (page - 1)).limit(limit) all_roles = roles.find().sort("name", 1).skip(10 * (page - 1)).limit(limit)
return [json.loads(json.dumps(role, default=str)) for role in all_roles] return [json.loads(json.dumps(role, default=str)) for role in await all_roles.to_list(length=limit)]
#### Security #################################################### #### Security ####################################################
@ -141,7 +141,7 @@ async def get_roles(request: Request,page: int = 1, limit: int = 10):
async def verify_user_permissions_on_roles(request: Request,action: str, current_user: PublicUser): async def verify_user_permissions_on_roles(request: Request,action: str, current_user: PublicUser):
users = request.app.db["users"] users = request.app.db["users"]
user = users.find_one({"user_id": current_user.user_id}) user = await users.find_one({"user_id": current_user.user_id})
if not user: if not user:
raise HTTPException( raise HTTPException(

View file

@ -42,7 +42,7 @@ async def verify_user_rights_with_roles(request: Request,action: str, user_id: s
# Info: permission actions are: read, create, delete, update # Info: permission actions are: read, create, delete, update
for role in user_roles_cursor: for role in await user_roles_cursor.to_list(length=100):
user_roles.append(role) user_roles.append(role)
for role in user_roles: for role in user_roles:

View file

@ -57,7 +57,7 @@ class Role(BaseModel):
async def get_user(request: Request, username: str): async def get_user(request: Request, username: str):
users = request.app.db["users"] users = request.app.db["users"]
user = users.find_one({"username": username}) user = await users.find_one({"username": username})
if not user: if not user:
raise HTTPException( raise HTTPException(
@ -71,7 +71,7 @@ async def get_profile_metadata(request: Request, user):
users = request.app.db["users"] users = request.app.db["users"]
roles = request.app.db["roles"] roles = request.app.db["roles"]
user = users.find_one({"user_id": user['user_id']}) user = await users.find_one({"user_id": user['user_id']})
if not user: if not user:
raise HTTPException( raise HTTPException(
@ -81,7 +81,7 @@ async def get_profile_metadata(request: Request, user):
user_roles = roles.find({"linked_users": user['user_id']}) user_roles = roles.find({"linked_users": user['user_id']})
user_roles_list = [] user_roles_list = []
for role in user_roles: for role in await user_roles.to_list(length=100):
print(role) print(role)
user_roles_list.append(Role(**role)) user_roles_list.append(Role(**role))
@ -94,7 +94,7 @@ async def get_profile_metadata(request: Request, user):
async def get_user_by_userid(request: Request, user_id: str): async def get_user_by_userid(request: Request, user_id: str):
users = request.app.db["users"] users = request.app.db["users"]
user = users.find_one({"user_id": user_id}) user = await users.find_one({"user_id": user_id})
if not user: if not user:
raise HTTPException( raise HTTPException(
@ -107,7 +107,7 @@ async def get_user_by_userid(request: Request, user_id: str):
async def security_get_user(request: Request, email: str): async def security_get_user(request: Request, email: str):
users = request.app.db["users"] users = request.app.db["users"]
user = users.find_one({"email": email}) user = await users.find_one({"email": email})
if not user: if not user:
raise HTTPException( raise HTTPException(
@ -119,7 +119,7 @@ async def security_get_user(request: Request, email: str):
async def get_userid_by_username(request: Request, username: str): async def get_userid_by_username(request: Request, username: str):
users = request.app.db["users"] users = request.app.db["users"]
user = users.find_one({"username": username}) user = await users.find_one({"username": username})
if not user: if not user:
raise HTTPException( raise HTTPException(
@ -131,8 +131,8 @@ async def get_userid_by_username(request: Request, username: str):
async def update_user(request: Request, user_id: str, user_object: UserWithPassword): async def update_user(request: Request, user_id: str, user_object: UserWithPassword):
users = request.app.db["users"] users = request.app.db["users"]
isUserExists = users.find_one({"user_id": user_id}) isUserExists = await users.find_one({"user_id": user_id})
isUsernameAvailable = users.find_one({"username": user_object.username}) isUsernameAvailable = await users.find_one({"username": user_object.username})
if not isUserExists: if not isUserExists:
raise HTTPException( raise HTTPException(
@ -153,7 +153,7 @@ async def update_user(request: Request, user_id: str, user_object: UserWithPassw
async def delete_user(request: Request, user_id: str): async def delete_user(request: Request, user_id: str):
users = request.app.db["users"] users = request.app.db["users"]
isUserAvailable = users.find_one({"user_id": user_id}) isUserAvailable = await users.find_one({"user_id": user_id})
if not isUserAvailable: if not isUserAvailable:
raise HTTPException( raise HTTPException(
@ -167,7 +167,7 @@ async def delete_user(request: Request, user_id: str):
async def create_user(request: Request, user_object: UserWithPassword): async def create_user(request: Request, user_object: UserWithPassword):
users = request.app.db["users"] users = request.app.db["users"]
isUserAvailable = users.find_one({"username": user_object.username}) isUserAvailable = await users.find_one({"username": user_object.username})
if isUserAvailable: if isUserAvailable:
raise HTTPException( raise HTTPException(
@ -184,6 +184,6 @@ async def create_user(request: Request, user_object: UserWithPassword):
user = UserInDB(user_id=user_id, creationDate=str(datetime.now()), user = UserInDB(user_id=user_id, creationDate=str(datetime.now()),
updateDate=str(datetime.now()), **user_object.dict()) updateDate=str(datetime.now()), **user_object.dict())
user_in_db = users.insert_one(user.dict()) user_in_db = await users.insert_one(user.dict())
return User(**user.dict()) return User(**user.dict())