mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-02 07:27:04 +00:00
update download dir/multi
This commit is contained in:
37
seahub/api2/endpoints/query_zip_progress.py
Normal file
37
seahub/api2/endpoints/query_zip_progress.py
Normal file
@@ -0,0 +1,37 @@
|
||||
import logging
|
||||
import json
|
||||
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework import status
|
||||
|
||||
from seahub.api2.throttling import UserRateThrottle
|
||||
from seahub.api2.utils import api_error
|
||||
|
||||
from seaserv import seafile_api
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class QueryZipProgressView(APIView):
|
||||
|
||||
throttle_classes = (UserRateThrottle, )
|
||||
|
||||
def get(self, request, format=None):
|
||||
""" check progress when download dir/multi.
|
||||
|
||||
Permission checking:
|
||||
"""
|
||||
|
||||
token = request.GET.get('token', None)
|
||||
if not token:
|
||||
error_msg = 'token invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
try:
|
||||
progress = seafile_api.query_zip_progress(token)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
return Response(json.loads(progress))
|
120
seahub/api2/endpoints/share_link_zip_task.py
Normal file
120
seahub/api2/endpoints/share_link_zip_task.py
Normal file
@@ -0,0 +1,120 @@
|
||||
import logging
|
||||
import os
|
||||
import json
|
||||
import posixpath
|
||||
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework import status
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from seahub.api2.throttling import UserRateThrottle
|
||||
from seahub.api2.utils import api_error
|
||||
|
||||
from seahub.views.file import send_file_access_msg
|
||||
from seahub.share.models import FileShare
|
||||
from seahub.utils import is_windows_operating_system, \
|
||||
is_pro_version
|
||||
|
||||
import seaserv
|
||||
from seaserv import seafile_api
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class ShareLinkZipTaskView(APIView):
|
||||
|
||||
throttle_classes = (UserRateThrottle,)
|
||||
|
||||
def get(self, request, format=None):
|
||||
""" Only used for download dir when view dir share link from web.
|
||||
|
||||
|
||||
Permission checking:
|
||||
1. authenticated user OR anonymous user has passed email code check(if necessary);
|
||||
"""
|
||||
|
||||
# permission check
|
||||
if is_pro_version() and settings.ENABLE_SHARE_LINK_AUDIT:
|
||||
if not request.user.is_authenticated() and \
|
||||
not request.session.get('anonymous_email'):
|
||||
# if anonymous user has passed email code check,
|
||||
# then his/her email info will be in session.
|
||||
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
# argument check
|
||||
share_link_token = request.GET.get('share_link_token', None)
|
||||
if not share_link_token:
|
||||
error_msg = 'share_link_token invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
req_path = request.GET.get('path', None)
|
||||
if not req_path:
|
||||
error_msg = 'path invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
# recourse check
|
||||
fileshare = FileShare.objects.get_valid_dir_link_by_token(share_link_token)
|
||||
if not fileshare:
|
||||
error_msg = 'share_link_token %s not found.' % share_link_token
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
if req_path[-1] != '/':
|
||||
req_path += '/'
|
||||
|
||||
if req_path == '/':
|
||||
real_path = fileshare.path
|
||||
else:
|
||||
real_path = posixpath.join(fileshare.path, req_path.lstrip('/'))
|
||||
|
||||
if real_path[-1] != '/':
|
||||
real_path += '/'
|
||||
|
||||
repo_id = fileshare.repo_id
|
||||
repo = seafile_api.get_repo(repo_id)
|
||||
if not repo:
|
||||
error_msg = 'Library %s not found.' % repo_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
dir_id = seafile_api.get_dir_id_by_path(repo_id, real_path)
|
||||
if not dir_id:
|
||||
error_msg = 'Folder %s not found.' % real_path
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
# get file server access token
|
||||
dir_name = repo.name if real_path == '/' else \
|
||||
os.path.basename(real_path.rstrip('/'))
|
||||
|
||||
dir_size = seafile_api.get_dir_size(
|
||||
repo.store_id, repo.version, dir_id)
|
||||
if dir_size > seaserv.MAX_DOWNLOAD_DIR_SIZE:
|
||||
error_msg = 'Unable to download directory "%s": size is too large.' % dir_name
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
is_windows = 0
|
||||
if is_windows_operating_system(request):
|
||||
is_windows = 1
|
||||
|
||||
fake_obj_id = {
|
||||
'obj_id': dir_id,
|
||||
'dir_name': dir_name,
|
||||
'is_windows': is_windows
|
||||
}
|
||||
|
||||
username = request.user.username
|
||||
try:
|
||||
zip_token = seafile_api.get_fileserver_access_token(
|
||||
repo_id, json.dumps(fake_obj_id), 'download-dir', username)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
if request.session.get('anonymous_email'):
|
||||
request.user.username = request.session.get('anonymous_email')
|
||||
|
||||
send_file_access_msg(request, repo, real_path, 'share-link')
|
||||
|
||||
return Response({'zip_token': zip_token})
|
144
seahub/api2/endpoints/zip_task.py
Normal file
144
seahub/api2/endpoints/zip_task.py
Normal file
@@ -0,0 +1,144 @@
|
||||
import logging
|
||||
import json
|
||||
import stat
|
||||
import posixpath
|
||||
|
||||
from rest_framework.authentication import SessionAuthentication
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework import status
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from seahub.api2.throttling import UserRateThrottle
|
||||
from seahub.api2.authentication import TokenAuthentication
|
||||
from seahub.api2.utils import api_error
|
||||
|
||||
from seahub.views import check_folder_permission
|
||||
from seahub.views.file import send_file_access_msg
|
||||
from seahub.utils import is_windows_operating_system
|
||||
|
||||
import seaserv
|
||||
from seaserv import seafile_api
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class ZipTaskView(APIView):
|
||||
|
||||
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||
permission_classes = (IsAuthenticated,)
|
||||
throttle_classes = (UserRateThrottle,)
|
||||
|
||||
def get(self, request, repo_id, format=None):
|
||||
""" Get file server token for download-dir and download-multi.
|
||||
|
||||
Permission checking:
|
||||
1. user with 'r' or 'rw' permission;
|
||||
"""
|
||||
|
||||
# argument check
|
||||
parent_dir = request.GET.get('parent_dir', None)
|
||||
if not parent_dir:
|
||||
error_msg = 'parent_dir invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
dirent_name_list = request.GET.getlist('dirents', None)
|
||||
if not dirent_name_list:
|
||||
error_msg = 'dirents invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
if len(dirent_name_list) == 1:
|
||||
download_type = 'download-dir'
|
||||
elif len(dirent_name_list) > 1:
|
||||
download_type = 'download-multi'
|
||||
else:
|
||||
error_msg = 'dirents invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
# recourse check
|
||||
repo = seafile_api.get_repo(repo_id)
|
||||
if not repo:
|
||||
error_msg = 'Library %s not found.' % repo_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
if not seafile_api.get_dir_id_by_path(repo_id, parent_dir):
|
||||
error_msg = 'Folder %s not found.' % parent_dir
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
# permission check
|
||||
if not check_folder_permission(request, repo_id, parent_dir):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
# get file server access token
|
||||
is_windows = 0
|
||||
if is_windows_operating_system(request):
|
||||
is_windows = 1
|
||||
|
||||
if download_type == 'download-dir':
|
||||
dir_name = dirent_name_list[0].strip('/')
|
||||
full_dir_path = posixpath.join(parent_dir, dir_name)
|
||||
|
||||
dir_id = seafile_api.get_dir_id_by_path(repo_id, full_dir_path)
|
||||
if not dir_id:
|
||||
error_msg = 'Folder %s not found.' % full_dir_path
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
dir_size = seafile_api.get_dir_size(
|
||||
repo.store_id, repo.version, dir_id)
|
||||
|
||||
if dir_size > seaserv.MAX_DOWNLOAD_DIR_SIZE:
|
||||
error_msg = 'Unable to download directory "%s": size is too large.' % dir_name
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
fake_obj_id = {
|
||||
'obj_id': dir_id,
|
||||
'dir_name': dir_name,
|
||||
'is_windows': is_windows
|
||||
}
|
||||
|
||||
if download_type == 'download-multi':
|
||||
dirent_list = []
|
||||
total_size = 0
|
||||
for dirent_name in dirent_name_list:
|
||||
dirent_name = dirent_name.strip('/')
|
||||
dirent_list.append(dirent_name)
|
||||
|
||||
full_dirent_path = posixpath.join(parent_dir, dirent_name)
|
||||
current_dirent = seafile_api.get_dirent_by_path(repo_id, full_dirent_path)
|
||||
if not current_dirent:
|
||||
continue
|
||||
|
||||
if stat.S_ISDIR(current_dirent.mode):
|
||||
total_size += seafile_api.get_dir_size(repo.store_id,
|
||||
repo.version, current_dirent.obj_id)
|
||||
else:
|
||||
total_size += current_dirent.size
|
||||
|
||||
if total_size > seaserv.MAX_DOWNLOAD_DIR_SIZE:
|
||||
error_msg = _('Total size exceeds limit.')
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
fake_obj_id = {
|
||||
'parent_dir': parent_dir,
|
||||
'file_list': dirent_list,
|
||||
'is_windows': is_windows
|
||||
}
|
||||
|
||||
username = request.user.username
|
||||
try:
|
||||
zip_token = seafile_api.get_fileserver_access_token(
|
||||
repo_id, json.dumps(fake_obj_id), download_type, username)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
if len(dirent_name_list) > 10:
|
||||
send_file_access_msg(request, repo, parent_dir, 'web')
|
||||
else:
|
||||
for dirent_name in dirent_name_list:
|
||||
full_dirent_path = posixpath.join(parent_dir, dirent_name)
|
||||
send_file_access_msg(request, repo, full_dirent_path, 'web')
|
||||
|
||||
return Response({'zip_token': zip_token})
|
@@ -61,6 +61,9 @@ def base(request):
|
||||
repo_id_patt = r".*/([a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12})/.*"
|
||||
m = re.match(repo_id_patt, request.get_full_path())
|
||||
search_repo_id = m.group(1) if m is not None else None
|
||||
file_server_root = config.FILE_SERVER_ROOT
|
||||
if not file_server_root.endswith('/'):
|
||||
file_server_root += '/'
|
||||
|
||||
return {
|
||||
'seafile_version': SEAFILE_VERSION,
|
||||
@@ -90,4 +93,5 @@ def base(request):
|
||||
'search_repo_id': search_repo_id,
|
||||
'SITE_ROOT': SITE_ROOT,
|
||||
'constance_enabled': dj_settings.CONSTANCE_ENABLED,
|
||||
'FILE_SERVER_ROOT': file_server_root,
|
||||
}
|
||||
|
@@ -112,7 +112,8 @@
|
||||
var app = {
|
||||
config: {
|
||||
mediaUrl: '{{ MEDIA_URL }}',
|
||||
siteRoot: '{{ SITE_ROOT }}'
|
||||
siteRoot: '{{ SITE_ROOT }}',
|
||||
fileServerRoot: '{{ FILE_SERVER_ROOT }}'
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@@ -105,6 +105,7 @@
|
||||
<% if (!encrypted && user_perm == 'r') { %>
|
||||
<div id="multi-dirents-op" class="hide">
|
||||
<button id="cp-dirents" title="{% trans 'Copy' %}" class="op-btn sf2-icon-copy op-icon"></button>
|
||||
<button id="download-dirents" title="{% trans 'Download' %}" class="op-btn sf2-icon-download op-icon"></button>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
@@ -206,7 +207,9 @@
|
||||
<td class="dirent-op">
|
||||
<div class="op-container">
|
||||
<div class="displayed-op">
|
||||
<a class="op-icon download sf2-icon-download sf2-x vh" href="<%= download_url %>" title="{% trans "Download" %}" aria-label="{% trans "Download" %}"></a>
|
||||
|
||||
<a class="op-icon download sf2-icon-download sf2-x vh download-dir" href="#" title="{% trans "Download" %}" aria-label="{% trans "Download" %}"></a>
|
||||
|
||||
<% if (!repo_encrypted && can_generate_shared_link) { %>
|
||||
<a href="#" class="op-icon share sf2-icon-share sf2-x vh" title="{% trans "Share" %}" aria-label="{% trans "Share" %}"></a>
|
||||
<% } %>
|
||||
|
@@ -42,7 +42,7 @@
|
||||
{% endif %}
|
||||
</a>
|
||||
{% if not traffic_over_limit %}
|
||||
<a href="?p={{ path|urlencode }}&dl=1" class="obv-btn vam shared-dir-zip">{% trans "ZIP"%}</a>
|
||||
<a href="#" class="obv-btn vam shared-dir-zip" data-name="{{ dirent.obj_name }}">{% trans "ZIP"%}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
<tbody>
|
||||
{% for dirent in dir_list %}
|
||||
<tr>
|
||||
<tr data-name="{{dirent.obj_name}}" >
|
||||
<td class="alc"><img src="{{ MEDIA_URL }}img/folder-24.png" alt="{% trans "Directory icon"%}" /></td>
|
||||
<td>
|
||||
<a href="?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}&mode={{mode}}" class="normal">{{ dirent.obj_name }}</a>
|
||||
@@ -69,7 +69,7 @@
|
||||
<td>{{ dirent.last_modified|translate_seahub_time }}</td>
|
||||
<td>
|
||||
{% if not traffic_over_limit %}
|
||||
<a class="op-icon vh" href="{% url "view_shared_dir" token %}?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}&dl=1" title="{% trans 'Download' %}" aria-label="{% trans 'Download' %}">
|
||||
<a class="op-icon vh download-dir" data-name="{{ dirent.obj_name }}" href="#" aria-label="{% trans 'Download' %}">
|
||||
<img src="{{MEDIA_URL}}img/download.png" alt="{% trans 'Download' %}" />
|
||||
</a>
|
||||
{% endif %}
|
||||
@@ -119,7 +119,7 @@
|
||||
</a>
|
||||
<a href="?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}&mode={{mode}}" class="normal text-link ellipsis">{{ dirent.obj_name }}</a>
|
||||
{% if not traffic_over_limit %}
|
||||
<a class="op-icon vh" href="{% url "view_shared_dir" token %}?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}&dl=1" title="{% trans 'Download' %}">
|
||||
<a class="op-icon vh download-dir" data-name="{{ dirent.obj_name }}" href="#" title="{% trans 'Download' %}">
|
||||
<img src="{{MEDIA_URL}}img/download.png" alt="" />
|
||||
</a>
|
||||
{% endif %}
|
||||
@@ -185,9 +185,73 @@ var magnificOptions = {
|
||||
$('.img-name-link').magnificPopup(magnificOptions);
|
||||
$('.img-img-link').magnificPopup(magnificOptions);
|
||||
|
||||
var cur_path = '{{path|escapejs}}';
|
||||
var share_link_token = '{{token}}';
|
||||
var file_server_root = '{{FILE_SERVER_ROOT}}';
|
||||
|
||||
$('.shared-dir-zip, .download-dir').click(function (e) {
|
||||
var cur_download_dir_path,
|
||||
cur_download_dir_name,
|
||||
zip_token;
|
||||
|
||||
var target = e.target || event.srcElement;
|
||||
|
||||
if ($(target).hasClass("shared-dir-zip")) {
|
||||
cur_download_dir_path = cur_path;
|
||||
} else {
|
||||
cur_download_dir_name = $(target).closest('a').attr('data-name');
|
||||
if (cur_path.lastIndexOf('/') != cur_path.length - 1) {
|
||||
// cur_path NOT end with '/'
|
||||
cur_download_dir_path = cur_path.substring(0, cur_path.lastIndexOf('/')) + '/' + cur_download_dir_name;
|
||||
} else {
|
||||
cur_download_dir_path = cur_path + cur_download_dir_name;
|
||||
}
|
||||
}
|
||||
|
||||
var queryZipProgress = function() {
|
||||
$.ajax({
|
||||
url: '{% url 'api-v2.1-query-zip-progress' %}' + '?token=' + zip_token,
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
success: function (data) {
|
||||
if (data['total'] == data['zipped']) {
|
||||
clearInterval(interval);
|
||||
location.href = file_server_root + 'zip/' + zip_token;
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
if (xhr.responseText) {
|
||||
feedback($.parseJSON(xhr.responseText).error_msg, 'error');
|
||||
} else {
|
||||
feedback("{% trans "Failed. Please check the network." %}", 'error');
|
||||
}
|
||||
clearInterval(interval);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: '{% url 'api-v2.1-share-link-zip-task' %}' + '?share_link_token=' + share_link_token + '&path=' + encodeURIComponent(cur_download_dir_path),
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
zip_token = data['zip_token'];
|
||||
queryZipProgress();
|
||||
interval = setInterval(queryZipProgress, 1000);
|
||||
},
|
||||
error: function (xhr) {
|
||||
if (xhr.responseText) {
|
||||
feedback($.parseJSON(xhr.responseText).error_msg, 'error');
|
||||
} else {
|
||||
feedback("{% trans "Failed. Please check the network." %}", 'error');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
{% if not repo.encrypted and ENABLE_THUMBNAIL %}
|
||||
// get thumbnails for image files
|
||||
var cur_path = "{{path|escapejs}}";
|
||||
|
||||
$(function() {
|
||||
var img_icons = $('.not-thumbnail');
|
||||
if (img_icons.length == 0) {
|
||||
|
@@ -27,6 +27,9 @@ from seahub.api2.endpoints.file import FileView
|
||||
from seahub.api2.endpoints.dir import DirView
|
||||
from seahub.api2.endpoints.repo_set_password import RepoSetPassword
|
||||
from seahub.api2.endpoints.dirents_download_link import DirentsDownloadLinkView
|
||||
from seahub.api2.endpoints.zip_task import ZipTaskView
|
||||
from seahub.api2.endpoints.share_link_zip_task import ShareLinkZipTaskView
|
||||
from seahub.api2.endpoints.query_zip_progress import QueryZipProgressView
|
||||
from seahub.api2.endpoints.admin.login import Login
|
||||
from seahub.api2.endpoints.admin.file_audit import FileAudit
|
||||
from seahub.api2.endpoints.admin.file_update import FileUpdate
|
||||
@@ -187,6 +190,9 @@ urlpatterns = patterns(
|
||||
url(r'^api/v2.1/upload-links/(?P<token>[a-f0-9]{10})/$', UploadLink.as_view(), name='api-v2.1-upload-link'),
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/file/$', FileView.as_view(), name='api-v2.1-file-view'),
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/dirents/download-link/$', DirentsDownloadLinkView.as_view(), name='api-v2.1-dirents-download-link-view'),
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/zip-task/$', ZipTaskView.as_view(), name='api-v2.1-zip-task'),
|
||||
url(r'^api/v2.1/share-link-zip-task/$', ShareLinkZipTaskView.as_view(), name='api-v2.1-share-link-zip-task'),
|
||||
url(r'^api/v2.1/query-zip-progress/$', QueryZipProgressView.as_view(), name='api-v2.1-query-zip-progress'),
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/dir/$', DirView.as_view(), name='api-v2.1-dir-view'),
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/set-password/$', RepoSetPassword.as_view(), name="api-v2.1-repo-set-password"),
|
||||
url(r'^api/v2.1/admin/sysinfo/$', SysInfo.as_view(), name='api-v2.1-sysinfo'),
|
||||
|
@@ -1298,3 +1298,12 @@ def get_system_admins():
|
||||
admins.append(user)
|
||||
|
||||
return admins
|
||||
|
||||
def is_windows_operating_system(request):
|
||||
if not request.META.has_key('HTTP_USER_AGENT'):
|
||||
return False
|
||||
|
||||
if 'windows' in request.META['HTTP_USER_AGENT'].lower():
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
@@ -21,7 +21,6 @@ from seahub.share.models import FileShare, UploadLinkShare, \
|
||||
check_share_link_common
|
||||
from seahub.views import gen_path_link, get_repo_dirents, \
|
||||
check_folder_permission
|
||||
from seahub.views.file import send_file_access_msg
|
||||
|
||||
from seahub.utils import gen_file_upload_url, gen_dir_share_link, \
|
||||
gen_shared_upload_link, user_traffic_over_limit, render_error, \
|
||||
@@ -29,7 +28,6 @@ from seahub.utils import gen_file_upload_url, gen_dir_share_link, \
|
||||
from seahub.settings import ENABLE_UPLOAD_FOLDER, \
|
||||
ENABLE_RESUMABLE_FILEUPLOAD, ENABLE_THUMBNAIL, \
|
||||
THUMBNAIL_ROOT, THUMBNAIL_DEFAULT_SIZE, THUMBNAIL_SIZE_FOR_GRID
|
||||
from seahub.utils import gen_file_get_url
|
||||
from seahub.utils.file_types import IMAGE
|
||||
from seahub.thumbnail.utils import get_share_link_thumbnail_src
|
||||
|
||||
@@ -158,47 +156,6 @@ def repo_history_view(request, repo_id):
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
########## shared dir/uploadlink
|
||||
def _download_dir_from_share_link(request, fileshare, repo, real_path):
|
||||
# check whether owner's traffic over the limit
|
||||
if user_traffic_over_limit(fileshare.username):
|
||||
return render_error(
|
||||
request, _(u'Unable to access file: share link traffic is used up.'))
|
||||
|
||||
shared_by = fileshare.username
|
||||
if real_path == '/':
|
||||
dirname = repo.name
|
||||
else:
|
||||
dirname = os.path.basename(real_path.rstrip('/'))
|
||||
|
||||
dir_id = seafile_api.get_dir_id_by_path(repo.id, real_path)
|
||||
if not dir_id:
|
||||
return render_error(
|
||||
request, _(u'Unable to download: folder not found.'))
|
||||
|
||||
try:
|
||||
total_size = seaserv.seafserv_threaded_rpc.get_dir_size(
|
||||
repo.store_id, repo.version, dir_id)
|
||||
except Exception as e:
|
||||
logger.error(str(e))
|
||||
return render_error(request, _(u'Internal Error'))
|
||||
|
||||
if total_size > seaserv.MAX_DOWNLOAD_DIR_SIZE:
|
||||
return render_error(request, _(u'Unable to download directory "%s": size is too large.') % dirname)
|
||||
|
||||
token = seafile_api.get_fileserver_access_token(repo.id,
|
||||
dir_id,
|
||||
'download-dir',
|
||||
request.user.username)
|
||||
|
||||
try:
|
||||
seaserv.send_message('seahub.stats', 'dir-download\t%s\t%s\t%s\t%s' %
|
||||
(repo.id, shared_by, dir_id, total_size))
|
||||
send_file_access_msg(request, repo, real_path, 'web')
|
||||
except Exception as e:
|
||||
logger.error('Error when sending dir-download message: %s' % str(e))
|
||||
|
||||
return HttpResponseRedirect(gen_file_get_url(token, dirname))
|
||||
|
||||
@share_link_audit
|
||||
def view_shared_dir(request, fileshare):
|
||||
token = fileshare.token
|
||||
@@ -233,11 +190,6 @@ def view_shared_dir(request, fileshare):
|
||||
if not seafile_api.get_dir_id_by_path(repo.id, fileshare.path):
|
||||
return render_error(request, _('"%s" does not exist.') % fileshare.path)
|
||||
|
||||
# download shared dir
|
||||
if request.GET.get('dl', '') == '1':
|
||||
return _download_dir_from_share_link(request, fileshare, repo,
|
||||
real_path)
|
||||
|
||||
if fileshare.path == '/':
|
||||
# use repo name as dir name if share whole library
|
||||
dir_name = repo.name
|
||||
|
@@ -67,7 +67,7 @@ define([
|
||||
_this.remove();
|
||||
|
||||
var msg = gettext("Successfully unlink %(name)s.")
|
||||
.replace('%(name)s', Common.HTMLescape(device_name));
|
||||
.replace('%(name)s', device_name);
|
||||
Common.feedback(msg, 'success');
|
||||
},
|
||||
error: function(xhr) {
|
||||
@@ -87,7 +87,7 @@ define([
|
||||
_this.remove();
|
||||
|
||||
var msg = gettext("Successfully unlink %(name)s.")
|
||||
.replace('%(name)s', Common.HTMLescape(device_name));
|
||||
.replace('%(name)s', device_name);
|
||||
Common.feedback(msg, 'success');
|
||||
},
|
||||
error: function(xhr) {
|
||||
|
@@ -197,10 +197,10 @@ define([
|
||||
|
||||
if (_this.op_type == 'mv') {
|
||||
msg = gettext("Successfully moved %(name)s")
|
||||
.replace('%(name)s', Common.HTMLescape(obj_name));
|
||||
.replace('%(name)s', obj_name);
|
||||
} else {
|
||||
msg = gettext("Successfully copied %(name)s")
|
||||
.replace('%(name)s', Common.HTMLescape(obj_name));
|
||||
.replace('%(name)s', obj_name);
|
||||
}
|
||||
|
||||
if (!data['task_id']) { // no progress
|
||||
|
@@ -807,22 +807,53 @@ define([
|
||||
},
|
||||
|
||||
download: function () {
|
||||
var dirents = this.dir,
|
||||
selected_dirents = dirents.where({'selected':true}),
|
||||
selected_names = '';
|
||||
var dirents = this.dir;
|
||||
var parent_dir = dirents.path;
|
||||
var selected_dirents = dirents.where({'selected':true});
|
||||
var selected_names = [];
|
||||
var interval;
|
||||
var zip_token;
|
||||
var queryZipProgress = function() {
|
||||
$.ajax({
|
||||
url: Common.getUrl({name: 'query_zip_progress'}) + '?token=' + zip_token,
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
success: function (data) {
|
||||
if (data['total'] == data['zipped']) {
|
||||
clearInterval(interval);
|
||||
location.href = Common.getUrl({name: 'download_dir_zip_url', zip_token: zip_token});
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
Common.ajaxErrorHandler(xhr);
|
||||
clearInterval(interval);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (selected_dirents.length == 1 && selected_dirents[0].get('is_file')) {
|
||||
// only select one file
|
||||
var file_path = parent_dir + '/' + selected_dirents[0].get('obj_name');
|
||||
location.href = Common.getUrl({name: 'get_file_download_url', repo_id: dirents.repo_id, file_path: encodeURIComponent(file_path)});
|
||||
return false
|
||||
}
|
||||
|
||||
$(selected_dirents).each(function() {
|
||||
selected_names += this.get('obj_name') + ',';
|
||||
selected_names.push(this.get('obj_name'));
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
url: Common.getUrl({
|
||||
name: 'download_dirents',
|
||||
repo_id: dirents.repo_id
|
||||
}) + '?parent_dir=' + encodeURIComponent(dirents.path) + '&dirents=' + encodeURIComponent(selected_names),
|
||||
url: Common.getUrl({name: 'zip_task', repo_id: dirents.repo_id}),
|
||||
data: {
|
||||
'parent_dir': parent_dir,
|
||||
'dirents': selected_names
|
||||
},
|
||||
dataType: 'json',
|
||||
traditional: true,
|
||||
success: function(data) {
|
||||
location.href = data['url'];
|
||||
zip_token = data['zip_token'];
|
||||
queryZipProgress();
|
||||
interval = setInterval(queryZipProgress, 1000);
|
||||
},
|
||||
error: function (xhr) {
|
||||
Common.ajaxErrorHandler(xhr);
|
||||
@@ -877,7 +908,7 @@ define([
|
||||
} else {
|
||||
msg_s = gettext("Successfully deleted %(name)s and %(amount)s other items.");
|
||||
}
|
||||
msg_s = msg_s.replace('%(name)s', Common.HTMLescape(data['deleted'][0])).replace('%(amount)s', del_len - 1);
|
||||
msg_s = msg_s.replace('%(name)s', data['deleted'][0]).replace('%(amount)s', del_len - 1);
|
||||
Common.feedback(msg_s, 'success');
|
||||
}
|
||||
if (not_del_len > 0) {
|
||||
@@ -888,7 +919,7 @@ define([
|
||||
} else {
|
||||
msg_f = gettext("Failed to delete %(name)s and %(amount)s other items.");
|
||||
}
|
||||
msg_f = msg_f.replace('%(name)s', Common.HTMLescape(data['undeleted'][0])).replace('%(amount)s', not_del_len - 1);
|
||||
msg_f = msg_f.replace('%(name)s', data['undeleted'][0]).replace('%(amount)s', not_del_len - 1);
|
||||
Common.feedback(msg_f, 'error');
|
||||
}
|
||||
$.modal.close();
|
||||
@@ -1033,7 +1064,7 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
msg_s = msg_s.replace('%(name)s', Common.HTMLescape(data['success'][0])).replace('%(amount)s', success_len - 1);
|
||||
msg_s = msg_s.replace('%(name)s', data['success'][0]).replace('%(amount)s', success_len - 1);
|
||||
//msg_s += ' <a href="' + view_url + '">' + "View" + '</a>';
|
||||
Common.feedback(msg_s, 'success');
|
||||
}
|
||||
@@ -1052,7 +1083,7 @@ define([
|
||||
msg_f = gettext("Internal error. Failed to copy %(name)s.");
|
||||
}
|
||||
}
|
||||
msg_f = msg_f.replace('%(name)s', Common.HTMLescape(data['failed'][0])).replace('%(amount)s', data['failed'].length - 1);
|
||||
msg_f = msg_f.replace('%(name)s', data['failed'][0]).replace('%(amount)s', data['failed'].length - 1);
|
||||
Common.feedback(msg_f, 'error');
|
||||
}
|
||||
},
|
||||
|
@@ -152,7 +152,7 @@ define([
|
||||
this.model.deleteFromServer({
|
||||
success: function(data) {
|
||||
var msg = gettext("Successfully deleted %(name)s")
|
||||
.replace('%(name)s', Common.HTMLescape(dirent_name));
|
||||
.replace('%(name)s', dirent_name);
|
||||
Common.feedback(msg, 'success');
|
||||
},
|
||||
error: function(xhr) {
|
||||
|
@@ -69,6 +69,7 @@ define([
|
||||
events: {
|
||||
'click .select': 'select',
|
||||
'click .file-star': 'starFile',
|
||||
'click .download-dir': 'downloadDir',
|
||||
'click .share': 'share',
|
||||
'click .delete': 'del', // 'delete' is a preserve word
|
||||
'click .rename': 'rename',
|
||||
@@ -118,6 +119,48 @@ define([
|
||||
}
|
||||
},
|
||||
|
||||
downloadDir: function() {
|
||||
var dir = this.dirView.dir;
|
||||
var obj_name = this.model.get('obj_name');
|
||||
var interval;
|
||||
var zip_token;
|
||||
var queryZipProgress = function() {
|
||||
$.ajax({
|
||||
url: Common.getUrl({name: 'query_zip_progress'}) + '?token=' + zip_token,
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
success: function (data) {
|
||||
if (data['total'] == data['zipped']) {
|
||||
clearInterval(interval);
|
||||
location.href = Common.getUrl({name: 'download_dir_zip_url', zip_token: zip_token});
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
Common.ajaxErrorHandler(xhr);
|
||||
clearInterval(interval);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: Common.getUrl({
|
||||
name: 'zip_task',
|
||||
repo_id: dir.repo_id
|
||||
}) + '?parent_dir=' + encodeURIComponent(dir.path) + '&dirents=' + encodeURIComponent(obj_name),
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
zip_token = data['zip_token'];
|
||||
queryZipProgress();
|
||||
interval = setInterval(queryZipProgress, 1000);
|
||||
},
|
||||
error: function (xhr) {
|
||||
Common.ajaxErrorHandler(xhr);
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
starFile: function() {
|
||||
var _this = this;
|
||||
var dir = this.dirView.dir;
|
||||
@@ -185,7 +228,7 @@ define([
|
||||
this.model.deleteFromServer({
|
||||
success: function(data) {
|
||||
var msg = gettext("Successfully deleted %(name)s")
|
||||
.replace('%(name)s', Common.HTMLescape(dirent_name));
|
||||
.replace('%(name)s', dirent_name);
|
||||
Common.feedback(msg, 'success');
|
||||
},
|
||||
error: function(xhr) {
|
||||
|
@@ -54,7 +54,7 @@ define([
|
||||
this.model.destroy({
|
||||
wait: true,
|
||||
success: function() {
|
||||
var msg = gettext('Successfully unshared {placeholder}').replace('{placeholder}', '<span class="op-target">' + Common.HTMLescape(lib_name) + '</span>');
|
||||
var msg = gettext('Successfully unshared 1 item.');
|
||||
Common.feedback(msg, 'success', Common.SUCCESS_TIMOUT);
|
||||
},
|
||||
error: function(model, response) {
|
||||
|
@@ -45,7 +45,7 @@ define([
|
||||
dataType: 'json',
|
||||
success: function () {
|
||||
el.remove();
|
||||
var msg = gettext('Successfully unshared {placeholder}').replace('{placeholder}', '<span class="op-target">' + Common.HTMLescape(lib_name) + '</span>');
|
||||
var msg = gettext('Successfully unshared 1 item.');
|
||||
Common.feedback(msg, 'success', Common.SUCCESS_TIMOUT);
|
||||
},
|
||||
error: function(xhr) {
|
||||
|
@@ -328,11 +328,11 @@ define([
|
||||
var after_op_success = function(data) {
|
||||
$.modal.close();
|
||||
var msg = gettext("Successfully sent to {placeholder}")
|
||||
.replace('{placeholder}', Common.HTMLescape(data['send_success'].join(', ')));
|
||||
.replace('{placeholder}', data['send_success'].join(', '));
|
||||
Common.feedback(msg, 'success');
|
||||
if (data['send_failed'].length > 0) {
|
||||
msg += '<br />' + gettext("Failed to send to {placeholder}")
|
||||
.replace('{placeholder}', Common.HTMLescape(data['send_failed'].join(', ')));
|
||||
.replace('{placeholder}', data['send_failed'].join(', '));
|
||||
Common.feedback(msg, 'info');
|
||||
}
|
||||
};
|
||||
|
@@ -42,7 +42,7 @@ define([
|
||||
beforeSend: Common.prepareCSRFToken,
|
||||
success: function() {
|
||||
_this.remove();
|
||||
Common.feedback(gettext("Successfully unstared {placeholder}").replace('{placeholder}', Common.HTMLescape(file_name)), 'success');
|
||||
Common.feedback(gettext("Successfully unstared {placeholder}").replace('{placeholder}', file_name), 'success');
|
||||
},
|
||||
error: function (xhr) {
|
||||
Common.ajaxErrorHandler(xhr);
|
||||
|
@@ -73,12 +73,15 @@ define([
|
||||
|
||||
getUrl: function(options) {
|
||||
var siteRoot = app.config.siteRoot;
|
||||
var fileServerRoot = app.config.fileServerRoot;
|
||||
switch (options.name) {
|
||||
// File Operations
|
||||
case 'list_lib_dir': return siteRoot + 'ajax/lib/' + options.repo_id + '/dir/';
|
||||
case 'del_dir': return siteRoot + 'api/v2.1/repos/' + options.repo_id + '/dir/';
|
||||
case 'del_file': return siteRoot + 'api/v2.1/repos/' + options.repo_id + '/file/';
|
||||
case 'download_dirents': return siteRoot + 'api/v2.1/repos/' + options.repo_id + '/dirents/download-link/';
|
||||
case 'download_dir_zip_url': return fileServerRoot + 'zip/' + options.zip_token;
|
||||
case 'zip_task': return siteRoot + 'api/v2.1/repos/' + options.repo_id + '/zip-task/';
|
||||
case 'query_zip_progress': return siteRoot + 'api/v2.1/query-zip-progress/';
|
||||
case 'rename_dir': return siteRoot + 'api/v2.1/repos/' + options.repo_id + '/dir/';
|
||||
case 'rename_file': return siteRoot + 'api/v2.1/repos/' + options.repo_id + '/file/';
|
||||
case 'mv_dir': return siteRoot + 'ajax/repo/' + options.repo_id + '/dir/mv/';
|
||||
@@ -94,6 +97,7 @@ define([
|
||||
case 'get_cp_progress': return siteRoot + 'ajax/cp_progress/';
|
||||
case 'cancel_cp': return siteRoot + 'ajax/cancel_cp/';
|
||||
case 'get_file_op_url': return siteRoot + 'ajax/repo/' + options.repo_id + '/file_op_url/';
|
||||
case 'get_file_download_url': return siteRoot + 'lib/' + options.repo_id + '/file' + options.file_path + '?dl=1';
|
||||
case 'get_file_uploaded_bytes': return siteRoot + 'ajax/repo/' + options.repo_id + '/get-file-uploaded-bytes/';
|
||||
case 'get_dirents': return siteRoot + 'ajax/repo/' + options.repo_id + '/dirents/';
|
||||
|
||||
@@ -327,9 +331,9 @@ define([
|
||||
feedback: function(con, type, time) {
|
||||
var time = time || 5000;
|
||||
if ($('.messages').length > 0) {
|
||||
$('.messages').html('<li class="' + type + '">' + con + '</li>');
|
||||
$('.messages').html('<li class="' + type + '">' + this.HTMLescape(con) + '</li>');
|
||||
} else {
|
||||
var html = '<ul class="messages"><li class="' + type + '">' + con + '</li></ul>';
|
||||
var html = '<ul class="messages"><li class="' + type + '">' + this.HTMLescape(con) + '</li></ul>';
|
||||
$('#main').append(html);
|
||||
}
|
||||
$('.messages').css({'left':($(window).width() - $('.messages').width())/2, 'top':10}).removeClass('hide');
|
||||
|
@@ -42,7 +42,7 @@ define([
|
||||
_this.remove();
|
||||
|
||||
var msg = gettext("Successfully unlink %(name)s.")
|
||||
.replace('%(name)s', Common.HTMLescape(device_name));
|
||||
.replace('%(name)s', device_name);
|
||||
Common.feedback(msg, 'success');
|
||||
},
|
||||
error: function(xhr) {
|
||||
|
@@ -6,11 +6,6 @@ from django.core.urlresolvers import reverse
|
||||
|
||||
from seahub.test_utils import BaseTestCase
|
||||
|
||||
try:
|
||||
from seahub.settings import LOCAL_PRO_DEV_ENV
|
||||
except ImportError:
|
||||
LOCAL_PRO_DEV_ENV = False
|
||||
|
||||
|
||||
class DirentsDownloadLinkViewTest(BaseTestCase):
|
||||
|
||||
|
40
tests/api/endpoints/test_query_zip_progress.py
Normal file
40
tests/api/endpoints/test_query_zip_progress.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import json
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from seahub.test_utils import BaseTestCase
|
||||
|
||||
class QueryZipProgressViewTest(BaseTestCase):
|
||||
|
||||
def _get_zip_token(self):
|
||||
self.login_as(self.user)
|
||||
|
||||
parent_dir = '/'
|
||||
folder_name = self.folder
|
||||
args = '?parent_dir=%s&dirents=%s' % (parent_dir, folder_name)
|
||||
url = reverse('api-v2.1-zip-task', args=[self.repo.id]) + args
|
||||
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
json_resp = json.loads(resp.content)
|
||||
return json_resp['zip_token']
|
||||
|
||||
def setUp(self):
|
||||
self.url = reverse('api-v2.1-query-zip-progress')
|
||||
|
||||
def tearDown(self):
|
||||
self.remove_repo()
|
||||
|
||||
def test_can_get_progress(self):
|
||||
|
||||
token = self._get_zip_token()
|
||||
|
||||
url = self.url + '?token=%s' % token
|
||||
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
json_resp = json.loads(resp.content)
|
||||
assert json_resp['total'] is not None
|
||||
assert json_resp['zipped'] is not None
|
93
tests/api/endpoints/test_share_link_zip_task.py
Normal file
93
tests/api/endpoints/test_share_link_zip_task.py
Normal file
@@ -0,0 +1,93 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import json
|
||||
from mock import patch
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from seahub.test_utils import BaseTestCase
|
||||
from seahub.share.models import FileShare
|
||||
|
||||
class ShareLinkZipTaskViewTest(BaseTestCase):
|
||||
|
||||
def _add_dir_share_link(self):
|
||||
fs = FileShare.objects.create_dir_link(self.user.username,
|
||||
self.repo.id, self.folder, None, None)
|
||||
|
||||
return fs.token
|
||||
|
||||
def setUp(self):
|
||||
self.url = reverse('api-v2.1-share-link-zip-task')
|
||||
|
||||
def tearDown(self):
|
||||
self.remove_repo()
|
||||
|
||||
def test_can_get_share_link_zip_task(self):
|
||||
|
||||
share_link_token = self._add_dir_share_link()
|
||||
|
||||
url = self.url + '?share_link_token=%s&path=/' % share_link_token
|
||||
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
json_resp = json.loads(resp.content)
|
||||
assert len(json_resp['zip_token']) == 36
|
||||
|
||||
@patch('seahub.api2.endpoints.share_link_zip_task.settings.ENABLE_SHARE_LINK_AUDIT')
|
||||
@patch('seahub.api2.endpoints.share_link_zip_task.is_pro_version')
|
||||
def test_get_zip_token_with_unauthenticated_user(self,
|
||||
mock_is_pro_version, mock_enable_share_link_audit):
|
||||
|
||||
mock_is_pro_version.return_value = True
|
||||
mock_enable_share_link_audit = True
|
||||
|
||||
share_link_token = self._add_dir_share_link()
|
||||
|
||||
url = self.url + '?share_link_token=%s&path=/' % share_link_token
|
||||
|
||||
# user neither login in nor passed code check
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(403, resp.status_code)
|
||||
|
||||
@patch('seahub.api2.endpoints.share_link_zip_task.settings.ENABLE_SHARE_LINK_AUDIT')
|
||||
@patch('seahub.api2.endpoints.share_link_zip_task.is_pro_version')
|
||||
def test_get_zip_token_with_authenticated_user(self,
|
||||
mock_is_pro_version, mock_enable_share_link_audit):
|
||||
|
||||
mock_is_pro_version.return_value = True
|
||||
mock_enable_share_link_audit = True
|
||||
|
||||
share_link_token = self._add_dir_share_link()
|
||||
|
||||
# user login in
|
||||
self.login_as(self.admin)
|
||||
url = self.url + '?share_link_token=%s&path=/' % share_link_token
|
||||
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
json_resp = json.loads(resp.content)
|
||||
assert len(json_resp['zip_token']) == 36
|
||||
|
||||
@patch('seahub.api2.endpoints.share_link_zip_task.settings.ENABLE_SHARE_LINK_AUDIT')
|
||||
@patch('seahub.api2.endpoints.share_link_zip_task.is_pro_version')
|
||||
def test_get_zip_token_with_anonymous_user_passed_code_check(self,
|
||||
mock_is_pro_version, mock_enable_share_link_audit):
|
||||
|
||||
mock_is_pro_version.return_value = True
|
||||
mock_enable_share_link_audit = True
|
||||
|
||||
share_link_token = self._add_dir_share_link()
|
||||
|
||||
url = self.url + '?share_link_token=%s&path=/' % share_link_token
|
||||
|
||||
# user pass code check
|
||||
session = self.client.session
|
||||
session['anonymous_email'] = 'anonymous@email.com'
|
||||
session.save()
|
||||
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
json_resp = json.loads(resp.content)
|
||||
assert len(json_resp['zip_token']) == 36
|
109
tests/api/endpoints/test_zip_task.py
Normal file
109
tests/api/endpoints/test_zip_task.py
Normal file
@@ -0,0 +1,109 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import json
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from seahub.test_utils import BaseTestCase
|
||||
|
||||
from seaserv import seafile_api
|
||||
|
||||
try:
|
||||
from seahub.settings import LOCAL_PRO_DEV_ENV
|
||||
except ImportError:
|
||||
LOCAL_PRO_DEV_ENV = False
|
||||
|
||||
|
||||
class ZipTaskViewTest(BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.repo_id = self.repo.id
|
||||
self.folder_path = self.folder
|
||||
self.folder_name = os.path.basename(self.folder_path)
|
||||
|
||||
self.url = reverse('api-v2.1-zip-task', args=[self.repo_id])
|
||||
|
||||
def tearDown(self):
|
||||
self.remove_repo()
|
||||
|
||||
def test_can_get_download_dir_zip_token(self):
|
||||
self.login_as(self.user)
|
||||
|
||||
parent_dir = '/'
|
||||
folder_name = self.folder_name
|
||||
url = self.url + '?parent_dir=%s&dirents=%s' % (parent_dir, folder_name)
|
||||
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
json_resp = json.loads(resp.content)
|
||||
assert len(json_resp['zip_token']) == 36
|
||||
|
||||
def test_can_get_download_multi_zip_token(self):
|
||||
|
||||
# create another folder for download multi
|
||||
another_folder_name = 'another_folder_name'
|
||||
seafile_api.post_dir(repo_id=self.repo.id,
|
||||
parent_dir='/', dirname=another_folder_name,
|
||||
username=self.user.username)
|
||||
|
||||
self.login_as(self.user)
|
||||
|
||||
parent_dir = '/'
|
||||
folder_name = self.folder_name
|
||||
url = self.url + '?parent_dir=%s&dirents=%s&dirents=%s' % (parent_dir,
|
||||
folder_name, another_folder_name)
|
||||
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
json_resp = json.loads(resp.content)
|
||||
assert len(json_resp['zip_token']) == 36
|
||||
|
||||
def test_can_get_zip_token_with_invalid_repo_permission(self):
|
||||
self.login_as(self.admin)
|
||||
|
||||
parent_dir = '/'
|
||||
folder_name = self.folder_name
|
||||
url = self.url + '?parent_dir=%s&dirents=%s' % (parent_dir, folder_name)
|
||||
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(403, resp.status_code)
|
||||
|
||||
def test_can_get_zip_token_for_r_permission_folder(self):
|
||||
|
||||
if not LOCAL_PRO_DEV_ENV:
|
||||
return
|
||||
|
||||
self.set_user_folder_r_permission_to_admin()
|
||||
|
||||
self.login_as(self.admin)
|
||||
|
||||
parent_dir = '/'
|
||||
folder_name = self.folder_name
|
||||
url = self.url + '?parent_dir=%s&dirents=%s' % (parent_dir, folder_name)
|
||||
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
json_resp = json.loads(resp.content)
|
||||
assert len(json_resp['zip_token']) == 36
|
||||
|
||||
def test_can_get_zip_token_for_rw_permission_folder(self):
|
||||
|
||||
if not LOCAL_PRO_DEV_ENV:
|
||||
return
|
||||
|
||||
self.set_user_folder_rw_permission_to_admin()
|
||||
|
||||
self.login_as(self.admin)
|
||||
|
||||
parent_dir = '/'
|
||||
folder_name = self.folder_name
|
||||
url = self.url + '?parent_dir=%s&dirents=%s' % (parent_dir, folder_name)
|
||||
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
json_resp = json.loads(resp.content)
|
||||
assert len(json_resp['zip_token']) == 36
|
@@ -28,16 +28,6 @@ class SharedDirTest(TestCase, Fixtures):
|
||||
|
||||
self.assertContains(resp, '<h2>%s</h2>' % self.repo.name)
|
||||
|
||||
zip_url = 'href="?p=/&dl=1"'
|
||||
self.assertContains(resp, zip_url)
|
||||
|
||||
def test_can_download(self):
|
||||
dl_url = reverse('view_shared_dir', args=[self.fs.token]) + \
|
||||
'?p=/&dl=1'
|
||||
resp = self.client.get(dl_url)
|
||||
self.assertEqual(302, resp.status_code)
|
||||
assert '8082/files/' in resp.get('location')
|
||||
|
||||
def test_view_raw_file_via_shared_dir(self):
|
||||
resp = self.client.get(
|
||||
reverse('view_file_via_shared_dir', args=[self.fs.token]) + '?p=' + self.file + '&raw=1'
|
||||
|
Reference in New Issue
Block a user