payload-auth 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 (200) hide show
  1. package/LICENSE.md +17 -0
  2. package/dist/authjs/index.d.ts +1 -0
  3. package/dist/authjs/index.js +3 -0
  4. package/dist/authjs/index.js.map +1 -0
  5. package/dist/better-auth/adapter/dev/bin/run.d.ts +1 -0
  6. package/dist/better-auth/adapter/dev/bin/run.js +64 -0
  7. package/dist/better-auth/adapter/dev/bin/run.js.map +1 -0
  8. package/dist/better-auth/adapter/dev/bin/schema.d.ts +22 -0
  9. package/dist/better-auth/adapter/dev/bin/schema.js +160 -0
  10. package/dist/better-auth/adapter/dev/bin/schema.js.map +1 -0
  11. package/dist/better-auth/adapter/dev/collections.d.ts +3 -0
  12. package/dist/better-auth/adapter/dev/collections.js +212 -0
  13. package/dist/better-auth/adapter/dev/collections.js.map +1 -0
  14. package/dist/better-auth/adapter/dev/index.d.ts +3 -0
  15. package/dist/better-auth/adapter/dev/index.js +168 -0
  16. package/dist/better-auth/adapter/dev/index.js.map +1 -0
  17. package/dist/better-auth/adapter/generate-schema/generate-schema-builder.d.ts +23 -0
  18. package/dist/better-auth/adapter/generate-schema/generate-schema-builder.js +326 -0
  19. package/dist/better-auth/adapter/generate-schema/generate-schema-builder.js.map +1 -0
  20. package/dist/better-auth/adapter/generate-schema/get-payload-schema.d.ts +1 -0
  21. package/dist/better-auth/adapter/generate-schema/get-payload-schema.js +23 -0
  22. package/dist/better-auth/adapter/generate-schema/get-payload-schema.js.map +1 -0
  23. package/dist/better-auth/adapter/generate-schema/index.d.ts +4 -0
  24. package/dist/better-auth/adapter/generate-schema/index.js +19 -0
  25. package/dist/better-auth/adapter/generate-schema/index.js.map +1 -0
  26. package/dist/better-auth/adapter/generate-schema/utils.d.ts +2 -0
  27. package/dist/better-auth/adapter/generate-schema/utils.js +20 -0
  28. package/dist/better-auth/adapter/generate-schema/utils.js.map +1 -0
  29. package/dist/better-auth/adapter/index.d.ts +5 -0
  30. package/dist/better-auth/adapter/index.js +578 -0
  31. package/dist/better-auth/adapter/index.js.map +1 -0
  32. package/dist/better-auth/adapter/test/adapter.test.d.ts +1 -0
  33. package/dist/better-auth/adapter/test/adapter.test.js +181 -0
  34. package/dist/better-auth/adapter/test/adapter.test.js.map +1 -0
  35. package/dist/better-auth/adapter/test/better-auth-adapter-test.d.ts +7 -0
  36. package/dist/better-auth/adapter/test/better-auth-adapter-test.js +425 -0
  37. package/dist/better-auth/adapter/test/better-auth-adapter-test.js.map +1 -0
  38. package/dist/better-auth/adapter/test/schema.test.d.ts +1 -0
  39. package/dist/better-auth/adapter/test/schema.test.js +796 -0
  40. package/dist/better-auth/adapter/test/schema.test.js.map +1 -0
  41. package/dist/better-auth/adapter/test/test_payload1/schema.d.ts +23 -0
  42. package/dist/better-auth/adapter/test/test_payload1/schema.js +177 -0
  43. package/dist/better-auth/adapter/test/test_payload1/schema.js.map +1 -0
  44. package/dist/better-auth/adapter/test/test_payload2/schema.d.ts +23 -0
  45. package/dist/better-auth/adapter/test/test_payload2/schema.js +167 -0
  46. package/dist/better-auth/adapter/test/test_payload2/schema.js.map +1 -0
  47. package/dist/better-auth/adapter/test/test_payload3/schema.d.ts +23 -0
  48. package/dist/better-auth/adapter/test/test_payload3/schema.js +198 -0
  49. package/dist/better-auth/adapter/test/test_payload3/schema.js.map +1 -0
  50. package/dist/better-auth/adapter/transform/index.d.ts +16 -0
  51. package/dist/better-auth/adapter/transform/index.js +252 -0
  52. package/dist/better-auth/adapter/transform/index.js.map +1 -0
  53. package/dist/better-auth/adapter/types.d.ts +6 -0
  54. package/dist/better-auth/adapter/types.js +3 -0
  55. package/dist/better-auth/adapter/types.js.map +1 -0
  56. package/dist/better-auth/index.d.ts +6 -0
  57. package/dist/better-auth/index.js +8 -0
  58. package/dist/better-auth/index.js.map +1 -0
  59. package/dist/better-auth/plugin/collections/accounts/hooks/sync-password-to-user.d.ts +7 -0
  60. package/dist/better-auth/plugin/collections/accounts/hooks/sync-password-to-user.js +47 -0
  61. package/dist/better-auth/plugin/collections/accounts/hooks/sync-password-to-user.js.map +1 -0
  62. package/dist/better-auth/plugin/collections/users/endpoints/refresh-token.d.ts +6 -0
  63. package/dist/better-auth/plugin/collections/users/endpoints/refresh-token.js +106 -0
  64. package/dist/better-auth/plugin/collections/users/endpoints/refresh-token.js.map +1 -0
  65. package/dist/better-auth/plugin/collections/users/hooks/after-login.d.ts +11 -0
  66. package/dist/better-auth/plugin/collections/users/hooks/after-login.js +71 -0
  67. package/dist/better-auth/plugin/collections/users/hooks/after-login.js.map +1 -0
  68. package/dist/better-auth/plugin/collections/users/hooks/after-logout.d.ts +6 -0
  69. package/dist/better-auth/plugin/collections/users/hooks/after-logout.js +49 -0
  70. package/dist/better-auth/plugin/collections/users/hooks/after-logout.js.map +1 -0
  71. package/dist/better-auth/plugin/collections/users/hooks/before-login.d.ts +5 -0
  72. package/dist/better-auth/plugin/collections/users/hooks/before-login.js +18 -0
  73. package/dist/better-auth/plugin/collections/users/hooks/before-login.js.map +1 -0
  74. package/dist/better-auth/plugin/collections/users/hooks/clean-up-user-after-delete.d.ts +5 -0
  75. package/dist/better-auth/plugin/collections/users/hooks/clean-up-user-after-delete.js +33 -0
  76. package/dist/better-auth/plugin/collections/users/hooks/clean-up-user-after-delete.js.map +1 -0
  77. package/dist/better-auth/plugin/collections/users/hooks/on-verified-change.d.ts +2 -0
  78. package/dist/better-auth/plugin/collections/users/hooks/on-verified-change.js +14 -0
  79. package/dist/better-auth/plugin/collections/users/hooks/on-verified-change.js.map +1 -0
  80. package/dist/better-auth/plugin/collections/users/hooks/sync-account.d.ts +7 -0
  81. package/dist/better-auth/plugin/collections/users/hooks/sync-account.js +82 -0
  82. package/dist/better-auth/plugin/collections/users/hooks/sync-account.js.map +1 -0
  83. package/dist/better-auth/plugin/helpers/generate-verify-email-url.d.ts +29 -0
  84. package/dist/better-auth/plugin/helpers/generate-verify-email-url.js +46 -0
  85. package/dist/better-auth/plugin/helpers/generate-verify-email-url.js.map +1 -0
  86. package/dist/better-auth/plugin/helpers/get-ip.d.ts +2 -0
  87. package/dist/better-auth/plugin/helpers/get-ip.js +31 -0
  88. package/dist/better-auth/plugin/helpers/get-ip.js.map +1 -0
  89. package/dist/better-auth/plugin/helpers/index.d.ts +1 -0
  90. package/dist/better-auth/plugin/helpers/index.js +3 -0
  91. package/dist/better-auth/plugin/helpers/index.js.map +1 -0
  92. package/dist/better-auth/plugin/helpers/serialize-cookie.d.ts +104 -0
  93. package/dist/better-auth/plugin/helpers/serialize-cookie.js +186 -0
  94. package/dist/better-auth/plugin/helpers/serialize-cookie.js.map +1 -0
  95. package/dist/better-auth/plugin/index.d.ts +7 -0
  96. package/dist/better-auth/plugin/index.js +64 -0
  97. package/dist/better-auth/plugin/index.js.map +1 -0
  98. package/dist/better-auth/plugin/lib/auth-strategy.d.ts +8 -0
  99. package/dist/better-auth/plugin/lib/auth-strategy.js +48 -0
  100. package/dist/better-auth/plugin/lib/auth-strategy.js.map +1 -0
  101. package/dist/better-auth/plugin/lib/build-collection-configs.d.ts +11 -0
  102. package/dist/better-auth/plugin/lib/build-collection-configs.js +1558 -0
  103. package/dist/better-auth/plugin/lib/build-collection-configs.js.map +1 -0
  104. package/dist/better-auth/plugin/lib/config.d.ts +41 -0
  105. package/dist/better-auth/plugin/lib/config.js +43 -0
  106. package/dist/better-auth/plugin/lib/config.js.map +1 -0
  107. package/dist/better-auth/plugin/lib/ensure-password-set-before-create.d.ts +7 -0
  108. package/dist/better-auth/plugin/lib/ensure-password-set-before-create.js +24 -0
  109. package/dist/better-auth/plugin/lib/ensure-password-set-before-create.js.map +1 -0
  110. package/dist/better-auth/plugin/lib/get-payload-auth.d.ts +5 -0
  111. package/dist/better-auth/plugin/lib/get-payload-auth.js +9 -0
  112. package/dist/better-auth/plugin/lib/get-payload-auth.js.map +1 -0
  113. package/dist/better-auth/plugin/lib/get-required-collection-slugs.d.ts +9 -0
  114. package/dist/better-auth/plugin/lib/get-required-collection-slugs.js +52 -0
  115. package/dist/better-auth/plugin/lib/get-required-collection-slugs.js.map +1 -0
  116. package/dist/better-auth/plugin/lib/init-better-auth.d.ts +6 -0
  117. package/dist/better-auth/plugin/lib/init-better-auth.js +13 -0
  118. package/dist/better-auth/plugin/lib/init-better-auth.js.map +1 -0
  119. package/dist/better-auth/plugin/lib/password.d.ts +25 -0
  120. package/dist/better-auth/plugin/lib/password.js +63 -0
  121. package/dist/better-auth/plugin/lib/password.js.map +1 -0
  122. package/dist/better-auth/plugin/lib/payload-access.d.ts +14 -0
  123. package/dist/better-auth/plugin/lib/payload-access.js +64 -0
  124. package/dist/better-auth/plugin/lib/payload-access.js.map +1 -0
  125. package/dist/better-auth/plugin/lib/prepare-session-data.d.ts +21 -0
  126. package/dist/better-auth/plugin/lib/prepare-session-data.js +42 -0
  127. package/dist/better-auth/plugin/lib/prepare-session-data.js.map +1 -0
  128. package/dist/better-auth/plugin/lib/respect-save-to-jwt-fields-middleware.d.ts +15 -0
  129. package/dist/better-auth/plugin/lib/respect-save-to-jwt-fields-middleware.js +30 -0
  130. package/dist/better-auth/plugin/lib/respect-save-to-jwt-fields-middleware.js.map +1 -0
  131. package/dist/better-auth/plugin/lib/sanitize-auth-options.d.ts +5 -0
  132. package/dist/better-auth/plugin/lib/sanitize-auth-options.js +298 -0
  133. package/dist/better-auth/plugin/lib/sanitize-auth-options.js.map +1 -0
  134. package/dist/better-auth/plugin/payload/components/admin-buttons.d.ts +5 -0
  135. package/dist/better-auth/plugin/payload/components/admin-buttons.js +222 -0
  136. package/dist/better-auth/plugin/payload/components/admin-buttons.js.map +1 -0
  137. package/dist/better-auth/plugin/payload/components/login-redirect.d.ts +1 -0
  138. package/dist/better-auth/plugin/payload/components/login-redirect.js +6 -0
  139. package/dist/better-auth/plugin/payload/components/login-redirect.js.map +1 -0
  140. package/dist/better-auth/plugin/payload/components/logo.d.ts +1 -0
  141. package/dist/better-auth/plugin/payload/components/logo.js +36 -0
  142. package/dist/better-auth/plugin/payload/components/logo.js.map +1 -0
  143. package/dist/better-auth/plugin/payload/components/logout.d.ts +1 -0
  144. package/dist/better-auth/plugin/payload/components/logout.js +61 -0
  145. package/dist/better-auth/plugin/payload/components/logout.js.map +1 -0
  146. package/dist/better-auth/plugin/payload/components/sign-in.d.ts +3 -0
  147. package/dist/better-auth/plugin/payload/components/sign-in.js +384 -0
  148. package/dist/better-auth/plugin/payload/components/sign-in.js.map +1 -0
  149. package/dist/better-auth/plugin/payload/components/sign-up.d.ts +6 -0
  150. package/dist/better-auth/plugin/payload/components/sign-up.js +502 -0
  151. package/dist/better-auth/plugin/payload/components/sign-up.js.map +1 -0
  152. package/dist/better-auth/plugin/payload/components/styles.css +73 -0
  153. package/dist/better-auth/plugin/payload/components/ui/button.d.ts +10 -0
  154. package/dist/better-auth/plugin/payload/components/ui/button.js +42 -0
  155. package/dist/better-auth/plugin/payload/components/ui/button.js.map +1 -0
  156. package/dist/better-auth/plugin/payload/components/ui/card.d.ts +9 -0
  157. package/dist/better-auth/plugin/payload/components/ui/card.js +55 -0
  158. package/dist/better-auth/plugin/payload/components/ui/card.js.map +1 -0
  159. package/dist/better-auth/plugin/payload/components/ui/checkbox.d.ts +4 -0
  160. package/dist/better-auth/plugin/payload/components/ui/checkbox.js +23 -0
  161. package/dist/better-auth/plugin/payload/components/ui/checkbox.js.map +1 -0
  162. package/dist/better-auth/plugin/payload/components/ui/cn.d.ts +2 -0
  163. package/dist/better-auth/plugin/payload/components/ui/cn.js +7 -0
  164. package/dist/better-auth/plugin/payload/components/ui/cn.js.map +1 -0
  165. package/dist/better-auth/plugin/payload/components/ui/input.d.ts +3 -0
  166. package/dist/better-auth/plugin/payload/components/ui/input.js +14 -0
  167. package/dist/better-auth/plugin/payload/components/ui/input.js.map +1 -0
  168. package/dist/better-auth/plugin/payload/components/ui/label.d.ts +4 -0
  169. package/dist/better-auth/plugin/payload/components/ui/label.js +15 -0
  170. package/dist/better-auth/plugin/payload/components/ui/label.js.map +1 -0
  171. package/dist/better-auth/plugin/payload/components/ui/password-input.d.ts +2 -0
  172. package/dist/better-auth/plugin/payload/components/ui/password-input.js +55 -0
  173. package/dist/better-auth/plugin/payload/components/ui/password-input.js.map +1 -0
  174. package/dist/better-auth/plugin/payload/exports/client.d.ts +3 -0
  175. package/dist/better-auth/plugin/payload/exports/client.js +5 -0
  176. package/dist/better-auth/plugin/payload/exports/client.js.map +1 -0
  177. package/dist/better-auth/plugin/payload/exports/rsc.d.ts +5 -0
  178. package/dist/better-auth/plugin/payload/exports/rsc.js +7 -0
  179. package/dist/better-auth/plugin/payload/exports/rsc.js.map +1 -0
  180. package/dist/better-auth/plugin/payload/views/create-first-admin/index.d.ts +4 -0
  181. package/dist/better-auth/plugin/payload/views/create-first-admin/index.js +112 -0
  182. package/dist/better-auth/plugin/payload/views/create-first-admin/index.js.map +1 -0
  183. package/dist/better-auth/plugin/payload/views/login/index.d.ts +4 -0
  184. package/dist/better-auth/plugin/payload/views/login/index.js +78 -0
  185. package/dist/better-auth/plugin/payload/views/login/index.js.map +1 -0
  186. package/dist/better-auth/plugin/types.d.ts +224 -0
  187. package/dist/better-auth/plugin/types.js +3 -0
  188. package/dist/better-auth/plugin/types.js.map +1 -0
  189. package/dist/better-auth/types.d.ts +2 -0
  190. package/dist/better-auth/types.js +4 -0
  191. package/dist/better-auth/types.js.map +1 -0
  192. package/dist/clerk/index.d.ts +1 -0
  193. package/dist/clerk/index.js +3 -0
  194. package/dist/clerk/index.js.map +1 -0
  195. package/dist/index.js +7 -0
  196. package/dist/index.js.map +1 -0
  197. package/dist/kinde/index.d.ts +1 -0
  198. package/dist/kinde/index.js +3 -0
  199. package/dist/kinde/index.js.map +1 -0
  200. package/package.json +87 -0
