1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-19 18:29:23 +00:00

Fix activate request email not sent bug on registration, and apply to shibboleth login

This commit is contained in:
zhengxie
2016-03-24 15:07:19 +08:00
parent 7e1fad59aa
commit 42c90bda2e
5 changed files with 154 additions and 31 deletions

View File

@@ -1,5 +1,6 @@
# encoding: utf-8 # encoding: utf-8
from django import forms from django import forms
from django.core.mail import send_mail
from django.utils.encoding import smart_str from django.utils.encoding import smart_str
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.conf import settings from django.conf import settings
@@ -230,7 +231,6 @@ class User(object):
def email_user(self, subject, message, from_email=None): def email_user(self, subject, message, from_email=None):
"Sends an e-mail to this User." "Sends an e-mail to this User."
from django.core.mail import send_mail
send_mail(subject, message, from_email, [self.email]) send_mail(subject, message, from_email, [self.email])
def remove_repo_passwds(self): def remove_repo_passwds(self):

View File

@@ -0,0 +1,29 @@
from django.core import mail
from django.core.urlresolvers import reverse
from constance import config
from seahub.test_utils import BaseTestCase
class EmailAdminOnRegistrationTest(BaseTestCase):
def setUp(self):
config.ENABLE_SIGNUP = True
self.email = 'newuser@test.com'
self.remove_user(self.email)
def test_can_notify_admin(self):
assert bool(config.ENABLE_SIGNUP) is True
self.assertEqual(len(mail.outbox), 0)
config.ACTIVATE_AFTER_REGISTRATION = False
config.REGISTRATION_SEND_MAIL = False
resp = self.client.post(reverse('registration_register'), {
'email': self.email,
'password1': '123',
'password2': '123'
})
self.assertRedirects(resp, 'http://testserver/accounts/register/complete/')
assert len(mail.outbox) != 0
assert 'a newly registered account need to be activated' in mail.outbox[0].body

View File

@@ -0,0 +1,88 @@
from django.core import mail
from django.conf import settings
from shibboleth import backends
from seahub.base.accounts import User
from seahub.auth import authenticate
from seahub.test_utils import BaseTestCase
SAMPLE_HEADERS = {
"REMOTE_USER": 'sampledeveloper@school.edu',
"Shib-Application-ID": "default",
"Shib-Authentication-Method": "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified",
"Shib-AuthnContext-Class": "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified",
"Shib-Identity-Provider": "https://sso.college.edu/idp/shibboleth",
"Shib-Session-ID": "1",
"Shib-Session-Index": "12",
"Shibboleth-affiliation": "member@college.edu;staff@college.edu",
"Shibboleth-schoolBarCode": "12345678",
"Shibboleth-schoolNetId": "Sample_Developer",
"Shibboleth-schoolStatus": "active",
"Shibboleth-department": "University Library, Integrated Technology Services",
"Shibboleth-displayName": "Sample Developer",
"Shibboleth-eppn": "sampledeveloper@school.edu",
"Shibboleth-givenName": "Sample",
"Shibboleth-isMemberOf": "SCHOOL:COMMUNITY:EMPLOYEE:ADMINISTRATIVE:BASE;SCHOOL:COMMUNITY:EMPLOYEE:STAFF:SAC:P;COMMUNITY:ALL;SCHOOL:COMMUNITY:EMPLOYEE:STAFF:SAC:M;",
"Shibboleth-mail": "Sample_Developer@school.edu",
"Shibboleth-persistent-id": "https://sso.college.edu/idp/shibboleth!https://server.college.edu/shibboleth-sp!sk1Z9qKruvXY7JXvsq4GRb8GCUk=",
"Shibboleth-sn": "Developer",
"Shibboleth-title": "Library Developer",
"Shibboleth-unscoped-affiliation": "member;staff"
}
settings.SHIBBOLETH_ATTRIBUTE_MAP = {
"Shib-Identity-Provider": (True, "idp"),
"Shibboleth-mail": (True, "email"),
"Shibboleth-eppn": (True, "username"),
"Shibboleth-schoolStatus": (True, "status"),
"Shibboleth-affiliation": (True, "affiliation"),
"Shib-Session-ID": (True, "session_id"),
"Shibboleth-givenName": (True, "first_name"),
"Shibboleth-sn": (True, "last_name"),
"Shibboleth-mail": (True, "email"),
"Shibboleth-schoolBarCode": (False, "barcode")
}
settings.AUTHENTICATION_BACKENDS += (
'shibboleth.backends.ShibbolethRemoteUserBackend',
)
settings.MIDDLEWARE_CLASSES += (
'shibboleth.middleware.ShibbolethRemoteUserMiddleware',
)
class ShibbolethRemoteUserBackendTest(BaseTestCase):
def setUp(self):
self.remote_user = 'sampledeveloper@school.edu'
self.remove_user(self.remote_user)
def test_create_unknown_user(self):
with self.assertRaises(User.DoesNotExist):
self.assertFalse(User.objects.get(self.remote_user))
user = authenticate(remote_user=self.remote_user,
shib_meta=SAMPLE_HEADERS)
assert user.is_active is True
self.assertEqual(user.username, 'sampledeveloper@school.edu')
self.assertEqual(User.objects.get(self.remote_user).username,
'sampledeveloper@school.edu')
def test_notify_admins_on_activate_request(self):
self.assertEqual(len(mail.outbox), 0)
with self.assertRaises(User.DoesNotExist):
self.assertFalse(User.objects.get(self.remote_user))
with self.settings(SHIB_ACTIVATE_AFTER_CREATION=False):
# reload our shibboleth.backends module, so it picks up the settings change
reload(backends)
user = authenticate(remote_user=self.remote_user,
shib_meta=SAMPLE_HEADERS)
self.assertEqual(user.username, 'sampledeveloper@school.edu')
assert user.is_active is False
assert len(mail.outbox) != 0
assert 'a newly registered account need to be activated' in mail.outbox[0].body
# now reload again, so it reverts to original settings
reload(backends)

