strapi-plugin-keycloak-realm-users 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/README.md +239 -336
  2. package/dist/_chunks/{App-DO6syS77.js → App-Cxl4vy52.js} +45 -34
  3. package/dist/_chunks/{App-BaKrvCeS.mjs → App-ZmFgfMD9.mjs} +45 -34
  4. package/dist/_chunks/{index-jTVd7LdQ.mjs → index-BXykyqCE.mjs} +5 -2
  5. package/dist/_chunks/{index-DwDO4-0C.js → index-_Hrf07zU.js} +5 -2
  6. package/dist/admin/index.js +1 -1
  7. package/dist/admin/index.mjs +1 -1
  8. package/dist/server/index.js +67 -58
  9. package/dist/server/index.mjs +67 -58
  10. package/package.json +21 -9
  11. package/strapi-admin.js +3 -0
  12. package/strapi-server.js +3 -0
  13. package/__tests__/constants.test.mjs +0 -207
  14. package/__tests__/mocks/strapi.mjs +0 -182
  15. package/__tests__/services/audit-log.test.mjs +0 -283
  16. package/__tests__/services/keycloak-client.test.mjs +0 -651
  17. package/__tests__/services/permission.test.mjs +0 -374
  18. package/__tests__/services/realm.test.mjs +0 -415
  19. package/__tests__/services/user.test.mjs +0 -487
  20. package/__tests__/utils/errors.test.mjs +0 -109
  21. package/admin/src/components/Initializer.jsx +0 -14
  22. package/admin/src/components/RealmBadge.jsx +0 -17
  23. package/admin/src/constants.js +0 -14
  24. package/admin/src/hooks/useAuditLogs.js +0 -142
  25. package/admin/src/hooks/useKeycloakRoles.js +0 -182
  26. package/admin/src/hooks/useKeycloakUsers.js +0 -477
  27. package/admin/src/hooks/useRealmAdmins.js +0 -249
  28. package/admin/src/hooks/useRealms.js +0 -269
  29. package/admin/src/index.js +0 -46
  30. package/admin/src/pages/App.jsx +0 -21
  31. package/admin/src/pages/AuditPage/index.jsx +0 -213
  32. package/admin/src/pages/RealmsPage/RealmEditPage.jsx +0 -791
  33. package/admin/src/pages/RealmsPage/RealmListPage.jsx +0 -231
  34. package/admin/src/pages/RealmsPage/index.jsx +0 -7
  35. package/admin/src/pages/UsersPage/UserEditPage.jsx +0 -313
  36. package/admin/src/pages/UsersPage/UserListPage.jsx +0 -437
  37. package/admin/src/pages/UsersPage/index.jsx +0 -7
  38. package/admin/src/pluginId.js +0 -2
  39. package/admin/src/translations/en.json +0 -77
  40. package/admin/src/translations/fr.json +0 -77
  41. package/babel.config.cjs +0 -17
  42. package/coverage/clover.xml +0 -422
  43. package/coverage/coverage-final.json +0 -8
  44. package/coverage/lcov-report/base.css +0 -224
  45. package/coverage/lcov-report/block-navigation.js +0 -87
  46. package/coverage/lcov-report/favicon.png +0 -0
  47. package/coverage/lcov-report/index.html +0 -146
  48. package/coverage/lcov-report/prettify.css +0 -1
  49. package/coverage/lcov-report/prettify.js +0 -2
  50. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  51. package/coverage/lcov-report/sorter.js +0 -210
  52. package/coverage/lcov-report/src/bootstrap.js.html +0 -346
  53. package/coverage/lcov-report/src/config/index.html +0 -116
  54. package/coverage/lcov-report/src/config/index.js.html +0 -106
  55. package/coverage/lcov-report/src/constants.js.html +0 -850
  56. package/coverage/lcov-report/src/content-types/audit-log/index.html +0 -116
  57. package/coverage/lcov-report/src/content-types/audit-log/index.js.html +0 -94
  58. package/coverage/lcov-report/src/content-types/index.html +0 -116
  59. package/coverage/lcov-report/src/content-types/index.js.html +0 -112
  60. package/coverage/lcov-report/src/content-types/realm-admin/index.html +0 -116
  61. package/coverage/lcov-report/src/content-types/realm-admin/index.js.html +0 -94
  62. package/coverage/lcov-report/src/content-types/realm-config/index.html +0 -116
  63. package/coverage/lcov-report/src/content-types/realm-config/index.js.html +0 -94
  64. package/coverage/lcov-report/src/controllers/audit.js.html +0 -517
  65. package/coverage/lcov-report/src/controllers/index.html +0 -161
  66. package/coverage/lcov-report/src/controllers/index.js.html +0 -112
  67. package/coverage/lcov-report/src/controllers/realm.js.html +0 -1057
  68. package/coverage/lcov-report/src/controllers/user.js.html +0 -1324
  69. package/coverage/lcov-report/src/destroy.js.html +0 -100
  70. package/coverage/lcov-report/src/index.html +0 -116
  71. package/coverage/lcov-report/src/policies/can-access-realm.js.html +0 -163
  72. package/coverage/lcov-report/src/policies/index.html +0 -146
  73. package/coverage/lcov-report/src/policies/index.js.html +0 -106
  74. package/coverage/lcov-report/src/policies/is-authenticated.js.html +0 -100
  75. package/coverage/lcov-report/src/register.js.html +0 -106
  76. package/coverage/lcov-report/src/routes/admin.js.html +0 -844
  77. package/coverage/lcov-report/src/routes/index.html +0 -131
  78. package/coverage/lcov-report/src/routes/index.js.html +0 -109
  79. package/coverage/lcov-report/src/services/audit-log.js.html +0 -673
  80. package/coverage/lcov-report/src/services/index.html +0 -176
  81. package/coverage/lcov-report/src/services/index.js.html +0 -124
  82. package/coverage/lcov-report/src/services/keycloak-client.js.html +0 -2359
  83. package/coverage/lcov-report/src/services/permission.js.html +0 -955
  84. package/coverage/lcov-report/src/services/realm.js.html +0 -1207
  85. package/coverage/lcov-report/src/services/user.js.html +0 -1924
  86. package/coverage/lcov-report/src/utils/errors.js.html +0 -274
  87. package/coverage/lcov-report/src/utils/index.html +0 -116
  88. package/coverage/lcov-report/src/utils/index.js.html +0 -103
  89. package/coverage/lcov.info +0 -804
  90. package/jest.config.cjs +0 -50
  91. package/server/src/bootstrap.js +0 -87
  92. package/server/src/config/index.js +0 -7
  93. package/server/src/constants.js +0 -255
  94. package/server/src/content-types/audit-log/index.js +0 -3
  95. package/server/src/content-types/audit-log/schema.json +0 -61
  96. package/server/src/content-types/index.js +0 -9
  97. package/server/src/content-types/realm-admin/index.js +0 -3
  98. package/server/src/content-types/realm-admin/schema.json +0 -45
  99. package/server/src/content-types/realm-config/index.js +0 -3
  100. package/server/src/content-types/realm-config/schema.json +0 -56
  101. package/server/src/controllers/audit.js +0 -144
  102. package/server/src/controllers/index.js +0 -9
  103. package/server/src/controllers/realm.js +0 -324
  104. package/server/src/controllers/user.js +0 -413
  105. package/server/src/destroy.js +0 -5
  106. package/server/src/index.js +0 -21
  107. package/server/src/policies/can-access-realm.js +0 -26
  108. package/server/src/policies/index.js +0 -7
  109. package/server/src/policies/is-authenticated.js +0 -5
  110. package/server/src/register.js +0 -7
  111. package/server/src/routes/admin.js +0 -253
  112. package/server/src/routes/index.js +0 -8
  113. package/server/src/services/audit-log.js +0 -196
  114. package/server/src/services/index.js +0 -13
  115. package/server/src/services/keycloak-client.js +0 -758
  116. package/server/src/services/permission.js +0 -290
  117. package/server/src/services/realm.js +0 -374
  118. package/server/src/services/user.js +0 -613
  119. package/server/src/utils/errors.js +0 -63
  120. package/server/src/utils/index.js +0 -6
