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."""
|
"""Callback from OnlyOffice when document is saved."""
|
||||||
import urllib.request
|
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', '')
|
callback_key = request.args.get('key', '')
|
||||||
file_id_str = AppSettings.get(f'oo_callback_{callback_key}', '')
|
file_id_str = AppSettings.get(f'oo_callback_{callback_key}', '')
|
||||||
|
|
||||||
if not file_id_str:
|
if not file_id_str:
|
||||||
return jsonify({'error': 1}), 200 # OnlyOffice expects {"error": 0} for success
|
return jsonify({'error': 1}), 200 # OnlyOffice expects {"error": 0} for success
|
||||||
|
|
||||||
|
# OnlyOffice may wrap the body in a JWT token
|
||||||
data = request.get_json()
|
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
|
# Status 2 = document ready for saving, 6 = force save
|
||||||
if status in (2, 6):
|
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
|
filepath = Path(current_app.config['UPLOAD_PATH']) / str(f.owner_id) / f.storage_path
|
||||||
|
|
||||||
# Download the saved document from OnlyOffice
|
# 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
|
# Update metadata
|
||||||
f.size = os.path.getsize(str(filepath))
|
f.size = os.path.getsize(str(filepath))
|
||||||
|
|
@ -455,7 +484,9 @@ def onlyoffice_callback():
|
||||||
f.updated_at = datetime.now(timezone.utc)
|
f.updated_at = datetime.now(timezone.utc)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
except Exception as e:
|
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
|
return jsonify({'error': 1}), 200
|
||||||
|
|
||||||
# Status 4 = closed without changes
|
# Status 4 = closed without changes
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue