@arch-cadre/core 0.0.6

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 (190) hide show
  1. package/dist/_virtual/_rolldown/runtime.cjs +29 -0
  2. package/dist/_virtual/_rolldown/runtime.mjs +18 -0
  3. package/dist/core/auth/augment.cjs +71 -0
  4. package/dist/core/auth/augment.d.cts +20 -0
  5. package/dist/core/auth/augment.d.cts.map +1 -0
  6. package/dist/core/auth/augment.d.mts +20 -0
  7. package/dist/core/auth/augment.d.mts.map +1 -0
  8. package/dist/core/auth/augment.mjs +66 -0
  9. package/dist/core/auth/augment.mjs.map +1 -0
  10. package/dist/core/auth/email-verification.cjs +99 -0
  11. package/dist/core/auth/email-verification.d.cts +62 -0
  12. package/dist/core/auth/email-verification.d.cts.map +1 -0
  13. package/dist/core/auth/email-verification.d.mts +62 -0
  14. package/dist/core/auth/email-verification.d.mts.map +1 -0
  15. package/dist/core/auth/email-verification.mjs +92 -0
  16. package/dist/core/auth/email-verification.mjs.map +1 -0
  17. package/dist/core/auth/logic.cjs +224 -0
  18. package/dist/core/auth/logic.d.cts +110 -0
  19. package/dist/core/auth/logic.d.cts.map +1 -0
  20. package/dist/core/auth/logic.d.mts +110 -0
  21. package/dist/core/auth/logic.d.mts.map +1 -0
  22. package/dist/core/auth/logic.mjs +213 -0
  23. package/dist/core/auth/logic.mjs.map +1 -0
  24. package/dist/core/auth/password-reset.cjs +118 -0
  25. package/dist/core/auth/password-reset.d.cts +39 -0
  26. package/dist/core/auth/password-reset.d.cts.map +1 -0
  27. package/dist/core/auth/password-reset.d.mts +39 -0
  28. package/dist/core/auth/password-reset.d.mts.map +1 -0
  29. package/dist/core/auth/password-reset.mjs +111 -0
  30. package/dist/core/auth/password-reset.mjs.map +1 -0
  31. package/dist/core/auth/rbac.cjs +118 -0
  32. package/dist/core/auth/rbac.d.cts +61 -0
  33. package/dist/core/auth/rbac.d.cts.map +1 -0
  34. package/dist/core/auth/rbac.d.mts +61 -0
  35. package/dist/core/auth/rbac.d.mts.map +1 -0
  36. package/dist/core/auth/rbac.mjs +104 -0
  37. package/dist/core/auth/rbac.mjs.map +1 -0
  38. package/dist/core/auth/session.cjs +161 -0
  39. package/dist/core/auth/session.d.cts +54 -0
  40. package/dist/core/auth/session.d.cts.map +1 -0
  41. package/dist/core/auth/session.d.mts +54 -0
  42. package/dist/core/auth/session.d.mts.map +1 -0
  43. package/dist/core/auth/session.mjs +150 -0
  44. package/dist/core/auth/session.mjs.map +1 -0
  45. package/dist/core/auth/types.d.cts +55 -0
  46. package/dist/core/auth/types.d.cts.map +1 -0
  47. package/dist/core/auth/types.d.mts +55 -0
  48. package/dist/core/auth/types.d.mts.map +1 -0
  49. package/dist/core/auth/utils/encode.cjs +27 -0
  50. package/dist/core/auth/utils/encode.d.cts +15 -0
  51. package/dist/core/auth/utils/encode.d.cts.map +1 -0
  52. package/dist/core/auth/utils/encode.d.mts +15 -0
  53. package/dist/core/auth/utils/encode.d.mts.map +1 -0
  54. package/dist/core/auth/utils/encode.mjs +26 -0
  55. package/dist/core/auth/utils/encode.mjs.map +1 -0
  56. package/dist/core/auth/utils/encryption.cjs +67 -0
  57. package/dist/core/auth/utils/encryption.d.cts +28 -0
  58. package/dist/core/auth/utils/encryption.d.cts.map +1 -0
  59. package/dist/core/auth/utils/encryption.d.mts +28 -0
  60. package/dist/core/auth/utils/encryption.d.mts.map +1 -0
  61. package/dist/core/auth/utils/encryption.mjs +64 -0
  62. package/dist/core/auth/utils/encryption.mjs.map +1 -0
  63. package/dist/core/auth/validation.cjs +39 -0
  64. package/dist/core/auth/validation.d.cts +48 -0
  65. package/dist/core/auth/validation.d.cts.map +1 -0
  66. package/dist/core/auth/validation.d.mts +48 -0
  67. package/dist/core/auth/validation.d.mts.map +1 -0
  68. package/dist/core/auth/validation.mjs +31 -0
  69. package/dist/core/auth/validation.mjs.map +1 -0
  70. package/dist/core/bootstrap.cjs +32 -0
  71. package/dist/core/bootstrap.d.cts +5 -0
  72. package/dist/core/bootstrap.d.cts.map +1 -0
  73. package/dist/core/bootstrap.d.mts +5 -0
  74. package/dist/core/bootstrap.d.mts.map +1 -0
  75. package/dist/core/bootstrap.mjs +33 -0
  76. package/dist/core/bootstrap.mjs.map +1 -0
  77. package/dist/core/config.cjs +6 -0
  78. package/dist/core/config.d.cts +11 -0
  79. package/dist/core/config.d.cts.map +1 -0
  80. package/dist/core/config.d.mts +11 -0
  81. package/dist/core/config.d.mts.map +1 -0
  82. package/dist/core/config.mjs +6 -0
  83. package/dist/core/config.mjs.map +1 -0
  84. package/dist/core/config.server.cjs +60 -0
  85. package/dist/core/config.server.d.cts +16 -0
  86. package/dist/core/config.server.d.cts.map +1 -0
  87. package/dist/core/config.server.d.mts +16 -0
  88. package/dist/core/config.server.d.mts.map +1 -0
  89. package/dist/core/config.server.mjs +57 -0
  90. package/dist/core/config.server.mjs.map +1 -0
  91. package/dist/core/event-bus.cjs +48 -0
  92. package/dist/core/event-bus.d.cts +17 -0
  93. package/dist/core/event-bus.d.cts.map +1 -0
  94. package/dist/core/event-bus.d.mts +17 -0
  95. package/dist/core/event-bus.d.mts.map +1 -0
  96. package/dist/core/event-bus.mjs +48 -0
  97. package/dist/core/event-bus.mjs.map +1 -0
  98. package/dist/core/filesystem/service.cjs +43 -0
  99. package/dist/core/filesystem/service.d.cts +19 -0
  100. package/dist/core/filesystem/service.d.cts.map +1 -0
  101. package/dist/core/filesystem/service.d.mts +19 -0
  102. package/dist/core/filesystem/service.d.mts.map +1 -0
  103. package/dist/core/filesystem/service.mjs +43 -0
  104. package/dist/core/filesystem/service.mjs.map +1 -0
  105. package/dist/core/filesystem/types.d.cts +22 -0
  106. package/dist/core/filesystem/types.d.cts.map +1 -0
  107. package/dist/core/filesystem/types.d.mts +22 -0
  108. package/dist/core/filesystem/types.d.mts.map +1 -0
  109. package/dist/core/notifications/actions.cjs +36 -0
  110. package/dist/core/notifications/actions.d.cts +58 -0
  111. package/dist/core/notifications/actions.d.cts.map +1 -0
  112. package/dist/core/notifications/actions.d.mts +58 -0
  113. package/dist/core/notifications/actions.d.mts.map +1 -0
  114. package/dist/core/notifications/actions.mjs +33 -0
  115. package/dist/core/notifications/actions.mjs.map +1 -0
  116. package/dist/core/notifications/index.cjs +2 -0
  117. package/dist/core/notifications/index.mjs +4 -0
  118. package/dist/core/notifications/service.cjs +30 -0
  119. package/dist/core/notifications/service.d.cts +9 -0
  120. package/dist/core/notifications/service.d.cts.map +1 -0
  121. package/dist/core/notifications/service.d.mts +9 -0
  122. package/dist/core/notifications/service.d.mts.map +1 -0
  123. package/dist/core/notifications/service.mjs +31 -0
  124. package/dist/core/notifications/service.mjs.map +1 -0
  125. package/dist/core/notifications/types.d.cts +21 -0
  126. package/dist/core/notifications/types.d.cts.map +1 -0
  127. package/dist/core/notifications/types.d.mts +21 -0
  128. package/dist/core/notifications/types.d.mts.map +1 -0
  129. package/dist/core/setup.cjs +25 -0
  130. package/dist/core/setup.d.cts +9 -0
  131. package/dist/core/setup.d.cts.map +1 -0
  132. package/dist/core/setup.d.mts +9 -0
  133. package/dist/core/setup.d.mts.map +1 -0
  134. package/dist/core/setup.mjs +25 -0
  135. package/dist/core/setup.mjs.map +1 -0
  136. package/dist/core/types.d.cts +13 -0
  137. package/dist/core/types.d.cts.map +1 -0
  138. package/dist/core/types.d.mts +13 -0
  139. package/dist/core/types.d.mts.map +1 -0
  140. package/dist/index.cjs +30 -0
  141. package/dist/index.d.cts +8 -0
  142. package/dist/index.d.mts +8 -0
  143. package/dist/index.mjs +6 -0
  144. package/dist/server/auth/email.cjs +24 -0
  145. package/dist/server/auth/email.d.cts +13 -0
  146. package/dist/server/auth/email.d.cts.map +1 -0
  147. package/dist/server/auth/email.d.mts +13 -0
  148. package/dist/server/auth/email.d.mts.map +1 -0
  149. package/dist/server/auth/email.mjs +23 -0
  150. package/dist/server/auth/email.mjs.map +1 -0
  151. package/dist/server/auth/password.cjs +37 -0
  152. package/dist/server/auth/password.d.cts +23 -0
  153. package/dist/server/auth/password.d.cts.map +1 -0
  154. package/dist/server/auth/password.d.mts +23 -0
  155. package/dist/server/auth/password.d.mts.map +1 -0
  156. package/dist/server/auth/password.mjs +34 -0
  157. package/dist/server/auth/password.mjs.map +1 -0
  158. package/dist/server/auth/user.cjs +165 -0
  159. package/dist/server/auth/user.d.cts +58 -0
  160. package/dist/server/auth/user.d.cts.map +1 -0
  161. package/dist/server/auth/user.d.mts +58 -0
  162. package/dist/server/auth/user.d.mts.map +1 -0
  163. package/dist/server/auth/user.mjs +153 -0
  164. package/dist/server/auth/user.mjs.map +1 -0
  165. package/dist/server/database/inject.cjs +24 -0
  166. package/dist/server/database/inject.d.cts +15 -0
  167. package/dist/server/database/inject.d.cts.map +1 -0
  168. package/dist/server/database/inject.d.mts +15 -0
  169. package/dist/server/database/inject.d.mts.map +1 -0
  170. package/dist/server/database/inject.mjs +23 -0
  171. package/dist/server/database/inject.mjs.map +1 -0
  172. package/dist/server/database/schema.cjs +163 -0
  173. package/dist/server/database/schema.d.cts +2962 -0
  174. package/dist/server/database/schema.d.cts.map +1 -0
  175. package/dist/server/database/schema.d.mts +2962 -0
  176. package/dist/server/database/schema.d.mts.map +1 -0
  177. package/dist/server/database/schema.mjs +151 -0
  178. package/dist/server/database/schema.mjs.map +1 -0
  179. package/dist/server/emails/index.cjs +32 -0
  180. package/dist/server/emails/index.d.cts +26 -0
  181. package/dist/server/emails/index.d.cts.map +1 -0
  182. package/dist/server/emails/index.d.mts +26 -0
  183. package/dist/server/emails/index.d.mts.map +1 -0
  184. package/dist/server/emails/index.mjs +29 -0
  185. package/dist/server/emails/index.mjs.map +1 -0
  186. package/dist/server.cjs +145 -0
  187. package/dist/server.d.cts +26 -0
  188. package/dist/server.d.mts +26 -0
  189. package/dist/server.mjs +23 -0
  190. package/package.json +60 -0