package/README.md CHANGED
@@ -1,81 +1,111 @@
1
1
  <p align="center">
2
- <img src="https://raw.githubusercontent.com/strapi/strapi/main/packages/core/admin/admin/src/assets/images/logo-strapi-2022.svg" width="200" alt="Strapi Logo" />
3
- <span style="font-size: 48px; margin: 0 20px;">+</span>
4
- <img src="https://www.keycloak.org/resources/images/logo.svg" width="200" alt="Keycloak Logo" />
2
+ <img src="https://raw.githubusercontent.com/strapi/strapi/main/packages/core/admin/admin/src/assets/images/logo-strapi-2022.svg" width="160" alt="Strapi Logo" />
3
+ <img src="https://user-images.githubusercontent.com/4129325/166460470-2e9d9f5c-3b8c-4fee-9754-1b1c90119e60.png" width="60" alt="handshake" />
4
+ <img src="https://www.keycloak.org/resources/images/logo.svg" width="160" alt="Keycloak Logo" />
5
5
  </p>
6
6
 
7
- <h1 align="center">Strapi Plugin: Keycloak Realm Users</h1>
7
+ <h1 align="center">🏰 Strapi Plugin: Keycloak Realm Users</h1>
8
8
 
9
9
  <p align="center">
10
- <strong>Seamlessly manage Keycloak users across multiple realms directly from your Strapi admin panel</strong>
10
+ <em>Manage Keycloak users across <strong>all your realms</strong> without ever leaving Strapi.</em>
11
11
  </p>
12
12
 
13
13
  <p align="center">
