1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-02 07:47:32 +00:00

add batch copy/move item api

This commit is contained in:
lian 2018-05-28 16:09:56 +08:00
parent 25aa891bcd
commit bed4bb9bd7
2 changed files with 351 additions and 2 deletions

View File

@ -22,7 +22,8 @@ from seahub.base.accounts import User
from seahub.share.signals import share_repo_to_user_successful, \
share_repo_to_group_successful
from seahub.utils import is_org_context, send_perm_audit_msg, \
normalize_dir_path, get_folder_permission_recursively
normalize_dir_path, get_folder_permission_recursively, \
normalize_file_path, check_filename_with_rename
from seahub.views import check_folder_permission
from seahub.settings import MAX_PATH
@ -596,3 +597,348 @@ class ReposBatchCreateDirView(APIView):
result['success'].append(common_dict)
return Response(result)
class ReposBatchCopyItemView(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated, )
throttle_classes = (UserRateThrottle, )
def post(self, request):
""" Multi copy files/folders.
Permission checking:
1. User must has `r/rw` permission for src folder.
2. User must has `rw` permission for dst folder.
Parameter:
{
"src_repo_id":"7460f7ac-a0ff-4585-8906-bb5a57d2e118",
"dst_repo_id":"a3fa768d-0f00-4343-8b8d-07b4077881db",
"paths":[
{"src_path":"/1/2/3/","dst_path":"/4/5/6/"},
{"src_path":"/a/b/c/","dst_path":"/d/e/f/"},
]
}
"""
# argument check
path_list = request.data.get('paths', None)
if not path_list:
error_msg = 'paths invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
src_repo_id = request.data.get('src_repo_id', None)
if not src_repo_id:
error_msg = 'src_repo_id invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
dst_repo_id = request.data.get('dst_repo_id', None)
if not dst_repo_id:
error_msg = 'dst_repo_id invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# resource check
src_repo = seafile_api.get_repo(src_repo_id)
if not src_repo:
error_msg = 'Library %s not found.' % src_repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
dst_repo = seafile_api.get_repo(dst_repo_id)
if not dst_repo:
error_msg = 'Library %s not found.' % dst_repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# permission check
if check_folder_permission(request, src_repo_id, '/') is None:
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
if check_folder_permission(request, dst_repo_id, '/') is None:
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
result = {}
result['failed'] = []
result['success'] = []
username = request.user.username
for path_item in path_list:
src_path = path_item['src_path']
src_path = normalize_dir_path(src_path)
src_parent_dir = os.path.dirname(src_path.rstrip('/'))
src_parent_dir = normalize_dir_path(src_parent_dir)
src_obj_name = os.path.basename(src_path.rstrip('/'))
dst_path = path_item['dst_path']
dst_path = normalize_dir_path(dst_path)
dst_parent_dir = dst_path
dst_obj_name = src_obj_name
common_dict = {
'src_repo_id': src_repo_id,
'src_path': src_path,
'dst_repo_id': dst_repo_id,
'dst_path': dst_path,
}
# src/dst parameter check
if src_repo_id == dst_repo_id and \
dst_path.startswith(src_path):
error_dict = {
'error_msg': "The destination directory is the same as the source, or is it's subfolder."
}
common_dict.update(error_dict)
result['failed'].append(common_dict)
continue
if src_path == '/':
error_dict = {
'error_msg': "The source path can not be '/'."
}
common_dict.update(error_dict)
result['failed'].append(common_dict)
continue
if len(dst_parent_dir + dst_obj_name) > MAX_PATH:
error_dict = {
'error_msg': "'Destination path is too long."
}
common_dict.update(error_dict)
result['failed'].append(common_dict)
continue
# src resource check
## as we don't know if `src_path` stands for a file or a folder,
## so we check both
src_dir_id = seafile_api.get_dir_id_by_path(src_repo_id, src_path)
src_file_id = seafile_api.get_file_id_by_path(src_repo_id,
normalize_file_path(src_path))
if not src_dir_id and not src_file_id:
error_dict = {
'error_msg': '%s not found.' % src_path
}
common_dict.update(error_dict)
result['failed'].append(common_dict)
continue
# dst resource check
if not seafile_api.get_dir_id_by_path(dst_repo_id, dst_path):
error_dict = {
'error_msg': 'Folder %s not found.' % dst_path
}
common_dict.update(error_dict)
result['failed'].append(common_dict)
continue
# src path permission check, user must has `r/rw` permission for src folder.
if check_folder_permission(request, src_repo_id, src_parent_dir) is None:
error_dict = {
'error_msg': 'Permission denied.'
}
common_dict.update(error_dict)
result['failed'].append(common_dict)
continue
# dst path permission check, user must has `rw` permission for dst folder.
if check_folder_permission(request, dst_repo_id, dst_path) != 'rw':
error_dict = {
'error_msg': 'Permission denied.'
}
common_dict.update(error_dict)
result['failed'].append(common_dict)
continue
try:
dst_obj_name = check_filename_with_rename(dst_repo_id,
dst_parent_dir, dst_obj_name)
# need_progress=0, synchronous=1
seafile_api.copy_file(src_repo_id, src_parent_dir, src_obj_name,
dst_repo_id, dst_parent_dir, dst_obj_name, username, 0, 1)
except Exception as e:
logger.error(e)
error_dict = {
'error_msg': 'Internal Server Error'
}
common_dict.update(error_dict)
result['failed'].append(common_dict)
continue
common_dict['dst_obj_name'] = dst_obj_name
result['success'].append(common_dict)
return Response(result)
class ReposBatchMoveItemView(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated, )
throttle_classes = (UserRateThrottle, )
def post(self, request):
""" Multi move files/folders.
Permission checking:
1. User must has `rw` permission for src folder.
2. User must has `rw` permission for dst folder.
Parameter:
{
"src_repo_id":"7460f7ac-a0ff-4585-8906-bb5a57d2e118",
"dst_repo_id":"a3fa768d-0f00-4343-8b8d-07b4077881db",
"paths":[
{"src_path":"/1/2/3/","dst_path":"/4/5/6/"},
{"src_path":"/a/b/c/","dst_path":"/d/e/f/"},
]
}
"""
# argument check
path_list = request.data.get('paths', None)
if not path_list:
error_msg = 'paths invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
src_repo_id = request.data.get('src_repo_id', None)
if not src_repo_id:
error_msg = 'src_repo_id invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
dst_repo_id = request.data.get('dst_repo_id', None)
if not dst_repo_id:
error_msg = 'dst_repo_id invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# resource check
src_repo = seafile_api.get_repo(src_repo_id)
if not src_repo:
error_msg = 'Library %s not found.' % src_repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
dst_repo = seafile_api.get_repo(dst_repo_id)
if not dst_repo:
error_msg = 'Library %s not found.' % dst_repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# permission check
if check_folder_permission(request, src_repo_id, '/') is None:
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
if check_folder_permission(request, dst_repo_id, '/') is None:
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
result = {}
result['failed'] = []
result['success'] = []
username = request.user.username
for path_item in path_list:
src_path = path_item['src_path']
src_path = normalize_dir_path(src_path)
src_parent_dir = os.path.dirname(src_path.rstrip('/'))
src_parent_dir = normalize_dir_path(src_parent_dir)
src_obj_name = os.path.basename(src_path.rstrip('/'))
dst_path = path_item['dst_path']
dst_path = normalize_dir_path(dst_path)
dst_parent_dir = dst_path
dst_obj_name = src_obj_name
common_dict = {
'src_repo_id': src_repo_id,
'src_path': src_path,
'dst_repo_id': dst_repo_id,
'dst_path': dst_path,
}
# src/dst parameter check
if src_repo_id == dst_repo_id and \
dst_path.startswith(src_path):
error_dict = {
'error_msg': "The destination directory is the same as the source, or is it's subfolder."
}
common_dict.update(error_dict)
result['failed'].append(common_dict)
continue
if src_path == '/':
error_dict = {
'error_msg': "The source path can not be '/'."
}
common_dict.update(error_dict)
result['failed'].append(common_dict)
continue
if len(dst_parent_dir + dst_obj_name) > MAX_PATH:
error_dict = {
'error_msg': "'Destination path is too long."
}
common_dict.update(error_dict)
result['failed'].append(common_dict)
continue
# src resource check
## as we don't know if `src_path` stands for a file or a folder,
## so we check both
src_dir_id = seafile_api.get_dir_id_by_path(src_repo_id, src_path)
src_file_id = seafile_api.get_file_id_by_path(src_repo_id,
normalize_file_path(src_path))
if not src_dir_id and not src_file_id:
error_dict = {
'error_msg': '%s not found.' % src_path
}
common_dict.update(error_dict)
result['failed'].append(common_dict)
continue
# dst resource check
if not seafile_api.get_dir_id_by_path(dst_repo_id, dst_path):
error_dict = {
'error_msg': 'Folder %s not found.' % dst_path
}
common_dict.update(error_dict)
result['failed'].append(common_dict)
continue
# src path permission check, user must has `rw` permission for src folder.
if check_folder_permission(request, src_repo_id, src_parent_dir) != 'rw':
error_dict = {
'error_msg': 'Permission denied.'
}
common_dict.update(error_dict)
result['failed'].append(common_dict)
continue
# dst path permission check, user must has `rw` permission for dst folder.
if check_folder_permission(request, dst_repo_id, dst_path) != 'rw':
error_dict = {
'error_msg': 'Permission denied.'
}
common_dict.update(error_dict)
result['failed'].append(common_dict)
continue
try:
dst_obj_name = check_filename_with_rename(dst_repo_id,
dst_parent_dir, dst_obj_name)
# replace=False, username=username, need_progress=0, synchronous=1
seafile_api.move_file(src_repo_id, src_parent_dir, src_obj_name,
dst_repo_id, dst_parent_dir, dst_obj_name,
False, username, 0, 1)
except Exception as e:
logger.error(e)
error_dict = {
'error_msg': 'Internal Server Error'
}
common_dict.update(error_dict)
result['failed'].append(common_dict)
continue
common_dict['dst_obj_name'] = dst_obj_name
result['success'].append(common_dict)
return Response(result)

