@arch-cadre/core 0.0.23 → 0.0.24

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 (90) hide show
  1. package/dist/_virtual/_rolldown/runtime.cjs +1 -29
  2. package/dist/_virtual/_rolldown/runtime.mjs +1 -18
  3. package/dist/core/auth/augment.cjs +1 -71
  4. package/dist/core/auth/augment.d.cts.map +1 -1
  5. package/dist/core/auth/augment.d.mts.map +1 -1
  6. package/dist/core/auth/augment.mjs +1 -65
  7. package/dist/core/auth/augment.mjs.map +1 -1
  8. package/dist/core/auth/email-verification.cjs +1 -99
  9. package/dist/core/auth/email-verification.mjs +1 -91
  10. package/dist/core/auth/email-verification.mjs.map +1 -1
  11. package/dist/core/auth/logic.cjs +1 -224
  12. package/dist/core/auth/logic.mjs +1 -212
  13. package/dist/core/auth/logic.mjs.map +1 -1
  14. package/dist/core/auth/password-reset.cjs +1 -118
  15. package/dist/core/auth/password-reset.mjs +1 -110
  16. package/dist/core/auth/password-reset.mjs.map +1 -1
  17. package/dist/core/auth/rbac.cjs +1 -118
  18. package/dist/core/auth/rbac.mjs +1 -103
  19. package/dist/core/auth/rbac.mjs.map +1 -1
  20. package/dist/core/auth/session.cjs +1 -154
  21. package/dist/core/auth/session.mjs +1 -142
  22. package/dist/core/auth/session.mjs.map +1 -1
  23. package/dist/core/auth/types.d.cts.map +1 -1
  24. package/dist/core/auth/types.d.mts.map +1 -1
  25. package/dist/core/auth/utils/encode.cjs +1 -27
  26. package/dist/core/auth/utils/encode.mjs +1 -25
  27. package/dist/core/auth/utils/encode.mjs.map +1 -1
  28. package/dist/core/auth/utils/encryption.cjs +1 -67
  29. package/dist/core/auth/utils/encryption.mjs +1 -63
  30. package/dist/core/auth/utils/encryption.mjs.map +1 -1
  31. package/dist/core/auth/validation.cjs +1 -39
  32. package/dist/core/auth/validation.mjs +1 -30
  33. package/dist/core/auth/validation.mjs.map +1 -1
  34. package/dist/core/bootstrap.cjs +1 -39
  35. package/dist/core/bootstrap.mjs +1 -39
  36. package/dist/core/bootstrap.mjs.map +1 -1
  37. package/dist/core/config.cjs +1 -6
  38. package/dist/core/config.mjs +1 -5
  39. package/dist/core/config.mjs.map +1 -1
  40. package/dist/core/config.server.cjs +1 -60
  41. package/dist/core/config.server.mjs +1 -56
  42. package/dist/core/config.server.mjs.map +1 -1
  43. package/dist/core/event-bus.cjs +1 -48
  44. package/dist/core/event-bus.d.cts.map +1 -1
  45. package/dist/core/event-bus.d.mts.map +1 -1
  46. package/dist/core/event-bus.mjs +1 -47
  47. package/dist/core/event-bus.mjs.map +1 -1
  48. package/dist/core/filesystem/index.cjs +1 -11
  49. package/dist/core/filesystem/index.mjs +1 -12
  50. package/dist/core/filesystem/index.mjs.map +1 -1
  51. package/dist/core/filesystem/providers/local.cjs +1 -43
  52. package/dist/core/filesystem/providers/local.mjs +1 -40
  53. package/dist/core/filesystem/providers/local.mjs.map +1 -1
  54. package/dist/core/filesystem/service.cjs +1 -43
  55. package/dist/core/filesystem/service.mjs +1 -42
  56. package/dist/core/filesystem/service.mjs.map +1 -1
  57. package/dist/core/notifications/actions.cjs +1 -36
  58. package/dist/core/notifications/actions.mjs +1 -32
  59. package/dist/core/notifications/actions.mjs.map +1 -1
  60. package/dist/core/notifications/index.cjs +1 -2
  61. package/dist/core/notifications/index.mjs +1 -4
  62. package/dist/core/notifications/service.cjs +1 -30
  63. package/dist/core/notifications/service.mjs +1 -30
  64. package/dist/core/notifications/service.mjs.map +1 -1
  65. package/dist/core/setup.cjs +1 -25
  66. package/dist/core/setup.mjs +1 -24
  67. package/dist/core/setup.mjs.map +1 -1
  68. package/dist/index.cjs +1 -30
  69. package/dist/index.mjs +1 -6
  70. package/dist/server/auth/email.cjs +1 -24
  71. package/dist/server/auth/email.mjs +1 -22
  72. package/dist/server/auth/email.mjs.map +1 -1
  73. package/dist/server/auth/password.cjs +1 -37
  74. package/dist/server/auth/password.mjs +1 -33
  75. package/dist/server/auth/password.mjs.map +1 -1
  76. package/dist/server/auth/user.cjs +1 -165
  77. package/dist/server/auth/user.mjs +1 -152
  78. package/dist/server/auth/user.mjs.map +1 -1
  79. package/dist/server/database/inject.cjs +1 -24
  80. package/dist/server/database/inject.mjs +1 -22
  81. package/dist/server/database/inject.mjs.map +1 -1
  82. package/dist/server/database/schema.cjs +1 -163
  83. package/dist/server/database/schema.mjs +1 -150
  84. package/dist/server/database/schema.mjs.map +1 -1
  85. package/dist/server/emails/index.cjs +1 -32
  86. package/dist/server/emails/index.mjs +1 -28
  87. package/dist/server/emails/index.mjs.map +1 -1
  88. package/dist/server.cjs +1 -145
  89. package/dist/server.mjs +1 -23
  90. package/package.json +1 -1
