def download_file(request, repo_id, obj_id): """Download file. Arguments: - `request`: - `repo_id`: - `obj_id`: """ username = request.user.username repo = get_repo(repo_id) if not repo: raise Http404 if repo.encrypted and not seafile_api.is_password_set(repo_id, username): return HttpResponseRedirect(reverse('repo', args=[repo_id])) # If vistor's file shared token in url params matches the token in db, # then we know the vistor is from file shared link. share_token = request.GET.get('t', '') fileshare = FileShare.objects.get( token=share_token) if share_token else None shared_by = None if fileshare: from_shared_link = True shared_by = fileshare.username else: from_shared_link = False if from_shared_link: # check whether owner's traffic over the limit if user_traffic_over_limit(fileshare.username): messages.error( request, _(u'Unable to access file: share link traffic is used up.')) next = request.META.get('HTTP_REFERER', settings.SITE_ROOT) return HttpResponseRedirect(next) # Permission check and generate download link path = request.GET.get('p', '') if check_repo_access_permission(repo_id, request.user) or \ get_file_access_permission(repo_id, path, username) or from_shared_link: # Get a token to access file token = seafserv_rpc.web_get_access_token(repo_id, obj_id, 'download', username) else: messages.error(request, _(u'Unable to download file')) next = request.META.get('HTTP_REFERER', settings.SITE_ROOT) return HttpResponseRedirect(next) # send stats message if from_shared_link: try: file_size = seafile_api.get_file_size(repo.store_id, repo.version, obj_id) send_message( 'seahub.stats', 'file-download\t%s\t%s\t%s\t%s' % (repo.id, shared_by, obj_id, file_size)) except Exception, e: logger.error('Error when sending file-download message: %s' % str(e))
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 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 download_file(request, repo_id, obj_id): """Download file. Arguments: - `request`: - `repo_id`: - `obj_id`: """ username = request.user.username repo = get_repo(repo_id) if not repo: raise Http404 if repo.encrypted and not seafile_api.is_password_set(repo_id, username): return HttpResponseRedirect(reverse("repo", args=[repo_id])) # If vistor's file shared token in url params matches the token in db, # then we know the vistor is from file shared link. share_token = request.GET.get("t", "") fileshare = FileShare.objects.get(token=share_token) if share_token else None shared_by = None if fileshare: from_shared_link = True shared_by = fileshare.username else: from_shared_link = False if from_shared_link: # check whether owner's traffic over the limit if user_traffic_over_limit(fileshare.username): messages.error(request, _(u"Unable to access file: share link traffic is used up.")) next = request.META.get("HTTP_REFERER", settings.SITE_ROOT) return HttpResponseRedirect(next) # Permission check and generate download link path = request.GET.get("p", "") if ( check_repo_access_permission(repo_id, request.user) or get_file_access_permission(repo_id, path, username) or from_shared_link ): # Get a token to access file token = seafserv_rpc.web_get_access_token(repo_id, obj_id, "download", username) else: messages.error(request, _(u"Unable to download file")) next = request.META.get("HTTP_REFERER", settings.SITE_ROOT) return HttpResponseRedirect(next) # send stats message if from_shared_link: try: file_size = seafile_api.get_file_size(repo.store_id, repo.version, obj_id) send_message("seahub.stats", "file-download\t%s\t%s\t%s\t%s" % (repo.id, shared_by, obj_id, file_size)) except Exception, e: logger.error("Error when sending file-download message: %s" % str(e))
def send_draft_publish_msg(draft, username, path): """ send draft publish msg to seafevents """ repo_id = draft.origin_repo_id old_path = draft.draft_file_path msg = '%s\t%s\t%s\t%s\t%s\t%s' % ("publish", "draft", repo_id, username, path, old_path) msg_utf8 = msg.encode('utf-8') try: send_message('seahub.draft', msg_utf8) except Exception as e: logger.error("Error when sending draft publish message: %s" % str(e))
def send_perm_audit_msg(etype, from_user, to, repo_id, path, perm): """Send repo permission audit msg. Arguments: - `request`: - `repo`: - `obj_id`: - `dl_type`: web or api """ msg = 'perm-update\t%s\t%s\t%s\t%s\t%s\t%s' % \ (etype, from_user, to, repo_id, path, perm) msg_utf8 = msg.encode('utf-8') try: send_message('seahub.stats', msg_utf8) except Exception as e: logger.error("Error when sending perm-audit-%s message: %s" % (etype, str(e)))
def send_perm_audit_msg(etype, from_user, to, repo_id, path, perm): """Send repo permission audit msg. Arguments: - `etype`: add/modify/delete-repo-perm - `from_user`: email - `to`: email or group_id or all(public) - `repo_id`: origin repo id - `path`: dir path - `perm`: r or rw """ msg = "perm-update\t%s\t%s\t%s\t%s\t%s\t%s" % (etype, from_user, to, repo_id, path, perm) msg_utf8 = msg.encode("utf-8") try: seaserv.send_message("seahub.stats", msg_utf8) except Exception as e: logger.error("Error when sending perm-audit-%s message: %s" % (etype, str(e)))
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)) send_file_access_msg(request, repo, real_path, 'web') except Exception as e: logger.error('Error when sending dir-download message: %s' % str(e)) return HttpResponseRedirect(gen_file_get_url(token, dirname))
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 send_perm_audit_msg(etype, from_user, to, repo_id, path, perm): """Send repo permission audit msg. Arguments: - `etype`: add/modify/delete-repo-perm - `from_user`: email - `to`: email or group_id or all(public) - `repo_id`: origin repo id - `path`: dir path - `perm`: r or rw """ msg = 'perm-update\t%s\t%s\t%s\t%s\t%s\t%s' % \ (etype, from_user, to, repo_id, path, perm) msg_utf8 = msg.encode('utf-8') try: seaserv.send_message('seahub.stats', msg_utf8) except Exception as e: logger.error("Error when sending perm-audit-%s message: %s" % (etype, str(e)))
def send_file_download_msg(request, repo, path, dl_type): """Send file downlaod msg. Arguments: - `request`: - `repo`: - `obj_id`: - `dl_type`: web or api """ username = request.user.username ip = get_remote_ip(request) user_agent = request.META.get("HTTP_USER_AGENT") msg = "file-download-%s\t%s\t%s\t%s\t%s\t%s\t%s" % (dl_type, username, ip, user_agent, repo.id, repo.name, path) msg_utf8 = msg.encode("utf-8") try: send_message("seahub.stats", msg_utf8) except Exception as e: logger.error("Error when sending file-download-%s message: %s" % (dl_type, str(e)))
def send_file_download_msg(request, repo, path, dl_type): """Send file downlaod msg. Arguments: - `request`: - `repo`: - `obj_id`: - `dl_type`: web or api """ username = request.user.username ip = get_remote_ip(request) user_agent = request.META.get("HTTP_USER_AGENT") msg = 'file-download-%s\t%s\t%s\t%s\t%s\t%s\t%s' % \ (dl_type, username, ip, user_agent, repo.id, repo.name, path) msg_utf8 = msg.encode('utf-8') try: send_message('seahub.stats', msg_utf8) except Exception as e: logger.error("Error when sending file-download-%s message: %s" % (dl_type, str(e)))
def send_review_status_msg(request, review): """ send review status change to seafevents """ status = review.status.lower() if status not in ['open', 'finished', 'closed']: logger.warn('Invalid status in review status msg: %s' % status) return repo_id = review.origin_repo_id op_user = request.user.username review_id = review.id draft_flag = os.path.splitext(os.path.basename( review.draft_file_path))[0][-7:] if draft_flag == '(draft)': old_path = review.draft_file_path if status == 'finished': publish_path = posixpath.join(review.origin_file_uuid.parent_path, review.origin_file_uuid.filename) else: publish_path = None else: old_path = posixpath.join(review.origin_file_uuid.parent_path, review.origin_file_uuid.filename) publish_path = review.draft_file_path if status == 'finished' else None path = publish_path if publish_path else old_path creator = review.creator msg = '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s' % ( status, repo_id, op_user, "review", path, review_id, old_path, creator) msg_utf8 = msg.encode('utf-8') try: send_message('seahub.review', msg_utf8) except Exception as e: logger.error("Error when sending %s message: %s" % (status, str(e)))
def view_shared_file(request, token): """ Preview file via shared link. """ assert token is not None # Checked by URLconf fileshare = FileShare.objects.get_valid_file_link_by_token(token) if fileshare is None: raise Http404 if fileshare.is_encrypted(): if not check_share_link_access(request.user.username, token): d = { 'token': token, 'view_name': 'view_shared_file', } if request.method == 'POST': post_values = request.POST.copy() post_values['enc_password'] = fileshare.password form = SharedLinkPasswordForm(post_values) d['form'] = form if form.is_valid(): # set cache for non-anonymous user if request.user.is_authenticated(): set_share_link_access(request.user.username, token) else: return render_to_response( 'share_access_validation.html', d, context_instance=RequestContext(request)) else: return render_to_response( 'share_access_validation.html', d, context_instance=RequestContext(request)) 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(repo.store_id, repo.version, 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 } exceeds_limit, err_msg = file_size_exceeds_preview_limit( file_size, filetype) if exceeds_limit: ret_dict['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 == SPREADSHEET: handle_spreadsheet(inner_path, obj_id, fileext, ret_dict) elif filetype == OPENDOCUMENT: if file_size == 0: ret_dict['err'] = _(u'Invalid file format.') 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: send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \ (repo.id, shared_by, obj_id, file_size)) except SearpcError, e: logger.error('Error when sending file-view message: %s' % str(e))
def view_file_via_shared_dir(request, token): assert token is not None # Checked by URLconf fileshare = FileShare.objects.get_valid_file_link_by_token(token) if fileshare is None: 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(repo.store_id, repo.version, 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) img_prev = None img_next = None # get file content ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '', 'file_encoding_list': [], 'html_exists': False, 'filetype': filetype} exceeds_limit, err_msg = file_size_exceeds_preview_limit(file_size, filetype) if exceeds_limit: ret_dict['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 == SPREADSHEET: handle_spreadsheet(inner_path, obj_id, fileext, ret_dict) elif filetype == PDF: handle_pdf(inner_path, obj_id, fileext, ret_dict) elif filetype == IMAGE: current_commit = get_commits(repo_id, 0, 1)[0] parent_dir = os.path.dirname(path) dirs = seafile_api.list_dir_by_commit_and_path(current_commit.repo_id, current_commit.id, parent_dir) if not dirs: raise Http404 img_list = [] for dirent in dirs: if not stat.S_ISDIR(dirent.props.mode): fltype, flext = get_file_type_and_ext(dirent.obj_name) if fltype == 'Image': img_list.append(dirent.obj_name) if len(img_list) > 1: img_list.sort(lambda x, y : cmp(x.lower(), y.lower())) cur_img_index = img_list.index(filename) if cur_img_index != 0: img_prev = posixpath.join(parent_dir, img_list[cur_img_index - 1]) if cur_img_index != len(img_list) - 1: img_next = posixpath.join(parent_dir, img_list[cur_img_index + 1]) # send statistic messages if ret_dict['filetype'] != 'Unknown': try: send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \ (repo.id, shared_by, obj_id, file_size)) except SearpcError, e: logger.error('Error when sending file-view message: %s' % str(e))
def view_shared_file(request, token): """ Preview file via shared link. """ assert token is not None # Checked by URLconf fileshare = FileShare.objects.get_valid_file_link_by_token(token) if fileshare is None: raise Http404 if fileshare.is_encrypted(): if not check_share_link_access(request.user.username, token): d = {'token': token, 'view_name': 'view_shared_file', } if request.method == 'POST': post_values = request.POST.copy() post_values['enc_password'] = fileshare.password form = SharedLinkPasswordForm(post_values) d['form'] = form if form.is_valid(): # set cache for non-anonymous user if request.user.is_authenticated(): set_share_link_access(request.user.username, token) else: return render_to_response('share_access_validation.html', d, context_instance=RequestContext(request)) else: return render_to_response('share_access_validation.html', d, context_instance=RequestContext(request)) 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(repo.store_id, repo.version, 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} exceeds_limit, err_msg = file_size_exceeds_preview_limit(file_size, filetype) if exceeds_limit: ret_dict['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 == SPREADSHEET: handle_spreadsheet(inner_path, obj_id, fileext, ret_dict) elif filetype == OPENDOCUMENT: if file_size == 0: ret_dict['err'] = _(u'Invalid file format.') 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: send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \ (repo.id, shared_by, obj_id, file_size)) except SearpcError, e: logger.error('Error when sending file-view message: %s' % str(e))
def get(self, request): """ Return repos user can access. Permission checking: 1. all authenticated user can perform this action. """ filter_by = { 'mine': False, 'shared': False, 'group': False, 'public': False, } request_type_list = request.GET.getlist('type', "") if not request_type_list: # set all to True, no filter applied filter_by = filter_by.fromkeys(filter_by.iterkeys(), True) for request_type in request_type_list: request_type = request_type.strip() filter_by[request_type] = True email = request.user.username # Use dict to reduce memcache fetch cost in large for-loop. contact_email_dict = {} nickname_dict = {} org_id = None if is_org_context(request): org_id = request.user.org.org_id try: starred_repos = UserStarredFiles.objects.get_starred_repos_by_user( email) starred_repo_id_list = [item.repo_id for item in starred_repos] except Exception as e: logger.error(e) starred_repo_id_list = [] repo_info_list = [] if filter_by['mine']: if org_id: owned_repos = seafile_api.get_org_owned_repo_list( org_id, email, ret_corrupted=True) else: owned_repos = seafile_api.get_owned_repo_list( email, ret_corrupted=True) # Reduce memcache fetch ops. modifiers_set = set([x.last_modifier for x in owned_repos]) for e in modifiers_set: if e not in contact_email_dict: contact_email_dict[e] = email2contact_email(e) if e not in nickname_dict: nickname_dict[e] = email2nickname(e) owned_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify)) for r in owned_repos: # do not return virtual repos if r.is_virtual: continue repo_info = { "type": "mine", "repo_id": r.id, "repo_name": r.name, "owner_email": email, "owner_name": email2nickname(email), "owner_contact_email": email2contact_email(email), "last_modified": timestamp_to_isoformat_timestr(r.last_modify), "modifier_email": r.last_modifier, "modifier_name": nickname_dict.get(r.last_modifier, ''), "modifier_contact_email": contact_email_dict.get(r.last_modifier, ''), "size": r.size, "encrypted": r.encrypted, "permission": 'rw', # Always have read-write permission to owned repo "starred": r.repo_id in starred_repo_id_list, "status": normalize_repo_status_code(r.status), } if is_pro_version() and ENABLE_STORAGE_CLASSES: repo_info['storage_name'] = r.storage_name repo_info['storage_id'] = r.storage_id repo_info_list.append(repo_info) if filter_by['shared']: if org_id: shared_repos = seafile_api.get_org_share_in_repo_list( org_id, email, -1, -1) else: shared_repos = seafile_api.get_share_in_repo_list( email, -1, -1) repos_with_admin_share_to = ExtraSharePermission.objects.\ get_repos_with_admin_permission(email) # Reduce memcache fetch ops. owners_set = set([x.user for x in shared_repos]) modifiers_set = set([x.last_modifier for x in shared_repos]) for e in owners_set | modifiers_set: if e not in contact_email_dict: contact_email_dict[e] = email2contact_email(e) if e not in nickname_dict: nickname_dict[e] = email2nickname(e) shared_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify)) for r in shared_repos: owner_email = r.user group_name = '' is_group_owned_repo = False if '@seafile_group' in owner_email: is_group_owned_repo = True group_id = get_group_id_by_repo_owner(owner_email) group_name = group_id_to_name(group_id) owner_name = group_name if is_group_owned_repo else \ nickname_dict.get(owner_email, '') owner_contact_email = '' if is_group_owned_repo else \ contact_email_dict.get(owner_email, '') repo_info = { "type": "shared", "repo_id": r.repo_id, "repo_name": r.repo_name, "last_modified": timestamp_to_isoformat_timestr(r.last_modify), "modifier_email": r.last_modifier, "modifier_name": nickname_dict.get(r.last_modifier, ''), "modifier_contact_email": contact_email_dict.get(r.last_modifier, ''), "owner_email": owner_email, "owner_name": owner_name, "owner_contact_email": owner_contact_email, "size": r.size, "encrypted": r.encrypted, "permission": r.permission, "starred": r.repo_id in starred_repo_id_list, "status": normalize_repo_status_code(r.status), } if r.repo_id in repos_with_admin_share_to: repo_info['is_admin'] = True else: repo_info['is_admin'] = False repo_info_list.append(repo_info) if filter_by['group']: if org_id: group_repos = seafile_api.get_org_group_repos_by_user( email, org_id) else: group_repos = seafile_api.get_group_repos_by_user(email) group_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify)) # Reduce memcache fetch ops. share_from_set = set([x.user for x in group_repos]) modifiers_set = set([x.last_modifier for x in group_repos]) for e in modifiers_set | share_from_set: if e not in contact_email_dict: contact_email_dict[e] = email2contact_email(e) if e not in nickname_dict: nickname_dict[e] = email2nickname(e) for r in group_repos: repo_info = { "type": "group", "group_id": r.group_id, "group_name": r.group_name, "repo_id": r.repo_id, "repo_name": r.repo_name, "last_modified": timestamp_to_isoformat_timestr(r.last_modify), "modifier_email": r.last_modifier, "modifier_name": nickname_dict.get(r.last_modifier, ''), "modifier_contact_email": contact_email_dict.get(r.last_modifier, ''), "size": r.size, "encrypted": r.encrypted, "permission": r.permission, "starred": r.repo_id in starred_repo_id_list, "status": normalize_repo_status_code(r.status), } repo_info_list.append(repo_info) if filter_by['public'] and request.user.permissions.can_view_org(): public_repos = list_inner_pub_repos(request) # get repo id owner dict all_repo_owner = [] repo_id_owner_dict = {} for repo in public_repos: repo_id = repo.repo_id if repo_id not in repo_id_owner_dict: repo_owner = get_repo_owner(request, repo_id) all_repo_owner.append(repo_owner) repo_id_owner_dict[repo_id] = repo_owner # Reduce memcache fetch ops. owner_set = set(all_repo_owner) share_from_set = set([x.user for x in public_repos]) modifiers_set = set([x.last_modifier for x in public_repos]) for e in modifiers_set | share_from_set | owner_set: if e not in contact_email_dict: contact_email_dict[e] = email2contact_email(e) if e not in nickname_dict: nickname_dict[e] = email2nickname(e) for r in public_repos: repo_owner = repo_id_owner_dict[r.repo_id] repo_info = { "type": "public", "repo_id": r.repo_id, "repo_name": r.repo_name, "last_modified": timestamp_to_isoformat_timestr(r.last_modify), "modifier_email": r.last_modifier, "modifier_name": nickname_dict.get(r.last_modifier, ''), "modifier_contact_email": contact_email_dict.get(r.last_modifier, ''), "owner_email": repo_owner, "owner_name": nickname_dict.get(repo_owner, ''), "owner_contact_email": contact_email_dict.get(repo_owner, ''), "size": r.size, "encrypted": r.encrypted, "permission": r.permission, "starred": r.repo_id in starred_repo_id_list, "status": normalize_repo_status_code(r.status), } repo_info_list.append(repo_info) utc_dt = datetime.datetime.utcnow() timestamp = utc_dt.strftime('%Y-%m-%d %H:%M:%S') org_id = request.user.org.org_id if is_org_context(request) else -1 try: send_message('seahub.stats', 'user-login\t%s\t%s\t%s' % (email, timestamp, org_id)) except Exception as e: logger.error('Error when sending user-login message: %s' % str(e)) return Response({'repos': repo_info_list})
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 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', 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', 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', 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') # used for traffic seaserv.send_message( 'seahub.stats', 'dir-download\t%s\t%s\t%s\t%s' % (repo_id, sharelink.username, real_obj_id, dir_size)) except Exception as e: logger.error(e) result['download_link'] = gen_dir_zip_download_url(zip_token) return Response(result)
def view_file_via_shared_dir(request, token): assert token is not None # Checked by URLconf fileshare = FileShare.objects.get_valid_file_link_by_token(token) if fileshare is None: 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(repo.store_id, repo.version, 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) img_prev = None img_next = None # get file content ret_dict = { 'err': '', 'file_content': '', 'encoding': '', 'file_enc': '', 'file_encoding_list': [], 'html_exists': False, 'filetype': filetype } exceeds_limit, err_msg = file_size_exceeds_preview_limit( file_size, filetype) if exceeds_limit: ret_dict['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 == SPREADSHEET: handle_spreadsheet(inner_path, obj_id, fileext, ret_dict) elif filetype == PDF: handle_pdf(inner_path, obj_id, fileext, ret_dict) elif filetype == IMAGE: current_commit = get_commits(repo_id, 0, 1)[0] parent_dir = os.path.dirname(path) dirs = seafile_api.list_dir_by_commit_and_path( current_commit.repo_id, current_commit.id, parent_dir) if not dirs: raise Http404 img_list = [] for dirent in dirs: if not stat.S_ISDIR(dirent.props.mode): fltype, flext = get_file_type_and_ext(dirent.obj_name) if fltype == 'Image': img_list.append(dirent.obj_name) if len(img_list) > 1: img_list.sort(lambda x, y: cmp(x.lower(), y.lower())) cur_img_index = img_list.index(filename) if cur_img_index != 0: img_prev = posixpath.join(parent_dir, img_list[cur_img_index - 1]) if cur_img_index != len(img_list) - 1: img_next = posixpath.join(parent_dir, img_list[cur_img_index + 1]) # send statistic messages if ret_dict['filetype'] != 'Unknown': try: send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \ (repo.id, shared_by, obj_id, file_size)) except SearpcError, e: logger.error('Error when sending file-view message: %s' % str(e))
def get(self, request): """ Return repos user can access. Permission checking: 1. all authenticated user can perform this action. """ filter_by = { 'mine': False, 'shared': False, 'group': False, 'public': False, } request_type_list = request.GET.getlist('type', "") if not request_type_list: # set all to True, no filter applied filter_by = filter_by.fromkeys(filter_by.iterkeys(), True) for request_type in request_type_list: request_type = request_type.strip() filter_by[request_type] = True email = request.user.username # Use dict to reduce memcache fetch cost in large for-loop. contact_email_dict = {} nickname_dict = {} org_id = None if is_org_context(request): org_id = request.user.org.org_id try: starred_repos = UserStarredFiles.objects.get_starred_repos_by_user(email) starred_repo_id_list = [item.repo_id for item in starred_repos] except Exception as e: logger.error(e) starred_repo_id_list = [] repo_info_list = [] if filter_by['mine']: if org_id: owned_repos = seafile_api.get_org_owned_repo_list(org_id, email, ret_corrupted=True) else: owned_repos = seafile_api.get_owned_repo_list(email, ret_corrupted=True) # Reduce memcache fetch ops. modifiers_set = set([x.last_modifier for x in owned_repos]) for e in modifiers_set: if e not in contact_email_dict: contact_email_dict[e] = email2contact_email(e) if e not in nickname_dict: nickname_dict[e] = email2nickname(e) owned_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify)) for r in owned_repos: # do not return virtual repos if r.is_virtual: continue repo_info = { "type": "mine", "repo_id": r.id, "repo_name": r.name, "owner_email": email, "owner_name": email2nickname(email), "owner_contact_email": email2contact_email(email), "last_modified": timestamp_to_isoformat_timestr(r.last_modify), "modifier_email": r.last_modifier, "modifier_name": nickname_dict.get(r.last_modifier, ''), "modifier_contact_email": contact_email_dict.get(r.last_modifier, ''), "size": r.size, "encrypted": r.encrypted, "permission": 'rw', # Always have read-write permission to owned repo "starred": r.repo_id in starred_repo_id_list, } if is_pro_version() and ENABLE_STORAGE_CLASSES: repo_info['storage_name'] = r.storage_name repo_info['storage_id'] = r.storage_id repo_info_list.append(repo_info) if filter_by['shared']: if org_id: shared_repos = seafile_api.get_org_share_in_repo_list(org_id, email, -1, -1) else: shared_repos = seafile_api.get_share_in_repo_list( email, -1, -1) repos_with_admin_share_to = ExtraSharePermission.objects.\ get_repos_with_admin_permission(email) # Reduce memcache fetch ops. owners_set = set([x.user for x in shared_repos]) modifiers_set = set([x.last_modifier for x in shared_repos]) for e in owners_set | modifiers_set: if e not in contact_email_dict: contact_email_dict[e] = email2contact_email(e) if e not in nickname_dict: nickname_dict[e] = email2nickname(e) shared_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify)) for r in shared_repos: owner_email = r.user group_name = '' is_group_owned_repo = False if '@seafile_group' in owner_email: is_group_owned_repo = True group_id = get_group_id_by_repo_owner(owner_email) group_name= group_id_to_name(group_id) owner_name = group_name if is_group_owned_repo else \ nickname_dict.get(owner_email, '') owner_contact_email = '' if is_group_owned_repo else \ contact_email_dict.get(owner_email, '') repo_info = { "type": "shared", "repo_id": r.repo_id, "repo_name": r.repo_name, "last_modified": timestamp_to_isoformat_timestr(r.last_modify), "modifier_email": r.last_modifier, "modifier_name": nickname_dict.get(r.last_modifier, ''), "modifier_contact_email": contact_email_dict.get(r.last_modifier, ''), "owner_email": owner_email, "owner_name": owner_name, "owner_contact_email": owner_contact_email, "size": r.size, "encrypted": r.encrypted, "permission": r.permission, "starred": r.repo_id in starred_repo_id_list, } if r.repo_id in repos_with_admin_share_to: repo_info['is_admin'] = True else: repo_info['is_admin'] = False repo_info_list.append(repo_info) if filter_by['group']: if org_id: group_repos = seafile_api.get_org_group_repos_by_user(email, org_id) else: group_repos = seafile_api.get_group_repos_by_user(email) group_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify)) # Reduce memcache fetch ops. share_from_set = set([x.user for x in group_repos]) modifiers_set = set([x.last_modifier for x in group_repos]) for e in modifiers_set | share_from_set: if e not in contact_email_dict: contact_email_dict[e] = email2contact_email(e) if e not in nickname_dict: nickname_dict[e] = email2nickname(e) for r in group_repos: repo_info = { "type": "group", "group_id": r.group_id, "group_name": r.group_name, "repo_id": r.repo_id, "repo_name": r.repo_name, "last_modified": timestamp_to_isoformat_timestr(r.last_modify), "modifier_email": r.last_modifier, "modifier_name": nickname_dict.get(r.last_modifier, ''), "modifier_contact_email": contact_email_dict.get(r.last_modifier, ''), "size": r.size, "encrypted": r.encrypted, "permission": r.permission, "starred": r.repo_id in starred_repo_id_list, } repo_info_list.append(repo_info) if filter_by['public'] and request.user.permissions.can_view_org(): public_repos = list_inner_pub_repos(request) # get repo id owner dict all_repo_owner = [] repo_id_owner_dict = {} for repo in public_repos: repo_id = repo.repo_id if repo_id not in repo_id_owner_dict: repo_owner = get_repo_owner(request, repo_id) all_repo_owner.append(repo_owner) repo_id_owner_dict[repo_id] = repo_owner # Reduce memcache fetch ops. owner_set = set(all_repo_owner) share_from_set = set([x.user for x in public_repos]) modifiers_set = set([x.last_modifier for x in public_repos]) for e in modifiers_set | share_from_set | owner_set: if e not in contact_email_dict: contact_email_dict[e] = email2contact_email(e) if e not in nickname_dict: nickname_dict[e] = email2nickname(e) for r in public_repos: repo_owner = repo_id_owner_dict[r.repo_id] repo_info = { "type": "public", "repo_id": r.repo_id, "repo_name": r.repo_name, "last_modified": timestamp_to_isoformat_timestr(r.last_modify), "modifier_email": r.last_modifier, "modifier_name": nickname_dict.get(r.last_modifier, ''), "modifier_contact_email": contact_email_dict.get(r.last_modifier, ''), "owner_email": repo_owner, "owner_name": nickname_dict.get(repo_owner, ''), "owner_contact_email": contact_email_dict.get(repo_owner, ''), "size": r.size, "encrypted": r.encrypted, "permission": r.permission, "starred": r.repo_id in starred_repo_id_list, } repo_info_list.append(repo_info) utc_dt = datetime.datetime.utcnow() timestamp = utc_dt.strftime('%Y-%m-%d %H:%M:%S') org_id = request.user.org.org_id if is_org_context(request) else -1 try: send_message('seahub.stats', 'user-login\t%s\t%s\t%s' % (email, timestamp, org_id)) except Exception as e: logger.error('Error when sending user-login message: %s' % str(e)) return Response({'repos': repo_info_list})
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 not seafile_api.check_permission_by_path(repo_id, '/', fileshare.username): 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('/')) dir_size = seafile_api.get_dir_size(repo.store_id, repo.version, dir_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) try: seaserv.send_message( 'seahub.stats', 'dir-download\t%s\t%s\t%s\t%s' % (repo_id, fileshare.username, dir_id, dir_size)) except Exception as e: logger.error(e) 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 } username = request.user.username try: zip_token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), 'download-dir', 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 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) # get file server access token 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, dir_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) try: seaserv.send_message('seahub.stats', 'dir-download\t%s\t%s\t%s\t%s' % (repo_id, fileshare.username, dir_id, dir_size)) except Exception as e: logger.error(e) 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 } username = request.user.username try: zip_token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), 'download-dir', 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 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})