import base64 import logging from odoo import http from odoo.http import request from .base import EncoachMixin _logger = logging.getLogger(__name__) class StorageController(EncoachMixin, http.Controller): # ------------------------------------------------------------- upload @http.route('/api/storage', type='http', auth='public', methods=['POST', 'OPTIONS'], csrf=False, cors='*') def upload_file(self, **kwargs): """Upload a file and return its public URL via ``ir.attachment``.""" try: user = self._authenticate() if not user: return self._error_response('Unauthorized', 401) uploaded = request.httprequest.files.get('file') if not uploaded: return self._error_response('No file provided', 400) data = uploaded.read() attachment = request.env['ir.attachment'].sudo().create({ 'name': uploaded.filename, 'datas': base64.b64encode(data), 'res_model': 'encoach.storage', 'type': 'binary', 'public': True, }) base_url = request.env['ir.config_parameter'].sudo().get_param('web.base.url', '') file_url = f"{base_url}/web/content/{attachment.id}/{uploaded.filename}" return self._json_response({ 'ok': True, 'id': attachment.id, 'url': file_url, 'filename': uploaded.filename, 'size': len(data), }) except Exception: _logger.exception("Upload file error") return self._error_response('Internal server error', 500) # ------------------------------------------------------------ delete @http.route('/api/storage/delete', type='http', auth='public', methods=['POST', 'OPTIONS'], csrf=False, cors='*') def delete_file(self, **kwargs): try: user = self._authenticate() if not user: return self._error_response('Unauthorized', 401) body = self._get_json_body() attachment_id = body.get('id') or body.get('attachmentId') url = body.get('url', '') Attachment = request.env['ir.attachment'].sudo() if attachment_id: att = Attachment.browse(int(attachment_id)) elif url: parts = url.rstrip('/').split('/') try: att_id = int(parts[-2]) if len(parts) >= 2 else 0 except (ValueError, IndexError): att_id = 0 att = Attachment.browse(att_id) if att_id else Attachment else: return self._error_response('id or url is required', 400) if att.exists(): att.unlink() return self._json_response({'ok': True}) except Exception: _logger.exception("Delete file error") return self._error_response('Internal server error', 500)