mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-10 03:11:07 +00:00
Merge pull request #2144 from haiwen/move-dir-merge
add move folder merge api
This commit is contained in:
181
seahub/api2/endpoints/move_folder_merge.py
Normal file
181
seahub/api2/endpoints/move_folder_merge.py
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
# Copyright (c) 2012-2018 Seafile Ltd.
|
||||||
|
|
||||||
|
import stat
|
||||||
|
import logging
|
||||||
|
import posixpath
|
||||||
|
|
||||||
|
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 seahub.api2.throttling import UserRateThrottle
|
||||||
|
from seahub.api2.authentication import TokenAuthentication
|
||||||
|
from seahub.api2.utils import api_error
|
||||||
|
from seahub.api2.views import HTTP_443_ABOVE_QUOTA
|
||||||
|
|
||||||
|
from seahub.views import check_folder_permission
|
||||||
|
from seahub.utils.repo import get_repo_owner
|
||||||
|
from seahub.settings import MAX_PATH
|
||||||
|
|
||||||
|
from seaserv import seafile_api
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
def get_dirent_name_list(username, repo_id, parent_path):
|
||||||
|
|
||||||
|
file_name_list = []
|
||||||
|
folder_name_list = []
|
||||||
|
|
||||||
|
path_id = seafile_api.get_dir_id_by_path(repo_id, parent_path)
|
||||||
|
dirs = seafile_api.list_dir_with_perm(repo_id, parent_path,
|
||||||
|
path_id, username, -1, -1)
|
||||||
|
|
||||||
|
for dirent in dirs:
|
||||||
|
if stat.S_ISDIR(dirent.mode):
|
||||||
|
folder_name_list.append(dirent.obj_name)
|
||||||
|
else:
|
||||||
|
file_name_list.append(dirent.obj_name)
|
||||||
|
|
||||||
|
return folder_name_list, file_name_list
|
||||||
|
|
||||||
|
def folder_name_duplicate(username, src_folder_name, dst_repo_id, dst_parent_dir):
|
||||||
|
|
||||||
|
dst_folder_name_list, dst_file_name_list = get_dirent_name_list(username,
|
||||||
|
dst_repo_id, dst_parent_dir)
|
||||||
|
|
||||||
|
if src_folder_name in dst_folder_name_list:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def move_folder_with_merge(username,
|
||||||
|
src_repo_id, src_parent_dir, src_dirent_name,
|
||||||
|
dst_repo_id, dst_parent_dir, dst_dirent_name):
|
||||||
|
|
||||||
|
if folder_name_duplicate(username, src_dirent_name,
|
||||||
|
dst_repo_id, dst_parent_dir):
|
||||||
|
|
||||||
|
src_folder_path = posixpath.join(src_parent_dir, src_dirent_name)
|
||||||
|
dst_folder_path = posixpath.join(dst_parent_dir, dst_dirent_name)
|
||||||
|
src_sub_folder_name_list, src_sub_file_name_list = get_dirent_name_list(username,
|
||||||
|
src_repo_id, src_folder_path)
|
||||||
|
|
||||||
|
# for sub file, copy it directly
|
||||||
|
for src_sub_file_name in src_sub_file_name_list:
|
||||||
|
seafile_api.move_file(
|
||||||
|
src_repo_id, src_folder_path, src_sub_file_name,
|
||||||
|
dst_repo_id, dst_folder_path, src_sub_file_name,
|
||||||
|
replace=False, username=username, need_progress=0)
|
||||||
|
|
||||||
|
for src_sub_folder_name in src_sub_folder_name_list:
|
||||||
|
move_folder_with_merge(username,
|
||||||
|
src_repo_id, src_folder_path, src_sub_folder_name,
|
||||||
|
dst_repo_id, dst_folder_path, src_sub_folder_name)
|
||||||
|
else:
|
||||||
|
seafile_api.move_file(
|
||||||
|
src_repo_id, src_parent_dir, src_dirent_name,
|
||||||
|
dst_repo_id, dst_parent_dir, dst_dirent_name,
|
||||||
|
replace=False, username=username, need_progress=0)
|
||||||
|
|
||||||
|
|
||||||
|
class MoveFolderMergeView(APIView):
|
||||||
|
|
||||||
|
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||||
|
permission_classes = (IsAuthenticated,)
|
||||||
|
throttle_classes = (UserRateThrottle,)
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
""" Only support move folder.
|
||||||
|
|
||||||
|
Permission checking:
|
||||||
|
|
||||||
|
User with 'rw' permission for src/dst folder.
|
||||||
|
"""
|
||||||
|
src_repo_id = request.data.get('src_repo_id', None)
|
||||||
|
src_parent_dir = request.data.get('src_parent_dir', None)
|
||||||
|
src_folder_name = request.data.get('src_dirent_name', None)
|
||||||
|
dst_repo_id = request.data.get('dst_repo_id', None)
|
||||||
|
dst_parent_dir = request.data.get('dst_parent_dir', None)
|
||||||
|
|
||||||
|
# argument check
|
||||||
|
if not src_repo_id:
|
||||||
|
error_msg = 'src_repo_id invalid.'
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
if not src_parent_dir:
|
||||||
|
error_msg = 'src_parent_dir invalid.'
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
if not src_folder_name:
|
||||||
|
error_msg = 'src_dirent_name invalid.'
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
if not dst_repo_id:
|
||||||
|
error_msg = 'dst_repo_id invalid.'
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
if not dst_parent_dir:
|
||||||
|
error_msg = 'dst_parent_dir invalid.'
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
if src_repo_id == dst_repo_id and src_parent_dir == dst_parent_dir:
|
||||||
|
error_msg = _('Invalid destination path')
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
if len(dst_parent_dir + src_folder_name) > MAX_PATH:
|
||||||
|
error_msg = _('Destination path is too long.')
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
# src 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)
|
||||||
|
|
||||||
|
src_folder_path = posixpath.join(src_parent_dir, src_folder_name)
|
||||||
|
dir_id = seafile_api.get_dir_id_by_path(src_repo_id, src_folder_path)
|
||||||
|
if not dir_id:
|
||||||
|
error_msg = 'Folder %s not found.' % src_folder_path
|
||||||
|
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||||
|
|
||||||
|
# dst resource check
|
||||||
|
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)
|
||||||
|
|
||||||
|
if not seafile_api.get_dir_id_by_path(dst_repo_id, dst_parent_dir):
|
||||||
|
error_msg = 'Folder %s not found.' % dst_parent_dir
|
||||||
|
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||||
|
|
||||||
|
# permission check for src folder
|
||||||
|
if check_folder_permission(request, src_repo_id, src_folder_path) != 'rw':
|
||||||
|
error_msg = 'Permission denied.'
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||||
|
|
||||||
|
# permission check for dst parent dir
|
||||||
|
if check_folder_permission(request, dst_repo_id, dst_parent_dir) != 'rw':
|
||||||
|
error_msg = 'Permission denied.'
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||||
|
|
||||||
|
## check if above quota for dst repo
|
||||||
|
if get_repo_owner(request, src_repo_id) != get_repo_owner(request, dst_repo_id):
|
||||||
|
|
||||||
|
current_size = 0
|
||||||
|
current_size = seafile_api.get_dir_size(src_repo.store_id,
|
||||||
|
src_repo.version, dir_id)
|
||||||
|
|
||||||
|
if seafile_api.check_quota(dst_repo_id, current_size) < 0:
|
||||||
|
return api_error(HTTP_443_ABOVE_QUOTA, _(u"Out of quota."))
|
||||||
|
|
||||||
|
username = request.user.username
|
||||||
|
move_folder_with_merge(username,
|
||||||
|
src_repo_id, src_parent_dir, src_folder_name,
|
||||||
|
dst_repo_id, dst_parent_dir, src_folder_name)
|
||||||
|
|
||||||
|
seafile_api.del_file(src_repo_id, src_parent_dir, src_folder_name, username)
|
||||||
|
|
||||||
|
return Response({'success': True})
|
@@ -46,6 +46,7 @@ from seahub.api2.endpoints.share_link_zip_task import ShareLinkZipTaskView
|
|||||||
from seahub.api2.endpoints.query_zip_progress import QueryZipProgressView
|
from seahub.api2.endpoints.query_zip_progress import QueryZipProgressView
|
||||||
from seahub.api2.endpoints.copy_move_task import CopyMoveTaskView
|
from seahub.api2.endpoints.copy_move_task import CopyMoveTaskView
|
||||||
from seahub.api2.endpoints.query_copy_move_progress import QueryCopyMoveProgressView
|
from seahub.api2.endpoints.query_copy_move_progress import QueryCopyMoveProgressView
|
||||||
|
from seahub.api2.endpoints.move_folder_merge import MoveFolderMergeView
|
||||||
from seahub.api2.endpoints.invitations import InvitationsView, InvitationsBatchView
|
from seahub.api2.endpoints.invitations import InvitationsView, InvitationsBatchView
|
||||||
from seahub.api2.endpoints.invitation import InvitationView
|
from seahub.api2.endpoints.invitation import InvitationView
|
||||||
from seahub.api2.endpoints.notifications import NotificationsView, NotificationView
|
from seahub.api2.endpoints.notifications import NotificationsView, NotificationView
|
||||||
@@ -270,6 +271,9 @@ urlpatterns = patterns(
|
|||||||
url(r'^api/v2.1/query-zip-progress/$', QueryZipProgressView.as_view(), name='api-v2.1-query-zip-progress'),
|
url(r'^api/v2.1/query-zip-progress/$', QueryZipProgressView.as_view(), name='api-v2.1-query-zip-progress'),
|
||||||
url(r'^api/v2.1/copy-move-task/$', CopyMoveTaskView.as_view(), name='api-v2.1-copy-move-task'),
|
url(r'^api/v2.1/copy-move-task/$', CopyMoveTaskView.as_view(), name='api-v2.1-copy-move-task'),
|
||||||
url(r'^api/v2.1/query-copy-move-progress/$', QueryCopyMoveProgressView.as_view(), name='api-v2.1-query-copy-move-progress'),
|
url(r'^api/v2.1/query-copy-move-progress/$', QueryCopyMoveProgressView.as_view(), name='api-v2.1-query-copy-move-progress'),
|
||||||
|
|
||||||
|
url(r'^api/v2.1/move-folder-merge/$', MoveFolderMergeView.as_view(), name='api-v2.1-move-folder-merge'),
|
||||||
|
|
||||||
url(r'^api/v2.1/notifications/$', NotificationsView.as_view(), name='api-v2.1-notifications'),
|
url(r'^api/v2.1/notifications/$', NotificationsView.as_view(), name='api-v2.1-notifications'),
|
||||||
url(r'^api/v2.1/notification/$', NotificationView.as_view(), name='api-v2.1-notification'),
|
url(r'^api/v2.1/notification/$', NotificationView.as_view(), name='api-v2.1-notification'),
|
||||||
url(r'^api/v2.1/user-enabled-modules/$', UserEnabledModulesView.as_view(), name='api-v2.1-user-enabled-module'),
|
url(r'^api/v2.1/user-enabled-modules/$', UserEnabledModulesView.as_view(), name='api-v2.1-user-enabled-module'),
|
||||||
|
Reference in New Issue
Block a user