def list_shared_links(request): """List shared links, and remove invalid links(file/dir is deleted or moved). """ username = request.user.username # download links fileshares = FileShare.objects.filter(username=username) p_fileshares = [] # personal file share for fs in fileshares: if is_personal_repo(fs.repo_id): # only list files in personal repos r = seafile_api.get_repo(fs.repo_id) if not r: fs.delete() continue if fs.s_type == 'f': if seafile_api.get_file_id_by_path(r.id, fs.path) is None: fs.delete() continue fs.filename = os.path.basename(fs.path) fs.shared_link = gen_file_share_link(fs.token) else: if seafile_api.get_dir_id_by_path(r.id, fs.path) is None: fs.delete() continue fs.filename = os.path.basename(fs.path.rstrip('/')) fs.shared_link = gen_dir_share_link(fs.token) fs.repo = r p_fileshares.append(fs) # upload links uploadlinks = UploadLinkShare.objects.filter(username=username) p_uploadlinks = [] for link in uploadlinks: if is_personal_repo(link.repo_id): r = seafile_api.get_repo(link.repo_id) if not r: link.delete() continue if seafile_api.get_dir_id_by_path(r.id, link.path) is None: link.delete() continue link.dir_name = os.path.basename(link.path.rstrip('/')) link.shared_link = gen_shared_upload_link(link.token) link.repo = r p_uploadlinks.append(link) return render_to_response('share/links.html', { "fileshares": p_fileshares, "uploadlinks": p_uploadlinks, }, context_instance=RequestContext(request))
def delete(self, request, repo_id): """ delete a single file/folder in a library """ 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_file_path(path) file_id = None dir_id = None try: file_id = seafile_api.get_file_id_by_path(repo_id, path) dir_id = seafile_api.get_dir_id_by_path(repo_id, path) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not file_id and not dir_id: return Response({'success': True}) parent_dir = os.path.dirname(path) file_name = os.path.basename(path) try: seafile_api.del_file(repo_id, parent_dir, file_name, request.user.username) 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})
def get_locked_files_by_dir(request, repo_id, folder_path): """ Get locked files in a folder Returns: A dict contains locked file name and locker owner. locked_files = { 'file_name': 'lock_owner'; ... } """ username = request.user.username # get lock files dir_id = seafile_api.get_dir_id_by_path(repo_id, folder_path) dirents = seafile_api.list_dir_with_perm(repo_id, folder_path, dir_id, username, -1, -1) locked_files = {} for dirent in dirents: if dirent.is_locked: locked_files[dirent.obj_name] = dirent.lock_owner return locked_files
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 _decorated(view, request, *args, **kwargs): # argument check if request.method == 'GET': repo_id = request.GET.get('repo_id', None) path = request.GET.get('path', '/') share_type = request.GET.get('share_type', None) else: repo_id = request.data.get('repo_id', None) path = request.data.get('path', '/') share_type = request.data.get('share_type', None) if not repo_id: error_msg = 'repo_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not share_type or share_type not in ('user', 'group'): error_msg = 'share_type 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 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) return func(view, request, repo, path, share_type, *args, **kwargs)
def check_user_folder_perm_args(from_user, repo_id, path, to_user, perm=None): if not seafile_api.get_repo(repo_id): return {'error': _(u'Library does not exist.'), 'status': 400} if check_repo_access_permission(repo_id, from_user) != 'rw': return {'error': _('Permission denied'), 'status': 403} if perm is not None: # add or toggle folder perm if seafile_api.get_dir_id_by_path(repo_id, path) is None: return {'error': _('Invalid path'), 'status': 400} if perm != 'r' and perm != 'rw': return {'error': _('Invalid folder permission'), 'status': 400} if not path.startswith('/'): return {'error': _('Path should start with "/"'), 'status': 400} if path != '/' and path.endswith('/'): return {'error': _('Path should NOT ends with "/"'), 'status': 400} try: user = User.objects.get(email = to_user) except User.DoesNotExist: user = None if user is None: return {'error': _('Invalid username, should be a user already registered'), 'status': 400} return {'success': True}
def check_group_folder_perm_args(from_user, repo_id, path, group_id, perm = None): if not seafile_api.get_repo(repo_id): return {'error': _(u'Library does not exist.'), 'status': 400} if check_repo_access_permission(repo_id, from_user) != 'rw': return {'error': _('Permission denied'), 'status': 403} if perm is not None: # add or toggle folder perm if seafile_api.get_dir_id_by_path(repo_id, path) is None: return {'error': _('Invalid path'), 'status': 400} if perm != 'r' and perm != 'rw': return {'error': _('Invalid folder permission'), 'status': 400} if not path.startswith('/'): return {'error': _('Path should start with "/"'), 'status': 400} if path != '/' and path.endswith('/'): return {'error': _('Path should NOT ends with "/"'), 'status': 400} if not seaserv.get_group(group_id): return {'error': _('Invalid group'), 'status': 400} return {'success': True}
def get(self, request, repo_id): """ List repo user share info. Permission checking: 1. is group admin """ # 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) path = request.GET.get('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) # 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 = self.list_user_shared_items(request, repo_id, path) return Response(result)
def get_dir_files_last_modified(self, repo_id, parent_dir, dir_id=None): """Calc the last modified time of all the files under the directory <parent_dir> of the repo <repo_id>. Return a dict whose keys are the file names and values are their corresponding last modified timestamps. Arguments: - `self`: - `repo_id`: - `parent_dir`: - `dir_id`: """ if not dir_id: dir_id = seafile_api.get_dir_id_by_path(repo_id, parent_dir) parent_dir_hash = calc_file_path_hash(parent_dir) if not dir_id: return {} try: info = super(DirFilesLastModifiedInfoManager, self).get( repo_id=repo_id, parent_dir_hash=parent_dir_hash) except self.model.DoesNotExist: # no cache yet return self._calc_dir_files_last_modified(repo_id, parent_dir, parent_dir_hash, dir_id) else: # cache exist if info.dir_id != dir_id: # cache is outdated info.delete() return self._calc_dir_files_last_modified(repo_id, parent_dir, parent_dir_hash, dir_id) else: # cache is valid return json.loads(info.last_modified_info)
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, org_id, format=None): """ Update repo group share permission. Permission checking: 1. is group admin """ # parameter check to_group_id = request.data.get('group_id', None) if not to_group_id: error_msg = 'group_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: to_group_id = int(to_group_id) except ValueError: error_msg = 'group_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) permission = request.data.get('permission', PERMISSION_READ) if permission 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) 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) if not ccnet_api.get_group(to_group_id): error_msg = 'Group %s not found.' % to_group_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) path = request.data.get('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) # 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) update_group_dir_permission( repo_id, path, repo_owner, to_group_id, permission, org_id) send_perm_audit_msg('modify-repo-perm', username, to_group_id, repo_id, path, permission) return Response({'success': True})
def post(self, request): """ Create upload link. Permission checking: 1. default(NOT guest) user; 2. user with '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) password = request.data.get('password', None) if password and len(password) < config.SHARE_LINK_PASSWORD_MIN_LENGTH: error_msg = _('Password is too short') 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: dir_id = seafile_api.get_dir_id_by_path(repo_id, path) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not dir_id: error_msg = 'folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if not self._can_generate_shared_link(request): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if check_folder_permission(request, repo_id, path) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) username = request.user.username uls = UploadLinkShare.objects.get_upload_link_by_path(username, repo_id, path) if not uls: uls = UploadLinkShare.objects.create_upload_link_share(username, repo_id, path, password) link_info = self._get_upload_link_info(uls) return Response(link_info)
def get(self, request): """ List all starred file/folder. Permission checking: 1. all authenticated user can perform this action. """ email = request.user.username all_starred_items = UserStarredFiles.objects.filter(email=email) repo_dict = {} for starred_item in all_starred_items: repo_id = starred_item.repo_id if repo_id not in repo_dict: repo = seafile_api.get_repo(repo_id) if repo: repo_dict[repo_id] = repo starred_repos = [] starred_folders = [] starred_files = [] for starred_item in all_starred_items: repo_id = starred_item.repo_id if repo_id not in repo_dict: continue path = starred_item.path if starred_item.is_dir: if not seafile_api.get_dir_id_by_path(repo_id, path): continue else: if not seafile_api.get_file_id_by_path(repo_id, path): continue repo = repo_dict[repo_id] item_info = self.get_starred_item_info(repo, starred_item) email = starred_item.email item_info['user_email'] = email item_info['user_name'] = email2nickname(email) item_info['user_contact_email'] = email2contact_email(email) if path == '/': starred_repos.append(item_info) elif starred_item.is_dir: starred_folders.append(item_info) else: starred_files.append(item_info) starred_repos.sort(lambda x, y: cmp(y['mtime'], x['mtime'])) starred_folders.sort(lambda x, y: cmp(y['mtime'], x['mtime'])) starred_files.sort(lambda x, y: cmp(y['mtime'], x['mtime'])) return Response({'starred_item_list': starred_repos + \ starred_folders + starred_files})
def repo_recycle_view(request, repo_id): if not seafile_api.get_dir_id_by_path(repo_id, '/') or \ check_folder_permission(request, repo_id, '/') != 'rw': return render_permission_error(request, _(u'Unable to view recycle page')) commit_id = request.GET.get('commit_id', '') if not commit_id: return render_recycle_root(request, repo_id) else: return render_recycle_dir(request, repo_id, commit_id)
def get(self, request): """ Get all upload links of a user. Permission checking: 1. default(NOT guest) user; """ if not self._can_generate_shared_link(request): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # get all upload links username = request.user.username upload_link_shares = UploadLinkShare.objects.filter(username=username) repo_id = request.GET.get('repo_id', None) if 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) # filter share links by repo upload_link_shares = filter(lambda ufs: ufs.repo_id==repo_id, upload_link_shares) path = request.GET.get('path', None) if path: try: dir_id = seafile_api.get_dir_id_by_path(repo_id, path) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not dir_id: error_msg = 'folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if path[-1] != '/': path = path + '/' # filter share links by path upload_link_shares = filter(lambda ufs: ufs.path==path, upload_link_shares) result = [] for uls in upload_link_shares: link_info = self._get_upload_link_info(uls) result.append(link_info) if len(result) == 1: result = result else: result.sort(lambda x, y: cmp(x['obj_name'], y['obj_name'])) return Response(result)
def _generate_obj_id_and_type_by_path(self, repo_id, path): file_id = seafile_api.get_file_id_by_path(repo_id, path) if file_id: return (file_id, 'f') dir_id = seafile_api.get_dir_id_by_path(repo_id, path) if dir_id: return (dir_id, 'd') return (None, None)
def get(self, request, repo_id, format=None): # list dir 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', '/') if path[-1] != '/': path = path + '/' try: dir_id = seafile_api.get_dir_id_by_path(repo_id, path) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not dir_id: error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if check_folder_permission(request, repo_id, path) is None: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) old_oid = request.GET.get('oid', None) if old_oid and old_oid == dir_id: resp = Response({'success': True}) resp["oid"] = dir_id return resp else: request_type = request.GET.get('t', None) if request_type and request_type not in ('f', 'd'): error_msg = "'t'(type) should be 'f' or 'd'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if request_type == 'd': recursive = request.GET.get('recursive', '0') if recursive not in ('1', '0'): error_msg = "If you want to get recursive dir entries, you should set 'recursive' argument as '1'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if recursive == '1': username = request.user.username dir_list = get_dir_recursively(username, repo_id, path, []) dir_list.sort(lambda x, y: cmp(x['name'].lower(), y['name'].lower())) resp = Response(dir_list) resp["oid"] = dir_id resp["dir_perm"] = seafile_api.check_permission_by_path(repo_id, path, username) return resp return get_dir_entrys_by_id(request, repo, path, dir_id, request_type)
def get(self, request, repo_id, format=None): """ get all file/folder in a library """ 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 not can_view_sys_admin_repo(repo): error_msg = 'Feature disabled.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) parent_dir = request.GET.get('parent_dir', '/') if not parent_dir: error_msg = 'parent_dir invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if parent_dir[-1] != '/': parent_dir = 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) 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) try: dirs = seafserv_threaded_rpc.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 get(self, request): """ get upload link. """ if not self._can_generate_shared_link(request): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) repo_id = request.GET.get('repo_id', None) if 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) path = request.GET.get('path', None) if path: try: dir_id = seafile_api.get_dir_id_by_path(repo_id, path) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not dir_id: error_msg = 'folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) username = request.user.username upload_link_shares = UploadLinkShare.objects.filter(username=username) # filter result by args if repo_id: upload_link_shares = filter(lambda ufs: ufs.repo_id == repo_id, upload_link_shares) if path: if path[-1] != '/': path = path + '/' upload_link_shares = filter(lambda ufs: ufs.path == path, upload_link_shares) result = [] for uls in upload_link_shares: link_info = self._get_upload_link_info(uls) result.append(link_info) if len(result) == 1: result = result[0] return Response(result)
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 delete(self, request, repo_id, format=None): """ Delete dir. Permission checking: 1. user with '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) if path == '/': error_msg = 'Can not delete root path.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check dir_id = seafile_api.get_dir_id_by_path(repo_id, path) if not dir_id: error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) 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, path) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if path[-1] == '/': path = path[:-1] path = path.rstrip('/') username = request.user.username parent_dir = os.path.dirname(path) dir_name = os.path.basename(path) try: seafile_api.del_file(repo_id, parent_dir, dir_name, username) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return Response({'success': True})
def get_dirent_name_list(username, repo_id, parent_path): file_name_list = [] folder_name_list = [] path_id = seafile_api.get_dir_id_by_path(repo_id, parent_path) dirs = seafile_api.list_dir_with_perm(repo_id, parent_path, path_id, username, -1, -1) for dirent in dirs: if stat.S_ISDIR(dirent.mode): folder_name_list.append(dirent.obj_name) else: file_name_list.append(dirent.obj_name) return folder_name_list, file_name_list
def create_exist_file_draft(self, repo, username, file_uuid, file_path): # create drafts dir if does not exist draft_dir_id = seafile_api.get_dir_id_by_path(repo.id, '/Drafts') if draft_dir_id is None: seafile_api.post_dir(repo.id, '/', 'Drafts', username) # check draft file does not exists and copy origin file content to # draft file draft_file_name = get_draft_file_name(repo.id, file_path) draft_file_path = '/Drafts/' + draft_file_name try: # Determine if there is a draft of the file d = self.get(origin_file_uuid=file_uuid.uuid) except Draft.DoesNotExist: try: # Determine if there is a draft with the same name as # the generated draft file path d_2 = self.get(origin_repo_id=repo.id, draft_file_path=draft_file_path) d_2.delete(operator=username) except Draft.DoesNotExist: pass # copy file to draft dir seafile_api.copy_file(repo.id, file_uuid.parent_path, file_uuid.filename, repo.id, '/Drafts', draft_file_name, username=username, need_progress=0, synchronous=1) return draft_file_path if d: file_id = seafile_api.get_file_id_by_path(repo.id, d.draft_file_path) # If the database entry exists and the draft file exists, # then raise DraftFileExist if file_id: raise DraftFileExist # If the database entry exists and the draft file does not exist, # delete the database entry else: d.delete(operator=username) # copy file to draft dir seafile_api.copy_file(repo.id, file_uuid.parent_path, file_uuid.filename, repo.id, '/Drafts', draft_file_name, username=username, need_progress=0, synchronous=1) return draft_file_path
def post(self, request, repo_id, format=None): """ create file/folder in a library """ 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 not can_view_sys_admin_repo(repo): error_msg = 'Feature disabled.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) parent_dir = request.GET.get('parent_dir', '/') if not parent_dir: error_msg = 'parent_dir invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if parent_dir[-1] != '/': parent_dir = 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 seafile_api.is_valid_filename(repo_id, obj_name): error_msg = 'obj_name invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) obj_name = check_filename_with_rename(repo_id, parent_dir, obj_name) username = request.user.username try: 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 get(self, request, token): """ Get file upload url according to upload link token. Permission checking: 1. anyone has the upload link token can perform this action; """ try: uls = UploadLinkShare.objects.get(token=token) except UploadLinkShare.DoesNotExist: error_msg = 'token %s not found.' % token return api_error(status.HTTP_404_NOT_FOUND, error_msg) # currently not support encrypted upload link if uls.is_encrypted(): error_msg = 'Upload link %s is encrypted.' % token return api_error(status.HTTP_403_FORBIDDEN, error_msg) repo_id = uls.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) path = uls.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) if repo.encrypted or \ seafile_api.check_permission_by_path(repo_id, '/', uls.username) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) token = seafile_api.get_fileserver_access_token(repo_id, dir_id, 'upload-link', uls.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 repo_download_dir(request, repo_id): repo = get_repo(repo_id) if not repo: return render_error(request, _(u'Library does not exist')) path = request.GET.get('p', '/') if path[-1] != '/': # Normalize dir path path += '/' if not seafile_api.get_dir_id_by_path(repo.id, path): return render_error(request, _('"%s" does not exist.') % path) if len(path) > 1: dirname = os.path.basename(path.rstrip('/')) # Here use `rstrip` to cut out last '/' in path else: dirname = repo.name allow_download = True if check_folder_permission(request, repo_id, '/') else False if allow_download: dir_id = seafile_api.get_dir_id_by_commit_and_path(repo.id, repo.head_cmmt_id, path) try: total_size = seafile_api.get_dir_size(repo.store_id, repo.version, dir_id) except Exception, e: logger.error(str(e)) return render_error(request, _(u'Internal Error')) if total_size > MAX_DOWNLOAD_DIR_SIZE: return render_error(request, _(u'Unable to download directory "%s": size is too large.') % dirname) is_windows = 0 if is_windows_operating_system(request): is_windows = 1 fake_obj_id = { 'obj_id': dir_id, 'dir_name': dirname, 'is_windows': is_windows } token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), 'download-dir', request.user.username)
def delete(self, request, repo_id): """ delete a single file/folder in a library """ 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 not can_view_sys_admin_repo(repo): error_msg = 'Feature disabled.' return api_error(status.HTTP_403_FORBIDDEN, 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) if path[0] != '/': path = '/' + path file_id = None dir_id = None try: file_id = seafile_api.get_file_id_by_path(repo_id, path) dir_id = seafile_api.get_dir_id_by_path(repo_id, path) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not file_id and not dir_id: return Response({'success': True}) parent_dir = os.path.dirname(path) file_name = os.path.basename(path) try: seafile_api.del_file(repo_id, parent_dir, file_name, request.user.username) 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})
def _decorated(view, request, repo_id, *args, **kwargs): 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) # check permission 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) username = request.user.username if repo.is_virtual or username != repo_owner: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check arguments group_id = request.data.get('group_id', None) path = request.data.get('folder_path', None) perm = request.data.get('permission', None) try: group_id = int(group_id) except ValueError: error_msg = 'group_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not seaserv.get_group(group_id): error_msg = 'Group %s not found.' % group_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) if path: path = path.rstrip('/') if path != '/' else path if seafile_api.get_dir_id_by_path(repo_id, path) is None: error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if request.method in ('POST', 'PUT') and perm not in ('r', 'rw'): error_msg = 'permission invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return func(view, request, repo_id, *args, **kwargs)
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 _download_dir_from_share_link(request, fileshare, repo, real_path): # check whether owner's traffic over the limit if user_traffic_over_limit(fileshare.username): return render_error( request, _(u'Unable to access file: share link traffic is used up.')) shared_by = fileshare.username if real_path == '/': dirname = repo.name else: dirname = os.path.basename(real_path.rstrip('/')) dir_id = seafile_api.get_dir_id_by_path(repo.id, real_path) if not dir_id: return render_error(request, _(u'Unable to download: folder not found.')) try: total_size = seaserv.seafserv_threaded_rpc.get_dir_size( repo.store_id, repo.version, dir_id) except Exception as e: logger.error(str(e)) return render_error(request, _(u'Internal Error')) if total_size > seaserv.MAX_DOWNLOAD_DIR_SIZE: return render_error( request, _(u'Unable to download directory "%s": size is too large.') % dirname) token = seafile_api.get_fileserver_access_token( repo.id, dir_id, 'download-dir', request.user.username) try: seaserv.send_message( 'seahub.stats', 'dir-download\t%s\t%s\t%s\t%s' % (repo.id, shared_by, dir_id, total_size)) except Exception as e: logger.error('Error when sending dir-download message: %s' % str(e)) return HttpResponseRedirect(gen_file_get_url(token, dirname))
def post(self, request, repo_id, format=None): """ Create, rename, move, copy 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; """ # argument check path = request.GET.get('p', None) if not path or path[0] != '/': error_msg = 'p invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) 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'): error_msg = "operation can only be 'create', 'rename', 'move' or 'copy'." 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 file new_file_name = os.path.basename(path) 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) 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)
def get_dir_file_info_list(username, request_type, repo_obj, parent_dir, with_thumbnail, thumbnail_size): repo_id = repo_obj.id dir_info_list = [] file_info_list = [] # get dirent(folder and file) list parent_dir_id = seafile_api.get_dir_id_by_path(repo_id, parent_dir) dir_file_list = seafile_api.list_dir_with_perm(repo_id, parent_dir, parent_dir_id, username, -1, -1) try: starred_items = UserStarredFiles.objects.filter( email=username, repo_id=repo_id, path__startswith=parent_dir, org_id=-1) starred_item_path_list = [f.path.rstrip('/') for f in starred_items] except Exception as e: logger.error(e) starred_item_path_list = [] # only get dir info list if not request_type or request_type == 'd': dir_list = [ dirent for dirent in dir_file_list if stat.S_ISDIR(dirent.mode) ] for dirent in dir_list: dir_info = {} dir_info["type"] = "dir" dir_info["id"] = dirent.obj_id dir_info["name"] = dirent.obj_name dir_info["mtime"] = dirent.mtime dir_info["permission"] = dirent.permission dir_info["parent_dir"] = parent_dir dir_info_list.append(dir_info) # get star info dir_info['starred'] = False dir_path = posixpath.join(parent_dir, dirent.obj_name) if dir_path.rstrip('/') in starred_item_path_list: dir_info['starred'] = True # only get file info list if not request_type or request_type == 'f': file_list = [ dirent for dirent in dir_file_list if not stat.S_ISDIR(dirent.mode) ] # Use dict to reduce memcache fetch cost in large for-loop. nickname_dict = {} contact_email_dict = {} modifier_set = set([x.modifier for x in file_list]) lock_owner_set = set([x.lock_owner for x in file_list]) for e in modifier_set | lock_owner_set: if e not in nickname_dict: nickname_dict[e] = email2nickname(e) if e not in contact_email_dict: contact_email_dict[e] = email2contact_email(e) try: files_tags_in_dir = get_files_tags_in_dir(repo_id, parent_dir) except Exception as e: logger.error(e) files_tags_in_dir = {} for dirent in file_list: file_name = dirent.obj_name file_path = posixpath.join(parent_dir, file_name) file_obj_id = dirent.obj_id file_info = {} file_info["type"] = "file" file_info["id"] = file_obj_id file_info["name"] = file_name file_info["mtime"] = dirent.mtime file_info["permission"] = dirent.permission file_info["parent_dir"] = parent_dir file_info["size"] = dirent.size modifier_email = dirent.modifier file_info['modifier_email'] = modifier_email file_info['modifier_name'] = nickname_dict.get(modifier_email, '') file_info['modifier_contact_email'] = contact_email_dict.get( modifier_email, '') # get lock info if is_pro_version(): file_info["is_locked"] = dirent.is_locked file_info["lock_time"] = dirent.lock_time lock_owner_email = dirent.lock_owner or '' file_info["lock_owner"] = lock_owner_email file_info['lock_owner_name'] = nickname_dict.get( lock_owner_email, '') file_info['lock_owner_contact_email'] = contact_email_dict.get( lock_owner_email, '') if username == lock_owner_email: file_info["locked_by_me"] = True else: file_info["locked_by_me"] = False # get star info file_info['starred'] = False if file_path.rstrip('/') in starred_item_path_list: file_info['starred'] = True # get tag info file_tags = files_tags_in_dir.get(file_name, []) if file_tags: file_info['file_tags'] = [] for file_tag in file_tags: file_info['file_tags'].append(file_tag) # get thumbnail info if with_thumbnail and not repo_obj.encrypted: # used for providing a way to determine # if send a request to create thumbnail. fileExt = os.path.splitext(file_name)[1][1:].lower() file_type = FILEEXT_TYPE_MAP.get(fileExt) 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(thumbnail_size), file_obj_id) if os.path.exists(thumbnail_file_path): src = get_thumbnail_src(repo_id, thumbnail_size, file_path) file_info['encoded_thumbnail_src'] = urlquote(src) file_info_list.append(file_info) dir_info_list.sort(lambda x, y: cmp(x['name'].lower(), y['name'].lower())) file_info_list.sort(lambda x, y: cmp(x['name'].lower(), y['name'].lower())) return dir_info_list, file_info_list
def user_info(request, email): owned_repos = seafile_api.get_owned_repo_list(email) org = ccnet_threaded_rpc.get_orgs_by_user(email) org_name = None if not org: space_usage = seafile_api.get_user_self_usage(email) space_quota = seafile_api.get_user_quota(email) if CALC_SHARE_USAGE: share_usage = seafile_api.get_user_share_usage(email) share_quota = seafile_api.get_user_share_quota(email) else: share_quota = share_usage = 0 else: org_id = org[0].org_id org_name = org[0].org_name space_usage = seafserv_threaded_rpc.get_org_user_quota_usage( org_id, email) space_quota = seafserv_threaded_rpc.get_org_user_quota(org_id, email) share_usage = share_quota = 0 # Repos that are share to user in_repos = seafile_api.get_share_in_repo_list(email, -1, -1) # get user profile profile = Profile.objects.get_profile_by_user(email) d_profile = DetailedProfile.objects.get_detailed_profile_by_user(email) user_shared_links = [] # download links p_fileshares = [] fileshares = list(FileShare.objects.filter(username=email)) for fs in fileshares: r = seafile_api.get_repo(fs.repo_id) if not r: fs.delete() continue if fs.is_file_share_link(): if seafile_api.get_file_id_by_path(r.id, fs.path) is None: fs.delete() continue fs.filename = os.path.basename(fs.path) path = fs.path.rstrip('/') # Normalize file path obj_id = seafile_api.get_file_id_by_path(r.id, path) fs.file_size = seafile_api.get_file_size(r.store_id, r.version, obj_id) else: if seafile_api.get_dir_id_by_path(r.id, fs.path) is None: fs.delete() continue fs.filename = os.path.basename(fs.path.rstrip('/')) path = fs.path if path[-1] != '/': # Normalize dir path path += '/' # get dir size dir_id = seafserv_threaded_rpc.get_dirid_by_path( r.id, r.head_cmmt_id, path) fs.dir_size = seafserv_threaded_rpc.get_dir_size( r.store_id, r.version, dir_id) fs.is_download = True p_fileshares.append(fs) p_fileshares.sort(key=lambda x: x.view_cnt, reverse=True) user_shared_links += p_fileshares # upload links uploadlinks = list(UploadLinkShare.objects.filter(username=email)) p_uploadlinks = [] for link in uploadlinks: r = seafile_api.get_repo(link.repo_id) if not r: link.delete() continue if seafile_api.get_dir_id_by_path(r.id, link.path) is None: link.delete() continue link.dir_name = os.path.basename(link.path.rstrip('/')) link.is_upload = True p_uploadlinks.append(link) p_uploadlinks.sort(key=lambda x: x.view_cnt, reverse=True) user_shared_links += p_uploadlinks return render_to_response('sysadmin/userinfo.html', { 'owned_repos': owned_repos, 'space_quota': space_quota, 'space_usage': space_usage, 'share_quota': share_quota, 'share_usage': share_usage, 'CALC_SHARE_USAGE': CALC_SHARE_USAGE, 'in_repos': in_repos, 'email': email, 'profile': profile, 'd_profile': d_profile, 'org_name': org_name, 'user_shared_links': user_shared_links, }, context_instance=RequestContext(request))
def post(self, request): """ Create upload link. Permission checking: 1. default(NOT guest) user; 2. user with '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) password = request.data.get('password', None) if password and len(password) < config.SHARE_LINK_PASSWORD_MIN_LENGTH: error_msg = _('Password is too short') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) expire_days = request.data.get('expire_days', '') expiration_time = request.data.get('expiration_time', '') if expire_days and expiration_time: error_msg = 'Can not pass expire_days and expiration_time at the same time.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) expire_date = None if expire_days: try: expire_days = int(expire_days) except ValueError: error_msg = 'expire_days invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if expire_days <= 0: error_msg = 'expire_days invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if UPLOAD_LINK_EXPIRE_DAYS_MIN > 0: if expire_days < UPLOAD_LINK_EXPIRE_DAYS_MIN: error_msg = _('Expire days should be greater or equal to %s') % \ UPLOAD_LINK_EXPIRE_DAYS_MIN return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if UPLOAD_LINK_EXPIRE_DAYS_MAX > 0: if expire_days > UPLOAD_LINK_EXPIRE_DAYS_MAX: error_msg = _('Expire days should be less than or equal to %s') % \ UPLOAD_LINK_EXPIRE_DAYS_MAX return api_error(status.HTTP_400_BAD_REQUEST, error_msg) expire_date = timezone.now() + relativedelta(days=expire_days) elif expiration_time: try: expire_date = dateutil.parser.isoparse(expiration_time) except Exception as e: logger.error(e) error_msg = 'expiration_time invalid, should be iso format, for example: 2020-05-17T10:26:22+08:00' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) expire_date = expire_date.astimezone( get_current_timezone()).replace(tzinfo=None) if UPLOAD_LINK_EXPIRE_DAYS_MIN > 0: expire_date_min_limit = timezone.now() + relativedelta( days=UPLOAD_LINK_EXPIRE_DAYS_MIN) expire_date_min_limit = expire_date_min_limit.replace( hour=0).replace(minute=0).replace(second=0) if expire_date < expire_date_min_limit: error_msg = _('Expiration time should be later than %s.') % \ expire_date_min_limit.strftime("%Y-%m-%d %H:%M:%S") return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if UPLOAD_LINK_EXPIRE_DAYS_MAX > 0: expire_date_max_limit = timezone.now() + relativedelta( days=UPLOAD_LINK_EXPIRE_DAYS_MAX) expire_date_max_limit = expire_date_max_limit.replace( hour=23).replace(minute=59).replace(second=59) if expire_date > expire_date_max_limit: error_msg = _('Expiration time should be earlier than %s.') % \ expire_date_max_limit.strftime("%Y-%m-%d %H:%M:%S") return api_error(status.HTTP_400_BAD_REQUEST, error_msg) else: if UPLOAD_LINK_EXPIRE_DAYS_DEFAULT > 0: expire_date = timezone.now() + relativedelta( days=UPLOAD_LINK_EXPIRE_DAYS_DEFAULT) # 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: dir_id = seafile_api.get_dir_id_by_path(repo_id, path) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not dir_id: error_msg = 'folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if check_folder_permission(request, repo_id, path) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) username = request.user.username uls = UploadLinkShare.objects.get_upload_link_by_path( username, repo_id, path) if not uls: uls = UploadLinkShare.objects.create_upload_link_share( username, repo_id, path, password, expire_date) link_info = get_upload_link_info(uls) return Response(link_info)
def ajax_private_share_dir(request): content_type = 'application/json; charset=utf-8' repo_id = request.POST.get('repo_id', '') path = request.POST.get('path', '') username = request.user.username result = {} repo = seafile_api.get_repo(repo_id) if not repo: result['error'] = _(u'Library does not exist.') return HttpResponse(json.dumps(result), status=400, content_type=content_type) if seafile_api.get_dir_id_by_path(repo_id, path) is None: result['error'] = _(u'Directory does not exist.') return HttpResponse(json.dumps(result), status=400, content_type=content_type) if path != '/': # if share a dir, check sub-repo first try: if is_org_context(request): org_id = request.user.org.org_id sub_repo = seaserv.seafserv_threaded_rpc.get_org_virtual_repo( org_id, repo_id, path, username) else: sub_repo = seafile_api.get_virtual_repo(repo_id, path, username) except SearpcError as e: result['error'] = e.msg return HttpResponse(json.dumps(result), status=500, content_type=content_type) if not sub_repo: name = os.path.basename(path) # create a sub-lib try: # use name as 'repo_name' & 'repo_desc' for sub_repo if is_org_context(request): org_id = request.user.org.org_id sub_repo_id = seaserv.seafserv_threaded_rpc.create_org_virtual_repo( org_id, repo_id, path, name, name, username) else: sub_repo_id = seafile_api.create_virtual_repo(repo_id, path, name, name, username) sub_repo = seafile_api.get_repo(sub_repo_id) except SearpcError as e: result['error'] = e.msg return HttpResponse(json.dumps(result), status=500, content_type=content_type) shared_repo_id = sub_repo.id shared_repo = sub_repo else: shared_repo_id = repo_id shared_repo = repo emails_string = request.POST.get('emails', '') groups_string = request.POST.get('groups', '') perm = request.POST.get('perm', '') emails = string2list(emails_string) groups = string2list(groups_string) # Test whether user is the repo owner. if not seafile_api.is_repo_owner(username, shared_repo_id) and \ not is_org_repo_owner(username, shared_repo_id): result['error'] = _(u'Only the owner of the library has permission to share it.') return HttpResponse(json.dumps(result), status=500, content_type=content_type) # Parsing input values. # no 'share_to_all' share_to_groups, share_to_users, shared_success, shared_failed = [], [], [], [] for email in emails: email = email.lower() if is_valid_username(email): share_to_users.append(email) else: shared_failed.append(email) for group_id in groups: share_to_groups.append(seaserv.get_group(group_id)) for email in share_to_users: # Add email to contacts. mail_sended.send(sender=None, user=request.user.username, email=email) if share_to_user(request, shared_repo, email, perm): shared_success.append(email) else: shared_failed.append(email) for group in share_to_groups: if share_to_group(request, shared_repo, group, perm): shared_success.append(group.group_name) else: shared_failed.append(group.group_name) if len(shared_success) > 0: return HttpResponse(json.dumps({ "shared_success": shared_success, "shared_failed": shared_failed }), content_type=content_type) else: # for case: only share to users and the emails are not valid data = json.dumps({"error": _("Please check the email(s) you entered")}) return HttpResponse(data, status=400, content_type=content_type)
def get(self, request, repo_id, format=None): """ Get dir info. Permission checking: 1. user with either 'r' or 'rw' permission. """ path = request.GET.get('p', '/') if path[-1] != '/': path = path + '/' # recource check repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: dir_id = seafile_api.get_dir_id_by_path(repo_id, path) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not dir_id: error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if not check_folder_permission(request, repo_id, path): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) old_oid = request.GET.get('oid', None) if old_oid and old_oid == dir_id: resp = Response({'success': True}) resp["oid"] = dir_id return resp else: request_type = request.GET.get('t', None) if request_type and request_type not in ('f', 'd'): error_msg = "'t'(type) should be 'f' or 'd'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if request_type == 'd': recursive = request.GET.get('recursive', '0') if recursive not in ('1', '0'): error_msg = "If you want to get recursive dir entries, you should set 'recursive' argument as '1'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if recursive == '1': username = request.user.username dir_list = get_dir_recursively(username, repo_id, path, []) dir_list.sort( lambda x, y: cmp(x['name'].lower(), y['name'].lower())) resp = Response(dir_list) resp["oid"] = dir_id resp["dir_perm"] = seafile_api.check_permission_by_path( repo_id, path, username) return resp return get_dir_entrys_by_id(request, repo, path, dir_id, request_type)
def get(self, request, format=None): repo_id = request.repo_api_token_obj.repo_id # 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('type', '') if request_type and request_type not in ('f', 'd'): error_msg = "'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('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) # permission check permission = check_folder_permission_by_repo_api( 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 username = seafile_api.get_repo_owner(repo_id) if recursive == '1': try: dir_file_info_list = get_dir_file_recursively( 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 'path' 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 response_dict["repo_name"] = repo.repo_name if request_type == 'f': response_dict['dirent_list'] = all_file_info_list elif request_type == 'd': response_dict['dirent_list'] = all_dir_info_list else: response_dict[ 'dirent_list'] = all_dir_info_list + all_file_info_list return Response(response_dict)
def post(self, request, repo_id, format=None): """ Batch add repo share invitations. """ # argument check path = request.data.get('path', None) if not path: return api_error(status.HTTP_400_BAD_REQUEST, 'path invalid.') itype = request.data.get('type', '').lower() if not itype or itype != GUEST_USER: return api_error(status.HTTP_400_BAD_REQUEST, 'type invalid.') accepters = request.data.get('accepters', None) if not accepters or not isinstance(accepters, list): return api_error(status.HTTP_400_BAD_REQUEST, 'accepters invalid.') permission = request.data.get('permission', PERMISSION_READ) if permission not in (PERMISSION_READ, PERMISSION_READ_WRITE): return api_error(status.HTTP_400_BAD_REQUEST, 'permission invalid.') # recourse check repo = seafile_api.get_repo(repo_id) if not repo: return api_error(status.HTTP_404_NOT_FOUND, 'Library %s not found.' % repo_id) if seafile_api.get_dir_id_by_path(repo.id, path) is None: return api_error(status.HTTP_404_NOT_FOUND, 'Folder %s not found.' % path) # permission check username = request.user.username 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) if username != repo_owner and not is_repo_admin(username, repo_id): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # main result = {} result['failed'] = [] result['success'] = [] inviter_name = email2nickname(request.user.username) try: invitation_queryset = Invitation.objects.order_by( '-invite_time').filter(inviter=request.user.username, accept_time=None) shared_queryset = RepoShareInvitation.objects.list_by_repo_id_and_path( repo_id=repo_id, path=path) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) for accepter in accepters: if not accepter.strip(): continue accepter = accepter.lower() if not is_valid_email(accepter): result['failed'].append({ 'email': accepter, 'error_msg': _('Email %s invalid.') % accepter }) continue if block_accepter(accepter): result['failed'].append({ 'email': accepter, 'error_msg': _('The email address is not allowed to be invited as a guest.' ) }) continue try: user = User.objects.get(accepter) # user is active return exist if user.is_active is True: result['failed'].append({ 'email': accepter, 'error_msg': _('User %s already exists.') % accepter }) continue except User.DoesNotExist: pass if invitation_queryset.filter(accepter=accepter).exists(): invitation = invitation_queryset.filter(accepter=accepter)[0] else: invitation = Invitation.objects.add( inviter=request.user.username, accepter=accepter) if shared_queryset.filter(invitation=invitation).exists(): result['failed'].append({ 'email': accepter, 'error_msg': _('This item has been shared to %s.') % accepter }) continue try: RepoShareInvitation.objects.add(invitation=invitation, repo_id=repo_id, path=path, permission=permission) except Exception as e: logger.error(e) result['failed'].append({ 'email': accepter, 'error_msg': _('Internal Server Error'), }) data = invitation.to_dict() data['permission'] = permission data['inviter_name'] = inviter_name result['success'].append(data) send_sucess = invitation.send_to(email=accepter) if not send_sucess: result['failed'].append({ 'email': accepter, 'error_msg': _('Failed to send email, email service is not properly configured, please contact administrator.' ), }) return Response(result)
def post(self, request, repo_id, format=None): """Update shared item permission. """ username = request.user.username repo = seafile_api.get_repo(repo_id) if not repo: return api_error(status.HTTP_404_NOT_FOUND, 'Library %s not found.' % repo_id) path = request.GET.get('p', '/') if seafile_api.get_dir_id_by_path(repo.id, path) is None: return api_error(status.HTTP_404_NOT_FOUND, 'Folder %s not found.' % path) permission = request.data.get('permission', PERMISSION_READ) if permission not in [ PERMISSION_READ, PERMISSION_READ_WRITE, PERMISSION_ADMIN ]: return api_error(status.HTTP_400_BAD_REQUEST, 'permission invalid.') repo_owner = self.get_repo_owner(request, repo_id) if repo_owner != username and not is_repo_admin(username, repo_id): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') shared_to_user, shared_to_group = self.handle_shared_to_args(request) if shared_to_user: shared_to = request.GET.get('username') if shared_to is None or not is_valid_username(shared_to): return api_error(status.HTTP_400_BAD_REQUEST, 'Email %s invalid.' % shared_to) try: User.objects.get(email=shared_to) except User.DoesNotExist: return api_error(status.HTTP_400_BAD_REQUEST, 'Invalid user, should be registered') if is_org_context(request): # when calling seafile API to share authority related functions, change the uesrname to repo owner. repo_owner = seafile_api.get_org_repo_owner(repo_id) org_id = request.user.org.org_id update_user_dir_permission(repo_id, path, repo_owner, shared_to, permission, org_id) else: repo_owner = seafile_api.get_repo_owner(repo_id) update_user_dir_permission(repo_id, path, repo_owner, shared_to, permission) send_perm_audit_msg('modify-repo-perm', username, shared_to, repo_id, path, permission) if shared_to_group: gid = request.GET.get('group_id') try: gid = int(gid) except ValueError: return api_error(status.HTTP_400_BAD_REQUEST, 'group_id %s invalid.' % gid) group = seaserv.get_group(gid) if not group: return api_error(status.HTTP_404_NOT_FOUND, 'Group %s not found.' % gid) if is_org_context(request): # when calling seafile API to share authority related functions, change the uesrname to repo owner. repo_owner = seafile_api.get_org_repo_owner(repo_id) org_id = request.user.org.org_id update_group_dir_permission(repo_id, path, repo_owner, gid, permission, org_id) else: repo_owner = seafile_api.get_repo_owner(repo_id) update_group_dir_permission(repo_id, path, repo_owner, gid, permission, None) send_perm_audit_msg('modify-repo-perm', username, gid, repo_id, path, permission) return HttpResponse(json.dumps({'success': True}), status=200, content_type=json_content_type)
def put(self, request, repo_id, format=None): username = request.user.username repo = seafile_api.get_repo(repo_id) if not repo: return api_error(status.HTTP_404_NOT_FOUND, 'Library %s not found.' % repo_id) path = request.GET.get('p', '/') if seafile_api.get_dir_id_by_path(repo.id, path) is None: return api_error(status.HTTP_404_NOT_FOUND, 'Folder %s not found.' % path) share_type = request.data.get('share_type') if share_type != 'user' and share_type != 'group': return api_error(status.HTTP_400_BAD_REQUEST, 'share_type invalid.') repo_owner = self.get_repo_owner(request, repo_id) if repo_owner != username and not is_repo_admin(username, repo_id): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') permission = request.data.get('permission', PERMISSION_READ) if permission not in [ PERMISSION_READ, PERMISSION_READ_WRITE, PERMISSION_ADMIN ]: return api_error(status.HTTP_400_BAD_REQUEST, 'permission invalid.') result = {} result['failed'] = [] result['success'] = [] if share_type == 'user': share_to_users = request.data.getlist('username') for to_user in share_to_users: if not is_valid_username(to_user): result['failed'].append({ 'email': to_user, 'error_msg': _(u'username invalid.') }) continue try: User.objects.get(email=to_user) except User.DoesNotExist: result['failed'].append({ 'email': to_user, 'error_msg': _(u'User %s not found.') % to_user }) continue if self.has_shared_to_user(request, repo_id, path, to_user): result['failed'].append({ 'email': to_user, 'error_msg': _(u'This item has been shared to %s.') % to_user }) continue try: org_id = None if is_org_context(request): org_id = request.user.org.org_id if not is_org_user(to_user, int(org_id)): org_name = request.user.org.org_name error_msg = 'User %s is not member of organization %s.' \ % (to_user, org_name) result['failed'].append({ 'email': to_user, 'error_msg': error_msg }) continue # when calling seafile API to share authority related functions, change the uesrname to repo owner. repo_owner = seafile_api.get_org_repo_owner(repo_id) # can't share to owner if to_user == repo_owner: error_msg = "Library can not be shared to owner" return api_error(status.HTTP_400_BAD_REQUEST, error_msg) share_dir_to_user(repo, path, repo_owner, username, to_user, permission, org_id) else: if is_org_user(to_user): error_msg = 'User %s is a member of organization.' % to_user result['failed'].append({ 'email': to_user, 'error_msg': error_msg }) continue repo_owner = seafile_api.get_repo_owner(repo_id) # can't share to owner if to_user == repo_owner: error_msg = "Library can not be shared to owner" return api_error(status.HTTP_400_BAD_REQUEST, error_msg) share_dir_to_user(repo, path, repo_owner, username, to_user, permission, None) result['success'].append({ "share_type": "user", "user_info": { "name": to_user, "nickname": email2nickname(to_user), }, "permission": PERMISSION_READ_WRITE if permission == PERMISSION_ADMIN else permission, "is_admin": permission == PERMISSION_ADMIN }) # send a signal when sharing repo successful share_repo_to_user_successful.send(sender=None, from_user=username, to_user=to_user, repo=repo, path=path, org_id=org_id) send_perm_audit_msg('add-repo-perm', username, to_user, repo_id, path, permission) except SearpcError as e: logger.error(e) result['failed'].append({ 'email': to_user, 'error_msg': 'Internal Server Error' }) continue if share_type == 'group': group_ids = request.data.getlist('group_id') for gid in group_ids: try: gid = int(gid) except ValueError: result['failed'].append( {'error_msg': 'group_id %s invalid.' % gid}) continue group = ccnet_api.get_group(gid) if not group: result['failed'].append( {'error_msg': 'Group %s not found' % gid}) continue if not config.ENABLE_SHARE_TO_ALL_GROUPS and \ not ccnet_api.is_group_user(gid, username): result['failed'].append({ 'group_name': group.group_name, 'error_msg': 'Permission denied.' }) continue if self.has_shared_to_group(request, repo_id, path, gid): result['failed'].append({ 'group_name': group.group_name, 'error_msg': _(u'This item has been shared to %s.') % group.group_name }) continue try: org_id = None if is_org_context(request): # when calling seafile API to share authority related functions, change the uesrname to repo owner. repo_owner = seafile_api.get_org_repo_owner(repo_id) org_id = request.user.org.org_id share_dir_to_group(repo, path, repo_owner, username, gid, permission, org_id) else: repo_owner = seafile_api.get_repo_owner(repo_id) share_dir_to_group(repo, path, repo_owner, username, gid, permission, None) result['success'].append({ "share_type": "group", "group_info": { "id": gid, "name": group.group_name, }, "permission": PERMISSION_READ_WRITE if permission == PERMISSION_ADMIN else permission, "is_admin": permission == PERMISSION_ADMIN }) share_repo_to_group_successful.send(sender=None, from_user=username, group_id=gid, repo=repo, path=path, org_id=org_id) send_perm_audit_msg('add-repo-perm', username, gid, repo_id, path, permission) except SearpcError as e: logger.error(e) result['failed'].append({ 'group_name': group.group_name, 'error_msg': 'Internal Server Error' }) continue return HttpResponse(json.dumps(result), status=200, content_type=json_content_type)
def delete(self, request, repo_id, format=None): username = request.user.username repo = seafile_api.get_repo(repo_id) if not repo: return api_error(status.HTTP_404_NOT_FOUND, 'Library %s not found.' % repo_id) path = request.GET.get('p', '/') if seafile_api.get_dir_id_by_path(repo.id, path) is None: return api_error(status.HTTP_404_NOT_FOUND, 'Folder %s not found.' % path) repo_owner = self.get_repo_owner(request, repo_id) if repo_owner != username and not is_repo_admin(username, repo_id): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') shared_to_user, shared_to_group = self.handle_shared_to_args(request) if shared_to_user: shared_to = request.GET.get('username') if shared_to is None or not is_valid_username(shared_to): return api_error(status.HTTP_400_BAD_REQUEST, 'Email %s invalid.' % shared_to) permission = check_user_share_out_permission( repo_id, path, shared_to, is_org_context(request)) if is_org_context(request): # when calling seafile API to share authority related functions, change the uesrname to repo owner. org_id = request.user.org.org_id if path == '/': seaserv.seafserv_threaded_rpc.org_remove_share( org_id, repo_id, repo_owner, shared_to) else: seafile_api.org_unshare_subdir_for_user( org_id, repo_id, path, repo_owner, shared_to) else: if path == '/': seaserv.remove_share(repo_id, repo_owner, shared_to) else: seafile_api.unshare_subdir_for_user( repo_id, path, repo_owner, shared_to) # Delete share permission at ExtraSharePermission table. if path == '/': ExtraSharePermission.objects.delete_share_permission( repo_id, shared_to) send_perm_audit_msg('delete-repo-perm', username, shared_to, repo_id, path, permission) if shared_to_group: group_id = request.GET.get('group_id') try: group_id = int(group_id) except ValueError: return api_error(status.HTTP_400_BAD_REQUEST, 'group_id %s invalid' % group_id) # hacky way to get group repo permission is_org = is_org_context(request) permission = check_group_share_out_permission( repo_id, path, group_id, is_org) if is_org: # when calling seafile API to share authority related functions, change the uesrname to repo owner. org_id = request.user.org.org_id if path == '/': seaserv.del_org_group_repo(repo_id, org_id, group_id) else: seafile_api.org_unshare_subdir_for_group( org_id, repo_id, path, repo_owner, group_id) else: if path == '/': seafile_api.unset_group_repo(repo_id, group_id, username) else: seafile_api.unshare_subdir_for_group( repo_id, path, repo_owner, group_id) # delete share permission if repo is deleted if path == '/': ExtraGroupsSharePermission.objects.delete_share_permission( repo_id, group_id) send_perm_audit_msg('delete-repo-perm', username, group_id, repo_id, path, permission) return HttpResponse(json.dumps({'success': True}), status=200, content_type=json_content_type)
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) dirent = seafile_api.get_dirent_by_path(repo_id, path) 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 post(self, request): """ Create upload link. Permission checking: 1. default(NOT guest) user; 2. user with '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) password = request.data.get('password', None) if password and len(password) < config.SHARE_LINK_PASSWORD_MIN_LENGTH: error_msg = _('Password is too short') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: expire_days = int(request.data.get('expire_days', 0)) except ValueError: error_msg = 'expire_days 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: dir_id = seafile_api.get_dir_id_by_path(repo_id, path) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not dir_id: error_msg = 'folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if check_folder_permission(request, repo_id, path) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if expire_days <= 0: expire_date = None else: expire_date = timezone.now() + relativedelta(days=expire_days) username = request.user.username uls = UploadLinkShare.objects.get_upload_link_by_path( username, repo_id, path) if not uls: uls = UploadLinkShare.objects.create_upload_link_share( username, repo_id, path, password, expire_date) link_info = get_upload_link_info(uls) return Response(link_info)
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) is_locked, locked_by_me = check_file_lock(repo_id, file_path, username) 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 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; """ # argument check path = request.GET.get('p', None) if not path or path[0] != '/': error_msg = 'p invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) 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'): error_msg = "operation can only be 'create', 'rename', 'move' or 'copy'." 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 file new_file_name = os.path.basename(path) 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) 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 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) # 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) # 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) # move file if dst_dir[ -1] != '/': # Append '/' to the end of directory if necessary dst_dir += '/' 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) # 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) # copy file if dst_dir[ -1] != '/': # Append '/' to the end of directory if necessary dst_dir += '/' 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.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)
def get(self, request): """get file upload link by dtable api token Permission: 1. valid token """ # argument check auth = request.META.get('HTTP_AUTHORIZATION', '').split() if not auth or auth[0].lower() != 'token' or len(auth) != 2: return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') api_token = auth[1] # resource check try: api_token_obj = DTableAPIToken.objects.get_by_token(api_token) if not api_token_obj: return api_error(status.HTTP_404_NOT_FOUND, 'api token not found.') except Exception as e: logger.error(e) error_msg = 'Internal Server Error.' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) dtable = api_token_obj.dtable table_name = dtable.name workspace_id = dtable.workspace_id error, workspace, dtable = _resource_check(workspace_id, table_name) if error: return error if not check_user_workspace_quota(workspace): return api_error(HTTP_443_ABOVE_QUOTA, 'Asset quota exceeded.') # create asset dir repo_id = workspace.repo_id asset_dir_path = '/asset/' + str(dtable.uuid) asset_dir_id = seafile_api.get_dir_id_by_path(repo_id, asset_dir_path) if not asset_dir_id: try: seafile_api.mkdir_with_parents(repo_id, '/', asset_dir_path[1:], api_token_obj.generated_by) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # get token obj_id = json.dumps({'parent_dir': asset_dir_path}) try: token = seafile_api.get_fileserver_access_token(repo_id, obj_id, 'upload', '', use_onetime=False) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) upload_link = gen_file_upload_url(token, 'upload-api') api_token_obj.update_last_access() res = dict() res['upload_link'] = upload_link res['parent_path'] = asset_dir_path return Response(res)
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 post(self, request, format=None): repo_id = request.repo_api_token_obj.repo_id # argument check path = request.GET.get('path', None) if not path or path[0] != '/': error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if path == '/': error_msg = 'Can not operate root dir.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) operation = request.data.get('operation', None) if not operation: error_msg = 'operation invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) operation = operation.lower() if operation not in ('mkdir', 'rename', 'revert'): error_msg = "operation can only be 'mkdir', 'rename' or 'revert'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) path = path.rstrip('/') username = request.user.username parent_dir = os.path.dirname(path) if operation == 'mkdir': # resource check parent_dir_id = seafile_api.get_dir_id_by_path(repo_id, parent_dir) if not parent_dir_id: error_msg = 'Folder %s not found.' % parent_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if check_folder_permission_by_repo_api(request, repo_id, parent_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) new_dir_name = os.path.basename(path) if not is_valid_dirent_name(new_dir_name): return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.') retry_count = 0 while retry_count < 10: new_dir_name = check_filename_with_rename( repo_id, parent_dir, new_dir_name) try: seafile_api.post_dir(repo_id, parent_dir, new_dir_name, username) break except SearpcError as e: if str(e) == 'file already exists': retry_count += 1 else: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) new_dir_path = posixpath.join(parent_dir, new_dir_name) dir_info = self.get_dir_info(repo_id, new_dir_path) resp = Response(dir_info) return resp if operation == 'rename': # resource check dir_id = seafile_api.get_dir_id_by_path(repo_id, path) if not dir_id: error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if check_folder_permission_by_repo_api(request, repo_id, path) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) old_dir_name = os.path.basename(path) new_dir_name = request.data.get('newname', None) if not new_dir_name: error_msg = 'newname invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not is_valid_dirent_name(new_dir_name): return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.') if new_dir_name == old_dir_name: dir_info = self.get_dir_info(repo_id, path) resp = Response(dir_info) return resp try: # rename duplicate name new_dir_name = check_filename_with_rename( repo_id, parent_dir, new_dir_name) # rename dir seafile_api.rename_file(repo_id, parent_dir, old_dir_name, new_dir_name, username) new_dir_path = posixpath.join(parent_dir, new_dir_name) dir_info = self.get_dir_info(repo_id, new_dir_path) resp = Response(dir_info) return resp except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if operation == 'revert': commit_id = request.data.get('commit_id', None) if not commit_id: error_msg = 'commit_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if seafile_api.get_dir_id_by_path(repo_id, path): # dir exists in repo if check_folder_permission_by_repo_api(request, repo_id, path) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) else: # dir NOT exists in repo if check_folder_permission_by_repo_api(request, repo_id, '/') != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: seafile_api.revert_dir(repo_id, commit_id, path, username) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return Response({'success': True})
def get(self, request, format=None): """ Only used for download dir when view dir share link from web. Permission checking: 1. authenticated user OR anonymous user has passed email code check(if necessary); """ # permission check if is_pro_version() and settings.ENABLE_SHARE_LINK_AUDIT: if not request.user.is_authenticated and \ not request.session.get('anonymous_email'): # if anonymous user has passed email code check, # then his/her email info will be in session. error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # argument check share_link_token = request.GET.get('share_link_token', None) if not share_link_token: error_msg = 'share_link_token invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) req_path = request.GET.get('path', None) if not req_path: error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # recourse check fileshare = FileShare.objects.get_valid_dir_link_by_token( share_link_token) if not fileshare: error_msg = 'share_link_token %s not found.' % share_link_token return api_error(status.HTTP_404_NOT_FOUND, error_msg) if req_path[-1] != '/': req_path += '/' if req_path == '/': real_path = fileshare.path else: real_path = posixpath.join(fileshare.path, req_path.lstrip('/')) if real_path[-1] != '/': real_path += '/' repo_id = fileshare.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) dir_id = seafile_api.get_dir_id_by_path(repo_id, real_path) if not dir_id: error_msg = 'Folder %s not found.' % real_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if parse_repo_perm( seafile_api.check_permission_by_path( repo_id, '/', fileshare.username)).can_download is False: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # get file server access token dir_name = repo.name if real_path == '/' else \ os.path.basename(real_path.rstrip('/')) is_windows = 0 if is_windows_operating_system(request): is_windows = 1 fake_obj_id = { 'obj_id': dir_id, 'dir_name': dir_name, 'is_windows': is_windows } try: zip_token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), 'download-dir-link', fileshare.username, 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) if request.session.get('anonymous_email'): request.user.username = request.session.get('anonymous_email') send_file_access_msg(request, repo, real_path, 'share-link') return Response({'zip_token': zip_token})
def post(self, request, repo_id, format=None): """ Create, rename dir. Permission checking: 1. user with 'rw' permission. """ # argument check path = request.GET.get('p', None) if not path or path[0] != '/': error_msg = 'p invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if path == '/': error_msg = 'Can not make or rename root dir.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) operation = request.data.get('operation', None) if not operation: error_msg = 'operation invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) operation = operation.lower() if operation not in ('mkdir', 'rename'): error_msg = "operation can only be 'mkdir', 'rename'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) path = path.rstrip('/') username = request.user.username parent_dir = os.path.dirname(path) if operation == 'mkdir': # permission check if check_folder_permission(request, repo_id, parent_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # resource check parent_dir_id = seafile_api.get_dir_id_by_path(repo_id, parent_dir) if not parent_dir_id: error_msg = 'Folder %s not found.' % parent_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) new_dir_name = os.path.basename(path) new_dir_name = check_filename_with_rename(repo_id, parent_dir, new_dir_name) try: seafile_api.post_dir(repo_id, parent_dir, new_dir_name, username) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) new_dir_path = posixpath.join(parent_dir, new_dir_name) dir_info = self.get_dir_info(repo_id, new_dir_path) resp = Response(dir_info) return resp if operation == 'rename': # resource check dir_id = seafile_api.get_dir_id_by_path(repo_id, path) if not dir_id: error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if check_folder_permission(request, repo_id, path) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) old_dir_name = os.path.basename(path) new_dir_name = request.data.get('newname', None) if not new_dir_name: error_msg = 'newname invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if new_dir_name == old_dir_name: dir_info = self.get_dir_info(repo_id, path) resp = Response(dir_info) return resp try: # rename duplicate name new_dir_name = check_filename_with_rename( repo_id, parent_dir, new_dir_name) # rename dir seafile_api.rename_file(repo_id, parent_dir, old_dir_name, new_dir_name, username) new_dir_path = posixpath.join(parent_dir, new_dir_name) dir_info = self.get_dir_info(repo_id, new_dir_path) resp = Response(dir_info) return resp except SearpcError, e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
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 = [] 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 dirent_list.append(dirent_name) 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): """ Copy/move file/dir, and return task id. Permission checking: 1. move: user with 'rw' permission for current file, 'rw' permission for dst parent dir; 2. copy: user with 'r' permission for current file, 'rw' permission for dst parent dir; """ src_repo_id = request.data.get('src_repo_id', None) src_parent_dir = request.data.get('src_parent_dir', None) src_dirent_name = request.data.get('src_dirent_name', None) dst_repo_id = request.data.get('dst_repo_id', None) dst_parent_dir = request.data.get('dst_parent_dir', None) operation = request.data.get('operation', None) dirent_type = request.data.get('dirent_type', None) # argument check if not src_repo_id: error_msg = 'src_repo_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not src_parent_dir: error_msg = 'src_parent_dir invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not src_dirent_name: error_msg = 'src_dirent_name invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not dst_repo_id: error_msg = 'dst_repo_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not dst_parent_dir: error_msg = 'dst_parent_dir invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not operation: error_msg = 'operation invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not dirent_type: error_msg = 'dirent_type invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if src_repo_id == dst_repo_id and src_parent_dir == dst_parent_dir: error_msg = _('Invalid destination path') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if len(dst_parent_dir + src_dirent_name) > MAX_PATH: error_msg = _('Destination path is too long.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) operation = operation.lower() if operation not in ('move', 'copy'): error_msg = "operation can only be 'move' or 'copy'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) dirent_type = dirent_type.lower() if dirent_type not in ('file', 'dir'): error_msg = "operation can only be 'file' or 'dir'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # src resource check src_dirent_path = posixpath.join(src_parent_dir, src_dirent_name) if dirent_type == 'file': if not seafile_api.get_file_id_by_path(src_repo_id, src_dirent_path): error_msg = 'File %s not found.' % src_dirent_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if dirent_type == 'dir': if not seafile_api.get_dir_id_by_path(src_repo_id, src_dirent_path): error_msg = 'Folder %s not found.' % src_dirent_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # dst resource check if not seafile_api.get_dir_id_by_path(dst_repo_id, dst_parent_dir): error_msg = 'Folder %s not found.' % dst_parent_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check for dst parent dir if check_folder_permission(request, dst_repo_id, dst_parent_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) new_dirent_name = check_filename_with_rename(dst_repo_id, dst_parent_dir, src_dirent_name) username = request.user.username if operation == 'move': if dirent_type == 'dir' and src_repo_id == dst_repo_id and \ dst_parent_dir.startswith(src_parent_dir + '/'): error_msg = _(u'Can not move directory %(src)s to its subdirectory %(des)s') \ % {'src': escape(src_parent_dir), 'des': escape( dst_parent_dir)} return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # permission check for src parent dir if check_folder_permission(request, src_repo_id, src_parent_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: res = seafile_api.move_file(src_repo_id, src_parent_dir, src_dirent_name, dst_repo_id, dst_parent_dir, new_dirent_name, replace=False, username=username, need_progress=1) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if operation == 'copy': # permission check for src parent dir if not check_folder_permission(request, src_repo_id, src_parent_dir): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: res = seafile_api.copy_file(src_repo_id, src_parent_dir, src_dirent_name, dst_repo_id, dst_parent_dir, new_dirent_name, username=username, need_progress=1) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not res: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) result = {} if res.background: result['task_id'] = res.task_id return Response(result)
def get(self, request, token): """ Get FileServer download url of the shared file/dir. Permission checking: 1. only admin can perform this action. """ try: sharelink = 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) repo_id = sharelink.repo_id repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) result = {} obj_path = sharelink.path if sharelink.s_type == 'f': # download shared file obj_id = seafile_api.get_file_id_by_path(repo_id, obj_path) if not obj_id: error_msg = 'File not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: # `username` parameter only used for encrypted repo download_token = seafile_api.get_fileserver_access_token( repo_id, obj_id, 'download-link', sharelink.username, use_onetime=False) 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 download_token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) obj_name = os.path.basename(obj_path.rstrip('/')) result['download_link'] = gen_file_get_url(download_token, obj_name) else: # download (sub) file/folder in shared dir obj_id = seafile_api.get_dir_id_by_path(repo_id, obj_path) if not obj_id: error_msg = 'Folder not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) download_type = request.GET.get('type', None) if not download_type or download_type not in ('file', 'folder'): error_msg = 'type invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) req_path = request.GET.get('path', None) if not req_path: error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if req_path == '/': real_path = obj_path else: real_path = posixpath.join(obj_path, req_path.strip('/')) if download_type == 'file': # download sub file in shared dir real_obj_id = seafile_api.get_file_id_by_path( repo_id, real_path) if not real_obj_id: error_msg = 'File not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: download_token = seafile_api.get_fileserver_access_token( repo_id, real_obj_id, 'download-link', sharelink.username, use_onetime=False) 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 download_token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) file_name = os.path.basename(real_path.rstrip('/')) result['download_link'] = gen_file_get_url( download_token, file_name) else: # download sub folder in shared dir if real_path[-1] != '/': real_path += '/' real_obj_id = seafile_api.get_dir_id_by_path( repo_id, real_path) if not real_obj_id: error_msg = 'Folder %s not found.' % req_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) dir_name = repo.name if real_path == '/' else \ os.path.basename(real_path.rstrip('/')) dir_size = seafile_api.get_dir_size(repo.store_id, repo.version, real_obj_id) if dir_size > seaserv.MAX_DOWNLOAD_DIR_SIZE: error_msg = 'Unable to download directory "%s": size is too large.' % dir_name return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # get file server access token is_windows = 0 if is_windows_operating_system(request): is_windows = 1 fake_obj_id = { 'obj_id': real_obj_id, 'dir_name': dir_name, 'is_windows': is_windows } try: zip_token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), 'download-dir-link', sharelink.username, use_onetime=False) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) try: # used for file audit send_file_access_msg(request, repo, real_path, 'share-link') except Exception as e: logger.error(e) result['download_link'] = gen_dir_zip_download_url(zip_token) return Response(result)
def slug(request, slug, file_path="home.md"): """Show wiki page. """ # get wiki object or 404 wiki = get_object_or_404(Wiki, slug=slug) file_path = "/" + file_path is_dir = None file_id = seafile_api.get_file_id_by_path(wiki.repo_id, file_path) if file_id: is_dir = False dir_id = seafile_api.get_dir_id_by_path(wiki.repo_id, file_path) if dir_id: is_dir = True # compatible with old wiki url if is_dir is None: if len(file_path.split('.')) == 1: new_path = file_path[1:] + '.md' return HttpResponseRedirect( reverse('wiki:slug', args=[slug, new_path])) # perm check req_user = request.user.username if not req_user and not wiki.has_read_perm(request): return redirect('auth_login') else: if not wiki.has_read_perm(request): return render_permission_error(request, _(u'Unable to view Wiki')) file_type, ext = get_file_type_and_ext(posixpath.basename(file_path)) if file_type == IMAGE: file_url = reverse('view_lib_file', args=[wiki.repo_id, file_path]) return HttpResponseRedirect(file_url + "?raw=1") if not req_user: user_can_write = False elif req_user == wiki.username or check_folder_permission( request, wiki.repo_id, '/') == 'rw': user_can_write = True else: user_can_write = False is_public_wiki = False if wiki.permission == 'public': is_public_wiki = True has_index = False dirs = seafile_api.list_dir_by_path(wiki.repo_id, '/') for dir_obj in dirs: if dir_obj.obj_name == 'index.md': has_index = True break try: fs = FileShare.objects.get(repo_id=wiki.repo_id, path='/') except FileShare.DoesNotExist: fs = FileShare.objects.create_dir_link(wiki.username, wiki.repo_id, '/', permission='view_download') wiki.permission = 'public' wiki.save() is_public_wiki = True return render( request, "wiki/wiki.html", { "wiki": wiki, "page_name": file_path, "shared_token": fs.token, "shared_type": fs.s_type, "user_can_write": user_can_write, "file_path": file_path, "repo_id": wiki.repo_id, "search_repo_id": wiki.repo_id, "search_wiki": True, "is_public_wiki": is_public_wiki, "is_dir": is_dir, "has_index": has_index, })
def get(self, request, token): """ Get dirents of shared download dir. Permission checking: 1. only admin can perform this action. """ try: sharelink = 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) repo_id = sharelink.repo_id repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) obj_path = sharelink.path obj_id = seafile_api.get_dir_id_by_path(repo_id, obj_path) if not obj_id: error_msg = 'Folder not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) req_path = request.GET.get('path', '/') if req_path == '/': real_path = obj_path else: real_path = posixpath.join(obj_path, req_path.strip('/')) if real_path[-1] != '/': real_path += '/' real_obj_id = seafile_api.get_dir_id_by_path(repo_id, real_path) if not real_obj_id: error_msg = 'Folder %s not found.' % req_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, real_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: dirent_info = {} dirent_info['obj_name'] = dirent.obj_name dirent_info['path'] = posixpath.join(req_path, dirent.obj_name) 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 else: dirent_info['is_dir'] = False result.append(dirent_info) return Response(result)
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, repo_id, format=None): 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) # argument checking parent_dir = request.GET.get('parent_dir', None) dirent_name_string = request.GET.get('dirents', None) if not parent_dir: error_msg = 'parent_dir invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not dirent_name_string: error_msg = 'dirents invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # folder exist checking if not seafile_api.get_dir_id_by_path(repo_id, parent_dir): error_msg = 'Folder %s not found.' % parent_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission checking if check_folder_permission(request, repo_id, parent_dir) is None: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) dirent_name_list = string2list(dirent_name_string) dirent_list = [] total_size = 0 for dirent_name in dirent_name_list: dirent_name = dirent_name.strip('/') dirent_list.append(dirent_name) full_dirent_path = posixpath.join(parent_dir, dirent_name) current_dirent = seafile_api.get_dirent_by_path( repo_id, full_dirent_path) 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 if total_size > seaserv.MAX_DOWNLOAD_DIR_SIZE: error_msg = _('Total size exceeds limit.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) fake_obj_id = {} fake_obj_id['file_list'] = dirent_list fake_obj_id['parent_dir'] = parent_dir username = request.user.username try: token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), 'download-multi', username, False) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if len(dirent_list) > 10: send_file_access_msg(request, repo, parent_dir, 'web') else: for dirent_name in dirent_list: full_dirent_path = posixpath.join(parent_dir, dirent_name) send_file_access_msg(request, repo, full_dirent_path, 'web') download_url = '%s/files/%s' % (get_fileserver_root(), token) return Response({'url': download_url})
class DirView(APIView): """ Support uniform interface for directory operations, including create/delete/rename/list, etc. """ authentication_classes = (TokenAuthentication, SessionAuthentication) permission_classes = (IsAuthenticated, ) throttle_classes = (UserRateThrottle, ) def get_dir_info(self, repo_id, dir_path): dir_obj = seafile_api.get_dirent_by_path(repo_id, dir_path) dir_info = { 'type': 'dir', 'repo_id': repo_id, 'parent_dir': os.path.dirname(dir_path.rstrip('/')), 'obj_name': dir_obj.obj_name, 'obj_id': dir_obj.obj_id, 'mtime': timestamp_to_isoformat_timestr(dir_obj.mtime), } return dir_info def get(self, request, repo_id, format=None): """ Get sub dirent list info. Permission checking: 1. user with either 'r' or 'rw' permission. """ # argument check recursive = request.GET.get('recursive', '0') if recursive not in ('1', '0'): error_msg = "If you want to get recursive dir entries, you should set 'recursive' argument as '1'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) request_type = request.GET.get('t', '') if request_type and request_type not in ('f', 'd'): error_msg = "'t'(type) should be 'f' or 'd'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) with_thumbnail = request.GET.get('with_thumbnail', 'false') if with_thumbnail not in ('true', 'false'): error_msg = 'with_thumbnail invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) with_thumbnail = to_python_boolean(with_thumbnail) thumbnail_size = request.GET.get('thumbnail_size', 48) try: thumbnail_size = int(thumbnail_size) except ValueError: error_msg = 'thumbnail_size invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) with_parents = request.GET.get('with_parents', 'false') if with_parents not in ('true', 'false'): error_msg = 'with_parents invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) with_parents = to_python_boolean(with_parents) # recource check repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) parent_dir = request.GET.get('p', '/') parent_dir = normalize_dir_path(parent_dir) dir_id = seafile_api.get_dir_id_by_path(repo_id, parent_dir) if not dir_id: error_msg = 'Folder %s not found.' % parent_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check permission = check_folder_permission(request, repo_id, parent_dir) if not permission: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # get dir/file list recursively username = request.user.username if recursive == '1': try: dir_file_info_list = get_dir_file_recursively( username, repo_id, parent_dir, []) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) response_dict = {} response_dict['dirent_list'] = [] if request_type == 'f': for item in dir_file_info_list: if item['type'] == 'file': response_dict['dirent_list'].append(item) elif request_type == 'd': for item in dir_file_info_list: if item['type'] == 'dir': response_dict['dirent_list'].append(item) else: response_dict['dirent_list'] = dir_file_info_list return Response(response_dict) parent_dir_list = [] if not with_parents: # only return dirent list in current parent folder parent_dir_list.append(parent_dir) else: # if value of 'p' parameter is '/a/b/c' add with_parents's is 'true' # then return dirent list in '/', '/a', '/a/b' and '/a/b/c'. if parent_dir == '/': parent_dir_list.append(parent_dir) else: tmp_parent_dir = '/' parent_dir_list.append(tmp_parent_dir) for folder_name in parent_dir.strip('/').split('/'): tmp_parent_dir = posixpath.join(tmp_parent_dir, folder_name) 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 post(self, request, repo_id, format=None): """ Create, rename, revert dir. Permission checking: 1. create: user with 'rw' permission for current dir's parent dir; 2. rename: user with 'rw' permission for current dir; 3. revert: user with 'rw' permission for current dir's parent dir; """ # argument check path = request.GET.get('p', None) if not path or path[0] != '/': error_msg = 'p invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if path == '/': error_msg = 'Can not operate root dir.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) operation = request.data.get('operation', None) if not operation: error_msg = 'operation invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) operation = operation.lower() if operation not in ('mkdir', 'rename', 'revert'): error_msg = "operation can only be 'mkdir', 'rename' or 'revert'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) path = path.rstrip('/') username = request.user.username parent_dir = os.path.dirname(path) if operation == 'mkdir': # resource check parent_dir_id = seafile_api.get_dir_id_by_path(repo_id, parent_dir) if not parent_dir_id: error_msg = 'Folder %s not found.' % parent_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if check_folder_permission(request, repo_id, parent_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) new_dir_name = os.path.basename(path) if not is_valid_dirent_name(new_dir_name): return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.') retry_count = 0 while retry_count < 10: new_dir_name = check_filename_with_rename( repo_id, parent_dir, new_dir_name) try: seafile_api.post_dir(repo_id, parent_dir, new_dir_name, username) break except SearpcError as e: if str(e) == 'file already exists': retry_count += 1 else: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) new_dir_path = posixpath.join(parent_dir, new_dir_name) dir_info = self.get_dir_info(repo_id, new_dir_path) resp = Response(dir_info) return resp if operation == 'rename': # resource check dir_id = seafile_api.get_dir_id_by_path(repo_id, path) if not dir_id: error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if check_folder_permission(request, repo_id, path) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) old_dir_name = os.path.basename(path) new_dir_name = request.data.get('newname', None) if not new_dir_name: error_msg = 'newname invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not is_valid_dirent_name(new_dir_name): return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.') if new_dir_name == old_dir_name: dir_info = self.get_dir_info(repo_id, path) resp = Response(dir_info) return resp try: # rename duplicate name new_dir_name = check_filename_with_rename( repo_id, parent_dir, new_dir_name) # rename dir seafile_api.rename_file(repo_id, parent_dir, old_dir_name, new_dir_name, username) new_dir_path = posixpath.join(parent_dir, new_dir_name) dir_info = self.get_dir_info(repo_id, new_dir_path) resp = Response(dir_info) return resp except SearpcError, e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if operation == 'revert': commit_id = request.data.get('commit_id', None) if not commit_id: error_msg = 'commit_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if seafile_api.get_dir_id_by_path(repo_id, path): # dir exists in repo if check_folder_permission(request, repo_id, path) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) else: # dir NOT exists in repo if check_folder_permission(request, repo_id, '/') != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: seafile_api.revert_dir(repo_id, commit_id, path, username) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return Response({'success': True})
def get(self, request): """get file download link by dtable api token Permission: 1. valid token """ # argument check auth = request.META.get('HTTP_AUTHORIZATION', '').split() if not auth or auth[0].lower() != 'token' or len(auth) != 2: return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') api_token = auth[1] path = request.GET.get('path', '/') # resource check try: api_token_obj = DTableAPIToken.objects.get_by_token(api_token) if not api_token_obj: return api_error(status.HTTP_404_NOT_FOUND, 'api token not found.') except Exception as e: logger.error(e) error_msg = 'Internal Server Error.' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) dtable = api_token_obj.dtable table_name = dtable.name workspace_id = dtable.workspace_id error, workspace, dtable = _resource_check(workspace_id, table_name) if error: return error repo_id = workspace.repo_id asset_dir_path = '/asset/' + str(dtable.uuid) asset_dir_id = seafile_api.get_dir_id_by_path(repo_id, asset_dir_path) if not asset_dir_id: error_msg = 'asset not found.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) target_path = os.path.join( asset_dir_path, path.strip('/')) # target_path is path inside repo file_id = seafile_api.get_file_id_by_path(repo_id, target_path.strip('/')) if not file_id: error_msg = 'path %s not found.' % path return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: download_token = seafile_api.get_fileserver_access_token( repo_id, file_id, 'download-link', request.user.username, use_onetime=False) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) file_name = os.path.basename(path.rstrip('/')) download_link = gen_file_get_url(download_token, file_name) return Response({'download_link': download_link})
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', '/') if req_path[-1] != '/': req_path += '/' if req_path == '/': real_path = fileshare.path else: real_path = posixpath.join(fileshare.path, req_path.lstrip('/')) if real_path[-1] != '/': # 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, _(u'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() traffic_over_limit = user_traffic_over_limit(fileshare.username) 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 == IMAGE or file_type == VIDEO) and ENABLE_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) return render(request, 'view_shared_dir.html', { 'repo': repo, 'token': token, 'path': req_path, 'username': username, 'dir_name': dir_name, 'file_list': file_list, 'dir_list': dir_list, 'zipped': zipped, 'traffic_over_limit': traffic_over_limit, 'permissions': permissions, 'ENABLE_THUMBNAIL': ENABLE_THUMBNAIL, 'mode': mode, 'thumbnail_size': thumbnail_size, })
def get(self, request): """ get upload link. """ if not self._can_generate_shared_link(request): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) repo_id = request.GET.get('repo_id', None) if 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) # repo level permission check if not check_folder_permission(request, repo_id, '/'): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) path = request.GET.get('path', None) if path: try: dir_id = seafile_api.get_dir_id_by_path(repo_id, path) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not dir_id: error_msg = 'folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # folder permission check if not check_folder_permission(request, repo_id, path): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) username = request.user.username upload_link_shares = UploadLinkShare.objects.filter(username=username) # filter result by args if repo_id: upload_link_shares = filter(lambda ufs: ufs.repo_id == repo_id, upload_link_shares) if path: if path[-1] != '/': path = path + '/' upload_link_shares = filter(lambda ufs: ufs.path == path, upload_link_shares) result = [] for uls in upload_link_shares: link_info = self._get_upload_link_info(uls) result.append(link_info) if len(result) == 1: result = result[0] return Response(result)