FossilRepo
Public access: anonymous users see /explore and public projects - Root URL redirects to /explore for anonymous, /dashboard for authenticated - core/decorators.py: public_or_login decorator for future use - Read-only views already support anonymous access via require_project_read
Commit
664cf598b638074157707f4f0fae76ce6fa633a5e82facf697945a102eadb8c1
Parent
ea3b5a33834d850…
2 files changed
+1
-1
+39
+1
-1
| --- config/urls.py | ||
| +++ config/urls.py | ||
| @@ -243,11 +243,11 @@ | ||
| 243 | 243 | |
| 244 | 244 | return explore(request) |
| 245 | 245 | |
| 246 | 246 | |
| 247 | 247 | urlpatterns = [ |
| 248 | - path("", RedirectView.as_view(pattern_name="dashboard", permanent=False)), | |
| 248 | + path("", lambda request: _redirect("/explore/") if not request.user.is_authenticated else _redirect("/dashboard/"), name="home"), | |
| 249 | 249 | path("profile/", RedirectView.as_view(pattern_name="accounts:profile", permanent=False)), |
| 250 | 250 | path("status/", status_page, name="status"), |
| 251 | 251 | path("explore/", _explore_view, name="explore"), |
| 252 | 252 | path("dashboard/", include("core.urls")), |
| 253 | 253 | path("auth/", include("accounts.urls")), |
| 254 | 254 | |
| 255 | 255 | ADDED core/decorators.py |
| --- config/urls.py | |
| +++ config/urls.py | |
| @@ -243,11 +243,11 @@ | |
| 243 | |
| 244 | return explore(request) |
| 245 | |
| 246 | |
| 247 | urlpatterns = [ |
| 248 | path("", RedirectView.as_view(pattern_name="dashboard", permanent=False)), |
| 249 | path("profile/", RedirectView.as_view(pattern_name="accounts:profile", permanent=False)), |
| 250 | path("status/", status_page, name="status"), |
| 251 | path("explore/", _explore_view, name="explore"), |
| 252 | path("dashboard/", include("core.urls")), |
| 253 | path("auth/", include("accounts.urls")), |
| 254 | |
| 255 | DDED core/decorators.py |
| --- config/urls.py | |
| +++ config/urls.py | |
| @@ -243,11 +243,11 @@ | |
| 243 | |
| 244 | return explore(request) |
| 245 | |
| 246 | |
| 247 | urlpatterns = [ |
| 248 | path("", lambda request: _redirect("/explore/") if not request.user.is_authenticated else _redirect("/dashboard/"), name="home"), |
| 249 | path("profile/", RedirectView.as_view(pattern_name="accounts:profile", permanent=False)), |
| 250 | path("status/", status_page, name="status"), |
| 251 | path("explore/", _explore_view, name="explore"), |
| 252 | path("dashboard/", include("core.urls")), |
| 253 | path("auth/", include("accounts.urls")), |
| 254 | |
| 255 | DDED core/decorators.py |
+39
| --- a/core/decorators.py | ||
| +++ b/core/decorators.py | ||
| @@ -0,0 +1,39 @@ | ||
| 1 | +"""Custom view decorators for fossilrepo.""" | |
| 2 | + | |
| 3 | +from functools import wraps | |
| 4 | + | |
| 5 | +from django.contrib.auth.decorators import login_required | |
| 6 | + | |
| 7 | + | |
| 8 | +def public_or_login(view_func): | |
| 9 | + """Allow anonymous access to public project views. | |
| 10 | + | |
| 11 | + For views that take a `slug` parameter: if the project is public, | |
| 12 | + let anonymous users through. Otherwise, redirect to login. | |
| 13 | + | |
| 14 | + This replaces @login_required on read-only project/fossil views. | |
| 15 | + The view itself must still call require_project_read() for the | |
| 16 | + actual permission check. | |
| 17 | + """ | |
| 18 | + | |
| 19 | + @wraps(view_func) | |
| 20 | + def wrapper(request, *args, **kwargs): | |
| 21 | + if request.user.is_authenticated: | |
| 22 | + return view_func(request, *args, **kwargs) | |
| 23 | + | |
| 24 | + # Check if this is a public project | |
| 25 | + slug = kwargs.get("slug") or (args[0] if args else None) | |
| 26 | + if slug: | |
| 27 | + from projects.models import Project | |
| 28 | + | |
| 29 | + try: | |
| 30 | + project = Project.objects.get(slug=slug, deleted_at__isnull=True) | |
| 31 | + if project.visibility == "public": | |
| 32 | + return view_func(request, *args, **kwargs) | |
| 33 | + except Project.DoesNotExist: | |
| 34 | + pass | |
| 35 | + | |
| 36 | + # Not public or no slug -- require login | |
| 37 | + return login_required(view_func)(request, *args, **kwargs) | |
| 38 | + | |
| 39 | + return wrapper |
| --- a/core/decorators.py | |
| +++ b/core/decorators.py | |
| @@ -0,0 +1,39 @@ | |
| --- a/core/decorators.py | |
| +++ b/core/decorators.py | |
| @@ -0,0 +1,39 @@ | |
| 1 | """Custom view decorators for fossilrepo.""" |
| 2 | |
| 3 | from functools import wraps |
| 4 | |
| 5 | from django.contrib.auth.decorators import login_required |
| 6 | |
| 7 | |
| 8 | def public_or_login(view_func): |
| 9 | """Allow anonymous access to public project views. |
| 10 | |
| 11 | For views that take a `slug` parameter: if the project is public, |
| 12 | let anonymous users through. Otherwise, redirect to login. |
| 13 | |
| 14 | This replaces @login_required on read-only project/fossil views. |
| 15 | The view itself must still call require_project_read() for the |
| 16 | actual permission check. |
| 17 | """ |
| 18 | |
| 19 | @wraps(view_func) |
| 20 | def wrapper(request, *args, **kwargs): |
| 21 | if request.user.is_authenticated: |
| 22 | return view_func(request, *args, **kwargs) |
| 23 | |
| 24 | # Check if this is a public project |
| 25 | slug = kwargs.get("slug") or (args[0] if args else None) |
| 26 | if slug: |
| 27 | from projects.models import Project |
| 28 | |
| 29 | try: |
| 30 | project = Project.objects.get(slug=slug, deleted_at__isnull=True) |
| 31 | if project.visibility == "public": |
| 32 | return view_func(request, *args, **kwargs) |
| 33 | except Project.DoesNotExist: |
| 34 | pass |
| 35 | |
| 36 | # Not public or no slug -- require login |
| 37 | return login_required(view_func)(request, *args, **kwargs) |
| 38 | |
| 39 | return wrapper |