mirror of
https://github.com/haiwen/seahub.git
synced 2025-04-28 03:10:45 +00:00
Add anonymous share feature
This commit is contained in:
parent
82263b6787
commit
705f86e68d
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
*.pyc
|
||||
*~
|
||||
*#
|
||||
seahub.db*
|
||||
local_settings.py
|
||||
startserver.sh
|
||||
|
@ -62,3 +62,14 @@ def translate_commit_time(value):
|
||||
return u'%d 分钟前' % (seconds/60)
|
||||
else:
|
||||
return u'%d 秒前' % (seconds)
|
||||
|
||||
@register.filter(name='translate_remain_time')
|
||||
def translate_remain_time(value):
|
||||
if value > 24 * 60 * 60:
|
||||
return u'%d 天' % (value/24/3600)
|
||||
elif value > 60 * 60:
|
||||
return u'%d 小时' % (value/3600)
|
||||
elif value > 60:
|
||||
return u'%d 分钟' % (value/60)
|
||||
else:
|
||||
return u'%d 秒' % (value)
|
||||
|
@ -32,7 +32,7 @@ def contact_add(request):
|
||||
emailuser = ccnet_rpc.get_emailuser(contact_email)
|
||||
if not emailuser:
|
||||
error_msg = u"用户不存在"
|
||||
elif cmp(contact_email, request.user.username) == 0:
|
||||
elif contact_email == request.user.username:
|
||||
error_msg = u"不能添加自己为联系人"
|
||||
elif Contact.objects.filter(user_email=request.user.username,
|
||||
contact_email=contact_email).count() > 0:
|
||||
|
@ -324,7 +324,8 @@ h2.repo-history {
|
||||
padding:0 0 6px 0;
|
||||
}
|
||||
/*repo-share-form*/
|
||||
#to_email,
|
||||
#email_or_group,
|
||||
#share-link,
|
||||
#added-member-name {
|
||||
width:260px;
|
||||
height:80px;
|
||||
|
@ -65,6 +65,7 @@ MIDDLEWARE_CLASSES = (
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.middleware.csrf.CsrfResponseMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'auth.middleware.AuthenticationMiddleware',
|
||||
'seahub.base.middleware.InfobarMiddleware',
|
||||
# 'seahub.base.middleware.UseridMiddleware',
|
||||
@ -89,6 +90,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
|
||||
'django.core.context_processors.media',
|
||||
'djblets.util.context_processors.siteRoot',
|
||||
'django.core.context_processors.request',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
'seahub.base.context_processors.base',
|
||||
)
|
||||
|
||||
@ -99,6 +101,7 @@ INSTALLED_APPS = (
|
||||
'django.contrib.sessions',
|
||||
# 'django.contrib.sites',
|
||||
# 'django.contrib.admin',
|
||||
'django.contrib.messages',
|
||||
'registration',
|
||||
'avatar',
|
||||
'seahub.notifications',
|
||||
@ -106,7 +109,7 @@ INSTALLED_APPS = (
|
||||
'seahub.profile',
|
||||
'seahub.contacts',
|
||||
'seahub.group',
|
||||
# 'seahub.share',
|
||||
'seahub.share',
|
||||
)
|
||||
|
||||
AUTHENTICATION_BACKENDS = (
|
||||
|
@ -1,43 +1,9 @@
|
||||
from django import forms
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
|
||||
class GroupAddRepoForm(forms.Form):
|
||||
class RepoShareForm(forms.Form):
|
||||
"""
|
||||
Form for adding repo to a group.
|
||||
|
||||
Form for sharing repo to user or group.
|
||||
"""
|
||||
|
||||
email_or_group = forms.CharField(max_length=512)
|
||||
repo_id = forms.CharField(max_length=36)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(GroupAddRepoForm, self).__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class UserShareForm(forms.Form):
|
||||
"""
|
||||
Form for sharing repo to a user.
|
||||
"""
|
||||
|
||||
user_email = forms.EmailField()
|
||||
repo_id = forms.CharField(max_length=36)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(UserShareForm, self).__init__(*args, **kwargs)
|
||||
|
||||
def clean_user_email(self):
|
||||
data = self.cleaned_data['user_email']
|
||||
try:
|
||||
# put the user in form.to_user for further use
|
||||
self.to_user = User.objects.get(email=data)
|
||||
except User.DoesNotExist:
|
||||
raise forms.ValidationError("No user with such email")
|
||||
|
||||
return data
|
||||
|
||||
def clean_repo_id(self):
|
||||
data = self.cleaned_data['repo_id']
|
||||
if len(data) != 36:
|
||||
raise forms.ValidationError("Invalid repo id")
|
||||
|
||||
return data
|
||||
|
@ -1,19 +1,8 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
class UserShare(models.Model):
|
||||
"""Record a repo shared to a user."""
|
||||
|
||||
from_user = models.ForeignKey(User, related_name="myshare_items")
|
||||
to_user = models.ForeignKey(User, related_name="share2me_items")
|
||||
class AnonymousShare(models.Model):
|
||||
repo_owner = models.EmailField(max_length=255)
|
||||
repo_id = models.CharField(max_length=36)
|
||||
|
||||
|
||||
class GroupShare(models.Model):
|
||||
"""A repo shared to a group."""
|
||||
|
||||
group_id = models.CharField(max_length=36)
|
||||
repo_id = models.CharField(max_length=36)
|
||||
|
||||
class Meta:
|
||||
unique_together = ("group_id", "repo_id")
|
||||
anonymous_email = models.EmailField(max_length=255)
|
||||
token = models.CharField(max_length=25, unique=True)
|
||||
|
||||
|
4
share/settings.py
Normal file
4
share/settings.py
Normal file
@ -0,0 +1,4 @@
|
||||
from django.conf import settings
|
||||
|
||||
ANONYMOUS_SHARE_COOKIE_TIMEOUT = getattr(settings, 'ANONYMOUS_SHARE_COOKIE_TIMEOUT', 24*60*60)
|
||||
ANONYMOUS_SHARE_LINK_TIMEOUT = getattr(settings, 'ANONYMOUS_SHARE_LINK_TIMEOUT', 2)
|
9
share/templates/repo/anonymous_share_confirm.html
Normal file
9
share/templates/repo/anonymous_share_confirm.html
Normal file
@ -0,0 +1,9 @@
|
||||
{% extends "myhome_base.html" %}
|
||||
|
||||
{% block title %}{% endblock %}
|
||||
|
||||
{% block main_panel %}
|
||||
<div class="text-panel">
|
||||
<p>该访问链接已失效,如有需要,请联系目录拥有者 {{ repo_owner }}!</p>
|
||||
</div>
|
||||
{% endblock %}
|
12
share/templates/repo/anonymous_share_email.html
Normal file
12
share/templates/repo/anonymous_share_email.html
Normal file
@ -0,0 +1,12 @@
|
||||
{% autoescape off %}
|
||||
亲爱的:{{ anon_email }} 您好!
|
||||
|
||||
{{ email }} 在SeaCloud上共享了一个同步目录给你,请点击以下链接查看:
|
||||
|
||||
{{ protocol }}://{{ domain }}{% url share.views.anonymous_share_confirm token=token %}
|
||||
|
||||
感谢使用我们的网站!
|
||||
|
||||
Seafile团队
|
||||
|
||||
{% endautoescape %}
|
@ -1,4 +1,5 @@
|
||||
{% extends "myhome_base.html" %}
|
||||
{% load seahub_tags %}
|
||||
|
||||
{% block nav_shareadmin_class %}class="cur"{% endblock %}
|
||||
|
||||
@ -30,6 +31,37 @@
|
||||
{% else %}
|
||||
<p>暂无</p>
|
||||
{% endif %}
|
||||
|
||||
<h3>我管理的共享链接</h3>
|
||||
{% if out_links %}
|
||||
<table class="link-list">
|
||||
<tr>
|
||||
<th width="20%">名字</th>
|
||||
<th width="30%">共享给</th>
|
||||
<th width="30%">有效期</th>
|
||||
<th width="20%">操作</th>
|
||||
</tr>
|
||||
{% for link in out_links %}
|
||||
<tr>
|
||||
<td><a href="{{ SITE_ROOT }}repo/{{ repo.id }}">{{ link.repo_name }}</a></td>
|
||||
<td>{{ link.anonymous_email }}</td>
|
||||
{% if link.remain_time %}
|
||||
<td>{{ link.remain_time|translate_remain_time }}</td>
|
||||
{% else %}
|
||||
<td>已过期</td>
|
||||
{% endif %}
|
||||
<td><a class="op" href="#" class="view-link" data="{{ link.token }}">查看链接</a>
|
||||
<a class="op" href="{{ SITE_ROOT }}share/remove/{{ link.token }}/">删除</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
<form id="view-link-form" name="view-link-form" class="hide">
|
||||
<textarea id="share-link" name="share-link"></textarea>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_script %}
|
||||
@ -46,5 +78,14 @@ $("table tr:gt(0)").hover(
|
||||
$(this).find('img').addClass('vh');
|
||||
}
|
||||
);
|
||||
|
||||
$(".view-link").click(function() {
|
||||
var t = $(this).attr('data');
|
||||
var l = '{{ protocol }}://' + '{{ domain }}{{ SITE_ROOT }}share/' + t + '/';
|
||||
$('textarea[name="share-link"]').val(l);
|
||||
$("#view-link-form").modal({appendTo: "#main", containerCss:{padding:18}});
|
||||
return false;
|
||||
});
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
@ -1,25 +0,0 @@
|
||||
{% extends "myhome_base.html" %}
|
||||
|
||||
{% block left_panel %}
|
||||
<ul>
|
||||
<li><a href="{{ SITE_ROOT }}share/list/">共享列表</a></li>
|
||||
<li>共享同步目录</li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
{% block right_panel %}
|
||||
|
||||
<h2>共享同步目录</h2>
|
||||
|
||||
<form action="" method="post">
|
||||
{{ form.non_field_errors }}
|
||||
{{ form.user_email.errors }}
|
||||
<label>联系人 Email:</label><br/>
|
||||
{{ form.user_email }}<br />
|
||||
{{ form.repo_id.errors }}
|
||||
<label>同步目录 ID:</label><br/>
|
||||
{{ form.repo_id }}<br />
|
||||
<input type="submit" value="Submit" />
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
@ -1,46 +0,0 @@
|
||||
{% extends "myhome_base.html" %}
|
||||
|
||||
{% block left_panel %}
|
||||
<ul>
|
||||
<li>共享列表</li>
|
||||
<li><a href="{{ SITE_ROOT }}share/add/">共享同步目录</a></li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
{% block right_panel %}
|
||||
|
||||
<h2>共享给我的同步目录</h2>
|
||||
<table class="repo-list default">
|
||||
<tr>
|
||||
<th>共享人</th>
|
||||
<th>ID</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
{% for item in share2me_items %}
|
||||
<tr>
|
||||
<td>{{ item.from_user.email }}</td>
|
||||
<td><a href="{{ SITE_ROOT }}repo/{{ item.repo_id }}/">{{ item.repo_id }}</a></td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
<h2>所有共享的同步目录</h2>
|
||||
<table class="repo-list default">
|
||||
<tr>
|
||||
<th>共享给</th>
|
||||
<th>ID</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
{% for item in share_items %}
|
||||
<tr>
|
||||
<td>{{ item.to_user.email }}</td>
|
||||
<td><a href="{{ SITE_ROOT }}repo/{{ item.repo_id }}/">{{ item.repo_id }}</a></td>
|
||||
<td><a href="{{ SITE_ROOT }}share/delete/{{ item.id }}/">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
87
share/tokens.py
Normal file
87
share/tokens.py
Normal file
@ -0,0 +1,87 @@
|
||||
import random
|
||||
from datetime import date
|
||||
from datetime import datetime as dt
|
||||
from django.conf import settings
|
||||
from django.utils.http import int_to_base36, base36_to_int
|
||||
|
||||
from settings import ANONYMOUS_SHARE_LINK_TIMEOUT
|
||||
|
||||
class AnonymousShareTokenGenerator(object):
|
||||
"""
|
||||
Strategy object used to generate and check tokens for the repo anonymous
|
||||
share mechanism.
|
||||
"""
|
||||
def make_token(self):
|
||||
"""
|
||||
Returns a token that can be used once to do a anonymous share for repo.
|
||||
"""
|
||||
return self._make_token_with_timestamp(self._num_days(self._today()))
|
||||
|
||||
def check_token(self, token):
|
||||
"""
|
||||
Check that a anonymous share token is valid.
|
||||
"""
|
||||
# Parse the token
|
||||
try:
|
||||
ts_b36, hash = token.split("-")
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
try:
|
||||
ts = base36_to_int(ts_b36)
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
# Check the timestamp is within limit
|
||||
if (self._num_days(self._today()) - ts) > ANONYMOUS_SHARE_LINK_TIMEOUT:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def get_remain_time(self, token):
|
||||
"""
|
||||
Get token remain time.
|
||||
"""
|
||||
try:
|
||||
ts_b36, hash = token.split("-")
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
try:
|
||||
ts = base36_to_int(ts_b36)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
days = ANONYMOUS_SHARE_LINK_TIMEOUT - (self._num_days(self._today()) - ts)
|
||||
if days < 0:
|
||||
return None
|
||||
|
||||
now = dt.now()
|
||||
tomorrow = dt(now.year, now.month, now.day+1)
|
||||
|
||||
return (tomorrow - now).seconds + days * 24 * 60 * 60
|
||||
|
||||
def _make_token_with_timestamp(self, timestamp):
|
||||
# timestamp is number of days since 2001-1-1. Converted to
|
||||
# base 36, this gives us a 3 digit string until about 2121
|
||||
ts_b36 = int_to_base36(timestamp)
|
||||
|
||||
# We limit the hash to 20 chars to keep URL short
|
||||
from django.utils.hashcompat import sha_constructor
|
||||
import datetime
|
||||
now = datetime.datetime.now()
|
||||
hash = sha_constructor(settings.SECRET_KEY +
|
||||
unicode(random.randint(0, 999999)) +
|
||||
now.strftime('%Y-%m-%d %H:%M:%S') +
|
||||
unicode(timestamp)).hexdigest()[::2]
|
||||
|
||||
return "%s-%s" % (ts_b36, hash)
|
||||
|
||||
def _num_days(self, dt):
|
||||
return (dt - date(2001,1,1)).days
|
||||
|
||||
def _today(self):
|
||||
# Used for mocking in tests
|
||||
return date.today()
|
||||
|
||||
anon_share_token_generator = AnonymousShareTokenGenerator()
|
@ -2,10 +2,8 @@ from django.conf.urls.defaults import *
|
||||
|
||||
from views import *
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^$', list_shared_repos),
|
||||
url(r'^list/$', list_shared_repos, name='shared_repo_list'),
|
||||
url(r'^add/$', share_repo),
|
||||
url(r'^delete/(?P<item_id>[^/]+)/$', delete_share_item),
|
||||
url('^remove/(?P<token>.+)/$', remove_anonymous_share, name='remove_anonymous_share'),
|
||||
url('^(?P<token>.+)/$', anonymous_share_confirm, name='anonymous_share_confirm'),
|
||||
)
|
||||
|
257
share/views.py
257
share/views.py
@ -1,62 +1,221 @@
|
||||
from django.http import HttpResponse, HttpResponseRedirect
|
||||
from django.shortcuts import render_to_response
|
||||
# encoding: utf-8
|
||||
from django.core.mail import send_mail
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.template import RequestContext
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpResponse, HttpResponseRedirect, Http404
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template import Context, loader, RequestContext
|
||||
|
||||
from forms import UserShareForm
|
||||
from models import UserShare
|
||||
from auth.decorators import login_required
|
||||
from django.contrib import messages
|
||||
from django.contrib.sites.models import Site, RequestSite
|
||||
from pysearpc import SearpcError
|
||||
from seaserv import seafserv_threaded_rpc, get_repo, ccnet_rpc
|
||||
|
||||
|
||||
@login_required
|
||||
def list_shared_repos(request):
|
||||
"""Show the repos I shared."""
|
||||
|
||||
share_items = UserShare.objects.filter(from_user=request.user)
|
||||
share2me_items = UserShare.objects.filter(to_user=request.user)
|
||||
#for repo in s_repos:
|
||||
# s_repos
|
||||
# pass
|
||||
return render_to_response("repo/shared_repo_list.html",
|
||||
{ 'share_items': share_items,
|
||||
"share2me_items": share2me_items },
|
||||
context_instance=RequestContext(request))
|
||||
from forms import RepoShareForm
|
||||
from models import AnonymousShare
|
||||
#from seahub.contacts.models import Contact
|
||||
from seahub.views import validate_owner, validate_emailuser
|
||||
from seahub.utils import go_permission_error
|
||||
from settings import ANONYMOUS_SHARE_COOKIE_TIMEOUT
|
||||
from tokens import anon_share_token_generator
|
||||
|
||||
@login_required
|
||||
def share_repo(request):
|
||||
"""Share a repo to a user."""
|
||||
|
||||
if request.method == 'POST':
|
||||
form = UserShareForm(request.POST)
|
||||
if form.is_valid():
|
||||
repo_share = UserShare()
|
||||
repo_share.from_user = request.user
|
||||
repo_share.to_user = form.to_user
|
||||
repo_share.repo_id = form.cleaned_data['repo_id']
|
||||
try:
|
||||
repo_share.save()
|
||||
except IntegrityError:
|
||||
# catch the case repo added to group before
|
||||
pass
|
||||
return HttpResponseRedirect(reverse('shared_repo_list', args=[]))
|
||||
else:
|
||||
user_email = request.REQUEST.get('user_email', '')
|
||||
repo_id = request.REQUEST.get('repo_id', '')
|
||||
form = UserShareForm(initial={'user_email': user_email, 'repo_id': repo_id})
|
||||
"""
|
||||
Handle repo share request
|
||||
"""
|
||||
if request.method != 'POST':
|
||||
raise Http404
|
||||
|
||||
return render_to_response("repo/share_repo.html", {
|
||||
'form': form,
|
||||
}, context_instance=RequestContext(request))
|
||||
form = RepoShareForm(request.POST)
|
||||
if not form.is_valid():
|
||||
# TODO: may display error msg on form
|
||||
raise Http404
|
||||
|
||||
email_or_group = form.cleaned_data['email_or_group']
|
||||
repo_id = form.cleaned_data['repo_id']
|
||||
from_email = request.user.username
|
||||
|
||||
# Test whether user is the repo owner
|
||||
if not validate_owner(request, repo_id):
|
||||
return go_permission_error(request, u'只有目录拥有者有权共享目录')
|
||||
|
||||
# Handle the diffent separator
|
||||
to_email_str = email_or_group.replace(';',',')
|
||||
to_email_str = to_email_str.replace('\n',',')
|
||||
to_email_str = to_email_str.replace('\r',',')
|
||||
to_email_list = to_email_str.split(',')
|
||||
|
||||
for to_email in to_email_list:
|
||||
to_email = to_email.strip(' ')
|
||||
if not to_email:
|
||||
continue
|
||||
|
||||
# if to_email is user name, the format is: 'example@mail.com';
|
||||
# if to_email is group, the format is 'group_name <creator@mail.com>'
|
||||
if (to_email.split(' ')[0].find('@') == -1):
|
||||
# share repo to group
|
||||
# TODO: if we know group id, then we can simplly call group_share_repo
|
||||
if len(to_email.split(' ')) < 2:
|
||||
messages.add_message(request, messages.ERROR, to_email)
|
||||
continue
|
||||
|
||||
group_name = to_email.split(' ')[0]
|
||||
group_creator = to_email.split(' ')[1]
|
||||
# get all the groups the user joined
|
||||
groups = ccnet_rpc.get_groups(request.user.username)
|
||||
find = False
|
||||
for group in groups:
|
||||
# for every group that user joined, if group name and
|
||||
# group creator matchs, then has find the group
|
||||
if group.props.group_name == group_name and \
|
||||
group_creator.find(group.props.creator_name) >= 0:
|
||||
from seahub.group.views import group_share_repo
|
||||
group_share_repo(request, repo_id, int(group.props.id),
|
||||
from_email)
|
||||
find = True
|
||||
messages.add_message(request, messages.INFO, group_name)
|
||||
break
|
||||
if not find:
|
||||
messages.add_message(request, messages.ERROR, group_name)
|
||||
else:
|
||||
if validate_emailuser(to_email):
|
||||
# share repo to registered user
|
||||
try:
|
||||
seafserv_threaded_rpc.add_share(repo_id, from_email,
|
||||
to_email, 'rw')
|
||||
messages.add_message(request, messages.INFO, to_email)
|
||||
except SearpcError, e:
|
||||
messages.add_message(request, messages.ERROR, to_email)
|
||||
# else:
|
||||
# # add email to contacts if not in contacts list
|
||||
# # TODO: condition should be removed
|
||||
# if from_email != to_email and Contact.objects.filter(user_email=from_email, contact_email=to_email).count() = 0:
|
||||
# contact = Contact()
|
||||
# contact.user_email = from_email
|
||||
# contact.contact_email = to_email
|
||||
# contact.contact_name = ''
|
||||
# contact.note = ''
|
||||
# contact.save()
|
||||
else:
|
||||
# share repo to anonymous user
|
||||
kwargs = {'repo_id': repo_id,
|
||||
'repo_owner': from_email,
|
||||
'anon_email': to_email
|
||||
}
|
||||
anonymous_share(request, **kwargs)
|
||||
|
||||
return HttpResponseRedirect(reverse('myhome'))
|
||||
|
||||
@login_required
|
||||
def delete_share_item(request, item_id):
|
||||
"""Delete a share item."""
|
||||
def share_admin(request):
|
||||
"""
|
||||
List repos I share to others or groups, and list my anonymous share links
|
||||
"""
|
||||
username = request.user.username
|
||||
|
||||
# repos that are share to user
|
||||
out_repos = seafserv_threaded_rpc.list_share_repos(username, 'from_email', -1, -1)
|
||||
|
||||
# repos that are share to groups
|
||||
group_repos = seafserv_threaded_rpc.get_group_my_share_repos(request.user.username)
|
||||
for group_repo in group_repos:
|
||||
repo_id = group_repo.props.repo_id
|
||||
if not repo_id:
|
||||
continue
|
||||
repo = get_repo(repo_id)
|
||||
if not repo:
|
||||
continue
|
||||
group_id = group_repo.props.group_id
|
||||
group = ccnet_rpc.get_group(int(group_id))
|
||||
if not group:
|
||||
continue
|
||||
repo.props.shared_email = group.props.group_name
|
||||
repo.gid = group_id
|
||||
|
||||
out_repos.append(repo)
|
||||
|
||||
# anonymous share links
|
||||
out_links = AnonymousShare.objects.filter(repo_owner=request.user.username)
|
||||
for link in out_links:
|
||||
repo = get_repo(link.repo_id)
|
||||
link.repo_name = repo.name
|
||||
link.remain_time = anon_share_token_generator.get_remain_time(link.token)
|
||||
|
||||
return render_to_response('repo/share_admin.html', {
|
||||
"out_repos": out_repos,
|
||||
"out_links": out_links,
|
||||
"protocol": request.is_secure() and 'https' or 'http',
|
||||
"domain": RequestSite(request).domain,
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
# 2 views for anonymous share:
|
||||
# - anonymous_share records share infomation to db and sends the mail
|
||||
# - anonymous_share_confirm checks the link use clicked and
|
||||
# adds token to client COOKIE, then redirect client to repo page
|
||||
|
||||
def anonymous_share(request, email_template_name='repo/anonymous_share_email.html', **kwargs):
|
||||
repo_id = kwargs['repo_id']
|
||||
repo_owner = kwargs['repo_owner']
|
||||
anon_email = kwargs['anon_email']
|
||||
token = anon_share_token_generator.make_token()
|
||||
|
||||
anon_share = AnonymousShare()
|
||||
anon_share.repo_owner = repo_owner
|
||||
anon_share.repo_id = repo_id
|
||||
anon_share.anonymous_email = anon_email
|
||||
anon_share.token = token
|
||||
|
||||
try:
|
||||
item = UserShare.objects.get(pk=item_id)
|
||||
item.delete()
|
||||
except UserShare.DoesNotExist:
|
||||
pass
|
||||
anon_share.save()
|
||||
except:
|
||||
messages.add_message(request, messages.ERROR, kwargs['anon_email'])
|
||||
else:
|
||||
# send mail
|
||||
use_https = request.is_secure()
|
||||
site_name = domain = RequestSite(request).domain
|
||||
|
||||
t = loader.get_template(email_template_name)
|
||||
c = {
|
||||
'email': repo_owner,
|
||||
'anon_email': anon_email,
|
||||
'domain': domain,
|
||||
'site_name': site_name,
|
||||
'token': token,
|
||||
'protocol': use_https and 'https' or 'http',
|
||||
}
|
||||
|
||||
try:
|
||||
send_mail(u'您在SeaCloud上收到一个同步目录', t.render(Context(c)), None,
|
||||
[anon_email], fail_silently=False)
|
||||
except:
|
||||
AnonymousShare.objects.filter(token=token).delete()
|
||||
messages.add_message(request, messages.ERROR, anon_email)
|
||||
else:
|
||||
messages.add_message(request, messages.INFO, anon_email)
|
||||
|
||||
def anonymous_share_confirm(request, token=None):
|
||||
assert token is not None # checked by URLconf
|
||||
|
||||
# Check whether token in db
|
||||
try:
|
||||
anon_share = AnonymousShare.objects.get(token=token)
|
||||
except AnonymousShare.DoesNotExist:
|
||||
raise Http404
|
||||
|
||||
context_instance = RequestContext(request)
|
||||
context_instance['repo_owner'] = anon_share.repo_owner
|
||||
if anon_share_token_generator.check_token(token):
|
||||
res = HttpResponseRedirect(reverse('repo', args=[anon_share.repo_id]))
|
||||
res.set_cookie("anontoken", token,
|
||||
max_age=ANONYMOUS_SHARE_COOKIE_TIMEOUT)
|
||||
return res
|
||||
else:
|
||||
return render_to_response('repo/anonymous_share_confirm.html',
|
||||
context_instance=context_instance)
|
||||
|
||||
def remove_anonymous_share(request, token):
|
||||
AnonymousShare.objects.filter(token=token).delete()
|
||||
|
||||
return HttpResponseRedirect(reverse('share_admin'))
|
||||
|
||||
return HttpResponseRedirect(request.META['HTTP_REFERER'])
|
@ -13,13 +13,15 @@
|
||||
|
||||
<body>
|
||||
<div id="wrapper">
|
||||
{% block info_bar_message %}
|
||||
{% if request.user.is_authenticated and request.cur_note %}
|
||||
<div id="info-bar">
|
||||
<span class="info">{{ request.cur_note.message|urlize }}</span>
|
||||
<a href="{{ SITE_ROOT }}notification/close/{{ request.cur_note.id }}/?next={{ request.path }}"><span class="close"></span></a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock info_bar_message %}
|
||||
|
||||
<div id="top-bar">
|
||||
<div class="top-bar">
|
||||
<div class="top-bar-in w100 ovhd">
|
||||
|
@ -39,6 +39,20 @@
|
||||
|
||||
|
||||
{% block right_panel %}
|
||||
{% if messages %}
|
||||
<ul class="messages">
|
||||
{% for message in messages %}
|
||||
{% if message.tags == 'info' %}
|
||||
<li class="notification">共享给 {{ message }} 成功,请前往<a href="{{ SITE_ROOT }}shareadmin/">共享管理</a>查看。</li>
|
||||
{% endif %}
|
||||
{% if message.tags == 'error' %}
|
||||
<li class="error">共享给 {{ message }} 失败</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{% if output_msg %}
|
||||
{% for key, value in output_msg.items %}
|
||||
{% if key == 'info_msg' %}
|
||||
@ -101,10 +115,10 @@
|
||||
<p>暂无</p>
|
||||
{% endif %}
|
||||
|
||||
<form id="repo-share-form" action="{{ SITE_ROOT }}home/my/" method="post" name="repo-share-form" class="hide">
|
||||
<form id="repo-share-form" action="{{ SITE_ROOT }}share/add/" method="post" name="repo-share-form" class="hide">
|
||||
<label>邮箱或小组:</label><br />
|
||||
<textarea id="to_email" name="to_email"></textarea><br />
|
||||
<input id="share_repo_id" type="hidden" name="share_repo_id" value="" />
|
||||
<textarea id="email_or_group" name="email_or_group"></textarea><br />
|
||||
<input id="repo_id" type="hidden" name="repo_id" value="" />
|
||||
<p class="error hide">输入不能为空。</p>
|
||||
<input type="submit" value="提交" id="share-submit-btn" />
|
||||
</form>
|
||||
@ -125,14 +139,14 @@ $(function() {
|
||||
{% endfor %}
|
||||
|
||||
$(".repo-share-btn").click(function() {
|
||||
$("#share_repo_id").val($(this).attr("data"));
|
||||
$("#repo_id").val($(this).attr("data"));
|
||||
$("#repo-share-form").modal({appendTo: "#main"});
|
||||
addAutocomplete('#to_email', '#repo-share-form', share_list);
|
||||
addAutocomplete('#email_or_group', '#repo-share-form', share_list);
|
||||
});
|
||||
|
||||
//check before post
|
||||
$('#share-submit-btn').click(function() {
|
||||
if (!$.trim($('#to_email').attr('value'))) {
|
||||
if (!$.trim($('#email_or_group').attr('value'))) {
|
||||
$('#repo-share-form .error').removeClass('hide');
|
||||
return false;
|
||||
}
|
||||
|
@ -34,4 +34,3 @@
|
||||
-->
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
|
@ -1,93 +1,103 @@
|
||||
{% extends "myhome_base.html" %}
|
||||
{% load seahub_tags %}
|
||||
|
||||
{% block info_bar_message %}
|
||||
{% if request.user.is_authenticated %}
|
||||
{{ block.super }}
|
||||
{% else %}
|
||||
<div id="info-bar">
|
||||
<span class="info">当前链接会在短期内失效,欢迎您 <a href="http://seafile.com/" target="_blank">加入Seafile </a>体验更多功能。</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block main_panel %}
|
||||
<h2 class="subject">
|
||||
{{repo.props.name}}
|
||||
</h2>
|
||||
|
||||
<div class="side fright">
|
||||
<h3>基本信息</h3>
|
||||
<p>{{repo.props.desc}}</p>
|
||||
<p>大小:{{ repo_size|filesizeformat }}</p>
|
||||
|
||||
{% if not repo.props.encrypted or password_set %}
|
||||
{% if is_owner or repo_ap == 'public' or share_to_me %}
|
||||
<div class="latest-commit">
|
||||
<h3>基本信息</h3>
|
||||
<p>{{repo.props.desc}}</p>
|
||||
<p>大小:{{ repo_size|filesizeformat }}</p>
|
||||
|
||||
{% if not repo.props.encrypted or password_set %}
|
||||
{% if can_access %}
|
||||
<div class="latest-commit">
|
||||
<h3>最新修改<a href="{{ SITE_ROOT }}repo/history/{{repo.props.id}}/" class="more">(更多)</a></h3>
|
||||
<p>{{ latest_commit.props.desc|translate_commit_desc }}</p>
|
||||
<p class="al-rt">
|
||||
<span class="author">by
|
||||
{% if latest_commit.props.creator_name %}
|
||||
{{ latest_commit.props.creator_name }}
|
||||
{% else %}
|
||||
未知
|
||||
{% endif %}
|
||||
</span>
|
||||
<span class="time">{{ latest_commit.props.ctime|translate_commit_time }}</span>
|
||||
<span class="author">by
|
||||
{% if latest_commit.props.creator_name %}
|
||||
{{ latest_commit.props.creator_name }}
|
||||
{% else %}
|
||||
未知
|
||||
{% endif %}
|
||||
</span>
|
||||
<span class="time">{{ latest_commit.props.ctime|translate_commit_time }}</span>
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="main fleft">
|
||||
{% if repo.props.encrypted and not password_set %}
|
||||
<p class="access-notice">该目录已加密。如需在线查看里面的内容,请输入解密密码。密码只会在服务器上暂存1小时。</p>
|
||||
<form action="{{ SITE_ROOT }}repo/{{ repo.id }}/" method="post">
|
||||
<label>密码:</label>
|
||||
<input id="id_password" type="password" name="password" maxlength="64" /><br />
|
||||
{% if error %}
|
||||
<p class="error">{{ error }}</p>
|
||||
{% endif %}
|
||||
<input type="submit" value="提交" />
|
||||
</form>
|
||||
|
||||
{% else %}
|
||||
{% if not is_owner and repo_ap == 'own' and not share_to_me %}
|
||||
<p class="access-notice">该同步目录web匿名访问未开启,不能在线查看。</p>
|
||||
{% else %}
|
||||
<p class="path">
|
||||
当前路径:
|
||||
{% for name, link in zipped %}
|
||||
{% if not forloop.last %}
|
||||
<a href="{{ SITE_ROOT }}repo/{{ repo.id }}/?p={{ link|urlencode }}">{{ name }}</a> /
|
||||
{% else %}
|
||||
{{ name }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
<table>
|
||||
<tr>
|
||||
<th width="5%"></th>
|
||||
<th width="69%">名字</th>
|
||||
<th width="13%">大小</th>
|
||||
<th width="13%">操作</th>
|
||||
</tr>
|
||||
|
||||
{% for dirent in dir_list %}
|
||||
<tr>
|
||||
<td class="icon-container"><img src="{{ MEDIA_URL }}img/folder-icon-24.png" alt="目录" /></td>
|
||||
<td><a href="{{ SITE_ROOT }}repo/{{ repo.id }}/?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}">{{ dirent.obj_name }}</a></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
{% for dirent in file_list %}
|
||||
<tr>
|
||||
<td class="icon-container"><img src="{{ MEDIA_URL }}img/{{ dirent.obj_name|file_icon_filter }}" alt="文件" /></td>
|
||||
<td>{{ dirent.props.obj_name }}</td>
|
||||
<td>{{ dirent.file_size|filesizeformat }}</td>
|
||||
<td>
|
||||
<a class="op" href="{{ SITE_ROOT }}repo/{{ repo.props.id }}/{{ dirent.props.obj_id }}/?file_name={{ dirent.props.obj_name }}&op=view">查看</a>
|
||||
<a class="op" href="{{ SITE_ROOT }}repo/{{ repo.props.id }}/{{ dirent.props.obj_id }}/?file_name={{ dirent.props.obj_name }}&op=download">下载</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
{% if repo.props.encrypted and not password_set %}
|
||||
<p class="access-notice">该目录已加密。如需在线查看里面的内容,请输入解密密码。密码只会在服务器上暂存1小时。</p>
|
||||
<form action="{{ SITE_ROOT }}repo/{{ repo.id }}/" method="post">
|
||||
<label>密码:</label>
|
||||
<input id="id_password" type="password" name="password" maxlength="64" /><br />
|
||||
{% if error %}
|
||||
<p class="error">{{ error }}</p>
|
||||
{% endif %}
|
||||
<input type="submit" value="提交" />
|
||||
</form>
|
||||
|
||||
{% else %}
|
||||
{% if not can_access %}
|
||||
<p class="access-notice">无法在线查看该同步目录。</p>
|
||||
{% else %}
|
||||
<p class="path">
|
||||
当前路径:
|
||||
{% for name, link in zipped %}
|
||||
{% if not forloop.last %}
|
||||
<a href="{{ SITE_ROOT }}repo/{{ repo.id }}/?p={{ link|urlencode }}">{{ name }}</a> /
|
||||
{% else %}
|
||||
{{ name }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
<table>
|
||||
<tr>
|
||||
<th width="5%"></th>
|
||||
<th width="69%">名字</th>
|
||||
<th width="13%">大小</th>
|
||||
<th width="13%">操作</th>
|
||||
</tr>
|
||||
|
||||
{% for dirent in dir_list %}
|
||||
<tr>
|
||||
<td class="icon-container"><img src="{{ MEDIA_URL }}img/folder-icon-24.png" alt="目录" /></td>
|
||||
<td><a href="{{ SITE_ROOT }}repo/{{ repo.id }}/?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}">{{ dirent.obj_name }}</a></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
{% for dirent in file_list %}
|
||||
<tr>
|
||||
<td class="icon-container"><img src="{{ MEDIA_URL }}img/{{ dirent.obj_name|file_icon_filter }}" alt="文件" /></td>
|
||||
<td>{{ dirent.props.obj_name }}</td>
|
||||
<td>{{ dirent.file_size|filesizeformat }}</td>
|
||||
<td>
|
||||
<a class="op" href="{{ SITE_ROOT }}repo/{{ repo.props.id }}/{{ dirent.props.obj_id }}/?file_name={{ dirent.props.obj_name }}&op=view">查看</a>
|
||||
<a class="op" href="{{ SITE_ROOT }}repo/{{ repo.props.id }}/{{ dirent.props.obj_id }}/?file_name={{ dirent.props.obj_name }}&op=download">下载</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
</h2>
|
||||
|
||||
<div class="side fright">
|
||||
{% if is_owner or repo_ap == 'public' or share_to_me %}
|
||||
{% if can_access %}
|
||||
<div class="latest-commit">
|
||||
<h3>修改信息</h3>
|
||||
<p>{{ current_commit.props.desc|translate_commit_desc }}</p>
|
||||
@ -24,6 +24,7 @@
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h3>操作</h3>
|
||||
<ul class="with-bg">
|
||||
<li><a href="{{ SITE_ROOT }}repo/history/{{ repo.id }}/">返回历史列表</a></li>
|
||||
@ -31,8 +32,8 @@
|
||||
</div>
|
||||
|
||||
<div class="main fleft">
|
||||
{% if not is_owner and repo_ap == 'own' and not share_to_me %}
|
||||
<p class="access-notice">该同步目录web匿名访问未开启,不能在线查看。</p>
|
||||
{% if not can_access %}
|
||||
<p class="access-notice">无法在线查看该同步目录。</p>
|
||||
{% else %}
|
||||
<p class="path">当前路径:
|
||||
{% for name, link in zipped %}
|
||||
|
10
urls.py
10
urls.py
@ -7,9 +7,10 @@ from seahub.views import root, peers, myhome, \
|
||||
activate_user, user_add, user_remove, \
|
||||
ownerhome, repo_history_dir, repo_history_revert, \
|
||||
user_info, repo_set_access_property, repo_access_file, \
|
||||
repo_add_share, repo_list_share, repo_remove_share, repo_download, \
|
||||
repo_remove_share, repo_download, \
|
||||
seafile_access_check, back_local, group_admin, repo_history_changes
|
||||
from seahub.notifications.views import notification_list
|
||||
from seahub.share.views import share_admin
|
||||
|
||||
# Uncomment the next two lines to enable the admin:
|
||||
#from django.contrib import admin
|
||||
@ -32,9 +33,9 @@ urlpatterns = patterns('',
|
||||
#url(r'^home/$', direct_to_template, { 'template': 'home.html' } ),
|
||||
url(r'^home/my/$', myhome, name='myhome'),
|
||||
url(r'^home/owner/(?P<owner_name>[^/]+)/$', ownerhome, name='ownerhome'),
|
||||
|
||||
url(r'^shareadmin/$', repo_list_share, name='repo_list_share'),
|
||||
url(r'^shareadmin/addshare/$', repo_add_share, name='repo_add_share'),
|
||||
|
||||
(r'^share/', include('share.urls')),
|
||||
url(r'^shareadmin/$', share_admin, name='share_admin'),
|
||||
(r'^shareadmin/removeshare/$', repo_remove_share),
|
||||
|
||||
url(r'^repo/(?P<repo_id>[^/]+)/$', repo, name='repo'),
|
||||
@ -66,7 +67,6 @@ urlpatterns = patterns('',
|
||||
(r'^group/', include('seahub.group.urls')),
|
||||
url(r'^groupadmin/$', group_admin, name='group_admin'),
|
||||
(r'^profile/', include('seahub.profile.urls')),
|
||||
(r'^share/', include('share.urls')),
|
||||
|
||||
(r'^back/local/$', back_local),
|
||||
)
|
||||
|
223
views.py
223
views.py
@ -4,6 +4,7 @@ import stat
|
||||
import simplejson as json
|
||||
from urllib import quote
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.contrib import messages
|
||||
from django.db import IntegrityError
|
||||
from django.http import HttpResponse, HttpResponseRedirect, Http404
|
||||
from django.shortcuts import render_to_response, redirect
|
||||
@ -22,8 +23,6 @@ from pysearpc import SearpcError
|
||||
|
||||
from seahub.base.accounts import CcnetUser
|
||||
from seahub.contacts.models import Contact
|
||||
from seahub.share.forms import GroupAddRepoForm
|
||||
from seahub.share.models import GroupShare, UserShare
|
||||
from forms import AddUserForm
|
||||
from utils import go_permission_error, go_error, list_to_string, \
|
||||
get_httpserver_root, get_ccnetapplet_root, gen_token
|
||||
@ -54,29 +53,11 @@ def peers(request):
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
def validate_owner(request, repo_id):
|
||||
# check whether email in the request own the repo
|
||||
return seafserv_threaded_rpc.is_repo_owner(request.user.username, repo_id)
|
||||
|
||||
def check_shared_repo(request, repo_id):
|
||||
"""
|
||||
check whether user has been shared this repo or
|
||||
the repo share to the groups user join
|
||||
Check whether email in the request own the repo
|
||||
|
||||
"""
|
||||
repos = seafserv_threaded_rpc.list_share_repos(request.user.username, 'to_email', -1, -1)
|
||||
for repo in repos:
|
||||
if repo.props.id == repo_id:
|
||||
return True
|
||||
|
||||
groups = ccnet_rpc.get_groups(request.user.username)
|
||||
# for every group that user joined...
|
||||
for group in groups:
|
||||
# ...get repo ids in that group, and check whether repo ids contains that repo id
|
||||
repo_ids = get_group_repoids(group.props.id)
|
||||
if repo_ids.__contains__(repo_id):
|
||||
return True
|
||||
|
||||
return False
|
||||
return seafserv_threaded_rpc.is_repo_owner(request.user.username, repo_id)
|
||||
|
||||
def validate_emailuser(emailuser):
|
||||
"""
|
||||
@ -93,14 +74,41 @@ def validate_emailuser(emailuser):
|
||||
else:
|
||||
return False
|
||||
|
||||
def check_shared_repo(request, repo_id):
|
||||
"""
|
||||
Check whether user has been shared this repo or
|
||||
the repo share to the groups user join or
|
||||
got token if user is not logged in
|
||||
|
||||
"""
|
||||
if not request.user.is_authenticated():
|
||||
token = request.COOKIES.get('anontoken', None)
|
||||
if token:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
repos = seafserv_threaded_rpc.list_share_repos(request.user.username, 'to_email', -1, -1)
|
||||
for repo in repos:
|
||||
if repo.props.id == repo_id:
|
||||
return True
|
||||
|
||||
groups = ccnet_rpc.get_groups(request.user.username)
|
||||
# for every group that user joined...
|
||||
for group in groups:
|
||||
# ...get repo ids in that group, and check whether repo ids contains that repo id
|
||||
repo_ids = get_group_repoids(group.props.id)
|
||||
if repo_id in repo_ids:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def access_to_repo(request, repo_id, repo_ap):
|
||||
"""
|
||||
Check whether user in the request can access to repo, which means user can
|
||||
view directory entries on repo page, and repo_history_dir page.
|
||||
|
||||
"""
|
||||
# if repo is 'own' and user is not staff and is not owner
|
||||
# and not shared this repo, then goto 404 page..
|
||||
if repo_ap == 'own' and not validate_owner(request, repo_id) \
|
||||
and not check_shared_repo(request, repo_id) and not request.user.is_staff:
|
||||
return False
|
||||
@ -133,16 +141,26 @@ def render_repo(request, repo_id, error=''):
|
||||
# get repo web access property, if no repo access property in db, then
|
||||
# assume repo ap is 'own'
|
||||
repo_ap = seafserv_threaded_rpc.repo_query_access_property(repo_id)
|
||||
if repo_ap == None:
|
||||
if not repo_ap:
|
||||
repo_ap = 'own'
|
||||
|
||||
if not access_to_repo(request, repo_id, repo_ap):
|
||||
return go_permission_error(request, u'该同步目录未公开')
|
||||
|
||||
# check whether user can view repo
|
||||
if access_to_repo(request, repo_id, repo_ap):
|
||||
can_access = True
|
||||
else:
|
||||
can_access = False
|
||||
|
||||
# check whether use is repo owner
|
||||
if validate_owner(request, repo_id):
|
||||
is_owner = True
|
||||
else:
|
||||
is_owner = False
|
||||
|
||||
repo = get_repo(repo_id)
|
||||
if not repo:
|
||||
return go_error(request, u'该同步目录不存在')
|
||||
|
||||
# query whether set password if repo is encrypted
|
||||
password_set = False
|
||||
if repo.props.encrypted:
|
||||
try:
|
||||
@ -152,9 +170,11 @@ def render_repo(request, repo_id, error=''):
|
||||
except SearpcError, e:
|
||||
return go_error(request, e.msg)
|
||||
|
||||
# query repo infomation
|
||||
repo_size = seafserv_threaded_rpc.server_repo_size(repo_id)
|
||||
latest_commit = get_commits(repo_id, 0, 1)[0]
|
||||
|
||||
# get repo dirents
|
||||
dirs = []
|
||||
path = ''
|
||||
zipped = []
|
||||
@ -190,22 +210,9 @@ def render_repo(request, repo_id, error=''):
|
||||
# generate path and link
|
||||
zipped = gen_path_link(path, repo.name)
|
||||
|
||||
# check whether use is repo owner
|
||||
is_owner = False
|
||||
if request.user.is_authenticated():
|
||||
if validate_owner(request, repo_id):
|
||||
is_owner = True
|
||||
|
||||
# used to determin whether show repo content in repo.html
|
||||
# if a repo is shared to me, or repo shared to the group I joined,
|
||||
# then I can view repo content on the web
|
||||
if check_shared_repo(request, repo_id):
|
||||
share_to_me = True
|
||||
else:
|
||||
share_to_me = False
|
||||
|
||||
return render_to_response('repo.html', {
|
||||
"repo": repo,
|
||||
"can_access": can_access,
|
||||
"latest_commit": latest_commit,
|
||||
"is_owner": is_owner,
|
||||
"password_set": password_set,
|
||||
@ -213,7 +220,6 @@ def render_repo(request, repo_id, error=''):
|
||||
"repo_size": repo_size,
|
||||
"dir_list": dir_list,
|
||||
"file_list": file_list,
|
||||
"share_to_me": share_to_me,
|
||||
"path" : path,
|
||||
"zipped" : zipped,
|
||||
"error" : error,
|
||||
@ -307,14 +313,24 @@ def repo_history_dir(request, repo_id):
|
||||
repo_ap = seafserv_threaded_rpc.repo_query_access_property(repo_id)
|
||||
if not repo_ap:
|
||||
repo_ap = 'own'
|
||||
|
||||
if not access_to_repo(request, repo_id, repo_ap):
|
||||
raise Http404
|
||||
|
||||
# check whether user can view repo
|
||||
if access_to_repo(request, repo_id, repo_ap):
|
||||
can_access = True
|
||||
else:
|
||||
can_access = False
|
||||
|
||||
# check whether use is repo owner
|
||||
if validate_owner(request, repo_id):
|
||||
is_owner = True
|
||||
else:
|
||||
is_owner = False
|
||||
|
||||
repo = get_repo(repo_id)
|
||||
if not repo:
|
||||
raise Http404
|
||||
|
||||
# query whether set password if repo is encrypted
|
||||
password_set = False
|
||||
if repo.props.encrypted:
|
||||
try:
|
||||
@ -334,11 +350,7 @@ def repo_history_dir(request, repo_id):
|
||||
if not current_commit:
|
||||
raise Http404
|
||||
|
||||
is_owner = False
|
||||
if request.user.is_authenticated():
|
||||
if validate_owner(request, repo_id):
|
||||
is_owner = True
|
||||
|
||||
# get repo dirents
|
||||
dirs = []
|
||||
path = ''
|
||||
zipped = []
|
||||
@ -367,22 +379,14 @@ def repo_history_dir(request, repo_id):
|
||||
# generate path and link
|
||||
zipped = gen_path_link(path, repo.name)
|
||||
|
||||
# used to determin whether show repo content in repo.html
|
||||
# if a repo is shared to me, or repo shared to the group I joined,
|
||||
# then I can view repo content on the web
|
||||
if check_shared_repo(request, repo_id):
|
||||
share_to_me = True
|
||||
else:
|
||||
share_to_me = False
|
||||
|
||||
return render_to_response('repo_history_dir.html', {
|
||||
"repo": repo,
|
||||
"can_access": can_access,
|
||||
"current_commit": current_commit,
|
||||
"is_owner": is_owner,
|
||||
"repo_ap": repo_ap,
|
||||
"dir_list": dir_list,
|
||||
"file_list": file_list,
|
||||
"share_to_me": share_to_me,
|
||||
"path" : path,
|
||||
"zipped" : zipped,
|
||||
}, context_instance=RequestContext(request))
|
||||
@ -554,10 +558,6 @@ def myhome(request):
|
||||
in_repos = seafserv_threaded_rpc.list_share_repos(request.user.username,
|
||||
'to_email', -1, -1)
|
||||
|
||||
# handle share repo request
|
||||
if request.method == 'POST':
|
||||
output_msg = repo_add_share(request)
|
||||
|
||||
# my contacts
|
||||
contacts = Contact.objects.filter(user_email=email)
|
||||
|
||||
@ -570,12 +570,11 @@ def myhome(request):
|
||||
groups_manage.append(group)
|
||||
else:
|
||||
groups_join.append(group)
|
||||
|
||||
|
||||
return render_to_response('myhome.html', {
|
||||
"owned_repos": owned_repos,
|
||||
"quota_usage": quota_usage,
|
||||
"in_repos": in_repos,
|
||||
"output_msg": output_msg,
|
||||
"contacts": contacts,
|
||||
"groups": groups,
|
||||
"groups_manage": groups_manage,
|
||||
@ -658,96 +657,6 @@ def repo_access_file(request, repo_id, obj_id):
|
||||
token,
|
||||
request.user.username)
|
||||
return HttpResponseRedirect(redirect_url)
|
||||
|
||||
@login_required
|
||||
def repo_add_share(request):
|
||||
output_msg = {}
|
||||
|
||||
if request.method == 'POST':
|
||||
from_email = request.user.username
|
||||
repo_id = request.POST.get('share_repo_id', '')
|
||||
|
||||
# Handle the diffent separator
|
||||
to_email_str = request.POST.get('to_email', '').replace(';',',')
|
||||
to_email_str = to_email_str.replace('\n',',')
|
||||
to_email_str = to_email_str.replace('\r',',')
|
||||
|
||||
to_email_list = to_email_str.split(',')
|
||||
info_emails = []
|
||||
err_emails = []
|
||||
for to_email in to_email_list:
|
||||
to_email = to_email.strip(' ')
|
||||
if not to_email:
|
||||
continue
|
||||
|
||||
# if to_email is user name, the format is: 'example@mail.com';
|
||||
# if to_email is group, the format is 'group_name <creator@mail.com>'
|
||||
if (to_email.split(' ')[0].find('@') == -1):
|
||||
group_name = to_email.split(' ')[0]
|
||||
group_creator = to_email.split(' ')[1]
|
||||
if validate_owner(request, repo_id):
|
||||
# get all the groups the user joined
|
||||
groups = ccnet_rpc.get_groups(request.user.username)
|
||||
find = False
|
||||
for group in groups:
|
||||
# for every group that user joined, if group name and
|
||||
# group creator matchs, then has find the group
|
||||
if group.props.group_name == group_name and \
|
||||
group_creator.find(group.props.creator_name) >= 0:
|
||||
from seahub.group.views import group_share_repo
|
||||
group_share_repo(request, repo_id, int(group.props.id), from_email)
|
||||
find = True
|
||||
info_emails.append(group_name)
|
||||
|
||||
if not find:
|
||||
err_emails.append(group_name)
|
||||
else:
|
||||
err_emails.append(group_name)
|
||||
else:
|
||||
if validate_emailuser(to_email) and validate_owner(request, repo_id):
|
||||
try:
|
||||
seafserv_threaded_rpc.add_share(repo_id, from_email, to_email, 'rw')
|
||||
info_emails.append(to_email)
|
||||
except SearpcError, e:
|
||||
err_emails.append(to_email)
|
||||
else:
|
||||
err_emails.append(to_email)
|
||||
|
||||
if info_emails:
|
||||
output_msg['info_msg'] = u'共享给%s成功,' % list_to_string(info_emails)
|
||||
if err_emails:
|
||||
output_msg['err_msg'] = u'共享给%s失败' % list_to_string(err_emails)
|
||||
|
||||
return output_msg
|
||||
|
||||
@login_required
|
||||
def repo_list_share(request):
|
||||
username = request.user.username
|
||||
|
||||
# repos that are share to user
|
||||
out_repos = seafserv_threaded_rpc.list_share_repos(username, 'from_email', -1, -1)
|
||||
|
||||
# repos that are share to groups
|
||||
group_repos = seafserv_threaded_rpc.get_group_my_share_repos(request.user.username)
|
||||
for group_repo in group_repos:
|
||||
repo_id = group_repo.props.repo_id
|
||||
if not repo_id:
|
||||
continue
|
||||
repo = get_repo(repo_id)
|
||||
if not repo:
|
||||
continue
|
||||
group_id = group_repo.props.group_id
|
||||
group = ccnet_rpc.get_group(int(group_id))
|
||||
if not group:
|
||||
continue
|
||||
repo.props.shared_email = group.props.group_name
|
||||
repo.gid = group_id
|
||||
|
||||
out_repos.append(repo)
|
||||
|
||||
return render_to_response('share_repos.html', {
|
||||
"out_repos": out_repos,
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
@login_required
|
||||
def repo_download(request):
|
||||
@ -816,7 +725,7 @@ def repo_remove_share(request):
|
||||
|
||||
referer = request.META.get('HTTP_REFERER', None)
|
||||
if not referer:
|
||||
referer = 'repo_list_share'
|
||||
referer = 'share_admin'
|
||||
return HttpResponseRedirect(reverse(referer))
|
||||
else:
|
||||
return HttpResponseRedirect(referer)
|
||||
|
Loading…
Reference in New Issue
Block a user