14
- <a href="#features">Features</a>
15
- <a href="#installation">Installation</a>
16
- <a href="#configuration">Configuration</a>
17
- <a href="#usage">Usage</a>
18
- <a href="#api-reference">API</a> •
19
- <a href="#permissions">Permissions</a> •
20
- <a href="#contributing">Contributing</a>
14
+ <a href="https://www.npmjs.com/package/strapi-plugin-keycloak-realm-users"><img src="https://img.shields.io/npm/v/strapi-plugin-keycloak-realm-users?style=for-the-badge&logo=npm&logoColor=white&color=CB3837" alt="npm version" /></a>
15
+ <img src="https://img.shields.io/badge/Strapi-v5-4945FF?style=for-the-badge&logo=strapi&logoColor=white" alt="Strapi v5" />
16
+ <img src="https://img.shields.io/badge/Keycloak-17%2B-4D8AB5?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZmlsbD0id2hpdGUiIGQ9Ik0xMiAyTDIgN3Y1YzAgNS41NSAzLjg0IDEwLjc0IDEwIDEyIDYuMTYtMS4yNiAxMC02LjQ1IDEwLTEyVjdsLTEwLTV6Ii8+PC9zdmc+" alt="Keycloak 17+" />
17
+ <img src="https://img.shields.io/npm/l/strapi-plugin-keycloak-realm-users?style=for-the-badge&color=22C55E" alt="MIT License" />
21
18
  </p>
22
19
 
23
20
  <p align="center">
24
- <img src="https://img.shields.io/npm/v/strapi-plugin-keycloak-realm-users?style=flat-square&color=4945ff" alt="npm version" />
25
- <img src="https://img.shields.io/npm/l/strapi-plugin-keycloak-realm-users?style=flat-square" alt="license" />
26
- <img src="https://img.shields.io/badge/strapi-v5-blue?style=flat-square" alt="Strapi v5" />
27
- <img src="https://img.shields.io/badge/keycloak-17%2B-orange?style=flat-square" alt="Keycloak 17+" />
21
+ <a href="#-quick-start">Quick Start</a> &nbsp;&bull;&nbsp;
22
+ <a href="#-what-can-it-do">Features</a> &nbsp;&bull;&nbsp;
23
+ <a href="#%EF%B8%8F-configuration">Configuration</a> &nbsp;&bull;&nbsp;
24
+ <a href="#-api-reference">API</a> &nbsp;&bull;&nbsp;
25
+ <a href="#-troubleshooting">Troubleshooting</a>
28
26
  </p>
29
27
 
30
28
  ---
31
29
 
32
- ## Why This Plugin?
30
+ ## 💡 The Problem
33
31
 
34
- Managing users across multiple Keycloak realms typically requires:
35
- - Switching between different Keycloak admin consoles
36
- - Granting full Keycloak admin access to team members
37
- - No centralized audit trail of user management actions
32
+ You have **multiple Keycloak realms** dev, staging, production, client tenants — and managing users means:
38
33
 
39
- **This plugin solves all of that** by bringing Keycloak user management into Strapi with fine-grained permissions, multi-realm support, and comprehensive audit logging.
34
+ - 🔀 Juggling between different Keycloak admin consoles
35
+ - 🔓 Giving **full Keycloak admin access** to people who just need to reset a password
36
+ - 🕵️ No centralized log of who did what, where, and when
37
+
38
+ ## ✅ The Solution
39
+
40
+ Install this plugin. Now your **Strapi admin panel** is the single pane of glass for Keycloak user management — with **per-realm permissions**, **audit logging**, and **zero Keycloak console access required** for your team.
40
41
 
41
42
  ---
42
43
 
43
- ## Features
44
+ ## 🚀 Quick Start
45
+
46
+ **1. Install**
47
+
48
+ ```bash
49
+ npm install strapi-plugin-keycloak-realm-users
50
+ # or
51
+ yarn add strapi-plugin-keycloak-realm-users
52
+ ```
53
+
54
+ **2. Enable**
55
+
56
+ ```javascript
57
+ // config/plugins.js
58
+ module.exports = {
59
+ 'strapi-plugin-keycloak-realm-users': {
60
+ enabled: true,
61
+ },
62
+ };
63
+ ```
64
+
65
+ **3. Connect a realm** — go to **Settings → Keycloak Realm Users → Create Realm**, fill in your Keycloak URL, client ID & secret, hit **Test Connection**, and you're live. 🎉
66
+
67
+ ---
68
+
69
+ ## 🎯 What Can It Do?
44
70
 
45
71
  <table>
46
72
  <tr>
47
- <td width="50%">
73
+ <td width="50%" valign="top">
48
74
 
49
75
  ### 🏰 Multi-Realm Management
50
- Connect and manage users across unlimited Keycloak realms from a single interface. Each realm is configured independently with its own credentials.
76
+ Connect **unlimited Keycloak realms** from a single Strapi interface. Each realm gets its own credentials, color tag, and admin team.
77
+
78
+ ### 🔐 Granular Permissions
79
+ Assign Strapi admins to specific realms with fine-grained control:
51
80
 
52
- ### 🔐 Fine-Grained Permissions
53
- Assign Strapi admins to specific realms with granular permissions:
54
- - **Read** - View users
55
- - **Create** - Add new users
56
- - **Update** - Modify user details, enable/disable accounts
57
- - **Delete** - Remove users
58
- - **Reset Password** - Change passwords (separate from Update for compliance)
59
- - **Manage Roles** - Assign/remove Keycloak roles
81
+ | Permission | What it unlocks |
82
+ |:---:|---|
83
+ | 👁️ **Read** | View users |
84
+ | **Create** | Add new users |
85
+ | ✏️ **Update** | Edit details, enable/disable |
86
+ | 🗑️ **Delete** | Remove users |
87
+ | 🔑 **Reset Password** | Change passwords (separate for compliance!) |
88
+ | 🎭 **Manage Roles** | Assign/remove Keycloak roles |
60
89
 
61
90
  </td>
62
- <td width="50%">
63
-
64
- ### 📋 Comprehensive Audit Log
65
- Every action is logged with:
66
- - Who performed the action
67
- - What was changed
68
- - When it happened
69
- - Which realm was affected
70
-
71
- ### 🚀 Full User Lifecycle
72
- - Create, update, delete users
73
- - Enable/disable accounts
74
- - Reset passwords (temporary or permanent)
75
- - Send verification emails
76
- - Send password reset emails
77
- - Bulk import from JSON/CSV
78
- - Export users
91
+ <td width="50%" valign="top">
92
+
93
+ ### 📋 Full Audit Trail
94
+ Every action is logged:
95
+ - **Who** performed it
96
+ - **What** changed
97
+ - **When** it happened
98
+ - **Which realm** was affected
99
+
100
+ Never wonder "who deleted that user?" again.
101
+
102
+ ### 🧰 Full User Lifecycle
103
+ - Create, ✏️ update, 🗑️ delete users
104
+ - Enable / disable accounts
105
+ - 🔑 Reset passwords (temporary or permanent)
106
+ - 📧 Send verification & password reset emails
107
+ - 📦 Bulk import from JSON/CSV
108
+ - 📤 Export users
79
109
 
80
110
  </td>
81
111
  </tr>
@@ -83,403 +113,276 @@ Every action is logged with:
83
113
 
84
114
  ---
85
115
 
86
- ## Architecture
116
+ ## 🏗️ How It Works
87
117
 
88
118
  ```
89
- ┌─────────────────────────────────────────────────────────────────┐
90
- Strapi Admin Panel
91
- ├─────────────────────────────────────────────────────────────────┤
92
- ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
93
- │ │ Realms Users │ Audit Log
94
- │ │ Config │ Management Viewer
95
- └──────┬──────┘ └──────┬──────┘ └──────┬──────┘
96
- │ │ │
97
- └────────────────┼────────────────┘
98
-
99
- ┌───────────────────────▼───────────────────────┐
100
- Plugin Permission Layer
101
- (Realm-based access control) │ │
102
- │ └───────────────────────┬───────────────────────┘ │
103
- └──────────────────────────┼──────────────────────────────────────┘
104
-
105
- ┌───────────────┼───────────────┐
106
- │ │ │
107
- ▼ ▼ ▼
108
- ┌────────────┐ ┌────────────┐ ┌────────────┐
109
- │ Keycloak │ │ Keycloak │ │ Keycloak │
110
- │ Realm A │ │ Realm B │ │ Realm C │
111
- └────────────┘ └────────────┘ └────────────┘
119
+ ┌──────────────────────────────────────────────────────────┐
120
+ Strapi Admin Panel
121
+ │ │
122
+ ┌──────────┐ ┌──────────┐ ┌──────────┐
123
+ Realms │ │ Users │ Audit
124
+ Config │ │ Manager│ Log
125
+ └────┬─────┘ └────┬─────┘ └────┬─────┘
126
+ └───────────────┼──────────────┘
127
+
128
+ ┌───────────────────────────────┐
129
+ Permission Layer │ │
130
+ (per-realm access control)
131
+ └───────────────┬───────────────┘
132
+ └────────────────────────┼─────────────────────────────────┘
133
+
134
+ ┌──────────────┼──────────────┐
135
+ ▼ ▼ ▼
136
+ ┌────────────┐ ┌────────────┐ ┌────────────┐
137
+ │ Keycloak │ │ Keycloak │ │ Keycloak │
138
+ Realm A │ │ Realm B │ │ Realm C │
139
+ └────────────┘ └────────────┘ └────────────┘
112
140
  ```
113
141
 
142
+ Your Strapi admins **never touch Keycloak directly**. They get exactly the permissions they need, and every action is logged.
143
+
114
144
  ---
115
145
 
116
- ## Installation
146
+ ## ⚙️ Configuration
117
147
 
118
- ```bash
119
- # Using npm
120
- npm install strapi-plugin-keycloak-realm-users
148
+ ### Keycloak Client Setup
121
149
 
122
- # Using yarn
123
- yarn add strapi-plugin-keycloak-realm-users
124
- ```
150
+ For each realm you want to manage, create a **service account client** in Keycloak:
125
151
 
126
- ---
152
+ <details>
153
+ <summary>📖 <strong>Step-by-step Keycloak setup</strong> (click to expand)</summary>
127
154
 
128
- ## Configuration
155
+ <br />
129
156
 
130
- ### 1. Enable the Plugin
157
+ **1. Create a new client** in your Keycloak realm:
158
+ - Client ID: `strapi-admin` (or your preferred name)
159
+ - Client Protocol: `openid-connect`
131
160
 
132
- ```javascript
133
- // config/plugins.js
134
- module.exports = {
135
- 'strapi-plugin-keycloak-realm-users': {
136
- enabled: true,
137
- },
138
- };
139
- ```
161
+ **2. Configure client settings:**
140
162
 
141
- ### 2. Configure Keycloak Client
163
+ | Setting | Value |
164
+ |---------|-------|
165
+ | Client authentication | **ON** |
166
+ | Service accounts roles | **Enabled** |
142
167
 
