diff --git a/seahub/api2/endpoints/dir_shared_items.py b/seahub/api2/endpoints/dir_shared_items.py index 71c2e1995d..92215823b7 100644 --- a/seahub/api2/endpoints/dir_shared_items.py +++ b/seahub/api2/endpoints/dir_shared_items.py @@ -16,6 +16,7 @@ from seahub.api2.authentication import TokenAuthentication from seahub.api2.permissions import IsRepoAccessible from seahub.api2.utils import api_error from seahub.base.templatetags.seahub_tags import email2nickname +from seahub.base.accounts import User from seahub.share.signals import share_repo_to_user_successful from seahub.share.views import check_user_share_quota from seahub.utils import (is_org_context, is_valid_username, @@ -154,16 +155,19 @@ class DirSharedItemsEndpoint(APIView): if not repo: return api_error(status.HTTP_400_BAD_REQUEST, 'Repo not found.') + 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.') + + if username != seafile_api.get_repo_owner(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, 'Bad permission') - 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.') - if path == '/': shared_repo = repo else: @@ -182,6 +186,11 @@ class DirSharedItemsEndpoint(APIView): if shared_to is None or not is_valid_username(shared_to): return api_error(status.HTTP_400_BAD_REQUEST, 'Bad username.') + try: + User.objects.get(email=shared_to) + except User.DoesNotExist: + return api_error(status.HTTP_400_BAD_REQUEST, 'Invalid user, should be registered') + if is_org_context(request): org_id = request.user.org.org_id seaserv.seafserv_threaded_rpc.org_set_share_permission( @@ -227,6 +236,9 @@ class DirSharedItemsEndpoint(APIView): if seafile_api.get_dir_id_by_path(repo.id, path) is None: return api_error(status.HTTP_400_BAD_REQUEST, 'Directory not found.') + if username != seafile_api.get_repo_owner(repo_id): + return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') + if path != '/': try: sub_repo = self.get_or_create_sub_repo_by_path(request, repo, path) @@ -250,8 +262,14 @@ class DirSharedItemsEndpoint(APIView): share_to_users = request.DATA.getlist('username') for to_user in share_to_users: if not is_valid_username(to_user): - return api_error(status.HTTP_400_BAD_REQUEST, - 'Username must be a valid email address.') + failed.append(to_user) + continue + + try: + User.objects.get(email=to_user) + except User.DoesNotExist: + failed.append(to_user) + continue if not check_user_share_quota(username, shared_repo, users=[to_user]): return api_error(status.HTTP_403_FORBIDDEN, @@ -340,12 +358,15 @@ class DirSharedItemsEndpoint(APIView): if not repo: return api_error(status.HTTP_400_BAD_REQUEST, 'Repo not found.') - shared_to_user, shared_to_group = self.handle_shared_to_args(request) - 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.') + if username != seafile_api.get_repo_owner(repo_id): + return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') + + shared_to_user, shared_to_group = self.handle_shared_to_args(request) + if path == '/': shared_repo = repo else: @@ -364,6 +385,11 @@ class DirSharedItemsEndpoint(APIView): if shared_to is None or not is_valid_username(shared_to): return api_error(status.HTTP_400_BAD_REQUEST, 'Bad argument.') + try: + User.objects.get(email=shared_to) + except User.DoesNotExist: + return api_error(status.HTTP_400_BAD_REQUEST, 'Invalid user, should be registered') + if is_org_context(request): org_id = request.user.org.org_id seaserv.seafserv_threaded_rpc.org_remove_share( diff --git a/tests/api/endpoints/test_dir_shared_items.py b/tests/api/endpoints/test_dir_shared_items.py index a1fea2812f..7a0418f9a9 100644 --- a/tests/api/endpoints/test_dir_shared_items.py +++ b/tests/api/endpoints/test_dir_shared_items.py @@ -2,6 +2,8 @@ import json from seaserv import seafile_api +from tests.common.utils import randstring + from seahub.test_utils import BaseTestCase class DirSharedItemsTest(BaseTestCase): @@ -60,24 +62,43 @@ class DirSharedItemsTest(BaseTestCase): resp = self.client.put( '/api2/repos/%s/dir/shared_items/?p=%s' % (self.repo.id, self.folder), - "share_type=user&username=a@a.com&username=b@b.com", + "share_type=user&username=%s" % self.admin.email, 'application/x-www-form-urlencoded', ) self.assertEqual(200, resp.status_code) json_resp = json.loads(resp.content) - assert len(json_resp['success']) == 2 + assert len(json_resp['success']) == 1 assert json_resp['success'][0]['permission'] == 'r' def test_share_folder_to_invalid_email(self): self.login_as(self.user) + invalid_email = '%s' % randstring(6) resp = self.client.put( '/api2/repos/%s/dir/shared_items/?p=%s' % (self.repo.id, self.folder), - "share_type=user&username=abc", + "share_type=user&username=%s" % invalid_email, 'application/x-www-form-urlencoded', ) - self.assertEqual(400, resp.status_code) + self.assertEqual(200, resp.status_code) + json_resp = json.loads(resp.content) + assert len(json_resp['failed']) == 1 + assert invalid_email in json_resp['failed'] + + def test_share_folder_to_unregistered_user(self): + self.login_as(self.user) + unregistered_user = '%s@%s.com' % (randstring(6), randstring(6)) + + resp = self.client.put( + '/api2/repos/%s/dir/shared_items/?p=%s' % (self.repo.id, + self.folder), + "share_type=user&username=%s" % unregistered_user, + 'application/x-www-form-urlencoded', + ) + self.assertEqual(200, resp.status_code) + json_resp = json.loads(resp.content) + assert len(json_resp['failed']) == 1 + assert unregistered_user in json_resp['failed'] def test_can_share_root_to_groups(self): self.login_as(self.user) @@ -134,6 +155,21 @@ class DirSharedItemsTest(BaseTestCase): json_resp = json.loads(resp.content) assert json_resp[0]['permission'] == 'r' + def test_modify_shared_repo_with_unregistered_user(self): + self._add_shared_items() + self.login_as(self.user) + + unregistered_user = '%s@%s.com' % (randstring(6), randstring(6)) + + resp = self.client.post('/api2/repos/%s/dir/shared_items/?p=%s&share_type=user&username=%s' % ( + self.repo.id, + self.folder, + unregistered_user), { + 'permission': 'r' + } + ) + self.assertEqual(400, resp.status_code) + def test_can_modify_group_shared_repo(self): self._add_shared_items() self.login_as(self.user) @@ -174,6 +210,19 @@ class DirSharedItemsTest(BaseTestCase): json_resp = json.loads(resp.content) assert len(json_resp) == 0 + def test_unshare_repo_with_unregistered_user(self): + self._add_shared_items() + self.login_as(self.user) + + unregistered_user = '%s@%s.com' % (randstring(6), randstring(6)) + + resp = self.client.delete('/api2/repos/%s/dir/shared_items/?p=%s&share_type=user&username=%s' % ( + self.repo.id, + self.folder, + unregistered_user + )) + self.assertEqual(400, resp.status_code) + def test_can_unshare_repo_to_group(self): self._add_shared_items() self.login_as(self.user)