intent/config/urls.py
Alec Perkins 99f810d043 Harden auth, invites and deployment after security review
- Signed-out visitors get the same login redirect for missing and
  private projects, so the redirect no longer reveals private ones.
- Production refuses the console email backend; sign-in codes must
  never reach the logs.
- Database cache shared by all workers for allauth rate limits; invite
  sending throttled per sender and per recipient.
- Email invite links are claimed on first use and the token rotated,
  so a token copied from request logs is worthless.
- allauth password URLs removed; adding an email requires a fresh code
  and notifies existing addresses.
- Markdown drops remote images until uploads exist.
- Project and org slugs lowercased; only superusers can grant staff
  status or permissions in the admin.
- Container runs as a non-root user; CI actions pinned to commits.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-27 08:42:19 -04:00

35 lines
1.3 KiB
Python

import allauth.urls
from allauth.account import urls as allauth_account_urls
from django.contrib import admin
from django.urls import URLResolver, include, path
from intent.core import views
from intent.orgs.urls import invite_urlpatterns
from intent.projects.views import project_create
def _without_passwords(patterns):
"""allauth's URLs minus the password views: regular users sign in with a code only."""
return [p for p in patterns if not str(p.pattern).startswith("password/")]
account_urlpatterns = [
(
path("", include(_without_passwords(allauth_account_urls.urlpatterns)))
if isinstance(p, URLResolver) and p.urlconf_name is allauth_account_urls
else p
)
for p in allauth.urls.urlpatterns
]
urlpatterns = [
path("", views.home, name="home"),
path("admin/", admin.site.urls),
path("accounts/", include(account_urlpatterns)),
path("invites/", include(invite_urlpatterns)),
# Organizations own the rest of the URL space (see RESERVED_SLUGS in orgs and projects).
path("<slug:org_slug>/new/", project_create, name="project_create"),
path("<slug:org_slug>/", include("intent.orgs.urls")),
path("<slug:org_slug>/<slug:project_slug>/", include("intent.projects.urls")),
path("<slug:org_slug>/<slug:project_slug>/features/", include("intent.features.urls")),
]