Пример #1
0
    def clean_email(self):
        # we override the default django auth clean_email to provide more
        # detailed messages in case of inactive users
        email = self.cleaned_data['email']
        try:
            user = AstakosUser.objects.get_by_identifier(email)
            self.users_cache = [user]
            if not user.is_active:
                if not user.has_auth_provider('local', auth_backend='astakos'):
                    provider = auth_providers.get_provider('local', user)
                    msg = mark_safe(provider.get_unusable_password_msg)
                    raise forms.ValidationError(msg)

                msg = mark_safe(user.get_inactive_message('local'))
                raise forms.ValidationError(msg)

            provider = auth_providers.get_provider('local', user)
            if not user.has_usable_password():
                msg = provider.get_unusable_password_msg
                raise forms.ValidationError(mark_safe(msg))

            if not user.can_change_password():
                msg = provider.get_cannot_change_password_msg
                raise forms.ValidationError(mark_safe(msg))

        except AstakosUser.DoesNotExist:
            raise forms.ValidationError(_(astakos_messages.EMAIL_UNKNOWN))
        return email
Пример #2
0
    def clean_email(self):
        # we override the default django auth clean_email to provide more
        # detailed messages in case of inactive users
        email = self.cleaned_data['email']
        try:
            user = AstakosUser.objects.get_by_identifier(email)
            self.users_cache = [user]
            if not user.is_active:
                if not user.has_auth_provider('local', auth_backend='astakos'):
                    provider = auth_providers.get_provider('local', user)
                    msg = mark_safe(provider.get_unusable_password_msg)
                    raise forms.ValidationError(msg)

                msg = mark_safe(user.get_inactive_message('local'))
                raise forms.ValidationError(msg)

            provider = auth_providers.get_provider('local', user)
            if not user.has_usable_password():
                msg = provider.get_unusable_password_msg
                raise forms.ValidationError(mark_safe(msg))

            if not user.can_change_password():
                msg = provider.get_cannot_change_password_msg
                raise forms.ValidationError(mark_safe(msg))

        except AstakosUser.DoesNotExist:
            raise forms.ValidationError(_(astakos_messages.EMAIL_UNKNOWN))
        return email
Пример #3
0
def add(request, template_name='im/auth/ldap_add.html'):

    provider = auth.get_provider('ldap', request.user)

    # Check that provider's policy allows to add provider to account
    if not provider.get_add_policy:
        messages.error(request, provider.get_add_disabled_msg)
        return HttpResponseRedirect(reverse('edit_profile'))

    if request.method == "GET":
        return render_response(template_name,
                               login_form=LDAPLoginForm(request=request),
                               context_instance=get_context(
                                   request, provider=LDAP_PROVIDER))

    form = LDAPLoginForm(data=request.POST, request=request)

    if form.is_valid():
        provider = auth.get_provider('ldap', request.user)

        user = form.ldap_user_cache

        provider_info = dict(user.ldap_user.attrs)
        try:
            user_info = populate_user_attributes(provider, provider_info)
            user_id = user_info.pop('identifier')
        except (ValueError, KeyError):
            logger.exception(
                "Failed to map attributes from LDAP provider."
                " Provider attributes: %s", provider_info)
            msg = 'Invalid LDAP response. Please contact support.'
            messages.error(request, msg)
            return HttpResponseRedirect(reverse('login'))
        affiliation = 'LDAP'  # TODO: Add LDAP server name?
        user_info['affiliation'] = affiliation
        provider_info = dict([(k, smart_unicode(v, errors="ignore"))
                              for k, v in provider_info.items()
                              if k in provider.get_provider_info_attributes()])

    if hasattr(user, 'group_names') and provider.get_policy('mirror_groups'):
        groups = [
            Group.objects.get_or_create(name=group_name)[0]
            for group_name in user.group_names
        ]
        user_info['groups'] = groups

        return handle_third_party_login(request,
                                        provider_module="ldap",
                                        identifier=user_id,
                                        provider_info=provider_info,
                                        affiliation=affiliation,
                                        user_info=user_info)
    else:
        return render_response(template_name,
                               form=LDAPLoginForm(request=request),
                               context_instance=get_context(
                                   request, provider=LDAP_PROVIDER))
Пример #4
0
def add(request, template_name='im/auth/ldap_add.html'):

    provider = auth.get_provider('ldap', request.user)

    # Check that provider's policy allows to add provider to account
    if not provider.get_add_policy:
        messages.error(request, provider.get_add_disabled_msg)
        return HttpResponseRedirect(reverse('edit_profile'))

    if request.method == "GET":
        return render_response(
            template_name,
            login_form=LDAPLoginForm(request=request),
            context_instance=get_context(request, provider=LDAP_PROVIDER)
        )

    form = LDAPLoginForm(data=request.POST,
                         request=request)

    if form.is_valid():
        provider = auth.get_provider('ldap', request.user)

        user = form.ldap_user_cache

        provider_info = dict(user.ldap_user.attrs)
        try:
            user_info = populate_user_attributes(provider, provider_info)
            user_id = user_info.pop('identifier')
        except (ValueError, KeyError):
            logger.exception("Failed to map attributes from LDAP provider."
                             " Provider attributes: %s", provider_info)
            msg = 'Invalid LDAP response. Please contact support.'
            messages.error(request, msg)
            return HttpResponseRedirect(reverse('login'))
        affiliation = 'LDAP'  # TODO: Add LDAP server name?
        user_info['affiliation'] = affiliation
        provider_info = dict([(k, smart_unicode(v, errors="ignore"))
                              for k, v in provider_info.items()
                              if k in provider.get_provider_info_attributes()])

    if hasattr(user, 'group_names') and provider.get_policy('mirror_groups'):
        groups = [Group.objects.get_or_create(name=group_name)[0]
                  for group_name in user.group_names]
        user_info['groups'] = groups

        return handle_third_party_login(request, provider_module="ldap",
                                        identifier=user_id,
                                        provider_info=provider_info,
                                        affiliation=affiliation,
                                        user_info=user_info)
    else:
        return render_response(
            template_name,
            form=LDAPLoginForm(request=request),
            context_instance=get_context(request, provider=LDAP_PROVIDER)
        )
Пример #5
0
def signup(request,
           template_name='im/signup.html',
           on_success='index',
           extra_context=None,
           activation_backend=None):
    """
    Allows a user to create a local account.

    In case of GET request renders a form for entering the user information.
    In case of POST handles the signup.

    The user activation will be delegated to the backend specified by the
    ``activation_backend`` keyword argument if present, otherwise to the
    ``astakos.im.activation_backends.InvitationBackend`` if
    settings.ASTAKOS_INVITATIONS_ENABLED is True or
    ``astakos.im.activation_backends.SimpleBackend`` if not (see
    activation_backends);

    Upon successful user creation, if ``next`` url parameter is present the
    user is redirected there otherwise renders the same page with a success
    message.

    On unsuccessful creation, renders ``template_name`` with an error message.

    **Arguments**

    ``template_name``
        A custom template to render. This is optional;
        if not specified, this will default to ``im/signup.html``.

    ``extra_context``
        An dictionary of variables to add to the template context.

    ``on_success``
        Resolvable view name to redirect on registration success.

    **Template:**

    im/signup.html or ``template_name`` keyword argument.
    """
    extra_context = extra_context or {}
    if request.user.is_authenticated():
        logger.info("%s already signed in, redirect to index",
                    request.user.log_display)
        return HttpResponseRedirect(reverse('index'))

    provider = get_query(request).get('provider', 'local')
    try:
        auth.get_provider(provider)
    except auth.InvalidProvider, e:
        messages.error(request, e.message)
        return HttpResponseRedirect(reverse("signup"))
