diff --git a/.env.example b/.env.example index a047dda..9d31b2f 100644 --- a/.env.example +++ b/.env.example @@ -28,6 +28,12 @@ OIDC_CLIENT_SECRET= OIDC_REDIRECT_URI=https://octane.dandrove.com/auth/callback ADMIN_GROUP_NAME=octane-admins +# Optional — public URL of Authentik (the one users' browsers can actually +# reach, unlike AUTHENTIK_ISSUER_URL above which may be an internal Docker +# address). Shows a "Mon compte" link in the nav and on the profile page so +# users can change their own password. Hidden entirely if left blank. +AUTHENTIK_PUBLIC_URL=https://auth.dandrove.com + # Docker networking: external network shared with Traefik and Authentik TRAEFIK_NETWORK_NAME=traefik-proxy diff --git a/README.md b/README.md index 11e2c3f..f97815b 100644 --- a/README.md +++ b/README.md @@ -340,6 +340,7 @@ Le [Démarrage rapide](#démarrage-rapide-serveur-avec-traefik) ci-dessus couvre | `OIDC_CLIENT_ID` / `OIDC_CLIENT_SECRET` | Identifiants du provider Authentik | | `OIDC_REDIRECT_URI` | URL publique de callback, doit correspondre à celle configurée dans Authentik (ex: `https://octane.dandrove.com/auth/callback`) | | `ADMIN_GROUP_NAME` | Nom du groupe Authentik dont les membres deviennent admins | +| `AUTHENTIK_PUBLIC_URL` | Optionnel — URL publique d'Authentik, pour afficher un lien "Mon compte" (nav + page profil) permettant à chacun de changer son mot de passe. Masqué si absent | | `TRAEFIK_NETWORK_NAME` | Nom du réseau Docker externe partagé avec Traefik et Authentik (défaut `traefik-proxy`) | | `APP_DOMAIN` | Nom de domaine public utilisé par Traefik pour router vers l'app (ex: `octane.dandrove.com`) | | `APP_PORT` | Port hôte utilisé uniquement par `docker-compose.dev.yml` (test local sans Traefik) | diff --git a/public/js/nav.js b/public/js/nav.js index 5af2d6e..e73c2f3 100644 --- a/public/js/nav.js +++ b/public/js/nav.js @@ -34,6 +34,7 @@ async function initNav(activePage) {
-

Identité gérée par Authentik — pour changer votre nom, email ou mot de passe, rendez-vous sur votre compte Authentik.

+

+ Identité gérée par Authentik — pour changer votre nom, email ou mot de passe, + ${profile.authentikAccountUrl + ? `rendez-vous sur votre compte Authentik.` + : 'rendez-vous sur votre compte Authentik.'} +

`; diff --git a/src/config.js b/src/config.js index 089eb93..b25bad0 100644 --- a/src/config.js +++ b/src/config.js @@ -42,6 +42,11 @@ module.exports = { process.env.POST_LOGOUT_REDIRECT_URI || (process.env.OIDC_REDIRECT_URI ? new URL('/', process.env.OIDC_REDIRECT_URI).href : undefined), adminGroupName: process.env.ADMIN_GROUP_NAME || 'octane-admins', + // Optional: public URL of the Authentik instance (e.g. https://auth.dandrove.com), + // used only to show users a link to manage their own account/password. + // Distinct from AUTHENTIK_ISSUER_URL, which is often an internal/Docker + // address not reachable from a user's browser. Hidden from the UI if unset. + authentikPublicUrl: process.env.AUTHENTIK_PUBLIC_URL || null, // All optional: the "add a song" autocomplete works with none of these set // (title/artist suggestions come from Apple's free, key-less iTunes Search // API). Without Spotify/YouTube credentials, the matching links are just diff --git a/src/routes/users.js b/src/routes/users.js index 4e8a90f..d69e2fc 100644 --- a/src/routes/users.js +++ b/src/routes/users.js @@ -1,14 +1,28 @@ const express = require('express'); const usersRepo = require('../repositories/usersRepo'); +const config = require('../config'); const asyncHandler = require('../lib/asyncHandler'); const router = express.Router(); +function authentikAccountUrl() { + if (!config.authentikPublicUrl) return null; + return new URL('/if/user/', config.authentikPublicUrl).href; +} + router.get( '/me', asyncHandler(async (req, res) => { const { id, name, username, email, avatar_url, is_admin } = req.user; - res.json({ id, name, username, email, avatarUrl: avatar_url, isAdmin: is_admin }); + res.json({ + id, + name, + username, + email, + avatarUrl: avatar_url, + isAdmin: is_admin, + authentikAccountUrl: authentikAccountUrl(), + }); }) ); @@ -27,6 +41,7 @@ router.get( isAdmin: is_admin, createdAt: created_at, stats, + authentikAccountUrl: authentikAccountUrl(), }); }) );