mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-02 15:38:15 +00:00
Impove registration process and add user admin page
This commit is contained in:
81
HACKING
Normal file
81
HACKING
Normal file
@@ -0,0 +1,81 @@
|
||||
|
||||
About Registration
|
||||
==================
|
||||
|
||||
We use a customized registration process based on thirdpart/registration.
|
||||
The customization begins with:
|
||||
|
||||
(r'^accounts/', include('base.registration_urls'))
|
||||
|
||||
See base.registration_urls to follow the code.
|
||||
|
||||
Registration is seperated into two phase: registration and activation.
|
||||
|
||||
Registration Page with Form -----> Registration Complete Page
|
||||
(Notify User to check mail)
|
||||
|
|
||||
|
|
||||
V
|
||||
User check email and click activate link
|
||||
|
|
||||
|
|
||||
V
|
||||
User Home Page <----- Activate and login User.
|
||||
|
||||
|
||||
The registration app provide two view functions, i.e., `register` and `activate`.
|
||||
|
||||
### Register
|
||||
|
||||
The actual registration of the account will be delegated to the
|
||||
backend; it will be used as follows:
|
||||
|
||||
1. The backend's ``registration_allowed()`` method will be called,
|
||||
passing the ``HttpRequest``, to determine whether registration of
|
||||
an account is to be allowed; if not, a redirect is issued to the
|
||||
view corresponding to the named URL pattern
|
||||
``registration_disallowed``.
|
||||
|
||||
2. The form to use for account registration will be obtained by
|
||||
calling the backend's ``get_form_class()`` method, passing the
|
||||
``HttpRequest``.
|
||||
|
||||
3. If valid, the form's ``cleaned_data`` will be passed (as keyword
|
||||
arguments, and along with the ``HttpRequest``) to the backend's
|
||||
``register()`` method, which should return the new ``User`` object.
|
||||
|
||||
4. Upon successful registration, the backend's
|
||||
``post_registration_redirect()`` method will be called, passing the
|
||||
``HttpRequest`` and the new ``User``, to determine the URL to
|
||||
redirect the user to.
|
||||
|
||||
|
||||
We use a customized backend: seahub.base.accounts.RegistrationBackend
|
||||
|
||||
### Registration Process
|
||||
|
||||
Process 1:
|
||||
1. User register
|
||||
2. Admin activate
|
||||
3. User login and bind ccnet ID
|
||||
|
||||
To Enable this process, just set
|
||||
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
|
||||
EMAIL_FILE_PATH = '/tmp/app-messages'
|
||||
|
||||
|
||||
Process 2:
|
||||
1. User register and active account and bind ccnet ID
|
||||
|
||||
|
||||
About Authentication
|
||||
====================
|
||||
|
||||
We use a custimized authentication method. See
|
||||
seahub.base.accounts.EmailOrUsernameModelBackend
|
||||
|
||||
AUTHENTICATION_BACKENDS = (
|
||||
'seahub.base.accounts.EmailOrUsernameModelBackend',
|
||||
'django.contrib.auth.backends.ModelBackend'
|
||||
)
|
@@ -14,7 +14,7 @@ from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from seahub.profile.models import UserProfile
|
||||
|
||||
from seaserv import ccnet_rpc
|
||||
|
||||
class EmailOrUsernameModelBackend(object):
|
||||
def authenticate(self, username=None, password=None):
|
||||
@@ -109,8 +109,9 @@ class RegistrationBackend(object):
|
||||
password, site)
|
||||
|
||||
userid = kwargs['userid']
|
||||
profile = UserProfile(user=new_user, ccnet_user_id=userid)
|
||||
profile.save()
|
||||
if userid:
|
||||
profile = UserProfile(user=new_user, ccnet_user_id=userid)
|
||||
profile.save()
|
||||
|
||||
signals.user_registered.send(sender=self.__class__,
|
||||
user=new_user,
|
||||
@@ -136,6 +137,12 @@ class RegistrationBackend(object):
|
||||
# login the user
|
||||
activated.backend='django.contrib.auth.backends.ModelBackend'
|
||||
login(request, activated)
|
||||
try:
|
||||
profile = request.user.get_profile()
|
||||
if profile.ccnet_user_id:
|
||||
ccnet_rpc.add_client(ccnet_user_id)
|
||||
except:
|
||||
pass
|
||||
|
||||
return activated
|
||||
|
||||
@@ -192,7 +199,8 @@ class RegistrationForm(forms.Form):
|
||||
label=_("Email address"))
|
||||
userid = forms.RegexField(regex=r'^\w+$',
|
||||
max_length=40,
|
||||
widget=forms.TextInput(attrs=attrs_dict),
|
||||
required=False,
|
||||
widget=forms.TextInput(),
|
||||
label=_("Username"),
|
||||
error_messages={ 'invalid': _("This value must be of length 40") })
|
||||
|
||||
@@ -209,12 +217,10 @@ class RegistrationForm(forms.Form):
|
||||
|
||||
raise forms.ValidationError(_("A user with this email alread"))
|
||||
|
||||
|
||||
def clean_userid(self):
|
||||
if len(self.cleaned_data['userid']) != 40:
|
||||
if self.cleaned_data['userid'] and len(self.cleaned_data['userid']) != 40:
|
||||
raise forms.ValidationError(_("Invalid user id."))
|
||||
|
||||
return self.cleaned_data['userid']
|
||||
return self.cleaned_data['userid']
|
||||
|
||||
def clean(self):
|
||||
"""
|
||||
|
@@ -146,4 +146,6 @@ div.home-page h2 { font-style: italic; }
|
||||
.help-page { width: 550px; }
|
||||
.help-page img { display: block; margin: 20px auto; }
|
||||
|
||||
#id_repo_id { width:300px; }
|
||||
#id_repo_id { width:300px; }
|
||||
|
||||
span.role-remove-link { font-size: 9px; }
|
@@ -10,7 +10,7 @@
|
||||
<script type="text/javascript" src="{{ MEDIA_URL }}js/jquery.simplemodal.1.4.1.min.js"></script>
|
||||
|
||||
{% block extra_style %}{% endblock %}
|
||||
{% block extra_script %}{% endblock %}
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
@@ -96,5 +96,7 @@
|
||||
</div>
|
||||
|
||||
</div><!-- wrapper -->
|
||||
|
||||
{% block extra_script %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
@@ -4,16 +4,13 @@
|
||||
<li>
|
||||
<a href="{{ SITE_ROOT }}home/my/">我的页面</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ SITE_ROOT }}share/">共享</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ SITE_ROOT }}contacts/">联系人</a>
|
||||
</li>
|
||||
{% if request.user.is_staff %}
|
||||
<li>
|
||||
<a href="{{ SITE_ROOT }}seafadmin/">中继管理</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ SITE_ROOT }}useradmin/">用户管理</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a href="http://www.gonggeng.org/seasite/help/">使用帮助</a>
|
||||
|
@@ -3,8 +3,8 @@
|
||||
{% block main_panel %}
|
||||
<h2>用户注册</h2>
|
||||
<form action="" method="post" class="reg">
|
||||
<label for="id_username">用户 ID:</label>
|
||||
{{ form.userid }}
|
||||
<label for="id_username">Ccnet 公钥 ID:</label>
|
||||
{{ form.userid }} (可以以后再绑定)
|
||||
{% if form.userid.errors %}
|
||||
{{ form.userid.errors }}
|
||||
{% endif %}<br />
|
||||
|
59
templates/useradmin.html
Normal file
59
templates/useradmin.html
Normal file
@@ -0,0 +1,59 @@
|
||||
{% extends "myhome_base.html" %}
|
||||
|
||||
{% block right_panel %}
|
||||
|
||||
<h2>所有用户</h2>
|
||||
<table class="user-list default">
|
||||
<tr>
|
||||
<th>邮件</th>
|
||||
<td>激活</td>
|
||||
<td>Ccnet ID</td>
|
||||
<td>角色</td>
|
||||
<td>操作</td>
|
||||
</tr>
|
||||
|
||||
{% for user in users %}
|
||||
<tr>
|
||||
<td>{{ user.email }}</td>
|
||||
<td>{{ user.is_active }}</td>
|
||||
{% if user.profile %}
|
||||
<td>{{ user.profile.ccnet_user_id }}</td>
|
||||
<td>
|
||||
{% for role in user.role_list %}
|
||||
{{ role }}<span class="role-remove-link">(<a href="{{ SITE_ROOT }}useradmin/{{ user.profile.ccnet_user_id }}/role/remove/?role={{ role }}">删除</a>)</span>
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td><button class="add-role-btn" userid="{{ user.profile.ccnet_user_id }}" email="{{ user.email }}">添加角色</button></td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
<div class="hidden">
|
||||
|
||||
<form id="add-role-form" action="" method="post">
|
||||
<p><span id="user_email"></span> 的新角色 (即 MyClient 等):</p>
|
||||
<input id="id_role" type="text" name="role" /><br/>
|
||||
<input id="id_summit" type="submit" value="Submit" />
|
||||
</form>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_script %}
|
||||
<script>
|
||||
|
||||
$(function() {
|
||||
|
||||
$(".add-role-btn").each(function(index, item) {
|
||||
item.onclick = function() {
|
||||
url = "{{ SITE_ROOT }}useradmin/" + $(item).attr("userid") + "/role/add/";
|
||||
$("#add-role-form").attr( { action: url } );
|
||||
$("#add-role-form #user_email").html($(item).attr("email"));
|
||||
$("#add-role-form").modal({appendTo: "#main"});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
6
urls.py
6
urls.py
@@ -3,7 +3,8 @@ from django.conf import settings
|
||||
from django.views.generic.simple import direct_to_template
|
||||
|
||||
from seahub.views import root, peers, groups, myhome, \
|
||||
repo, group, modify_token, remove_repo, seafadmin
|
||||
repo, group, modify_token, remove_repo, seafadmin, useradmin, \
|
||||
role_add, role_remove
|
||||
|
||||
# Uncomment the next two lines to enable the admin:
|
||||
from django.contrib import admin
|
||||
@@ -30,6 +31,9 @@ urlpatterns = patterns('',
|
||||
(r'^repo/remove/(?P<repo_id>[^/]+)/$', remove_repo),
|
||||
|
||||
(r'^seafadmin/$', seafadmin),
|
||||
(r'^useradmin/$', useradmin),
|
||||
(r'^useradmin/(?P<user_id>[^/]+)/role/add/$', role_add),
|
||||
(r'^useradmin/(?P<user_id>[^/]+)/role/remove/$', role_remove),
|
||||
(r'^avatar/', include('avatar.urls')),
|
||||
(r'^profile/', include('seahub.profile.urls')),
|
||||
|
||||
|
47
views.py
47
views.py
@@ -4,6 +4,7 @@ from django.core.urlresolvers import reverse
|
||||
from django.template import RequestContext
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.db import IntegrityError
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
from seaserv import cclient, ccnet_rpc, get_groups, get_users, get_repos, \
|
||||
get_repo, get_commits, get_branches, \
|
||||
@@ -176,3 +177,49 @@ def seafadmin(request):
|
||||
'repos': repos,
|
||||
},
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
@login_required
|
||||
def useradmin(request):
|
||||
if not request.user.is_staff:
|
||||
raise Http404
|
||||
|
||||
users = User.objects.all()
|
||||
for user in users:
|
||||
try:
|
||||
user.profile = user.get_profile()
|
||||
user.ccnet_user = ccnet_rpc.get_user(user.profile.ccnet_user_id)
|
||||
user.role_list = user.ccnet_user.props.role_list.split(',')
|
||||
except UserProfile.DoesNotExist:
|
||||
user.profile = None
|
||||
user.ccnet_user = None
|
||||
|
||||
return render_to_response(
|
||||
'useradmin.html', {
|
||||
'users': users,
|
||||
},
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
|
||||
@login_required
|
||||
def role_add(request, user_id):
|
||||
if not request.user.is_staff:
|
||||
raise Http404
|
||||
|
||||
if request.method == 'POST':
|
||||
role = request.POST.get('role', '')
|
||||
if role and len(role) <= 16:
|
||||
ccnet_rpc.add_role(user_id, role)
|
||||
|
||||
return HttpResponseRedirect(request.META['HTTP_REFERER'])
|
||||
|
||||
|
||||
@login_required
|
||||
def role_remove(request, user_id):
|
||||
if not request.user.is_staff:
|
||||
raise Http404
|
||||
|
||||
role = request.REQUEST.get('role', '')
|
||||
if role and len(role) <= 16:
|
||||
ccnet_rpc.remove_role(user_id, role)
|
||||
|
||||
return HttpResponseRedirect(request.META['HTTP_REFERER'])
|
||||
|
Reference in New Issue
Block a user