def publish(self, operator): # check whether origin file is updated r_repo = seafile_api.get_repo(self.origin_repo_id) if not r_repo: raise DraftFileConflict file_uuid = FileUUIDMap.objects.get_fileuuidmap_by_uuid(self.origin_file_uuid) if not file_uuid: # TODO update error msg raise DraftFileConflict if file_uuid.parent_path == '/': origin_file_path = file_uuid.parent_path + file_uuid.filename else: origin_file_path = file_uuid.parent_path + '/' + file_uuid.filename file_id = seafile_api.get_file_id_by_path(self.origin_repo_id, origin_file_path) draft_file_name = os.path.basename(self.draft_file_path) draft_file_path = os.path.dirname(self.draft_file_path) file_name = file_uuid.filename if file_id: if file_id != self.origin_file_version and self.draft_file_path != origin_file_path: raise DraftFileConflict if self.draft_file_path == origin_file_path: f = os.path.splitext(draft_file_name)[0][:-7] file_type = os.path.splitext(draft_file_name)[-1] file_name = f + file_type # move draft file to origin file seafile_api.move_file( self.origin_repo_id, draft_file_path, draft_file_name, self.origin_repo_id, file_uuid.parent_path, file_name, replace=1, username=operator, need_progress=0, synchronous=1 ) else: # move draft file to origin file seafile_api.move_file( self.origin_repo_id, draft_file_path, draft_file_name, self.origin_repo_id, file_uuid.parent_path, file_name, replace=1, username=operator, need_progress=0, synchronous=1 ) published_file_path = posixpath.join(file_uuid.parent_path, file_name) # get draft published version file_id = seafile_api.get_file_id_by_path(self.origin_repo_id, published_file_path) self.publish_file_version = file_id self.status = 'published' self.save() return published_file_path
def get_onlyoffice_dict(username, repo_id, file_path, file_id='', can_edit=False, can_download=True): repo = seafile_api.get_repo(repo_id) if repo.is_virtual: origin_repo_id = repo.origin_repo_id origin_file_path = posixpath.join(repo.origin_path, file_path.strip('/')) # for view history/trash/snapshot file if not file_id: file_id = seafile_api.get_file_id_by_path(origin_repo_id, origin_file_path) else: origin_repo_id = repo_id origin_file_path = file_path if not file_id: file_id = seafile_api.get_file_id_by_path(repo_id, file_path) dl_token = seafile_api.get_fileserver_access_token(repo_id, file_id, 'download', username, use_onetime=True) if not dl_token: return None filetype, fileext = get_file_type_and_ext(file_path) if fileext in ('xls', 'xlsx', 'ods', 'fods', 'csv'): document_type = 'spreadsheet' elif fileext in ('pptx', 'ppt', 'odp', 'fodp', 'ppsx', 'pps'): document_type = 'presentation' else: document_type = 'text' doc_info = json.dumps({'repo_id': repo_id, 'file_path': file_path, 'username': username}) doc_key = hashlib.md5(force_bytes(origin_repo_id + origin_file_path + file_id)).hexdigest()[:20] cache.set("ONLYOFFICE_%s" % doc_key, doc_info, None) file_name = os.path.basename(file_path.rstrip('/')) doc_url = gen_file_get_url(dl_token, file_name) base_url = get_site_scheme_and_netloc() onlyoffice_editor_callback_url = reverse('onlyoffice_editor_callback') calllback_url = urlparse.urljoin(base_url, onlyoffice_editor_callback_url) return_dict = { 'repo_id': repo_id, 'path': file_path, 'ONLYOFFICE_APIJS_URL': ONLYOFFICE_APIJS_URL, 'file_type': fileext, 'doc_key': doc_key, 'doc_title': file_name, 'doc_url': doc_url, 'document_type': document_type, 'callback_url': calllback_url, 'can_edit': can_edit, 'can_download': can_download, 'username': username, 'enable_watermark': ENABLE_WATERMARK and not can_edit, } return return_dict
def list_shared_links(request): """List share links, and remove invalid links(file/dir is deleted or moved). """ username = request.user.username 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) return render_to_response('repo/shared_links.html', { "fileshares": p_fileshares, }, context_instance=RequestContext(request))
def post(self, request, org_id, format=None): """Create a file draft if the user has read-write permission to the origin file """ repo_id = request.POST.get('repo_id', '') file_path = request.POST.get('file_path', '') repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) # perm check perm = check_folder_permission(request, repo.id, file_path) if perm != PERMISSION_READ_WRITE: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) file_id = seafile_api.get_file_id_by_path(repo.id, file_path) if not file_id: return api_error(status.HTTP_404_NOT_FOUND, "File %s not found" % file_path) username = request.user.username try: d = Draft.objects.add(username, repo, file_path, file_id) return Response(d.to_dict()) except DraftFileExist: return api_error(status.HTTP_409_CONFLICT, 'Draft already exists.') except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
def format_file_comment_msg(self): try: d = json.loads(self.detail) except Exception as e: logger.error(e) return _(u"Internal error") repo_id = d['repo_id'] file_path = d['file_path'] author = d['author'] comment = d['comment'] repo = seafile_api.get_repo(repo_id) if repo is None or not seafile_api.get_file_id_by_path(repo.id, file_path): self.delete() return None file_name = os.path.basename(file_path) msg = _("File <a href='%(file_url)s'>%(file_name)s</a> has a new comment from user %(author)s") % { 'file_url': reverse('view_lib_file', args=[repo_id, file_path]), 'file_name': escape(file_name), 'author': escape(email2nickname(author)), } return msg
def post(self, request, repo_id, format=None): """Post a comments of a file. """ path = request.GET.get('p', '/').rstrip('/') if not path: return api_error(status.HTTP_400_BAD_REQUEST, 'Wrong path.') try: avatar_size = int(request.GET.get('avatar_size', AVATAR_DEFAULT_SIZE)) except ValueError: avatar_size = AVATAR_DEFAULT_SIZE try: obj_id = seafile_api.get_file_id_by_path(repo_id, path) except SearpcError as e: logger.error(e) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal error.') if not obj_id: return api_error(status.HTTP_404_NOT_FOUND, 'File not found.') comment = request.data.get('comment', '') if not comment: return api_error(status.HTTP_400_BAD_REQUEST, 'Comment can not be empty.') username = request.user.username o = FileComment.objects.add_by_file_path( repo_id=repo_id, file_path=path, author=username, comment=comment) comment = o.to_dict() comment.update(user_to_dict(request.user.username, request=request, avatar_size=avatar_size)) return Response(comment, status=201)
def extract_xmind_image(repo_id, path, size=XMIND_IMAGE_SIZE): # get inner path file_name = os.path.basename(path) file_id = seafile_api.get_file_id_by_path(repo_id, path) fileserver_token = seafile_api.get_fileserver_access_token(repo_id, file_id, 'view', '') inner_path = gen_inner_file_get_url(fileserver_token, file_name) # extract xmind image xmind_file = urllib2.urlopen(inner_path) xmind_file_str = StringIO(xmind_file.read()) xmind_zip_file = zipfile.ZipFile(xmind_file_str, 'r') extracted_xmind_image = xmind_zip_file.read('Thumbnails/thumbnail.png') extracted_xmind_image_str = StringIO(extracted_xmind_image) # save origin xmind image to thumbnail folder thumbnail_dir = os.path.join(THUMBNAIL_ROOT, str(size)) if not os.path.exists(thumbnail_dir): os.makedirs(thumbnail_dir) local_xmind_image = os.path.join(thumbnail_dir, file_id) try: ret = _create_thumbnail_common(extracted_xmind_image_str, local_xmind_image, size) return ret except Exception as e: logger.error(e) return (False, 500)
def handleMove(self, destPath): if self.provider.readonly: raise DAVError(HTTP_FORBIDDEN) parts = destPath.strip("/").split("/", 1) if len(parts) <= 1: raise DAVError(HTTP_BAD_REQUEST) repo_name = parts[0] rel_path = parts[1] dest_dir, dest_file = os.path.split(rel_path) dest_repo = getRepoByName(repo_name, self.username, self.org_id, self.is_guest) if seafile_api.check_permission_by_path(dest_repo.id, self.rel_path, self.username) != "rw": raise DAVError(HTTP_FORBIDDEN) src_dir, src_file = os.path.split(self.rel_path) if not src_file: raise DAVError(HTTP_BAD_REQUEST) if not seafile_api.is_valid_filename(dest_repo.id, dest_file): raise DAVError(HTTP_BAD_REQUEST) # some clients such as GoodReader requires "overwrite" semantics file_id_dest = seafile_api.get_file_id_by_path(dest_repo.id, rel_path) if file_id_dest != None: seafile_api.del_file(dest_repo.id, dest_dir, dest_file, self.username) seafile_api.move_file(self.repo.id, src_dir, src_file, dest_repo.id, dest_dir, dest_file, self.username, NEED_PROGRESS, SYNCHRONOUS) return True
def prepare_starred_files(files): array = [] for f in files: sfile = {'org' : f.org_id, 'repo' : f.repo.id, 'repo_id' : f.repo.id, 'repo_name' : f.repo.name, 'path' : f.path, 'icon_path' : file_icon_filter(f.path), 'file_name' : os.path.basename(f.path), 'mtime' : f.last_modified, 'mtime_relative': translate_seahub_time(f.last_modified), 'dir' : f.is_dir, 'repo_encrypted' : f.repo.encrypted } if not f.is_dir: try: file_id = seafile_api.get_file_id_by_path(f.repo.id, f.path) sfile['oid'] = file_id sfile['size'] = get_file_size(f.repo.store_id, f.repo.version, file_id) except SearpcError as e: logger.error(e) pass array.append(sfile) return array
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(self, request, repo_id): """list all tags of a file. """ # argument check file_path = request.GET.get('file_path') if not file_path: error_msg = 'file_path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_path = normalize_file_path(file_path) # 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) file_id = seafile_api.get_file_id_by_path(repo_id, file_path) if not file_id: error_msg = 'File not found.' 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) try: file_tags = FileTags.objects.get_file_tag_by_path(repo_id, file_path) except Exception as e: logger.error(e) error_msg = 'Internal Server Error.' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return Response({"file_tags": file_tags}, status=status.HTTP_200_OK)
def get_file_last_modified(self, repo_id, file_path): """ Arguments: - `self`: - `repo_id`: - `file_path`: """ last_modified = 0 file_path_hash = calc_file_path_hash(file_path) file_id = seafile_api.get_file_id_by_path(repo_id, file_path) try: fc = super(FileLastModifiedInfoManager, self).get( repo_id=repo_id, file_path_hash=file_path_hash) except self.model.DoesNotExist: # has no cache yet user, last_modified = self._calc_file_last_modified( repo_id, file_path, file_path_hash, file_id) else: # cache found if fc.file_id != file_id: # but cache is outdated fc.delete() user, last_modified = self._calc_file_last_modified( repo_id, file_path, file_path_hash, file_id) else: # cache is valid user, last_modified = fc.email, fc.last_modified return user, last_modified
def view_shared_file(request, token): """ Preview file via shared link. """ assert token is not None # Checked by URLconf try: fileshare = FileShare.objects.get(token=token) except FileShare.DoesNotExist: raise Http404 shared_by = fileshare.username repo_id = fileshare.repo_id repo = get_repo(repo_id) if not repo: raise Http404 path = fileshare.path.rstrip('/') # Normalize file path obj_id = seafile_api.get_file_id_by_path(repo_id, path) if not obj_id: return render_error(request, _(u'File does not exist')) file_size = seafile_api.get_file_size(obj_id) filename = os.path.basename(path) filetype, fileext = get_file_type_and_ext(filename) access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id, 'view', '') raw_path = gen_file_get_url(access_token, filename) inner_path = gen_inner_file_get_url(access_token, filename) # get file content ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '', 'file_encoding_list': [], 'html_exists': False, 'filetype': filetype} fsize = get_file_size(obj_id) exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype) if exceeds_limit: err = err_msg else: """Choose different approach when dealing with different type of file.""" if is_textual_file(file_type=filetype): handle_textual_file(request, filetype, inner_path, ret_dict) elif filetype == DOCUMENT: handle_document(inner_path, obj_id, fileext, ret_dict) elif filetype == PDF: handle_pdf(inner_path, obj_id, fileext, ret_dict) # Increase file shared link view_cnt, this operation should be atomic fileshare.view_cnt = F('view_cnt') + 1 fileshare.save() # send statistic messages if ret_dict['filetype'] != 'Unknown': try: obj_size = seafserv_threaded_rpc.get_file_size(obj_id) send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \ (repo.id, shared_by, obj_id, obj_size)) except SearpcError, e: logger.error('Error when sending file-view message: %s' % str(e))
def delete(self, request, repo_id, format=None): # delete file 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', None) if not path: error_msg = 'p invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_id = seafile_api.get_file_id_by_path(repo_id, path) if not file_id: return Response({'success': True}) parent_dir = os.path.dirname(path) if check_folder_permission(request, repo_id, parent_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) 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) if request.GET.get('reloaddir', '').lower() == 'true': return reloaddir(request, repo, parent_dir) else: return Response({'success': True})
def get_group_msgs(groupid, page, username): # Show 15 group messages per page. paginator = Paginator(GroupMessage.objects.filter(group_id=groupid).order_by("-timestamp"), 15) # If page request (9999) is out of range, return None try: group_msgs = paginator.page(page) except (EmptyPage, InvalidPage): return None # Force evaluate queryset to fix some database error for mysql. group_msgs.object_list = list(group_msgs.object_list) attachments = MessageAttachment.objects.filter(group_message__in=group_msgs.object_list) msg_replies = MessageReply.objects.filter(reply_to__in=group_msgs.object_list) reply_to_list = [r.reply_to_id for r in msg_replies] for msg in group_msgs.object_list: msg.reply_cnt = reply_to_list.count(msg.id) msg.replies = [] for r in msg_replies: if msg.id == r.reply_to_id: msg.replies.append(r) msg.replies = msg.replies[-3:] for att in attachments: if att.group_message_id != msg.id: continue # Attachment name is file name or directory name. # If is top directory, use repo name instead. path = att.path if path == "/": repo = seafile_api.get_repo(att.repo_id) if not repo: # TODO: what should we do here, tell user the repo # is no longer exists? continue att.name = repo.name else: path = path.rstrip("/") # cut out last '/' if possible att.name = os.path.basename(path) # Load to discuss page if attachment is a image and from recommend. if att.attach_type == "file" and att.src == "recommend": att.filetype, att.fileext = get_file_type_and_ext(att.name) if att.filetype == IMAGE: att.obj_id = seafile_api.get_file_id_by_path(att.repo_id, path) if not att.obj_id: att.err = "File does not exist" else: att.token = seafile_api.get_fileserver_access_token(att.repo_id, att.obj_id, "view", username) att.img_url = gen_file_get_url(att.token, att.name) msg.attachment = att return group_msgs
def test_can_get_file_downloadblks_info(self): file_id = seafile_api.get_file_id_by_path(self.repo_id, self.file_path) self.login_as(self.user) resp = self.client.get(self.url + '?p=' + self.file_path + '&op=downloadblks') self.assertEqual(200, resp.status_code) json_resp = json.loads(resp.content) assert json_resp['file_id'] == file_id
def test_can_download(self): obj_id = seafile_api.get_file_id_by_path(self.repo.id, self.file) resp = self.client.get(reverse('download_file', args=[ self.repo.id, obj_id])) self.assertEqual(302, resp.status_code) assert '8082' in resp.get('location')
def test_can_get(self): obj_id = seafile_api.get_file_id_by_path(self.repo.id, self.file) rst = get_file_view_path_and_perm(self.request, self.repo.id, obj_id, self.file) assert '8082' in rst[0] assert '8082' in rst[1] assert rst[2] == 'rw'
def view_file_via_shared_dir(request, token): assert token is not None # Checked by URLconf try: fileshare = FileShare.objects.get(token=token) except FileShare.DoesNotExist: raise Http404 shared_by = fileshare.username repo_id = fileshare.repo_id repo = get_repo(repo_id) if not repo: raise Http404 path = request.GET.get('p', '').rstrip('/') if not path: raise Http404 if not path.startswith(fileshare.path): # Can not view upper dir of shared dir raise Http404 zipped = gen_path_link(path, '') obj_id = seafile_api.get_file_id_by_path(repo_id, path) if not obj_id: return render_error(request, _(u'File does not exist')) file_size = seafile_api.get_file_size(obj_id) filename = os.path.basename(path) filetype, fileext = get_file_type_and_ext(filename) access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id, 'view', '') raw_path = gen_file_get_url(access_token, filename) inner_path = gen_inner_file_get_url(access_token, filename) # get file content ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '', 'file_encoding_list': [], 'html_exists': False, 'filetype': filetype} fsize = get_file_size(obj_id) exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype) if exceeds_limit: err = err_msg else: """Choose different approach when dealing with different type of file.""" if is_textual_file(file_type=filetype): handle_textual_file(request, filetype, inner_path, ret_dict) elif filetype == DOCUMENT: handle_document(inner_path, obj_id, fileext, ret_dict) elif filetype == PDF: handle_pdf(inner_path, obj_id, fileext, ret_dict) # send statistic messages try: obj_size = seafserv_threaded_rpc.get_file_size(obj_id) send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \ (repo.id, shared_by, obj_id, obj_size)) except SearpcError, e: logger.error('Error when sending file-view message: %s' % str(e))
def delete(self, request, repo_id, format=None): """ Delete file. 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) path = normalize_file_path(path) # 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) file_id = seafile_api.get_file_id_by_path(repo_id, path) if not file_id: return Response({'success': True}) # permission check parent_dir = os.path.dirname(path) username = request.user.username if check_folder_permission(request, repo_id, parent_dir) != PERMISSION_READ_WRITE: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check file lock try: is_locked, locked_by_me = check_file_lock(repo_id, path, username) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if is_locked and not locked_by_me: error_msg = _("File is locked") return api_error(status.HTTP_403_FORBIDDEN, error_msg) # delete file 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 put(self, request, repo_id, format=None): """ Currently only for lock and unlock file operation. Permission checking: 1. user with 'rw' permission for current file; """ if not is_pro_version(): error_msg = 'file lock feature only supported in professional edition.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # 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) 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 ('lock', 'unlock'): error_msg = "operation can only be 'lock', or 'unlock'." 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) file_id = seafile_api.get_file_id_by_path(repo_id, path) 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) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) username = request.user.username is_locked, locked_by_me = check_file_lock(repo_id, path, username) if operation == 'lock': if not is_locked: # lock file expire = request.data.get('expire', FILE_LOCK_EXPIRATION_DAYS) try: seafile_api.lock_file(repo_id, path.lstrip('/'), username, expire) except SearpcError, e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
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 post(self, request, repo_id, format=None): """Post a comments of a file. """ # argument check path = request.GET.get('p', '/').rstrip('/') if not path: return api_error(status.HTTP_400_BAD_REQUEST, 'Wrong path.') comment = request.data.get('comment', '') if not comment: return api_error(status.HTTP_400_BAD_REQUEST, 'Comment can not be empty.') try: avatar_size = int(request.GET.get('avatar_size', AVATAR_DEFAULT_SIZE)) except ValueError: avatar_size = AVATAR_DEFAULT_SIZE # resource check try: file_id = seafile_api.get_file_id_by_path(repo_id, path) except SearpcError as e: logger.error(e) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal error.') if not file_id: return api_error(status.HTTP_404_NOT_FOUND, 'File not found.') # permission check if check_folder_permission(request, repo_id, '/') is None: return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') detail = request.data.get('detail', '') username = request.user.username file_comment = FileComment.objects.add_by_file_path( repo_id=repo_id, file_path=path, author=username, comment=comment, detail=detail) repo = seafile_api.get_repo(repo_id) repo_owner = get_repo_owner(request, repo.id) if is_draft_file(repo_id, path): draft = Draft.objects.get(origin_repo_id=repo_id, draft_file_path=path) comment_draft_successful.send(sender=None, draft=draft, comment=comment, author=username) else: comment_file_successful.send(sender=None, repo=repo, repo_owner=repo_owner, file_path=path, comment=comment, author=username) comment = file_comment.to_dict() comment.update(user_to_dict(username, request=request, avatar_size=avatar_size)) return Response(comment, status=201)
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 setUp(self): share_file_info = { 'username': '******', 'repo_id': self.repo.id, 'path': '/', 'password': '******', 'expire_date': None, } self.fs = FileShare.objects.create_dir_link(**share_file_info) self.file_id = seafile_api.get_file_id_by_path(self.repo.id, self.file) self.filename= os.path.basename(self.file)
def draft(request, pk): d = get_object_or_404(Draft, pk=pk) # check perm uuid = FileUUIDMap.objects.get_fileuuidmap_by_uuid(d.origin_file_uuid) origin_repo_id = d.origin_repo_id permission = check_folder_permission(request, origin_repo_id, '/') if not permission: return render_permission_error(request, _(u'Permission denied.')) origin_file_path = posixpath.join(uuid.parent_path, uuid.filename) origin_file = seafile_api.get_file_id_by_path(origin_repo_id, origin_file_path) origin_file_exists = True if not origin_file: origin_file_exists = False draft_file = seafile_api.get_file_id_by_path(origin_repo_id, d.draft_file_path) draft_file_exists = True if not draft_file: draft_file_exists = False draft_file_name = os.path.basename(d.draft_file_path) author_info = user_to_dict(d.username, avatar_size=32) return render(request, "draft.html", { "draft_id": d.id, "draft_repo_id": origin_repo_id, "draft_origin_file_path": origin_file_path, "draft_file_path": d.draft_file_path, "draft_file_name": draft_file_name, "permission": permission, "author": author_info['user_name'], "author_avatar_url": author_info['avatar_url'], "origin_file_exists": origin_file_exists, "draft_file_exists": draft_file_exists, "draft_status": d.status, "publish_file_version": d.publish_file_version, "origin_file_version": d.origin_file_version })
def prepare_starred_files(files): array = [] for f in files: sfile = {"org": f.org_id, "repo": f.repo.id, "path": f.path, "mtime": f.last_modified, "dir": f.is_dir} if not f.is_dir: try: file_id = seafile_api.get_file_id_by_path(f.repo.id, f.path) sfile["oid"] = file_id sfile["size"] = get_file_size(f.repo.store_id, f.repo.version, file_id) except SearpcError, e: pass array.append(sfile)
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: 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: 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 post(self, request, repo_id): """add a tag for a file. """ # argument check file_path = request.data.get('file_path') if not file_path: error_msg = 'file_path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_path = normalize_file_path(file_path) repo_tag_id = request.data.get('repo_tag_id') if not repo_tag_id: error_msg = 'repo_tag_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) file_id = seafile_api.get_file_id_by_path(repo_id, file_path) if not file_id: error_msg = 'File not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) repo_tag = RepoTags.objects.get_repo_tag_by_id(repo_tag_id) if not repo_tag: error_msg = 'repo_tag not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) file_tag = FileTags.objects.get_file_tag(repo_id, repo_tag_id, file_path) if file_tag: error_msg = 'file tag %s already exist.' % repo_tag_id return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # permission check if check_folder_permission(request, repo_id, '/') != PERMISSION_READ_WRITE: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: file_tag = FileTags.objects.add_file_tag(repo_id, repo_tag_id, file_path) except Exception as e: logger.error(e) error_msg = 'Internal Server Error.' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return Response({"file_tag": file_tag.to_dict()}, status=status.HTTP_201_CREATED)
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 put(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) path = request.GET.get('p', '') if not path: error_msg = 'p invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_id = seafile_api.get_file_id_by_path(repo_id, path) if not file_id: error_msg = 'File %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 operation = request.data.get('operation', '') if operation.lower() == 'lock': is_locked, locked_by_me = check_file_lock(repo_id, path, username) if is_locked: error_msg = 'File is already locked.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # lock file expire = request.data.get('expire', FILE_LOCK_EXPIRATION_DAYS) try: seafile_api.lock_file(repo_id, path.lstrip('/'), username, expire) return Response({'success': True}) except SearpcError, e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
def prepare_starred_files(files): array = [] for f in files: sfile = {'org' : f.org_id, 'repo' : f.repo.id, 'repo_name' : f.repo.name, 'path' : f.path, 'icon_path' : file_icon_filter(f.path), 'file_name' : os.path.basename(f.path), 'mtime' : f.last_modified, 'mtime_relative': translate_seahub_time(f.last_modified), 'dir' : f.is_dir } if not f.is_dir: try: file_id = seafile_api.get_file_id_by_path(f.repo.id, f.path) sfile['oid'] = file_id sfile['size'] = get_file_size(f.repo.store_id, f.repo.version, file_id) except SearpcError, e: pass array.append(sfile)
def add(self, username, repo, file_path, file_exist=True, file_id=None, org_id=-1, status='open'): file_path = normalize_file_path(file_path) parent_path = os.path.dirname(file_path) filename = os.path.basename(file_path) # origin file uuid file_uuid = FileUUIDMap.objects.get_or_create_fileuuidmap( repo.id, parent_path, filename, is_dir=False) if file_id is None: file_id = seafile_api.get_file_id_by_path(repo.id, file_path) if file_exist: file_path = self.create_exist_file_draft(repo, username, file_uuid, file_path) draft = self.model(username=username, origin_repo_id=repo.id, origin_file_uuid=file_uuid.uuid, status=status, origin_file_version=file_id, draft_file_path=file_path) draft.save(using=self._db) return draft
def delete(self, request, repo_id, format=None): """Delete a participant """ # argument check path = request.data.get('path') if not path: return api_error(status.HTTP_400_BAD_REQUEST, 'path invalid.') path = normalize_file_path(path) email = request.data.get('email') if not email or not is_valid_username(email): return api_error(status.HTTP_400_BAD_REQUEST, 'email invalid.') # resource check file_id = seafile_api.get_file_id_by_path(repo_id, path) if not file_id: return api_error(status.HTTP_404_NOT_FOUND, 'File %s not found.' % path) # permission check if not check_folder_permission(request, repo_id, '/'): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') # main try: file_uuid = FileUUIDMap.objects.get_or_create_fileuuidmap_by_path( repo_id, path, False) if not FileParticipant.objects.get_participant(file_uuid, email): return api_error(status.HTTP_404_NOT_FOUND, 'Participant %s not found.' % email) FileParticipant.objects.delete_participant(file_uuid, email) except Exception as e: logger.error(e) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error') return Response({'success': True})
def delete(self, request, repo_id): """ delete a single file/folder in a library """ if not request.user.admin_permissions.can_manage_library(): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') 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(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 latest_entry(request, workspace_id, dtable_uuid, path): workspace = Workspaces.objects.get_workspace_by_id(workspace_id) if not workspace: return None repo_id = workspace.repo_id path = normalize_file_path(os.path.join('/asset', dtable_uuid, path)) file_id = seafile_api.get_file_id_by_path(repo_id, path) if file_id: try: size = request.GET.get('size') thumbnail_file = os.path.join(THUMBNAIL_ROOT, str(size), file_id) last_modified_time = os.path.getmtime(thumbnail_file) # convert float to datatime obj return datetime.datetime.fromtimestamp(last_modified_time) except os.error: # no thumbnail file exists return None except Exception as e: # catch all other errors logger.error(e, exc_info=True) return None else: return None
def view_lib_as_wiki(request, repo_id, path): if not path.startswith('/'): path = '/' + path repo = seafile_api.get_repo(repo_id) is_dir = None file_id = seafile_api.get_file_id_by_path(repo.id, path) if file_id: is_dir = False dir_id = seafile_api.get_dir_id_by_path(repo.id, path) if dir_id: is_dir = True user_perm = check_folder_permission(request, repo.id, '/') if user_perm is None: return render_error(request, _('Permission denied')) if user_perm == 'rw': user_can_write = True else: user_can_write = False return render( request, 'view_lib_as_wiki.html', { 'seafile_collab_server': SEAFILE_COLLAB_SERVER, 'repo_id': repo_id, 'service_url': get_service_url().rstrip('/'), 'initial_path': path, 'is_dir': is_dir, 'repo_name': repo.name, 'permission': user_can_write, 'share_link_expire_days_min': SHARE_LINK_EXPIRE_DAYS_MIN, 'share_link_expire_days_max': SHARE_LINK_EXPIRE_DAYS_MAX, })
def get(self, request, repo_id, format=None): """List all participants of a file. """ # argument check path = request.GET.get('path') if not path: return api_error(status.HTTP_400_BAD_REQUEST, 'path invalid.') path = normalize_file_path(path) # resource check file_id = seafile_api.get_file_id_by_path(repo_id, path) if not file_id: return api_error(status.HTTP_404_NOT_FOUND, 'File %s not found.' % path) # permission check if not check_folder_permission(request, repo_id, '/'): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') # main try: file_uuid = FileUUIDMap.objects.get_or_create_fileuuidmap_by_path( repo_id, path, False) participant_list = [] participant_queryset = FileParticipant.objects.get_participants( file_uuid) for participant in participant_queryset: participant_info = get_user_common_info(participant.username) participant_list.append(participant_info) except Exception as e: logger.error(e) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error.') return Response({'participant_list': participant_list})
def get(self, request, format=None): """ get file content """ token = request.GET.get('access_token', None) info_dict = cache.get('thirdparty_editor_access_token_' + token) repo_id = info_dict['repo_id'] file_path = info_dict['file_path'] obj_id = seafile_api.get_file_id_by_path(repo_id, file_path) file_name = os.path.basename(file_path) try: fileserver_token = seafile_api.get_fileserver_access_token( repo_id, obj_id, 'view', '', use_onetime=False) except SearpcError as e: logger.error(e) return HttpResponse(json.dumps({}), status=500, content_type=json_content_type) if not fileserver_token: return HttpResponse(json.dumps({}), status=500, content_type=json_content_type) inner_path = gen_inner_file_get_url(fileserver_token, file_name) try: file_content = urllib.request.urlopen(inner_path).read() except urllib.error.URLError as e: logger.error(e) return HttpResponse(json.dumps({}), status=500, content_type=json_content_type) return HttpResponse(file_content, content_type="application/octet-stream")
def view_raw_shared_file(request, token, obj_id, file_name): """Returns raw content of a shared file. Arguments: - `request`: - `token`: - `obj_id`: - `file_name`: """ fileshare = FileShare.objects.get_valid_file_link_by_token(token) if fileshare is None: raise Http404 repo_id = fileshare.repo_id repo = get_repo(repo_id) if not repo: raise Http404 # Normalize file path based on file or dir share link if fileshare.is_file_share_link(): file_path = fileshare.path.rstrip('/') else: file_path = fileshare.path.rstrip('/') + '/' + file_name real_obj_id = seafile_api.get_file_id_by_path(repo_id, file_path) if not real_obj_id: raise Http404 if real_obj_id != obj_id: # perm check raise Http404 filename = os.path.basename(file_path) username = request.user.username token = web_get_access_token(repo_id, real_obj_id, 'view', username) outer_url = gen_file_get_url(token, filename) return HttpResponseRedirect(outer_url)
def publish(self): # check whether origin file is updated r_repo = seafile_api.get_repo(self.origin_repo_id) if not r_repo: raise DraftFileConflict origin_file_path = self.origin_file_uuid.parent_path + self.origin_file_uuid.filename file_id = seafile_api.get_file_id_by_path(self.origin_repo_id, origin_file_path) if not file_id: raise DraftFileConflict if file_id != self.origin_file_version: raise DraftFileConflict # move draft file to origin file seafile_api.move_file( self.draft_repo_id, '/', self.draft_file_path.lstrip('/'), self.origin_repo_id, self.origin_file_uuid.parent_path, self.origin_file_uuid.filename, replace=1, username=self.username, need_progress=0, synchronous=1 ) self.delete()
def publish(self): # check whether origin file is updated r_repo = seafile_api.get_repo(self.origin_repo_id) if not r_repo: raise DraftFileConflict if self.origin_file_uuid.parent_path == '/': origin_file_path = self.origin_file_uuid.parent_path + self.origin_file_uuid.filename else: origin_file_path = self.origin_file_uuid.parent_path + '/' + self.origin_file_uuid.filename file_id = seafile_api.get_file_id_by_path(self.origin_repo_id, origin_file_path) if not file_id: raise DraftFileConflict draft_file_name = os.path.basename(self.draft_file_path) draft_file_path = os.path.dirname(self.draft_file_path) file_name = self.origin_file_uuid.filename if file_id != self.origin_file_version and self.draft_file_path != origin_file_path: raise DraftFileConflict if self.draft_file_path == origin_file_path: f = os.path.splitext(draft_file_name)[0][:-7] file_type = os.path.splitext(draft_file_name)[-1] file_name = f + file_type # move draft file to origin file seafile_api.move_file( self.origin_repo_id, draft_file_path, draft_file_name, self.origin_repo_id, self.origin_file_uuid.parent_path, file_name, replace=1, username=self.username, need_progress=0, synchronous=1 )
def extract_xmind_image(repo_id, path, size=XMIND_IMAGE_SIZE): # get inner path file_name = os.path.basename(path) file_id = seafile_api.get_file_id_by_path(repo_id, path) fileserver_token = seafile_api.get_fileserver_access_token( repo_id, file_id, 'view', '') inner_path = gen_inner_file_get_url(fileserver_token, file_name) # extract xmind image xmind_file = urllib2.urlopen(inner_path) xmind_file_str = StringIO(xmind_file.read()) xmind_zip_file = zipfile.ZipFile(xmind_file_str, 'r') extracted_xmind_image = xmind_zip_file.read('Thumbnails/thumbnail.png') extracted_xmind_image_str = StringIO(extracted_xmind_image) # save origin xmind image to thumbnail folder thumbnail_dir = os.path.join(THUMBNAIL_ROOT, str(size)) if not os.path.exists(thumbnail_dir): os.makedirs(thumbnail_dir) local_xmind_image = os.path.join(thumbnail_dir, file_id) return _create_thumbnail_common(extracted_xmind_image_str, local_xmind_image, size)
def handle_move(self, dest_path): if self.provider.readonly: raise DAVError(HTTP_FORBIDDEN) parts = dest_path.strip("/").split("/", 1) if len(parts) <= 1: raise DAVError(HTTP_BAD_REQUEST) repo_name = parts[0] rel_path = parts[1] dest_dir, dest_file = os.path.split(rel_path) dest_repo = getRepoByName(repo_name, self.username, self.org_id, self.is_guest) if seafile_api.check_permission_by_path(dest_repo.id, self.rel_path, self.username) != "rw": raise DAVError(HTTP_FORBIDDEN) src_dir, src_file = os.path.split(self.rel_path) if not src_file: raise DAVError(HTTP_BAD_REQUEST) if not seafile_api.is_valid_filename(dest_repo.id, dest_file): raise DAVError(HTTP_BAD_REQUEST) # some clients such as GoodReader requires "overwrite" semantics file_id_dest = seafile_api.get_file_id_by_path(dest_repo.id, rel_path) if file_id_dest != None: seafile_api.del_file(dest_repo.id, dest_dir, dest_file, self.username) seafile_api.move_file(self.repo.id, src_dir, src_file, dest_repo.id, dest_dir, dest_file, 1, self.username, NEED_PROGRESS, SYNCHRONOUS) return True
def delete(self, request, org_id, dtable_id): error, _ = _check_org(org_id) if error: return error # resource check dtable = DTables.objects.filter( id=dtable_id, deleted=False, workspace__org_id=org_id).select_related('workspace').first() if not dtable: error_msg = 'table not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) username = request.user.username repo_id = dtable.workspace.repo_id # rename .dtable file new_dtable_name, old_dtable_file_name, new_dtable_file_name = convert_dtable_trash_names( dtable) table_path = normalize_file_path(old_dtable_file_name) table_file_id = seafile_api.get_file_id_by_path(repo_id, table_path) # if has .dtable file, then rename, else skip if table_file_id: seafile_api.rename_file(repo_id, '/', old_dtable_file_name, new_dtable_file_name, username) try: DTables.objects.filter(id=dtable.id).update( deleted=True, delete_time=datetime.utcnow(), name=new_dtable_name) except Exception as e: logger.error('delete dtable: %s error: %s', dtable.id, e) error_msg = 'Internal Server Error.' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return Response({'success': True})
def has_draft_file(repo_id, file_path): has_draft = False file_path = normalize_file_path(file_path) parent_path = os.path.dirname(file_path) filename = os.path.basename(file_path) file_uuid = FileUUIDMap.objects.get_fileuuidmap_by_path(repo_id, parent_path, filename, is_dir=False) from .models import Draft if file_uuid: try: d = Draft.objects.get(origin_file_uuid=file_uuid) file_id = seafile_api.get_file_id_by_path(repo_id, d.draft_file_path) if file_id: has_draft = True except Draft.DoesNotExist: pass return has_draft
def get_group_msgs(groupid, page, username): # Show 15 group messages per page. paginator = Paginator(GroupMessage.objects.filter( group_id=groupid).order_by('-timestamp'), 15) # If page request (9999) is out of range, return None try: group_msgs = paginator.page(page) except (EmptyPage, InvalidPage): return None # Force evaluate queryset to fix some database error for mysql. group_msgs.object_list = list(group_msgs.object_list) attachments = MessageAttachment.objects.filter(group_message__in=group_msgs.object_list) msg_replies = MessageReply.objects.filter(reply_to__in=group_msgs.object_list) reply_to_list = [ r.reply_to_id for r in msg_replies ] for msg in group_msgs.object_list: msg.reply_cnt = reply_to_list.count(msg.id) msg.replies = [] for r in msg_replies: if msg.id == r.reply_to_id: msg.replies.append(r) msg.replies = msg.replies[-3:] for att in attachments: if att.group_message_id != msg.id: continue # Attachment name is file name or directory name. # If is top directory, use repo name instead. path = att.path if path == '/': repo = seafile_api.get_repo(att.repo_id) if not repo: # TODO: what should we do here, tell user the repo # is no longer exists? continue att.name = repo.name else: path = path.rstrip('/') # cut out last '/' if possible att.name = os.path.basename(path) # Load to discuss page if attachment is a image and from recommend. if att.attach_type == 'file' and att.src == 'recommend': att.filetype, att.fileext = get_file_type_and_ext(att.name) if att.filetype == IMAGE: att.obj_id = seafile_api.get_file_id_by_path(att.repo_id, path) if not att.obj_id: att.err = 'File does not exist' else: att.token = seafile_api.get_fileserver_access_token( att.repo_id, att.obj_id, 'view', username) att.img_url = gen_file_get_url(att.token, att.name) msg.attachment = att return group_msgs
def get(self, request, slug): """Get content of a wiki """ path = request.GET.get('p', '/') try: wiki = Wiki.objects.get(slug=slug) except Wiki.DoesNotExist: error_msg = "Wiki not found." return api_error(status.HTTP_404_NOT_FOUND, error_msg) # perm check if not wiki.check_access_wiki(request): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if request.user.username: parent_dir = os.path.dirname(path) permission = check_folder_permission(request, wiki.repo_id, parent_dir) else: permission = 'r' try: repo = seafile_api.get_repo(wiki.repo_id) if not repo: error_msg = "Wiki library not found." return api_error(status.HTTP_404_NOT_FOUND, error_msg) except SearpcError: error_msg = _("Internal Server Error") return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) file_id = None try: file_id = seafile_api.get_file_id_by_path(repo.repo_id, path) except SearpcError as e: logger.error(e) return api_error(HTTP_520_OPERATION_FAILED, "Failed to get file id by path.") if not file_id: return api_error(status.HTTP_404_NOT_FOUND, "File not found") # send stats message send_file_access_msg(request, repo, path, 'api') file_name = os.path.basename(path) token = seafile_api.get_fileserver_access_token( repo.repo_id, file_id, 'download', request.user.username, 'False') if not token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) url = gen_inner_file_get_url(token, file_name) file_response = urllib2.urlopen(url) content = file_response.read() try: dirent = seafile_api.get_dirent_by_path(repo.repo_id, path) if dirent: latest_contributor, last_modified = dirent.modifier, dirent.mtime else: latest_contributor, last_modified = None, 0 except SearpcError as e: logger.error(e) latest_contributor, last_modified = None, 0 return Response({ "content": content, "latest_contributor": email2nickname(latest_contributor), "last_modified": last_modified, "permission": permission, })
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, revert file Permission checking: 1. create: user with 'rw' permission for current parent dir; 2. rename: user with 'rw' permission for current file; 3. move : user with 'rw' permission for current file, 'rw' permission for dst parent dir; 4. copy : user with 'r' permission for current file, 'rw' permission for dst parent dir; 4. revert: user with 'rw' permission for current file's parent dir; """ # argument check path = request.GET.get('p', None) if not path 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', 'revert'): error_msg = "operation can only be 'create', 'rename', 'move', 'copy' or 'revert'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) username = request.user.username parent_dir = os.path.dirname(path) if operation == 'create': # resource check try: parent_dir_id = seafile_api.get_dir_id_by_path( repo_id, parent_dir) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not parent_dir_id: error_msg = 'Folder %s not found.' % parent_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if check_folder_permission(request, repo_id, parent_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # create 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) if operation == 'revert': commit_id = request.data.get('commit_id', None) if not commit_id: error_msg = 'commit_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if seafile_api.get_file_id_by_path(repo_id, path): # file exists in repo if check_folder_permission(request, repo_id, parent_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) is_locked, locked_by_me = check_file_lock( repo_id, path, username) if (is_locked, locked_by_me) == (None, None): error_msg = _("Check file lock error") return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if is_locked and not locked_by_me: error_msg = _("File is locked") return api_error(status.HTTP_403_FORBIDDEN, error_msg) else: # file NOT exists in repo if check_folder_permission(request, repo_id, '/') != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: seafile_api.revert_file(repo_id, commit_id, path, username) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return Response({'success': True})
def 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, _('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 repo = seafile_api.get_repo(wiki.repo_id) return render(request, "wiki/wiki.html", { "wiki": wiki, "repo_name": repo.name if repo else '', "page_name": file_path, "shared_token": fs.token, "shared_type": fs.s_type, "user_can_write": user_can_write, "file_path": file_path, "filename": os.path.splitext(os.path.basename(file_path))[0], "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, file_id, format=None): """ WOPI endpoint for check file info """ token = request.GET.get('access_token', None) request_user, repo_id, file_path = get_file_info_by_token(token) repo = seafile_api.get_repo(repo_id) obj_id = seafile_api.get_file_id_by_path(repo_id, file_path) try: file_size = seafile_api.get_file_size(repo.store_id, repo.version, obj_id) except SearpcError as e: logger.error(e) return HttpResponse(json.dumps({}), status=500, content_type=json_content_type) if file_size == -1: logger.error('File %s not found.') % file_path return HttpResponse(json.dumps({}), status=401, content_type=json_content_type) result = {} # necessary result['BaseFileName'] = os.path.basename(file_path) result['OwnerId'] = seafile_api.get_repo_owner(repo_id) result['Size'] = file_size result['UserId'] = request_user result['Version'] = obj_id # optional result['UserFriendlyName'] = email2nickname(request_user) absolute_uri = request.build_absolute_uri('/') result['PostMessageOrigin'] = urlparse.urljoin(absolute_uri, SITE_ROOT).strip('/') result['HidePrintOption'] = False result['HideSaveOption'] = False result['HideExportOption'] = False result['EnableOwnerTermination'] = True result['SupportsLocks'] = True result['SupportsGetLock'] = True result['SupportsUpdate'] = True filename = os.path.basename(file_path) filetype, fileext = get_file_type_and_ext(filename) is_locked, locked_by_me = check_file_lock(repo_id, file_path, request_user) perm = seafile_api.check_permission_by_path(repo_id, file_path, request_user) if ENABLE_OFFICE_WEB_APP_EDIT and not repo.encrypted and \ perm == 'rw' and ((not is_locked) or (is_locked and locked_by_me)) and \ fileext in OFFICE_WEB_APP_EDIT_FILE_EXTENSION: result['UserCanWrite'] = True return HttpResponse(json.dumps(result), status=200, content_type=json_content_type)
def post(self, request, format=None): """Add a new wiki. """ username = request.user.username org_id = -1 if is_org_context(request): org_id = request.user.org.org_id repo_id = request.POST.get('repo_id', '') if not repo_id: msg = 'Repo id is invalid.' return api_error(status.HTTP_400_BAD_REQUEST, 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) # check perm if not (request.user.permissions.can_publish_repo() and request.user.permissions.can_generate_share_link()): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) is_owner = is_repo_owner(request, repo_id, username) if not is_owner: repo_admin = is_repo_admin(username, repo_id) if not repo_admin: is_group_repo_admin = is_group_repo_staff(request, repo_id, username) if not is_group_repo_admin: error_msg = _('Permission denied.') return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: wiki = Wiki.objects.add(wiki_name=repo.repo_name, username=username, repo_id=repo.repo_id, org_id=org_id, permission='public') except DuplicateWikiNameError: msg = _('%s is taken by others, please try another name.') % repo.repo_name return api_error(status.HTTP_400_BAD_REQUEST, msg) except IntegrityError: msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, msg) # create home page if not exist page_name = "home.md" if not seafile_api.get_file_id_by_path(repo_id, "/" + page_name): try: seafile_api.post_empty_file(repo_id, '/', page_name, username) except SearpcError as e: logger.error(e) msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, msg) fs = FileShare.objects.get_dir_link_by_path(username, repo_id, '/') if not fs: fs = FileShare.objects.create_dir_link(username, repo_id, '/', permission='view_download', org_id=org_id) return Response(wiki.to_dict())
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': # permission check for src parent dir if check_folder_permission(request, src_repo_id, src_parent_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if dirent_type == 'dir' and src_repo_id == dst_repo_id and \ dst_parent_dir.startswith(src_dirent_path + '/'): error_msg = _(u'Can not move directory %(src)s to its subdirectory %(des)s') \ % {'src': escape(src_dirent_path), 'des': escape(dst_parent_dir)} return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if dirent_type == 'file': # check file lock try: is_locked, locked_by_me = check_file_lock( src_repo_id, src_dirent_path, username) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if is_locked and not locked_by_me: error_msg = _("File is locked") return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: res = seafile_api.move_file(src_repo_id, src_parent_dir, src_dirent_name, dst_repo_id, dst_parent_dir, new_dirent_name, replace=False, username=username, need_progress=1) is_dir = True if dirent_type == 'dir' else 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 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): """list all related files of a file. """ # argument check repo_id = request.GET.get('repo_id') if not repo_id: error_msg = 'repo_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_path = request.GET.get('file_path') if not file_path: error_msg = 'file_path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_path = normalize_file_path(file_path) # 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) file_id = seafile_api.get_file_id_by_path(repo_id, file_path) if not file_id: error_msg = 'File %s not found.' % file_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) filename = os.path.basename(file_path) parent_path = os.path.dirname(file_path) uuid = FileUUIDMap.objects.get_or_create_fileuuidmap(repo_id, parent_path, filename, is_dir=False) try: file_uuid_list = RelatedFiles.objects.get_related_files_uuid(uuid) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) related_files = list() for file_uuid in file_uuid_list: if file_uuid.o_uuid == uuid: r_path = posixpath.join(file_uuid.r_uuid.parent_path, file_uuid.r_uuid.filename) r_repo_id = file_uuid.r_uuid.repo_id r_file_id = seafile_api.get_file_id_by_path(r_repo_id, r_path) if not r_file_id: continue related_file = self.get_related_file(r_repo_id, r_path, file_uuid.r_uuid) related_file["related_id"] = file_uuid.pk related_files.append(related_file) else: r_path = posixpath.join(file_uuid.o_uuid.parent_path, file_uuid.o_uuid.filename) r_repo_id = file_uuid.o_uuid.repo_id r_file_id = seafile_api.get_file_id_by_path(r_repo_id, r_path) if not r_file_id: continue related_file = self.get_related_file(r_repo_id, r_path, file_uuid.o_uuid) related_file["related_id"] = file_uuid.pk related_files.append(related_file) return Response({"related_files": related_files}, status=status.HTTP_200_OK)
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) result['download_link'] = gen_dir_zip_download_url(zip_token) return Response(result)
def post(self, request, format=None): """Add a new wiki. """ use_exist_repo = request.POST.get('use_exist_repo', '') if not use_exist_repo: msg = 'Use exist repo is invalid' return api_error(status.HTTP_400_BAD_REQUEST, msg) name = request.POST.get('name', '') if not name: msg = 'Name is invalid' return api_error(status.HTTP_400_BAD_REQUEST, msg) if not is_valid_wiki_name(name): msg = _('Name can only contain letters, numbers, blank, hyphen or underscore.') return api_error(status.HTTP_400_BAD_REQUEST, msg) username = request.user.username org_id = -1 if is_org_context(request): org_id = request.user.org.org_id if use_exist_repo == 'false': try: wiki = Wiki.objects.add(name, username, org_id=org_id) except DuplicateWikiNameError: msg = _('%s is taken by others, please try another name.') % name return api_error(status.HTTP_400_BAD_REQUEST, msg) except IntegrityError: msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, msg) # create home page page_name = "home.md" try: seafile_api.post_empty_file(wiki.repo_id, '/', page_name, request.user.username) except SearpcError as e: logger.error(e) msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, msg) return Response(wiki.to_dict()) if use_exist_repo == 'true': repo_id = request.POST.get('repo_id', '') if not repo_id: msg = 'Repo id is invalid.' return api_error(status.HTTP_400_BAD_REQUEST, msg) repo = seafile_api.get_repo(repo_id) if check_folder_permission(request, repo_id, '/') != 'rw': error_msg = _('Permission denied.') return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: wiki = Wiki.objects.add(wiki_name=repo.repo_name, username=username, repo_id=repo.repo_id, org_id=org_id) except DuplicateWikiNameError: msg = _('%s is taken by others, please try another name.') % repo.repo_name return api_error(status.HTTP_400_BAD_REQUEST, msg) except IntegrityError: msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, msg) # create home page if not exist page_name = "home.md" if not seafile_api.get_file_id_by_path(repo_id, "/" + page_name): try: seafile_api.post_empty_file(repo_id, '/', page_name, username) except SearpcError as e: logger.error(e) msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, msg) return Response(wiki.to_dict())
def get(self, request): """ Get smart link of a file/dir. """ # argument check repo_id = request.GET.get('repo_id', None) if not repo_id or not is_valid_repo_id_format(repo_id): error_msg = 'repo_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) path = request.GET.get('path', None) if not path: error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) is_dir = request.GET.get('is_dir', None) if not is_dir: error_msg = 'is_dir invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) is_dir = is_dir.lower() if is_dir not in ('true', 'false'): error_msg = "is_dir can only be 'true' or 'false'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) is_dir = to_python_boolean(is_dir) if is_dir: if not seafile_api.get_dir_id_by_path(repo_id, normalize_dir_path(path)): error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) else: if not seafile_api.get_file_id_by_path(repo_id, normalize_file_path(path)): error_msg = 'File %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if not check_folder_permission(request, repo_id, '/'): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # make sure path: # 1. starts with '/' # 2. NOT ends with '/' path = normalize_file_path(path) parent_dir = os.path.dirname(path) dirent_name = os.path.basename(path) # get file/dir uuid if repo.is_virtual: repo_id = repo.origin_repo_id path = posixpath.join(repo.origin_path, path.strip('/')) path = normalize_file_path(path) parent_dir = os.path.dirname(path) dirent_name = os.path.basename(path) try: uuid_map = FileUUIDMap.objects.get_or_create_fileuuidmap(repo_id, parent_dir, dirent_name, is_dir) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) dirent_uuid = uuid_map.uuid smart_link = gen_smart_link(dirent_uuid, dirent_name) result = {} result['smart_link'] = smart_link result['smart_link_token'] = dirent_uuid return Response(result)
def put(self, request, pk, format=None): """update review status Close: the user has read permission to the repo Publish: the user has read-write permission to the repo """ st = request.data.get('status', '') if not st: return api_error(status.HTTP_400_BAD_REQUEST, 'Status %s invalid.') try: r = DraftReview.objects.get(pk=pk) except DraftReview.DoesNotExist: return api_error(status.HTTP_404_NOT_FOUND, 'Review %s not found' % pk) uuid = r.origin_file_uuid origin_file_path = posixpath.join(uuid.parent_path, uuid.filename) perm = check_folder_permission(request, r.origin_repo_id, '/') # Close: the user has read permission to the repo if st == 'closed': if perm is None: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) r.status = st r.save() # Publish: the user has read-write permission to the repo if st == 'finished': if perm != PERMISSION_READ_WRITE: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: d = Draft.objects.get(pk=r.draft_id_id) except Draft.DoesNotExist: return api_error(status.HTTP_404_NOT_FOUND, 'Draft %s not found.' % pk) try: d.publish() except (DraftFileConflict, IntegrityError): return api_error(status.HTTP_409_CONFLICT, 'There is a conflict between the draft and the original file') # if it is a new draft # case1. '/path/test(draft).md' ---> '/path/test.md' # case2. '/path/test(dra.md' ---> '/path/test(dra.md' if d.draft_file_path == origin_file_path: new_draft_dir = os.path.dirname(origin_file_path) new_draft_name = os.path.basename(origin_file_path) draft_flag = os.path.splitext(new_draft_name)[0][-7:] # remove `(draft)` from file name if draft_flag == '(draft)': f = os.path.splitext(new_draft_name)[0][:-7] file_type = os.path.splitext(new_draft_name)[-1] new_draft_name = f + file_type if new_draft_dir == '/': origin_file_path = new_draft_dir + new_draft_name else: origin_file_path = new_draft_dir + '/' + new_draft_name r.draft_file_path = origin_file_path # get draft published version file_id = seafile_api.get_file_id_by_path(r.origin_repo_id, origin_file_path) r.publish_file_version = file_id r.status = st r.save() d.delete() reviewers = ReviewReviewer.objects.filter(review_id=r) # send notice to other reviewers if has if reviewers: for i in reviewers: # If it is a reviewer operation, exclude it. if i.reviewer == request.user.username: continue update_review_successful.send(sender=None, from_user=request.user.username, to_user=i.reviewer, review_id=r.id, status=st) # send notice to review owner if request.user.username != r.creator: update_review_successful.send(sender=None, from_user=request.user.username, to_user=r.creator, review_id=r.id, status=st) result = r.to_dict() return Response(result)
def post(self, request): """add a related file for a file """ # argument check o_repo_id = request.data.get('o_repo_id') if not o_repo_id: error_msg = 'o_repo_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) r_repo_id = request.data.get('r_repo_id') if not r_repo_id: error_msg = 'r_repo_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) o_path = request.data.get('o_path') if not o_path: error_msg = 'o_file_path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) o_path = normalize_file_path(o_path) r_path = request.data.get('r_path') if not r_path: error_msg = 'r_file_path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) r_path = normalize_file_path(r_path) if o_repo_id == r_repo_id and o_path == r_path: error_msg = 'Cannot relate itself.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check o_repo = seafile_api.get_repo(o_repo_id) r_repo = seafile_api.get_repo(r_repo_id) if not o_repo: error_msg = 'Library %s not found.' % o_repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) if not r_repo: error_msg = 'Library %s not found.' % r_repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) o_file_id = seafile_api.get_file_id_by_path(o_repo_id, o_path) r_file_id = seafile_api.get_file_id_by_path(r_repo_id, r_path) if not o_file_id: error_msg = 'File %s not found.' % o_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if not r_file_id: error_msg = 'File %s not found.' % r_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) related_file_uuid = RelatedFiles.objects.get_related_file_uuid(o_repo_id, r_repo_id, o_path, r_path) if related_file_uuid: error_msg = 'related file already exist.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # permission check if check_folder_permission(request, o_repo_id, '/') != PERMISSION_READ_WRITE: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: related_file_uuid = RelatedFiles.objects.add_related_file_uuid(o_repo_id, r_repo_id, o_path, r_path) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) related_file = self.get_related_file(r_repo_id, r_path, related_file_uuid.r_uuid) related_file["related_id"] = related_file_uuid.pk return Response({"related_file": related_file}, status.HTTP_201_CREATED)