diff --git a/base/accounts.py b/base/accounts.py index 3c022c8466..0e0027f2af 100644 --- a/base/accounts.py +++ b/base/accounts.py @@ -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.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 Site @@ -9,32 +14,131 @@ from registration import signals from registration.forms import RegistrationForm 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): - def authenticate(self, username=None, password=None): - if '@' in username: - kwargs = {'email': username} + ccnetuser = get_ccnetuser(username=username) + return ccnetuser + +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: - kwargs = {'username': username} - try: - user = User.objects.get(**kwargs) - if user.check_password(password): - 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 + self.objects.create_user(username=self.username, + password=self.raw_password, + is_staff=self.is_staff, + is_active=self.is_active) + 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): """ A registration backend which follows a simple workflow: @@ -104,11 +208,10 @@ class RegistrationBackend(object): site = Site.objects.get_current() else: site = RequestSite(request) + new_user = RegistrationProfile.objects.create_inactive_user(username, email, password, site, send_email=settings.REGISTRATION_SEND_MAIL) - # save email and password to EmailUser table - ccnet_rpc.add_emailuser(email, password) userid = kwargs['userid'] if userid: @@ -136,8 +239,9 @@ class RegistrationBackend(object): user=activated, request=request) # login the user - activated.backend='django.contrib.auth.backends.ModelBackend' + activated.backend='auth.backends.ModelBackend' login(request, activated) + # TODO: user.user_id should be change try: if request.user.user_id: ccnet_rpc.add_client(ccnet_user_id) @@ -210,12 +314,12 @@ class RegistrationForm(forms.Form): label=_("Password (again)")) def clean_email(self): - try: - user = User.objects.get(email__iexact=self.cleaned_data['email']) - except User.DoesNotExist: + email = self.cleaned_data['email'] + emailuser = ccnet_rpc.get_emailuser(email) + if not emailuser: return self.cleaned_data['email'] - - raise forms.ValidationError(_("A user with this email already")) + else: + raise forms.ValidationError(_("A user with this email already")) def clean_userid(self): 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']: raise forms.ValidationError(_("The two password fields didn't match.")) return self.cleaned_data + diff --git a/settings.py b/settings.py index 66b999c356..296ac92f15 100644 --- a/settings.py +++ b/settings.py @@ -65,7 +65,7 @@ MIDDLEWARE_CLASSES = ( 'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfResponseMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'auth.middleware.AuthenticationMiddleware', 'seahub.base.middleware.UseridMiddleware', ) @@ -93,11 +93,11 @@ TEMPLATE_CONTEXT_PROCESSORS = ( INSTALLED_APPS = ( - 'django.contrib.auth', + 'auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', - 'django.contrib.admin', +# 'django.contrib.admin', 'registration', # 'avatar', 'seahub.base', @@ -108,8 +108,7 @@ INSTALLED_APPS = ( ) AUTHENTICATION_BACKENDS = ( - 'seahub.base.accounts.EmailOrUsernameModelBackend', - 'django.contrib.auth.backends.ModelBackend' + 'auth.backends.ModelBackend', ) ACCOUNT_ACTIVATION_DAYS = 7 diff --git a/templates/base.html b/templates/base.html index 545539fc1d..046decf1ab 100644 --- a/templates/base.html +++ b/templates/base.html @@ -20,9 +20,11 @@ {% if request.user.is_authenticated %} 欢迎, {{ request.user }} 设置 + 退出 {% else %} 登录 @@ -85,7 +87,7 @@ diff --git a/templates/registration/password_reset_email.html b/templates/registration/password_reset_email.html index 4e4bd6d1b2..1c9df0a2f4 100644 --- a/templates/registration/password_reset_email.html +++ b/templates/registration/password_reset_email.html @@ -4,7 +4,7 @@ {% trans "Please go to the following page and choose a new password:" %} {% 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 %} {% trans "Your username, in case you've forgotten:" %} {{ user.username }} diff --git a/templates/useradmin.html b/templates/useradmin.html index 8ccf91e237..b2a17f1468 100644 --- a/templates/useradmin.html +++ b/templates/useradmin.html @@ -22,11 +22,11 @@ {% for user in users %} - {{ user.email }} - {% if user.is_active %} + {{ user.props.email }} + {% if user.props.is_active %} 已激活 {% else %} - + {% endif %} {% if user.userid_list %} {{ user.userid_list|first }} @@ -42,7 +42,7 @@ {% if user.profile %} {% endif %} - + {% endfor %} diff --git a/thirdpart/auth/__init__.py b/thirdpart/auth/__init__.py index 169ae01070..7efe320744 100644 --- a/thirdpart/auth/__init__.py +++ b/thirdpart/auth/__init__.py @@ -66,17 +66,17 @@ def login(request, user): user = request.user # TODO: It would be nice to support different login methods, like signed cookies. user.last_login = datetime.datetime.now() - user.save() 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 # session if the existing session corresponds to a different # authenticated user. request.session.flush() else: request.session.cycle_key() - request.session[SESSION_KEY] = user.id + + request.session[SESSION_KEY] = user.username request.session[BACKEND_SESSION_KEY] = user.backend if hasattr(request, 'user'): request.user = user @@ -88,16 +88,16 @@ def logout(request): """ request.session.flush() if hasattr(request, 'user'): - from django.contrib.auth.models import AnonymousUser + from auth.models import AnonymousUser request.user = AnonymousUser() def get_user(request): - from django.contrib.auth.models import AnonymousUser + from auth.models import AnonymousUser try: - user_id = request.session[SESSION_KEY] + username = request.session[SESSION_KEY] backend_path = request.session[BACKEND_SESSION_KEY] backend = load_backend(backend_path) - user = backend.get_user(user_id) or AnonymousUser() + user = backend.get_user(username) or AnonymousUser() except KeyError: user = AnonymousUser() return user diff --git a/thirdpart/auth/backends.py b/thirdpart/auth/backends.py index 9d674664eb..0f7ef78940 100644 --- a/thirdpart/auth/backends.py +++ b/thirdpart/auth/backends.py @@ -1,5 +1,8 @@ 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): @@ -12,12 +15,11 @@ class ModelBackend(object): # TODO: Model, login attribute name and password attribute name should be # configurable. def authenticate(self, username=None, password=None): - try: - user = User.objects.get(username=username) - if user.check_password(password): - return user - except User.DoesNotExist: - return None + ccnetuser = get_ccnetuser(username=username) + if ccnetuser and ccnetuser.check_password(password): + return ccnetuser + + return None def get_group_permissions(self, user_obj): """ @@ -51,11 +53,8 @@ class ModelBackend(object): return True return False - def get_user(self, user_id): - try: - return User.objects.get(pk=user_id) - except User.DoesNotExist: - return None + def get_user(self, username): + return get_ccnetuser(username=username) class RemoteUserBackend(ModelBackend): diff --git a/thirdpart/auth/decorators.py b/thirdpart/auth/decorators.py index 09dcf42e42..ce9b320227 100644 --- a/thirdpart/auth/decorators.py +++ b/thirdpart/auth/decorators.py @@ -3,7 +3,7 @@ try: except ImportError: 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.utils.decorators import available_attrs from django.utils.http import urlquote diff --git a/thirdpart/auth/forms.py b/thirdpart/auth/forms.py index d20c472495..0df889215f 100644 --- a/thirdpart/auth/forms.py +++ b/thirdpart/auth/forms.py @@ -1,12 +1,15 @@ -from django.contrib.auth.models import User -from django.contrib.auth import authenticate -from django.contrib.auth.tokens import default_token_generator +from auth.models import User +from auth import authenticate +from auth.tokens import default_token_generator + from django.contrib.sites.models import Site from django.template import Context, loader from django import forms from django.utils.translation import ugettext_lazy as _ from django.utils.http import int_to_base36 +from seaserv import get_ccnetuser + class UserCreationForm(forms.ModelForm): """ 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. """ 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?")) + return email 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 """ from django.core.mail import send_mail - for user in self.users_cache: - if not domain_override: - current_site = Site.objects.get_current() - site_name = current_site.name - domain = current_site.domain - else: - site_name = domain = domain_override - t = loader.get_template(email_template_name) - c = { - 'email': user.email, - 'domain': domain, - 'site_name': site_name, - 'uid': int_to_base36(user.id), - 'user': user, - 'token': token_generator.make_token(user), - 'protocol': use_https and 'https' or 'http', - } - send_mail(_("Password reset on %s") % site_name, - t.render(Context(c)), None, [user.email]) + + ccnetuser = self.users_cache + if not domain_override: + current_site = Site.objects.get_current() + site_name = current_site.name + domain = current_site.domain + else: + site_name = domain = domain_override + t = loader.get_template(email_template_name) + + c = { + 'email': ccnetuser.username, + 'domain': domain, + 'site_name': site_name, + 'uid': int_to_base36(ccnetuser.id), + 'user': ccnetuser, + 'token': token_generator.make_token(ccnetuser), + 'protocol': use_https and 'https' or 'http', + } + send_mail(_("Password reset on %s") % site_name, + t.render(Context(c)), None, [ccnetuser.username]) class SetPasswordForm(forms.Form): """ @@ -152,6 +159,7 @@ class SetPasswordForm(forms.Form): def __init__(self, user, *args, **kwargs): self.user = user + super(SetPasswordForm, self).__init__(*args, **kwargs) def clean_new_password2(self): diff --git a/thirdpart/auth/middleware.py b/thirdpart/auth/middleware.py index 11c61b28a3..d9d965b285 100644 --- a/thirdpart/auth/middleware.py +++ b/thirdpart/auth/middleware.py @@ -5,7 +5,7 @@ from django.core.exceptions import ImproperlyConfigured class LazyUser(object): def __get__(self, request, obj_type=None): if not hasattr(request, '_cached_user'): - from django.contrib.auth import get_user + from auth import get_user request._cached_user = get_user(request) return request._cached_user diff --git a/thirdpart/auth/models.py b/thirdpart/auth/models.py index 681cf1422a..a0e95a402d 100644 --- a/thirdpart/auth/models.py +++ b/thirdpart/auth/models.py @@ -1,7 +1,7 @@ import datetime import urllib -from django.contrib import auth +import auth from django.core.exceptions import ImproperlyConfigured from django.db import models from django.db.models.manager import EmptyManager diff --git a/thirdpart/auth/tokens.py b/thirdpart/auth/tokens.py index f61f52d903..259fab594a 100644 --- a/thirdpart/auth/tokens.py +++ b/thirdpart/auth/tokens.py @@ -51,9 +51,12 @@ class PasswordResetTokenGenerator(object): # invalid as soon as it is used. # We limit the hash to 20 chars to keep URL short 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) + - 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] + return "%s-%s" % (ts_b36, hash) def _num_days(self, dt): diff --git a/thirdpart/auth/views.py b/thirdpart/auth/views.py index b2e875a869..e5f5a0ae9b 100644 --- a/thirdpart/auth/views.py +++ b/thirdpart/auth/views.py @@ -1,12 +1,6 @@ import re from django.conf import settings -from django.contrib.auth import REDIRECT_FIELD_NAME # 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.core.urlresolvers import reverse 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.utils.http import urlquote, base36_to_int from django.utils.translation import ugettext as _ -from django.contrib.auth.models import User 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 @never_cache def login(request, template_name='registration/login.html', @@ -40,10 +43,11 @@ def login(request, template_name='registration/login.html', # question mark. elif '//' in redirect_to and re.match(r'[^\?]*//', redirect_to): redirect_to = settings.LOGIN_REDIRECT_URL - + # Okay, security checks complete. Log the user in. auth_login(request, form.get_user()) + if request.session.test_cookie_worked(): 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): "Logs out the user and displays 'You are logged out' message." - from django.contrib.auth import logout + from auth import logout logout(request) if next_page is None: 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, post_reset_redirect=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": form = password_reset_form(request.POST) 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 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: uid_int = base36_to_int(uidb36) except ValueError: 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) - if token_generator.check_token(user, token): + if token_generator.check_token(ccnetuser, token): context_instance['validlink'] = True if request.method == 'POST': - form = set_password_form(user, request.POST) + form = set_password_form(ccnetuser, request.POST) if form.is_valid(): form.save() 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', post_change_redirect=None, password_change_form=PasswordChangeForm): 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": form = password_change_form(user=request.user, data=request.POST) if form.is_valid(): diff --git a/thirdpart/registration/auth_urls.py b/thirdpart/registration/auth_urls.py index 89f8a48d5d..dfbd989a6d 100644 --- a/thirdpart/registration/auth_urls.py +++ b/thirdpart/registration/auth_urls.py @@ -25,10 +25,7 @@ consult a specific backend's documentation for details. from django.conf.urls.defaults import * -from django.contrib.auth import views as auth_views - -from seahub.views import password_change - +from auth import views as auth_views urlpatterns = patterns('', url(r'^login/$', @@ -40,7 +37,7 @@ urlpatterns = patterns('', {'template_name': 'registration/logout.html'}, name='auth_logout'), url(r'^password/change/$', - password_change, + auth_views.password_change, name='auth_password_change'), url(r'^password/change/done/$', auth_views.password_change_done, diff --git a/thirdpart/registration/models.py b/thirdpart/registration/models.py index a2a04ae125..51fa9b561e 100644 --- a/thirdpart/registration/models.py +++ b/thirdpart/registration/models.py @@ -3,13 +3,15 @@ import random import re 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 transaction from django.template.loader import render_to_string from django.utils.hashcompat import sha_constructor from django.utils.translation import ugettext_lazy as _ +from seaserv import ccnet_rpc, get_ccnetuser SHA1_RE = re.compile('^[a-f0-9]{40}$') @@ -51,12 +53,13 @@ class RegistrationManager(models.Manager): except self.model.DoesNotExist: return False if not profile.activation_key_expired(): - user = profile.user - user.is_active = True - user.save() + # Activate emailuser + ccnetuser = get_ccnetuser(userid=profile.emailuser_id) + ccnetuser.is_active = True + ccnetuser.save() profile.activation_key = self.model.ACTIVATED profile.save() - return user + return ccnetuser return False def create_inactive_user(self, username, email, password, @@ -70,16 +73,19 @@ class RegistrationManager(models.Manager): 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: registration_profile.send_activation_email(site) - return new_user + return ccnetuser create_inactive_user = transaction.commit_on_success(create_inactive_user) def create_profile(self, user): @@ -97,7 +103,7 @@ class RegistrationManager(models.Manager): if isinstance(username, unicode): username = username.encode('utf-8') activation_key = sha_constructor(salt+username).hexdigest() - return self.create(user=user, + return self.create(emailuser_id=user.id, activation_key=activation_key) def delete_expired_users(self): @@ -142,10 +148,9 @@ class RegistrationManager(models.Manager): """ for profile in self.all(): if profile.activation_key_expired(): - user = profile.user - if not user.is_active: - user.delete() - + ccnetuser = get_ccnetuser(userid=profile.emailuser_id) + if not ccnetuser.is_active: + ccnet_rpc.remove_emailuser(ccnetuser.username) class RegistrationProfile(models.Model): """ @@ -165,7 +170,8 @@ class RegistrationProfile(models.Model): """ 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) objects = RegistrationManager() @@ -175,7 +181,7 @@ class RegistrationProfile(models.Model): verbose_name_plural = _('registration profiles') 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): """ @@ -200,8 +206,12 @@ class RegistrationProfile(models.Model): """ expiration_date = datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS) + + ccnetuser = get_ccnetuser(userid=self.emailuser_id) + 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 def send_activation_email(self, site): @@ -254,5 +264,6 @@ class RegistrationProfile(models.Model): message = render_to_string('registration/activation_email.txt', 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) diff --git a/thirdpart/seaserv/__init__.py b/thirdpart/seaserv/__init__.py index 1fd47d2045..fe397111ad 100644 --- a/thirdpart/seaserv/__init__.py +++ b/thirdpart/seaserv/__init__.py @@ -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_repos, get_repo, get_commits, get_branches from service import get_binding_userids +from service import get_ccnetuser from service import CCNET_CONF_PATH diff --git a/thirdpart/seaserv/service.py b/thirdpart/seaserv/service.py index 08eb89e822..aa77b3bc4d 100644 --- a/thirdpart/seaserv/service.py +++ b/thirdpart/seaserv/service.py @@ -296,6 +296,20 @@ def get_user(user_id): user = ccnet_rpc.get_user(user_id) 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(): """Get group object list. """ diff --git a/urls.py b/urls.py index 6493d7eedc..8d4316fd6e 100644 --- a/urls.py +++ b/urls.py @@ -8,8 +8,8 @@ from seahub.views import root, peers, groups, myhome, \ ownerhome, remove_fetched_repo # Uncomment the next two lines to enable the admin: -from django.contrib import admin -admin.autodiscover() +#from django.contrib import admin +#admin.autodiscover() urlpatterns = patterns('', # Example: @@ -20,7 +20,7 @@ urlpatterns = patterns('', # (r'^admin/doc/', include('django.contrib.admindocs.urls')), # 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')), diff --git a/views.py b/views.py index 4e524219fc..7abd62ce7c 100644 --- a/views.py +++ b/views.py @@ -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.core.urlresolvers import reverse 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.contrib.auth.models import User +from auth.models import User 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, \ 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.forms import GroupAddRepoForm +from seahub.base.accounts import CcnetUser from forms import AddUserForm @login_required @@ -272,11 +273,11 @@ def useradmin(request): if not request.user.is_staff: raise Http404 - users = User.objects.all() + users = ccnet_rpc.get_emailusers(-1,-1) for user in users: try: - user.userid_list = get_binding_userids(user.username) - user.ccnet_user = ccnet_rpc.get_user(user.profile.ccnet_user_id) + user.userid_list = get_binding_userids(user.get_email()) +# user.ccnet_user = ccnet_rpc.get_user(user.profile.ccnet_user_id) user.role_list = user.ccnet_user.props.role_list.split(',') except: user.ccnet_user = None @@ -317,32 +318,24 @@ def user_remove(request, user_id): if not request.user.is_staff: raise Http404 - user = User.objects.get(id=user_id) - user.delete() - - # Also remove from ccnet EmailUser table and Binding table - ccnet_rpc.remove_emailuser(user.username) - ccnet_rpc.remove_binding(user.username) + ccnetuser = get_ccnetuser(userid=int(user_id)) + ccnetuser.delete() return HttpResponseRedirect(request.META['HTTP_REFERER']) @login_required 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: raise Http404 - try: - user = User.objects.get(pk=user_id) - user.is_active = True - user.save() - except User.DoesNotExist: - pass - + ccnetuser = get_ccnetuser(userid=int(user_id)) + ccnetuser.is_active = True + ccnetuser.save() + return HttpResponseRedirect(request.META['HTTP_REFERER']) - @login_required def user_add(request): """Add a user""" @@ -354,14 +347,11 @@ def user_add(request): form = AddUserForm(request.POST) if form.is_valid(): email = form.cleaned_data['email'] - username = email password = form.cleaned_data['password1'] - new_user = User.objects.create_user(username, email, password) - new_user.is_active = True - new_user.save() - - # Also save to ccnet EmailUser table - ccnet_rpc.add_emailuser(username, password) + + ccnetuser = CcnetUser(username=email, raw_password=password) + ccnetuser.is_active = True + ccnetuser.save() return HttpResponseRedirect(reverse('useradmin', args=[])) else: @@ -370,32 +360,3 @@ def user_add(request): return render_to_response("add_user_form.html", { 'form': form, }, 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))