Пример #6
0
def signup(request, template_name='im/signup.html', on_success='index',
           extra_context=None, activation_backend=None):
    """
    Allows a user to create a local account.

    In case of GET request renders a form for entering the user information.
    In case of POST handles the signup.

    The user activation will be delegated to the backend specified by the
    ``activation_backend`` keyword argument if present, otherwise to the
    ``astakos.im.activation_backends.InvitationBackend`` if
    settings.ASTAKOS_INVITATIONS_ENABLED is True or
    ``astakos.im.activation_backends.SimpleBackend`` if not (see
    activation_backends);

    Upon successful user creation, if ``next`` url parameter is present the
    user is redirected there otherwise renders the same page with a success
    message.

    On unsuccessful creation, renders ``template_name`` with an error message.

    **Arguments**

    ``template_name``
        A custom template to render. This is optional;
        if not specified, this will default to ``im/signup.html``.

    ``extra_context``
        An dictionary of variables to add to the template context.

    ``on_success``
        Resolvable view name to redirect on registration success.

    **Template:**

    im/signup.html or ``template_name`` keyword argument.
    """
    extra_context = extra_context or {}
    if request.user.is_authenticated():
        logger.info("%s already signed in, redirect to index",
                    request.user.log_display)
        return HttpResponseRedirect(reverse('index'))

    provider = get_query(request).get('provider', 'local')
    try:
        auth.get_provider(provider)
    except auth.InvalidProvider, e:
        messages.error(request, e.message)
        return HttpResponseRedirect(reverse("signup"))
Пример #7
0
    def clean(self):
        """
        Override default behavior in order to check user's activation later
        """
        username = self.cleaned_data.get('username')

        if username:
            try:
                user = AstakosUser.objects.get_by_identifier(username)
                if not user.has_auth_provider('local'):
                    provider = auth_providers.get_provider('local', user)
                    msg = provider.get_login_disabled_msg
                    raise forms.ValidationError(mark_safe(msg))
            except AstakosUser.DoesNotExist:
                pass

        try:
            super(LoginForm, self).clean()
        except forms.ValidationError, e:
            if self.user_cache is None:
                raise
            if not self.user_cache.is_active:
                msg = self.user_cache.get_inactive_message('local')
                raise forms.ValidationError(msg)
            if self.request:
                if not self.request.session.test_cookie_worked():
                    raise
Пример #8
0
def populate_user_attributes(provider, provider_info):
    """Populate user attributes based on the providers attribute mapping.

    Map attributes returned by the provider to user attributes based on the
    attribute mapping of the provider. If the value is missing and attribute
    is not mutable (cannot by set by the user) it will fail.

    """
    user_attributes = {}
    if isinstance(provider, basestring):
        provider = auth_providers.get_provider(provider)
    for attr, (provider_attr, mutable) in provider.get_user_attr_map().items():
        try:
            if callable(provider_attr):
                value = provider_attr(provider_info)
            else:
                value = provider_info[provider_attr]
                if isinstance(value, list):
                    value = value[0]
            user_attributes[attr] = smart_unicode(value)
        except (KeyError, IndexError):
            if mutable:
                user_attributes[attr] = None
            else:
                msg = ("Provider '%s' response does not have a value for"
                       " attribute '%s'. Provider returned those attributes:"
                       " %s" % (provider, provider_attr, provider_info))
                logger.error(msg)
                raise ValueError(msg)
    return user_attributes
Пример #9
0
def populate_user_attributes(provider, provider_info):
    """Populate user attributes based on the providers attribute mapping.

    Map attributes returned by the provider to user attributes based on the
    attribute mapping of the provider. If the value is missing and attribute
    is not mutable (cannot by set by the user) it will fail.

    """
    user_attributes = {}
    if isinstance(provider, basestring):
        provider = auth_providers.get_provider(provider)
    for attr, (provider_attr, mutable) in provider.get_user_attr_map().items():
        try:
            if callable(provider_attr):
                value = provider_attr(provider_info)
            else:
                value = provider_info[provider_attr]
                if isinstance(value, list):
                    value = value[0]
            user_attributes[attr] = smart_unicode(value)
        except (KeyError, IndexError):
            if mutable:
                user_attributes[attr] = None
            else:
                msg = ("Provider '%s' response does not have a value for"
                       " attribute '%s'. Provider returned those attributes:"
                       " %s" % (provider, provider_attr, provider_info))
                logger.error(msg)
                raise ValueError(msg)
    return user_attributes
Пример #10
0
def handle_third_party_signup(request, userid, provider_module,
                              third_party_key,
                              provider_info=None,
                              pending_user_params=None,
                              template="im/third_party_check_local.html",
                              extra_context=None):

    if provider_info is None:
        provider_info = {}

    if pending_user_params is None:
        pending_user_params = {}

    if extra_context is None:
        extra_context = {}

    # build provider module object
    provider_data = {
        'affiliation': pending_user_params.get('affiliation', provider_module),
        'info_data': provider_info
    }
    provider = auth.get_provider(provider_module, request.user, userid,
                                 **provider_data)

    # user wants to add another third party login method
    if third_party_key:
        messages.error(request, provider.get_invalid_login_msg)
        return HttpResponseRedirect(reverse('login') + "?key=%s" %
                                    third_party_key)

    if not provider.get_create_policy:
        messages.error(request, provider.get_disabled_for_create_msg)
        return HttpResponseRedirect(reverse('login'))

    # TODO: this could be stored in session
    # TODO: create a management command to clean old PendingThirdPartyUser
    user, created = PendingThirdPartyUser.objects.get_or_create(
        third_party_identifier=userid,
        provider=provider_module,
    )

    # update pending user
    for param, value in pending_user_params.iteritems():
        setattr(user, param, value)

    user.info = json.dumps(provider_info)
    user.generate_token()
    user.save()

    extra_context['provider'] = provider.module
    extra_context['provider_title'] = provider.get_title_msg
    extra_context['token'] = user.token
    extra_context['signup_url'] = reverse('signup') + \
        "?third_party_token=%s" % user.token
    extra_context['add_url'] = reverse('index') + \
        "?key=%s#other-login-methods" % user.token
    extra_context['can_create'] = provider.get_create_policy
    extra_context['can_add'] = provider.get_add_policy

    return HttpResponseRedirect(extra_context['signup_url'])
Пример #11
0
    def clean(self):
        """
        Override default behavior in order to check user's activation later
        """
        username = self.cleaned_data.get('username')

        if username:
            try:
                user = AstakosUser.objects.get_by_identifier(username)
                if not user.has_auth_provider('local'):
                    provider = auth_providers.get_provider('local', user)
                    msg = provider.get_login_disabled_msg
                    raise forms.ValidationError(mark_safe(msg))
            except AstakosUser.DoesNotExist:
                pass

        try:
            super(LoginForm, self).clean()
        except forms.ValidationError, e:
            if self.user_cache is None:
                raise
            if not self.user_cache.is_active:
                msg = self.user_cache.get_inactive_message('local')
                raise forms.ValidationError(msg)
            if self.request:
                if not self.request.session.test_cookie_worked():
                    raise
Пример #12
0
    def clean(self):
        username = self.cleaned_data.get('username')
        password = self.cleaned_data.get('password')

        if username:
            try:
                user = AstakosUser.objects.get_by_identifier(username)
                if not user.has_auth_provider('ldap'):
                    provider = auth_providers.get_provider('ldap', user)
                    msg = provider.get_login_disabled_msg
                    raise forms.ValidationError(mark_safe(msg))
            except AstakosUser.DoesNotExist:
                pass

        # Set user cache to None, so that methods of 'AuthenticationForm'
        # work
        self.user_cache = None

        if username and password:
            self.ldap_user_cache = LDAPBackend().authenticate(username=username,
                                                              password=password)
            if self.ldap_user_cache is None:
                if self.request:
                    if not self.request.session.test_cookie_worked():
                        raise
                raise forms.ValidationError(
                    self.error_messages['invalid_login'])
        self.check_for_test_cookie()
        return self.cleaned_data
Пример #13
0
def _handle_third_party_auto_signup(request, provider, provider_info,
                                    identifier, user_info):
    """Create AstakosUser for third party user without requiring signup form.

    Handle third party signup by automatically creating an AstakosUser. This
    is performed when the user's profile is automatically set by the provider.

    """
    try:
        email = user_info['email']
        first_name = user_info['first_name']
        last_name = user_info['last_name']
    except KeyError as e:
        raise Exception("Invalid user info. Missing '%s'", str(e))

    has_signed_terms = not get_latest_terms()
    user = auth.make_user(email=email,
                          first_name=first_name, last_name=last_name,
                          has_signed_terms=has_signed_terms)

    provider_data = {
        'affiliation': user_info.get('affiliation', provider),
        'info': provider_info
    }
    provider = auth_providers.get_provider(module=provider, user_obj=user,
                                           identifier=identifier,
                                           **provider_data)
    provider.add_to_user()

    # Handle user activation
    activation_backend = activation_backends.get_backend()
    result = activation_backend.handle_registration(user)
    activation_backend.send_result_notifications(result, user)

    return user
Пример #14
0
def password_change(request,
                    template_name='registration/password_change_form.html',
                    post_change_redirect=None,
                    password_change_form=ExtendedPasswordChangeForm):

    create_password = False

    provider = auth.get_provider('local', request.user)

    # no local backend user wants to create a password
    if not request.user.has_auth_provider('local'):
        if not provider.get_add_policy:
            messages.error(request, provider.get_add_disabled_msg)
            return HttpResponseRedirect(reverse('edit_profile'))

        create_password = True
        password_change_form = ExtendedSetPasswordForm

    if post_change_redirect is None:
        post_change_redirect = reverse('edit_profile')

    if request.method == "POST":
        form_kwargs = dict(
            user=request.user,
            data=request.POST,
        )
        if not create_password:
            form_kwargs['session_key'] = request.session.session_key

        form = password_change_form(**form_kwargs)
        if form.is_valid():
            form.save()
            if create_password:
                provider = auth.get_provider('local', request.user)
                messages.success(request, provider.get_added_msg)
            else:
                messages.success(request,
                                 astakos_messages.PASSWORD_RESET_CONFIRM_DONE)
            return HttpResponseRedirect(post_change_redirect)
    else:
        form = password_change_form(user=request.user)
    return render_to_response(template_name, {
        'form': form,
    },
                              context_instance=RequestContext(
                                  request,
                                  {'create_password': create_password}))
Пример #15
0
def handle_third_party_signup(request, userid, provider_module,
                              third_party_key,
                              provider_info=None,
                              pending_user_params=None,
                              template="im/third_party_check_local.html",
                              extra_context=None):

    if provider_info is None:
        provider_info = {}

    if pending_user_params is None:
        pending_user_params = {}

    if extra_context is None:
        extra_context = {}

    # build provider module object
    provider_data = {
        'affiliation': pending_user_params.get('affiliation', provider_module),
        'info_data': provider_info
    }
    provider = auth.get_provider(provider_module, request.user, userid,
                                 **provider_data)

    # user wants to add another third party login method
    if third_party_key:
        messages.error(request, provider.get_invalid_login_msg)
        return HttpResponseRedirect(reverse('login') + "?key=%s" %
                                    third_party_key)

    if not provider.get_create_policy:
        messages.error(request, provider.get_disabled_for_create_msg)
        return HttpResponseRedirect(reverse('login'))

    # TODO: this could be stored in session
    # TODO: create a management command to clean old PendingThirdPartyUser
    user, created = PendingThirdPartyUser.objects.get_or_create(
        third_party_identifier=userid,
        provider=provider_module,
    )

    # update pending user
    for param, value in pending_user_params.iteritems():
        setattr(user, param, value)

    user.info = json.dumps(provider_info)
    user.generate_token()

    # skip non required fields validation errors. Reset the field instead of
    # raising a validation exception.
    try:
        user.full_clean()
    except ValidationError, e:
        non_required_fields = ['email', 'first_name',
                               'last_name', 'affiliation']
        for field in e.message_dict.keys():
            if field in non_required_fields:
                setattr(user, field, None)
Пример #16
0
def handle_third_party_signup(request, userid, provider_module,
                              third_party_key,
                              provider_info=None,
                              pending_user_params=None,
                              template="im/third_party_check_local.html",
                              extra_context=None):

    if provider_info is None:
        provider_info = {}

    if pending_user_params is None:
        pending_user_params = {}

    if extra_context is None:
        extra_context = {}

    # build provider module object
    provider_data = {
        'affiliation': pending_user_params.get('affiliation', provider_module),
        'info_data': provider_info
    }
    provider = auth_providers.get_provider(provider_module, request.user,
                                           userid, **provider_data)

    # user wants to add another third party login method
    if third_party_key:
        messages.error(request, provider.get_invalid_login_msg)
        return HttpResponseRedirect(reverse('login') + "?key=%s" %
                                    third_party_key)

    if not provider.get_create_policy:
        messages.error(request, provider.get_disabled_for_create_msg)
        return HttpResponseRedirect(reverse('login'))

    # TODO: this could be stored in session
    # TODO: create a management command to clean old PendingThirdPartyUser
    user, created = PendingThirdPartyUser.objects.get_or_create(
        third_party_identifier=userid,
        provider=provider_module,
    )

    # update pending user
    for param, value in pending_user_params.iteritems():
        setattr(user, param, value)

    user.info = json.dumps(provider_info)
    user.generate_token()

    # skip non required fields validation errors. Reset the field instead of
    # raising a validation exception.
    try:
        user.full_clean()
    except ValidationError, e:
        non_required_fields = ['email', 'first_name',
                               'last_name', 'affiliation']
        for field in e.message_dict.keys():
            if field in non_required_fields:
                setattr(user, field, None)
Пример #17
0
def password_change(request,
                    template_name='registration/password_change_form.html',
                    post_change_redirect=None,
                    password_change_form=ExtendedPasswordChangeForm):

    create_password = False

    provider = auth.get_provider('local', request.user)

    # no local backend user wants to create a password
    if not request.user.has_auth_provider('local'):
        if not provider.get_add_policy:
            messages.error(request, provider.get_add_disabled_msg)
            return HttpResponseRedirect(reverse('edit_profile'))

        create_password = True
        password_change_form = ExtendedSetPasswordForm

    if post_change_redirect is None:
        post_change_redirect = reverse('edit_profile')

    if request.method == "POST":
        form_kwargs = dict(
            user=request.user,
            data=request.POST,
        )
        if not create_password:
            form_kwargs['session_key'] = request.session.session_key

        form = password_change_form(**form_kwargs)
        if form.is_valid():
            form.save()
            if create_password:
                provider = auth.get_provider('local', request.user)
                messages.success(request, provider.get_added_msg)
            else:
                messages.success(request,
                                 astakos_messages.PASSWORD_RESET_CONFIRM_DONE)
            return HttpResponseRedirect(post_change_redirect)
    else:
        form = password_change_form(user=request.user)
    return render_to_response(template_name, {
        'form': form,
    }, context_instance=RequestContext(request, {'create_password':
                                                 create_password}))
