1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-14 21:23:50 +00:00

Merge pull request #2003 from haiwen/share-link-upload

add api for upload file via upload link foken
This commit is contained in:
xiez 2018-02-08 14:37:51 +08:00 committed by GitHub
commit 35b7d76c82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 146 additions and 41 deletions

View File

@ -94,7 +94,7 @@ class AdminUploadLinkUpload(APIView):
throttle_classes = (UserRateThrottle,) throttle_classes = (UserRateThrottle,)
def get(self, request, token): def get(self, request, token):
""" Get FileServer url of the shared file. """ Get FileServer url of the shared folder.
Permission checking: Permission checking:
1. only admin can perform this action. 1. only admin can perform this action.

View File

@ -16,56 +16,57 @@ from pysearpc import SearpcError
from seahub.api2.utils import api_error from seahub.api2.utils import api_error
from seahub.api2.authentication import TokenAuthentication from seahub.api2.authentication import TokenAuthentication
from seahub.api2.throttling import UserRateThrottle from seahub.api2.throttling import AnonRateThrottle, UserRateThrottle
from seahub.api2.permissions import CanGenerateUploadLink from seahub.api2.permissions import CanGenerateUploadLink
from seahub.share.models import UploadLinkShare from seahub.share.models import UploadLinkShare
from seahub.utils import gen_shared_upload_link from seahub.utils import gen_shared_upload_link, gen_file_upload_url
from seahub.views import check_folder_permission from seahub.views import check_folder_permission
from seahub.utils.timeutils import datetime_to_isoformat_timestr from seahub.utils.timeutils import datetime_to_isoformat_timestr
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def get_upload_link_info(uls):
data = {}
token = uls.token
repo_id = uls.repo_id
try:
repo = seafile_api.get_repo(repo_id)
except Exception as e:
logger.error(e)
repo = None
path = uls.path
if path:
obj_name = '/' if path == '/' else os.path.basename(path.rstrip('/'))
else:
obj_name = ''
if uls.ctime:
ctime = datetime_to_isoformat_timestr(uls.ctime)
else:
ctime = ''
data['repo_id'] = repo_id
data['repo_name'] = repo.repo_name if repo else ''
data['path'] = path
data['obj_name'] = obj_name
data['view_cnt'] = uls.view_cnt
data['ctime'] = ctime
data['link'] = gen_shared_upload_link(token)
data['token'] = token
data['username'] = uls.username
return data
class UploadLinks(APIView): class UploadLinks(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication) authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated, CanGenerateUploadLink) permission_classes = (IsAuthenticated, CanGenerateUploadLink)
throttle_classes = (UserRateThrottle, ) throttle_classes = (UserRateThrottle, )
def _get_upload_link_info(self, uls):
data = {}
token = uls.token
repo_id = uls.repo_id
try:
repo = seafile_api.get_repo(repo_id)
except Exception as e:
logger.error(e)
repo = None
path = uls.path
if path:
obj_name = '/' if path == '/' else os.path.basename(path.rstrip('/'))
else:
obj_name = ''
if uls.ctime:
ctime = datetime_to_isoformat_timestr(uls.ctime)
else:
ctime = ''
data['repo_id'] = repo_id
data['repo_name'] = repo.repo_name if repo else ''
data['path'] = path
data['obj_name'] = obj_name
data['view_cnt'] = uls.view_cnt
data['ctime'] = ctime
data['link'] = gen_shared_upload_link(token)
data['token'] = token
data['username'] = uls.username
return data
def get(self, request): def get(self, request):
""" Get all upload links of a user. """ Get all upload links of a user.
@ -108,7 +109,7 @@ class UploadLinks(APIView):
result = [] result = []
for uls in upload_link_shares: for uls in upload_link_shares:
link_info = self._get_upload_link_info(uls) link_info = get_upload_link_info(uls)
result.append(link_info) result.append(link_info)
if len(result) == 1: if len(result) == 1:
@ -169,7 +170,7 @@ class UploadLinks(APIView):
uls = UploadLinkShare.objects.create_upload_link_share(username, uls = UploadLinkShare.objects.create_upload_link_share(username,
repo_id, path, password) repo_id, path, password)
link_info = self._get_upload_link_info(uls) link_info = get_upload_link_info(uls)
return Response(link_info) return Response(link_info)
class UploadLink(APIView): class UploadLink(APIView):
@ -191,7 +192,7 @@ class UploadLink(APIView):
error_msg = 'token %s not found.' % token error_msg = 'token %s not found.' % token
return api_error(status.HTTP_404_NOT_FOUND, error_msg) return api_error(status.HTTP_404_NOT_FOUND, error_msg)
link_info = self._get_upload_link_info(uls) link_info = get_upload_link_info(uls)
return Response(link_info) return Response(link_info)
def delete(self, request, token): def delete(self, request, token):
@ -220,3 +221,49 @@ class UploadLink(APIView):
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True}) return Response({'success': True})
class UploadLinkUpload(APIView):
throttle_classes = (AnonRateThrottle, )
def get(self, request, token):
""" Get file upload url according to upload link token.
Permission checking:
1. anyone has the upload link token can perform this action;
"""
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)
# currently not support encrypted upload link
if uls.is_encrypted():
error_msg = 'Upload link %s is encrypted.' % token
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
repo_id = uls.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 = uls.path
dir_id = seafile_api.get_dir_id_by_path(repo_id, path)
if not dir_id:
error_msg = 'Folder %s not found.' % path
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
token = seafile_api.get_fileserver_access_token(repo_id,
dir_id, 'upload', uls.username, use_onetime=False)
if not token:
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
result = {}
result['upload_link'] = gen_file_upload_url(token, 'upload-api')
return Response(result)

