120 lines
3.9 KiB
Python
120 lines
3.9 KiB
Python
"""Rotas libertação ACCOUNT_EXISTS — Spec 022."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
from pydantic import BaseModel, Field
|
|
|
|
from app import auth, carbonio_release_store, vm112_domains
|
|
from app.permissions import can_read_tickets
|
|
|
|
router = APIRouter(prefix="/api/v1/carbonio-blocks", tags=["carbonio-release"])
|
|
|
|
|
|
class ResolveBlockBody(BaseModel):
|
|
confirm_email: str = Field(..., min_length=5)
|
|
password: str = Field(..., min_length=1)
|
|
|
|
|
|
def _require_ticket_reader(user: auth.DeskUser = Depends(auth.get_current_user)) -> auth.DeskUser:
|
|
if not can_read_tickets(user.role):
|
|
raise HTTPException(403, "permissão insuficiente")
|
|
return user
|
|
|
|
|
|
def _verify_user_password(conn, username: str, password: str) -> bool:
|
|
row = conn.execute(
|
|
"SELECT password_hash FROM desk_users WHERE username = ? AND active = 1",
|
|
(username,),
|
|
).fetchone()
|
|
if not row or not row["password_hash"]:
|
|
return False
|
|
return auth.verify_password(password, row["password_hash"])
|
|
|
|
|
|
@router.get("")
|
|
def list_carbonio_blocks(
|
|
status: str = Query("pending"),
|
|
session_id: str = "",
|
|
ticket_id: int | None = None,
|
|
limit: int = Query(100, ge=1, le=500),
|
|
user: auth.DeskUser = Depends(_require_ticket_reader),
|
|
):
|
|
conn = auth.db()
|
|
try:
|
|
return carbonio_release_store.list_blocks(
|
|
conn,
|
|
status=status or "all",
|
|
session_id=session_id.strip() or None,
|
|
ticket_id=ticket_id,
|
|
limit=limit,
|
|
)
|
|
finally:
|
|
conn.close()
|
|
|
|
|
|
@router.get("/{block_id}")
|
|
def get_carbonio_block(
|
|
block_id: int,
|
|
user: auth.DeskUser = Depends(_require_ticket_reader),
|
|
):
|
|
conn = auth.db()
|
|
try:
|
|
block = carbonio_release_store.get_block(conn, block_id)
|
|
finally:
|
|
conn.close()
|
|
if not block:
|
|
raise HTTPException(404, "bloqueio não encontrado")
|
|
return block
|
|
|
|
|
|
@router.post("/{block_id}/resolve")
|
|
def resolve_carbonio_block(
|
|
block_id: int,
|
|
body: ResolveBlockBody,
|
|
user: auth.DeskUser = Depends(_require_ticket_reader),
|
|
):
|
|
conn = auth.db()
|
|
try:
|
|
block = carbonio_release_store.get_block(conn, block_id)
|
|
if not block:
|
|
raise HTTPException(404, "bloqueio não encontrado")
|
|
if block["status"] == "resolved":
|
|
raise HTTPException(409, f"Já resolvido por {block.get('resolved_by') or 'outro técnico'}")
|
|
if body.confirm_email.lower().strip() != block["email"].lower():
|
|
raise HTTPException(400, "E-mail de confirmação não coincide")
|
|
if not _verify_user_password(conn, user.username, body.password):
|
|
raise HTTPException(403, "Senha incorrecta")
|
|
|
|
try:
|
|
vm_result = vm112_domains.delete_carbonio_account(block["email"])
|
|
except Exception as e:
|
|
raise HTTPException(502, f"VM112/Carbonio: {e}") from e
|
|
|
|
try:
|
|
resolved = carbonio_release_store.resolve_block(
|
|
conn,
|
|
block_id,
|
|
resolved_by=user.username,
|
|
note=vm_result.get("message", "zmprov da"),
|
|
)
|
|
except ValueError as e:
|
|
if str(e) == "already_resolved":
|
|
raise HTTPException(409, "Outro técnico já resolveu este bloqueio") from e
|
|
raise HTTPException(404, "Bloqueio indisponível") from e
|
|
|
|
if block.get("ticket_id"):
|
|
carbonio_release_store.append_ticket_resolution_note(
|
|
conn,
|
|
int(block["ticket_id"]),
|
|
email=block["email"],
|
|
by=user.username,
|
|
)
|
|
return {
|
|
"ok": True,
|
|
"block": resolved,
|
|
"vm112": vm_result,
|
|
"message": f"Conta {block['email']} removida do Carbonio. Peça ao cliente para repetir «Criar conta» no wizard.",
|
|
}
|
|
finally:
|
|
conn.close()
|