Пример #18
0
def logout(request, template='registration/logged_out.html',
           extra_context=None):
    """
    Wraps `django.contrib.auth.logout`.
    """
    extra_context = extra_context or {}
    response = HttpResponse()
    if request.user.is_authenticated():
        email = request.user.email
        auth_logout(request)
    else:
        response['Location'] = reverse('index')
        response.status_code = 301
        return response

    next = restrict_next(
        request.GET.get('next'),
        domain=settings.COOKIE_DOMAIN
    )

    if next:
        response['Location'] = next
        response.status_code = 302
    elif settings.LOGOUT_NEXT:
        response['Location'] = settings.LOGOUT_NEXT
        response.status_code = 301
    else:
        last_provider = request.COOKIES.get(
            'astakos_last_login_method', 'local')
        try:
            provider = auth.get_provider(last_provider)
        except auth.InvalidProvider:
            provider = auth.get_provider('local')

        message = provider.get_logout_success_msg
        extra = provider.get_logout_success_extra_msg

        if extra:
            message += "<br />" + extra
        messages.success(request, message)
        response['Location'] = reverse('index')
        response.status_code = 301
    return response
Пример #19
0
def logout(request, template='registration/logged_out.html',
           extra_context=None):
    """
    Wraps `django.contrib.auth.logout`.
    """
    extra_context = extra_context or {}
    response = HttpResponse()
    if request.user.is_authenticated():
        email = request.user.email
        auth_logout(request)
    else:
        response['Location'] = reverse('index')
        response.status_code = 301
        return response

    next = restrict_next(
        request.GET.get('next'),
        domain=settings.COOKIE_DOMAIN
    )

    if next:
        response['Location'] = next
        response.status_code = 302
    elif settings.LOGOUT_NEXT:
        response['Location'] = settings.LOGOUT_NEXT
        response.status_code = 301
    else:
        last_provider = request.COOKIES.get(
            'astakos_last_login_method', 'local')
        try:
            provider = auth.get_provider(last_provider)
        except auth.InvalidProvider:
            provider = auth.get_provider('local')

        message = provider.get_logout_success_msg
        extra = provider.get_logout_success_extra_msg

        if extra:
            message += "<br />" + extra
        messages.success(request, message)
        response['Location'] = reverse('index')
        response.status_code = 301
    return response
Пример #20
0
    def clean_email(self):
        email = self.cleaned_data['email']
        if not email:
            raise forms.ValidationError(_(astakos_messages.REQUIRED_FIELD))
        if reserved_verified_email(email):
            provider_id = self.provider
            provider = auth_providers.get_provider(provider_id)
            extra_message = provider.get_add_to_existing_account_msg

            raise forms.ValidationError(mark_safe(
                _(astakos_messages.EMAIL_USED) + ' ' + extra_message))
        return email
Пример #21
0
    def clean_email(self):
        email = self.cleaned_data['email']
        if not email:
            raise forms.ValidationError(_(astakos_messages.REQUIRED_FIELD))
        if reserved_verified_email(email):
            provider_id = self.provider
            provider = auth_providers.get_provider(provider_id)
            extra_message = provider.get_add_to_existing_account_msg

            raise forms.ValidationError(mark_safe(
                _(astakos_messages.EMAIL_USED) + ' ' + extra_message))
        return email
Пример #22
0
        def wrapper(request, *args, **kwargs):
            provider = auth.get_provider(provider_id)

            if not provider or not provider.is_active():
                raise PermissionDenied

            for pkey, value in perms.iteritems():
                attr = 'get_%s_policy' % pkey.lower()
                if getattr(provider, attr) != value:
                    #TODO: add session message
                    return HttpResponseRedirect(reverse('login'))
            return func(request, *args)
Пример #23
0
        def wrapper(request, *args, **kwargs):
            provider = auth.get_provider(provider_id)

            if not provider or not provider.is_active():
                raise PermissionDenied

            for pkey, value in perms.iteritems():
                attr = 'get_%s_policy' % pkey.lower()
                if getattr(provider, attr) != value:
                    #TODO: add session message
                    return HttpResponseRedirect(reverse('login'))
            return func(request, *args)
Пример #24
0
    def save(self, commit=True, **kwargs):
        try:
            self.user = AstakosUser.objects.get(id=self.user.id)
            if settings.NEWPASSWD_INVALIDATE_TOKEN or \
                    self.cleaned_data.get('renew'):
                self.user.renew_token()

            provider = auth_providers.get_provider('local', self.user)
            if provider.get_add_policy:
                provider.add_to_user()

        except BaseException, e:
            logger.exception(e)
Пример #25
0
    def save(self, commit=True):
        try:
            self.user = AstakosUser.objects.get(id=self.user.id)
            if settings.NEWPASSWD_INVALIDATE_TOKEN or \
                    self.cleaned_data.get('renew'):
                self.user.renew_token()

            provider = auth_providers.get_provider('local', self.user)
            if provider.get_add_policy:
                provider.add_to_user()

        except BaseException, e:
            logger.exception(e)
Пример #26
0
    def __init__(self, *args, **kwargs):
        """
        Changes the order of fields, and removes the username field.
        """

        self.provider = kwargs.pop('provider', None)
        self.request = kwargs.pop('request', None)
        if not self.provider or self.provider == 'local':
            raise Exception('Invalid provider, %r' % self.provider)

        # ThirdPartyUserCreationForm should always get instantiated with
        # a third_party_token value
        self.third_party_token = kwargs.pop('third_party_token', None)
        if not self.third_party_token:
            raise Exception('ThirdPartyUserCreationForm'
                            ' requires third_party_token')

        super(ThirdPartyUserCreationForm, self).__init__(*args, **kwargs)

        if not get_latest_terms():
            del self.fields['has_signed_terms']

        if 'has_signed_terms' in self.fields:
            # Overriding field label since we need to apply a link
            # to the terms within the label
            terms_link_html = '<a href="%s" target="_blank">%s</a>' \
                % (reverse('latest_terms'), _("the terms"))
            self.fields['has_signed_terms'].label = \
                mark_safe("I agree with %s" % terms_link_html)

        auth_provider = auth_providers.get_provider(self.provider)
        user_attr_map = auth_provider.get_user_attr_map()
        for field in ['email', 'first_name', 'last_name']:
            if not user_attr_map[field][1]:
                self.ro_fields.append(field)
                self.fields[field].widget.attrs['readonly'] = True
                self.fields[field].help_text = _(READ_ONLY_FIELD_MSG)
