@voltro/plugin-auth 0.86.0 → 0.87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,9 @@
1
- import { newAuthId as e, subjectFromUser as t } from "./userStore.js";
2
- import { Effect as n } from "effect";
3
- import { IMPERSONATION_METADATA_KEY as r, rawImpersonationMark as i } from "@voltro/protocol";
1
+ import { isSessionCredentialLiveFor as e } from "./sessionFamily.js";
2
+ import { newAuthId as t, subjectFromUser as n } from "./userStore.js";
3
+ import { Effect as r } from "effect";
4
+ import { IMPERSONATION_METADATA_KEY as i, rawImpersonationMark as a } from "@voltro/protocol";
4
5
  //#region src/impersonation.ts
5
- var a = 900, o = [
6
+ var o = 900, s = [
6
7
  "/mfa/enroll/start",
7
8
  "/mfa/enroll/verify",
8
9
  "/mfa/unenroll",
@@ -12,7 +13,7 @@ var a = 900, o = [
12
13
  "/sessions/revoke-others",
13
14
  "/switch-tenant",
14
15
  "/impersonate/start"
15
- ], s = (e) => {
16
+ ], c = (e) => {
16
17
  if (typeof e != "object" || !e) return null;
17
18
  let t = e;
18
19
  return typeof t.actorUserId != "string" || t.actorUserId.length === 0 || typeof t.grantId != "string" || typeof t.expiresAt != "string" || typeof t.actorSessionId != "string" || typeof t.startedAt != "string" ? null : {
@@ -23,93 +24,93 @@ var a = 900, o = [
23
24
  expiresAt: t.expiresAt,
24
25
  ...typeof t.reason == "string" ? { reason: t.reason } : {}
25
26
  };
26
- }, c = (e) => e.type === "user" ? s(i(e)) : null, l = (e) => c(e) !== null, u = () => (e) => {
27
+ }, l = (e) => e.type === "user" ? c(a(e)) : null, u = (e) => l(e) !== null, d = () => (e) => {
27
28
  if (e.type !== "user" || e.metadata === void 0) return e;
28
- let t = s(e.metadata[r]), { metadata: n, ...i } = e;
29
+ let t = c(e.metadata[i]), { metadata: n, ...r } = e;
29
30
  return {
30
- ...i,
31
+ ...r,
31
32
  metadata: t === null ? { __redacted: "all" } : {
32
33
  __redacted: "all-except-impersonation",
33
- [r]: t
34
+ [i]: t
34
35
  }
35
36
  };
36
- }, d = (e, t, n = {}) => ({
37
+ }, f = (e, t, n = {}) => ({
37
38
  status: e,
38
39
  body: JSON.stringify(t),
39
40
  contentType: "application/json; charset=utf-8",
40
41
  ...n
41
- }), f = (e, t) => n.suspend(() => {
42
- let r = e.audit(t);
43
- return r === void 0 ? n.void : n.isEffect(r) ? r : n.tryPromise({
44
- try: () => Promise.resolve(r),
42
+ }), p = (e, t) => r.suspend(() => {
43
+ let n = e.audit(t);
44
+ return n === void 0 ? r.void : r.isEffect(n) ? n : r.tryPromise({
45
+ try: () => Promise.resolve(n),
45
46
  catch: (e) => e
46
47
  });
47
- }).pipe(n.catchCause(() => n.void)), p = (i, a, o) => n.gen(function* () {
48
- let s = o.impersonation, c = (o.now ?? Date.now)(), u = new Date(c), p = i.actorSubject, m = (e, t, r = {}) => f(s, {
48
+ }).pipe(r.catchCause(() => r.void)), m = (e, a, o) => r.gen(function* () {
49
+ let s = o.impersonation, c = (o.now ?? Date.now)(), l = new Date(c), d = e.actorSubject, m = (t, n, i = {}) => p(s, {
49
50
  kind: "refused",
50
- at: u,
51
- actorUserId: r.actorUser?.id ?? (p.type === "user" ? p.id : null),
52
- actorEmail: r.actorUser?.email ?? null,
53
- targetUserId: r.target?.id ?? null,
54
- targetEmail: r.target?.email ?? null,
55
- tenantId: p.tenantId ?? null,
56
- reason: i.reason ?? null,
57
- refusal: t,
58
- ipAddress: i.ipAddress ?? null,
59
- userAgent: i.userAgent ?? null
60
- }).pipe(n.as(d(e, {
61
- error: t,
62
- ...r.message === void 0 ? {} : { message: r.message }
51
+ at: l,
52
+ actorUserId: i.actorUser?.id ?? (d.type === "user" ? d.id : null),
53
+ actorEmail: i.actorUser?.email ?? null,
54
+ targetUserId: i.target?.id ?? null,
55
+ targetEmail: i.target?.email ?? null,
56
+ tenantId: d.tenantId ?? null,
57
+ reason: e.reason ?? null,
58
+ refusal: n,
59
+ ipAddress: e.ipAddress ?? null,
60
+ userAgent: e.userAgent ?? null
61
+ }).pipe(r.as(f(t, {
62
+ error: n,
63
+ ...i.message === void 0 ? {} : { message: i.message }
63
64
  })));
64
- if (p.type !== "user") return yield* m(401, "unauthenticated");
65
- if (l(p)) return yield* m(403, "nested_impersonation", { message: "An impersonated session may not start another impersonation. Stop the current one first." });
66
- if (!i.actorSessionId) return yield* m(400, "no_actor_session");
67
- let h = yield* a.findById(p.id);
65
+ if (d.type !== "user") return yield* m(401, "unauthenticated");
66
+ if (u(d)) return yield* m(403, "nested_impersonation", { message: "An impersonated session may not start another impersonation. Stop the current one first." });
67
+ if (!e.actorSessionId) return yield* m(400, "no_actor_session");
68
+ let h = yield* a.findById(d.id);
68
69
  if (!h) return yield* m(401, "unauthenticated");
69
- if (!i.targetUserId && !i.targetEmail) return yield* m(400, "target_required", { actorUser: h });
70
- let g = i.targetUserId ? yield* a.findById(i.targetUserId) : yield* a.findByEmail(i.targetEmail);
70
+ if (!e.targetUserId && !e.targetEmail) return yield* m(400, "target_required", { actorUser: h });
71
+ let g = e.targetUserId ? yield* a.findById(e.targetUserId) : yield* a.findByEmail(e.targetEmail);
71
72
  if (!g) return yield* m(404, "target_not_found", { actorUser: h });
72
73
  if (g.id === h.id) return yield* m(400, "self_impersonation", {
73
74
  actorUser: h,
74
75
  target: g
75
76
  });
76
- let _ = i.reason?.trim() ?? "";
77
+ let _ = e.reason?.trim() ?? "";
77
78
  if ((s.requireReason ?? !0) && _.length === 0) return yield* m(400, "reason_required", {
78
79
  actorUser: h,
79
80
  target: g,
80
81
  message: "A reason is required to impersonate a user."
81
82
  });
82
83
  if (!(yield* s.authority({
83
- actor: p,
84
+ actor: d,
84
85
  actorUser: h,
85
86
  target: g
86
- }).pipe(n.catchCause(() => n.succeed(!1))))) return yield* m(403, "not_permitted", {
87
+ }).pipe(r.catchCause(() => r.succeed(!1))))) return yield* m(403, "not_permitted", {
87
88
  actorUser: h,
88
89
  target: g
89
90
  });
90
91
  if (yield* s.authority({
91
- actor: t(g),
92
+ actor: n(g),
92
93
  actorUser: g,
93
94
  target: h
94
- }).pipe(n.catchCause(() => n.succeed(!0)))) return yield* m(403, "target_may_impersonate", {
95
+ }).pipe(r.catchCause(() => r.succeed(!0)))) return yield* m(403, "target_may_impersonate", {
95
96
  actorUser: h,
96
97
  target: g,
97
98
  message: "This user may themselves impersonate others and cannot be impersonated."
98
99
  });
99
- let v = s.maxDurationSeconds ?? 900, y = Math.max(1, Math.min(i.durationSeconds ?? v, v)), b = new Date(c + y * 1e3), x = e("sess"), S = yield* a.insertImpersonationGrant({
100
- id: e("imp"),
100
+ let v = s.maxDurationSeconds ?? 900, y = Math.max(1, Math.min(e.durationSeconds ?? v, v)), b = new Date(c + y * 1e3), x = t("sess"), S = yield* a.insertImpersonationGrant({
101
+ id: t("imp"),
101
102
  sessionId: x,
102
103
  actorUserId: h.id,
103
- actorSessionId: i.actorSessionId,
104
+ actorSessionId: e.actorSessionId,
104
105
  targetUserId: g.id,
105
106
  tenantId: g.tenantId,
106
107
  reason: _.length > 0 ? _ : null,
107
108
  expiresAt: b,
108
- ipAddress: i.ipAddress ?? null,
109
- userAgent: i.userAgent ?? null
109
+ ipAddress: e.ipAddress ?? null,
110
+ userAgent: e.userAgent ?? null
110
111
  }), C = {
111
112
  actorUserId: h.id,
112
- actorSessionId: i.actorSessionId,
113
+ actorSessionId: e.actorSessionId,
113
114
  grantId: S.id,
114
115
  startedAt: S.startedAt.toISOString(),
115
116
  expiresAt: b.toISOString(),
@@ -117,13 +118,13 @@ var a = 900, o = [
117
118
  }, w = yield* o.issuer.issue(g, {
118
119
  sessionId: x,
119
120
  ttlSeconds: y,
120
- metadata: { [r]: C },
121
- ipAddress: i.ipAddress ?? null,
122
- userAgent: i.userAgent ?? null
121
+ metadata: { [i]: C },
122
+ ipAddress: e.ipAddress ?? null,
123
+ userAgent: e.userAgent ?? null
123
124
  });
124
- return yield* f(s, {
125
+ return yield* p(s, {
125
126
  kind: "started",
126
- at: u,
127
+ at: l,
127
128
  actorUserId: h.id,
128
129
  actorEmail: h.email,
129
130
  targetUserId: g.id,
@@ -133,43 +134,43 @@ var a = 900, o = [
133
134
  grantId: S.id,
134
135
  reason: _.length > 0 ? _ : null,
135
136
  expiresAt: b,
136
- ipAddress: i.ipAddress ?? null,
137
- userAgent: i.userAgent ?? null
138
- }), d(200, {
137
+ ipAddress: e.ipAddress ?? null,
138
+ userAgent: e.userAgent ?? null
139
+ }), f(200, {
139
140
  ok: !0,
140
141
  impersonation: C,
141
142
  subject: w.subject
142
143
  }, { setCookie: w.setCookie });
143
- }), m = (e, t, r) => n.gen(function* () {
144
- let i = r.impersonation, a = (r.now ?? Date.now)(), o = new Date(a), s = c(e.subject);
145
- if (!s || !e.sessionId) return d(400, { error: "not_impersonating" });
146
- let l = yield* t.findImpersonationGrantBySession(e.sessionId);
147
- yield* t.endImpersonationGrant(e.sessionId, "stopped", o).pipe(n.ignore), e.subject.type === "user" && (yield* t.revokeSession(e.subject.id, e.sessionId).pipe(n.ignore)), r.invalidateSession?.(e.sessionId);
148
- let u = yield* t.findById(s.actorUserId), p = yield* t.findSession(s.actorSessionId), m = p ? Math.floor((p.expiresAt.getTime() - a) / 1e3) : 0;
149
- if (yield* f(i, {
144
+ }), h = (t, n, i) => r.gen(function* () {
145
+ let a = i.impersonation, o = (i.now ?? Date.now)(), s = new Date(o), c = l(t.subject);
146
+ if (!c || !t.sessionId) return f(400, { error: "not_impersonating" });
147
+ let u = yield* n.findImpersonationGrantBySession(t.sessionId);
148
+ yield* n.endImpersonationGrant(t.sessionId, "stopped", s).pipe(r.ignore), t.subject.type === "user" && (yield* n.revokeSession(t.subject.id, t.sessionId).pipe(r.ignore)), i.invalidateSession?.(t.sessionId);
149
+ let d = yield* n.findById(c.actorUserId), m = yield* n.findSession(c.actorSessionId), h = m ? Math.floor((m.expiresAt.getTime() - o) / 1e3) : 0;
150
+ if (yield* p(a, {
150
151
  kind: "stopped",
151
- at: o,
152
- actorUserId: s.actorUserId,
153
- actorEmail: u?.email ?? null,
154
- targetUserId: e.subject.type === "user" ? e.subject.id : null,
152
+ at: s,
153
+ actorUserId: c.actorUserId,
154
+ actorEmail: d?.email ?? null,
155
+ targetUserId: t.subject.type === "user" ? t.subject.id : null,
155
156
  targetEmail: null,
156
- tenantId: l?.tenantId ?? e.subject.tenantId ?? null,
157
- sessionId: e.sessionId,
158
- ...l ? { grantId: l.id } : {},
159
- reason: l?.reason ?? null
160
- }), !u || !p || m <= 0) return d(200, {
157
+ tenantId: u?.tenantId ?? t.subject.tenantId ?? null,
158
+ sessionId: t.sessionId,
159
+ ...u ? { grantId: u.id } : {},
160
+ reason: u?.reason ?? null
161
+ }), !d || !e(m, c.actorSessionId, d.id, o) || !Number.isSafeInteger(h) || h <= 0) return f(200, {
161
162
  ok: !0,
162
163
  restored: !1
163
- }, { setCookie: r.issuer.clear() });
164
- let h = yield* r.issuer.reissue(u, {
165
- sessionId: s.actorSessionId,
166
- ttlSeconds: m
164
+ }, { setCookie: i.issuer.clear() });
165
+ let g = yield* i.issuer.reissue(d, {
166
+ sessionId: c.actorSessionId,
167
+ ttlSeconds: h
167
168
  });
168
- return d(200, {
169
+ return f(200, {
169
170
  ok: !0,
170
171
  restored: !0,
171
- subject: h.subject
172
- }, { setCookie: h.setCookie });
172
+ subject: g.subject
173
+ }, { setCookie: g.setCookie });
173
174
  });
174
175
  //#endregion
175
- export { a as IMPERSONATION_DEFAULT_DURATION_S, o as IMPERSONATION_FORBIDDEN_SUBPATHS, p as handleImpersonationStart, m as handleImpersonationStop, u as impersonationAuditRedactor, c as impersonationOf, l as isImpersonated };
176
+ export { o as IMPERSONATION_DEFAULT_DURATION_S, s as IMPERSONATION_FORBIDDEN_SUBPATHS, m as handleImpersonationStart, h as handleImpersonationStop, d as impersonationAuditRedactor, l as impersonationOf, u as isImpersonated };