@delmaredigital/payload-better-auth 0.3.6 → 0.3.8

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 (164) hide show
  1. package/README.md +60 -12
  2. package/dist/adapter/collections.d.ts.map +1 -1
  3. package/dist/adapter/collections.js +126 -88
  4. package/dist/adapter/collections.js.map +1 -1
  5. package/dist/adapter/index.js +197 -150
  6. package/dist/adapter/index.js.map +1 -1
  7. package/dist/components/BeforeLogin.d.ts +1 -1
  8. package/dist/components/BeforeLogin.d.ts.map +1 -1
  9. package/dist/components/BeforeLogin.js +15 -7
  10. package/dist/components/BeforeLogin.js.map +1 -1
  11. package/dist/components/LoginView.d.ts +2 -2
  12. package/dist/components/LoginView.d.ts.map +1 -1
  13. package/dist/components/LoginView.js +660 -218
  14. package/dist/components/LoginView.js.map +1 -1
  15. package/dist/components/LoginViewWrapper.d.ts +1 -1
  16. package/dist/components/LoginViewWrapper.d.ts.map +1 -1
  17. package/dist/components/LoginViewWrapper.js +14 -4
  18. package/dist/components/LoginViewWrapper.js.map +1 -1
  19. package/dist/components/LogoutButton.d.ts +1 -1
  20. package/dist/components/LogoutButton.d.ts.map +1 -1
  21. package/dist/components/LogoutButton.js +19 -11
  22. package/dist/components/LogoutButton.js.map +1 -1
  23. package/dist/components/PasskeyRegisterButton.d.ts +2 -2
  24. package/dist/components/PasskeyRegisterButton.d.ts.map +1 -1
  25. package/dist/components/PasskeyRegisterButton.js +20 -16
  26. package/dist/components/PasskeyRegisterButton.js.map +1 -1
  27. package/dist/components/PasskeySignInButton.d.ts +2 -2
  28. package/dist/components/PasskeySignInButton.d.ts.map +1 -1
  29. package/dist/components/PasskeySignInButton.js +14 -12
  30. package/dist/components/PasskeySignInButton.js.map +1 -1
  31. package/dist/components/auth/ForgotPasswordView.d.ts +1 -1
  32. package/dist/components/auth/ForgotPasswordView.d.ts.map +1 -1
  33. package/dist/components/auth/ForgotPasswordView.js +133 -43
  34. package/dist/components/auth/ForgotPasswordView.js.map +1 -1
  35. package/dist/components/auth/ResetPasswordView.d.ts +1 -1
  36. package/dist/components/auth/ResetPasswordView.d.ts.map +1 -1
  37. package/dist/components/auth/ResetPasswordView.js +154 -50
  38. package/dist/components/auth/ResetPasswordView.js.map +1 -1
  39. package/dist/components/auth/index.js +2 -2
  40. package/dist/components/auth/index.js.map +1 -1
  41. package/dist/components/management/ApiKeysManagementClient.d.ts +2 -2
  42. package/dist/components/management/ApiKeysManagementClient.d.ts.map +1 -1
  43. package/dist/components/management/ApiKeysManagementClient.js +539 -222
  44. package/dist/components/management/ApiKeysManagementClient.js.map +1 -1
  45. package/dist/components/management/PasskeysManagementClient.d.ts +2 -2
  46. package/dist/components/management/PasskeysManagementClient.d.ts.map +1 -1
  47. package/dist/components/management/PasskeysManagementClient.js +215 -92
  48. package/dist/components/management/PasskeysManagementClient.js.map +1 -1
  49. package/dist/components/management/SecurityNavLinks.d.ts +1 -1
  50. package/dist/components/management/SecurityNavLinks.d.ts.map +1 -1
  51. package/dist/components/management/SecurityNavLinks.js +51 -24
  52. package/dist/components/management/SecurityNavLinks.js.map +1 -1
  53. package/dist/components/management/TwoFactorManagementClient.d.ts +2 -2
  54. package/dist/components/management/TwoFactorManagementClient.d.ts.map +1 -1
  55. package/dist/components/management/TwoFactorManagementClient.js +270 -111
  56. package/dist/components/management/TwoFactorManagementClient.js.map +1 -1
  57. package/dist/components/management/index.js +2 -2
  58. package/dist/components/management/index.js.map +1 -1
  59. package/dist/components/management/views/ApiKeysView.d.ts +1 -1
  60. package/dist/components/management/views/ApiKeysView.d.ts.map +1 -1
  61. package/dist/components/management/views/ApiKeysView.js +19 -4
  62. package/dist/components/management/views/ApiKeysView.js.map +1 -1
  63. package/dist/components/management/views/PasskeysView.d.ts +1 -1
  64. package/dist/components/management/views/PasskeysView.d.ts.map +1 -1
  65. package/dist/components/management/views/PasskeysView.js +16 -4
  66. package/dist/components/management/views/PasskeysView.js.map +1 -1
  67. package/dist/components/management/views/TwoFactorView.d.ts +1 -1
  68. package/dist/components/management/views/TwoFactorView.d.ts.map +1 -1
  69. package/dist/components/management/views/TwoFactorView.js +16 -4
  70. package/dist/components/management/views/TwoFactorView.js.map +1 -1
  71. package/dist/components/management/views/index.js +2 -2
  72. package/dist/components/management/views/index.js.map +1 -1
  73. package/dist/components/twoFactor/TwoFactorSetupView.d.ts +1 -1
  74. package/dist/components/twoFactor/TwoFactorSetupView.d.ts.map +1 -1
  75. package/dist/components/twoFactor/TwoFactorSetupView.js +240 -87
  76. package/dist/components/twoFactor/TwoFactorSetupView.js.map +1 -1
  77. package/dist/components/twoFactor/TwoFactorVerifyView.d.ts +1 -1
  78. package/dist/components/twoFactor/TwoFactorVerifyView.d.ts.map +1 -1
  79. package/dist/components/twoFactor/TwoFactorVerifyView.js +108 -45
  80. package/dist/components/twoFactor/TwoFactorVerifyView.js.map +1 -1
  81. package/dist/components/twoFactor/index.js +2 -2
  82. package/dist/components/twoFactor/index.js.map +1 -1
  83. package/dist/exports/client.d.ts +2356 -2
  84. package/dist/exports/client.d.ts.map +1 -1
  85. package/dist/exports/client.js +48 -8
  86. package/dist/exports/client.js.map +1 -1
  87. package/dist/exports/components.js +2 -2
  88. package/dist/exports/components.js.map +1 -1
  89. package/dist/exports/management.js +3 -3
  90. package/dist/exports/management.js.map +1 -1
  91. package/dist/exports/rsc.js +2 -2
  92. package/dist/exports/rsc.js.map +1 -1
  93. package/dist/generated-types.js +4 -2
  94. package/dist/generated-types.js.map +1 -1
  95. package/dist/index.js +6 -6
  96. package/dist/index.js.map +1 -1
  97. package/dist/plugin/index.d.ts +35 -2
  98. package/dist/plugin/index.d.ts.map +1 -1
  99. package/dist/plugin/index.js +198 -162
  100. package/dist/plugin/index.js.map +1 -1
  101. package/dist/scripts/generate-types.js +66 -50
  102. package/dist/scripts/generate-types.js.map +1 -1
  103. package/dist/types/apiKey.js +7 -2
  104. package/dist/types/apiKey.js.map +1 -1
  105. package/dist/types/betterAuth.js +23 -2
  106. package/dist/types/betterAuth.js.map +1 -1
  107. package/dist/utils/access.js +78 -81
  108. package/dist/utils/access.js.map +1 -1
  109. package/dist/utils/apiKeyAccess.js +65 -72
  110. package/dist/utils/apiKeyAccess.js.map +1 -1
  111. package/dist/utils/betterAuthDefaults.js +8 -8
  112. package/dist/utils/betterAuthDefaults.js.map +1 -1
  113. package/dist/utils/detectAuthConfig.js +8 -11
  114. package/dist/utils/detectAuthConfig.js.map +1 -1
  115. package/dist/utils/detectEnabledPlugins.js +6 -7
  116. package/dist/utils/detectEnabledPlugins.js.map +1 -1
  117. package/dist/utils/firstUserAdmin.js +18 -20
  118. package/dist/utils/firstUserAdmin.js.map +1 -1
  119. package/dist/utils/generateScopes.js +40 -41
  120. package/dist/utils/generateScopes.js.map +1 -1
  121. package/dist/utils/session.js +8 -9
  122. package/dist/utils/session.js.map +1 -1
  123. package/package.json +97 -26
  124. package/src/adapter/collections.ts +621 -0
  125. package/src/adapter/index.ts +712 -0
  126. package/src/components/BeforeLogin.tsx +39 -0
  127. package/src/components/LoginView.tsx +1516 -0
  128. package/src/components/LoginViewWrapper.tsx +35 -0
  129. package/src/components/LogoutButton.tsx +58 -0
  130. package/src/components/PasskeyRegisterButton.tsx +105 -0
  131. package/src/components/PasskeySignInButton.tsx +96 -0
  132. package/src/components/auth/ForgotPasswordView.tsx +274 -0
  133. package/src/components/auth/ResetPasswordView.tsx +331 -0
  134. package/src/components/auth/index.ts +8 -0
  135. package/src/components/management/ApiKeysManagementClient.tsx +988 -0
  136. package/src/components/management/PasskeysManagementClient.tsx +409 -0
  137. package/src/components/management/SecurityNavLinks.tsx +117 -0
  138. package/src/components/management/TwoFactorManagementClient.tsx +560 -0
  139. package/src/components/management/index.ts +20 -0
  140. package/src/components/management/views/ApiKeysView.tsx +57 -0
  141. package/src/components/management/views/PasskeysView.tsx +42 -0
  142. package/src/components/management/views/TwoFactorView.tsx +42 -0
  143. package/src/components/management/views/index.ts +10 -0
  144. package/src/components/twoFactor/TwoFactorSetupView.tsx +515 -0
  145. package/src/components/twoFactor/TwoFactorVerifyView.tsx +238 -0
  146. package/src/components/twoFactor/index.ts +8 -0
  147. package/src/exports/client.ts +77 -0
  148. package/src/exports/components.ts +30 -0
  149. package/src/exports/management.ts +25 -0
  150. package/src/exports/rsc.ts +11 -0
  151. package/src/generated-types.ts +269 -0
  152. package/src/index.ts +135 -0
  153. package/src/plugin/index.ts +834 -0
  154. package/src/scripts/generate-types.ts +269 -0
  155. package/src/types/apiKey.ts +63 -0
  156. package/src/types/betterAuth.ts +253 -0
  157. package/src/utils/access.ts +410 -0
  158. package/src/utils/apiKeyAccess.ts +443 -0
  159. package/src/utils/betterAuthDefaults.ts +102 -0
  160. package/src/utils/detectAuthConfig.ts +47 -0
  161. package/src/utils/detectEnabledPlugins.ts +69 -0
  162. package/src/utils/firstUserAdmin.ts +164 -0
  163. package/src/utils/generateScopes.ts +150 -0
  164. package/src/utils/session.ts +91 -0
