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
83 lines
3.0 KiB
Python
83 lines
3.0 KiB
Python
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)
|