View File

@ -30,7 +30,8 @@ from seahub.api2.endpoints.shared_repos import SharedRepos, SharedRepo
from seahub.api2.endpoints.upload_links import UploadLinks, UploadLink, \
UploadLinkUpload
from seahub.api2.endpoints.repos_batch import ReposBatchView, \
ReposBatchCopyDirView, ReposBatchCreateDirView
ReposBatchCopyDirView, ReposBatchCreateDirView, \
ReposBatchCopyItemView, ReposBatchMoveItemView
from seahub.api2.endpoints.repos import RepoView
from seahub.api2.endpoints.file import FileView
from seahub.api2.endpoints.file_history import FileHistoryView
@ -247,6 +248,8 @@ urlpatterns = patterns(
url(r'^api/v2.1/repos/batch/$', ReposBatchView.as_view(), name='api-v2.1-repos-batch'),
url(r'^api/v2.1/repos/batch-copy-dir/$', ReposBatchCopyDirView.as_view(), name='api-v2.1-repos-batch-copy-dir'),
url(r'^api/v2.1/repos/batch-create-dir/$', ReposBatchCreateDirView.as_view(), name='api-v2.1-repos-batch-create-dir'),
url(r'^api/v2.1/repos/batch-copy-item/$', ReposBatchCopyItemView.as_view(), name='api-v2.1-repos-batch-copy-item'),
url(r'^api/v2.1/repos/batch-move-item/$', ReposBatchMoveItemView.as_view(), name='api-v2.1-repos-batch-move-item'),
## user::deleted repos
url(r'^api/v2.1/deleted-repos/$', DeletedRepos.as_view(), name='api2-v2.1-deleted-repos'),