Merge pull request 'ObsiGate 2.86.1 — barre v0.6.0 : entrée « Administration » du menu compte (fusion #142)' (#72) from menu-compte-admin-v060 into main
This commit was merged in pull request #72.
This commit is contained in:
+7
-1
@@ -6,7 +6,7 @@ Format basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/),
|
|||||||
et [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
et [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
> **En cours de développement** : les changements à venir sont listés dans la section
|
> **En cours de développement** : les changements à venir sont listés dans la section
|
||||||
> [Unreleased](#unreleased). La dernière version livrée est **2.86.0**.
|
> [Unreleased](#unreleased). La dernière version livrée est **2.86.1**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -14,6 +14,12 @@ et [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## [2.86.1] — 2026-11-06
|
||||||
|
|
||||||
|
- **Barre commune v0.6.0 — entrée « Administration » du menu compte** (fusion #142, demande de Bruno) : barre re-vendangée **verbatim** depuis dracodev-commons (PR commons #14) — `frontend/draco-barre.js` et `frontend/draco-barre.css`. Le menu compte gagne un cinquième lien Hub, « Administration » → `<hub>/admin` (le Hub redirige vers `/admin/utilisateurs`), après le séparateur et avant « Déconnexion », à **visibilité conditionnelle** : l'entrée n'apparaît que si l'hôte affirme que le compte courant est administrateur de suite (`DRACO_BAR.setAdmin`). Branchement hôte : `frontend/index.html` affirme le statut depuis la réponse de `/api/auth/me` déjà chargée pour l'avatar — `setAdmin(u.role === "admin")`. Le rôle global du compte chez ObsiGate est la définition même de l'administrateur de suite (c'est lui que la garde `/admin/*` du Hub vérifie, via ce même endpoint) : ObsiGate le connaît nativement. Tout autre rôle, ou échec de l'appel : aucune affirmation, l'entrée reste masquée. Garde : `tests/test_draco_barre.py` (`test_barre_v060_entree_administration`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## [2.86.0] — 2026-11-06
|
## [2.86.0] — 2026-11-06
|
||||||
|
|
||||||
- **BUG-122 — Déconnexion globale navigable : `GET /sso/logout`** (fusion #141) : le bouton « Déconnexion » du menu compte de la barre commune ne faisait rien dans les applications sœurs — la barre relaie l'action à l'hôte, et la déconnexion globale d'ObsiGate (ACC-3.1, #216) n'était appelable qu'en same-origin depuis l'interface d'ObsiGate (`POST /api/auth/logout`). Nouvelle route `GET /sso/logout?return_to=`, symétrique de `/sso/authorize` : elle exécute la déconnexion globale — logique extraite dans `apply_global_logout()` (`backend/auth/router.py`), désormais partagée par les deux entrées (jetons natifs refresh/access révoqués, `jti` du cookie `draco_session` révoqué, cookie effacé sur le domaine parent) — puis redirige vers le `return_to` validé par la liste blanche existante (`validate_return_to` : https + `*.dracodev.net`, repli « / »). Idempotente sans session. Les applications sœurs branchent leur action `deconnexion` sur cette route (leur session locale est détruite d'abord chez celles qui en ont une) — et la barre d'ObsiGate elle-même aussi (`frontend/index.html`, retour à sa racine). Tests : `tests/test_draco_session.py` (+3 : révocation et redirection, liste blanche, idempotence), `tests/test_draco_barre.py` (+1 : branchement de la barre d'ObsiGate). Fiche : `docs/features/deconnexion-globale-bug-122.md`.
|
- **BUG-122 — Déconnexion globale navigable : `GET /sso/logout`** (fusion #141) : le bouton « Déconnexion » du menu compte de la barre commune ne faisait rien dans les applications sœurs — la barre relaie l'action à l'hôte, et la déconnexion globale d'ObsiGate (ACC-3.1, #216) n'était appelable qu'en same-origin depuis l'interface d'ObsiGate (`POST /api/auth/logout`). Nouvelle route `GET /sso/logout?return_to=`, symétrique de `/sso/authorize` : elle exécute la déconnexion globale — logique extraite dans `apply_global_logout()` (`backend/auth/router.py`), désormais partagée par les deux entrées (jetons natifs refresh/access révoqués, `jti` du cookie `draco_session` révoqué, cookie effacé sur le domaine parent) — puis redirige vers le `return_to` validé par la liste blanche existante (`validate_return_to` : https + `*.dracodev.net`, repli « / »). Idempotente sans session. Les applications sœurs branchent leur action `deconnexion` sur cette route (leur session locale est détruite d'abord chez celles qui en ont une) — et la barre d'ObsiGate elle-même aussi (`frontend/index.html`, retour à sa racine). Tests : `tests/test_draco_session.py` (+3 : révocation et redirection, liste blanche, idempotence), `tests/test_draco_barre.py` (+1 : branchement de la barre d'ObsiGate). Fiche : `docs/features/deconnexion-globale-bug-122.md`.
|
||||||
|
|||||||
+3
-3
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
**Porte d'entrée web ultra-léger pour vos vaults Obsidian** — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive.
|
**Porte d'entrée web ultra-léger pour vos vaults Obsidian** — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive.
|
||||||
|
|
||||||
[]()
|
[]()
|
||||||
[](https://opensource.org/licenses/MIT)
|
[](https://opensource.org/licenses/MIT)
|
||||||
[](https://www.docker.com/)
|
[](https://www.docker.com/)
|
||||||
[](https://www.python.org/)
|
[](https://www.python.org/)
|
||||||
@@ -977,8 +977,8 @@ Ce projet est sous licence **MIT** — voir le fichier [LICENSE](LICENSE) pour l
|
|||||||
|
|
||||||
## 📝 Changelog
|
## 📝 Changelog
|
||||||
|
|
||||||
Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.86.0).
|
Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.86.1).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*Projet : ObsiGate | Version : 2.86.0 | Dernière mise à jour : Septembre 2026*
|
*Projet : ObsiGate | Version : 2.86.1 | Dernière mise à jour : Septembre 2026*
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
**Ultra-light web gateway for your Obsidian vaults** — Access, browse, and search all your Obsidian notes from any device via a modern, responsive web interface.
|
**Ultra-light web gateway for your Obsidian vaults** — Access, browse, and search all your Obsidian notes from any device via a modern, responsive web interface.
|
||||||
|
|
||||||
[]()
|
[]()
|
||||||
[](https://opensource.org/licenses/MIT)
|
[](https://opensource.org/licenses/MIT)
|
||||||
[](https://www.docker.com/)
|
[](https://www.docker.com/)
|
||||||
[](https://www.python.org/)
|
[](https://www.python.org/)
|
||||||
@@ -1152,8 +1152,8 @@ This project is licensed under the **MIT License** - see the [LICENSE](LICENSE)
|
|||||||
|
|
||||||
## 📝 Changelog
|
## 📝 Changelog
|
||||||
|
|
||||||
See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.86.0).
|
See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.86.1).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*Project: ObsiGate | Version: 2.86.0 | Last updated: September 2026*
|
*Project: ObsiGate | Version: 2.86.1 | Last updated: September 2026*
|
||||||
|
|||||||
Generated
+1
-1
@@ -2626,7 +2626,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "obsigate-desktop"
|
name = "obsigate-desktop"
|
||||||
version = "2.86.0"
|
version = "2.86.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "obsigate-desktop"
|
name = "obsigate-desktop"
|
||||||
version = "2.86.0"
|
version = "2.86.1"
|
||||||
description = "ObsiGate Desktop — Porte d'entrée native pour vos vaults Obsidian"
|
description = "ObsiGate Desktop — Porte d'entrée native pour vos vaults Obsidian"
|
||||||
authors = ["Bruno Charest"]
|
authors = ["Bruno Charest"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://raw.githubusercontent.com/nicedoc/obsigate/main/desktop/tauri.conf.schema.json",
|
"$schema": "https://raw.githubusercontent.com/nicedoc/obsigate/main/desktop/tauri.conf.schema.json",
|
||||||
"productName": "ObsiGate",
|
"productName": "ObsiGate",
|
||||||
"version": "2.86.0",
|
"version": "2.86.1",
|
||||||
"identifier": "com.obsigate.desktop",
|
"identifier": "com.obsigate.desktop",
|
||||||
"build": {
|
"build": {
|
||||||
"frontendDist": "../frontend",
|
"frontendDist": "../frontend",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
# ObsiGate — Roadmap
|
# ObsiGate — Roadmap
|
||||||
|
|
||||||
> **Version :** 2.86.0 | **Dernière mise à jour :** 2026-11-06
|
> **Version :** 2.86.1 | **Dernière mise à jour :** 2026-11-06
|
||||||
> **Ce fichier ne contient que le travail à venir** (🔵 En cours + ⚪ Backlog) et un index compact
|
> **Ce fichier ne contient que le travail à venir** (🔵 En cours + ⚪ Backlog) et un index compact
|
||||||
> vers les fonctionnalités livrées.
|
> vers les fonctionnalités livrées.
|
||||||
> - **Méthode de livraison à appliquer pour toute tâche : [DELIVERY_WORKFLOW.md](./DELIVERY_WORKFLOW.md)**
|
> - **Méthode de livraison à appliquer pour toute tâche : [DELIVERY_WORKFLOW.md](./DELIVERY_WORKFLOW.md)**
|
||||||
|
|||||||
@@ -101,6 +101,11 @@
|
|||||||
text-decoration: none; cursor: pointer;
|
text-decoration: none; cursor: pointer;
|
||||||
}
|
}
|
||||||
.draco-menu-item:hover, .draco-menu-item:focus-visible { background: var(--surface-2); }
|
.draco-menu-item:hover, .draco-menu-item:focus-visible { background: var(--surface-2); }
|
||||||
|
/* Item conditionnel masqué (v0.6.0 : « Administration » tant que
|
||||||
|
l'hôte n'a pas affirmé le statut d'administrateur) — le
|
||||||
|
display:flex ci-dessus écraserait l'attribut hidden sans cette
|
||||||
|
règle, même patron que .draco-compte-menu[hidden]. */
|
||||||
|
.draco-menu-item[hidden] { display: none; }
|
||||||
/* Icônes monoline du menu compte (v0.4.0) : appendues après le
|
/* Icônes monoline du menu compte (v0.4.0) : appendues après le
|
||||||
libellé dans le DOM, replacées à gauche par order: -1. */
|
libellé dans le DOM, replacées à gauche par order: -1. */
|
||||||
.draco-menu-icone {
|
.draco-menu-icone {
|
||||||
|
|||||||
@@ -42,6 +42,22 @@
|
|||||||
* l'ouverture par le mécanisme data-theme des hôtes, avec cache
|
* l'ouverture par le mécanisme data-theme des hôtes, avec cache
|
||||||
* local court et repli intégral sur le comportement actuel de
|
* local court et repli intégral sur le comportement actuel de
|
||||||
* l'hôte si le Hub ne répond pas. Voir « Thème commun » plus bas.
|
* l'hôte si le Hub ne répond pas. Voir « Thème commun » plus bas.
|
||||||
|
* v0.6.0 (demande de Bruno, 2026-11-06) : le menu compte gagne un
|
||||||
|
* cinquième lien Hub, « Administration » → <hub>/admin (le Hub y
|
||||||
|
* redirige vers /admin/utilisateurs), placé après le séparateur,
|
||||||
|
* avant « Déconnexion », avec son icône monoline (curseurs de
|
||||||
|
* réglage). AFFICHAGE CONDITIONNEL : l'entrée n'apparaît que si
|
||||||
|
* l'hôte AFFIRME que le compte courant est administrateur de
|
||||||
|
* suite — cfg.admin === true à la configuration, ou
|
||||||
|
* DRACO_BAR.setAdmin(true) quand l'hôte l'apprend après coup
|
||||||
|
* (patron setUrls). L'hôte ne passe le drapeau que s'il l'a établi
|
||||||
|
* depuis SA source d'autorité (rôle global du compte chez
|
||||||
|
* ObsiGate, niveau du registre des rôles du Hub pour son app…) ;
|
||||||
|
* à défaut de certitude, pas de drapeau et l'entrée reste masquée.
|
||||||
|
* La barre ne devine jamais : le jeton draco ne porte aucun rôle
|
||||||
|
* (claims minimaux, par design). La vraie protection reste la
|
||||||
|
* garde serveur du Hub (/admin/*), pas ce masquage d'affichage.
|
||||||
|
* Voir le README, « Administration » — contrat de visibilité.
|
||||||
*
|
*
|
||||||
* Aucun gestionnaire inline : un seul écouteur délégué sur le document
|
* Aucun gestionnaire inline : un seul écouteur délégué sur le document
|
||||||
* (patron validé par le prototype — les onclick du HTML généré sont
|
* (patron validé par le prototype — les onclick du HTML généré sont
|
||||||
@@ -54,6 +70,11 @@
|
|||||||
* counts: { tiktak: 3, kanbante: 3, alertes: 3, spark: 0 },
|
* counts: { tiktak: 3, kanbante: 3, alertes: 3, spark: 0 },
|
||||||
* user: "Bruno", // nom affiché (v0.1.6) ;
|
* user: "Bruno", // nom affiché (v0.1.6) ;
|
||||||
* // ou { display_name: "Bruno", username: "bruno" }
|
* // ou { display_name: "Bruno", username: "bruno" }
|
||||||
|
* admin: true, // (v0.6.0, optionnel)
|
||||||
|
* // administrateur de suite ÉTABLI par l'hôte : démasque
|
||||||
|
* // l'entrée « Administration » du menu compte. Absent ou
|
||||||
|
* // non-strictement-true → entrée masquée. Peut aussi être
|
||||||
|
* // posé après coup via DRACO_BAR.setAdmin(true).
|
||||||
* urls: { // bases des applications
|
* urls: { // bases des applications
|
||||||
* obsigate: "https://og.dracodev.net/",
|
* obsigate: "https://og.dracodev.net/",
|
||||||
* flowdeck: "https://flowdeck.dracodev.net/",
|
* flowdeck: "https://flowdeck.dracodev.net/",
|
||||||
@@ -653,6 +674,18 @@
|
|||||||
["path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }],
|
["path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }],
|
||||||
["circle", { cx: "12", cy: "7", r: "4" }]
|
["circle", { cx: "12", cy: "7", r: "4" }]
|
||||||
],
|
],
|
||||||
|
/* Curseurs de réglage (trois axes, trois boutons) — v0.6.0. */
|
||||||
|
"admin": [
|
||||||
|
["line", { x1: "4", y1: "21", x2: "4", y2: "14" }],
|
||||||
|
["line", { x1: "4", y1: "10", x2: "4", y2: "3" }],
|
||||||
|
["line", { x1: "12", y1: "21", x2: "12", y2: "12" }],
|
||||||
|
["line", { x1: "12", y1: "8", x2: "12", y2: "3" }],
|
||||||
|
["line", { x1: "20", y1: "21", x2: "20", y2: "16" }],
|
||||||
|
["line", { x1: "20", y1: "12", x2: "20", y2: "3" }],
|
||||||
|
["line", { x1: "1", y1: "14", x2: "7", y2: "14" }],
|
||||||
|
["line", { x1: "9", y1: "8", x2: "15", y2: "8" }],
|
||||||
|
["line", { x1: "17", y1: "16", x2: "23", y2: "16" }]
|
||||||
|
],
|
||||||
/* Flèche sortant d'un cadre (porte). */
|
/* Flèche sortant d'un cadre (porte). */
|
||||||
"deconnexion": [
|
"deconnexion": [
|
||||||
["path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }],
|
["path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }],
|
||||||
@@ -687,6 +720,15 @@
|
|||||||
return span;
|
return span;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Visibilité de l'entrée « Administration » (v0.6.0) : vraie
|
||||||
|
* seulement si l'hôte l'a AFFIRMÉE — cfg.admin === true à la
|
||||||
|
* configuration, ou DRACO_BAR.setAdmin(true) après coup. La
|
||||||
|
* barre ne déduit jamais ce statut (le jeton draco ne porte
|
||||||
|
* aucun rôle) ; à défaut, l'entrée reste masquée et la garde
|
||||||
|
* serveur du Hub reste la vraie protection. */
|
||||||
|
var compteAdmin = cfg.admin === true;
|
||||||
|
var adminItem = null;
|
||||||
|
|
||||||
/* Menu compte (v0.1.6 ; v0.3.0 pour les liens) — en-tête
|
/* Menu compte (v0.1.6 ; v0.3.0 pour les liens) — en-tête
|
||||||
* d'identité, puis les liens du Hub (Télécharger, À Propos,
|
* d'identité, puis les liens du Hub (Télécharger, À Propos,
|
||||||
* Aides, Profil — vrais <a href>, même patron que le menu des
|
* Aides, Profil — vrais <a href>, même patron que le menu des
|
||||||
@@ -719,6 +761,22 @@
|
|||||||
sep.className = "draco-menu-sep";
|
sep.className = "draco-menu-sep";
|
||||||
sep.setAttribute("aria-hidden", "true");
|
sep.setAttribute("aria-hidden", "true");
|
||||||
compteMenu.appendChild(sep);
|
compteMenu.appendChild(sep);
|
||||||
|
/* « Administration » (v0.6.0) : cinquième lien Hub
|
||||||
|
* (<hub>/admin, où le Hub redirige vers /admin/utilisateurs).
|
||||||
|
* data-hub-link="admin" : son href est resynchronisé par
|
||||||
|
* refreshCompteHrefs / setUrls comme les quatre autres liens.
|
||||||
|
* Toujours construit ; masqué tant que l'hôte n'a pas affirmé
|
||||||
|
* le statut d'administrateur (compteAdmin). */
|
||||||
|
var adm = document.createElement("a");
|
||||||
|
adm.className = "draco-menu-item";
|
||||||
|
adm.href = hubHref("admin");
|
||||||
|
adm.setAttribute("data-hub-link", "admin");
|
||||||
|
adm.setAttribute("role", "menuitem");
|
||||||
|
adm.textContent = "Administration";
|
||||||
|
adm.appendChild(menuIcone("admin"));
|
||||||
|
adm.hidden = !compteAdmin;
|
||||||
|
compteMenu.appendChild(adm);
|
||||||
|
adminItem = adm;
|
||||||
var b = document.createElement("button");
|
var b = document.createElement("button");
|
||||||
b.type = "button";
|
b.type = "button";
|
||||||
b.className = "draco-menu-item";
|
b.className = "draco-menu-item";
|
||||||
@@ -734,6 +792,7 @@
|
|||||||
var head = compteMenu.querySelector(".draco-compte-nom");
|
var head = compteMenu.querySelector(".draco-compte-nom");
|
||||||
var name = displayName();
|
var name = displayName();
|
||||||
if (head) head.textContent = name || "Compte";
|
if (head) head.textContent = name || "Compte";
|
||||||
|
if (adminItem) adminItem.hidden = !compteAdmin;
|
||||||
refreshCompteHrefs();
|
refreshCompteHrefs();
|
||||||
}
|
}
|
||||||
function toggleCompteMenu(force) {
|
function toggleCompteMenu(force) {
|
||||||
@@ -835,6 +894,14 @@
|
|||||||
window.DRACO_BAR.urls = resolvedUrls;
|
window.DRACO_BAR.urls = resolvedUrls;
|
||||||
applyUrls(resolvedUrls);
|
applyUrls(resolvedUrls);
|
||||||
refreshCompteHrefs();
|
refreshCompteHrefs();
|
||||||
|
},
|
||||||
|
/* Administration (v0.6.0) : l'hôte pose le drapeau quand il a
|
||||||
|
* ÉTABLI que le compte courant est administrateur de suite
|
||||||
|
* (sa source d'autorité — voir l'en-tête et le README). Toute
|
||||||
|
* valeur autre que le booléen true masque l'entrée. */
|
||||||
|
setAdmin: function (v) {
|
||||||
|
compteAdmin = v === true;
|
||||||
|
if (adminItem) adminItem.hidden = !compteAdmin;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -439,6 +439,17 @@
|
|||||||
var av = document.getElementById("draco-avatar");
|
var av = document.getElementById("draco-avatar");
|
||||||
if (av) { av.textContent = nom.charAt(0).toUpperCase(); av.title = nom; }
|
if (av) { av.textContent = nom.charAt(0).toUpperCase(); av.title = nom; }
|
||||||
}
|
}
|
||||||
|
/* Barre v0.6.0 (commons) : entrée « Administration »
|
||||||
|
du menu compte. Le rôle global du compte chez
|
||||||
|
ObsiGate EST la définition de l'administrateur
|
||||||
|
de suite (c'est lui que la garde /admin/* du Hub
|
||||||
|
vérifie, via ce même /api/auth/me) — ObsiGate le
|
||||||
|
connaît nativement, il l'affirme à la barre.
|
||||||
|
Tout autre rôle (ou échec) : pas d'affirmation,
|
||||||
|
l'entrée reste masquée. */
|
||||||
|
if (u && window.DRACO_BAR && window.DRACO_BAR.setAdmin) {
|
||||||
|
window.DRACO_BAR.setAdmin(u.role === "admin");
|
||||||
|
}
|
||||||
}).catch(function () { /* avatar générique conservé */ });
|
}).catch(function () { /* avatar générique conservé */ });
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -386,6 +386,12 @@ const AuthManager = {
|
|||||||
const section = document.getElementById("sidebar-user");
|
const section = document.getElementById("sidebar-user");
|
||||||
if (!user || !this._authEnabled) {
|
if (!user || !this._authEnabled) {
|
||||||
if (section) section.hidden = true;
|
if (section) section.hidden = true;
|
||||||
|
// Barre commune v0.6.0 (fusion #142) : sans identité
|
||||||
|
// établie, l'entrée « Administration » du menu compte
|
||||||
|
// reste masquée.
|
||||||
|
if (window.DRACO_BAR && window.DRACO_BAR.setAdmin) {
|
||||||
|
window.DRACO_BAR.setAdmin(false);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!section) return;
|
if (!section) return;
|
||||||
@@ -427,6 +433,19 @@ const AuthManager = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Barre commune v0.6.0 (fusion #142) : l'entrée
|
||||||
|
// « Administration » du menu compte suit le rôle natif du
|
||||||
|
// compte — la définition même de l'administrateur de suite
|
||||||
|
// (garde /admin/* du Hub), même source que la rangée
|
||||||
|
// d'administration native ci-dessous. renderUserSection()
|
||||||
|
// est appelée par showApp() pour toutes les sessions
|
||||||
|
// établies (connexion, restauration, renouvellement
|
||||||
|
// silencieux) ; le fetch d'amorçage d'index.html ne couvre
|
||||||
|
// que les sessions déjà présentes au chargement de la page.
|
||||||
|
if (window.DRACO_BAR && window.DRACO_BAR.setAdmin) {
|
||||||
|
window.DRACO_BAR.setAdmin(user.role === "admin");
|
||||||
|
}
|
||||||
|
|
||||||
const adminRow = document.getElementById("admin-menu-row");
|
const adminRow = document.getElementById("admin-menu-row");
|
||||||
if (adminRow) {
|
if (adminRow) {
|
||||||
if (user.role === "admin") {
|
if (user.role === "admin") {
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "obsigate",
|
"name": "obsigate",
|
||||||
"version": "2.86.0",
|
"version": "2.86.1",
|
||||||
"description": "**Porte d'entrée web ultra-léger pour vos vaults Obsidian** — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive.",
|
"description": "**Porte d'entrée web ultra-léger pour vos vaults Obsidian** — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive.",
|
||||||
"main": "patch.js",
|
"main": "patch.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
|
|||||||
@@ -101,6 +101,38 @@ def test_barre_v030_liens_hub_menu_compte():
|
|||||||
assert "v0.3.0" in html
|
assert "v0.3.0" in html
|
||||||
|
|
||||||
|
|
||||||
|
def test_barre_v060_entree_administration():
|
||||||
|
# Barre v0.6.0 (dracodev-commons, demande de Bruno du
|
||||||
|
# 2026-11-06) : entrée « Administration » du menu compte —
|
||||||
|
# lien Hub <hub>/admin à visibilité conditionnelle. Le JS
|
||||||
|
# vendangé la construit (data-hub-link="admin"), masquée tant
|
||||||
|
# que l'hôte n'affirme pas le statut d'administrateur
|
||||||
|
# (cfg.admin / DRACO_BAR.setAdmin) ; le CSS porte la règle
|
||||||
|
# [hidden] qui la masque malgré le display:flex des items.
|
||||||
|
# Branchement hôte : index.html affirme le statut depuis le
|
||||||
|
# rôle global de /api/auth/me — la définition même de
|
||||||
|
# l'administrateur de suite (garde /admin/* du Hub).
|
||||||
|
js = (FRONTEND / "draco-barre.js").read_text(encoding="utf-8")
|
||||||
|
assert 'data-hub-link", "admin"' in js
|
||||||
|
assert '"Administration"' in js
|
||||||
|
assert "setAdmin" in js
|
||||||
|
assert "compteAdmin = cfg.admin === true" in js
|
||||||
|
css = _css()
|
||||||
|
assert ".draco-menu-item[hidden]" in css
|
||||||
|
html = _index()
|
||||||
|
assert 'window.DRACO_BAR.setAdmin(u.role === "admin")' in html
|
||||||
|
# Le fetch d'amorçage d'index.html tourne avant toute
|
||||||
|
# connexion : le branchement qui couvre la connexion par le
|
||||||
|
# formulaire vit dans renderUserSection() (js/auth.js — le
|
||||||
|
# frontend servi est en modules ES ; le app.js monolithique
|
||||||
|
# à la racine n'est plus chargé), appelée par showApp() pour
|
||||||
|
# toutes les sessions établies, au même endroit que la
|
||||||
|
# rangée d'administration native.
|
||||||
|
auth_js = (FRONTEND / "js" / "auth.js").read_text(encoding="utf-8")
|
||||||
|
assert "window.DRACO_BAR.setAdmin(user.role === \"admin\")" in auth_js
|
||||||
|
assert "window.DRACO_BAR.setAdmin(false)" in auth_js
|
||||||
|
|
||||||
|
|
||||||
def test_panneau_spark_integre_218():
|
def test_panneau_spark_integre_218():
|
||||||
# #218 : le bouton Spark de la barre ouvre le panneau de l'agent
|
# #218 : le bouton Spark de la barre ouvre le panneau de l'agent
|
||||||
# commun (mêmes assets partagés que TikTak / Flowdeck / Kanbante).
|
# commun (mêmes assets partagés que TikTak / Flowdeck / Kanbante).
|
||||||
|
|||||||
Reference in New Issue
Block a user