2013-03-28 06:53:53 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
2013-06-16 09:13:18 +00:00
|
|
|
import logging
|
2013-06-18 02:50:15 +00:00
|
|
|
import stat
|
2013-06-16 09:13:18 +00:00
|
|
|
|
2013-03-28 06:53:53 +00:00
|
|
|
from django.core.urlresolvers import reverse
|
2013-03-30 13:08:50 +00:00
|
|
|
from django.contrib.sites.models import RequestSite
|
|
|
|
from django.http import Http404, HttpResponseRedirect
|
2013-06-16 09:13:18 +00:00
|
|
|
from django.shortcuts import render_to_response
|
|
|
|
from django.template import RequestContext
|
2013-03-28 12:22:33 +00:00
|
|
|
from django.template.loader import render_to_string
|
2013-06-16 09:13:18 +00:00
|
|
|
|
|
|
|
import seaserv
|
|
|
|
from seaserv import seafile_api, MAX_UPLOAD_FILE_SIZE
|
|
|
|
|
|
|
|
from seahub.auth.decorators import login_required
|
2013-05-02 11:27:17 +00:00
|
|
|
from seahub.contacts.models import Contact
|
2013-03-28 06:53:53 +00:00
|
|
|
from seahub.forms import RepoPassowrdForm
|
2013-06-16 09:13:18 +00:00
|
|
|
from seahub.share.models import FileShare
|
2013-03-28 06:53:53 +00:00
|
|
|
from seahub.views import gen_path_link, get_user_permission, get_repo_dirents
|
2013-06-16 09:13:18 +00:00
|
|
|
from seahub.utils import get_ccnetapplet_root, is_file_starred, \
|
|
|
|
gen_file_upload_url, get_httpserver_root, gen_shared_link, \
|
|
|
|
EMPTY_SHA1, get_user_repos
|
2013-06-20 02:34:03 +00:00
|
|
|
from seahub.settings import ENABLE_SUB_LIBRARY
|
2013-03-28 06:53:53 +00:00
|
|
|
|
2013-06-16 09:13:18 +00:00
|
|
|
# Get an instance of a logger
|
|
|
|
logger = logging.getLogger(__name__)
|
2013-03-28 06:53:53 +00:00
|
|
|
|
2013-06-16 09:13:18 +00:00
|
|
|
def get_repo(repo_id):
|
|
|
|
return seafile_api.get_repo(repo_id)
|
2013-03-28 06:53:53 +00:00
|
|
|
|
2013-06-16 09:13:18 +00:00
|
|
|
def get_commit(commit_id):
|
|
|
|
return seaserv.get_commit(commit_id)
|
2013-03-28 06:53:53 +00:00
|
|
|
|
2013-06-16 09:13:18 +00:00
|
|
|
def get_repo_size(repo_id):
|
|
|
|
return seafile_api.get_repo_size(repo_id)
|
2013-03-28 06:53:53 +00:00
|
|
|
|
2013-06-16 09:13:18 +00:00
|
|
|
def list_dir_by_commit_and_path(commit, path):
|
|
|
|
return seafile_api.list_dir_by_commit_and_path(commit.id, path)
|
2013-03-28 06:53:53 +00:00
|
|
|
|
2013-06-16 09:13:18 +00:00
|
|
|
def is_password_set(repo_id, username):
|
|
|
|
return seafile_api.is_password_set(repo_id, username)
|
2013-03-28 06:53:53 +00:00
|
|
|
|
2013-06-16 09:13:18 +00:00
|
|
|
def check_repo_access_permission(repo_id, username):
|
|
|
|
return seafile_api.check_repo_access_permission(repo_id, username)
|
2013-03-28 06:53:53 +00:00
|
|
|
|
2013-06-16 09:13:18 +00:00
|
|
|
def get_path_from_request(request):
|
|
|
|
path = request.GET.get('p', '/')
|
|
|
|
if path[-1] != '/':
|
|
|
|
path = path + '/'
|
|
|
|
return path
|
|
|
|
|
|
|
|
def get_next_url_from_request(request):
|
|
|
|
return request.GET.get('next', None)
|
|
|
|
|
|
|
|
def get_nav_path(path, repo_name):
|
|
|
|
return gen_path_link(path, repo_name)
|
|
|
|
|
|
|
|
def get_unencry_rw_repos_by_user(username):
|
|
|
|
"""Get all unencrypted repos the user can read and write.
|
2013-03-28 06:53:53 +00:00
|
|
|
"""
|
2013-06-16 09:13:18 +00:00
|
|
|
def check_has_subdir(repo):
|
|
|
|
latest_commit = seaserv.get_commits(repo.id, 0, 1)[0]
|
|
|
|
if not latest_commit:
|
|
|
|
return False
|
|
|
|
if latest_commit.root_id == EMPTY_SHA1:
|
|
|
|
return False
|
2013-03-28 06:53:53 +00:00
|
|
|
|
2013-06-16 09:13:18 +00:00
|
|
|
try:
|
|
|
|
dirs = seafile_api.list_dir_by_commit_and_path(latest_commit.id, '/')
|
|
|
|
except Exception, e:
|
|
|
|
logger.error(e)
|
|
|
|
return False
|
2013-03-28 06:53:53 +00:00
|
|
|
else:
|
2013-06-16 09:13:18 +00:00
|
|
|
for dirent in dirs:
|
|
|
|
if stat.S_ISDIR(dirent.props.mode):
|
|
|
|
return True
|
|
|
|
return False
|
2013-03-28 06:53:53 +00:00
|
|
|
|
2013-06-16 09:13:18 +00:00
|
|
|
def has_repo(repos, repo):
|
|
|
|
for r in repos:
|
|
|
|
if repo.id == r.id:
|
|
|
|
return True
|
|
|
|
return False
|
2013-03-28 06:53:53 +00:00
|
|
|
|
2013-06-16 09:13:18 +00:00
|
|
|
owned_repos, shared_repos, groups_repos, public_repos = get_user_repos(username)
|
2013-03-28 06:53:53 +00:00
|
|
|
|
2013-06-16 09:13:18 +00:00
|
|
|
accessible_repos = []
|
2013-06-20 02:34:03 +00:00
|
|
|
|
2013-06-16 09:13:18 +00:00
|
|
|
for r in owned_repos:
|
|
|
|
if not has_repo(accessible_repos, r) and not r.encrypted:
|
|
|
|
r.has_subdir = check_has_subdir(r)
|
|
|
|
accessible_repos.append(r)
|
2013-03-28 06:53:53 +00:00
|
|
|
|
2013-06-16 09:13:18 +00:00
|
|
|
for r in shared_repos + public_repos:
|
|
|
|
# For compatibility with diffrent fields names in Repo and
|
|
|
|
# SharedRepo objects.
|
|
|
|
r.id = r.repo_id
|
|
|
|
r.name = r.repo_name
|
|
|
|
r.desc = r.repo_desc
|
2013-03-28 06:53:53 +00:00
|
|
|
|
2013-06-16 09:13:18 +00:00
|
|
|
if not has_repo(accessible_repos, r) and not r.encrypted:
|
|
|
|
if seafile_api.check_repo_access_permission(r.id, username) == 'rw':
|
|
|
|
r.has_subdir = check_has_subdir(r)
|
|
|
|
accessible_repos.append(r)
|
2013-03-28 06:53:53 +00:00
|
|
|
|
2013-06-16 09:13:18 +00:00
|
|
|
for r in groups_repos:
|
|
|
|
if not has_repo(accessible_repos, r) and not r.encrypted :
|
|
|
|
if seafile_api.check_repo_access_permission(r.id, username) == 'rw':
|
|
|
|
r.has_subdir = check_has_subdir(r)
|
|
|
|
accessible_repos.append(r)
|
|
|
|
|
|
|
|
return accessible_repos
|
|
|
|
|
|
|
|
def get_shared_groups_by_repo_and_user(repo_id, username):
|
|
|
|
"""Get all groups which this repo is shared.
|
|
|
|
"""
|
|
|
|
repo_shared_groups = seaserv.get_shared_groups_by_repo(repo_id)
|
|
|
|
|
|
|
|
# Filter out groups that user is joined.
|
|
|
|
groups = [ x for x in repo_shared_groups if \
|
|
|
|
seaserv.is_group_user(x.id, username)]
|
|
|
|
return groups
|
|
|
|
|
|
|
|
def is_no_quota(repo_id):
|
|
|
|
return True if seaserv.check_quota(repo_id) < 0 else False
|
|
|
|
|
|
|
|
def get_upload_url(request, repo_id):
|
|
|
|
username = request.user.username
|
|
|
|
if get_user_permission(request, repo_id) == 'rw':
|
|
|
|
token = seafile_api.get_httpserver_access_token(repo_id, 'dummy',
|
|
|
|
'upload', username)
|
|
|
|
return gen_file_upload_url(token, 'upload')
|
|
|
|
else:
|
|
|
|
return ''
|
|
|
|
|
|
|
|
def get_update_url(request, repo_id):
|
|
|
|
username = request.user.username
|
|
|
|
if get_user_permission(request, repo_id) == 'rw':
|
|
|
|
token = seafile_api.get_httpserver_access_token(repo_id, 'dummy',
|
|
|
|
'update', username)
|
|
|
|
return gen_file_upload_url(token, 'update')
|
|
|
|
else:
|
|
|
|
return ''
|
2013-03-28 06:53:53 +00:00
|
|
|
|
2013-06-16 09:13:18 +00:00
|
|
|
def get_fileshare(repo_id, username, path):
|
|
|
|
if path == '/': # no shared link for root dir
|
|
|
|
return None
|
|
|
|
|
|
|
|
l = FileShare.objects.filter(repo_id=repo_id).filter(
|
|
|
|
username=username).filter(path=path)
|
|
|
|
return l[0] if len(l) > 0 else None
|
|
|
|
|
|
|
|
def get_shared_link(request, fileshare):
|
|
|
|
# dir shared link
|
|
|
|
if fileshare:
|
|
|
|
dir_shared_link = gen_shared_link(request, fileshare.token, 'd')
|
|
|
|
else:
|
|
|
|
dir_shared_link = ''
|
|
|
|
return dir_shared_link
|
|
|
|
|
|
|
|
def render_repo(request, repo):
|
|
|
|
"""Steps to show repo page:
|
|
|
|
If user has permission to view repo
|
|
|
|
If repo is encrypt and password is not set on server
|
|
|
|
return decrypt repo page
|
|
|
|
If repo is not encrypt or password is set on server
|
|
|
|
Show repo direntries based on requested path
|
|
|
|
If user does not have permission to view repo
|
|
|
|
return permission deny page
|
2013-03-28 06:53:53 +00:00
|
|
|
"""
|
2013-06-16 09:13:18 +00:00
|
|
|
username = request.user.username
|
|
|
|
user_perm = check_repo_access_permission(repo.id, username)
|
|
|
|
if user_perm is None:
|
|
|
|
return render_to_response('repo_access_deny.html', {
|
|
|
|
'repo': repo,
|
|
|
|
}, context_instance=RequestContext(request))
|
|
|
|
|
|
|
|
if repo.encrypted and not is_password_set(repo.id, username):
|
|
|
|
return render_to_response('decrypt_repo_form.html', {
|
|
|
|
'repo': repo,
|
|
|
|
'next': get_next_url_from_request(request) or \
|
|
|
|
reverse('repo', args=[repo.id])
|
|
|
|
}, context_instance=RequestContext(request))
|
|
|
|
|
|
|
|
# query context args
|
|
|
|
applet_root = get_ccnetapplet_root()
|
|
|
|
httpserver_root = get_httpserver_root()
|
|
|
|
max_upload_file_size = MAX_UPLOAD_FILE_SIZE
|
|
|
|
|
|
|
|
protocol = request.is_secure() and 'https' or 'http'
|
|
|
|
domain = RequestSite(request).domain
|
|
|
|
path = get_path_from_request(request)
|
|
|
|
|
|
|
|
contacts = Contact.objects.get_contacts_by_user(username)
|
|
|
|
accessible_repos = [repo] if repo.encrypted else get_unencry_rw_repos_by_user(username)
|
|
|
|
|
|
|
|
head_commit = get_commit(repo.head_cmmt_id)
|
|
|
|
if not head_commit:
|
|
|
|
raise Http404
|
|
|
|
repo_size = get_repo_size(repo.id)
|
|
|
|
no_quota = is_no_quota(repo.id)
|
|
|
|
history_limit = seaserv.get_repo_history_limit(repo.id)
|
|
|
|
search_repo_id = None if repo.encrypted else repo.id
|
|
|
|
|
|
|
|
is_repo_owner = seafile_api.is_repo_owner(username, repo.id)
|
|
|
|
file_list, dir_list = get_repo_dirents(request, repo.id, head_commit, path)
|
|
|
|
zipped = get_nav_path(path, repo.name)
|
|
|
|
repo_groups = get_shared_groups_by_repo_and_user(repo.id, username)
|
|
|
|
if len(repo_groups) > 1:
|
|
|
|
repo_group_str = render_to_string("snippets/repo_group_list.html",
|
|
|
|
{'groups': repo_groups})
|
|
|
|
else:
|
|
|
|
repo_group_str = ''
|
|
|
|
upload_url = get_upload_url(request, repo.id)
|
|
|
|
update_url = get_update_url(request, repo.id)
|
|
|
|
fileshare = get_fileshare(repo.id, username, path)
|
|
|
|
dir_shared_link = get_shared_link(request, fileshare)
|
|
|
|
|
|
|
|
return render_to_response('repo.html', {
|
|
|
|
'repo': repo,
|
|
|
|
'user_perm': user_perm,
|
|
|
|
'is_repo_owner': is_repo_owner,
|
|
|
|
'current_commit': head_commit,
|
|
|
|
'password_set': True,
|
|
|
|
'repo_size': repo_size,
|
|
|
|
'dir_list': dir_list,
|
|
|
|
'file_list': file_list,
|
|
|
|
'path': path,
|
|
|
|
'zipped': zipped,
|
|
|
|
'accessible_repos': accessible_repos,
|
|
|
|
'applet_root': applet_root,
|
|
|
|
'groups': repo_groups,
|
|
|
|
'repo_group_str': repo_group_str,
|
|
|
|
'no_quota': no_quota,
|
|
|
|
'max_upload_file_size': max_upload_file_size,
|
|
|
|
'upload_url': upload_url,
|
|
|
|
'update_url': update_url,
|
|
|
|
'httpserver_root': httpserver_root,
|
|
|
|
'protocol': protocol,
|
|
|
|
'domain': domain,
|
|
|
|
'contacts': contacts,
|
|
|
|
'fileshare': fileshare,
|
|
|
|
'dir_shared_link': dir_shared_link,
|
|
|
|
'history_limit': history_limit,
|
|
|
|
'search_repo_id': search_repo_id,
|
2013-06-20 02:34:03 +00:00
|
|
|
'ENABLE_SUB_LIBRARY': ENABLE_SUB_LIBRARY,
|
2013-06-16 09:13:18 +00:00
|
|
|
}, context_instance=RequestContext(request))
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
def repo(request, repo_id):
|
|
|
|
"""Show repo page and handle POST request to decrypt repo.
|
2013-03-28 06:53:53 +00:00
|
|
|
"""
|
2013-06-16 09:13:18 +00:00
|
|
|
repo = get_repo(repo_id)
|
|
|
|
if not repo:
|
|
|
|
raise Http404
|
|
|
|
|
|
|
|
if request.method == 'GET':
|
|
|
|
return render_repo(request, repo)
|
|
|
|
elif request.method == 'POST':
|
|
|
|
form = RepoPassowrdForm(request.POST)
|
|
|
|
next = get_next_url_from_request(request) or reverse('repo',
|
|
|
|
args=[repo_id])
|
|
|
|
if form.is_valid():
|
|
|
|
return HttpResponseRedirect(next)
|
2013-03-28 06:53:53 +00:00
|
|
|
else:
|
2013-06-16 09:13:18 +00:00
|
|
|
return render_to_response('decrypt_repo_form.html', {
|
|
|
|
'repo': repo,
|
|
|
|
'form': form,
|
|
|
|
'next': next,
|
|
|
|
}, context_instance=RequestContext(request))
|
2013-03-28 06:53:53 +00:00
|
|
|
|
2013-06-16 09:13:18 +00:00
|
|
|
@login_required
|
|
|
|
def repo_history_view(request, repo_id):
|
|
|
|
"""View repo in history.
|
|
|
|
"""
|
|
|
|
repo = get_repo(repo_id)
|
|
|
|
if not repo:
|
|
|
|
raise Http404
|
|
|
|
|
|
|
|
username = request.user.username
|
|
|
|
user_perm = check_repo_access_permission(repo.id, username)
|
|
|
|
if user_perm is None:
|
|
|
|
return render_to_response('repo_access_deny.html', {
|
|
|
|
'repo': repo,
|
|
|
|
}, context_instance=RequestContext(request))
|
|
|
|
|
|
|
|
if repo.encrypted and not is_password_set(repo.id, username):
|
|
|
|
return render_to_response('decrypt_repo_form.html', {
|
|
|
|
'repo': repo,
|
|
|
|
'next': get_next_url_from_request(request) or \
|
|
|
|
reverse('repo', args=[repo.id])
|
|
|
|
}, context_instance=RequestContext(request))
|
|
|
|
|
|
|
|
commit_id = request.GET.get('commit_id', None)
|
|
|
|
if commit_id is None:
|
|
|
|
return HttpResponseRedirect(reverse('repo', args=[repo.id]))
|
|
|
|
current_commit = get_commit(commit_id)
|
|
|
|
if not current_commit:
|
|
|
|
current_commit = get_commit(repo.head_cmmt_id)
|
|
|
|
|
|
|
|
path = get_path_from_request(request)
|
|
|
|
file_list, dir_list = get_repo_dirents(request, repo.id, current_commit, path)
|
|
|
|
zipped = get_nav_path(path, repo.name)
|
|
|
|
search_repo_id = None if repo.encrypted else repo.id
|
|
|
|
|
|
|
|
return render_to_response('repo_history_view.html', {
|
|
|
|
'repo': repo,
|
|
|
|
'user_perm': user_perm,
|
|
|
|
'current_commit': current_commit,
|
|
|
|
'dir_list': dir_list,
|
|
|
|
'file_list': file_list,
|
|
|
|
'path': path,
|
|
|
|
'zipped': zipped,
|
|
|
|
'search_repo_id': search_repo_id,
|
|
|
|
}, context_instance=RequestContext(request))
|
|
|
|
|