mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-15 14:49:09 +00:00
[api2] Clarify 403 error message
This commit is contained in:
30
seahub/api2/utils.py
Normal file
30
seahub/api2/utils.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# Utility functions for api2
|
||||||
|
|
||||||
|
from seaserv import seafile_api
|
||||||
|
|
||||||
|
def is_repo_writable(repo_id, username):
|
||||||
|
"""Check whether a user has write permission to a repo.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
- `repo_id`:
|
||||||
|
- `username`:
|
||||||
|
"""
|
||||||
|
if seafile_api.check_repo_access_permission(repo_id, username) == 'rw':
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def is_repo_accessible(repo_id, username):
|
||||||
|
"""Check whether a user can read or write to a repo.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
- `repo_id`:
|
||||||
|
- `username`:
|
||||||
|
"""
|
||||||
|
if seafile_api.check_repo_access_permission(repo_id, username) is None:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
@@ -19,8 +19,8 @@ from django.http import HttpResponse
|
|||||||
|
|
||||||
from models import Token
|
from models import Token
|
||||||
from authentication import TokenAuthentication
|
from authentication import TokenAuthentication
|
||||||
from permissions import IsRepoWritable, IsRepoAccessible, IsRepoOwner
|
|
||||||
from serializers import AuthTokenSerializer
|
from serializers import AuthTokenSerializer
|
||||||
|
from utils import is_repo_writable, is_repo_accessible
|
||||||
from seahub.base.accounts import User
|
from seahub.base.accounts import User
|
||||||
from seahub.base.models import FileDiscuss, UserStarredFiles
|
from seahub.base.models import FileDiscuss, UserStarredFiles
|
||||||
from seahub.share.models import FileShare
|
from seahub.share.models import FileShare
|
||||||
@@ -340,7 +340,7 @@ def check_repo_access_permission(request, repo):
|
|||||||
|
|
||||||
class Repo(APIView):
|
class Repo(APIView):
|
||||||
authentication_classes = (TokenAuthentication, )
|
authentication_classes = (TokenAuthentication, )
|
||||||
permission_classes = (IsAuthenticated, IsRepoAccessible, )
|
permission_classes = (IsAuthenticated, )
|
||||||
throttle_classes = (UserRateThrottle, )
|
throttle_classes = (UserRateThrottle, )
|
||||||
|
|
||||||
def get(self, request, repo_id, format=None):
|
def get(self, request, repo_id, format=None):
|
||||||
@@ -348,6 +348,11 @@ class Repo(APIView):
|
|||||||
if not repo:
|
if not repo:
|
||||||
return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.')
|
return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.')
|
||||||
|
|
||||||
|
username = request.user.username
|
||||||
|
if not is_repo_accessible(repo.id, username):
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN,
|
||||||
|
'You do not have permission to get repo.')
|
||||||
|
|
||||||
# check whether user is repo owner
|
# check whether user is repo owner
|
||||||
if validate_owner(request, repo_id):
|
if validate_owner(request, repo_id):
|
||||||
owner = "self"
|
owner = "self"
|
||||||
@@ -373,7 +378,7 @@ class Repo(APIView):
|
|||||||
"encrypted":repo.encrypted,
|
"encrypted":repo.encrypted,
|
||||||
"encversion":r.encversion,
|
"encversion":r.encversion,
|
||||||
"root":root_id,
|
"root":root_id,
|
||||||
"permission": check_permission(repo.id, request.user.username),
|
"permission": check_permission(repo.id, username),
|
||||||
}
|
}
|
||||||
|
|
||||||
return Response(repo_json)
|
return Response(repo_json)
|
||||||
@@ -408,10 +413,15 @@ class Repo(APIView):
|
|||||||
|
|
||||||
class DownloadRepo(APIView):
|
class DownloadRepo(APIView):
|
||||||
authentication_classes = (TokenAuthentication, )
|
authentication_classes = (TokenAuthentication, )
|
||||||
permission_classes = (IsAuthenticated, IsRepoAccessible, )
|
permission_classes = (IsAuthenticated, )
|
||||||
throttle_classes = (UserRateThrottle, )
|
throttle_classes = (UserRateThrottle, )
|
||||||
|
|
||||||
def get(self, request, repo_id, format=None):
|
def get(self, request, repo_id, format=None):
|
||||||
|
username = request.user.username
|
||||||
|
if not is_repo_accessible(repo_id, username):
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN,
|
||||||
|
'You do not have permission to get repo.')
|
||||||
|
|
||||||
return repo_download_info(request, repo_id)
|
return repo_download_info(request, repo_id)
|
||||||
|
|
||||||
class UploadLinkView(APIView):
|
class UploadLinkView(APIView):
|
||||||
@@ -606,13 +616,18 @@ class OpDeleteView(APIView):
|
|||||||
Delete a file.
|
Delete a file.
|
||||||
"""
|
"""
|
||||||
authentication_classes = (TokenAuthentication, )
|
authentication_classes = (TokenAuthentication, )
|
||||||
permission_classes = (IsAuthenticated, IsRepoWritable, )
|
permission_classes = (IsAuthenticated, )
|
||||||
|
|
||||||
def post(self, request, repo_id, format=None):
|
def post(self, request, repo_id, format=None):
|
||||||
repo = get_repo(repo_id)
|
repo = get_repo(repo_id)
|
||||||
if not repo:
|
if not repo:
|
||||||
return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.')
|
return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.')
|
||||||
|
|
||||||
|
username = request.user.username
|
||||||
|
if not is_repo_writable(repo.id, username):
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN,
|
||||||
|
'You do not have permission to delete file.')
|
||||||
|
|
||||||
resp = check_repo_access_permission(request, repo)
|
resp = check_repo_access_permission(request, repo)
|
||||||
if resp:
|
if resp:
|
||||||
return resp
|
return resp
|
||||||
@@ -628,7 +643,7 @@ class OpDeleteView(APIView):
|
|||||||
file_name = unquote(file_name.encode('utf-8'))
|
file_name = unquote(file_name.encode('utf-8'))
|
||||||
try:
|
try:
|
||||||
seafserv_threaded_rpc.del_file(repo_id, parent_dir,
|
seafserv_threaded_rpc.del_file(repo_id, parent_dir,
|
||||||
file_name, request.user.username)
|
file_name, username)
|
||||||
except SearpcError,e:
|
except SearpcError,e:
|
||||||
return api_error(HTTP_520_OPERATION_FAILED,
|
return api_error(HTTP_520_OPERATION_FAILED,
|
||||||
"Failed to delete file.")
|
"Failed to delete file.")
|
||||||
@@ -707,7 +722,7 @@ class FileView(APIView):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
authentication_classes = (TokenAuthentication, )
|
authentication_classes = (TokenAuthentication, )
|
||||||
permission_classes = (IsAuthenticated, IsRepoWritable, )
|
permission_classes = (IsAuthenticated, )
|
||||||
throttle_classes = (UserRateThrottle, )
|
throttle_classes = (UserRateThrottle, )
|
||||||
|
|
||||||
def get(self, request, repo_id, format=None):
|
def get(self, request, repo_id, format=None):
|
||||||
@@ -740,7 +755,7 @@ class FileView(APIView):
|
|||||||
return get_repo_file(request, repo_id, file_id, file_name, op)
|
return get_repo_file(request, repo_id, file_id, file_name, op)
|
||||||
|
|
||||||
def post(self, request, repo_id, format=None):
|
def post(self, request, repo_id, format=None):
|
||||||
# rename or move file
|
# rename, move or create file
|
||||||
repo = get_repo(repo_id)
|
repo = get_repo(repo_id)
|
||||||
if not repo:
|
if not repo:
|
||||||
return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.')
|
return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.')
|
||||||
@@ -754,8 +769,13 @@ class FileView(APIView):
|
|||||||
return api_error(status.HTTP_400_BAD_REQUEST,
|
return api_error(status.HTTP_400_BAD_REQUEST,
|
||||||
'Path is missing or invalid.')
|
'Path is missing or invalid.')
|
||||||
|
|
||||||
|
username = request.user.username
|
||||||
operation = request.POST.get('operation', '')
|
operation = request.POST.get('operation', '')
|
||||||
if operation.lower() == 'rename':
|
if operation.lower() == 'rename':
|
||||||
|
if not is_repo_writable(repo.id, username):
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN,
|
||||||
|
'You do not have permission to rename file.')
|
||||||
|
|
||||||
newname = request.POST.get('newname', '')
|
newname = request.POST.get('newname', '')
|
||||||
if not newname:
|
if not newname:
|
||||||
return api_error(status.HTTP_400_BAD_REQUEST,
|
return api_error(status.HTTP_400_BAD_REQUEST,
|
||||||
@@ -777,7 +797,7 @@ class FileView(APIView):
|
|||||||
try:
|
try:
|
||||||
seafserv_threaded_rpc.rename_file (repo_id, parent_dir_utf8,
|
seafserv_threaded_rpc.rename_file (repo_id, parent_dir_utf8,
|
||||||
oldname_utf8, newname,
|
oldname_utf8, newname,
|
||||||
request.user.username)
|
username)
|
||||||
except SearpcError,e:
|
except SearpcError,e:
|
||||||
return api_error(HTTP_520_OPERATION_FAILED,
|
return api_error(HTTP_520_OPERATION_FAILED,
|
||||||
"Failed to rename file: %s" % e)
|
"Failed to rename file: %s" % e)
|
||||||
@@ -791,6 +811,10 @@ class FileView(APIView):
|
|||||||
return resp
|
return resp
|
||||||
|
|
||||||
elif operation.lower() == 'move':
|
elif operation.lower() == 'move':
|
||||||
|
if not is_repo_writable(repo.id, username):
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN,
|
||||||
|
'You do not have permission to move file.')
|
||||||
|
|
||||||
src_dir = os.path.dirname(path)
|
src_dir = os.path.dirname(path)
|
||||||
src_dir_utf8 = src_dir.encode('utf-8')
|
src_dir_utf8 = src_dir.encode('utf-8')
|
||||||
src_repo_id = repo_id
|
src_repo_id = repo_id
|
||||||
@@ -826,7 +850,7 @@ class FileView(APIView):
|
|||||||
seafserv_threaded_rpc.move_file(src_repo_id, src_dir_utf8,
|
seafserv_threaded_rpc.move_file(src_repo_id, src_dir_utf8,
|
||||||
filename_utf8, dst_repo_id,
|
filename_utf8, dst_repo_id,
|
||||||
dst_dir_utf8, new_filename_utf8,
|
dst_dir_utf8, new_filename_utf8,
|
||||||
request.user.username)
|
username)
|
||||||
except SearpcError, e:
|
except SearpcError, e:
|
||||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
|
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
"SearpcError:" + e.msg)
|
"SearpcError:" + e.msg)
|
||||||
@@ -839,6 +863,10 @@ class FileView(APIView):
|
|||||||
resp['Location'] = uri + '?p=' + quote(dst_dir_utf8) + quote(new_filename_utf8)
|
resp['Location'] = uri + '?p=' + quote(dst_dir_utf8) + quote(new_filename_utf8)
|
||||||
return resp
|
return resp
|
||||||
elif operation.lower() == 'create':
|
elif operation.lower() == 'create':
|
||||||
|
if not is_repo_writable(repo.id, username):
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN,
|
||||||
|
'You do not have permission to create file.')
|
||||||
|
|
||||||
parent_dir = os.path.dirname(path)
|
parent_dir = os.path.dirname(path)
|
||||||
parent_dir_utf8 = parent_dir.encode('utf-8')
|
parent_dir_utf8 = parent_dir.encode('utf-8')
|
||||||
new_file_name = os.path.basename(path)
|
new_file_name = os.path.basename(path)
|
||||||
@@ -848,11 +876,10 @@ class FileView(APIView):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
seafserv_threaded_rpc.post_empty_file(repo_id, parent_dir,
|
seafserv_threaded_rpc.post_empty_file(repo_id, parent_dir,
|
||||||
new_file_name,
|
new_file_name, username)
|
||||||
request.user.username)
|
|
||||||
except SearpcError, e:
|
except SearpcError, e:
|
||||||
return api_error(HTTP_520_OPERATION_FAILED,
|
return api_error(HTTP_520_OPERATION_FAILED,
|
||||||
'Failed to make directory.')
|
'Failed to create file.')
|
||||||
|
|
||||||
if request.GET.get('reloaddir', '').lower() == 'true':
|
if request.GET.get('reloaddir', '').lower() == 'true':
|
||||||
return reloaddir(request, repo_id, parent_dir)
|
return reloaddir(request, repo_id, parent_dir)
|
||||||
@@ -877,6 +904,11 @@ class FileView(APIView):
|
|||||||
if not repo:
|
if not repo:
|
||||||
return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.')
|
return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.')
|
||||||
|
|
||||||
|
username = request.user.username
|
||||||
|
if not is_repo_writable(repo.id, username):
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN,
|
||||||
|
'You do not have permission to delete file.')
|
||||||
|
|
||||||
resp = check_repo_access_permission(request, repo)
|
resp = check_repo_access_permission(request, repo)
|
||||||
if resp:
|
if resp:
|
||||||
return resp
|
return resp
|
||||||
@@ -948,7 +980,7 @@ class DirView(APIView):
|
|||||||
create/delete/rename/list, etc.
|
create/delete/rename/list, etc.
|
||||||
"""
|
"""
|
||||||
authentication_classes = (TokenAuthentication, )
|
authentication_classes = (TokenAuthentication, )
|
||||||
permission_classes = (IsAuthenticated, IsRepoWritable, )
|
permission_classes = (IsAuthenticated, )
|
||||||
throttle_classes = (UserRateThrottle, )
|
throttle_classes = (UserRateThrottle, )
|
||||||
|
|
||||||
def get(self, request, repo_id, format=None):
|
def get(self, request, repo_id, format=None):
|
||||||
@@ -993,18 +1025,22 @@ class DirView(APIView):
|
|||||||
resp = check_repo_access_permission(request, repo)
|
resp = check_repo_access_permission(request, repo)
|
||||||
if resp:
|
if resp:
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
path = request.GET.get('p', '')
|
path = request.GET.get('p', '')
|
||||||
if not path or path[0] != '/':
|
if not path or path[0] != '/':
|
||||||
return api_error(status.HTTP_400_BAD_REQUEST, "Path is missing.")
|
return api_error(status.HTTP_400_BAD_REQUEST, "Path is missing.")
|
||||||
|
|
||||||
if path == '/': # Can not make root dir.
|
if path == '/': # Can not make root dir.
|
||||||
return api_error(status.HTTP_400_BAD_REQUEST, "Path is invalid.")
|
return api_error(status.HTTP_400_BAD_REQUEST, "Path is invalid.")
|
||||||
|
|
||||||
if path[-1] == '/': # Cut out last '/' if possible.
|
if path[-1] == '/': # Cut out last '/' if possible.
|
||||||
path = path[:-1]
|
path = path[:-1]
|
||||||
|
|
||||||
|
username = request.user.username
|
||||||
operation = request.POST.get('operation', '')
|
operation = request.POST.get('operation', '')
|
||||||
if operation.lower() == 'mkdir':
|
if operation.lower() == 'mkdir':
|
||||||
|
if not is_repo_writable(repo.id, username):
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN,
|
||||||
|
'You do not have permission to create folder.')
|
||||||
|
|
||||||
parent_dir = os.path.dirname(path)
|
parent_dir = os.path.dirname(path)
|
||||||
parent_dir_utf8 = parent_dir.encode('utf-8')
|
parent_dir_utf8 = parent_dir.encode('utf-8')
|
||||||
new_dir_name = os.path.basename(path)
|
new_dir_name = os.path.basename(path)
|
||||||
@@ -1014,8 +1050,7 @@ class DirView(APIView):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
seafserv_threaded_rpc.post_dir(repo_id, parent_dir,
|
seafserv_threaded_rpc.post_dir(repo_id, parent_dir,
|
||||||
new_dir_name,
|
new_dir_name, username)
|
||||||
request.user.username)
|
|
||||||
except SearpcError, e:
|
except SearpcError, e:
|
||||||
return api_error(HTTP_520_OPERATION_FAILED,
|
return api_error(HTTP_520_OPERATION_FAILED,
|
||||||
'Failed to make directory.')
|
'Failed to make directory.')
|
||||||
@@ -1042,6 +1077,11 @@ class DirView(APIView):
|
|||||||
if not repo:
|
if not repo:
|
||||||
return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.')
|
return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.')
|
||||||
|
|
||||||
|
username = request.user.username
|
||||||
|
if not is_repo_writable(repo.id, username):
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN,
|
||||||
|
'You do not have permission to delete folder.')
|
||||||
|
|
||||||
resp = check_repo_access_permission(request, repo)
|
resp = check_repo_access_permission(request, repo)
|
||||||
if resp:
|
if resp:
|
||||||
return resp
|
return resp
|
||||||
@@ -1062,8 +1102,7 @@ class DirView(APIView):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
seafserv_threaded_rpc.del_file(repo_id, parent_dir_utf8,
|
seafserv_threaded_rpc.del_file(repo_id, parent_dir_utf8,
|
||||||
file_name_utf8,
|
file_name_utf8, username)
|
||||||
request.user.username)
|
|
||||||
except SearpcError, e:
|
except SearpcError, e:
|
||||||
return api_error(HTTP_520_OPERATION_FAILED,
|
return api_error(HTTP_520_OPERATION_FAILED,
|
||||||
"Failed to delete file.")
|
"Failed to delete file.")
|
||||||
@@ -1138,13 +1177,18 @@ class SharedRepo(APIView):
|
|||||||
Support uniform interface for shared libraries.
|
Support uniform interface for shared libraries.
|
||||||
"""
|
"""
|
||||||
authentication_classes = (TokenAuthentication, )
|
authentication_classes = (TokenAuthentication, )
|
||||||
permission_classes = (IsAuthenticated, IsRepoOwner)
|
permission_classes = (IsAuthenticated, )
|
||||||
throttle_classes = (UserRateThrottle, )
|
throttle_classes = (UserRateThrottle, )
|
||||||
|
|
||||||
def delete(self, request, repo_id, format=None):
|
def delete(self, request, repo_id, format=None):
|
||||||
"""
|
"""
|
||||||
Unshare a library. Only repo owner can perform this operation.
|
Unshare a library. Only repo owner can perform this operation.
|
||||||
"""
|
"""
|
||||||
|
username = request.user.username
|
||||||
|
if not seafile_api.is_repo_owner(username, repo_id):
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN,
|
||||||
|
'You do not have permission to unshare library.')
|
||||||
|
|
||||||
share_type = request.GET.get('share_type', '')
|
share_type = request.GET.get('share_type', '')
|
||||||
user = request.GET.get('user', '')
|
user = request.GET.get('user', '')
|
||||||
group_id = request.GET.get('group_id', '')
|
group_id = request.GET.get('group_id', '')
|
||||||
@@ -1153,7 +1197,7 @@ class SharedRepo(APIView):
|
|||||||
'share_type and user and group_id is required.')
|
'share_type and user and group_id is required.')
|
||||||
|
|
||||||
if share_type == 'personal':
|
if share_type == 'personal':
|
||||||
remove_share(repo_id, request.user.username, user)
|
remove_share(repo_id, username, user)
|
||||||
elif share_type == 'group':
|
elif share_type == 'group':
|
||||||
unshare_group_repo(repo_id, group_id, user)
|
unshare_group_repo(repo_id, group_id, user)
|
||||||
elif share_type == 'public':
|
elif share_type == 'public':
|
||||||
@@ -1168,6 +1212,11 @@ class SharedRepo(APIView):
|
|||||||
"""
|
"""
|
||||||
Share a repo to users/groups/public.
|
Share a repo to users/groups/public.
|
||||||
"""
|
"""
|
||||||
|
username = request.user.username
|
||||||
|
if not seafile_api.is_repo_owner(username, repo_id):
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN,
|
||||||
|
'You do not have permission to share library.')
|
||||||
|
|
||||||
share_type = request.GET.get('share_type')
|
share_type = request.GET.get('share_type')
|
||||||
user = request.GET.get('user')
|
user = request.GET.get('user')
|
||||||
group_id = request.GET.get('group_id')
|
group_id = request.GET.get('group_id')
|
||||||
|
Reference in New Issue
Block a user