mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-04 08:28:11 +00:00
Add group feature
This commit is contained in:
@@ -6,4 +6,8 @@ register = template.Library()
|
|||||||
@register.filter(name='tsstr_sec')
|
@register.filter(name='tsstr_sec')
|
||||||
def tsstr_sec(value):
|
def tsstr_sec(value):
|
||||||
"""Turn a timestamp to string"""
|
"""Turn a timestamp to string"""
|
||||||
return datetime.fromtimestamp(value).strftime("%Y-%m-%d %H:%M:%S")
|
try:
|
||||||
|
return datetime.fromtimestamp(value).strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
except:
|
||||||
|
return datetime.fromtimestamp(value/1000000).strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
@@ -1,33 +1,3 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
|
# Create your models here.
|
||||||
class Group(models.Model):
|
|
||||||
"""A group is identified uniquely by group_id."""
|
|
||||||
|
|
||||||
group_id = models.CharField(max_length=36, primary_key=True, db_column='uuid')
|
|
||||||
name = models.CharField(max_length=20, editable=False, unique=True)
|
|
||||||
creator = models.ForeignKey(User, verbose_name=_("creator"), related_name="%(class)s_created")
|
|
||||||
admin = models.ForeignKey(User, verbose_name=_("admin"), related_name="%(class)s_admined")
|
|
||||||
ctime = models.DateTimeField('create time', editable=False)
|
|
||||||
description = models.TextField(_("description"))
|
|
||||||
users = models.ManyToManyField(User)
|
|
||||||
|
|
||||||
def __unicode__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
|
|
||||||
class JoinRequest(models.Model):
|
|
||||||
"""A request for joining a group."""
|
|
||||||
group = models.ForeignKey(Group)
|
|
||||||
user = models.ForeignKey(User)
|
|
||||||
ctime = models.DateTimeField('create time', editable=False)
|
|
||||||
|
|
||||||
|
|
||||||
class Invitation(models.Model):
|
|
||||||
"""An invitation for joining a group."""
|
|
||||||
|
|
||||||
group = models.ForeignKey(Group)
|
|
||||||
user = models.ForeignKey(User)
|
|
||||||
ctime = models.DateTimeField('create time', editable=False)
|
|
||||||
|
118
group/templates/group/group_info.html
Normal file
118
group/templates/group/group_info.html
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
{% extends "myhome_base.html" %}
|
||||||
|
{% load seahub_tags %}
|
||||||
|
|
||||||
|
{% block nav_group_class %}class="cur"{% endblock %}
|
||||||
|
{% block left_panel %}
|
||||||
|
<ul>
|
||||||
|
<li>管理员</li>
|
||||||
|
{% for member in members %}
|
||||||
|
{% if member.props.is_staff == 1 %}
|
||||||
|
<p><a href="{{ SITE_ROOT }}useradmin/info/{{ member.props.user_name }}/">{{ member.props.user_name }}</a></p>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
<li>成员</li>
|
||||||
|
{% for member in members %}
|
||||||
|
{% if member.props.is_staff == 0 %}
|
||||||
|
<p><a href="{{ SITE_ROOT }}useradmin/info/{{ member.props.user_name }}/">{{ member.props.user_name }}</a></p>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
<li>操作</li>
|
||||||
|
{% if is_creator %}
|
||||||
|
<p><a id="add-member" href="#">添加成员</a></p>
|
||||||
|
<p><a id="remove-member" href="#">删除成员</a></p>
|
||||||
|
<p><a id="remove-group" href="#">解散小组</a></p>
|
||||||
|
{% else %}
|
||||||
|
<p><a id="quit-group" href="#">退出小组</a></p>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block right_panel %}
|
||||||
|
|
||||||
|
<h3>小组里共享的同步目录</h3>
|
||||||
|
{% if repos %}
|
||||||
|
<table class="repo-list">
|
||||||
|
<tr>
|
||||||
|
<th width="30%">名字</th>
|
||||||
|
<th width="30%">描述</th>
|
||||||
|
<th width="20%">共享来源</th>
|
||||||
|
<th width="20%">操作</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{% for repo in repos %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{{ SITE_ROOT }}repo/{{ repo.props.id }}/">{{ repo.props.name }}</a></td>
|
||||||
|
<td>{{ repo.props.desc }}</td>
|
||||||
|
<td>{{ repo.share_from }}</td>
|
||||||
|
<td>
|
||||||
|
<button data="{{ SITE_ROOT }}download/repo/?repo_id={{ repo.props.id }}" class="download-btn">下载</button>
|
||||||
|
{% if is_creator or repo.share_from_me %}
|
||||||
|
<button data="{{ SITE_ROOT }}shareadmin/removeshare/?repo_id={{ repo.props.id }}&gid={{ group_id }}" class="repo-delete-btn">删除</button>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
{% else %}
|
||||||
|
<p>暂无</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<form id="member-add-form" action="{{ SITE_ROOT }}group/memberadd/" method="post" name="member-add-form" class="hide">
|
||||||
|
<label>邮箱</label><br />
|
||||||
|
<input id="user_name" name="user_name" value="" />
|
||||||
|
<input type="hidden" id="group_id" name="group_id" value="{{ group_id }}" />
|
||||||
|
<input type="submit" value="提交" />
|
||||||
|
</form>
|
||||||
|
<form id="member-remove-form" action="{{ SITE_ROOT }}group/memberrm/" method="post" name="member-remove-form" class="hide">
|
||||||
|
<label>邮箱</label><br />
|
||||||
|
<input id="user_name" name="user_name" value="" />
|
||||||
|
<input type="hidden" id="group_id" name="group_id" value="{{ group_id }}" />
|
||||||
|
<input type="submit" value="提交" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div id="dialog-remove-confirm" class="center hide">
|
||||||
|
<p>确定要解散?</p>
|
||||||
|
<button id="rm-yes-btn">确定</button>
|
||||||
|
<button class="simplemodal-close">取消</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="dialog-quit-confirm" class="center hide">
|
||||||
|
<p>确定要退出?</p>
|
||||||
|
<button id="quit-yes-btn">确定</button>
|
||||||
|
<button class="simplemodal-close">取消</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_script %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
$("#add-member").click(function() {
|
||||||
|
$("#member-add-form").modal({appendTo: "#main", containerCss:{padding:18}});
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#remove-member").click(function() {
|
||||||
|
$("#member-remove-form").modal({appendTo: "#main", containerCss:{padding:18}});
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#remove-group").click(function() {
|
||||||
|
$('#dialog-remove-confirm').modal({appendTo:'#main'});
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#quit-group").click(function() {
|
||||||
|
$('#dialog-quit-confirm').modal({appendTo:'#main'});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#rm-yes-btn').click(function() {
|
||||||
|
location.href = "{{ SITE_ROOT }}group/rm/?gid={{ group_id }}";
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#quit-yes-btn').click(function() {
|
||||||
|
location.href = "{{ SITE_ROOT }}group/quit/?gid={{ group_id }}";
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.repo-delete-btn').click(function() {
|
||||||
|
location.href = $(this).attr('data');
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
49
group/templates/group/groups.html
Normal file
49
group/templates/group/groups.html
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
{% extends "myhome_base.html" %}
|
||||||
|
{% load seahub_tags %}
|
||||||
|
|
||||||
|
{% block nav_group_class %}class="cur"{% endblock %}
|
||||||
|
{% block left_panel %}
|
||||||
|
<ul>
|
||||||
|
<li><a id="group-add" href="#">添加小组</a></li>
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block right_panel %}
|
||||||
|
|
||||||
|
<h3>我参加的小组</h3>
|
||||||
|
{% if groups %}
|
||||||
|
<table class="group-list">
|
||||||
|
<tr>
|
||||||
|
<th width="30%">名字</th>
|
||||||
|
<th width="40%">创建者</th>
|
||||||
|
<th width="30%">创建时间</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{% for group in groups %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{{ SITE_ROOT }}group/{{ group.props.id }}/">{{ group.props.group_name }}</a></td>
|
||||||
|
<td>{{ group.props.creator_name }}</td>
|
||||||
|
<td>{{ group.props.timestamp|tsstr_sec }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
{% else %}
|
||||||
|
<p>暂无</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<form id="group-add-form" action="{{ SITE_ROOT }}group/add/" method="post" name="group-add-form" class="hide">
|
||||||
|
<label>小组名称</label><br />
|
||||||
|
<input id="group_name" name="group_name" value="" />
|
||||||
|
<input type="submit" value="提交" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_script %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
$("#group-add").click(function() {
|
||||||
|
$("#group-add-form").modal({appendTo: "#main", containerCss:{padding:18}});
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
23
group/tests.py
Normal file
23
group/tests.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
"""
|
||||||
|
This file demonstrates two different styles of tests (one doctest and one
|
||||||
|
unittest). These will both pass when you run "manage.py test".
|
||||||
|
|
||||||
|
Replace these with more appropriate tests for your application.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
class SimpleTest(TestCase):
|
||||||
|
def test_basic_addition(self):
|
||||||
|
"""
|
||||||
|
Tests that 1 + 1 always equals 2.
|
||||||
|
"""
|
||||||
|
self.failUnlessEqual(1 + 1, 2)
|
||||||
|
|
||||||
|
__test__ = {"doctest": """
|
||||||
|
Another way to test that 1 + 1 is equal to 2.
|
||||||
|
|
||||||
|
>>> 1 + 1 == 2
|
||||||
|
True
|
||||||
|
"""}
|
||||||
|
|
15
group/urls.py
Normal file
15
group/urls.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from django.conf.urls.defaults import *
|
||||||
|
|
||||||
|
from views import group_list, group_add, group_info, \
|
||||||
|
group_add_member, group_remove_member, \
|
||||||
|
group_quit, group_remove
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
url(r'^$', group_list, name='group_list'),
|
||||||
|
(r'^add/$', group_add),
|
||||||
|
(r'^rm/$', group_remove),
|
||||||
|
(r'^memberadd/$', group_add_member),
|
||||||
|
(r'^memberrm/$', group_remove_member),
|
||||||
|
(r'^quit/$', group_quit),
|
||||||
|
url(r'^(?P<group_id>[^/]+)/$', group_info, name='group_info'),
|
||||||
|
)
|
153
group/views.py
153
group/views.py
@@ -1,4 +1,153 @@
|
|||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.http import HttpResponse, HttpResponseRedirect, Http404
|
||||||
from django.contrib.auth.models import User
|
from django.shortcuts import render_to_response, redirect
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
from django.template import RequestContext
|
||||||
|
from auth.decorators import login_required
|
||||||
|
|
||||||
|
from seaserv import ccnet_rpc, seafserv_threaded_rpc, get_repo, \
|
||||||
|
get_group_repoids
|
||||||
|
|
||||||
|
from seahub.views import validate_emailuser
|
||||||
|
from seahub.utils import go_error, go_permission_error
|
||||||
|
|
||||||
|
from pysearpc import SearpcError
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def group_list(request):
|
||||||
|
groups = ccnet_rpc.get_groups(request.user.username);
|
||||||
|
|
||||||
|
return render_to_response("group/groups.html", {
|
||||||
|
"groups": groups,
|
||||||
|
}, context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def group_add(request):
|
||||||
|
error_msg = None
|
||||||
|
if request.method == 'POST':
|
||||||
|
group_name = request.POST.get('group_name')
|
||||||
|
if group_name.find('@') >= 0:
|
||||||
|
return go_error(request, u'小组名称不能包含@')
|
||||||
|
|
||||||
|
try:
|
||||||
|
ccnet_rpc.create_group(group_name.encode('utf-8'), request.user.username)
|
||||||
|
except SearpcError, e:
|
||||||
|
error_msg = e.msg
|
||||||
|
return go_error(request, error_msg)
|
||||||
|
|
||||||
|
return HttpResponseRedirect(reverse('group_list', args=[]))
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def group_remove(request):
|
||||||
|
group_id = request.GET.get('gid')
|
||||||
|
|
||||||
|
try:
|
||||||
|
group_id_int = int(group_id)
|
||||||
|
except ValueError:
|
||||||
|
group_id_int = -1
|
||||||
|
|
||||||
|
try:
|
||||||
|
ccnet_rpc.remove_group(group_id_int, request.user.username)
|
||||||
|
seafserv_threaded_rpc.remove_repo_group(group_id_int, None)
|
||||||
|
except SearpcError, e:
|
||||||
|
return go_error(request, e.msg)
|
||||||
|
|
||||||
|
return HttpResponseRedirect(reverse('group_list', args=[]))
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def group_info(request, group_id):
|
||||||
|
try:
|
||||||
|
group_id_int = int(group_id)
|
||||||
|
except ValueError:
|
||||||
|
return HttpResponseRedirect(reverse('group_list', args=[]))
|
||||||
|
|
||||||
|
group = ccnet_rpc.get_group(group_id_int)
|
||||||
|
if not group:
|
||||||
|
return HttpResponseRedirect(reverse('group_list', args=[]))
|
||||||
|
|
||||||
|
if group.props.creator_name == request.user.username:
|
||||||
|
is_creator = True
|
||||||
|
else:
|
||||||
|
is_creator = False
|
||||||
|
|
||||||
|
members = ccnet_rpc.get_group_members(group_id_int)
|
||||||
|
|
||||||
|
repos = []
|
||||||
|
repo_ids = get_group_repoids(group_id=group_id_int)
|
||||||
|
for repo_id in repo_ids:
|
||||||
|
if not repo_id:
|
||||||
|
continue
|
||||||
|
repo = get_repo(repo_id)
|
||||||
|
repo.share_from = seafserv_threaded_rpc.get_group_repo_share_from(repo_id)
|
||||||
|
if request.user.username == repo.share_from:
|
||||||
|
repo.share_from_me = True
|
||||||
|
else:
|
||||||
|
repo.share_from_me = False
|
||||||
|
repos.append(repo)
|
||||||
|
|
||||||
|
return render_to_response("group/group_info.html", {
|
||||||
|
"members": members,
|
||||||
|
"repos": repos,
|
||||||
|
"group_id": group_id,
|
||||||
|
"is_creator": is_creator,
|
||||||
|
}, context_instance=RequestContext(request));
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def group_add_member(request):
|
||||||
|
if request.method == 'POST':
|
||||||
|
group_id = request.POST.get('group_id')
|
||||||
|
member_name = request.POST.get('user_name')
|
||||||
|
if not validate_emailuser(member_name):
|
||||||
|
err_msg = u'用户不存在'
|
||||||
|
return go_error(request, err_msg)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
group_id_int = int(group_id)
|
||||||
|
except ValueError:
|
||||||
|
return go_error(request, u'group id 不是有效参数')
|
||||||
|
try:
|
||||||
|
ccnet_rpc.group_add_member(group_id_int, request.user.username,
|
||||||
|
member_name)
|
||||||
|
except SearpcError, e:
|
||||||
|
return go_error(request, e.msg)
|
||||||
|
|
||||||
|
return HttpResponseRedirect(reverse('group_info', args=[group_id]))
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def group_remove_member(request):
|
||||||
|
if request.method == 'POST':
|
||||||
|
group_id = request.POST.get('group_id')
|
||||||
|
member_name = request.POST.get('user_name')
|
||||||
|
if not validate_emailuser(member_name):
|
||||||
|
err_msg = u'用户不存在'
|
||||||
|
return go_error(request, err_msg)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
group_id_int = int(group_id)
|
||||||
|
except ValueError:
|
||||||
|
raise Http404
|
||||||
|
try:
|
||||||
|
ccnet_rpc.group_remove_member(group_id_int, request.user.username,
|
||||||
|
member_name)
|
||||||
|
seafserv_threaded_rpc.remove_repo_group(group_id_int, member_name)
|
||||||
|
except SearpcError, e:
|
||||||
|
return go_error(request, e.msg)
|
||||||
|
|
||||||
|
return HttpResponseRedirect(reverse('group_info', args=[group_id]))
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def group_quit(request):
|
||||||
|
group_id = request.GET.get('gid')
|
||||||
|
try:
|
||||||
|
group_id_int = int(group_id)
|
||||||
|
except ValueError:
|
||||||
|
raise Http404
|
||||||
|
|
||||||
|
try:
|
||||||
|
ccnet_rpc.quit_group(group_id_int, request.user.username)
|
||||||
|
seafserv_threaded_rpc.remove_repo_group(group_id_int, request.user.username)
|
||||||
|
except SearpcError, e:
|
||||||
|
return go_error(request, e.msg)
|
||||||
|
|
||||||
|
return HttpResponseRedirect(reverse('group_list', args=[]))
|
||||||
|
@@ -103,7 +103,7 @@ INSTALLED_APPS = (
|
|||||||
'seahub.base',
|
'seahub.base',
|
||||||
'seahub.profile',
|
'seahub.profile',
|
||||||
'seahub.contacts',
|
'seahub.contacts',
|
||||||
# 'seahub.group',
|
'seahub.group',
|
||||||
# 'seahub.share',
|
# 'seahub.share',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
8
templates/error.html
Normal file
8
templates/error.html
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{% extends "myhome_base.html" %}
|
||||||
|
|
||||||
|
{% block title %}错误{% endblock %}
|
||||||
|
|
||||||
|
{% block main_panel %}
|
||||||
|
|
||||||
|
<p>{{ error_msg }}</p>
|
||||||
|
{% endblock %}
|
@@ -1,33 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block title %}Groups{% endblock %}
|
|
||||||
|
|
||||||
{% block left_panel %}
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block right_panel %}
|
|
||||||
|
|
||||||
<p>Use the following command to add a group:</p>
|
|
||||||
<div><code>ccnet-tool group-follow <group-id> <rendevous-id></code></div>
|
|
||||||
|
|
||||||
<h3>Groups</h3>
|
|
||||||
|
|
||||||
<table class="group-list default">
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>ID</th>
|
|
||||||
<th>Rendezvous</th>
|
|
||||||
<th>Maintainer</th>
|
|
||||||
</tr>
|
|
||||||
{% for group in groups %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ group.props.name }}</td>
|
|
||||||
<td>{{ group.props.id }}</td>
|
|
||||||
<td>{{ group.props.rendezvous }}</td>
|
|
||||||
<td>{{ group.props.maintainers }}</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
@@ -70,7 +70,7 @@
|
|||||||
{% endif %}
|
{% 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 }}home/my/" method="post" name="repo-share-form" class="hide">
|
||||||
<label>邮箱:</label><br />
|
<label>邮箱或小组:</label><br />
|
||||||
<textarea id="to_email" name="to_email"></textarea><br />
|
<textarea id="to_email" name="to_email"></textarea><br />
|
||||||
<input id="share_repo_id" type="hidden" name="share_repo_id" value="" />
|
<input id="share_repo_id" type="hidden" name="share_repo_id" value="" />
|
||||||
<p class="error hide">输入不能为空。</p>
|
<p class="error hide">输入不能为空。</p>
|
||||||
@@ -88,6 +88,10 @@ $(function() {
|
|||||||
contact_list.push('{{ contact.contact_email }}');
|
contact_list.push('{{ contact.contact_email }}');
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
{% for group in groups %}
|
||||||
|
contact_list.push('{{ group.props.group_name }} <{{ group.props.creator_name }}>');
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
function split(val) {
|
function split(val) {
|
||||||
return val.split(/,\s*/);
|
return val.split(/,\s*/);
|
||||||
}
|
}
|
||||||
|
@@ -10,7 +10,9 @@
|
|||||||
<li>
|
<li>
|
||||||
<a href="{{ SITE_ROOT }}contacts/" {% block nav_contacts_class %}{% endblock %}>联系人</a>
|
<a href="{{ SITE_ROOT }}contacts/" {% block nav_contacts_class %}{% endblock %}>联系人</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ SITE_ROOT }}group/" {% block nav_group_class %}{% endblock %}>小组</a>
|
||||||
|
</li>
|
||||||
{% if request.user.is_staff %}
|
{% if request.user.is_staff %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ SITE_ROOT }}seafadmin/" {% block nav_seafadmin_class %}{% endblock %}>目录管理</a>
|
<a href="{{ SITE_ROOT }}seafadmin/" {% block nav_seafadmin_class %}{% endblock %}>目录管理</a>
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
{% extends "myhome_base.html" %}
|
{% extends "myhome_base.html" %}
|
||||||
|
|
||||||
{% block title %}Permission Error{% endblock %}
|
{% block title %}权限错误{% endblock %}
|
||||||
|
|
||||||
{% block main_panel %}
|
{% block main_panel %}
|
||||||
|
|
||||||
<p>Permission Error.</p>
|
<p>{{ error_msg }}</p>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@@ -18,7 +18,7 @@
|
|||||||
<td>{{ repo.props.shared_email }}</td>
|
<td>{{ repo.props.shared_email }}</td>
|
||||||
<td>{{ repo.props.desc }}</td>
|
<td>{{ repo.props.desc }}</td>
|
||||||
<td>
|
<td>
|
||||||
<button data="{{ SITE_ROOT }}shareadmin/removeshare/?repo_id={{ repo.props.id }}&to_email={{ repo.props.shared_email }}" class="cancel-share-btn">取消共享</button>
|
<button data="{{ SITE_ROOT }}shareadmin/removeshare/?repo_id={{ repo.props.id }}&to_email={{ repo.props.shared_email }}&gid={{ repo.gid }}" class="cancel-share-btn">取消共享</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@@ -12,6 +12,7 @@ from service import get_users, get_user, get_events, count_event
|
|||||||
from service import get_repos, get_repo, get_commits, get_branches
|
from service import get_repos, get_repo, get_commits, get_branches
|
||||||
from service import get_binding_peerids
|
from service import get_binding_peerids
|
||||||
from service import get_ccnetuser
|
from service import get_ccnetuser
|
||||||
|
from service import get_group_repoids
|
||||||
|
|
||||||
from service import CCNET_CONF_PATH
|
from service import CCNET_CONF_PATH
|
||||||
|
|
||||||
|
@@ -385,9 +385,31 @@ def get_binding_peerids(email):
|
|||||||
except SearpcError:
|
except SearpcError:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
if not peer_ids:
|
||||||
|
return []
|
||||||
|
|
||||||
peerid_list = []
|
peerid_list = []
|
||||||
for peer_id in peer_ids.split("\n"):
|
for peer_id in peer_ids.split("\n"):
|
||||||
if peer_id == '':
|
if peer_id == '':
|
||||||
continue
|
continue
|
||||||
peerid_list.append(peer_id)
|
peerid_list.append(peer_id)
|
||||||
return peerid_list
|
return peerid_list
|
||||||
|
|
||||||
|
def get_group_repoids(group_id=None):
|
||||||
|
"""Get repo ids of a given group id or username"""
|
||||||
|
try:
|
||||||
|
repo_ids = seafserv_threaded_rpc.get_group_repoids(group_id)
|
||||||
|
except SearpcError:
|
||||||
|
return []
|
||||||
|
|
||||||
|
if not repo_ids:
|
||||||
|
return []
|
||||||
|
|
||||||
|
repoid_list = []
|
||||||
|
for repo_id in repo_ids.split("\n"):
|
||||||
|
if repo_id == '':
|
||||||
|
continue
|
||||||
|
repoid_list.append(repo_id)
|
||||||
|
return repoid_list
|
||||||
|
|
||||||
|
|
||||||
|
5
urls.py
5
urls.py
@@ -2,8 +2,8 @@ from django.conf.urls.defaults import *
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.views.generic.simple import direct_to_template
|
from django.views.generic.simple import direct_to_template
|
||||||
|
|
||||||
from seahub.views import root, peers, groups, myhome, \
|
from seahub.views import root, peers, myhome, \
|
||||||
repo, repo_history, group, modify_token, remove_repo, seafadmin, useradmin, \
|
repo, repo_history, modify_token, remove_repo, seafadmin, useradmin, \
|
||||||
role_add, role_remove, activate_user, user_add, user_remove, \
|
role_add, role_remove, activate_user, user_add, user_remove, \
|
||||||
ownerhome, remove_fetched_repo, \
|
ownerhome, remove_fetched_repo, \
|
||||||
repo_list_dir, user_info, repo_set_access_property, repo_operation_file, \
|
repo_list_dir, user_info, repo_set_access_property, repo_operation_file, \
|
||||||
@@ -54,6 +54,7 @@ urlpatterns = patterns('',
|
|||||||
(r'^useradmin/(?P<user_id>[^/]+)/user/remove/$', user_remove),
|
(r'^useradmin/(?P<user_id>[^/]+)/user/remove/$', user_remove),
|
||||||
(r'^useradmin/activate/(?P<user_id>[^/]+)/$', activate_user),
|
(r'^useradmin/activate/(?P<user_id>[^/]+)/$', activate_user),
|
||||||
# (r'^avatar/', include('avatar.urls')),
|
# (r'^avatar/', include('avatar.urls')),
|
||||||
|
(r'^group/', include('seahub.group.urls')),
|
||||||
(r'^profile/', include('seahub.profile.urls')),
|
(r'^profile/', include('seahub.profile.urls')),
|
||||||
(r'^back/local/$', back_local),
|
(r'^back/local/$', back_local),
|
||||||
|
|
||||||
|
73
utils.py
Normal file
73
utils.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
from django.shortcuts import render_to_response
|
||||||
|
from django.template import RequestContext
|
||||||
|
|
||||||
|
from django.utils.hashcompat import sha_constructor
|
||||||
|
|
||||||
|
import time
|
||||||
|
import settings
|
||||||
|
|
||||||
|
def go_permission_error(request, msg=None):
|
||||||
|
"""
|
||||||
|
return permisson error page
|
||||||
|
|
||||||
|
"""
|
||||||
|
return render_to_response('permission_error.html', {
|
||||||
|
'error_msg': msg or u'权限错误',
|
||||||
|
}, context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
def go_error(request, msg=None):
|
||||||
|
"""
|
||||||
|
return normal error page
|
||||||
|
|
||||||
|
"""
|
||||||
|
return render_to_response('error.html', {
|
||||||
|
'error_msg': msg or u'内部错误',
|
||||||
|
}, context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
def list_to_string(l):
|
||||||
|
"""
|
||||||
|
return string of a list
|
||||||
|
|
||||||
|
"""
|
||||||
|
tmp_str = ''
|
||||||
|
for e in l[:-1]:
|
||||||
|
tmp_str = tmp_str + e + ', '
|
||||||
|
tmp_str = tmp_str + l[-1]
|
||||||
|
|
||||||
|
return tmp_str
|
||||||
|
|
||||||
|
def get_httpserver_root():
|
||||||
|
"""
|
||||||
|
Get seafile http server address and port from settings.py,
|
||||||
|
and cut out last '/'
|
||||||
|
|
||||||
|
"""
|
||||||
|
if settings.HTTP_SERVER_ROOT[-1] == '/':
|
||||||
|
http_server_root = settings.HTTP_SERVER_ROOT[:-1]
|
||||||
|
else:
|
||||||
|
http_server_root = settings.HTTP_SERVER_ROOT
|
||||||
|
return http_server_root
|
||||||
|
|
||||||
|
def get_ccnetapplet_root():
|
||||||
|
"""
|
||||||
|
Get ccnet applet address and port from settings.py,
|
||||||
|
and cut out last '/'
|
||||||
|
|
||||||
|
"""
|
||||||
|
if settings.CCNET_APPLET_ROOT[-1] == '/':
|
||||||
|
ccnet_applet_root = settings.CCNET_APPLET_ROOT[:-1]
|
||||||
|
else:
|
||||||
|
ccnet_applet_root = settings.CCNET_APPLET_ROOT
|
||||||
|
return ccnet_applet_root
|
||||||
|
|
||||||
|
def gen_token():
|
||||||
|
"""
|
||||||
|
Generate short token used for owner to access repo file
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
token = sha_constructor(settings.SECRET_KEY + unicode(time.time())).hexdigest()[::8]
|
||||||
|
return token
|
270
views.py
270
views.py
@@ -1,4 +1,5 @@
|
|||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
|
|
||||||
from django.http import HttpResponse, HttpResponseRedirect, Http404
|
from django.http import HttpResponse, HttpResponseRedirect, Http404
|
||||||
from django.shortcuts import render_to_response, redirect
|
from django.shortcuts import render_to_response, redirect
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
@@ -6,13 +7,15 @@ from django.template import RequestContext
|
|||||||
from auth.decorators import login_required
|
from auth.decorators import login_required
|
||||||
from django.db import IntegrityError
|
from django.db import IntegrityError
|
||||||
from django.views.decorators.csrf import csrf_protect
|
from django.views.decorators.csrf import csrf_protect
|
||||||
from auth.forms import AuthenticationForm, PasswordResetForm, SetPasswordForm, PasswordChangeForm
|
from auth.forms import AuthenticationForm, PasswordResetForm, SetPasswordForm, \
|
||||||
|
PasswordChangeForm
|
||||||
from auth.tokens import default_token_generator
|
from auth.tokens import default_token_generator
|
||||||
|
|
||||||
from pysearpc import SearpcError
|
from pysearpc import SearpcError
|
||||||
from seaserv import ccnet_rpc, get_groups, get_users, get_repos, \
|
from seaserv import ccnet_rpc, get_groups, get_users, get_repos, \
|
||||||
get_repo, get_commits, get_branches, \
|
get_repo, get_commits, get_branches, \
|
||||||
seafserv_threaded_rpc, seafserv_rpc, get_binding_peerids, get_ccnetuser
|
seafserv_threaded_rpc, seafserv_rpc, get_binding_peerids, get_ccnetuser, \
|
||||||
|
get_group_repoids
|
||||||
|
|
||||||
from seahub.share.models import GroupShare, UserShare
|
from seahub.share.models import GroupShare, UserShare
|
||||||
from seahub.share.forms import GroupAddRepoForm
|
from seahub.share.forms import GroupAddRepoForm
|
||||||
@@ -22,43 +25,62 @@ from urllib import quote
|
|||||||
|
|
||||||
from seahub.contacts.models import Contact
|
from seahub.contacts.models import Contact
|
||||||
|
|
||||||
|
from utils import go_permission_error, go_error, list_to_string, get_httpserver_root, \
|
||||||
|
get_ccnetapplet_root, gen_token
|
||||||
|
|
||||||
import stat
|
import stat
|
||||||
import time
|
|
||||||
import settings
|
import settings
|
||||||
|
|
||||||
def list_to_string(l):
|
|
||||||
tmp_str = ''
|
|
||||||
for e in l[:-1]:
|
|
||||||
tmp_str = tmp_str + e + ', '
|
|
||||||
tmp_str = tmp_str + l[-1]
|
|
||||||
|
|
||||||
return tmp_str
|
|
||||||
|
|
||||||
def get_httpserver_root():
|
def group_share_repo(request, repo_id, group_id, from_email):
|
||||||
# Get seafile http server address and port from settings.py,
|
"""
|
||||||
# and cut out last '/'
|
share a repo to a group
|
||||||
if settings.HTTP_SERVER_ROOT[-1] == '/':
|
|
||||||
http_server_root = settings.HTTP_SERVER_ROOT[:-1]
|
|
||||||
else:
|
|
||||||
http_server_root = settings.HTTP_SERVER_ROOT
|
|
||||||
return http_server_root
|
|
||||||
|
|
||||||
def get_ccnetapplet_root():
|
|
||||||
# Get ccnet applet address and port from settings.py,
|
|
||||||
# and cut out last '/'
|
|
||||||
if settings.CCNET_APPLET_ROOT[-1] == '/':
|
|
||||||
ccnet_applet_root = settings.CCNET_APPLET_ROOT[:-1]
|
|
||||||
else:
|
|
||||||
ccnet_applet_root = settings.CCNET_APPLET_ROOT
|
|
||||||
return ccnet_applet_root
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
# check whether group exists
|
||||||
|
group = ccnet_rpc.get_group(group_id)
|
||||||
|
if not group:
|
||||||
|
return go_error(request, u'共享失败:小组不存在')
|
||||||
|
|
||||||
def gen_token():
|
# check whether user belong to the group
|
||||||
# Generate short token used for owner to access repo file
|
joined = False
|
||||||
from django.utils.hashcompat import sha_constructor
|
groups = ccnet_rpc.get_groups(request.user.username)
|
||||||
token = sha_constructor(settings.SECRET_KEY + unicode(time.time())).hexdigest()[::8]
|
for group in groups:
|
||||||
return token
|
if group.props.id == group_id:
|
||||||
|
joined = True
|
||||||
|
if not joined:
|
||||||
|
return go_error(request, u'共享失败:未加入该小组')
|
||||||
|
|
||||||
|
if seafserv_threaded_rpc.group_share_repo(repo_id, group_id, from_email) != 0:
|
||||||
|
return go_error(request, u'共享失败:内部错误')
|
||||||
|
|
||||||
|
def group_unshare_repo(request, repo_id, group_id, from_email):
|
||||||
|
"""
|
||||||
|
unshare a repo to a group
|
||||||
|
|
||||||
|
"""
|
||||||
|
# check whether group exists
|
||||||
|
group = ccnet_rpc.get_group(group_id)
|
||||||
|
if not group:
|
||||||
|
return go_error(request, u'共享失败:小组不存在')
|
||||||
|
|
||||||
|
# check whether user belong to the group
|
||||||
|
joined = False
|
||||||
|
groups = ccnet_rpc.get_groups(from_email)
|
||||||
|
for group in groups:
|
||||||
|
if group.props.id == group_id:
|
||||||
|
joined = True
|
||||||
|
if not joined:
|
||||||
|
return go_error(request, u'共享失败:未加入该小组')
|
||||||
|
|
||||||
|
# check whether user is group staff or the one share the repo
|
||||||
|
if not ccnet_rpc.check_group_staff(group_id, from_email) and \
|
||||||
|
seafserv_threaded_rpc.get_group_repo_share_from(repo_id) != from_email:
|
||||||
|
return go_permission_error(request, u'取消共享失败:只有小组管理员或共享目录发布者有权取消共享')
|
||||||
|
|
||||||
|
if seafserv_threaded_rpc.group_unshare_repo(repo_id, group_id, from_email) != 0:
|
||||||
|
return go_error(request, u'共享失败:内部错误')
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def root(request):
|
def root(request):
|
||||||
return HttpResponseRedirect(reverse(myhome))
|
return HttpResponseRedirect(reverse(myhome))
|
||||||
@@ -84,75 +106,27 @@ def peers(request):
|
|||||||
'users': users,
|
'users': users,
|
||||||
}, context_instance=RequestContext(request))
|
}, context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
|
||||||
def groups(request):
|
|
||||||
groups = get_groups()
|
|
||||||
return render_to_response('groups.html', {
|
|
||||||
'groups': groups,
|
|
||||||
}, context_instance=RequestContext(request))
|
|
||||||
|
|
||||||
|
|
||||||
def group(request, group_id):
|
|
||||||
"""Show a group.
|
|
||||||
|
|
||||||
Login is not required, but permission check based on token should
|
|
||||||
be added later.
|
|
||||||
"""
|
|
||||||
|
|
||||||
group = get_group(group_id)
|
|
||||||
shared_repos = GroupShare.objects.filter(group_id=group_id)
|
|
||||||
return render_to_response('group.html', {
|
|
||||||
'group': group, 'shared_repos': shared_repos,
|
|
||||||
}, context_instance=RequestContext(request))
|
|
||||||
|
|
||||||
|
|
||||||
def group_add_repo(request, group_id):
|
|
||||||
"""Add a repo to a group"""
|
|
||||||
|
|
||||||
group = get_group(group_id)
|
|
||||||
if not group:
|
|
||||||
raise Http404
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
|
||||||
form = GroupAddRepoForm(request.POST)
|
|
||||||
if form.is_valid():
|
|
||||||
group_repo = GroupShare()
|
|
||||||
group_repo.group_id = group_id
|
|
||||||
group_repo.repo_id = form.cleaned_data['repo_id']
|
|
||||||
try:
|
|
||||||
group_repo.save()
|
|
||||||
except IntegrityError:
|
|
||||||
# catch the case repo added to group before
|
|
||||||
pass
|
|
||||||
return HttpResponseRedirect(reverse('view_group', args=[group_id]))
|
|
||||||
else:
|
|
||||||
form = GroupAddRepoForm()
|
|
||||||
|
|
||||||
return render_to_response("group_add_repo.html", {
|
|
||||||
'form': form, 'group': group
|
|
||||||
}, context_instance=RequestContext(request))
|
|
||||||
|
|
||||||
def validate_owner(request, repo_id):
|
def validate_owner(request, repo_id):
|
||||||
# check whether email in the request own the repo
|
# check whether email in the request own the repo
|
||||||
return seafserv_threaded_rpc.is_repo_owner(request.user.username, repo_id)
|
return seafserv_threaded_rpc.is_repo_owner(request.user.username, repo_id)
|
||||||
|
|
||||||
#def check_fetched_repo(request, repo_id):
|
|
||||||
# # check whether user has fetched the repo
|
|
||||||
# peerid_list = get_binding_peerids(request.user.username)
|
|
||||||
# for peer_id in peerid_list:
|
|
||||||
# repos = seafserv_threaded_rpc.list_fetched_repos(peer_id)
|
|
||||||
# for repo in repos:
|
|
||||||
# if cmp(repo.props.id, repo_id):
|
|
||||||
# return True
|
|
||||||
#
|
|
||||||
# return False
|
|
||||||
|
|
||||||
def check_shared_repo(request, repo_id):
|
def check_shared_repo(request, repo_id):
|
||||||
# check whether user has been shared this repo
|
"""
|
||||||
repos = seafserv_threaded_rpc.list_share_repos(request.user.username, 'to_email', -1, -1)
|
check whether user has been shared this repo or
|
||||||
|
the repo share to the groups user join
|
||||||
|
|
||||||
|
"""
|
||||||
|
repos = seafserv_threaded_rpc.list_share_repos(request.user.username, 'to_email', -1, -1)
|
||||||
for repo in repos:
|
for repo in repos:
|
||||||
if cmp(repo.props.id, repo_id) == 0:
|
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 True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
@@ -210,11 +184,13 @@ def repo(request, repo_id):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
# used to determin whether show repo content in repo.html
|
# used to determin whether show repo content in repo.html
|
||||||
# if a repo is shared to me, then I can view repo content on the web
|
# 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):
|
if check_shared_repo(request, repo_id):
|
||||||
share_to_me = True
|
share_to_me = True
|
||||||
else:
|
else:
|
||||||
share_to_me = False
|
share_to_me = False
|
||||||
|
|
||||||
return render_to_response('repo.html', {
|
return render_to_response('repo.html', {
|
||||||
"repo": repo,
|
"repo": repo,
|
||||||
"latest_commit": latest_commit,
|
"latest_commit": latest_commit,
|
||||||
@@ -256,15 +232,6 @@ def repo_history(request, repo_id):
|
|||||||
}, context_instance=RequestContext(request))
|
}, context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def repo_share(request, repo_id):
|
|
||||||
return render_to_response('repo_share.html', {
|
|
||||||
"repo": repo,
|
|
||||||
"commits": commits,
|
|
||||||
"branches": branches,
|
|
||||||
}, context_instance=RequestContext(request))
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def modify_token(request, repo_id):
|
def modify_token(request, repo_id):
|
||||||
if not validate_owner(request, repo_id):
|
if not validate_owner(request, repo_id):
|
||||||
@@ -280,9 +247,8 @@ def modify_token(request, repo_id):
|
|||||||
@login_required
|
@login_required
|
||||||
def remove_repo(request, repo_id):
|
def remove_repo(request, repo_id):
|
||||||
if not validate_owner(request, repo_id) and not request.user.is_staff:
|
if not validate_owner(request, repo_id) and not request.user.is_staff:
|
||||||
return render_to_response('permission_error.html', {
|
return go_permission_error(request, u'权限不足:无法查看该用户信息')
|
||||||
}, context_instance=RequestContext(request))
|
|
||||||
|
|
||||||
seafserv_threaded_rpc.remove_repo(repo_id)
|
seafserv_threaded_rpc.remove_repo(repo_id)
|
||||||
return HttpResponseRedirect(request.META['HTTP_REFERER'])
|
return HttpResponseRedirect(request.META['HTTP_REFERER'])
|
||||||
|
|
||||||
@@ -305,18 +271,24 @@ def myhome(request):
|
|||||||
|
|
||||||
# Repos that are share to me
|
# Repos that are share to me
|
||||||
in_repos = seafserv_threaded_rpc.list_share_repos(request.user.username, 'to_email', -1, -1)
|
in_repos = seafserv_threaded_rpc.list_share_repos(request.user.username, 'to_email', -1, -1)
|
||||||
|
|
||||||
|
# handle share repo request
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
output_msg = repo_add_share(request)
|
output_msg = repo_add_share(request)
|
||||||
|
|
||||||
|
# my contacts
|
||||||
contacts = Contact.objects.filter(user_email=email)
|
contacts = Contact.objects.filter(user_email=email)
|
||||||
|
|
||||||
|
# groups I join
|
||||||
|
groups = ccnet_rpc.get_groups(email)
|
||||||
|
|
||||||
return render_to_response('myhome.html', {
|
return render_to_response('myhome.html', {
|
||||||
"owned_repos": owned_repos,
|
"owned_repos": owned_repos,
|
||||||
"quota_usage": quota_usage,
|
"quota_usage": quota_usage,
|
||||||
"in_repos": in_repos,
|
"in_repos": in_repos,
|
||||||
"output_msg": output_msg,
|
"output_msg": output_msg,
|
||||||
"contacts": contacts,
|
"contacts": contacts,
|
||||||
|
"groups": groups,
|
||||||
}, context_instance=RequestContext(request))
|
}, context_instance=RequestContext(request))
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@@ -426,7 +398,13 @@ def repo_add_share(request):
|
|||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
from_email = request.user.username
|
from_email = request.user.username
|
||||||
repo_id = request.POST.get('share_repo_id', '')
|
repo_id = request.POST.get('share_repo_id', '')
|
||||||
to_email_list = request.POST.get('to_email', '').split(',')
|
|
||||||
|
# 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 = []
|
info_emails = []
|
||||||
err_emails = []
|
err_emails = []
|
||||||
for to_email in to_email_list:
|
for to_email in to_email_list:
|
||||||
@@ -434,16 +412,36 @@ def repo_add_share(request):
|
|||||||
if not to_email:
|
if not to_email:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if validate_emailuser(to_email) and validate_owner(request, repo_id):
|
# if to_email is user name, the format is: 'example@mail.com';
|
||||||
seafserv_threaded_rpc.add_share(repo_id, from_email, to_email, 'rw')
|
# if to_email is group, the format is 'group_name <creator@mail.com>'
|
||||||
info_emails.append(to_email)
|
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):
|
||||||
|
groups = ccnet_rpc.get_groups(request.user.username)
|
||||||
|
find = False
|
||||||
|
for group in groups:
|
||||||
|
if group.props.group_name == group_name and \
|
||||||
|
group_creator.find(group.props.creator_name) >= 0:
|
||||||
|
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:
|
else:
|
||||||
err_emails.append(to_email)
|
if validate_emailuser(to_email) and validate_owner(request, repo_id):
|
||||||
|
seafserv_threaded_rpc.add_share(repo_id, from_email, to_email, 'rw')
|
||||||
|
info_emails.append(to_email)
|
||||||
|
else:
|
||||||
|
err_emails.append(to_email)
|
||||||
|
|
||||||
if info_emails:
|
if info_emails:
|
||||||
output_msg['info_msg'] = u'共享给%s成功,' % list_to_string(info_emails)
|
output_msg['info_msg'] = u'共享给%s成功,' % list_to_string(info_emails)
|
||||||
if err_emails:
|
if err_emails:
|
||||||
output_msg['err_msg'] = u'共享给%s失败:用户不存在' % list_to_string(err_emails)
|
output_msg['err_msg'] = u'共享给%s失败:用户或组不存在' % list_to_string(err_emails)
|
||||||
|
|
||||||
return output_msg
|
return output_msg
|
||||||
|
|
||||||
@@ -451,8 +449,23 @@ def repo_add_share(request):
|
|||||||
def repo_list_share(request):
|
def repo_list_share(request):
|
||||||
username = request.user.username
|
username = request.user.username
|
||||||
|
|
||||||
|
# repos that are share to user
|
||||||
out_repos = seafserv_threaded_rpc.list_share_repos(username, 'from_email', -1, -1)
|
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)
|
||||||
|
group_id = group_repo.props.group_id
|
||||||
|
group = ccnet_rpc.get_group(int(group_id))
|
||||||
|
repo.props.shared_email = group.props.group_name
|
||||||
|
repo.gid = group_id
|
||||||
|
|
||||||
|
out_repos.append(repo)
|
||||||
|
|
||||||
return render_to_response('share_repos.html', {
|
return render_to_response('share_repos.html', {
|
||||||
"out_repos": out_repos,
|
"out_repos": out_repos,
|
||||||
}, context_instance=RequestContext(request))
|
}, context_instance=RequestContext(request))
|
||||||
@@ -480,18 +493,32 @@ def repo_download(request):
|
|||||||
ccnet_applet_root, repo_id, relay_id, quote_repo_name, enc)
|
ccnet_applet_root, repo_id, relay_id, quote_repo_name, enc)
|
||||||
|
|
||||||
return HttpResponseRedirect(redirect_url)
|
return HttpResponseRedirect(redirect_url)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def repo_remove_share(request):
|
def repo_remove_share(request):
|
||||||
repo_id = request.GET.get('repo_id', '')
|
repo_id = request.GET.get('repo_id', '')
|
||||||
if not validate_owner(request, repo_id):
|
if not validate_owner(request, repo_id):
|
||||||
raise Http404
|
return go_permission_error(request, u'取消共享失败:不是目录拥有者')
|
||||||
|
|
||||||
to_email = request.GET.get('to_email', '')
|
|
||||||
from_email = request.user.username
|
from_email = request.user.username
|
||||||
seafserv_threaded_rpc.remove_share(repo_id, from_email, to_email)
|
|
||||||
|
|
||||||
return HttpResponseRedirect(request.META['HTTP_REFERER'])
|
group_id = request.GET.get('gid')
|
||||||
|
|
||||||
|
# if request params don't have 'gid', then remove repos that share to
|
||||||
|
# to other person; else, remove repos that share to groups
|
||||||
|
if not group_id:
|
||||||
|
to_email = request.GET.get('to_email', '')
|
||||||
|
seafserv_threaded_rpc.remove_share(repo_id, from_email, to_email)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
group_id_int = int(group_id)
|
||||||
|
except:
|
||||||
|
return HttpResponseRedirect(request.META['HTTP_REFERER'])
|
||||||
|
|
||||||
|
group_unshare_repo(request, repo_id, group_id_int, from_email)
|
||||||
|
|
||||||
|
return HttpResponseRedirect(request.META['HTTP_REFERER'])
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def mypeers(request):
|
def mypeers(request):
|
||||||
@@ -553,8 +580,11 @@ def useradmin(request):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def user_info(request, email):
|
def user_info(request, email):
|
||||||
|
if request.user.username == email:
|
||||||
|
return HttpResponseRedirect(reverse(myhome))
|
||||||
|
|
||||||
if not request.user.is_staff:
|
if not request.user.is_staff:
|
||||||
raise Http404
|
return go_permission_error(request, u'权限不足:无法查看该用户信息')
|
||||||
|
|
||||||
user_dict = {}
|
user_dict = {}
|
||||||
owned_repos = []
|
owned_repos = []
|
||||||
|
Reference in New Issue
Block a user