View File

@@ -302,6 +302,29 @@ from constance import config
# Get an instance of a logger # Get an instance of a logger
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def notify_admins_on_activate_request(reg_email):
ctx_dict = {
"site_name": settings.SITE_NAME,
"user_search_link": "%s%s?email=%s" % (
get_site_scheme_and_netloc(), reverse("user_search"),
urlquote(reg_email)),
}
subject = render_to_string('registration/activate_request_email_subject.txt',
ctx_dict)
# Email subject *must not* contain newlines
subject = ''.join(subject.splitlines())
message = render_to_string('registration/activate_request_email.txt',
ctx_dict)
admins = User.objects.get_superusers()
for admin in admins:
try:
admin.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
except Exception as e:
logger.error(e)
@receiver(user_registered) @receiver(user_registered)
def email_admin_on_registration(sender, **kwargs): def email_admin_on_registration(sender, **kwargs):
"""Send an email notification to admin when a newly registered user need """Send an email notification to admin when a newly registered user need
@@ -310,28 +333,7 @@ def email_admin_on_registration(sender, **kwargs):
This email will be sent when both ``ACTIVATE_AFTER_REGISTRATION`` and This email will be sent when both ``ACTIVATE_AFTER_REGISTRATION`` and
``REGISTRATION_SEND_MAIL`` are set to False. ``REGISTRATION_SEND_MAIL`` are set to False.
""" """
if bool(config.ACTIVATE_AFTER_REGISTRATION) is False and \
if config.ACTIVATE_AFTER_REGISTRATION is False and \ bool(config.REGISTRATION_SEND_MAIL) is False:
config.REGISTRATION_SEND_MAIL is False:
reg_email = kwargs['user'].email reg_email = kwargs['user'].email
notify_admins_on_activate_request(reg_email)
ctx_dict = {
"site_name": settings.SITE_NAME,
"user_search_link": "%s%s?email=%s" % (
get_site_scheme_and_netloc(), reverse("user_search"),
urlquote(reg_email)),
}
subject = render_to_string('registration/activate_request_email_subject.txt',
ctx_dict)
# Email subject *must not* contain newlines
subject = ''.join(subject.splitlines())
message = render_to_string('registration/activate_request_email.txt',
ctx_dict)
admins = User.objects.get_superusers()
for admin in admins:
try:
admin.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
except Exception as e:
logger.error(e)

View File

@@ -1,7 +1,9 @@
from django.conf import settings
from django.db import connection from django.db import connection
from django.contrib.auth.backends import RemoteUserBackend from django.contrib.auth.backends import RemoteUserBackend
from seahub.base.accounts import User from seahub.base.accounts import User
from registration.models import notify_admins_on_activate_request
class ShibbolethRemoteUserBackend(RemoteUserBackend): class ShibbolethRemoteUserBackend(RemoteUserBackend):
""" """
@@ -17,6 +19,8 @@ class ShibbolethRemoteUserBackend(RemoteUserBackend):
# Create a User object if not already in the database? # Create a User object if not already in the database?
create_unknown_user = True create_unknown_user = True
# Create active user by default.
activate_after_creation = getattr(settings, 'SHIB_ACTIVATE_AFTER_CREATION', True)
def get_user(self, username): def get_user(self, username):
try: try:
@@ -36,17 +40,17 @@ class ShibbolethRemoteUserBackend(RemoteUserBackend):
""" """
if not remote_user: if not remote_user:
return return
user = None
username = self.clean_username(remote_user) username = self.clean_username(remote_user)
# Note that this could be accomplished in one try-except clause, but
# instead we use get_or_create when creating unknown users since it has
# built-in safeguards for multiple threads.
try: try:
user = User.objects.get(email=username) user = User.objects.get(email=username)
except User.DoesNotExist: except User.DoesNotExist:
if self.create_unknown_user: if self.create_unknown_user:
user = User.objects.create_user(email=username, is_active=True) user = User.objects.create_user(
email=username, is_active=self.activate_after_creation)
if user and self.activate_after_creation is False:
notify_admins_on_activate_request(user.email)
else: else:
pass user = None
return user return user