EnCoach Odoo 19 custom modules
Full backend implementation with custom Odoo modules: - encoach_api: Core API, user management, JWT auth - encoach_exam: Exam generation (reading, writing, listening, speaking) - encoach_evaluate: AI-powered evaluation (writing, speaking) - encoach_training: Training tips and walkthrough - encoach_storage: File storage management - encoach_payment: Stripe, PayPal, Paymob integration - encoach_mail: Email notifications Made-with: Cursor
This commit is contained in:
73
encoach_api/controllers/base.py
Normal file
73
encoach_api/controllers/base.py
Normal file
@@ -0,0 +1,73 @@
|
||||
import json
|
||||
import logging
|
||||
|
||||
import jwt as pyjwt
|
||||
|
||||
from odoo.http import request
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EncoachMixin:
|
||||
"""Shared authentication and response helpers for all EnCoach API controllers."""
|
||||
|
||||
def _authenticate(self):
|
||||
"""Decode JWT Bearer token and return the corresponding ``res.users`` record.
|
||||
|
||||
Returns ``None`` when the token is missing, expired or invalid.
|
||||
"""
|
||||
auth_header = request.httprequest.headers.get("Authorization", "")
|
||||
if not auth_header.startswith("Bearer "):
|
||||
return None
|
||||
token = auth_header[7:]
|
||||
secret = (
|
||||
request.env["ir.config_parameter"]
|
||||
.sudo()
|
||||
.get_param("encoach.jwt_secret")
|
||||
)
|
||||
if not secret:
|
||||
_logger.error("System parameter 'encoach.jwt_secret' is not configured")
|
||||
return None
|
||||
try:
|
||||
payload = pyjwt.decode(token, secret, algorithms=["HS256"])
|
||||
except pyjwt.ExpiredSignatureError:
|
||||
return None
|
||||
except pyjwt.InvalidTokenError:
|
||||
return None
|
||||
user_id = payload.get("user_id")
|
||||
if not user_id:
|
||||
return None
|
||||
user = request.env["res.users"].sudo().browse(int(user_id))
|
||||
if not user.exists():
|
||||
return None
|
||||
return user
|
||||
|
||||
def _json_response(self, data, status=200):
|
||||
return request.make_json_response(data, status=status)
|
||||
|
||||
def _error_response(self, message, status=400, code=None):
|
||||
body = {"error": message}
|
||||
if code:
|
||||
body["code"] = code
|
||||
return request.make_json_response(body, status=status)
|
||||
|
||||
def _get_json_body(self):
|
||||
try:
|
||||
return json.loads(request.httprequest.get_data(as_text=True))
|
||||
except (ValueError, TypeError):
|
||||
return {}
|
||||
|
||||
def _paginate_params(self, kwargs):
|
||||
page = max(int(kwargs.get("page", 1)), 1)
|
||||
limit = min(max(int(kwargs.get("limit", 20)), 1), 100)
|
||||
offset = (page - 1) * limit
|
||||
return offset, limit, page
|
||||
|
||||
def _serialize(self, record):
|
||||
"""Delegate to the record's own to_encoach_dict() if available."""
|
||||
if hasattr(record, "to_encoach_dict"):
|
||||
return record.to_encoach_dict()
|
||||
return {"id": record.id}
|
||||
|
||||
def _serialize_list(self, records):
|
||||
return [self._serialize(r) for r in records]
|
||||
Reference in New Issue
Block a user