mirror of
https://github.com/haiwen/seahub.git
synced 2025-08-12 12:22:13 +00:00
Let user specify ccnet user id when registration
This commit is contained in:
parent
e999ebe663
commit
2f7ee386e2
209
base/accounts.py
209
base/accounts.py
@ -1,5 +1,20 @@
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
from django.contrib.auth import authenticate, login
|
||||||
|
|
||||||
|
from django.contrib.sites.models import RequestSite
|
||||||
|
from django.contrib.sites.models import Site
|
||||||
|
|
||||||
|
from registration import signals
|
||||||
|
from registration.forms import RegistrationForm
|
||||||
|
from registration.models import RegistrationProfile
|
||||||
|
|
||||||
|
from django import forms
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from seahub.profile.models import UserProfile
|
||||||
|
|
||||||
|
|
||||||
class EmailOrUsernameModelBackend(object):
|
class EmailOrUsernameModelBackend(object):
|
||||||
def authenticate(self, username=None, password=None):
|
def authenticate(self, username=None, password=None):
|
||||||
@ -19,3 +34,197 @@ class EmailOrUsernameModelBackend(object):
|
|||||||
return User.objects.get(pk=user_id)
|
return User.objects.get(pk=user_id)
|
||||||
except User.DoesNotExist:
|
except User.DoesNotExist:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class RegistrationBackend(object):
|
||||||
|
"""
|
||||||
|
A registration backend which follows a simple workflow:
|
||||||
|
|
||||||
|
1. User signs up, inactive account is created.
|
||||||
|
|
||||||
|
2. Email is sent to user with activation link.
|
||||||
|
|
||||||
|
3. User clicks activation link, account is now active.
|
||||||
|
|
||||||
|
Using this backend requires that
|
||||||
|
|
||||||
|
* ``registration`` be listed in the ``INSTALLED_APPS`` setting
|
||||||
|
(since this backend makes use of models defined in this
|
||||||
|
application).
|
||||||
|
|
||||||
|
* The setting ``ACCOUNT_ACTIVATION_DAYS`` be supplied, specifying
|
||||||
|
(as an integer) the number of days from registration during
|
||||||
|
which a user may activate their account (after that period
|
||||||
|
expires, activation will be disallowed).
|
||||||
|
|
||||||
|
* The creation of the templates
|
||||||
|
``registration/activation_email_subject.txt`` and
|
||||||
|
``registration/activation_email.txt``, which will be used for
|
||||||
|
the activation email. See the notes for this backends
|
||||||
|
``register`` method for details regarding these templates.
|
||||||
|
|
||||||
|
Additionally, registration can be temporarily closed by adding the
|
||||||
|
setting ``REGISTRATION_OPEN`` and setting it to
|
||||||
|
``False``. Omitting this setting, or setting it to ``True``, will
|
||||||
|
be interpreted as meaning that registration is currently open and
|
||||||
|
permitted.
|
||||||
|
|
||||||
|
Internally, this is accomplished via storing an activation key in
|
||||||
|
an instance of ``registration.models.RegistrationProfile``. See
|
||||||
|
that model and its custom manager for full documentation of its
|
||||||
|
fields and supported operations.
|
||||||
|
|
||||||
|
"""
|
||||||
|
def register(self, request, **kwargs):
|
||||||
|
"""
|
||||||
|
Given a username, email address and password, register a new
|
||||||
|
user account, which will initially be inactive.
|
||||||
|
|
||||||
|
Along with the new ``User`` object, a new
|
||||||
|
``registration.models.RegistrationProfile`` will be created,
|
||||||
|
tied to that ``User``, containing the activation key which
|
||||||
|
will be used for this account.
|
||||||
|
|
||||||
|
An email will be sent to the supplied email address; this
|
||||||
|
email should contain an activation link. The email will be
|
||||||
|
rendered using two templates. See the documentation for
|
||||||
|
``RegistrationProfile.send_activation_email()`` for
|
||||||
|
information about these templates and the contexts provided to
|
||||||
|
them.
|
||||||
|
|
||||||
|
After the ``User`` and ``RegistrationProfile`` are created and
|
||||||
|
the activation email is sent, the signal
|
||||||
|
``registration.signals.user_registered`` will be sent, with
|
||||||
|
the new ``User`` as the keyword argument ``user`` and the
|
||||||
|
class of this backend as the sender.
|
||||||
|
|
||||||
|
"""
|
||||||
|
email, password = kwargs['email'], kwargs['password1']
|
||||||
|
username = email
|
||||||
|
if Site._meta.installed:
|
||||||
|
site = Site.objects.get_current()
|
||||||
|
else:
|
||||||
|
site = RequestSite(request)
|
||||||
|
new_user = RegistrationProfile.objects.create_inactive_user(username, email,
|
||||||
|
password, site)
|
||||||
|
|
||||||
|
userid = kwargs['userid']
|
||||||
|
profile = UserProfile(user=new_user, ccnet_user_id=userid)
|
||||||
|
profile.save()
|
||||||
|
|
||||||
|
signals.user_registered.send(sender=self.__class__,
|
||||||
|
user=new_user,
|
||||||
|
request=request)
|
||||||
|
return new_user
|
||||||
|
|
||||||
|
def activate(self, request, activation_key):
|
||||||
|
"""
|
||||||
|
Given an an activation key, look up and activate the user
|
||||||
|
account corresponding to that key (if possible).
|
||||||
|
|
||||||
|
After successful activation, the signal
|
||||||
|
``registration.signals.user_activated`` will be sent, with the
|
||||||
|
newly activated ``User`` as the keyword argument ``user`` and
|
||||||
|
the class of this backend as the sender.
|
||||||
|
|
||||||
|
"""
|
||||||
|
activated = RegistrationProfile.objects.activate_user(activation_key)
|
||||||
|
if activated:
|
||||||
|
signals.user_activated.send(sender=self.__class__,
|
||||||
|
user=activated,
|
||||||
|
request=request)
|
||||||
|
# login the user
|
||||||
|
activated.backend='django.contrib.auth.backends.ModelBackend'
|
||||||
|
login(request, activated)
|
||||||
|
|
||||||
|
return activated
|
||||||
|
|
||||||
|
def registration_allowed(self, request):
|
||||||
|
"""
|
||||||
|
Indicate whether account registration is currently permitted,
|
||||||
|
based on the value of the setting ``REGISTRATION_OPEN``. This
|
||||||
|
is determined as follows:
|
||||||
|
|
||||||
|
* If ``REGISTRATION_OPEN`` is not specified in settings, or is
|
||||||
|
set to ``True``, registration is permitted.
|
||||||
|
|
||||||
|
* If ``REGISTRATION_OPEN`` is both specified and set to
|
||||||
|
``False``, registration is not permitted.
|
||||||
|
|
||||||
|
"""
|
||||||
|
return getattr(settings, 'REGISTRATION_OPEN', True)
|
||||||
|
|
||||||
|
def get_form_class(self, request):
|
||||||
|
"""
|
||||||
|
Return the default form class used for user registration.
|
||||||
|
|
||||||
|
"""
|
||||||
|
return RegistrationForm
|
||||||
|
|
||||||
|
def post_registration_redirect(self, request, user):
|
||||||
|
"""
|
||||||
|
Return the name of the URL to redirect to after successful
|
||||||
|
user registration.
|
||||||
|
|
||||||
|
"""
|
||||||
|
return ('registration_complete', (), {})
|
||||||
|
|
||||||
|
def post_activation_redirect(self, request, user):
|
||||||
|
"""
|
||||||
|
Return the name of the URL to redirect to after successful
|
||||||
|
account activation.
|
||||||
|
|
||||||
|
"""
|
||||||
|
return ('myhome', (), {})
|
||||||
|
|
||||||
|
|
||||||
|
class RegistrationForm(forms.Form):
|
||||||
|
"""
|
||||||
|
Form for registering a new user account.
|
||||||
|
|
||||||
|
Validates that the requested email is not already in use, and
|
||||||
|
requires the password to be entered twice to catch typos.
|
||||||
|
"""
|
||||||
|
attrs_dict = { 'class': 'required' }
|
||||||
|
|
||||||
|
email = forms.EmailField(widget=forms.TextInput(attrs=dict(attrs_dict,
|
||||||
|
maxlength=75)),
|
||||||
|
label=_("Email address"))
|
||||||
|
userid = forms.RegexField(regex=r'^\w+$',
|
||||||
|
max_length=40,
|
||||||
|
widget=forms.TextInput(attrs=attrs_dict),
|
||||||
|
label=_("Username"),
|
||||||
|
error_messages={ 'invalid': _("This value must be of length 40") })
|
||||||
|
|
||||||
|
password1 = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict, render_value=False),
|
||||||
|
label=_("Password"))
|
||||||
|
password2 = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict, render_value=False),
|
||||||
|
label=_("Password (again)"))
|
||||||
|
|
||||||
|
def clean_email(self):
|
||||||
|
try:
|
||||||
|
user = User.objects.get(email__iexact=self.cleaned_data['email'])
|
||||||
|
except User.DoesNotExist:
|
||||||
|
return self.cleaned_data['email']
|
||||||
|
|
||||||
|
raise forms.ValidationError(_("A user with this email alread"))
|
||||||
|
|
||||||
|
|
||||||
|
def clean_userid(self):
|
||||||
|
if len(self.cleaned_data['userid']) != 40:
|
||||||
|
raise forms.ValidationError(_("Invalid user id."))
|
||||||
|
|
||||||
|
return self.cleaned_data['userid']
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
"""
|
||||||
|
Verifiy that the values entered into the two password fields
|
||||||
|
match. Note that an error here will end up in
|
||||||
|
``non_field_errors()`` because it doesn't apply to a single
|
||||||
|
field.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data:
|
||||||
|
if self.cleaned_data['password1'] != self.cleaned_data['password2']:
|
||||||
|
raise forms.ValidationError(_("The two password fields didn't match."))
|
||||||
|
return self.cleaned_data
|
||||||
|
19
base/middleware.py
Normal file
19
base/middleware.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
from seahub.profile.models import UserProfile
|
||||||
|
|
||||||
|
class UseridMiddleware(object):
|
||||||
|
|
||||||
|
def process_request(self, request):
|
||||||
|
if not request.user.is_authenticated():
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
profile = request.user.get_profile()
|
||||||
|
request.user.user_id = profile.ccnet_user_id
|
||||||
|
except UserProfile.DoesNotExist:
|
||||||
|
request.user.user_id = ''
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def process_response(self, request, response):
|
||||||
|
return response
|
37
base/registration_urls.py
Normal file
37
base/registration_urls.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
from django.conf.urls.defaults import *
|
||||||
|
from django.views.generic.simple import direct_to_template
|
||||||
|
|
||||||
|
from registration.views import activate
|
||||||
|
from registration.views import register
|
||||||
|
|
||||||
|
from seahub.base.accounts import RegistrationForm
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
url(r'^activate/complete/$',
|
||||||
|
direct_to_template,
|
||||||
|
{ 'template': 'registration/activation_complete.html' },
|
||||||
|
name='registration_activation_complete'),
|
||||||
|
# Activation keys get matched by \w+ instead of the more specific
|
||||||
|
# [a-fA-F0-9]{40} because a bad activation key should still get to the view;
|
||||||
|
# that way it can return a sensible "invalid key" message instead of a
|
||||||
|
# confusing 404.
|
||||||
|
url(r'^activate/(?P<activation_key>\w+)/$',
|
||||||
|
activate,
|
||||||
|
{ 'backend': 'seahub.base.accounts.RegistrationBackend', },
|
||||||
|
name='registration_activate'),
|
||||||
|
url(r'^register/$',
|
||||||
|
register,
|
||||||
|
{ 'backend': 'seahub.base.accounts.RegistrationBackend',
|
||||||
|
'form_class': RegistrationForm },
|
||||||
|
name='registration_register'),
|
||||||
|
url(r'^register/complete/$',
|
||||||
|
direct_to_template,
|
||||||
|
{ 'template': 'registration/registration_complete.html' },
|
||||||
|
name='registration_complete'),
|
||||||
|
url(r'^register/closed/$',
|
||||||
|
direct_to_template,
|
||||||
|
{ 'template': 'registration/registration_closed.html' },
|
||||||
|
name='registration_disallowed'),
|
||||||
|
(r'', include('registration.auth_urls')),
|
||||||
|
)
|
@ -39,6 +39,8 @@ table.default tr.first { background-color: #00FF00; }
|
|||||||
#header .top_operation a { font-weight:normal; font-size:13px; margin-left:2px; text-decoration: none; }
|
#header .top_operation a { font-weight:normal; font-size:13px; margin-left:2px; text-decoration: none; }
|
||||||
#header .top_operation a:hover { background:#0A0; color:#FFF; }
|
#header .top_operation a:hover { background:#0A0; color:#FFF; }
|
||||||
#logo { margin-top: 4px; }
|
#logo { margin-top: 4px; }
|
||||||
|
#user-info { float: right; font-size: 12px; color: #808; font-style:normal; margin-bottom:10px; }
|
||||||
|
#user-info span { color: #888; display:inline-block; width:60px; text-align:right; margin-right:5px; }
|
||||||
#header #ident { margin-top: 8px; float: right; font-size: 12px; }
|
#header #ident { margin-top: 8px; float: right; font-size: 12px; }
|
||||||
#header #ident p { color: #808; }
|
#header #ident p { color: #808; }
|
||||||
#header #ident label { color: #888; }
|
#header #ident label { color: #888; }
|
||||||
|
6
run-seahub.sh.template
Executable file
6
run-seahub.sh.template
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export CCNET_CONF_DIR=/home/plt/dev/ccnet/seafile/tests/basic/conf2
|
||||||
|
export PYTHONPATH=/opt/lib/python2.6/site-packages:thirdpart
|
||||||
|
|
||||||
|
./manage.py runserver
|
@ -66,6 +66,7 @@ MIDDLEWARE_CLASSES = (
|
|||||||
'django.middleware.csrf.CsrfResponseMiddleware',
|
'django.middleware.csrf.CsrfResponseMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'seahub.base.middleware.UseridMiddleware',
|
||||||
)
|
)
|
||||||
|
|
||||||
SITE_ROOT_URLCONF = 'seahub.urls'
|
SITE_ROOT_URLCONF = 'seahub.urls'
|
||||||
|
@ -38,6 +38,11 @@
|
|||||||
<div id="header">
|
<div id="header">
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
<a href="/home/" id="logo"><img src="{{ MEDIA_URL }}img/logo.png" title="Seafile" alt="Seafile logo" /></a>
|
<a href="/home/" id="logo"><img src="{{ MEDIA_URL }}img/logo.png" title="Seafile" alt="Seafile logo" /></a>
|
||||||
|
{% if request.user.is_authenticated %}
|
||||||
|
<div id="user-info">
|
||||||
|
<span>用户 ID:</span>{{user.user_id}}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="navs">
|
<div class="navs">
|
||||||
{% block nav %}
|
{% block nav %}
|
||||||
|
@ -1,16 +1,6 @@
|
|||||||
{% extends "myhome_base.html" %}
|
{% extends "myhome_base.html" %}
|
||||||
|
|
||||||
{% block right_panel %}
|
{% block right_panel %}
|
||||||
<h3>基本信息</h3>
|
|
||||||
<table class="default">
|
|
||||||
<tr>
|
|
||||||
<td>Seafile ID</td>
|
|
||||||
<td>{{ ccnet_user_id }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>我的文件盒</h3>
|
<h3>我的文件盒</h3>
|
||||||
<table class="repo-list default">
|
<table class="repo-list default">
|
||||||
|
@ -17,3 +17,4 @@
|
|||||||
-->
|
-->
|
||||||
</ul>
|
</ul>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
7
templates/registration/activate.html
Normal file
7
templates/registration/activate.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Create an account{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
激活码错误。
|
||||||
|
{% endblock %}
|
@ -3,10 +3,10 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>用户注册</h2>
|
<h2>用户注册</h2>
|
||||||
<form action="" method="post" class="reg">
|
<form action="" method="post" class="reg">
|
||||||
<label for="id_username">用户名:</label>
|
<label for="id_username">用户 ID:</label>
|
||||||
{{ form.username }}
|
{{ form.userid }}
|
||||||
{% if form.username.errors %}
|
{% if form.userid.errors %}
|
||||||
{{ form.username.errors }}
|
{{ form.userid.errors }}
|
||||||
{% endif %}<br />
|
{% endif %}<br />
|
||||||
<label for="id_email">邮箱:</label>
|
<label for="id_email">邮箱:</label>
|
||||||
{{ form.email }}<span>(我们将给您发送帐号激活邮件.)</span>
|
{{ form.email }}<span>(我们将给您发送帐号激活邮件.)</span>
|
||||||
|
@ -10,7 +10,6 @@ from django.template import RequestContext
|
|||||||
|
|
||||||
from registration.backends import get_backend
|
from registration.backends import get_backend
|
||||||
|
|
||||||
|
|
||||||
def activate(request, backend,
|
def activate(request, backend,
|
||||||
template_name='registration/activate.html',
|
template_name='registration/activate.html',
|
||||||
success_url=None, extra_context=None, **kwargs):
|
success_url=None, extra_context=None, **kwargs):
|
||||||
@ -191,7 +190,8 @@ def register(request, backend, success_url=None, form_class=None,
|
|||||||
else:
|
else:
|
||||||
return redirect(success_url)
|
return redirect(success_url)
|
||||||
else:
|
else:
|
||||||
form = form_class()
|
userid = request.REQUEST.get('userid', '')
|
||||||
|
form = form_class(initial={'userid': userid })
|
||||||
|
|
||||||
if extra_context is None:
|
if extra_context is None:
|
||||||
extra_context = {}
|
extra_context = {}
|
||||||
|
4
urls.py
4
urls.py
@ -18,11 +18,11 @@ urlpatterns = patterns('',
|
|||||||
# Uncomment the next line to enable the admin:
|
# Uncomment the next line to enable the admin:
|
||||||
(r'^admin/', include(admin.site.urls)),
|
(r'^admin/', include(admin.site.urls)),
|
||||||
|
|
||||||
(r'^accounts/', include('registration.backends.default.urls')),
|
(r'^accounts/', include('base.registration_urls')),
|
||||||
|
|
||||||
(r'^$', root),
|
(r'^$', root),
|
||||||
(r'^home/$', home),
|
(r'^home/$', home),
|
||||||
(r'^home/my/$', myhome),
|
url(r'^home/my/$', myhome, name='myhome'),
|
||||||
(r'^peers/$', peers),
|
(r'^peers/$', peers),
|
||||||
(r'^groups/$', groups),
|
(r'^groups/$', groups),
|
||||||
url(r'^group/(?P<group_id>[^/]+)/$', group, name='view_group'),
|
url(r'^group/(?P<group_id>[^/]+)/$', group, name='view_group'),
|
||||||
|
15
views.py
15
views.py
@ -150,19 +150,12 @@ def modify_token(request, repo_id):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def myhome(request):
|
def myhome(request):
|
||||||
ccnet_user_id = ""
|
|
||||||
try:
|
|
||||||
profile = request.user.get_profile()
|
|
||||||
ccnet_user_id = profile.ccnet_user_id
|
|
||||||
except UserProfile.DoesNotExist:
|
|
||||||
pass
|
|
||||||
|
|
||||||
owned_repos = []
|
owned_repos = []
|
||||||
if ccnet_user_id:
|
user_id = request.user.user_id
|
||||||
owned_repos = seafile_rpc.list_owned_repos(ccnet_user_id)
|
if user_id:
|
||||||
|
owned_repos = seafile_rpc.list_owned_repos(user_id)
|
||||||
|
|
||||||
return render_to_response('myhome.html', {
|
return render_to_response('myhome.html', {
|
||||||
"ccnet_user_id": ccnet_user_id,
|
|
||||||
"owned_repos": owned_repos,
|
"owned_repos": owned_repos,
|
||||||
}, context_instance=RequestContext(request))
|
}, context_instance=RequestContext(request))
|
||||||
|
|
||||||
@ -175,7 +168,7 @@ def mypeers(request):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def myrepos(request):
|
def myrepos(request):
|
||||||
cid = get_user_cid(request.user)
|
cid = request.user.user_id
|
||||||
owned_repos = seafile_rpc.list_owned_repos(cid)
|
owned_repos = seafile_rpc.list_owned_repos(cid)
|
||||||
|
|
||||||
return render_to_response('myrepos.html', {
|
return render_to_response('myrepos.html', {
|
||||||
|
Loading…
Reference in New Issue
Block a user