mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-20 10:58:33 +00:00
add new online office refresh lock api for share link (#2497)
This commit is contained in:
@@ -19,15 +19,17 @@ from pysearpc import SearpcError
|
|||||||
from seahub.api2.utils import api_error
|
from seahub.api2.utils import api_error
|
||||||
from seahub.api2.authentication import TokenAuthentication
|
from seahub.api2.authentication import TokenAuthentication
|
||||||
from seahub.api2.throttling import UserRateThrottle
|
from seahub.api2.throttling import UserRateThrottle
|
||||||
from seahub.api2.permissions import CanGenerateShareLink
|
from seahub.api2.permissions import CanGenerateShareLink, IsProVersion
|
||||||
|
|
||||||
from seahub.share.models import FileShare, OrgFileShare
|
from seahub.share.models import FileShare
|
||||||
from seahub.utils import gen_shared_link, is_org_context
|
from seahub.utils import gen_shared_link, is_org_context, normalize_file_path
|
||||||
|
from seahub.utils.file_op import if_locked_by_online_office
|
||||||
from seahub.views import check_folder_permission
|
from seahub.views import check_folder_permission
|
||||||
from seahub.utils.timeutils import datetime_to_isoformat_timestr
|
from seahub.utils.timeutils import datetime_to_isoformat_timestr
|
||||||
|
from seahub.constants import PERMISSION_READ_WRITE
|
||||||
|
|
||||||
from seahub.settings import SHARE_LINK_EXPIRE_DAYS_MAX, \
|
from seahub.settings import SHARE_LINK_EXPIRE_DAYS_MAX, \
|
||||||
SHARE_LINK_EXPIRE_DAYS_MIN
|
SHARE_LINK_EXPIRE_DAYS_MIN, SHARE_LINK_LOGIN_REQUIRED
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -343,3 +345,64 @@ class ShareLink(APIView):
|
|||||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||||
|
|
||||||
return Response({'success': True})
|
return Response({'success': True})
|
||||||
|
|
||||||
|
|
||||||
|
class ShareLinkOnlineOfficeLock(APIView):
|
||||||
|
|
||||||
|
permission_classes = (IsProVersion,)
|
||||||
|
throttle_classes = (UserRateThrottle,)
|
||||||
|
|
||||||
|
def put(self, request, token):
|
||||||
|
""" This api only used for refresh OnlineOffice lock
|
||||||
|
when user edit office file via share link.
|
||||||
|
|
||||||
|
Permission checking:
|
||||||
|
1, If enable SHARE_LINK_LOGIN_REQUIRED, user must have been authenticated.
|
||||||
|
2, Share link should have can_edit permission.
|
||||||
|
3, File must have been locked by OnlineOffice.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if SHARE_LINK_LOGIN_REQUIRED and \
|
||||||
|
not request.user.is_authenticated():
|
||||||
|
error_msg = 'Permission denied.'
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||||
|
|
||||||
|
try:
|
||||||
|
share_link = FileShare.objects.get(token=token)
|
||||||
|
except FileShare.DoesNotExist:
|
||||||
|
error_msg = 'Share link %s not found.' % token
|
||||||
|
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||||
|
|
||||||
|
if share_link.is_expired():
|
||||||
|
error_msg = 'Share link %s is expired.' % token
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
shared_by = share_link.username
|
||||||
|
repo_id = share_link.repo_id
|
||||||
|
path = normalize_file_path(share_link.path)
|
||||||
|
parent_dir = os.path.dirname(path)
|
||||||
|
if seafile_api.check_permission_by_path(repo_id,
|
||||||
|
parent_dir, shared_by) != PERMISSION_READ_WRITE:
|
||||||
|
error_msg = 'Permission denied.'
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||||
|
|
||||||
|
permissions = share_link.get_permissions()
|
||||||
|
can_edit = permissions['can_edit']
|
||||||
|
if not can_edit:
|
||||||
|
error_msg = 'Share link %s has no edit permission.' % token
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||||
|
|
||||||
|
locked_by_online_office = if_locked_by_online_office(repo_id, path)
|
||||||
|
if locked_by_online_office:
|
||||||
|
# refresh lock file
|
||||||
|
try:
|
||||||
|
seafile_api.refresh_file_lock(repo_id, path)
|
||||||
|
except SearpcError, e:
|
||||||
|
logger.error(e)
|
||||||
|
error_msg = 'Internal Server Error'
|
||||||
|
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||||
|
else:
|
||||||
|
error_msg = _("You can not refresh this file's lock.")
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||||
|
|
||||||
|
return Response({'success': True})
|
||||||
|
@@ -52,6 +52,7 @@ var SEAFILE_GLOBAL = {
|
|||||||
var docEditor = new DocsAPI.DocEditor("placeholder", config);
|
var docEditor = new DocsAPI.DocEditor("placeholder", config);
|
||||||
|
|
||||||
{% if can_edit %}
|
{% if can_edit %}
|
||||||
|
{% if not share_link_token %}
|
||||||
var interval;
|
var interval;
|
||||||
var refreshLock = function() {
|
var refreshLock = function() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@@ -76,6 +77,29 @@ var SEAFILE_GLOBAL = {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
interval = setInterval(refreshLock, 60 * 1000);
|
interval = setInterval(refreshLock, 60 * 1000);
|
||||||
|
{% else %}
|
||||||
|
var interval;
|
||||||
|
var refreshLock = function() {
|
||||||
|
$.ajax({
|
||||||
|
url: '{% url "api-v2.1-share-link-online-office-lock" share_link_token %}',
|
||||||
|
type: 'PUT',
|
||||||
|
dataType: 'json',
|
||||||
|
cache: false,
|
||||||
|
beforeSend: prepareCSRFToken,
|
||||||
|
success: function(data) {
|
||||||
|
},
|
||||||
|
error: function(xhr) {
|
||||||
|
if (xhr.responseText) {
|
||||||
|
feedback(JSON.parse(xhr.responseText).error_msg, 'error');
|
||||||
|
} else {
|
||||||
|
feedback("{% trans "Failed. Please check the network." %}", 'error');
|
||||||
|
}
|
||||||
|
clearInterval(interval);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
interval = setInterval(refreshLock, 60 * 1000);
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</script>
|
</script>
|
||||||
{% if enable_watermark %}
|
{% if enable_watermark %}
|
||||||
|
@@ -51,6 +51,7 @@ var SEAFILE_GLOBAL = {
|
|||||||
document.getElementById('office_frame').className = '';
|
document.getElementById('office_frame').className = '';
|
||||||
|
|
||||||
{% if can_edit %}
|
{% if can_edit %}
|
||||||
|
{% if not share_link_token %}
|
||||||
var interval;
|
var interval;
|
||||||
var refreshLock = function() {
|
var refreshLock = function() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@@ -75,6 +76,29 @@ var SEAFILE_GLOBAL = {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
interval = setInterval(refreshLock, 60 * 1000);
|
interval = setInterval(refreshLock, 60 * 1000);
|
||||||
|
{% else %}
|
||||||
|
var interval;
|
||||||
|
var refreshLock = function() {
|
||||||
|
$.ajax({
|
||||||
|
url: '{% url "api-v2.1-share-link-online-office-lock" share_link_token %}',
|
||||||
|
type: 'PUT',
|
||||||
|
dataType: 'json',
|
||||||
|
cache: false,
|
||||||
|
beforeSend: prepareCSRFToken,
|
||||||
|
success: function(data) {
|
||||||
|
},
|
||||||
|
error: function(xhr) {
|
||||||
|
if (xhr.responseText) {
|
||||||
|
feedback(JSON.parse(xhr.responseText).error_msg, 'error');
|
||||||
|
} else {
|
||||||
|
feedback("{% trans "Failed. Please check the network." %}", 'error');
|
||||||
|
}
|
||||||
|
clearInterval(interval);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
interval = setInterval(refreshLock, 60 * 1000);
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</script>
|
</script>
|
||||||
{% if enable_watermark %}
|
{% if enable_watermark %}
|
||||||
|
@@ -34,7 +34,8 @@ from seahub.api2.endpoints.address_book.members import AddressBookGroupsSearchMe
|
|||||||
|
|
||||||
from seahub.api2.endpoints.group_members import GroupMembers, GroupMembersBulk, GroupMember
|
from seahub.api2.endpoints.group_members import GroupMembers, GroupMembersBulk, GroupMember
|
||||||
from seahub.api2.endpoints.search_group import SearchGroup
|
from seahub.api2.endpoints.search_group import SearchGroup
|
||||||
from seahub.api2.endpoints.share_links import ShareLinks, ShareLink
|
from seahub.api2.endpoints.share_links import ShareLinks, ShareLink, \
|
||||||
|
ShareLinkOnlineOfficeLock
|
||||||
from seahub.api2.endpoints.shared_folders import SharedFolders
|
from seahub.api2.endpoints.shared_folders import SharedFolders
|
||||||
from seahub.api2.endpoints.shared_repos import SharedRepos, SharedRepo
|
from seahub.api2.endpoints.shared_repos import SharedRepos, SharedRepo
|
||||||
from seahub.api2.endpoints.upload_links import UploadLinks, UploadLink, \
|
from seahub.api2.endpoints.upload_links import UploadLinks, UploadLink, \
|
||||||
@@ -251,6 +252,8 @@ urlpatterns = [
|
|||||||
## user::shared-download-links
|
## user::shared-download-links
|
||||||
url(r'^api/v2.1/share-links/$', ShareLinks.as_view(), name='api-v2.1-share-links'),
|
url(r'^api/v2.1/share-links/$', ShareLinks.as_view(), name='api-v2.1-share-links'),
|
||||||
url(r'^api/v2.1/share-links/(?P<token>[a-f0-9]+)/$', ShareLink.as_view(), name='api-v2.1-share-link'),
|
url(r'^api/v2.1/share-links/(?P<token>[a-f0-9]+)/$', ShareLink.as_view(), name='api-v2.1-share-link'),
|
||||||
|
url(r'^api/v2.1/share-links/(?P<token>[a-f0-9]+)/online-office-lock/$',
|
||||||
|
ShareLinkOnlineOfficeLock.as_view(), name='api-v2.1-share-link-online-office-lock'),
|
||||||
|
|
||||||
## user::shared-upload-links
|
## user::shared-upload-links
|
||||||
url(r'^api/v2.1/upload-links/$', UploadLinks.as_view(), name='api-v2.1-upload-links'),
|
url(r'^api/v2.1/upload-links/$', UploadLinks.as_view(), name='api-v2.1-upload-links'),
|
||||||
|
@@ -28,6 +28,7 @@ from django.shortcuts import render
|
|||||||
from django.utils.http import urlquote
|
from django.utils.http import urlquote
|
||||||
from django.utils.translation import get_language, ugettext as _
|
from django.utils.translation import get_language, ugettext as _
|
||||||
from django.views.decorators.http import require_POST
|
from django.views.decorators.http import require_POST
|
||||||
|
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||||
from django.template.defaultfilters import filesizeformat
|
from django.template.defaultfilters import filesizeformat
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
|
|
||||||
@@ -915,7 +916,6 @@ def _download_file_from_share_link(request, fileshare):
|
|||||||
"""
|
"""
|
||||||
next = request.META.get('HTTP_REFERER', settings.SITE_ROOT)
|
next = request.META.get('HTTP_REFERER', settings.SITE_ROOT)
|
||||||
|
|
||||||
username = request.user.username
|
|
||||||
repo = get_repo(fileshare.repo_id)
|
repo = get_repo(fileshare.repo_id)
|
||||||
if not repo:
|
if not repo:
|
||||||
raise Http404
|
raise Http404
|
||||||
@@ -952,6 +952,7 @@ def _download_file_from_share_link(request, fileshare):
|
|||||||
|
|
||||||
return HttpResponseRedirect(gen_file_get_url(dl_token, filename))
|
return HttpResponseRedirect(gen_file_get_url(dl_token, filename))
|
||||||
|
|
||||||
|
@ensure_csrf_cookie
|
||||||
@share_link_audit
|
@share_link_audit
|
||||||
@share_link_login_required
|
@share_link_login_required
|
||||||
def view_shared_file(request, fileshare):
|
def view_shared_file(request, fileshare):
|
||||||
@@ -1042,6 +1043,23 @@ def view_shared_file(request, fileshare):
|
|||||||
else:
|
else:
|
||||||
username = request.user.username
|
username = request.user.username
|
||||||
|
|
||||||
|
def online_office_lock_or_refresh_lock(repo_id, path, username):
|
||||||
|
# check file lock info
|
||||||
|
try:
|
||||||
|
is_locked, locked_by_me = check_file_lock(repo_id, path, username)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
is_locked = False
|
||||||
|
|
||||||
|
locked_by_online_office = if_locked_by_online_office(repo_id, path)
|
||||||
|
try:
|
||||||
|
if not is_locked:
|
||||||
|
seafile_api.lock_file(repo_id, path, ONLINE_OFFICE_LOCK_OWNER, 0)
|
||||||
|
elif locked_by_online_office:
|
||||||
|
seafile_api.refresh_file_lock(repo_id, path)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
|
||||||
if ENABLE_OFFICE_WEB_APP and fileext in OFFICE_WEB_APP_FILE_EXTENSION:
|
if ENABLE_OFFICE_WEB_APP and fileext in OFFICE_WEB_APP_FILE_EXTENSION:
|
||||||
|
|
||||||
action_name = 'edit' if can_edit else 'view'
|
action_name = 'edit' if can_edit else 'view'
|
||||||
@@ -1050,6 +1068,10 @@ def view_shared_file(request, fileshare):
|
|||||||
language_code=request.LANGUAGE_CODE)
|
language_code=request.LANGUAGE_CODE)
|
||||||
|
|
||||||
if wopi_dict:
|
if wopi_dict:
|
||||||
|
if is_pro_version() and can_edit:
|
||||||
|
online_office_lock_or_refresh_lock(repo_id, path, username)
|
||||||
|
|
||||||
|
wopi_dict['share_link_token'] = token
|
||||||
return render(request, 'view_file_wopi.html', wopi_dict)
|
return render(request, 'view_file_wopi.html', wopi_dict)
|
||||||
else:
|
else:
|
||||||
ret_dict['err'] = _(u'Error when prepare Office Online file preview page.')
|
ret_dict['err'] = _(u'Error when prepare Office Online file preview page.')
|
||||||
@@ -1060,6 +1082,10 @@ def view_shared_file(request, fileshare):
|
|||||||
can_edit=can_edit, can_download=can_download)
|
can_edit=can_edit, can_download=can_download)
|
||||||
|
|
||||||
if onlyoffice_dict:
|
if onlyoffice_dict:
|
||||||
|
if is_pro_version() and can_edit:
|
||||||
|
online_office_lock_or_refresh_lock(repo_id, path, username)
|
||||||
|
|
||||||
|
onlyoffice_dict['share_link_token'] = token
|
||||||
return render(request, 'view_file_onlyoffice.html',
|
return render(request, 'view_file_onlyoffice.html',
|
||||||
onlyoffice_dict)
|
onlyoffice_dict)
|
||||||
else:
|
else:
|
||||||
|
Reference in New Issue
Block a user