mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-18 11:59:26 +00:00
✨ init orgs
This commit is contained in:
parent
91f4291d9b
commit
13c6193bea
5 changed files with 221 additions and 22 deletions
13
src/main.py
13
src/main.py
|
|
@ -1,18 +1,13 @@
|
||||||
from .routers import users
|
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
from .routers import users, auth, houses
|
from src.routers import users, auth, houses, orgs
|
||||||
from starlette.responses import FileResponse
|
from starlette.responses import FileResponse
|
||||||
|
|
||||||
|
|
||||||
global_router = APIRouter(prefix="/api")
|
global_router = APIRouter(prefix="/api")
|
||||||
|
|
||||||
|
|
||||||
## API Routes
|
# API Routes
|
||||||
global_router.include_router(users.router, prefix="/users", tags=["users"])
|
global_router.include_router(users.router, prefix="/users", tags=["users"])
|
||||||
global_router.include_router(auth.router, prefix="/auth", tags=["auth"])
|
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"])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ async def api_get_house(house_id: str):
|
||||||
return await get_house(house_id)
|
return await get_house(house_id)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/page/{house_id}/limit/{limit}")
|
@router.get("/page/{page}/limit/{limit}")
|
||||||
async def api_get_house_by(page: int, limit: int):
|
async def api_get_house_by(page: int, limit: int):
|
||||||
"""
|
"""
|
||||||
Get houses by page and limit
|
Get houses by page and limit
|
||||||
|
|
|
||||||
48
src/routers/orgs.py
Normal file
48
src/routers/orgs.py
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
from fastapi import APIRouter, Depends
|
||||||
|
from src.services.auth import get_current_user
|
||||||
|
from src.services.orgs import Organization, create_org, delete_org, get_organization, get_orgs, update_org
|
||||||
|
from src.services.users import User
|
||||||
|
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/")
|
||||||
|
async def api_create_org(org_object: Organization, current_user: User = Depends(get_current_user)):
|
||||||
|
"""
|
||||||
|
Create new organization
|
||||||
|
"""
|
||||||
|
return await create_org(org_object, current_user)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/{org_id}")
|
||||||
|
async def api_get_org(org_id: str):
|
||||||
|
"""
|
||||||
|
Get single Org by ID
|
||||||
|
"""
|
||||||
|
return await get_organization(org_id)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/page/{page}/limit/{limit}")
|
||||||
|
async def api_get_org_by(page: int, limit: int):
|
||||||
|
"""
|
||||||
|
Get orgs by page and limit
|
||||||
|
"""
|
||||||
|
return await get_orgs(page, limit)
|
||||||
|
|
||||||
|
|
||||||
|
@router.put("/{org_id}")
|
||||||
|
async def api_update_org(org_object: Organization, org_id: str, current_user: User = Depends(get_current_user)):
|
||||||
|
"""
|
||||||
|
Update Org by ID
|
||||||
|
"""
|
||||||
|
return await update_org(org_object, org_id, current_user)
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete("/{org_id}")
|
||||||
|
async def api_delete_org(org_id: str, current_user: User = Depends(get_current_user)):
|
||||||
|
"""
|
||||||
|
Delete Org by ID
|
||||||
|
"""
|
||||||
|
|
||||||
|
return await delete_org(org_id, current_user)
|
||||||
|
|
@ -22,6 +22,7 @@ class House(BaseModel):
|
||||||
class HouseInDB(House):
|
class HouseInDB(House):
|
||||||
house_id: str
|
house_id: str
|
||||||
owners: List[str]
|
owners: List[str]
|
||||||
|
admins: List[str]
|
||||||
|
|
||||||
#### Classes ####################################################
|
#### Classes ####################################################
|
||||||
|
|
||||||
|
|
@ -55,6 +56,7 @@ async def create_house(house_object: House, current_user: User):
|
||||||
house_id = str(f"house_{uuid4()}")
|
house_id = str(f"house_{uuid4()}")
|
||||||
|
|
||||||
house = HouseInDB(house_id=house_id, owners=[
|
house = HouseInDB(house_id=house_id, owners=[
|
||||||
|
current_user.username], admins=[
|
||||||
current_user.username], **house_object.dict())
|
current_user.username], **house_object.dict())
|
||||||
|
|
||||||
house_in_db = houses.insert_one(house.dict())
|
house_in_db = houses.insert_one(house.dict())
|
||||||
|
|
@ -68,22 +70,24 @@ async def create_house(house_object: House, current_user: User):
|
||||||
|
|
||||||
async def update_house(house_object: House, house_id: str, current_user: User):
|
async def update_house(house_object: House, house_id: str, current_user: User):
|
||||||
await check_database()
|
await check_database()
|
||||||
|
|
||||||
# verify house rights
|
# verify house rights
|
||||||
await verify_house_ownership(house_id, current_user)
|
await verify_house_rights(house_id, current_user)
|
||||||
|
|
||||||
houses = learnhouseDB["houses"]
|
houses = learnhouseDB["houses"]
|
||||||
|
|
||||||
house = houses.find_one({"house_id": house_id})
|
house = houses.find_one({"house_id": house_id})
|
||||||
|
|
||||||
## get owner value from house object database
|
# get owner value from house object database
|
||||||
owners = house["owners"]
|
owners = house["owners"]
|
||||||
|
admins = house["admins"]
|
||||||
|
|
||||||
if not house:
|
if not house:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="House does not exist")
|
status_code=status.HTTP_409_CONFLICT, detail="House does not exist")
|
||||||
|
|
||||||
updated_house = HouseInDB(house_id=house_id, owners=owners, **house_object.dict())
|
updated_house = HouseInDB(
|
||||||
|
house_id=house_id, owners=owners, admins=admins, **house_object.dict())
|
||||||
|
|
||||||
houses.update_one({"house_id": house_id}, {"$set": updated_house.dict()})
|
houses.update_one({"house_id": house_id}, {"$set": updated_house.dict()})
|
||||||
|
|
||||||
|
|
@ -92,10 +96,10 @@ async def update_house(house_object: House, house_id: str, current_user: User):
|
||||||
|
|
||||||
async def delete_house(house_id: str, current_user: User):
|
async def delete_house(house_id: str, current_user: User):
|
||||||
await check_database()
|
await check_database()
|
||||||
|
|
||||||
# verify house rights
|
# verify house rights
|
||||||
await verify_house_ownership(house_id, current_user)
|
await verify_house_rights(house_id, current_user)
|
||||||
|
|
||||||
houses = learnhouseDB["houses"]
|
houses = learnhouseDB["houses"]
|
||||||
|
|
||||||
house = houses.find_one({"house_id": house_id})
|
house = houses.find_one({"house_id": house_id})
|
||||||
|
|
@ -125,7 +129,7 @@ async def get_houses(page: int = 1, limit: int = 10):
|
||||||
|
|
||||||
#### Security ####################################################
|
#### Security ####################################################
|
||||||
|
|
||||||
async def verify_house_ownership(house_id: str, current_user: User):
|
async def verify_house_rights(house_id: str, current_user: User):
|
||||||
await check_database()
|
await check_database()
|
||||||
houses = learnhouseDB["houses"]
|
houses = learnhouseDB["houses"]
|
||||||
|
|
||||||
|
|
@ -135,9 +139,12 @@ async def verify_house_ownership(house_id: str, current_user: User):
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="House does not exist")
|
status_code=status.HTTP_409_CONFLICT, detail="House does not exist")
|
||||||
|
|
||||||
if current_user.username not in house["owners"]:
|
isAdmin = current_user.username in house["admins"]
|
||||||
|
isOwner = current_user.username in house["owners"]
|
||||||
|
|
||||||
|
if not isAdmin and not isOwner:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_409_CONFLICT, detail="User does not own this house")
|
status_code=status.HTTP_403_FORBIDDEN, detail="You do not have rights to this house")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
||||||
149
src/services/orgs.py
Normal file
149
src/services/orgs.py
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
import json
|
||||||
|
from typing import List
|
||||||
|
from uuid import uuid4
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from src.services.users import User
|
||||||
|
from ..services.database import create_config_collection, check_database, create_database, learnhouseDB, learnhouseDB
|
||||||
|
from ..services.security import *
|
||||||
|
from fastapi import FastAPI, HTTPException, status, Request, Response, BackgroundTasks
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
#### Classes ####################################################
|
||||||
|
|
||||||
|
|
||||||
|
class Organization(BaseModel):
|
||||||
|
name: str
|
||||||
|
description: str
|
||||||
|
email: str
|
||||||
|
|
||||||
|
|
||||||
|
class OrganizationInDB(Organization):
|
||||||
|
org_id: str
|
||||||
|
owners: List[str]
|
||||||
|
admins: List[str]
|
||||||
|
|
||||||
|
|
||||||
|
#### Classes ####################################################
|
||||||
|
|
||||||
|
|
||||||
|
async def get_organization(org_id: str):
|
||||||
|
await check_database()
|
||||||
|
orgs = learnhouseDB["organizations"]
|
||||||
|
|
||||||
|
org = orgs.find_one({"org_id": org_id})
|
||||||
|
|
||||||
|
if not org:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_409_CONFLICT, detail="Organization does not exist")
|
||||||
|
|
||||||
|
org = Organization(**org)
|
||||||
|
return org
|
||||||
|
|
||||||
|
|
||||||
|
async def create_org(org_object: Organization, current_user: User):
|
||||||
|
await check_database()
|
||||||
|
orgs = learnhouseDB["organizations"]
|
||||||
|
|
||||||
|
# find if org already exists using name
|
||||||
|
isOrgAvailable = orgs.find_one({"name": org_object.name})
|
||||||
|
|
||||||
|
if isOrgAvailable:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_409_CONFLICT, detail="Organization name already exists")
|
||||||
|
|
||||||
|
# generate org_id with uuid4
|
||||||
|
org_id = str(f"org_{uuid4()}")
|
||||||
|
|
||||||
|
org = OrganizationInDB(org_id=org_id, owners=[
|
||||||
|
current_user.username], admins=[
|
||||||
|
current_user.username], **org_object.dict())
|
||||||
|
|
||||||
|
org_in_db = orgs.insert_one(org.dict())
|
||||||
|
|
||||||
|
if not org_in_db:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Unavailable database")
|
||||||
|
|
||||||
|
return org.dict()
|
||||||
|
|
||||||
|
|
||||||
|
async def update_org(org_object: Organization, org_id: str, current_user: User):
|
||||||
|
await check_database()
|
||||||
|
|
||||||
|
# verify org rights
|
||||||
|
await verify_org_rights(org_id, current_user)
|
||||||
|
|
||||||
|
orgs = learnhouseDB["organizations"]
|
||||||
|
|
||||||
|
org = orgs.find_one({"org_id": org_id})
|
||||||
|
|
||||||
|
# get owner & adminds value from org object database
|
||||||
|
owners = org["owners"]
|
||||||
|
admins = org["admins"]
|
||||||
|
|
||||||
|
if not org:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_409_CONFLICT, detail="Organization does not exist")
|
||||||
|
|
||||||
|
updated_org = OrganizationInDB(
|
||||||
|
org_id=org_id, owners=owners, admins=admins, **org_object.dict())
|
||||||
|
|
||||||
|
orgs.update_one({"org_id": org_id}, {"$set": updated_org.dict()})
|
||||||
|
|
||||||
|
return Organization(**updated_org.dict())
|
||||||
|
|
||||||
|
|
||||||
|
async def delete_org(org_id: str, current_user: User):
|
||||||
|
await check_database()
|
||||||
|
|
||||||
|
await verify_org_rights(org_id, current_user)
|
||||||
|
|
||||||
|
orgs = learnhouseDB["organizations"]
|
||||||
|
|
||||||
|
org = orgs.find_one({"org_id": org_id})
|
||||||
|
|
||||||
|
if not org:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_409_CONFLICT, detail="Organization does not exist")
|
||||||
|
|
||||||
|
isDeleted = orgs.delete_one({"org_id": org_id})
|
||||||
|
|
||||||
|
if isDeleted:
|
||||||
|
return {"detail": "Org deleted"}
|
||||||
|
else:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Unavailable database")
|
||||||
|
|
||||||
|
|
||||||
|
async def get_orgs(page: int = 1, limit: int = 10):
|
||||||
|
await check_database()
|
||||||
|
orgs = learnhouseDB["orgs"]
|
||||||
|
|
||||||
|
# get all orgs from database
|
||||||
|
all_orgs = orgs.find().sort("name", 1).skip(10 * (page - 1)).limit(limit)
|
||||||
|
|
||||||
|
return [json.loads(json.dumps(house, default=str)) for house in all_orgs]
|
||||||
|
|
||||||
|
|
||||||
|
#### Security ####################################################
|
||||||
|
|
||||||
|
async def verify_org_rights(org_id: str, current_user: User):
|
||||||
|
await check_database()
|
||||||
|
orgs = learnhouseDB["organizations"]
|
||||||
|
|
||||||
|
org = orgs.find_one({"org_id": org_id})
|
||||||
|
|
||||||
|
if not org:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_409_CONFLICT, detail="Organization does not exist")
|
||||||
|
|
||||||
|
isAdmin = current_user.username in org["admins"]
|
||||||
|
isOwner = current_user.username in org["owners"]
|
||||||
|
|
||||||
|
if not isAdmin and not isOwner:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN, detail="You do not have rights to this organization")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
#### Security ####################################################
|
||||||
Loading…
Add table
Add a link
Reference in a new issue