diff --git a/PyRIGS/settings.py b/PyRIGS/settings.py index 8eee78c7..03c7c73a 100644 --- a/PyRIGS/settings.py +++ b/PyRIGS/settings.py @@ -79,58 +79,21 @@ AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', ) -# Environ -# DISCOURSE_HOST='http://localhost:4000' -# DISCOURSE_SSO_SECRET='ABCDEFGHIJKLMNOP' - -SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/rigboard' -SOCIAL_AUTH_LOGIN_URL = '/' - SOCIAL_AUTH_PIPELINE = ( - # Get the information we can about the user and return it in a simple - # format to create the user instance later. On some cases the details are - # already part of the auth response from the provider, but sometimes this - # could hit a provider API. - 'social.pipeline.social_auth.social_details', - - # Get the social uid from whichever service we're authing thru. The uid is - # the unique identifier of the given user in the provider. - 'social.pipeline.social_auth.social_uid', - - # Verifies that the current auth process is valid within the current - # project, this is were emails and domains whitelists are applied (if - # defined). - 'social.pipeline.social_auth.auth_allowed', - - # Checks if the current social-account is already associated in the site. - 'social.pipeline.social_auth.social_user', - - # Make up a username for this person, appends a random string at the end if - # there's any collision. - # 'social.pipeline.user.get_username', - - # Send a validation email to the user to verify its email address. - # Disabled by default. - # 'social.pipeline.mail.mail_validation', - - # Associates the current social details with another user account with - # a similar email address. Disabled by default. - 'social.pipeline.social_auth.associate_by_email', - - # Create a user account if we haven't found one yet. - #'social.pipeline.user.create_user', - - # Create the record that associated the social account with this user. - #'social.pipeline.social_auth.associate_user', - - # Populate the extra_data field in the social record with the values - # specified by settings (and the default ones like access_token, etc). - 'social.pipeline.social_auth.load_extra_data', - - # Update the user record with any changed info from the auth service. - 'social.pipeline.user.user_details', + 'social.pipeline.social_auth.social_details', # Load remote details + 'social.pipeline.social_auth.social_uid', # Load remote ID + 'social.pipeline.social_auth.auth_allowed', # Check not blacklisted + 'social.pipeline.social_auth.social_user', # If already associated, login + 'RIGS.discourse.pipeline.new_connection', # Choose a user account, much UI + 'social.pipeline.social_auth.associate_user', # Associate the social auth with the user + 'social.pipeline.user.user_details', # Save any details that changed ) +DISCOURSE_HOST=os.environ.get('DISCOURSE_HOST') if os.environ.get('DISCOURSE_HOST') else 'http://localhost:4000' +DISCOURSE_SSO_SECRET=os.environ.get('DISCOURSE_SSO_SECRET') if os.environ.get('DISCOURSE_SSO_SECRET') else 'ABCDEFGHIJKLMNOP' + +REGISTRATION_OPEN = False # Disable built-in django registration - must register using forum + ROOT_URLCONF = 'PyRIGS.urls' WSGI_APPLICATION = 'PyRIGS.wsgi.application' diff --git a/RIGS/discourse/discourse.py b/RIGS/discourse/discourse.py index dea26039..ae7d8089 100644 --- a/RIGS/discourse/discourse.py +++ b/RIGS/discourse/discourse.py @@ -1,7 +1,6 @@ from __future__ import unicode_literals -import os from social.backends.base import BaseAuth -from social.exceptions import AuthException +from django.conf import settings from .sso import DiscourseSSO @@ -20,8 +19,8 @@ class DiscourseAssociation(object): class DiscourseAuth(BaseAuth): """Discourse authentication backend""" name = 'discourse' - secret = os.environ['DISCOURSE_SSO_SECRET'] - host = os.environ['DISCOURSE_HOST'] + secret = settings.DISCOURSE_SSO_SECRET + host = settings.DISCOURSE_HOST EXTRA_DATA = [ ('username', 'username'), diff --git a/RIGS/discourse/pipeline.py b/RIGS/discourse/pipeline.py new file mode 100644 index 00000000..06fcbc18 --- /dev/null +++ b/RIGS/discourse/pipeline.py @@ -0,0 +1,62 @@ +from django.core.urlresolvers import reverse +from django.contrib.auth import REDIRECT_FIELD_NAME +from django.shortcuts import render_to_response +from django.core.exceptions import ValidationError + +from social.pipeline.partial import partial + +from RIGS.models import Profile +from RIGS import forms + + +class SocialRegisterForm(forms.ProfileRegistrationFormUniqueEmail): + def __init__(self, *args, **kwargs): + super(SocialRegisterForm, self).__init__(*args, **kwargs) + self.fields.pop('password1') + self.fields.pop('password2') + self.fields.pop('captcha') + + self.fields['email'].widget.attrs['readonly'] = True + + def clean_email(self): + initial = getattr(self, 'initial', None) + if(initial['email'] != self.cleaned_data['email']): + raise ValidationError("You cannot change the email") + + return initial['email'] + + +@partial +def new_connection(backend, details, response, user=None, is_new=False, social=None, request=None, *args, **kwargs): + if social is not None: + return + + data = backend.strategy.request_data() + + if data.get('UseCurrentAccount') is not None: + return + + alreadyLoggedIn = user is not None + + context = { + 'details': details, + 'alreadyLoggedIn': alreadyLoggedIn, + 'loggedInUser': user, + } + + if not alreadyLoggedIn: + completeUrl = reverse('social:complete', kwargs={'backend': backend.name}) + context['login_url'] = "{0}?{1}={2}".format(reverse('login'), REDIRECT_FIELD_NAME, completeUrl) + + if data.get('username') is None: + form = SocialRegisterForm(initial=details) + else: + form = SocialRegisterForm(data, initial=details) + + if form.is_valid(): + new_user = Profile.objects.create_user(**form.cleaned_data) + return {'user': new_user} + + context['form'] = form + + return render_to_response('RIGS/social-associate.html', context) diff --git a/RIGS/forms.py b/RIGS/forms.py index e1e95012..6d164fb9 100644 --- a/RIGS/forms.py +++ b/RIGS/forms.py @@ -3,6 +3,7 @@ from django import forms from django.utils import formats from django.conf import settings from django.core import serializers +from django.core.exceptions import ValidationError from django.contrib.auth.forms import UserCreationForm, UserChangeForm, AuthenticationForm, PasswordResetForm from registration.forms import RegistrationFormUniqueEmail from captcha.fields import ReCaptchaField @@ -27,6 +28,16 @@ class ProfileRegistrationFormUniqueEmail(RegistrationFormUniqueEmail): raise forms.ValidationError("These initials are already in use. Please supply different initials.") return self.cleaned_data['initials'] + def clean_first_name(self): + if self.cleaned_data["first_name"].strip() == '': + raise ValidationError("First name is required.") + return self.cleaned_data["first_name"] + + def clean_last_name(self): + if self.cleaned_data["last_name"].strip() == '': + raise ValidationError("Last name is required.") + return self.cleaned_data["last_name"] + # Login form class PasswordReset(PasswordResetForm): diff --git a/RIGS/static/imgs/forum-logo.gif b/RIGS/static/imgs/forum-logo.gif new file mode 100644 index 00000000..ca41e56c Binary files /dev/null and b/RIGS/static/imgs/forum-logo.gif differ diff --git a/RIGS/templates/RIGS/profile_detail.html b/RIGS/templates/RIGS/profile_detail.html index 11904b18..491bcaff 100644 --- a/RIGS/templates/RIGS/profile_detail.html +++ b/RIGS/templates/RIGS/profile_detail.html @@ -133,6 +133,20 @@ {% endif %} + +