def create_empty_resource(self, name): """Create an empty (length-0) resource. See DAVResource.createEmptyResource() """ assert not "/" in name if self.provider.readonly: raise DAVError(HTTP_FORBIDDEN) if seafile_api.check_permission_by_path(self.repo.id, self.rel_path, self.username) != "rw": raise DAVError(HTTP_FORBIDDEN) if seafile_api.check_quota(self.repo.id) < 0: raise DAVError(HTTP_FORBIDDEN, "The quota of the repo owner is exceeded") try: seafile_api.post_empty_file(self.repo.id, self.rel_path, name, self.username) except SearpcError as e: if e.msg == 'Invalid file name': raise DAVError(HTTP_BAD_REQUEST) raise # Repo was updated, can't use self.repo repo = seafile_api.get_repo(self.repo.id) if not repo: raise DAVError(HTTP_INTERNAL_ERROR) member_rel_path = "/".join([self.rel_path, name]) member_path = "/".join([self.path, name]) obj = resolveRepoPath(repo, member_rel_path) if not obj or not isinstance(obj, SeafFile): raise DAVError(HTTP_INTERNAL_ERROR) return SeafileResource(member_path, repo, member_rel_path, obj, self.environ)
def check_repo_owner_quota(self, isnewfile=True, contentlength=-1): """Check if the upload would cause the user quota be exceeded `contentlength` is only positive when the client does not use "transfer-encode: chunking" Return True if the quota would not be exceeded, otherwise return False. """ if contentlength <= 0: # When client use "transfer-encode: chunking", the content length # is not included in the request headers if isnewfile: return seafile_api.check_quota(self.repo.id) >= 0 else: return True else: delta = contentlength - self.obj.size return seafile_api.check_quota(self.repo.id, delta) >= 0
def get(self, request, repo_id): """ Return repo info Permission checking: 1. all authenticated user can perform this action. """ # resource check 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) # permission check permission = check_folder_permission(request, repo_id, '/') if permission is None: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) username = request.user.username lib_need_decrypt = False if repo.encrypted \ and not seafile_api.is_password_set(repo.id, username): lib_need_decrypt = True repo_owner = get_repo_owner(request, repo_id) try: has_been_shared_out = repo_has_been_shared_out(request, repo_id) except Exception as e: has_been_shared_out = False logger.error(e) result = { "repo_id": repo.id, "repo_name": repo.name, "owner_email": repo_owner, "owner_name": email2nickname(repo_owner), "owner_contact_email": email2contact_email(repo_owner), "size": repo.size, "encrypted": repo.encrypted, "file_count": repo.file_count, "permission": permission, "no_quota": True if seafile_api.check_quota(repo_id) < 0 else False, "is_admin": is_repo_admin(username, repo_id), "is_virtual": repo.is_virtual, "has_been_shared_out": has_been_shared_out, "lib_need_decrypt": lib_need_decrypt, "last_modified": timestamp_to_isoformat_timestr(repo.last_modify), "status": normalize_repo_status_code(repo.status), } return Response(result)
def get(self, request, repo_id): """ Return repo info Permission checking: 1. all authenticated user can perform this action. """ # resource check 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) # permission check permission = check_folder_permission(request, repo_id, '/') if permission is None: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) username = request.user.username lib_need_decrypt = False if repo.encrypted \ and not seafile_api.is_password_set(repo.id, username): lib_need_decrypt = True repo_owner = get_repo_owner(request, repo_id) try: has_been_shared_out = repo_has_been_shared_out(request, repo_id) except Exception as e: has_been_shared_out = False logger.error(e) result = { "repo_id": repo.id, "repo_name": repo.name, "owner_email": repo_owner, "owner_name": email2nickname(repo_owner), "owner_contact_email": email2contact_email(repo_owner), "size": repo.size, "encrypted": repo.encrypted, "file_count": repo.file_count, "permission": permission, "no_quota": True if seafile_api.check_quota(repo_id) < 0 else False, "is_admin": is_repo_admin(username, repo_id), "is_virtual": repo.is_virtual, "has_been_shared_out": has_been_shared_out, "lib_need_decrypt": lib_need_decrypt, "last_modified": timestamp_to_isoformat_timestr(repo.last_modify), } return Response(result)
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, _("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})
def post(self, request): """ Multi copy 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) # permission check, user must has `r/rw` permission for src repo. if check_folder_permission(request, src_repo_id, '/') is None: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # permission check, user must has `rw` permission for dst repo. if check_folder_permission(request, dst_repo_id, '/') != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, 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) # get total size of file/dir to be copied total_size = 0 for path_item in path_list: src_path = path_item['src_path'] src_path = normalize_dir_path(src_path) current_size = 0 current_dir_id = seafile_api.get_dir_id_by_path( src_repo_id, src_path) current_size = seafile_api.get_dir_size(src_repo.store_id, src_repo.version, current_dir_id) total_size += current_size # check if above quota for dst repo if seafile_api.check_quota(dst_repo_id, total_size) < 0: return api_error(HTTP_443_ABOVE_QUOTA, _(u"Out of quota.")) 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 if not seafile_api.get_dir_id_by_path(src_repo_id, src_path): error_dict = {'error_msg': 'Folder %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: # 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 result['success'].append(common_dict) return Response(result)
def _arguments_wrapper(request, repo_id, *args, **kwargs): if request.method != 'POST': raise Http404 result = {} content_type = 'application/json; charset=utf-8' repo = get_repo(repo_id) if not repo: result['error'] = _(u'Library does not exist.') return HttpResponse(json.dumps(result), status=400, content_type=content_type) # arguments validation parent_dir = request.GET.get('parent_dir') obj_file_names = request.POST.getlist('file_names') obj_dir_names = request.POST.getlist('dir_names') dst_repo_id = request.POST.get('dst_repo') dst_path = request.POST.get('dst_path') if not (parent_dir and dst_repo_id and dst_path) and \ not (obj_file_names or obj_dir_names): result['error'] = _('Argument missing') return HttpResponse(json.dumps(result), status=400, content_type=content_type) # check file path for obj_name in obj_file_names + obj_dir_names: if len(dst_path+obj_name) > settings.MAX_PATH: result['error'] = _('Destination path is too long for %s.') % escape(obj_name) return HttpResponse(json.dumps(result), status=400, content_type=content_type) # when dst is the same as src if repo_id == dst_repo_id and parent_dir == dst_path: result['error'] = _('Invalid destination path') return HttpResponse(json.dumps(result), status=400, content_type=content_type) # check whether user has write permission to dest repo if check_folder_permission(request, dst_repo_id, dst_path) != 'rw': result['error'] = _('Permission denied') return HttpResponse(json.dumps(result), status=403, content_type=content_type) # Leave src folder/file permission checking to corresponding # views, only need to check folder permission when perform 'move' # operation, 1), if move file, check parent dir perm, 2), if move # folder, check that folder perm. file_obj_size = 0 for obj_name in obj_file_names: full_obj_path = posixpath.join(parent_dir, obj_name) file_obj_id = seafile_api.get_file_id_by_path(repo_id, full_obj_path) file_obj_size += seafile_api.get_file_size( repo.store_id, repo.version, file_obj_id) dir_obj_size = 0 for obj_name in obj_dir_names: full_obj_path = posixpath.join(parent_dir, obj_name) dir_obj_id = seafile_api.get_dir_id_by_path(repo_id, full_obj_path) dir_obj_size += seafile_api.get_dir_size( repo.store_id, repo.version, dir_obj_id) # check quota src_repo_owner = seafile_api.get_repo_owner(repo_id) dst_repo_owner = seafile_api.get_repo_owner(dst_repo_id) try: # always check quota when copy file if view_method.__name__ == 'cp_dirents': out_of_quota = seafile_api.check_quota( dst_repo_id, delta=file_obj_size + dir_obj_size) else: # when move file if src_repo_owner != dst_repo_owner: # only check quota when src_repo_owner != dst_repo_owner out_of_quota = seafile_api.check_quota( dst_repo_id, delta=file_obj_size + dir_obj_size) else: # not check quota when src and dst repo are both mine out_of_quota = False except Exception as e: logger.error(e) result['error'] = _(u'Internal server error') return HttpResponse(json.dumps(result), status=500, content_type=content_type) if out_of_quota: result['error'] = _('Out of quota.') return HttpResponse(json.dumps(result), status=403, content_type=content_type) return view_method(request, repo_id, parent_dir, dst_repo_id, dst_path, obj_file_names, obj_dir_names)
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})
def post(self, request): """ Copy/move file/dir, and return task id. Permission checking: 1. move: user with 'rw' permission for current file, 'rw' permission for dst parent dir; 2. copy: user with 'r' permission for current file, 'rw' permission for dst parent dir; """ src_repo_id = request.data.get('src_repo_id', None) src_parent_dir = request.data.get('src_parent_dir', None) src_dirent_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) operation = request.data.get('operation', None) dirent_type = request.data.get('dirent_type', 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_dirent_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 not operation: error_msg = 'operation invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not dirent_type: error_msg = 'dirent_type invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if len(dst_parent_dir + src_dirent_name) > MAX_PATH: error_msg = _('Destination path is too long.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) operation = operation.lower() if operation not in ('move', 'copy'): error_msg = "operation can only be 'move' or 'copy'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if operation == 'move': 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) dirent_type = dirent_type.lower() if dirent_type not in ('file', 'dir'): error_msg = "operation can only be 'file' or 'dir'." 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_dirent_path = posixpath.join(src_parent_dir, src_dirent_name) file_id = None if dirent_type == 'file': file_id = seafile_api.get_file_id_by_path(src_repo_id, src_dirent_path) if not file_id: error_msg = 'File %s not found.' % src_dirent_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) dir_id = None if dirent_type == 'dir': dir_id = seafile_api.get_dir_id_by_path(src_repo_id, src_dirent_path) if not dir_id: error_msg = 'Folder %s not found.' % src_dirent_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 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) if operation == 'copy' or \ operation == 'move' and \ get_repo_owner(request, src_repo_id) != get_repo_owner(request, dst_repo_id): current_size = 0 if file_id: current_size = seafile_api.get_file_size(src_repo.store_id, src_repo.version, file_id) if dir_id: current_size = seafile_api.get_dir_size(src_repo.store_id, src_repo.version, dir_id) # check if above quota for dst repo if seafile_api.check_quota(dst_repo_id, current_size) < 0: return api_error(HTTP_443_ABOVE_QUOTA, _("Out of quota.")) new_dirent_name = check_filename_with_rename(dst_repo_id, dst_parent_dir, src_dirent_name) username = request.user.username if operation == 'move': # permission check for src parent dir if check_folder_permission(request, src_repo_id, src_parent_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if dirent_type == 'dir' and src_repo_id == dst_repo_id and \ dst_parent_dir.startswith(src_dirent_path + '/'): error_msg = _('Can not move directory %(src)s to its subdirectory %(des)s') \ % {'src': escape(src_dirent_path), 'des': escape(dst_parent_dir)} return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if dirent_type == 'file': # check file lock try: is_locked, locked_by_me = check_file_lock(src_repo_id, src_dirent_path, username) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if is_locked and not locked_by_me: error_msg = _("File is locked") return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: res = seafile_api.move_file(src_repo_id, src_parent_dir, src_dirent_name, dst_repo_id, dst_parent_dir, new_dirent_name, replace=False, username=username, need_progress=1) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if operation == 'copy': # permission check for src parent dir if parse_repo_perm(check_folder_permission( request, src_repo_id, src_parent_dir)).can_copy is False: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: res = seafile_api.copy_file(src_repo_id, src_parent_dir, src_dirent_name, dst_repo_id, dst_parent_dir, new_dirent_name, username=username, need_progress=1) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not res: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) result = {} if res.background: result['task_id'] = res.task_id return Response(result)
def post(self, request): """ Copy/move file/dir, and return task id. Permission checking: 1. move: user with 'rw' permission for current file, 'rw' permission for dst parent dir; 2. copy: user with 'r' permission for current file, 'rw' permission for dst parent dir; """ src_repo_id = request.data.get('src_repo_id', None) src_parent_dir = request.data.get('src_parent_dir', None) src_dirent_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) operation = request.data.get('operation', None) dirent_type = request.data.get('dirent_type', 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_dirent_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 not operation: error_msg = 'operation invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not dirent_type: error_msg = 'dirent_type invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if len(dst_parent_dir + src_dirent_name) > MAX_PATH: error_msg = _('Destination path is too long.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) operation = operation.lower() if operation not in ('move', 'copy'): error_msg = "operation can only be 'move' or 'copy'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if operation == 'move': 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) dirent_type = dirent_type.lower() if dirent_type not in ('file', 'dir'): error_msg = "operation can only be 'file' or 'dir'." 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_dirent_path = posixpath.join(src_parent_dir, src_dirent_name) file_id = None if dirent_type == 'file': file_id = seafile_api.get_file_id_by_path(src_repo_id, src_dirent_path) if not file_id: error_msg = 'File %s not found.' % src_dirent_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) dir_id = None if dirent_type == 'dir': dir_id = seafile_api.get_dir_id_by_path(src_repo_id, src_dirent_path) if not dir_id: error_msg = 'Folder %s not found.' % src_dirent_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 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) if operation == 'copy' or \ operation == 'move' and \ get_repo_owner(request, src_repo_id) != get_repo_owner(request, dst_repo_id): current_size = 0 if file_id: current_size = seafile_api.get_file_size(src_repo.store_id, src_repo.version, file_id) if dir_id: current_size = seafile_api.get_dir_size(src_repo.store_id, src_repo.version, dir_id) # check if above quota for dst repo if seafile_api.check_quota(dst_repo_id, current_size) < 0: return api_error(HTTP_443_ABOVE_QUOTA, _(u"Out of quota.")) new_dirent_name = check_filename_with_rename(dst_repo_id, dst_parent_dir, src_dirent_name) username = request.user.username if operation == 'move': # permission check for src parent dir if check_folder_permission(request, src_repo_id, src_parent_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if dirent_type == 'dir' and src_repo_id == dst_repo_id and \ dst_parent_dir.startswith(src_dirent_path + '/'): error_msg = _(u'Can not move directory %(src)s to its subdirectory %(des)s') \ % {'src': escape(src_dirent_path), 'des': escape(dst_parent_dir)} return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if dirent_type == 'file': # check file lock try: is_locked, locked_by_me = check_file_lock(src_repo_id, src_dirent_path, username) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if is_locked and not locked_by_me: error_msg = _("File is locked") return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: res = seafile_api.move_file(src_repo_id, src_parent_dir, src_dirent_name, dst_repo_id, dst_parent_dir, new_dirent_name, replace=False, username=username, need_progress=1) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if operation == 'copy': # permission check for src parent dir if parse_repo_perm(check_folder_permission( request, src_repo_id, src_parent_dir)).can_copy is False: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: res = seafile_api.copy_file(src_repo_id, src_parent_dir, src_dirent_name, dst_repo_id, dst_parent_dir, new_dirent_name, username=username, need_progress=1) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not res: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) result = {} if res.background: result['task_id'] = res.task_id return Response(result)
def post(self, request): """ Multi copy 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) # permission check, user must has `r/rw` permission for src repo. if check_folder_permission(request, src_repo_id, '/') is None: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # permission check, user must has `rw` permission for dst repo. if check_folder_permission(request, dst_repo_id, '/') != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, 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) # get total size of file/dir to be copied total_size = 0 for path_item in path_list: src_path = path_item['src_path'] src_path = normalize_dir_path(src_path) current_size = 0 current_dir_id = seafile_api.get_dir_id_by_path(src_repo_id, src_path) current_size = seafile_api.get_dir_size(src_repo.store_id, src_repo.version, current_dir_id) total_size += current_size # check if above quota for dst repo if seafile_api.check_quota(dst_repo_id, total_size) < 0: return api_error(HTTP_443_ABOVE_QUOTA, _(u"Out of quota.")) 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 if not seafile_api.get_dir_id_by_path(src_repo_id, src_path): error_dict = { 'error_msg': 'Folder %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: # 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 result['success'].append(common_dict) return Response(result)