mirror of
https://github.com/haiwen/seahub.git
synced 2025-07-31 06:40:39 +00:00
Merge pull request #1024 from haiwen/file-shared-link
[api-v2.1] add file share links api
This commit is contained in:
commit
ce8ed1a4a3
245
seahub/api2/endpoints/share_links.py
Normal file
245
seahub/api2/endpoints/share_links.py
Normal file
@ -0,0 +1,245 @@
|
||||
import logging
|
||||
from constance import config
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
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 import timezone
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from seaserv import seafile_api
|
||||
from pysearpc import SearpcError
|
||||
|
||||
from seahub.api2.utils import api_error
|
||||
from seahub.api2.authentication import TokenAuthentication
|
||||
from seahub.api2.throttling import UserRateThrottle
|
||||
|
||||
from seahub.share.models import FileShare, OrgFileShare
|
||||
from seahub.utils import gen_shared_link, is_org_context
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ShareLinks(APIView):
|
||||
|
||||
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||
permission_classes = (IsAuthenticated,)
|
||||
throttle_classes = (UserRateThrottle, )
|
||||
|
||||
def _can_generate_shared_link(self, request):
|
||||
|
||||
return request.user.permissions.can_generate_shared_link()
|
||||
|
||||
def _generate_obj_id_and_type_by_path(self, repo_id, path):
|
||||
|
||||
file_id = seafile_api.get_file_id_by_path(repo_id, path)
|
||||
if file_id:
|
||||
return (file_id, 'f')
|
||||
|
||||
dir_id = seafile_api.get_dir_id_by_path(repo_id, path)
|
||||
if dir_id:
|
||||
return (dir_id, 'd')
|
||||
|
||||
return (None, None)
|
||||
|
||||
def _get_share_link_info(self, fileshare):
|
||||
data = {}
|
||||
token = fileshare.token
|
||||
|
||||
data['repo_id'] = fileshare.repo_id
|
||||
data['path'] = fileshare.path
|
||||
data['ctime'] = fileshare.ctime
|
||||
data['view_cnt'] = fileshare.view_cnt
|
||||
data['link'] = gen_shared_link(token, fileshare.s_type)
|
||||
data['token'] = token
|
||||
data['expire_date'] = fileshare.expire_date
|
||||
data['is_expired'] = fileshare.is_expired()
|
||||
data['username'] = fileshare.username
|
||||
|
||||
return data
|
||||
|
||||
def get(self, request):
|
||||
""" get share links.
|
||||
"""
|
||||
|
||||
if not self._can_generate_shared_link(request):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
# check if args invalid
|
||||
repo_id = request.GET.get('repo_id', None)
|
||||
if 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)
|
||||
|
||||
path = request.GET.get('path', None)
|
||||
if path:
|
||||
try:
|
||||
obj_id, s_type = self._generate_obj_id_and_type_by_path(repo_id, path)
|
||||
except SearpcError as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
if not obj_id:
|
||||
if s_type == 'f':
|
||||
error_msg = 'file %s not found.' % path
|
||||
elif s_type == 'd':
|
||||
error_msg = 'folder %s not found.' % path
|
||||
else:
|
||||
error_msg = 'path %s not found.' % path
|
||||
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
username = request.user.username
|
||||
fileshares = FileShare.objects.filter(username=username)
|
||||
|
||||
# filter result by args
|
||||
if repo_id:
|
||||
fileshares = filter(lambda fs: fs.repo_id == repo_id, fileshares)
|
||||
|
||||
if path:
|
||||
if s_type == 'd' and path[-1] != '/':
|
||||
path = path + '/'
|
||||
|
||||
fileshares = filter(lambda fs: fs.path == path, fileshares)
|
||||
|
||||
result = []
|
||||
for fs in fileshares:
|
||||
link_info = self._get_share_link_info(fs)
|
||||
result.append(link_info)
|
||||
|
||||
if len(result) == 1:
|
||||
result = result[0]
|
||||
|
||||
return Response(result)
|
||||
|
||||
def post(self, request):
|
||||
""" create share link.
|
||||
"""
|
||||
|
||||
if not self._can_generate_shared_link(request):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
repo_id = request.data.get('repo_id', None)
|
||||
if not repo_id:
|
||||
error_msg = 'repo_id invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
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)
|
||||
|
||||
path = request.data.get('path', None)
|
||||
if not path:
|
||||
error_msg = 'path invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
try:
|
||||
obj_id, s_type = self._generate_obj_id_and_type_by_path(repo_id, path)
|
||||
except SearpcError as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
if not obj_id:
|
||||
if s_type == 'f':
|
||||
error_msg = 'file %s not found.' % path
|
||||
elif s_type == 'd':
|
||||
error_msg = 'folder %s not found.' % path
|
||||
else:
|
||||
error_msg = 'path %s not found.' % path
|
||||
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
password = request.data.get('password', None)
|
||||
if password and len(password) < config.SHARE_LINK_PASSWORD_MIN_LENGTH:
|
||||
error_msg = _('Password is too short.')
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
try:
|
||||
expire_days = int(request.data.get('expire_days', 0))
|
||||
except ValueError:
|
||||
expire_days = 0
|
||||
|
||||
if expire_days <= 0:
|
||||
expire_date = None
|
||||
else:
|
||||
expire_date = timezone.now() + relativedelta(days=expire_days)
|
||||
|
||||
username = request.user.username
|
||||
if s_type == 'f':
|
||||
fs = FileShare.objects.get_file_link_by_path(username, repo_id, path)
|
||||
if not fs:
|
||||
fs = FileShare.objects.create_file_link(username, repo_id, path,
|
||||
password, expire_date)
|
||||
if is_org_context(request):
|
||||
org_id = request.user.org.org_id
|
||||
OrgFileShare.objects.set_org_file_share(org_id, fs)
|
||||
|
||||
elif s_type == 'd':
|
||||
fs = FileShare.objects.get_dir_link_by_path(username, repo_id, path)
|
||||
if not fs:
|
||||
fs = FileShare.objects.create_dir_link(username, repo_id, path,
|
||||
password, expire_date)
|
||||
if is_org_context(request):
|
||||
org_id = request.user.org.org_id
|
||||
OrgFileShare.objects.set_org_file_share(org_id, fs)
|
||||
|
||||
link_info = self._get_share_link_info(fs)
|
||||
return Response(link_info)
|
||||
|
||||
class ShareLink(APIView):
|
||||
|
||||
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||
permission_classes = (IsAuthenticated,)
|
||||
throttle_classes = (UserRateThrottle, )
|
||||
|
||||
def _can_generate_shared_link(self, request):
|
||||
|
||||
return request.user.permissions.can_generate_shared_link()
|
||||
|
||||
def get(self, request, token):
|
||||
try:
|
||||
fs = FileShare.objects.get(token=token)
|
||||
except FileShare.DoesNotExist:
|
||||
error_msg = 'token %s not found.' % token
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
link_info = self._get_share_link_info(fs)
|
||||
return Response(link_info)
|
||||
|
||||
def delete(self, request, token):
|
||||
""" delete share link.
|
||||
"""
|
||||
|
||||
if not self._can_generate_shared_link(request):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
try:
|
||||
fs = FileShare.objects.get(token=token)
|
||||
except FileShare.DoesNotExist:
|
||||
error_msg = 'token %s not found.' % token
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
username = request.user.username
|
||||
if not fs.is_owner(username):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
try:
|
||||
fs.delete()
|
||||
return Response({'success': True})
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
200
seahub/api2/endpoints/upload_links.py
Normal file
200
seahub/api2/endpoints/upload_links.py
Normal file
@ -0,0 +1,200 @@
|
||||
import logging
|
||||
from constance import config
|
||||
|
||||
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 seaserv import seafile_api
|
||||
from pysearpc import SearpcError
|
||||
|
||||
from seahub.api2.utils import api_error
|
||||
from seahub.api2.authentication import TokenAuthentication
|
||||
from seahub.api2.throttling import UserRateThrottle
|
||||
|
||||
from seahub.share.models import UploadLinkShare
|
||||
from seahub.utils import gen_shared_upload_link
|
||||
from seahub.views import check_folder_permission
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class UploadLinks(APIView):
|
||||
|
||||
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||
permission_classes = (IsAuthenticated,)
|
||||
throttle_classes = (UserRateThrottle, )
|
||||
|
||||
def _can_generate_shared_link(self, request):
|
||||
|
||||
return request.user.permissions.can_generate_shared_link()
|
||||
|
||||
def _get_upload_link_info(self, uls):
|
||||
data = {}
|
||||
token = uls.token
|
||||
|
||||
data['repo_id'] = uls.repo_id
|
||||
data['path'] = uls.path
|
||||
data['ctime'] = uls.ctime
|
||||
data['link'] = gen_shared_upload_link(token)
|
||||
data['token'] = token
|
||||
data['username'] = uls.username
|
||||
|
||||
return data
|
||||
|
||||
def get(self, request):
|
||||
""" get upload link.
|
||||
"""
|
||||
|
||||
if not self._can_generate_shared_link(request):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
repo_id = request.GET.get('repo_id', None)
|
||||
if 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)
|
||||
|
||||
path = request.GET.get('path', None)
|
||||
if path:
|
||||
try:
|
||||
dir_id = seafile_api.get_dir_id_by_path(repo_id, path)
|
||||
except SearpcError as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
if not dir_id:
|
||||
error_msg = 'folder %s not found.' % path
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
username = request.user.username
|
||||
upload_link_shares = UploadLinkShare.objects.filter(username=username)
|
||||
|
||||
# filter result by args
|
||||
if repo_id:
|
||||
upload_link_shares = filter(lambda ufs: ufs.repo_id == repo_id, upload_link_shares)
|
||||
|
||||
if path:
|
||||
if path[-1] != '/':
|
||||
path = path + '/'
|
||||
|
||||
upload_link_shares = filter(lambda ufs: ufs.path == path, upload_link_shares)
|
||||
|
||||
result = []
|
||||
for uls in upload_link_shares:
|
||||
link_info = self._get_upload_link_info(uls)
|
||||
result.append(link_info)
|
||||
|
||||
if len(result) == 1:
|
||||
result = result[0]
|
||||
|
||||
return Response(result)
|
||||
|
||||
def post(self, request):
|
||||
""" create upload link.
|
||||
"""
|
||||
|
||||
if not self._can_generate_shared_link(request):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
repo_id = request.data.get('repo_id', None)
|
||||
if not repo_id:
|
||||
error_msg = 'repo_id invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
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)
|
||||
|
||||
path = request.data.get('path', None)
|
||||
if not path:
|
||||
error_msg = 'path invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
try:
|
||||
dir_id = seafile_api.get_dir_id_by_path(repo_id, path)
|
||||
except SearpcError as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
if not dir_id:
|
||||
error_msg = 'folder %s not found.' % path
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
password = request.data.get('password', None)
|
||||
if password and len(password) < config.SHARE_LINK_PASSWORD_MIN_LENGTH:
|
||||
error_msg = _('Password is too short.')
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
user_perm = check_folder_permission(request, repo_id, '/')
|
||||
if user_perm != 'rw':
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
username = request.user.username
|
||||
uls = UploadLinkShare.objects.get_upload_link_by_path(username, repo_id, path)
|
||||
if not uls:
|
||||
uls = UploadLinkShare.objects.create_upload_link_share(username,
|
||||
repo_id, path, password)
|
||||
|
||||
link_info = self._get_upload_link_info(uls)
|
||||
return Response(link_info)
|
||||
|
||||
class UploadLink(APIView):
|
||||
|
||||
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||
permission_classes = (IsAuthenticated,)
|
||||
throttle_classes = (UserRateThrottle, )
|
||||
|
||||
def _can_generate_shared_link(self, request):
|
||||
|
||||
return request.user.permissions.can_generate_shared_link()
|
||||
|
||||
def get(self, request, token):
|
||||
""" get upload link info.
|
||||
"""
|
||||
|
||||
try:
|
||||
uls = UploadLinkShare.objects.get(token=token)
|
||||
except UploadLinkShare.DoesNotExist:
|
||||
error_msg = 'token %s not found.' % token
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
link_info = self._get_upload_link_info(uls)
|
||||
return Response(link_info)
|
||||
|
||||
def delete(self, request, token):
|
||||
""" delete upload link.
|
||||
"""
|
||||
|
||||
if not self._can_generate_shared_link(request):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
try:
|
||||
uls = UploadLinkShare.objects.get(token=token)
|
||||
except UploadLinkShare.DoesNotExist:
|
||||
error_msg = 'token %s not found.' % token
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
username = request.user.username
|
||||
if not uls.is_owner(username):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
try:
|
||||
uls.delete()
|
||||
return Response({'success': True})
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
@ -21,6 +21,8 @@ from seahub.views.sysadmin import *
|
||||
from seahub.views.ajax import *
|
||||
from seahub.api2.endpoints.groups import Groups, Group
|
||||
from seahub.api2.endpoints.group_members import GroupMembers, GroupMembersBulk, GroupMember
|
||||
from seahub.api2.endpoints.share_links import ShareLinks, ShareLink
|
||||
from seahub.api2.endpoints.upload_links import UploadLinks, UploadLink
|
||||
|
||||
# Uncomment the next two lines to enable the admin:
|
||||
#from django.contrib import admin
|
||||
@ -195,6 +197,11 @@ urlpatterns = patterns(
|
||||
url(r'^api/v2.1/groups/(?P<group_id>\d+)/members/$', GroupMembers.as_view(), name='api-v2.1-group-members'),
|
||||
url(r'^api/v2.1/groups/(?P<group_id>\d+)/members/bulk/$', GroupMembersBulk.as_view(), name='api-v2.1-group-members-bulk'),
|
||||
url(r'^api/v2.1/groups/(?P<group_id>\d+)/members/(?P<email>[^/]+)/$', GroupMember.as_view(), name='api-v2.1-group-member'),
|
||||
url(r'^api/v2.1/share-links/$', ShareLinks.as_view(), name='api-v2.1-share-links'),
|
||||
url(r'^api/v2.1/share-link/(?P<token>[a-f0-9]{10})/$', ShareLink.as_view(), name='api-v2.1-share-link'),
|
||||
url(r'^api/v2.1/upload-links/$', UploadLinks.as_view(), name='api-v2.1-upload-links'),
|
||||
url(r'^api/v2.1/upload-link/(?P<token>[a-f0-9]{10})/$', UploadLink.as_view(), name='api-v2.1-upload-link'),
|
||||
|
||||
(r'^avatar/', include('seahub.avatar.urls')),
|
||||
(r'^notification/', include('seahub.notifications.urls')),
|
||||
(r'^contacts/', include('seahub.contacts.urls')),
|
||||
|
156
tests/api/endpoints/test_share_links.py
Normal file
156
tests/api/endpoints/test_share_links.py
Normal file
@ -0,0 +1,156 @@
|
||||
# -*- 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
|
||||
from seahub.api2.endpoints.share_links import ShareLinks, ShareLink
|
||||
|
||||
class ShareLinksTest(BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.repo_id = self.repo.id
|
||||
self.file_path= self.file
|
||||
self.folder_path= self.folder
|
||||
self.url = reverse('api-v2.1-share-links')
|
||||
|
||||
def tearDown(self):
|
||||
self.remove_repo()
|
||||
|
||||
def _add_file_share_link(self):
|
||||
fs = FileShare.objects.create_file_link(self.user.username,
|
||||
self.repo.id, self.file, None, None)
|
||||
|
||||
return fs.token
|
||||
|
||||
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 _remove_share_link(self, token):
|
||||
link = FileShare.objects.get(token=token)
|
||||
link.delete()
|
||||
|
||||
# test file share link
|
||||
def test_get_file_share_link(self):
|
||||
self.login_as(self.user)
|
||||
token = self._add_file_share_link()
|
||||
|
||||
resp = self.client.get(self.url + '?path=' + self.file_path + '&repo_id=' + self.repo_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
json_resp = json.loads(resp.content)
|
||||
|
||||
assert json_resp['link'] is not None
|
||||
assert json_resp['token'] is not None
|
||||
assert json_resp['is_expired'] is not None
|
||||
|
||||
assert token in json_resp['link']
|
||||
assert 'f' in json_resp['link']
|
||||
|
||||
assert token == json_resp['token']
|
||||
|
||||
self._remove_share_link(token)
|
||||
|
||||
def test_create_file_share_link(self):
|
||||
self.login_as(self.user)
|
||||
|
||||
resp = self.client.post(self.url, {'path': self.file_path, 'repo_id': self.repo_id})
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
json_resp = json.loads(resp.content)
|
||||
assert json_resp['link'] is not None
|
||||
assert json_resp['token'] is not None
|
||||
assert json_resp['is_expired'] is not None
|
||||
|
||||
assert json_resp['token'] in json_resp['link']
|
||||
assert 'f' in json_resp['link']
|
||||
|
||||
self._remove_share_link(json_resp['token'])
|
||||
|
||||
def test_delete_file_share_link(self):
|
||||
self.login_as(self.user)
|
||||
token = self._add_file_share_link()
|
||||
|
||||
url = reverse('api-v2.1-share-link', args=[token])
|
||||
resp = self.client.delete(url, {}, 'application/x-www-form-urlencoded')
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
json_resp = json.loads(resp.content)
|
||||
assert json_resp['success'] is True
|
||||
|
||||
# test dir share link
|
||||
def test_get_dir_share_link(self):
|
||||
self.login_as(self.user)
|
||||
token = self._add_dir_share_link()
|
||||
|
||||
resp = self.client.get(self.url + '?path=' + self.folder_path + '&repo_id=' + self.repo_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
json_resp = json.loads(resp.content)
|
||||
|
||||
assert json_resp['link'] is not None
|
||||
assert json_resp['token'] is not None
|
||||
assert json_resp['is_expired'] is not None
|
||||
|
||||
assert token in json_resp['link']
|
||||
assert 'd' in json_resp['link']
|
||||
|
||||
assert token == json_resp['token']
|
||||
|
||||
self._remove_share_link(token)
|
||||
|
||||
def test_create_dir_share_link(self):
|
||||
self.login_as(self.user)
|
||||
|
||||
resp = self.client.post(self.url, {'path': self.folder_path, 'repo_id': self.repo_id})
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
json_resp = json.loads(resp.content)
|
||||
assert json_resp['link'] is not None
|
||||
assert json_resp['token'] is not None
|
||||
assert json_resp['is_expired'] is not None
|
||||
|
||||
assert json_resp['token'] in json_resp['link']
|
||||
assert 'd' in json_resp['link']
|
||||
|
||||
self._remove_share_link(json_resp['token'])
|
||||
|
||||
def test_delete_dir_share_link(self):
|
||||
self.login_as(self.user)
|
||||
token = self._add_file_share_link()
|
||||
url = reverse('api-v2.1-share-link', args=[token])
|
||||
resp = self.client.delete(url, {}, 'application/x-www-form-urlencoded')
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
json_resp = json.loads(resp.content)
|
||||
assert json_resp['success'] is True
|
||||
|
||||
# test permission
|
||||
def test_can_not_delete_link_if_not_owner(self):
|
||||
self.login_as(self.admin)
|
||||
token = self._add_file_share_link()
|
||||
url = reverse('api-v2.1-share-link', args=[token])
|
||||
resp = self.client.delete(url, {}, 'application/x-www-form-urlencoded')
|
||||
self.assertEqual(403, resp.status_code)
|
||||
|
||||
@patch.object(ShareLinks, '_can_generate_shared_link')
|
||||
def test_can_not_get_and_create_link_with_invalid_permission(self, mock_can_generate_shared_link):
|
||||
self.login_as(self.user)
|
||||
mock_can_generate_shared_link.return_value = False
|
||||
|
||||
resp = self.client.get(self.url)
|
||||
self.assertEqual(403, resp.status_code)
|
||||
|
||||
resp = self.client.post(self.url)
|
||||
self.assertEqual(403, resp.status_code)
|
||||
|
||||
@patch.object(ShareLink, '_can_generate_shared_link')
|
||||
def test_can_not_delete_link_with_invalid_permission(self, mock_can_generate_shared_link):
|
||||
token = self._add_file_share_link()
|
||||
url = reverse('api-v2.1-share-link', args=[token])
|
||||
resp = self.client.delete(url, {}, 'application/x-www-form-urlencoded')
|
||||
self.assertEqual(403, resp.status_code)
|
100
tests/api/endpoints/test_upload_links.py
Normal file
100
tests/api/endpoints/test_upload_links.py
Normal file
@ -0,0 +1,100 @@
|
||||
# -*- 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 UploadLinkShare
|
||||
from seahub.api2.endpoints.upload_links import UploadLinks, UploadLink
|
||||
|
||||
class UploadLinksTest(BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.repo_id = self.repo.id
|
||||
self.folder_path= self.folder
|
||||
self.url = reverse('api-v2.1-upload-links')
|
||||
|
||||
def tearDown(self):
|
||||
self.remove_repo()
|
||||
|
||||
def _add_upload_link(self):
|
||||
upload_link = UploadLinkShare.objects.create_upload_link_share(self.user.username,
|
||||
self.repo.id, self.folder, None, None)
|
||||
|
||||
return upload_link.token
|
||||
|
||||
def _remove_upload_link(self, token):
|
||||
link = UploadLinkShare.objects.get(token=token)
|
||||
link.delete()
|
||||
|
||||
def test_get_upload_link(self):
|
||||
self.login_as(self.user)
|
||||
token = self._add_upload_link()
|
||||
|
||||
resp = self.client.get(self.url + '?path=' + self.folder_path + '&repo_id=' + self.repo_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
json_resp = json.loads(resp.content)
|
||||
|
||||
assert json_resp['link'] is not None
|
||||
assert json_resp['token'] is not None
|
||||
|
||||
assert token in json_resp['link']
|
||||
assert 'u/d' in json_resp['link']
|
||||
|
||||
assert token == json_resp['token']
|
||||
|
||||
self._remove_upload_link(token)
|
||||
|
||||
def test_create_upload_link(self):
|
||||
self.login_as(self.user)
|
||||
|
||||
resp = self.client.post(self.url, {'path': self.folder_path, 'repo_id': self.repo_id})
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
json_resp = json.loads(resp.content)
|
||||
assert json_resp['link'] is not None
|
||||
assert json_resp['token'] is not None
|
||||
|
||||
assert json_resp['token'] in json_resp['link']
|
||||
assert 'u/d' in json_resp['link']
|
||||
|
||||
self._remove_upload_link(json_resp['token'])
|
||||
|
||||
def test_delete_upload_link(self):
|
||||
self.login_as(self.user)
|
||||
token = self._add_upload_link()
|
||||
|
||||
url = reverse('api-v2.1-upload-link', args=[token])
|
||||
resp = self.client.delete(url, {}, 'application/x-www-form-urlencoded')
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
json_resp = json.loads(resp.content)
|
||||
assert json_resp['success'] is True
|
||||
|
||||
# test permission
|
||||
def test_can_not_delete_link_if_not_owner(self):
|
||||
self.login_as(self.admin)
|
||||
token = self._add_upload_link()
|
||||
|
||||
url = reverse('api-v2.1-upload-link', args=[token])
|
||||
resp = self.client.delete(url, {}, 'application/x-www-form-urlencoded')
|
||||
self.assertEqual(403, resp.status_code)
|
||||
|
||||
@patch.object(UploadLinks, '_can_generate_shared_link')
|
||||
def test_can_not_get_and_create_link_with_invalid_permission(self, mock_can_generate_shared_link):
|
||||
self.login_as(self.user)
|
||||
mock_can_generate_shared_link.return_value = False
|
||||
|
||||
resp = self.client.get(self.url)
|
||||
self.assertEqual(403, resp.status_code)
|
||||
|
||||
resp = self.client.post(self.url)
|
||||
self.assertEqual(403, resp.status_code)
|
||||
|
||||
@patch.object(UploadLink, '_can_generate_shared_link')
|
||||
def test_can_not_delete_link_with_invalid_permission(self, mock_can_generate_shared_link):
|
||||
token = self._add_upload_link()
|
||||
url = reverse('api-v2.1-upload-link', args=[token])
|
||||
resp = self.client.delete(url, {}, 'application/x-www-form-urlencoded')
|
||||
self.assertEqual(403, resp.status_code)
|
Loading…
Reference in New Issue
Block a user