Exemple #1
0
 def _run_test(username):
     try:
         result = get_account_username_split(username)
         self.fail("get_account_username_split did not raise an "
                 "exception when provided username for a non unlinked "
                 "Institution.\n'%s' returned '%s'" % (username, result))
     except ValueError:
         pass
Exemple #2
0
def link_from_profile(request, institution):
    """
    Attempts to authenticate a CAS account for the provided
    institution, and links it to the current Uniauth profile
    if successful.
    """
    next_url = request.GET.get('next')
    ticket = request.GET.get('ticket')

    # Ensure there is an institution with the provided slug
    try:
        institution = Institution.objects.get(slug=institution)
    except Institution.DoesNotExist:
        raise Http404

    if not next_url:
        next_url = get_redirect_url(request, use_referer=True)

    # If the user is not already logged into a verified
    # Uniauth account, raise permission denied
    if not request.user.is_authenticated or is_tmp_user(request.user) \
            or is_unlinked_account(request.user):
        raise PermissionDenied("Must be logged in as verified Uniauth user.")

    service_url = get_service_url(request, next_url)
    client = CASClient(version=2,
                       service_url=service_url,
                       server_url=institution.cas_server_url)

    # If a ticket was provided, attempt to authenticate with it
    if ticket:
        user = authenticate(request=request,
                            institution=institution,
                            ticket=ticket,
                            service=service_url)

        # Authentication successful: link to Uniauth profile if
        # the institution account has not been linked yet + proceed
        if user:
            if is_unlinked_account(user):
                merge_model_instances(request.user, [user])
                username_split = get_account_username_split(user.username)
                _add_institution_account(request.user.profile,
                                         username_split[1], username_split[2])

            return HttpResponseRedirect(next_url)

        # Authentication failed: raise permission denied
        else:
            raise PermissionDenied("Verification of CAS ticket failed")

    # If no ticket was provided, redirect to the
    # login URL for the institution's CAS server
    else:
        return HttpResponseRedirect(client.get_login_url())
Exemple #3
0
    def get_display_id(self):
        """
        Returns a display-friendly ID for this User, using their
        username. Users created via CAS authentication will have
        their CAS ID returned (without the cas-institution prefix),
        and Users with an email address for a username will have
        the string preceeding the "@" returned. All other users
        will have their raw username returned.

        Note that these IDs are not guaranteed to be unique.
        """
        username = self.user.username
        if "@" in username:
            return username.split("@")[0]
        if username.startswith('cas-'):
            from uniauth.utils import get_account_username_split
            return get_account_username_split(username)[-1]
        return username
Exemple #4
0
def verify_token(request, pk_base64, token):
    """
    Verifies a token generated for validating an email
    address, and notifies the user whether verification
    was successful.
    """
    next_url = request.GET.get('next') or request.GET.get(REDIRECT_FIELD_NAME)
    context = {'next_url': next_url, 'is_signup': False}
    user_model = get_user_model()

    # Attempt to get the linked email to verify
    try:
        email_pk = decode_pk(pk_base64)
        email = LinkedEmail.objects.get(pk=email_pk)
    except (TypeError, ValueError, OverflowError, user_model.DoesNotExist,
            LinkedEmail.DoesNotExist):
        email = None

    # In the unlikely scenario that a user is trying to sign up
    # with an email another verified user has as a primary email
    # address, reject verification immediately
    if email is not None and is_tmp_user(email.profile.user) and \
            get_user_model().objects.filter(email=email.address).exists():
        email = None

    # If the token successfully verifies, update the linked email
    if email is not None and token_generator.check_token(email, token):
        email.is_verified = True
        email.save()

        # If the user this email is linked to is a temporary
        # one, change it to a fully registered user
        user = email.profile.user
        if is_tmp_user(user) or is_unlinked_account(user):
            context['is_signup'] = True
            old_username = user.username

            # Change the email + username to the verified email
            user.email = email.address
            user.username = choose_username(user.email)
            user.save()

            # If the user was created via CAS, add the institution
            # account described by the temporary username
            if old_username.startswith("cas"):
                username_split = get_account_username_split(old_username)
                _add_institution_account(user.profile, username_split[1],
                                         username_split[2])

        # If UNIAUTH_ALLOW_SHARED_EMAILS is False, and there were
        # pending LinkedEmails for this address on other accounts,
        # delete them
        if not get_setting('UNIAUTH_ALLOW_SHARED_EMAILS'):
            LinkedEmail.objects.filter(address=email.address,
                                       is_verified=False).delete()

        return render(request, 'uniauth/verification-success.html', context)

    # If anything went wrong, just render the failed verification template
    else:
        return render(request, 'uniauth/verification-failure.html', context)
Exemple #5
0
def link_to_profile(request):
    """
    If the user is a temporary one who was logged in via
    an institution (not through a Uniauth profile), offers
    them the choice between logging to an existing Uniauth
    account or creating a new one.

    The institution account is (eventually) linked to the
    Uniauth profile the user logged into / created.
    """
    next_url = request.GET.get('next')
    context = _get_global_context(request)

    if not next_url:
        next_url = get_redirect_url(request)

    params = urlencode({'next': next_url})
    context['next_url'] = next_url

    # If the user is not authenticated at all, redirect to login page
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse('uniauth:login') + '?' + params)

    # If the user is already authenticated + verified, proceed to next page
    if not is_tmp_user(request.user) and not is_unlinked_account(request.user):
        return HttpResponseRedirect(next_url)

    # If the user is temporary, but was not logged in via an institution
    # (e.g. created through Uniauth, but not verified), redirect to signup
    if not is_unlinked_account(request.user):
        return HttpResponseRedirect(reverse('uniauth:signup') + '?' + params)

    # At this point, we've ensured the user is temporary and was
    # logged in via an institution. We just need to handle the
    # Login Form, if the user chooses to link to an existing account.

    # If it's a POST request, attempt to validate the form
    if request.method == "POST":
        form = LoginForm(request, request.POST)

        # Authentication successful
        if form.is_valid():
            unlinked_user = request.user
            username_split = get_account_username_split(request.user.username)

            # Log in as the authenticated Uniauth user
            user = form.get_user()
            auth_login(request, user)

            # Merge the unlinked account into the logged in profile,
            # then add the institution account described by the username
            merge_model_instances(user, [unlinked_user])
            _add_institution_account(user.profile, username_split[1],
                                     username_split[2])

            slug = username_split[1]
            context['institution'] = Institution.objects.get(slug=slug)
            return render(request, 'uniauth/link-success.html', context)

        # Authentication failed: render form errors
        else:
            context['form'] = form
            return render(request, 'uniauth/link-to-profile.html', context)

    # Otherwise, render a blank Login form
    else:
        form = LoginForm(request)
        context['form'] = form
        return render(request, 'uniauth/link-to-profile.html', context)
 def _run_test(username, expected_result):
     result = get_account_username_split(username)
     self.assertEqual(result[0], expected_result[0])
     self.assertEqual(result[1], expected_result[1])
     self.assertEqual(result[2], expected_result[2])