[{"data":1,"prerenderedAt":577},["ShallowReactive",2],{"docs-\u002Fmodules\u002Fpermissions":3},{"id":4,"title":5,"body":6,"description":567,"extension":568,"meta":569,"navTitle":570,"navigation":571,"path":572,"rawbody":573,"seo":574,"stem":575,"__hash__":576},"docs\u002Fmodules\u002Fpermissions.md","Permissions",{"type":7,"value":8,"toc":553},"minimark",[9,13,17,22,25,36,39,45,48,52,55,77,84,101,105,111,137,140,158,162,165,177,188,192,195,201,204,210,214,221,227,230,236,241,250,436,474,478,516,522,526,532,538,541,547,550],[10,11,5],"h1",{"id":12},"permissions",[14,15,16],"p",{},"MagicUtils commands generate and evaluate permission nodes automatically. The\nregistry prefix controls namespacing, while annotations control explicit nodes,\ndefaults, and conditional argument checks.",[18,19,21],"h2",{"id":20},"permission-prefix","Permission Prefix",[14,23,24],{},"Every command registry has a permission prefix. You set it either directly on\nthe registry:",[26,27,33],"pre",{"className":28,"code":30,"language":31,"meta":32},[29],"language-java","CommandRegistry registry = CommandRegistry.create(plugin, \"donatemenu\", logger);\n","java","",[34,35,30],"code",{"__ignoreMap":32},[14,37,38],{},"or through the bootstrap helper:",[26,40,43],{"className":41,"code":42,"language":31,"meta":32},[29],"BukkitBootstrap.forPlugin(plugin)\n        .permissionPrefix(\"donatemenu\")\n        .enableCommands()\n        .buildRuntime();\n",[34,44,42],{"__ignoreMap":32},[14,46,47],{},"MagicUtils prepends that prefix to all generated nodes.",[18,49,51],{"id":50},"generated-nodes","Generated Nodes",[14,53,54],{},"When annotations omit explicit permission strings, MagicUtils builds defaults:",[56,57,58,65,71],"ul",{},[59,60,61,62],"li",{},"Command: ",[34,63,64],{},"commands.\u003Ccommand>",[59,66,67,68],{},"Subcommand: ",[34,69,70],{},"commands.\u003Ccommand>.subcommand.\u003Cpath>",[59,72,73,74],{},"Argument: ",[34,75,76],{},"commands.\u003Ccommand>.subcommand.\u003Cpath>.argument.\u003Cname>",[14,78,79,80,83],{},"With prefix ",[34,81,82],{},"donatemenu",":",[56,85,86,91,96],{},[59,87,88],{},[34,89,90],{},"donatemenu.commands.donate",[59,92,93],{},[34,94,95],{},"donatemenu.commands.donate.subcommand.give",[59,97,98],{},[34,99,100],{},"donatemenu.commands.donate.subcommand.give.argument.player",[18,102,104],{"id":103},"default-access","Default Access",[14,106,107,110],{},[34,108,109],{},"MagicPermissionDefault"," controls what happens when the permission node is not\ngranted explicitly:",[56,112,113,119,125,131],{},[59,114,115,118],{},[34,116,117],{},"TRUE"," -> everyone",[59,120,121,124],{},[34,122,123],{},"OP"," -> operators or elevated senders",[59,126,127,130],{},[34,128,129],{},"NOT_OP"," -> non-operators \u002F non-elevated senders",[59,132,133,136],{},[34,134,135],{},"FALSE"," -> nobody",[14,138,139],{},"Platform behaviour differs slightly:",[56,141,142,145,152,155],{},[59,143,144],{},"Bukkit registers permission nodes with Bukkit's permission manager and uses\nBukkit permission defaults.",[59,146,147,148,151],{},"Fabric checks ",[34,149,150],{},"fabric-permissions-api-v0"," when available and falls back to\nop-level checks.",[59,153,154],{},"NeoForge falls back to command-source permission level checks.",[59,156,157],{},"Velocity relies on the proxy's permission checks and uses the default policy\nonly when the node itself is absent.",[18,159,161],{"id":160},"wildcards","Wildcards",[14,163,164],{},"On Bukkit, MagicUtils also registers wildcard nodes:",[56,166,167,172],{},[59,168,169],{},[34,170,171],{},"...commands.\u003Ccommand>.*",[59,173,174],{},[34,175,176],{},"...commands.\u003Ccommand>.subcommand.*",[14,178,179,180,183,184,187],{},"Velocity also honours prefix-style wildcard checks such as ",[34,181,182],{},"prefix.*"," and\n",[34,185,186],{},"prefix\u003Cnode>.*"," when the proxy reports them as granted.",[18,189,191],{"id":190},"explicit-permission-annotations","Explicit Permission Annotations",[14,193,194],{},"Use explicit nodes when you want stable names independent of the generated\nshape:",[26,196,199],{"className":197,"code":198,"language":31,"meta":32},[29],"@CommandInfo(\n        name = \"donate\",\n        permission = \"donatemenu.open\",\n        permissionDefault = MagicPermissionDefault.TRUE\n)\npublic final class DonateCommand extends MagicCommand {\n}\n",[34,200,198],{"__ignoreMap":32},[14,202,203],{},"Subcommands support the same fields:",[26,205,208],{"className":206,"code":207,"language":31,"meta":32},[29],"@SubCommand(\n        name = \"reload\",\n        permission = \"donatemenu.admin.reload\",\n        permissionDefault = MagicPermissionDefault.OP\n)\npublic CommandResult reload(@Sender MagicSender sender) {\n    return CommandResult.success(\"Reloaded\");\n}\n",[34,209,207],{"__ignoreMap":32},[18,211,213],{"id":212},"argument-permissions","Argument Permissions",[14,215,216,217,220],{},"Use ",[34,218,219],{},"@Permission"," on parameters to gate argument usage:",[26,222,225],{"className":223,"code":224,"language":31,"meta":32},[29],"public CommandResult grant(\n        @Sender MagicSender sender,\n        @Permission(when = \"other(player)\") @ParamName(\"player\") Player target\n) {\n    return CommandResult.success(\"ok\");\n}\n",[34,226,224],{"__ignoreMap":32},[14,228,229],{},"You can override the generated node segment:",[26,231,234],{"className":232,"code":233,"language":31,"meta":32},[29],"@Permission(node = \"target\", includeArgumentSegment = false)\n",[34,235,233],{"__ignoreMap":32},[237,238,240],"h3",{"id":239},"permission-members","@Permission Members",[14,242,243,245,246,249],{},[34,244,219],{}," supports both a string DSL (",[34,247,248],{},"when",") and structured members:",[251,252,253,269],"table",{},[254,255,256],"thead",{},[257,258,259,263,266],"tr",{},[260,261,262],"th",{},"Member",[260,264,265],{},"Default",[260,267,268],{},"Purpose",[270,271,272,288,305,326,341,355,374,405,421],"tbody",{},[257,273,274,280,285],{},[275,276,277],"td",{},[34,278,279],{},"value",[275,281,282],{},[34,283,284],{},"\"\"",[275,286,287],{},"Explicit permission node; empty means use the generated node.",[257,289,290,294,298],{},[275,291,292],{},[34,293,248],{},[275,295,296],{},[34,297,284],{},[275,299,300,301,304],{},"Condition DSL string, for example ",[34,302,303],{},"other(player)"," (see keywords below).",[257,306,307,312,317],{},[275,308,309],{},[34,310,311],{},"condition",[275,313,314],{},[34,315,316],{},"ALWAYS",[275,318,319,322,323,325],{},[34,320,321],{},"PermissionConditionType"," when set structurally instead of via ",[34,324,248],{},".",[257,327,328,333,338],{},[275,329,330],{},[34,331,332],{},"conditionArgs",[275,334,335],{},[34,336,337],{},"{}",[275,339,340],{},"Argument names the condition applies to.",[257,342,343,348,352],{},[275,344,345],{},[34,346,347],{},"node",[275,349,350],{},[34,351,284],{},[275,353,354],{},"Override the generated node segment.",[257,356,357,362,367],{},[275,358,359],{},[34,360,361],{},"includeArgumentSegment",[275,363,364],{},[34,365,366],{},"true",[275,368,369,370,373],{},"Include the ",[34,371,372],{},".argument."," segment before the node.",[257,375,376,381,386],{},[275,377,378],{},[34,379,380],{},"compare",[275,382,383],{},[34,384,385],{},"AUTO",[275,387,388,391,392,394,395,394,398,394,401,404],{},[34,389,390],{},"CompareMode"," (",[34,393,385],{},", ",[34,396,397],{},"UUID",[34,399,400],{},"NAME",[34,402,403],{},"EQUALS",") for value comparisons.",[257,406,407,412,416],{},[275,408,409],{},[34,410,411],{},"defaultValue",[275,413,414],{},[34,415,123],{},[275,417,418,420],{},[34,419,109],{}," for this argument node.",[257,422,423,428,433],{},[275,424,425],{},[34,426,427],{},"message",[275,429,430],{},[34,431,432],{},"magicutils.noPermission",[275,434,435],{},"Language key used when the check fails.",[14,437,438,440,441,394,443,394,446,394,449,452,453,394,456,394,459,394,462,394,464,394,467,470,471,473],{},[34,439,321],{}," values: ",[34,442,316],{},[34,444,445],{},"NOT_NULL",[34,447,448],{},"SELF",[34,450,451],{},"OTHER",",\n",[34,454,455],{},"ANY_OTHER",[34,457,458],{},"DISTINCT",[34,460,461],{},"ALL_DISTINCT",[34,463,403],{},[34,465,466],{},"NOT_EQUALS",[34,468,469],{},"EXISTS",". The\n",[34,472,248],{}," DSL keywords below map onto these types, so use whichever style reads\nbetter for your command.",[18,475,477],{"id":476},"conditional-permission-keywords","Conditional Permission Keywords",[56,479,480,492,500,508],{},[59,481,482,485,486,485,489],{},[34,483,484],{},"self(arg)"," \u002F ",[34,487,488],{},"other(arg)",[34,490,491],{},"anyother(arg)",[59,493,494,485,497],{},[34,495,496],{},"not_null(arg)",[34,498,499],{},"exists(arg)",[59,501,502,485,505],{},[34,503,504],{},"distinct(a,b)",[34,506,507],{},"all_distinct(a,b)",[59,509,510,485,513],{},[34,511,512],{},"equals(a,b)",[34,514,515],{},"not_equals(a,b)",[14,517,216,518,521],{},[34,519,520],{},"compare = CompareMode.UUID\u002FNAME\u002FEQUALS\u002FAUTO"," to control how values are\ncompared.",[18,523,525],{"id":524},"manual-checks","Manual Checks",[14,527,528,531],{},[34,529,530],{},"MagicSender"," exposes direct permission checks when you need custom logic\noutside annotation processing:",[26,533,536],{"className":534,"code":535,"language":31,"meta":32},[29],"MagicSender sender = MagicSender.wrap(rawSender);\nif (MagicSender.hasPermission(rawSender, \"donatemenu.commands.donate\")) {\n    \u002F\u002F ...\n}\n",[34,537,535],{"__ignoreMap":32},[14,539,540],{},"When the platform adapter uses op-level fallback semantics, the two-argument\nform keeps the adapter default, while the three-argument form overrides it for\nthat one check:",[26,542,545],{"className":543,"code":544,"language":31,"meta":32},[29],"if (MagicSender.hasPermission(rawSender, \"leavepulse.whitelist.notify\", 3)) {\n    \u002F\u002F ...\n}\n\nif (sender != null && sender.hasPermission(\"leavepulse.admin\", 4)) {\n    \u002F\u002F ...\n}\n",[34,546,544],{"__ignoreMap":32},[14,548,549],{},"This matters most on Fabric and NeoForge, where permission backends may fall\nback to command-source op levels when a node is unknown or no backend responds.",[14,551,552],{},"You can also use the registry prefix when building related manual nodes so the\nmanual and generated permissions stay in the same namespace.",{"title":32,"searchDepth":554,"depth":554,"links":555},3,[556,558,559,560,561,562,565,566],{"id":20,"depth":557,"text":21},2,{"id":50,"depth":557,"text":51},{"id":103,"depth":557,"text":104},{"id":160,"depth":557,"text":161},{"id":190,"depth":557,"text":191},{"id":212,"depth":557,"text":213,"children":563},[564],{"id":239,"depth":554,"text":240},{"id":476,"depth":557,"text":477},{"id":524,"depth":557,"text":525},"How MagicUtils resolves permission nodes for commands, including permission prefixes and per-platform behavior.","md",{},null,true,"\u002Fmodules\u002Fpermissions","---\ntitle: Permissions\ndescription: How MagicUtils resolves permission nodes for commands, including permission prefixes and per-platform behavior.\n---\n\n# Permissions\n\nMagicUtils commands generate and evaluate permission nodes automatically. The\nregistry prefix controls namespacing, while annotations control explicit nodes,\ndefaults, and conditional argument checks.\n\n## Permission Prefix\n\nEvery command registry has a permission prefix. You set it either directly on\nthe registry:\n\n```java\nCommandRegistry registry = CommandRegistry.create(plugin, \"donatemenu\", logger);\n```\n\nor through the bootstrap helper:\n\n```java\nBukkitBootstrap.forPlugin(plugin)\n        .permissionPrefix(\"donatemenu\")\n        .enableCommands()\n        .buildRuntime();\n```\n\nMagicUtils prepends that prefix to all generated nodes.\n\n## Generated Nodes\n\nWhen annotations omit explicit permission strings, MagicUtils builds defaults:\n\n- Command: `commands.\u003Ccommand>`\n- Subcommand: `commands.\u003Ccommand>.subcommand.\u003Cpath>`\n- Argument: `commands.\u003Ccommand>.subcommand.\u003Cpath>.argument.\u003Cname>`\n\nWith prefix `donatemenu`:\n\n- `donatemenu.commands.donate`\n- `donatemenu.commands.donate.subcommand.give`\n- `donatemenu.commands.donate.subcommand.give.argument.player`\n\n## Default Access\n\n`MagicPermissionDefault` controls what happens when the permission node is not\ngranted explicitly:\n\n- `TRUE` -> everyone\n- `OP` -> operators or elevated senders\n- `NOT_OP` -> non-operators \u002F non-elevated senders\n- `FALSE` -> nobody\n\nPlatform behaviour differs slightly:\n\n- Bukkit registers permission nodes with Bukkit's permission manager and uses\n  Bukkit permission defaults.\n- Fabric checks `fabric-permissions-api-v0` when available and falls back to\n  op-level checks.\n- NeoForge falls back to command-source permission level checks.\n- Velocity relies on the proxy's permission checks and uses the default policy\n  only when the node itself is absent.\n\n## Wildcards\n\nOn Bukkit, MagicUtils also registers wildcard nodes:\n\n- `...commands.\u003Ccommand>.*`\n- `...commands.\u003Ccommand>.subcommand.*`\n\nVelocity also honours prefix-style wildcard checks such as `prefix.*` and\n`prefix\u003Cnode>.*` when the proxy reports them as granted.\n\n## Explicit Permission Annotations\n\nUse explicit nodes when you want stable names independent of the generated\nshape:\n\n```java\n@CommandInfo(\n        name = \"donate\",\n        permission = \"donatemenu.open\",\n        permissionDefault = MagicPermissionDefault.TRUE\n)\npublic final class DonateCommand extends MagicCommand {\n}\n```\n\nSubcommands support the same fields:\n\n```java\n@SubCommand(\n        name = \"reload\",\n        permission = \"donatemenu.admin.reload\",\n        permissionDefault = MagicPermissionDefault.OP\n)\npublic CommandResult reload(@Sender MagicSender sender) {\n    return CommandResult.success(\"Reloaded\");\n}\n```\n\n## Argument Permissions\n\nUse `@Permission` on parameters to gate argument usage:\n\n```java\npublic CommandResult grant(\n        @Sender MagicSender sender,\n        @Permission(when = \"other(player)\") @ParamName(\"player\") Player target\n) {\n    return CommandResult.success(\"ok\");\n}\n```\n\nYou can override the generated node segment:\n\n```java\n@Permission(node = \"target\", includeArgumentSegment = false)\n```\n\n### @Permission Members\n\n`@Permission` supports both a string DSL (`when`) and structured members:\n\n| Member | Default | Purpose |\n| --- | --- | --- |\n| `value` | `\"\"` | Explicit permission node; empty means use the generated node. |\n| `when` | `\"\"` | Condition DSL string, for example `other(player)` (see keywords below). |\n| `condition` | `ALWAYS` | `PermissionConditionType` when set structurally instead of via `when`. |\n| `conditionArgs` | `{}` | Argument names the condition applies to. |\n| `node` | `\"\"` | Override the generated node segment. |\n| `includeArgumentSegment` | `true` | Include the `.argument.` segment before the node. |\n| `compare` | `AUTO` | `CompareMode` (`AUTO`, `UUID`, `NAME`, `EQUALS`) for value comparisons. |\n| `defaultValue` | `OP` | `MagicPermissionDefault` for this argument node. |\n| `message` | `magicutils.noPermission` | Language key used when the check fails. |\n\n`PermissionConditionType` values: `ALWAYS`, `NOT_NULL`, `SELF`, `OTHER`,\n`ANY_OTHER`, `DISTINCT`, `ALL_DISTINCT`, `EQUALS`, `NOT_EQUALS`, `EXISTS`. The\n`when` DSL keywords below map onto these types, so use whichever style reads\nbetter for your command.\n\n## Conditional Permission Keywords\n\n- `self(arg)` \u002F `other(arg)` \u002F `anyother(arg)`\n- `not_null(arg)` \u002F `exists(arg)`\n- `distinct(a,b)` \u002F `all_distinct(a,b)`\n- `equals(a,b)` \u002F `not_equals(a,b)`\n\nUse `compare = CompareMode.UUID\u002FNAME\u002FEQUALS\u002FAUTO` to control how values are\ncompared.\n\n## Manual Checks\n\n`MagicSender` exposes direct permission checks when you need custom logic\noutside annotation processing:\n\n```java\nMagicSender sender = MagicSender.wrap(rawSender);\nif (MagicSender.hasPermission(rawSender, \"donatemenu.commands.donate\")) {\n    \u002F\u002F ...\n}\n```\n\nWhen the platform adapter uses op-level fallback semantics, the two-argument\nform keeps the adapter default, while the three-argument form overrides it for\nthat one check:\n\n```java\nif (MagicSender.hasPermission(rawSender, \"leavepulse.whitelist.notify\", 3)) {\n    \u002F\u002F ...\n}\n\nif (sender != null && sender.hasPermission(\"leavepulse.admin\", 4)) {\n    \u002F\u002F ...\n}\n```\n\nThis matters most on Fabric and NeoForge, where permission backends may fall\nback to command-source op levels when a node is unknown or no backend responds.\n\nYou can also use the registry prefix when building related manual nodes so the\nmanual and generated permissions stay in the same namespace.\n",{"title":5,"description":567},"modules\u002Fpermissions","oXD_U0vKVoVhg-CpC7rKEN3XgiXA3N55avDEAJ03ur0",1783944488211]