1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-08 10:22:46 +00:00

Using ccnet EmailUser table instead of seahub auth_user table.

* Rewrite auth module, change user to emailuser.
* Remove site app, and remove EmailOrUsernameModelBackend.
This commit is contained in:
xiez
2012-04-11 19:48:20 +08:00
parent 0ccd1ea981
commit 8c9a5084e6
19 changed files with 296 additions and 189 deletions

View File

@@ -1,6 +1,11 @@
from django import forms
from django.utils.encoding import smart_str
from django.utils.hashcompat import md5_constructor, sha_constructor
from django.utils.translation import ugettext_lazy as _
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login from auth.models import User, Permission, get_hexdigest
from auth import authenticate, login
from django.contrib.sites.models import RequestSite from django.contrib.sites.models import RequestSite
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
@@ -9,32 +14,131 @@ from registration import signals
from registration.forms import RegistrationForm from registration.forms import RegistrationForm
from registration.models import RegistrationProfile from registration.models import RegistrationProfile
from django import forms from seaserv import ccnet_rpc, get_ccnetuser
from django.utils.translation import ugettext_lazy as _
from seaserv import ccnet_rpc class UserManager(object):
def create_user(self, username, password=None, is_staff=False, is_active=False):
ccnet_rpc.add_emailuser(username, password, is_staff, is_active)
class EmailOrUsernameModelBackend(object): ccnetuser = get_ccnetuser(username=username)
def authenticate(self, username=None, password=None): return ccnetuser
if '@' in username:
kwargs = {'email': username} def convert_to_ccnetuser(emailuser):
ccnetuser = CcnetUser(emailuser.get_email(),
raw_password='')
ccnetuser.id = emailuser.get_id()
ccnetuser.email = emailuser.get_email()
ccnetuser.password = emailuser.get_passwd()
ccnetuser.is_staff = emailuser.get_is_staff()
ccnetuser.is_active = emailuser.get_is_active()
ccnetuser.ctime = emailuser.get_ctime()
return ccnetuser
class CcnetUser(object):
is_staff = False
is_active = False
user_permissions = Permission()
objects = UserManager()
def __init__(self, username, raw_password):
self.username = username
self.raw_password = raw_password
def __unicode__(self):
return self.username
def validate_emailuser(self, email, raw_password):
self.set_password(raw_password)
return ccnet_rpc.validate_emailuser(email, raw_password)
def is_authenticated(self):
return True
def is_anonymous(self):
"""
Always returns False. This is a way of comparing User objects to
anonymous users.
"""
return False
def save(self):
emailuser = ccnet_rpc.get_emailuser(self.username)
if emailuser:
ccnet_rpc.update_emailuser(self.id, self.password, self.is_staff,
self.is_active)
else: else:
kwargs = {'username': username} self.objects.create_user(username=self.username,
try: password=self.raw_password,
user = User.objects.get(**kwargs) is_staff=self.is_staff,
if user.check_password(password): is_active=self.is_active)
return user
except User.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
def delete(self):
"""
Remove from ccnet EmailUser table and Binding table
"""
ccnet_rpc.remove_emailuser(self.username)
ccnet_rpc.remove_binding(self.username)
def get_and_delete_messages(self):
messages = []
return messages
def set_password(self, raw_password):
if raw_password is None:
self.set_unusable_password()
else:
algo = 'sha1'
hsh = get_hexdigest(algo, '', raw_password)
self.password = '%s' % hsh
def check_password(self, raw_password):
"""
Returns a boolean of whether the raw_password was correct. Handles
encryption formats behind the scenes.
"""
# Backwards-compatibility check. Older passwords won't include the
# algorithm or salt.
if '$' not in self.password:
is_correct = (self.password == get_hexdigest('sha1', '', raw_password))
return is_correct
return check_password(raw_password, self.password)
def email_user(self, subject, message, from_email=None):
"Sends an e-mail to this User."
from django.core.mail import send_mail
send_mail(subject, message, from_email, [self.username])
def has_perm(self, perm, obj=None):
"""
Returns True if the user has the specified permission. This method
queries all available auth backends, but returns immediately if any
backend returns True. Thus, a user who has permission from a single
auth backend is assumed to have permission in general. If an object
is provided, permissions for this specific object are checked.
"""
# Active superusers have all permissions.
if self.is_active and self.is_superuser:
return True
# Otherwise we need to check the backends.
return _user_has_perm(self, perm, obj)
def has_module_perms(self, app_label):
"""
Returns True if the user has any permissions in the given app
label. Uses pretty much the same logic as has_perm, above.
"""
# Active superusers have all permissions.
if self.is_active and self.is_superuser:
return True
from auth.models import _user_has_module_perms
return _user_has_module_perms(self, app_label)
class RegistrationBackend(object): class RegistrationBackend(object):
""" """
A registration backend which follows a simple workflow: A registration backend which follows a simple workflow:
@@ -104,11 +208,10 @@ class RegistrationBackend(object):
site = Site.objects.get_current() site = Site.objects.get_current()
else: else:
site = RequestSite(request) site = RequestSite(request)
new_user = RegistrationProfile.objects.create_inactive_user(username, email, new_user = RegistrationProfile.objects.create_inactive_user(username, email,
password, site, password, site,
send_email=settings.REGISTRATION_SEND_MAIL) send_email=settings.REGISTRATION_SEND_MAIL)
# save email and password to EmailUser table
ccnet_rpc.add_emailuser(email, password)
userid = kwargs['userid'] userid = kwargs['userid']
if userid: if userid:
@@ -136,8 +239,9 @@ class RegistrationBackend(object):
user=activated, user=activated,
request=request) request=request)
# login the user # login the user
activated.backend='django.contrib.auth.backends.ModelBackend' activated.backend='auth.backends.ModelBackend'
login(request, activated) login(request, activated)
# TODO: user.user_id should be change
try: try:
if request.user.user_id: if request.user.user_id:
ccnet_rpc.add_client(ccnet_user_id) ccnet_rpc.add_client(ccnet_user_id)
@@ -210,12 +314,12 @@ class RegistrationForm(forms.Form):
label=_("Password (again)")) label=_("Password (again)"))
def clean_email(self): def clean_email(self):
try: email = self.cleaned_data['email']
user = User.objects.get(email__iexact=self.cleaned_data['email']) emailuser = ccnet_rpc.get_emailuser(email)
except User.DoesNotExist: if not emailuser:
return self.cleaned_data['email'] return self.cleaned_data['email']
else:
raise forms.ValidationError(_("A user with this email already")) raise forms.ValidationError(_("A user with this email already"))
def clean_userid(self): def clean_userid(self):
if self.cleaned_data['userid'] and len(self.cleaned_data['userid']) != 40: if self.cleaned_data['userid'] and len(self.cleaned_data['userid']) != 40:
@@ -234,3 +338,4 @@ class RegistrationForm(forms.Form):
if self.cleaned_data['password1'] != self.cleaned_data['password2']: if self.cleaned_data['password1'] != self.cleaned_data['password2']:
raise forms.ValidationError(_("The two password fields didn't match.")) raise forms.ValidationError(_("The two password fields didn't match."))
return self.cleaned_data return self.cleaned_data

View File

@@ -65,7 +65,7 @@ MIDDLEWARE_CLASSES = (
'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.csrf.CsrfResponseMiddleware', 'django.middleware.csrf.CsrfResponseMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', 'auth.middleware.AuthenticationMiddleware',
'seahub.base.middleware.UseridMiddleware', 'seahub.base.middleware.UseridMiddleware',
) )
@@ -93,11 +93,11 @@ TEMPLATE_CONTEXT_PROCESSORS = (
INSTALLED_APPS = ( INSTALLED_APPS = (
'django.contrib.auth', 'auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
'django.contrib.sessions', 'django.contrib.sessions',
'django.contrib.sites', 'django.contrib.sites',
'django.contrib.admin', # 'django.contrib.admin',
'registration', 'registration',
# 'avatar', # 'avatar',
'seahub.base', 'seahub.base',
@@ -108,8 +108,7 @@ INSTALLED_APPS = (
) )
AUTHENTICATION_BACKENDS = ( AUTHENTICATION_BACKENDS = (
'seahub.base.accounts.EmailOrUsernameModelBackend', 'auth.backends.ModelBackend',
'django.contrib.auth.backends.ModelBackend'
) )
ACCOUNT_ACTIVATION_DAYS = 7 ACCOUNT_ACTIVATION_DAYS = 7

View File

@@ -20,9 +20,11 @@
{% if request.user.is_authenticated %} {% if request.user.is_authenticated %}
欢迎, {{ request.user }} 欢迎, {{ request.user }}
<a href="{{ SITE_ROOT }}profile/">设置</a> <a href="{{ SITE_ROOT }}profile/">设置</a>
<!--
{% if request.user.is_staff %} {% if request.user.is_staff %}
<a href="{{ SITE_ROOT }}admin/">管理</a> <a href="{{ SITE_ROOT }}admin/">管理</a>
{% endif %} {% endif %}
-->
<a href="{{ SITE_ROOT }}accounts/logout/">退出</a> <a href="{{ SITE_ROOT }}accounts/logout/">退出</a>
{% else %} {% else %}
<a href="{{ SITE_ROOT }}accounts/login/">登录</a> <a href="{{ SITE_ROOT }}accounts/login/">登录</a>
@@ -85,7 +87,7 @@
</div> </div>
</div> </div>
<div id="footer" class="ovhd"> <div id="footer" class="ovhd">
<p class="fleft">Copyright © 2012 海文网络. All rights reserved.</p> <p class="fleft">Copyright © 2012 海文互知. All rights reserved.</p>
<p class="fright">Contact | About</p> <p class="fright">Contact | About</p>
</div> </div>

View File

@@ -4,7 +4,7 @@
{% trans "Please go to the following page and choose a new password:" %} {% trans "Please go to the following page and choose a new password:" %}
{% block reset_link %} {% block reset_link %}
{{ protocol }}://{{ domain }}{% url django.contrib.auth.views.password_reset_confirm uidb36=uid, token=token %} {{ protocol }}://{{ domain }}{% url auth.views.password_reset_confirm uidb36=uid, token=token %}
{% endblock %} {% endblock %}
{% trans "Your username, in case you've forgotten:" %} {{ user.username }} {% trans "Your username, in case you've forgotten:" %} {{ user.username }}

View File

@@ -22,11 +22,11 @@
{% for user in users %} {% for user in users %}
<tr> <tr>
<td>{{ user.email }}</td> <td>{{ user.props.email }}</td>
{% if user.is_active %} {% if user.props.is_active %}
<td>已激活</td> <td>已激活</td>
{% else %} {% else %}
<td><button data="{{ SITE_ROOT }}useradmin/activate/{{ user.id }}/" class="activate">激活</button></td> <td><button data="{{ SITE_ROOT }}useradmin/activate/{{ user.props.id }}/" class="activate">激活</button></td>
{% endif %} {% endif %}
{% if user.userid_list %} {% if user.userid_list %}
<td>{{ user.userid_list|first }}</td> <td>{{ user.userid_list|first }}</td>
@@ -42,7 +42,7 @@
{% if user.profile %} {% if user.profile %}
<!-- <button class="add-role-btn" userid="{{ user.profile.ccnet_user_id }}" email="{{ user.email }}">添加角色</button> --> <!-- <button class="add-role-btn" userid="{{ user.profile.ccnet_user_id }}" email="{{ user.email }}">添加角色</button> -->
{% endif %} {% endif %}
<button class="remove-user-btn" data="{{ SITE_ROOT }}useradmin/{{ user.id }}/user/remove/">删除</button> <button class="remove-user-btn" data="{{ SITE_ROOT }}useradmin/{{ user.props.id }}/user/remove/">删除</button>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}

View File

@@ -66,17 +66,17 @@ def login(request, user):
user = request.user user = request.user
# TODO: It would be nice to support different login methods, like signed cookies. # TODO: It would be nice to support different login methods, like signed cookies.
user.last_login = datetime.datetime.now() user.last_login = datetime.datetime.now()
user.save()
if SESSION_KEY in request.session: if SESSION_KEY in request.session:
if request.session[SESSION_KEY] != user.id: if request.session[SESSION_KEY] != user.username:
# To avoid reusing another user's session, create a new, empty # To avoid reusing another user's session, create a new, empty
# session if the existing session corresponds to a different # session if the existing session corresponds to a different
# authenticated user. # authenticated user.
request.session.flush() request.session.flush()
else: else:
request.session.cycle_key() request.session.cycle_key()
request.session[SESSION_KEY] = user.id
request.session[SESSION_KEY] = user.username
request.session[BACKEND_SESSION_KEY] = user.backend request.session[BACKEND_SESSION_KEY] = user.backend
if hasattr(request, 'user'): if hasattr(request, 'user'):
request.user = user request.user = user
@@ -88,16 +88,16 @@ def logout(request):
""" """
request.session.flush() request.session.flush()
if hasattr(request, 'user'): if hasattr(request, 'user'):
from django.contrib.auth.models import AnonymousUser from auth.models import AnonymousUser
request.user = AnonymousUser() request.user = AnonymousUser()
def get_user(request): def get_user(request):
from django.contrib.auth.models import AnonymousUser from auth.models import AnonymousUser
try: try:
user_id = request.session[SESSION_KEY] username = request.session[SESSION_KEY]
backend_path = request.session[BACKEND_SESSION_KEY] backend_path = request.session[BACKEND_SESSION_KEY]
backend = load_backend(backend_path) backend = load_backend(backend_path)
user = backend.get_user(user_id) or AnonymousUser() user = backend.get_user(username) or AnonymousUser()
except KeyError: except KeyError:
user = AnonymousUser() user = AnonymousUser()
return user return user

View File

@@ -1,5 +1,8 @@
from django.db import connection from django.db import connection
from django.contrib.auth.models import User, Permission from auth.models import User, Permission
from seahub.base.accounts import CcnetUser
from seaserv import ccnet_rpc, get_ccnetuser
class ModelBackend(object): class ModelBackend(object):
@@ -12,12 +15,11 @@ class ModelBackend(object):
# TODO: Model, login attribute name and password attribute name should be # TODO: Model, login attribute name and password attribute name should be
# configurable. # configurable.
def authenticate(self, username=None, password=None): def authenticate(self, username=None, password=None):
try: ccnetuser = get_ccnetuser(username=username)
user = User.objects.get(username=username) if ccnetuser and ccnetuser.check_password(password):
if user.check_password(password): return ccnetuser
return user
except User.DoesNotExist: return None
return None
def get_group_permissions(self, user_obj): def get_group_permissions(self, user_obj):
""" """
@@ -51,11 +53,8 @@ class ModelBackend(object):
return True return True
return False return False
def get_user(self, user_id): def get_user(self, username):
try: return get_ccnetuser(username=username)
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
class RemoteUserBackend(ModelBackend): class RemoteUserBackend(ModelBackend):

View File

@@ -3,7 +3,7 @@ try:
except ImportError: except ImportError:
from django.utils.functional import update_wrapper, wraps # Python 2.4 fallback. from django.utils.functional import update_wrapper, wraps # Python 2.4 fallback.
from django.contrib.auth import REDIRECT_FIELD_NAME from auth import REDIRECT_FIELD_NAME
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.utils.decorators import available_attrs from django.utils.decorators import available_attrs
from django.utils.http import urlquote from django.utils.http import urlquote

View File

@@ -1,12 +1,15 @@
from django.contrib.auth.models import User from auth.models import User
from django.contrib.auth import authenticate from auth import authenticate
from django.contrib.auth.tokens import default_token_generator from auth.tokens import default_token_generator
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.template import Context, loader from django.template import Context, loader
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.http import int_to_base36 from django.utils.http import int_to_base36
from seaserv import get_ccnetuser
class UserCreationForm(forms.ModelForm): class UserCreationForm(forms.ModelForm):
""" """
A form that creates a user, with no privileges, from the given username and password. A form that creates a user, with no privileges, from the given username and password.
@@ -111,9 +114,11 @@ class PasswordResetForm(forms.Form):
Validates that a user exists with the given e-mail address. Validates that a user exists with the given e-mail address.
""" """
email = self.cleaned_data["email"] email = self.cleaned_data["email"]
self.users_cache = User.objects.filter(email__iexact=email)
if len(self.users_cache) == 0: self.users_cache = get_ccnetuser(username=email)
if not self.users_cache:
raise forms.ValidationError(_("That e-mail address doesn't have an associated user account. Are you sure you've registered?")) raise forms.ValidationError(_("That e-mail address doesn't have an associated user account. Are you sure you've registered?"))
return email return email
def save(self, domain_override=None, email_template_name='registration/password_reset_email.html', def save(self, domain_override=None, email_template_name='registration/password_reset_email.html',
@@ -122,25 +127,27 @@ class PasswordResetForm(forms.Form):
Generates a one-use only link for resetting password and sends to the user Generates a one-use only link for resetting password and sends to the user
""" """
from django.core.mail import send_mail from django.core.mail import send_mail
for user in self.users_cache:
if not domain_override: ccnetuser = self.users_cache
current_site = Site.objects.get_current() if not domain_override:
site_name = current_site.name current_site = Site.objects.get_current()
domain = current_site.domain site_name = current_site.name
else: domain = current_site.domain
site_name = domain = domain_override else:
t = loader.get_template(email_template_name) site_name = domain = domain_override
c = { t = loader.get_template(email_template_name)
'email': user.email,
'domain': domain, c = {
'site_name': site_name, 'email': ccnetuser.username,
'uid': int_to_base36(user.id), 'domain': domain,
'user': user, 'site_name': site_name,
'token': token_generator.make_token(user), 'uid': int_to_base36(ccnetuser.id),
'protocol': use_https and 'https' or 'http', 'user': ccnetuser,
} 'token': token_generator.make_token(ccnetuser),
send_mail(_("Password reset on %s") % site_name, 'protocol': use_https and 'https' or 'http',
t.render(Context(c)), None, [user.email]) }
send_mail(_("Password reset on %s") % site_name,
t.render(Context(c)), None, [ccnetuser.username])
class SetPasswordForm(forms.Form): class SetPasswordForm(forms.Form):
""" """
@@ -152,6 +159,7 @@ class SetPasswordForm(forms.Form):
def __init__(self, user, *args, **kwargs): def __init__(self, user, *args, **kwargs):
self.user = user self.user = user
super(SetPasswordForm, self).__init__(*args, **kwargs) super(SetPasswordForm, self).__init__(*args, **kwargs)
def clean_new_password2(self): def clean_new_password2(self):

View File

@@ -5,7 +5,7 @@ from django.core.exceptions import ImproperlyConfigured
class LazyUser(object): class LazyUser(object):
def __get__(self, request, obj_type=None): def __get__(self, request, obj_type=None):
if not hasattr(request, '_cached_user'): if not hasattr(request, '_cached_user'):
from django.contrib.auth import get_user from auth import get_user
request._cached_user = get_user(request) request._cached_user = get_user(request)
return request._cached_user return request._cached_user

View File

@@ -1,7 +1,7 @@
import datetime import datetime
import urllib import urllib
from django.contrib import auth import auth
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.db import models from django.db import models
from django.db.models.manager import EmptyManager from django.db.models.manager import EmptyManager

View File

@@ -51,9 +51,12 @@ class PasswordResetTokenGenerator(object):
# invalid as soon as it is used. # invalid as soon as it is used.
# We limit the hash to 20 chars to keep URL short # We limit the hash to 20 chars to keep URL short
from django.utils.hashcompat import sha_constructor from django.utils.hashcompat import sha_constructor
import datetime
ctime = datetime.datetime.fromtimestamp(user.ctime/1000000)
hash = sha_constructor(settings.SECRET_KEY + unicode(user.id) + hash = sha_constructor(settings.SECRET_KEY + unicode(user.id) +
user.password + user.last_login.strftime('%Y-%m-%d %H:%M:%S') + user.password + ctime.strftime('%Y-%m-%d %H:%M:%S') +
unicode(timestamp)).hexdigest()[::2] unicode(timestamp)).hexdigest()[::2]
return "%s-%s" % (ts_b36, hash) return "%s-%s" % (ts_b36, hash)
def _num_days(self, dt): def _num_days(self, dt):

View File

@@ -1,12 +1,6 @@
import re import re
from django.conf import settings from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME
# Avoid shadowing the login() view below. # Avoid shadowing the login() view below.
from django.contrib.auth import login as auth_login
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.forms import PasswordResetForm, SetPasswordForm, PasswordChangeForm
from django.contrib.auth.tokens import default_token_generator
from django.views.decorators.csrf import csrf_protect from django.views.decorators.csrf import csrf_protect
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.shortcuts import render_to_response, get_object_or_404 from django.shortcuts import render_to_response, get_object_or_404
@@ -15,9 +9,18 @@ from django.http import HttpResponseRedirect, Http404
from django.template import RequestContext from django.template import RequestContext
from django.utils.http import urlquote, base36_to_int from django.utils.http import urlquote, base36_to_int
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.contrib.auth.models import User
from django.views.decorators.cache import never_cache from django.views.decorators.cache import never_cache
from auth import REDIRECT_FIELD_NAME
from auth import login as auth_login
from auth.decorators import login_required
from auth.forms import AuthenticationForm
from auth.forms import PasswordResetForm, SetPasswordForm, PasswordChangeForm
from auth.tokens import default_token_generator
from auth.models import User
from seaserv import get_ccnetuser
@csrf_protect @csrf_protect
@never_cache @never_cache
def login(request, template_name='registration/login.html', def login(request, template_name='registration/login.html',
@@ -40,10 +43,11 @@ def login(request, template_name='registration/login.html',
# question mark. # question mark.
elif '//' in redirect_to and re.match(r'[^\?]*//', redirect_to): elif '//' in redirect_to and re.match(r'[^\?]*//', redirect_to):
redirect_to = settings.LOGIN_REDIRECT_URL redirect_to = settings.LOGIN_REDIRECT_URL
# Okay, security checks complete. Log the user in. # Okay, security checks complete. Log the user in.
auth_login(request, form.get_user()) auth_login(request, form.get_user())
if request.session.test_cookie_worked(): if request.session.test_cookie_worked():
request.session.delete_test_cookie() request.session.delete_test_cookie()
@@ -68,7 +72,7 @@ def login(request, template_name='registration/login.html',
def logout(request, next_page=None, template_name='registration/logged_out.html', redirect_field_name=REDIRECT_FIELD_NAME): def logout(request, next_page=None, template_name='registration/logged_out.html', redirect_field_name=REDIRECT_FIELD_NAME):
"Logs out the user and displays 'You are logged out' message." "Logs out the user and displays 'You are logged out' message."
from django.contrib.auth import logout from auth import logout
logout(request) logout(request)
if next_page is None: if next_page is None:
redirect_to = request.REQUEST.get(redirect_field_name, '') redirect_to = request.REQUEST.get(redirect_field_name, '')
@@ -107,7 +111,7 @@ def password_reset(request, is_admin_site=False, template_name='registration/pas
password_reset_form=PasswordResetForm, token_generator=default_token_generator, password_reset_form=PasswordResetForm, token_generator=default_token_generator,
post_reset_redirect=None): post_reset_redirect=None):
if post_reset_redirect is None: if post_reset_redirect is None:
post_reset_redirect = reverse('django.contrib.auth.views.password_reset_done') post_reset_redirect = reverse('auth.views.password_reset_done')
if request.method == "POST": if request.method == "POST":
form = password_reset_form(request.POST) form = password_reset_form(request.POST)
if form.is_valid(): if form.is_valid():
@@ -141,19 +145,22 @@ def password_reset_confirm(request, uidb36=None, token=None, template_name='regi
""" """
assert uidb36 is not None and token is not None # checked by URLconf assert uidb36 is not None and token is not None # checked by URLconf
if post_reset_redirect is None: if post_reset_redirect is None:
post_reset_redirect = reverse('django.contrib.auth.views.password_reset_complete') post_reset_redirect = reverse('auth.views.password_reset_complete')
try: try:
uid_int = base36_to_int(uidb36) uid_int = base36_to_int(uidb36)
except ValueError: except ValueError:
raise Http404 raise Http404
user = get_object_or_404(User, id=uid_int) ccnetuser = get_ccnetuser(userid=uid_int)
if not ccnetuser:
raise Http404
context_instance = RequestContext(request) context_instance = RequestContext(request)
if token_generator.check_token(user, token): if token_generator.check_token(ccnetuser, token):
context_instance['validlink'] = True context_instance['validlink'] = True
if request.method == 'POST': if request.method == 'POST':
form = set_password_form(user, request.POST) form = set_password_form(ccnetuser, request.POST)
if form.is_valid(): if form.is_valid():
form.save() form.save()
return HttpResponseRedirect(post_reset_redirect) return HttpResponseRedirect(post_reset_redirect)
@@ -174,7 +181,7 @@ def password_reset_complete(request, template_name='registration/password_reset_
def password_change(request, template_name='registration/password_change_form.html', def password_change(request, template_name='registration/password_change_form.html',
post_change_redirect=None, password_change_form=PasswordChangeForm): post_change_redirect=None, password_change_form=PasswordChangeForm):
if post_change_redirect is None: if post_change_redirect is None:
post_change_redirect = reverse('django.contrib.auth.views.password_change_done') post_change_redirect = reverse('auth.views.password_change_done')
if request.method == "POST": if request.method == "POST":
form = password_change_form(user=request.user, data=request.POST) form = password_change_form(user=request.user, data=request.POST)
if form.is_valid(): if form.is_valid():

View File

@@ -25,10 +25,7 @@ consult a specific backend's documentation for details.
from django.conf.urls.defaults import * from django.conf.urls.defaults import *
from django.contrib.auth import views as auth_views from auth import views as auth_views
from seahub.views import password_change
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'^login/$', url(r'^login/$',
@@ -40,7 +37,7 @@ urlpatterns = patterns('',
{'template_name': 'registration/logout.html'}, {'template_name': 'registration/logout.html'},
name='auth_logout'), name='auth_logout'),
url(r'^password/change/$', url(r'^password/change/$',
password_change, auth_views.password_change,
name='auth_password_change'), name='auth_password_change'),
url(r'^password/change/done/$', url(r'^password/change/done/$',
auth_views.password_change_done, auth_views.password_change_done,

View File

@@ -3,13 +3,15 @@ import random
import re import re
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User from auth.models import User
from django.db import models from django.db import models
from django.db import transaction from django.db import transaction
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.utils.hashcompat import sha_constructor from django.utils.hashcompat import sha_constructor
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from seaserv import ccnet_rpc, get_ccnetuser
SHA1_RE = re.compile('^[a-f0-9]{40}$') SHA1_RE = re.compile('^[a-f0-9]{40}$')
@@ -51,12 +53,13 @@ class RegistrationManager(models.Manager):
except self.model.DoesNotExist: except self.model.DoesNotExist:
return False return False
if not profile.activation_key_expired(): if not profile.activation_key_expired():
user = profile.user # Activate emailuser
user.is_active = True ccnetuser = get_ccnetuser(userid=profile.emailuser_id)
user.save() ccnetuser.is_active = True
ccnetuser.save()
profile.activation_key = self.model.ACTIVATED profile.activation_key = self.model.ACTIVATED
profile.save() profile.save()
return user return ccnetuser
return False return False
def create_inactive_user(self, username, email, password, def create_inactive_user(self, username, email, password,
@@ -70,16 +73,19 @@ class RegistrationManager(models.Manager):
user. To disable this, pass ``send_email=False``. user. To disable this, pass ``send_email=False``.
""" """
new_user = User.objects.create_user(username, email, password)
new_user.is_active = False
new_user.save()
registration_profile = self.create_profile(new_user) from seahub.base.accounts import CcnetUser
ccnetuser = CcnetUser.objects.create_user(username, password, False, False)
ccnetuser.is_active = False
ccnetuser.save()
registration_profile = self.create_profile(ccnetuser)
if send_email: if send_email:
registration_profile.send_activation_email(site) registration_profile.send_activation_email(site)
return new_user return ccnetuser
create_inactive_user = transaction.commit_on_success(create_inactive_user) create_inactive_user = transaction.commit_on_success(create_inactive_user)
def create_profile(self, user): def create_profile(self, user):
@@ -97,7 +103,7 @@ class RegistrationManager(models.Manager):
if isinstance(username, unicode): if isinstance(username, unicode):
username = username.encode('utf-8') username = username.encode('utf-8')
activation_key = sha_constructor(salt+username).hexdigest() activation_key = sha_constructor(salt+username).hexdigest()
return self.create(user=user, return self.create(emailuser_id=user.id,
activation_key=activation_key) activation_key=activation_key)
def delete_expired_users(self): def delete_expired_users(self):
@@ -142,10 +148,9 @@ class RegistrationManager(models.Manager):
""" """
for profile in self.all(): for profile in self.all():
if profile.activation_key_expired(): if profile.activation_key_expired():
user = profile.user ccnetuser = get_ccnetuser(userid=profile.emailuser_id)
if not user.is_active: if not ccnetuser.is_active:
user.delete() ccnet_rpc.remove_emailuser(ccnetuser.username)
class RegistrationProfile(models.Model): class RegistrationProfile(models.Model):
""" """
@@ -165,7 +170,8 @@ class RegistrationProfile(models.Model):
""" """
ACTIVATED = u"ALREADY_ACTIVATED" ACTIVATED = u"ALREADY_ACTIVATED"
user = models.ForeignKey(User, unique=True, verbose_name=_('user')) # user = models.ForeignKey(User, unique=True, verbose_name=_('user'))
emailuser_id = models.IntegerField()
activation_key = models.CharField(_('activation key'), max_length=40) activation_key = models.CharField(_('activation key'), max_length=40)
objects = RegistrationManager() objects = RegistrationManager()
@@ -175,7 +181,7 @@ class RegistrationProfile(models.Model):
verbose_name_plural = _('registration profiles') verbose_name_plural = _('registration profiles')
def __unicode__(self): def __unicode__(self):
return u"Registration information for %s" % self.user return u"Registration information for %s" % self.emailuser_id
def activation_key_expired(self): def activation_key_expired(self):
""" """
@@ -200,8 +206,12 @@ class RegistrationProfile(models.Model):
""" """
expiration_date = datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS) expiration_date = datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS)
ccnetuser = get_ccnetuser(userid=self.emailuser_id)
return self.activation_key == self.ACTIVATED or \ return self.activation_key == self.ACTIVATED or \
(self.user.date_joined + expiration_date <= datetime.datetime.now()) (datetime.datetime.fromtimestamp(ccnetuser.ctime/1000000) + expiration_date <= datetime.datetime.now())
activation_key_expired.boolean = True activation_key_expired.boolean = True
def send_activation_email(self, site): def send_activation_email(self, site):
@@ -254,5 +264,6 @@ class RegistrationProfile(models.Model):
message = render_to_string('registration/activation_email.txt', message = render_to_string('registration/activation_email.txt',
ctx_dict) ctx_dict)
self.user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL) ccnetuser = get_ccnetuser(userid=self.emailuser_id)
ccnetuser.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)

View File

@@ -11,6 +11,7 @@ from service import get_groups, get_group
from service import get_users, get_user, get_events, count_event 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_userids from service import get_binding_userids
from service import get_ccnetuser
from service import CCNET_CONF_PATH from service import CCNET_CONF_PATH

View File

@@ -296,6 +296,20 @@ def get_user(user_id):
user = ccnet_rpc.get_user(user_id) user = ccnet_rpc.get_user(user_id)
return user return user
def get_ccnetuser(username=None, userid=None):
# Get emailuser from db
if username != None:
emailuser = ccnet_rpc.get_emailuser(username)
if userid != None:
emailuser = ccnet_rpc.get_emailuser_by_id(userid)
if emailuser == None:
return None
# And convert to ccnetuser
from seahub.base.accounts import convert_to_ccnetuser
ccnetuser = convert_to_ccnetuser(emailuser)
return ccnetuser
def get_groups(): def get_groups():
"""Get group object list. """ """Get group object list. """

View File

@@ -8,8 +8,8 @@ from seahub.views import root, peers, groups, myhome, \
ownerhome, remove_fetched_repo ownerhome, remove_fetched_repo
# Uncomment the next two lines to enable the admin: # Uncomment the next two lines to enable the admin:
from django.contrib import admin #from django.contrib import admin
admin.autodiscover() #admin.autodiscover()
urlpatterns = patterns('', urlpatterns = patterns('',
# Example: # Example:
@@ -20,7 +20,7 @@ urlpatterns = patterns('',
# (r'^admin/doc/', include('django.contrib.admindocs.urls')), # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
# 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('base.registration_urls')), (r'^accounts/', include('base.registration_urls')),

View File

@@ -1,19 +1,20 @@
from django.http import HttpResponse, HttpResponseRedirect from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.template import RequestContext from django.template import RequestContext
from django.contrib.auth.decorators import login_required from auth.decorators import login_required
from django.db import IntegrityError from django.db import IntegrityError
from django.contrib.auth.models import User from auth.models import User
from django.views.decorators.csrf import csrf_protect from django.views.decorators.csrf import csrf_protect
from django.contrib.auth.forms import AuthenticationForm, PasswordResetForm, SetPasswordForm, PasswordChangeForm from auth.forms import AuthenticationForm, PasswordResetForm, SetPasswordForm, PasswordChangeForm
from seaserv import cclient, ccnet_rpc, get_groups, get_users, get_repos, \ from seaserv import cclient, ccnet_rpc, get_groups, get_users, get_repos, \
get_repo, get_commits, get_branches, \ get_repo, get_commits, get_branches, \
seafserv_threaded_rpc, get_binding_userids seafserv_threaded_rpc, get_binding_userids, get_ccnetuser
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
from seahub.base.accounts import CcnetUser
from forms import AddUserForm from forms import AddUserForm
@login_required @login_required
@@ -272,11 +273,11 @@ def useradmin(request):
if not request.user.is_staff: if not request.user.is_staff:
raise Http404 raise Http404
users = User.objects.all() users = ccnet_rpc.get_emailusers(-1,-1)
for user in users: for user in users:
try: try:
user.userid_list = get_binding_userids(user.username) user.userid_list = get_binding_userids(user.get_email())
user.ccnet_user = ccnet_rpc.get_user(user.profile.ccnet_user_id) # user.ccnet_user = ccnet_rpc.get_user(user.profile.ccnet_user_id)
user.role_list = user.ccnet_user.props.role_list.split(',') user.role_list = user.ccnet_user.props.role_list.split(',')
except: except:
user.ccnet_user = None user.ccnet_user = None
@@ -317,32 +318,24 @@ def user_remove(request, user_id):
if not request.user.is_staff: if not request.user.is_staff:
raise Http404 raise Http404
user = User.objects.get(id=user_id) ccnetuser = get_ccnetuser(userid=int(user_id))
user.delete() ccnetuser.delete()
# Also remove from ccnet EmailUser table and Binding table
ccnet_rpc.remove_emailuser(user.username)
ccnet_rpc.remove_binding(user.username)
return HttpResponseRedirect(request.META['HTTP_REFERER']) return HttpResponseRedirect(request.META['HTTP_REFERER'])
@login_required @login_required
def activate_user(request, user_id): def activate_user(request, user_id):
"""The user id is django user id.""" """The user id is emailuser id."""
if not request.user.is_staff: if not request.user.is_staff:
raise Http404 raise Http404
try: ccnetuser = get_ccnetuser(userid=int(user_id))
user = User.objects.get(pk=user_id) ccnetuser.is_active = True
user.is_active = True ccnetuser.save()
user.save()
except User.DoesNotExist:
pass
return HttpResponseRedirect(request.META['HTTP_REFERER']) return HttpResponseRedirect(request.META['HTTP_REFERER'])
@login_required @login_required
def user_add(request): def user_add(request):
"""Add a user""" """Add a user"""
@@ -354,14 +347,11 @@ def user_add(request):
form = AddUserForm(request.POST) form = AddUserForm(request.POST)
if form.is_valid(): if form.is_valid():
email = form.cleaned_data['email'] email = form.cleaned_data['email']
username = email
password = form.cleaned_data['password1'] password = form.cleaned_data['password1']
new_user = User.objects.create_user(username, email, password)
new_user.is_active = True ccnetuser = CcnetUser(username=email, raw_password=password)
new_user.save() ccnetuser.is_active = True
ccnetuser.save()
# Also save to ccnet EmailUser table
ccnet_rpc.add_emailuser(username, password)
return HttpResponseRedirect(reverse('useradmin', args=[])) return HttpResponseRedirect(reverse('useradmin', args=[]))
else: else:
@@ -370,32 +360,3 @@ def user_add(request):
return render_to_response("add_user_form.html", { return render_to_response("add_user_form.html", {
'form': form, 'form': form,
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
@csrf_protect
@login_required
def password_change(request,
template_name='registration/password_change_form.html',
post_change_redirect=None,
password_change_form=PasswordChangeForm,
current_app=None, extra_context=None):
if post_change_redirect is None:
post_change_redirect = reverse('django.contrib.auth.views.password_change_done')
if request.method == "POST":
form = password_change_form(user=request.user, data=request.POST)
if form.is_valid():
form.save()
# Also change ccnet EmailUser table
email = request.user.username
passwd = request.POST.get('new_password1')
ccnet_rpc.change_emailuser(email, passwd)
return HttpResponseRedirect(post_change_redirect)
else:
form = password_change_form(user=request.user)
context = {
'form': form,
}
context.update(extra_context or {})
return render_to_response(template_name, context,
context_instance=RequestContext(request, current_app=current_app))