@arch-cadre/core 0.0.40 → 0.0.41

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 (111) hide show
  1. package/package.json +1 -1
  2. package/dist/_virtual/_rolldown/runtime.mjs +0 -1
  3. package/dist/core/auth/augment.d.mts +0 -20
  4. package/dist/core/auth/augment.d.mts.map +0 -1
  5. package/dist/core/auth/augment.mjs +0 -2
  6. package/dist/core/auth/augment.mjs.map +0 -1
  7. package/dist/core/auth/email-verification.d.mts +0 -62
  8. package/dist/core/auth/email-verification.d.mts.map +0 -1
  9. package/dist/core/auth/email-verification.mjs +0 -2
  10. package/dist/core/auth/email-verification.mjs.map +0 -1
  11. package/dist/core/auth/logic.d.mts +0 -110
  12. package/dist/core/auth/logic.d.mts.map +0 -1
  13. package/dist/core/auth/logic.mjs +0 -2
  14. package/dist/core/auth/logic.mjs.map +0 -1
  15. package/dist/core/auth/password-reset.d.mts +0 -39
  16. package/dist/core/auth/password-reset.d.mts.map +0 -1
  17. package/dist/core/auth/password-reset.mjs +0 -2
  18. package/dist/core/auth/password-reset.mjs.map +0 -1
  19. package/dist/core/auth/rbac.d.mts +0 -61
  20. package/dist/core/auth/rbac.d.mts.map +0 -1
  21. package/dist/core/auth/rbac.mjs +0 -2
  22. package/dist/core/auth/rbac.mjs.map +0 -1
  23. package/dist/core/auth/session.d.mts +0 -54
  24. package/dist/core/auth/session.d.mts.map +0 -1
  25. package/dist/core/auth/session.mjs +0 -2
  26. package/dist/core/auth/session.mjs.map +0 -1
  27. package/dist/core/auth/types.d.mts +0 -55
  28. package/dist/core/auth/types.d.mts.map +0 -1
  29. package/dist/core/auth/utils/encode.d.mts +0 -15
  30. package/dist/core/auth/utils/encode.d.mts.map +0 -1
  31. package/dist/core/auth/utils/encode.mjs +0 -2
  32. package/dist/core/auth/utils/encode.mjs.map +0 -1
  33. package/dist/core/auth/utils/encryption.d.mts +0 -28
  34. package/dist/core/auth/utils/encryption.d.mts.map +0 -1
  35. package/dist/core/auth/utils/encryption.mjs +0 -2
  36. package/dist/core/auth/utils/encryption.mjs.map +0 -1
  37. package/dist/core/auth/validation.d.mts +0 -48
  38. package/dist/core/auth/validation.d.mts.map +0 -1
  39. package/dist/core/auth/validation.mjs +0 -2
  40. package/dist/core/auth/validation.mjs.map +0 -1
  41. package/dist/core/bootstrap.d.mts +0 -5
  42. package/dist/core/bootstrap.d.mts.map +0 -1
  43. package/dist/core/bootstrap.mjs +0 -2
  44. package/dist/core/bootstrap.mjs.map +0 -1
  45. package/dist/core/config.d.mts +0 -11
  46. package/dist/core/config.d.mts.map +0 -1
  47. package/dist/core/config.mjs +0 -2
  48. package/dist/core/config.mjs.map +0 -1
  49. package/dist/core/config.server.d.mts +0 -16
  50. package/dist/core/config.server.d.mts.map +0 -1
  51. package/dist/core/config.server.mjs +0 -2
  52. package/dist/core/config.server.mjs.map +0 -1
  53. package/dist/core/event-bus.d.mts +0 -17
  54. package/dist/core/event-bus.d.mts.map +0 -1
  55. package/dist/core/event-bus.mjs +0 -2
  56. package/dist/core/event-bus.mjs.map +0 -1
  57. package/dist/core/filesystem/index.mjs +0 -2
  58. package/dist/core/filesystem/index.mjs.map +0 -1
  59. package/dist/core/filesystem/providers/local.mjs +0 -2
  60. package/dist/core/filesystem/providers/local.mjs.map +0 -1
  61. package/dist/core/filesystem/service.d.mts +0 -19
  62. package/dist/core/filesystem/service.d.mts.map +0 -1
  63. package/dist/core/filesystem/service.mjs +0 -2
  64. package/dist/core/filesystem/service.mjs.map +0 -1
  65. package/dist/core/filesystem/types.d.mts +0 -22
  66. package/dist/core/filesystem/types.d.mts.map +0 -1
  67. package/dist/core/notifications/actions.d.mts +0 -58
  68. package/dist/core/notifications/actions.d.mts.map +0 -1
  69. package/dist/core/notifications/actions.mjs +0 -2
  70. package/dist/core/notifications/actions.mjs.map +0 -1
  71. package/dist/core/notifications/index.mjs +0 -1
  72. package/dist/core/notifications/service.d.mts +0 -9
  73. package/dist/core/notifications/service.d.mts.map +0 -1
  74. package/dist/core/notifications/service.mjs +0 -2
  75. package/dist/core/notifications/service.mjs.map +0 -1
  76. package/dist/core/notifications/types.d.mts +0 -21
  77. package/dist/core/notifications/types.d.mts.map +0 -1
  78. package/dist/core/setup.d.mts +0 -9
  79. package/dist/core/setup.d.mts.map +0 -1
  80. package/dist/core/setup.mjs +0 -2
  81. package/dist/core/setup.mjs.map +0 -1
  82. package/dist/core/types.d.mts +0 -13
  83. package/dist/core/types.d.mts.map +0 -1
  84. package/dist/index.d.mts +0 -8
  85. package/dist/index.mjs +0 -1
  86. package/dist/server/auth/email.d.mts +0 -13
  87. package/dist/server/auth/email.d.mts.map +0 -1
  88. package/dist/server/auth/email.mjs +0 -2
  89. package/dist/server/auth/email.mjs.map +0 -1
  90. package/dist/server/auth/password.d.mts +0 -23
  91. package/dist/server/auth/password.d.mts.map +0 -1
  92. package/dist/server/auth/password.mjs +0 -2
  93. package/dist/server/auth/password.mjs.map +0 -1
  94. package/dist/server/auth/user.d.mts +0 -58
  95. package/dist/server/auth/user.d.mts.map +0 -1
  96. package/dist/server/auth/user.mjs +0 -2
  97. package/dist/server/auth/user.mjs.map +0 -1
  98. package/dist/server/database/inject.d.mts +0 -15
  99. package/dist/server/database/inject.d.mts.map +0 -1
  100. package/dist/server/database/inject.mjs +0 -2
  101. package/dist/server/database/inject.mjs.map +0 -1
  102. package/dist/server/database/schema.d.mts +0 -2962
  103. package/dist/server/database/schema.d.mts.map +0 -1
  104. package/dist/server/database/schema.mjs +0 -2
  105. package/dist/server/database/schema.mjs.map +0 -1
  106. package/dist/server/emails/index.d.mts +0 -26
  107. package/dist/server/emails/index.d.mts.map +0 -1
  108. package/dist/server/emails/index.mjs +0 -2
  109. package/dist/server/emails/index.mjs.map +0 -1
  110. package/dist/server.d.mts +0 -26
  111. package/dist/server.mjs +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arch-cadre/core",
3
- "version": "0.0.40",
3
+ "version": "0.0.41",
4
4
  "type": "module",
5
5
  "description": "Core logic for Kryo framework",
6
6
  "types": "./dist/index.d.ts",
