From 6922c8fa0d2f6f6ba5321476031da73491514371 Mon Sep 17 00:00:00 2001 From: lian Date: Mon, 17 Apr 2017 14:57:46 +0800 Subject: [PATCH 1/8] use true/false as the return value of "is_admin" field --- seahub/group/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seahub/group/utils.py b/seahub/group/utils.py index 5b8f1d0091..ef6e4964b4 100644 --- a/seahub/group/utils.py +++ b/seahub/group/utils.py @@ -88,7 +88,7 @@ def get_group_member_info(request, group_id, email, avatar_size=AVATAR_DEFAULT_S role = 'Member' group = ccnet_api.get_group(int(group_id)) - is_admin = ccnet_api.check_group_staff(int(group_id), email) + is_admin = bool(ccnet_api.check_group_staff(int(group_id), email)) if email == group.creator_name: role = 'Owner' elif is_admin: From 02a3078829190020a39ae14010cb836cc80a6acd Mon Sep 17 00:00:00 2001 From: lian Date: Wed, 19 Apr 2017 16:05:59 +0800 Subject: [PATCH 2/8] check if repo/dir has been shared when share repo/dir --- seahub/api2/endpoints/dir_shared_items.py | 47 +++++++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/seahub/api2/endpoints/dir_shared_items.py b/seahub/api2/endpoints/dir_shared_items.py index f5dbfdc3bd..4cdcb28db2 100644 --- a/seahub/api2/endpoints/dir_shared_items.py +++ b/seahub/api2/endpoints/dir_shared_items.py @@ -116,6 +116,28 @@ class DirSharedItemsEndpoint(APIView): else: return seafile_api.get_repo_owner(repo_id) + def has_shared_to_user(self, request, repo_id, path, username): + items = self.list_user_shared_items(request, repo_id, path) + + has_shared = False + for item in items: + if username == item['user_info']['name']: + has_shared = True + break + + return has_shared + + def has_shared_to_group(self, request, repo_id, path, group_id): + items = self.list_group_shared_items(request, repo_id, path) + + has_shared = False + for item in items: + if group_id == item['group_info']['id']: + has_shared = True + break + + return has_shared + def get(self, request, repo_id, format=None): """List shared items(shared to users/groups) for a folder/library. """ @@ -149,21 +171,16 @@ class DirSharedItemsEndpoint(APIView): path = request.GET.get('p', '/') if seafile_api.get_dir_id_by_path(repo.id, path) is None: - return api_error(status.HTTP_400_BAD_REQUEST, 'Directory not found.') + return api_error(status.HTTP_404_NOT_FOUND, 'Folder %s not found.' % path) if username != self.get_repo_owner(request, repo_id): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') - shared_to_user, shared_to_group = self.handle_shared_to_args(request) - permission = request.data.get('permission', 'r') if permission not in ['r', 'rw']: return api_error(status.HTTP_400_BAD_REQUEST, 'permission invalid.') - path = request.GET.get('p', '/') - if seafile_api.get_dir_id_by_path(repo.id, path) is None: - return api_error(status.HTTP_404_NOT_FOUND, 'Folder %s not found.' % path) - + shared_to_user, shared_to_group = self.handle_shared_to_args(request) if shared_to_user: shared_to = request.GET.get('username') if shared_to is None or not is_valid_username(shared_to): @@ -268,6 +285,13 @@ class DirSharedItemsEndpoint(APIView): }) continue + if self.has_shared_to_user(request, repo_id, path, to_user): + result['failed'].append({ + 'email': to_user, + 'error_msg': 'This item has been shared to %s.' % to_user + }) + continue + try: if is_org_context(request): org_id = request.user.org.org_id @@ -321,10 +345,18 @@ class DirSharedItemsEndpoint(APIView): gid = int(gid) except ValueError: return api_error(status.HTTP_400_BAD_REQUEST, 'group_id %s invalid.' % gid) + group = seaserv.get_group(gid) if not group: return api_error(status.HTTP_404_NOT_FOUND, 'Group %s not found' % gid) + if self.has_shared_to_group(request, repo_id, path, gid): + result['failed'].append({ + 'group_name': group.group_name, + 'error_msg': 'This item has been shared to %s.' % group.group_name + }) + continue + try: if is_org_context(request): org_id = request.user.org.org_id @@ -386,7 +418,6 @@ class DirSharedItemsEndpoint(APIView): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') shared_to_user, shared_to_group = self.handle_shared_to_args(request) - if shared_to_user: shared_to = request.GET.get('username') if shared_to is None or not is_valid_username(shared_to): From 7c82cada607e58dc7a1748cfc62c9df83f31d7bd Mon Sep 17 00:00:00 2001 From: llj Date: Sat, 22 Apr 2017 16:30:58 +0800 Subject: [PATCH 3/8] [dir view] rename: fix --- static/scripts/app/models/dirent.js | 2 +- static/scripts/app/views/dialogs/dirent-rename.js | 1 + static/scripts/app/views/dirent.js | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/static/scripts/app/models/dirent.js b/static/scripts/app/models/dirent.js index 92b007b00c..d2651fb77d 100644 --- a/static/scripts/app/models/dirent.js +++ b/static/scripts/app/models/dirent.js @@ -108,7 +108,7 @@ define([ data: post_data, success: function(data) { var renamed_dirent_data = { - 'obj_name': options.newname, + 'obj_name': data.obj_name, 'last_modified': new Date().getTime()/1000, 'last_update': gettext("Just now") }; diff --git a/static/scripts/app/views/dialogs/dirent-rename.js b/static/scripts/app/views/dialogs/dirent-rename.js index e6c7d530ef..a94805db5c 100644 --- a/static/scripts/app/views/dialogs/dirent-rename.js +++ b/static/scripts/app/views/dialogs/dirent-rename.js @@ -24,6 +24,7 @@ define([ var $input = this.$('[name="newname"]'); var dot_index = this.dirent.get('obj_name').lastIndexOf('.'); if (!this.dirent.get('is_dir') && dot_index != -1) { + $input[0].focus(); $input[0].setSelectionRange(0, dot_index); } else { $input.select(); diff --git a/static/scripts/app/views/dirent.js b/static/scripts/app/views/dirent.js index 2bc1ca43b2..acaa3c1881 100644 --- a/static/scripts/app/views/dirent.js +++ b/static/scripts/app/views/dirent.js @@ -245,6 +245,7 @@ define([ var $input = $('[name="newname"]', form); var dot_index = dirent_name.lastIndexOf('.'); if (!this.model.get('is_dir') && dot_index != -1) { + $input[0].focus(); $input[0].setSelectionRange(0, dot_index); } else { $input.select(); From 1e4b3ae5a2032e7238334654671594c439a82010 Mon Sep 17 00:00:00 2001 From: lian Date: Mon, 24 Apr 2017 17:31:25 +0800 Subject: [PATCH 4/8] return repo name when search file via api --- seahub/api2/views.py | 1 + 1 file changed, 1 insertion(+) diff --git a/seahub/api2/views.py b/seahub/api2/views.py index 4b8c492583..dd82e25778 100644 --- a/seahub/api2/views.py +++ b/seahub/api2/views.py @@ -346,6 +346,7 @@ class Search(APIView): file_id = seafile_api.get_file_id_by_path(e['repo_id'], path) e['oid'] = file_id repo = get_repo(e['repo_id']) + e['repo_name'] = repo.name e['size'] = get_file_size(repo.store_id, repo.version, file_id) except SearpcError, err: pass From c93d7a8736e018ed1c61e834cda301f779b35384 Mon Sep 17 00:00:00 2001 From: lian Date: Mon, 24 Apr 2017 18:17:58 +0800 Subject: [PATCH 5/8] update return value when copy/move file via web api --- seahub/api2/views.py | 11 ++++- tests/api/test_files.py | 90 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 94 insertions(+), 7 deletions(-) diff --git a/seahub/api2/views.py b/seahub/api2/views.py index 4b8c492583..3432bb1b3d 100644 --- a/seahub/api2/views.py +++ b/seahub/api2/views.py @@ -2007,6 +2007,7 @@ class FileView(APIView): parent_dir = os.path.dirname(path) operation = request.POST.get('operation', '') + file_info = {} if operation.lower() == 'rename': if check_folder_permission(request, repo_id, parent_dir) != 'rw': return api_error(status.HTTP_403_FORBIDDEN, @@ -2090,7 +2091,10 @@ class FileView(APIView): if request.GET.get('reloaddir', '').lower() == 'true': return reloaddir(request, dst_repo, dst_dir) else: - resp = Response('success', status=status.HTTP_301_MOVED_PERMANENTLY) + file_info['repo_id'] = dst_repo_id + file_info['parent_dir'] = dst_dir + file_info['obj_name'] = new_filename_utf8 + resp = Response(file_info, status=status.HTTP_301_MOVED_PERMANENTLY) uri = reverse('FileView', args=[dst_repo_id], request=request) resp['Location'] = uri + '?p=' + quote(dst_dir_utf8) + quote(new_filename_utf8) return resp @@ -2140,7 +2144,10 @@ class FileView(APIView): if request.GET.get('reloaddir', '').lower() == 'true': return reloaddir(request, dst_repo, dst_dir) else: - resp = Response('success', status=status.HTTP_200_OK) + file_info['repo_id'] = dst_repo_id + file_info['parent_dir'] = dst_dir + file_info['obj_name'] = new_filename_utf8 + resp = Response(file_info, status=status.HTTP_200_OK) uri = reverse('FileView', args=[dst_repo_id], request=request) resp['Location'] = uri + '?p=' + quote(dst_dir_utf8) + quote(new_filename_utf8) return resp diff --git a/tests/api/test_files.py b/tests/api/test_files.py index 7002d2575d..f82c24b42c 100644 --- a/tests/api/test_files.py +++ b/tests/api/test_files.py @@ -8,6 +8,7 @@ import pytest import urllib from urllib import urlencode, quote import urlparse +from nose.tools import assert_in from tests.common.utils import randstring, urljoin from tests.api.apitestbase import ApiTestBase @@ -32,15 +33,70 @@ class FilesApiTest(ApiTestBase): def test_move_file(self): with self.get_tmp_repo() as repo: - _, furl = self.create_file(repo) # TODO: create another repo here, and use it as dst_repo + + # create sub folder(dpath) + dpath, _ = self.create_dir(repo) + + # create tmp file in sub folder(dpath) + tmp_file = 'tmp_file.txt' + file_path = dpath + '/' + tmp_file + furl = repo.get_filepath_url(file_path) + data = {'operation': 'create'} + res = self.post(furl, data=data, expected=201) + + # copy tmp file from sub folder(dpath) to dst dir('/') data = { - 'operation': 'move', 'dst_repo': repo.repo_id, 'dst_dir': '/', + 'operation': 'copy', } - res = self.post(furl, data=data) - self.assertEqual(res.text, '"success"') + u = urlparse.urlparse(furl) + parsed_furl = urlparse.urlunparse((u.scheme, u.netloc, u.path, '', '', '')) + res = self.post(parsed_furl+ '?p=' + quote(file_path), data=data) + assert_in(tmp_file, res.text) + + # get info of copied file in dst dir('/') + fdurl = repo.file_url + u'detail/?p=/%s' % quote(tmp_file) + detail = self.get(fdurl).json() + self.assertIsNotNone(detail) + self.assertIsNotNone(detail['id']) + + # copy tmp file from sub folder(dpath) to dst dir('/') again + # for test can rename file if a file with the same name is dst dir + data = { + 'dst_repo': repo.repo_id, + 'dst_dir': '/', + 'operation': 'copy', + } + u = urlparse.urlparse(furl) + parsed_furl = urlparse.urlunparse((u.scheme, u.netloc, u.path, '', '', '')) + res = self.post(parsed_furl+ '?p=' + quote(file_path), data=data) + assert_in('tmp_file (1).txt', res.text) + + # copy tmp file from sub folder(dpath) to dst dir('/') again + # for test can rename file if a file with the same name is dst dir + data = { + 'dst_repo': repo.repo_id, + 'dst_dir': '/', + 'operation': 'copy', + } + u = urlparse.urlparse(furl) + parsed_furl = urlparse.urlunparse((u.scheme, u.netloc, u.path, '', '', '')) + res = self.post(parsed_furl+ '?p=' + quote(file_path), data=data) + assert_in('tmp_file (2).txt', res.text) + + # then move file to dst dir + data = { + 'dst_repo': repo.repo_id, + 'dst_dir': '/', + 'operation': 'move', + } + u = urlparse.urlparse(furl) + parsed_furl = urlparse.urlunparse((u.scheme, u.netloc, u.path, '', '', '')) + res = self.post(parsed_furl+ '?p=' + quote(file_path), data=data) + assert_in('tmp_file%20%283%29.txt', res.text) + def test_copy_file(self): with self.get_tmp_repo() as repo: @@ -65,7 +121,7 @@ class FilesApiTest(ApiTestBase): u = urlparse.urlparse(furl) parsed_furl = urlparse.urlunparse((u.scheme, u.netloc, u.path, '', '', '')) res = self.post(parsed_furl+ '?p=' + quote(file_path), data=data) - self.assertEqual(res.text, '"success"') + assert_in(tmp_file, res.text) # get info of copied file in dst dir('/') fdurl = repo.file_url + u'detail/?p=/%s' % quote(tmp_file) @@ -73,6 +129,30 @@ class FilesApiTest(ApiTestBase): self.assertIsNotNone(detail) self.assertIsNotNone(detail['id']) + # copy tmp file from sub folder(dpath) to dst dir('/') again + # for test can rename file if a file with the same name is dst dir + data = { + 'dst_repo': repo.repo_id, + 'dst_dir': '/', + 'operation': 'copy', + } + u = urlparse.urlparse(furl) + parsed_furl = urlparse.urlunparse((u.scheme, u.netloc, u.path, '', '', '')) + res = self.post(parsed_furl+ '?p=' + quote(file_path), data=data) + assert_in('tmp_file (1).txt', res.text) + + # copy tmp file from sub folder(dpath) to dst dir('/') again + # for test can rename file if a file with the same name is dst dir + data = { + 'dst_repo': repo.repo_id, + 'dst_dir': '/', + 'operation': 'copy', + } + u = urlparse.urlparse(furl) + parsed_furl = urlparse.urlunparse((u.scheme, u.netloc, u.path, '', '', '')) + res = self.post(parsed_furl+ '?p=' + quote(file_path), data=data) + assert_in('tmp_file (2).txt', res.text) + def test_download_file(self): with self.get_tmp_repo() as repo: fname, furl = self.create_file(repo) From 5da3d7387097c597d6cf408bcf8b5be040412810 Mon Sep 17 00:00:00 2001 From: lian Date: Tue, 25 Apr 2017 10:29:21 +0800 Subject: [PATCH 6/8] rm SVG type when search file --- seahub/templates/snippets/search_form.html | 4 ---- 1 file changed, 4 deletions(-) diff --git a/seahub/templates/snippets/search_form.html b/seahub/templates/snippets/search_form.html index 2b884e5b10..e9b0a8ff37 100644 --- a/seahub/templates/snippets/search_form.html +++ b/seahub/templates/snippets/search_form.html @@ -60,10 +60,6 @@ {% trans "Audio" %} -