import hashlib import hmac import json import logging from odoo import http from odoo.http import request from odoo.addons.encoach_api.controllers.base import ( _json_response, _error_response, ) _logger = logging.getLogger(__name__) class EncoachVerifyController(http.Controller): # ------------------------------------------------------------------ # GET /api/verify/ — public, no auth required # ------------------------------------------------------------------ @http.route('/api/verify/', type='http', auth='none', methods=['GET'], csrf=False) def verify_result(self, hash_code, **kw): try: env = request.env(su=True) Attempt = env['encoach.student.attempt'] Score = env['encoach.score'] secret = env['ir.config_parameter'].get_param( 'encoach.verification_secret', 'default-secret-change-me', ) attempts = Attempt.search([('status', '=', 'released')]) for attempt in attempts: student_name = ( attempt.student_id.name if attempt.student_id else '' ) exam_name = ( attempt.exam_id.name if attempt.exam_id else '' ) message = f"{attempt.id}:{student_name}:{exam_name}" computed = hmac.new( secret.encode('utf-8'), message.encode('utf-8'), hashlib.sha256, ).hexdigest() if hmac.compare_digest(computed, hash_code): scores = Score.search([('attempt_id', '=', attempt.id)]) skills = [] for s in scores: skills.append({ 'skill': s.skill or '', 'band': s.band_score, }) return _json_response({ 'verified': True, 'student_name': student_name, 'exam_name': exam_name, 'date': str(attempt.started_at or attempt.create_date or '')[:19], 'skills': skills, 'overall_band': attempt.overall_band, 'cefr_level': attempt.cefr_level or '', }) return _error_response('Verification hash not found', 404) except Exception as e: _logger.exception('verify_result failed') return _error_response(str(e), 500)