@@ -1,224 +1 @@
1
- "use server";
2
-
3
- const require_runtime = require('../../_virtual/_rolldown/runtime.cjs');
4
- const require_validation = require('./validation.cjs');
5
- const require_event_bus = require('../event-bus.cjs');
6
- const require_inject = require('../../server/database/inject.cjs');
7
- const require_schema = require('../../server/database/schema.cjs');
8
- const require_augment = require('./augment.cjs');
9
- const require_password = require('../../server/auth/password.cjs');
10
- const require_user = require('../../server/auth/user.cjs');
11
- const require_email_verification = require('./email-verification.cjs');
12
- const require_session = require('./session.cjs');
13
- let drizzle_orm = require("drizzle-orm");
14
-
15
- //#region src/core/auth/logic.ts
16
- /**
17
- * Podstawowy moduł rozszerzający tożsamość dla ról i uprawnień
18
- */
19
- async function coreRbacAugmenter(user) {
20
- try {
21
- const roles = (await require_inject.db.select({ name: require_schema.rolesTable.name }).from(require_schema.usersToRolesTable).innerJoin(require_schema.rolesTable, (0, drizzle_orm.eq)(require_schema.usersToRolesTable.roleId, require_schema.rolesTable.id)).where((0, drizzle_orm.eq)(require_schema.usersToRolesTable.userId, user.id))).map((r) => r.name);
22
- const directPerms = (await require_inject.db.select({ name: require_schema.permissionsTable.name }).from(require_schema.usersToPermissionsTable).innerJoin(require_schema.permissionsTable, (0, drizzle_orm.eq)(require_schema.usersToPermissionsTable.permissionId, require_schema.permissionsTable.id)).where((0, drizzle_orm.eq)(require_schema.usersToPermissionsTable.userId, user.id))).map((p) => p.name);
23
- let rolePerms = [];
24
- if (roles.length > 0) {
25
- const roleIds = (await require_inject.db.select({ id: require_schema.rolesTable.id }).from(require_schema.rolesTable).where((0, drizzle_orm.inArray)(require_schema.rolesTable.name, roles))).map((r) => r.id);
26
- if (roleIds.length > 0) rolePerms = (await require_inject.db.select({ name: require_schema.permissionsTable.name }).from(require_schema.rolesToPermissionsTable).innerJoin(require_schema.permissionsTable, (0, drizzle_orm.eq)(require_schema.rolesToPermissionsTable.permissionId, require_schema.permissionsTable.id)).where((0, drizzle_orm.inArray)(require_schema.rolesToPermissionsTable.roleId, roleIds))).map((p) => p.name);
27
- }
28
- return {
29
- roles,
30
- permissions: Array.from(new Set([...directPerms, ...rolePerms]))
31
- };
32
- } catch (error) {
33
- console.error("[Auth:RBAC] Failed to augment user:", error);
34
- return {
35
- roles: [],
36
- permissions: []
37
- };
38
- }
39
- }
40
- const globalForAuth = globalThis;
41
- const authValidators = globalForAuth.__KRYO_AUTH_VALIDATORS__ ?? /* @__PURE__ */ new Set();
42
- const securityRequirements = globalForAuth.__KRYO_SECURITY_REQUIREMENTS__ ?? /* @__PURE__ */ new Set();
43
- const passwordResetValidators = globalForAuth.__KRYO_PASSWORD_RESET_VALIDATORS__ ?? /* @__PURE__ */ new Set();
44
- const emailVerificationValidators = globalForAuth.__KRYO_EMAIL_VERIFICATION_VALIDATORS__ ?? /* @__PURE__ */ new Set();
45
- globalForAuth.__KRYO_AUTH_VALIDATORS__ = authValidators;
46
- globalForAuth.__KRYO_SECURITY_REQUIREMENTS__ = securityRequirements;
47
- globalForAuth.__KRYO_PASSWORD_RESET_VALIDATORS__ = passwordResetValidators;
48
- globalForAuth.__KRYO_EMAIL_VERIFICATION_VALIDATORS__ = emailVerificationValidators;
49
- async function registerAuthValidator(validator) {
50
- authValidators.add(validator);
51
- }
52
- async function registerPasswordResetValidator(validator) {
53
- passwordResetValidators.add(validator);
54
- }
55
- async function registerEmailVerificationValidator(validator) {
56
- emailVerificationValidators.add(validator);
57
- }
58
- async function registerSecurityRequirement(requirement) {
59
- securityRequirements.add(requirement);
60
- }
61
- async function runPasswordResetValidators(userId) {
62
- for (const validator of passwordResetValidators) {
63
- const interception = await validator(userId);
64
- if (interception) return interception;
65
- }
66
- return null;
67
- }
68
- async function runEmailVerificationValidators(userId) {
69
- for (const validator of emailVerificationValidators) {
70
- const interception = await validator(userId);
71
- if (interception) return interception;
72
- }
73
- return null;
74
- }
75
- /**
76
- * Augments a base user with data from all registered modules.
77
- * This is now just a wrapper that includes core RBAC data.
78
- */
79
- async function performFullUserAugmentation(user) {
80
- return await require_augment.augmentUser(user, await coreRbacAugmenter(user));
81
- }
82
- /**
83
- * Checks if the current session satisfies all registered security requirements.
84
- */
85
- async function checkSecurity(session, user, requiredRoles, requiredPermissions, fallbackRedirect) {
86
- if (!user) {
87
- console.warn("User is required for security check");
88
- return {
89
- satisfied: false,
90
- redirect: fallbackRedirect ?? "/signin"
91
- };
92
- }
93
- const userRoles = Array.isArray(user.roles) ? user.roles : [];
94
- const userPermissions = Array.isArray(user.permissions) ? user.permissions : [];
95
- if (requiredRoles && requiredRoles.length > 0) {
96
- if (!requiredRoles.some((role) => userRoles.includes(role))) {
97
- console.warn(`User lacks required roles: ${requiredRoles.join(", ")}`);
98
- return {
99
- satisfied: false,
100
- redirect: fallbackRedirect
101
- };
102
- }
103
- }
104
- if (requiredPermissions && requiredPermissions.length > 0) {
105
- if (!requiredPermissions.every((perm) => userPermissions.includes(perm))) {
106
- console.warn(`User lacks required permissions: ${requiredPermissions.join(", ")}`);
107
- return {
108
- satisfied: false,
109
- redirect: fallbackRedirect
110
- };
111
- }
112
- }
113
- if (securityRequirements) for (const requirement of securityRequirements) try {
114
- const result = await requirement(session, user);
115
- if (result && !result.satisfied) return {
116
- ...result,
117
- redirect: result.redirect ?? fallbackRedirect
118
- };
119
- } catch (error) {
120
- console.error("[Auth:Security] Requirement failed:", error);
121
- }
122
- return { satisfied: true };
123
- }
124
- /**
125
- * Sign In Logic
126
- */
127
- async function signIn(data) {
128
- const { email, password } = await require_validation.loginSchema.parseAsync(data);
129
- const user = await require_user.getUserFromEmail(email);
130
- if (!user) return {
131
- status: "ERROR",
132
- message: "Invalid email or password"
133
- };
134
- const passwordHash = await require_user.getUserPasswordHash(user.id);
135
- if (!passwordHash || !await require_password.verifyPasswordHash(passwordHash, password)) return {
136
- status: "ERROR",
137
- message: "Invalid email or password"
138
- };
139
- for (const validator of authValidators) {
140
- const interception = await validator(user.id);
141
- if (interception) return interception;
142
- }
143
- const sessionFlags = {};
144
- const sessionToken = await require_session.generateSessionToken();
145
- const session = await require_session.createSession(sessionToken, user.id, sessionFlags);
146
- await require_session.setSessionTokenCookie(sessionToken, session.expiresAt);
147
- const fullUser = await performFullUserAugmentation(user);
148
- await require_event_bus.eventBus.publish("auth:session-created", {
149
- session,
150
- user: fullUser
151
- });
152
- return {
153
- status: "SUCCESS",
154
- session: { ...session },
155
- user: { ...fullUser }
156
- };
157
- }
158
- /**
159
- * Sign Up Logic
160
- */
161
- async function signUp(data) {
162
- const { email, username, password } = require_validation.registerSchema.parse(data);
163
- if (!await require_user.verifyUsernameInput(username)) throw new Error("Invalid username");
164
- if (!await require_password.verifyPasswordStrength(password)) throw new Error("Weak password");
165
- const user = await require_user.createUser(email, username, password);
166
- const verificationRequest = await require_email_verification.createEmailVerificationRequest(user.id, user.email);
167
- await require_email_verification.sendVerificationEmail(verificationRequest.email, verificationRequest.code);
168
- await require_email_verification.setEmailVerificationRequestCookie(verificationRequest);
169
- const sessionFlags = {};
170
- const sessionToken = await require_session.generateSessionToken();
171
- const session = await require_session.createSession(sessionToken, user.id, sessionFlags);
172
- await require_session.setSessionTokenCookie(sessionToken, session.expiresAt);
173
- const fullUser = await performFullUserAugmentation(user);
174
- await require_event_bus.eventBus.publish("auth:session-created", {
175
- session,
176
- user: fullUser
177
- });
178
- return {
179
- session: { ...session },
180
- user: { ...fullUser }
181
- };
182
- }
183
- /**
184
- * Finalizes login after a challenge
185
- */
186
- async function finalizeLogin(userId, flags) {
187
- const sessionToken = await require_session.generateSessionToken();
188
- const session = await require_session.createSession(sessionToken, userId, flags);
189
- await require_session.setSessionTokenCookie(sessionToken, session.expiresAt);
190
- const user = await require_user.getUserById(userId);
191
- if (user) await require_event_bus.eventBus.publish("auth:session-created", {
192
- session,
193
- user
194
- });
195
- return {
196
- session: session ? { ...session } : null,
197
- user: user ? { ...user } : null
198
- };
199
- }
200
- /**
201
- * Sign Out
202
- */
203
- async function signOut() {
204
- const { session, user } = await require_session.getCurrentSession();
205
- if (session) {
206
- if (user) await require_event_bus.eventBus.publish("auth:signed-out", { userId: user.id });
207
- await require_session.invalidateSession(session.id);
208
- await require_session.deleteSessionTokenCookie();
209
- }
210
- }
211
-
212
- //#endregion
213
- exports.checkSecurity = checkSecurity;
214
- exports.finalizeLogin = finalizeLogin;
215
- exports.performFullUserAugmentation = performFullUserAugmentation;
216
- exports.registerAuthValidator = registerAuthValidator;
217
- exports.registerEmailVerificationValidator = registerEmailVerificationValidator;
218
- exports.registerPasswordResetValidator = registerPasswordResetValidator;
219
- exports.registerSecurityRequirement = registerSecurityRequirement;
220
- exports.runEmailVerificationValidators = runEmailVerificationValidators;
221
- exports.runPasswordResetValidators = runPasswordResetValidators;
222
- exports.signIn = signIn;
223
- exports.signOut = signOut;
224
- exports.signUp = signUp;
1
+ "use server";require(`../../_virtual/_rolldown/runtime.cjs`);const e=require(`./validation.cjs`),t=require(`../event-bus.cjs`),n=require(`../../server/database/inject.cjs`),r=require(`../../server/database/schema.cjs`),i=require(`./augment.cjs`),a=require(`../../server/auth/password.cjs`),o=require(`../../server/auth/user.cjs`),s=require(`./email-verification.cjs`),c=require(`./session.cjs`);let l=require(`drizzle-orm`);async function u(e){try{let t=(await n.db.select({name:r.rolesTable.name}).from(r.usersToRolesTable).innerJoin(r.rolesTable,(0,l.eq)(r.usersToRolesTable.roleId,r.rolesTable.id)).where((0,l.eq)(r.usersToRolesTable.userId,e.id))).map(e=>e.name),i=(await n.db.select({name:r.permissionsTable.name}).from(r.usersToPermissionsTable).innerJoin(r.permissionsTable,(0,l.eq)(r.usersToPermissionsTable.permissionId,r.permissionsTable.id)).where((0,l.eq)(r.usersToPermissionsTable.userId,e.id))).map(e=>e.name),a=[];if(t.length>0){let e=(await n.db.select({id:r.rolesTable.id}).from(r.rolesTable).where((0,l.inArray)(r.rolesTable.name,t))).map(e=>e.id);e.length>0&&(a=(await n.db.select({name:r.permissionsTable.name}).from(r.rolesToPermissionsTable).innerJoin(r.permissionsTable,(0,l.eq)(r.rolesToPermissionsTable.permissionId,r.permissionsTable.id)).where((0,l.inArray)(r.rolesToPermissionsTable.roleId,e))).map(e=>e.name))}return{roles:t,permissions:Array.from(new Set([...i,...a]))}}catch(e){return console.error(`[Auth:RBAC] Failed to augment user:`,e),{roles:[],permissions:[]}}}const d=globalThis,f=d.__KRYO_AUTH_VALIDATORS__??new Set,p=d.__KRYO_SECURITY_REQUIREMENTS__??new Set,m=d.__KRYO_PASSWORD_RESET_VALIDATORS__??new Set,h=d.__KRYO_EMAIL_VERIFICATION_VALIDATORS__??new Set;d.__KRYO_AUTH_VALIDATORS__=f,d.__KRYO_SECURITY_REQUIREMENTS__=p,d.__KRYO_PASSWORD_RESET_VALIDATORS__=m,d.__KRYO_EMAIL_VERIFICATION_VALIDATORS__=h;async function g(e){f.add(e)}async function _(e){m.add(e)}async function v(e){h.add(e)}async function y(e){p.add(e)}async function b(e){for(let t of m){let n=await t(e);if(n)return n}return null}async function x(e){for(let t of h){let n=await t(e);if(n)return n}return null}async function S(e){return await i.augmentUser(e,await u(e))}async function C(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(p)for(let n of p)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 w(n){let{email:r,password:i}=await e.loginSchema.parseAsync(n),s=await o.getUserFromEmail(r);if(!s)return{status:`ERROR`,message:`Invalid email or password`};let l=await o.getUserPasswordHash(s.id);if(!l||!await a.verifyPasswordHash(l,i))return{status:`ERROR`,message:`Invalid email or password`};for(let e of f){let t=await e(s.id);if(t)return t}let u={},d=await c.generateSessionToken(),p=await c.createSession(d,s.id,u);await c.setSessionTokenCookie(d,p.expiresAt);let m=await S(s);return await t.eventBus.publish(`auth:session-created`,{session:p,user:m}),{status:`SUCCESS`,session:{...p},user:{...m}}}async function T(n){let{email:r,username:i,password:l}=e.registerSchema.parse(n);if(!await o.verifyUsernameInput(i))throw Error(`Invalid username`);if(!await a.verifyPasswordStrength(l))throw Error(`Weak password`);let u=await o.createUser(r,i,l),d=await s.createEmailVerificationRequest(u.id,u.email);await s.sendVerificationEmail(d.email,d.code),await s.setEmailVerificationRequestCookie(d);let f={},p=await c.generateSessionToken(),m=await c.createSession(p,u.id,f);await c.setSessionTokenCookie(p,m.expiresAt);let h=await S(u);return await t.eventBus.publish(`auth:session-created`,{session:m,user:h}),{session:{...m},user:{...h}}}async function E(e,n){let r=await c.generateSessionToken(),i=await c.createSession(r,e,n);await c.setSessionTokenCookie(r,i.expiresAt);let a=await o.getUserById(e);return a&&await t.eventBus.publish(`auth:session-created`,{session:i,user:a}),{session:i?{...i}:null,user:a?{...a}:null}}async function D(){let{session:e,user:n}=await c.getCurrentSession();e&&(n&&await t.eventBus.publish(`auth:signed-out`,{userId:n.id}),await c.invalidateSession(e.id),await c.deleteSessionTokenCookie())}exports.checkSecurity=C,exports.finalizeLogin=E,exports.performFullUserAugmentation=S,exports.registerAuthValidator=g,exports.registerEmailVerificationValidator=v,exports.registerPasswordResetValidator=_,exports.registerSecurityRequirement=y,exports.runEmailVerificationValidators=x,exports.runPasswordResetValidators=b,exports.signIn=w,exports.signOut=D,exports.signUp=T;
@@ -1,213 +1,2 @@
1
- "use server";
2
-
3
- import { loginSchema, registerSchema } from "./validation.mjs";
4
- import { eventBus } from "../event-bus.mjs";
5
- import { db } from "../../server/database/inject.mjs";
6
- import { permissionsTable, rolesTable, rolesToPermissionsTable, usersToPermissionsTable, usersToRolesTable } from "../../server/database/schema.mjs";
7
- import { augmentSession, augmentUser, registerIdentityAugmenter, registerPasswordResetSessionAugmenter, registerSessionAugmenter } from "./augment.mjs";
8
- import { verifyPasswordHash, verifyPasswordStrength } from "../../server/auth/password.mjs";
9
- import { createUser, getUserById, getUserFromEmail, getUserPasswordHash, verifyUsernameInput } from "../../server/auth/user.mjs";
10
- import { createEmailVerificationRequest, sendVerificationEmail, setEmailVerificationRequestCookie } from "./email-verification.mjs";
11
- import { createSession, deleteSessionTokenCookie, generateSessionToken, getCurrentSession, invalidateSession, setSessionTokenCookie } from "./session.mjs";
12
- import { eq, inArray } from "drizzle-orm";
13
-
14
- //#region src/core/auth/logic.ts
15
- /**
16
- * Podstawowy moduł rozszerzający tożsamość dla ról i uprawnień
17
- */
18
- async function coreRbacAugmenter(user) {
19
- try {
20
- const roles = (await db.select({ name: rolesTable.name }).from(usersToRolesTable).innerJoin(rolesTable, eq(usersToRolesTable.roleId, rolesTable.id)).where(eq(usersToRolesTable.userId, user.id))).map((r) => r.name);
21
- const directPerms = (await db.select({ name: permissionsTable.name }).from(usersToPermissionsTable).innerJoin(permissionsTable, eq(usersToPermissionsTable.permissionId, permissionsTable.id)).where(eq(usersToPermissionsTable.userId, user.id))).map((p) => p.name);
22
- let rolePerms = [];
23
- if (roles.length > 0) {
24
- const roleIds = (await db.select({ id: rolesTable.id }).from(rolesTable).where(inArray(rolesTable.name, roles))).map((r) => r.id);
25
- if (roleIds.length > 0) rolePerms = (await db.select({ name: permissionsTable.name }).from(rolesToPermissionsTable).innerJoin(permissionsTable, eq(rolesToPermissionsTable.permissionId, permissionsTable.id)).where(inArray(rolesToPermissionsTable.roleId, roleIds))).map((p) => p.name);
26
- }
27
- return {
28
- roles,
29
- permissions: Array.from(new Set([...directPerms, ...rolePerms]))
30
- };
31
- } catch (error) {
32
- console.error("[Auth:RBAC] Failed to augment user:", error);
33
- return {
34
- roles: [],
35
- permissions: []
36
- };
37
- }
38
- }
39
- const globalForAuth = globalThis;
40
- const authValidators = globalForAuth.__KRYO_AUTH_VALIDATORS__ ?? /* @__PURE__ */ new Set();
41
- const securityRequirements = globalForAuth.__KRYO_SECURITY_REQUIREMENTS__ ?? /* @__PURE__ */ new Set();
42
- const passwordResetValidators = globalForAuth.__KRYO_PASSWORD_RESET_VALIDATORS__ ?? /* @__PURE__ */ new Set();
43
- const emailVerificationValidators = globalForAuth.__KRYO_EMAIL_VERIFICATION_VALIDATORS__ ?? /* @__PURE__ */ new Set();
44
- globalForAuth.__KRYO_AUTH_VALIDATORS__ = authValidators;
45
- globalForAuth.__KRYO_SECURITY_REQUIREMENTS__ = securityRequirements;
46
- globalForAuth.__KRYO_PASSWORD_RESET_VALIDATORS__ = passwordResetValidators;
47
- globalForAuth.__KRYO_EMAIL_VERIFICATION_VALIDATORS__ = emailVerificationValidators;
48
- async function registerAuthValidator(validator) {
49
- authValidators.add(validator);
50
- }
51
- async function registerPasswordResetValidator(validator) {
52
- passwordResetValidators.add(validator);
53
- }
54
- async function registerEmailVerificationValidator(validator) {
55
- emailVerificationValidators.add(validator);
56
- }
57
- async function registerSecurityRequirement(requirement) {
58
- securityRequirements.add(requirement);
59
- }
60
- async function runPasswordResetValidators(userId) {
61
- for (const validator of passwordResetValidators) {
62
- const interception = await validator(userId);
63
- if (interception) return interception;
64
- }
65
- return null;
66
- }
67
- async function runEmailVerificationValidators(userId) {
68
- for (const validator of emailVerificationValidators) {
69
- const interception = await validator(userId);
70
- if (interception) return interception;
71
- }
72
- return null;
73
- }
74
- /**
75
- * Augments a base user with data from all registered modules.
76
- * This is now just a wrapper that includes core RBAC data.
77
- */
78
- async function performFullUserAugmentation(user) {
79
- return await augmentUser(user, await coreRbacAugmenter(user));
80
- }
81
- /**
82
- * Checks if the current session satisfies all registered security requirements.
83
- */
84
- async function checkSecurity(session, user, requiredRoles, requiredPermissions, fallbackRedirect) {
85
- if (!user) {
86
- console.warn("User is required for security check");
87
- return {
88
- satisfied: false,
89
- redirect: fallbackRedirect ?? "/signin"
90
- };
91
- }
92
- const userRoles = Array.isArray(user.roles) ? user.roles : [];
93
- const userPermissions = Array.isArray(user.permissions) ? user.permissions : [];
94
- if (requiredRoles && requiredRoles.length > 0) {
95
- if (!requiredRoles.some((role) => userRoles.includes(role))) {
96
- console.warn(`User lacks required roles: ${requiredRoles.join(", ")}`);
97
- return {
98
- satisfied: false,
99
- redirect: fallbackRedirect
100
- };
101
- }
102
- }
103
- if (requiredPermissions && requiredPermissions.length > 0) {
104
- if (!requiredPermissions.every((perm) => userPermissions.includes(perm))) {
105
- console.warn(`User lacks required permissions: ${requiredPermissions.join(", ")}`);
106
- return {
107
- satisfied: false,
108
- redirect: fallbackRedirect
109
- };
110
- }
111
- }
112
- if (securityRequirements) for (const requirement of securityRequirements) try {
113
- const result = await requirement(session, user);
114
- if (result && !result.satisfied) return {
115
- ...result,
116
- redirect: result.redirect ?? fallbackRedirect
117
- };
118
- } catch (error) {
119
- console.error("[Auth:Security] Requirement failed:", error);
120
- }
121
- return { satisfied: true };
122
- }
123
- /**
124
- * Sign In Logic
125
- */
126
- async function signIn(data) {
127
- const { email, password } = await loginSchema.parseAsync(data);
128
- const user = await getUserFromEmail(email);
129
- if (!user) return {
130
- status: "ERROR",
131
- message: "Invalid email or password"
132
- };
133
- const passwordHash = await getUserPasswordHash(user.id);
134
- if (!passwordHash || !await verifyPasswordHash(passwordHash, password)) return {
135
- status: "ERROR",
136
- message: "Invalid email or password"
137
- };
138
- for (const validator of authValidators) {
139
- const interception = await validator(user.id);
140
- if (interception) return interception;
141
- }
142
- const sessionFlags = {};
143
- const sessionToken = await generateSessionToken();
144
- const session = await createSession(sessionToken, user.id, sessionFlags);
145
- await setSessionTokenCookie(sessionToken, session.expiresAt);
146
- const fullUser = await performFullUserAugmentation(user);
147
- await eventBus.publish("auth:session-created", {
148
- session,
149
- user: fullUser
150
- });
151
- return {
152
- status: "SUCCESS",
153
- session: { ...session },
154
- user: { ...fullUser }
155
- };
156
- }
157
- /**
158
- * Sign Up Logic
159
- */
160
- async function signUp(data) {
161
- const { email, username, password } = registerSchema.parse(data);
162
- if (!await verifyUsernameInput(username)) throw new Error("Invalid username");
163
- if (!await verifyPasswordStrength(password)) throw new Error("Weak password");
164
- const user = await createUser(email, username, password);
165
- const verificationRequest = await createEmailVerificationRequest(user.id, user.email);
166
- await sendVerificationEmail(verificationRequest.email, verificationRequest.code);
167
- await setEmailVerificationRequestCookie(verificationRequest);
168
- const sessionFlags = {};
169
- const sessionToken = await generateSessionToken();
170
- const session = await createSession(sessionToken, user.id, sessionFlags);
171
- await setSessionTokenCookie(sessionToken, session.expiresAt);
172
- const fullUser = await performFullUserAugmentation(user);
173
- await eventBus.publish("auth:session-created", {
174
- session,
175
- user: fullUser
176
- });
177
- return {
178
- session: { ...session },
179
- user: { ...fullUser }
180
- };
181
- }
182
- /**
183
- * Finalizes login after a challenge
184
- */
185
- async function finalizeLogin(userId, flags) {
186
- const sessionToken = await generateSessionToken();
187
- const session = await createSession(sessionToken, userId, flags);
188
- await setSessionTokenCookie(sessionToken, session.expiresAt);
189
- const user = await getUserById(userId);
190
- if (user) await eventBus.publish("auth:session-created", {
191
- session,
192
- user
193
- });
194
- return {
195
- session: session ? { ...session } : null,
196
- user: user ? { ...user } : null
197
- };
198
- }
199
- /**
200
- * Sign Out
201
- */
202
- async function signOut() {
203
- const { session, user } = await getCurrentSession();
204
- if (session) {
205
- if (user) await eventBus.publish("auth:signed-out", { userId: user.id });
206
- await invalidateSession(session.id);
207
- await deleteSessionTokenCookie();
208
- }
209
- }
210
-
211
- //#endregion
212
- export { checkSecurity, finalizeLogin, performFullUserAugmentation, registerAuthValidator, registerEmailVerificationValidator, registerPasswordResetValidator, registerSecurityRequirement, runEmailVerificationValidators, runPasswordResetValidators, signIn, signOut, signUp };
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};
213
2
  //# sourceMappingURL=logic.mjs.map
