Fix Agentic Ops 401 — reuse Desk global api() and session check.
Forward Authorization in nginx; accept Spec 027 roles in JWT decode. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
40bb16bbc9
commit
6daa692af8
5 changed files with 37 additions and 16 deletions
|
|
@ -14,8 +14,8 @@ from typing import Any
|
|||
from fastapi import Depends, Header, HTTPException, Request
|
||||
from jose import JWTError, jwt
|
||||
import bcrypt
|
||||
import time
|
||||
|
||||
from app.permissions import HUMAN_ROLES
|
||||
from app.totp_util import verify_code as verify_totp_code
|
||||
|
||||
DB_PATH = Path(os.getenv("SQLITE_PATH", "/data/ops.db"))
|
||||
|
|
@ -134,7 +134,7 @@ def decode_token(token: str) -> DeskUser:
|
|||
raise HTTPException(401, "invalid or expired token") from exc
|
||||
username = payload.get("sub")
|
||||
role = payload.get("role")
|
||||
if not username or role not in {"super_admin", "ops_lead", "technician", "noc"}:
|
||||
if not username or role not in HUMAN_ROLES:
|
||||
raise HTTPException(401, "invalid token claims")
|
||||
with db() as conn:
|
||||
row = conn.execute(
|
||||
|
|
|
|||
|
|
@ -2,10 +2,13 @@
|
|||
const esc = (s) => String(s ?? '').replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
|
||||
let state = { threadId: null, selectedAgent: 'A6' };
|
||||
|
||||
async function api(path, opts = {}) {
|
||||
/** Usa o helper global do Desk (app.js) — garante JWT igual aos outros módulos. */
|
||||
async function agentsApi(path, opts = {}) {
|
||||
const deskApi = typeof globalThis.api === 'function' ? globalThis.api : null;
|
||||
if (deskApi) return deskApi(`/v1/agents${path}`, opts);
|
||||
const h = authHeaders({ ...(opts.headers || {}) });
|
||||
if (!(opts.body instanceof FormData) && !h['Content-Type']) h['Content-Type'] = 'application/json';
|
||||
const r = await fetchWithTimeout(`/api/v1/agents${path}`, { ...opts, headers: h });
|
||||
const r = await fetchWithTimeout(`/api/v1/agents${path}`, { ...opts, headers: h }, 60000);
|
||||
if (r.status === 401) {
|
||||
logout();
|
||||
throw new Error('sessão expirada — faça login novamente');
|
||||
|
|
@ -53,7 +56,7 @@
|
|||
const box = el.querySelector('#agentic-thread-messages');
|
||||
if (!box) return;
|
||||
box.innerHTML = '<p class="loading">Carregando thread…</p>';
|
||||
const data = await api(`/threads/${threadId}/messages`);
|
||||
const data = await agentsApi(`/threads/${threadId}/messages`);
|
||||
box.innerHTML = data.messages.map(threadBubble).join('') || '<p class="empty">Sem mensagens.</p>';
|
||||
box.scrollTop = box.scrollHeight;
|
||||
}
|
||||
|
|
@ -62,13 +65,24 @@
|
|||
const el = document.getElementById('agentic-ops-content');
|
||||
if (!el) return;
|
||||
el.innerHTML = '<p class="loading">Carregando Agentic Ops…</p>';
|
||||
if (!getToken()) {
|
||||
el.innerHTML = '<p class="error">Sessão não encontrada neste endereço. <a href="/login.html">Fazer login</a> (use sempre o mesmo URL — ex. desk.ligbox.com.br).</p>';
|
||||
return;
|
||||
}
|
||||
if (typeof ensureValidSession === 'function') {
|
||||
const ok = await ensureValidSession();
|
||||
if (!ok) {
|
||||
el.innerHTML = '<p class="error">Sessão expirada. <a href="/login.html">Fazer login</a></p>';
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
const [health, roster, inbox, threads, findings] = await Promise.all([
|
||||
api('/health'),
|
||||
api('/roster'),
|
||||
api('/inbox?limit=20'),
|
||||
api('/threads?limit=15'),
|
||||
api('/findings?limit=15'),
|
||||
agentsApi('/health'),
|
||||
agentsApi('/roster'),
|
||||
agentsApi('/inbox?limit=20'),
|
||||
agentsApi('/threads?limit=15'),
|
||||
agentsApi('/findings?limit=15'),
|
||||
]);
|
||||
const tier = health.tier === 't1' ? 'T1 LLM' : 'T0';
|
||||
const ollama = health.ollama
|
||||
|
|
@ -149,7 +163,7 @@
|
|||
});
|
||||
el.querySelectorAll('[data-ack-msg]').forEach(btn => {
|
||||
btn.addEventListener('click', async () => {
|
||||
await api(`/messages/${btn.dataset.ackMsg}/ack`, { method: 'POST' });
|
||||
await agentsApi(`/messages/${btn.dataset.ackMsg}/ack`, { method: 'POST' });
|
||||
await renderAgenticOps();
|
||||
});
|
||||
});
|
||||
|
|
@ -162,7 +176,7 @@
|
|||
const tid = state.threadId || parseInt(el.querySelector('#agentic-thread-select')?.value, 10);
|
||||
const body = (input?.value || '').trim();
|
||||
if (!tid || !body) return;
|
||||
await api(`/threads/${tid}/reply`, {
|
||||
await agentsApi(`/threads/${tid}/reply`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ body, target_agent: state.selectedAgent }),
|
||||
});
|
||||
|
|
@ -177,7 +191,7 @@
|
|||
out.hidden = false;
|
||||
out.innerHTML = '<p class="loading">A pensar…</p>';
|
||||
try {
|
||||
const res = await api('/chat', {
|
||||
const res = await agentsApi('/chat', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ question: q, include_findings: true, target_agent: state.selectedAgent }),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -443,7 +443,7 @@
|
|||
<script src="/assets/tickets-workspace.js?v=20260619tickets2"></script>
|
||||
<script src="/assets/tickets-detail-panel.js?v=20260619tickets2"></script>
|
||||
<script src="/assets/servicos.js?v=20260620agentic"></script>
|
||||
<script src="/assets/agentic-ops.js?v=20260620agentic2"></script>
|
||||
<script src="/assets/app.js?v=20260620agentic"></script>
|
||||
<script src="/assets/agentic-ops.js?v=20260620agentic3"></script>
|
||||
<script src="/assets/app.js?v=20260620agentic3"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ server {
|
|||
|
||||
resolver 127.0.0.11 valid=10s ipv6=off;
|
||||
|
||||
location ~* \.(html)$ {
|
||||
location ~* \.(html|js)$ {
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@ server {
|
|||
proxy_pass http://$upstream:8080$request_uri;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header Authorization $http_authorization;
|
||||
proxy_connect_timeout 30s;
|
||||
proxy_send_timeout 600s;
|
||||
proxy_read_timeout 600s;
|
||||
|
|
|
|||
|
|
@ -11,9 +11,15 @@ server {
|
|||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Authorization $http_authorization;
|
||||
proxy_read_timeout 180s;
|
||||
}
|
||||
|
||||
location ~* \.(html|js)$ {
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue