From 1672bbd5ff03c03c885531031fb76cd33bdd95a0 Mon Sep 17 00:00:00 2001 From: zhengxie Date: Wed, 23 Dec 2015 17:31:07 +0800 Subject: [PATCH 1/2] [api2] Add list shared upload links --- seahub/api2/endpoints/shared_upload_links.py | 63 +++++++++++++++++++ seahub/api2/urls.py | 2 + .../api/endpoints/test_shared_upload_links.py | 35 +++++++++++ 3 files changed, 100 insertions(+) create mode 100644 seahub/api2/endpoints/shared_upload_links.py create mode 100644 tests/api/endpoints/test_shared_upload_links.py diff --git a/seahub/api2/endpoints/shared_upload_links.py b/seahub/api2/endpoints/shared_upload_links.py new file mode 100644 index 0000000000..4f2d3d5745 --- /dev/null +++ b/seahub/api2/endpoints/shared_upload_links.py @@ -0,0 +1,63 @@ +import json +import os + +from django.http import HttpResponse +from django.utils.dateformat import DateFormat +from rest_framework.authentication import SessionAuthentication +from rest_framework.permissions import IsAuthenticated +from rest_framework.throttling import UserRateThrottle +from rest_framework.views import APIView + +from seaserv import seafile_api + +from seahub.api2.authentication import TokenAuthentication +from seahub.share.models import UploadLinkShare +from seahub.utils import gen_shared_upload_link + +json_content_type = 'application/json; charset=utf-8' + +class SharedUploadLinksView(APIView): + authentication_classes = (TokenAuthentication, SessionAuthentication ) + permission_classes = (IsAuthenticated,) + throttle_classes = (UserRateThrottle, ) + + def get(self, request, format=None): + username = request.user.username + + uploadlinks = UploadLinkShare.objects.filter(username=username) + p_uploadlinks = [] + for link in uploadlinks: + r = seafile_api.get_repo(link.repo_id) + if not r: + link.delete() + continue + + if seafile_api.get_dir_id_by_path(r.id, link.path) is None: + link.delete() + continue + + if link.path != '/': + link.dir_name = os.path.basename(link.path.rstrip('/')) + else: + link.dir_name = link.path + + link.shared_link = gen_shared_upload_link(link.token) + link.repo = r + + if link.expire_date: + expire_date = link.expire_date.strftime("%Y-%m-%dT%H:%M:%S") + DateFormat(link.expire_date).format('O') + else: + expire_date = "" + + p_uploadlinks.append({ + "username": link.username, + "repo_id": link.repo_id, + "path": link.path, + "token": link.token, + "ctime": link.ctime.strftime("%Y-%m-%dT%H:%M:%S") + DateFormat(link.ctime).format('O'), + "view_cnt": link.view_cnt, + "expire_date": expire_date, + }) + + return HttpResponse(json.dumps(p_uploadlinks), + status=200, content_type=json_content_type) diff --git a/seahub/api2/urls.py b/seahub/api2/urls.py index 2b128f1886..3fba174fc6 100644 --- a/seahub/api2/urls.py +++ b/seahub/api2/urls.py @@ -5,6 +5,7 @@ from .views_misc import ServerInfoView from .views_auth import LogoutDeviceView, ClientLoginTokenView from .endpoints.dir_shared_items import DirSharedItemsEndpoint from .endpoints.account import Account +from .endpoints.shared_upload_links import SharedUploadLinksView urlpatterns = patterns('', url(r'^ping/$', Ping.as_view()), @@ -50,6 +51,7 @@ urlpatterns = patterns('', url(r'^beshared-repos/$', BeShared.as_view(), name='beshared'), url(r'^default-repo/$', DefaultRepoView.as_view(), name='api2-defaultrepo'), url(r'^shared-links/$', SharedLinksView.as_view()), + url(r'^shared-upload-links/$', SharedUploadLinksView.as_view()), url(r'^shared-files/$', SharedFilesView.as_view()), url(r'^virtual-repos/$', VirtualRepos.as_view()), url(r'^repo-tokens/$', RepoTokensView.as_view()), diff --git a/tests/api/endpoints/test_shared_upload_links.py b/tests/api/endpoints/test_shared_upload_links.py new file mode 100644 index 0000000000..ef1419f054 --- /dev/null +++ b/tests/api/endpoints/test_shared_upload_links.py @@ -0,0 +1,35 @@ +import json + +from django.utils.dateformat import DateFormat + +from seahub.share.models import UploadLinkShare +from seahub.test_utils import BaseTestCase + +class SharedUploadLinksTest(BaseTestCase): + def tearDown(self): + self.remove_repo() + + def test_can_list(self): + ls = UploadLinkShare.objects.create_upload_link_share( + self.user.username, + self.repo.id, self.folder) + + enc_ls = UploadLinkShare.objects.create_upload_link_share( + self.user.username, + self.repo.id, self.folder, password='123', expire_date=None) + + self.login_as(self.user) + resp = self.client.get( + '/api2/shared-upload-links/', + ) + self.assertEqual(200, resp.status_code) + json_resp = json.loads(resp.content) + assert len(json_resp) == 2 + + assert json_resp[0]['username'] == ls.username + assert json_resp[0]['repo_id'] == ls.repo_id + assert json_resp[0]['ctime'].startswith( + ls.ctime.strftime("%Y-%m-%dT%H:%M:%S")) + assert json_resp[0]['token'] == ls.token + assert json_resp[0]['view_cnt'] == ls.view_cnt + assert json_resp[0]['path'] == ls.path From bbb9e8664e802d7104b6d21f02d46af2680e9596 Mon Sep 17 00:00:00 2001 From: lian Date: Wed, 23 Dec 2015 18:53:12 +0800 Subject: [PATCH 2/2] [api] add delete be shared repo api --- seahub/api2/endpoints/be_shared_repo.py | 86 +++++++++++++++++++++ seahub/api2/urls.py | 2 + tests/api/endpoints/test_be_shared_repos.py | 73 +++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 seahub/api2/endpoints/be_shared_repo.py create mode 100644 tests/api/endpoints/test_be_shared_repos.py diff --git a/seahub/api2/endpoints/be_shared_repo.py b/seahub/api2/endpoints/be_shared_repo.py new file mode 100644 index 0000000000..a196ff0399 --- /dev/null +++ b/seahub/api2/endpoints/be_shared_repo.py @@ -0,0 +1,86 @@ +from rest_framework.authentication import SessionAuthentication +from rest_framework.permissions import IsAuthenticated +from rest_framework.throttling import UserRateThrottle +from rest_framework.response import Response +from rest_framework.views import APIView +from rest_framework import status + +import seaserv +from seaserv import seafile_api + +from seahub.api2.authentication import TokenAuthentication +from seahub.api2.utils import api_error +from seahub.utils import is_valid_username, is_org_context + +json_content_type = 'application/json; charset=utf-8' + +class BeSharedReposView(APIView): + authentication_classes = (TokenAuthentication, SessionAuthentication ) + permission_classes = (IsAuthenticated,) + throttle_classes = (UserRateThrottle, ) + + def delete(self, request, repo_id, format=None): + + if not seafile_api.get_repo(repo_id): + return api_error(status.HTTP_400_BAD_REQUEST, 'Library does not exist') + + username = request.user.username + share_type = request.GET.get('share_type', None) + if share_type == 'personal': + + from_email = request.GET.get('from', None) + if not is_valid_username(from_email): + return api_error(status.HTTP_400_BAD_REQUEST, 'Invalid argument') + + if is_org_context(request): + org_id = request.user.org.org_id + seaserv.seafserv_threaded_rpc.org_remove_share(org_id, + repo_id, + from_email, + username) + else: + seaserv.remove_share(repo_id, from_email, username) + + elif share_type == 'group': + + from_email = request.GET.get('from', None) + if not is_valid_username(from_email): + return api_error(status.HTTP_400_BAD_REQUEST, 'Invalid argument') + + group_id = request.GET.get('group_id', None) + group = seaserv.get_group(group_id) + if not group: + return api_error(status.HTTP_400_BAD_REQUEST, 'Group does not exist') + + if not seaserv.check_group_staff(group_id, username) and \ + not seafile_api.is_repo_owner(username, repo_id): + return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied') + + if seaserv.is_org_group(group_id): + org_id = seaserv.get_org_id_by_group(group_id) + seaserv.del_org_group_repo(repo_id, org_id, group_id) + else: + seafile_api.unset_group_repo(repo_id, group_id, from_email) + + elif share_type == 'public': + + if is_org_context(request): + org_repo_owner = seafile_api.get_org_repo_owner(repo_id) + is_org_repo_owner = True if org_repo_owner == username else False + + if not request.user.org.is_staff and not is_org_repo_owner: + return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied') + + org_id = request.user.org.org_id + seaserv.seafserv_threaded_rpc.unset_org_inner_pub_repo(org_id, + repo_id) + else: + if not seafile_api.is_repo_owner(username, repo_id) and \ + not request.user.is_staff: + return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied') + + seaserv.unset_inner_pub_repo(repo_id) + else: + return api_error(status.HTTP_400_BAD_REQUEST, 'Invalid argument') + + return Response({'success': True}, status=status.HTTP_200_OK) diff --git a/seahub/api2/urls.py b/seahub/api2/urls.py index 3fba174fc6..21ca7f5502 100644 --- a/seahub/api2/urls.py +++ b/seahub/api2/urls.py @@ -6,6 +6,7 @@ from .views_auth import LogoutDeviceView, ClientLoginTokenView from .endpoints.dir_shared_items import DirSharedItemsEndpoint from .endpoints.account import Account from .endpoints.shared_upload_links import SharedUploadLinksView +from .endpoints.be_shared_repo import BeSharedReposView urlpatterns = patterns('', url(r'^ping/$', Ping.as_view()), @@ -49,6 +50,7 @@ urlpatterns = patterns('', url(r'^shared-repos/$', SharedRepos.as_view(), name='sharedrepos'), url(r'^shared-repos/(?P[-0-9-a-f]{36})/$', SharedRepo.as_view(), name='sharedrepo'), url(r'^beshared-repos/$', BeShared.as_view(), name='beshared'), + url(r'^beshared-repos/(?P[-0-9-a-f]{36})/$', BeSharedReposView.as_view(), name='beshared-repos'), url(r'^default-repo/$', DefaultRepoView.as_view(), name='api2-defaultrepo'), url(r'^shared-links/$', SharedLinksView.as_view()), url(r'^shared-upload-links/$', SharedUploadLinksView.as_view()), diff --git a/tests/api/endpoints/test_be_shared_repos.py b/tests/api/endpoints/test_be_shared_repos.py new file mode 100644 index 0000000000..76e34d460a --- /dev/null +++ b/tests/api/endpoints/test_be_shared_repos.py @@ -0,0 +1,73 @@ +import json + +import seaserv +from seaserv import seafile_api + +from seahub.test_utils import BaseTestCase + +class BeSharedReposTest(BaseTestCase): + def setUp(self): + self.login_as(self.admin) + + def tearDown(self): + self.remove_repo() + + def _add_shared_items(self): + # create repo for user + sub_repo_id = seafile_api.create_virtual_repo(self.repo.id, + self.folder, + self.repo.name, '', + self.user.username) + + self.sub_repo_id = sub_repo_id + + + # create group for admin + admin_group_id = seaserv.ccnet_threaded_rpc.create_group('admin-group', + self.admin.email) + self.admin_group_id = admin_group_id + + # A user shares a folder to admin with permission 'rw'. + seafile_api.share_repo(sub_repo_id, self.user.username, + self.admin.username, 'rw') + + # A user shares a folder to admin group with permission 'rw'. + seafile_api.set_group_repo(sub_repo_id, admin_group_id, + self.user.username, 'rw') + + # A user shares a folder to public with permission 'rw'. + seafile_api.add_inner_pub_repo(sub_repo_id, 'rw') + + def test_can_delete_personal_shared_repo(self): + self._add_shared_items() + + resp = self.client.delete('/api2/beshared-repos/%s/?share_type=personal&from=%s' % ( + self.sub_repo_id, + self.user.email, + )) + self.assertEqual(200, resp.status_code) + json_resp = json.loads(resp.content) + assert json_resp['success'] is True + + def test_can_delete_group_repo(self): + self._add_shared_items() + + resp = self.client.delete('/api2/beshared-repos/%s/?share_type=group&from=%s&group_id=%d' % ( + self.sub_repo_id, + self.user.email, + self.admin_group_id, + )) + self.assertEqual(200, resp.status_code) + json_resp = json.loads(resp.content) + assert json_resp['success'] is True + + def test_can_delete_public_repo(self): + self._add_shared_items() + + resp = self.client.delete('/api2/beshared-repos/%s/?share_type=public' % ( + self.sub_repo_id, + )) + self.assertEqual(200, resp.status_code) + json_resp = json.loads(resp.content) + assert json_resp['success'] is True +