mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-18 11:59:26 +00:00
✨ init roles
This commit is contained in:
parent
13c6193bea
commit
62fe8dbe89
4 changed files with 225 additions and 6 deletions
|
|
@ -1,5 +1,5 @@
|
|||
from fastapi import APIRouter
|
||||
from src.routers import users, auth, houses, orgs
|
||||
from src.routers import users, auth, houses, orgs, roles
|
||||
from starlette.responses import FileResponse
|
||||
|
||||
|
||||
|
|
@ -11,3 +11,4 @@ global_router.include_router(users.router, prefix="/users", tags=["users"])
|
|||
global_router.include_router(auth.router, prefix="/auth", tags=["auth"])
|
||||
global_router.include_router(houses.router, prefix="/houses", tags=["houses"])
|
||||
global_router.include_router(orgs.router, prefix="/orgs", tags=["orgs"])
|
||||
global_router.include_router(roles.router, prefix="/roles", tags=["roles"])
|
||||
|
|
|
|||
49
src/routers/roles.py
Normal file
49
src/routers/roles.py
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
from fastapi import APIRouter, Depends
|
||||
from src.services.auth import get_current_user
|
||||
|
||||
from src.services.roles import Role, create_role, delete_role, get_role, update_role
|
||||
from src.services.users import User
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/")
|
||||
async def api_create_role(role_object: Role, current_user: User = Depends(get_current_user)):
|
||||
"""
|
||||
Create new role
|
||||
"""
|
||||
return await create_role(role_object, current_user)
|
||||
|
||||
|
||||
@router.get("/{role_id}")
|
||||
async def api_get_role(role_id: str):
|
||||
"""
|
||||
Get single role by role_id
|
||||
"""
|
||||
return await get_role(role_id)
|
||||
|
||||
|
||||
@router.get("/page/{page}/limit/{limit}")
|
||||
async def api_get_role_by(page: int, limit: int):
|
||||
"""
|
||||
Get roles by page and limit
|
||||
"""
|
||||
return await get_role(page, limit)
|
||||
|
||||
|
||||
@router.put("/{role_id}")
|
||||
async def api_update_role(role_object: Role, role_id: str, current_user: User = Depends(get_current_user)):
|
||||
"""
|
||||
Update role by role_id
|
||||
"""
|
||||
return await update_role(role_object, role_id, current_user)
|
||||
|
||||
|
||||
@router.delete("/{role_id}")
|
||||
async def api_delete_role(role_id: str, current_user: User = Depends(get_current_user)):
|
||||
"""
|
||||
Delete role by ID
|
||||
"""
|
||||
|
||||
return await delete_role(role_id, current_user)
|
||||
168
src/services/roles.py
Normal file
168
src/services/roles.py
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
import json
|
||||
from typing import List
|
||||
from uuid import uuid4
|
||||
from pydantic import BaseModel
|
||||
from src.services.users import User
|
||||
from ..services.database import check_database, learnhouseDB, learnhouseDB
|
||||
from ..services.security import *
|
||||
from ..services.houses import House
|
||||
from fastapi import HTTPException, status
|
||||
from datetime import datetime
|
||||
|
||||
#### Classes ####################################################
|
||||
|
||||
|
||||
class Permission(BaseModel):
|
||||
create: bool
|
||||
read: bool
|
||||
update: bool
|
||||
delete: bool
|
||||
|
||||
|
||||
class Elements(BaseModel):
|
||||
course: List[str]
|
||||
users: List[str]
|
||||
houses: List[str]
|
||||
paths: List[str]
|
||||
coursegroups: List[str]
|
||||
|
||||
|
||||
class Role(BaseModel):
|
||||
name: str
|
||||
description: str
|
||||
permissions: Permission
|
||||
elements: Elements
|
||||
|
||||
|
||||
class RoleInDB(Role):
|
||||
role_id: str
|
||||
creationDate: str
|
||||
updateDate: str
|
||||
|
||||
#### Classes ####################################################
|
||||
|
||||
|
||||
async def get_role(role_id: str):
|
||||
await check_database()
|
||||
roles = learnhouseDB["roles"]
|
||||
|
||||
role = roles.find_one({"role_id": role_id})
|
||||
|
||||
if not role:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT, detail="Role does not exist")
|
||||
|
||||
role = Role(**role)
|
||||
return role
|
||||
|
||||
|
||||
async def create_role(role_object: Role, current_user: User):
|
||||
await check_database()
|
||||
roles = learnhouseDB["roles"]
|
||||
|
||||
# find if house already exists using name
|
||||
isRoleAvailable = roles.find_one({"name": role_object.name})
|
||||
|
||||
if isRoleAvailable:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT, detail="Role name already exists")
|
||||
|
||||
await verify_user_permissions("create", current_user)
|
||||
|
||||
# generate house_id with uuid4
|
||||
role_id = str(f"role_{uuid4()}")
|
||||
|
||||
role = RoleInDB(role_id=role_id, creationDate=str(datetime.now()),
|
||||
updateDate=str(datetime.now()), **role_object.dict())
|
||||
|
||||
role_in_db = roles.insert_one(role.dict())
|
||||
|
||||
if not role_in_db:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Unavailable database")
|
||||
|
||||
return role.dict()
|
||||
|
||||
|
||||
async def update_role(role_object: House, role_id: str, current_user: User):
|
||||
await check_database()
|
||||
|
||||
# verify house rights
|
||||
await verify_user_permissions("update", current_user)
|
||||
|
||||
roles = learnhouseDB["roles"]
|
||||
|
||||
role = roles.find_one({"role_id": role_id})
|
||||
|
||||
if not role:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT, detail="House does not exist")
|
||||
|
||||
updated_role = RoleInDB(
|
||||
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()})
|
||||
|
||||
return RoleInDB(**updated_role.dict())
|
||||
|
||||
|
||||
async def delete_role(role_id: str, current_user: User):
|
||||
await check_database()
|
||||
|
||||
# verify house rights
|
||||
await verify_user_permissions("delete", current_user)
|
||||
|
||||
roles = learnhouseDB["roles"]
|
||||
|
||||
role = roles.find_one({"role_id": role_id})
|
||||
|
||||
if not role:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT, detail="Role does not exist")
|
||||
|
||||
isDeleted = roles.delete_one({"role_id": role_id})
|
||||
|
||||
if isDeleted:
|
||||
return {"detail": "Role deleted"}
|
||||
else:
|
||||
raise HTTPException(
|
||||
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"]
|
||||
|
||||
# get all roles from database
|
||||
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]
|
||||
|
||||
|
||||
#### Security ####################################################
|
||||
|
||||
async def verify_user_permissions(action: str, current_user: User):
|
||||
await check_database()
|
||||
users = learnhouseDB["users"]
|
||||
|
||||
user = users.find_one({"username": current_user.username})
|
||||
|
||||
if not user:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT, detail="User does not exist")
|
||||
|
||||
isOwner = "owner" in user["user_type"]
|
||||
isEditor = "editor" in user["user_type"]
|
||||
|
||||
if action == "delete":
|
||||
if isEditor:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN, detail="You do not have rights to this Role")
|
||||
|
||||
if not isOwner and not isEditor:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN, detail="You do not have rights to this Role")
|
||||
|
||||
return True
|
||||
|
||||
#### Security ####################################################
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
from pydantic import BaseModel
|
||||
from ..services.database import create_config_collection, check_database, create_database, learnhouseDB, learnhouseDB
|
||||
from ..services.database import check_database, learnhouseDB, learnhouseDB
|
||||
from ..services.security import *
|
||||
from fastapi import FastAPI, HTTPException, status, Request, Response, BackgroundTasks
|
||||
from fastapi import HTTPException, status
|
||||
from datetime import datetime
|
||||
|
||||
#### Classes ####################################################
|
||||
|
|
@ -15,7 +15,8 @@ class User(BaseModel):
|
|||
avatar_url: str | None = None
|
||||
verified: bool
|
||||
created_date: str
|
||||
bio : str | None = None
|
||||
user_type: str
|
||||
bio: str | None = None
|
||||
|
||||
|
||||
class UserInDB(User):
|
||||
|
|
@ -61,7 +62,7 @@ async def update_user(user_object: UserInDB):
|
|||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT, detail="User does not exist")
|
||||
|
||||
user_object.password = security_hash_password(user_object.password)
|
||||
user_object.password = await security_hash_password(user_object.password)
|
||||
|
||||
updated_user = {"$set": user_object.dict()}
|
||||
users.update_one({"username": user_object.username}, updated_user)
|
||||
|
|
@ -96,7 +97,7 @@ async def create_user(user_object: UserInDB):
|
|||
|
||||
# lowercase username
|
||||
user_object.username = user_object.username.lower()
|
||||
|
||||
|
||||
user_object.created_date = str(datetime.now())
|
||||
|
||||
user_object.password = await security_hash_password(user_object.password)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue