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

lmata 2026-04-07 17:49 trunk
Commit 664cf598b638074157707f4f0fae76ce6fa633a5e82facf697945a102eadb8c1
+1 -1
--- config/urls.py
+++ config/urls.py
@@ -243,11 +243,11 @@
243243
244244
return explore(request)
245245
246246
247247
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"),
249249
path("profile/", RedirectView.as_view(pattern_name="accounts:profile", permanent=False)),
250250
path("status/", status_page, name="status"),
251251
path("explore/", _explore_view, name="explore"),
252252
path("dashboard/", include("core.urls")),
253253
path("auth/", include("accounts.urls")),
254254
255255
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
--- 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

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button