Backup automatico script del 2026-08-23 12:04
This commit is contained in:
1 parent
11823447a2
commit
795a15a7b6
66 files changed
+8546
No files matched your search
@@ -0,0 +1,136 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""JWT utilities for OAuth access tokens."""
|
||||
|
||||
import datetime
|
||||
import os
|
||||
import secrets
|
||||
import uuid
|
||||
from typing import Optional
|
||||
|
||||
import jwt
|
||||
|
||||
from .db import get_conn
|
||||
|
||||
JWT_ALG = "HS256"
|
||||
ACCESS_TOKEN_HOURS = 1
|
||||
REFRESH_TOKEN_DAYS = 30
|
||||
|
||||
|
||||
def jwt_secret() -> str:
|
||||
secret = os.environ.get("MCP_JWT_SECRET", "").strip()
|
||||
if not secret:
|
||||
secret = secrets.token_urlsafe(48)
|
||||
os.environ["MCP_JWT_SECRET"] = secret
|
||||
return secret
|
||||
|
||||
|
||||
def base_url() -> str:
|
||||
return os.environ.get("MCP_BASE_URL", "https://mcp.loogle.it").rstrip("/")
|
||||
|
||||
|
||||
def scopes_for_user(user: dict, requested: str) -> str:
|
||||
parts = [s for s in requested.split() if s]
|
||||
allowed = {
|
||||
"context:read",
|
||||
"context:write",
|
||||
"knowledge:read",
|
||||
"knowledge:write",
|
||||
"gitea:read",
|
||||
"gitea:write",
|
||||
"home:read",
|
||||
"irrigation:read",
|
||||
"turni:read",
|
||||
}
|
||||
if user.get("is_admin"):
|
||||
allowed.add("admin")
|
||||
filtered = [s for s in parts if s in allowed]
|
||||
if not filtered:
|
||||
filtered = [
|
||||
"context:read",
|
||||
"context:write",
|
||||
"knowledge:read",
|
||||
"knowledge:write",
|
||||
"gitea:read",
|
||||
"gitea:write",
|
||||
"home:read",
|
||||
"irrigation:read",
|
||||
"turni:read",
|
||||
]
|
||||
return " ".join(filtered)
|
||||
|
||||
|
||||
def create_access_token(user: dict, scope: str, client_id: str) -> tuple[str, str]:
|
||||
jti = str(uuid.uuid4())
|
||||
now = datetime.datetime.utcnow()
|
||||
payload = {
|
||||
"iss": base_url(),
|
||||
"sub": user["username"],
|
||||
"uid": user["id"],
|
||||
"scope": scope,
|
||||
"client_id": client_id,
|
||||
"jti": jti,
|
||||
"iat": now,
|
||||
"exp": now + datetime.timedelta(hours=ACCESS_TOKEN_HOURS),
|
||||
}
|
||||
token = jwt.encode(payload, jwt_secret(), algorithm=JWT_ALG)
|
||||
return token, jti
|
||||
|
||||
|
||||
def create_refresh_token(user_id: int, scope: str, client_id: str) -> str:
|
||||
token = secrets.token_urlsafe(48)
|
||||
expires = (
|
||||
datetime.datetime.utcnow() + datetime.timedelta(days=REFRESH_TOKEN_DAYS)
|
||||
).strftime("%Y-%m-%d %H:%M:%S")
|
||||
get_conn().execute(
|
||||
"INSERT INTO refresh_tokens(token,user_id,client_id,scope,expires_at) VALUES (?,?,?,?,?)",
|
||||
(token, user_id, client_id, scope, expires),
|
||||
)
|
||||
get_conn().commit()
|
||||
return token
|
||||
|
||||
|
||||
def decode_access_token(token: str) -> Optional[dict]:
|
||||
try:
|
||||
payload = jwt.decode(token, jwt_secret(), algorithms=[JWT_ALG], issuer=base_url())
|
||||
except jwt.PyJWTError:
|
||||
return None
|
||||
jti = payload.get("jti")
|
||||
if not jti:
|
||||
return None
|
||||
row = get_conn().execute(
|
||||
"SELECT 1 FROM revoked_jtis WHERE jti=? AND expires_at > datetime('now')",
|
||||
(jti,),
|
||||
).fetchone()
|
||||
if row:
|
||||
return None
|
||||
return payload
|
||||
|
||||
|
||||
def revoke_jti(jti: str, expires_at: datetime.datetime) -> None:
|
||||
get_conn().execute(
|
||||
"INSERT OR IGNORE INTO revoked_jtis(jti,expires_at) VALUES (?,?)",
|
||||
(jti, expires_at.strftime("%Y-%m-%d %H:%M:%S")),
|
||||
)
|
||||
get_conn().commit()
|
||||
|
||||
|
||||
def revoke_refresh_token(token: str) -> None:
|
||||
get_conn().execute("UPDATE refresh_tokens SET revoked=1 WHERE token=?", (token,))
|
||||
get_conn().commit()
|
||||
|
||||
|
||||
def consume_refresh_token(token: str) -> Optional[dict]:
|
||||
row = get_conn().execute(
|
||||
"SELECT * FROM refresh_tokens WHERE token=? AND revoked=0 AND expires_at > datetime('now')",
|
||||
(token,),
|
||||
).fetchone()
|
||||
if not row:
|
||||
return None
|
||||
return dict(row)
|
||||
|
||||
|
||||
def has_scope(claims: dict, scope: str) -> bool:
|
||||
scopes = set((claims.get("scope") or "").split())
|
||||
if "admin" in scopes:
|
||||
return True
|
||||
return scope in scopes
|
||||
Reference in new issue
Block a user