Skip to content

Commit 4cf335d

Browse files
Fix: profile redirects
1 parent 700d261 commit 4cf335d

5 files changed

Lines changed: 49 additions & 19 deletions

File tree

app/custom/templates/umap/navigation.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,11 @@
6363
<a href="/chatmap">{% trans "Upload (ChatMap)" %}</a>
6464
</li>
6565
<li>
66-
<a href="{% url 'map_new' %}" class="button button-primary">{% trans "Create a map" %}</a>
66+
{% if AUTH_PROVIDER == 'hanko' and not hanko_authenticated %}
67+
<a href="{{ HANKO_PUBLIC_URL }}/app?return_to={{ SITE_URL|urlencode }}" class="button button-primary">{% trans "Create a map" %}</a>
68+
{% else %}
69+
<a href="{% url 'map_new' %}" class="button button-primary">{% trans "Create a map" %}</a>
70+
{% endif %}
6771
</li>
6872
{% endif %}
6973
</ul>

app/hotumap/dashboard_views.py

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from django.conf import settings
99
from django.contrib.auth import get_user_model
10+
from django.contrib.auth import views as auth_views
1011
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
1112
from django.db.models import QuerySet
1213
from django.http import HttpResponseRedirect
@@ -311,31 +312,29 @@ def user_templates(request):
311312
def user_profile(request):
312313
"""
313314
User profile view that supports both Hanko and Django auth.
315+
316+
When Hanko auth is enabled, redirects to Hanko's profile page so users
317+
manage their email/username there. Changes are synced back via middleware.
314318
"""
315319
from django import forms
316320

317-
user = None
318-
hanko_user = None
319-
320-
# Check Hanko authentication first
321+
# If Hanko auth is enabled, redirect to Hanko profile page
321322
if getattr(settings, 'AUTH_PROVIDER', 'legacy') == 'hanko':
322-
if hasattr(request, 'hotosm') and request.hotosm.user:
323-
hanko_user = request.hotosm.user
324-
user = get_hanko_django_user(request)
323+
from urllib.parse import quote
324+
hanko_public_url = getattr(settings, 'HANKO_PUBLIC_URL', '') or getattr(settings, 'HANKO_API_URL', '')
325+
site_url = getattr(settings, 'SITE_URL', '/')
326+
return_to = quote(site_url, safe='')
327+
return HttpResponseRedirect(f"{hanko_public_url}/app/profile?return_to={return_to}")
325328

326-
# Fall back to Django session auth
327-
if not user and request.user.is_authenticated:
329+
user = None
330+
331+
# Legacy Django session auth
332+
if request.user.is_authenticated:
328333
user = request.user
329334

330-
# Only redirect if no Hanko user AND no Django user
331-
if not user and not hanko_user:
335+
if not user:
332336
return HttpResponseRedirect(reverse('login'))
333337

334-
# Hanko-only users (no Django user) cannot access profile page
335-
# Redirect them to the dashboard
336-
if hanko_user and not user:
337-
return HttpResponseRedirect(reverse('user_dashboard'))
338-
339338
# Simple form for profile
340339
class UserProfileForm(forms.ModelForm):
341340
class Meta:
@@ -361,9 +360,32 @@ class Meta:
361360
context = {
362361
'object': user,
363362
'user': user,
364-
'hanko_user': hanko_user,
365363
'form': form,
366364
'providers': providers,
367365
}
368366

369367
return render(request, "auth/user_form.html", context)
368+
369+
370+
class HankoAwareLoginView(auth_views.LoginView):
371+
"""
372+
Custom login view that checks for Hanko authentication.
373+
374+
If user is authenticated with Hanko, redirect to 'next' URL directly
375+
without showing the legacy login form.
376+
"""
377+
378+
def dispatch(self, request, *args, **kwargs):
379+
# Check if Hanko auth is enabled and user is authenticated with Hanko
380+
if getattr(settings, 'AUTH_PROVIDER', 'legacy') == 'hanko':
381+
if hasattr(request, 'hotosm') and request.hotosm.user:
382+
# User is authenticated with Hanko - redirect to 'next' or dashboard
383+
next_url = request.GET.get('next') or request.POST.get('next')
384+
if next_url:
385+
return HttpResponseRedirect(next_url)
386+
else:
387+
# Default to user dashboard
388+
return HttpResponseRedirect(reverse('user_dashboard'))
389+
390+
# Fall through to normal login view
391+
return super().dispatch(request, *args, **kwargs)

app/hotumap/test_hanko_auth.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
class UserMappingTestCase(TestCase):
2020
"""Test user mapping helper functions."""
21-
2221
def setUp(self):
2322
"""Create test users."""
2423
self.user1 = User.objects.create_user(

app/settings.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@
110110
if AUTH_PROVIDER == 'hanko':
111111
auth_middleware_index = MIDDLEWARE.index("django.contrib.auth.middleware.AuthenticationMiddleware")
112112
MIDDLEWARE.insert(auth_middleware_index, "hotosm_auth_django.HankoAuthMiddleware")
113+
# Add our custom middleware AFTER AuthenticationMiddleware to set request.user
114+
# This makes @login_required and is_authenticated work with Hanko
115+
MIDDLEWARE.append("hotumap.middleware.HankoUserMiddleware")
113116

114117
MIDDLEWARE = tuple(MIDDLEWARE)
115118

app/urls.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
langs = ['es', 'en', 'fr', 'de', 'pt', 'it', 'nl', 'pl', 'ru', 'ja', 'zh', 'ko']
4343
for lang in langs:
4444
urlpatterns += [
45+
# Override login to redirect Hanko users to 'next' directly
46+
path(f'{lang}/login/', dashboard_views.HankoAwareLoginView.as_view(), name=f"login_{lang}"),
4547
path(f'{lang}/me', dashboard_views.user_dashboard, name=f"user_dashboard_{lang}"),
4648
path(f'{lang}/me/teams', dashboard_views.user_teams, name=f"user_teams_{lang}"),
4749
path(f'{lang}/me/templates', dashboard_views.user_templates, name=f"user_templates_{lang}"),

0 commit comments

Comments
 (0)