@better-auth/infra 0.1.9-beta.1 → 0.1.10
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.
- package/dist/client.mjs +1 -1
- package/dist/{constants-DWl1utFw.mjs → constants-B-e0_Nsv.mjs} +1 -1
- package/dist/email.mjs +1 -1
- package/dist/index.d.mts +261 -257
- package/dist/index.mjs +84 -92
- package/package.json +7 -4
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { n as INFRA_KV_URL, r as KV_TIMEOUT_MS, t as INFRA_API_URL } from "./constants-
|
|
1
|
+
import { n as INFRA_KV_URL, r as KV_TIMEOUT_MS, t as INFRA_API_URL } from "./constants-B-e0_Nsv.mjs";
|
|
2
2
|
import { EMAIL_TEMPLATES, createEmailSender, sendBulkEmails, sendEmail } from "./email.mjs";
|
|
3
3
|
import { APIError, generateId, getAuthTables, logger, parseState } from "better-auth";
|
|
4
4
|
import { env } from "@better-auth/core/env";
|
|
5
5
|
import { APIError as APIError$1, createAuthEndpoint, createAuthMiddleware, requestPasswordReset, sendVerificationEmailFn, sessionMiddleware } from "better-auth/api";
|
|
6
|
+
import { getCurrentAuthContext } from "@better-auth/core/context";
|
|
6
7
|
import { betterFetch, createFetch } from "@better-fetch/fetch";
|
|
7
8
|
import { isValidPhoneNumber, parsePhoneNumberFromString } from "libphonenumber-js";
|
|
8
9
|
import { createLocalJWKSet, jwtVerify } from "jose";
|
|
@@ -133,21 +134,6 @@ const ORGANIZATION_EVENT_TYPES = {
|
|
|
133
134
|
ORGANIZATION_TEAM_MEMBER_REMOVED: "organization_team_member_removed"
|
|
134
135
|
};
|
|
135
136
|
|
|
136
|
-
//#endregion
|
|
137
|
-
//#region src/events/utils.ts
|
|
138
|
-
function backgroundTask(task) {
|
|
139
|
-
let result;
|
|
140
|
-
try {
|
|
141
|
-
result = task();
|
|
142
|
-
} catch (error) {
|
|
143
|
-
logger.debug("[Dash] Background operation failed: ", error);
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
Promise.resolve(result).catch((error) => {
|
|
147
|
-
logger.debug("[Dash] Background operation failed: ", error);
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
|
|
151
137
|
//#endregion
|
|
152
138
|
//#region src/events/core/adapter.ts
|
|
153
139
|
const getUserByEmail = async (email, ctx) => {
|
|
@@ -245,7 +231,7 @@ const initAccountEvents = (tracker) => {
|
|
|
245
231
|
countryCode: location?.countryCode
|
|
246
232
|
});
|
|
247
233
|
};
|
|
248
|
-
|
|
234
|
+
ctx.context.runInBackground(track());
|
|
249
235
|
};
|
|
250
236
|
const trackAccountUnlink = (account, trigger, ctx, location) => {
|
|
251
237
|
const track = async () => {
|
|
@@ -269,7 +255,7 @@ const initAccountEvents = (tracker) => {
|
|
|
269
255
|
countryCode: location?.countryCode
|
|
270
256
|
});
|
|
271
257
|
};
|
|
272
|
-
|
|
258
|
+
ctx.context.runInBackground(track());
|
|
273
259
|
};
|
|
274
260
|
const trackAccountPasswordChange = (account, trigger, ctx, location) => {
|
|
275
261
|
const track = async () => {
|
|
@@ -293,7 +279,7 @@ const initAccountEvents = (tracker) => {
|
|
|
293
279
|
countryCode: location?.countryCode
|
|
294
280
|
});
|
|
295
281
|
};
|
|
296
|
-
|
|
282
|
+
ctx.context.runInBackground(track());
|
|
297
283
|
};
|
|
298
284
|
return {
|
|
299
285
|
trackAccountLinking,
|
|
@@ -358,7 +344,7 @@ const initSessionEvents = (tracker) => {
|
|
|
358
344
|
countryCode: location?.countryCode
|
|
359
345
|
});
|
|
360
346
|
};
|
|
361
|
-
|
|
347
|
+
ctx.context.runInBackground(track());
|
|
362
348
|
};
|
|
363
349
|
const trackUserSignedOut = (session, trigger, ctx, location) => {
|
|
364
350
|
const track = async () => {
|
|
@@ -384,7 +370,7 @@ const initSessionEvents = (tracker) => {
|
|
|
384
370
|
countryCode: location?.countryCode
|
|
385
371
|
});
|
|
386
372
|
};
|
|
387
|
-
|
|
373
|
+
ctx.context.runInBackground(track());
|
|
388
374
|
};
|
|
389
375
|
const trackSessionRevoked = (session, trigger, ctx, location) => {
|
|
390
376
|
const track = async () => {
|
|
@@ -410,7 +396,7 @@ const initSessionEvents = (tracker) => {
|
|
|
410
396
|
countryCode: location?.countryCode
|
|
411
397
|
});
|
|
412
398
|
};
|
|
413
|
-
|
|
399
|
+
ctx.context.runInBackground(track());
|
|
414
400
|
};
|
|
415
401
|
const trackSessionRevokedAll = (session, trigger, ctx, _location) => {
|
|
416
402
|
const track = async () => {
|
|
@@ -428,7 +414,7 @@ const initSessionEvents = (tracker) => {
|
|
|
428
414
|
}
|
|
429
415
|
});
|
|
430
416
|
};
|
|
431
|
-
|
|
417
|
+
ctx.context.runInBackground(track());
|
|
432
418
|
};
|
|
433
419
|
const trackUserImpersonated = (session, trigger, ctx, location) => {
|
|
434
420
|
const track = async () => {
|
|
@@ -457,7 +443,7 @@ const initSessionEvents = (tracker) => {
|
|
|
457
443
|
countryCode: location?.countryCode
|
|
458
444
|
});
|
|
459
445
|
};
|
|
460
|
-
|
|
446
|
+
ctx.context.runInBackground(track());
|
|
461
447
|
};
|
|
462
448
|
const trackUserImpersonationStop = (session, trigger, ctx, location) => {
|
|
463
449
|
const track = async () => {
|
|
@@ -486,7 +472,7 @@ const initSessionEvents = (tracker) => {
|
|
|
486
472
|
countryCode: location?.countryCode
|
|
487
473
|
});
|
|
488
474
|
};
|
|
489
|
-
|
|
475
|
+
ctx.context.runInBackground(track());
|
|
490
476
|
};
|
|
491
477
|
const trackSessionCreated = (session, trigger, ctx, location) => {
|
|
492
478
|
const track = async () => {
|
|
@@ -512,7 +498,7 @@ const initSessionEvents = (tracker) => {
|
|
|
512
498
|
countryCode: location?.countryCode
|
|
513
499
|
});
|
|
514
500
|
};
|
|
515
|
-
|
|
501
|
+
ctx.context.runInBackground(track());
|
|
516
502
|
};
|
|
517
503
|
const trackEmailVerificationSent = (session, user, trigger, _ctx) => {
|
|
518
504
|
trackEvent({
|
|
@@ -546,7 +532,7 @@ const initSessionEvents = (tracker) => {
|
|
|
546
532
|
}
|
|
547
533
|
});
|
|
548
534
|
};
|
|
549
|
-
|
|
535
|
+
ctx.context.runInBackground(track());
|
|
550
536
|
};
|
|
551
537
|
const trackSocialSignInAttempt = (ctx, trigger) => {
|
|
552
538
|
const track = async () => {
|
|
@@ -565,11 +551,11 @@ const initSessionEvents = (tracker) => {
|
|
|
565
551
|
}
|
|
566
552
|
});
|
|
567
553
|
};
|
|
568
|
-
|
|
554
|
+
ctx.context.runInBackground(track());
|
|
569
555
|
};
|
|
570
556
|
const trackSocialSignInRedirectionAttempt = (ctx, trigger) => {
|
|
571
557
|
const track = async () => {
|
|
572
|
-
const user = await getUserByAuthorizationCode(ctx.
|
|
558
|
+
const user = await getUserByAuthorizationCode(ctx.params?.id, ctx);
|
|
573
559
|
trackEvent({
|
|
574
560
|
eventKey: user?.id.toString() ?? UNKNOWN_USER,
|
|
575
561
|
eventType: EVENT_TYPES.USER_SIGN_IN_FAILED,
|
|
@@ -584,7 +570,7 @@ const initSessionEvents = (tracker) => {
|
|
|
584
570
|
}
|
|
585
571
|
});
|
|
586
572
|
};
|
|
587
|
-
|
|
573
|
+
ctx.context.runInBackground(track());
|
|
588
574
|
};
|
|
589
575
|
return {
|
|
590
576
|
trackUserSignedIn,
|
|
@@ -773,7 +759,7 @@ const initVerificationEvents = (tracker) => {
|
|
|
773
759
|
countryCode: location?.countryCode
|
|
774
760
|
});
|
|
775
761
|
};
|
|
776
|
-
|
|
762
|
+
ctx.context.runInBackground(track());
|
|
777
763
|
};
|
|
778
764
|
const trackPasswordResetRequestCompletion = (verification, trigger, ctx, location) => {
|
|
779
765
|
const track = async () => {
|
|
@@ -795,7 +781,7 @@ const initVerificationEvents = (tracker) => {
|
|
|
795
781
|
countryCode: location?.countryCode
|
|
796
782
|
});
|
|
797
783
|
};
|
|
798
|
-
|
|
784
|
+
ctx.context.runInBackground(track());
|
|
799
785
|
};
|
|
800
786
|
return {
|
|
801
787
|
trackPasswordResetRequest,
|
|
@@ -851,7 +837,13 @@ const initTrackEvents = (options) => {
|
|
|
851
837
|
logger.debug("[Dash] Failed to track event:", e);
|
|
852
838
|
}
|
|
853
839
|
};
|
|
854
|
-
|
|
840
|
+
const onSuccess = (ctx) => {
|
|
841
|
+
ctx.context.runInBackground(track());
|
|
842
|
+
};
|
|
843
|
+
const onError = () => {
|
|
844
|
+
track();
|
|
845
|
+
};
|
|
846
|
+
getCurrentAuthContext().then(onSuccess, onError);
|
|
855
847
|
};
|
|
856
848
|
return { tracker: { trackEvent } };
|
|
857
849
|
};
|
|
@@ -2042,7 +2034,7 @@ const sentinel = (options) => {
|
|
|
2042
2034
|
const { trackEvent } = tracker;
|
|
2043
2035
|
if (!opts.apiKey) logger.warn("[Sentinel] Missing BETTER_AUTH_API_KEY. Security checks may fall back to allow mode when the Infra API rejects requests.");
|
|
2044
2036
|
const securityService = createSecurityClient(opts.apiUrl, opts.apiKey, opts.security || {}, (event) => {
|
|
2045
|
-
|
|
2037
|
+
trackEvent({
|
|
2046
2038
|
eventKey: event.visitorId || event.userId || "unknown",
|
|
2047
2039
|
eventType: `security_${event.type}`,
|
|
2048
2040
|
eventDisplayName: `Security: ${event.type.replace(/_/g, " ")}`,
|
|
@@ -2073,7 +2065,7 @@ const sentinel = (options) => {
|
|
|
2073
2065
|
const displayName = isNoMxRecord ? `Security: invalid email domain ${actionVerb}` : `Security: disposable email ${actionVerb}`;
|
|
2074
2066
|
const description = isNoMxRecord ? `${actionVerb.charAt(0).toUpperCase() + actionVerb.slice(1)} signup attempt with invalid email domain (no MX records): ${data.email}` : `${actionVerb.charAt(0).toUpperCase() + actionVerb.slice(1)} signup attempt with disposable email: ${data.email} (${data.reason}, ${data.confidence} confidence)`;
|
|
2075
2067
|
logger.info(`[Sentinel] Tracking ${reason} event for email: ${data.email} (action: ${actionLabel})`);
|
|
2076
|
-
|
|
2068
|
+
trackEvent({
|
|
2077
2069
|
eventKey: data.email,
|
|
2078
2070
|
eventType,
|
|
2079
2071
|
eventDisplayName: displayName,
|
|
@@ -2091,28 +2083,28 @@ const sentinel = (options) => {
|
|
|
2091
2083
|
});
|
|
2092
2084
|
return {
|
|
2093
2085
|
id: "sentinel",
|
|
2094
|
-
init(
|
|
2086
|
+
init() {
|
|
2095
2087
|
return { options: { databaseHooks: {
|
|
2096
2088
|
user: { create: {
|
|
2097
|
-
async before(_user,
|
|
2098
|
-
if (!
|
|
2099
|
-
const visitorId =
|
|
2089
|
+
async before(_user, ctx) {
|
|
2090
|
+
if (!ctx) return;
|
|
2091
|
+
const visitorId = ctx.context.visitorId;
|
|
2100
2092
|
if (visitorId && opts.security?.freeTrialAbuse?.enabled) {
|
|
2101
2093
|
const abuseCheck = await securityService.checkFreeTrialAbuse(visitorId);
|
|
2102
2094
|
if (abuseCheck.isAbuse && abuseCheck.action === "block") throw new APIError("FORBIDDEN", { message: "Account creation is not allowed from this device." });
|
|
2103
2095
|
}
|
|
2104
2096
|
},
|
|
2105
|
-
async after(user,
|
|
2106
|
-
if (!
|
|
2107
|
-
const visitorId =
|
|
2108
|
-
if (visitorId && opts.security?.freeTrialAbuse?.enabled)
|
|
2097
|
+
async after(user, ctx) {
|
|
2098
|
+
if (!ctx) return;
|
|
2099
|
+
const visitorId = ctx.context.visitorId;
|
|
2100
|
+
if (visitorId && opts.security?.freeTrialAbuse?.enabled) await ctx.context.runInBackgroundOrAwait(securityService.trackFreeTrialSignup(visitorId, user.id));
|
|
2109
2101
|
}
|
|
2110
2102
|
} },
|
|
2111
2103
|
session: { create: {
|
|
2112
|
-
async before(session,
|
|
2113
|
-
if (!
|
|
2114
|
-
const visitorId =
|
|
2115
|
-
const identification =
|
|
2104
|
+
async before(session, ctx) {
|
|
2105
|
+
if (!ctx) return;
|
|
2106
|
+
const visitorId = ctx.context.visitorId;
|
|
2107
|
+
const identification = ctx.context.identification;
|
|
2116
2108
|
if (session.userId && identification?.location && visitorId) {
|
|
2117
2109
|
const travelCheck = await securityService.checkImpossibleTravel(session.userId, identification.location, visitorId);
|
|
2118
2110
|
if (travelCheck?.isImpossible) {
|
|
@@ -2121,13 +2113,13 @@ const sentinel = (options) => {
|
|
|
2121
2113
|
}
|
|
2122
2114
|
}
|
|
2123
2115
|
},
|
|
2124
|
-
async after(session,
|
|
2125
|
-
if (!
|
|
2126
|
-
const visitorId =
|
|
2127
|
-
const identification =
|
|
2116
|
+
async after(session, ctx) {
|
|
2117
|
+
if (!ctx || !session.userId) return;
|
|
2118
|
+
const visitorId = ctx.context.visitorId;
|
|
2119
|
+
const identification = ctx.context.identification;
|
|
2128
2120
|
let user = null;
|
|
2129
2121
|
try {
|
|
2130
|
-
user = await
|
|
2122
|
+
user = await ctx.context.adapter.findOne({
|
|
2131
2123
|
model: "user",
|
|
2132
2124
|
select: [
|
|
2133
2125
|
"email",
|
|
@@ -2143,7 +2135,7 @@ const sentinel = (options) => {
|
|
|
2143
2135
|
logger.warn("[Sentinel] Failed to fetch user for security checks:", error);
|
|
2144
2136
|
}
|
|
2145
2137
|
if (visitorId) {
|
|
2146
|
-
if (await securityService.checkUnknownDevice(session.userId, visitorId) && user?.email)
|
|
2138
|
+
if (await securityService.checkUnknownDevice(session.userId, visitorId) && user?.email) await ctx.context.runInBackgroundOrAwait(securityService.notifyUnknownDevice(session.userId, user.email, identification));
|
|
2147
2139
|
}
|
|
2148
2140
|
if (opts.security?.staleUsers?.enabled && user) {
|
|
2149
2141
|
const staleCheck = await securityService.checkStaleUser(session.userId, user.lastActiveAt || null);
|
|
@@ -2182,7 +2174,7 @@ const sentinel = (options) => {
|
|
|
2182
2174
|
});
|
|
2183
2175
|
}
|
|
2184
2176
|
}
|
|
2185
|
-
if (identification?.location)
|
|
2177
|
+
if (identification?.location) await ctx.context.runInBackgroundOrAwait(securityService.storeLastLocation(session.userId, identification.location));
|
|
2186
2178
|
}
|
|
2187
2179
|
} }
|
|
2188
2180
|
} } };
|
|
@@ -2195,11 +2187,11 @@ const sentinel = (options) => {
|
|
|
2195
2187
|
},
|
|
2196
2188
|
{
|
|
2197
2189
|
matcher: (ctx) => ctx.request?.method !== "GET",
|
|
2198
|
-
handler: createAuthMiddleware(async (
|
|
2199
|
-
const visitorId =
|
|
2200
|
-
const powSolution =
|
|
2190
|
+
handler: createAuthMiddleware(async (ctx) => {
|
|
2191
|
+
const visitorId = ctx.context.visitorId;
|
|
2192
|
+
const powSolution = ctx.headers?.get?.("X-PoW-Solution");
|
|
2201
2193
|
if (visitorId && powSolution) {
|
|
2202
|
-
if ((await securityService.verifyPoWSolution(visitorId, powSolution)).valid)
|
|
2194
|
+
if ((await securityService.verifyPoWSolution(visitorId, powSolution)).valid) ctx.context.powVerified = true;
|
|
2203
2195
|
}
|
|
2204
2196
|
})
|
|
2205
2197
|
},
|
|
@@ -2207,10 +2199,10 @@ const sentinel = (options) => {
|
|
|
2207
2199
|
...phoneValidationHooks.before,
|
|
2208
2200
|
{
|
|
2209
2201
|
matcher: (ctx) => ctx.request?.method !== "GET",
|
|
2210
|
-
handler: createAuthMiddleware(async (
|
|
2211
|
-
const visitorId =
|
|
2212
|
-
const identification =
|
|
2213
|
-
const isSignIn = matchesAnyRoute(
|
|
2202
|
+
handler: createAuthMiddleware(async (ctx) => {
|
|
2203
|
+
const visitorId = ctx.context.visitorId;
|
|
2204
|
+
const identification = ctx.context.identification;
|
|
2205
|
+
const isSignIn = matchesAnyRoute(ctx.path, [
|
|
2214
2206
|
routes.SIGN_IN_EMAIL,
|
|
2215
2207
|
routes.SIGN_IN_USERNAME,
|
|
2216
2208
|
routes.SIGN_IN_EMAIL_OTP,
|
|
@@ -2220,17 +2212,17 @@ const sentinel = (options) => {
|
|
|
2220
2212
|
routes.SIGN_IN_SSO,
|
|
2221
2213
|
routes.SIGN_IN_ANONYMOUS
|
|
2222
2214
|
]);
|
|
2223
|
-
const isSignUp = matchesAnyRoute(
|
|
2224
|
-
const isPasswordReset = matchesAnyRoute(
|
|
2225
|
-
const isTwoFactor = matchesAnyRoute(
|
|
2215
|
+
const isSignUp = matchesAnyRoute(ctx.path, [routes.SIGN_UP_EMAIL]);
|
|
2216
|
+
const isPasswordReset = matchesAnyRoute(ctx.path, [routes.FORGET_PASSWORD, routes.REQUEST_PASSWORD_RESET]);
|
|
2217
|
+
const isTwoFactor = matchesAnyRoute(ctx.path, [
|
|
2226
2218
|
routes.TWO_FACTOR_VERIFY_TOTP,
|
|
2227
2219
|
routes.TWO_FACTOR_VERIFY_BACKUP,
|
|
2228
2220
|
routes.TWO_FACTOR_VERIFY_OTP
|
|
2229
2221
|
]);
|
|
2230
|
-
const isOtpSend = matchesAnyRoute(
|
|
2231
|
-
const isMagicLinkVerify = matchesAnyRoute(
|
|
2232
|
-
const isOrgCreate = matchesAnyRoute(
|
|
2233
|
-
const isSensitiveAction = matchesAnyRoute(
|
|
2222
|
+
const isOtpSend = matchesAnyRoute(ctx.path, [routes.EMAIL_OTP_SEND, routes.PHONE_SEND_OTP]);
|
|
2223
|
+
const isMagicLinkVerify = matchesAnyRoute(ctx.path, [routes.MAGIC_LINK_VERIFY]);
|
|
2224
|
+
const isOrgCreate = matchesAnyRoute(ctx.path, [routes.ORG_CREATE]);
|
|
2225
|
+
const isSensitiveAction = matchesAnyRoute(ctx.path, [
|
|
2234
2226
|
routes.CHANGE_EMAIL,
|
|
2235
2227
|
routes.CHANGE_PASSWORD,
|
|
2236
2228
|
routes.SET_PASSWORD,
|
|
@@ -2238,9 +2230,9 @@ const sentinel = (options) => {
|
|
|
2238
2230
|
routes.PASSKEY_ADD
|
|
2239
2231
|
]);
|
|
2240
2232
|
if (!(isSignIn || isSignUp || isPasswordReset || isTwoFactor || isOtpSend || isMagicLinkVerify || isOrgCreate || isSensitiveAction)) return;
|
|
2241
|
-
const requestBody =
|
|
2233
|
+
const requestBody = ctx.body;
|
|
2242
2234
|
const identifier = requestBody?.email || requestBody?.phone || requestBody?.username || void 0;
|
|
2243
|
-
const powVerified =
|
|
2235
|
+
const powVerified = ctx.context.powVerified === true;
|
|
2244
2236
|
if (visitorId && powVerified) trackEvent({
|
|
2245
2237
|
eventKey: visitorId,
|
|
2246
2238
|
eventType: "security_allowed",
|
|
@@ -2249,8 +2241,8 @@ const sentinel = (options) => {
|
|
|
2249
2241
|
action: "allowed",
|
|
2250
2242
|
reason: "pow_verified",
|
|
2251
2243
|
visitorId,
|
|
2252
|
-
path:
|
|
2253
|
-
userAgent:
|
|
2244
|
+
path: ctx.path,
|
|
2245
|
+
userAgent: ctx.headers?.get?.("user-agent") || "",
|
|
2254
2246
|
identifier,
|
|
2255
2247
|
detectionLabel: "Challenge Completed",
|
|
2256
2248
|
description: identifier ? `Successfully completed security challenge for "${identifier}"` : "Successfully completed security challenge"
|
|
@@ -2270,8 +2262,8 @@ const sentinel = (options) => {
|
|
|
2270
2262
|
action: "blocked",
|
|
2271
2263
|
reason: "credential_stuffing",
|
|
2272
2264
|
visitorId,
|
|
2273
|
-
path:
|
|
2274
|
-
userAgent:
|
|
2265
|
+
path: ctx.path,
|
|
2266
|
+
userAgent: ctx.headers?.get?.("user-agent") || "",
|
|
2275
2267
|
identifier,
|
|
2276
2268
|
detectionType: "cooldown_active",
|
|
2277
2269
|
detectionLabel: "Credential Stuffing",
|
|
@@ -2287,19 +2279,19 @@ const sentinel = (options) => {
|
|
|
2287
2279
|
}
|
|
2288
2280
|
}
|
|
2289
2281
|
await runSecurityChecks({
|
|
2290
|
-
path:
|
|
2282
|
+
path: ctx.path,
|
|
2291
2283
|
identifier,
|
|
2292
2284
|
visitorId,
|
|
2293
2285
|
identification,
|
|
2294
|
-
userAgent:
|
|
2286
|
+
userAgent: ctx.headers?.get?.("user-agent") || ""
|
|
2295
2287
|
}, securityService, trackEvent, powVerified);
|
|
2296
|
-
if (matchesAnyRoute(
|
|
2288
|
+
if (matchesAnyRoute(ctx.path, [
|
|
2297
2289
|
routes.SIGN_UP_EMAIL,
|
|
2298
2290
|
routes.CHANGE_PASSWORD,
|
|
2299
2291
|
routes.SET_PASSWORD,
|
|
2300
2292
|
routes.RESET_PASSWORD
|
|
2301
2293
|
])) {
|
|
2302
|
-
const body =
|
|
2294
|
+
const body = ctx.body;
|
|
2303
2295
|
const passwordToCheck = body?.newPassword || body?.password;
|
|
2304
2296
|
if (passwordToCheck) {
|
|
2305
2297
|
const compromisedResult = await securityService.checkCompromisedPassword(passwordToCheck);
|
|
@@ -2316,18 +2308,18 @@ const sentinel = (options) => {
|
|
|
2316
2308
|
],
|
|
2317
2309
|
after: [{
|
|
2318
2310
|
matcher: (ctx) => ctx.request?.method !== "GET",
|
|
2319
|
-
handler: createAuthMiddleware(async (
|
|
2320
|
-
const visitorId =
|
|
2321
|
-
const identification =
|
|
2322
|
-
const body =
|
|
2323
|
-
if (matchesAnyRoute(
|
|
2311
|
+
handler: createAuthMiddleware(async (ctx) => {
|
|
2312
|
+
const visitorId = ctx.context.visitorId;
|
|
2313
|
+
const identification = ctx.context.identification;
|
|
2314
|
+
const body = ctx.body;
|
|
2315
|
+
if (matchesAnyRoute(ctx.path, [routes.SIGN_IN_EMAIL, routes.SIGN_IN_EMAIL_OTP]) && ctx.context.returned instanceof Error && body?.email && body?.password && visitorId) {
|
|
2324
2316
|
const { email, password } = body;
|
|
2325
2317
|
const ip = identification?.ip || null;
|
|
2326
|
-
|
|
2318
|
+
await ctx.context.runInBackgroundOrAwait(securityService.trackFailedAttempt(email, visitorId, password, ip));
|
|
2327
2319
|
}
|
|
2328
|
-
if (matchesAnyRoute(
|
|
2320
|
+
if (matchesAnyRoute(ctx.path, [routes.SIGN_IN_EMAIL, routes.SIGN_IN_EMAIL_OTP]) && !(ctx.context.returned instanceof Error) && body?.email) {
|
|
2329
2321
|
const email = body.email;
|
|
2330
|
-
|
|
2322
|
+
await ctx.context.runInBackgroundOrAwait(securityService.clearFailedAttempts(email));
|
|
2331
2323
|
}
|
|
2332
2324
|
})
|
|
2333
2325
|
}]
|
|
@@ -4127,13 +4119,13 @@ const listOrganizations = (options) => {
|
|
|
4127
4119
|
});
|
|
4128
4120
|
const needsInMemoryProcessing = sortBy === "members" || !!filterMembers;
|
|
4129
4121
|
const dbSortBy = sortBy === "members" ? "createdAt" : sortBy;
|
|
4122
|
+
const fetchLimit = needsInMemoryProcessing ? 1e3 : limit;
|
|
4123
|
+
const fetchOffset = needsInMemoryProcessing ? 0 : offset;
|
|
4130
4124
|
const [organizations, initialTotal] = await Promise.all([ctx.context.adapter.findMany({
|
|
4131
4125
|
model: "organization",
|
|
4132
4126
|
where,
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
offset
|
|
4136
|
-
},
|
|
4127
|
+
limit: fetchLimit,
|
|
4128
|
+
offset: fetchOffset,
|
|
4137
4129
|
sortBy: {
|
|
4138
4130
|
field: dbSortBy,
|
|
4139
4131
|
direction: sortOrder
|
|
@@ -8054,7 +8046,7 @@ const dash = (options) => {
|
|
|
8054
8046
|
getDashDirectoryDetails: getDirectoryDetails(opts),
|
|
8055
8047
|
dashExecuteAdapter: executeAdapter(opts)
|
|
8056
8048
|
},
|
|
8057
|
-
schema:
|
|
8049
|
+
schema: opts.activityTracking?.enabled ? { user: { fields: { lastActiveAt: { type: "date" } } } } : {}
|
|
8058
8050
|
};
|
|
8059
8051
|
};
|
|
8060
8052
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-auth/infra",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "Dashboard and analytics plugin for Better Auth",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -10,15 +10,18 @@
|
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
12
|
"types": "./dist/index.d.mts",
|
|
13
|
-
"import": "./dist/index.mjs"
|
|
13
|
+
"import": "./dist/index.mjs",
|
|
14
|
+
"default": "./dist/index.mjs"
|
|
14
15
|
},
|
|
15
16
|
"./client": {
|
|
16
17
|
"types": "./dist/client.d.mts",
|
|
17
|
-
"import": "./dist/client.mjs"
|
|
18
|
+
"import": "./dist/client.mjs",
|
|
19
|
+
"default": "./dist/client.mjs"
|
|
18
20
|
},
|
|
19
21
|
"./email": {
|
|
20
22
|
"types": "./dist/email.d.mts",
|
|
21
|
-
"import": "./dist/email.mjs"
|
|
23
|
+
"import": "./dist/email.mjs",
|
|
24
|
+
"default": "./dist/email.mjs"
|
|
22
25
|
}
|
|
23
26
|
},
|
|
24
27
|
"files": [
|