fix: OnlyOffice Callback JWT-Validierung + Speichern
Problem: OnlyOffice sendete JWT-Token im Callback-Request und im Body, unser Endpoint hat das ignoriert -> Speichern schlug fehl. Fix: - Callback validiert OnlyOffice JWT aus Authorization-Header - Callback entpackt JWT-wrapped Body (OnlyOffice wraps den Body in einen JWT-Token wenn JWT_ENABLED=true) - Download der gespeicherten Datei sendet JWT-Header mit - Besseres Error-Logging mit Traceback Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1f9b87900c
commit
9d1f4e117c
|
|
@ -422,14 +422,35 @@ def onlyoffice_callback():
|
|||
"""Callback from OnlyOffice when document is saved."""
|
||||
import urllib.request
|
||||
|
||||
# Validate OnlyOffice JWT token if JWT is enabled
|
||||
jwt_secret = os.environ.get('JWT_SECRET_KEY', '')
|
||||
if jwt_secret:
|
||||
import jwt as pyjwt
|
||||
auth_header = request.headers.get('Authorization', '')
|
||||
if auth_header.startswith('Bearer '):
|
||||
oo_token = auth_header[7:]
|
||||
try:
|
||||
pyjwt.decode(oo_token, jwt_secret, algorithms=['HS256'])
|
||||
except Exception as e:
|
||||
print(f'[OnlyOffice Callback] JWT validation failed: {e}')
|
||||
return jsonify({'error': 1}), 200
|
||||
|
||||
callback_key = request.args.get('key', '')
|
||||
file_id_str = AppSettings.get(f'oo_callback_{callback_key}', '')
|
||||
|
||||
if not file_id_str:
|
||||
return jsonify({'error': 1}), 200 # OnlyOffice expects {"error": 0} for success
|
||||
|
||||
# OnlyOffice may wrap the body in a JWT token
|
||||
data = request.get_json()
|
||||
status = data.get('status', 0)
|
||||
if data and 'token' in data and jwt_secret:
|
||||
import jwt as pyjwt
|
||||
try:
|
||||
data = pyjwt.decode(data['token'], jwt_secret, algorithms=['HS256'])
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
status = data.get('status', 0) if data else 0
|
||||
|
||||
# Status 2 = document ready for saving, 6 = force save
|
||||
if status in (2, 6):
|
||||
|
|
@ -443,7 +464,15 @@ def onlyoffice_callback():
|
|||
filepath = Path(current_app.config['UPLOAD_PATH']) / str(f.owner_id) / f.storage_path
|
||||
|
||||
# Download the saved document from OnlyOffice
|
||||
urllib.request.urlretrieve(download_url, str(filepath))
|
||||
req = urllib.request.Request(download_url)
|
||||
if jwt_secret:
|
||||
# OnlyOffice may require JWT for download too
|
||||
import jwt as pyjwt
|
||||
dl_token = pyjwt.encode({'url': download_url}, jwt_secret, algorithm='HS256')
|
||||
req.add_header('Authorization', f'Bearer {dl_token}')
|
||||
with urllib.request.urlopen(req) as resp, open(str(filepath), 'wb') as out:
|
||||
import shutil
|
||||
shutil.copyfileobj(resp, out)
|
||||
|
||||
# Update metadata
|
||||
f.size = os.path.getsize(str(filepath))
|
||||
|
|
@ -455,7 +484,9 @@ def onlyoffice_callback():
|
|||
f.updated_at = datetime.now(timezone.utc)
|
||||
db.session.commit()
|
||||
except Exception as e:
|
||||
print(f'[OnlyOffice Callback] Error: {e}')
|
||||
print(f'[OnlyOffice Callback] Save error: {e}')
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return jsonify({'error': 1}), 200
|
||||
|
||||
# Status 4 = closed without changes
|
||||
|
|
|
|||
Loading…
Reference in New Issue