Пример #27
0
def handle_third_party_login(request,
                             provider_module,
                             identifier,
                             provider_info=None,
                             affiliation=None,
                             third_party_key=None):

    if not provider_info:
        provider_info = {}

    if not affiliation:
        affiliation = provider_module.title()

    next_redirect = request.GET.get('next',
                                    request.session.get('next_url', None))

    if 'next_url' in request.session:
        del request.session['next_url']

    third_party_request_params = get_third_party_session_params(request)
    from_login = third_party_request_params.get('from_login', False)
    switch_from = third_party_request_params.get('switch_from', False)
    provider_data = {'affiliation': affiliation, 'info': provider_info}

    provider = auth.get_provider(provider_module, request.user, identifier,
                                 **provider_data)

    # an existing user accessed the view
    if request.user.is_authenticated():
        if request.user.has_auth_provider(provider.module,
                                          identifier=identifier):
            return HttpResponseRedirect(reverse('edit_profile'))

        if provider.verified_exists():
            provider.log("add failed (identifier exists to another user)")
            messages.error(request, provider.get_add_exists_msg)
            return HttpResponseRedirect(reverse('edit_profile'))

        # automatically add identifier provider to user
        if not switch_from and not provider.get_add_policy:
            # TODO: handle existing uuid message separately
            provider.log("user cannot add provider")
            messages.error(request, provider.get_add_failed_msg)
            return HttpResponseRedirect(reverse('edit_profile'))

        user = request.user
        if switch_from:
            existing_provider = \
                request.user.auth_providers.active().get(
                    pk=int(switch_from), module=provider_module).settings

            # this is not a provider removal so we don't not use
            # provider.remove_from_user. Use low level access to the provider
            # db instance.
            if not provider.verified_exists():
                if provider.get_add_policy:
                    existing_provider._instance.delete()
                    existing_provider.log("removed")
                    provider.add_to_user()
                    provider.log("added")
            else:
                messages.error(request, provider.get_add_exists_msg)
                return HttpResponseRedirect(reverse('edit_profile'))

            messages.success(request, provider.get_switch_success_msg)
            return HttpResponseRedirect(reverse('edit_profile'))

        provider.add_to_user()
        provider.log("added")
        provider = user.get_auth_provider(provider_module, identifier)
        messages.success(request, provider.get_added_msg)
        return HttpResponseRedirect(reverse('edit_profile'))

    # astakos user exists ?
    try:
        user = AstakosUser.objects.get_auth_provider_user(
            provider_module,
            identifier=identifier,
            user__email_verified=True,
        )
    except AstakosUser.DoesNotExist:
        # TODO: add a message ? redirec to login ?
        if astakos_messages.AUTH_PROVIDER_SIGNUP_FROM_LOGIN:
            messages.warning(request,
                             astakos_messages.AUTH_PROVIDER_SIGNUP_FROM_LOGIN)
        raise

    if not third_party_key:
        third_party_key = get_pending_key(request)

    provider = user.get_auth_provider(provider_module, identifier)
    if user.is_active:
        if not provider.get_login_policy:
            messages.error(request, provider.get_login_disabled_msg)
            return HttpResponseRedirect(reverse('login'))

        # authenticate user
        response = prepare_response(request, user, next_redirect, 'renew'
                                    in request.GET)

        messages.success(request, provider.get_login_success_msg)
        add_pending_auth_provider(request, third_party_key, provider)
        response.set_cookie('astakos_last_login_method', provider_module)
        return response
    else:
        message = user.get_inactive_message(provider_module, identifier)
        messages.error(request, message)
        return HttpResponseRedirect(login_url(request))
Пример #28
0
def signup(request,
           template_name='im/signup.html',
           on_success='index',
           extra_context=None,
           activation_backend=None):
    """
    Allows a user to create a local account.

    In case of GET request renders a form for entering the user information.
    In case of POST handles the signup.

    The user activation will be delegated to the backend specified by the
    ``activation_backend`` keyword argument if present, otherwise to the
    ``astakos.im.activation_backends.InvitationBackend`` if
    settings.ASTAKOS_INVITATIONS_ENABLED is True or
    ``astakos.im.activation_backends.SimpleBackend`` if not (see
    activation_backends);

    Upon successful user creation, if ``next`` url parameter is present the
    user is redirected there otherwise renders the same page with a success
    message.

    On unsuccessful creation, renders ``template_name`` with an error message.

    **Arguments**

    ``template_name``
        A custom template to render. This is optional;
        if not specified, this will default to ``im/signup.html``.

    ``extra_context``
        An dictionary of variables to add to the template context.

    ``on_success``
        Resolvable view name to redirect on registration success.

    **Template:**

    im/signup.html or ``template_name`` keyword argument.
    """
    extra_context = extra_context or {}
    if request.user.is_authenticated():
        logger.info("%s already signed in, redirect to index",
                    request.user.log_display)
        transaction.rollback()
        return HttpResponseRedirect(reverse('index'))

    provider = get_query(request).get('provider', 'local')
    if not auth.get_provider(provider).get_create_policy:
        logger.error("%s provider not available for signup", provider)
        transaction.rollback()
        raise PermissionDenied

    instance = None

    # user registered using third party provider
    third_party_token = request.REQUEST.get('third_party_token', None)
    unverified = None
    if third_party_token:
        # retreive third party entry. This was created right after the initial
        # third party provider handshake.
        pending = get_object_or_404(PendingThirdPartyUser,
                                    token=third_party_token)

        provider = pending.provider

        # clone third party instance into the corresponding AstakosUser
        instance = pending.get_user_instance()
        get_unverified = AstakosUserAuthProvider.objects.unverified

        # check existing unverified entries
        unverified = get_unverified(pending.provider,
                                    identifier=pending.third_party_identifier)

        if unverified and request.method == 'GET':
            messages.warning(request, unverified.get_pending_registration_msg)
            if unverified.user.moderated:
                messages.warning(request,
                                 unverified.get_pending_resend_activation_msg)
            else:
                messages.warning(request,
                                 unverified.get_pending_moderation_msg)

    # prepare activation backend based on current request
    if not activation_backend:
        activation_backend = activation_backends.get_backend()

    form_kwargs = {'instance': instance, 'request': request}
    if third_party_token:
        form_kwargs['third_party_token'] = third_party_token

    form = activation_backend.get_signup_form(provider, None, **form_kwargs)

    if request.method == 'POST':
        form = activation_backend.get_signup_form(provider, request.POST,
                                                  **form_kwargs)

        if form.is_valid():
            commited = False
            try:
                user = form.save(commit=False)

                # delete previously unverified accounts
                if AstakosUser.objects.user_exists(user.email):
                    AstakosUser.objects.get_by_identifier(user.email).delete()

                # store_user so that user auth providers get initialized
                form.store_user(user, request)
                result = activation_backend.handle_registration(user)
                if result.status == \
                        activation_backend.Result.PENDING_MODERATION:
                    # user should be warned that his account is not active yet
                    status = messages.WARNING
                else:
                    status = messages.SUCCESS
                message = result.message
                activation_backend.send_result_notifications(result, user)

                # commit user entry
                transaction.commit()
                # commited flag
                # in case an exception get raised from this point
                commited = True

                if user and user.is_active:
                    # activation backend directly activated the user
                    # log him in
                    next = request.POST.get('next', '')
                    response = prepare_response(request, user, next=next)
                    return response

                messages.add_message(request, status, message)
                return HttpResponseRedirect(reverse(on_success))
            except Exception, e:
                if not commited:
                    transaction.rollback()
                raise
Пример #29
0
def login(request,
          template_name="im/login.html",
          on_failure='im/login.html',
          signup_template="/im/third_party_check_local.html",
          extra_context=None):
    """
    on_failure: the template name to render on login failure
    """
    if request.method == 'GET':
        return handle_get_to_login_view(request,
                                        primary_provider=LDAP_PROVIDER,
                                        login_form=LDAPLoginForm(request),
                                        template_name=template_name,
                                        extra_context=extra_context)

    # 'limited' attribute is used by recapatcha
    was_limited = getattr(request, 'limited', False)
    next = get_query(request).get('next', '')
    third_party_token = get_query(request).get('key', False)

    form = LDAPLoginForm(data=request.POST,
                         was_limited=was_limited,
                         request=request)
    provider = LDAP_PROVIDER

    if not form.is_valid():
        if third_party_token:
            messages.info(request, provider.get_login_to_add_msg)

        return render_to_response(on_failure, {
            'login_form': form,
            'next': next,
            'key': third_party_token
        },
                                  context_instance=get_context(
                                      request, primary_provider=LDAP_PROVIDER))

    # get the user from the cache
    user = form.ldap_user_cache
    provider = auth.get_provider('ldap', user)

    affiliation = 'LDAP'
    provider_info = dict(user.ldap_user.attrs)
    try:
        user_info = populate_user_attributes(provider, provider_info)
        user_id = user_info.pop('identifier')
    except (ValueError, KeyError):
        logger.exception(
            "Failed to map attributes from LDAP provider."
            " Provider attributes: %s", provider_info)
        msg = 'Invalid LDAP response. Please contact support.'
        messages.error(request, msg)
        return HttpResponseRedirect(reverse('login'))

    provider_info = dict([(k, smart_unicode(v, errors="ignore"))
                          for k, v in provider_info.items()
                          if k in provider.get_provider_info_attributes()])

    user_info['affiliation'] = affiliation

    if hasattr(user, 'group_names') and provider.get_policy('mirror_groups'):
        groups = [
            Group.objects.get_or_create(name=group_name)[0]
            for group_name in user.group_names
        ]
        user_info['groups'] = groups

    try:
        return handle_third_party_login(request,
                                        provider_module="ldap",
                                        identifier=user_id,
                                        provider_info=provider_info,
                                        affiliation=affiliation,
                                        user_info=user_info)
    except AstakosUser.DoesNotExist:
        third_party_key = get_pending_key(request)
        return handle_third_party_signup(request, user_id, 'ldap',
                                         third_party_key, provider_info,
                                         user_info, signup_template,
                                         extra_context)
