156 lines
6.1 KiB
Python
156 lines
6.1 KiB
Python
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
|
|
|
from app.core.crypto import create_access_token
|
|
from app.core.dependencies import get_current_user, require_superuser
|
|
from app.modules.sync import repository as sync_repo
|
|
from app.modules.sync.schemas import EnterpriseOut, FarmHubOut
|
|
from app.modules.users.models import User
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/enterprises")
|
|
def list_enterprises(user: User = Depends(get_current_user)):
|
|
# Superuser sees all; regular users see memberships only (simplified v1)
|
|
if user.is_superuser:
|
|
from sqlalchemy import select
|
|
|
|
from app.core.database import session_scope
|
|
from app.modules.sync.models import Enterprise
|
|
|
|
with session_scope() as db:
|
|
rows = list(db.scalars(select(Enterprise).order_by(Enterprise.name)))
|
|
return [
|
|
EnterpriseOut(id=r.id, name=r.name, slug=r.slug, status=r.status).model_dump()
|
|
for r in rows
|
|
]
|
|
from sqlalchemy import select
|
|
|
|
from app.core.database import session_scope
|
|
from app.modules.sync.models import Enterprise, EnterpriseMember
|
|
|
|
with session_scope() as db:
|
|
rows = list(
|
|
db.scalars(
|
|
select(Enterprise)
|
|
.join(EnterpriseMember, EnterpriseMember.enterprise_id == Enterprise.id)
|
|
.where(EnterpriseMember.user_id == user.id)
|
|
)
|
|
)
|
|
return [EnterpriseOut(id=r.id, name=r.name, slug=r.slug, status=r.status).model_dump() for r in rows]
|
|
|
|
|
|
@router.post("/enterprises")
|
|
def create_enterprise(body: dict, _: User = Depends(require_superuser)):
|
|
ent = sync_repo.create_enterprise(body["name"], body["slug"])
|
|
return EnterpriseOut(id=ent.id, name=ent.name, slug=ent.slug, status=ent.status).model_dump()
|
|
|
|
|
|
@router.get("/enterprises/{enterprise_id}/farms")
|
|
def list_farms(enterprise_id: str, user: User = Depends(get_current_user)):
|
|
member = sync_repo.get_member(user.id, enterprise_id)
|
|
if not member and not user.is_superuser:
|
|
from fastapi import HTTPException, status
|
|
|
|
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="ENTERPRISE_FORBIDDEN")
|
|
hubs = sync_repo.list_farm_hubs(enterprise_id)
|
|
return [
|
|
FarmHubOut(
|
|
id=h.id,
|
|
enterprise_id=h.enterprise_id,
|
|
name=h.name,
|
|
hub_site_id=h.hub_site_id,
|
|
url=h.url,
|
|
status=h.status,
|
|
last_seen=h.last_seen,
|
|
wesp_version=h.wesp_version,
|
|
).model_dump()
|
|
for h in hubs
|
|
]
|
|
|
|
|
|
@router.post("/enterprises/{enterprise_id}/session")
|
|
def enterprise_session(enterprise_id: str, user: User = Depends(get_current_user)):
|
|
member = sync_repo.get_member(user.id, enterprise_id)
|
|
if not member and not user.is_superuser:
|
|
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="ENTERPRISE_FORBIDDEN")
|
|
role = member.role if member else "admin"
|
|
farm_ids = None if role == "admin" else sync_repo.list_farm_access(user.id, enterprise_id)
|
|
token = create_access_token(
|
|
user.id,
|
|
user.role,
|
|
user.is_superuser,
|
|
enterprise_id=enterprise_id,
|
|
enterprise_role=role,
|
|
farm_ids=farm_ids,
|
|
)
|
|
return {
|
|
"access_token": token,
|
|
"enterprise_id": enterprise_id,
|
|
"enterprise_role": role,
|
|
"farm_ids": farm_ids,
|
|
}
|
|
|
|
|
|
@router.get("/enterprises/{enterprise_id}/sync-status")
|
|
def enterprise_sync_status(enterprise_id: str, user: User = Depends(get_current_user)):
|
|
member = sync_repo.get_member(user.id, enterprise_id)
|
|
if not member and not user.is_superuser:
|
|
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="ENTERPRISE_FORBIDDEN")
|
|
from app.modules.sync.service import get_sync_metrics
|
|
|
|
return get_sync_metrics(enterprise_id)
|
|
|
|
|
|
@router.get("/enterprises/{enterprise_id}/members")
|
|
def list_members(enterprise_id: str, user: User = Depends(get_current_user)):
|
|
member = sync_repo.get_member(user.id, enterprise_id)
|
|
if not member or member.role != "admin":
|
|
if not user.is_superuser:
|
|
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="ENTERPRISE_ADMIN_ONLY")
|
|
from app.modules.users.repository import get_user_by_id
|
|
|
|
rows = sync_repo.list_members(enterprise_id)
|
|
return [
|
|
{
|
|
"user_id": m.user_id,
|
|
"role": m.role,
|
|
"email": (get_user_by_id(m.user_id).email if get_user_by_id(m.user_id) else None),
|
|
"farm_ids": sync_repo.list_farm_access(m.user_id, enterprise_id),
|
|
}
|
|
for m in rows
|
|
]
|
|
|
|
|
|
@router.post("/enterprises/{enterprise_id}/members")
|
|
def add_enterprise_member(enterprise_id: str, body: dict, user: User = Depends(get_current_user)):
|
|
member = sync_repo.get_member(user.id, enterprise_id)
|
|
if not member or member.role != "admin":
|
|
if not user.is_superuser:
|
|
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="ENTERPRISE_ADMIN_ONLY")
|
|
from app.modules.users.repository import get_user_by_email
|
|
|
|
target = get_user_by_email(body["email"].strip().lower())
|
|
if not target:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="USER_NOT_FOUND")
|
|
existing = sync_repo.get_member(target.id, enterprise_id)
|
|
if existing:
|
|
sync_repo.set_member_role(target.id, enterprise_id, body.get("role", existing.role))
|
|
else:
|
|
sync_repo.add_member(target.id, enterprise_id, body.get("role", "viewer"))
|
|
for farm_id in body.get("farm_ids") or []:
|
|
sync_repo.grant_farm_access(target.id, farm_id)
|
|
return {"status": "ok", "user_id": target.id}
|
|
|
|
|
|
@router.post("/enterprises/{enterprise_id}/farm-access")
|
|
def grant_farm_access(enterprise_id: str, body: dict, user: User = Depends(get_current_user)):
|
|
member = sync_repo.get_member(user.id, enterprise_id)
|
|
if not member or member.role != "admin":
|
|
if not user.is_superuser:
|
|
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="ENTERPRISE_ADMIN_ONLY")
|
|
sync_repo.grant_farm_access(body["user_id"], body["farm_hub_id"])
|
|
return {"status": "ok"}
|