# -*- coding: utf-8 -*- """CRUD de claves de API de terceros (Configuración -> API).""" import json from odoo import http from odoo.http import request, Response from odoo.addons.skeen_whatsapp.controllers.auth import require_role, require_perm from odoo.addons.skeen_plataforma.models.api_key import SCOPES BASE = '/skeen/frontend/v1' def _json(data, status=200): return Response( json.dumps(data, default=str), status=status, mimetype='application/json', headers={ 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization', }, ) def _body(): try: raw = request.httprequest.get_data(as_text=True) return json.loads(raw) if raw else {} except Exception: return {} def _login(): return getattr(request.frontend_user, 'login', '') if hasattr(request, 'frontend_user') else '' class SkeenApiKeysController(http.Controller): @http.route(BASE + '/api_keys', type='http', auth='none', methods=['GET', 'OPTIONS'], csrf=False) @require_role('gerencia') @require_perm('api.claves') def list_api_keys(self, **kw): try: keys = request.env['skeen.api.key'].sudo().search([]) return _json({ 'status': 'success', 'api_keys': [k.to_public_dict() for k in keys], 'scopes': [{'clave': c, 'label': l} for c, l in SCOPES], }) except Exception as e: return _json({'status': 'error', 'message': str(e)}, 500) @http.route(BASE + '/api_keys', type='http', auth='none', methods=['POST', 'OPTIONS'], csrf=False) @require_role('gerencia') @require_perm('api.claves') def create_api_key(self, **kw): try: data = _body() nombre = (data.get('name') or '').strip() if not nombre: return _json({'status': 'error', 'message': 'El nombre es obligatorio'}, 400) key, raw = request.env['skeen.api.key'].sudo().generar({ 'name': nombre, 'scopes': data.get('scopes') or [], 'vence': data.get('vence') or False, 'notas': data.get('notas') or '', }, login=_login()) return _json({ 'status': 'success', 'clave': raw, # se muestra UNA sola vez 'api_key': key.to_public_dict(), 'message': 'Guarda esta clave: no se volverá a mostrar.', }) except Exception as e: request.env.cr.rollback() return _json({'status': 'error', 'message': str(e)}, 500) @http.route(BASE + '/api_keys/', type='http', auth='none', methods=['PUT', 'OPTIONS'], csrf=False) @require_role('gerencia') @require_perm('api.claves') def update_api_key(self, key_id, **kw): try: key = request.env['skeen.api.key'].sudo().browse(key_id) if not key.exists(): return _json({'status': 'error', 'message': 'Clave no encontrada'}, 404) data = _body() vals = {} if 'name' in data and (data.get('name') or '').strip(): vals['name'] = data['name'].strip() if 'scopes' in data: vals['scopes'] = json.dumps(key._normalizar_scopes(data.get('scopes') or [])) if 'activo' in data: vals['activo'] = bool(data['activo']) if 'vence' in data: vals['vence'] = data.get('vence') or False if 'notas' in data: vals['notas'] = data.get('notas') or '' if vals: key.write(vals) return _json({'status': 'success', 'api_key': key.to_public_dict()}) except Exception as e: request.env.cr.rollback() return _json({'status': 'error', 'message': str(e)}, 500) @http.route(BASE + '/api_keys//revocar', type='http', auth='none', methods=['POST', 'OPTIONS'], csrf=False) @require_role('gerencia') @require_perm('api.claves') def revocar_api_key(self, key_id, **kw): try: key = request.env['skeen.api.key'].sudo().browse(key_id) if not key.exists(): return _json({'status': 'error', 'message': 'Clave no encontrada'}, 404) key.action_revocar(login=_login()) return _json({'status': 'success', 'message': 'Clave revocada.', 'api_key': key.to_public_dict()}) except Exception as e: request.env.cr.rollback() return _json({'status': 'error', 'message': str(e)}, 500)