1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-01 23:20:51 +00:00

Add group feature

This commit is contained in:
xiez
2012-05-15 10:59:16 +08:00
parent 661439d83a
commit d63b068b2d
19 changed files with 631 additions and 195 deletions

View File

@@ -6,4 +6,8 @@ register = template.Library()
@register.filter(name='tsstr_sec')
def tsstr_sec(value):
"""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")

View File

@@ -1,33 +1,3 @@
from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
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)
# Create your models here.

View 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 %}

View 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
View 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
View 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'),
)

View File

@@ -1,4 +1,153 @@
# encoding: utf-8
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.http import HttpResponse, HttpResponseRedirect, Http404
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=[]))

View File

@@ -103,7 +103,7 @@ INSTALLED_APPS = (
'seahub.base',
'seahub.profile',
'seahub.contacts',
# 'seahub.group',
'seahub.group',
# 'seahub.share',
)

8
templates/error.html Normal file
View File

@@ -0,0 +1,8 @@
{% extends "myhome_base.html" %}
{% block title %}错误{% endblock %}
{% block main_panel %}
<p>{{ error_msg }}</p>
{% endblock %}

View File

@@ -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 &lt;group-id&gt; &lt;rendevous-id&gt;</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 %}

View File

@@ -70,7 +70,7 @@
{% endif %}
<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 />
<input id="share_repo_id" type="hidden" name="share_repo_id" value="" />
<p class="error hide">输入不能为空。</p>
@@ -88,6 +88,10 @@ $(function() {
contact_list.push('{{ contact.contact_email }}');
{% endfor %}
{% for group in groups %}
contact_list.push('{{ group.props.group_name }} <{{ group.props.creator_name }}>');
{% endfor %}
function split(val) {
return val.split(/,\s*/);
}

View File

@@ -10,7 +10,9 @@
<li>
<a href="{{ SITE_ROOT }}contacts/" {% block nav_contacts_class %}{% endblock %}>联系人</a>
</li>
<li>
<a href="{{ SITE_ROOT }}group/" {% block nav_group_class %}{% endblock %}>小组</a>
</li>
{% if request.user.is_staff %}
<li>
<a href="{{ SITE_ROOT }}seafadmin/" {% block nav_seafadmin_class %}{% endblock %}>目录管理</a>

View File

@@ -1,8 +1,8 @@
{% extends "myhome_base.html" %}
{% block title %}Permission Error{% endblock %}
{% block title %}权限错误{% endblock %}
{% block main_panel %}
<p>Permission Error.</p>
<p>{{ error_msg }}</p>
{% endblock %}

View File

@@ -18,7 +18,7 @@
<td>{{ repo.props.shared_email }}</td>
<td>{{ repo.props.desc }}</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>
</tr>
{% endfor %}

View File

@@ -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_binding_peerids
from service import get_ccnetuser
from service import get_group_repoids
from service import CCNET_CONF_PATH

View File

@@ -385,9 +385,31 @@ def get_binding_peerids(email):
except SearpcError:
return []
if not peer_ids:
return []
peerid_list = []
for peer_id in peer_ids.split("\n"):
if peer_id == '':
continue
peerid_list.append(peer_id)
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

View File

@@ -2,8 +2,8 @@ from django.conf.urls.defaults import *
from django.conf import settings
from django.views.generic.simple import direct_to_template
from seahub.views import root, peers, groups, myhome, \
repo, repo_history, group, modify_token, remove_repo, seafadmin, useradmin, \
from seahub.views import root, peers, myhome, \
repo, repo_history, modify_token, remove_repo, seafadmin, useradmin, \
role_add, role_remove, activate_user, user_add, user_remove, \
ownerhome, remove_fetched_repo, \
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/activate/(?P<user_id>[^/]+)/$', activate_user),
# (r'^avatar/', include('avatar.urls')),
(r'^group/', include('seahub.group.urls')),
(r'^profile/', include('seahub.profile.urls')),
(r'^back/local/$', back_local),

73
utils.py Normal file
View 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

258
views.py
View File

@@ -1,4 +1,5 @@
# encoding: utf-8
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.shortcuts import render_to_response, redirect
from django.core.urlresolvers import reverse
@@ -6,13 +7,15 @@ from django.template import RequestContext
from auth.decorators import login_required
from django.db import IntegrityError
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 pysearpc import SearpcError
from seaserv import ccnet_rpc, get_groups, get_users, get_repos, \
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.forms import GroupAddRepoForm
@@ -22,42 +25,61 @@ from urllib import quote
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 time
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 group_share_repo(request, repo_id, group_id, from_email):
"""
share a repo to a group
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
"""
# check whether group exists
group = ccnet_rpc.get_group(group_id)
if not group:
return go_error(request, u'共享失败:小组不存在')
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 user belong to the group
joined = False
groups = ccnet_rpc.get_groups(request.user.username)
for group in groups:
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 gen_token():
# Generate short token used for owner to access repo file
from django.utils.hashcompat import sha_constructor
token = sha_constructor(settings.SECRET_KEY + unicode(time.time())).hexdigest()[::8]
return token
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
def root(request):
@@ -84,75 +106,27 @@ def peers(request):
'users': users,
}, 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):
# check whether email in the request own the repo
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):
# 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:
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 False
@@ -210,11 +184,13 @@ def repo(request, repo_id):
pass
# 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):
share_to_me = True
else:
share_to_me = False
return render_to_response('repo.html', {
"repo": repo,
"latest_commit": latest_commit,
@@ -256,15 +232,6 @@ def repo_history(request, repo_id):
}, 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
def modify_token(request, repo_id):
if not validate_owner(request, repo_id):
@@ -280,8 +247,7 @@ def modify_token(request, repo_id):
@login_required
def remove_repo(request, repo_id):
if not validate_owner(request, repo_id) and not request.user.is_staff:
return render_to_response('permission_error.html', {
}, context_instance=RequestContext(request))
return go_permission_error(request, u'权限不足:无法查看该用户信息')
seafserv_threaded_rpc.remove_repo(repo_id)
return HttpResponseRedirect(request.META['HTTP_REFERER'])
@@ -306,17 +272,23 @@ def myhome(request):
# Repos that are share to me
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)
# groups I join
groups = ccnet_rpc.get_groups(email)
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,
}, context_instance=RequestContext(request))
@login_required
@@ -426,7 +398,13 @@ def repo_add_share(request):
if request.method == 'POST':
from_email = request.user.username
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 = []
err_emails = []
for to_email in to_email_list:
@@ -434,16 +412,36 @@ def repo_add_share(request):
if not to_email:
continue
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)
# 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):
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:
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:
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)
output_msg['err_msg'] = u'共享给%s失败:用户或组不存在' % list_to_string(err_emails)
return output_msg
@@ -451,8 +449,23 @@ def repo_add_share(request):
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)
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', {
"out_repos": out_repos,
}, context_instance=RequestContext(request))
@@ -481,15 +494,29 @@ def repo_download(request):
return HttpResponseRedirect(redirect_url)
@login_required
def repo_remove_share(request):
repo_id = request.GET.get('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
seafserv_threaded_rpc.remove_share(repo_id, from_email, to_email)
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'])
@@ -553,8 +580,11 @@ def useradmin(request):
@login_required
def user_info(request, email):
if request.user.username == email:
return HttpResponseRedirect(reverse(myhome))
if not request.user.is_staff:
raise Http404
return go_permission_error(request, u'权限不足:无法查看该用户信息')
user_dict = {}
owned_repos = []