143
- For each Keycloak realm you want to manage, you'll need a **service account client** with the following configuration:
168
+ **3. Assign service account roles:**
144
169
 
145
- <details>
146
- <summary><strong>Keycloak Client Setup (Click to expand)</strong></summary>
147
-
148
- 1. **Create a new client** in your Keycloak realm:
149
- - Client ID: `strapi-admin` (or your preferred name)
150
- - Client Protocol: `openid-connect`
151
-
152
- 2. **Configure client settings**:
153
- | Setting | Value |
154
- |---------|-------|
155
- | Client authentication | ON |
156
- | Service accounts roles | Enabled |
157
- | Valid redirect URIs | (not required for service accounts) |
158
-
159
- 3. **Assign Service Account Roles**:
160
- - Go to the client's **Service Account Roles** tab
161
- - Click **Assign role**
162
- - Filter by **realm-management** client
163
- - Assign the following roles:
164
-
165
- | Role | Required For |
166
- |------|--------------|
167
- | `view-users` | Listing and viewing users |
168
- | `manage-users` | Creating, updating, deleting users |
169
- | `view-realm` | Testing connection |
170
- | `query-users` | Searching users |
171
-
172
- > **Tip**: For full admin access, you can assign `realm-admin` instead.
173
-
174
- 4. **Get the client secret**:
175
- - Go to the **Credentials** tab
176
- - Copy the **Client secret**
170
+ Go to **Service Account Roles** → **Assign role** → Filter by **realm-management** → Add:
177
171
 
178
- </details>
172
+ | Role | Why |
173
+ |:---:|---|
174
+ | `view-users` | List & view users |
175
+ | `manage-users` | Create, update, delete users |
176
+ | `view-realm` | Test connection |
177
+ | `query-users` | Search users |
179
178
 
180
- ---
179
+ > 💡 **Shortcut**: Assign `realm-admin` for full access.
181
180
 
182
- ## Usage
181
+ **4. Copy the client secret** from the **Credentials** tab.
183
182
 
184
- ### Adding a Realm
183
+ </details>
185
184
 
186
- 1. Navigate to **Settings** **Keycloak Realm Users**
187
- 2. Click **Create Realm**
188
- 3. Fill in the connection details:
185
+ ### Adding a Realm in Strapi
189
186
 
190
- | Field | Description | Example |
191
- |-------|-------------|---------|
192
- | Name | Unique identifier (lowercase, hyphens) | `production-users` |
193
- | Display Name | Human-readable name | `Production Users` |
194
- | Server URL | Keycloak base URL | `https://keycloak.example.com` |
195
- | Realm Name | The Keycloak realm name | `my-realm` |
196
- | Client ID | Service account client ID | `strapi-admin` |
197
- | Client Secret | Client credentials secret | `xxxxx-xxxxx-xxxxx` |
198
- | Color | UI accent color | `#4945ff` |
187
+ | Field | What it is | Example |
188
+ |-------|-----------|---------|
189
+ | **Name** | Unique slug (lowercase, hyphens) | `production-users` |
190
+ | **Display Name** | Human-readable label | `Production Users` |
191
+ | **Server URL** | Keycloak base URL | `https://keycloak.example.com` |
192
+ | **Realm Name** | Keycloak realm | `my-realm` |
193
+ | **Client ID** | Service account client | `strapi-admin` |
194
+ | **Client Secret** | From credentials tab | `xxxxx-xxxxx-xxxxx` |
195
+ | **Color** | UI accent color | `#4945ff` |
199
196
 
200
- 4. Click **Test Connection** to verify
201
- 5. Click **Save**
197
+ Hit **Test Connection** **Save** → Done! ✅
202
198
 
203
- ### Managing Users
199
+ ---
204
200
 
205
- Once a realm is configured, you can:
201
+ ## 👥 Managing Users
206
202
 
207
- - **View Users**: Click "Manage Users" on any realm card
208
- - **Search**: Use the search bar to filter by username, email, or name
209
- - **Create**: Click "Create User" and fill in the details
210
- - **Edit**: Click the edit icon to modify user details
211
- - **Actions**:
212
- - 🔑 Reset password
213
- - ✅ Enable/disable account
214
- - 📧 Send verification email
215
- - 🗑️ Delete user
203
+ Once a realm is connected:
216
204
 
217
- ### Assigning Realm Admins
205
+ | Action | How |
206
+ |--------|-----|
207
+ | **Browse users** | Click "Manage Users" on any realm card |
208
+ | **Search** | Filter by username, email, or name |
209
+ | **Create user** | Click "Create User" → fill in details |
210
+ | **Edit user** | Click the edit icon on any row |
211
+ | **Reset password** | 🔑 Set temporary or permanent password |
212
+ | **Toggle account** | ✅ Enable or disable with one click |
213
+ | **Verification email** | 📧 Send from the user actions menu |
214
+ | **Delete user** | 🗑️ With confirmation dialog |
215
+ | **Bulk import** | 📦 Upload JSON or CSV |
216
+ | **Export** | 📤 Download all realm users |
218
217
 
219
- Super admins can assign other Strapi users to manage specific realms:
218
+ ### Assigning Realm Admins
220
219
 