Пример #30
0
def login(request, template_name="im/login.html", on_failure='im/login.html',
          signup_template="/im/third_party_check_local.html",
          extra_context=None):
    """
    on_failure: the template name to render on login failure
    """
    if request.method == 'GET':
        return handle_get_to_login_view(request,
                                        primary_provider=LDAP_PROVIDER,
                                        login_form=LDAPLoginForm(request),
                                        template_name=template_name,
                                        extra_context=extra_context)

    # 'limited' attribute is used by recapatcha
    was_limited = getattr(request, 'limited', False)
    next = get_query(request).get('next', '')
    third_party_token = get_query(request).get('key', False)

    form = LDAPLoginForm(data=request.POST,
                         was_limited=was_limited,
                         request=request)
    provider = LDAP_PROVIDER

    if not form.is_valid():
        if third_party_token:
            messages.info(request, provider.get_login_to_add_msg)

        return render_to_response(
            on_failure,
            {'login_form': form,
             'next': next,
             'key': third_party_token},
            context_instance=get_context(request,
                                         primary_provider=LDAP_PROVIDER))

    # get the user from the cache
    user = form.ldap_user_cache
    provider = auth.get_provider('ldap', user)

    affiliation = 'LDAP'
    provider_info = dict(user.ldap_user.attrs)
    try:
        user_info = populate_user_attributes(provider, provider_info)
        user_id = user_info.pop('identifier')
    except (ValueError, KeyError):
        logger.exception("Failed to map attributes from LDAP provider."
                         " Provider attributes: %s", provider_info)
        msg = 'Invalid LDAP response. Please contact support.'
        messages.error(request, msg)
        return HttpResponseRedirect(reverse('login'))

    provider_info = dict([(k, smart_unicode(v, errors="ignore"))
                          for k, v in provider_info.items()
                          if k in provider.get_provider_info_attributes()])

    user_info['affiliation'] = affiliation

    if hasattr(user, 'group_names') and provider.get_policy('mirror_groups'):
        groups = [Group.objects.get_or_create(name=group_name)[0]
                  for group_name in user.group_names]
        user_info['groups'] = groups

    try:
        return handle_third_party_login(request, provider_module="ldap",
                                        identifier=user_id,
                                        provider_info=provider_info,
                                        affiliation=affiliation,
                                        user_info=user_info)
    except AstakosUser.DoesNotExist:
        third_party_key = get_pending_key(request)
        return handle_third_party_signup(request, user_id, 'ldap',
                                         third_party_key,
                                         provider_info,
                                         user_info,
                                         signup_template,
                                         extra_context)
Пример #31
0
from astakos.im.views.util import render_response
from astakos.im.forms import LDAPLoginForm
from astakos.im.util import get_query, get_context
from astakos.im.views.im import handle_get_to_login_view
from django.shortcuts import render_to_response
from django.utils.encoding import smart_unicode
from astakos.im.views.decorators import login_required

import logging

retries = settings.RATELIMIT_RETRIES_ALLOWED - 1
rate = str(retries) + '/m'

logger = logging.getLogger(__name__)

LDAP_PROVIDER = auth.get_provider('ldap')


@requires_auth_provider('ldap')
@require_http_methods(["GET", "POST"])
@csrf_exempt
@requires_anonymous
@cookie_fix
@ratelimit(field='username', method='POST', rate=rate)
def login(request,
          template_name="im/login.html",
          on_failure='im/login.html',
          signup_template="/im/third_party_check_local.html",
          extra_context=None):
    """
    on_failure: the template name to render on login failure
Пример #32
0
from synnefo.lib.services import get_public_endpoint
from astakos.im.user_utils import send_feedback, logout as auth_logout, \
    invite as invite_func, change_user_email
from astakos.im import settings
from astakos.im import presentation
from astakos.im import auth_providers as auth
from astakos.im import quotas
from astakos.im.views.util import render_response, _resources_catalog
from astakos.im.views.decorators import cookie_fix, signed_terms_required,\
    required_auth_methods_assigned, valid_astakos_user_required, login_required
from astakos.api import projects as projects_api
from astakos.api.util import _dthandler

logger = logging.getLogger(__name__)

PRIMARY_PROVIDER = auth.get_provider(settings.IM_MODULES[0])


def handle_get_to_login_view(request,
                             primary_provider,
                             login_form,
                             template_name="im/login.html",
                             extra_context=None):
    """Common handling of a GET request to a login view.

    Handle a GET request to a login view either by redirecting the user
    to landing page in case the user is authenticated, or by rendering
    the login template with the 'primary_provider' correctly set.

    """
    extra_context = extra_context or {}
Пример #33
0
from astakos.im.models import PendingThirdPartyUser
from astakos.im.forms import LoginForm, ExtendedPasswordChangeForm, \
    ExtendedSetPasswordForm
from astakos.im import settings
import astakos.im.messages as astakos_messages
from astakos.im import auth_providers as auth
from astakos.im.views.util import render_response
from astakos.im.views.decorators import cookie_fix, requires_anonymous, \
    signed_terms_required, requires_auth_provider, login_required

from ratelimit.decorators import ratelimit

retries = settings.RATELIMIT_RETRIES_ALLOWED - 1
rate = str(retries) + '/m'

LOCAL_PROVIDER = auth.get_provider('local')


@requires_auth_provider('local')
@require_http_methods(["GET", "POST"])
@csrf_exempt
@requires_anonymous
@cookie_fix
@ratelimit(field='username', method='POST', rate=rate)
def login(request, template_name="im/login.html", on_failure='im/login.html',
          extra_context=None):
    """
    on_failure: the template name to render on login failure
    """
    if request.method == 'GET':
        extra_context = extra_context or {}
Пример #34
0
            return None

        if user.check_password(password):
            return user
        else:
            msg = 'Invalid password during authentication for %s'
            logger.log(settings.LOGGING_LEVEL, msg, username)

    def get_user(self, user_id):
        try:
            return AstakosUser.objects.get(pk=user_id)
        except AstakosUser.DoesNotExist:
            return None


LDAP_PROVIDER = auth.get_provider('ldap')


class MockedAstakosUser(object):
    """Mock AstakosUser object to be used by LDAPBackend.

    The 'LDAPAuthenticationBackend' requires the creation or existence of an
    Django User object. However, the creation of the 'AstakosUser' by the
    'LDAPAuthenticationBackend' does not match with how Astakos is handling
    thirt party authentication providers. To overcome this issue we create
    a mock object, whose attributes will be populated by the
    'LDAPAuthenticationBackend'.

    """
    def set_unusable_password(self):
        pass
Пример #35
0
from synnefo.lib.services import get_public_endpoint
from astakos.im.user_utils import send_feedback, logout as auth_logout, \
    invite as invite_func, change_user_email
from astakos.im import settings
from astakos.im import presentation
from astakos.im import auth_providers as auth
from astakos.im import quotas
from astakos.im.views.util import render_response, _resources_catalog
from astakos.im.views.decorators import cookie_fix, signed_terms_required,\
    required_auth_methods_assigned, valid_astakos_user_required, login_required
from astakos.api import projects as projects_api
from astakos.api.util import _dthandler

logger = logging.getLogger(__name__)

PRIMARY_PROVIDER = auth.get_provider(settings.IM_MODULES[0])


def handle_get_to_login_view(request, primary_provider, login_form,
                             template_name="im/login.html",
                             extra_context=None):
    """Common handling of a GET request to a login view.

    Handle a GET request to a login view either by redirecting the user
    to landing page in case the user is authenticated, or by rendering
    the login template with the 'primary_provider' correctly set.

    """
    extra_context = extra_context or {}

    third_party_token = request.GET.get('key', False)
Пример #36
0
def handle_third_party_signup(request,
                              userid,
                              provider_module,
                              third_party_key,
                              provider_info=None,
                              pending_user_params=None,
                              template="im/third_party_check_local.html",
                              extra_context=None):

    if provider_info is None:
        provider_info = {}

    if pending_user_params is None:
        pending_user_params = {}

    if extra_context is None:
        extra_context = {}

    # build provider module object
    provider_data = {
        'affiliation': pending_user_params.get('affiliation', provider_module),
        'info_data': provider_info
    }
    provider = auth.get_provider(provider_module, request.user, userid,
                                 **provider_data)

    # user wants to add another third party login method
    if third_party_key:
        messages.error(request, provider.get_invalid_login_msg)
        return HttpResponseRedirect(
            reverse('login') + "?key=%s" % third_party_key)

    if not provider.get_create_policy:
        messages.error(request, provider.get_disabled_for_create_msg)
        return HttpResponseRedirect(reverse('login'))

    # TODO: this could be stored in session
    # TODO: create a management command to clean old PendingThirdPartyUser
    user, created = PendingThirdPartyUser.objects.get_or_create(
        third_party_identifier=userid,
        provider=provider_module,
    )

    # update pending user
    for param, value in pending_user_params.iteritems():
        setattr(user, param, value)

    user.info = json.dumps(provider_info)
    user.generate_token()
    user.save()

    extra_context['provider'] = provider.module
    extra_context['provider_title'] = provider.get_title_msg
    extra_context['token'] = user.token
    extra_context['signup_url'] = reverse('signup') + \
        "?third_party_token=%s" % user.token
    extra_context['add_url'] = reverse('index') + \
        "?key=%s#other-login-methods" % user.token
    extra_context['can_create'] = provider.get_create_policy
    extra_context['can_add'] = provider.get_add_policy

    return HttpResponseRedirect(extra_context['signup_url'])
Пример #37
0
    im/signup.html or ``template_name`` keyword argument.
    """
    extra_context = extra_context or {}
    if request.user.is_authenticated():
        logger.info("%s already signed in, redirect to index",
                    request.user.log_display)
        return HttpResponseRedirect(reverse('index'))

    provider = get_query(request).get('provider', 'local')
    try:
        auth.get_provider(provider)
    except auth.InvalidProvider, e:
        messages.error(request, e.message)
        return HttpResponseRedirect(reverse("signup"))

    if not auth.get_provider(provider).get_create_policy:
        logger.error("%s provider not available for signup", provider)
        raise PermissionDenied

    instance = None

    # user registered using third party provider
    third_party_token = request.REQUEST.get('third_party_token', None)
    unverified = None
    pending = None
    if third_party_token:
        # retreive third party entry. This was created right after the initial
        # third party provider handshake.
        pending = get_object_or_404(PendingThirdPartyUser,
                                    token=third_party_token)
Пример #38
0
def login(request, on_failure='im/login.html'):
    """
    on_failure: the template name to render on login failure
    """
    if request.method == 'GET':
        return HttpResponseRedirect(reverse('login'))

    was_limited = getattr(request, 'limited', False)
    form = LoginForm(data=request.POST,
                     was_limited=was_limited,
                     request=request)
    next = get_query(request).get('next', '')
    third_party_token = get_query(request).get('key', False)
    provider = auth.get_provider('local')

    if not form.is_valid():
        if third_party_token:
            messages.info(request, provider.get_login_to_add_msg)

        return render_to_response(on_failure, {
            'login_form': form,
            'next': next,
            'key': third_party_token
        },
                                  context_instance=RequestContext(request))

    # get the user from the cache
    user = form.user_cache
    provider = auth.get_provider('local', user)

    if not provider.get_login_policy:
        message = provider.get_login_disabled_msg
        messages.error(request, message)
        return HttpResponseRedirect(reverse('login'))

    message = None
    if not user:
        message = provider.get_authentication_failed_msg
    elif not user.is_active:
        message = user.get_inactive_message('local')

    elif not user.has_auth_provider('local'):
        # valid user logged in with no auth providers set, add local provider
        # and let him log in
        if not user.get_available_auth_providers():
            user.add_auth_provider('local')
        else:
            message = _(astakos_messages.NO_LOCAL_AUTH)

    if message:
        messages.error(request, message)
        return render_to_response(on_failure, {'login_form': form},
                                  context_instance=RequestContext(request))

    response = prepare_response(request, user, next)
    if third_party_token:
        # use requests to assign the account he just authenticated with with
        # a third party provider account
        try:
            request.user.add_pending_auth_provider(third_party_token)
        except PendingThirdPartyUser.DoesNotExist:
            provider = auth.get_provider('local', request.user)
            messages.error(request, provider.get_add_failed_msg)

    provider = user.get_auth_provider('local')
    messages.success(request, provider.get_login_success_msg)
    response.set_cookie('astakos_last_login_method', 'local')
    return response
Пример #39
0
def login(request, template_name="im/login.html", on_failure='im/login.html',
          extra_context=None):
    """
    on_failure: the template name to render on login failure
    """
    if request.method == 'GET':
        extra_context = extra_context or {}

        third_party_token = request.GET.get('key', False)
        if third_party_token:
            messages.info(request, astakos_messages.AUTH_PROVIDER_LOGIN_TO_ADD)

        if request.user.is_authenticated():
            return HttpResponseRedirect(reverse('landing'))

        extra_context["primary_provider"] = LOCAL_PROVIDER

        return render_response(
            template_name,
            login_form=LoginForm(request=request),
            context_instance=get_context(request, extra_context)
        )

    was_limited = getattr(request, 'limited', False)
    form = LoginForm(data=request.POST,
                     was_limited=was_limited,
                     request=request)
    next = get_query(request).get('next', '')
    third_party_token = get_query(request).get('key', False)
    provider = auth.get_provider('local')

    if not form.is_valid():
        if third_party_token:
            messages.info(request, provider.get_login_to_add_msg)

        return render_to_response(
            on_failure,
            {'login_form': form,
             'next': next,
             'key': third_party_token},
            context_instance=get_context(request,
                                         primary_provider=LOCAL_PROVIDER))

    # get the user from the cache
    user = form.user_cache
    provider = auth.get_provider('local', user)

    if not provider.get_login_policy:
        message = provider.get_login_disabled_msg
        messages.error(request, message)
        return HttpResponseRedirect(reverse('login'))

    message = None
    if not user:
        message = provider.get_authentication_failed_msg
    elif not user.is_active:
        message = user.get_inactive_message('local')

    elif not user.has_auth_provider('local'):
        # valid user logged in with no auth providers set, add local provider
        # and let him log in
        if not user.get_available_auth_providers():
            user.add_auth_provider('local')
        else:
            message = _(astakos_messages.NO_LOCAL_AUTH)

    if message:
        messages.error(request, message)
        return render_to_response(on_failure,
                                  {'login_form': form},
                                  context_instance=RequestContext(request))

    response = prepare_response(request, user, next)
    if third_party_token:
        # use requests to assign the account he just authenticated with with
        # a third party provider account
        try:
            request.user.add_pending_auth_provider(third_party_token)
        except PendingThirdPartyUser.DoesNotExist:
            provider = auth.get_provider('local', request.user)
            messages.error(request, provider.get_add_failed_msg)

    provider = user.get_auth_provider('local')
    messages.success(request, provider.get_login_success_msg)
    response.set_cookie('astakos_last_login_method', 'local')
    provider.update_last_login_at()

    return response
