@delmaredigital/payload-better-auth 0.3.8 → 0.3.10
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.
- package/dist/adapter/collections.d.ts +0 -1
- package/dist/adapter/collections.js +0 -2
- package/dist/adapter/index.d.ts +0 -1
- package/dist/adapter/index.js +0 -2
- package/dist/components/BeforeLogin.d.ts +0 -1
- package/dist/components/BeforeLogin.js +0 -2
- package/dist/components/LoginView.d.ts +0 -1
- package/dist/components/LoginView.js +0 -2
- package/dist/components/LoginViewWrapper.d.ts +0 -1
- package/dist/components/LoginViewWrapper.js +0 -2
- package/dist/components/LogoutButton.d.ts +0 -1
- package/dist/components/LogoutButton.js +0 -2
- package/dist/components/PasskeyRegisterButton.d.ts +0 -1
- package/dist/components/PasskeyRegisterButton.js +0 -2
- package/dist/components/PasskeySignInButton.d.ts +0 -1
- package/dist/components/PasskeySignInButton.js +0 -2
- package/dist/components/auth/ForgotPasswordView.d.ts +0 -1
- package/dist/components/auth/ForgotPasswordView.js +0 -2
- package/dist/components/auth/ResetPasswordView.d.ts +0 -1
- package/dist/components/auth/ResetPasswordView.js +0 -2
- package/dist/components/auth/index.d.ts +0 -1
- package/dist/components/auth/index.js +0 -2
- package/dist/components/management/ApiKeysManagementClient.d.ts +0 -1
- package/dist/components/management/ApiKeysManagementClient.js +0 -2
- package/dist/components/management/PasskeysManagementClient.d.ts +0 -1
- package/dist/components/management/PasskeysManagementClient.js +0 -2
- package/dist/components/management/SecurityNavLinks.d.ts +0 -1
- package/dist/components/management/SecurityNavLinks.js +0 -2
- package/dist/components/management/TwoFactorManagementClient.d.ts +0 -1
- package/dist/components/management/TwoFactorManagementClient.js +0 -2
- package/dist/components/management/index.d.ts +0 -1
- package/dist/components/management/index.js +0 -2
- package/dist/components/management/views/ApiKeysView.d.ts +0 -1
- package/dist/components/management/views/ApiKeysView.js +0 -2
- package/dist/components/management/views/PasskeysView.d.ts +0 -1
- package/dist/components/management/views/PasskeysView.js +0 -2
- package/dist/components/management/views/TwoFactorView.d.ts +0 -1
- package/dist/components/management/views/TwoFactorView.js +0 -2
- package/dist/components/management/views/index.d.ts +0 -1
- package/dist/components/management/views/index.js +0 -2
- package/dist/components/twoFactor/TwoFactorSetupView.d.ts +0 -1
- package/dist/components/twoFactor/TwoFactorSetupView.js +0 -2
- package/dist/components/twoFactor/TwoFactorVerifyView.d.ts +0 -1
- package/dist/components/twoFactor/TwoFactorVerifyView.js +0 -2
- package/dist/components/twoFactor/index.d.ts +0 -1
- package/dist/components/twoFactor/index.js +0 -2
- package/dist/exports/client.d.ts +0 -1
- package/dist/exports/client.js +0 -2
- package/dist/exports/components.d.ts +0 -1
- package/dist/exports/components.js +0 -2
- package/dist/exports/management.d.ts +0 -1
- package/dist/exports/management.js +0 -2
- package/dist/exports/rsc.d.ts +0 -1
- package/dist/exports/rsc.js +0 -2
- package/dist/generated-types.d.ts +0 -1
- package/dist/generated-types.js +0 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -2
- package/dist/plugin/index.d.ts +0 -1
- package/dist/plugin/index.js +0 -2
- package/dist/scripts/generate-types.d.ts +0 -1
- package/dist/scripts/generate-types.js +0 -2
- package/dist/types/apiKey.d.ts +0 -1
- package/dist/types/apiKey.js +0 -2
- package/dist/types/betterAuth.d.ts +0 -1
- package/dist/types/betterAuth.js +0 -2
- package/dist/utils/access.d.ts +0 -1
- package/dist/utils/access.js +0 -2
- package/dist/utils/apiKeyAccess.d.ts +0 -1
- package/dist/utils/apiKeyAccess.js +0 -2
- package/dist/utils/betterAuthDefaults.d.ts +0 -1
- package/dist/utils/betterAuthDefaults.js +0 -2
- package/dist/utils/detectAuthConfig.d.ts +0 -1
- package/dist/utils/detectAuthConfig.js +0 -2
- package/dist/utils/detectEnabledPlugins.d.ts +0 -1
- package/dist/utils/detectEnabledPlugins.js +0 -2
- package/dist/utils/firstUserAdmin.d.ts +0 -1
- package/dist/utils/firstUserAdmin.js +0 -2
- package/dist/utils/generateScopes.d.ts +0 -1
- package/dist/utils/generateScopes.js +0 -2
- package/dist/utils/session.d.ts +0 -1
- package/dist/utils/session.js +0 -2
- package/package.json +34 -91
- package/dist/adapter/collections.d.ts.map +0 -1
- package/dist/adapter/collections.js.map +0 -1
- package/dist/adapter/index.d.ts.map +0 -1
- package/dist/adapter/index.js.map +0 -1
- package/dist/components/BeforeLogin.d.ts.map +0 -1
- package/dist/components/BeforeLogin.js.map +0 -1
- package/dist/components/LoginView.d.ts.map +0 -1
- package/dist/components/LoginView.js.map +0 -1
- package/dist/components/LoginViewWrapper.d.ts.map +0 -1
- package/dist/components/LoginViewWrapper.js.map +0 -1
- package/dist/components/LogoutButton.d.ts.map +0 -1
- package/dist/components/LogoutButton.js.map +0 -1
- package/dist/components/PasskeyRegisterButton.d.ts.map +0 -1
- package/dist/components/PasskeyRegisterButton.js.map +0 -1
- package/dist/components/PasskeySignInButton.d.ts.map +0 -1
- package/dist/components/PasskeySignInButton.js.map +0 -1
- package/dist/components/auth/ForgotPasswordView.d.ts.map +0 -1
- package/dist/components/auth/ForgotPasswordView.js.map +0 -1
- package/dist/components/auth/ResetPasswordView.d.ts.map +0 -1
- package/dist/components/auth/ResetPasswordView.js.map +0 -1
- package/dist/components/auth/index.d.ts.map +0 -1
- package/dist/components/auth/index.js.map +0 -1
- package/dist/components/management/ApiKeysManagementClient.d.ts.map +0 -1
- package/dist/components/management/ApiKeysManagementClient.js.map +0 -1
- package/dist/components/management/PasskeysManagementClient.d.ts.map +0 -1
- package/dist/components/management/PasskeysManagementClient.js.map +0 -1
- package/dist/components/management/SecurityNavLinks.d.ts.map +0 -1
- package/dist/components/management/SecurityNavLinks.js.map +0 -1
- package/dist/components/management/TwoFactorManagementClient.d.ts.map +0 -1
- package/dist/components/management/TwoFactorManagementClient.js.map +0 -1
- package/dist/components/management/index.d.ts.map +0 -1
- package/dist/components/management/index.js.map +0 -1
- package/dist/components/management/views/ApiKeysView.d.ts.map +0 -1
- package/dist/components/management/views/ApiKeysView.js.map +0 -1
- package/dist/components/management/views/PasskeysView.d.ts.map +0 -1
- package/dist/components/management/views/PasskeysView.js.map +0 -1
- package/dist/components/management/views/TwoFactorView.d.ts.map +0 -1
- package/dist/components/management/views/TwoFactorView.js.map +0 -1
- package/dist/components/management/views/index.d.ts.map +0 -1
- package/dist/components/management/views/index.js.map +0 -1
- package/dist/components/twoFactor/TwoFactorSetupView.d.ts.map +0 -1
- package/dist/components/twoFactor/TwoFactorSetupView.js.map +0 -1
- package/dist/components/twoFactor/TwoFactorVerifyView.d.ts.map +0 -1
- package/dist/components/twoFactor/TwoFactorVerifyView.js.map +0 -1
- package/dist/components/twoFactor/index.d.ts.map +0 -1
- package/dist/components/twoFactor/index.js.map +0 -1
- package/dist/exports/client.d.ts.map +0 -1
- package/dist/exports/client.js.map +0 -1
- package/dist/exports/components.d.ts.map +0 -1
- package/dist/exports/components.js.map +0 -1
- package/dist/exports/management.d.ts.map +0 -1
- package/dist/exports/management.js.map +0 -1
- package/dist/exports/rsc.d.ts.map +0 -1
- package/dist/exports/rsc.js.map +0 -1
- package/dist/generated-types.d.ts.map +0 -1
- package/dist/generated-types.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/plugin/index.d.ts.map +0 -1
- package/dist/plugin/index.js.map +0 -1
- package/dist/scripts/generate-types.d.ts.map +0 -1
- package/dist/scripts/generate-types.js.map +0 -1
- package/dist/types/apiKey.d.ts.map +0 -1
- package/dist/types/apiKey.js.map +0 -1
- package/dist/types/betterAuth.d.ts.map +0 -1
- package/dist/types/betterAuth.js.map +0 -1
- package/dist/utils/access.d.ts.map +0 -1
- package/dist/utils/access.js.map +0 -1
- package/dist/utils/apiKeyAccess.d.ts.map +0 -1
- package/dist/utils/apiKeyAccess.js.map +0 -1
- package/dist/utils/betterAuthDefaults.d.ts.map +0 -1
- package/dist/utils/betterAuthDefaults.js.map +0 -1
- package/dist/utils/detectAuthConfig.d.ts.map +0 -1
- package/dist/utils/detectAuthConfig.js.map +0 -1
- package/dist/utils/detectEnabledPlugins.d.ts.map +0 -1
- package/dist/utils/detectEnabledPlugins.js.map +0 -1
- package/dist/utils/firstUserAdmin.d.ts.map +0 -1
- package/dist/utils/firstUserAdmin.js.map +0 -1
- package/dist/utils/generateScopes.d.ts.map +0 -1
- package/dist/utils/generateScopes.js.map +0 -1
- package/dist/utils/session.d.ts.map +0 -1
- package/dist/utils/session.js.map +0 -1
- package/src/adapter/collections.ts +0 -621
- package/src/adapter/index.ts +0 -712
- package/src/components/BeforeLogin.tsx +0 -39
- package/src/components/LoginView.tsx +0 -1516
- package/src/components/LoginViewWrapper.tsx +0 -35
- package/src/components/LogoutButton.tsx +0 -58
- package/src/components/PasskeyRegisterButton.tsx +0 -105
- package/src/components/PasskeySignInButton.tsx +0 -96
- package/src/components/auth/ForgotPasswordView.tsx +0 -274
- package/src/components/auth/ResetPasswordView.tsx +0 -331
- package/src/components/auth/index.ts +0 -8
- package/src/components/management/ApiKeysManagementClient.tsx +0 -988
- package/src/components/management/PasskeysManagementClient.tsx +0 -409
- package/src/components/management/SecurityNavLinks.tsx +0 -117
- package/src/components/management/TwoFactorManagementClient.tsx +0 -560
- package/src/components/management/index.ts +0 -20
- package/src/components/management/views/ApiKeysView.tsx +0 -57
- package/src/components/management/views/PasskeysView.tsx +0 -42
- package/src/components/management/views/TwoFactorView.tsx +0 -42
- package/src/components/management/views/index.ts +0 -10
- package/src/components/twoFactor/TwoFactorSetupView.tsx +0 -515
- package/src/components/twoFactor/TwoFactorVerifyView.tsx +0 -238
- package/src/components/twoFactor/index.ts +0 -8
- package/src/exports/client.ts +0 -77
- package/src/exports/components.ts +0 -30
- package/src/exports/management.ts +0 -25
- package/src/exports/rsc.ts +0 -11
- package/src/generated-types.ts +0 -269
- package/src/index.ts +0 -135
- package/src/plugin/index.ts +0 -834
- package/src/scripts/generate-types.ts +0 -269
- package/src/types/apiKey.ts +0 -63
- package/src/types/betterAuth.ts +0 -253
- package/src/utils/access.ts +0 -410
- package/src/utils/apiKeyAccess.ts +0 -443
- package/src/utils/betterAuthDefaults.ts +0 -102
- package/src/utils/detectAuthConfig.ts +0 -47
- package/src/utils/detectEnabledPlugins.ts +0 -69
- package/src/utils/firstUserAdmin.ts +0 -164
- package/src/utils/generateScopes.ts +0 -150
- package/src/utils/session.ts +0 -91
package/src/utils/access.ts
DELETED
|
@@ -1,410 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Access control utilities for Payload collections.
|
|
3
|
-
*
|
|
4
|
-
* These helpers simplify common access control patterns when using
|
|
5
|
-
* Better Auth with Payload CMS. They handle role checking, self-access
|
|
6
|
-
* patterns, and field-level permissions.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```ts
|
|
10
|
-
* import { isAdmin, isAdminOrSelf } from '@delmaredigital/payload-better-auth'
|
|
11
|
-
*
|
|
12
|
-
* export const Users: CollectionConfig = {
|
|
13
|
-
* slug: 'users',
|
|
14
|
-
* access: {
|
|
15
|
-
* read: isAdminOrSelf({ adminRoles: ['admin', 'editor'] }),
|
|
16
|
-
* update: isAdminOrSelf({ adminRoles: ['admin'] }),
|
|
17
|
-
* delete: isAdmin({ adminRoles: ['admin'] }),
|
|
18
|
-
* },
|
|
19
|
-
* }
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import type { Access, FieldAccess, PayloadRequest } from 'payload'
|
|
24
|
-
|
|
25
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
26
|
-
// Types
|
|
27
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
28
|
-
|
|
29
|
-
export type RoleCheckConfig = {
|
|
30
|
-
/**
|
|
31
|
-
* Roles considered admin roles.
|
|
32
|
-
* @default ['admin']
|
|
33
|
-
*/
|
|
34
|
-
adminRoles?: string[]
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export type SelfAccessConfig = RoleCheckConfig & {
|
|
38
|
-
/**
|
|
39
|
-
* The field to use for user ID comparison.
|
|
40
|
-
* @default 'id'
|
|
41
|
-
*/
|
|
42
|
-
idField?: string
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export type FieldUpdateConfig = SelfAccessConfig & {
|
|
46
|
-
/**
|
|
47
|
-
* Fields the user is allowed to update on their own record.
|
|
48
|
-
* Password is handled specially and requires currentPassword.
|
|
49
|
-
* @default ['name']
|
|
50
|
-
*/
|
|
51
|
-
allowedFields?: string[]
|
|
52
|
-
/**
|
|
53
|
-
* The user collection slug for password verification.
|
|
54
|
-
*/
|
|
55
|
-
userSlug?: string
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
59
|
-
// Role Checking Utilities
|
|
60
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Normalize a user's role to an array.
|
|
64
|
-
*
|
|
65
|
-
* Handles various role formats:
|
|
66
|
-
* - Array of roles
|
|
67
|
-
* - Comma-separated string
|
|
68
|
-
* - Single role string
|
|
69
|
-
*
|
|
70
|
-
* @param role - The role value from the user object
|
|
71
|
-
* @returns Array of role strings
|
|
72
|
-
*/
|
|
73
|
-
export function normalizeRoles(role: unknown): string[] {
|
|
74
|
-
if (Array.isArray(role)) {
|
|
75
|
-
return role.filter((r): r is string => typeof r === 'string')
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (typeof role === 'string') {
|
|
79
|
-
if (role.includes(',')) {
|
|
80
|
-
return role
|
|
81
|
-
.split(',')
|
|
82
|
-
.map((r) => r.trim())
|
|
83
|
-
.filter(Boolean)
|
|
84
|
-
}
|
|
85
|
-
return role ? [role] : []
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return []
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Check if a user has any of the specified roles.
|
|
93
|
-
*
|
|
94
|
-
* @param user - The user object
|
|
95
|
-
* @param roles - Roles to check for
|
|
96
|
-
* @returns True if user has at least one matching role
|
|
97
|
-
*
|
|
98
|
-
* @example
|
|
99
|
-
* ```ts
|
|
100
|
-
* const user = { role: ['admin', 'editor'] }
|
|
101
|
-
* hasAnyRole(user, ['admin']) // true
|
|
102
|
-
* hasAnyRole(user, ['superadmin']) // false
|
|
103
|
-
* ```
|
|
104
|
-
*/
|
|
105
|
-
export function hasAnyRole(
|
|
106
|
-
user: { role?: unknown } | null | undefined,
|
|
107
|
-
roles: string[]
|
|
108
|
-
): boolean {
|
|
109
|
-
if (!user?.role) return false
|
|
110
|
-
const userRoles = normalizeRoles(user.role)
|
|
111
|
-
return userRoles.some((role) => roles.includes(role))
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Check if a user has all of the specified roles.
|
|
116
|
-
*
|
|
117
|
-
* @param user - The user object
|
|
118
|
-
* @param roles - Roles to check for
|
|
119
|
-
* @returns True if user has all matching roles
|
|
120
|
-
*
|
|
121
|
-
* @example
|
|
122
|
-
* ```ts
|
|
123
|
-
* const user = { role: ['admin', 'editor'] }
|
|
124
|
-
* hasAllRoles(user, ['admin', 'editor']) // true
|
|
125
|
-
* hasAllRoles(user, ['admin', 'superadmin']) // false
|
|
126
|
-
* ```
|
|
127
|
-
*/
|
|
128
|
-
export function hasAllRoles(
|
|
129
|
-
user: { role?: unknown } | null | undefined,
|
|
130
|
-
roles: string[]
|
|
131
|
-
): boolean {
|
|
132
|
-
if (!user?.role) return false
|
|
133
|
-
const userRoles = normalizeRoles(user.role)
|
|
134
|
-
return roles.every((role) => userRoles.includes(role))
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
138
|
-
// Access Control Functions
|
|
139
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Check if the current request user has admin roles.
|
|
143
|
-
*
|
|
144
|
-
* Use this as a reusable check within access functions.
|
|
145
|
-
*
|
|
146
|
-
* @param config - Configuration with admin roles
|
|
147
|
-
* @returns Access check function
|
|
148
|
-
*/
|
|
149
|
-
export function hasAdminRoles(
|
|
150
|
-
config: RoleCheckConfig = {}
|
|
151
|
-
): (args: { req: PayloadRequest }) => boolean {
|
|
152
|
-
const { adminRoles = ['admin'] } = config
|
|
153
|
-
|
|
154
|
-
return ({ req }) => {
|
|
155
|
-
return hasAnyRole(req.user as { role?: unknown } | null, adminRoles)
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Access control: Only allow users with admin roles.
|
|
161
|
-
*
|
|
162
|
-
* @param config - Configuration with admin roles
|
|
163
|
-
* @returns Payload access function
|
|
164
|
-
*
|
|
165
|
-
* @example
|
|
166
|
-
* ```ts
|
|
167
|
-
* access: {
|
|
168
|
-
* delete: isAdmin({ adminRoles: ['admin', 'superadmin'] }),
|
|
169
|
-
* }
|
|
170
|
-
* ```
|
|
171
|
-
*/
|
|
172
|
-
export function isAdmin(config: RoleCheckConfig = {}): Access {
|
|
173
|
-
const checkAdmin = hasAdminRoles(config)
|
|
174
|
-
|
|
175
|
-
return ({ req }) => {
|
|
176
|
-
return checkAdmin({ req })
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Field access control: Only allow users with admin roles.
|
|
182
|
-
*
|
|
183
|
-
* @param config - Configuration with admin roles
|
|
184
|
-
* @returns Payload field access function
|
|
185
|
-
*
|
|
186
|
-
* @example
|
|
187
|
-
* ```ts
|
|
188
|
-
* fields: [
|
|
189
|
-
* {
|
|
190
|
-
* name: 'role',
|
|
191
|
-
* type: 'select',
|
|
192
|
-
* access: {
|
|
193
|
-
* update: isAdminField({ adminRoles: ['admin'] }),
|
|
194
|
-
* },
|
|
195
|
-
* },
|
|
196
|
-
* ]
|
|
197
|
-
* ```
|
|
198
|
-
*/
|
|
199
|
-
export function isAdminField(config: RoleCheckConfig = {}): FieldAccess {
|
|
200
|
-
const checkAdmin = hasAdminRoles(config)
|
|
201
|
-
|
|
202
|
-
return ({ req }) => {
|
|
203
|
-
return checkAdmin({ req })
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Access control: Allow admin OR the user accessing their own record.
|
|
209
|
-
*
|
|
210
|
-
* Returns a query constraint for non-admin users to limit access
|
|
211
|
-
* to their own records only.
|
|
212
|
-
*
|
|
213
|
-
* @param config - Configuration with admin roles and ID field
|
|
214
|
-
* @returns Payload access function
|
|
215
|
-
*
|
|
216
|
-
* @example
|
|
217
|
-
* ```ts
|
|
218
|
-
* access: {
|
|
219
|
-
* read: isAdminOrSelf({ adminRoles: ['admin'] }),
|
|
220
|
-
* update: isAdminOrSelf({ adminRoles: ['admin'] }),
|
|
221
|
-
* }
|
|
222
|
-
* ```
|
|
223
|
-
*/
|
|
224
|
-
export function isAdminOrSelf(config: SelfAccessConfig = {}): Access {
|
|
225
|
-
const { adminRoles = ['admin'], idField = 'id' } = config
|
|
226
|
-
const checkAdmin = hasAdminRoles({ adminRoles })
|
|
227
|
-
|
|
228
|
-
return ({ req }) => {
|
|
229
|
-
// Admins can access everything
|
|
230
|
-
if (checkAdmin({ req })) return true
|
|
231
|
-
|
|
232
|
-
// Non-authenticated users have no access
|
|
233
|
-
if (!req.user) return false
|
|
234
|
-
|
|
235
|
-
// Restrict to own record
|
|
236
|
-
return {
|
|
237
|
-
[idField]: {
|
|
238
|
-
equals: req.user.id,
|
|
239
|
-
},
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* Access control: Allow admin OR user updating allowed fields on own record.
|
|
246
|
-
*
|
|
247
|
-
* This is useful for allowing users to update specific fields (like name)
|
|
248
|
-
* on their own profile while preventing them from changing sensitive fields
|
|
249
|
-
* like role.
|
|
250
|
-
*
|
|
251
|
-
* Password changes require `currentPassword` to be provided and validated.
|
|
252
|
-
*
|
|
253
|
-
* @param config - Configuration with admin roles, allowed fields, and user slug
|
|
254
|
-
* @returns Payload access function
|
|
255
|
-
*
|
|
256
|
-
* @example
|
|
257
|
-
* ```ts
|
|
258
|
-
* access: {
|
|
259
|
-
* update: canUpdateOwnFields({
|
|
260
|
-
* adminRoles: ['admin'],
|
|
261
|
-
* allowedFields: ['name', 'image'],
|
|
262
|
-
* userSlug: 'users',
|
|
263
|
-
* }),
|
|
264
|
-
* }
|
|
265
|
-
* ```
|
|
266
|
-
*/
|
|
267
|
-
export function canUpdateOwnFields(config: FieldUpdateConfig = {}): Access {
|
|
268
|
-
const {
|
|
269
|
-
adminRoles = ['admin'],
|
|
270
|
-
allowedFields = ['name'],
|
|
271
|
-
idField = 'id',
|
|
272
|
-
userSlug = 'users',
|
|
273
|
-
} = config
|
|
274
|
-
const checkAdmin = hasAdminRoles({ adminRoles })
|
|
275
|
-
|
|
276
|
-
return async ({ req, id, data }) => {
|
|
277
|
-
// Admins can update everything
|
|
278
|
-
if (checkAdmin({ req })) return true
|
|
279
|
-
|
|
280
|
-
// Must be authenticated
|
|
281
|
-
if (!req.user) return false
|
|
282
|
-
|
|
283
|
-
// Must be updating own record
|
|
284
|
-
const userId = req.user[idField]
|
|
285
|
-
if (userId !== id || !data) return false
|
|
286
|
-
|
|
287
|
-
const dataKeys = Object.keys(data)
|
|
288
|
-
const effectiveAllowed = [...allowedFields]
|
|
289
|
-
|
|
290
|
-
// Handle password changes specially
|
|
291
|
-
const hasCurrentPassword = dataKeys.includes('currentPassword')
|
|
292
|
-
const hasPassword = dataKeys.includes('password')
|
|
293
|
-
|
|
294
|
-
if (hasPassword || hasCurrentPassword) {
|
|
295
|
-
// Both must be provided for password change
|
|
296
|
-
if (!(hasCurrentPassword && hasPassword)) return false
|
|
297
|
-
|
|
298
|
-
try {
|
|
299
|
-
// Verify current password
|
|
300
|
-
if (!req.user.email) return false
|
|
301
|
-
|
|
302
|
-
const result = await req.payload.login({
|
|
303
|
-
collection: userSlug,
|
|
304
|
-
data: {
|
|
305
|
-
email: req.user.email as string,
|
|
306
|
-
password: data.currentPassword as string,
|
|
307
|
-
},
|
|
308
|
-
})
|
|
309
|
-
|
|
310
|
-
if (!result) return false
|
|
311
|
-
|
|
312
|
-
effectiveAllowed.push('password', 'currentPassword')
|
|
313
|
-
} catch {
|
|
314
|
-
return false
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// Check all fields are allowed
|
|
319
|
-
const hasDisallowed = dataKeys.some((key) => !effectiveAllowed.includes(key))
|
|
320
|
-
return !hasDisallowed
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
325
|
-
// Authenticated Access
|
|
326
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
327
|
-
|
|
328
|
-
/**
|
|
329
|
-
* Access control: Allow any authenticated user.
|
|
330
|
-
*
|
|
331
|
-
* @returns Payload access function
|
|
332
|
-
*
|
|
333
|
-
* @example
|
|
334
|
-
* ```ts
|
|
335
|
-
* access: {
|
|
336
|
-
* read: isAuthenticated(),
|
|
337
|
-
* }
|
|
338
|
-
* ```
|
|
339
|
-
*/
|
|
340
|
-
export function isAuthenticated(): Access {
|
|
341
|
-
return ({ req }) => {
|
|
342
|
-
return !!req.user
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/**
|
|
347
|
-
* Field access control: Allow any authenticated user.
|
|
348
|
-
*
|
|
349
|
-
* @returns Payload field access function
|
|
350
|
-
*/
|
|
351
|
-
export function isAuthenticatedField(): FieldAccess {
|
|
352
|
-
return ({ req }) => {
|
|
353
|
-
return !!req.user
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
358
|
-
// Role-Based Access
|
|
359
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* Access control: Allow users with any of the specified roles.
|
|
363
|
-
*
|
|
364
|
-
* @param roles - Roles that have access
|
|
365
|
-
* @returns Payload access function
|
|
366
|
-
*
|
|
367
|
-
* @example
|
|
368
|
-
* ```ts
|
|
369
|
-
* access: {
|
|
370
|
-
* read: hasRole(['admin', 'editor', 'viewer']),
|
|
371
|
-
* update: hasRole(['admin', 'editor']),
|
|
372
|
-
* }
|
|
373
|
-
* ```
|
|
374
|
-
*/
|
|
375
|
-
export function hasRole(roles: string[]): Access {
|
|
376
|
-
return ({ req }) => {
|
|
377
|
-
return hasAnyRole(req.user as { role?: unknown } | null, roles)
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
/**
|
|
382
|
-
* Field access control: Allow users with any of the specified roles.
|
|
383
|
-
*
|
|
384
|
-
* @param roles - Roles that have access
|
|
385
|
-
* @returns Payload field access function
|
|
386
|
-
*/
|
|
387
|
-
export function hasRoleField(roles: string[]): FieldAccess {
|
|
388
|
-
return ({ req }) => {
|
|
389
|
-
return hasAnyRole(req.user as { role?: unknown } | null, roles)
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
/**
|
|
394
|
-
* Access control: Allow users with all of the specified roles.
|
|
395
|
-
*
|
|
396
|
-
* @param roles - All roles required for access
|
|
397
|
-
* @returns Payload access function
|
|
398
|
-
*
|
|
399
|
-
* @example
|
|
400
|
-
* ```ts
|
|
401
|
-
* access: {
|
|
402
|
-
* delete: requireAllRoles(['admin', 'verified']),
|
|
403
|
-
* }
|
|
404
|
-
* ```
|
|
405
|
-
*/
|
|
406
|
-
export function requireAllRoles(roles: string[]): Access {
|
|
407
|
-
return ({ req }) => {
|
|
408
|
-
return hasAllRoles(req.user as { role?: unknown } | null, roles)
|
|
409
|
-
}
|
|
410
|
-
}
|