- New apps/guides app with GuidePage model and audience mapping by wiki path - sync_guides management command: one-way read-only sync from wikijs DB - Read-only wikijs_ro DB role + WIKI_DB_* env config (secrets, gitignored) - Markdown rendering with bleach sanitisation; rewrites internal guide links to the portal help root and wiki image paths to WIKI_PUBLIC_BASE - /portal/help/ (buyer) and /ops/help/ (ops) index + detail views with role-based audience filtering (404 on cross-role guides) - Help nav item added to both portal base templates - Tests: audience filtering, markdown sanitisation, link rewriting, sync command
51 lines
1.8 KiB
Python
51 lines
1.8 KiB
Python
from django.contrib.auth.mixins import LoginRequiredMixin
|
|
from django.http import Http404
|
|
from django.shortcuts import get_object_or_404
|
|
from django.views.generic import DetailView, ListView
|
|
|
|
from .markdown import render_markdown
|
|
from .models import AUDIENCES_BY_ROLE, GuidePage
|
|
|
|
|
|
class GuideAccessMixin:
|
|
def get_allowed_audiences(self):
|
|
user = self.request.user
|
|
if user.is_superuser:
|
|
return set(GuidePage.Audience.values)
|
|
return AUDIENCES_BY_ROLE.get(getattr(user, "role", ""), set())
|
|
|
|
def get_help_root(self):
|
|
namespace = getattr(self.request.resolver_match, "namespace", None) or "portal"
|
|
return f"/{namespace}/help/"
|
|
|
|
|
|
class GuideIndexView(LoginRequiredMixin, GuideAccessMixin, ListView):
|
|
model = GuidePage
|
|
context_object_name = "guides"
|
|
|
|
def get_queryset(self):
|
|
return GuidePage.objects.filter(audience__in=self.get_allowed_audiences())
|
|
|
|
def get_context_data(self, **kwargs):
|
|
ctx = super().get_context_data(**kwargs)
|
|
ctx["help_root"] = self.get_help_root()
|
|
return ctx
|
|
|
|
|
|
class GuideDetailView(LoginRequiredMixin, GuideAccessMixin, DetailView):
|
|
model = GuidePage
|
|
|
|
def get_object(self, queryset=None):
|
|
path = f"user-guides/{self.kwargs['page_path']}"
|
|
page = get_object_or_404(GuidePage, path=path)
|
|
if page.audience not in self.get_allowed_audiences():
|
|
raise Http404("This guide is not available to your role.")
|
|
return page
|
|
|
|
def get_context_data(self, **kwargs):
|
|
ctx = super().get_context_data(**kwargs)
|
|
help_root = self.get_help_root()
|
|
ctx["help_root"] = help_root
|
|
ctx["guide_html"] = render_markdown(self.object.content, self.object.path, help_root)
|
|
ctx["guides"] = GuidePage.objects.filter(audience__in=self.get_allowed_audiences())
|
|
return ctx
|