221
- 1. Open a realm's settings
222
- 2. Go to the **Admins** tab
223
- 3. Click **Add Admin**
224
- 4. Select a Strapi user
225
- 5. Configure their permissions:
220
+ Super admins can delegate realm management to other Strapi users:
226
221
 
227
222
  ```
228
- ┌───────────────────────────────────────────────────────────────┐
229
- │ Admin: john@example.com
230
- ├───────────────────────────────────────────────────────────────┤
231
- │ ☑ Can Read ☑ Can Create ☐ Can Delete
232
- │ ☑ Can Update ☐ Can Reset Password
233
- │ ☐ Can Manage Roles
234
- └───────────────────────────────────────────────────────────────┘
223
+ ┌─────────────────────────────────────────────────────────┐
224
+ │ Admin: john@example.com
225
+ ├─────────────────────────────────────────────────────────┤
226
+ │ ☑ Can Read ☑ Can Create ☐ Can Delete
227
+ │ ☑ Can Update ☐ Can Reset Password
228
+ │ ☐ Can Manage Roles
229
+ └─────────────────────────────────────────────────────────┘
235
230
  ```
236
231
 
232
+ Each admin sees **only the realms they're assigned to** with **only the actions they're permitted**.
233
+
237
234
  ---
238
235
 
239
- ## API Reference
236
+ ## 📡 API Reference
240
237
 
241
- The plugin exposes a REST API for programmatic access.
238
+ All endpoints live under `/api/keycloak-realm-users`.
242
239
 
243
240
  ### Realms
244
241
 
245
242
  | Method | Endpoint | Description |
246
- |--------|----------|-------------|
247
- | `GET` | `/api/keycloak-realm-users/realms` | List all accessible realms |
248
- | `GET` | `/api/keycloak-realm-users/realms/:id` | Get realm details |
249
- | `POST` | `/api/keycloak-realm-users/realms` | Create realm (super admin) |
250
- | `PUT` | `/api/keycloak-realm-users/realms/:id` | Update realm (super admin) |
251
- | `DELETE` | `/api/keycloak-realm-users/realms/:id` | Delete realm (super admin) |
252
- | `POST` | `/api/keycloak-realm-users/realms/:id/test` | Test realm connection |
243
+ |:------:|----------|-------------|
244
+ | `GET` | `/realms` | List all accessible realms |
245
+ | `GET` | `/realms/:id` | Get realm details |
246
+ | `POST` | `/realms` | Create realm *(super admin)* |
247
+ | `PUT` | `/realms/:id` | Update realm *(super admin)* |
248
+ | `DELETE` | `/realms/:id` | Delete realm *(super admin)* |
249
+ | `POST` | `/realms/:id/test` | Test connection |
253
250
 
254
251
  ### Users
255
252
 
256
253
  | Method | Endpoint | Description |
257
- |--------|----------|-------------|
258
- | `GET` | `/api/keycloak-realm-users/realms/:id/users` | List users (paginated) |
259
- | `GET` | `/api/keycloak-realm-users/realms/:id/users/:userId` | Get user details |
260
- | `POST` | `/api/keycloak-realm-users/realms/:id/users` | Create user |
261
- | `PUT` | `/api/keycloak-realm-users/realms/:id/users/:userId` | Update user |
262
- | `DELETE` | `/api/keycloak-realm-users/realms/:id/users/:userId` | Delete user |
254
+ |:------:|----------|-------------|
255
+ | `GET` | `/realms/:id/users` | List users (paginated) |
256
+ | `GET` | `/realms/:id/users/:userId` | Get user details |
257
+ | `POST` | `/realms/:id/users` | Create user |
258
+ | `PUT` | `/realms/:id/users/:userId` | Update user |
259
+ | `DELETE` | `/realms/:id/users/:userId` | Delete user |
263
260
 
264
261
  ### User Actions
265
262
 
266
263
  | Method | Endpoint | Description |
267
- |--------|----------|-------------|
268
- | `POST` | `/api/.../users/:userId/reset-password` | Reset user password |
269
- | `POST` | `/api/.../users/:userId/enable` | Enable user |
270
- | `POST` | `/api/.../users/:userId/disable` | Disable user |
271
- | `POST` | `/api/.../users/:userId/send-verify-email` | Send verification email |
272
- | `POST` | `/api/.../users/:userId/send-reset-password-email` | Send password reset email |
264
+ |:------:|----------|-------------|
265
+ | `POST` | `/.../users/:userId/reset-password` | Reset password |
266
+ | `POST` | `/.../users/:userId/enable` | Enable user |
267
+ | `POST` | `/.../users/:userId/disable` | Disable user |
268
+ | `POST` | `/.../users/:userId/send-verify-email` | Send verification email |
269
+ | `POST` | `/.../users/:userId/send-reset-password-email` | Send password reset email |
273
270
 
274
271
  ### Roles
275
272
 
276
273
  | Method | Endpoint | Description |
277
- |--------|----------|-------------|
278
- | `GET` | `/api/.../realms/:id/roles` | List realm roles |
279
- | `GET` | `/api/.../users/:userId/roles` | Get user's roles |
280
- | `POST` | `/api/.../users/:userId/roles` | Assign roles |
281
- | `DELETE` | `/api/.../users/:userId/roles` | Remove roles |
274
+ |:------:|----------|-------------|
275
+ | `GET` | `/.../realms/:id/roles` | List realm roles |
276
+ | `GET` | `/.../users/:userId/roles` | Get user's roles |
277
+ | `POST` | `/.../users/:userId/roles` | Assign roles |
278
+ | `DELETE` | `/.../users/:userId/roles` | Remove roles |
282
279
 
