diff --git a/api2/permissions.py b/api2/permissions.py index bd3ee61392..c0cc2d1da2 100644 --- a/api2/permissions.py +++ b/api2/permissions.py @@ -10,7 +10,7 @@ SAFE_METHODS = ['GET', 'HEAD', 'OPTIONS'] class IsRepoWritable(BasePermission): """ - Allows access only for users who has write permission to the repo. + Allows access only for user who has write permission to the repo. """ def has_permission(self, request, view, obj=None): @@ -23,3 +23,14 @@ class IsRepoWritable(BasePermission): if user and check_permission(repo_id, user) == 'rw': return True return False + +class IsRepoAccessible(BasePermission): + """ + Check whether user has Read or Write permission to a repo. + """ + def has_permission(self, request, view, obj=None): + repo_id = view.kwargs.get('repo_id', '') + user = request.user.username if request.user else '' + + return True if check_permission(repo_id, user) else False + diff --git a/api2/urls.py b/api2/urls.py index 9e15f75dc7..2585e8ae4a 100644 --- a/api2/urls.py +++ b/api2/urls.py @@ -25,6 +25,7 @@ urlpatterns = patterns('', url(r'^repos/$', Repos.as_view()), url(r'^repos/(?P[-0-9a-f]{36})/$', Repo.as_view()), url(r'^repos/(?P[-0-9a-f]{36})/download-info/$', DownloadRepo.as_view()), + url(r'^repos/(?P[-0-9a-f]{36})/upload-link/$', UploadLinkView.as_view()), url(r'^repos/(?P[-0-9-a-f]{36})/file/$', FileView.as_view(), name='FileView'), url(r'^repos/(?P[-0-9-a-f]{36})/file/shared-link/$', FileSharedLinkView.as_view()), url(r'^repos/(?P[-0-9-a-f]{36})/dir/$', DirView.as_view(), name='DirView'), diff --git a/api2/views.py b/api2/views.py index bf54d224d2..0df1930cbc 100644 --- a/api2/views.py +++ b/api2/views.py @@ -17,7 +17,7 @@ from django.http import HttpResponse from models import Token from authentication import TokenAuthentication -from permissions import IsRepoWritable +from permissions import IsRepoWritable, IsRepoAccessible from serializers import AuthTokenSerializer from base.accounts import User from share.models import FileShare @@ -99,7 +99,6 @@ class Account(APIView): info['email'] = email info['usage'] = seafserv_threaded_rpc.get_user_quota_usage(email) info['total'] = seafserv_threaded_rpc.get_user_quota(email) - info['feedback'] = settings.DEFAULT_FROM_EMAIL return Response(info) def calculate_repo_info(repo_list, username): @@ -193,9 +192,6 @@ def can_access_repo(request, repo_id): return True def check_repo_access_permission(request, repo): - if not repo: - return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') - if not can_access_repo(request, repo.id): return api_error(status.HTTP_403_FORBIDDEN, 'Forbid to access this repo.') @@ -219,22 +215,14 @@ def check_repo_access_permission(request, repo): class Repo(APIView): authentication_classes = (TokenAuthentication, ) - permission_classes = (IsAuthenticated,) - - def head(self, request, repo_id, format=None): - # TODO - assert False + permission_classes = (IsAuthenticated, IsRepoAccessible, ) def get(self, request, repo_id, format=None): - # check whether user can view repo repo = get_repo(repo_id) if not repo: return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') - # if not can_access_repo(request, repo.id): - # return api_error('403') - - # check whether use is repo owner + # check whether user is repo owner if validate_owner(request, repo_id): owner = "self" else: @@ -263,7 +251,11 @@ class Repo(APIView): return Response(repo_json) def post(self, request, repo_id, format=None): - resp = check_repo_access_permission(request, get_repo(repo_id)) + repo = get_repo(repo_id) + if not repo: + return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') + + resp = check_repo_access_permission(request, repo) if resp: return resp op = request.GET.get('op', 'setpassword') @@ -274,22 +266,20 @@ class Repo(APIView): class DownloadRepo(APIView): authentication_classes = (TokenAuthentication, ) - permission_classes = (IsAuthenticated,) + permission_classes = (IsAuthenticated, IsRepoAccessible, ) def get(self, request, repo_id, format=None): repo = get_repo(repo_id) if not repo: return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') - # TODO: check whether user can access this repo - # generate download url for client ccnet_applet_root = get_ccnetapplet_root() relay_id = get_session_info().id addr, port = get_ccnet_server_addr_port () - email = quote(request.user.username) + email = request.user.username token = get_repo_token_nonnull(repo_id, request.user.username) - quote_repo_name = quote(repo.name.encode('utf-8')) + repo_name = repo.name enc = 1 if repo.encrypted else '' info_json = { @@ -300,10 +290,30 @@ class DownloadRepo(APIView): 'email': email, 'token': token, 'repo_id': repo_id, - 'repo_name': quote_repo_name, + 'repo_name': repo_name, 'encrypted': enc, } return Response(info_json) + +class UploadLinkView(APIView): + authentication_classes = (TokenAuthentication, ) + permission_classes = (IsAuthenticated, ) + + def get(self, request, repo_id, format=None): + repo = get_repo(repo_id) + if check_permission(repo_id, request.user.username) == 'rw': + token = seafserv_rpc.web_get_access_token(repo_id, + 'dummy', + 'upload', + request.user.username) + else: + return api_error(status.HTTP_403_FORBIDDEN, "Can not access repo") + + if request.cloud_mode and seafserv_threaded_rpc.check_quota(repo_id) < 0: + return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Above quota') + + upload_url = gen_file_upload_url(token, 'upload') + return Response(upload_url) def get_file_size (id): size = seafserv_threaded_rpc.get_file_size(id) @@ -348,6 +358,9 @@ class RepoDirents(APIView): def get(self, request, repo_id): repo = get_repo(repo_id) + if not repo: + return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') + resp = check_repo_access_permission(request, repo) if resp: return resp @@ -391,6 +404,9 @@ class RepoDirs(APIView): def get(self, request, repo_id, dir_id, format=None): repo = get_repo(repo_id) + if not repo: + return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') + resp = check_repo_access_permission(request, repo) if resp: return resp @@ -449,6 +465,9 @@ class RepoFilepath(APIView): def get(self, request, repo_id, format=None): repo = get_repo(repo_id) + if not repo: + return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') + resp = check_repo_access_permission(request, repo) if resp: return resp @@ -474,6 +493,9 @@ class RepoFilepath(APIView): def post(self, request, repo_id, format=None): repo = get_repo(repo_id) + if not repo: + return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') + resp = check_repo_access_permission(request, repo) if resp: return resp @@ -501,6 +523,9 @@ class RepoFiles(APIView): def get(self, request, repo_id, file_id, format=None): repo = get_repo(repo_id) + if not repo: + return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') + resp = check_repo_access_permission(request, repo) if resp: return resp @@ -545,7 +570,11 @@ class OpDeleteView(APIView): permission_classes = (IsAuthenticated, IsRepoWritable, ) def post(self, request, repo_id, format=None): - resp = check_repo_access_permission(request, get_repo(repo_id)) + repo = get_repo(repo_id) + if not repo: + return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') + + resp = check_repo_access_permission(request, repo) if resp: return resp @@ -577,7 +606,11 @@ class OpRenameView(APIView): permission_classes = (IsAuthenticated, IsRepoWritable, ) def post(self, request, repo_id, format=None): - resp = check_repo_access_permission(request, get_repo(repo_id)) + repo = get_repo(repo_id) + if not repo: + return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') + + resp = check_repo_access_permission(request, repo) if resp: return resp @@ -668,7 +701,11 @@ class OpMkdirView(APIView): permission_classes = (IsAuthenticated, IsRepoWritable, ) def post(self, request, repo_id, format=None): - resp = check_repo_access_permission(request, get_repo(repo_id)) + repo = get_repo(repo_id) + if not repo: + return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') + + resp = check_repo_access_permission(request, repo) if resp: return resp path = request.GET.get('p') @@ -788,6 +825,9 @@ class FileView(APIView): def get(self, request, repo_id, format=None): # view file repo = get_repo(repo_id) + if not repo: + return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') + resp = check_repo_access_permission(request, repo) if resp: return resp @@ -813,7 +853,11 @@ class FileView(APIView): def post(self, request, repo_id, format=None): # rename or move file - resp = check_repo_access_permission(request, get_repo(repo_id)) + repo = get_repo(repo_id) + if not repo: + return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') + + resp = check_repo_access_permission(request, repo) if resp: return resp @@ -918,6 +962,9 @@ class FileView(APIView): def delete(self, request, repo_id, format=None): # delete file repo = get_repo(repo_id) + if not repo: + return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') + resp = check_repo_access_permission(request, repo) if resp: return resp @@ -993,6 +1040,9 @@ class DirView(APIView): def get(self, request, repo_id, format=None): # list dir repo = get_repo(repo_id) + if not repo: + return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') + resp = check_repo_access_permission(request, repo) if resp: return resp @@ -1022,7 +1072,11 @@ class DirView(APIView): def post(self, request, repo_id, format=None): # new dir - resp = check_repo_access_permission(request, get_repo(repo_id)) + repo = get_repo(repo_id) + if not repo: + return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') + + resp = check_repo_access_permission(request, repo) if resp: return resp path = request.GET.get('p', '') @@ -1071,6 +1125,9 @@ class DirView(APIView): def delete(self, request, repo_id, format=None): # delete dir or file repo = get_repo(repo_id) + if not repo: + return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') + resp = check_repo_access_permission(request, repo) if resp: return resp diff --git a/share/views.py b/share/views.py index 20b2a49c92..d26b882c25 100644 --- a/share/views.py +++ b/share/views.py @@ -108,15 +108,6 @@ def share_repo(request): mail_sended.send(sender=None, user=request.user.username, email=to_email) - # Record share info to db. - try: - seafserv_threaded_rpc.add_share(repo_id, from_email, to_email, - permission) - except SearpcError, e: - msg = _(u'Failed to share to %s .') % to_email - messages.add_message(request, messages.ERROR, msg) - continue - if not is_registered_user(to_email): # Generate shared link and send mail if user has not registered. # kwargs = {'repo_id': repo_id, @@ -129,6 +120,15 @@ def share_repo(request): messages.add_message(request, messages.ERROR, msg) continue else: + # Record share info to db. + try: + seafserv_threaded_rpc.add_share(repo_id, from_email, to_email, + permission) + except SearpcError, e: + msg = _(u'Failed to share to %s .') % to_email + messages.add_message(request, messages.ERROR, msg) + continue + msg = _(u'Shared to %(email)s successfully,go check it at Share.') % \ {'email':to_email, 'share':reverse('share_admin')} messages.add_message(request, messages.INFO, msg) diff --git a/thirdpart/seaserv/service.py b/thirdpart/seaserv/service.py index 1781b98cb0..431f58aebd 100644 --- a/thirdpart/seaserv/service.py +++ b/thirdpart/seaserv/service.py @@ -558,9 +558,7 @@ def list_inner_pub_repos(username): shared_repos = [] for repo in shared_repos: - perm = seafserv_threaded_rpc.check_permission(repo.props.repo_id, - username) - repo.user_perm = perm + repo.user_perm = check_permission(repo.props.repo_id, username) shared_repos.sort(lambda x, y: cmp(y.props.last_modified, x.props.last_modified)) return shared_repos @@ -588,9 +586,7 @@ def list_org_inner_pub_repos(org_id, username, start=None, limit=None): shared_repos = [] for repo in shared_repos: - perm = seafserv_threaded_rpc.check_permission(repo.props.repo_id, - username) - repo.user_perm = perm + repo.user_perm = check_permission(repo.props.repo_id, username) # sort repos by last modify time shared_repos.sort(lambda x, y: cmp(y.props.last_modified, x.props.last_modified)) @@ -600,12 +596,12 @@ def list_org_inner_pub_repos(org_id, username, start=None, limit=None): def check_permission(repo_id, user): """ Check whether user has permission to access repo. - Return true if user has permission otherwise false. + Return values can be 'rw' or 'r' or None. """ try: ret = seafserv_threaded_rpc.check_permission(repo_id, user) except SearpcError: - ret = "" + ret = None return ret def is_personal_repo(repo_id):