def repo_revert_dir(request, repo_id): repo = get_repo(repo_id) if not repo: raise Http404 commit_id = request.GET.get('commit') path = request.GET.get('p') if not (commit_id and path): return render_error(request, _(u"Invalid arguments")) referer = request.META.get('HTTP_REFERER', None) next = settings.SITE_ROOT if referer is None else referer # perm check if check_folder_permission(request, repo.id, path) != 'rw': messages.error(request, _("Permission denied")) return HttpResponseRedirect(next) try: ret = seafile_api.revert_dir(repo_id, commit_id, path, request.user.username) except Exception as e: logger.error(e) messages.error(request, _('Failed to restore, please try again later.')) return HttpResponseRedirect(next) if ret == 1: root_url = reverse('view_common_lib_dir', args=[repo_id, '']) msg = _( u'Successfully revert %(path)s to <a href="%(url)s">root directory.</a>' ) % { "path": escape(path.lstrip('/')), "url": root_url } messages.success(request, msg, extra_tags='safe') else: dir_view_url = reverse('view_common_lib_dir', args=[repo_id, path.strip('/').encode('utf-8')]) msg = _(u'Successfully revert <a href="%(url)s">%(path)s</a>') % { "url": dir_view_url, "path": escape(path.lstrip('/')) } messages.success(request, msg, extra_tags='safe') return HttpResponseRedirect(next)
def repo_revert_dir(request, repo_id): repo = get_repo(repo_id) if not repo: raise Http404 commit_id = request.GET.get('commit') path = request.GET.get('p') if not (commit_id and path): return render_error(request, _(u"Invalid arguments")) referer = request.META.get('HTTP_REFERER', None) next = settings.SITE_ROOT if referer is None else referer # perm check if check_folder_permission(request, repo.id, path) != 'rw': messages.error(request, _("Permission denied")) return HttpResponseRedirect(next) try: ret = seafile_api.revert_dir(repo_id, commit_id, path, request.user.username) except Exception as e: logger.error(e) messages.error(request, _('Failed to restore, please try again later.')) return HttpResponseRedirect(next) if ret == 1: root_url = reverse('view_common_lib_dir', args=[repo_id, '']) msg = _(u'Successfully revert %(path)s to <a href="%(url)s">root directory.</a>') % {"path": escape(path.lstrip('/')), "url": root_url} messages.success(request, msg, extra_tags='safe') else: dir_view_url = reverse('view_common_lib_dir', args=[repo_id, path.strip('/').encode('utf-8')]) msg = _(u'Successfully revert <a href="%(url)s">%(path)s</a>') % {"url": dir_view_url, "path": escape(path.lstrip('/'))} messages.success(request, msg, extra_tags='safe') return HttpResponseRedirect(next)
class DirView(APIView): """ Support uniform interface for directory operations, including create/delete/rename/list, etc. """ authentication_classes = (TokenAuthentication, SessionAuthentication) permission_classes = (IsAuthenticated, ) throttle_classes = (UserRateThrottle, ) def get_dir_info(self, repo_id, dir_path): dir_obj = seafile_api.get_dirent_by_path(repo_id, dir_path) dir_info = { 'type': 'dir', 'repo_id': repo_id, 'parent_dir': os.path.dirname(dir_path.rstrip('/')), 'obj_name': dir_obj.obj_name, 'obj_id': dir_obj.obj_id, 'mtime': timestamp_to_isoformat_timestr(dir_obj.mtime), } return dir_info def get(self, request, repo_id, format=None): """ Get dir info. Permission checking: 1. user with either 'r' or 'rw' permission. """ path = request.GET.get('p', '/') if path[-1] != '/': path = path + '/' # recource 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) try: dir_id = seafile_api.get_dir_id_by_path(repo_id, path) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not dir_id: error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if not check_folder_permission(request, repo_id, path): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) old_oid = request.GET.get('oid', None) if old_oid and old_oid == dir_id: resp = Response({'success': True}) resp["oid"] = dir_id return resp else: request_type = request.GET.get('t', None) if request_type and request_type not in ('f', 'd'): error_msg = "'t'(type) should be 'f' or 'd'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if request_type == 'd': recursive = request.GET.get('recursive', '0') if recursive not in ('1', '0'): error_msg = "If you want to get recursive dir entries, you should set 'recursive' argument as '1'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if recursive == '1': username = request.user.username dir_list = get_dir_recursively(username, repo_id, path, []) dir_list.sort( lambda x, y: cmp(x['name'].lower(), y['name'].lower())) resp = Response(dir_list) resp["oid"] = dir_id resp["dir_perm"] = seafile_api.check_permission_by_path( repo_id, path, username) return resp return get_dir_entrys_by_id(request, repo, path, dir_id, request_type) def post(self, request, repo_id, format=None): """ Create, rename, revert dir. Permission checking: 1. create: user with 'rw' permission for current dir's parent dir; 2. rename: user with 'rw' permission for current dir; 3. revert: user with 'rw' permission for current dir's parent dir; """ # argument check path = request.GET.get('p', None) if not path or path[0] != '/': error_msg = 'p invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if path == '/': error_msg = 'Can not operate root dir.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) operation = request.data.get('operation', None) if not operation: error_msg = 'operation invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) operation = operation.lower() if operation not in ('mkdir', 'rename', 'revert'): error_msg = "operation can only be 'mkdir', 'rename' or 'revert'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # 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) path = path.rstrip('/') username = request.user.username parent_dir = os.path.dirname(path) if operation == 'mkdir': # permission check if check_folder_permission(request, repo_id, parent_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # resource check parent_dir_id = seafile_api.get_dir_id_by_path(repo_id, parent_dir) if not parent_dir_id: error_msg = 'Folder %s not found.' % parent_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) new_dir_name = os.path.basename(path) if not is_valid_dirent_name(new_dir_name): return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.') new_dir_name = check_filename_with_rename(repo_id, parent_dir, new_dir_name) try: seafile_api.post_dir(repo_id, parent_dir, new_dir_name, username) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) new_dir_path = posixpath.join(parent_dir, new_dir_name) dir_info = self.get_dir_info(repo_id, new_dir_path) resp = Response(dir_info) return resp if operation == 'rename': # resource check dir_id = seafile_api.get_dir_id_by_path(repo_id, path) if not dir_id: error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if check_folder_permission(request, repo_id, path) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) old_dir_name = os.path.basename(path) new_dir_name = request.data.get('newname', None) if not new_dir_name: error_msg = 'newname invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not is_valid_dirent_name(new_dir_name): return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.') if new_dir_name == old_dir_name: dir_info = self.get_dir_info(repo_id, path) resp = Response(dir_info) return resp try: # rename duplicate name new_dir_name = check_filename_with_rename( repo_id, parent_dir, new_dir_name) # rename dir seafile_api.rename_file(repo_id, parent_dir, old_dir_name, new_dir_name, username) new_dir_path = posixpath.join(parent_dir, new_dir_name) dir_info = self.get_dir_info(repo_id, new_dir_path) resp = Response(dir_info) return resp except SearpcError, e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if operation == 'revert': commit_id = request.data.get('commit_id', None) if not commit_id: error_msg = 'commit_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if seafile_api.get_dir_id_by_path(repo_id, path): # dir exists in repo if check_folder_permission(request, repo_id, path) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) else: # dir NOT exists in repo if check_folder_permission(request, repo_id, '/') != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: seafile_api.revert_dir(repo_id, commit_id, 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) return Response({'success': True})
def post(self, request, repo_id, format=None): """ Create, rename, revert dir. Permission checking: 1. create: user with 'rw' permission for current dir's parent dir; 2. rename: user with 'rw' permission for current dir; 3. revert: user with 'rw' permission for current dir's parent dir; """ # argument check path = request.GET.get('p', None) if not path or path[0] != '/': error_msg = 'p invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if path == '/': error_msg = 'Can not operate root dir.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) operation = request.data.get('operation', None) if not operation: error_msg = 'operation invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) operation = operation.lower() if operation not in ('mkdir', 'rename', 'revert'): error_msg = "operation can only be 'mkdir', 'rename' or 'revert'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # 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) path = path.rstrip('/') username = request.user.username parent_dir = os.path.dirname(path) if operation == 'mkdir': # resource check parent_dir_id = seafile_api.get_dir_id_by_path(repo_id, parent_dir) if not parent_dir_id: error_msg = 'Folder %s not found.' % parent_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if check_folder_permission(request, repo_id, parent_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) new_dir_name = os.path.basename(path) if not is_valid_dirent_name(new_dir_name): return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.') retry_count = 0 while retry_count < 10: new_dir_name = check_filename_with_rename( repo_id, parent_dir, new_dir_name) try: seafile_api.post_dir(repo_id, parent_dir, new_dir_name, username) break except SearpcError as e: if str(e) == 'file already exists': retry_count += 1 else: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) new_dir_path = posixpath.join(parent_dir, new_dir_name) dir_info = self.get_dir_info(repo_id, new_dir_path) resp = Response(dir_info) return resp if operation == 'rename': # resource check dir_id = seafile_api.get_dir_id_by_path(repo_id, path) if not dir_id: error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if check_folder_permission(request, repo_id, path) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) old_dir_name = os.path.basename(path) new_dir_name = request.data.get('newname', None) if not new_dir_name: error_msg = 'newname invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not is_valid_dirent_name(new_dir_name): return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.') if new_dir_name == old_dir_name: dir_info = self.get_dir_info(repo_id, path) resp = Response(dir_info) return resp try: # rename duplicate name new_dir_name = check_filename_with_rename( repo_id, parent_dir, new_dir_name) # rename dir seafile_api.rename_file(repo_id, parent_dir, old_dir_name, new_dir_name, username) new_dir_path = posixpath.join(parent_dir, new_dir_name) dir_info = self.get_dir_info(repo_id, new_dir_path) resp = Response(dir_info) return resp except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if operation == 'revert': commit_id = request.data.get('commit_id', None) if not commit_id: error_msg = 'commit_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if seafile_api.get_dir_id_by_path(repo_id, path): # dir exists in repo if check_folder_permission(request, repo_id, path) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) else: # dir NOT exists in repo if check_folder_permission(request, repo_id, '/') != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: seafile_api.revert_dir(repo_id, commit_id, 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) return Response({'success': True})
class DirView(APIView): """ Support uniform interface for directory operations, including create/delete/rename/list, etc. """ authentication_classes = (TokenAuthentication, SessionAuthentication) permission_classes = (IsAuthenticated, ) throttle_classes = (UserRateThrottle, ) def get_dir_info(self, repo_id, dir_path): dir_obj = seafile_api.get_dirent_by_path(repo_id, dir_path) dir_info = { 'type': 'dir', 'repo_id': repo_id, 'parent_dir': os.path.dirname(dir_path.rstrip('/')), 'obj_name': dir_obj.obj_name, 'obj_id': dir_obj.obj_id, 'mtime': timestamp_to_isoformat_timestr(dir_obj.mtime), } return dir_info def get(self, request, repo_id, format=None): """ Get sub dirent list info. Permission checking: 1. user with either 'r' or 'rw' permission. """ # argument check recursive = request.GET.get('recursive', '0') if recursive not in ('1', '0'): error_msg = "If you want to get recursive dir entries, you should set 'recursive' argument as '1'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) request_type = request.GET.get('t', '') if request_type and request_type not in ('f', 'd'): error_msg = "'t'(type) should be 'f' or 'd'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) with_thumbnail = request.GET.get('with_thumbnail', 'false') if with_thumbnail not in ('true', 'false'): error_msg = 'with_thumbnail invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) with_thumbnail = to_python_boolean(with_thumbnail) thumbnail_size = request.GET.get('thumbnail_size', 48) try: thumbnail_size = int(thumbnail_size) except ValueError: error_msg = 'thumbnail_size invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) with_parents = request.GET.get('with_parents', 'false') if with_parents not in ('true', 'false'): error_msg = 'with_parents invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) with_parents = to_python_boolean(with_parents) # recource 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) parent_dir = request.GET.get('p', '/') parent_dir = normalize_dir_path(parent_dir) dir_id = seafile_api.get_dir_id_by_path(repo_id, parent_dir) if not dir_id: error_msg = 'Folder %s not found.' % parent_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check permission = check_folder_permission(request, repo_id, parent_dir) if not permission: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # get dir/file list recursively username = request.user.username if recursive == '1': try: dir_file_info_list = get_dir_file_recursively(username, repo_id, parent_dir, []) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) response_dict = {} response_dict['dirent_list'] = [] if request_type == 'f': for item in dir_file_info_list: if item['type'] == 'file': response_dict['dirent_list'].append(item) elif request_type == 'd': for item in dir_file_info_list: if item['type'] == 'dir': response_dict['dirent_list'].append(item) else: response_dict['dirent_list'] = dir_file_info_list return Response(response_dict) parent_dir_list = [] if not with_parents: # only return dirent list in current parent folder parent_dir_list.append(parent_dir) else: # if value of 'p' parameter is '/a/b/c' add with_parents's is 'true' # then return dirent list in '/', '/a', '/a/b' and '/a/b/c'. if parent_dir == '/': parent_dir_list.append(parent_dir) else: tmp_parent_dir = '/' parent_dir_list.append(tmp_parent_dir) for folder_name in parent_dir.strip('/').split('/'): tmp_parent_dir = posixpath.join(tmp_parent_dir, folder_name) parent_dir_list.append(tmp_parent_dir) all_dir_info_list = [] all_file_info_list = [] try: for parent_dir in parent_dir_list: # get dir file info list dir_info_list, file_info_list = get_dir_file_info_list(username, request_type, repo, parent_dir, with_thumbnail, thumbnail_size) all_dir_info_list.extend(dir_info_list) all_file_info_list.extend(file_info_list) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) response_dict = {} response_dict["user_perm"] = permission if request_type == 'f': response_dict['dirent_list'] = all_file_info_list elif request_type == 'd': response_dict['dirent_list'] = all_dir_info_list else: response_dict['dirent_list'] = all_dir_info_list + all_file_info_list return Response(response_dict) def post(self, request, repo_id, format=None): """ Create, rename, revert dir. Permission checking: 1. create: user with 'rw' permission for current dir's parent dir; 2. rename: user with 'rw' permission for current dir; 3. revert: user with 'rw' permission for current dir's parent dir; """ # argument check path = request.GET.get('p', None) if not path or path[0] != '/': error_msg = 'p invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if path == '/': error_msg = 'Can not operate root dir.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) operation = request.data.get('operation', None) if not operation: error_msg = 'operation invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) operation = operation.lower() if operation not in ('mkdir', 'rename', 'revert'): error_msg = "operation can only be 'mkdir', 'rename' or 'revert'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # 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) path = path.rstrip('/') username = request.user.username parent_dir = os.path.dirname(path) if operation == 'mkdir': # resource check parent_dir_id = seafile_api.get_dir_id_by_path(repo_id, parent_dir) if not parent_dir_id: error_msg = 'Folder %s not found.' % parent_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if check_folder_permission(request, repo_id, parent_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) new_dir_name = os.path.basename(path) if not is_valid_dirent_name(new_dir_name): return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.') retry_count = 0 while retry_count < 10: new_dir_name = check_filename_with_rename(repo_id, parent_dir, new_dir_name) try: seafile_api.post_dir(repo_id, parent_dir, new_dir_name, username) break except SearpcError as e: if str(e) == 'file already exists': retry_count += 1 else: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) new_dir_path = posixpath.join(parent_dir, new_dir_name) dir_info = self.get_dir_info(repo_id, new_dir_path) resp = Response(dir_info) return resp if operation == 'rename': # resource check dir_id = seafile_api.get_dir_id_by_path(repo_id, path) if not dir_id: error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if check_folder_permission(request, repo_id, path) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) old_dir_name = os.path.basename(path) new_dir_name = request.data.get('newname', None) if not new_dir_name: error_msg = 'newname invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not is_valid_dirent_name(new_dir_name): return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.') if new_dir_name == old_dir_name: dir_info = self.get_dir_info(repo_id, path) resp = Response(dir_info) return resp try: # rename duplicate name new_dir_name = check_filename_with_rename(repo_id, parent_dir, new_dir_name) # rename dir seafile_api.rename_file(repo_id, parent_dir, old_dir_name, new_dir_name, username) new_dir_path = posixpath.join(parent_dir, new_dir_name) dir_info = self.get_dir_info(repo_id, new_dir_path) resp = Response(dir_info) return resp except SearpcError, e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if operation == 'revert': commit_id = request.data.get('commit_id', None) if not commit_id: error_msg = 'commit_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if seafile_api.get_dir_id_by_path(repo_id, path): # dir exists in repo if check_folder_permission(request, repo_id, path) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) else: # dir NOT exists in repo if check_folder_permission(request, repo_id, '/') != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: seafile_api.revert_dir(repo_id, commit_id, 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) return Response({'success': True})