283
- ### Bulk Operations
280
+ ### Bulk Operations & Audit
284
281
 
285
282
  | Method | Endpoint | Description |
286
- |--------|----------|-------------|
287
- | `POST` | `/api/.../realms/:id/users/import` | Bulk import users |
288
- | `GET` | `/api/.../realms/:id/users/export` | Export all users |
289
-
290
- ### Audit Log
291
-
292
- | Method | Endpoint | Description |
293
- |--------|----------|-------------|
294
- | `GET` | `/api/keycloak-realm-users/audit` | Query audit logs |
283
+ |:------:|----------|-------------|
284
+ | `POST` | `/.../realms/:id/users/import` | Bulk import users |
285
+ | `GET` | `/.../realms/:id/users/export` | Export all users |
286
+ | `GET` | `/audit` | Query audit logs |
295
287
 
296
288
  ---
297
289
 
298
- ## Permissions
299
-
300
- ### Permission Hierarchy
301
-
302
- ```
303
- Super Admin (Strapi)
304
-
305
- ├── Can manage all realms
306
- ├── Can create/edit/delete realm configurations
307
- └── Can assign realm admins
308
-
309
- └── Realm Admin (Assigned per realm)
310
-
311
- ├── canRead → View users
312
- ├── canCreate → Create users
313
- ├── canUpdate → Update user details, enable/disable
314
- ├── canDelete → Delete users
315
- ├── canResetPassword → Reset passwords, send password reset emails
316
- └── canManageRoles → Assign/remove Keycloak roles
317
- ```
318
-
319
- ### RBAC Integration
290
+ ## 🛡️ Security
320
291
 
321
- The plugin integrates with Strapi's Role-Based Access Control system. You can configure permissions under **Settings** → **Roles** → **[Role Name]** → **Keycloak Realm Users**.
292
+ | Aspect | How we handle it |
293
+ |--------|-----------------|
294
+ | 🔒 **Client Secrets** | Stored with `private: true` — never exposed in API responses |
295
+ | ⚡ **Token Caching** | Access tokens cached in memory, auto-refreshed before expiry |
296
+ | 🚪 **Permission Checks** | Every API call validated before execution |
297
+ | 📋 **Audit Trail** | All actions logged with performer identity |
298
+ | ✅ **Input Validation** | Server-side validation on all inputs |
299
+ | 🧹 **Error Sanitization** | Internal details never leak to clients |
322
300
 
323
301
  ---
324
302
 
325
- ## Data Model
326
-
327
- ### Realm Configuration
328
-
329
- ```typescript
330
- interface RealmConfig {
331
- name: string; // Unique slug identifier
332
- displayName: string; // Human-readable name
333
- serverUrl: string; // Keycloak server URL
334
- realmName: string; // Keycloak realm name
335
- clientId: string; // Service account client ID
336
- clientSecret: string; // Client secret (stored securely)
337
- enabled: boolean; // Whether realm is active
338
- color: string; // UI accent color
339
- }
340
- ```
341
-
342
- ### Audit Log Entry
343
-
344
- ```typescript
345
- interface AuditLog {
346
- action: 'CREATE_USER' | 'UPDATE_USER' | 'DELETE_USER' |
347
- 'RESET_PASSWORD' | 'ENABLE_USER' | 'DISABLE_USER' |
348
- 'ASSIGN_ROLE' | 'REMOVE_ROLE' | 'BULK_IMPORT' | ...;
349
- realmName: string;
350
- realmDisplayName: string;
351
- keycloakUserId: string;
352
- keycloakUsername: string;
353
- performedBy: number; // Strapi admin user ID
354
- performedByEmail: string;
355
- details: object; // Action-specific metadata
356
- createdAt: Date;
357
- }
358
- ```
359
-
360
- ---
361
-
362
- ## Security Considerations
363
-
364
- | Aspect | Implementation |
365
- |--------|----------------|
366
- | **Client Secrets** | Stored with `private: true` attribute, never exposed in API responses |
367
- | **Token Caching** | Access tokens cached in memory with automatic refresh before expiry |
368
- | **Permission Checks** | Every API call validates user permissions before execution |
369
- | **Audit Trail** | All user management actions logged with performer identity |
370
- | **Input Validation** | Server-side validation on all inputs |
371
- | **Error Sanitization** | Internal errors sanitized before sending to client |
372
-
373
- ---
374
-
375
- ## Troubleshooting
303
+ ## 🔧 Troubleshooting
376
304
 
377
305
  <details>
378
- <summary><strong>403 Forbidden when testing connection</strong></summary>
306
+ <summary>🔴 <strong>403 Forbidden when testing connection</strong></summary>
379
307
 
380
- This usually means the Keycloak client doesn't have the required roles.
308
+ The Keycloak client is missing required roles.
381
309
 
