strapi-plugin-keycloak-realm-users 1.0.0

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 (123) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +485 -0
  3. package/__tests__/constants.test.mjs +207 -0
  4. package/__tests__/mocks/strapi.mjs +182 -0
  5. package/__tests__/services/audit-log.test.mjs +283 -0
  6. package/__tests__/services/keycloak-client.test.mjs +651 -0
  7. package/__tests__/services/permission.test.mjs +374 -0
  8. package/__tests__/services/realm.test.mjs +415 -0
  9. package/__tests__/services/user.test.mjs +487 -0
  10. package/__tests__/utils/errors.test.mjs +109 -0
  11. package/admin/src/components/Initializer.jsx +14 -0
  12. package/admin/src/components/RealmBadge.jsx +17 -0
  13. package/admin/src/constants.js +14 -0
  14. package/admin/src/hooks/useAuditLogs.js +142 -0
  15. package/admin/src/hooks/useKeycloakRoles.js +182 -0
  16. package/admin/src/hooks/useKeycloakUsers.js +477 -0
  17. package/admin/src/hooks/useRealmAdmins.js +249 -0
  18. package/admin/src/hooks/useRealms.js +269 -0
  19. package/admin/src/index.js +46 -0
  20. package/admin/src/pages/App.jsx +21 -0
  21. package/admin/src/pages/AuditPage/index.jsx +213 -0
  22. package/admin/src/pages/RealmsPage/RealmEditPage.jsx +791 -0
  23. package/admin/src/pages/RealmsPage/RealmListPage.jsx +231 -0
  24. package/admin/src/pages/RealmsPage/index.jsx +7 -0
  25. package/admin/src/pages/UsersPage/UserEditPage.jsx +313 -0
  26. package/admin/src/pages/UsersPage/UserListPage.jsx +437 -0
  27. package/admin/src/pages/UsersPage/index.jsx +7 -0
  28. package/admin/src/pluginId.js +2 -0
  29. package/admin/src/translations/en.json +77 -0
  30. package/admin/src/translations/fr.json +77 -0
  31. package/babel.config.cjs +17 -0
  32. package/coverage/clover.xml +422 -0
  33. package/coverage/coverage-final.json +8 -0
  34. package/coverage/lcov-report/base.css +224 -0
  35. package/coverage/lcov-report/block-navigation.js +87 -0
  36. package/coverage/lcov-report/favicon.png +0 -0
  37. package/coverage/lcov-report/index.html +146 -0
  38. package/coverage/lcov-report/prettify.css +1 -0
  39. package/coverage/lcov-report/prettify.js +2 -0
  40. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  41. package/coverage/lcov-report/sorter.js +210 -0
  42. package/coverage/lcov-report/src/bootstrap.js.html +346 -0
  43. package/coverage/lcov-report/src/config/index.html +116 -0
  44. package/coverage/lcov-report/src/config/index.js.html +106 -0
  45. package/coverage/lcov-report/src/constants.js.html +850 -0
  46. package/coverage/lcov-report/src/content-types/audit-log/index.html +116 -0
  47. package/coverage/lcov-report/src/content-types/audit-log/index.js.html +94 -0
  48. package/coverage/lcov-report/src/content-types/index.html +116 -0
  49. package/coverage/lcov-report/src/content-types/index.js.html +112 -0
  50. package/coverage/lcov-report/src/content-types/realm-admin/index.html +116 -0
  51. package/coverage/lcov-report/src/content-types/realm-admin/index.js.html +94 -0
  52. package/coverage/lcov-report/src/content-types/realm-config/index.html +116 -0
  53. package/coverage/lcov-report/src/content-types/realm-config/index.js.html +94 -0
  54. package/coverage/lcov-report/src/controllers/audit.js.html +517 -0
  55. package/coverage/lcov-report/src/controllers/index.html +161 -0
  56. package/coverage/lcov-report/src/controllers/index.js.html +112 -0
  57. package/coverage/lcov-report/src/controllers/realm.js.html +1057 -0
  58. package/coverage/lcov-report/src/controllers/user.js.html +1324 -0
  59. package/coverage/lcov-report/src/destroy.js.html +100 -0
  60. package/coverage/lcov-report/src/index.html +116 -0
  61. package/coverage/lcov-report/src/policies/can-access-realm.js.html +163 -0
  62. package/coverage/lcov-report/src/policies/index.html +146 -0
  63. package/coverage/lcov-report/src/policies/index.js.html +106 -0
  64. package/coverage/lcov-report/src/policies/is-authenticated.js.html +100 -0
  65. package/coverage/lcov-report/src/register.js.html +106 -0
  66. package/coverage/lcov-report/src/routes/admin.js.html +844 -0
  67. package/coverage/lcov-report/src/routes/index.html +131 -0
  68. package/coverage/lcov-report/src/routes/index.js.html +109 -0
  69. package/coverage/lcov-report/src/services/audit-log.js.html +673 -0
  70. package/coverage/lcov-report/src/services/index.html +176 -0
  71. package/coverage/lcov-report/src/services/index.js.html +124 -0
  72. package/coverage/lcov-report/src/services/keycloak-client.js.html +2359 -0
  73. package/coverage/lcov-report/src/services/permission.js.html +955 -0
  74. package/coverage/lcov-report/src/services/realm.js.html +1207 -0
  75. package/coverage/lcov-report/src/services/user.js.html +1924 -0
  76. package/coverage/lcov-report/src/utils/errors.js.html +274 -0
  77. package/coverage/lcov-report/src/utils/index.html +116 -0
  78. package/coverage/lcov-report/src/utils/index.js.html +103 -0
  79. package/coverage/lcov.info +804 -0
  80. package/dist/_chunks/App-BaKrvCeS.mjs +1975 -0
  81. package/dist/_chunks/App-DO6syS77.js +1975 -0
  82. package/dist/_chunks/en-Li-XBDe9.mjs +72 -0
  83. package/dist/_chunks/en-aCyfgNfr.js +72 -0
  84. package/dist/_chunks/fr-Cj33Q8jI.js +72 -0
  85. package/dist/_chunks/fr-vLrXph-Z.mjs +72 -0
  86. package/dist/_chunks/index-DwDO4-0C.js +69 -0
  87. package/dist/_chunks/index-jTVd7LdQ.mjs +70 -0
  88. package/dist/admin/index.js +3 -0
  89. package/dist/admin/index.mjs +4 -0
  90. package/dist/server/index.js +3003 -0
  91. package/dist/server/index.mjs +3004 -0
  92. package/jest.config.cjs +50 -0
  93. package/package.json +55 -0
  94. package/server/src/bootstrap.js +87 -0
  95. package/server/src/config/index.js +7 -0
  96. package/server/src/constants.js +255 -0
  97. package/server/src/content-types/audit-log/index.js +3 -0
  98. package/server/src/content-types/audit-log/schema.json +61 -0
  99. package/server/src/content-types/index.js +9 -0
  100. package/server/src/content-types/realm-admin/index.js +3 -0
  101. package/server/src/content-types/realm-admin/schema.json +45 -0
  102. package/server/src/content-types/realm-config/index.js +3 -0
  103. package/server/src/content-types/realm-config/schema.json +56 -0
  104. package/server/src/controllers/audit.js +144 -0
  105. package/server/src/controllers/index.js +9 -0
  106. package/server/src/controllers/realm.js +324 -0
  107. package/server/src/controllers/user.js +413 -0
  108. package/server/src/destroy.js +5 -0
  109. package/server/src/index.js +21 -0
  110. package/server/src/policies/can-access-realm.js +26 -0
  111. package/server/src/policies/index.js +7 -0
  112. package/server/src/policies/is-authenticated.js +5 -0
  113. package/server/src/register.js +7 -0
  114. package/server/src/routes/admin.js +253 -0
  115. package/server/src/routes/index.js +8 -0
  116. package/server/src/services/audit-log.js +196 -0
  117. package/server/src/services/index.js +13 -0
  118. package/server/src/services/keycloak-client.js +758 -0
  119. package/server/src/services/permission.js +290 -0
  120. package/server/src/services/realm.js +374 -0
  121. package/server/src/services/user.js +613 -0
  122. package/server/src/utils/errors.js +63 -0
  123. package/server/src/utils/index.js +6 -0
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @fileoverview Jest configuration for strapi-plugin-keycloak-realm-users.
3
+ * Uses Babel for ES module transformation.
4
+ * @see https://jestjs.io/docs/configuration
5
+ */
6
+
7
+ module.exports = {
8
+ testEnvironment: 'node',
9
+
10
+ // Use Babel to transform ES modules
11
+ transform: {
12
+ '^.+\\.m?js$': 'babel-jest',
13
+ },
14
+
15
+ // Don't ignore server/src when transforming
16
+ transformIgnorePatterns: [
17
+ '/node_modules/',
18
+ ],
19
+
20
+ // Test file patterns
21
+ testMatch: [
22
+ '**/__tests__/**/*.test.mjs',
23
+ ],
24
+
25
+ // Coverage configuration - focus on services and utils (tested modules)
26
+ collectCoverageFrom: [
27
+ 'server/src/services/*.js',
28
+ 'server/src/utils/*.js',
29
+ 'server/src/constants.js',
30
+ '!server/src/services/index.js',
31
+ '!server/src/utils/index.js',
32
+ '!**/node_modules/**',
33
+ ],
34
+
35
+ // Coverage thresholds for tested modules
36
+ coverageThreshold: {
37
+ global: {
38
+ branches: 75,
39
+ functions: 95,
40
+ lines: 90,
41
+ statements: 90,
42
+ },
43
+ },
44
+
45
+ // Clear mocks between tests
46
+ clearMocks: true,
47
+
48
+ // Verbose output
49
+ verbose: true,
50
+ };
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "strapi-plugin-keycloak-realm-users",
3
+ "version": "1.0.0",
4
+ "description": "Strapi plugin for managing Keycloak users across multiple realms with role-based access control",
5
+ "license": "MIT",
6
+ "strapi": {
7
+ "name": "keycloak-realm-users",
8
+ "displayName": "Keycloak Realm Users",
9
+ "description": "Manage Keycloak users across multiple realms",
10
+ "kind": "plugin"
11
+ },
12
+ "type": "commonjs",
13
+ "exports": {
14
+ "./strapi-admin": {
15
+ "types": "./dist/admin/src/index.d.ts",
16
+ "source": "./admin/src/index.js",
17
+ "import": "./dist/admin/index.mjs",
18
+ "require": "./dist/admin/index.js",
19
+ "default": "./dist/admin/index.js"
20
+ },
21
+ "./strapi-server": {
22
+ "types": "./dist/server/src/index.d.ts",
23
+ "source": "./server/src/index.js",
24
+ "import": "./dist/server/index.mjs",
25
+ "require": "./dist/server/index.js",
26
+ "default": "./dist/server/index.js"
27
+ },
28
+ "./package.json": "./package.json"
29
+ },
30
+ "scripts": {
31
+ "build": "strapi-plugin build",
32
+ "watch": "strapi-plugin watch",
33
+ "verify": "strapi-plugin verify",
34
+ "test": "jest --config jest.config.cjs",
35
+ "test:watch": "jest --config jest.config.cjs --watch",
36
+ "test:coverage": "jest --config jest.config.cjs --coverage"
37
+ },
38
+ "peerDependencies": {
39
+ "@strapi/strapi": "^5.0.0"
40
+ },
41
+ "devDependencies": {
42
+ "@babel/core": "^7.29.0",
43
+ "@babel/preset-env": "^7.29.0",
44
+ "@strapi/sdk-plugin": "^5.0.0",
45
+ "babel-jest": "^30.2.0",
46
+ "jest": "^29.7.0"
47
+ },
48
+ "dependencies": {
49
+ "@strapi/design-system": "^2.1.2",
50
+ "@strapi/icons": "^2.1.2",
51
+ "react": "^19.2.4",
52
+ "react-intl": "^8.1.3",
53
+ "react-router-dom": "^7.13.0"
54
+ }
55
+ }
@@ -0,0 +1,87 @@
1
+ import { PLUGIN_ID } from './constants.js';
2
+
3
+ const bootstrap = async ({ strapi }) => {
4
+ // Register custom actions for RBAC
5
+ try {
6
+ await strapi.admin.services.permission.actionProvider.registerMany([
7
+ {
8
+ uid: `plugin::${PLUGIN_ID}.realm.read`,
9
+ displayName: 'Read Realms',
10
+ pluginName: PLUGIN_ID,
11
+ section: 'settings',
12
+ category: 'Keycloak User Management',
13
+ subCategory: 'Realms',
14
+ },
15
+ {
16
+ uid: `plugin::${PLUGIN_ID}.realm.create`,
17
+ displayName: 'Create Realms',
18
+ pluginName: PLUGIN_ID,
19
+ section: 'settings',
20
+ category: 'Keycloak User Management',
21
+ subCategory: 'Realms',
22
+ },
23
+ {
24
+ uid: `plugin::${PLUGIN_ID}.realm.update`,
25
+ displayName: 'Update Realms',
26
+ pluginName: PLUGIN_ID,
27
+ section: 'settings',
28
+ category: 'Keycloak User Management',
29
+ subCategory: 'Realms',
30
+ },
31
+ {
32
+ uid: `plugin::${PLUGIN_ID}.realm.delete`,
33
+ displayName: 'Delete Realms',
34
+ pluginName: PLUGIN_ID,
35
+ section: 'settings',
36
+ category: 'Keycloak User Management',
37
+ subCategory: 'Realms',
38
+ },
39
+ {
40
+ uid: `plugin::${PLUGIN_ID}.user.read`,
41
+ displayName: 'Read Keycloak Users',
42
+ pluginName: PLUGIN_ID,
43
+ section: 'settings',
44
+ category: 'Keycloak User Management',
45
+ subCategory: 'Users',
46
+ },
47
+ {
48
+ uid: `plugin::${PLUGIN_ID}.user.create`,
49
+ displayName: 'Create Keycloak Users',
50
+ pluginName: PLUGIN_ID,
51
+ section: 'settings',
52
+ category: 'Keycloak User Management',
53
+ subCategory: 'Users',
54
+ },
55
+ {
56
+ uid: `plugin::${PLUGIN_ID}.user.update`,
57
+ displayName: 'Update Keycloak Users',
58
+ pluginName: PLUGIN_ID,
59
+ section: 'settings',
60
+ category: 'Keycloak User Management',
61
+ subCategory: 'Users',
62
+ },
63
+ {
64
+ uid: `plugin::${PLUGIN_ID}.user.delete`,
65
+ displayName: 'Delete Keycloak Users',
66
+ pluginName: PLUGIN_ID,
67
+ section: 'settings',
68
+ category: 'Keycloak User Management',
69
+ subCategory: 'Users',
70
+ },
71
+ {
72
+ uid: `plugin::${PLUGIN_ID}.audit.read`,
73
+ displayName: 'Read Audit Logs',
74
+ pluginName: PLUGIN_ID,
75
+ section: 'settings',
76
+ category: 'Keycloak User Management',
77
+ subCategory: 'Audit',
78
+ },
79
+ ]);
80
+
81
+ strapi.log.info(`[${PLUGIN_ID}] Plugin bootstrapped with permissions registered`);
82
+ } catch (err) {
83
+ strapi.log.error(`[${PLUGIN_ID}] Failed to register permissions:`, err);
84
+ }
85
+ };
86
+
87
+ export default bootstrap;
@@ -0,0 +1,7 @@
1
+ export default {
2
+ default: {},
3
+ validator(config) {
4
+ // No runtime config validation needed
5
+ // Realm configurations are stored in the database
6
+ },
7
+ };
@@ -0,0 +1,255 @@
1
+ /**
2
+ * @fileoverview Constants and configuration values for the Keycloak Realm Users plugin.
3
+ * All magic values, identifiers, and configurable defaults are centralized here.
4
+ * @module constants
5
+ */
6
+
7
+ // ============================================================================
8
+ // Plugin Identification
9
+ // ============================================================================
10
+
11
+ /**
12
+ * Unique plugin identifier used for Strapi registration.
13
+ * @constant {string}
14
+ */
15
+ export const PLUGIN_ID = 'strapi-plugin-keycloak-realm-users';
16
+
17
+ // ============================================================================
18
+ // Content Type Identifiers
19
+ // ============================================================================
20
+
21
+ /**
22
+ * Strapi content type UIDs for plugin entities.
23
+ * @constant {Object}
24
+ * @property {string} REALM_CONFIG - Realm configuration content type
25
+ * @property {string} REALM_ADMIN - Realm admin assignment content type
26
+ * @property {string} AUDIT_LOG - Audit log entry content type
27
+ */
28
+ export const CONTENT_TYPES = {
29
+ REALM_CONFIG: `plugin::${PLUGIN_ID}.realm-config`,
30
+ REALM_ADMIN: `plugin::${PLUGIN_ID}.realm-admin`,
31
+ AUDIT_LOG: `plugin::${PLUGIN_ID}.audit-log`,
32
+ };
33
+
34
+ // ============================================================================
35
+ // Service Identifiers
36
+ // ============================================================================
37
+
38
+ /**
39
+ * Service names for internal plugin service resolution.
40
+ * @constant {Object}
41
+ * @property {string} REALM - Realm management service
42
+ * @property {string} KEYCLOAK_CLIENT - Keycloak API client service
43
+ * @property {string} USER - User management service
44
+ * @property {string} PERMISSION - Permission checking service
45
+ * @property {string} AUDIT_LOG - Audit logging service
46
+ */
47
+ export const SERVICES = {
48
+ REALM: 'realm',
49
+ KEYCLOAK_CLIENT: 'keycloak-client',
50
+ USER: 'user',
51
+ PERMISSION: 'permission',
52
+ AUDIT_LOG: 'audit-log',
53
+ };
54
+
55
+ // ============================================================================
56
+ // Audit Action Types
57
+ // ============================================================================
58
+
59
+ /**
60
+ * Action types recorded in the audit log.
61
+ * @constant {Object}
62
+ */
63
+ export const AUDIT_ACTIONS = {
64
+ /** User was created in Keycloak */
65
+ CREATE_USER: 'CREATE_USER',
66
+ /** User details were modified */
67
+ UPDATE_USER: 'UPDATE_USER',
68
+ /** User was permanently deleted */
69
+ DELETE_USER: 'DELETE_USER',
70
+ /** User password was reset */
71
+ RESET_PASSWORD: 'RESET_PASSWORD',
72
+ /** Realm role was assigned to user */
73
+ ASSIGN_ROLE: 'ASSIGN_ROLE',
74
+ /** Realm role was removed from user */
75
+ REMOVE_ROLE: 'REMOVE_ROLE',
76
+ /** User account was enabled */
77
+ ENABLE_USER: 'ENABLE_USER',
78
+ /** User account was disabled */
79
+ DISABLE_USER: 'DISABLE_USER',
80
+ /** Email verification was sent */
81
+ SEND_VERIFY_EMAIL: 'SEND_VERIFY_EMAIL',
82
+ /** Password reset email was sent */
83
+ SEND_RESET_PASSWORD_EMAIL: 'SEND_RESET_PASSWORD_EMAIL',
84
+ /** Bulk user import was performed */
85
+ BULK_IMPORT: 'BULK_IMPORT',
86
+ };
87
+
88
+ // ============================================================================
89
+ // Error Messages (User-Safe)
90
+ // ============================================================================
91
+
92
+ /**
93
+ * Sanitized error messages safe for API responses.
94
+ * Internal error details are logged separately for debugging.
95
+ * @constant {Object}
96
+ */
97
+ export const ERROR_MESSAGES = {
98
+ REALM_NOT_FOUND: 'Realm configuration not found.',
99
+ REALM_DISABLED: 'This realm is currently disabled.',
100
+ USER_NOT_FOUND: 'Keycloak user not found.',
101
+ INSUFFICIENT_PERMISSIONS: 'You do not have permission to perform this action.',
102
+ REALM_ACCESS_DENIED: 'You do not have access to this realm.',
103
+ KEYCLOAK_CONNECTION_FAILED: 'Failed to connect to Keycloak server.',
104
+ KEYCLOAK_AUTH_FAILED: 'Failed to authenticate with Keycloak.',
105
+ INVALID_USER_DATA: 'Invalid user data provided.',
106
+ MISSING_REQUIRED_FIELDS: 'Missing required fields.',
107
+ UNKNOWN_ERROR: 'An unexpected error occurred.',
108
+ USER_ALREADY_EXISTS: 'A user with this username or email already exists.',
109
+ PASSWORD_RESET_FAILED: 'Failed to reset password.',
110
+ EMAIL_SEND_FAILED: 'Failed to send email.',
111
+ ROLE_ASSIGNMENT_FAILED: 'Failed to assign roles.',
112
+ ROLE_REMOVAL_FAILED: 'Failed to remove roles.',
113
+ LOGOUT_FAILED: 'Failed to logout user.',
114
+ INVALID_NAME_FORMAT: 'Name must contain only lowercase letters, numbers, and hyphens.',
115
+ REALM_NAME_EXISTS: 'A realm with this name already exists.',
116
+ };
117
+
118
+ // ============================================================================
119
+ // Default Permissions
120
+ // ============================================================================
121
+
122
+ /**
123
+ * Default permissions for realm admin assignments.
124
+ * New realm admins receive read-only access by default.
125
+ * @constant {Object}
126
+ * @property {boolean} canRead - Can view users in the realm
127
+ * @property {boolean} canCreate - Can create new users
128
+ * @property {boolean} canUpdate - Can modify existing users (includes enable/disable)
129
+ * @property {boolean} canDelete - Can permanently delete users
130
+ * @property {boolean} canManageRoles - Can assign/remove realm roles
131
+ * @property {boolean} canResetPassword - Can reset user passwords and send password reset emails
132
+ */
133
+ export const DEFAULT_REALM_PERMISSIONS = {
134
+ canRead: true,
135
+ canCreate: false,
136
+ canUpdate: false,
137
+ canDelete: false,
138
+ canManageRoles: false,
139
+ canResetPassword: false,
140
+ };
141
+
142
+ // ============================================================================
143
+ // Strapi Role Constants
144
+ // ============================================================================
145
+
146
+ /**
147
+ * Strapi admin role code for super administrators.
148
+ * Super admins have unrestricted access to all plugin functionality.
149
+ * @constant {string}
150
+ */
151
+ export const STRAPI_SUPER_ADMIN_ROLE = 'strapi-super-admin';
152
+
153
+ // ============================================================================
154
+ // Keycloak Configuration
155
+ // ============================================================================
156
+
157
+ /**
158
+ * Time buffer (in milliseconds) before token expiry to trigger refresh.
159
+ * Tokens are refreshed 60 seconds before expiration to prevent request failures.
160
+ * @constant {number}
161
+ */
162
+ export const TOKEN_EXPIRY_BUFFER_MS = 60000;
163
+
164
+ /**
165
+ * Default lifespan (in seconds) for email action links sent to users.
166
+ * Default: 12 hours (43200 seconds)
167
+ * @constant {number}
168
+ */
169
+ export const EMAIL_ACTION_LIFESPAN_SECONDS = 43200;
170
+
171
+ /**
172
+ * Default color for realm UI badge/indicator.
173
+ * @constant {string}
174
+ */
175
+ export const DEFAULT_REALM_COLOR = '#4945ff';
176
+
177
+ // ============================================================================
178
+ // Pagination Defaults
179
+ // ============================================================================
180
+
181
+ /**
182
+ * Default pagination settings for list operations.
183
+ * @constant {Object}
184
+ * @property {number} PAGE_SIZE - Default number of items per page
185
+ * @property {number} AUDIT_LOG_LIMIT - Default limit for audit log queries
186
+ * @property {number} EXPORT_BATCH_SIZE - Batch size for user export operations
187
+ */
188
+ export const PAGINATION = {
189
+ PAGE_SIZE: 25,
190
+ AUDIT_LOG_LIMIT: 50,
191
+ EXPORT_BATCH_SIZE: 100,
192
+ };
193
+
194
+ // ============================================================================
195
+ // HTTP Constants
196
+ // ============================================================================
197
+
198
+ /**
199
+ * HTTP status codes used for error handling.
200
+ * @constant {Object}
201
+ */
202
+ export const HTTP_STATUS = {
203
+ OK: 200,
204
+ CREATED: 201,
205
+ NO_CONTENT: 204,
206
+ BAD_REQUEST: 400,
207
+ UNAUTHORIZED: 401,
208
+ FORBIDDEN: 403,
209
+ NOT_FOUND: 404,
210
+ CONFLICT: 409,
211
+ INTERNAL_ERROR: 500,
212
+ };
213
+
214
+ /**
215
+ * HTTP headers used in Keycloak API requests.
216
+ * @constant {Object}
217
+ */
218
+ export const HTTP_HEADERS = {
219
+ CONTENT_TYPE_JSON: 'application/json',
220
+ CONTENT_TYPE_FORM: 'application/x-www-form-urlencoded',
221
+ };
222
+
223
+ // ============================================================================
224
+ // Keycloak Email Actions
225
+ // ============================================================================
226
+
227
+ /**
228
+ * Keycloak required action types for email operations.
229
+ * @constant {Object}
230
+ */
231
+ export const KEYCLOAK_EMAIL_ACTIONS = {
232
+ VERIFY_EMAIL: 'VERIFY_EMAIL',
233
+ UPDATE_PASSWORD: 'UPDATE_PASSWORD',
234
+ };
235
+
236
+ // ============================================================================
237
+ // Validation Patterns
238
+ // ============================================================================
239
+
240
+ /**
241
+ * Regex pattern for validating realm slug names.
242
+ * Allows only lowercase letters, numbers, and hyphens.
243
+ * @constant {RegExp}
244
+ */
245
+ export const REALM_NAME_PATTERN = /^[a-z0-9-]+$/;
246
+
247
+ // ============================================================================
248
+ // Default Values
249
+ // ============================================================================
250
+
251
+ /**
252
+ * Placeholder value for unknown user emails in audit logs.
253
+ * @constant {string}
254
+ */
255
+ export const UNKNOWN_USER_EMAIL = 'unknown';
@@ -0,0 +1,3 @@
1
+ import schema from './schema.json';
2
+
3
+ export default { schema };
@@ -0,0 +1,61 @@
1
+ {
2
+ "kind": "collectionType",
3
+ "collectionName": "kru_audit_logs",
4
+ "info": {
5
+ "singularName": "audit-log",
6
+ "pluralName": "audit-logs",
7
+ "displayName": "Keycloak Audit Log"
8
+ },
9
+ "options": {
10
+ "draftAndPublish": false
11
+ },
12
+ "pluginOptions": {
13
+ "content-manager": {
14
+ "visible": true
15
+ },
16
+ "content-type-builder": {
17
+ "visible": false
18
+ }
19
+ },
20
+ "attributes": {
21
+ "realmName": {
22
+ "type": "string",
23
+ "required": true
24
+ },
25
+ "realmDisplayName": {
26
+ "type": "string"
27
+ },
28
+ "action": {
29
+ "type": "enumeration",
30
+ "enum": [
31
+ "CREATE_USER",
32
+ "UPDATE_USER",
33
+ "DELETE_USER",
34
+ "RESET_PASSWORD",
35
+ "ASSIGN_ROLE",
36
+ "REMOVE_ROLE",
37
+ "ENABLE_USER",
38
+ "DISABLE_USER",
39
+ "SEND_VERIFY_EMAIL",
40
+ "SEND_RESET_PASSWORD_EMAIL",
41
+ "BULK_IMPORT"
42
+ ],
43
+ "required": true
44
+ },
45
+ "keycloakUserId": {
46
+ "type": "string"
47
+ },
48
+ "keycloakUsername": {
49
+ "type": "string"
50
+ },
51
+ "details": {
52
+ "type": "json"
53
+ },
54
+ "performedById": {
55
+ "type": "integer"
56
+ },
57
+ "performedByEmail": {
58
+ "type": "string"
59
+ }
60
+ }
61
+ }
@@ -0,0 +1,9 @@
1
+ import realmConfig from './realm-config';
2
+ import realmAdmin from './realm-admin';
3
+ import auditLog from './audit-log';
4
+
5
+ export default {
6
+ 'realm-config': realmConfig,
7
+ 'realm-admin': realmAdmin,
8
+ 'audit-log': auditLog,
9
+ };
@@ -0,0 +1,3 @@
1
+ import schema from './schema.json';
2
+
3
+ export default { schema };
@@ -0,0 +1,45 @@
1
+ {
2
+ "kind": "collectionType",
3
+ "collectionName": "kru_realm_admins",
4
+ "info": {
5
+ "singularName": "realm-admin",
6
+ "pluralName": "realm-admins",
7
+ "displayName": "Realm Admin Assignment"
8
+ },
9
+ "options": {
10
+ "draftAndPublish": false
11
+ },
12
+ "pluginOptions": {
13
+ "content-manager": {
14
+ "visible": false
15
+ },
16
+ "content-type-builder": {
17
+ "visible": false
18
+ }
19
+ },
20
+ "attributes": {
21
+ "strapiUserId": {
22
+ "type": "integer",
23
+ "required": true
24
+ },
25
+ "strapiUserEmail": {
26
+ "type": "string"
27
+ },
28
+ "realmConfig": {
29
+ "type": "relation",
30
+ "relation": "manyToOne",
31
+ "target": "plugin::strapi-plugin-keycloak-realm-users.realm-config"
32
+ },
33
+ "permissions": {
34
+ "type": "json",
35
+ "default": {
36
+ "canRead": true,
37
+ "canCreate": false,
38
+ "canUpdate": false,
39
+ "canDelete": false,
40
+ "canManageRoles": false,
41
+ "canResetPassword": false
42
+ }
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,3 @@
1
+ import schema from './schema.json';
2
+
3
+ export default { schema };
@@ -0,0 +1,56 @@
1
+ {
2
+ "kind": "collectionType",
3
+ "collectionName": "kru_realm_configs",
4
+ "info": {
5
+ "singularName": "realm-config",
6
+ "pluralName": "realm-configs",
7
+ "displayName": "Keycloak Realm"
8
+ },
9
+ "options": {
10
+ "draftAndPublish": false
11
+ },
12
+ "pluginOptions": {
13
+ "content-manager": {
14
+ "visible": false
15
+ },
16
+ "content-type-builder": {
17
+ "visible": false
18
+ }
19
+ },
20
+ "attributes": {
21
+ "name": {
22
+ "type": "string",
23
+ "required": true,
24
+ "unique": true,
25
+ "regex": "^[a-z0-9-]+$"
26
+ },
27
+ "displayName": {
28
+ "type": "string",
29
+ "required": true
30
+ },
31
+ "serverUrl": {
32
+ "type": "string",
33
+ "required": true
34
+ },
35
+ "realmName": {
36
+ "type": "string",
37
+ "required": true
38
+ },
39
+ "clientId": {
40
+ "type": "string",
41
+ "required": true
42
+ },
43
+ "clientSecret": {
44
+ "type": "string",
45
+ "private": true
46
+ },
47
+ "enabled": {
48
+ "type": "boolean",
49
+ "default": true
50
+ },
51
+ "color": {
52
+ "type": "string",
53
+ "default": "#4945ff"
54
+ }
55
+ }
56
+ }