@@ -0,0 +1,106 @@
1
+ import { setCookieCache } from 'better-auth/cookies';
2
+ import { getFieldsToSign, refreshOperation } from 'payload';
3
+ import { getPayloadAuth } from '../../../lib/get-payload-auth';
4
+ export const getRefreshTokenEndpoint = (options)=>{
5
+ const userSlug = options?.userSlug;
6
+ const endpoint = {
7
+ path: '/refresh-token',
8
+ method: 'post',
9
+ handler: async (req)=>{
10
+ const payload = await getPayloadAuth(req.payload.config);
11
+ const betterAuth = payload.betterAuth;
12
+ const authContext = await betterAuth?.$context;
13
+ const userCollection = payload.collections[userSlug];
14
+ if (!betterAuth || !authContext) {
15
+ return new Response(JSON.stringify({
16
+ message: 'BetterAuth not initialized'
17
+ }), {
18
+ status: 500
19
+ });
20
+ }
21
+ const sessionTokenName = authContext.authCookies.sessionToken.name;
22
+ const cookieHeader = req.headers.get('cookie') || '';
23
+ const hasSessionToken = cookieHeader.includes(`${sessionTokenName}=`);
24
+ if (!hasSessionToken) {
25
+ try {
26
+ const result = await refreshOperation({
27
+ collection: userCollection,
28
+ req
29
+ });
30
+ return new Response(JSON.stringify(result), {
31
+ status: 200
32
+ });
33
+ } catch (error) {
34
+ console.error('Token refresh failed:', error);
35
+ return new Response(JSON.stringify({
36
+ message: 'Token refresh failed'
37
+ }), {
38
+ status: 401
39
+ });
40
+ }
41
+ }
42
+ // @ts-ignore - @TODO, fix type of .api
43
+ const session = await betterAuth.api.getSession({
44
+ headers: req.headers,
45
+ query: {
46
+ disableCookieCache: true
47
+ }
48
+ });
49
+ if (!session?.session?.userId) {
50
+ return new Response(JSON.stringify({
51
+ message: 'No user in session'
52
+ }), {
53
+ status: 401
54
+ });
55
+ }
56
+ const user = await payload.findByID({
57
+ collection: userSlug,
58
+ id: session.session.userId
59
+ });
60
+ if (!user) {
61
+ return new Response(JSON.stringify({
62
+ message: 'No user found'
63
+ }), {
64
+ status: 401
65
+ });
66
+ }
67
+ const cookieCacheFields = getFieldsToSign({
68
+ collectionConfig: userCollection.config,
69
+ email: user.email,
70
+ user: user
71
+ });
72
+ const responseData = {
73
+ refreshedToken: null,
74
+ setCookie: !!authContext.options.session?.cookieCache?.enabled,
75
+ strategy: 'better-auth',
76
+ user: {
77
+ ...user,
78
+ collection: userSlug
79
+ }
80
+ };
81
+ const response = new Response(JSON.stringify(responseData), {
82
+ status: 200
83
+ });
84
+ const ctx = {
85
+ context: authContext,
86
+ setCookie (name, value, options) {
87
+ const path = options?.path || '/';
88
+ const maxAge = options?.maxAge ? `; Max-Age=${options.maxAge}` : '';
89
+ const httpOnly = options?.httpOnly ? '; HttpOnly' : '';
90
+ const secure = options?.secure ? '; Secure' : '';
91
+ const sameSite = options?.sameSite ? `; SameSite=${options.sameSite}` : '; SameSite=Lax';
92
+ response.headers.set('Set-Cookie', `${name}=${value}; Path=${path}${maxAge}${httpOnly}${secure}${sameSite}`);
93
+ return name;
94
+ }
95
+ };
96
+ await setCookieCache(ctx, {
97
+ session: session.session,
98
+ user: cookieCacheFields
99
+ });
100
+ return response;
101
+ }
102
+ };
103
+ return endpoint;
104
+ };
105
+
106
+ //# sourceMappingURL=refresh-token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/plugin/collections/users/endpoints/refresh-token.ts"],"sourcesContent":["import { setCookieCache } from 'better-auth/cookies'\nimport { CollectionSlug, type Endpoint, getFieldsToSign, refreshOperation, User } from 'payload'\nimport { GenericEndpointContext } from 'better-auth/types'\nimport { EndpointWithBetterAuth } from '../../../types'\nimport { getPayloadAuth } from '../../../lib/get-payload-auth'\n\ntype RefreshTokenEndpointOptions = {\n userSlug: CollectionSlug\n}\n\nexport const getRefreshTokenEndpoint = (options?: RefreshTokenEndpointOptions): Endpoint => {\n const userSlug = options?.userSlug\n\n const endpoint: EndpointWithBetterAuth = {\n path: '/refresh-token',\n method: 'post',\n handler: async (req) => {\n const payload = await getPayloadAuth(req.payload.config)\n const betterAuth = payload.betterAuth\n const authContext = await betterAuth?.$context\n const userCollection = payload.collections[userSlug as CollectionSlug]\n\n if (!betterAuth || !authContext) {\n return new Response(JSON.stringify({ message: 'BetterAuth not initialized' }), {\n status: 500,\n })\n }\n\n const sessionTokenName = authContext.authCookies.sessionToken.name\n const cookieHeader = req.headers.get('cookie') || ''\n const hasSessionToken = cookieHeader.includes(`${sessionTokenName}=`)\n\n if (!hasSessionToken) {\n try {\n const result = await refreshOperation({ collection: userCollection, req })\n return new Response(JSON.stringify(result), { status: 200 })\n } catch (error) {\n console.error('Token refresh failed:', error)\n return new Response(JSON.stringify({ message: 'Token refresh failed' }), { status: 401 })\n }\n }\n\n // @ts-ignore - @TODO, fix type of .api\n const session = await betterAuth.api.getSession({\n headers: req.headers,\n query: { disableCookieCache: true },\n })\n\n if (!session?.session?.userId) {\n return new Response(JSON.stringify({ message: 'No user in session' }), { status: 401 })\n }\n\n const user = await payload.findByID({\n collection: userSlug as string,\n id: session.session.userId,\n })\n\n if (!user) {\n return new Response(JSON.stringify({ message: 'No user found' }), { status: 401 })\n }\n\n const cookieCacheFields = getFieldsToSign({\n collectionConfig: userCollection.config,\n email: user.email,\n user: user as User,\n })\n\n const responseData = {\n refreshedToken: null,\n setCookie: !!authContext.options.session?.cookieCache?.enabled,\n strategy: 'better-auth',\n user: { ...user, collection: userSlug },\n }\n\n const response = new Response(JSON.stringify(responseData), {\n status: 200,\n })\n\n const ctx = {\n context: authContext,\n setCookie(name, value, options) {\n const path = options?.path || '/'\n const maxAge = options?.maxAge ? `; Max-Age=${options.maxAge}` : ''\n const httpOnly = options?.httpOnly ? '; HttpOnly' : ''\n const secure = options?.secure ? '; Secure' : ''\n const sameSite = options?.sameSite ? `; SameSite=${options.sameSite}` : '; SameSite=Lax'\n\n response.headers.set(\n 'Set-Cookie',\n `${name}=${value}; Path=${path}${maxAge}${httpOnly}${secure}${sameSite}`,\n )\n return name\n },\n } as GenericEndpointContext\n\n await setCookieCache(ctx, {\n session: session.session,\n user: cookieCacheFields as any,\n })\n\n return response\n },\n }\n\n return endpoint as unknown as Endpoint\n}\n"],"names":["setCookieCache","getFieldsToSign","refreshOperation","getPayloadAuth","getRefreshTokenEndpoint","options","userSlug","endpoint","path","method","handler","req","payload","config","betterAuth","authContext","$context","userCollection","collections","Response","JSON","stringify","message","status","sessionTokenName","authCookies","sessionToken","name","cookieHeader","headers","get","hasSessionToken","includes","result","collection","error","console","session","api","getSession","query","disableCookieCache","userId","user","findByID","id","cookieCacheFields","collectionConfig","email","responseData","refreshedToken","setCookie","cookieCache","enabled","strategy","response","ctx","context","value","maxAge","httpOnly","secure","sameSite","set"],"mappings":"AAAA,SAASA,cAAc,QAAQ,sBAAqB;AACpD,SAAwCC,eAAe,EAAEC,gBAAgB,QAAc,UAAS;AAGhG,SAASC,cAAc,QAAQ,gCAA+B;AAM9D,OAAO,MAAMC,0BAA0B,CAACC;IACtC,MAAMC,WAAWD,SAASC;IAE1B,MAAMC,WAAmC;QACvCC,MAAM;QACNC,QAAQ;QACRC,SAAS,OAAOC;YACd,MAAMC,UAAU,MAAMT,eAAeQ,IAAIC,OAAO,CAACC,MAAM;YACvD,MAAMC,aAAaF,QAAQE,UAAU;YACrC,MAAMC,cAAc,MAAMD,YAAYE;YACtC,MAAMC,iBAAiBL,QAAQM,WAAW,CAACZ,SAA2B;YAEtE,IAAI,CAACQ,cAAc,CAACC,aAAa;gBAC/B,OAAO,IAAII,SAASC,KAAKC,SAAS,CAAC;oBAAEC,SAAS;gBAA6B,IAAI;oBAC7EC,QAAQ;gBACV;YACF;YAEA,MAAMC,mBAAmBT,YAAYU,WAAW,CAACC,YAAY,CAACC,IAAI;YAClE,MAAMC,eAAejB,IAAIkB,OAAO,CAACC,GAAG,CAAC,aAAa;YAClD,MAAMC,kBAAkBH,aAAaI,QAAQ,CAAC,GAAGR,iBAAiB,CAAC,CAAC;YAEpE,IAAI,CAACO,iBAAiB;gBACpB,IAAI;oBACF,MAAME,SAAS,MAAM/B,iBAAiB;wBAAEgC,YAAYjB;wBAAgBN;oBAAI;oBACxE,OAAO,IAAIQ,SAASC,KAAKC,SAAS,CAACY,SAAS;wBAAEV,QAAQ;oBAAI;gBAC5D,EAAE,OAAOY,OAAO;oBACdC,QAAQD,KAAK,CAAC,yBAAyBA;oBACvC,OAAO,IAAIhB,SAASC,KAAKC,SAAS,CAAC;wBAAEC,SAAS;oBAAuB,IAAI;wBAAEC,QAAQ;oBAAI;gBACzF;YACF;YAEA,uCAAuC;YACvC,MAAMc,UAAU,MAAMvB,WAAWwB,GAAG,CAACC,UAAU,CAAC;gBAC9CV,SAASlB,IAAIkB,OAAO;gBACpBW,OAAO;oBAAEC,oBAAoB;gBAAK;YACpC;YAEA,IAAI,CAACJ,SAASA,SAASK,QAAQ;gBAC7B,OAAO,IAAIvB,SAASC,KAAKC,SAAS,CAAC;oBAAEC,SAAS;gBAAqB,IAAI;oBAAEC,QAAQ;gBAAI;YACvF;YAEA,MAAMoB,OAAO,MAAM/B,QAAQgC,QAAQ,CAAC;gBAClCV,YAAY5B;gBACZuC,IAAIR,QAAQA,OAAO,CAACK,MAAM;YAC5B;YAEA,IAAI,CAACC,MAAM;gBACT,OAAO,IAAIxB,SAASC,KAAKC,SAAS,CAAC;oBAAEC,SAAS;gBAAgB,IAAI;oBAAEC,QAAQ;gBAAI;YAClF;YAEA,MAAMuB,oBAAoB7C,gBAAgB;gBACxC8C,kBAAkB9B,eAAeJ,MAAM;gBACvCmC,OAAOL,KAAKK,KAAK;gBACjBL,MAAMA;YACR;YAEA,MAAMM,eAAe;gBACnBC,gBAAgB;gBAChBC,WAAW,CAAC,CAACpC,YAAYV,OAAO,CAACgC,OAAO,EAAEe,aAAaC;gBACvDC,UAAU;gBACVX,MAAM;oBAAE,GAAGA,IAAI;oBAAET,YAAY5B;gBAAS;YACxC;YAEA,MAAMiD,WAAW,IAAIpC,SAASC,KAAKC,SAAS,CAAC4B,eAAe;gBAC1D1B,QAAQ;YACV;YAEA,MAAMiC,MAAM;gBACVC,SAAS1C;gBACToC,WAAUxB,IAAI,EAAE+B,KAAK,EAAErD,OAAO;oBAC5B,MAAMG,OAAOH,SAASG,QAAQ;oBAC9B,MAAMmD,SAAStD,SAASsD,SAAS,CAAC,UAAU,EAAEtD,QAAQsD,MAAM,EAAE,GAAG;oBACjE,MAAMC,WAAWvD,SAASuD,WAAW,eAAe;oBACpD,MAAMC,SAASxD,SAASwD,SAAS,aAAa;oBAC9C,MAAMC,WAAWzD,SAASyD,WAAW,CAAC,WAAW,EAAEzD,QAAQyD,QAAQ,EAAE,GAAG;oBAExEP,SAAS1B,OAAO,CAACkC,GAAG,CAClB,cACA,GAAGpC,KAAK,CAAC,EAAE+B,MAAM,OAAO,EAAElD,OAAOmD,SAASC,WAAWC,SAASC,UAAU;oBAE1E,OAAOnC;gBACT;YACF;YAEA,MAAM3B,eAAewD,KAAK;gBACxBnB,SAASA,QAAQA,OAAO;gBACxBM,MAAMG;YACR;YAEA,OAAOS;QACT;IACF;IAEA,OAAOhD;AACT,EAAC"}
@@ -0,0 +1,11 @@
1
+ import { CollectionAfterLoginHook } from 'payload';
2
+ type AfterLoginOptions = {
3
+ usersCollectionSlug: string;
4
+ sessionsCollectionSlug: string;
5
+ };
6
+ /**
7
+ * This hook is used to sync the admin login token with better-auth session token
8
+ * It also creates a new session in better-auth
9
+ */
10
+ export declare const getAfterLoginHook: (options: AfterLoginOptions) => CollectionAfterLoginHook;
11
+ export {};
@@ -0,0 +1,71 @@
1
+ import { generateId } from 'better-auth';
2
+ import { createAuthMiddleware } from 'better-auth/api';
3
+ import { setCookieCache } from 'better-auth/cookies';
4
+ import { parseSetCookie } from 'next/dist/compiled/@edge-runtime/cookies';
5
+ import { cookies } from 'next/headers';
6
+ import { getPayloadAuth } from '../../../lib/get-payload-auth';
7
+ import { getIp } from '../../../helpers/get-ip';
8
+ import { prepareSessionData } from '../../../lib/prepare-session-data';
9
+ /**
10
+ * This hook is used to sync the admin login token with better-auth session token
11
+ * It also creates a new session in better-auth
12
+ */ export const getAfterLoginHook = (options)=>{
13
+ const hook = async ({ collection, context, req, token, user })=>{
14
+ const config = req.payload.config;
15
+ const payload = await getPayloadAuth(config);
16
+ const cookieStore = await cookies();
17
+ const authContext = await payload.betterAuth.$context;
18
+ const sessionExpiration = payload.betterAuth.options.session?.expiresIn || 60 * 60 * 24 * 7 // 7 days
19
+ ;
20
+ // we can't use internal adapter as we can cause a race condition unless we pass req to the payload.create
21
+ const session = await payload.create({
22
+ collection: options.sessionsCollectionSlug,
23
+ data: {
24
+ ipAddress: getIp(req.headers, payload.betterAuth.options) || '',
25
+ userAgent: req.headers?.get('user-agent') || '',
26
+ user: user.id,
27
+ token: generateId(32),
28
+ expiresAt: new Date(Date.now() + sessionExpiration * 1000)
29
+ },
30
+ req
31
+ });
32
+ const betterAuthHandleRequest = createAuthMiddleware(async (ctx)=>{
33
+ ctx.context = {
34
+ ...authContext,
35
+ user: user
36
+ };
37
+ await ctx.setSignedCookie(ctx.context.authCookies.sessionToken.name, session.token, ctx.context.secret, ctx.context.authCookies.sessionToken.options);
38
+ const filteredSessionData = await prepareSessionData({
39
+ newSession: {
40
+ session,
41
+ user
42
+ },
43
+ payloadConfig: config,
44
+ collectionSlugs: {
45
+ userCollectionSlug: options.usersCollectionSlug,
46
+ sessionCollectionSlug: options.sessionsCollectionSlug
47
+ }
48
+ });
49
+ await setCookieCache(ctx, filteredSessionData);
50
+ if ('responseHeaders' in ctx) {
51
+ return ctx.responseHeaders;
52
+ }
53
+ return null;
54
+ });
55
+ const responseHeaders = await betterAuthHandleRequest(req);
56
+ const responseCookies = responseHeaders?.getSetCookie().map((cookie)=>parseSetCookie(cookie)).filter(Boolean);
57
+ if (responseCookies) {
58
+ for (const cookieData of responseCookies){
59
+ const { name, value, ...options } = cookieData;
60
+ cookieStore.set({
61
+ ...options,
62
+ name,
63
+ value: decodeURIComponent(value)
64
+ });
65
+ }
66
+ }
67
+ };
68
+ return hook;
69
+ };
70
+
71
+ //# sourceMappingURL=after-login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/plugin/collections/users/hooks/after-login.ts"],"sourcesContent":["import { generateId, Session } from 'better-auth'\nimport { createAuthMiddleware } from 'better-auth/api'\nimport { setCookieCache } from 'better-auth/cookies'\nimport { parseSetCookie, type ResponseCookie } from 'next/dist/compiled/@edge-runtime/cookies'\nimport { cookies } from 'next/headers'\nimport { CollectionAfterLoginHook } from 'payload'\nimport { getPayloadAuth } from '../../../lib/get-payload-auth'\nimport { getIp } from '../../../helpers/get-ip'\nimport { prepareSessionData } from '../../../lib/prepare-session-data'\n\ntype AfterLoginOptions = {\n usersCollectionSlug: string\n sessionsCollectionSlug: string\n}\n\n/**\n * This hook is used to sync the admin login token with better-auth session token\n * It also creates a new session in better-auth\n */\nexport const getAfterLoginHook = (options: AfterLoginOptions): CollectionAfterLoginHook => {\n const hook: CollectionAfterLoginHook = async ({ collection, context, req, token, user }) => {\n const config = req.payload.config\n const payload = await getPayloadAuth(config)\n const cookieStore = await cookies()\n const authContext = await payload.betterAuth.$context\n\n const sessionExpiration = payload.betterAuth.options.session?.expiresIn || 60 * 60 * 24 * 7 // 7 days\n // we can't use internal adapter as we can cause a race condition unless we pass req to the payload.create\n const session = (await payload.create({\n collection: options.sessionsCollectionSlug,\n data: {\n ipAddress: getIp(req.headers, payload.betterAuth.options) || '',\n userAgent: req.headers?.get('user-agent') || '',\n user: user.id,\n token: generateId(32),\n expiresAt: new Date(Date.now() + sessionExpiration * 1000),\n },\n req,\n })) as Session\n\n const betterAuthHandleRequest = createAuthMiddleware(async (ctx): Promise<Headers | null> => {\n ctx.context = { ...authContext, user: user }\n await ctx.setSignedCookie(\n ctx.context.authCookies.sessionToken.name,\n session.token,\n ctx.context.secret,\n ctx.context.authCookies.sessionToken.options,\n )\n const filteredSessionData = await prepareSessionData({\n newSession: { session, user },\n payloadConfig: config,\n collectionSlugs: {\n userCollectionSlug: options.usersCollectionSlug,\n sessionCollectionSlug: options.sessionsCollectionSlug,\n },\n })\n await setCookieCache(ctx, filteredSessionData as any)\n if ('responseHeaders' in ctx) {\n return ctx.responseHeaders as Headers\n }\n return null\n })\n\n const responseHeaders = await betterAuthHandleRequest(req)\n const responseCookies = responseHeaders\n ?.getSetCookie()\n .map((cookie) => parseSetCookie(cookie))\n .filter(Boolean) as ResponseCookie[]\n\n if (responseCookies) {\n for (const cookieData of responseCookies) {\n const { name, value, ...options } = cookieData\n cookieStore.set({\n ...options,\n name,\n value: decodeURIComponent(value),\n })\n }\n }\n }\n\n return hook as CollectionAfterLoginHook\n}\n"],"names":["generateId","createAuthMiddleware","setCookieCache","parseSetCookie","cookies","getPayloadAuth","getIp","prepareSessionData","getAfterLoginHook","options","hook","collection","context","req","token","user","config","payload","cookieStore","authContext","betterAuth","$context","sessionExpiration","session","expiresIn","create","sessionsCollectionSlug","data","ipAddress","headers","userAgent","get","id","expiresAt","Date","now","betterAuthHandleRequest","ctx","setSignedCookie","authCookies","sessionToken","name","secret","filteredSessionData","newSession","payloadConfig","collectionSlugs","userCollectionSlug","usersCollectionSlug","sessionCollectionSlug","responseHeaders","responseCookies","getSetCookie","map","cookie","filter","Boolean","cookieData","value","set","decodeURIComponent"],"mappings":"AAAA,SAASA,UAAU,QAAiB,cAAa;AACjD,SAASC,oBAAoB,QAAQ,kBAAiB;AACtD,SAASC,cAAc,QAAQ,sBAAqB;AACpD,SAASC,cAAc,QAA6B,2CAA0C;AAC9F,SAASC,OAAO,QAAQ,eAAc;AAEtC,SAASC,cAAc,QAAQ,gCAA+B;AAC9D,SAASC,KAAK,QAAQ,0BAAyB;AAC/C,SAASC,kBAAkB,QAAQ,oCAAmC;AAOtE;;;CAGC,GACD,OAAO,MAAMC,oBAAoB,CAACC;IAChC,MAAMC,OAAiC,OAAO,EAAEC,UAAU,EAAEC,OAAO,EAAEC,GAAG,EAAEC,KAAK,EAAEC,IAAI,EAAE;QACrF,MAAMC,SAASH,IAAII,OAAO,CAACD,MAAM;QACjC,MAAMC,UAAU,MAAMZ,eAAeW;QACrC,MAAME,cAAc,MAAMd;QAC1B,MAAMe,cAAc,MAAMF,QAAQG,UAAU,CAACC,QAAQ;QAErD,MAAMC,oBAAoBL,QAAQG,UAAU,CAACX,OAAO,CAACc,OAAO,EAAEC,aAAa,KAAK,KAAK,KAAK,EAAE,SAAS;;QACrG,0GAA0G;QAC1G,MAAMD,UAAW,MAAMN,QAAQQ,MAAM,CAAC;YACpCd,YAAYF,QAAQiB,sBAAsB;YAC1CC,MAAM;gBACJC,WAAWtB,MAAMO,IAAIgB,OAAO,EAAEZ,QAAQG,UAAU,CAACX,OAAO,KAAK;gBAC7DqB,WAAWjB,IAAIgB,OAAO,EAAEE,IAAI,iBAAiB;gBAC7ChB,MAAMA,KAAKiB,EAAE;gBACblB,OAAOd,WAAW;gBAClBiC,WAAW,IAAIC,KAAKA,KAAKC,GAAG,KAAKb,oBAAoB;YACvD;YACAT;QACF;QAEA,MAAMuB,0BAA0BnC,qBAAqB,OAAOoC;YAC1DA,IAAIzB,OAAO,GAAG;gBAAE,GAAGO,WAAW;gBAAEJ,MAAMA;YAAK;YAC3C,MAAMsB,IAAIC,eAAe,CACvBD,IAAIzB,OAAO,CAAC2B,WAAW,CAACC,YAAY,CAACC,IAAI,EACzClB,QAAQT,KAAK,EACbuB,IAAIzB,OAAO,CAAC8B,MAAM,EAClBL,IAAIzB,OAAO,CAAC2B,WAAW,CAACC,YAAY,CAAC/B,OAAO;YAE9C,MAAMkC,sBAAsB,MAAMpC,mBAAmB;gBACnDqC,YAAY;oBAAErB;oBAASR;gBAAK;gBAC5B8B,eAAe7B;gBACf8B,iBAAiB;oBACfC,oBAAoBtC,QAAQuC,mBAAmB;oBAC/CC,uBAAuBxC,QAAQiB,sBAAsB;gBACvD;YACF;YACA,MAAMxB,eAAemC,KAAKM;YAC1B,IAAI,qBAAqBN,KAAK;gBAC5B,OAAOA,IAAIa,eAAe;YAC5B;YACA,OAAO;QACT;QAEA,MAAMA,kBAAkB,MAAMd,wBAAwBvB;QACtD,MAAMsC,kBAAkBD,iBACpBE,eACDC,IAAI,CAACC,SAAWnD,eAAemD,SAC/BC,OAAOC;QAEV,IAAIL,iBAAiB;YACnB,KAAK,MAAMM,cAAcN,gBAAiB;gBACxC,MAAM,EAAEV,IAAI,EAAEiB,KAAK,EAAE,GAAGjD,SAAS,GAAGgD;gBACpCvC,YAAYyC,GAAG,CAAC;oBACd,GAAGlD,OAAO;oBACVgC;oBACAiB,OAAOE,mBAAmBF;gBAC5B;YACF;QACF;IACF;IAEA,OAAOhD;AACT,EAAC"}
@@ -0,0 +1,6 @@
1
+ import type { CollectionAfterLogoutHook } from 'payload';
2
+ type AfterLogoutOptions = {
3
+ sessionsCollectionSlug: string;
4
+ };
5
+ export declare const getAfterLogoutHook: (options: AfterLogoutOptions) => CollectionAfterLogoutHook;
6
+ export {};
@@ -0,0 +1,49 @@
1
+ import { cookies } from 'next/headers';
2
+ import { getPayloadAuth } from '../../../lib/get-payload-auth';
3
+ export const getAfterLogoutHook = (options)=>{
4
+ const hook = async ({ req })=>{
5
+ const cookieStore = await cookies();
6
+ const payload = await getPayloadAuth(req.payload.config);
7
+ const authContext = await payload.betterAuth.$context;
8
+ const sessionTokenName = authContext.authCookies.sessionToken.name;
9
+ const sessionDataName = authContext.authCookies.sessionData.name;
10
+ const dontRememberTokenName = authContext.authCookies.dontRememberToken.name;
11
+ const sessionCookieValue = cookieStore.get(sessionTokenName)?.value;
12
+ if (sessionCookieValue) {
13
+ const payload = req.payload;
14
+ const [token] = sessionCookieValue.split('.');
15
+ const { docs: sessions } = await payload.find({
16
+ collection: options.sessionsCollectionSlug,
17
+ where: {
18
+ token: {
19
+ equals: token
20
+ }
21
+ },
22
+ limit: 1
23
+ });
24
+ const session = sessions.at(0);
25
+ if (session) {
26
+ await payload.delete({
27
+ collection: options.sessionsCollectionSlug,
28
+ id: session.id
29
+ });
30
+ }
31
+ }
32
+ const baseMultiSessionName = sessionTokenName + '_multi';
33
+ const multiSessionCookies = cookieStore.getAll();
34
+ multiSessionCookies.forEach((cookie)=>{
35
+ if (cookie.name.startsWith(baseMultiSessionName)) {
36
+ cookieStore.delete(cookie.name);
37
+ }
38
+ });
39
+ //TODO: this is a hack to delete the admin session cookie
40
+ // we need to find a better way to do this (BETTER AUTH HARDCODED THIS)
41
+ cookieStore.delete('admin_session');
42
+ cookieStore.delete(sessionTokenName);
43
+ cookieStore.delete(sessionDataName);
44
+ cookieStore.delete(dontRememberTokenName);
45
+ };
46
+ return hook;
47
+ };
48
+
49
+ //# sourceMappingURL=after-logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/plugin/collections/users/hooks/after-logout.ts"],"sourcesContent":["import { cookies } from 'next/headers'\nimport type { CollectionAfterLogoutHook } from 'payload'\nimport type { CollectionHookWithBetterAuth } from '../../../types'\nimport { getPayloadAuth } from '../../../lib/get-payload-auth'\n\ntype CollectionAfterLogoutHookWithBetterAuth =\n CollectionHookWithBetterAuth<CollectionAfterLogoutHook>\n\ntype AfterLogoutOptions = {\n sessionsCollectionSlug: string\n}\n\nexport const getAfterLogoutHook = (options: AfterLogoutOptions): CollectionAfterLogoutHook => {\n const hook: CollectionAfterLogoutHookWithBetterAuth = async ({ req }) => {\n const cookieStore = await cookies()\n const payload = await getPayloadAuth(req.payload.config)\n const authContext = await payload.betterAuth.$context\n const sessionTokenName = authContext.authCookies.sessionToken.name\n\n const sessionDataName = authContext.authCookies.sessionData.name\n const dontRememberTokenName = authContext.authCookies.dontRememberToken.name\n\n const sessionCookieValue = cookieStore.get(sessionTokenName)?.value\n if (sessionCookieValue) {\n const payload = req.payload\n const [token] = sessionCookieValue.split('.')\n const { docs: sessions } = await payload.find({\n collection: options.sessionsCollectionSlug,\n where: {\n token: { equals: token },\n },\n limit: 1,\n })\n const session = sessions.at(0)\n if (session) {\n await payload.delete({\n collection: options.sessionsCollectionSlug,\n id: session.id,\n })\n }\n }\n\n const baseMultiSessionName = sessionTokenName + '_multi'\n const multiSessionCookies = cookieStore.getAll()\n multiSessionCookies.forEach((cookie) => {\n if (cookie.name.startsWith(baseMultiSessionName)) {\n cookieStore.delete(cookie.name)\n }\n })\n\n //TODO: this is a hack to delete the admin session cookie\n // we need to find a better way to do this (BETTER AUTH HARDCODED THIS)\n cookieStore.delete('admin_session')\n\n cookieStore.delete(sessionTokenName)\n cookieStore.delete(sessionDataName)\n cookieStore.delete(dontRememberTokenName)\n }\n\n return hook as CollectionAfterLogoutHook\n}\n"],"names":["cookies","getPayloadAuth","getAfterLogoutHook","options","hook","req","cookieStore","payload","config","authContext","betterAuth","$context","sessionTokenName","authCookies","sessionToken","name","sessionDataName","sessionData","dontRememberTokenName","dontRememberToken","sessionCookieValue","get","value","token","split","docs","sessions","find","collection","sessionsCollectionSlug","where","equals","limit","session","at","delete","id","baseMultiSessionName","multiSessionCookies","getAll","forEach","cookie","startsWith"],"mappings":"AAAA,SAASA,OAAO,QAAQ,eAAc;AAGtC,SAASC,cAAc,QAAQ,gCAA+B;AAS9D,OAAO,MAAMC,qBAAqB,CAACC;IACjC,MAAMC,OAAgD,OAAO,EAAEC,GAAG,EAAE;QAClE,MAAMC,cAAc,MAAMN;QAC1B,MAAMO,UAAU,MAAMN,eAAeI,IAAIE,OAAO,CAACC,MAAM;QACvD,MAAMC,cAAc,MAAMF,QAAQG,UAAU,CAACC,QAAQ;QACrD,MAAMC,mBAAmBH,YAAYI,WAAW,CAACC,YAAY,CAACC,IAAI;QAElE,MAAMC,kBAAkBP,YAAYI,WAAW,CAACI,WAAW,CAACF,IAAI;QAChE,MAAMG,wBAAwBT,YAAYI,WAAW,CAACM,iBAAiB,CAACJ,IAAI;QAE5E,MAAMK,qBAAqBd,YAAYe,GAAG,CAACT,mBAAmBU;QAC9D,IAAIF,oBAAoB;YACtB,MAAMb,UAAUF,IAAIE,OAAO;YAC3B,MAAM,CAACgB,MAAM,GAAGH,mBAAmBI,KAAK,CAAC;YACzC,MAAM,EAAEC,MAAMC,QAAQ,EAAE,GAAG,MAAMnB,QAAQoB,IAAI,CAAC;gBAC5CC,YAAYzB,QAAQ0B,sBAAsB;gBAC1CC,OAAO;oBACLP,OAAO;wBAAEQ,QAAQR;oBAAM;gBACzB;gBACAS,OAAO;YACT;YACA,MAAMC,UAAUP,SAASQ,EAAE,CAAC;YAC5B,IAAID,SAAS;gBACX,MAAM1B,QAAQ4B,MAAM,CAAC;oBACnBP,YAAYzB,QAAQ0B,sBAAsB;oBAC1CO,IAAIH,QAAQG,EAAE;gBAChB;YACF;QACF;QAEA,MAAMC,uBAAuBzB,mBAAmB;QAChD,MAAM0B,sBAAsBhC,YAAYiC,MAAM;QAC9CD,oBAAoBE,OAAO,CAAC,CAACC;YAC3B,IAAIA,OAAO1B,IAAI,CAAC2B,UAAU,CAACL,uBAAuB;gBAChD/B,YAAY6B,MAAM,CAACM,OAAO1B,IAAI;YAChC;QACF;QAEA,yDAAyD;QACzD,uEAAuE;QACvET,YAAY6B,MAAM,CAAC;QAEnB7B,YAAY6B,MAAM,CAACvB;QACnBN,YAAY6B,MAAM,CAACnB;QACnBV,YAAY6B,MAAM,CAACjB;IACrB;IAEA,OAAOd;AACT,EAAC"}
@@ -0,0 +1,5 @@
1
+ import { CollectionBeforeLoginHook } from 'payload';
2
+ /**
3
+ * This hook blocks login attempts if email verification is required and the user's email is not verified
4
+ */
5
+ export declare const getBeforeLoginHook: () => CollectionBeforeLoginHook;
@@ -0,0 +1,18 @@
1
+ import { APIError } from 'payload';
2
+ import { getPayloadAuth } from '../../../lib/get-payload-auth';
3
+ /**
4
+ * This hook blocks login attempts if email verification is required and the user's email is not verified
5
+ */ export const getBeforeLoginHook = ()=>{
6
+ const hook = async ({ req, user })=>{
7
+ const config = req.payload.config;
8
+ const payload = await getPayloadAuth(config);
9
+ const requireEmailVerification = payload.betterAuth.options.emailAndPassword?.requireEmailVerification ?? false;
10
+ if (requireEmailVerification && !user.emailVerified) {
11
+ throw new APIError('Email verification required. Please verify your email before logging in.', 403);
12
+ }
13
+ return user;
14
+ };
15
+ return hook;
16
+ };
17
+
18
+ //# sourceMappingURL=before-login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/plugin/collections/users/hooks/before-login.ts"],"sourcesContent":["import { APIError, CollectionBeforeLoginHook } from 'payload'\nimport { getPayloadAuth } from '../../../lib/get-payload-auth'\n\n/**\n * This hook blocks login attempts if email verification is required and the user's email is not verified\n */\nexport const getBeforeLoginHook = (): CollectionBeforeLoginHook => {\n const hook: CollectionBeforeLoginHook = async ({ req, user }) => {\n const config = req.payload.config\n const payload = await getPayloadAuth(config)\n\n const requireEmailVerification =\n payload.betterAuth.options.emailAndPassword?.requireEmailVerification ?? false\n\n if (requireEmailVerification && !user.emailVerified) {\n throw new APIError(\n 'Email verification required. Please verify your email before logging in.',\n 403,\n )\n }\n\n return user\n }\n\n return hook\n}\n"],"names":["APIError","getPayloadAuth","getBeforeLoginHook","hook","req","user","config","payload","requireEmailVerification","betterAuth","options","emailAndPassword","emailVerified"],"mappings":"AAAA,SAASA,QAAQ,QAAmC,UAAS;AAC7D,SAASC,cAAc,QAAQ,gCAA+B;AAE9D;;CAEC,GACD,OAAO,MAAMC,qBAAqB;IAChC,MAAMC,OAAkC,OAAO,EAAEC,GAAG,EAAEC,IAAI,EAAE;QAC1D,MAAMC,SAASF,IAAIG,OAAO,CAACD,MAAM;QACjC,MAAMC,UAAU,MAAMN,eAAeK;QAErC,MAAME,2BACJD,QAAQE,UAAU,CAACC,OAAO,CAACC,gBAAgB,EAAEH,4BAA4B;QAE3E,IAAIA,4BAA4B,CAACH,KAAKO,aAAa,EAAE;YACnD,MAAM,IAAIZ,SACR,4EACA;QAEJ;QAEA,OAAOK;IACT;IAEA,OAAOF;AACT,EAAC"}
@@ -0,0 +1,5 @@
1
+ import type { CollectionAfterDeleteHook } from 'payload';
2
+ import type { CollectionHookWithBetterAuth } from '../../../types';
3
+ type CollectionAfterDeleteHookWithBetterAuth = CollectionHookWithBetterAuth<CollectionAfterDeleteHook>;
4
+ export declare const cleanUpUserAfterDelete: CollectionAfterDeleteHookWithBetterAuth;
5
+ export {};
@@ -0,0 +1,33 @@
1
+ export const cleanUpUserAfterDelete = async ({ doc, req })=>{
2
+ try {
3
+ const { payload } = req;
4
+ const betterAuthContext = await payload.betterAuth.$context;
5
+ const userId = doc.id;
6
+ const beforeDelete = betterAuthContext.options.user?.deleteUser?.beforeDelete;
7
+ if (typeof beforeDelete === 'function') {
8
+ await beforeDelete(doc, req);
9
+ }
10
+ await betterAuthContext.internalAdapter.deleteSessions(userId);
11
+ await betterAuthContext.internalAdapter.deleteAccounts(userId);
12
+ if (payload.collections.verifications) {
13
+ await payload.delete({
14
+ collection: payload.collections.verifications.config.slug,
15
+ where: {
16
+ value: {
17
+ like: `"${userId}"`
18
+ }
19
+ }
20
+ });
21
+ }
22
+ const afterDelete = betterAuthContext.options.user?.deleteUser?.afterDelete;
23
+ if (typeof afterDelete === 'function') {
24
+ await afterDelete(doc, req);
25
+ }
26
+ return doc;
27
+ } catch (error) {
28
+ console.error('Error in user afterDelete hook:', error);
29
+ return doc;
30
+ }
31
+ };
32
+
33
+ //# sourceMappingURL=clean-up-user-after-delete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/plugin/collections/users/hooks/clean-up-user-after-delete.ts"],"sourcesContent":["import type { CollectionAfterDeleteHook } from 'payload'\nimport type { CollectionHookWithBetterAuth } from '../../../types'\n\ntype CollectionAfterDeleteHookWithBetterAuth =\n CollectionHookWithBetterAuth<CollectionAfterDeleteHook>\n\nexport const cleanUpUserAfterDelete: CollectionAfterDeleteHookWithBetterAuth = async ({\n doc,\n req,\n}) => {\n try {\n const { payload } = req\n const betterAuthContext = await payload.betterAuth.$context\n const userId = doc.id\n const beforeDelete = betterAuthContext.options.user?.deleteUser?.beforeDelete\n if (typeof beforeDelete === 'function') {\n await beforeDelete(doc, req as Request)\n }\n await betterAuthContext.internalAdapter.deleteSessions(userId)\n await betterAuthContext.internalAdapter.deleteAccounts(userId)\n if (payload.collections.verifications) {\n await payload.delete({\n collection: payload.collections.verifications.config.slug,\n where: {\n value: {\n like: `\"${userId}\"`,\n },\n },\n })\n }\n const afterDelete = betterAuthContext.options.user?.deleteUser?.afterDelete\n if (typeof afterDelete === 'function') {\n await afterDelete(doc, req as Request)\n }\n return doc\n } catch (error) {\n console.error('Error in user afterDelete hook:', error)\n return doc\n }\n}\n"],"names":["cleanUpUserAfterDelete","doc","req","payload","betterAuthContext","betterAuth","$context","userId","id","beforeDelete","options","user","deleteUser","internalAdapter","deleteSessions","deleteAccounts","collections","verifications","delete","collection","config","slug","where","value","like","afterDelete","error","console"],"mappings":"AAMA,OAAO,MAAMA,yBAAkE,OAAO,EACpFC,GAAG,EACHC,GAAG,EACJ;IACC,IAAI;QACF,MAAM,EAAEC,OAAO,EAAE,GAAGD;QACpB,MAAME,oBAAoB,MAAMD,QAAQE,UAAU,CAACC,QAAQ;QAC3D,MAAMC,SAASN,IAAIO,EAAE;QACrB,MAAMC,eAAeL,kBAAkBM,OAAO,CAACC,IAAI,EAAEC,YAAYH;QACjE,IAAI,OAAOA,iBAAiB,YAAY;YACtC,MAAMA,aAAaR,KAAKC;QAC1B;QACA,MAAME,kBAAkBS,eAAe,CAACC,cAAc,CAACP;QACvD,MAAMH,kBAAkBS,eAAe,CAACE,cAAc,CAACR;QACvD,IAAIJ,QAAQa,WAAW,CAACC,aAAa,EAAE;YACrC,MAAMd,QAAQe,MAAM,CAAC;gBACnBC,YAAYhB,QAAQa,WAAW,CAACC,aAAa,CAACG,MAAM,CAACC,IAAI;gBACzDC,OAAO;oBACLC,OAAO;wBACLC,MAAM,CAAC,CAAC,EAAEjB,OAAO,CAAC,CAAC;oBACrB;gBACF;YACF;QACF;QACA,MAAMkB,cAAcrB,kBAAkBM,OAAO,CAACC,IAAI,EAAEC,YAAYa;QAChE,IAAI,OAAOA,gBAAgB,YAAY;YACrC,MAAMA,YAAYxB,KAAKC;QACzB;QACA,OAAOD;IACT,EAAE,OAAOyB,OAAO;QACdC,QAAQD,KAAK,CAAC,mCAAmCA;QACjD,OAAOzB;IACT;AACF,EAAC"}
@@ -0,0 +1,2 @@
1
+ import { CollectionBeforeChangeHook } from 'payload';
2
+ export declare const onVerifiedChange: CollectionBeforeChangeHook;
@@ -0,0 +1,14 @@
1
+ export const onVerifiedChange = async ({ data, originalDoc })=>{
2
+ const isVerifiedChangingToTrue = Boolean(data._verified) && !Boolean(originalDoc?._verified);
3
+ const isEmailVerifiedChangingToTrue = Boolean(data.emailVerified) && !Boolean(originalDoc?.emailVerified);
4
+ if (!isVerifiedChangingToTrue && !isEmailVerifiedChangingToTrue) {
5
+ return data;
6
+ }
7
+ return {
8
+ ...data,
9
+ _verified: true,
10
+ emailVerified: true
11
+ };
12
+ };
13
+
14
+ //# sourceMappingURL=on-verified-change.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/plugin/collections/users/hooks/on-verified-change.ts"],"sourcesContent":["import { CollectionBeforeChangeHook } from 'payload'\n\nexport const onVerifiedChange: CollectionBeforeChangeHook = async ({ data, originalDoc }) => {\n const isVerifiedChangingToTrue = Boolean(data._verified) && !Boolean(originalDoc?._verified)\n const isEmailVerifiedChangingToTrue =\n Boolean(data.emailVerified) && !Boolean(originalDoc?.emailVerified)\n\n if (!isVerifiedChangingToTrue && !isEmailVerifiedChangingToTrue) {\n return data\n }\n\n return {\n ...data,\n _verified: true,\n emailVerified: true,\n }\n}\n"],"names":["onVerifiedChange","data","originalDoc","isVerifiedChangingToTrue","Boolean","_verified","isEmailVerifiedChangingToTrue","emailVerified"],"mappings":"AAEA,OAAO,MAAMA,mBAA+C,OAAO,EAAEC,IAAI,EAAEC,WAAW,EAAE;IACtF,MAAMC,2BAA2BC,QAAQH,KAAKI,SAAS,KAAK,CAACD,QAAQF,aAAaG;IAClF,MAAMC,gCACJF,QAAQH,KAAKM,aAAa,KAAK,CAACH,QAAQF,aAAaK;IAEvD,IAAI,CAACJ,4BAA4B,CAACG,+BAA+B;QAC/D,OAAOL;IACT;IAEA,OAAO;QACL,GAAGA,IAAI;QACPI,WAAW;QACXE,eAAe;IACjB;AACF,EAAC"}
@@ -0,0 +1,7 @@
1
+ import type { CollectionAfterChangeHook } from 'payload';
2
+ type SyncAccountOptions = {
3
+ userSlug: string;
4
+ accountSlug: string;
5
+ };
6
+ export declare const getSyncAccountHook: (options: SyncAccountOptions) => CollectionAfterChangeHook;
7
+ export {};
@@ -0,0 +1,82 @@
1
+ import { BETTER_AUTH_CONTEXT_KEY } from 'payload-auth/better-auth/adapter';
2
+ export const getSyncAccountHook = (options)=>{
3
+ const hook = async ({ doc, req, operation, context })=>{
4
+ if (context?.syncPasswordToUser) return doc;
5
+ if (operation !== 'create' && operation !== 'update') return doc;
6
+ const user = await req.payload.findByID({
7
+ collection: options.userSlug,
8
+ id: doc.id,
9
+ depth: 0,
10
+ req,
11
+ showHiddenFields: true
12
+ });
13
+ if (!user || !user.hash || !user.salt) return doc;
14
+ const passwordValue = `${user.salt}:${user.hash}`;
15
+ const userField = req.payload.betterAuth.options.account?.fields?.userId || 'userId';
16
+ if (operation === 'create' && !(BETTER_AUTH_CONTEXT_KEY in context)) {
17
+ try {
18
+ await req.payload.create({
19
+ collection: options.accountSlug,
20
+ data: {
21
+ [userField]: doc.id,
22
+ accountId: doc.id.toString(),
23
+ providerId: 'credential',
24
+ password: passwordValue,
25
+ context: {
26
+ syncAccountHook: true
27
+ }
28
+ },
29
+ req
30
+ });
31
+ } catch (error) {
32
+ console.error('Failed to create account for user:', error);
33
+ }
34
+ }
35
+ if (operation === 'update') {
36
+ try {
37
+ const accounts = await req.payload.find({
38
+ collection: options.accountSlug,
39
+ where: {
40
+ and: [
41
+ {
42
+ [userField]: {
43
+ equals: doc.id
44
+ }
45
+ },
46
+ {
47
+ providerId: {
48
+ equals: 'credential'
49
+ }
50
+ }
51
+ ]
52
+ },
53
+ req,
54
+ depth: 0,
55
+ context: {
56
+ syncAccountHook: true
57
+ }
58
+ });
59
+ const account = accounts.docs.at(0);
60
+ if (account) {
61
+ await req.payload.update({
62
+ collection: options.accountSlug,
63
+ id: account.id,
64
+ data: {
65
+ password: passwordValue
66
+ },
67
+ req,
68
+ context: {
69
+ syncAccountHook: true
70
+ }
71
+ });
72
+ }
73
+ } catch (error) {
74
+ console.error('Failed to sync hash/salt to account:', error);
75
+ }
76
+ }
77
+ return doc;
78
+ };
79
+ return hook;
80
+ };
81
+
82
+ //# sourceMappingURL=sync-account.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/plugin/collections/users/hooks/sync-account.ts"],"sourcesContent":["import type { CollectionAfterChangeHook } from 'payload'\nimport type { CollectionHookWithBetterAuth } from '../../../types'\nimport { BETTER_AUTH_CONTEXT_KEY } from 'payload-auth/better-auth/adapter'\n\ntype CollectionAfterChangeHookWithBetterAuth =\n CollectionHookWithBetterAuth<CollectionAfterChangeHook>\n\ntype SyncAccountOptions = {\n userSlug: string\n accountSlug: string\n}\n\nexport const getSyncAccountHook = (options: SyncAccountOptions): CollectionAfterChangeHook => {\n const hook: CollectionAfterChangeHookWithBetterAuth = async ({\n doc,\n req,\n operation,\n context,\n }) => {\n if (context?.syncPasswordToUser) return doc\n\n if (operation !== 'create' && operation !== 'update') return doc\n\n const user = await req.payload.findByID({\n collection: options.userSlug,\n id: doc.id,\n depth: 0,\n req,\n showHiddenFields: true,\n })\n\n if (!user || !user.hash || !user.salt) return doc\n\n const passwordValue = `${user.salt}:${user.hash}`\n const userField = req.payload.betterAuth.options.account?.fields?.userId || 'userId'\n\n if (operation === 'create' && !(BETTER_AUTH_CONTEXT_KEY in context)) {\n try {\n await req.payload.create({\n collection: options.accountSlug,\n data: {\n [userField]: doc.id,\n accountId: doc.id.toString(),\n providerId: 'credential',\n password: passwordValue,\n context: { syncAccountHook: true },\n },\n req,\n })\n } catch (error) {\n console.error('Failed to create account for user:', error)\n }\n }\n\n if (operation === 'update') {\n try {\n const accounts = await req.payload.find({\n collection: options.accountSlug,\n where: {\n and: [{ [userField]: { equals: doc.id } }, { providerId: { equals: 'credential' } }],\n },\n req,\n depth: 0,\n context: { syncAccountHook: true },\n })\n\n const account = accounts.docs.at(0)\n if (account) {\n await req.payload.update({\n collection: options.accountSlug,\n id: account.id,\n data: {\n password: passwordValue,\n },\n req,\n context: { syncAccountHook: true },\n })\n }\n } catch (error) {\n console.error('Failed to sync hash/salt to account:', error)\n }\n }\n\n return doc\n }\n\n return hook as CollectionAfterChangeHook\n}\n"],"names":["BETTER_AUTH_CONTEXT_KEY","getSyncAccountHook","options","hook","doc","req","operation","context","syncPasswordToUser","user","payload","findByID","collection","userSlug","id","depth","showHiddenFields","hash","salt","passwordValue","userField","betterAuth","account","fields","userId","create","accountSlug","data","accountId","toString","providerId","password","syncAccountHook","error","console","accounts","find","where","and","equals","docs","at","update"],"mappings":"AAEA,SAASA,uBAAuB,QAAQ,mCAAkC;AAU1E,OAAO,MAAMC,qBAAqB,CAACC;IACjC,MAAMC,OAAgD,OAAO,EAC3DC,GAAG,EACHC,GAAG,EACHC,SAAS,EACTC,OAAO,EACR;QACC,IAAIA,SAASC,oBAAoB,OAAOJ;QAExC,IAAIE,cAAc,YAAYA,cAAc,UAAU,OAAOF;QAE7D,MAAMK,OAAO,MAAMJ,IAAIK,OAAO,CAACC,QAAQ,CAAC;YACtCC,YAAYV,QAAQW,QAAQ;YAC5BC,IAAIV,IAAIU,EAAE;YACVC,OAAO;YACPV;YACAW,kBAAkB;QACpB;QAEA,IAAI,CAACP,QAAQ,CAACA,KAAKQ,IAAI,IAAI,CAACR,KAAKS,IAAI,EAAE,OAAOd;QAE9C,MAAMe,gBAAgB,GAAGV,KAAKS,IAAI,CAAC,CAAC,EAAET,KAAKQ,IAAI,EAAE;QACjD,MAAMG,YAAYf,IAAIK,OAAO,CAACW,UAAU,CAACnB,OAAO,CAACoB,OAAO,EAAEC,QAAQC,UAAU;QAE5E,IAAIlB,cAAc,YAAY,CAAEN,CAAAA,2BAA2BO,OAAM,GAAI;YACnE,IAAI;gBACF,MAAMF,IAAIK,OAAO,CAACe,MAAM,CAAC;oBACvBb,YAAYV,QAAQwB,WAAW;oBAC/BC,MAAM;wBACJ,CAACP,UAAU,EAAEhB,IAAIU,EAAE;wBACnBc,WAAWxB,IAAIU,EAAE,CAACe,QAAQ;wBAC1BC,YAAY;wBACZC,UAAUZ;wBACVZ,SAAS;4BAAEyB,iBAAiB;wBAAK;oBACnC;oBACA3B;gBACF;YACF,EAAE,OAAO4B,OAAO;gBACdC,QAAQD,KAAK,CAAC,sCAAsCA;YACtD;QACF;QAEA,IAAI3B,cAAc,UAAU;YAC1B,IAAI;gBACF,MAAM6B,WAAW,MAAM9B,IAAIK,OAAO,CAAC0B,IAAI,CAAC;oBACtCxB,YAAYV,QAAQwB,WAAW;oBAC/BW,OAAO;wBACLC,KAAK;4BAAC;gCAAE,CAAClB,UAAU,EAAE;oCAAEmB,QAAQnC,IAAIU,EAAE;gCAAC;4BAAE;4BAAG;gCAAEgB,YAAY;oCAAES,QAAQ;gCAAa;4BAAE;yBAAE;oBACtF;oBACAlC;oBACAU,OAAO;oBACPR,SAAS;wBAAEyB,iBAAiB;oBAAK;gBACnC;gBAEA,MAAMV,UAAUa,SAASK,IAAI,CAACC,EAAE,CAAC;gBACjC,IAAInB,SAAS;oBACX,MAAMjB,IAAIK,OAAO,CAACgC,MAAM,CAAC;wBACvB9B,YAAYV,QAAQwB,WAAW;wBAC/BZ,IAAIQ,QAAQR,EAAE;wBACda,MAAM;4BACJI,UAAUZ;wBACZ;wBACAd;wBACAE,SAAS;4BAAEyB,iBAAiB;wBAAK;oBACnC;gBACF;YACF,EAAE,OAAOC,OAAO;gBACdC,QAAQD,KAAK,CAAC,wCAAwCA;YACxD;QACF;QAEA,OAAO7B;IACT;IAEA,OAAOD;AACT,EAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Generates a verification URL for email verification
3
+ *
4
+ * This utility function creates a JWT token containing the user's email and
5
+ * expiration information, signs it with the provided secret, and constructs
6
+ * a verification URL with the token as a query parameter.
7
+ *
8
+ * @param userEmail - The email address of the user to verify
9
+ * @param secret - The secret used to sign the JWT
10
+ * @param expiresIn - Duration in seconds for token expiration (default: 3600)
11
+ * @param verifyRouteUrl - The base URL for the verification endpoint
12
+ * @param callbackURL - Optional callback URL after verification (default: "/")
13
+ * @returns The complete verification URL with token
14
+ *
15
+ * @example
16
+ * const url = await generateVerifyEmailUrl({
17
+ * userEmail: 'user@example.com',
18
+ * secret: 'your-secret-key',
19
+ * verifyRouteUrl: 'https://your-app.com/api/auth/verify-email',
20
+ * callbackURL: '/profile'
21
+ * });
22
+ */
23
+ export declare const generateVerifyEmailUrl: ({ userEmail, secret, expiresIn, verifyRouteUrl, callbackURL, }: {
24
+ userEmail: string;
25
+ secret: string;
26
+ expiresIn?: number;
27
+ verifyRouteUrl: string;
28
+ callbackURL?: string;
29
+ }) => Promise<string>;
@@ -0,0 +1,46 @@
1
+ import { SignJWT } from 'jose';
2
+ /**
3
+ * Generates a verification URL for email verification
4
+ *
5
+ * This utility function creates a JWT token containing the user's email and
6
+ * expiration information, signs it with the provided secret, and constructs
7
+ * a verification URL with the token as a query parameter.
8
+ *
9
+ * @param userEmail - The email address of the user to verify
10
+ * @param secret - The secret used to sign the JWT
11
+ * @param expiresIn - Duration in seconds for token expiration (default: 3600)
12
+ * @param verifyRouteUrl - The base URL for the verification endpoint
13
+ * @param callbackURL - Optional callback URL after verification (default: "/")
14
+ * @returns The complete verification URL with token
15
+ *
16
+ * @example
17
+ * const url = await generateVerifyEmailUrl({
18
+ * userEmail: 'user@example.com',
19
+ * secret: 'your-secret-key',
20
+ * verifyRouteUrl: 'https://your-app.com/api/auth/verify-email',
21
+ * callbackURL: '/profile'
22
+ * });
23
+ */ export const generateVerifyEmailUrl = async ({ userEmail, secret, expiresIn = 3600, verifyRouteUrl, callbackURL = '/' })=>{
24
+ if (!userEmail) {
25
+ throw new Error('userEmail is required to generate a verification URL');
26
+ }
27
+ if (!secret) {
28
+ throw new Error('secret is required to sign the JWT token');
29
+ }
30
+ if (!verifyRouteUrl) {
31
+ throw new Error('verifyRouteUrl is required to generate a verification URL');
32
+ }
33
+ // Create and sign the JWT token
34
+ const jwt = await new SignJWT({
35
+ email: userEmail,
36
+ iat: Math.floor(Date.now() / 1000),
37
+ exp: Math.floor(Date.now() / 1000) + expiresIn
38
+ }).setProtectedHeader({
39
+ alg: 'HS256'
40
+ }).sign(new TextEncoder().encode(secret));
41
+ // Build the verification URL
42
+ const verifyUrl = `${verifyRouteUrl}?token=${jwt}${callbackURL ? `&callbackURL=${encodeURIComponent(callbackURL)}` : ''}`;
43
+ return verifyUrl;
44
+ };
45
+
46
+ //# sourceMappingURL=generate-verify-email-url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/plugin/helpers/generate-verify-email-url.ts"],"sourcesContent":["import { SignJWT } from 'jose'\n\n/**\n * Generates a verification URL for email verification\n *\n * This utility function creates a JWT token containing the user's email and\n * expiration information, signs it with the provided secret, and constructs\n * a verification URL with the token as a query parameter.\n *\n * @param userEmail - The email address of the user to verify\n * @param secret - The secret used to sign the JWT\n * @param expiresIn - Duration in seconds for token expiration (default: 3600)\n * @param verifyRouteUrl - The base URL for the verification endpoint\n * @param callbackURL - Optional callback URL after verification (default: \"/\")\n * @returns The complete verification URL with token\n *\n * @example\n * const url = await generateVerifyEmailUrl({\n * userEmail: 'user@example.com',\n * secret: 'your-secret-key',\n * verifyRouteUrl: 'https://your-app.com/api/auth/verify-email',\n * callbackURL: '/profile'\n * });\n */\nexport const generateVerifyEmailUrl = async ({\n userEmail,\n secret,\n expiresIn = 3600,\n verifyRouteUrl,\n callbackURL = '/',\n}: {\n userEmail: string\n secret: string\n expiresIn?: number\n verifyRouteUrl: string\n callbackURL?: string\n}): Promise<string> => {\n if (!userEmail) {\n throw new Error('userEmail is required to generate a verification URL')\n }\n\n if (!secret) {\n throw new Error('secret is required to sign the JWT token')\n }\n\n if (!verifyRouteUrl) {\n throw new Error('verifyRouteUrl is required to generate a verification URL')\n }\n\n // Create and sign the JWT token\n const jwt = await new SignJWT({\n email: userEmail,\n iat: Math.floor(Date.now() / 1000),\n exp: Math.floor(Date.now() / 1000) + expiresIn,\n })\n .setProtectedHeader({ alg: 'HS256' })\n .sign(new TextEncoder().encode(secret))\n\n // Build the verification URL\n const verifyUrl = `${verifyRouteUrl}?token=${jwt}${callbackURL ? `&callbackURL=${encodeURIComponent(callbackURL)}` : ''}`\n\n return verifyUrl\n}\n"],"names":["SignJWT","generateVerifyEmailUrl","userEmail","secret","expiresIn","verifyRouteUrl","callbackURL","Error","jwt","email","iat","Math","floor","Date","now","exp","setProtectedHeader","alg","sign","TextEncoder","encode","verifyUrl","encodeURIComponent"],"mappings":"AAAA,SAASA,OAAO,QAAQ,OAAM;AAE9B;;;;;;;;;;;;;;;;;;;;;CAqBC,GACD,OAAO,MAAMC,yBAAyB,OAAO,EAC3CC,SAAS,EACTC,MAAM,EACNC,YAAY,IAAI,EAChBC,cAAc,EACdC,cAAc,GAAG,EAOlB;IACC,IAAI,CAACJ,WAAW;QACd,MAAM,IAAIK,MAAM;IAClB;IAEA,IAAI,CAACJ,QAAQ;QACX,MAAM,IAAII,MAAM;IAClB;IAEA,IAAI,CAACF,gBAAgB;QACnB,MAAM,IAAIE,MAAM;IAClB;IAEA,gCAAgC;IAChC,MAAMC,MAAM,MAAM,IAAIR,QAAQ;QAC5BS,OAAOP;QACPQ,KAAKC,KAAKC,KAAK,CAACC,KAAKC,GAAG,KAAK;QAC7BC,KAAKJ,KAAKC,KAAK,CAACC,KAAKC,GAAG,KAAK,QAAQV;IACvC,GACGY,kBAAkB,CAAC;QAAEC,KAAK;IAAQ,GAClCC,IAAI,CAAC,IAAIC,cAAcC,MAAM,CAACjB;IAEjC,6BAA6B;IAC7B,MAAMkB,YAAY,GAAGhB,eAAe,OAAO,EAAEG,MAAMF,cAAc,CAAC,aAAa,EAAEgB,mBAAmBhB,cAAc,GAAG,IAAI;IAEzH,OAAOe;AACT,EAAC"}
@@ -0,0 +1,2 @@
1
+ import type { BetterAuthOptions } from 'better-auth';
2
+ export declare function getIp(headers: Headers, options: BetterAuthOptions): string | null;
@@ -0,0 +1,31 @@
1
+ export function getIp(headers, options) {
2
+ if (options.advanced?.ipAddress?.disableIpTracking) {
3
+ return null;
4
+ }
5
+ const testIP = '127.0.0.1';
6
+ if ((process.env.NODE_ENV === 'test' || process.env.NODE_ENV === 'development') ?? false) {
7
+ return testIP;
8
+ }
9
+ const ipHeaders = options.advanced?.ipAddress?.ipAddressHeaders;
10
+ const keys = ipHeaders || [
11
+ 'x-client-ip',
12
+ 'x-forwarded-for',
13
+ 'cf-connecting-ip',
14
+ 'fastly-client-ip',
15
+ 'x-real-ip',
16
+ 'x-cluster-client-ip',
17
+ 'x-forwarded',
18
+ 'forwarded-for',
19
+ 'forwarded'
20
+ ];
21
+ for (const key of keys){
22
+ const value = headers.get(key);
23
+ if (typeof value === 'string') {
24
+ const ip = value.split(',')[0].trim();
25
+ if (ip) return ip;
26
+ }
27
+ }
28
+ return null;
29
+ }
30
+
31
+ //# sourceMappingURL=get-ip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/plugin/helpers/get-ip.ts"],"sourcesContent":["import type { BetterAuthOptions } from 'better-auth'\n\nexport function getIp(headers: Headers, options: BetterAuthOptions): string | null {\n if (options.advanced?.ipAddress?.disableIpTracking) {\n return null\n }\n const testIP = '127.0.0.1'\n if ((process.env.NODE_ENV === 'test' || process.env.NODE_ENV === 'development') ?? false) {\n return testIP\n }\n const ipHeaders = options.advanced?.ipAddress?.ipAddressHeaders\n const keys = ipHeaders || [\n 'x-client-ip',\n 'x-forwarded-for',\n 'cf-connecting-ip',\n 'fastly-client-ip',\n 'x-real-ip',\n 'x-cluster-client-ip',\n 'x-forwarded',\n 'forwarded-for',\n 'forwarded',\n ]\n for (const key of keys) {\n const value = headers.get(key)\n if (typeof value === 'string') {\n const ip = value.split(',')[0].trim()\n if (ip) return ip\n }\n }\n return null\n}\n"],"names":["getIp","headers","options","advanced","ipAddress","disableIpTracking","testIP","process","env","NODE_ENV","ipHeaders","ipAddressHeaders","keys","key","value","get","ip","split","trim"],"mappings":"AAEA,OAAO,SAASA,MAAMC,OAAgB,EAAEC,OAA0B;IAChE,IAAIA,QAAQC,QAAQ,EAAEC,WAAWC,mBAAmB;QAClD,OAAO;IACT;IACA,MAAMC,SAAS;IACf,IAAI,AAACC,CAAAA,QAAQC,GAAG,CAACC,QAAQ,KAAK,UAAUF,QAAQC,GAAG,CAACC,QAAQ,KAAK,aAAY,KAAM,OAAO;QACxF,OAAOH;IACT;IACA,MAAMI,YAAYR,QAAQC,QAAQ,EAAEC,WAAWO;IAC/C,MAAMC,OAAOF,aAAa;QACxB;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;KACD;IACD,KAAK,MAAMG,OAAOD,KAAM;QACtB,MAAME,QAAQb,QAAQc,GAAG,CAACF;QAC1B,IAAI,OAAOC,UAAU,UAAU;YAC7B,MAAME,KAAKF,MAAMG,KAAK,CAAC,IAAI,CAAC,EAAE,CAACC,IAAI;YACnC,IAAIF,IAAI,OAAOA;QACjB;IACF;IACA,OAAO;AACT"}