@@ -18,8 +18,7 @@
18
18
  * },
19
19
  * }
20
20
  * ```
21
- */
22
- // ─────────────────────────────────────────────────────────────────────────────
21
+ */ // ─────────────────────────────────────────────────────────────────────────────
23
22
  // Role Checking Utilities
24
23
  // ─────────────────────────────────────────────────────────────────────────────
25
24
  /**
@@ -32,19 +31,17 @@
32
31
  *
33
32
  * @param role - The role value from the user object
34
33
  * @returns Array of role strings
35
- */
36
- export function normalizeRoles(role) {
34
+ */ export function normalizeRoles(role) {
37
35
  if (Array.isArray(role)) {
38
- return role.filter((r) => typeof r === 'string');
36
+ return role.filter((r)=>typeof r === 'string');
39
37
  }
40
38
  if (typeof role === 'string') {
41
39
  if (role.includes(',')) {
42
- return role
43
- .split(',')
44
- .map((r) => r.trim())
45
- .filter(Boolean);
40
+ return role.split(',').map((r)=>r.trim()).filter(Boolean);
46
41
  }
47
- return role ? [role] : [];
42
+ return role ? [
43
+ role
44
+ ] : [];
48
45
  }
49
46
  return [];
50
47
  }
@@ -61,12 +58,10 @@ export function normalizeRoles(role) {
61
58
  * hasAnyRole(user, ['admin']) // true
62
59
  * hasAnyRole(user, ['superadmin']) // false
63
60
  * ```
