From 5958d7e91e42d029199671ca43484b1b49b51bf4 Mon Sep 17 00:00:00 2001 From: lian Date: Fri, 25 Dec 2020 18:23:42 +0800 Subject: [PATCH] unlock file when saving file via onlyoffice; (#4757) * unlock file when saving file via onlyoffice * add log when no doc_key in cache and locked by online office Co-authored-by: lian --- seahub/onlyoffice/utils.py | 8 +++++ seahub/onlyoffice/views.py | 74 ++++++++++++++++++++++++-------------- 2 files changed, 56 insertions(+), 26 deletions(-) diff --git a/seahub/onlyoffice/utils.py b/seahub/onlyoffice/utils.py index f8124e3a71..9c6d14909a 100644 --- a/seahub/onlyoffice/utils.py +++ b/seahub/onlyoffice/utils.py @@ -1,6 +1,7 @@ import os import json import hashlib +import logging import urllib.parse import posixpath @@ -13,11 +14,15 @@ from seaserv import seafile_api from seahub.base.templatetags.seahub_tags import email2nickname from seahub.utils import get_file_type_and_ext, gen_file_get_url, \ get_site_scheme_and_netloc, normalize_cache_key +from seahub.utils.file_op import if_locked_by_online_office from seahub.settings import ENABLE_WATERMARK from seahub.onlyoffice.settings import ONLYOFFICE_APIJS_URL, \ ONLYOFFICE_FORCE_SAVE, ONLYOFFICE_JWT_SECRET +# Get an instance of a logger +logger = logging.getLogger(__name__) + def generate_onlyoffice_cache_key(repo_id, file_path): prefix = "ONLYOFFICE_" @@ -68,6 +73,9 @@ def get_onlyoffice_dict(request, username, repo_id, file_path, file_id='', if not doc_key: doc_key = cache.get(cache_key) + if not doc_key and if_locked_by_online_office(repo_id, file_path): + logger.error('no doc_key in cache and locked by online office') + if not doc_key: info_bytes = force_bytes(origin_repo_id + origin_file_path + file_id) doc_key = hashlib.md5(info_bytes).hexdigest()[:20] diff --git a/seahub/onlyoffice/views.py b/seahub/onlyoffice/views.py index 25309769cb..3c5510579d 100644 --- a/seahub/onlyoffice/views.py +++ b/seahub/onlyoffice/views.py @@ -11,11 +11,14 @@ from seaserv import seafile_api from seahub.onlyoffice.settings import VERIFY_ONLYOFFICE_CERTIFICATE from seahub.onlyoffice.utils import generate_onlyoffice_cache_key -from seahub.utils import gen_inner_file_upload_url +from seahub.utils import gen_inner_file_upload_url, is_pro_version +from seahub.utils.file_op import if_locked_by_online_office + # Get an instance of a logger logger = logging.getLogger(__name__) + @csrf_exempt def onlyoffice_editor_callback(request): """ Callback func of OnlyOffice. @@ -31,13 +34,13 @@ def onlyoffice_editor_callback(request): # otherwise the document editor will display an error message. return HttpResponse('{"error": 0}') - #### body info of POST rquest when open file on browser + # body info of POST rquest when open file on browser # {u'actions': [{u'type': 1, u'userid': u'uid-1527736776860'}], # u'key': u'8062bdccf9b4cf809ae3', # u'status': 1, # u'users': [u'uid-1527736776860']} - #### body info of POST rquest when close file's web page (save file) + # body info of POST rquest when close file's web page (save file) # {u'actions': [{u'type': 0, u'userid': u'uid-1527736951523'}], # u'changesurl': u'...', # u'history': {u'changes': [{u'created': u'2018-05-31 03:17:17', @@ -74,9 +77,21 @@ def onlyoffice_editor_callback(request): post_data = json.loads(request.body) status = int(post_data.get('status', -1)) - # When forcesave is initiated, document editing service performs request to - # the callback handler with the link to the document as the url parameter and - # with the 6 value for the status parameter. + if status not in (1, 2, 4, 6): + logger.error('onlyoffice status invalid: {}'.format(status)) + return HttpResponse('{"error": 0}') + + # get file basic info + doc_key = post_data.get('key') + doc_info = json.loads(cache.get("ONLYOFFICE_%s" % doc_key)) + + repo_id = doc_info['repo_id'] + file_path = doc_info['file_path'] + username = doc_info['username'] + + cache_key = generate_onlyoffice_cache_key(repo_id, file_path) + + # save file if status in (2, 6): # Defines the link to the edited document to be saved with the document storage service. @@ -87,27 +102,11 @@ def onlyoffice_editor_callback(request): logger.error('[OnlyOffice] No response from file content url.') return HttpResponse('{"error": 0}') - # get file basic info - doc_key = post_data.get('key') - doc_info = json.loads(cache.get("ONLYOFFICE_%s" % doc_key)) - - repo_id = doc_info['repo_id'] - file_path = doc_info['file_path'] - username = doc_info['username'] - - cache_key = generate_onlyoffice_cache_key(repo_id, file_path) - # cache document key when forcesave - if status == 6: - cache.set(cache_key, doc_key) - - # remove document key from cache when document is ready for saving - # no one is editting - if status == 2: - cache.delete(cache_key) - - fake_obj_id = {'online_office_update': True,} + fake_obj_id = {'online_office_update': True} update_token = seafile_api.get_fileserver_access_token(repo_id, - json.dumps(fake_obj_id), 'update', username) + json.dumps(fake_obj_id), + 'update', + username) if not update_token: logger.error('[OnlyOffice] No fileserver access token.') @@ -124,4 +123,27 @@ def onlyoffice_editor_callback(request): update_url = gen_inner_file_upload_url('update-api', update_token) requests.post(update_url, files=files) + # 2 - document is ready for saving, + if status == 2: + + cache.delete(cache_key) + cache.delete("ONLYOFFICE_%s" % doc_key) + + if is_pro_version() and if_locked_by_online_office(repo_id, file_path): + seafile_api.unlock_file(repo_id, file_path) + + # 6 - document is being edited, but the current document state is saved, + if status == 6: + # cache document key when forcesave + cache.set(cache_key, doc_key) + + # 4 - document is closed with no changes, + if status == 4: + + cache.delete(cache_key) + cache.delete("ONLYOFFICE_%s" % doc_key) + + if is_pro_version() and if_locked_by_online_office(repo_id, file_path): + seafile_api.unlock_file(repo_id, file_path) + return HttpResponse('{"error": 0}')