Skip to content
Content
Skill

/admin-permissions

Admin-side permission UI registration and DI-backed permission checking. Use this skill when adding permission controls to the admin UI — schema-based auto-generated forms, injectable permissions via createPermissionsAbstraction/ createPermissionsFeature, typed hooks

BOOST
From plugin
webiny-js
8k76 skills3 MCP
Install
$ npx -y skills add webiny/webiny-js --skill admin-permissions --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/admin-permissions

Context preview

The summary Claude sees to decide when to auto-load this skill.

Admin-side permission UI registration and DI-backed permission checking. Use this skill when adding permission controls to the admin UI — schema-based auto-generated forms, injectable permissions via createPermissionsAbstraction/ createPermissionsFeature, typed hooks

SKILL.md

admin-permissions.SKILL.md
name: webiny-admin-permissions
description: >
  Admin-side permission UI registration and DI-backed permission checking.
  Use this skill when adding permission controls to the admin UI — schema-based
  auto-generated forms, injectable permissions via createPermissionsAbstraction/
  createPermissionsFeature, typed hooks (createUsePermissions), the HasPermission
  component (createHasPermission), and the Security.Permissions component props.
  Covers both simple apps and complex multi-entity permission schemas.

Admin Permissions

Overview

Permissions follow three layers: **domain** (schema), **features** (DI artifacts + registration), and **presentation** (hooks, components, UI config). The framework auto-generates the permission UI from a schema and provides injectable permission checking via the DI container.

Layer 1: Domain — Permission Schema

Define the schema in `src/domain/permissionsSchema.ts`:

import { createPermissionSchema } from "webiny/admin/security";

export const SM_PERMISSIONS_SCHEMA = createPermissionSchema({
  prefix: "sm",
  fullAccess: true,
  entities: [
    {
      id: "product",
      title: "Products",
      permission: "sm.product",
      scopes: ["full", "own"],
      actions: [
        { name: "rwd" },
        { name: "pw" },
        { name: "import", label: "Import products" },
        { name: "export", label: "Export products" }
      ]
    },
    {
      id: "category",
      title: "Categories",
      permission: "sm.category",
      scopes: ["full"],
      actions: [{ name: "rwd" }]
    },
    {
      id: "settings",
      title: "Settings",
      permission: "sm.settings",
      scopes: ["full"]
    }
  ]
});

Schema Reference

| Field | Type | Required | Description | | ---------------- | -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------ | | `prefix` | `string` | Yes | Permission prefix (e.g., `"sm"`) | | `fullAccess` | `true \| object` | Yes | `true` for standard full access. Pass an object with custom boolean flags for full-access extras (e.g., `{ canForceUnlock: true }`). | | `readOnlyAccess` | `boolean` | No | Whether to show a "Read-only access" option | | `entities` | `EntityDefinition[]` | No | Entity definitions. Omit for binary full/no access. |

Entity Definition

| Field | Type | Required | Description | | ------------ | -------------------------------------- | -------- | ---------------------------------------------- | | `id` | `string` | Yes | Unique identifier for form field naming | | `title` | `string` | No | Display title. Falls back to `id`. | | `permission` | `string` | Yes | Permission name emitted (e.g., `"sm.product"`) | | `scopes` | `("full" \| "own")[]` | Yes | Available access scopes | | `actions` | `ActionDefinition[]` | No | Actions on this entity | | `dependsOn` | `{ entity: string; requires: string }` | No | Dependency on another entity |

Actions

  • `{ name: "rwd" }` — Read/Write/Delete select dropdown. Auto-set to `"rwd"` when scope is `"own"`.
  • `{ name: "pw" }` — Publish/Unpublish checkbox group.
  • `{ name: "custom", label: "Label" }` — Custom boolean flag.

Entity Dependencies

Child entities can depend on a parent. If the parent lacks the required action, the child is pruned from output. `"own"` scope cascades to dependents.

{
    id: "review",
    permission: "sm.review",
    scopes: ["full", "own"],
    actions: [{ name: "rwd" }],
    dependsOn: { entity: "product", requires: "r" }
}

Simple Apps (No Entities)

Omit `entities` for binary full/no access:

export const MA_PERMISSIONS_SCHEMA = createPermissionSchema({
  prefix: "ma",
  fullAccess: true
});

---

Layer 2: Features — DI Artifacts + Registration

Abstraction (`src/features/permissions/abstractions.ts`)

import { createPermissionsAbstraction } from "webiny/admin/security";
import type { Permissions } from "webiny/admin/security";
import { SM_PERMISSIONS_SCHEMA } from "~/domain/permissionsSchema.js";

export const SmPermissions = createPermissionsAbstraction(SM_PERMISSIONS_SCHEMA);

export namespace SmPermissions {
  export type Interface = Permissions<typeof SM_PERMISSIONS_SCHEMA>;
}

Feature (`src/features/permissions/feature.ts`)

import { createPermissionsFeature } from "webiny/admin/security";
import { SM_PERMISSIONS_SCHEMA } from "~/domain/permissionsSchema.js";
import { SmPermissions } from "./abstractions.js";

export const SmPermissionsFeature = createPermissionsFeature(SM_PERMISSIONS_SCHEMA, SmPermissions);

Extension Registration

Register the feature and the permission UI in your extension component:

import { AdminConfig, RegisterFeature } from "webiny/admin/security";
import { ReactComponent as Icon } from "@webiny/icons/shield.svg";
import { SM_PERMISSIONS_SCHEMA } from "~/domain/permissionsSchema.js";
import { SmPermissionsFeature } from "~/features/permissions/feature.js";

const { Security } = AdminConfig;

export const Extension = () => {
  return (
    <>
      <RegisterFeature feature={SmPermissionsFeatur
Read more
Ships withwebiny-js

Open-source content platform. Self-hosted on AWS serverless. Built as a TypeScript framework you extend with code, not a closed product you configure through a UI. Runs on Lambda, DynamoDB, S3, and CloudFront inside your own AWS account. Scales automatically.

Get the whole plugin
Stats
8,048
Stars
682
Forks
Active
Maintenance
TypeScript
Language
2h ago
Last commit
8y ago
Created
9h ago
Added

Repo: webiny/webiny-js

Other skills on webiny-js.