Пример #40
0
def signup(request, template_name='im/signup.html', on_success='index',
           extra_context=None, activation_backend=None):
    """
    Allows a user to create a local account.

    In case of GET request renders a form for entering the user information.
    In case of POST handles the signup.

    The user activation will be delegated to the backend specified by the
    ``activation_backend`` keyword argument if present, otherwise to the
    ``astakos.im.activation_backends.InvitationBackend`` if
    settings.ASTAKOS_INVITATIONS_ENABLED is True or
    ``astakos.im.activation_backends.SimpleBackend`` if not (see
    activation_backends);

    Upon successful user creation, if ``next`` url parameter is present the
    user is redirected there otherwise renders the same page with a success
    message.

    On unsuccessful creation, renders ``template_name`` with an error message.

    **Arguments**

    ``template_name``
        A custom template to render. This is optional;
        if not specified, this will default to ``im/signup.html``.

    ``extra_context``
        An dictionary of variables to add to the template context.

    ``on_success``
        Resolvable view name to redirect on registration success.

    **Template:**

    im/signup.html or ``template_name`` keyword argument.
    """
    extra_context = extra_context or {}
    if request.user.is_authenticated():
        logger.info("%s already signed in, redirect to index",
                    request.user.log_display)
        return HttpResponseRedirect(reverse('index'))

    provider = get_query(request).get('provider', 'local')
    if not auth.get_provider(provider).get_create_policy:
        logger.error("%s provider not available for signup", provider)
        raise PermissionDenied

    instance = None

    # user registered using third party provider
    third_party_token = request.REQUEST.get('third_party_token', None)
    unverified = None
    if third_party_token:
        # retreive third party entry. This was created right after the initial
        # third party provider handshake.
        pending = get_object_or_404(PendingThirdPartyUser,
                                    token=third_party_token)

        provider = pending.provider

        # clone third party instance into the corresponding AstakosUser
        instance = pending.get_user_instance()
        get_unverified = AstakosUserAuthProvider.objects.unverified

        # check existing unverified entries
        unverified = get_unverified(pending.provider,
                                    identifier=pending.third_party_identifier)

        if unverified and request.method == 'GET':
            messages.warning(request, unverified.get_pending_registration_msg)
            if unverified.user.moderated:
                messages.warning(request,
                                 unverified.get_pending_resend_activation_msg)
            else:
                messages.warning(request,
                                 unverified.get_pending_moderation_msg)

    # prepare activation backend based on current request
    if not activation_backend:
        activation_backend = activation_backends.get_backend()

    form_kwargs = {'instance': instance, 'request': request}
    if third_party_token:
        form_kwargs['third_party_token'] = third_party_token

    form = activation_backend.get_signup_form(
        provider, None, **form_kwargs)

    if request.method == 'POST':
        form = activation_backend.get_signup_form(
            provider,
            request.POST,
            **form_kwargs)

        if form.is_valid():
            user = form.save(commit=False)

            # delete previously unverified accounts
            if AstakosUser.objects.user_exists(user.email):
                AstakosUser.objects.get_by_identifier(user.email).delete()

            # store_user so that user auth providers get initialized
            form.store_user(user, request)
            result = activation_backend.handle_registration(user)
            if result.status == \
                    activation_backend.Result.PENDING_MODERATION:
                # user should be warned that his account is not active yet
                status = messages.WARNING
            else:
                status = messages.SUCCESS
            message = result.message
            activation_backend.send_result_notifications(result, user)

            # commit user entry
            transaction.commit()

            if user and user.is_active:
                # activation backend directly activated the user
                # log him in
                next = request.POST.get('next', '')
                response = prepare_response(request, user, next=next)
                return response

            messages.add_message(request, status, message)
            return HttpResponseRedirect(reverse(on_success))

    return render_response(template_name,
                           signup_form=form,
                           third_party_token=third_party_token,
                           provider=provider,
                           context_instance=get_context(request, extra_context))
Пример #41
0
def handle_third_party_login(request, provider_module, identifier,
                             provider_info=None, affiliation=None,
                             third_party_key=None):

    if not provider_info:
        provider_info = {}

    if not affiliation:
        affiliation = provider_module.title()

    next_redirect = request.GET.get(
        'next', request.session.get('next_url', None))

    if 'next_url' in request.session:
        del request.session['next_url']

    third_party_request_params = get_third_party_session_params(request)
    from_login = third_party_request_params.get('from_login', False)
    switch_from = third_party_request_params.get('switch_from', False)
    provider_data = {
        'affiliation': affiliation,
        'info': provider_info
    }

    provider = auth.get_provider(provider_module, request.user, identifier,
                                 **provider_data)

    # an existing user accessed the view
    if request.user.is_authenticated():
        if request.user.has_auth_provider(provider.module,
                                          identifier=identifier):
            return HttpResponseRedirect(reverse('edit_profile'))

        if provider.verified_exists():
            provider.log("add failed (identifier exists to another user)")
            messages.error(request, provider.get_add_exists_msg)
            return HttpResponseRedirect(reverse('edit_profile'))

        # automatically add identifier provider to user
        if not switch_from and not provider.get_add_policy:
            # TODO: handle existing uuid message separately
            provider.log("user cannot add provider")
            messages.error(request, provider.get_add_failed_msg)
            return HttpResponseRedirect(reverse('edit_profile'))

        user = request.user
        if switch_from:
            existing_provider = \
                request.user.auth_providers.active().get(
                    pk=int(switch_from), module=provider_module).settings

            # this is not a provider removal so we don't not use
            # provider.remove_from_user. Use low level access to the provider
            # db instance.
            if not provider.verified_exists():
                if provider.get_add_policy:
                    existing_provider._instance.delete()
                    existing_provider.log("removed")
                    provider.add_to_user()
                    provider.log("added")
            else:
                messages.error(request, provider.get_add_exists_msg)
                return HttpResponseRedirect(reverse('edit_profile'))

            messages.success(request, provider.get_switch_success_msg)
            return HttpResponseRedirect(reverse('edit_profile'))

        provider.add_to_user()
        provider.log("added")
        provider = user.get_auth_provider(provider_module, identifier)
        messages.success(request, provider.get_added_msg)
        return HttpResponseRedirect(reverse('edit_profile'))

    # astakos user exists ?
    try:
        user = AstakosUser.objects.get_auth_provider_user(
            provider_module,
            identifier=identifier,
            user__email_verified=True,
        )
    except AstakosUser.DoesNotExist:
        # TODO: add a message ? redirec to login ?
        if astakos_messages.AUTH_PROVIDER_SIGNUP_FROM_LOGIN:
            messages.warning(request,
                             astakos_messages.AUTH_PROVIDER_SIGNUP_FROM_LOGIN)
        raise

    if not third_party_key:
        third_party_key = get_pending_key(request)

    provider = user.get_auth_provider(provider_module, identifier)
    if user.is_active:
        if not provider.get_login_policy:
            messages.error(request, provider.get_login_disabled_msg)
            return HttpResponseRedirect(reverse('login'))

        # authenticate user
        response = prepare_response(request, user, next_redirect,
                                    'renew' in request.GET)

        messages.success(request, provider.get_login_success_msg)
        add_pending_auth_provider(request, third_party_key, provider)
        response.set_cookie('astakos_last_login_method', provider_module)
        return response
    else:
        message = user.get_inactive_message(provider_module, identifier)
        messages.error(request, message)
        return HttpResponseRedirect(login_url(request))