docs: switch to mermaid diagrams
This commit is contained in:
parent
3a5de63491
commit
810dd71681
17 changed files with 189 additions and 240 deletions
|
|
@ -47,6 +47,7 @@
|
||||||
- Soft rejection/removal states for users/listings with timestamps; owner listing removal; login redirects home; listing visibility hides removed/not-published.
|
- Soft rejection/removal states for users/listings with timestamps; owner listing removal; login redirects home; listing visibility hides removed/not-published.
|
||||||
- Profile page now allows editing name and password (email immutable).
|
- Profile page now allows editing name and password (email immutable).
|
||||||
- Docs: Added docs in `docs/` (tracked, not shipped) with HTML + PlantUML sequences + draw.io diagrams. Ignored from deploy via runtime paths; kept in git.
|
- Docs: Added docs in `docs/` (tracked, not shipped) with HTML + PlantUML sequences + draw.io diagrams. Ignored from deploy via runtime paths; kept in git.
|
||||||
|
- Documentation pivoted to Mermaid-only diagrams (sequence + architecture/infra/pipeline), rendered in-browser; legacy draw.io/PlantUML assets removed for simplicity.
|
||||||
- Listing details: right rail now surfaces quick facts + amenity icons; browse map given fixed height so OpenStreetMap tiles show reliably; footer links to privacy page with version indicator.
|
- Listing details: right rail now surfaces quick facts + amenity icons; browse map given fixed height so OpenStreetMap tiles show reliably; footer links to privacy page with version indicator.
|
||||||
|
|
||||||
To resume:
|
To resume:
|
||||||
|
|
|
||||||
|
|
@ -12,25 +12,26 @@
|
||||||
</header>
|
</header>
|
||||||
<main class="grid">
|
<main class="grid">
|
||||||
<section class="card">
|
<section class="card">
|
||||||
<h2>Components</h2>
|
<h2>Component map</h2>
|
||||||
<ul>
|
|
||||||
<li><strong>Web</strong>: Next.js app (App Router), server-rendered pages, client hooks for auth state.</li>
|
|
||||||
<li><strong>API routes</strong>: Authentication, admin approvals, listings CRUD (soft-delete), profile update.</li>
|
|
||||||
<li><strong>Data</strong>: Postgres via Prisma (models: User, Listing, ListingTranslation, ListingImage, VerificationToken).</li>
|
|
||||||
<li><strong>Mail</strong>: SMTP (smtp.sohva.org) + DKIM signing for verification emails.</li>
|
|
||||||
<li><strong>Auth</strong>: Email/password, verified+approved requirement, JWT session cookie (<code>session_token</code>), roles.</li>
|
|
||||||
</ul>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="card">
|
|
||||||
<h2>Layers Diagram</h2>
|
|
||||||
<p>Source: <code>docs/drawio/architecture.drawio</code>. Edit with draw.io and export locally.</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="card">
|
|
||||||
<h2>Domain Model Snapshot</h2>
|
|
||||||
<div class="diagram">
|
<div class="diagram">
|
||||||
<pre><code class="language-mermaid">erDiagram
|
<pre class="mermaid">
|
||||||
|
flowchart LR
|
||||||
|
Browser[Client browser] -->|HTTP/HTTPS| Next[Next.js App Router<br/>SSR/ISR + API routes]
|
||||||
|
Next --> Prisma[Prisma ORM]
|
||||||
|
Prisma --> Postgres[(PostgreSQL)]
|
||||||
|
Next --> Mailer[SMTP mailer<br/>(smtp.sohva.org + DKIM)]
|
||||||
|
Next --> Storage[Image URLs (remote/bucket)]
|
||||||
|
Admin[Admin / Moderators] --> Next
|
||||||
|
Next --> Auth[Auth module<br/>JWT session cookie]
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
<div class="callout">Edit the Mermaid block above to evolve the architecture.</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="card">
|
||||||
|
<h2>Domain model</h2>
|
||||||
|
<div class="diagram">
|
||||||
|
<pre class="mermaid">erDiagram
|
||||||
USER ||--o{ LISTING : owns
|
USER ||--o{ LISTING : owns
|
||||||
USER ||--o{ LISTING : approves
|
USER ||--o{ LISTING : approves
|
||||||
LISTING ||--|{ LISTINGTRANSLATION : has
|
LISTING ||--|{ LISTINGTRANSLATION : has
|
||||||
|
|
@ -67,14 +68,24 @@
|
||||||
string id
|
string id
|
||||||
string url
|
string url
|
||||||
}
|
}
|
||||||
</code></pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="card">
|
<section class="card">
|
||||||
<h2>Auth Flow (High-Level)</h2>
|
<h2>Key notes</h2>
|
||||||
<p>See PlantUML source: <code>docs/plantuml/auth-register-login.puml</code>. Render locally with PlantUML.</p>
|
<ul>
|
||||||
|
<li><strong>Web</strong>: Next.js app (App Router), server-rendered pages, client hooks for auth state.</li>
|
||||||
|
<li><strong>API routes</strong>: Authentication, admin approvals, listings CRUD (soft-delete), profile update.</li>
|
||||||
|
<li><strong>Data</strong>: Postgres via Prisma (models: User, Listing, ListingTranslation, ListingImage, VerificationToken).</li>
|
||||||
|
<li><strong>Mail</strong>: SMTP (smtp.sohva.org) + DKIM signing for verification emails.</li>
|
||||||
|
<li><strong>Auth</strong>: Email/password, verified+approved requirement, JWT session cookie (<code>session_token</code>), roles.</li>
|
||||||
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
<script type="module">
|
||||||
|
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
|
||||||
|
mermaid.initialize({ startOnLoad: true, theme: 'dark' });
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,26 @@
|
||||||
<div class="meta">Node/Next build, Docker multi-stage, registry push, kubectl rollout.</div>
|
<div class="meta">Node/Next build, Docker multi-stage, registry push, kubectl rollout.</div>
|
||||||
</header>
|
</header>
|
||||||
<main class="grid">
|
<main class="grid">
|
||||||
|
<section class="card">
|
||||||
|
<h2>Pipeline at a glance</h2>
|
||||||
|
<div class="diagram">
|
||||||
|
<pre class="mermaid">
|
||||||
|
flowchart LR
|
||||||
|
Dev[Developer] -->|npm run lint| Lint
|
||||||
|
Dev --> BuildScript[./deploy/build.sh]
|
||||||
|
Lint --> BuildScript
|
||||||
|
BuildScript --> Docker[Docker buildx<br/>multi-stage]
|
||||||
|
Docker --> Image[registry.halla-aho.net<br/>thalla/lomavuokraus-web]
|
||||||
|
Image --> Push[./deploy/push.sh]
|
||||||
|
Push --> DeployStg[./deploy/deploy-staging.sh]
|
||||||
|
Push --> DeployProd[./deploy/deploy-prod.sh]
|
||||||
|
DeployStg --> K8sStg[kubectl apply<br/>rollout (staging)]
|
||||||
|
DeployProd --> K8sProd[kubectl apply<br/>rollout (prod)]
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
<div class="callout">Edit the Mermaid block to reflect pipeline changes; no external tooling required.</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section class="card">
|
<section class="card">
|
||||||
<h2>Build Inputs</h2>
|
<h2>Build Inputs</h2>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
@ -66,11 +86,10 @@
|
||||||
<li>App env resolution: <code>process.env.*</code> in Next server code.</li>
|
<li>App env resolution: <code>process.env.*</code> in Next server code.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="card">
|
|
||||||
<h2>Pipeline Diagram</h2>
|
|
||||||
<p>For visuals, edit/export <code>docs/drawio/architecture.drawio</code> or create a dedicated pipeline page in draw.io.</p>
|
|
||||||
</section>
|
|
||||||
</main>
|
</main>
|
||||||
|
<script type="module">
|
||||||
|
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
|
||||||
|
mermaid.initialize({ startOnLoad: true, theme: 'dark' });
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
<mxfile host="app.diagrams.net">
|
|
||||||
<diagram id="architecture" name="Architecture">
|
|
||||||
<mxGraphModel dx="923" dy="570" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1200" pageHeight="900" math="0" shadow="0">
|
|
||||||
<root>
|
|
||||||
<mxCell id="0" />
|
|
||||||
<mxCell id="1" parent="0" />
|
|
||||||
<mxCell id="browser" value="Browser" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#26A69A;fontColor=#ffffff" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="80" y="80" width="120" height="50" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="next" value="Next.js App" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#3949AB;fontColor=#ffffff" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="260" y="80" width="140" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="apiRoutes" value="API Routes (Auth, Listings, Admin)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#5E35B1;fontColor=#ffffff" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="260" y="170" width="200" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="prisma" value="Prisma Client" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#00897B;fontColor=#ffffff" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="520" y="170" width="140" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="db" value="PostgreSQL" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#8D6E63;fontColor=#ffffff" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="720" y="170" width="140" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="smtp" value="SMTP / DKIM" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F4511E;fontColor=#ffffff" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="720" y="270" width="140" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="cookie" value="JWT session_token" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#0097A7;fontColor=#ffffff" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="480" y="80" width="140" height="50" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="flow1" edge="1" source="browser" target="next" style="endArrow=block;strokeColor=#26A69A" parent="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="flow2" edge="1" source="next" target="apiRoutes" style="endArrow=block;strokeColor=#3949AB" parent="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="flow3" edge="1" source="apiRoutes" target="prisma" style="endArrow=block;strokeColor=#5E35B1" parent="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="flow4" edge="1" source="prisma" target="db" style="endArrow=block;strokeColor=#00897B" parent="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="flow5" edge="1" source="apiRoutes" target="smtp" style="endArrow=block;strokeColor=#F4511E" parent="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="flow6" edge="1" source="next" target="cookie" style="endArrow=block;strokeColor=#0097A7" parent="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="flow7" edge="1" source="cookie" target="browser" style="endArrow=block;strokeColor=#0097A7" parent="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</root>
|
|
||||||
</mxGraphModel>
|
|
||||||
</diagram>
|
|
||||||
</mxfile>
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
<mxfile host="app.diagrams.net">
|
|
||||||
<diagram id="infra" name="Infrastructure">
|
|
||||||
<mxGraphModel dx="923" dy="570" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1200" pageHeight="900" math="0" shadow="0">
|
|
||||||
<root>
|
|
||||||
<mxCell id="0" />
|
|
||||||
<mxCell id="1" parent="0" />
|
|
||||||
<mxCell id="cluster" value="k3s Cluster" style="swimlane;childLayout=stackLayout;horizontal=1;startSize=20;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="140" y="140" width="700" height="420" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="traefik" value="Traefik Ingress" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#1E88E5;fontColor=#ffffff" vertex="1" parent="cluster">
|
|
||||||
<mxGeometry x="40" y="60" width="140" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="svc" value="Service: lomavuokraus-web" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#3949AB;fontColor=#ffffff" vertex="1" parent="cluster">
|
|
||||||
<mxGeometry x="240" y="60" width="180" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pod" value="Deployment (Next.js pods)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#5E35B1;fontColor=#ffffff" vertex="1" parent="cluster">
|
|
||||||
<mxGeometry x="480" y="60" width="180" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="cm" value="ConfigMap + Secret" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#00897B;fontColor=#ffffff" vertex="1" parent="cluster">
|
|
||||||
<mxGeometry x="480" y="170" width="180" height="50" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="cert" value="cert-manager
ClusterIssuers" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#00838F;fontColor=#ffffff" vertex="1" parent="cluster">
|
|
||||||
<mxGeometry x="240" y="170" width="180" height="50" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="browser" value="Browser" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#26A69A;fontColor=#ffffff" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="40" y="70" width="100" height="50" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="registry" value="Registry
registry.halla-aho.net" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#6D4C41;fontColor=#ffffff" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="40" y="340" width="150" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="db" value="PostgreSQL
46.62.203.202" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#8D6E63;fontColor=#ffffff" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="860" y="220" width="160" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="smtp" value="SMTP
smtp.sohva.org" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F4511E;fontColor=#ffffff" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="860" y="320" width="160" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="registry-edge" edge="1" source="registry" target="pod" style="endArrow=block;strokeColor=#6D4C41" parent="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="browser-edge" edge="1" source="browser" target="traefik" style="endArrow=block;strokeColor=#26A69A" parent="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="traefik-svc-edge" edge="1" source="traefik" target="svc" style="endArrow=block;strokeColor=#1E88E5" parent="cluster">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="svc-pod-edge" edge="1" source="svc" target="pod" style="endArrow=block;strokeColor=#3949AB" parent="cluster">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pod-db-edge" edge="1" source="pod" target="db" style="endArrow=block;strokeColor=#8D6E63" parent="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pod-smtp-edge" edge="1" source="pod" target="smtp" style="endArrow=block;strokeColor=#F4511E" parent="1">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="cert-traefik-edge" edge="1" source="cert" target="traefik" style="endArrow=block;strokeColor=#00838F" parent="cluster">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="cm-pod-edge" edge="1" source="cm" target="pod" style="endArrow=block;strokeColor=#00897B" parent="cluster">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</root>
|
|
||||||
</mxGraphModel>
|
|
||||||
</diagram>
|
|
||||||
</mxfile>
|
|
||||||
|
|
@ -8,10 +8,10 @@
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<h1>Lomavuokraus Documentation</h1>
|
<h1>Lomavuokraus Documentation</h1>
|
||||||
<div class="meta">Docs tracked in git, not deployed with the app.</div>
|
<div class="meta">Diagram-first docs rendered with Mermaid; tracked in git, not deployed with the app.</div>
|
||||||
</header>
|
</header>
|
||||||
<main class="grid">
|
<main class="grid">
|
||||||
<div class="card">
|
<section class="card">
|
||||||
<h2>Contents</h2>
|
<h2>Contents</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="./infra.html">Infrastructure</a></li>
|
<li><a href="./infra.html">Infrastructure</a></li>
|
||||||
|
|
@ -19,16 +19,19 @@
|
||||||
<li><a href="./architecture.html">Logical Architecture</a></li>
|
<li><a href="./architecture.html">Logical Architecture</a></li>
|
||||||
<li><a href="./sequences.html">Feature Sequences</a></li>
|
<li><a href="./sequences.html">Feature Sequences</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</section>
|
||||||
<div class="card">
|
<section class="card">
|
||||||
<h3>Notes</h3>
|
<h3>How diagrams work</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Docs live in <code>docs/</code> (tracked, not shipped).</li>
|
<li>All diagrams use Mermaid (rendered in-browser via CDN; no extra tooling needed).</li>
|
||||||
<li>Sequence diagrams: PlantUML sources in <code>docs/plantuml</code>.</li>
|
<li>Graph definitions live inline in the HTML for quick edits.</li>
|
||||||
<li>Architecture/infra diagrams: draw.io sources in <code>docs/drawio</code>.</li>
|
<li>Docs live in <code>docs/</code>; they are tracked but not shipped with the app.</li>
|
||||||
<li>Generate locally: PlantUML CLI/JAR, draw.io desktop/CLI exports.</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
<script type="module">
|
||||||
|
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
|
||||||
|
mermaid.initialize({ startOnLoad: true, theme: 'dark' });
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,35 @@
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<h1>Infrastructure Overview</h1>
|
<h1>Infrastructure Overview</h1>
|
||||||
<div class="meta">
|
<div class="meta">Hetzner k3s cluster, Traefik ingress, cert-manager TLS, private registry, staging/prod namespaces.</div>
|
||||||
Hetzner k3s cluster, Traefik ingress, cert-manager TLS, private registry, staging/prod namespaces.
|
|
||||||
</div>
|
|
||||||
</header>
|
</header>
|
||||||
<main class="grid">
|
<main class="grid">
|
||||||
|
<section class="card">
|
||||||
|
<h2>Traffic flow</h2>
|
||||||
|
<div class="diagram">
|
||||||
|
<pre class="mermaid">
|
||||||
|
graph LR
|
||||||
|
User[User Browser] -->|HTTPS| Traefik[Traefik Ingress<br/>IngressClass traefik]
|
||||||
|
Traefik -->|Host: lomavuokraus.fi<br/>staging.lomavuokraus.fi| Service[Service<br/>port 80 -> 3000]
|
||||||
|
Service --> Pod[Next.js Pods (2)]
|
||||||
|
Pod --> DB[(PostgreSQL<br/>46.62.203.202)]
|
||||||
|
Pod --> SMTP[smtp.sohva.org]
|
||||||
|
subgraph Cluster [k3s Cluster hel1 cx22 157.180.66.64]
|
||||||
|
Traefik
|
||||||
|
Service
|
||||||
|
Pod
|
||||||
|
CertMgr[cert-manager]
|
||||||
|
Secret[Secrets: lomavuokraus-web-secrets]
|
||||||
|
CM[ConfigMap: lomavuokraus-web-config]
|
||||||
|
end
|
||||||
|
CertMgr -->|TLS| Traefik
|
||||||
|
Registry[registry.halla-aho.net/thalla/lomavuokraus-web] -->|pull| Pod
|
||||||
|
DNS[lomavuokraus.fi<br/>staging.lomavuokraus.fi<br/>api.lomavuokraus.fi] --> Traefik
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
<div class="callout">Mermaid renders directly in the browser; edit the graph in this file to update.</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section class="card">
|
<section class="card">
|
||||||
<h2>Cluster & Namespaces</h2>
|
<h2>Cluster & Namespaces</h2>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
@ -64,11 +88,10 @@
|
||||||
<li>Session auth: signed JWT cookie <code>session_token</code>; roles: USER, ADMIN, USER_MODERATOR, LISTING_MODERATOR.</li>
|
<li>Session auth: signed JWT cookie <code>session_token</code>; roles: USER, ADMIN, USER_MODERATOR, LISTING_MODERATOR.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="card">
|
|
||||||
<h2>Traffic Flow Diagram</h2>
|
|
||||||
<p>Source: <code>docs/drawio/infra.drawio</code> (edit with draw.io, export PNG locally).</p>
|
|
||||||
</section>
|
|
||||||
</main>
|
</main>
|
||||||
|
<script type="module">
|
||||||
|
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
|
||||||
|
mermaid.initialize({ startOnLoad: true, theme: 'dark' });
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
@startuml
|
|
||||||
title User registration, verification, login, approval
|
|
||||||
actor User
|
|
||||||
participant "Next API" as API
|
|
||||||
database Postgres as DB
|
|
||||||
participant SMTP as Mail
|
|
||||||
actor Admin
|
|
||||||
|
|
||||||
User -> API: POST /api/auth/register\n(email, password, name)
|
|
||||||
API -> DB: create User (status=PENDING)\ncreate VerificationToken
|
|
||||||
API -> Mail: send verification email
|
|
||||||
User -> API: POST /api/auth/verify (token)
|
|
||||||
API -> DB: set emailVerifiedAt
|
|
||||||
Admin -> API: POST /api/admin/users/approve
|
|
||||||
API -> DB: set status=ACTIVE, approvedAt
|
|
||||||
User -> API: POST /api/auth/login
|
|
||||||
API -> DB: validate password + status
|
|
||||||
API --> User: session_token cookie (JWT)
|
|
||||||
@enduml
|
|
||||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 12 KiB |
|
|
@ -1,18 +0,0 @@
|
||||||
@startuml
|
|
||||||
title Listing creation and admin approval
|
|
||||||
actor Owner
|
|
||||||
participant "Next API" as API
|
|
||||||
database Postgres as DB
|
|
||||||
actor Admin
|
|
||||||
actor User
|
|
||||||
|
|
||||||
Owner -> API: POST /api/listings\n(slug, details, images)
|
|
||||||
API -> DB: create Listing\nstatus=PENDING (or PUBLISHED if auto)
|
|
||||||
Admin -> API: GET /api/admin/pending
|
|
||||||
API -> DB: fetch pending listings
|
|
||||||
Admin -> API: POST /api/admin/listings/approve\n(action=approve|reject|remove)
|
|
||||||
API -> DB: update status, timestamps
|
|
||||||
User -> API: GET /listings/[slug]
|
|
||||||
API -> DB: fetch translation\nstatus=PUBLISHED and not removed
|
|
||||||
API --> User: render listing
|
|
||||||
@enduml
|
|
||||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 12 KiB |
|
|
@ -1,18 +0,0 @@
|
||||||
@startuml
|
|
||||||
title Listing removal by owner or moderator
|
|
||||||
actor Owner
|
|
||||||
participant "Next API" as API
|
|
||||||
database Postgres as DB
|
|
||||||
actor Moderator
|
|
||||||
|
|
||||||
Owner -> API: POST /api/listings/remove (listingId)
|
|
||||||
API -> DB: verify owner or moderator\nfetch listing
|
|
||||||
API -> DB: set status=REMOVED\npublished=false\nremovedAt/by
|
|
||||||
Moderator -> API: POST /api/admin/listings/approve\n(action=remove)
|
|
||||||
API -> DB: same status change if via admin path
|
|
||||||
Owner -> API: GET /api/listings/mine
|
|
||||||
API -> DB: fetch listings for owner (includes REMOVED)
|
|
||||||
Public -> API: GET /listings/[slug]
|
|
||||||
API -> DB: filter out removed listings
|
|
||||||
API --> Public: not found if removed
|
|
||||||
@enduml
|
|
||||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 12 KiB |
|
|
@ -1,10 +0,0 @@
|
||||||
@startuml
|
|
||||||
title Profile update (name/password)
|
|
||||||
actor User
|
|
||||||
participant "Next API" as API
|
|
||||||
database Postgres as DB
|
|
||||||
|
|
||||||
User -> API: PATCH /api/me\n(name?, password?)
|
|
||||||
API -> DB: update name/passwordHash\n(email immutable)
|
|
||||||
API --> User: updated profile payload
|
|
||||||
@enduml
|
|
||||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 6.3 KiB |
|
|
@ -8,40 +8,102 @@
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<h1>Sequence Diagrams</h1>
|
<h1>Sequence Diagrams</h1>
|
||||||
<div class="meta">PlantUML sources for key flows; render locally.</div>
|
<div class="meta">Mermaid-rendered flows for the most important user journeys.</div>
|
||||||
</header>
|
</header>
|
||||||
<main class="grid">
|
<main class="grid">
|
||||||
<section class="card">
|
<section class="card">
|
||||||
<h2>User Registration & Verification</h2>
|
<h2>User Registration & Verification</h2>
|
||||||
<p>PlantUML: <code>docs/plantuml/auth-register-login.puml</code></p>
|
<div class="diagram">
|
||||||
<img src="./plantuml/auth-register-login.svg" alt="User registration and verification sequence" class="diagram-img" />
|
<pre class="mermaid">
|
||||||
|
sequenceDiagram
|
||||||
|
participant U as User
|
||||||
|
participant W as Web (Next.js)
|
||||||
|
participant DB as Postgres
|
||||||
|
participant Mail as SMTP
|
||||||
|
|
||||||
|
U->>W: Submit registration form (email, password)
|
||||||
|
W->>DB: Create pending user + verification token
|
||||||
|
W->>Mail: Send verification email with token link
|
||||||
|
U-->>Mail: Opens email
|
||||||
|
U->>W: Click verify link
|
||||||
|
W->>DB: Mark email verified (status = verified, awaiting approval)
|
||||||
|
Admin->>W: Approves user
|
||||||
|
W->>DB: Update status = approved
|
||||||
|
U->>W: Login (email/password)
|
||||||
|
W->>DB: Validate credentials, create session token
|
||||||
|
W-->>U: Set session cookie
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="card">
|
<section class="card">
|
||||||
<h2>Listing Creation & Approval</h2>
|
<h2>Listing Creation & Approval</h2>
|
||||||
<p>PlantUML: <code>docs/plantuml/listing-create-approve.puml</code></p>
|
<div class="diagram">
|
||||||
<img src="./plantuml/listing-create-approve.svg" alt="Listing creation and approval sequence" class="diagram-img" />
|
<pre class="mermaid">
|
||||||
|
sequenceDiagram
|
||||||
|
participant Host as Host (logged in)
|
||||||
|
participant W as Web/API
|
||||||
|
participant DB as Postgres
|
||||||
|
participant Mod as Moderator
|
||||||
|
|
||||||
|
Host->>W: Open "New listing" and submit details (address, amenities, images)
|
||||||
|
W->>DB: Save listing (status = PENDING)
|
||||||
|
Mod->>W: Review pending listing
|
||||||
|
W->>DB: Approve -> status = PUBLISHED
|
||||||
|
Host-->>W: Listing appears in "My listings" and public browse
|
||||||
|
Public->>W: Browse latest/map; fetch listing translation + cover image
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="card">
|
<section class="card">
|
||||||
<h2>Listing Removal by Owner/Moderator</h2>
|
<h2>Listing Removal by Owner/Moderator</h2>
|
||||||
<p>PlantUML: <code>docs/plantuml/listing-removal.puml</code></p>
|
<div class="diagram">
|
||||||
<img src="./plantuml/listing-removal.svg" alt="Listing removal sequence" class="diagram-img" />
|
<pre class="mermaid">
|
||||||
|
sequenceDiagram
|
||||||
|
participant Owner as Owner/Moderator
|
||||||
|
participant W as Web/API
|
||||||
|
participant DB as Postgres
|
||||||
|
|
||||||
|
Owner->>W: Click "Remove" on listing
|
||||||
|
W->>Owner: Confirm removal
|
||||||
|
Owner-->>W: Confirm
|
||||||
|
W->>DB: Set removedAt timestamp, status = REMOVED
|
||||||
|
W-->>Owner: Show updated state in "My listings"
|
||||||
|
Public--xW: Listing hidden from browse/slug pages
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="card">
|
<section class="card">
|
||||||
<h2>Profile Update (Name/Password)</h2>
|
<h2>Profile Update (Name/Password)</h2>
|
||||||
<p>PlantUML: <code>docs/plantuml/profile-update.puml</code></p>
|
<div class="diagram">
|
||||||
<img src="./plantuml/profile-update.svg" alt="Profile update sequence" class="diagram-img" />
|
<pre class="mermaid">
|
||||||
|
sequenceDiagram
|
||||||
|
participant User
|
||||||
|
participant W as Web/API
|
||||||
|
participant DB as Postgres
|
||||||
|
|
||||||
|
User->>W: Open profile page (requires session cookie)
|
||||||
|
W->>DB: Fetch user record (email immutable)
|
||||||
|
User->>W: Submit updated name and/or password
|
||||||
|
W->>DB: Update fields (hash password if provided)
|
||||||
|
W-->>User: Show "Profile updated"
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="card">
|
<section class="card">
|
||||||
<h2>Rendering instructions</h2>
|
<h2>Rendering instructions</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>PlantUML: <code>plantuml docs/plantuml/*.puml</code> (local PlantUML/Java or Docker).</li>
|
<li>Mermaid renders automatically in-browser via CDN; no local tooling required.</li>
|
||||||
<li>Draw.io: open <code>docs/drawio/*.drawio</code> in the desktop app to edit/export PNG/SVG locally.</li>
|
<li>Edit the Mermaid blocks inline in these HTML files.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
<script type="module">
|
||||||
|
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
|
||||||
|
mermaid.initialize({ startOnLoad: true, theme: 'dark' });
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -80,3 +80,18 @@ ul {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: #0b1220;
|
background: #0b1220;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mermaid {
|
||||||
|
background: #0b1220;
|
||||||
|
border: 1px solid #1f2937;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.callout {
|
||||||
|
background: #0b1220;
|
||||||
|
border: 1px dashed #1f2937;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 12px;
|
||||||
|
color: #cbd5e1;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue