From a6e951b48c94f43a929089bc4800553376369b24 Mon Sep 17 00:00:00 2001 From: Hare Date: Thu, 4 Dec 2025 06:23:16 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20tag=E3=81=AE=E5=89=8A=E9=99=A4=E3=81=A8?= =?UTF-8?q?wildcard=E4=BC=9D=E6=92=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 +++++----- .../permits_lib/domain/MutablePermissionTree.kt | 10 ---------- .../permits_lib/domain/PermissionNode.kt | 3 +-- .../permits_lib/domain/PermissionNodeDraft.kt | 5 +---- .../permits_lib/domain/TreeSnapshot.kt | 3 --- .../permits_lib/domain/WildcardAugmentor.kt | 17 +++++++++++++++-- .../permits_lib/dsl/PermissionNodeBuilder.kt | 6 ------ 7 files changed, 22 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 765192e..fbe6b71 100644 --- a/README.md +++ b/README.md @@ -109,8 +109,8 @@ stage edits procedurally before ever touching `MutationSession`. ### Concepts - **Permission tree** – immutable graph of `PermissionNode`s. Nodes specify description, default value, - boolean children map, optional tags, and the `wildcard` flag (disabled by default) that, when enabled, - makes the library create/update `namespace.path.*` aggregate permissions automatically. + boolean children map, and the `wildcard` flag (enabled by default) that keeps `namespace.path.*` + aggregate permissions in sync automatically. - **DSL** – `permissionTree("namespace") { ... }` ensures consistent prefixes and validation (no cycles). Every `node("command", NodeRegistration.PERMISSION)` (or `.STRUCTURAL`) is relative to that namespace, so you never include the namespace manually at the root. - **Nested nodes** – `node("command", NodeRegistration.STRUCTURAL) { node("reload", NodeRegistration.PERMISSION) { ... } }` automatically produces `namespace.command` and `namespace.command.reload` plus wires the parent/child relationship so you don't @@ -125,9 +125,9 @@ stage edits procedurally before ever touching `MutationSession`. other namespaces. - **PermissionRegistry** – calculates a diff between snapshots and performs the minimum additions, removals, or updates via Bukkit's `PluginManager`. -- **Wildcards** – opt-in via `wildcard = true` to have the generated `namespace.command.*` child kept in sync, - so granting `example.command.*` automatically grants every nested node you marked; leave it `false` (default) - to keep nodes out of the wildcard. +- **Wildcards** – enabled by default; the generated `namespace.command.*` child stays in sync so granting + `example.command.*` automatically grants every nested node plus wildcard descendants such as + `example.command.debug.*`. Set `wildcard = false` on specific nodes to opt them out. - **Mutable edits** – `permits.edit { ... }` clones the currently registered tree, lets you mutate nodes imperatively, re-validates, and only pushes the structural diff to Bukkit. - **AttachmentSynchronizer** – manages identity-based `PermissionAttachment`s and exposes high-level diff --git a/src/main/kotlin/net/hareworks/permits_lib/domain/MutablePermissionTree.kt b/src/main/kotlin/net/hareworks/permits_lib/domain/MutablePermissionTree.kt index 5b3d1ca..830de21 100644 --- a/src/main/kotlin/net/hareworks/permits_lib/domain/MutablePermissionTree.kt +++ b/src/main/kotlin/net/hareworks/permits_lib/domain/MutablePermissionTree.kt @@ -70,15 +70,6 @@ class MutablePermissionTree internal constructor( draft.registration = value } - val tags: MutableSet - get() = draft.tags - - fun tag(value: String) { - if (value.isNotBlank()) { - draft.tags += value.trim() - } - } - fun child(id: String, value: Boolean = true) { require(id.isNotBlank()) { "Child id must not be blank." } val permissionId = PermissionId.of("${this.id.value}.${id.lowercase()}") @@ -158,7 +149,6 @@ class MutablePermissionTree internal constructor( description = draft.description, defaultValue = draft.defaultValue, children = draft.children.toMutableMap(), - tags = draft.tags.toMutableSet(), wildcard = draft.wildcard, registration = draft.registration ) diff --git a/src/main/kotlin/net/hareworks/permits_lib/domain/PermissionNode.kt b/src/main/kotlin/net/hareworks/permits_lib/domain/PermissionNode.kt index 930eb71..ac27aa5 100644 --- a/src/main/kotlin/net/hareworks/permits_lib/domain/PermissionNode.kt +++ b/src/main/kotlin/net/hareworks/permits_lib/domain/PermissionNode.kt @@ -13,8 +13,7 @@ data class PermissionNode( val description: String? = null, val defaultValue: PermissionDefault = PermissionDefault.FALSE, val children: Map = emptyMap(), - val tags: Set = emptySet(), - val wildcard: Boolean = false, + val wildcard: Boolean = true, val registration: NodeRegistration = NodeRegistration.PERMISSION ) { init { diff --git a/src/main/kotlin/net/hareworks/permits_lib/domain/PermissionNodeDraft.kt b/src/main/kotlin/net/hareworks/permits_lib/domain/PermissionNodeDraft.kt index 9df8a8c..c3e6c9d 100644 --- a/src/main/kotlin/net/hareworks/permits_lib/domain/PermissionNodeDraft.kt +++ b/src/main/kotlin/net/hareworks/permits_lib/domain/PermissionNodeDraft.kt @@ -7,8 +7,7 @@ internal data class PermissionNodeDraft( var description: String? = null, var defaultValue: PermissionDefault = PermissionDefault.FALSE, val children: MutableMap = linkedMapOf(), - val tags: MutableSet = linkedSetOf(), - var wildcard: Boolean = false, + var wildcard: Boolean = true, var registration: NodeRegistration = NodeRegistration.PERMISSION ) { fun toNode(): PermissionNode = @@ -17,7 +16,6 @@ internal data class PermissionNodeDraft( description = description, defaultValue = defaultValue, children = children.toMap(), - tags = tags.toSet(), wildcard = wildcard, registration = registration ) @@ -29,7 +27,6 @@ internal data class PermissionNodeDraft( description = node.description, defaultValue = node.defaultValue, children = node.children.toMutableMap(), - tags = node.tags.toMutableSet(), wildcard = node.wildcard, registration = node.registration ) diff --git a/src/main/kotlin/net/hareworks/permits_lib/domain/TreeSnapshot.kt b/src/main/kotlin/net/hareworks/permits_lib/domain/TreeSnapshot.kt index 045a02c..0171cfd 100644 --- a/src/main/kotlin/net/hareworks/permits_lib/domain/TreeSnapshot.kt +++ b/src/main/kotlin/net/hareworks/permits_lib/domain/TreeSnapshot.kt @@ -25,9 +25,6 @@ class TreeSnapshot internal constructor( digest.update(childId.value.toByteArray()) digest.update(if (flag) 1 else 0) } - node.tags.sorted().forEach { tag -> - digest.update(tag.toByteArray()) - } digest.update(if (node.wildcard) 1 else 0) digest.update(node.registration.name.toByteArray()) } diff --git a/src/main/kotlin/net/hareworks/permits_lib/domain/WildcardAugmentor.kt b/src/main/kotlin/net/hareworks/permits_lib/domain/WildcardAugmentor.kt index 4844ea1..6812fc7 100644 --- a/src/main/kotlin/net/hareworks/permits_lib/domain/WildcardAugmentor.kt +++ b/src/main/kotlin/net/hareworks/permits_lib/domain/WildcardAugmentor.kt @@ -9,7 +9,6 @@ internal object WildcardAugmentor { nodes.values.forEach { node -> if (!node.wildcard) return@forEach - if (node.id.value.endsWith(".*")) return@forEach val wildcardId = parentWildcardId(node.id) ?: return@forEach val existing = result[wildcardId] @@ -25,7 +24,6 @@ internal object WildcardAugmentor { description = "Wildcard for ${wildcardId.value}", defaultValue = node.defaultValue, children = updatedChildren, - tags = setOf("wildcard"), wildcard = false ) } else if (!alreadyPresent) { @@ -33,6 +31,21 @@ internal object WildcardAugmentor { } } + // Ensure wildcard permissions include descendant wildcard nodes so granting parent.* cascades. + val wildcardEntries = result + .filterKeys { it.value.endsWith(".*") } + .entries + .sortedBy { it.key.value.length } // parents before grandparents not necessary but deterministic + + wildcardEntries.forEach { (childWildcardId, _) -> + val parentWildcardId = parentWildcardId(childWildcardId) ?: return@forEach + val parent = result[parentWildcardId] ?: return@forEach + val updatedChildren = parent.children.toMutableMap() + if (updatedChildren[childWildcardId] == true) return@forEach + updatedChildren[childWildcardId] = true + result[parentWildcardId] = parent.copy(children = updatedChildren) + } + return result } diff --git a/src/main/kotlin/net/hareworks/permits_lib/dsl/PermissionNodeBuilder.kt b/src/main/kotlin/net/hareworks/permits_lib/dsl/PermissionNodeBuilder.kt index 5aec90c..21f50a8 100644 --- a/src/main/kotlin/net/hareworks/permits_lib/dsl/PermissionNodeBuilder.kt +++ b/src/main/kotlin/net/hareworks/permits_lib/dsl/PermissionNodeBuilder.kt @@ -34,12 +34,6 @@ class PermissionNodeBuilder internal constructor( draft.registration = value } - fun tag(value: String) { - if (value.isNotBlank()) { - draft.tags += value.trim() - } - } - fun child(id: String, value: Boolean = true) { treeBuilder.childRelative(draft, id, value) }