Пример #1
0
 def test_existing_user_invitation_accepted(self):
     """
     SsoBackend should create a new user if the username passed to does
     not exist and the email domain matches an AuthenticatedEmailDomain
     for the given IdentityProvider. It should also ensure that any
     user data from a registration form and/or the samlUserdata are all
     properly saved to the User model.
     """
     admin_role = StaticRole.domain_admin(domain=self.domain.name)
     existing_user = WebUser.create(None, '*****@*****.**', 'testpwd',
                                    None, None)
     invitation = Invitation(
         domain=self.domain.name,
         email=existing_user.username,
         invited_by=self.user.couch_id,
         invited_on=datetime.datetime.utcnow(),
         role=admin_role.get_qualified_id(),
     )
     invitation.save()
     AsyncSignupRequest.create_from_invitation(invitation)
     user = auth.authenticate(
         request=self.request,
         username=invitation.email,
         idp_slug=self.idp.slug,
         is_handshake_successful=True,
     )
     self.assertIsNotNone(user)
     self.assertEqual(user.username, invitation.email)
     self.assertEqual(self.request.sso_new_user_messages['success'], [
         f'You have been added to the "{invitation.domain}" project space.',
     ])
Пример #2
0
 def test_new_user_created_and_invitation_accepted(self):
     """
     When SsoBackend creates a new user and an invitation is present, that
     invitation should add the user to the invited project
     space and accept the invitation
     """
     admin_role = StaticRole.domain_admin(self.domain.name)
     invitation = Invitation(
         domain=self.domain.name,
         email='*****@*****.**',
         invited_by=self.user.couch_id,
         invited_on=datetime.datetime.utcnow(),
         role=admin_role.get_qualified_id(),
     )
     invitation.save()
     AsyncSignupRequest.create_from_invitation(invitation)
     generator.store_full_name_in_saml_user_data(self.request, 'Isa',
                                                 'Baas')
     user = auth.authenticate(
         request=self.request,
         username=invitation.email,
         idp_slug=self.idp.slug,
         is_handshake_successful=True,
     )
     self.assertIsNotNone(user)
     self.assertEqual(user.username, invitation.email)
     self.assertEqual(user.first_name, 'Isa')
     self.assertEqual(user.last_name, 'Baas')
     self.assertEqual(self.request.sso_new_user_messages['success'], [
         f'User account for {invitation.email} created.',
         f'You have been added to the "{invitation.domain}" project space.',
     ])
Пример #3
0
 def test_new_user_created_and_expired_invitation_declined(self):
     """
     When SsoBackend creates a new user and an EXPIRED invitation is present,
     a new user should still be created, but the invitation should be declined.
     """
     invitation = Invitation(
         domain=self.domain.name,
         email='*****@*****.**',
         invited_by=self.user.couch_id,
         invited_on=datetime.datetime.utcnow() - relativedelta(months=2),
     )
     invitation.save()
     AsyncSignupRequest.create_from_invitation(invitation)
     generator.store_full_name_in_saml_user_data(self.request, 'Zee', 'Bos')
     user = auth.authenticate(
         request=self.request,
         username=invitation.email,
         idp_slug=self.idp.slug,
         is_handshake_successful=True,
     )
     self.assertIsNotNone(user)
     self.assertEqual(user.username, invitation.email)
     self.assertEqual(user.first_name, 'Zee')
     self.assertEqual(user.last_name, 'Bos')
     self.assertEqual(self.request.sso_new_user_messages['success'], [
         f'User account for {invitation.email} created.',
     ])
     self.assertEqual(self.request.sso_new_user_messages['error'], [
         'Could not accept invitation because it is expired.',
     ])
Пример #4
0
def sso_test_create_user(request, idp_slug):
    """
    A testing view exclusively for staging. This will be removed once the
    UIs are in place to sign up users or invite new users who must log in with
    SSO.
    """
    if settings.SERVER_ENVIRONMENT not in ['staging']:
        raise Http404()

    username = request.GET.get('username')
    if username:
        prepare_session_with_sso_username(request, username)

    invitation_uuid = request.GET.get('invitation')
    invitation = Invitation.objects.get(
        uuid=invitation_uuid) if invitation_uuid else None
    if invitation:
        AsyncSignupRequest.create_from_invitation(invitation)

    return HttpResponseRedirect(reverse("sso_saml_login", args=(idp_slug, )))
