Skip to content

Commit 6150889

Browse files
annagavpre-commit-ci[bot]cp-at-mitrhysyngsun
authored
add redirect for user onboarding (#2612)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: CP <[email protected]> Co-authored-by: Nathan Levesque <[email protected]>
1 parent 6f84c89 commit 6150889

File tree

7 files changed

+95
-20
lines changed

7 files changed

+95
-20
lines changed

app.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,10 @@
374374
"description": "CyberSource security key",
375375
"required": false
376376
},
377+
"MITXONLINE_NEW_USER_LOGIN_URL": {
378+
"description": "URL to redirect new users to after login",
379+
"required": false
380+
},
377381
"MITX_ONLINE_ADMIN_EMAIL": {
378382
"description": "E-mail to send 500 reports to.",
379383
"required": true

authentication/new_views.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,15 @@ def get(
177177
"""
178178
redirect_url = get_redirect_url(request)
179179
if not request.user.is_anonymous:
180-
profile = getattr(request.user, "user_profile", None)
181-
if not profile:
182-
# If user is authenticated but has no profile, redirect to create profile
180+
profile = request.user.user_profile
181+
if (
182+
not profile.completed_onboarding
183+
and request.GET.get("skip_onboarding", "0") == "0"
184+
):
183185
params = urlencode({"next": redirect_url})
184-
redirect_url = f"{reverse('profile-details')}?{params}"
186+
redirect_url = f"{settings.MITXONLINE_NEW_USER_LOGIN_URL}?{params}"
187+
profile.completed_onboarding = True
188+
profile.save()
185189
return redirect(redirect_url)
186190

187191

authentication/new_views_test.py

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import pytest
2+
from django.test import RequestFactory
23
from django.urls import reverse
34
from rest_framework import status
45

6+
from authentication.new_views import CustomLoginView
57
from users.api import User
8+
from users.factories import UserFactory
69
from users.models import MALE, UserProfile
710

811

@@ -71,19 +74,35 @@ def test_post_user_extra_detail(mocker, client, user):
7174

7275

7376
@pytest.mark.django_db
74-
@pytest.mark.parametrize(
75-
("has_profile", "expected_url"),
76-
[
77-
(True, "/dashboard"),
78-
(False, f"{reverse('profile-details')}?next=%2Fdashboard"),
79-
],
80-
)
81-
def test_login_view(client, user, has_profile, expected_url):
82-
"""Test that the login endpoint redirects the user properly based on profile existence"""
83-
if not has_profile:
84-
user.user_profile.delete()
85-
client.force_login(user)
86-
url = reverse("gateway-login")
87-
resp = client.get(url)
88-
assert resp.url == expected_url
89-
assert resp.status_code == status.HTTP_302_FOUND
77+
def test_custom_login_view_authenticated_user_with_onboarding(mocker):
78+
"""Test CustomLoginView for an authenticated user with incomplete onboarding"""
79+
factory = RequestFactory()
80+
request = factory.get(reverse("login"), {"next": "/dashboard"})
81+
user = UserFactory()
82+
request.user = user
83+
mocker.patch("authentication.new_views.get_redirect_url", return_value="/dashboard")
84+
mocker.patch("authentication.new_views.urlencode", return_value="next=/dashboard")
85+
mocker.patch(
86+
"authentication.new_views.settings.MITXONLINE_NEW_USER_LOGIN_URL",
87+
"/create-profile",
88+
)
89+
90+
response = CustomLoginView().get(request)
91+
92+
assert response.status_code == 302
93+
assert response.url == "/create-profile?next=/dashboard"
94+
95+
96+
@pytest.mark.django_db
97+
def test_custom_login_view_authenticated_user_with_completed_onboarding(mocker):
98+
"""Test that user who has completed onboarding is redirected to next url"""
99+
factory = RequestFactory()
100+
request = factory.get(reverse("login"), {"next": "/dashboard"})
101+
user = UserFactory(user_profile__completed_onboarding=True)
102+
request.user = user
103+
mocker.patch("authentication.new_views.get_redirect_url", return_value="/dashboard")
104+
105+
response = CustomLoginView().get(request)
106+
107+
assert response.status_code == 302
108+
assert response.url == "/dashboard"

main/settings.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,11 @@
252252

253253
SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
254254

255+
MITXONLINE_NEW_USER_LOGIN_URL = get_string(
256+
name="MITXONLINE_NEW_USER_LOGIN_URL",
257+
default="http://mitxonline.odl.local:8013/create-profile",
258+
description="URL to redirect new users to after login",
259+
)
255260
LOGIN_REDIRECT_URL = "/"
256261
LOGIN_URL = "/signin"
257262
LOGOUT_REDIRECT_URL = get_string(
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Generated by Django 4.2.20 on 2025-04-25 02:55
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
dependencies = [
8+
("users", "0029_add_b2b_contract_fk"),
9+
]
10+
11+
operations = [
12+
migrations.AddField(
13+
model_name="userprofile",
14+
name="completed_onboarding",
15+
field=models.BooleanField(
16+
blank=True,
17+
default=False,
18+
help_text="Flags if user has completed filling out required onboarding information",
19+
),
20+
),
21+
]
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Generated by Django 4.2.20 on 2025-04-26 01:15
2+
3+
4+
from django.db import migrations
5+
6+
7+
def set_completed_onboarding(apps, schema_editor):
8+
UserProfile = apps.get_model("users", "UserProfile")
9+
UserProfile.objects.all().update(completed_onboarding=True)
10+
11+
12+
class Migration(migrations.Migration):
13+
dependencies = [
14+
("users", "0030_userprofile_completed_onboarding"),
15+
]
16+
17+
operations = [migrations.RunPython(set_completed_onboarding)]

users/models.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,11 @@ class UserProfile(TimestampedModel):
441441
user = models.OneToOneField(
442442
User, on_delete=models.CASCADE, related_name="user_profile"
443443
)
444+
completed_onboarding = models.BooleanField(
445+
default=False,
446+
blank=True,
447+
help_text="Flags if user has completed filling out required onboarding information",
448+
)
444449

445450
gender = models.CharField( # noqa: DJ001
446451
max_length=128, blank=True, null=True, choices=GENDER_CHOICES

0 commit comments

Comments
 (0)