@@ -0,0 +1,104 @@
1
+ "use server";
2
+
3
+ import { db } from "../../server/database/inject.mjs";
4
+ import { permissionsTable, rolesTable, rolesToPermissionsTable, usersToPermissionsTable, usersToRolesTable } from "../../server/database/schema.mjs";
5
+ import { notificationService } from "../notifications/service.mjs";
6
+ import "../notifications/index.mjs";
7
+ import { and, eq, inArray } from "drizzle-orm";
8
+
9
+ //#region src/core/auth/rbac.ts
10
+ if (typeof window === "undefined") notificationService.init();
11
+ /**
12
+ * CORE RBAC LOGIC
13
+ * This file handles all database operations for Roles and Permissions.
14
+ */
15
+ async function getRoles() {
16
+ return await db.select().from(rolesTable).orderBy(rolesTable.name);
17
+ }
18
+ async function getRoleById(roleId) {
19
+ const [role] = await db.select().from(rolesTable).where(eq(rolesTable.id, roleId));
20
+ return role;
21
+ }
22
+ async function createRole(name, description) {
23
+ return await db.insert(rolesTable).values({
24
+ name,
25
+ description
26
+ }).returning();
27
+ }
28
+ async function deleteRole(roleId) {
29
+ return await db.delete(rolesTable).where(eq(rolesTable.id, roleId));
30
+ }
31
+ async function getPermissions() {
32
+ return await db.select().from(permissionsTable).orderBy(permissionsTable.name);
33
+ }
34
+ async function createPermission(name, description) {
35
+ return await db.insert(permissionsTable).values({
36
+ name,
37
+ description
38
+ }).returning();
39
+ }
40
+ async function deletePermission(permissionId) {
41
+ return await db.delete(permissionsTable).where(eq(permissionsTable.id, permissionId));
42
+ }
43
+ async function getRolePermissions(roleId) {
44
+ return await db.select({
45
+ id: permissionsTable.id,
46
+ name: permissionsTable.name
47
+ }).from(rolesToPermissionsTable).innerJoin(permissionsTable, eq(rolesToPermissionsTable.permissionId, permissionsTable.id)).where(eq(rolesToPermissionsTable.roleId, roleId));
48
+ }
49
+ async function assignPermissionToRole(roleId, permissionId) {
50
+ return await db.insert(rolesToPermissionsTable).values({
51
+ roleId,
52
+ permissionId
53
+ }).onConflictDoNothing();
54
+ }
55
+ async function revokePermissionFromRole(roleId, permissionId) {
56
+ return await db.delete(rolesToPermissionsTable).where(and(eq(rolesToPermissionsTable.roleId, roleId), eq(rolesToPermissionsTable.permissionId, permissionId)));
57
+ }
58
+ async function assignRoleToUser(userId, roleId) {
59
+ return await db.insert(usersToRolesTable).values({
60
+ userId,
61
+ roleId
62
+ }).onConflictDoNothing();
63
+ }
64
+ async function revokeRoleFromUser(userId, roleId) {
65
+ return await db.delete(usersToRolesTable).where(and(eq(usersToRolesTable.userId, userId), eq(usersToRolesTable.roleId, roleId)));
66
+ }
67
+ async function assignPermissionToUser(userId, permissionId) {
68
+ return await db.insert(usersToPermissionsTable).values({
69
+ userId,
70
+ permissionId
71
+ }).onConflictDoNothing();
72
+ }
73
+ async function revokePermissionFromUser(userId, permissionId) {
74
+ return await db.delete(usersToPermissionsTable).where(and(eq(usersToPermissionsTable.userId, userId), eq(usersToPermissionsTable.permissionId, permissionId)));
75
+ }
76
+ async function getUserRbacData(userId) {
77
+ const roles = await db.select({
78
+ id: rolesTable.id,
79
+ name: rolesTable.name
80
+ }).from(usersToRolesTable).innerJoin(rolesTable, eq(usersToRolesTable.roleId, rolesTable.id)).where(eq(usersToRolesTable.userId, userId));
81
+ const directPermissions = await db.select({
82
+ id: permissionsTable.id,
83
+ name: permissionsTable.name
84
+ }).from(usersToPermissionsTable).innerJoin(permissionsTable, eq(usersToPermissionsTable.permissionId, permissionsTable.id)).where(eq(usersToPermissionsTable.userId, userId));
85
+ let rolePermissions = [];
86
+ if (roles.length > 0) {
87
+ const roleIds = roles.map((r) => r.id);
88
+ rolePermissions = await db.select({
89
+ id: permissionsTable.id,
90
+ name: permissionsTable.name
91
+ }).from(rolesToPermissionsTable).innerJoin(permissionsTable, eq(rolesToPermissionsTable.permissionId, permissionsTable.id)).where(inArray(rolesToPermissionsTable.roleId, roleIds));
92
+ }
93
+ const effectiveMap = /* @__PURE__ */ new Map();
94
+ for (const p of [...directPermissions, ...rolePermissions]) effectiveMap.set(p.id, p);
95
+ return {
96
+ roles,
97
+ directPermissions,
98
+ effectivePermissions: Array.from(effectiveMap.values())
99
+ };
100
+ }
101
+
102
+ //#endregion
103
+ export { assignPermissionToRole, assignPermissionToUser, assignRoleToUser, createPermission, createRole, deletePermission, deleteRole, getPermissions, getRoleById, getRolePermissions, getRoles, getUserRbacData, revokePermissionFromRole, revokePermissionFromUser, revokeRoleFromUser };
104
+ //# sourceMappingURL=rbac.mjs.map
@@ -0,0 +1 @@
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\";\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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"}
@@ -0,0 +1,161 @@
1
+ "use server";
2
+
3
+ const require_runtime = require('../../_virtual/_rolldown/runtime.cjs');
4
+ const require_inject = require('../../server/database/inject.cjs');
5
+ const require_schema = require('../../server/database/schema.cjs');
6
+ const require_augment = require('./augment.cjs');
7
+ const require_logic = require('./logic.cjs');
8
+ const require_bootstrap = require('../bootstrap.cjs');
9
+ let drizzle_orm = require("drizzle-orm");
10
+ let _oslojs_crypto_sha2 = require("@oslojs/crypto/sha2");
11
+ let _oslojs_encoding = require("@oslojs/encoding");
12
+ let date_fns = require("date-fns");
13
+ let next_headers = require("next/headers");
14
+ let next_navigation = require("next/navigation");
15
+
16
+ //#region src/core/auth/session.ts
17
+ /**
18
+ * Returns the user's IP address.
19
+ */
20
+ async function getIPAddress() {
21
+ return (await (0, next_headers.headers)()).get("x-forwarded-for");
22
+ }
23
+ /**
24
+ * Validates the session token.
25
+ */
26
+ async function validateSessionToken(token) {
27
+ await require_bootstrap.ensureSystemInitialized();
28
+ const sessionId = (0, _oslojs_encoding.encodeHexLowerCase)((0, _oslojs_crypto_sha2.sha256)(new TextEncoder().encode(token)));
29
+ const [row] = await require_inject.db.select({
30
+ session: require_schema.sessionTable,
31
+ user: require_schema.userTable
32
+ }).from(require_schema.sessionTable).innerJoin(require_schema.userTable, (0, drizzle_orm.eq)(require_schema.sessionTable.userId, require_schema.userTable.id)).where((0, drizzle_orm.eq)(require_schema.sessionTable.id, sessionId));
33
+ if (!row || !row.user) return {
34
+ session: null,
35
+ user: null
36
+ };
37
+ const { session: baseSession, user: baseUser } = row;
38
+ const { password, recovery_code, ...safeUser } = baseUser;
39
+ if (/* @__PURE__ */ new Date() > baseSession.expiresAt) {
40
+ await require_inject.db.delete(require_schema.sessionTable).where((0, drizzle_orm.eq)(require_schema.sessionTable.id, baseSession.id));
41
+ return {
42
+ session: null,
43
+ user: null
44
+ };
45
+ }
46
+ const augmentedUser = await require_logic.performFullUserAugmentation(safeUser);
47
+ const augmentedSession = await require_augment.augmentSession(baseSession);
48
+ return {
49
+ session: augmentedSession ? { ...augmentedSession } : null,
50
+ user: augmentedUser ? { ...augmentedUser } : null
51
+ };
52
+ }
53
+ /**
54
+ * Returns the current user session from cookies.
55
+ */
56
+ const getCurrentSession = async () => {
57
+ const token = (await (0, next_headers.cookies)()).get("session")?.value ?? null;
58
+ if (token === null) return {
59
+ session: null,
60
+ user: null
61
+ };
62
+ return await validateSessionToken(token);
63
+ };
64
+ /**
65
+ * Invalidates a single session.
66
+ */
67
+ async function invalidateSession(sessionId) {
68
+ await require_bootstrap.ensureSystemInitialized();
69
+ await require_inject.db.delete(require_schema.sessionTable).where((0, drizzle_orm.eq)(require_schema.sessionTable.id, sessionId));
70
+ }
71
+ /**
72
+ * Invalidates all user sessions.
73
+ */
74
+ async function invalidateUserSessions(userId) {
75
+ await require_bootstrap.ensureSystemInitialized();
76
+ await require_inject.db.delete(require_schema.sessionTable).where((0, drizzle_orm.eq)(require_schema.sessionTable.userId, userId));
77
+ }
78
+ /**
79
+ * Sets the session token in a cookie.
80
+ */
81
+ async function setSessionTokenCookie(token, expiresAt) {
82
+ (await (0, next_headers.cookies)()).set("session", token, {
83
+ httpOnly: true,
84
+ path: "/",
85
+ secure: process.env.NODE_ENV === "production",
86
+ sameSite: "lax",
87
+ expires: expiresAt
88
+ });
89
+ }
90
+ /**
91
+ * Removes the session token cookie.
92
+ */
93
+ async function deleteSessionTokenCookie() {
94
+ (await (0, next_headers.cookies)()).delete("session");
95
+ }
96
+ /**
97
+ * Generates a new random session token.
98
+ */
99
+ async function generateSessionToken() {
100
+ const tokenBytes = new Uint8Array(20);
101
+ crypto.getRandomValues(tokenBytes);
102
+ return (0, _oslojs_encoding.encodeBase32LowerCaseNoPadding)(tokenBytes).toLowerCase();
103
+ }
104
+ /**
105
+ * Creates a new session in the database.
106
+ */
107
+ async function createSession(token, userId, flags) {
108
+ await require_bootstrap.ensureSystemInitialized();
109
+ const sessionId = (0, _oslojs_encoding.encodeHexLowerCase)((0, _oslojs_crypto_sha2.sha256)(new TextEncoder().encode(token)));
110
+ const [session] = await require_inject.db.insert(require_schema.sessionTable).values({
111
+ id: sessionId,
112
+ expiresAt: new Date((0, date_fns.addDays)(/* @__PURE__ */ new Date(), 7)),
113
+ active_organization_id: flags.activeOrganizationId,
114
+ userId
115
+ }).returning();
116
+ return session;
117
+ }
118
+ /**
119
+ * Signs the user out and redirects to the sign-in page.
120
+ */
121
+ async function sessionSignOut() {
122
+ const { session } = await getCurrentSession();
123
+ if (session) {
124
+ await invalidateSession(session.id);
125
+ await deleteSessionTokenCookie();
126
+ }
127
+ (0, next_navigation.redirect)("/signin");
128
+ }
129
+ /**
130
+ * Get all active sessions for a user.
131
+ */
132
+ async function getUserSessions(userId, currentSessionId) {
133
+ await require_bootstrap.ensureSystemInitialized();
134
+ return (await require_inject.db.select().from(require_schema.sessionTable).where((0, drizzle_orm.eq)(require_schema.sessionTable.userId, userId))).map((session) => ({
135
+ id: session.id,
136
+ createdAt: session.createdAt,
137
+ expiresAt: session.expiresAt,
138
+ isCurrent: session.id === currentSessionId
139
+ }));
140
+ }
141
+ /**
142
+ * Invalidate all sessions for a user except the specified current one.
143
+ */
144
+ async function invalidateOtherSessions(userId, currentSessionId) {
145
+ await require_bootstrap.ensureSystemInitialized();
146
+ await require_inject.db.delete(require_schema.sessionTable).where((0, drizzle_orm.and)((0, drizzle_orm.eq)(require_schema.sessionTable.userId, userId), (0, drizzle_orm.ne)(require_schema.sessionTable.id, currentSessionId)));
147
+ }
148
+
149
+ //#endregion
150
+ exports.createSession = createSession;
151
+ exports.deleteSessionTokenCookie = deleteSessionTokenCookie;
152
+ exports.generateSessionToken = generateSessionToken;
153
+ exports.getCurrentSession = getCurrentSession;
154
+ exports.getIPAddress = getIPAddress;
155
+ exports.getUserSessions = getUserSessions;
156
+ exports.invalidateOtherSessions = invalidateOtherSessions;
157
+ exports.invalidateSession = invalidateSession;
158
+ exports.invalidateUserSessions = invalidateUserSessions;
159
+ exports.sessionSignOut = sessionSignOut;
160
+ exports.setSessionTokenCookie = setSessionTokenCookie;
161
+ exports.validateSessionToken = validateSessionToken;
@@ -0,0 +1,54 @@
1
+ import { AuthSession, Session, SessionFlags, UserSession } from "./types.cjs";
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.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.cts","names":[],"sources":["../../../src/core/auth/session.ts"],"mappings":";;;;;AA4BA;iBAAsB,YAAA,CAAA,GAAgB,OAAA;;;;iBAOhB,oBAAA,CACpB,KAAA,WACC,OAAA,CAAQ,WAAA;;;;cA0CE,iBAAA,QAA8B,OAAA,CAAQ,WAAA;;;;iBAc7B,iBAAA,CAAkB,SAAA,WAAoB,OAAA;AAd5D;;;AAAA,iBAsBsB,sBAAA,CAAuB,MAAA,WAAiB,OAAA;;AAR9D;;iBAgBsB,qBAAA,CACpB,KAAA,UACA,SAAA,EAAW,IAAA,GACV,OAAA;;;AAXH;iBAyBsB,wBAAA,CAAA,GAA4B,OAAA;;;;iBAQ5B,oBAAA,CAAA,GAAwB,OAAA;;;;iBASxB,aAAA,CACpB,KAAA,UACA,MAAA,UACA,KAAA,EAAO,YAAA,GACN,OAAA,CAAQ,OAAA;;;;iBAoBW,cAAA,CAAA,GAAc,OAAA;;AAzCpC;;iBAuDsB,eAAA,CACpB,MAAA,UACA,gBAAA,WACC,OAAA,CAAQ,WAAA;;;AAlDX;iBAoEsB,uBAAA,CACpB,MAAA,UACA,gBAAA,WACC,OAAA"}
@@ -0,0 +1,54 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.mts","names":[],"sources":["../../../src/core/auth/session.ts"],"mappings":";;;;;AA4BA;iBAAsB,YAAA,CAAA,GAAgB,OAAA;;;;iBAOhB,oBAAA,CACpB,KAAA,WACC,OAAA,CAAQ,WAAA;;;;cA0CE,iBAAA,QAA8B,OAAA,CAAQ,WAAA;;;;iBAc7B,iBAAA,CAAkB,SAAA,WAAoB,OAAA;AAd5D;;;AAAA,iBAsBsB,sBAAA,CAAuB,MAAA,WAAiB,OAAA;;AAR9D;;iBAgBsB,qBAAA,CACpB,KAAA,UACA,SAAA,EAAW,IAAA,GACV,OAAA;;;AAXH;iBAyBsB,wBAAA,CAAA,GAA4B,OAAA;;;;iBAQ5B,oBAAA,CAAA,GAAwB,OAAA;;;;iBASxB,aAAA,CACpB,KAAA,UACA,MAAA,UACA,KAAA,EAAO,YAAA,GACN,OAAA,CAAQ,OAAA;;;;iBAoBW,cAAA,CAAA,GAAc,OAAA;;AAzCpC;;iBAuDsB,eAAA,CACpB,MAAA,UACA,gBAAA,WACC,OAAA,CAAQ,WAAA;;;AAlDX;iBAoEsB,uBAAA,CACpB,MAAA,UACA,gBAAA,WACC,OAAA"}
@@ -0,0 +1,150 @@
1
+ "use server";
2
+
3
+ import { db } from "../../server/database/inject.mjs";
4
+ import { sessionTable, userTable } from "../../server/database/schema.mjs";
5
+ import { augmentSession } from "./augment.mjs";
6
+ import { performFullUserAugmentation } from "./logic.mjs";
7
+ import { ensureSystemInitialized } from "../bootstrap.mjs";
8
+ import { and, eq, ne } from "drizzle-orm";
9
+ import { sha256 } from "@oslojs/crypto/sha2";
10
+ import { encodeBase32LowerCaseNoPadding, encodeHexLowerCase } from "@oslojs/encoding";
11
+ import { addDays } from "date-fns";
12
+ import { cookies, headers } from "next/headers";
13
+ import { redirect } from "next/navigation";
14
+
15
+ //#region src/core/auth/session.ts
16
+ /**
17
+ * Returns the user's IP address.
18
+ */
19
+ async function getIPAddress() {
20
+ return (await headers()).get("x-forwarded-for");
21
+ }
22
+ /**
23
+ * Validates the session token.
24
+ */
25
+ async function validateSessionToken(token) {
26
+ await ensureSystemInitialized();
27
+ const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
28
+ const [row] = await db.select({
29
+ session: sessionTable,
30
+ user: userTable
31
+ }).from(sessionTable).innerJoin(userTable, eq(sessionTable.userId, userTable.id)).where(eq(sessionTable.id, sessionId));
32
+ if (!row || !row.user) return {
33
+ session: null,
34
+ user: null
35
+ };
36
+ const { session: baseSession, user: baseUser } = row;
37
+ const { password, recovery_code, ...safeUser } = baseUser;
38
+ if (/* @__PURE__ */ new Date() > baseSession.expiresAt) {
39
+ await db.delete(sessionTable).where(eq(sessionTable.id, baseSession.id));
40
+ return {
41
+ session: null,
42
+ user: null
43
+ };
44
+ }
45
+ const augmentedUser = await performFullUserAugmentation(safeUser);
46
+ const augmentedSession = await augmentSession(baseSession);
47
+ return {
48
+ session: augmentedSession ? { ...augmentedSession } : null,
49
+ user: augmentedUser ? { ...augmentedUser } : null
50
+ };
51
+ }
52
+ /**
53
+ * Returns the current user session from cookies.
54
+ */
55
+ const getCurrentSession = async () => {
56
+ const token = (await cookies()).get("session")?.value ?? null;
57
+ if (token === null) return {
58
+ session: null,
59
+ user: null
60
+ };
61
+ return await validateSessionToken(token);
62
+ };
63
+ /**
64
+ * Invalidates a single session.
65
+ */
66
+ async function invalidateSession(sessionId) {
67
+ await ensureSystemInitialized();
68
+ await db.delete(sessionTable).where(eq(sessionTable.id, sessionId));
69
+ }
70
+ /**
71
+ * Invalidates all user sessions.
72
+ */
73
+ async function invalidateUserSessions(userId) {
74
+ await ensureSystemInitialized();
75
+ await db.delete(sessionTable).where(eq(sessionTable.userId, userId));
76
+ }
77
+ /**
78
+ * Sets the session token in a cookie.
79
+ */
80
+ async function setSessionTokenCookie(token, expiresAt) {
81
+ (await cookies()).set("session", token, {
82
+ httpOnly: true,
83
+ path: "/",
84
+ secure: process.env.NODE_ENV === "production",
85
+ sameSite: "lax",
86
+ expires: expiresAt
87
+ });
88
+ }
89
+ /**
90
+ * Removes the session token cookie.
91
+ */
92
+ async function deleteSessionTokenCookie() {
93
+ (await cookies()).delete("session");
94
+ }
95
+ /**
96
+ * Generates a new random session token.
97
+ */
98
+ async function generateSessionToken() {
99
+ const tokenBytes = new Uint8Array(20);
100
+ crypto.getRandomValues(tokenBytes);
101
+ return encodeBase32LowerCaseNoPadding(tokenBytes).toLowerCase();
102
+ }
103
+ /**
104
+ * Creates a new session in the database.
105
+ */
106
+ async function createSession(token, userId, flags) {
107
+ await ensureSystemInitialized();
108
+ const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
109
+ const [session] = await db.insert(sessionTable).values({
110
+ id: sessionId,
111
+ expiresAt: new Date(addDays(/* @__PURE__ */ new Date(), 7)),
112
+ active_organization_id: flags.activeOrganizationId,
113
+ userId
114
+ }).returning();
115
+ return session;
116
+ }
117
+ /**
118
+ * Signs the user out and redirects to the sign-in page.
119
+ */
120
+ async function sessionSignOut() {
121
+ const { session } = await getCurrentSession();
122
+ if (session) {
123
+ await invalidateSession(session.id);
124
+ await deleteSessionTokenCookie();
125
+ }
126
+ redirect("/signin");
127
+ }
128
+ /**
129
+ * Get all active sessions for a user.
130
+ */
131
+ async function getUserSessions(userId, currentSessionId) {
132
+ await ensureSystemInitialized();
133
+ return (await db.select().from(sessionTable).where(eq(sessionTable.userId, userId))).map((session) => ({
134
+ id: session.id,
135
+ createdAt: session.createdAt,
136
+ expiresAt: session.expiresAt,
137
+ isCurrent: session.id === currentSessionId
138
+ }));
139
+ }
140
+ /**
141
+ * Invalidate all sessions for a user except the specified current one.
142
+ */
143
+ async function invalidateOtherSessions(userId, currentSessionId) {
144
+ await ensureSystemInitialized();
145
+ await db.delete(sessionTable).where(and(eq(sessionTable.userId, userId), ne(sessionTable.id, currentSessionId)));
146
+ }
147
+
148
+ //#endregion
149
+ export { createSession, deleteSessionTokenCookie, generateSessionToken, getCurrentSession, getIPAddress, getUserSessions, invalidateOtherSessions, invalidateSession, invalidateUserSessions, sessionSignOut, setSessionTokenCookie, validateSessionToken };
150
+ //# sourceMappingURL=session.mjs.map
@@ -0,0 +1 @@
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 { ensureSystemInitialized } from \"../bootstrap\";\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 await ensureSystemInitialized();\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 ensureSystemInitialized();\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 ensureSystemInitialized();\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 await ensureSystemInitialized();\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 await ensureSystemInitialized();\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 ensureSystemInitialized();\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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"}
@@ -0,0 +1,55 @@
1
+ import { passwordResetSessionTable, sessionTable, userTable } from "../../server/database/schema.cjs";
2
+ import { UserPermission, UserRole } from "../types.cjs";
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.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.cts","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;EAErD,MAAA;EACA,IAAA;EACA,MAAA;EACA,SAAA;EACA,QAAA;AAAA;EAEA,MAAA;EAAiB,OAAA;EAAiB,QAAA;AAAA;AAAA,UAEvB,wBAAA;EACf,OAAA,EAAS,oBAAA;EACT,IAAA,EAAM,QAAA;AAAA"}