def get(self, request, repo_id, format=None): """ Get all file/folder in a library """ repo = seafile_api.get_repo(repo_id) parent_dir = request.GET.get('parent_dir', '/') 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) repo_owner = get_repo_owner(request, repo_id) try: dirs = seafile_api.list_dir_with_perm(repo_id, parent_dir, dir_id, repo_owner, -1, -1) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return_results = {} return_results['repo_name'] = repo.repo_name return_results['repo_id'] = repo.repo_id return_results['is_system_library'] = True if \ repo.id == get_system_default_repo_id() else False return_results['dirent_list'] = [] for dirent in dirs: dirent_info = get_dirent_info(dirent) return_results['dirent_list'].append(dirent_info) return Response(return_results)
def put(self, request, repo_id): """ Copy a single file/folder to other place. """ # check parameter for src path = request.GET.get('path', None) if not path: error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: dirent = seafile_api.get_dirent_by_path(repo_id, path) 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 dirent: error_msg = 'File or folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if path == '/': error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # normalize path to '/1/2/3' format # NOT ends with '/' path = normalize_file_path(path) # now get `src_dir` and `obj_name` according to normalized path src_repo_id = repo_id src_dir = os.path.dirname(path) src_obj_name = os.path.basename(path) # check parameter for dst dst_repo_id = request.data.get('dst_repo_id', src_repo_id) if dst_repo_id != src_repo_id and not seafile_api.get_repo(dst_repo_id): error_msg = 'Library %s not found.' % dst_repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) dst_dir = request.data.get('dst_dir', '/') if dst_dir != '/': dst_dir = normalize_dir_path(dst_dir) if not seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir): error_msg = 'Folder %s not found.' % dst_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # copy file username = request.user.username dst_obj_name = check_filename_with_rename(dst_repo_id, dst_dir, src_obj_name) try: seafile_api.copy_file(src_repo_id, src_dir, src_obj_name, dst_repo_id, dst_dir, dst_obj_name, username, need_progress=0, synchronous=1) except SearpcError 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, 'dst_item_name': dst_obj_name})
def create_dir_link(self, username, repo_id, path, password=None, expire_date=None): """Create download link for directory. """ path = normalize_dir_path(path) return self._add_file_share(username, repo_id, path, 'd', password, expire_date)
def get_private_share_in_dir(self, username, repo_id, path): """Get a directory that private shared to ``username``. """ path = normalize_dir_path(path) ret = super(PrivateFileDirShareManager, self).filter( to_user=username, repo_id=repo_id, path=path, s_type='d') return ret[0] if len(ret) > 0 else None
def add_private_dir_share(self, from_user, to_user, repo_id, path, perm): """ """ path = normalize_dir_path(path) token = gen_token(max_length=10) pfs = self.model(from_user=from_user, to_user=to_user, repo_id=repo_id, path=path, s_type='d', token=token, permission=perm) pfs.save(using=self._db) return pfs
def create_upload_link_share(self, username, repo_id, path, password=None, expire_date=None): path = normalize_dir_path(path) token = gen_token(max_length=10) if password is not None: password_enc = make_password(password) else: password_enc = None uls = super(UploadLinkShareManager, self).create( username=username, repo_id=repo_id, path=path, token=token, password=password_enc, expire_date=expire_date) uls.save() return uls
def delete(self, request, repo_id): """ Delete repo user folder perm. Permission checking: 1. is group admin """ # argument check user = request.data.get('user_email', None) if not user: error_msg = 'user_email invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) path = request.data.get('folder_path', None) if not path: error_msg = 'folder_path invalid.' 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) repo_owner = get_repo_owner(request, repo_id) group_id = get_group_id_by_repo_owner(repo_owner) if not ccnet_api.get_group(group_id): error_msg = 'Group %s not found.' % group_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check username = request.user.username if not is_group_admin(group_id, username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # delete permission path = normalize_dir_path(path) permission = seafile_api.get_folder_user_perm(repo_id, path, user) if not permission: return Response({'success': True}) try: seafile_api.rm_folder_user_perm(repo_id, path, user) send_perm_audit_msg('delete-repo-perm', username, user, repo_id, path, permission) return Response({'success': True}) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
def get(self, request, repo_id): """ Get dir info. Permission checking: 1. user with either 'r' or 'rw' permission. """ # parameter check path = request.GET.get('path', None) if not path: error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) path = normalize_dir_path(path) if path == '/': error_msg = 'path invalid.' 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) 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 not check_folder_permission(request, repo_id, path): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: dir_obj = seafile_api.get_dirent_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) dir_info = { 'repo_id': repo_id, 'path': path, 'name': dir_obj.obj_name, 'mtime': timestamp_to_isoformat_timestr(dir_obj.mtime), } return Response(dir_info)
def is_file_starred(email, repo_id, path, org_id=-1): # Should use "get", but here we use "filter" to fix the bug caused by no # unique constraint in the table path_list = [normalize_file_path(path), normalize_dir_path(path)] result = UserStarredFiles.objects.filter(email=email, repo_id=repo_id).filter(Q(path__in=path_list)) n = len(result) if n == 0: return False else: # Fix the bug caused by no unique constraint in the table if n > 1: for r in result[1:]: r.delete() return True
def get(self, request): # argument check req_from = request.GET.get('from', 'web') if req_from not in ('web', 'api'): error_msg = 'from invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # recourse check try: repo_id = seafile_api.get_system_default_repo_id() repo = seafile_api.get_repo(repo_id) 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 repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) parent_dir = request.GET.get('path', '/') 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) token = seafile_api.get_fileserver_access_token(repo_id, 'dummy', 'upload', 'system', use_onetime=False) if not token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if req_from == 'api': url = gen_file_upload_url(token, 'upload-api') else: url = gen_file_upload_url(token, 'upload-aj') result = {} result['upload_link'] = url return Response(result)
def delete(self, request): """ Unstar a file/folder. Permission checking: 1. all authenticated user can perform this action. 2. r/rw permission """ # argument check repo_id = request.GET.get('repo_id', None) if not repo_id: error_msg = 'repo_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) path = request.GET.get('path', None) if not path: error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # handler path if item exist if seafile_api.get_dir_id_by_path(repo_id, path): path = normalize_dir_path(path) elif seafile_api.get_file_id_by_path(repo_id, path): path = normalize_file_path(path) email = request.user.username # database record check if not UserStarredFiles.objects.get_starred_item(email, repo_id, path): error_msg = 'Item %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # unstar a item try: UserStarredFiles.objects.delete_starred_item(email, repo_id, path) 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 file/folder in a library """ parent_dir = request.GET.get('parent_dir', '/') 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) obj_name = request.data.get('obj_name', None) if not obj_name or not is_valid_dirent_name(obj_name): error_msg = 'obj_name invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) is_file = request.data.get('is_file', 'false') is_file = is_file.lower() if is_file not in ('true', 'false'): error_msg = 'is_file invalid.' username = request.user.username obj_name = check_filename_with_rename(repo_id, parent_dir, obj_name) try: if is_file == 'true': seafile_api.post_empty_file(repo_id, parent_dir, obj_name, username) else: seafile_api.post_dir(repo_id, parent_dir, obj_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) dirent_path = posixpath.join(parent_dir, obj_name) dirent = seafile_api.get_dirent_by_path(repo_id, dirent_path) dirent_info = get_dirent_info(dirent) return Response(dirent_info)
def test_get(self): # delete a folder first seafile_api.del_file(self.repo_id, '/', self.folder_name, self.user_name) self.login_as(self.user) # get commit id trash_resp = self.client.get(self.trash_url) self.assertEqual(200, trash_resp.status_code) trash_json_resp = json.loads(trash_resp.content) assert trash_json_resp['data'][0]['obj_name'] == self.folder_name assert trash_json_resp['data'][0]['is_dir'] assert trash_json_resp['data'][0]['commit_id'] commit_id = trash_json_resp['data'][0]['commit_id'] url = reverse('api-v2.1-repo-commit-dir', args=[self.repo_id, commit_id]) # test can get resp = self.client.get(url + '?path=' + self.folder_path) self.assertEqual(200, resp.status_code) json_resp = json.loads(resp.content) assert json_resp['dirent_list'] assert json_resp['dirent_list'][0] assert json_resp['dirent_list'][0]['type'] == 'file' assert json_resp['dirent_list'][0]['name'] == self.inner_file_name assert json_resp['dirent_list'][0]['parent_dir'] == normalize_dir_path( self.folder_path) assert json_resp['dirent_list'][0]['size'] == 0 # test can get without path resp = self.client.get(url) self.assertEqual(200, resp.status_code) json_resp = json.loads(resp.content) assert json_resp['dirent_list'] assert json_resp['dirent_list'][0] assert json_resp['dirent_list'][0]['type'] == 'dir' assert json_resp['dirent_list'][0]['name'] == self.folder_name assert json_resp['dirent_list'][0]['parent_dir'] == '/' assert json_resp['dirent_list'][0]['obj_id'] assert json_resp['dirent_list'][1] assert json_resp['dirent_list'][1]['type'] == 'file' assert json_resp['dirent_list'][1]['name'] == self.file_name assert json_resp['dirent_list'][1]['parent_dir'] == '/' assert json_resp['dirent_list'][0]['obj_id'] assert json_resp['dirent_list'][1]['size'] == 0 # test_can_not_get_with_invalid_path_parameter invalid_path = randstring(6) resp = self.client.get(url + '?path=' + invalid_path) self.assertEqual(404, resp.status_code) # test_can_not_get_with_invalid_repo_permission self.logout() self.login_as(self.admin) resp = self.client.get(url + '?path=' + self.folder_path) self.assertEqual(403, resp.status_code)
def create_dir_link(self, username, repo_id, path): path = normalize_dir_path(path) return self._add_file_share(username, repo_id, path, 'd')
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) tmp_parent_dir = normalize_dir_path(tmp_parent_dir) 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 response_dict["dir_id"] = dir_id 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 get_upload_link_by_path(self, username, repo_id, path): path = normalize_dir_path(path) return self._get_upload_link_by_path(username, repo_id, path)
def get(self, request, token): """ Only used for get seafhttp upload link for a folder share link. Permission checking: 1, If enable SHARE_LINK_LOGIN_REQUIRED, user must have been authenticated. 2, If enable ENABLE_SHARE_LINK_AUDIT, user must have been authenticated, or have been audited. 3, If share link is encrypted, share link password must have been checked. 4, Share link must be a folder share link and has can_upload permission. """ # check if login required if SHARE_LINK_LOGIN_REQUIRED and \ not request.user.is_authenticated(): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check share link audit if is_pro_version() and ENABLE_SHARE_LINK_AUDIT and \ not request.user.is_authenticated() and \ not request.session.get('anonymous_email'): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # resource check try: share_link = FileShare.objects.get(token=token) except FileShare.DoesNotExist: error_msg = 'Share link %s not found.' % token return api_error(status.HTTP_404_NOT_FOUND, error_msg) if share_link.s_type != 'd': error_msg = 'Share link %s is not a folder share link.' % token return api_error(status.HTTP_400_BAD_REQUEST, error_msg) repo_id = share_link.repo_id 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) share_link_path = share_link.path request_path = request.GET.get('path', '/') if request_path == '/': path = share_link_path else: path = posixpath.join(share_link_path, request_path.strip('/')) path = normalize_dir_path(path) dir_id = seafile_api.get_dir_id_by_path(repo_id, path) if not dir_id: error_msg = 'Folder %s not found.' % request_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if share_link.is_encrypted() and not check_share_link_access(request, token): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if not share_link.get_permissions()['can_upload']: error_msg = 'Permission denied.' # generate token obj_id = json.dumps({'parent_dir': path}) token = seafile_api.get_fileserver_access_token(repo_id, obj_id, 'upload-link', share_link.username, use_onetime=False) if not token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) result = {} result['upload_link'] = gen_file_upload_url(token, 'upload-api') return Response(result)
def put(self, request, token): """ Update share link, currently only available for permission. Permission checking: share link creater """ # argument check try: perm = check_permissions_arg(request) except Exception: error_msg = 'permissions invalud.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check try: fs = FileShare.objects.get(token=token) except FileShare.DoesNotExist: error_msg = 'token %s not found.' % token return api_error(status.HTTP_404_NOT_FOUND, error_msg) repo_id = fs.repo_id repo = seafile_api.get_repo(repo_id) if not repo_id: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) if fs.path != '/': dirent = seafile_api.get_dirent_by_path(repo_id, fs.path) if not dirent: error_msg = 'Dirent %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check username = request.user.username if not fs.is_owner(username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # get permission of origin repo/folder if fs.s_type == 'd': folder_path = normalize_dir_path(fs.path) else: file_path = normalize_file_path(fs.path) folder_path = os.path.dirname(file_path) username = request.user.username repo_folder_permission = seafile_api.check_permission_by_path(repo_id, folder_path, username) if not repo_folder_permission: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if repo_folder_permission in (PERMISSION_PREVIEW_EDIT, PERMISSION_PREVIEW) \ and perm != FileShare.PERM_VIEW_ONLY: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if repo_folder_permission in (PERMISSION_READ) \ and perm not in (FileShare.PERM_VIEW_DL, FileShare.PERM_VIEW_ONLY): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if fs.s_type == 'f': file_name = os.path.basename(fs.path.rstrip('/')) can_edit, error_msg = can_edit_file(file_name, dirent.size, repo) if not can_edit and perm in (FileShare.PERM_EDIT_DL, FileShare.PERM_EDIT_ONLY): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # update share link permission fs.permission = perm fs.save() link_info = get_share_link_info(fs) return Response(link_info)
def post(self, request): """ Star a file/folder. Permission checking: 1. all authenticated user can perform this action. 2. r/rw permission """ # argument check repo_id = request.data.get('repo_id', None) if not repo_id: error_msg = 'repo_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) path = request.data.get('path', None) if not path: error_msg = 'path invalid.' 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) if seafile_api.get_dir_id_by_path(repo_id, path): is_dir = True path = normalize_dir_path(path) elif seafile_api.get_file_id_by_path(repo_id, path): is_dir = False path = normalize_file_path(path) else: error_msg = 'Item %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if not check_folder_permission(request, repo_id, '/'): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # star a item email = request.user.username starred_item = UserStarredFiles.objects.get_starred_item(email, repo_id, path) if not starred_item: org_id = None if is_org_context(request): org_id = request.user.org.org_id try: starred_item = UserStarredFiles.objects.add_starred_item(email, repo_id, path, is_dir, org_id or -1) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # get info of new starred item item_info = self.get_starred_item_info(repo, starred_item) item_info['user_email'] = email item_info['user_name'] = email2nickname(email) item_info['user_contact_email'] = email2contact_email(email) return Response(item_info)
def post(self, request, repo_id, format=None): """ Add repo group folder perm. Permission checking: 1. is group admin """ # argument check path = request.data.get('folder_path', None) if not path: error_msg = 'folder_path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) perm = request.data.get('permission', None) if not perm or perm not in get_available_repo_perms(): error_msg = 'permission invalid.' 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 = normalize_dir_path(path) if not seafile_api.get_dir_id_by_path(repo_id, path): error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) repo_owner = get_repo_owner(request, repo_id) group_id = get_group_id_by_repo_owner(repo_owner) if not ccnet_api.get_group(group_id): error_msg = 'Group %s not found.' % group_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check username = request.user.username if not is_group_admin(group_id, username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) result = {} result['failed'] = [] result['success'] = [] group_ids = request.data.getlist('group_id') for group_id in group_ids: try: group_id = int(group_id) except ValueError: result['failed'].append({ 'group_id': group_id, 'error_msg': 'group_id invalid.' }) continue if not ccnet_api.get_group(group_id): result['failed'].append({ 'group_id': group_id, 'error_msg': 'Group %s not found.' % group_id }) continue permission = seafile_api.get_folder_group_perm(repo_id, path, group_id) if permission: result['failed'].append({ 'group_id': group_id, 'error_msg': _(u'Permission already exists.') }) continue try: seafile_api.add_folder_group_perm(repo_id, path, perm, group_id) send_perm_audit_msg('add-repo-perm', username, group_id, repo_id, path, perm) except Exception as e: logger.error(e) result['failed'].append({ 'group_id': group_id, 'error_msg': 'Internal Server Error' }) new_perm = seafile_api.get_folder_group_perm(repo_id, path, group_id) new_perm_info = self._get_group_folder_perm_info( group_id, repo_id, path, new_perm) result['success'].append(new_perm_info) return Response(result)
def put(self, request, repo_id, format=None): """ Modify repo group folder perm. Permission checking: 1. is group admin """ # argument check path = request.data.get('folder_path', None) if not path: error_msg = 'folder_path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) perm = request.data.get('permission', None) if not perm or perm not in get_available_repo_perms(): error_msg = 'permission invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) group_id = request.data.get('group_id') if not group_id: error_msg = 'group_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: group_id = int(group_id) except ValueError: error_msg = 'group_id invalid.' 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 = normalize_dir_path(path) if not seafile_api.get_dir_id_by_path(repo_id, path): error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if not ccnet_api.get_group(group_id): error_msg = 'Group %s not found.' % group_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) repo_owner = get_repo_owner(request, repo_id) library_group_id = get_group_id_by_repo_owner(repo_owner) if not ccnet_api.get_group(library_group_id): error_msg = 'Group %s not found.' % group_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) permission = seafile_api.get_folder_group_perm(repo_id, path, group_id) if not permission: error_msg = 'Folder permission not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check username = request.user.username if not is_group_admin(library_group_id, username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # modify permission try: seafile_api.set_folder_group_perm(repo_id, path, perm, group_id) send_perm_audit_msg('modify-repo-perm', username, group_id, repo_id, path, perm) new_perm = seafile_api.get_folder_group_perm(repo_id, path, group_id) result = self._get_group_folder_perm_info(group_id, repo_id, path, new_perm) return Response(result) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
def put(self, request, repo_id): """ Copy a single file/folder to other place. """ if not request.user.admin_permissions.can_manage_library(): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') # check parameter for src path = request.GET.get('path', None) if not path: error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: dirent = seafile_api.get_dirent_by_path(repo_id, path) 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 dirent: error_msg = 'File or folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if path == '/': error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # normalize path to '/1/2/3' format # NOT ends with '/' path = normalize_file_path(path) # now get `src_dir` and `obj_name` according to normalized path src_repo_id = repo_id src_dir = os.path.dirname(path) src_obj_name = os.path.basename(path) # check parameter for dst dst_repo_id = request.data.get('dst_repo_id', src_repo_id) if dst_repo_id != src_repo_id and not seafile_api.get_repo( dst_repo_id): error_msg = 'Library %s not found.' % dst_repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) dst_dir = request.data.get('dst_dir', '/') if dst_dir != '/': dst_dir = normalize_dir_path(dst_dir) if not seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir): error_msg = 'Folder %s not found.' % dst_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # copy file username = request.user.username dst_obj_name = check_filename_with_rename(dst_repo_id, dst_dir, src_obj_name) try: seafile_api.copy_file(src_repo_id, src_dir, src_obj_name, dst_repo_id, dst_dir, dst_obj_name, username, need_progress=0, synchronous=1) except SearpcError 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, 'dst_item_name': dst_obj_name})
def convert_repo_path_when_can_not_view_folder(request, repo_id, path): content_type = 'application/json; charset=utf-8' path = normalize_dir_path(path) username = request.user.username converted_repo_path = seafile_api.convert_repo_path( repo_id, path, username) if not converted_repo_path: err_msg = _('Permission denied.') return HttpResponse(json.dumps({'error': err_msg}), status=403, content_type=content_type) converted_repo_path = json.loads(converted_repo_path) repo_id = converted_repo_path['repo_id'] repo = seafile_api.get_repo(repo_id) if not repo: err_msg = 'Library not found.' return HttpResponse(json.dumps({'error': err_msg}), status=404, content_type=content_type) path = converted_repo_path['path'] path = normalize_dir_path(path) dir_id = seafile_api.get_dir_id_by_path(repo.id, path) if not dir_id: err_msg = 'Folder not found.' return HttpResponse(json.dumps({'error': err_msg}), status=404, content_type=content_type) group_id = '' if 'group_id' in converted_repo_path: group_id = converted_repo_path['group_id'] if not ccnet_api.get_group(group_id): err_msg = 'Group not found.' return HttpResponse(json.dumps({'error': err_msg}), status=404, content_type=content_type) if not is_group_member(group_id, username): err_msg = _('Permission denied.') return HttpResponse(json.dumps({'error': err_msg}), status=403, content_type=content_type) user_perm = check_folder_permission(request, repo_id, path) if not user_perm: err_msg = _('Permission denied.') return HttpResponse(json.dumps({'error': err_msg}), status=403, content_type=content_type) if not group_id: next_url = '#shared-libs/lib/%s/%s' % (repo_id, path.strip('/')) else: next_url = '#group/%s/lib/%s/%s' % (group_id, repo_id, path.strip('/')) return HttpResponse(json.dumps({'next_url': next_url}), content_type=content_type)
def list_lib_dir(request, repo_id): ''' New ajax API for list library directory ''' content_type = 'application/json; charset=utf-8' result = {} repo = get_repo(repo_id) if not repo: err_msg = _('Library does not exist.') return HttpResponse(json.dumps({'error': err_msg}), status=400, content_type=content_type) username = request.user.username path = request.GET.get('p', '/') path = normalize_dir_path(path) dir_id = seafile_api.get_dir_id_by_path(repo.id, path) if not dir_id: err_msg = 'Folder not found.' return HttpResponse(json.dumps({'error': err_msg}), status=404, content_type=content_type) # perm for current dir user_perm = check_folder_permission(request, repo_id, path) if not user_perm: return convert_repo_path_when_can_not_view_folder( request, repo_id, path) if repo.encrypted \ and not seafile_api.is_password_set(repo.id, username): err_msg = _('Library is encrypted.') return HttpResponse(json.dumps({ 'error': err_msg, 'lib_need_decrypt': True }), status=403, content_type=content_type) head_commit = get_commit(repo.id, repo.version, repo.head_cmmt_id) if not head_commit: err_msg = _('Error: no head commit id') return HttpResponse(json.dumps({'error': err_msg}), status=500, content_type=content_type) dir_list = [] file_list = [] dirs = seafserv_threaded_rpc.list_dir_with_perm(repo_id, path, dir_id, username, -1, -1) starred_files = get_dir_starred_files(username, repo_id, path) for dirent in dirs: dirent.last_modified = dirent.mtime if stat.S_ISDIR(dirent.mode): dpath = posixpath.join(path, dirent.obj_name) if dpath[-1] != '/': dpath += '/' dir_list.append(dirent) else: if repo.version == 0: file_size = seafile_api.get_file_size(repo.store_id, repo.version, dirent.obj_id) else: file_size = dirent.size dirent.file_size = file_size if file_size else 0 dirent.starred = False fpath = posixpath.join(path, dirent.obj_name) if fpath in starred_files: dirent.starred = True file_list.append(dirent) if is_org_context(request): repo_owner = seafile_api.get_org_repo_owner(repo.id) else: repo_owner = seafile_api.get_repo_owner(repo.id) result["repo_owner"] = repo_owner result["is_repo_owner"] = False result["has_been_shared_out"] = False result["is_admin"] = is_repo_admin(username, repo_id) if repo_owner == username: result["is_repo_owner"] = True try: result["has_been_shared_out"] = repo_has_been_shared_out( request, repo_id) except Exception as e: logger.error(e) if result["is_admin"]: result["has_been_shared_out"] = True result["is_virtual"] = repo.is_virtual result["repo_name"] = repo.name result["user_perm"] = user_perm # check quota for fileupload result["no_quota"] = True if seaserv.check_quota(repo.id) < 0 else False result["encrypted"] = repo.encrypted dirent_list = [] for d in dir_list: d_ = {} d_['is_dir'] = True d_['obj_name'] = d.obj_name d_['last_modified'] = d.last_modified d_['last_update'] = translate_seahub_time(d.last_modified) d_['p_dpath'] = posixpath.join(path, d.obj_name) d_['perm'] = d.permission # perm for sub dir in current dir dirent_list.append(d_) size = int(request.GET.get('thumbnail_size', THUMBNAIL_DEFAULT_SIZE)) for f in file_list: f_ = {} f_['is_file'] = True f_['obj_name'] = f.obj_name f_['last_modified'] = f.last_modified f_['last_update'] = translate_seahub_time(f.last_modified) f_['starred'] = f.starred f_['file_size'] = filesizeformat(f.file_size) f_['obj_id'] = f.obj_id f_['perm'] = f.permission # perm for file in current dir if not repo.encrypted and ENABLE_THUMBNAIL: # used for providing a way to determine # if send a request to create thumbnail. fileExt = os.path.splitext(f.obj_name)[1][1:].lower() file_type = FILEEXT_TYPE_MAP.get(fileExt) if file_type == IMAGE: f_['is_img'] = True if file_type == VIDEO and ENABLE_VIDEO_THUMBNAIL: f_['is_video'] = True if file_type == XMIND: f_['is_xmind'] = True if file_type in (IMAGE, XMIND) or \ file_type == VIDEO and ENABLE_VIDEO_THUMBNAIL: # if thumbnail has already been created, return its src. # Then web browser will use this src to get thumbnail instead of # recreating it. thumbnail_file_path = os.path.join(THUMBNAIL_ROOT, str(size), f.obj_id) thumbnail_exist = os.path.exists(thumbnail_file_path) if thumbnail_exist: file_path = posixpath.join(path, f.obj_name) src = get_thumbnail_src(repo_id, size, file_path) f_['encoded_thumbnail_src'] = urlquote(src) if is_pro_version(): f_['is_locked'] = True if f.is_locked else False f_['lock_owner'] = f.lock_owner f_['lock_owner_name'] = email2nickname(f.lock_owner) f_['locked_by_me'] = False if f.lock_owner == username: f_['locked_by_me'] = True if f.lock_owner == ONLINE_OFFICE_LOCK_OWNER and \ user_perm == PERMISSION_READ_WRITE: f_['locked_by_me'] = True dirent_list.append(f_) result["dirent_list"] = dirent_list return HttpResponse(json.dumps(result), content_type=content_type)
def post(self, request): """ Multi create folders. Permission checking: 1. user with `rw` permission for every layer of subdirectories. Parameter: { "repo_id": "4dfdf5b6-806f-4a35-b2b7-604051d2114e", "paths": ["/1/2/", "/3/4/", "/5/6"] } """ # 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) repo_id = request.data.get('repo_id', None) if not repo_id: error_msg = 'repo_id invalid.' 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) # permission check if check_folder_permission(request, repo_id, '/') != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) result = {} result['failed'] = [] result['success'] = [] username = request.user.username for path in path_list: common_dict = { 'repo_id': repo_id, 'path': path, } path = normalize_dir_path(path) obj_name_list = path.strip('/').split('/') for obj_name in obj_name_list: try: # check if path is valid is_valid_name = seafile_api.is_valid_filename( 'fake_repo_id', obj_name) 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 if not is_valid_name: error_dict = {'error_msg': 'path invalid.'} common_dict.update(error_dict) result['failed'].append(common_dict) continue if seafile_api.get_dir_id_by_path(repo_id, path): error_dict = {'error_msg': 'Folder already exists.'} common_dict.update(error_dict) result['failed'].append(common_dict) continue # check parent directory's permission parent_dir = os.path.dirname(path.rstrip('/')) try: permission = get_folder_permission_recursively( username, repo_id, parent_dir) 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 if permission != 'rw': error_dict = {'error_msg': 'Permission denied.'} common_dict.update(error_dict) result['failed'].append(common_dict) continue try: # TODO # move seafile_api.mkdir_with_parents() to CE version # rename obj name if name is existed seafile_api.mkdir_with_parents(repo_id, '/', path.strip('/'), username) 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 get(self, request, slug): """List all dir files in a wiki. """ try: wiki = Wiki.objects.get(slug=slug) except Wiki.DoesNotExist: error_msg = "Wiki not found." return api_error(status.HTTP_404_NOT_FOUND, error_msg) # perm check if not wiki.has_read_perm(request): error_msg = "Permission denied" return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: repo = seafile_api.get_repo(wiki.repo_id) if not repo: error_msg = "Wiki library not found." return api_error(status.HTTP_404_NOT_FOUND, error_msg) except SearpcError: error_msg = "Internal Server Error" return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 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) parent_dir = request.GET.get("p", '/') parent_dir = normalize_dir_path(parent_dir) dir_id = seafile_api.get_dir_id_by_path(repo.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) 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_dirs_info = [] for parent_dir in parent_dir_list: all_dirs = get_wiki_dirs_by_path(repo.repo_id, parent_dir, []) all_dirs_info += all_dirs return Response({"dirent_list": all_dirs_info})
def get(self, request): """ Get all share links of a user. Permission checking: 1. default(NOT guest) user; """ username = request.user.username repo_id = request.GET.get('repo_id', '') path = request.GET.get('path', '') fileshares = [] # get all share links of current user if not repo_id and not path: fileshares = FileShare.objects.filter(username=username) # share links in repo if repo_id and not path: 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) fileshares = FileShare.objects.filter(username=username) \ .filter(repo_id=repo_id) # share links by repo and path if repo_id and path: 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) if path != '/': dirent = seafile_api.get_dirent_by_path(repo_id, path) if not dirent: error_msg = 'Dirent %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if stat.S_ISDIR(dirent.mode): path = normalize_dir_path(path) else: path = normalize_file_path(path) fileshares = FileShare.objects.filter(username=username) \ .filter(repo_id=repo_id) \ .filter(path=path) repo_folder_permission_dict = {} for fileshare in fileshares: if fileshare.s_type == 'd': folder_path = normalize_dir_path(fileshare.path) else: file_path = normalize_file_path(fileshare.path) folder_path = os.path.dirname(file_path) repo_id = fileshare.repo_id if repo_id not in repo_folder_permission_dict: try: permission = seafile_api.check_permission_by_path(repo_id, folder_path, fileshare.username) except Exception as e: logger.error(e) permission = '' repo_folder_permission_dict[repo_id] = permission links_info = [] for fs in fileshares: link_info = get_share_link_info(fs) link_info['repo_folder_permission'] = repo_folder_permission_dict.get(link_info['repo_id'], '') links_info.append(link_info) if len(links_info) == 1: result = links_info else: dir_list = [x for x in links_info if x['is_dir']] file_list = [x for x in links_info if not x['is_dir']] dir_list.sort(key=lambda x: x['obj_name']) file_list.sort(key=lambda x: x['obj_name']) result = dir_list + file_list return Response(result)
def post(self, request, repo_id, format=None): """ Create, rename, move, copy, revert file Permission checking: 1. create: user with 'rw' permission for current parent dir; 2. rename: user with 'rw' permission for current file; 3. move : user with 'rw' permission for current file, 'rw' permission for dst parent dir; 4. copy : user with 'r' permission for current file, 'rw' permission for dst parent dir; 4. revert: user with 'rw' permission for current file's parent dir; """ # argument check path = request.GET.get('p', None) if not path: error_msg = 'p invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) path = normalize_file_path(path) 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 ('create', 'rename', 'move', 'copy', 'revert'): error_msg = "operation can only be 'create', 'rename', 'move', 'copy' 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) username = request.user.username parent_dir = os.path.dirname(path) is_draft = request.POST.get('is_draft', '') if operation == 'create': # resource check try: parent_dir_id = seafile_api.get_dir_id_by_path(repo_id, parent_dir) 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 parent_dir_id: error_msg = 'Folder %s not found.' % parent_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if parse_repo_perm(check_folder_permission(request, repo_id, parent_dir)).can_edit_on_web is False: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if is_draft.lower() == 'true': file_name = os.path.basename(path) file_dir = os.path.dirname(path) draft_type = os.path.splitext(file_name)[0][-7:] file_type = os.path.splitext(file_name)[-1] if draft_type != '(draft)': f = os.path.splitext(file_name)[0] path = file_dir + '/' + f + '(draft)' + file_type # create new empty file new_file_name = os.path.basename(path) if not is_valid_dirent_name(new_file_name): return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.') new_file_name = check_filename_with_rename(repo_id, parent_dir, new_file_name) try: seafile_api.post_empty_file(repo_id, parent_dir, new_file_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) if is_draft.lower() == 'true': Draft.objects.add(username, repo, path, file_exist=False) # update office file by template if new_file_name.endswith('.xlsx'): empty_file_path = os.path.join(OFFICE_TEMPLATE_ROOT, 'empty.xlsx') elif new_file_name.endswith('.pptx'): empty_file_path = os.path.join(OFFICE_TEMPLATE_ROOT, 'empty.pptx') elif new_file_name.endswith('.docx'): empty_file_path = os.path.join(OFFICE_TEMPLATE_ROOT, 'empty.docx') else: empty_file_path = '' if empty_file_path: # get file server update url update_token = seafile_api.get_fileserver_access_token( repo_id, 'dummy', 'update', username) if not update_token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) update_url = gen_inner_file_upload_url('update-api', update_token) # update file new_file_path = posixpath.join(parent_dir, new_file_name) try: requests.post( update_url, data={'filename': new_file_name, 'target_file': new_file_path}, files={'file': open(empty_file_path, 'rb')} ) except Exception as e: logger.error(e) new_file_path = posixpath.join(parent_dir, new_file_name) file_info = self.get_file_info(username, repo_id, new_file_path) return Response(file_info) if operation == 'rename': # argument check new_file_name = request.data.get('newname', None) if not new_file_name: error_msg = 'newname invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not is_valid_dirent_name(new_file_name): return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.') if len(new_file_name) > MAX_UPLOAD_FILE_NAME_LEN: error_msg = 'newname is too long.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) oldname = os.path.basename(path) if oldname == new_file_name: error_msg = 'The new name is the same to the old' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check try: file_id = seafile_api.get_file_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 file_id: error_msg = 'File %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if parse_repo_perm(check_folder_permission(request, repo_id, parent_dir)).can_edit_on_web is False: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check file lock try: is_locked, locked_by_me = check_file_lock(repo_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) if is_locked and not locked_by_me: error_msg = _("File is locked") return api_error(status.HTTP_403_FORBIDDEN, error_msg) # rename file new_file_name = check_filename_with_rename(repo_id, parent_dir, new_file_name) try: seafile_api.rename_file(repo_id, parent_dir, oldname, new_file_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_file_path = posixpath.join(parent_dir, new_file_name) # rename draft file filetype, fileext = get_file_type_and_ext(new_file_name) if filetype == MARKDOWN or filetype == TEXT: is_draft = is_draft_file(repo.id, path) review = get_file_draft(repo.id, path, is_draft) draft_id = review['draft_id'] if is_draft: try: draft = Draft.objects.get(pk=draft_id) draft.draft_file_path = new_file_path draft.save() except Draft.DoesNotExist: pass file_info = self.get_file_info(username, repo_id, new_file_path) return Response(file_info) if operation == 'move': # argument check dst_repo_id = request.data.get('dst_repo', None) dst_dir = request.data.get('dst_dir', None) if not dst_repo_id: error_msg = 'dst_repo invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not dst_dir: error_msg = 'dst_dir invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) dst_dir = normalize_dir_path(dst_dir) # resource check for source file try: file_id = seafile_api.get_file_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 file_id: error_msg = 'File %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # resource check for dst repo and dir 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) dst_dir_id = seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir) if not dst_dir_id: error_msg = 'Folder %s not found.' % dst_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check for source file src_repo_id = repo_id src_dir = os.path.dirname(path) if check_folder_permission(request, src_repo_id, src_dir) != PERMISSION_READ_WRITE: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # permission check for dst dir if check_folder_permission(request, dst_repo_id, dst_dir) != PERMISSION_READ_WRITE: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check file lock try: is_locked, locked_by_me = check_file_lock(repo_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) if is_locked and not locked_by_me: error_msg = _("File is locked") return api_error(status.HTTP_403_FORBIDDEN, error_msg) # move file if src_repo_id == dst_repo_id and src_dir == dst_dir: file_info = self.get_file_info(username, repo_id, path) return Response(file_info) filename = os.path.basename(path) new_file_name = check_filename_with_rename(dst_repo_id, dst_dir, filename) try: seafile_api.move_file(src_repo_id, src_dir, filename, dst_repo_id, dst_dir, new_file_name, replace=False, username=username, need_progress=0, synchronous=1) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) dst_file_path = posixpath.join(dst_dir, new_file_name) dst_file_info = self.get_file_info(username, dst_repo_id, dst_file_path) return Response(dst_file_info) if operation == 'copy': # argument check dst_repo_id = request.data.get('dst_repo', None) dst_dir = request.data.get('dst_dir', None) if not dst_repo_id: error_msg = 'dst_repo_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not dst_dir: error_msg = 'dst_dir invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) dst_dir = normalize_dir_path(dst_dir) # resource check for source file try: file_id = seafile_api.get_file_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 file_id: error_msg = 'File %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # resource check for dst repo and dir 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) dst_dir_id = seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir) if not dst_dir_id: error_msg = 'Folder %s not found.' % dst_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check for source file src_repo_id = repo_id src_dir = os.path.dirname(path) if parse_repo_perm(check_folder_permission( request, src_repo_id, src_dir)).can_copy is False: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # permission check for dst dir if check_folder_permission(request, dst_repo_id, dst_dir) != PERMISSION_READ_WRITE: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) filename = os.path.basename(path) new_file_name = check_filename_with_rename(dst_repo_id, dst_dir, filename) try: seafile_api.copy_file(src_repo_id, src_dir, filename, dst_repo_id, dst_dir, new_file_name, username, 0, synchronous=1) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) dst_file_path = posixpath.join(dst_dir, new_file_name) dst_file_info = self.get_file_info(username, dst_repo_id, dst_file_path) return Response(dst_file_info) 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_file_id_by_path(repo_id, path): # file exists in repo if check_folder_permission(request, repo_id, parent_dir) != PERMISSION_READ_WRITE: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check file lock try: is_locked, locked_by_me = check_file_lock(repo_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) if is_locked and not locked_by_me: error_msg = _("File is locked") return api_error(status.HTTP_403_FORBIDDEN, error_msg) else: # file NOT exists in repo if check_folder_permission(request, repo_id, '/') != PERMISSION_READ_WRITE: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: seafile_api.revert_file(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 get(self, request, token): """ Only used for get dirents in a folder share link. Permission checking: 1, If enable SHARE_LINK_LOGIN_REQUIRED, user must have been authenticated. 2, If enable ENABLE_SHARE_LINK_AUDIT, user must have been authenticated, or have been audited. 3, If share link is encrypted, share link password must have been checked. """ # argument check 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) # permission check # check if login required if SHARE_LINK_LOGIN_REQUIRED and \ not request.user.is_authenticated(): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check share link audit if is_pro_version() and ENABLE_SHARE_LINK_AUDIT and \ not request.user.is_authenticated() and \ not request.session.get('anonymous_email'): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # resource check try: share_link = FileShare.objects.get(token=token) except FileShare.DoesNotExist: error_msg = 'Share link %s not found.' % token return api_error(status.HTTP_404_NOT_FOUND, error_msg) # check share link password if share_link.is_encrypted() and not check_share_link_access(request, token): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if share_link.s_type != 'd': error_msg = 'Share link %s is not a folder share link.' % token return api_error(status.HTTP_400_BAD_REQUEST, error_msg) repo_id = share_link.repo_id 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) share_link_path = share_link.path request_path = request.GET.get('path', '/') if request_path == '/': path = share_link_path else: path = posixpath.join(share_link_path, request_path.strip('/')) path = normalize_dir_path(path) dir_id = seafile_api.get_dir_id_by_path(repo_id, path) if not dir_id: error_msg = 'Folder %s not found.' % request_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: current_commit = seafile_api.get_commit_list(repo_id, 0, 1)[0] dirent_list = seafile_api.list_dir_by_commit_and_path(repo_id, current_commit.id, path, -1, -1) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) result = [] for dirent in dirent_list: # don't return parent folder(share link path) info to user # so use request_path here dirent_path = posixpath.join(request_path, dirent.obj_name) dirent_info = {} dirent_info['size'] = dirent.size dirent_info['last_modified'] = timestamp_to_isoformat_timestr(dirent.mtime) if stat.S_ISDIR(dirent.mode): dirent_info['is_dir'] = True dirent_info['folder_path'] = normalize_dir_path(dirent_path) dirent_info['folder_name'] = dirent.obj_name else: dirent_info['is_dir'] = False dirent_info['file_path'] = normalize_file_path(dirent_path) dirent_info['file_name'] = dirent.obj_name file_type, file_ext = get_file_type_and_ext(dirent.obj_name) if file_type in (IMAGE, XMIND) or \ file_type == VIDEO and ENABLE_VIDEO_THUMBNAIL: if os.path.exists(os.path.join(THUMBNAIL_ROOT, str(thumbnail_size), dirent.obj_id)): req_image_path = posixpath.join(request_path, dirent.obj_name) src = get_share_link_thumbnail_src(token, thumbnail_size, req_image_path) dirent_info['encoded_thumbnail_src'] = urlquote(src) result.append(dirent_info) return Response({'dirent_list': result})
def get(self, request, slug): """List all dir files in a wiki. """ try: wiki = Wiki.objects.get(slug=slug) except Wiki.DoesNotExist: error_msg = "Wiki not found." return api_error(status.HTTP_404_NOT_FOUND, error_msg) # perm check if not wiki.has_read_perm(request): error_msg = "Permission denied" return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: repo = seafile_api.get_repo(wiki.repo_id) if not repo: error_msg = "Wiki library not found." return api_error(status.HTTP_404_NOT_FOUND, error_msg) except SearpcError: error_msg = "Internal Server Error" return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 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) parent_dir = request.GET.get("p", '/') parent_dir = normalize_dir_path(parent_dir) dir_id = seafile_api.get_dir_id_by_path(repo.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) 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_dirs_info = [] for parent_dir in parent_dir_list: all_dirs = get_wiki_dirs_by_path(repo.repo_id, parent_dir, []) all_dirs_info += all_dirs return Response({ "dirent_list": all_dirs_info })
def get_dir_link_by_path(self, username, repo_id, path): path = normalize_dir_path(path) return self._get_file_share_by_path(username, repo_id, path)
def post(self, request, format=None): """ Only used for download dirents in a folder share link. Permission checking: 1, If enable SHARE_LINK_LOGIN_REQUIRED, user must have been authenticated. 2, If enable ENABLE_SHARE_LINK_AUDIT, user must have been authenticated, or have been audited. 3, If share link is encrypted, share link password must have been checked. """ # argument check share_link_token = request.data.get('token', None) if not share_link_token: error_msg = 'share_link_token invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) parent_dir = request.data.get('parent_dir', '/') if not parent_dir: error_msg = 'parent_dir invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) dirent_name_list = request.data.get('dirents', None) if not dirent_name_list: error_msg = 'dirent_name invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check try: share_link= FileShare.objects.get(token=share_link_token) except FileShare.DoesNotExist: error_msg = 'Share link %s not found.' % share_link_token return api_error(status.HTTP_404_NOT_FOUND, error_msg) if share_link.s_type != 'd': error_msg = 'Share link %s is not a folder share link.' % share_link_token return api_error(status.HTTP_400_BAD_REQUEST, error_msg) repo_id = share_link.repo_id 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) full_parent_dir = posixpath.join(normalize_dir_path(share_link.path), parent_dir.strip('/')) full_parent_dir = normalize_dir_path(full_parent_dir) dir_id = seafile_api.get_dir_id_by_path(repo_id, full_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 # check if login required if SHARE_LINK_LOGIN_REQUIRED and \ not request.user.is_authenticated(): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check share link audit if is_pro_version() and ENABLE_SHARE_LINK_AUDIT and \ not request.user.is_authenticated() and \ not request.session.get('anonymous_email'): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check share link password if share_link.is_encrypted() and not check_share_link_access(request, share_link_token): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check if has download permission for share link creator if not parse_repo_perm(seafile_api.check_permission_by_path( repo_id, full_parent_dir, share_link.username)).can_download: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check if share link has download permission if not share_link.get_permissions()['can_download']: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # get file server access token is_windows = 0 if is_windows_operating_system(request): is_windows = 1 dirent_list = [] total_size = 0 for dirent_name in dirent_name_list: dirent_name = dirent_name.strip('/') full_dirent_path = posixpath.join(full_parent_dir, dirent_name) current_dirent = seafile_api.get_dirent_by_path(repo_id, full_dirent_path) if not current_dirent: continue if stat.S_ISDIR(current_dirent.mode): total_size += seafile_api.get_dir_size(repo.store_id, repo.version, current_dirent.obj_id) else: total_size += current_dirent.size dirent_list.append(dirent_name) if total_size > seaserv.MAX_DOWNLOAD_DIR_SIZE: error_msg = _('Total size exceeds limit.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not dirent_list: error_msg = 'No valid dirent.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) fake_obj_id = { 'parent_dir': full_parent_dir, 'file_list': dirent_list, 'is_windows': is_windows } try: zip_token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), 'download-multi', '', use_onetime=settings.FILESERVER_TOKEN_ONCE_ONLY) 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 zip_token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return Response({'zip_token': zip_token})
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)
class FileView(APIView): """ Support uniform interface for file related operations, including create/delete/rename/view, etc. """ authentication_classes = (TokenAuthentication, SessionAuthentication) permission_classes = (IsAuthenticated, ) throttle_classes = (UserRateThrottle, ) def get_file_info(self, username, repo_id, file_path): file_obj = seafile_api.get_dirent_by_path(repo_id, file_path) try: is_locked, locked_by_me = check_file_lock(repo_id, file_path, username) except Exception as e: logger.error(e) is_locked = False file_info = { 'type': 'file', 'repo_id': repo_id, 'parent_dir': os.path.dirname(file_path), 'obj_name': file_obj.obj_name, 'obj_id': file_obj.obj_id, 'size': file_obj.size, 'mtime': timestamp_to_isoformat_timestr(file_obj.mtime), 'is_locked': is_locked, } return file_info def get(self, request, repo_id, format=None): """ Get file info. Permission checking: 1. user with either 'r' or 'rw' permission. """ # argument check path = request.GET.get('p', None) if not path: error_msg = 'p invalid.' 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) try: file_id = seafile_api.get_file_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 file_id: error_msg = 'File %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check parent_dir = os.path.dirname(path) if check_folder_permission(request, repo_id, parent_dir) is None: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) file_info = self.get_file_info(request.user.username, repo_id, path) return Response(file_info) def post(self, request, repo_id, format=None): """ Create, rename, move, copy, revert file Permission checking: 1. create: user with 'rw' permission for current parent dir; 2. rename: user with 'rw' permission for current file; 3. move : user with 'rw' permission for current file, 'rw' permission for dst parent dir; 4. copy : user with 'r' permission for current file, 'rw' permission for dst parent dir; 4. revert: user with 'rw' permission for current file's parent dir; """ # argument check path = request.GET.get('p', None) if not path: error_msg = 'p invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) path = normalize_file_path(path) 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 ('create', 'rename', 'move', 'copy', 'revert'): error_msg = "operation can only be 'create', 'rename', 'move', 'copy' 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) username = request.user.username parent_dir = os.path.dirname(path) if operation == 'create': # resource check try: parent_dir_id = seafile_api.get_dir_id_by_path( repo_id, parent_dir) 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 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) # create new empty file new_file_name = os.path.basename(path) if not is_valid_dirent_name(new_file_name): return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.') new_file_name = check_filename_with_rename(repo_id, parent_dir, new_file_name) try: seafile_api.post_empty_file(repo_id, parent_dir, new_file_name, username) except SearpcError, e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # update office file by template if new_file_name.endswith('.xlsx'): empty_file_path = os.path.join(OFFICE_TEMPLATE_ROOT, 'empty.xlsx') elif new_file_name.endswith('.pptx'): empty_file_path = os.path.join(OFFICE_TEMPLATE_ROOT, 'empty.pptx') elif new_file_name.endswith('.docx'): empty_file_path = os.path.join(OFFICE_TEMPLATE_ROOT, 'empty.docx') else: empty_file_path = '' if empty_file_path: # get file server update url update_token = seafile_api.get_fileserver_access_token( repo_id, 'dummy', 'update', username) if not update_token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) update_url = gen_inner_file_upload_url('update-api', update_token) # update file new_file_path = posixpath.join(parent_dir, new_file_name) try: requests.post(update_url, data={ 'filename': new_file_name, 'target_file': new_file_path }, files={'file': open(empty_file_path, 'rb')}) except Exception as e: logger.error(e) new_file_path = posixpath.join(parent_dir, new_file_name) file_info = self.get_file_info(username, repo_id, new_file_path) return Response(file_info) if operation == 'rename': # argument check new_file_name = request.data.get('newname', None) if not new_file_name: error_msg = 'newname invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not is_valid_dirent_name(new_file_name): return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.') if len(new_file_name) > MAX_UPLOAD_FILE_NAME_LEN: error_msg = 'newname is too long.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) oldname = os.path.basename(path) if oldname == new_file_name: error_msg = 'The new name is the same to the old' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check try: file_id = seafile_api.get_file_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 file_id: error_msg = 'File %s not found.' % path 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) # check file lock try: is_locked, locked_by_me = check_file_lock( repo_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) if is_locked and not locked_by_me: error_msg = _("File is locked") return api_error(status.HTTP_403_FORBIDDEN, error_msg) # rename file new_file_name = check_filename_with_rename(repo_id, parent_dir, new_file_name) try: seafile_api.rename_file(repo_id, parent_dir, oldname, new_file_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_file_path = posixpath.join(parent_dir, new_file_name) file_info = self.get_file_info(username, repo_id, new_file_path) return Response(file_info) if operation == 'move': # argument check dst_repo_id = request.data.get('dst_repo', None) dst_dir = request.data.get('dst_dir', None) if not dst_repo_id: error_msg = 'dst_repo invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not dst_dir: error_msg = 'dst_dir invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) dst_dir = normalize_dir_path(dst_dir) # resource check for source file try: file_id = seafile_api.get_file_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 file_id: error_msg = 'File %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # resource check for dst repo and dir 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) dst_dir_id = seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir) if not dst_dir_id: error_msg = 'Folder %s not found.' % dst_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check for source file src_repo_id = repo_id src_dir = os.path.dirname(path) if check_folder_permission(request, src_repo_id, src_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # permission check for dst dir if check_folder_permission(request, dst_repo_id, dst_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check file lock try: is_locked, locked_by_me = check_file_lock( repo_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) if is_locked and not locked_by_me: error_msg = _("File is locked") return api_error(status.HTTP_403_FORBIDDEN, error_msg) # move file if src_repo_id == dst_repo_id and src_dir == dst_dir: file_info = self.get_file_info(username, repo_id, path) return Response(file_info) filename = os.path.basename(path) new_file_name = check_filename_with_rename(dst_repo_id, dst_dir, filename) try: seafile_api.move_file(src_repo_id, src_dir, filename, dst_repo_id, dst_dir, new_file_name, replace=False, username=username, need_progress=0, synchronous=1) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) dst_file_path = posixpath.join(dst_dir, new_file_name) dst_file_info = self.get_file_info(username, dst_repo_id, dst_file_path) return Response(dst_file_info) if operation == 'copy': # argument check dst_repo_id = request.data.get('dst_repo', None) dst_dir = request.data.get('dst_dir', None) if not dst_repo_id: error_msg = 'dst_repo_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not dst_dir: error_msg = 'dst_dir invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) dst_dir = normalize_dir_path(dst_dir) # resource check for source file try: file_id = seafile_api.get_file_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 file_id: error_msg = 'File %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # resource check for dst repo and dir 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) dst_dir_id = seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir) if not dst_dir_id: error_msg = 'Folder %s not found.' % dst_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check for source file src_repo_id = repo_id src_dir = os.path.dirname(path) if not check_folder_permission(request, src_repo_id, src_dir): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # permission check for dst dir if check_folder_permission(request, dst_repo_id, dst_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) filename = os.path.basename(path) new_file_name = check_filename_with_rename(dst_repo_id, dst_dir, filename) try: seafile_api.copy_file(src_repo_id, src_dir, filename, dst_repo_id, dst_dir, new_file_name, username, 0, synchronous=1) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) dst_file_path = posixpath.join(dst_dir, new_file_name) dst_file_info = self.get_file_info(username, dst_repo_id, dst_file_path) return Response(dst_file_info) 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_file_id_by_path(repo_id, path): # file exists in repo if check_folder_permission(request, repo_id, parent_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check file lock try: is_locked, locked_by_me = check_file_lock( repo_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) if is_locked and not locked_by_me: error_msg = _("File is locked") return api_error(status.HTTP_403_FORBIDDEN, error_msg) else: # file 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_file(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 get(self, request): """ Get smart link of a file/dir. """ # argument check repo_id = request.GET.get('repo_id', None) if not repo_id or not is_valid_repo_id_format(repo_id): error_msg = 'repo_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) path = request.GET.get('path', None) if not path: error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) is_dir = request.GET.get('is_dir', None) if not is_dir: error_msg = 'is_dir invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) is_dir = is_dir.lower() if is_dir not in ('true', 'false'): error_msg = "is_dir can only be 'true' or 'false'." 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) is_dir = to_python_boolean(is_dir) if is_dir: if not seafile_api.get_dir_id_by_path(repo_id, normalize_dir_path(path)): error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) else: if not seafile_api.get_file_id_by_path(repo_id, normalize_file_path(path)): error_msg = 'File %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if not check_folder_permission(request, repo_id, '/'): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # make sure path: # 1. starts with '/' # 2. NOT ends with '/' path = normalize_file_path(path) parent_dir = os.path.dirname(path) dirent_name = os.path.basename(path) # get file/dir uuid if repo.is_virtual: repo_id = repo.origin_repo_id path = posixpath.join(repo.origin_path, path.strip('/')) path = normalize_file_path(path) parent_dir = os.path.dirname(path) dirent_name = os.path.basename(path) try: uuid_map = FileUUIDMap.objects.get_or_create_fileuuidmap(repo_id, parent_dir, dirent_name, is_dir) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) dirent_uuid = uuid_map.uuid smart_link = gen_smart_link(dirent_uuid) result = {} result['smart_link'] = smart_link result['smart_link_token'] = dirent_uuid result['name'] = dirent_name return Response(result)
def post(self, request, repo_id, format=None): """ Add repo user folder perm. Permission checking: 1. is group admin """ # argument check path = request.data.get('folder_path', None) if not path: error_msg = 'folder_path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) perm = request.data.get('permission', None) if not perm or perm not in [PERMISSION_READ, PERMISSION_READ_WRITE]: error_msg = 'permission invalid.' 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 = normalize_dir_path(path) if not seafile_api.get_dir_id_by_path(repo_id, path): error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) repo_owner = get_repo_owner(request, repo_id) group_id = get_group_id_by_repo_owner(repo_owner) if not ccnet_api.get_group(group_id): error_msg = 'Group %s not found.' % group_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check username = request.user.username if not is_group_admin(group_id, username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # add repo user folder perm result = {} result['failed'] = [] result['success'] = [] users = request.data.getlist('user_email') for user in users: if not is_valid_username(user): result['failed'].append({ 'user_email': user, 'error_msg': 'user_email invalid.' }) continue try: User.objects.get(email=user) except User.DoesNotExist: result['failed'].append({ 'user_email': user, 'error_msg': 'User %s not found.' % user }) continue permission = seafile_api.get_folder_user_perm(repo_id, path, user) if permission: result['failed'].append({ 'user_email': user, 'error_msg': _(u'Permission already exists.') }) continue try: seafile_api.add_folder_user_perm(repo_id, path, perm, user) send_perm_audit_msg('add-repo-perm', username, user, repo_id, path, perm) except Exception as e: logger.error(e) result['failed'].append({ 'user_email': user, 'error_msg': 'Internal Server Error' }) new_perm = seafile_api.get_folder_user_perm(repo_id, path, user) new_perm_info = self._get_user_folder_perm_info( user, repo_id, path, new_perm) result['success'].append(new_perm_info) return Response(result)
def post(self, request): """ Multi create folders. Permission checking: 1. user with `rw` permission for every layer of subdirectories. Parameter: { "repo_id": "4dfdf5b6-806f-4a35-b2b7-604051d2114e", "paths": ["/1/2/", "/3/4/", "/5/6"] } """ # 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) repo_id = request.data.get('repo_id', None) if not repo_id: error_msg = 'repo_id invalid.' 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) # permission check if check_folder_permission(request, repo_id, '/') != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) result = {} result['failed'] = [] result['success'] = [] username = request.user.username for path in path_list: common_dict = { 'repo_id': repo_id, 'path': path, } path = normalize_dir_path(path) obj_name_list = path.strip('/').split('/') for obj_name in obj_name_list: try: # check if path is valid is_valid_name = seafile_api.is_valid_filename( 'fake_repo_id', obj_name) 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 if not is_valid_name: error_dict = { 'error_msg': 'path invalid.' } common_dict.update(error_dict) result['failed'].append(common_dict) continue if seafile_api.get_dir_id_by_path(repo_id, path): error_dict = { 'error_msg': 'Folder already exists.' } common_dict.update(error_dict) result['failed'].append(common_dict) continue # check parent directory's permission parent_dir = os.path.dirname(path.rstrip('/')) try: permission = get_folder_permission_recursively( username, repo_id, parent_dir) 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 if permission != 'rw': error_dict = { 'error_msg': 'Permission denied.' } common_dict.update(error_dict) result['failed'].append(common_dict) continue try: # rename obj name if name is existed seafile_api.mkdir_with_parents(repo_id, '/', path.strip('/'), username) 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 view_shared_dir(request, fileshare): token = fileshare.token password_check_passed, err_msg = check_share_link_common( request, fileshare) if not password_check_passed: d = { 'token': token, 'view_name': 'view_shared_dir', 'err_msg': err_msg } return render(request, 'share_access_validation.html', d) username = fileshare.username repo_id = fileshare.repo_id # Get path from frontend, use '/' if missing, and construct request path # with fileshare.path to real path, used to fetch dirents by RPC. req_path = request.GET.get('p', '/') req_path = normalize_dir_path(req_path) if req_path == '/': real_path = fileshare.path else: real_path = posixpath.join(fileshare.path, req_path.lstrip('/')) real_path = normalize_dir_path(real_path) repo = get_repo(repo_id) if not repo: raise Http404 if repo.encrypted or not \ seafile_api.check_permission_by_path(repo_id, '/', username): return render_error(request, _('Permission denied')) # Check path still exist, otherwise show error if not seafile_api.get_dir_id_by_path(repo.id, fileshare.path): return render_error(request, _('"%s" does not exist.') % fileshare.path) if fileshare.path == '/': # use repo name as dir name if share whole library dir_name = repo.name else: dir_name = os.path.basename(real_path[:-1]) current_commit = seaserv.get_commits(repo_id, 0, 1)[0] file_list, dir_list, dirent_more = get_repo_dirents( request, repo, current_commit, real_path) # generate dir navigator if fileshare.path == '/': zipped = gen_path_link(req_path, repo.name) else: zipped = gen_path_link(req_path, os.path.basename(fileshare.path[:-1])) if req_path == '/': # When user view the root of shared dir.. # increase shared link view_cnt, fileshare = FileShare.objects.get(token=token) fileshare.view_cnt = F('view_cnt') + 1 fileshare.save() permissions = fileshare.get_permissions() # mode to view dir/file items mode = request.GET.get('mode', 'list') if mode != 'list': mode = 'grid' thumbnail_size = THUMBNAIL_DEFAULT_SIZE if mode == 'list' else THUMBNAIL_SIZE_FOR_GRID for f in file_list: file_type, file_ext = get_file_type_and_ext(f.obj_name) if file_type == IMAGE: f.is_img = True if file_type == VIDEO: f.is_video = True if file_type in (IMAGE, XMIND) or \ (file_type == VIDEO and ENABLE_VIDEO_THUMBNAIL): if os.path.exists( os.path.join(THUMBNAIL_ROOT, str(thumbnail_size), f.obj_id)): req_image_path = posixpath.join(req_path, f.obj_name) src = get_share_link_thumbnail_src(token, thumbnail_size, req_image_path) f.encoded_thumbnail_src = urlquote(src) # for 'upload file' no_quota = True if seaserv.check_quota(repo_id) < 0 else False template = 'view_shared_dir_react.html' dir_share_link = request.path desc_for_ogp = _('Share link for %s.') % dir_name return render( request, template, { 'repo': repo, 'token': token, 'path': req_path, 'username': username, 'dir_name': dir_name, 'dir_path': real_path, 'file_list': file_list, 'dir_list': dir_list, 'zipped': zipped, 'traffic_over_limit': False, 'no_quota': no_quota, 'permissions': permissions, 'mode': mode, 'thumbnail_size': thumbnail_size, 'dir_share_link': dir_share_link, 'desc_for_ogp': desc_for_ogp, 'enable_share_link_report_abuse': ENABLE_SHARE_LINK_REPORT_ABUSE, 'enable_video_thumbnail': ENABLE_VIDEO_THUMBNAIL, })
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 get(self, request, repo_id, format=None): """ Get dir 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) # 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) path = request.GET.get('p', '/') path = normalize_dir_path(path) 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 permission = check_folder_permission(request, repo_id, path) if not permission: 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 if recursive == '1': result = [] username = request.user.username dir_file_list = get_dir_file_recursively(username, repo_id, path, []) if request_type == 'f': for item in dir_file_list: if item['type'] == 'file': result.append(item) elif request_type == 'd': for item in dir_file_list: if item['type'] == 'dir': result.append(item) else: result = dir_file_list resp = Response(result) resp["oid"] = dir_id resp["dir_perm"] = permission return resp return get_dir_entrys_by_id(request, repo, path, dir_id, request_type)
def put(self, request, repo_id, format=None): """ Modify repo user folder perm. Permission checking: 1. is group admin """ # argument check user = request.data.get('user_email', None) if not user: error_msg = 'user_email invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) path = request.data.get('folder_path', None) if not path: error_msg = 'folder_path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) perm = request.data.get('permission', None) if not perm or perm not in [PERMISSION_READ, PERMISSION_READ_WRITE]: error_msg = 'permission invalid.' 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 = normalize_dir_path(path) if not seafile_api.get_dir_id_by_path(repo_id, path): error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) repo_owner = get_repo_owner(request, repo_id) group_id = get_group_id_by_repo_owner(repo_owner) if not ccnet_api.get_group(group_id): error_msg = 'Group %s not found.' % group_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: User.objects.get(email=user) except User.DoesNotExist: error_msg = 'User %s not found.' % user return api_error(status.HTTP_404_NOT_FOUND, error_msg) permission = seafile_api.get_folder_user_perm(repo_id, path, user) if not permission: error_msg = 'Folder permission not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check username = request.user.username if not is_group_admin(group_id, username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # modify permission try: seafile_api.set_folder_user_perm(repo_id, path, perm, user) send_perm_audit_msg('modify-repo-perm', username, user, repo_id, path, perm) new_perm = seafile_api.get_folder_user_perm(repo_id, path, user) result = self._get_user_folder_perm_info(user, repo_id, path, new_perm) return Response(result) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
def post(self, request): """ Star a file/folder. Permission checking: 1. all authenticated user can perform this action. 2. r/rw permission """ # argument check repo_id = request.data.get('repo_id', None) if not repo_id: error_msg = 'repo_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) path = request.data.get('path', None) if not path: error_msg = 'path invalid.' 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) if seafile_api.get_dir_id_by_path(repo_id, path): is_dir = True path = normalize_dir_path(path) elif seafile_api.get_file_id_by_path(repo_id, path): is_dir = False path = normalize_file_path(path) else: error_msg = 'Item %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if not check_folder_permission(request, repo_id, '/'): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # star a item email = request.user.username starred_item = UserStarredFiles.objects.get_starred_item( email, repo_id, path) if not starred_item: org_id = None if is_org_context(request): org_id = request.user.org.org_id try: starred_item = UserStarredFiles.objects.add_starred_item( email, repo_id, path, is_dir, org_id or -1) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # get info of new starred item item_info = self.get_starred_item_info(repo, starred_item) item_info['user_email'] = email item_info['user_name'] = email2nickname(email) item_info['user_contact_email'] = email2contact_email(email) return Response(item_info)
def get(self, request, token): """ Only used for get dirents in a folder share link. Permission checking: 1, If enable SHARE_LINK_LOGIN_REQUIRED, user must have been authenticated. 2, If enable ENABLE_SHARE_LINK_AUDIT, user must have been authenticated, or have been audited. 3, If share link is encrypted, share link password must have been checked. """ # argument check 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) # permission check # check if login required if SHARE_LINK_LOGIN_REQUIRED and \ not request.user.is_authenticated(): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check share link audit if is_pro_version() and ENABLE_SHARE_LINK_AUDIT and \ not request.user.is_authenticated() and \ not request.session.get('anonymous_email'): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # resource check try: share_link= FileShare.objects.get(token=token) except FileShare.DoesNotExist: error_msg = 'Share link %s not found.' % token return api_error(status.HTTP_404_NOT_FOUND, error_msg) # check share link password if share_link.is_encrypted() and not check_share_link_access(request, token): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if share_link.s_type != 'd': error_msg = 'Share link %s is not a folder share link.' % token return api_error(status.HTTP_400_BAD_REQUEST, error_msg) repo_id = share_link.repo_id 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) share_link_path = share_link.path request_path = request.GET.get('path', '/') if request_path == '/': path = share_link_path else: path = posixpath.join(share_link_path, request_path.strip('/')) path = normalize_dir_path(path) dir_id = seafile_api.get_dir_id_by_path(repo_id, path) if not dir_id: error_msg = 'Folder %s not found.' % request_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: current_commit = seafile_api.get_commit_list(repo_id, 0, 1)[0] dirent_list = seafile_api.list_dir_by_commit_and_path(repo_id, current_commit.id, path, -1, -1) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) result = [] for dirent in dirent_list: # don't return parent folder(share link path) info to user # so use request_path here dirent_path = posixpath.join(request_path, dirent.obj_name) dirent_info = {} dirent_info['size'] = dirent.size dirent_info['last_modified'] = timestamp_to_isoformat_timestr(dirent.mtime) if stat.S_ISDIR(dirent.mode): dirent_info['is_dir'] = True dirent_info['folder_path'] = normalize_dir_path(dirent_path) dirent_info['folder_name'] = dirent.obj_name else: dirent_info['is_dir'] = False dirent_info['file_path'] = normalize_file_path(dirent_path) dirent_info['file_name'] = dirent.obj_name file_type, file_ext = get_file_type_and_ext(dirent.obj_name) if file_type in (IMAGE, XMIND) or \ file_type == VIDEO and ENABLE_VIDEO_THUMBNAIL: if os.path.exists(os.path.join(THUMBNAIL_ROOT, str(thumbnail_size), dirent.obj_id)): req_image_path = posixpath.join(request_path, dirent.obj_name) src = get_share_link_thumbnail_src(token, thumbnail_size, req_image_path) dirent_info['encoded_thumbnail_src'] = urlquote(src) result.append(dirent_info) return Response({'dirent_list': result})