64
- */
65
- export function hasAnyRole(user, roles) {
66
- if (!user?.role)
67
- return false;
61
+ */ export function hasAnyRole(user, roles) {
62
+ if (!user?.role) return false;
68
63
  const userRoles = normalizeRoles(user.role);
69
- return userRoles.some((role) => roles.includes(role));
64
+ return userRoles.some((role)=>roles.includes(role));
70
65
  }
71
66
  /**
72
67
  * Check if a user has all of the specified roles.
@@ -81,12 +76,10 @@ export function hasAnyRole(user, roles) {
81
76
  * hasAllRoles(user, ['admin', 'editor']) // true
82
77
  * hasAllRoles(user, ['admin', 'superadmin']) // false
83
78
  * ```
84
- */
85
- export function hasAllRoles(user, roles) {
86
- if (!user?.role)
87
- return false;
79
+ */ export function hasAllRoles(user, roles) {
80
+ if (!user?.role) return false;
88
81
  const userRoles = normalizeRoles(user.role);
89
- return roles.every((role) => userRoles.includes(role));
82
+ return roles.every((role)=>userRoles.includes(role));
90
83
  }
91
84
  // ─────────────────────────────────────────────────────────────────────────────
92
85
  // Access Control Functions
@@ -98,10 +91,11 @@ export function hasAllRoles(user, roles) {
98
91
  *
99
92
  * @param config - Configuration with admin roles
100
93
  * @returns Access check function
101
- */
102
- export function hasAdminRoles(config = {}) {
103
- const { adminRoles = ['admin'] } = config;
104
- return ({ req }) => {
94
+ */ export function hasAdminRoles(config = {}) {
95
+ const { adminRoles = [
96
+ 'admin'
97
+ ] } = config;
98
+ return ({ req })=>{
105
99
  return hasAnyRole(req.user, adminRoles);
106
100
  };
107
101
  }
@@ -117,11 +111,12 @@ export function hasAdminRoles(config = {}) {
117
111
  * delete: isAdmin({ adminRoles: ['admin', 'superadmin'] }),
118
112
  * }
119
113
  * ```
120
- */
121
- export function isAdmin(config = {}) {
114
+ */ export function isAdmin(config = {}) {
122
115
  const checkAdmin = hasAdminRoles(config);
123
- return ({ req }) => {
124
- return checkAdmin({ req });
116
+ return ({ req })=>{
117
+ return checkAdmin({
118
+ req
119
+ });
125
120
  };
126
121
  }
127
122
  /**
@@ -142,11 +137,12 @@ export function isAdmin(config = {}) {
142
137
  * },
143
138
  * ]
144
139
  * ```
145
- */
146
- export function isAdminField(config = {}) {
140
+ */ export function isAdminField(config = {}) {
147
141
  const checkAdmin = hasAdminRoles(config);
148
- return ({ req }) => {
149
- return checkAdmin({ req });
142
+ return ({ req })=>{
143
+ return checkAdmin({
144
+ req
145
+ });
150
146
  };
151
147
  }
152
148
  /**
@@ -165,22 +161,25 @@ export function isAdminField(config = {}) {
165
161
  * update: isAdminOrSelf({ adminRoles: ['admin'] }),
166
162
  * }
167
163
  * ```
168
- */
169
- export function isAdminOrSelf(config = {}) {
170
- const { adminRoles = ['admin'], idField = 'id' } = config;
171
- const checkAdmin = hasAdminRoles({ adminRoles });
172
- return ({ req }) => {
164
+ */ export function isAdminOrSelf(config = {}) {
165
+ const { adminRoles = [
166
+ 'admin'
167
+ ], idField = 'id' } = config;
168
+ const checkAdmin = hasAdminRoles({
169
+ adminRoles
170
+ });
171
+ return ({ req })=>{
173
172
  // Admins can access everything
174
- if (checkAdmin({ req }))
175
- return true;
173
+ if (checkAdmin({
174
+ req
175
+ })) return true;
176
176
  // Non-authenticated users have no access
177
- if (!req.user)
178
- return false;
177
+ if (!req.user) return false;
179
178
  // Restrict to own record
180
179
  return {
181
180
  [idField]: {
182
- equals: req.user.id,
183
- },
181
+ equals: req.user.id
182
+ }
184
183
  };
185
184
  };
186
185
  }
@@ -206,51 +205,53 @@ export function isAdminOrSelf(config = {}) {
206
205
  * }),
207
206
  * }
208
207
  * ```
209
- */
210
- export function canUpdateOwnFields(config = {}) {
211
- const { adminRoles = ['admin'], allowedFields = ['name'], idField = 'id', userSlug = 'users', } = config;
212
- const checkAdmin = hasAdminRoles({ adminRoles });
213
- return async ({ req, id, data }) => {
208
+ */ export function canUpdateOwnFields(config = {}) {
209
+ const { adminRoles = [
210
+ 'admin'
211
+ ], allowedFields = [
212
+ 'name'
213
+ ], idField = 'id', userSlug = 'users' } = config;
214
+ const checkAdmin = hasAdminRoles({
215
+ adminRoles
216
+ });
217
+ return async ({ req, id, data })=>{
214
218
  // Admins can update everything
215
- if (checkAdmin({ req }))
216
- return true;
219
+ if (checkAdmin({
220
+ req
221
+ })) return true;
217
222
  // Must be authenticated
218
- if (!req.user)
219
- return false;
223
+ if (!req.user) return false;
220
224
  // Must be updating own record
221
225
  const userId = req.user[idField];
222
- if (userId !== id || !data)
223
- return false;
226
+ if (userId !== id || !data) return false;
224
227
  const dataKeys = Object.keys(data);
225
- const effectiveAllowed = [...allowedFields];
228
+ const effectiveAllowed = [
229
+ ...allowedFields
230
+ ];
226
231
  // Handle password changes specially
227
232
  const hasCurrentPassword = dataKeys.includes('currentPassword');
228
233
  const hasPassword = dataKeys.includes('password');
229
234
  if (hasPassword || hasCurrentPassword) {
230
235
  // Both must be provided for password change
231
- if (!(hasCurrentPassword && hasPassword))
232
- return false;
236
+ if (!(hasCurrentPassword && hasPassword)) return false;
233
237
  try {
234
238
  // Verify current password
235
- if (!req.user.email)
236
- return false;
239
+ if (!req.user.email) return false;
237
240
  const result = await req.payload.login({
238
241
  collection: userSlug,
239
242
  data: {
240
243
  email: req.user.email,
241
- password: data.currentPassword,
242
- },
244
+ password: data.currentPassword
245
+ }
243
246
  });
244
- if (!result)
245
- return false;
247
+ if (!result) return false;
246
248
  effectiveAllowed.push('password', 'currentPassword');
247
- }
248
- catch {
249
+ } catch {
249
250
  return false;
250
251
  }
251
252
  }
252
253
  // Check all fields are allowed
253
- const hasDisallowed = dataKeys.some((key) => !effectiveAllowed.includes(key));
254
+ const hasDisallowed = dataKeys.some((key)=>!effectiveAllowed.includes(key));
254
255
  return !hasDisallowed;
255
256
  };
256
257
  }
@@ -268,9 +269,8 @@ export function canUpdateOwnFields(config = {}) {
268
269
  * read: isAuthenticated(),
269
270
  * }
270
271
  * ```
271
- */
272
- export function isAuthenticated() {
273
- return ({ req }) => {
272
+ */ export function isAuthenticated() {
273
+ return ({ req })=>{
274
274
  return !!req.user;
275
275
  };
276
276
  }
@@ -278,9 +278,8 @@ export function isAuthenticated() {
278
278
  * Field access control: Allow any authenticated user.
279
279
  *
280
280
  * @returns Payload field access function
281
- */
282
- export function isAuthenticatedField() {
283
- return ({ req }) => {
281
+ */ export function isAuthenticatedField() {
282
+ return ({ req })=>{
284
283
  return !!req.user;
285
284
  };
286
285
  }
@@ -300,9 +299,8 @@ export function isAuthenticatedField() {
300
299
  * update: hasRole(['admin', 'editor']),
301
300
  * }
302
301
  * ```
303
- */
304
- export function hasRole(roles) {
305
- return ({ req }) => {
302
+ */ export function hasRole(roles) {
303
+ return ({ req })=>{
306
304
  return hasAnyRole(req.user, roles);
307
305
  };
308
306
  }
@@ -311,9 +309,8 @@ export function hasRole(roles) {
311
309
  *
312
310
  * @param roles - Roles that have access
313
311
  * @returns Payload field access function
314
- */
315
- export function hasRoleField(roles) {
316
- return ({ req }) => {
312
+ */ export function hasRoleField(roles) {
313
+ return ({ req })=>{
317
314
  return hasAnyRole(req.user, roles);
318
315
  };
319
316
  }
@@ -329,10 +326,10 @@ export function hasRoleField(roles) {
329
326
  * delete: requireAllRoles(['admin', 'verified']),
330
327
  * }
331
328
  * ```
332
- */
333
- export function requireAllRoles(roles) {
334
- return ({ req }) => {
329
+ */ export function requireAllRoles(roles) {
330
+ return ({ req })=>{
335
331
  return hasAllRoles(req.user, roles);
336
332
  };
337
333
  }
334
+
338
335
  //# sourceMappingURL=access.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"access.js","sourceRoot":"","sources":["../../src/utils/access.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/utils/access.ts"],"sourcesContent":["/**\n * Access control utilities for Payload collections.\n *\n * These helpers simplify common access control patterns when using\n * Better Auth with Payload CMS. They handle role checking, self-access\n * patterns, and field-level permissions.\n *\n * @example\n * ```ts\n * import { isAdmin, isAdminOrSelf } from '@delmaredigital/payload-better-auth'\n *\n * export const Users: CollectionConfig = {\n * slug: 'users',\n * access: {\n * read: isAdminOrSelf({ adminRoles: ['admin', 'editor'] }),\n * update: isAdminOrSelf({ adminRoles: ['admin'] }),\n * delete: isAdmin({ adminRoles: ['admin'] }),\n * },\n * }\n * ```\n */\n\nimport type { Access, FieldAccess, PayloadRequest } from 'payload'\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type RoleCheckConfig = {\n /**\n * Roles considered admin roles.\n * @default ['admin']\n */\n adminRoles?: string[]\n}\n\nexport type SelfAccessConfig = RoleCheckConfig & {\n /**\n * The field to use for user ID comparison.\n * @default 'id'\n */\n idField?: string\n}\n\nexport type FieldUpdateConfig = SelfAccessConfig & {\n /**\n * Fields the user is allowed to update on their own record.\n * Password is handled specially and requires currentPassword.\n * @default ['name']\n */\n allowedFields?: string[]\n /**\n * The user collection slug for password verification.\n */\n userSlug?: string\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Role Checking Utilities\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Normalize a user's role to an array.\n *\n * Handles various role formats:\n * - Array of roles\n * - Comma-separated string\n * - Single role string\n *\n * @param role - The role value from the user object\n * @returns Array of role strings\n */\nexport function normalizeRoles(role: unknown): string[] {\n if (Array.isArray(role)) {\n return role.filter((r): r is string => typeof r === 'string')\n }\n\n if (typeof role === 'string') {\n if (role.includes(',')) {\n return role\n .split(',')\n .map((r) => r.trim())\n .filter(Boolean)\n }\n return role ? [role] : []\n }\n\n return []\n}\n\n/**\n * Check if a user has any of the specified roles.\n *\n * @param user - The user object\n * @param roles - Roles to check for\n * @returns True if user has at least one matching role\n *\n * @example\n * ```ts\n * const user = { role: ['admin', 'editor'] }\n * hasAnyRole(user, ['admin']) // true\n * hasAnyRole(user, ['superadmin']) // false\n * ```\n */\nexport function hasAnyRole(\n user: { role?: unknown } | null | undefined,\n roles: string[]\n): boolean {\n if (!user?.role) return false\n const userRoles = normalizeRoles(user.role)\n return userRoles.some((role) => roles.includes(role))\n}\n\n/**\n * Check if a user has all of the specified roles.\n *\n * @param user - The user object\n * @param roles - Roles to check for\n * @returns True if user has all matching roles\n *\n * @example\n * ```ts\n * const user = { role: ['admin', 'editor'] }\n * hasAllRoles(user, ['admin', 'editor']) // true\n * hasAllRoles(user, ['admin', 'superadmin']) // false\n * ```\n */\nexport function hasAllRoles(\n user: { role?: unknown } | null | undefined,\n roles: string[]\n): boolean {\n if (!user?.role) return false\n const userRoles = normalizeRoles(user.role)\n return roles.every((role) => userRoles.includes(role))\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Access Control Functions\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Check if the current request user has admin roles.\n *\n * Use this as a reusable check within access functions.\n *\n * @param config - Configuration with admin roles\n * @returns Access check function\n */\nexport function hasAdminRoles(\n config: RoleCheckConfig = {}\n): (args: { req: PayloadRequest }) => boolean {\n const { adminRoles = ['admin'] } = config\n\n return ({ req }) => {\n return hasAnyRole(req.user as { role?: unknown } | null, adminRoles)\n }\n}\n\n/**\n * Access control: Only allow users with admin roles.\n *\n * @param config - Configuration with admin roles\n * @returns Payload access function\n *\n * @example\n * ```ts\n * access: {\n * delete: isAdmin({ adminRoles: ['admin', 'superadmin'] }),\n * }\n * ```\n */\nexport function isAdmin(config: RoleCheckConfig = {}): Access {\n const checkAdmin = hasAdminRoles(config)\n\n return ({ req }) => {\n return checkAdmin({ req })\n }\n}\n\n/**\n * Field access control: Only allow users with admin roles.\n *\n * @param config - Configuration with admin roles\n * @returns Payload field access function\n *\n * @example\n * ```ts\n * fields: [\n * {\n * name: 'role',\n * type: 'select',\n * access: {\n * update: isAdminField({ adminRoles: ['admin'] }),\n * },\n * },\n * ]\n * ```\n */\nexport function isAdminField(config: RoleCheckConfig = {}): FieldAccess {\n const checkAdmin = hasAdminRoles(config)\n\n return ({ req }) => {\n return checkAdmin({ req })\n }\n}\n\n/**\n * Access control: Allow admin OR the user accessing their own record.\n *\n * Returns a query constraint for non-admin users to limit access\n * to their own records only.\n *\n * @param config - Configuration with admin roles and ID field\n * @returns Payload access function\n *\n * @example\n * ```ts\n * access: {\n * read: isAdminOrSelf({ adminRoles: ['admin'] }),\n * update: isAdminOrSelf({ adminRoles: ['admin'] }),\n * }\n * ```\n */\nexport function isAdminOrSelf(config: SelfAccessConfig = {}): Access {\n const { adminRoles = ['admin'], idField = 'id' } = config\n const checkAdmin = hasAdminRoles({ adminRoles })\n\n return ({ req }) => {\n // Admins can access everything\n if (checkAdmin({ req })) return true\n\n // Non-authenticated users have no access\n if (!req.user) return false\n\n // Restrict to own record\n return {\n [idField]: {\n equals: req.user.id,\n },\n }\n }\n}\n\n/**\n * Access control: Allow admin OR user updating allowed fields on own record.\n *\n * This is useful for allowing users to update specific fields (like name)\n * on their own profile while preventing them from changing sensitive fields\n * like role.\n *\n * Password changes require `currentPassword` to be provided and validated.\n *\n * @param config - Configuration with admin roles, allowed fields, and user slug\n * @returns Payload access function\n *\n * @example\n * ```ts\n * access: {\n * update: canUpdateOwnFields({\n * adminRoles: ['admin'],\n * allowedFields: ['name', 'image'],\n * userSlug: 'users',\n * }),\n * }\n * ```\n */\nexport function canUpdateOwnFields(config: FieldUpdateConfig = {}): Access {\n const {\n adminRoles = ['admin'],\n allowedFields = ['name'],\n idField = 'id',\n userSlug = 'users',\n } = config\n const checkAdmin = hasAdminRoles({ adminRoles })\n\n return async ({ req, id, data }) => {\n // Admins can update everything\n if (checkAdmin({ req })) return true\n\n // Must be authenticated\n if (!req.user) return false\n\n // Must be updating own record\n const userId = req.user[idField]\n if (userId !== id || !data) return false\n\n const dataKeys = Object.keys(data)\n const effectiveAllowed = [...allowedFields]\n\n // Handle password changes specially\n const hasCurrentPassword = dataKeys.includes('currentPassword')\n const hasPassword = dataKeys.includes('password')\n\n if (hasPassword || hasCurrentPassword) {\n // Both must be provided for password change\n if (!(hasCurrentPassword && hasPassword)) return false\n\n try {\n // Verify current password\n if (!req.user.email) return false\n\n const result = await req.payload.login({\n collection: userSlug,\n data: {\n email: req.user.email as string,\n password: data.currentPassword as string,\n },\n })\n\n if (!result) return false\n\n effectiveAllowed.push('password', 'currentPassword')\n } catch {\n return false\n }\n }\n\n // Check all fields are allowed\n const hasDisallowed = dataKeys.some((key) => !effectiveAllowed.includes(key))\n return !hasDisallowed\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Authenticated Access\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Access control: Allow any authenticated user.\n *\n * @returns Payload access function\n *\n * @example\n * ```ts\n * access: {\n * read: isAuthenticated(),\n * }\n * ```\n */\nexport function isAuthenticated(): Access {\n return ({ req }) => {\n return !!req.user\n }\n}\n\n/**\n * Field access control: Allow any authenticated user.\n *\n * @returns Payload field access function\n */\nexport function isAuthenticatedField(): FieldAccess {\n return ({ req }) => {\n return !!req.user\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Role-Based Access\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Access control: Allow users with any of the specified roles.\n *\n * @param roles - Roles that have access\n * @returns Payload access function\n *\n * @example\n * ```ts\n * access: {\n * read: hasRole(['admin', 'editor', 'viewer']),\n * update: hasRole(['admin', 'editor']),\n * }\n * ```\n */\nexport function hasRole(roles: string[]): Access {\n return ({ req }) => {\n return hasAnyRole(req.user as { role?: unknown } | null, roles)\n }\n}\n\n/**\n * Field access control: Allow users with any of the specified roles.\n *\n * @param roles - Roles that have access\n * @returns Payload field access function\n */\nexport function hasRoleField(roles: string[]): FieldAccess {\n return ({ req }) => {\n return hasAnyRole(req.user as { role?: unknown } | null, roles)\n }\n}\n\n/**\n * Access control: Allow users with all of the specified roles.\n *\n * @param roles - All roles required for access\n * @returns Payload access function\n *\n * @example\n * ```ts\n * access: {\n * delete: requireAllRoles(['admin', 'verified']),\n * }\n * ```\n */\nexport function requireAllRoles(roles: string[]): Access {\n return ({ req }) => {\n return hasAllRoles(req.user as { role?: unknown } | null, roles)\n }\n}\n"],"names":["normalizeRoles","role","Array","isArray","filter","r","includes","split","map","trim","Boolean","hasAnyRole","user","roles","userRoles","some","hasAllRoles","every","hasAdminRoles","config","adminRoles","req","isAdmin","checkAdmin","isAdminField","isAdminOrSelf","idField","equals","id","canUpdateOwnFields","allowedFields","userSlug","data","userId","dataKeys","Object","keys","effectiveAllowed","hasCurrentPassword","hasPassword","email","result","payload","login","collection","password","currentPassword","push","hasDisallowed","key","isAuthenticated","isAuthenticatedField","hasRole","hasRoleField","requireAllRoles"],"mappings":"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"}
@@ -19,18 +19,15 @@
19
19
  * },
20
20
  * }
21
21
  * ```
22
- */
23
- // ─────────────────────────────────────────────────────────────────────────────
22
+ */ // ─────────────────────────────────────────────────────────────────────────────
24
23
  // Helpers
25
24
  // ─────────────────────────────────────────────────────────────────────────────
26
25
  /**
27
26
  * Extract API key from request headers.
28
27
  * Supports Bearer token format: Authorization: Bearer <api-key>
29
- */
30
- export function extractApiKeyFromRequest(req) {
28
+ */ export function extractApiKeyFromRequest(req) {
31
29
  const authHeader = req.headers?.get('authorization');
32
- if (!authHeader)
33
- return null;
30
+ if (!authHeader) return null;
34
31
  // Support "Bearer <key>" format
35
32
  if (authHeader.startsWith('Bearer ')) {
36
33
  return authHeader.slice(7).trim();
@@ -41,31 +38,38 @@ export function extractApiKeyFromRequest(req) {
41
38
  /**
42
39
  * Look up API key info from the database.
43
40
  * Returns null if key not found or disabled.
44
- */
45
- export async function getApiKeyInfo(req, apiKey, apiKeysCollection = 'apiKeys') {
41
+ */ export async function getApiKeyInfo(req, apiKey, apiKeysCollection = 'apiKeys') {
46
42
  try {
47
43
  // Try the provided collection name first
48
44
  let results = await req.payload.find({
49
45
  collection: apiKeysCollection,
50
46
  where: {
51
- key: { equals: apiKey },
52
- enabled: { not_equals: false },
47
+ key: {
48
+ equals: apiKey
49
+ },
50
+ enabled: {
51
+ not_equals: false
52
+ }
53
53
  },
54
54
  limit: 1,
55
- depth: 0,
56
- }).catch(() => null);
55
+ depth: 0
56
+ }).catch(()=>null);
57
57
  // If not found, try alternative slug
58
58
  if (!results || results.docs.length === 0) {
59
59
  const altSlug = apiKeysCollection === 'apiKeys' ? 'api-keys' : 'apiKeys';
60
60
  results = await req.payload.find({
61
61
  collection: altSlug,
62
62
  where: {
63
- key: { equals: apiKey },
64
- enabled: { not_equals: false },
63
+ key: {
64
+ equals: apiKey
65
+ },
66
+ enabled: {
67
+ not_equals: false
68
+ }
65
69
  },
66
70
  limit: 1,
67
- depth: 0,
68
- }).catch(() => null);
71
+ depth: 0
72
+ }).catch(()=>null);
69
73
  }
70
74
  if (!results || results.docs.length === 0) {
71
75
  return null;
@@ -78,29 +82,24 @@ export async function getApiKeyInfo(req, apiKey, apiKeysCollection = 'apiKeys')
78
82
  const parsed = JSON.parse(doc.permissions);
79
83
  if (Array.isArray(parsed)) {
80
84
  scopes = parsed;
81
- }
82
- else if (typeof parsed === 'object') {
85
+ } else if (typeof parsed === 'object') {
83
86
  // If it's an object, extract keys or flatten
84
87
  scopes = Object.keys(parsed);
85
88
  }
86
- }
87
- catch {
89
+ } catch {
88
90
  // If not JSON, treat as comma-separated
89
- scopes = doc.permissions.split(',').map((s) => s.trim()).filter(Boolean);
91
+ scopes = doc.permissions.split(',').map((s)=>s.trim()).filter(Boolean);
90
92
  }
91
- }
92
- else if (Array.isArray(doc.scopes)) {
93
+ } else if (Array.isArray(doc.scopes)) {
93
94
  scopes = doc.scopes;
94
95
  }
95
96
  // Get user ID (handle both direct field and relationship)
96
97
  let userId;
97
98
  if (doc.userId) {
98
99
  userId = String(doc.userId);
99
- }
100
- else if (doc.user) {
100
+ } else if (doc.user) {
101
101
  userId = typeof doc.user === 'object' ? String(doc.user.id) : String(doc.user);
102
- }
103
- else {
102
+ } else {
104
103
  return null;
105
104
  }
106
105
  // Parse metadata
@@ -109,12 +108,10 @@ export async function getApiKeyInfo(req, apiKey, apiKeysCollection = 'apiKeys')
109
108
  if (typeof doc.metadata === 'string') {
110
109
  try {
111
110
  metadata = JSON.parse(doc.metadata);
111
+ } catch {
112
+ // Ignore parse errors
112
113
  }
113
- catch {
114
- // Ignore parse errors
115
- }
116
- }
117
- else {
114
+ } else {
118
115
  metadata = doc.metadata;
119
116
  }
120
117
  }
@@ -123,44 +120,39 @@ export async function getApiKeyInfo(req, apiKey, apiKeysCollection = 'apiKeys')
123
120
  userId,
124
121
  scopes,
125
122
  keyPrefix: doc.start,
126
- metadata,
123
+ metadata
127
124
  };
128
- }
129
- catch {
125
+ } catch {
130
126
  return null;
131
127
  }
132
128
  }
133
129
  /**
134
130
  * Check if an API key has a specific scope.
135
131
  * Supports wildcard patterns like 'posts:*' matching 'posts:read', 'posts:write', etc.
136
- */
137
- export function hasScope(keyScopes, requiredScope) {
138
- return keyScopes.some((scope) => {
132
+ */ export function hasScope(keyScopes, requiredScope) {
133
+ return keyScopes.some((scope)=>{
139
134
  // Exact match
140
- if (scope === requiredScope)
141
- return true;
135
+ if (scope === requiredScope) return true;
142
136
  // Wildcard match: 'posts:*' matches 'posts:read'
143
137
  if (scope.endsWith(':*')) {
144
- const prefix = scope.slice(0, -1); // Remove '*', keep ':'
138
+ const prefix = scope.slice(0, -1) // Remove '*', keep ':'
139
+ ;
145
140
  return requiredScope.startsWith(prefix);
146
141
  }
147
142
  // Global wildcard
148
- if (scope === '*')
149
- return true;
143
+ if (scope === '*') return true;
150
144
  return false;
151
145
  });
152
146
  }
153
147
  /**
154
148
  * Check if an API key has any of the specified scopes.
155
- */
156
- export function hasAnyScope(keyScopes, requiredScopes) {
157
- return requiredScopes.some((scope) => hasScope(keyScopes, scope));
149
+ */ export function hasAnyScope(keyScopes, requiredScopes) {
150
+ return requiredScopes.some((scope)=>hasScope(keyScopes, scope));
158
151
  }
159
152
  /**
160
153
  * Check if an API key has all of the specified scopes.
161
- */
162
- export function hasAllScopes(keyScopes, requiredScopes) {
163
- return requiredScopes.every((scope) => hasScope(keyScopes, scope));
154
+ */ export function hasAllScopes(keyScopes, requiredScopes) {
155
+ return requiredScopes.every((scope)=>hasScope(keyScopes, scope));
164
156
  }
165
157
  // ─────────────────────────────────────────────────────────────────────────────
166
158
  // Access Control Functions
@@ -179,15 +171,15 @@ export function hasAllScopes(keyScopes, requiredScopes) {
179
171
  * create: requireScope('posts:write'),
180
172
  * }
181
173
  * ```
182
- */
183
- export function requireScope(scope, config = {}) {
184
- const { apiKeysCollection = 'apiKeys', allowAuthenticatedUsers = false, extractApiKey = extractApiKeyFromRequest, } = config;
185
- return async ({ req }) => {
174
+ */ export function requireScope(scope, config = {}) {
175
+ const { apiKeysCollection = 'apiKeys', allowAuthenticatedUsers = false, extractApiKey = extractApiKeyFromRequest } = config;
176
+ return async ({ req })=>{
186
177
  // If authenticated users are allowed and user is logged in without API key
187
178
  if (allowAuthenticatedUsers && req.user) {
188
179
  const apiKey = extractApiKey(req);
189
180
  if (!apiKey) {
190
- return true; // User authenticated via session, no API key = allow
181
+ return true // User authenticated via session, no API key = allow
182
+ ;
191
183
  }
192
184
  }
193
185
  // Extract API key from request
@@ -217,10 +209,9 @@ export function requireScope(scope, config = {}) {
217
209
  * read: requireAnyScope(['posts:read', 'content:read', 'admin:*']),
218
210
  * }
219
211
  * ```
220
- */
221
- export function requireAnyScope(scopes, config = {}) {
222
- const { apiKeysCollection = 'apiKeys', allowAuthenticatedUsers = false, extractApiKey = extractApiKeyFromRequest, } = config;
223
- return async ({ req }) => {
212
+ */ export function requireAnyScope(scopes, config = {}) {
213
+ const { apiKeysCollection = 'apiKeys', allowAuthenticatedUsers = false, extractApiKey = extractApiKeyFromRequest } = config;
214
+ return async ({ req })=>{
224
215
  // If authenticated users are allowed and user is logged in without API key
225
216
  if (allowAuthenticatedUsers && req.user) {
226
217
  const apiKey = extractApiKey(req);
@@ -252,10 +243,9 @@ export function requireAnyScope(scopes, config = {}) {
252
243
  * delete: requireAllScopes(['posts:delete', 'admin:write']),
253
244
  * }
254
245
  * ```
255
- */
256
- export function requireAllScopes(scopes, config = {}) {
257
- const { apiKeysCollection = 'apiKeys', allowAuthenticatedUsers = false, extractApiKey = extractApiKeyFromRequest, } = config;
258
- return async ({ req }) => {
246
+ */ export function requireAllScopes(scopes, config = {}) {
247
+ const { apiKeysCollection = 'apiKeys', allowAuthenticatedUsers = false, extractApiKey = extractApiKeyFromRequest } = config;
248
+ return async ({ req })=>{
259
249
  // If authenticated users are allowed and user is logged in without API key
260
250
  if (allowAuthenticatedUsers && req.user) {
261
251
  const apiKey = extractApiKey(req);
@@ -291,9 +281,11 @@ export function requireAllScopes(scopes, config = {}) {
291
281
  * read: allowSessionOrScope('posts:read'),
292
282
  * }
293
283
  * ```
294
- */
295
- export function allowSessionOrScope(scope, config = {}) {
296
- return requireScope(scope, { ...config, allowAuthenticatedUsers: true });
284
+ */ export function allowSessionOrScope(scope, config = {}) {
285
+ return requireScope(scope, {
286
+ ...config,
287
+ allowAuthenticatedUsers: true
288
+ });
297
289
  }
298
290
  /**
299
291
  * Create an access control function that allows either:
@@ -303,9 +295,11 @@ export function allowSessionOrScope(scope, config = {}) {
303
295
  * @param scopes - Array of acceptable scopes for API key access
304
296
  * @param config - Configuration options
305
297
  * @returns Payload access function
306
- */
307
- export function allowSessionOrAnyScope(scopes, config = {}) {
308
- return requireAnyScope(scopes, { ...config, allowAuthenticatedUsers: true });
298
+ */ export function allowSessionOrAnyScope(scopes, config = {}) {
299
+ return requireAnyScope(scopes, {
300
+ ...config,
301
+ allowAuthenticatedUsers: true
302
+ });
309
303
  }
310
304
  // ─────────────────────────────────────────────────────────────────────────────
311
305
  // Better Auth Integration
@@ -328,11 +322,10 @@ export function allowSessionOrAnyScope(scopes, config = {}) {
328
322
  * console.log('Scopes:', keyInfo.scopes)
329
323
  * }
330
324
  * ```
331
- */
332
- export async function validateApiKey(req, apiKeysCollection = 'apiKeys') {
325
+ */ export async function validateApiKey(req, apiKeysCollection = 'apiKeys') {
333
326
  const apiKey = extractApiKeyFromRequest(req);
334
- if (!apiKey)
335
- return null;
327
+ if (!apiKey) return null;
336
328
  return getApiKeyInfo(req, apiKey, apiKeysCollection);
337
329
  }
330
+
338
331
  //# sourceMappingURL=apiKeyAccess.js.map