Пример #5
0
    def __call__(self, request, uuid, **kwargs):
        # add the correct parameters to this instance
        self.request = request
        if 'domain' in kwargs:
            self.domain = kwargs['domain']

        if request.GET.get('switch') == 'true':
            logout(request)
            return redirect_to_login(request.path)
        if request.GET.get('create') == 'true':
            logout(request)
            return HttpResponseRedirect(request.path)
        try:
            invitation = Invitation.objects.get(uuid=uuid)
        except (Invitation.DoesNotExist, ValidationError):
            messages.error(
                request,
                _("Sorry, it looks like your invitation has expired. "
                  "Please check the invitation link you received and try again, or "
                  "request a project administrator to send you the invitation again."
                  ))
            return HttpResponseRedirect(reverse("login"))

        if invitation.is_accepted:
            messages.error(
                request,
                _("Sorry, that invitation has already been used up. "
                  "If you feel this is a mistake please ask the inviter for "
                  "another invitation."))
            return HttpResponseRedirect(reverse("login"))

        self.validate_invitation(invitation)

        if invitation.is_expired:
            return HttpResponseRedirect(reverse("no_permissions"))

        # Add zero-width space to username for better line breaking
        username = self.request.user.username.replace("@", "​@")
        context = {
            'formatted_username': username,
            'domain': self.domain,
            'invite_to': self.domain,
            'invite_type': _('Project'),
            'hide_password_feedback': has_custom_clean_password(),
        }
        if request.user.is_authenticated:
            context['current_page'] = {'page_name': _('Project Invitation')}
        else:
            context['current_page'] = {
                'page_name': _('Project Invitation, Account Required')
            }
        if request.user.is_authenticated:
            is_invited_user = request.couch_user.username.lower(
            ) == invitation.email.lower()
            if self.is_invited(invitation, request.couch_user
                               ) and not request.couch_user.is_superuser:
                if is_invited_user:
                    # if this invite was actually for this user, just mark it accepted
                    messages.info(
                        request,
                        _("You are already a member of {entity}.").format(
                            entity=self.inviting_entity))
                    invitation.is_accepted = True
                    invitation.save()
                else:
                    messages.error(
                        request,
                        _("It looks like you are trying to accept an invitation for "
                          "{invited} but you are already a member of {entity} with the "
                          "account {current}. Please sign out to accept this invitation "
                          "as another user.").format(
                              entity=self.inviting_entity,
                              invited=invitation.email,
                              current=request.couch_user.username))
                return HttpResponseRedirect(
                    self.redirect_to_on_success(invitation.email, self.domain))

            if not is_invited_user:
                messages.error(
                    request,
                    _("The invited user {invited} and your user {current} "
                      "do not match!").format(
                          invited=invitation.email,
                          current=request.couch_user.username))

            if request.method == "POST":
                couch_user = CouchUser.from_django_user(request.user,
                                                        strict=True)
                invitation.accept_invitation_and_join_domain(couch_user)
                log_user_change(
                    by_domain=invitation.domain,
                    for_domain=invitation.domain,
                    couch_user=couch_user,
                    changed_by_user=CouchUser.get_by_user_id(
                        invitation.invited_by),
                    changed_via=USER_CHANGE_VIA_INVITATION,
                    change_messages=UserChangeMessage.domain_addition(
                        invitation.domain))
                track_workflow(
                    request.couch_user.get_email(),
                    "Current user accepted a project invitation",
                    {"Current user accepted a project invitation": "yes"})
                send_hubspot_form(HUBSPOT_EXISTING_USER_INVITE_FORM, request)
                return HttpResponseRedirect(
                    self.redirect_to_on_success(invitation.email, self.domain))
            else:
                mobile_user = CouchUser.from_django_user(
                    request.user).is_commcare_user()
                context.update({
                    'mobile_user':
                    mobile_user,
                    "invited_user":
                    invitation.email
                    if request.couch_user.username != invitation.email else "",
                })
                return render(request, self.template, context)
        else:
            idp = None
            if settings.ENFORCE_SSO_LOGIN:
                idp = IdentityProvider.get_active_identity_provider_by_username(
                    invitation.email)

            if request.method == "POST":
                form = WebUserInvitationForm(request.POST,
                                             is_sso=idp is not None)
                if form.is_valid():
                    # create the new user
                    invited_by_user = CouchUser.get_by_user_id(
                        invitation.invited_by)

                    if idp:
                        signup_request = AsyncSignupRequest.create_from_invitation(
                            invitation)
                        return HttpResponseRedirect(
                            idp.get_login_url(signup_request.username))

                    user = activate_new_user_via_reg_form(
                        form,
                        created_by=invited_by_user,
                        created_via=USER_CHANGE_VIA_INVITATION,
                        domain=invitation.domain,
                        is_domain_admin=False,
                    )
                    user.save()
                    messages.success(
                        request,
                        _("User account for %s created!") %
                        form.cleaned_data["email"])
                    invitation.accept_invitation_and_join_domain(user)
                    messages.success(
                        self.request,
                        _('You have been added to the "{}" project space.').
                        format(self.domain))
                    authenticated = authenticate(
                        username=form.cleaned_data["email"],
                        password=form.cleaned_data["password"],
                        request=request)
                    if authenticated is not None and authenticated.is_active:
                        login(request, authenticated)
                    track_workflow(
                        request.POST['email'],
                        "New User Accepted a project invitation",
                        {"New User Accepted a project invitation": "yes"})
                    send_hubspot_form(HUBSPOT_NEW_USER_INVITE_FORM, request,
                                      user)
                    return HttpResponseRedirect(
                        self.redirect_to_on_success(invitation.email,
                                                    invitation.domain))
            else:
                if (CouchUser.get_by_username(invitation.email)
                        or User.objects.filter(
                            username__iexact=invitation.email).count() > 0):
                    login_url = reverse("login")
                    accept_invitation_url = reverse(
                        'domain_accept_invitation',
                        args=[invitation.domain, invitation.uuid])
                    return HttpResponseRedirect(
                        f"{login_url}"
                        f"?next={accept_invitation_url}"
                        f"&username={invitation.email}")
                form = WebUserInvitationForm(
                    initial={
                        'email': invitation.email,
                    },
                    is_sso=idp is not None,
                )

            context.update({
                'is_sso': idp is not None,
                'idp_name': idp.name if idp else None,
                'invited_user': invitation.email,
            })

        context.update({"form": form})
        return render(request, self.template, context)