382
- **Solution**: Go to your Keycloak client → Service Account Roles → Assign roles from `realm-management`:
310
+ **Fix**: Keycloak Your Client → Service Account Roles → Assign from `realm-management`:
383
311
  - `view-realm`
384
312
  - `view-users`
385
313
  - `manage-users`
386
314
  - `query-users`
387
-
388
315
  </details>
389
316
 
390
317
  <details>
391
- <summary><strong>Invalid client secret error</strong></summary>
392
-
393
- The client secret may have changed or been entered incorrectly.
318
+ <summary>🔴 <strong>Invalid client secret</strong></summary>
394
319
 
395
- **Solution**:
396
- 1. Go to Keycloak → Your Client → Credentials tab
397
- 2. Regenerate or copy the current secret
398
- 3. Update the realm configuration in Strapi
320
+ The secret may have changed or was entered incorrectly.
399
321
 
322
+ **Fix**: Keycloak → Your Client → Credentials tab → Copy the current secret → Update in Strapi.
400
323
  </details>
401
324
 
402
325
  <details>
403
- <summary><strong>Connection works but users fail to load</strong></summary>
326
+ <summary>🔴 <strong>Connection works but users fail to load</strong></summary>
404
327
 
405
- Test connection only verifies basic realm access. User operations require additional permissions.
406
-
407
- **Solution**: Ensure your client has `view-users` and `query-users` roles from `realm-management`.
328
+ Test connection only checks basic realm access. User operations need extra permissions.
408
329
 
330
+ **Fix**: Ensure your client has `view-users` and `query-users` roles from `realm-management`.
409
331
  </details>
410
332
 
411
333
  ---
412
334
 
413
- ## Compatibility
335
+ ## 📦 Compatibility
414
336
 
415
- | Strapi Version | Plugin Version | Keycloak Version |
416
- |----------------|----------------|------------------|
417
- | 5.x | 1.x | 17+ (recommended: 22+) |
337
+ | | Version |
338
+ |---|---------|
339
+ | **Strapi** | v5.x |
340
+ | **Keycloak** | 17+ *(recommended: 22+)* |
341
+ | **Node.js** | 18+ |
418
342
 
419
- > **Note**: Keycloak versions below 17 use a different URL structure (`/auth/...`). This plugin is designed for Keycloak 17+ which removed the `/auth` prefix.
343
+ > ⚠️ Keycloak versions below 17 use the legacy `/auth/...` URL prefix, which this plugin does not support.
420
344
 
421
345
  ---
422
346
 
423
- ## Development
424
-
425
- ### Setup
347
+ ## 🧪 Development
426
348
 
427
349
  ```bash
428
- # Clone the repository
429
- git clone https://github.com/your-org/strapi-plugin-keycloak-realm-users
430
-
431
350
  # Install dependencies
432
351
  npm install
433
- ```
434
-
435
- ### Testing
436
352
 
437
- The plugin includes a comprehensive test suite with ~95% code coverage on services and utilities.
438
-
439
- ```bash
440
- # Run all tests
353
+ # Run tests
441
354
  npm test
442
355
 
443
- # Run tests in watch mode
356
+ # Watch mode
444
357
  npm run test:watch
445
358
 
446
- # Run tests with coverage report
359
+ # Coverage report
447
360
  npm run test:coverage
448
361
  ```
449
362
 
450
- **Coverage thresholds:**
451
- - Branches: 75%
452
- - Functions: 95%
453
- - Lines: 90%
454
- - Statements: 90%
455
-
456
- ### Code Standards
457
-
458
- - **Pure ES6+** - Modern JavaScript throughout
459
- - **JSDoc Documentation** - All public functions, hooks, and types are fully documented
460
- - **Error Handling** - Sanitized errors prevent internal details from leaking to clients
461
- - **Centralized Constants** - No magic values; all constants defined in dedicated modules
363
+ **Coverage thresholds**: Branches 75% · Functions 95% · Lines 90% · Statements 90%
462
364
 
463
365
  ---
464
366
 
465
- ## Contributing
367
+ ## 🤝 Contributing
466
368
 
467
- Contributions are welcome! Please read our contributing guidelines before submitting a PR.
369
+ Contributions welcome! Before submitting a PR:
468
370
 
469
- **Before submitting:**
470
- 1. Ensure all tests pass: `npm test`
471
- 2. Maintain or improve code coverage: `npm run test:coverage`
472
- 3. Add JSDoc documentation for any new public APIs
473
- 4. Follow the existing code style and patterns
371
+ 1. ✅ All tests pass: `npm test`
372
+ 2. 📊 Coverage maintained: `npm run test:coverage`
373
+ 3. 📝 JSDoc added for new public APIs
374
+ 4. 🎨 Follows existing code style
474
375
 
475
376
  ---
476
377
 
477
- ## License
378
+ ## 📄 License
478
379
 
479
- MIT License - see [LICENSE](LICENSE) for details.
380
+ [MIT](LICENSE) use it, fork it, ship it.
480
381
 
481
382
  ---
482
383
 
483
384
  <p align="center">
484
- <sub>Built with ❤️ for the Strapi Community</sub>
385
+ <sub>Built with ❤️ for the Strapi community</sub>
386
+ <br />
387
+ <sub>If this plugin saved you time, give it a ⭐ on GitHub!</sub>
485
388
  </p>