@@ -1 +0,0 @@
1
- var e=Object.defineProperty,t=(t,n)=>{let r={};for(var i in t)e(r,i,{get:t[i],enumerable:!0});return n||e(r,Symbol.toStringTag,{value:`Module`}),r};export{t as __exportAll};
@@ -1,20 +0,0 @@
1
- import { FullUser, PasswordResetSession, Session, User } from "./types.mjs";
2
-
3
- //#region src/core/auth/augment.d.ts
4
- /**
5
- * REGISTRIES FOR MODULAR EXTENSIONS
6
- */
7
- type IdentityAugmenter = (user: User) => Promise<Partial<FullUser>>;
8
- type SessionAugmenter = (session: Session) => Promise<Partial<Session>>;
9
- type PasswordResetSessionAugmenter = (session: PasswordResetSession) => Promise<Partial<PasswordResetSession>>;
10
- declare function registerIdentityAugmenter(augmenter: IdentityAugmenter): void;
11
- declare function registerSessionAugmenter(augmenter: SessionAugmenter): void;
12
- declare function registerPasswordResetSessionAugmenter(augmenter: PasswordResetSessionAugmenter): void;
13
- /**
14
- * EXECUTION FUNCTIONS
15
- */
16
- declare function augmentUser(user: User, coreRbacData?: Record<string, any>): Promise<FullUser>;
17
- declare function augmentSession(session: Session): Promise<Session>;
18
- //#endregion
19
- export { augmentSession, augmentUser, registerIdentityAugmenter, registerPasswordResetSessionAugmenter, registerSessionAugmenter };
20
- //# sourceMappingURL=augment.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"augment.d.mts","names":[],"sources":["../../../src/core/auth/augment.ts"],"mappings":";;;;;AAA6E;KAMxE,iBAAA,IAAqB,IAAA,EAAM,IAAA,KAAS,OAAA,CAAQ,OAAA,CAAQ,QAAA;AAAA,KACpD,gBAAA,IAAoB,OAAA,EAAS,OAAA,KAAY,OAAA,CAAQ,OAAA,CAAQ,OAAA;AAAA,KACzD,6BAAA,IACH,OAAA,EAAS,oBAAA,KACN,OAAA,CAAQ,OAAA,CAAQ,oBAAA;AAAA,iBAuBL,yBAAA,CAA0B,SAAA,EAAW,iBAAA;AAAA,iBAIrC,wBAAA,CAAyB,SAAA,EAAW,gBAAA;AAAA,iBAIpC,qCAAA,CACd,SAAA,EAAW,6BAAA;;;;iBAQS,WAAA,CACpB,IAAA,EAAM,IAAA,EACN,YAAA,GAAe,MAAA,gBACd,OAAA,CAAQ,QAAA;AAAA,iBASW,cAAA,CAAe,OAAA,EAAS,OAAA,GAAU,OAAA,CAAQ,OAAA"}
@@ -1,2 +0,0 @@
1
- const e=globalThis,t=e.__KRYO_IDENTITY_AUGMENTERS__??new Set,n=e.__KRYO_SESSION_AUGMENTERS__??new Set,r=e.__KRYO_PASSWORD_RESET_SESSION_AUGMENTERS__??new Set;e.__KRYO_IDENTITY_AUGMENTERS__=t,e.__KRYO_SESSION_AUGMENTERS__=n,e.__KRYO_PASSWORD_RESET_SESSION_AUGMENTERS__=r;function i(e){t.add(e)}function a(e){n.add(e)}function o(e){r.add(e)}async function s(e,n){let r=n||{};for(let n of t){let t=await n(e);r={...r,...t}}return{...e,...r}}async function c(e){let t={};for(let r of n){let n=await r(e);t={...t,...n}}return{...e,...t}}async function l(e){let t={};for(let n of r){let r=await n(e);t={...t,...r}}return{...e,...t}}export{l as augmentPasswordResetSession,c as augmentSession,s as augmentUser,i as registerIdentityAugmenter,o as registerPasswordResetSessionAugmenter,a as registerSessionAugmenter};
2
- //# sourceMappingURL=augment.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"augment.mjs","names":[],"sources":["../../../src/core/auth/augment.ts"],"sourcesContent":["import type { FullUser, PasswordResetSession, Session, User } from \"./types\";\n\n/**\n * REGISTRIES FOR MODULAR EXTENSIONS\n */\n\ntype IdentityAugmenter = (user: User) => Promise<Partial<FullUser>>;\ntype SessionAugmenter = (session: Session) => Promise<Partial<Session>>;\ntype PasswordResetSessionAugmenter = (\n session: PasswordResetSession,\n) => Promise<Partial<PasswordResetSession>>;\n\nconst globalForAugment = globalThis as unknown as {\n __KRYO_IDENTITY_AUGMENTERS__: Set<IdentityAugmenter> | undefined;\n __KRYO_SESSION_AUGMENTERS__: Set<SessionAugmenter> | undefined;\n __KRYO_PASSWORD_RESET_SESSION_AUGMENTERS__:\n | Set<PasswordResetSessionAugmenter>\n | undefined;\n};\n\nconst identityAugmenters =\n globalForAugment.__KRYO_IDENTITY_AUGMENTERS__ ?? new Set<IdentityAugmenter>();\nconst sessionAugmenters =\n globalForAugment.__KRYO_SESSION_AUGMENTERS__ ?? new Set<SessionAugmenter>();\nconst passwordResetSessionAugmenters =\n globalForAugment.__KRYO_PASSWORD_RESET_SESSION_AUGMENTERS__ ??\n new Set<PasswordResetSessionAugmenter>();\n\nglobalForAugment.__KRYO_IDENTITY_AUGMENTERS__ = identityAugmenters;\nglobalForAugment.__KRYO_SESSION_AUGMENTERS__ = sessionAugmenters;\nglobalForAugment.__KRYO_PASSWORD_RESET_SESSION_AUGMENTERS__ =\n passwordResetSessionAugmenters;\n\nexport function registerIdentityAugmenter(augmenter: IdentityAugmenter) {\n identityAugmenters.add(augmenter);\n}\n\nexport function registerSessionAugmenter(augmenter: SessionAugmenter) {\n sessionAugmenters.add(augmenter);\n}\n\nexport function registerPasswordResetSessionAugmenter(\n augmenter: PasswordResetSessionAugmenter,\n) {\n passwordResetSessionAugmenters.add(augmenter);\n}\n\n/**\n * EXECUTION FUNCTIONS\n */\nexport async function augmentUser(\n user: User,\n coreRbacData?: Record<string, any>,\n): Promise<FullUser> {\n let augmentedData = coreRbacData || {};\n for (const augmenter of identityAugmenters) {\n const data = await augmenter(user);\n augmentedData = { ...augmentedData, ...data };\n }\n return { ...user, ...augmentedData } as FullUser;\n}\n\nexport async function augmentSession(session: Session): Promise<Session> {\n let augmentedData = {};\n for (const augmenter of sessionAugmenters) {\n const data = await augmenter(session);\n augmentedData = { ...augmentedData, ...data };\n }\n return { ...session, ...augmentedData } as Session;\n}\n\nexport async function augmentPasswordResetSession(\n session: PasswordResetSession,\n): Promise<PasswordResetSession> {\n let augmentedData = {};\n for (const augmenter of passwordResetSessionAugmenters) {\n const data = await augmenter(session);\n augmentedData = { ...augmentedData, ...data };\n }\n return { ...session, ...augmentedData } as PasswordResetSession;\n}\n"],"mappings":"AAYA,MAAM,EAAmB,WAQnB,EACJ,EAAiB,8BAAgC,IAAI,IACjD,EACJ,EAAiB,6BAA+B,IAAI,IAChD,EACJ,EAAiB,4CACjB,IAAI,IAEN,EAAiB,6BAA+B,EAChD,EAAiB,4BAA8B,EAC/C,EAAiB,2CACf,EAEF,SAAgB,EAA0B,EAA8B,CACtE,EAAmB,IAAI,EAAU,CAGnC,SAAgB,EAAyB,EAA6B,CACpE,EAAkB,IAAI,EAAU,CAGlC,SAAgB,EACd,EACA,CACA,EAA+B,IAAI,EAAU,CAM/C,eAAsB,EACpB,EACA,EACmB,CACnB,IAAI,EAAgB,GAAgB,EAAE,CACtC,IAAK,IAAM,KAAa,EAAoB,CAC1C,IAAM,EAAO,MAAM,EAAU,EAAK,CAClC,EAAgB,CAAE,GAAG,EAAe,GAAG,EAAM,CAE/C,MAAO,CAAE,GAAG,EAAM,GAAG,EAAe,CAGtC,eAAsB,EAAe,EAAoC,CACvE,IAAI,EAAgB,EAAE,CACtB,IAAK,IAAM,KAAa,EAAmB,CACzC,IAAM,EAAO,MAAM,EAAU,EAAQ,CACrC,EAAgB,CAAE,GAAG,EAAe,GAAG,EAAM,CAE/C,MAAO,CAAE,GAAG,EAAS,GAAG,EAAe,CAGzC,eAAsB,EACpB,EAC+B,CAC/B,IAAI,EAAgB,EAAE,CACtB,IAAK,IAAM,KAAa,EAAgC,CACtD,IAAM,EAAO,MAAM,EAAU,EAAQ,CACrC,EAAgB,CAAE,GAAG,EAAe,GAAG,EAAM,CAE/C,MAAO,CAAE,GAAG,EAAS,GAAG,EAAe"}
@@ -1,62 +0,0 @@
1
- import { emailVerificationTable } from "../../server/database/schema.mjs";
2
-
3
- //#region src/core/auth/email-verification.d.ts
4
- /**
5
- * Register Email Verification as a Core Security Requirement.
6
- */
7
- declare function initEmailVerification(): Promise<void>;
8
- /**
9
- * Retrieves a specific email verification request for a user.
10
- */
11
- declare function getUserEmailVerificationRequest(userId: string, id: string): Promise<{
12
- id: string;
13
- email: string;
14
- code: string;
15
- userId: string;
16
- expiresAt: Date;
17
- createdAt: Date;
18
- updatedAt: Date | null;
19
- }>;
20
- /**
21
- * Creates a new email verification request, deleting any existing one for the user.
22
- */
23
- declare function createEmailVerificationRequest(userId: string, email: string): Promise<{
24
- id: string;
25
- email: string;
26
- createdAt: Date;
27
- updatedAt: Date | null;
28
- userId: string;
29
- expiresAt: Date;
30
- code: string;
31
- }>;
32
- /**
33
- * Deletes all email verification requests for a user.
34
- */
35
- declare function deleteUserEmailVerificationRequest(userId: string): Promise<void>;
36
- /**
37
- * Sends a verification email with the OTP code.
38
- */
39
- declare function sendVerificationEmail(email: string, code: string): Promise<void>;
40
- /**
41
- * Sets the email verification request ID in a cookie.
42
- */
43
- declare function setEmailVerificationRequestCookie(request: typeof emailVerificationTable.$inferSelect): Promise<void>;
44
- /**
45
- * Removes the email verification request cookie.
46
- */
47
- declare function deleteEmailVerificationRequestCookie(): Promise<void>;
48
- /**
49
- * Retrieves the current email verification request based on session and cookie.
50
- */
51
- declare function getUserEmailVerificationRequestFromRequest(): Promise<{
52
- id: string;
53
- email: string;
54
- code: string;
55
- userId: string;
56
- expiresAt: Date;
57
- createdAt: Date;
58
- updatedAt: Date | null;
59
- } | null>;
60
- //#endregion
61
- export { createEmailVerificationRequest, deleteEmailVerificationRequestCookie, deleteUserEmailVerificationRequest, getUserEmailVerificationRequest, getUserEmailVerificationRequestFromRequest, initEmailVerification, sendVerificationEmail, setEmailVerificationRequestCookie };
62
- //# sourceMappingURL=email-verification.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"email-verification.d.mts","names":[],"sources":["../../../src/core/auth/email-verification.ts"],"mappings":";;;;;AAeA;iBAAsB,qBAAA,CAAA,GAAqB,OAAA;;;;iBAerB,+BAAA,CACpB,MAAA,UACA,EAAA,WAAU,OAAA;;;;;;;;;;;;iBAkBU,8BAAA,CACpB,MAAA,UACA,KAAA,WAAa,OAAA;;;;;;;;;;;;iBAsBO,kCAAA,CACpB,MAAA,WACC,OAAA;;;;iBASmB,qBAAA,CACpB,KAAA,UACA,IAAA,WACC,OAAA;;;;iBAOmB,iCAAA,CACpB,OAAA,SAAgB,sBAAA,CAAuB,YAAA,GACtC,OAAA;;;;iBAemB,oCAAA,CAAA,GAAwC,OAAA;;;;iBAQxC,0CAAA,CAAA,GAA0C,OAAA"}
@@ -1,2 +0,0 @@
1
- "use server";import{db as e}from"../../server/database/inject.mjs";import{emailVerificationTable as t}from"../../server/database/schema.mjs";import{generateRandomOTP as n}from"./utils/encode.mjs";import{sendVerifyEmail as r}from"../../server/emails/index.mjs";import{registerSecurityRequirement as i}from"./logic.mjs";import{getCurrentSession as a}from"./session.mjs";import{and as o,eq as s}from"drizzle-orm";import{addHours as c}from"date-fns";import{cookies as l}from"next/headers";async function u(){i(async(e,t)=>t.emailVerifiedAt?{satisfied:!0}:{satisfied:!1,redirect:`/verify-email?unverified`})}async function d(n,r){let[i]=await e.select().from(t).where(o(s(t.id,r),s(t.userId,n)));return i}async function f(r,i){await p(r);let a=n(),[o]=await e.insert(t).values({userId:r,code:a,email:i,expiresAt:new Date(c(new Date,1))}).returning();return o}async function p(n){await e.delete(t).where(s(t.userId,n))}async function m(e,t){await r(e,t)}async function h(e){(await l()).set(`email_verification`,e.id,{httpOnly:!0,path:`/`,secure:process.env.NODE_ENV===`production`,sameSite:`lax`,expires:e.expiresAt})}async function g(){(await l()).delete(`email_verification`)}async function _(){let{user:e}=await a();if(!e)return null;let t=(await l()).get(`email_verification`)?.value??null;if(!t)return null;let n=await d(e.id,t);return n||await g(),n}export{f as createEmailVerificationRequest,g as deleteEmailVerificationRequestCookie,p as deleteUserEmailVerificationRequest,d as getUserEmailVerificationRequest,_ as getUserEmailVerificationRequestFromRequest,u as initEmailVerification,m as sendVerificationEmail,h as setEmailVerificationRequestCookie};
2
- //# sourceMappingURL=email-verification.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"email-verification.mjs","names":[],"sources":["../../../src/core/auth/email-verification.ts"],"sourcesContent":["\"use server\";\n\nimport { addHours } from \"date-fns\";\nimport { and, eq } from \"drizzle-orm\";\nimport { cookies } from \"next/headers\";\nimport { db } from \"../../server/database/inject\";\nimport { emailVerificationTable } from \"../../server/database/schema\";\nimport { sendVerifyEmail } from \"../../server/emails/index\";\nimport { registerSecurityRequirement } from \"./logic\";\nimport { getCurrentSession } from \"./session\";\nimport { generateRandomOTP } from \"./utils/encode\";\n\n/**\n * Register Email Verification as a Core Security Requirement.\n */\nexport async function initEmailVerification() {\n registerSecurityRequirement(async (_session, user) => {\n if (!user.emailVerifiedAt) {\n return {\n satisfied: false,\n redirect: \"/verify-email?unverified\",\n };\n }\n return { satisfied: true };\n });\n}\n\n/**\n * Retrieves a specific email verification request for a user.\n */\nexport async function getUserEmailVerificationRequest(\n userId: string,\n id: string,\n) {\n const [session] = await db\n .select()\n .from(emailVerificationTable)\n .where(\n and(\n eq(emailVerificationTable.id, id),\n eq(emailVerificationTable.userId, userId),\n ),\n );\n\n return session;\n}\n\n/**\n * Creates a new email verification request, deleting any existing one for the user.\n */\nexport async function createEmailVerificationRequest(\n userId: string,\n email: string,\n) {\n await deleteUserEmailVerificationRequest(userId);\n\n const code = generateRandomOTP();\n\n const [verificationRequest] = await db\n .insert(emailVerificationTable)\n .values({\n userId,\n code,\n email,\n expiresAt: new Date(addHours(new Date(), 1)),\n })\n .returning();\n\n return verificationRequest;\n}\n\n/**\n * Deletes all email verification requests for a user.\n */\nexport async function deleteUserEmailVerificationRequest(\n userId: string,\n): Promise<void> {\n await db\n .delete(emailVerificationTable)\n .where(eq(emailVerificationTable.userId, userId));\n}\n\n/**\n * Sends a verification email with the OTP code.\n */\nexport async function sendVerificationEmail(\n email: string,\n code: string,\n): Promise<void> {\n await sendVerifyEmail(email, code);\n}\n\n/**\n * Sets the email verification request ID in a cookie.\n */\nexport async function setEmailVerificationRequestCookie(\n request: typeof emailVerificationTable.$inferSelect,\n): Promise<void> {\n const cookieStore = await cookies();\n\n cookieStore.set(\"email_verification\", request.id, {\n httpOnly: true,\n path: \"/\",\n secure: process.env.NODE_ENV === \"production\",\n sameSite: \"lax\",\n expires: request.expiresAt,\n });\n}\n\n/**\n * Removes the email verification request cookie.\n */\nexport async function deleteEmailVerificationRequestCookie(): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.delete(\"email_verification\");\n}\n\n/**\n * Retrieves the current email verification request based on session and cookie.\n */\nexport async function getUserEmailVerificationRequestFromRequest() {\n const { user } = await getCurrentSession();\n\n if (!user) {\n return null;\n }\n\n const cookieStore = await cookies();\n const id = cookieStore.get(\"email_verification\")?.value ?? null;\n\n if (!id) {\n return null;\n }\n\n const request = await getUserEmailVerificationRequest(user.id, id);\n\n if (!request) {\n await deleteEmailVerificationRequestCookie();\n }\n\n return request;\n}\n"],"mappings":"qeAeA,eAAsB,GAAwB,CAC5C,EAA4B,MAAO,EAAU,IACtC,EAAK,gBAMH,CAAE,UAAW,GAAM,CALjB,CACL,UAAW,GACX,SAAU,2BACX,CAGH,CAMJ,eAAsB,EACpB,EACA,EACA,CACA,GAAM,CAAC,GAAW,MAAM,EACrB,QAAQ,CACR,KAAK,EAAuB,CAC5B,MACC,EACE,EAAG,EAAuB,GAAI,EAAG,CACjC,EAAG,EAAuB,OAAQ,EAAO,CAC1C,CACF,CAEH,OAAO,EAMT,eAAsB,EACpB,EACA,EACA,CACA,MAAM,EAAmC,EAAO,CAEhD,IAAM,EAAO,GAAmB,CAE1B,CAAC,GAAuB,MAAM,EACjC,OAAO,EAAuB,CAC9B,OAAO,CACN,SACA,OACA,QACA,UAAW,IAAI,KAAK,EAAS,IAAI,KAAQ,EAAE,CAAC,CAC7C,CAAC,CACD,WAAW,CAEd,OAAO,EAMT,eAAsB,EACpB,EACe,CACf,MAAM,EACH,OAAO,EAAuB,CAC9B,MAAM,EAAG,EAAuB,OAAQ,EAAO,CAAC,CAMrD,eAAsB,EACpB,EACA,EACe,CACf,MAAM,EAAgB,EAAO,EAAK,CAMpC,eAAsB,EACpB,EACe,EACK,MAAM,GAAS,EAEvB,IAAI,qBAAsB,EAAQ,GAAI,CAChD,SAAU,GACV,KAAM,IACN,OAAQ,QAAQ,IAAI,WAAa,aACjC,SAAU,MACV,QAAS,EAAQ,UAClB,CAAC,CAMJ,eAAsB,GAAsD,EACtD,MAAM,GAAS,EACvB,OAAO,qBAAqB,CAM1C,eAAsB,GAA6C,CACjE,GAAM,CAAE,QAAS,MAAM,GAAmB,CAE1C,GAAI,CAAC,EACH,OAAO,KAIT,IAAM,GADc,MAAM,GAAS,EACZ,IAAI,qBAAqB,EAAE,OAAS,KAE3D,GAAI,CAAC,EACH,OAAO,KAGT,IAAM,EAAU,MAAM,EAAgC,EAAK,GAAI,EAAG,CAMlE,OAJK,GACH,MAAM,GAAsC,CAGvC"}
@@ -1,110 +0,0 @@
1
- import { UserPermission, UserRole } from "../types.mjs";
2
- import { AuthResponse, FullUser, Session, SessionFlags, User } from "./types.mjs";
3
- import { LoginInput, RegisterInput } from "./validation.mjs";
4
- import { augmentSession, augmentUser, registerIdentityAugmenter, registerPasswordResetSessionAugmenter, registerSessionAugmenter } from "./augment.mjs";
5
-
6
- //#region src/core/auth/logic.d.ts
7
- /**
8
- * Registry for login validators (e.g. 2FA module)
9
- */
10
- type AuthValidator = (userId: string) => Promise<AuthResponse | null>;
11
- /**
12
- * Registry for Security Requirements (e.g. checking if 2FA is needed for a session)
13
- */
14
- type SecurityRequirement = (session: Session, user: FullUser) => Promise<{
15
- satisfied: boolean;
16
- redirect?: string;
17
- } | null>;
18
- /**
19
- * Registry for password reset validators (e.g. 2FA module requiring check during reset)
20
- */
21
- type PasswordResetValidator = (userId: string) => Promise<AuthResponse | null>;
22
- /**
23
- * Registry for email verification validators
24
- */
25
- type EmailVerificationValidator = (userId: string) => Promise<AuthResponse | null>;
26
- declare function registerAuthValidator(validator: AuthValidator): Promise<void>;
27
- declare function registerPasswordResetValidator(validator: PasswordResetValidator): Promise<void>;
28
- declare function registerEmailVerificationValidator(validator: EmailVerificationValidator): Promise<void>;
29
- declare function registerSecurityRequirement(requirement: SecurityRequirement): Promise<void>;
30
- declare function runPasswordResetValidators(userId: string): Promise<AuthResponse | null>;
31
- declare function runEmailVerificationValidators(userId: string): Promise<AuthResponse | null>;
32
- /**
33
- * Augments a base user with data from all registered modules.
34
- * This is now just a wrapper that includes core RBAC data.
35
- */
36
- declare function performFullUserAugmentation(user: User): Promise<FullUser>;
37
- /**
38
- * Checks if the current session satisfies all registered security requirements.
39
- */
40
- declare function checkSecurity(session: Session, user: FullUser, requiredRoles?: UserRole[], requiredPermissions?: UserPermission[], fallbackRedirect?: string): Promise<{
41
- satisfied: boolean;
42
- redirect: string | undefined;
43
- } | {
44
- satisfied: boolean;
45
- redirect?: undefined;
46
- }>;
47
- /**
48
- * Sign In Logic
49
- */
50
- declare function signIn(data: LoginInput): Promise<AuthResponse>;
51
- /**
52
- * Sign Up Logic
53
- */
54
- declare function signUp(data: RegisterInput): Promise<{
55
- session: {
56
- [x: string]: any;
57
- id: string;
58
- active_organization_id: string | null;
59
- createdAt: Date;
60
- updatedAt: Date | null;
61
- userId: string;
62
- expiresAt: Date;
63
- };
64
- user: {
65
- [x: string]: any;
66
- id: string;
67
- email: string;
68
- name: string;
69
- password: string | null;
70
- image: string | null;
71
- recovery_code: Buffer<ArrayBufferLike>;
72
- emailVerifiedAt: Date | null;
73
- createdAt: Date;
74
- updatedAt: Date | null;
75
- roles: UserRole[];
76
- permissions: UserPermission[];
77
- };
78
- }>;
79
- /**
80
- * Finalizes login after a challenge
81
- */
82
- declare function finalizeLogin(userId: string, flags: SessionFlags): Promise<{
83
- session: {
84
- [x: string]: any;
85
- id: string;
86
- active_organization_id: string | null;
87
- createdAt: Date;
88
- updatedAt: Date | null;
89
- userId: string;
90
- expiresAt: Date;
91
- } | null;
92
- user: {
93
- id: string;
94
- email: string;
95
- name: string;
96
- password: string | null;
97
- image: string | null;
98
- recovery_code: Buffer<ArrayBufferLike>;
99
- emailVerifiedAt: Date | null;
100
- createdAt: Date;
101
- updatedAt: Date | null;
102
- } | null;
103
- }>;
104
- /**
105
- * Sign Out
106
- */
107
- declare function signOut(): Promise<void>;
108
- //#endregion
109
- export { checkSecurity, finalizeLogin, performFullUserAugmentation, registerAuthValidator, registerEmailVerificationValidator, registerPasswordResetValidator, registerSecurityRequirement, runEmailVerificationValidators, runPasswordResetValidators, signIn, signOut, signUp };
110
- //# sourceMappingURL=logic.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"logic.d.mts","names":[],"sources":["../../../src/core/auth/logic.ts"],"mappings":";;;;;;;;;KAyHK,aAAA,IAAiB,MAAA,aAAmB,OAAA,CAAQ,YAAA;;;;KAK5C,mBAAA,IACH,OAAA,EAAS,OAAA,EACT,IAAA,EAAM,QAAA,KACH,OAAA;EAAU,SAAA;EAAoB,QAAA;AAAA;;AAR0B;;KAaxD,sBAAA,IAA0B,MAAA,aAAmB,OAAA,CAAQ,YAAA;;;;KAKrD,0BAAA,IACH,MAAA,aACG,OAAA,CAAQ,YAAA;AAAA,iBA6BS,qBAAA,CAAsB,SAAA,EAAW,aAAA,GAAa,OAAA;AAAA,iBAI9C,8BAAA,CACpB,SAAA,EAAW,sBAAA,GAAsB,OAAA;AAAA,iBAKb,kCAAA,CACpB,SAAA,EAAW,0BAAA,GAA0B,OAAA;AAAA,iBAajB,2BAAA,CACpB,WAAA,EAAa,mBAAA,GAAmB,OAAA;AAAA,iBAKZ,0BAAA,CACpB,MAAA,WACC,OAAA,CAAQ,YAAA;AAAA,iBAQW,8BAAA,CACpB,MAAA,WACC,OAAA,CAAQ,YAAA;;;;AAnFgC;iBA+FrB,2BAAA,CACpB,IAAA,EAAM,IAAA,GACL,OAAA,CAAQ,QAAA;;;;iBAQW,aAAA,CACpB,OAAA,EAAS,OAAA,EACT,IAAA,EAAM,QAAA,EACN,aAAA,GAAgB,QAAA,IAChB,mBAAA,GAAsB,cAAA,IACtB,gBAAA,YAAyB,OAAA;;;;;;;;;;iBA+DL,MAAA,CAAO,IAAA,EAAM,UAAA,GAAa,OAAA,CAAQ,YAAA;;;AApIxD;iBAyKsB,MAAA,CAAO,IAAA,EAAM,aAAA,GAAa,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;AAjJhD;;iBAyLsB,aAAA,CAAc,MAAA,UAAgB,KAAA,EAAO,YAAA,GAAY,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;iBAoBjD,OAAA,CAAA,GAAO,OAAA"}
@@ -1,2 +0,0 @@
1
- "use server";import{loginSchema as e,registerSchema as t}from"./validation.mjs";import{eventBus as n}from"../event-bus.mjs";import{db as r}from"../../server/database/inject.mjs";import{permissionsTable as i,rolesTable as a,rolesToPermissionsTable as o,usersToPermissionsTable as s,usersToRolesTable as c}from"../../server/database/schema.mjs";import{augmentSession as l,augmentUser as u,registerIdentityAugmenter as d,registerPasswordResetSessionAugmenter as f,registerSessionAugmenter as p}from"./augment.mjs";import{verifyPasswordHash as m,verifyPasswordStrength as h}from"../../server/auth/password.mjs";import{createUser as g,getUserById as _,getUserFromEmail as v,getUserPasswordHash as y,verifyUsernameInput as b}from"../../server/auth/user.mjs";import{createEmailVerificationRequest as x,sendVerificationEmail as S,setEmailVerificationRequestCookie as C}from"./email-verification.mjs";import{createSession as w,deleteSessionTokenCookie as T,generateSessionToken as E,getCurrentSession as D,invalidateSession as O,setSessionTokenCookie as k}from"./session.mjs";import{eq as A,inArray as j}from"drizzle-orm";async function M(e){try{let t=(await r.select({name:a.name}).from(c).innerJoin(a,A(c.roleId,a.id)).where(A(c.userId,e.id))).map(e=>e.name),n=(await r.select({name:i.name}).from(s).innerJoin(i,A(s.permissionId,i.id)).where(A(s.userId,e.id))).map(e=>e.name),l=[];if(t.length>0){let e=(await r.select({id:a.id}).from(a).where(j(a.name,t))).map(e=>e.id);e.length>0&&(l=(await r.select({name:i.name}).from(o).innerJoin(i,A(o.permissionId,i.id)).where(j(o.roleId,e))).map(e=>e.name))}return{roles:t,permissions:Array.from(new Set([...n,...l]))}}catch(e){return console.error(`[Auth:RBAC] Failed to augment user:`,e),{roles:[],permissions:[]}}}const N=globalThis,P=N.__KRYO_AUTH_VALIDATORS__??new Set,F=N.__KRYO_SECURITY_REQUIREMENTS__??new Set,I=N.__KRYO_PASSWORD_RESET_VALIDATORS__??new Set,L=N.__KRYO_EMAIL_VERIFICATION_VALIDATORS__??new Set;N.__KRYO_AUTH_VALIDATORS__=P,N.__KRYO_SECURITY_REQUIREMENTS__=F,N.__KRYO_PASSWORD_RESET_VALIDATORS__=I,N.__KRYO_EMAIL_VERIFICATION_VALIDATORS__=L;async function R(e){P.add(e)}async function z(e){I.add(e)}async function B(e){L.add(e)}async function V(e){F.add(e)}async function H(e){for(let t of I){let n=await t(e);if(n)return n}return null}async function U(e){for(let t of L){let n=await t(e);if(n)return n}return null}async function W(e){return await u(e,await M(e))}async function G(e,t,n,r,i){if(!t)return console.warn(`User is required for security check`),{satisfied:!1,redirect:i??`/signin`};let a=Array.isArray(t.roles)?t.roles:[],o=Array.isArray(t.permissions)?t.permissions:[];if(n&&n.length>0&&!n.some(e=>a.includes(e)))return console.warn(`User lacks required roles: ${n.join(`, `)}`),{satisfied:!1,redirect:i};if(r&&r.length>0&&!r.every(e=>o.includes(e)))return console.warn(`User lacks required permissions: ${r.join(`, `)}`),{satisfied:!1,redirect:i};if(F)for(let n of F)try{let r=await n(e,t);if(r&&!r.satisfied)return{...r,redirect:r.redirect??i}}catch(e){console.error(`[Auth:Security] Requirement failed:`,e)}return{satisfied:!0}}async function K(t){let{email:r,password:i}=await e.parseAsync(t),a=await v(r);if(!a)return{status:`ERROR`,message:`Invalid email or password`};let o=await y(a.id);if(!o||!await m(o,i))return{status:`ERROR`,message:`Invalid email or password`};for(let e of P){let t=await e(a.id);if(t)return t}let s={},c=await E(),l=await w(c,a.id,s);await k(c,l.expiresAt);let u=await W(a);return await n.publish(`auth:session-created`,{session:l,user:u}),{status:`SUCCESS`,session:{...l},user:{...u}}}async function q(e){let{email:r,username:i,password:a}=t.parse(e);if(!await b(i))throw Error(`Invalid username`);if(!await h(a))throw Error(`Weak password`);let o=await g(r,i,a),s=await x(o.id,o.email);await S(s.email,s.code),await C(s);let c={},l=await E(),u=await w(l,o.id,c);await k(l,u.expiresAt);let d=await W(o);return await n.publish(`auth:session-created`,{session:u,user:d}),{session:{...u},user:{...d}}}async function J(e,t){let r=await E(),i=await w(r,e,t);await k(r,i.expiresAt);let a=await _(e);return a&&await n.publish(`auth:session-created`,{session:i,user:a}),{session:i?{...i}:null,user:a?{...a}:null}}async function Y(){let{session:e,user:t}=await D();e&&(t&&await n.publish(`auth:signed-out`,{userId:t.id}),await O(e.id),await T())}export{G as checkSecurity,J as finalizeLogin,W as performFullUserAugmentation,R as registerAuthValidator,B as registerEmailVerificationValidator,z as registerPasswordResetValidator,V as registerSecurityRequirement,U as runEmailVerificationValidators,H as runPasswordResetValidators,K as signIn,Y as signOut,q as signUp};
2
- //# sourceMappingURL=logic.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"logic.mjs","names":[],"sources":["../../../src/core/auth/logic.ts"],"sourcesContent":["\"use server\";\n\nimport { eq, inArray } from \"drizzle-orm\";\nimport {\n verifyPasswordHash,\n verifyPasswordStrength,\n} from \"../../server/auth/password\";\nimport {\n createUser,\n getUserById,\n getUserFromEmail,\n getUserPasswordHash,\n verifyUsernameInput,\n} from \"../../server/auth/user\";\nimport { db } from \"../../server/database/inject\";\nimport {\n permissionsTable,\n rolesTable,\n rolesToPermissionsTable,\n usersToPermissionsTable,\n usersToRolesTable,\n} from \"../../server/database/schema\";\nimport { eventBus } from \"../event-bus\";\nimport {\n augmentSession,\n augmentUser,\n registerIdentityAugmenter,\n registerPasswordResetSessionAugmenter,\n registerSessionAugmenter,\n} from \"./augment\";\nimport {\n createEmailVerificationRequest,\n sendVerificationEmail,\n setEmailVerificationRequestCookie,\n} from \"./email-verification\";\nimport {\n createSession,\n deleteSessionTokenCookie,\n generateSessionToken,\n getCurrentSession,\n invalidateSession,\n setSessionTokenCookie,\n} from \"./session\";\nimport type {\n AuthResponse,\n FullUser,\n Session,\n SessionFlags,\n User,\n UserPermission,\n UserRole,\n} from \"./types\";\nimport {\n type LoginInput,\n loginSchema,\n type RegisterInput,\n registerSchema,\n} from \"./validation\";\n\n/**\n * Podstawowy moduł rozszerzający tożsamość dla ról i uprawnień\n */\nasync function coreRbacAugmenter(user: User): Promise<Record<string, any>> {\n try {\n // 1. Fetch direct roles\n const userRoles = await db\n .select({ name: rolesTable.name })\n .from(usersToRolesTable)\n .innerJoin(rolesTable, eq(usersToRolesTable.roleId, rolesTable.id))\n .where(eq(usersToRolesTable.userId, user.id));\n\n const roles = userRoles.map((r) => r.name);\n\n // 2. Fetch direct permissions\n const userDirectPerms = await db\n .select({ name: permissionsTable.name })\n .from(usersToPermissionsTable)\n .innerJoin(\n permissionsTable,\n eq(usersToPermissionsTable.permissionId, permissionsTable.id),\n )\n .where(eq(usersToPermissionsTable.userId, user.id));\n\n const directPerms = userDirectPerms.map((p) => p.name);\n\n // 3. Fetch permissions from roles\n let rolePerms: string[] = [];\n if (roles.length > 0) {\n const roleIdsResult = await db\n .select({ id: rolesTable.id })\n .from(rolesTable)\n .where(inArray(rolesTable.name, roles));\n\n const roleIds = roleIdsResult.map((r) => r.id);\n\n if (roleIds.length > 0) {\n const rolePermsData = await db\n .select({ name: permissionsTable.name })\n .from(rolesToPermissionsTable)\n .innerJoin(\n permissionsTable,\n eq(rolesToPermissionsTable.permissionId, permissionsTable.id),\n )\n .where(inArray(rolesToPermissionsTable.roleId, roleIds));\n rolePerms = rolePermsData.map((p) => p.name);\n }\n }\n\n return {\n roles,\n permissions: Array.from(new Set([...directPerms, ...rolePerms])),\n };\n } catch (error) {\n console.error(\"[Auth:RBAC] Failed to augment user:\", error);\n return { roles: [], permissions: [] };\n }\n}\n\n/**\n * Registry for login validators (e.g. 2FA module)\n */\ntype AuthValidator = (userId: string) => Promise<AuthResponse | null>;\n\n/**\n * Registry for Security Requirements (e.g. checking if 2FA is needed for a session)\n */\ntype SecurityRequirement = (\n session: Session,\n user: FullUser,\n) => Promise<{ satisfied: boolean; redirect?: string } | null>;\n\n/**\n * Registry for password reset validators (e.g. 2FA module requiring check during reset)\n */\ntype PasswordResetValidator = (userId: string) => Promise<AuthResponse | null>;\n\n/**\n * Registry for email verification validators\n */\ntype EmailVerificationValidator = (\n userId: string,\n) => Promise<AuthResponse | null>;\n\nconst globalForAuth = globalThis as unknown as {\n __KRYO_AUTH_VALIDATORS__: Set<AuthValidator> | undefined;\n __KRYO_SECURITY_REQUIREMENTS__: Set<SecurityRequirement> | undefined;\n __KRYO_PASSWORD_RESET_VALIDATORS__: Set<PasswordResetValidator> | undefined;\n __KRYO_EMAIL_VERIFICATION_VALIDATORS__:\n | Set<EmailVerificationValidator>\n | undefined;\n};\n\nconst authValidators =\n globalForAuth.__KRYO_AUTH_VALIDATORS__ ?? new Set<AuthValidator>();\nconst securityRequirements =\n globalForAuth.__KRYO_SECURITY_REQUIREMENTS__ ??\n new Set<SecurityRequirement>();\nconst passwordResetValidators =\n globalForAuth.__KRYO_PASSWORD_RESET_VALIDATORS__ ??\n new Set<PasswordResetValidator>();\nconst emailVerificationValidators =\n globalForAuth.__KRYO_EMAIL_VERIFICATION_VALIDATORS__ ??\n new Set<EmailVerificationValidator>();\n\nglobalForAuth.__KRYO_AUTH_VALIDATORS__ = authValidators;\nglobalForAuth.__KRYO_SECURITY_REQUIREMENTS__ = securityRequirements;\nglobalForAuth.__KRYO_PASSWORD_RESET_VALIDATORS__ = passwordResetValidators;\nglobalForAuth.__KRYO_EMAIL_VERIFICATION_VALIDATORS__ =\n emailVerificationValidators;\n\nexport async function registerAuthValidator(validator: AuthValidator) {\n authValidators.add(validator);\n}\n\nexport async function registerPasswordResetValidator(\n validator: PasswordResetValidator,\n) {\n passwordResetValidators.add(validator);\n}\n\nexport async function registerEmailVerificationValidator(\n validator: EmailVerificationValidator,\n) {\n emailVerificationValidators.add(validator);\n}\n\nexport {\n registerIdentityAugmenter,\n registerSessionAugmenter,\n registerPasswordResetSessionAugmenter,\n augmentUser,\n augmentSession,\n};\n\nexport async function registerSecurityRequirement(\n requirement: SecurityRequirement,\n) {\n securityRequirements.add(requirement);\n}\n\nexport async function runPasswordResetValidators(\n userId: string,\n): Promise<AuthResponse | null> {\n for (const validator of passwordResetValidators) {\n const interception = await validator(userId);\n if (interception) return interception;\n }\n return null;\n}\n\nexport async function runEmailVerificationValidators(\n userId: string,\n): Promise<AuthResponse | null> {\n for (const validator of emailVerificationValidators) {\n const interception = await validator(userId);\n if (interception) return interception;\n }\n return null;\n}\n\n/**\n * Augments a base user with data from all registered modules.\n * This is now just a wrapper that includes core RBAC data.\n */\nexport async function performFullUserAugmentation(\n user: User,\n): Promise<FullUser> {\n const coreRbacData = await coreRbacAugmenter(user);\n return await augmentUser(user, coreRbacData);\n}\n\n/**\n * Checks if the current session satisfies all registered security requirements.\n */\nexport async function checkSecurity(\n session: Session,\n user: FullUser,\n requiredRoles?: UserRole[],\n requiredPermissions?: UserPermission[],\n fallbackRedirect?: string,\n) {\n if (!user) {\n console.warn(\"User is required for security check\");\n return { satisfied: false, redirect: fallbackRedirect ?? \"/signin\" };\n }\n\n const userRoles = Array.isArray(user.roles) ? user.roles : [];\n const userPermissions = Array.isArray(user.permissions)\n ? user.permissions\n : [];\n\n // 1. Core Role Check (At least one role must match)\n if (requiredRoles && requiredRoles.length > 0) {\n const hasRole = requiredRoles.some((role) => userRoles.includes(role));\n if (!hasRole) {\n console.warn(`User lacks required roles: ${requiredRoles.join(\", \")}`);\n return {\n satisfied: false,\n redirect: fallbackRedirect,\n };\n }\n }\n\n // 2. Core Permission Check (ALL permissions must match)\n if (requiredPermissions && requiredPermissions.length > 0) {\n const hasAllPermissions = requiredPermissions.every((perm) =>\n userPermissions.includes(perm),\n );\n if (!hasAllPermissions) {\n console.warn(\n `User lacks required permissions: ${requiredPermissions.join(\", \")}`,\n );\n\n return {\n satisfied: false,\n redirect: fallbackRedirect,\n };\n }\n }\n\n // 3. Modular Requirements Check\n if (securityRequirements) {\n for (const requirement of securityRequirements) {\n try {\n const result = await requirement(session, user);\n if (result && !result.satisfied) {\n return {\n ...result,\n redirect: result.redirect ?? fallbackRedirect,\n };\n }\n } catch (error) {\n console.error(\"[Auth:Security] Requirement failed:\", error);\n }\n }\n }\n return { satisfied: true };\n}\n\n/**\n * Sign In Logic\n */\nexport async function signIn(data: LoginInput): Promise<AuthResponse> {\n const { email, password } = await loginSchema.parseAsync(data);\n\n const user = await getUserFromEmail(email);\n if (!user) {\n return { status: \"ERROR\", message: \"Invalid email or password\" };\n }\n\n const passwordHash = await getUserPasswordHash(user.id);\n if (!passwordHash || !(await verifyPasswordHash(passwordHash, password))) {\n return { status: \"ERROR\", message: \"Invalid email or password\" };\n }\n\n // Interception Layer\n for (const validator of authValidators) {\n const interception = await validator(user.id);\n if (interception) return interception;\n }\n\n const sessionFlags: SessionFlags = {};\n const sessionToken = await generateSessionToken();\n const session = await createSession(sessionToken, user.id, sessionFlags);\n await setSessionTokenCookie(sessionToken, session.expiresAt);\n\n const fullUser = await performFullUserAugmentation(user);\n await eventBus.publish(\"auth:session-created\", { session, user: fullUser });\n\n return {\n status: \"SUCCESS\",\n session: { ...session },\n user: { ...fullUser },\n };\n}\n\n/**\n * Sign Up Logic\n */\nexport async function signUp(data: RegisterInput) {\n const { email, username, password } = registerSchema.parse(data);\n\n if (!(await verifyUsernameInput(username))) {\n throw new Error(\"Invalid username\");\n }\n\n if (!(await verifyPasswordStrength(password))) {\n throw new Error(\"Weak password\");\n }\n\n const user = await createUser(email, username, password);\n const verificationRequest = await createEmailVerificationRequest(\n user.id,\n user.email,\n );\n\n await sendVerificationEmail(\n verificationRequest.email,\n verificationRequest.code,\n );\n await setEmailVerificationRequestCookie(verificationRequest);\n\n const sessionFlags: SessionFlags = {};\n const sessionToken = await generateSessionToken();\n const session = await createSession(sessionToken, user.id, sessionFlags);\n await setSessionTokenCookie(sessionToken, session.expiresAt);\n\n const fullUser = await performFullUserAugmentation(user);\n await eventBus.publish(\"auth:session-created\", { session, user: fullUser });\n\n return {\n session: { ...session },\n user: { ...fullUser },\n };\n}\n\n/**\n * Finalizes login after a challenge\n */\nexport async function finalizeLogin(userId: string, flags: SessionFlags) {\n const sessionToken = await generateSessionToken();\n const session = await createSession(sessionToken, userId, flags);\n await setSessionTokenCookie(sessionToken, session.expiresAt);\n\n const user = await getUserById(userId);\n\n if (user) {\n await eventBus.publish(\"auth:session-created\", { session, user });\n }\n\n return {\n session: session ? { ...session } : null,\n user: user ? { ...user } : null,\n };\n}\n\n/**\n * Sign Out\n */\nexport async function signOut() {\n const { session, user } = await getCurrentSession();\n if (session) {\n if (user) {\n await eventBus.publish(\"auth:signed-out\", { userId: user.id });\n }\n await invalidateSession(session.id);\n await deleteSessionTokenCookie();\n }\n}\n"],"mappings":"ylCA8DA,eAAe,EAAkB,EAA0C,CACzE,GAAI,CAQF,IAAM,GANY,MAAM,EACrB,OAAO,CAAE,KAAM,EAAW,KAAM,CAAC,CACjC,KAAK,EAAkB,CACvB,UAAU,EAAY,EAAG,EAAkB,OAAQ,EAAW,GAAG,CAAC,CAClE,MAAM,EAAG,EAAkB,OAAQ,EAAK,GAAG,CAAC,EAEvB,IAAK,GAAM,EAAE,KAAK,CAYpC,GATkB,MAAM,EAC3B,OAAO,CAAE,KAAM,EAAiB,KAAM,CAAC,CACvC,KAAK,EAAwB,CAC7B,UACC,EACA,EAAG,EAAwB,aAAc,EAAiB,GAAG,CAC9D,CACA,MAAM,EAAG,EAAwB,OAAQ,EAAK,GAAG,CAAC,EAEjB,IAAK,GAAM,EAAE,KAAK,CAGlD,EAAsB,EAAE,CAC5B,GAAI,EAAM,OAAS,EAAG,CAMpB,IAAM,GALgB,MAAM,EACzB,OAAO,CAAE,GAAI,EAAW,GAAI,CAAC,CAC7B,KAAK,EAAW,CAChB,MAAM,EAAQ,EAAW,KAAM,EAAM,CAAC,EAEX,IAAK,GAAM,EAAE,GAAG,CAE1C,EAAQ,OAAS,IASnB,GARsB,MAAM,EACzB,OAAO,CAAE,KAAM,EAAiB,KAAM,CAAC,CACvC,KAAK,EAAwB,CAC7B,UACC,EACA,EAAG,EAAwB,aAAc,EAAiB,GAAG,CAC9D,CACA,MAAM,EAAQ,EAAwB,OAAQ,EAAQ,CAAC,EAChC,IAAK,GAAM,EAAE,KAAK,EAIhD,MAAO,CACL,QACA,YAAa,MAAM,KAAK,IAAI,IAAI,CAAC,GAAG,EAAa,GAAG,EAAU,CAAC,CAAC,CACjE,OACM,EAAO,CAEd,OADA,QAAQ,MAAM,sCAAuC,EAAM,CACpD,CAAE,MAAO,EAAE,CAAE,YAAa,EAAE,CAAE,EA6BzC,MAAM,EAAgB,WAShB,EACJ,EAAc,0BAA4B,IAAI,IAC1C,EACJ,EAAc,gCACd,IAAI,IACA,EACJ,EAAc,oCACd,IAAI,IACA,EACJ,EAAc,wCACd,IAAI,IAEN,EAAc,yBAA2B,EACzC,EAAc,+BAAiC,EAC/C,EAAc,mCAAqC,EACnD,EAAc,uCACZ,EAEF,eAAsB,EAAsB,EAA0B,CACpE,EAAe,IAAI,EAAU,CAG/B,eAAsB,EACpB,EACA,CACA,EAAwB,IAAI,EAAU,CAGxC,eAAsB,EACpB,EACA,CACA,EAA4B,IAAI,EAAU,CAW5C,eAAsB,EACpB,EACA,CACA,EAAqB,IAAI,EAAY,CAGvC,eAAsB,EACpB,EAC8B,CAC9B,IAAK,IAAM,KAAa,EAAyB,CAC/C,IAAM,EAAe,MAAM,EAAU,EAAO,CAC5C,GAAI,EAAc,OAAO,EAE3B,OAAO,KAGT,eAAsB,EACpB,EAC8B,CAC9B,IAAK,IAAM,KAAa,EAA6B,CACnD,IAAM,EAAe,MAAM,EAAU,EAAO,CAC5C,GAAI,EAAc,OAAO,EAE3B,OAAO,KAOT,eAAsB,EACpB,EACmB,CAEnB,OAAO,MAAM,EAAY,EADJ,MAAM,EAAkB,EAAK,CACN,CAM9C,eAAsB,EACpB,EACA,EACA,EACA,EACA,EACA,CACA,GAAI,CAAC,EAEH,OADA,QAAQ,KAAK,sCAAsC,CAC5C,CAAE,UAAW,GAAO,SAAU,GAAoB,UAAW,CAGtE,IAAM,EAAY,MAAM,QAAQ,EAAK,MAAM,CAAG,EAAK,MAAQ,EAAE,CACvD,EAAkB,MAAM,QAAQ,EAAK,YAAY,CACnD,EAAK,YACL,EAAE,CAGN,GAAI,GAAiB,EAAc,OAAS,GAEtC,CADY,EAAc,KAAM,GAAS,EAAU,SAAS,EAAK,CAAC,CAGpE,OADA,QAAQ,KAAK,8BAA8B,EAAc,KAAK,KAAK,GAAG,CAC/D,CACL,UAAW,GACX,SAAU,EACX,CAKL,GAAI,GAAuB,EAAoB,OAAS,GAIlD,CAHsB,EAAoB,MAAO,GACnD,EAAgB,SAAS,EAAK,CAC/B,CAMC,OAJA,QAAQ,KACN,oCAAoC,EAAoB,KAAK,KAAK,GACnE,CAEM,CACL,UAAW,GACX,SAAU,EACX,CAKL,GAAI,EACF,IAAK,IAAM,KAAe,EACxB,GAAI,CACF,IAAM,EAAS,MAAM,EAAY,EAAS,EAAK,CAC/C,GAAI,GAAU,CAAC,EAAO,UACpB,MAAO,CACL,GAAG,EACH,SAAU,EAAO,UAAY,EAC9B,OAEI,EAAO,CACd,QAAQ,MAAM,sCAAuC,EAAM,CAIjE,MAAO,CAAE,UAAW,GAAM,CAM5B,eAAsB,EAAO,EAAyC,CACpE,GAAM,CAAE,QAAO,YAAa,MAAM,EAAY,WAAW,EAAK,CAExD,EAAO,MAAM,EAAiB,EAAM,CAC1C,GAAI,CAAC,EACH,MAAO,CAAE,OAAQ,QAAS,QAAS,4BAA6B,CAGlE,IAAM,EAAe,MAAM,EAAoB,EAAK,GAAG,CACvD,GAAI,CAAC,GAAgB,CAAE,MAAM,EAAmB,EAAc,EAAS,CACrE,MAAO,CAAE,OAAQ,QAAS,QAAS,4BAA6B,CAIlE,IAAK,IAAM,KAAa,EAAgB,CACtC,IAAM,EAAe,MAAM,EAAU,EAAK,GAAG,CAC7C,GAAI,EAAc,OAAO,EAG3B,IAAM,EAA6B,EAAE,CAC/B,EAAe,MAAM,GAAsB,CAC3C,EAAU,MAAM,EAAc,EAAc,EAAK,GAAI,EAAa,CACxE,MAAM,EAAsB,EAAc,EAAQ,UAAU,CAE5D,IAAM,EAAW,MAAM,EAA4B,EAAK,CAGxD,OAFA,MAAM,EAAS,QAAQ,uBAAwB,CAAE,UAAS,KAAM,EAAU,CAAC,CAEpE,CACL,OAAQ,UACR,QAAS,CAAE,GAAG,EAAS,CACvB,KAAM,CAAE,GAAG,EAAU,CACtB,CAMH,eAAsB,EAAO,EAAqB,CAChD,GAAM,CAAE,QAAO,WAAU,YAAa,EAAe,MAAM,EAAK,CAEhE,GAAI,CAAE,MAAM,EAAoB,EAAS,CACvC,MAAU,MAAM,mBAAmB,CAGrC,GAAI,CAAE,MAAM,EAAuB,EAAS,CAC1C,MAAU,MAAM,gBAAgB,CAGlC,IAAM,EAAO,MAAM,EAAW,EAAO,EAAU,EAAS,CAClD,EAAsB,MAAM,EAChC,EAAK,GACL,EAAK,MACN,CAED,MAAM,EACJ,EAAoB,MACpB,EAAoB,KACrB,CACD,MAAM,EAAkC,EAAoB,CAE5D,IAAM,EAA6B,EAAE,CAC/B,EAAe,MAAM,GAAsB,CAC3C,EAAU,MAAM,EAAc,EAAc,EAAK,GAAI,EAAa,CACxE,MAAM,EAAsB,EAAc,EAAQ,UAAU,CAE5D,IAAM,EAAW,MAAM,EAA4B,EAAK,CAGxD,OAFA,MAAM,EAAS,QAAQ,uBAAwB,CAAE,UAAS,KAAM,EAAU,CAAC,CAEpE,CACL,QAAS,CAAE,GAAG,EAAS,CACvB,KAAM,CAAE,GAAG,EAAU,CACtB,CAMH,eAAsB,EAAc,EAAgB,EAAqB,CACvE,IAAM,EAAe,MAAM,GAAsB,CAC3C,EAAU,MAAM,EAAc,EAAc,EAAQ,EAAM,CAChE,MAAM,EAAsB,EAAc,EAAQ,UAAU,CAE5D,IAAM,EAAO,MAAM,EAAY,EAAO,CAMtC,OAJI,GACF,MAAM,EAAS,QAAQ,uBAAwB,CAAE,UAAS,OAAM,CAAC,CAG5D,CACL,QAAS,EAAU,CAAE,GAAG,EAAS,CAAG,KACpC,KAAM,EAAO,CAAE,GAAG,EAAM,CAAG,KAC5B,CAMH,eAAsB,GAAU,CAC9B,GAAM,CAAE,UAAS,QAAS,MAAM,GAAmB,CAC/C,IACE,GACF,MAAM,EAAS,QAAQ,kBAAmB,CAAE,OAAQ,EAAK,GAAI,CAAC,CAEhE,MAAM,EAAkB,EAAQ,GAAG,CACnC,MAAM,GAA0B"}
@@ -1,39 +0,0 @@
1
- import { PasswordResetAuthSession, PasswordResetSession } from "./types.mjs";
2
-
3
- //#region src/core/auth/password-reset.d.ts
4
- /**
5
- * Creates a new password reset session.
6
- */
7
- declare function createPasswordResetSession(token: string, userId: string, email: string): Promise<PasswordResetSession>;
8
- /**
9
- * Validates the password reset session token and retrieves user data.
10
- * The user data is augmented by registered modules (e.g. 2FA).
11
- */
12
- declare function validatePasswordResetSessionToken(token: string): Promise<PasswordResetAuthSession>;
13
- /**
14
- * Marks the password reset session as email verified.
15
- */
16
- declare function setPasswordResetSessionAsEmailVerified(sessionId: string): Promise<void>;
17
- /**
18
- * Invalidates all password reset sessions for a user.
19
- */
20
- declare function invalidateUserPasswordResetSessions(userId: string): Promise<void>;
21
- /**
22
- * Validates the current password reset session from cookies.
23
- */
24
- declare function getCurrentPasswordResetSession(): Promise<PasswordResetAuthSession>;
25
- /**
26
- * Sets the password reset session token cookie.
27
- */
28
- declare function setPasswordResetSessionTokenCookie(token: string, expiresAt: Date): Promise<void>;
29
- /**
30
- * Deletes the password reset session token cookie.
31
- */
32
- declare function deletePasswordResetSessionTokenCookie(): Promise<void>;
33
- /**
34
- * Sends a password reset email with the OTP code.
35
- */
36
- declare function sendPasswordResetEmail(email: string, code: string): Promise<void>;
37
- //#endregion
38
- export { createPasswordResetSession, deletePasswordResetSessionTokenCookie, getCurrentPasswordResetSession, invalidateUserPasswordResetSessions, sendPasswordResetEmail, setPasswordResetSessionAsEmailVerified, setPasswordResetSessionTokenCookie, validatePasswordResetSessionToken };
39
- //# sourceMappingURL=password-reset.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"password-reset.d.mts","names":[],"sources":["../../../src/core/auth/password-reset.ts"],"mappings":";;;;;AAqBA;iBAAsB,0BAAA,CACpB,KAAA,UACA,MAAA,UACA,KAAA,WACC,OAAA,CAAQ,oBAAA;;;;;iBAqBW,iCAAA,CACpB,KAAA,WACC,OAAA,CAAQ,wBAAA;;;;iBAyCW,sCAAA,CACpB,SAAA,WACC,OAAA;AA7CH;;;AAAA,iBAyDsB,mCAAA,CACpB,MAAA,WACC,OAAA;;;;iBASmB,8BAAA,CAAA,GAAkC,OAAA,CAAQ,wBAAA;;AAzBhE;;iBA6CsB,kCAAA,CACpB,KAAA,UACA,SAAA,EAAW,IAAA,GACV,OAAA;;;AAlCH;iBAiDsB,qCAAA,CAAA,GAAyC,OAAA;;;;iBAQzC,sBAAA,CACpB,KAAA,UACA,IAAA,WACC,OAAA"}
@@ -1,2 +0,0 @@
1
- "use server";import{db as e}from"../../server/database/inject.mjs";import{passwordResetSessionTable as t,userTable as n}from"../../server/database/schema.mjs";import{augmentPasswordResetSession as r}from"./augment.mjs";import{generateRandomOTP as i}from"./utils/encode.mjs";import{sendResetPassword as a}from"../../server/emails/index.mjs";import{performFullUserAugmentation as o}from"./logic.mjs";import{eq as s}from"drizzle-orm";import{sha256 as c}from"@oslojs/crypto/sha2";import{encodeHexLowerCase as l}from"@oslojs/encoding";import{addHours as u}from"date-fns";import{cookies as d}from"next/headers";async function f(n,r,a){let o=l(c(new TextEncoder().encode(n))),[s]=await e.insert(t).values({id:o,email:a,code:i(),expiresAt:new Date(u(new Date,1)),userId:r}).returning();return s}async function p(i){let a=l(c(new TextEncoder().encode(i))),[u]=await e.select({session:t,user:n}).from(t).innerJoin(n,s(t.userId,n.id)).where(s(t.id,a));if(!u||!u.user)return{session:null,user:null};let{session:d,user:f}=u;if(new Date>d.expiresAt)return await e.delete(t).where(s(t.id,d.id)),{session:null,user:null};let{password:p,recovery_code:m,...h}=f,g=await o(h);return{session:await r(d),user:g}}async function m(n){await e.update(t).set({emailVerified:!0}).where(s(t.id,n))}async function h(n){await e.delete(t).where(s(t.userId,n))}async function g(){let e=(await d()).get(`password_reset_session`)?.value??null;if(e===null)return{session:null,user:null};let t=await p(e);return t.session===null&&await v(),t}async function _(e,t){(await d()).set(`password_reset_session`,e,{expires:t,sameSite:`lax`,httpOnly:!0,path:`/`,secure:process.env.NODE_ENV===`production`})}async function v(){(await d()).delete(`password_reset_session`)}async function y(e,t){await a(e,t)}export{f as createPasswordResetSession,v as deletePasswordResetSessionTokenCookie,g as getCurrentPasswordResetSession,h as invalidateUserPasswordResetSessions,y as sendPasswordResetEmail,m as setPasswordResetSessionAsEmailVerified,_ as setPasswordResetSessionTokenCookie,p as validatePasswordResetSessionToken};
2
- //# sourceMappingURL=password-reset.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"password-reset.mjs","names":[],"sources":["../../../src/core/auth/password-reset.ts"],"sourcesContent":["\"use server\";\n\nimport { sha256 } from \"@oslojs/crypto/sha2\";\nimport { encodeHexLowerCase } from \"@oslojs/encoding\";\nimport { addHours } from \"date-fns\";\nimport { eq } from \"drizzle-orm\";\nimport { cookies } from \"next/headers\";\nimport { db } from \"../../server/database/inject\";\nimport {\n passwordResetSessionTable,\n userTable,\n} from \"../../server/database/schema\";\nimport { sendResetPassword } from \"../../server/emails/index\";\nimport { augmentPasswordResetSession } from \"./augment\";\nimport { performFullUserAugmentation } from \"./logic\";\nimport type { PasswordResetAuthSession, PasswordResetSession } from \"./types\";\nimport { generateRandomOTP } from \"./utils/encode\";\n\n/**\n * Creates a new password reset session.\n */\nexport async function createPasswordResetSession(\n token: string,\n userId: string,\n email: string,\n): Promise<PasswordResetSession> {\n const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));\n\n const [session] = await db\n .insert(passwordResetSessionTable)\n .values({\n id: sessionId,\n email: email,\n code: generateRandomOTP(),\n expiresAt: new Date(addHours(new Date(), 1)),\n userId: userId,\n })\n .returning();\n\n return session;\n}\n\n/**\n * Validates the password reset session token and retrieves user data.\n * The user data is augmented by registered modules (e.g. 2FA).\n */\nexport async function validatePasswordResetSessionToken(\n token: string,\n): Promise<PasswordResetAuthSession> {\n const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));\n\n const [row] = await db\n .select({\n session: passwordResetSessionTable,\n user: userTable,\n })\n .from(passwordResetSessionTable)\n .innerJoin(userTable, eq(passwordResetSessionTable.userId, userTable.id))\n .where(eq(passwordResetSessionTable.id, sessionId));\n\n if (!row || !row.user) {\n return { session: null, user: null };\n }\n\n const { session: baseSession, user: baseUser } = row;\n\n // Check for expiration\n if (new Date() > baseSession.expiresAt) {\n await db\n .delete(passwordResetSessionTable)\n .where(eq(passwordResetSessionTable.id, baseSession.id));\n return { session: null, user: null };\n }\n\n // STRICTLY remove non-serializable and sensitive fields\n const { password, recovery_code, ...safeUser } = baseUser;\n\n // AUGMENT (EXTENSIBILITY POINTS)\n const user = await performFullUserAugmentation(safeUser as any);\n const session = await augmentPasswordResetSession(\n baseSession as PasswordResetSession,\n );\n\n return { session, user };\n}\n\n/**\n * Marks the password reset session as email verified.\n */\nexport async function setPasswordResetSessionAsEmailVerified(\n sessionId: string,\n): Promise<void> {\n await db\n .update(passwordResetSessionTable)\n .set({\n emailVerified: true,\n })\n .where(eq(passwordResetSessionTable.id, sessionId));\n}\n\n/**\n * Invalidates all password reset sessions for a user.\n */\nexport async function invalidateUserPasswordResetSessions(\n userId: string,\n): Promise<void> {\n await db\n .delete(passwordResetSessionTable)\n .where(eq(passwordResetSessionTable.userId, userId));\n}\n\n/**\n * Validates the current password reset session from cookies.\n */\nexport async function getCurrentPasswordResetSession(): Promise<PasswordResetAuthSession> {\n const cookieStore = await cookies();\n const token = cookieStore.get(\"password_reset_session\")?.value ?? null;\n\n if (token === null) {\n return { session: null, user: null };\n }\n\n const result = await validatePasswordResetSessionToken(token);\n\n if (result.session === null) {\n await deletePasswordResetSessionTokenCookie();\n }\n\n return result;\n}\n\n/**\n * Sets the password reset session token cookie.\n */\nexport async function setPasswordResetSessionTokenCookie(\n token: string,\n expiresAt: Date,\n): Promise<void> {\n const cookieStore = await cookies();\n\n cookieStore.set(\"password_reset_session\", token, {\n expires: expiresAt,\n sameSite: \"lax\",\n httpOnly: true,\n path: \"/\",\n secure: process.env.NODE_ENV === \"production\",\n });\n}\n\n/**\n * Deletes the password reset session token cookie.\n */\nexport async function deletePasswordResetSessionTokenCookie(): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.delete(\"password_reset_session\");\n}\n\n/**\n * Sends a password reset email with the OTP code.\n */\nexport async function sendPasswordResetEmail(\n email: string,\n code: string,\n): Promise<void> {\n await sendResetPassword(email, code);\n}\n"],"mappings":"6lBAqBA,eAAsB,EACpB,EACA,EACA,EAC+B,CAC/B,IAAM,EAAY,EAAmB,EAAO,IAAI,aAAa,CAAC,OAAO,EAAM,CAAC,CAAC,CAEvE,CAAC,GAAW,MAAM,EACrB,OAAO,EAA0B,CACjC,OAAO,CACN,GAAI,EACG,QACP,KAAM,GAAmB,CACzB,UAAW,IAAI,KAAK,EAAS,IAAI,KAAQ,EAAE,CAAC,CACpC,SACT,CAAC,CACD,WAAW,CAEd,OAAO,EAOT,eAAsB,EACpB,EACmC,CACnC,IAAM,EAAY,EAAmB,EAAO,IAAI,aAAa,CAAC,OAAO,EAAM,CAAC,CAAC,CAEvE,CAAC,GAAO,MAAM,EACjB,OAAO,CACN,QAAS,EACT,KAAM,EACP,CAAC,CACD,KAAK,EAA0B,CAC/B,UAAU,EAAW,EAAG,EAA0B,OAAQ,EAAU,GAAG,CAAC,CACxE,MAAM,EAAG,EAA0B,GAAI,EAAU,CAAC,CAErD,GAAI,CAAC,GAAO,CAAC,EAAI,KACf,MAAO,CAAE,QAAS,KAAM,KAAM,KAAM,CAGtC,GAAM,CAAE,QAAS,EAAa,KAAM,GAAa,EAGjD,GAAI,IAAI,KAAS,EAAY,UAI3B,OAHA,MAAM,EACH,OAAO,EAA0B,CACjC,MAAM,EAAG,EAA0B,GAAI,EAAY,GAAG,CAAC,CACnD,CAAE,QAAS,KAAM,KAAM,KAAM,CAItC,GAAM,CAAE,WAAU,gBAAe,GAAG,GAAa,EAG3C,EAAO,MAAM,EAA4B,EAAgB,CAK/D,MAAO,CAAE,QAJO,MAAM,EACpB,EACD,CAEiB,OAAM,CAM1B,eAAsB,EACpB,EACe,CACf,MAAM,EACH,OAAO,EAA0B,CACjC,IAAI,CACH,cAAe,GAChB,CAAC,CACD,MAAM,EAAG,EAA0B,GAAI,EAAU,CAAC,CAMvD,eAAsB,EACpB,EACe,CACf,MAAM,EACH,OAAO,EAA0B,CACjC,MAAM,EAAG,EAA0B,OAAQ,EAAO,CAAC,CAMxD,eAAsB,GAAoE,CAExF,IAAM,GADc,MAAM,GAAS,EACT,IAAI,yBAAyB,EAAE,OAAS,KAElE,GAAI,IAAU,KACZ,MAAO,CAAE,QAAS,KAAM,KAAM,KAAM,CAGtC,IAAM,EAAS,MAAM,EAAkC,EAAM,CAM7D,OAJI,EAAO,UAAY,MACrB,MAAM,GAAuC,CAGxC,EAMT,eAAsB,EACpB,EACA,EACe,EACK,MAAM,GAAS,EAEvB,IAAI,yBAA0B,EAAO,CAC/C,QAAS,EACT,SAAU,MACV,SAAU,GACV,KAAM,IACN,OAAQ,QAAQ,IAAI,WAAa,aAClC,CAAC,CAMJ,eAAsB,GAAuD,EACvD,MAAM,GAAS,EACvB,OAAO,yBAAyB,CAM9C,eAAsB,EACpB,EACA,EACe,CACf,MAAM,EAAkB,EAAO,EAAK"}
@@ -1,61 +0,0 @@
1
- import * as pg from "pg";
2
-
3
- //#region src/core/auth/rbac.d.ts
4
- /**
5
- * CORE RBAC LOGIC
6
- * This file handles all database operations for Roles and Permissions.
7
- */
8
- declare function getRoles(): Promise<{
9
- id: string;
10
- name: string;
11
- description: string | null;
12
- }[]>;
13
- declare function getRoleById(roleId: string): Promise<{
14
- id: string;
15
- name: string;
16
- description: string | null;
17
- }>;
18
- declare function createRole(name: string, description?: string): Promise<{
19
- id: string;
20
- name: string;
21
- description: string | null;
22
- }[]>;
23
- declare function deleteRole(roleId: string): Promise<pg.QueryResult<never>>;
24
- declare function getPermissions(): Promise<{
25
- id: string;
26
- name: string;
27
- description: string | null;
28
- }[]>;
29
- declare function createPermission(name: string, description?: string): Promise<{
30
- id: string;
31
- name: string;
32
- description: string | null;
33
- }[]>;
34
- declare function deletePermission(permissionId: string): Promise<pg.QueryResult<never>>;
35
- declare function getRolePermissions(roleId: string): Promise<{
36
- id: string;
37
- name: string;
38
- }[]>;
39
- declare function assignPermissionToRole(roleId: string, permissionId: string): Promise<pg.QueryResult<never>>;
40
- declare function revokePermissionFromRole(roleId: string, permissionId: string): Promise<pg.QueryResult<never>>;
41
- declare function assignRoleToUser(userId: string, roleId: string): Promise<pg.QueryResult<never>>;
42
- declare function revokeRoleFromUser(userId: string, roleId: string): Promise<pg.QueryResult<never>>;
43
- declare function assignPermissionToUser(userId: string, permissionId: string): Promise<pg.QueryResult<never>>;
44
- declare function revokePermissionFromUser(userId: string, permissionId: string): Promise<pg.QueryResult<never>>;
45
- declare function getUserRbacData(userId: string): Promise<{
46
- roles: {
47
- id: string;
48
- name: string;
49
- }[];
50
- directPermissions: {
51
- id: string;
52
- name: string;
53
- }[];
54
- effectivePermissions: {
55
- id: string;
56
- name: string;
57
- }[];
58
- }>;
59
- //#endregion
60
- export { assignPermissionToRole, assignPermissionToUser, assignRoleToUser, createPermission, createRole, deletePermission, deleteRole, getPermissions, getRoleById, getRolePermissions, getRoles, getUserRbacData, revokePermissionFromRole, revokePermissionFromUser, revokeRoleFromUser };
61
- //# sourceMappingURL=rbac.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rbac.d.mts","names":[],"sources":["../../../src/core/auth/rbac.ts"],"mappings":";;;;;;AAyBA;iBAAsB,QAAA,CAAA,GAAQ,OAAA;;;;;iBAIR,WAAA,CAAY,MAAA,WAAc,OAAA;;;;;iBAQ1B,UAAA,CAAW,IAAA,UAAc,WAAA,YAAoB,OAAA;;;;;iBAI7C,UAAA,CAAW,MAAA,WAAc,OAAA,CAAf,EAAA,CAAe,WAAA;AAAA,iBAMzB,cAAA,CAAA,GAAc,OAAA;;;;;iBAOd,gBAAA,CAAiB,IAAA,UAAc,WAAA,YAAoB,OAAA;;;;;iBAOnD,gBAAA,CAAiB,YAAA,WAAoB,OAAA,CAArB,EAAA,CAAqB,WAAA;AAAA,iBAQrC,kBAAA,CAAmB,MAAA,WAAc,OAAA;;;;iBAcjC,sBAAA,CACpB,MAAA,UACA,YAAA,WAAoB,OAAA,CAFsB,EAAA,CAEtB,WAAA;AAAA,iBAQA,wBAAA,CACpB,MAAA,UACA,YAAA,WAAoB,OAAA,CAFwB,EAAA,CAExB,WAAA;AAAA,iBAcA,gBAAA,CAAiB,MAAA,UAAgB,MAAA,WAAc,OAAA,CAA/B,EAAA,CAA+B,WAAA;AAAA,iBAO/C,kBAAA,CAAmB,MAAA,UAAgB,MAAA,WAAc,OAAA,CAA/B,EAAA,CAA+B,WAAA;AAAA,iBAWjD,sBAAA,CACpB,MAAA,UACA,YAAA,WAAoB,OAAA,CAFsB,EAAA,CAEtB,WAAA;AAAA,iBAQA,wBAAA,CACpB,MAAA,UACA,YAAA,WAAoB,OAAA,CAFwB,EAAA,CAExB,WAAA;AAAA,iBAYA,eAAA,CAAgB,MAAA,WAAc,OAAA"}
@@ -1,2 +0,0 @@
1
- "use server";import{db as e}from"../../server/database/inject.mjs";import{permissionsTable as t,rolesTable as n,rolesToPermissionsTable as r,usersToPermissionsTable as i,usersToRolesTable as a}from"../../server/database/schema.mjs";import{notificationService as o}from"../notifications/service.mjs";import"../notifications/index.mjs";import{and as s,eq as c,inArray as l}from"drizzle-orm";typeof window>`u`&&o.init();async function u(){return await e.select().from(n).orderBy(n.name)}async function d(t){let[r]=await e.select().from(n).where(c(n.id,t));return r}async function f(t,r){return await e.insert(n).values({name:t,description:r}).returning()}async function p(t){return await e.delete(n).where(c(n.id,t))}async function m(){return await e.select().from(t).orderBy(t.name)}async function h(n,r){return await e.insert(t).values({name:n,description:r}).returning()}async function g(n){return await e.delete(t).where(c(t.id,n))}async function _(n){return await e.select({id:t.id,name:t.name}).from(r).innerJoin(t,c(r.permissionId,t.id)).where(c(r.roleId,n))}async function v(t,n){return await e.insert(r).values({roleId:t,permissionId:n}).onConflictDoNothing()}async function y(t,n){return await e.delete(r).where(s(c(r.roleId,t),c(r.permissionId,n)))}async function b(t,n){return await e.insert(a).values({userId:t,roleId:n}).onConflictDoNothing()}async function x(t,n){return await e.delete(a).where(s(c(a.userId,t),c(a.roleId,n)))}async function S(t,n){return await e.insert(i).values({userId:t,permissionId:n}).onConflictDoNothing()}async function C(t,n){return await e.delete(i).where(s(c(i.userId,t),c(i.permissionId,n)))}async function w(o){let s=await e.select({id:n.id,name:n.name}).from(a).innerJoin(n,c(a.roleId,n.id)).where(c(a.userId,o)),u=await e.select({id:t.id,name:t.name}).from(i).innerJoin(t,c(i.permissionId,t.id)).where(c(i.userId,o)),d=[];if(s.length>0){let n=s.map(e=>e.id);d=await e.select({id:t.id,name:t.name}).from(r).innerJoin(t,c(r.permissionId,t.id)).where(l(r.roleId,n))}let f=new Map;for(let e of[...u,...d])f.set(e.id,e);return{roles:s,directPermissions:u,effectivePermissions:Array.from(f.values())}}export{v as assignPermissionToRole,S as assignPermissionToUser,b as assignRoleToUser,h as createPermission,f as createRole,g as deletePermission,p as deleteRole,m as getPermissions,d as getRoleById,_ as getRolePermissions,u as getRoles,w as getUserRbacData,y as revokePermissionFromRole,C as revokePermissionFromUser,x as revokeRoleFromUser};
2
- //# sourceMappingURL=rbac.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rbac.mjs","names":[],"sources":["../../../src/core/auth/rbac.ts"],"sourcesContent":["\"use server\";\n\nimport { and, eq, inArray } from \"drizzle-orm\";\nimport { db } from \"../../server/database/inject\";\nimport {\n permissionsTable,\n rolesTable,\n rolesToPermissionsTable,\n usersToPermissionsTable,\n usersToRolesTable,\n} from \"../../server/database/schema\";\nimport { notificationService } from \"../notifications/index\";\n\n// Ensure notification service is loaded\nif (typeof window === \"undefined\") {\n notificationService.init();\n}\n\n/**\n * CORE RBAC LOGIC\n * This file handles all database operations for Roles and Permissions.\n */\n\n// --- Roles ---\n\nexport async function getRoles() {\n return await db.select().from(rolesTable).orderBy(rolesTable.name);\n}\n\nexport async function getRoleById(roleId: string) {\n const [role] = await db\n .select()\n .from(rolesTable)\n .where(eq(rolesTable.id, roleId));\n return role;\n}\n\nexport async function createRole(name: string, description?: string) {\n return await db.insert(rolesTable).values({ name, description }).returning();\n}\n\nexport async function deleteRole(roleId: string) {\n return await db.delete(rolesTable).where(eq(rolesTable.id, roleId));\n}\n\n// --- Permissions ---\n\nexport async function getPermissions() {\n return await db\n .select()\n .from(permissionsTable)\n .orderBy(permissionsTable.name);\n}\n\nexport async function createPermission(name: string, description?: string) {\n return await db\n .insert(permissionsTable)\n .values({ name, description })\n .returning();\n}\n\nexport async function deletePermission(permissionId: string) {\n return await db\n .delete(permissionsTable)\n .where(eq(permissionsTable.id, permissionId));\n}\n\n// --- Mappings ---\n\nexport async function getRolePermissions(roleId: string) {\n return await db\n .select({\n id: permissionsTable.id,\n name: permissionsTable.name,\n })\n .from(rolesToPermissionsTable)\n .innerJoin(\n permissionsTable,\n eq(rolesToPermissionsTable.permissionId, permissionsTable.id),\n )\n .where(eq(rolesToPermissionsTable.roleId, roleId));\n}\n\nexport async function assignPermissionToRole(\n roleId: string,\n permissionId: string,\n) {\n return await db\n .insert(rolesToPermissionsTable)\n .values({ roleId, permissionId })\n .onConflictDoNothing();\n}\n\nexport async function revokePermissionFromRole(\n roleId: string,\n permissionId: string,\n) {\n return await db\n .delete(rolesToPermissionsTable)\n .where(\n and(\n eq(rolesToPermissionsTable.roleId, roleId),\n eq(rolesToPermissionsTable.permissionId, permissionId),\n ),\n );\n}\n\n// --- User Assignment ---\n\nexport async function assignRoleToUser(userId: string, roleId: string) {\n return await db\n .insert(usersToRolesTable)\n .values({ userId, roleId })\n .onConflictDoNothing();\n}\n\nexport async function revokeRoleFromUser(userId: string, roleId: string) {\n return await db\n .delete(usersToRolesTable)\n .where(\n and(\n eq(usersToRolesTable.userId, userId),\n eq(usersToRolesTable.roleId, roleId),\n ),\n );\n}\n\nexport async function assignPermissionToUser(\n userId: string,\n permissionId: string,\n) {\n return await db\n .insert(usersToPermissionsTable)\n .values({ userId, permissionId })\n .onConflictDoNothing();\n}\n\nexport async function revokePermissionFromUser(\n userId: string,\n permissionId: string,\n) {\n return await db\n .delete(usersToPermissionsTable)\n .where(\n and(\n eq(usersToPermissionsTable.userId, userId),\n eq(usersToPermissionsTable.permissionId, permissionId),\n ),\n );\n}\n\nexport async function getUserRbacData(userId: string) {\n const roles = await db\n .select({\n id: rolesTable.id,\n name: rolesTable.name,\n })\n .from(usersToRolesTable)\n .innerJoin(rolesTable, eq(usersToRolesTable.roleId, rolesTable.id))\n .where(eq(usersToRolesTable.userId, userId));\n\n const directPermissions = await db\n .select({\n id: permissionsTable.id,\n name: permissionsTable.name,\n })\n .from(usersToPermissionsTable)\n .innerJoin(\n permissionsTable,\n eq(usersToPermissionsTable.permissionId, permissionsTable.id),\n )\n .where(eq(usersToPermissionsTable.userId, userId));\n\n // Fetch inherited permissions from roles\n let rolePermissions: { id: string; name: string }[] = [];\n if (roles.length > 0) {\n const roleIds = roles.map((r) => r.id);\n rolePermissions = await db\n .select({\n id: permissionsTable.id,\n name: permissionsTable.name,\n })\n .from(rolesToPermissionsTable)\n .innerJoin(\n permissionsTable,\n eq(rolesToPermissionsTable.permissionId, permissionsTable.id),\n )\n .where(inArray(rolesToPermissionsTable.roleId, roleIds));\n }\n\n // Combine for effective permissions\n const effectiveMap = new Map<string, { id: string; name: string }>();\n for (const p of [...directPermissions, ...rolePermissions]) {\n effectiveMap.set(p.id, p);\n }\n\n return {\n roles,\n directPermissions,\n effectivePermissions: Array.from(effectiveMap.values()),\n };\n}\n"],"mappings":"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"}
@@ -1,54 +0,0 @@
1
- import { AuthSession, Session, SessionFlags, UserSession } from "./types.mjs";
2
-
3
- //#region src/core/auth/session.d.ts
4
- /**
5
- * Returns the user's IP address.
6
- */
7
- declare function getIPAddress(): Promise<string | null>;
8
- /**
9
- * Validates the session token.
10
- */
11
- declare function validateSessionToken(token: string): Promise<AuthSession>;
12
- /**
13
- * Returns the current user session from cookies.
14
- */
15
- declare const getCurrentSession: () => Promise<AuthSession>;
16
- /**
17
- * Invalidates a single session.
18
- */
19
- declare function invalidateSession(sessionId: string): Promise<void>;
20
- /**
21
- * Invalidates all user sessions.
22
- */
23
- declare function invalidateUserSessions(userId: string): Promise<void>;
24
- /**
25
- * Sets the session token in a cookie.
26
- */
27
- declare function setSessionTokenCookie(token: string, expiresAt: Date): Promise<void>;
28
- /**
29
- * Removes the session token cookie.
30
- */
31
- declare function deleteSessionTokenCookie(): Promise<void>;
32
- /**
33
- * Generates a new random session token.
34
- */
35
- declare function generateSessionToken(): Promise<string>;
36
- /**
37
- * Creates a new session in the database.
38
- */
39
- declare function createSession(token: string, userId: string, flags: SessionFlags): Promise<Session>;
40
- /**
41
- * Signs the user out and redirects to the sign-in page.
42
- */
43
- declare function sessionSignOut(): Promise<void>;
44
- /**
45
- * Get all active sessions for a user.
46
- */
47
- declare function getUserSessions(userId: string, currentSessionId: string): Promise<UserSession[]>;
48
- /**
49
- * Invalidate all sessions for a user except the specified current one.
50
- */
51
- declare function invalidateOtherSessions(userId: string, currentSessionId: string): Promise<void>;
52
- //#endregion
53
- export { createSession, deleteSessionTokenCookie, generateSessionToken, getCurrentSession, getIPAddress, getUserSessions, invalidateOtherSessions, invalidateSession, invalidateUserSessions, sessionSignOut, setSessionTokenCookie, validateSessionToken };
54
- //# sourceMappingURL=session.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"session.d.mts","names":[],"sources":["../../../src/core/auth/session.ts"],"mappings":";;;;;AA2BA;iBAAsB,YAAA,CAAA,GAAgB,OAAA;;;;iBAOhB,oBAAA,CACpB,KAAA,WACC,OAAA,CAAQ,WAAA;;;;cAyCE,iBAAA,QAA8B,OAAA,CAAQ,WAAA;;;;iBAc7B,iBAAA,CAAkB,SAAA,WAAoB,OAAA;AAd5D;;;AAAA,iBAqBsB,sBAAA,CAAuB,MAAA,WAAiB,OAAA;;AAP9D;;iBAcsB,qBAAA,CACpB,KAAA,UACA,SAAA,EAAW,IAAA,GACV,OAAA;;;AAVH;iBAwBsB,wBAAA,CAAA,GAA4B,OAAA;;;;iBAQ5B,oBAAA,CAAA,GAAwB,OAAA;;;;iBASxB,aAAA,CACpB,KAAA,UACA,MAAA,UACA,KAAA,EAAO,YAAA,GACN,OAAA,CAAQ,OAAA;;;;iBAmBW,cAAA,CAAA,GAAc,OAAA;;AAxCpC;;iBAsDsB,eAAA,CACpB,MAAA,UACA,gBAAA,WACC,OAAA,CAAQ,WAAA;;;AAjDX;iBAkEsB,uBAAA,CACpB,MAAA,UACA,gBAAA,WACC,OAAA"}
@@ -1,2 +0,0 @@
1
- "use server";import{db as e}from"../../server/database/inject.mjs";import{sessionTable as t,userTable as n}from"../../server/database/schema.mjs";import{augmentSession as r}from"./augment.mjs";import{performFullUserAugmentation as i}from"./logic.mjs";import{and as a,eq as o,ne as s}from"drizzle-orm";import{sha256 as c}from"@oslojs/crypto/sha2";import{encodeBase32LowerCaseNoPadding as l,encodeHexLowerCase as u}from"@oslojs/encoding";import{addDays as d}from"date-fns";import{cookies as f,headers as p}from"next/headers";import{redirect as m}from"next/navigation";async function h(){return(await p()).get(`x-forwarded-for`)}async function g(a){let s=u(c(new TextEncoder().encode(a))),[l]=await e.select({session:t,user:n}).from(t).innerJoin(n,o(t.userId,n.id)).where(o(t.id,s));if(!l||!l.user)return{session:null,user:null};let{session:d,user:f}=l,{password:p,recovery_code:m,...h}=f;if(new Date>d.expiresAt)return await e.delete(t).where(o(t.id,d.id)),{session:null,user:null};let g=await i(h),_=await r(d);return{session:_?{..._}:null,user:g?{...g}:null}}const _=async()=>{let e=(await f()).get(`session`)?.value??null;return e===null?{session:null,user:null}:await g(e)};async function v(n){await e.delete(t).where(o(t.id,n))}async function y(n){await e.delete(t).where(o(t.userId,n))}async function b(e,t){(await f()).set(`session`,e,{httpOnly:!0,path:`/`,secure:process.env.NODE_ENV===`production`,sameSite:`lax`,expires:t})}async function x(){(await f()).delete(`session`)}async function S(){let e=new Uint8Array(20);return crypto.getRandomValues(e),l(e).toLowerCase()}async function C(n,r,i){let a=u(c(new TextEncoder().encode(n))),[o]=await e.insert(t).values({id:a,expiresAt:new Date(d(new Date,7)),active_organization_id:i.activeOrganizationId,userId:r}).returning();return o}async function w(){let{session:e}=await _();e&&(await v(e.id),await x()),m(`/signin`)}async function T(n,r){return(await e.select().from(t).where(o(t.userId,n))).map(e=>({id:e.id,createdAt:e.createdAt,expiresAt:e.expiresAt,isCurrent:e.id===r}))}async function E(n,r){await e.delete(t).where(a(o(t.userId,n),s(t.id,r)))}export{C as createSession,x as deleteSessionTokenCookie,S as generateSessionToken,_ as getCurrentSession,h as getIPAddress,T as getUserSessions,E as invalidateOtherSessions,v as invalidateSession,y as invalidateUserSessions,w as sessionSignOut,b as setSessionTokenCookie,g as validateSessionToken};
2
- //# sourceMappingURL=session.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"session.mjs","names":[],"sources":["../../../src/core/auth/session.ts"],"sourcesContent":["\"use server\";\n\nimport { sha256 } from \"@oslojs/crypto/sha2\";\nimport {\n encodeBase32LowerCaseNoPadding,\n encodeHexLowerCase,\n} from \"@oslojs/encoding\";\nimport { addDays } from \"date-fns\";\nimport { and, eq, ne } from \"drizzle-orm\";\nimport { cookies, headers } from \"next/headers\";\nimport { redirect } from \"next/navigation\";\nimport { db } from \"../../server/database/inject\";\nimport { sessionTable, userTable } from \"../../server/database/schema\";\nimport { augmentSession } from \"./augment\";\nimport { performFullUserAugmentation } from \"./logic\";\n\nimport type {\n AuthSession,\n Session,\n SessionFlags,\n User,\n UserSession,\n} from \"./types\";\n\n/**\n * Returns the user's IP address.\n */\nexport async function getIPAddress(): Promise<string | null> {\n return (await headers()).get(\"x-forwarded-for\");\n}\n\n/**\n * Validates the session token.\n */\nexport async function validateSessionToken(\n token: string,\n): Promise<AuthSession> {\n const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));\n\n const [row] = await db\n .select({\n session: sessionTable,\n user: userTable,\n })\n .from(sessionTable)\n .innerJoin(userTable, eq(sessionTable.userId, userTable.id))\n .where(eq(sessionTable.id, sessionId));\n\n if (!row || !row.user) {\n return { session: null, user: null };\n }\n\n const { session: baseSession, user: baseUser } = row;\n\n // STRICTLY remove non-serializable and sensitive fields\n const { password, recovery_code, ...safeUser } = baseUser;\n\n // Check if session is expired\n if (new Date() > baseSession.expiresAt) {\n await db.delete(sessionTable).where(eq(sessionTable.id, baseSession.id));\n return { session: null, user: null };\n }\n\n // AUGMENT (EXTENSIBILITY POINTS)\n const augmentedUser = await performFullUserAugmentation(safeUser as User);\n const augmentedSession = await augmentSession(baseSession as Session);\n\n // ENSURE PLAIN OBJECTS for Client Components\n return {\n session: augmentedSession ? { ...augmentedSession } : null,\n user: augmentedUser ? { ...augmentedUser } : null,\n };\n}\n\n/**\n * Returns the current user session from cookies.\n */\nexport const getCurrentSession = async (): Promise<AuthSession> => {\n const cookieStore = await cookies();\n const token = cookieStore.get(\"session\")?.value ?? null;\n\n if (token === null) {\n return { session: null, user: null };\n }\n\n return await validateSessionToken(token);\n};\n\n/**\n * Invalidates a single session.\n */\nexport async function invalidateSession(sessionId: string): Promise<void> {\n await db.delete(sessionTable).where(eq(sessionTable.id, sessionId));\n}\n\n/**\n * Invalidates all user sessions.\n */\nexport async function invalidateUserSessions(userId: string): Promise<void> {\n await db.delete(sessionTable).where(eq(sessionTable.userId, userId));\n}\n\n/**\n * Sets the session token in a cookie.\n */\nexport async function setSessionTokenCookie(\n token: string,\n expiresAt: Date,\n): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(\"session\", token, {\n httpOnly: true,\n path: \"/\",\n secure: process.env.NODE_ENV === \"production\",\n sameSite: \"lax\",\n expires: expiresAt,\n });\n}\n\n/**\n * Removes the session token cookie.\n */\nexport async function deleteSessionTokenCookie(): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.delete(\"session\");\n}\n\n/**\n * Generates a new random session token.\n */\nexport async function generateSessionToken(): Promise<string> {\n const tokenBytes = new Uint8Array(20);\n crypto.getRandomValues(tokenBytes);\n return encodeBase32LowerCaseNoPadding(tokenBytes).toLowerCase();\n}\n\n/**\n * Creates a new session in the database.\n */\nexport async function createSession(\n token: string,\n userId: string,\n flags: SessionFlags,\n): Promise<Session> {\n const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));\n\n const [session] = await db\n .insert(sessionTable)\n .values({\n id: sessionId,\n expiresAt: new Date(addDays(new Date(), 7)),\n active_organization_id: flags.activeOrganizationId,\n userId: userId,\n })\n .returning();\n\n return session;\n}\n\n/**\n * Signs the user out and redirects to the sign-in page.\n */\nexport async function sessionSignOut() {\n const { session } = await getCurrentSession();\n\n if (session) {\n await invalidateSession(session.id);\n await deleteSessionTokenCookie();\n }\n\n redirect(\"/signin\");\n}\n\n/**\n * Get all active sessions for a user.\n */\nexport async function getUserSessions(\n userId: string,\n currentSessionId: string,\n): Promise<UserSession[]> {\n const sessions = await db\n .select()\n .from(sessionTable)\n .where(eq(sessionTable.userId, userId));\n\n return sessions.map((session) => ({\n id: session.id,\n createdAt: session.createdAt,\n expiresAt: session.expiresAt,\n isCurrent: session.id === currentSessionId,\n }));\n}\n\n/**\n * Invalidate all sessions for a user except the specified current one.\n */\nexport async function invalidateOtherSessions(\n userId: string,\n currentSessionId: string,\n): Promise<void> {\n await db\n .delete(sessionTable)\n .where(\n and(\n eq(sessionTable.userId, userId),\n ne(sessionTable.id, currentSessionId),\n ),\n );\n}\n"],"mappings":"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"}
@@ -1,55 +0,0 @@
1
- import { passwordResetSessionTable, sessionTable, userTable } from "../../server/database/schema.mjs";
2
- import { UserPermission, UserRole } from "../types.mjs";
3
-
4
- //#region src/core/auth/types.d.ts
5
- type User = typeof userTable.$inferSelect;
6
- type Session = typeof sessionTable.$inferSelect & Record<string, any>;
7
- type PasswordResetSession = typeof passwordResetSessionTable.$inferSelect & Record<string, any>;
8
- /**
9
- * Represents a user with all potential extensions.
10
- * Use this type in UI components that require data added by modules.
11
- */
12
- type FullUser = User & Record<string, any> & {
13
- roles: UserRole[];
14
- permissions: UserPermission[];
15
- };
16
- /**
17
- * Basic session context.
18
- */
19
- interface AuthSession {
20
- session: Session | null;
21
- user: FullUser | null;
22
- }
23
- interface SessionFlags {
24
- [key: string]: any;
25
- }
26
- type UserSession = {
27
- id: string;
28
- createdAt: Date;
29
- expiresAt: Date;
30
- isCurrent: boolean;
31
- [key: string]: any;
32
- };
33
- type AuthResponse = {
34
- status: "SUCCESS";
35
- session: Session;
36
- user: FullUser;
37
- redirect?: string;
38
- } | {
39
- status: "CHALLENGE_REQUIRED";
40
- type: string;
41
- userId: string;
42
- tempToken?: string;
43
- redirect?: string;
44
- } | {
45
- status: "ERROR";
46
- message: string;
47
- redirect?: string;
48
- };
49
- interface PasswordResetAuthSession {
50
- session: PasswordResetSession | null;
51
- user: FullUser | null;
52
- }
53
- //#endregion
54
- export { AuthResponse, AuthSession, FullUser, PasswordResetAuthSession, PasswordResetSession, Session, SessionFlags, User, UserSession };
55
- //# sourceMappingURL=types.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.mts","names":[],"sources":["../../../src/core/auth/types.ts"],"mappings":";;;;KASY,IAAA,UAAc,SAAA,CAAU,YAAA;AAAA,KACxB,OAAA,UAAiB,YAAA,CAAa,YAAA,GAAe,MAAA;AAAA,KAC7C,oBAAA,UACH,yBAAA,CAA0B,YAAA,GAAe,MAAA;;;;AAFlD;KAQY,QAAA,GAAW,IAAA,GACrB,MAAA;EACE,KAAA,EAAO,QAAA;EACP,WAAA,EAAa,cAAA;AAAA;;;;UAMA,WAAA;EACf,OAAA,EAAS,OAAA;EACT,IAAA,EAAM,QAAA;AAAA;AAAA,UAGS,YAAA;EAAA,CACd,GAAA;AAAA;AAAA,KAGS,WAAA;EACV,EAAA;EACA,SAAA,EAAW,IAAA;EACX,SAAA,EAAW,IAAA;EACX,SAAA;EAAA,CACC,GAAA;AAAA;AAAA,KAGS,YAAA;EACN,MAAA;EAAmB,OAAA,EAAS,OAAA;EAAS,IAAA,EAAM,QAAA;EAAU,QAAA;AAAA;EAEvD,MAAA;EACA,IAAA;EACA,MAAA;EACA,SAAA;EACA,QAAA;AAAA;EAEE,MAAA;EAAiB,OAAA;EAAiB,QAAA;AAAA;AAAA,UAEvB,wBAAA;EACf,OAAA,EAAS,oBAAA;EACT,IAAA,EAAM,QAAA;AAAA"}