193 lines
6.9 KiB
Python
193 lines
6.9 KiB
Python
import logging
|
|
from typing import List, Optional
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from starlette import status
|
|
|
|
from api.dependency import get_dao
|
|
from api.endpoints.auth import get_current_user
|
|
from api.models.EnvironmentRequest import EnvironmentCreate, EnvironmentUpdate, AssetToEnvironment, AssetsToEnvironment
|
|
from models.Environment import Environment
|
|
from repos.dao import DAO
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
router = APIRouter(prefix="/api/environments", tags=["Environments"], dependencies=[Depends(get_current_user)])
|
|
|
|
|
|
async def check_character_access(character_id: str, current_user: dict, dao: DAO):
|
|
character = await dao.chars.get_character(character_id)
|
|
if not character:
|
|
raise HTTPException(status_code=404, detail="Character not found")
|
|
|
|
is_creator = character.created_by == str(current_user["_id"])
|
|
is_project_member = False
|
|
if character.project_id and character.project_id in current_user.get("project_ids", []):
|
|
is_project_member = True
|
|
|
|
if not is_creator and not is_project_member:
|
|
raise HTTPException(status_code=403, detail="Access denied to character")
|
|
return character
|
|
|
|
|
|
@router.post("/", response_model=Environment)
|
|
async def create_environment(
|
|
env_req: EnvironmentCreate,
|
|
dao: DAO = Depends(get_dao),
|
|
current_user: dict = Depends(get_current_user)
|
|
):
|
|
logger.info(f"Creating environment '{env_req.name}' for character {env_req.character_id}")
|
|
await check_character_access(env_req.character_id, current_user, dao)
|
|
|
|
# Verify assets exist if provided
|
|
if env_req.asset_ids:
|
|
for aid in env_req.asset_ids:
|
|
asset = await dao.assets.get_asset(aid)
|
|
if not asset:
|
|
raise HTTPException(status_code=400, detail=f"Asset {aid} not found")
|
|
|
|
new_env = Environment(**env_req.model_dump())
|
|
created_env = await dao.environments.create_env(new_env)
|
|
return created_env
|
|
|
|
|
|
@router.get("/character/{character_id}", response_model=List[Environment])
|
|
async def get_character_environments(
|
|
character_id: str,
|
|
dao: DAO = Depends(get_dao),
|
|
current_user: dict = Depends(get_current_user)
|
|
):
|
|
logger.info(f"Getting environments for character {character_id}")
|
|
await check_character_access(character_id, current_user, dao)
|
|
return await dao.environments.get_character_envs(character_id)
|
|
|
|
|
|
@router.get("/{env_id}", response_model=Environment)
|
|
async def get_environment(
|
|
env_id: str,
|
|
dao: DAO = Depends(get_dao),
|
|
current_user: dict = Depends(get_current_user)
|
|
):
|
|
env = await dao.environments.get_env(env_id)
|
|
if not env:
|
|
raise HTTPException(status_code=404, detail="Environment not found")
|
|
|
|
await check_character_access(env.character_id, current_user, dao)
|
|
return env
|
|
|
|
|
|
@router.put("/{env_id}", response_model=Environment)
|
|
async def update_environment(
|
|
env_id: str,
|
|
env_update: EnvironmentUpdate,
|
|
dao: DAO = Depends(get_dao),
|
|
current_user: dict = Depends(get_current_user)
|
|
):
|
|
env = await dao.environments.get_env(env_id)
|
|
if not env:
|
|
raise HTTPException(status_code=404, detail="Environment not found")
|
|
|
|
await check_character_access(env.character_id, current_user, dao)
|
|
|
|
update_data = env_update.model_dump(exclude_unset=True)
|
|
if not update_data:
|
|
return env
|
|
|
|
# Verify assets exist if provided
|
|
if "asset_ids" in update_data:
|
|
if update_data["asset_ids"] is None:
|
|
del update_data["asset_ids"]
|
|
elif update_data["asset_ids"]:
|
|
# Verify all assets exist using batch check
|
|
assets = await dao.assets.get_assets_by_ids(update_data["asset_ids"])
|
|
if len(assets) != len(update_data["asset_ids"]):
|
|
found_ids = {a.id for a in assets}
|
|
missing_ids = [aid for aid in update_data["asset_ids"] if aid not in found_ids]
|
|
raise HTTPException(status_code=400, detail=f"Some assets not found: {missing_ids}")
|
|
|
|
success = await dao.environments.update_env(env_id, update_data)
|
|
if not success:
|
|
raise HTTPException(status_code=500, detail="Failed to update environment")
|
|
|
|
return await dao.environments.get_env(env_id)
|
|
|
|
|
|
@router.delete("/{env_id}", status_code=status.HTTP_204_NO_CONTENT)
|
|
async def delete_environment(
|
|
env_id: str,
|
|
dao: DAO = Depends(get_dao),
|
|
current_user: dict = Depends(get_current_user)
|
|
):
|
|
env = await dao.environments.get_env(env_id)
|
|
if not env:
|
|
raise HTTPException(status_code=404, detail="Environment not found")
|
|
|
|
await check_character_access(env.character_id, current_user, dao)
|
|
|
|
success = await dao.environments.delete_env(env_id)
|
|
if not success:
|
|
raise HTTPException(status_code=500, detail="Failed to delete environment")
|
|
return None
|
|
|
|
|
|
@router.post("/{env_id}/assets", status_code=status.HTTP_200_OK)
|
|
async def add_asset_to_environment(
|
|
env_id: str,
|
|
req: AssetToEnvironment,
|
|
dao: DAO = Depends(get_dao),
|
|
current_user: dict = Depends(get_current_user)
|
|
):
|
|
env = await dao.environments.get_env(env_id)
|
|
if not env:
|
|
raise HTTPException(status_code=404, detail="Environment not found")
|
|
|
|
await check_character_access(env.character_id, current_user, dao)
|
|
|
|
# Verify asset exists
|
|
asset = await dao.assets.get_asset(req.asset_id)
|
|
if not asset:
|
|
raise HTTPException(status_code=404, detail="Asset not found")
|
|
|
|
success = await dao.environments.add_asset(env_id, req.asset_id)
|
|
return {"success": success}
|
|
|
|
|
|
@router.post("/{env_id}/assets/batch", status_code=status.HTTP_200_OK)
|
|
async def add_assets_batch_to_environment(
|
|
env_id: str,
|
|
req: AssetsToEnvironment,
|
|
dao: DAO = Depends(get_dao),
|
|
current_user: dict = Depends(get_current_user)
|
|
):
|
|
env = await dao.environments.get_env(env_id)
|
|
if not env:
|
|
raise HTTPException(status_code=404, detail="Environment not found")
|
|
|
|
await check_character_access(env.character_id, current_user, dao)
|
|
|
|
# Verify all assets exist
|
|
assets = await dao.assets.get_assets_by_ids(req.asset_ids)
|
|
if len(assets) != len(req.asset_ids):
|
|
found_ids = {a.id for a in assets}
|
|
missing_ids = [aid for aid in req.asset_ids if aid not in found_ids]
|
|
raise HTTPException(status_code=404, detail=f"Some assets not found: {missing_ids}")
|
|
|
|
success = await dao.environments.add_assets(env_id, req.asset_ids)
|
|
return {"success": success}
|
|
|
|
|
|
@router.delete("/{env_id}/assets/{asset_id}", status_code=status.HTTP_200_OK)
|
|
async def remove_asset_from_environment(
|
|
env_id: str,
|
|
asset_id: str,
|
|
dao: DAO = Depends(get_dao),
|
|
current_user: dict = Depends(get_current_user)
|
|
):
|
|
env = await dao.environments.get_env(env_id)
|
|
if not env:
|
|
raise HTTPException(status_code=404, detail="Environment not found")
|
|
|
|
await check_character_access(env.character_id, current_user, dao)
|
|
|
|
success = await dao.environments.remove_asset(env_id, asset_id)
|
|
return {"success": success}
|