fix: Dedizierter OnlyOffice Download-Endpunkt ohne JWT-Auth
Problem: OnlyOffice konnte Dateien nicht herunterladen weil unser token_required-Decorator den Request ablehnte - OnlyOffice sendet eigene Header die mit unserem JWT-System kollidieren. Loesung: Eigener Endpunkt GET /files/oo-download/<access_key> - Kein JWT noetig, stattdessen Einmal-Schluessel - Schluessel wird beim Oeffnen des Editors generiert und in der DB gespeichert - Schluessel enthaelt file_id + user_id, wird beim Download validiert - OnlyOffice ruft diesen Endpunkt intern auf (http://minicloud:5000) - Kein Token in der URL, keine JWT-Konflikte Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c3c0610750
commit
1f9b87900c
|
|
@ -353,22 +353,11 @@ def onlyoffice_config(file_id):
|
|||
AppSettings.set(f'oo_callback_{callback_key}', str(file_id))
|
||||
|
||||
# Build the config
|
||||
# Internal URL for OnlyOffice to reach our backend (Docker network)
|
||||
internal_url = os.environ.get('ONLYOFFICE_INTERNAL_URL', 'http://minicloud:5000')
|
||||
|
||||
# Generate a long-lived token for OnlyOffice file access (24h)
|
||||
from app.api.auth import create_access_token
|
||||
import jwt as pyjwt
|
||||
oo_file_token = pyjwt.encode(
|
||||
{
|
||||
'user_id': user.id,
|
||||
'type': 'access',
|
||||
'exp': datetime.now(timezone.utc) + timedelta(hours=24),
|
||||
'iat': datetime.now(timezone.utc),
|
||||
},
|
||||
current_app.config['JWT_SECRET_KEY'],
|
||||
algorithm='HS256',
|
||||
)
|
||||
# Generate a one-time file access key (no JWT needed, simpler for OnlyOffice)
|
||||
file_access_key = _secrets.token_urlsafe(32)
|
||||
AppSettings.set(f'oo_file_{file_access_key}', f'{file_id}:{user.id}')
|
||||
|
||||
config = {
|
||||
'available': True,
|
||||
|
|
@ -378,7 +367,7 @@ def onlyoffice_config(file_id):
|
|||
'fileType': ext,
|
||||
'key': f'{file_id}_{f.checksum or "0"}_{callback_key[:8]}',
|
||||
'title': f.name,
|
||||
'url': f'{internal_url}/api/files/{file_id}/download?token={oo_file_token}',
|
||||
'url': f'{internal_url}/api/files/oo-download/{file_access_key}',
|
||||
},
|
||||
'documentType': doc_type,
|
||||
'editorConfig': {
|
||||
|
|
@ -393,7 +382,7 @@ def onlyoffice_config(file_id):
|
|||
},
|
||||
}
|
||||
|
||||
# Sign with JWT if secret is set
|
||||
# Sign config with JWT for OnlyOffice validation
|
||||
jwt_secret = os.environ.get('JWT_SECRET_KEY', '')
|
||||
if jwt_secret:
|
||||
import jwt as pyjwt
|
||||
|
|
@ -402,6 +391,32 @@ def onlyoffice_config(file_id):
|
|||
return jsonify(config), 200
|
||||
|
||||
|
||||
@api_bp.route('/files/onlyoffice-callback', methods=['POST'])
|
||||
@api_bp.route('/files/oo-download/<access_key>', methods=['GET'])
|
||||
def oo_download(access_key):
|
||||
"""Dedicated download endpoint for OnlyOffice - no JWT auth, uses one-time key."""
|
||||
data = AppSettings.get(f'oo_file_{access_key}', '')
|
||||
if not data:
|
||||
return jsonify({'error': 'Ungueltiger Zugangsschluessel'}), 403
|
||||
|
||||
parts = data.split(':')
|
||||
if len(parts) != 2:
|
||||
return jsonify({'error': 'Ungueltiger Zugangsschluessel'}), 403
|
||||
|
||||
file_id = int(parts[0])
|
||||
from app.models.file import File
|
||||
f = db.session.get(File, file_id)
|
||||
if not f:
|
||||
return jsonify({'error': 'Datei nicht gefunden'}), 404
|
||||
|
||||
filepath = Path(current_app.config['UPLOAD_PATH']) / str(f.owner_id) / f.storage_path
|
||||
if not filepath.exists():
|
||||
return jsonify({'error': 'Datei nicht auf Datentraeger'}), 404
|
||||
|
||||
return send_file(str(filepath), mimetype=f.mime_type or 'application/octet-stream',
|
||||
as_attachment=False, download_name=f.name)
|
||||
|
||||
|
||||
@api_bp.route('/files/onlyoffice-callback', methods=['POST'])
|
||||
def onlyoffice_callback():
|
||||
"""Callback from OnlyOffice when document is saved."""
|
||||
|
|
|
|||
Loading…
Reference in New Issue