@@ -1 +1 @@
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":"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"}
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.js\";\nimport {\n createUser,\n getUserById,\n getUserFromEmail,\n getUserPasswordHash,\n verifyUsernameInput,\n} from \"../../server/auth/user.js\";\nimport { db } from \"../../server/database/inject.js\";\nimport {\n permissionsTable,\n rolesTable,\n rolesToPermissionsTable,\n usersToPermissionsTable,\n usersToRolesTable,\n} from \"../../server/database/schema.js\";\nimport { eventBus } from \"../event-bus.js\";\nimport {\n augmentSession,\n augmentUser,\n registerIdentityAugmenter,\n registerPasswordResetSessionAugmenter,\n registerSessionAugmenter,\n} from \"./augment.js\";\nimport {\n createEmailVerificationRequest,\n sendVerificationEmail,\n setEmailVerificationRequestCookie,\n} from \"./email-verification.js\";\nimport {\n createSession,\n deleteSessionTokenCookie,\n generateSessionToken,\n getCurrentSession,\n invalidateSession,\n setSessionTokenCookie,\n} from \"./session.js\";\nimport type {\n AuthResponse,\n FullUser,\n Session,\n SessionFlags,\n User,\n UserPermission,\n UserRole,\n} from \"./types.js\";\nimport {\n type LoginInput,\n loginSchema,\n type RegisterInput,\n registerSchema,\n} from \"./validation.js\";\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":"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"}
@@ -1,118 +1 @@
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_encode = require('./utils/encode.cjs');
8
- const require_index = require('../../server/emails/index.cjs');
9
- const require_logic = require('./logic.cjs');
10
- let drizzle_orm = require("drizzle-orm");
11
- let _oslojs_crypto_sha2 = require("@oslojs/crypto/sha2");
12
- let _oslojs_encoding = require("@oslojs/encoding");
13
- let date_fns = require("date-fns");
14
- let next_headers = require("next/headers");
15
-
16
- //#region src/core/auth/password-reset.ts
17
- /**
18
- * Creates a new password reset session.
19
- */
20
- async function createPasswordResetSession(token, userId, email) {
21
- const sessionId = (0, _oslojs_encoding.encodeHexLowerCase)((0, _oslojs_crypto_sha2.sha256)(new TextEncoder().encode(token)));
22
- const [session] = await require_inject.db.insert(require_schema.passwordResetSessionTable).values({
23
- id: sessionId,
24
- email,
25
- code: require_encode.generateRandomOTP(),
26
- expiresAt: new Date((0, date_fns.addHours)(/* @__PURE__ */ new Date(), 1)),
27
- userId
28
- }).returning();
29
- return session;
30
- }
31
- /**
32
- * Validates the password reset session token and retrieves user data.
33
- * The user data is augmented by registered modules (e.g. 2FA).
34
- */
35
- async function validatePasswordResetSessionToken(token) {
36
- const sessionId = (0, _oslojs_encoding.encodeHexLowerCase)((0, _oslojs_crypto_sha2.sha256)(new TextEncoder().encode(token)));
37
- const [row] = await require_inject.db.select({
38
- session: require_schema.passwordResetSessionTable,
39
- user: require_schema.userTable
40
- }).from(require_schema.passwordResetSessionTable).innerJoin(require_schema.userTable, (0, drizzle_orm.eq)(require_schema.passwordResetSessionTable.userId, require_schema.userTable.id)).where((0, drizzle_orm.eq)(require_schema.passwordResetSessionTable.id, sessionId));
41
- if (!row || !row.user) return {
42
- session: null,
43
- user: null
44
- };
45
- const { session: baseSession, user: baseUser } = row;
46
- if (/* @__PURE__ */ new Date() > baseSession.expiresAt) {
47
- await require_inject.db.delete(require_schema.passwordResetSessionTable).where((0, drizzle_orm.eq)(require_schema.passwordResetSessionTable.id, baseSession.id));
48
- return {
49
- session: null,
50
- user: null
51
- };
52
- }
53
- const { password, recovery_code, ...safeUser } = baseUser;
54
- const user = await require_logic.performFullUserAugmentation(safeUser);
55
- return {
56
- session: await require_augment.augmentPasswordResetSession(baseSession),
57
- user
58
- };
59
- }
60
- /**
61
- * Marks the password reset session as email verified.
62
- */
63
- async function setPasswordResetSessionAsEmailVerified(sessionId) {
64
- await require_inject.db.update(require_schema.passwordResetSessionTable).set({ emailVerified: true }).where((0, drizzle_orm.eq)(require_schema.passwordResetSessionTable.id, sessionId));
65
- }
66
- /**
67
- * Invalidates all password reset sessions for a user.
68
- */
69
- async function invalidateUserPasswordResetSessions(userId) {
70
- await require_inject.db.delete(require_schema.passwordResetSessionTable).where((0, drizzle_orm.eq)(require_schema.passwordResetSessionTable.userId, userId));
71
- }
72
- /**
73
- * Validates the current password reset session from cookies.
74
- */
75
- async function getCurrentPasswordResetSession() {
76
- const token = (await (0, next_headers.cookies)()).get("password_reset_session")?.value ?? null;
77
- if (token === null) return {
78
- session: null,
79
- user: null
80
- };
81
- const result = await validatePasswordResetSessionToken(token);
82
- if (result.session === null) await deletePasswordResetSessionTokenCookie();
83
- return result;
84
- }
85
- /**
86
- * Sets the password reset session token cookie.
87
- */
88
- async function setPasswordResetSessionTokenCookie(token, expiresAt) {
89
- (await (0, next_headers.cookies)()).set("password_reset_session", token, {
90
- expires: expiresAt,
91
- sameSite: "lax",
92
- httpOnly: true,
93
- path: "/",
94
- secure: process.env.NODE_ENV === "production"
95
- });
96
- }
97
- /**
98
- * Deletes the password reset session token cookie.
99
- */
100
- async function deletePasswordResetSessionTokenCookie() {
101
- (await (0, next_headers.cookies)()).delete("password_reset_session");
102
- }
103
- /**
104
- * Sends a password reset email with the OTP code.
105
- */
106
- async function sendPasswordResetEmail(email, code) {
107
- await /* @__PURE__ */ require_index.sendResetPassword(email, code);
108
- }
109
-
110
- //#endregion
111
- exports.createPasswordResetSession = createPasswordResetSession;
112
- exports.deletePasswordResetSessionTokenCookie = deletePasswordResetSessionTokenCookie;
113
- exports.getCurrentPasswordResetSession = getCurrentPasswordResetSession;
114
- exports.invalidateUserPasswordResetSessions = invalidateUserPasswordResetSessions;
115
- exports.sendPasswordResetEmail = sendPasswordResetEmail;
116
- exports.setPasswordResetSessionAsEmailVerified = setPasswordResetSessionAsEmailVerified;
117
- exports.setPasswordResetSessionTokenCookie = setPasswordResetSessionTokenCookie;
118
- exports.validatePasswordResetSessionToken = validatePasswordResetSessionToken;
1
+ "use server";require(`../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../server/database/inject.cjs`),t=require(`../../server/database/schema.cjs`),n=require(`./augment.cjs`),r=require(`./utils/encode.cjs`),i=require(`../../server/emails/index.cjs`),a=require(`./logic.cjs`);let o=require(`drizzle-orm`),s=require(`@oslojs/crypto/sha2`),c=require(`@oslojs/encoding`),l=require(`date-fns`),u=require(`next/headers`);async function d(n,i,a){let o=(0,c.encodeHexLowerCase)((0,s.sha256)(new TextEncoder().encode(n))),[u]=await e.db.insert(t.passwordResetSessionTable).values({id:o,email:a,code:r.generateRandomOTP(),expiresAt:new Date((0,l.addHours)(new Date,1)),userId:i}).returning();return u}async function f(r){let i=(0,c.encodeHexLowerCase)((0,s.sha256)(new TextEncoder().encode(r))),[l]=await e.db.select({session:t.passwordResetSessionTable,user:t.userTable}).from(t.passwordResetSessionTable).innerJoin(t.userTable,(0,o.eq)(t.passwordResetSessionTable.userId,t.userTable.id)).where((0,o.eq)(t.passwordResetSessionTable.id,i));if(!l||!l.user)return{session:null,user:null};let{session:u,user:d}=l;if(new Date>u.expiresAt)return await e.db.delete(t.passwordResetSessionTable).where((0,o.eq)(t.passwordResetSessionTable.id,u.id)),{session:null,user:null};let{password:f,recovery_code:p,...m}=d,h=await a.performFullUserAugmentation(m);return{session:await n.augmentPasswordResetSession(u),user:h}}async function p(n){await e.db.update(t.passwordResetSessionTable).set({emailVerified:!0}).where((0,o.eq)(t.passwordResetSessionTable.id,n))}async function m(n){await e.db.delete(t.passwordResetSessionTable).where((0,o.eq)(t.passwordResetSessionTable.userId,n))}async function h(){let e=(await(0,u.cookies)()).get(`password_reset_session`)?.value??null;if(e===null)return{session:null,user:null};let t=await f(e);return t.session===null&&await _(),t}async function g(e,t){(await(0,u.cookies)()).set(`password_reset_session`,e,{expires:t,sameSite:`lax`,httpOnly:!0,path:`/`,secure:process.env.NODE_ENV===`production`})}async function _(){(await(0,u.cookies)()).delete(`password_reset_session`)}async function v(e,t){await i.sendResetPassword(e,t)}exports.createPasswordResetSession=d,exports.deletePasswordResetSessionTokenCookie=_,exports.getCurrentPasswordResetSession=h,exports.invalidateUserPasswordResetSessions=m,exports.sendPasswordResetEmail=v,exports.setPasswordResetSessionAsEmailVerified=p,exports.setPasswordResetSessionTokenCookie=g,exports.validatePasswordResetSessionToken=f;