View File

@ -27,7 +27,8 @@ from seahub.api2.endpoints.search_group import SearchGroup
from seahub.api2.endpoints.share_links import ShareLinks, ShareLink from seahub.api2.endpoints.share_links import ShareLinks, ShareLink
from seahub.api2.endpoints.shared_folders import SharedFolders from seahub.api2.endpoints.shared_folders import SharedFolders
from seahub.api2.endpoints.shared_repos import SharedRepos, SharedRepo from seahub.api2.endpoints.shared_repos import SharedRepos, SharedRepo
from seahub.api2.endpoints.upload_links import UploadLinks, UploadLink from seahub.api2.endpoints.upload_links import UploadLinks, UploadLink, \
UploadLinkUpload
from seahub.api2.endpoints.repos_batch import ReposBatchView, \ from seahub.api2.endpoints.repos_batch import ReposBatchView, \
ReposBatchCopyDirView, ReposBatchCreateDirView ReposBatchCopyDirView, ReposBatchCreateDirView
from seahub.api2.endpoints.repos import RepoView from seahub.api2.endpoints.repos import RepoView
@ -237,6 +238,7 @@ urlpatterns = patterns(
## user::shared-upload-links ## user::shared-upload-links
url(r'^api/v2.1/upload-links/$', UploadLinks.as_view(), name='api-v2.1-upload-links'), url(r'^api/v2.1/upload-links/$', UploadLinks.as_view(), name='api-v2.1-upload-links'),
url(r'^api/v2.1/upload-links/(?P<token>[a-f0-9]+)/$', UploadLink.as_view(), name='api-v2.1-upload-link'), url(r'^api/v2.1/upload-links/(?P<token>[a-f0-9]+)/$', UploadLink.as_view(), name='api-v2.1-upload-link'),
url(r'^api/v2.1/upload-links/(?P<token>[a-f0-9]+)/upload/$', UploadLinkUpload.as_view(), name='api-v2.1-upload-link-upload'),
## user::revision-tags ## user::revision-tags
url(r'^api/v2.1/revision-tags/tagged-items/$', TaggedItemsView.as_view(), name='api-v2.1-revision-tags-tagged-items'), url(r'^api/v2.1/revision-tags/tagged-items/$', TaggedItemsView.as_view(), name='api-v2.1-revision-tags-tagged-items'),

View File

@ -3,6 +3,9 @@ import json
from mock import patch from mock import patch
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from tests.common.utils import upload_file_test, randstring
from seahub.test_utils import BaseTestCase from seahub.test_utils import BaseTestCase
from seahub.share.models import UploadLinkShare from seahub.share.models import UploadLinkShare
from seahub.api2.permissions import CanGenerateUploadLink from seahub.api2.permissions import CanGenerateUploadLink
@ -163,3 +166,56 @@ class UploadLinksTest(BaseTestCase):
url = reverse('api-v2.1-upload-link', args=[token]) url = reverse('api-v2.1-upload-link', args=[token])
resp = self.client.delete(url, {}, 'application/x-www-form-urlencoded') resp = self.client.delete(url, {}, 'application/x-www-form-urlencoded')
self.assertEqual(403, resp.status_code) self.assertEqual(403, resp.status_code)
class UploadLinkUploadTest(BaseTestCase):
def setUp(self):
self.repo_id = self.repo.id
self.folder_path= self.folder
self.invalid_token = '00000000000000000000'
def _add_upload_link(self, password=None):
fs = UploadLinkShare.objects.create_upload_link_share(
self.user.username, self.repo.id, self.folder_path, password, None)
return fs.token
def _remove_upload_link(self, token):
link = UploadLinkShare.objects.get(token=token)
link.delete()
def test_get_upload_link(self):
token = self._add_upload_link()
url = reverse('api-v2.1-upload-link-upload', args=[token])
resp = self.client.get(url)
self.assertEqual(200, resp.status_code)
json_resp = json.loads(resp.content)
assert '8082' in json_resp['upload_link']
assert 'upload' in json_resp['upload_link']
# test upload file via `upload_link`
upload_file_test(json_resp['upload_link'])
self._remove_upload_link(token)
def test_can_not_get_upload_link_with_invalid_token(self):
url = reverse('api-v2.1-upload-link-upload',
args=[self.invalid_token])
resp = self.client.get(url)
self.assertEqual(404, resp.status_code)
def test_can_not_get_upload_link_for_encrypted_upload_link_share(self):
token = self._add_upload_link(password=randstring(10))
url = reverse('api-v2.1-upload-link-upload', args=[token])
resp = self.client.get(url)
self.assertEqual(403, resp.status_code)