@better-auth/infra 0.2.6 → 0.2.7
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.d.mts +6 -1
- package/dist/client.mjs +34 -20
- package/dist/{constants-DdWGfvz1.mjs → constants-CvriWQVc.mjs} +6 -2
- package/dist/email.d.mts +5 -0
- package/dist/email.mjs +33 -31
- package/dist/fetch-DiAhoiKA.mjs +26 -0
- package/dist/index.d.mts +36 -9
- package/dist/index.mjs +274 -270
- package/dist/native.d.mts +6 -1
- package/dist/native.mjs +28 -15
- package/dist/{pow-CT9ehp8e.mjs → pow-retry-BTL4g3RP.mjs} +23 -21
- package/package.json +1 -1
- /package/dist/{dash-client-CVCHbtoB.d.mts → dash-client-B6U89e1S.d.mts} +0 -0
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { n as
|
|
1
|
+
import { n as INFRA_API_URL, r as INFRA_KV_URL } from "./constants-CvriWQVc.mjs";
|
|
2
|
+
import { n as createKV, t as createAPI } from "./fetch-DiAhoiKA.mjs";
|
|
2
3
|
import { EMAIL_TEMPLATES, createEmailSender, sendBulkEmails, sendEmail } from "./email.mjs";
|
|
3
4
|
import { APIError, generateId, getAuthTables, logger, parseState } from "better-auth";
|
|
4
5
|
import { env } from "@better-auth/core/env";
|
|
5
6
|
import { APIError as APIError$1, createAuthEndpoint, createAuthMiddleware, requestPasswordReset, sendVerificationEmailFn, sessionMiddleware } from "better-auth/api";
|
|
6
7
|
import { getCurrentAuthContext } from "@better-auth/core/context";
|
|
7
|
-
import {
|
|
8
|
+
import { createFetch } from "@better-fetch/fetch";
|
|
8
9
|
import { isValidPhoneNumber, parsePhoneNumberFromString } from "libphonenumber-js";
|
|
9
10
|
import { createLocalJWKSet, jwtVerify } from "jose";
|
|
10
11
|
import z$1, { z } from "zod";
|
|
@@ -14,7 +15,9 @@ function resolveConnectionOptions(options) {
|
|
|
14
15
|
return {
|
|
15
16
|
apiUrl: options?.apiUrl || INFRA_API_URL,
|
|
16
17
|
kvUrl: options?.kvUrl || INFRA_KV_URL,
|
|
17
|
-
apiKey: options?.apiKey || env.BETTER_AUTH_API_KEY || ""
|
|
18
|
+
apiKey: options?.apiKey || env.BETTER_AUTH_API_KEY || "",
|
|
19
|
+
apiTimeout: options?.apiTimeout ?? 3e3,
|
|
20
|
+
kvTimeout: options?.kvTimeout ?? 1e3
|
|
18
21
|
};
|
|
19
22
|
}
|
|
20
23
|
function resolveDashOptions(options) {
|
|
@@ -96,6 +99,8 @@ const routes = {
|
|
|
96
99
|
EMAIL_OTP_SEND: "/email-otp/send-verification-otp",
|
|
97
100
|
PHONE_SEND_OTP: "/phone-number/send-otp",
|
|
98
101
|
PHONE_VERIFY_OTP: "/phone-number/verify-phone-number",
|
|
102
|
+
DEVICE_TOKEN: "/device/token",
|
|
103
|
+
SIWE_VERIFY: "/siwe/verify",
|
|
99
104
|
ORG_CREATE: "/organization/create",
|
|
100
105
|
ORG_INVITE_MEMBER: "/organization/invite-member",
|
|
101
106
|
API_KEY_CREATE: "/api-key/create",
|
|
@@ -109,7 +114,8 @@ const routes = {
|
|
|
109
114
|
ADMIN_REVOKE_USER_SESSIONS: "/admin/revoke-user-sessions",
|
|
110
115
|
ADMIN_SET_PASSWORD: "/admin/set-user-password",
|
|
111
116
|
ADMIN_BAN_USER: "/admin/ban-user",
|
|
112
|
-
ADMIN_UNBAN_USER: "/admin/unban-user"
|
|
117
|
+
ADMIN_UNBAN_USER: "/admin/unban-user",
|
|
118
|
+
ADMIN_IMPERSONATE_USER: "/admin/impersonate-user"
|
|
113
119
|
};
|
|
114
120
|
const ORGANIZATION_EVENT_TYPES = {
|
|
115
121
|
ORGANIZATION_CREATED: "organization_created",
|
|
@@ -308,16 +314,33 @@ const matchesAnyRoute = (path, routes) => {
|
|
|
308
314
|
};
|
|
309
315
|
//#endregion
|
|
310
316
|
//#region src/events/login-methods.ts
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
routes.
|
|
314
|
-
routes.
|
|
315
|
-
routes.
|
|
316
|
-
routes.SIGN_IN_EMAIL_OTP,
|
|
317
|
-
routes.
|
|
317
|
+
const OAUTH_CALLBACK_PATHS = [routes.SIGN_IN_SOCIAL_CALLBACK, routes.SIGN_IN_OAUTH_CALLBACK];
|
|
318
|
+
const PATH_TO_METHOD = [
|
|
319
|
+
[routes.SIGN_IN_EMAIL, "email"],
|
|
320
|
+
[routes.SIGN_UP_EMAIL, "email"],
|
|
321
|
+
[routes.SIGN_IN_USERNAME, "username"],
|
|
322
|
+
[routes.SIGN_IN_EMAIL_OTP, "email-otp"],
|
|
323
|
+
[routes.SIGN_IN_SOCIAL, "social"],
|
|
324
|
+
[routes.SIGN_IN_ANONYMOUS, "anonymous"],
|
|
325
|
+
[routes.SIGN_IN_PASSKEY, "passkey"],
|
|
326
|
+
[routes.SIGN_IN_MAGIC_LINK, "magic-link"],
|
|
327
|
+
[routes.MAGIC_LINK_VERIFY, "magic-link"],
|
|
328
|
+
[routes.SIGN_IN_SSO, "sso"],
|
|
329
|
+
[routes.PHONE_VERIFY_OTP, "phone"],
|
|
330
|
+
[routes.TWO_FACTOR_VERIFY_TOTP, "totp"],
|
|
331
|
+
[routes.TWO_FACTOR_VERIFY_OTP, "two-factor-otp"],
|
|
332
|
+
[routes.TWO_FACTOR_VERIFY_BACKUP, "backup-code"],
|
|
333
|
+
[routes.ADMIN_IMPERSONATE_USER, "impersonation"],
|
|
334
|
+
[routes.DEVICE_TOKEN, "device-code"],
|
|
335
|
+
[routes.SIWE_VERIFY, "siwe"]
|
|
318
336
|
];
|
|
319
337
|
const getLoginMethod = (ctx) => {
|
|
320
|
-
if (matchesAnyRoute(ctx.path,
|
|
338
|
+
if (matchesAnyRoute(ctx.path, OAUTH_CALLBACK_PATHS)) {
|
|
339
|
+
const id = ctx.params?.id;
|
|
340
|
+
if (typeof id === "string" && id && !id.startsWith(":")) return id;
|
|
341
|
+
return null;
|
|
342
|
+
}
|
|
343
|
+
for (const [path, method] of PATH_TO_METHOD) if (matchesAnyRoute(ctx.path, [path])) return method;
|
|
321
344
|
return null;
|
|
322
345
|
};
|
|
323
346
|
//#endregion
|
|
@@ -812,18 +835,11 @@ const getOrganizationTriggerInfo = (user) => {
|
|
|
812
835
|
};
|
|
813
836
|
//#endregion
|
|
814
837
|
//#region src/events/index.ts
|
|
815
|
-
const initTrackEvents = (
|
|
816
|
-
const $fetch = createFetch({
|
|
817
|
-
baseURL: options.apiUrl,
|
|
818
|
-
headers: {
|
|
819
|
-
"user-agent": "better-auth",
|
|
820
|
-
"x-api-key": options.apiKey
|
|
821
|
-
}
|
|
822
|
-
});
|
|
838
|
+
const initTrackEvents = ($api) => {
|
|
823
839
|
const trackEvent = (data) => {
|
|
824
840
|
const track = async () => {
|
|
825
841
|
try {
|
|
826
|
-
await $
|
|
842
|
+
await $api("/events/track", {
|
|
827
843
|
method: "POST",
|
|
828
844
|
body: {
|
|
829
845
|
eventType: data.eventType,
|
|
@@ -874,11 +890,10 @@ function maybeCleanup() {
|
|
|
874
890
|
/**
|
|
875
891
|
* Fetch identification data from durable-kv by requestId
|
|
876
892
|
*/
|
|
877
|
-
async function getIdentification(requestId,
|
|
893
|
+
async function getIdentification(requestId, $kv) {
|
|
878
894
|
maybeCleanup();
|
|
879
895
|
const cached = identificationCache.get(requestId);
|
|
880
896
|
if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) return cached.data;
|
|
881
|
-
const baseUrl = kvUrl || INFRA_KV_URL;
|
|
882
897
|
const maxRetries = 3;
|
|
883
898
|
const retryDelays = [
|
|
884
899
|
50,
|
|
@@ -886,24 +901,20 @@ async function getIdentification(requestId, apiKey, kvUrl) {
|
|
|
886
901
|
200
|
|
887
902
|
];
|
|
888
903
|
for (let attempt = 0; attempt <= maxRetries; attempt++) try {
|
|
889
|
-
const
|
|
890
|
-
|
|
891
|
-
headers: { "x-api-key": apiKey },
|
|
892
|
-
signal: AbortSignal.timeout(KV_TIMEOUT_MS)
|
|
893
|
-
});
|
|
894
|
-
if (response.ok) {
|
|
895
|
-
const data = await response.json();
|
|
904
|
+
const { data, error } = await $kv(`/identify/${requestId}`, { method: "GET" });
|
|
905
|
+
if (data && !error) {
|
|
896
906
|
identificationCache.set(requestId, {
|
|
897
907
|
data,
|
|
898
908
|
timestamp: Date.now()
|
|
899
909
|
});
|
|
900
910
|
return data;
|
|
901
911
|
}
|
|
902
|
-
|
|
912
|
+
const status = error?.status;
|
|
913
|
+
if (status === 404 && attempt < maxRetries) {
|
|
903
914
|
await new Promise((resolve) => setTimeout(resolve, retryDelays[attempt]));
|
|
904
915
|
continue;
|
|
905
916
|
}
|
|
906
|
-
if (
|
|
917
|
+
if (status !== 404) identificationCache.set(requestId, {
|
|
907
918
|
data: null,
|
|
908
919
|
timestamp: Date.now()
|
|
909
920
|
});
|
|
@@ -931,16 +942,19 @@ function extractIdentificationHeaders(request) {
|
|
|
931
942
|
};
|
|
932
943
|
}
|
|
933
944
|
/**
|
|
934
|
-
* Early middleware that loads identification data
|
|
945
|
+
* Early middleware that loads identification data.
|
|
946
|
+
*
|
|
947
|
+
* @param $kv — KV client from {@link createKV} for the same plugin options (one instance per plugin).
|
|
935
948
|
*/
|
|
936
|
-
function createIdentificationMiddleware(
|
|
949
|
+
function createIdentificationMiddleware($kv) {
|
|
937
950
|
return createAuthMiddleware(async (ctx) => {
|
|
938
951
|
const { visitorId, requestId: headerRequestId } = extractIdentificationHeaders(ctx.request);
|
|
939
952
|
const requestId = headerRequestId ?? ctx.getCookie("__infra-rid") ?? null;
|
|
940
953
|
ctx.context.visitorId = visitorId;
|
|
941
954
|
ctx.context.requestId = requestId;
|
|
942
|
-
if (requestId)
|
|
943
|
-
|
|
955
|
+
if (requestId) {
|
|
956
|
+
if (ctx.context.identification === void 0) ctx.context.identification = await getIdentification(requestId, $kv) ?? null;
|
|
957
|
+
} else ctx.context.identification = null;
|
|
944
958
|
const ipConfig = ctx.context.options?.advanced?.ipAddress;
|
|
945
959
|
if (ipConfig?.disableIpTracking === true) {
|
|
946
960
|
ctx.context.location = void 0;
|
|
@@ -1064,23 +1078,19 @@ async function sha1Hash(input) {
|
|
|
1064
1078
|
/**
|
|
1065
1079
|
* Whether Sentinel should normalize emails for deduplication/sign-in consistency.
|
|
1066
1080
|
* If `emailNormalization` is set, it wins; otherwise legacy behavior uses `emailValidation.enabled`.
|
|
1067
|
-
* @internal Not part of the package public API; used by the sentinel plugin and email helpers.
|
|
1068
1081
|
*/
|
|
1069
1082
|
function isEmailNormalizationEnabled(security) {
|
|
1070
1083
|
const explicit = security?.emailNormalization;
|
|
1071
1084
|
if (explicit !== void 0) return explicit.enabled !== false;
|
|
1072
1085
|
return security?.emailValidation?.enabled !== false;
|
|
1073
1086
|
}
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
headers: { "x-api-key": apiKey },
|
|
1079
|
-
throw: true
|
|
1080
|
-
});
|
|
1087
|
+
/**
|
|
1088
|
+
* @param $api — Dash client from `createAPI(opts, { throw: true })`.
|
|
1089
|
+
*/
|
|
1090
|
+
function createSecurityClient(conn, $api, options, onSecurityEvent) {
|
|
1081
1091
|
const emailSender = createEmailSender({
|
|
1082
|
-
apiUrl:
|
|
1083
|
-
apiKey
|
|
1092
|
+
apiUrl: conn.apiUrl || INFRA_API_URL,
|
|
1093
|
+
apiKey: conn.apiKey
|
|
1084
1094
|
});
|
|
1085
1095
|
function logEvent(event) {
|
|
1086
1096
|
const fullEvent = {
|
|
@@ -1485,7 +1495,9 @@ const all = new Set([
|
|
|
1485
1495
|
"/forget-password",
|
|
1486
1496
|
"/request-password-reset",
|
|
1487
1497
|
"/send-verification-email",
|
|
1488
|
-
"/change-email"
|
|
1498
|
+
"/change-email",
|
|
1499
|
+
"/organization/invite-member",
|
|
1500
|
+
"/dash/organization/invite-member"
|
|
1489
1501
|
]);
|
|
1490
1502
|
/**
|
|
1491
1503
|
* Path is one of `[
|
|
@@ -1502,7 +1514,9 @@ const all = new Set([
|
|
|
1502
1514
|
* '/forget-password',
|
|
1503
1515
|
* '/request-password-reset',
|
|
1504
1516
|
* '/send-verification-email',
|
|
1505
|
-
* '/change-email'
|
|
1517
|
+
* '/change-email',
|
|
1518
|
+
* '/organization/invite-member',
|
|
1519
|
+
* '/dash/organization/invite-member'
|
|
1506
1520
|
* ]`.
|
|
1507
1521
|
* @param context Request context
|
|
1508
1522
|
* @param context.path Request path
|
|
@@ -1560,17 +1574,11 @@ function normalizeEmail(email, context) {
|
|
|
1560
1574
|
if (GMAIL_LIKE_DOMAINS.has(domain)) localPart = localPart.replace(/\./g, "");
|
|
1561
1575
|
return `${localPart}@${domain}`;
|
|
1562
1576
|
}
|
|
1563
|
-
function
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
});
|
|
1569
|
-
const $kv = createFetch({
|
|
1570
|
-
baseURL: kvUrl,
|
|
1571
|
-
headers: { "x-api-key": apiKey },
|
|
1572
|
-
timeout: KV_TIMEOUT_MS
|
|
1573
|
-
});
|
|
1577
|
+
function hasRemoteEmailClients(options) {
|
|
1578
|
+
return options.$api !== void 0 && options.$kv !== void 0;
|
|
1579
|
+
}
|
|
1580
|
+
function createEmailValidator(options) {
|
|
1581
|
+
const { $api, $kv, emailValidationOptions = {} } = options;
|
|
1574
1582
|
/**
|
|
1575
1583
|
* Fetch and resolve email validity policy from API with caching
|
|
1576
1584
|
* Sends client config to API which merges with user's dashboard settings
|
|
@@ -1744,18 +1752,10 @@ function createEmailValidationHook(validator, trackEvent) {
|
|
|
1744
1752
|
*
|
|
1745
1753
|
* @example
|
|
1746
1754
|
* // API-backed validation
|
|
1747
|
-
* createEmailHooks({
|
|
1748
|
-
*
|
|
1749
|
-
* @example
|
|
1750
|
-
* // High strictness + API
|
|
1751
|
-
* createEmailHooks({
|
|
1752
|
-
* emailValidationOptions: { strictness: "high" },
|
|
1753
|
-
* useApi: true,
|
|
1754
|
-
* apiKey: "your-api-key",
|
|
1755
|
-
* })
|
|
1755
|
+
* createEmailHooks({ $api, $kv })
|
|
1756
1756
|
*/
|
|
1757
1757
|
function createEmailHooks(options = {}) {
|
|
1758
|
-
const { emailValidationOptions, emailNormalizationOptions,
|
|
1758
|
+
const { emailValidationOptions, emailNormalizationOptions, trackEvent } = options;
|
|
1759
1759
|
const emailConfig = {
|
|
1760
1760
|
enabled: true,
|
|
1761
1761
|
strictness: "medium",
|
|
@@ -1765,10 +1765,9 @@ function createEmailHooks(options = {}) {
|
|
|
1765
1765
|
return { before: [...isEmailNormalizationEnabled({
|
|
1766
1766
|
emailValidation: emailValidationOptions,
|
|
1767
1767
|
emailNormalization: emailNormalizationOptions
|
|
1768
|
-
}) ? [createEmailNormalizationHook()] : [], ...emailConfig.enabled ? [createEmailValidationHook(
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
apiKey,
|
|
1768
|
+
}) ? [createEmailNormalizationHook()] : [], ...emailConfig.enabled ? [createEmailValidationHook(hasRemoteEmailClients(options) ? createEmailValidator({
|
|
1769
|
+
$api: options.$api,
|
|
1770
|
+
$kv: options.$kv,
|
|
1772
1771
|
emailValidationOptions: emailConfig
|
|
1773
1772
|
}) : void 0, trackEvent)] : []] };
|
|
1774
1773
|
}
|
|
@@ -2050,10 +2049,13 @@ async function runSecurityChecks(hookCtx, checkCtx, securityService, trackEvent,
|
|
|
2050
2049
|
//#region src/sentinel/sentinel.ts
|
|
2051
2050
|
const sentinel = (options) => {
|
|
2052
2051
|
const opts = resolveSentinelOptions(options);
|
|
2053
|
-
const
|
|
2052
|
+
const $api = createAPI(opts);
|
|
2053
|
+
const $apiThrowing = createAPI(opts, { throw: true });
|
|
2054
|
+
const $kv = createKV(opts);
|
|
2055
|
+
const { tracker } = initTrackEvents($api);
|
|
2054
2056
|
const { trackEvent } = tracker;
|
|
2055
2057
|
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.");
|
|
2056
|
-
const securityService = createSecurityClient(opts
|
|
2058
|
+
const securityService = createSecurityClient(opts, $apiThrowing, opts.security || {}, (event) => {
|
|
2057
2059
|
trackEvent({
|
|
2058
2060
|
eventKey: event.visitorId || event.userId || "unknown",
|
|
2059
2061
|
eventType: "security_signal",
|
|
@@ -2072,11 +2074,11 @@ const sentinel = (options) => {
|
|
|
2072
2074
|
const emailHooks = createEmailHooks({
|
|
2073
2075
|
emailValidationOptions: opts.security?.emailValidation,
|
|
2074
2076
|
emailNormalizationOptions: opts.security?.emailNormalization,
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2077
|
+
trackEvent,
|
|
2078
|
+
...opts.apiKey ? {
|
|
2079
|
+
$api,
|
|
2080
|
+
$kv
|
|
2081
|
+
} : {}
|
|
2080
2082
|
});
|
|
2081
2083
|
return {
|
|
2082
2084
|
id: "sentinel",
|
|
@@ -2209,7 +2211,7 @@ const sentinel = (options) => {
|
|
|
2209
2211
|
before: [
|
|
2210
2212
|
{
|
|
2211
2213
|
matcher: (ctx) => ctx.request?.method !== "GET",
|
|
2212
|
-
handler: createIdentificationMiddleware(
|
|
2214
|
+
handler: createIdentificationMiddleware($kv)
|
|
2213
2215
|
},
|
|
2214
2216
|
{
|
|
2215
2217
|
matcher: (ctx) => ctx.request?.method !== "GET",
|
|
@@ -2655,32 +2657,32 @@ const JTI_CHECK_GRACE_PERIOD_SECONDS = 30;
|
|
|
2655
2657
|
const JWKS_CACHE_TTL_MS = 900 * 1e3;
|
|
2656
2658
|
const jwksCache = /* @__PURE__ */ new Map();
|
|
2657
2659
|
const inflightRequests = /* @__PURE__ */ new Map();
|
|
2658
|
-
async function fetchJWKS(ctx,
|
|
2659
|
-
const { data, error } = await
|
|
2660
|
+
async function fetchJWKS(ctx, cacheKey, $api) {
|
|
2661
|
+
const { data, error } = await $api("/api/auth/jwks");
|
|
2660
2662
|
if (error || !data) {
|
|
2661
2663
|
ctx.context.logger.warn("[Dash] Failed to fetch JWKS", error);
|
|
2662
|
-
throw
|
|
2664
|
+
throw ctx.error("UNAUTHORIZED", { message: "Invalid API key" });
|
|
2663
2665
|
}
|
|
2664
|
-
jwksCache.set(
|
|
2666
|
+
jwksCache.set(cacheKey, {
|
|
2665
2667
|
data,
|
|
2666
2668
|
expiresAt: Date.now() + JWKS_CACHE_TTL_MS
|
|
2667
2669
|
});
|
|
2668
2670
|
return createLocalJWKSet(data);
|
|
2669
2671
|
}
|
|
2670
|
-
async function prefetchJWKS(ctx,
|
|
2671
|
-
const fetchPromise = fetchJWKS(ctx,
|
|
2672
|
-
inflightRequests.set(
|
|
2673
|
-
fetchPromise.finally(() => inflightRequests.delete(
|
|
2672
|
+
async function prefetchJWKS(ctx, cacheKey, $api) {
|
|
2673
|
+
const fetchPromise = fetchJWKS(ctx, cacheKey, $api);
|
|
2674
|
+
inflightRequests.set(cacheKey, fetchPromise);
|
|
2675
|
+
fetchPromise.finally(() => inflightRequests.delete(cacheKey));
|
|
2674
2676
|
return fetchPromise;
|
|
2675
2677
|
}
|
|
2676
|
-
async function getJWKs(ctx,
|
|
2677
|
-
const cached = jwksCache.get(
|
|
2678
|
+
async function getJWKs(ctx, cacheKey, $api) {
|
|
2679
|
+
const cached = jwksCache.get(cacheKey);
|
|
2678
2680
|
if (cached && Date.now() < cached.expiresAt) return createLocalJWKSet(cached.data);
|
|
2679
2681
|
if (cached) {
|
|
2680
|
-
if (!inflightRequests.has(
|
|
2682
|
+
if (!inflightRequests.has(cacheKey)) prefetchJWKS(ctx, cacheKey, $api);
|
|
2681
2683
|
return createLocalJWKSet(cached.data);
|
|
2682
2684
|
}
|
|
2683
|
-
return inflightRequests.get(
|
|
2685
|
+
return inflightRequests.get(cacheKey) ?? prefetchJWKS(ctx, cacheKey, $api);
|
|
2684
2686
|
}
|
|
2685
2687
|
/**
|
|
2686
2688
|
* Check if JWT is recently issued and can skip JTI verification.
|
|
@@ -2692,86 +2694,92 @@ function isRecentlyIssued(payload) {
|
|
|
2692
2694
|
const issuedAt = payload.iat * 1e3;
|
|
2693
2695
|
return Date.now() - issuedAt < JTI_CHECK_GRACE_PERIOD_SECONDS * 1e3;
|
|
2694
2696
|
}
|
|
2695
|
-
const jwtMiddleware = (options, schema, getJWT) =>
|
|
2696
|
-
const
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
ctx.context.logger.warn("[Dash] JWT verification failed:", e);
|
|
2703
|
-
throw ctx.error("UNAUTHORIZED", { message: "Invalid API key" });
|
|
2704
|
-
});
|
|
2705
|
-
if (!isRecentlyIssued(payload)) {
|
|
2706
|
-
const { error, data } = await betterFetch("/api/auth/check-jti", {
|
|
2707
|
-
baseURL: options.apiUrl,
|
|
2708
|
-
method: "POST",
|
|
2709
|
-
headers: { "x-api-key": options.apiKey },
|
|
2710
|
-
body: {
|
|
2711
|
-
jti: payload.jti,
|
|
2712
|
-
expiresAt: payload.exp
|
|
2713
|
-
}
|
|
2714
|
-
});
|
|
2715
|
-
if (error || !data?.valid) {
|
|
2716
|
-
ctx.context.logger.warn("[Dash] JTI check failed with error", error, data?.valid);
|
|
2697
|
+
const jwtMiddleware = (options, schema, getJWT) => {
|
|
2698
|
+
const { $api } = options;
|
|
2699
|
+
const cacheKey = options.apiUrl;
|
|
2700
|
+
return createAuthMiddleware(async (ctx) => {
|
|
2701
|
+
const jwsFromHeader = getJWT ? await getJWT(ctx) : ctx.headers?.get("Authorization")?.split(" ")[1];
|
|
2702
|
+
if (!jwsFromHeader) {
|
|
2703
|
+
ctx.context.logger.warn("[Dash] JWT is missing from header");
|
|
2717
2704
|
throw ctx.error("UNAUTHORIZED", { message: "Invalid API key" });
|
|
2718
2705
|
}
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
ctx.context.logger.warn("[Dash] API key hash is missing or invalid", {
|
|
2723
|
-
apiKeyHash,
|
|
2724
|
-
apiKey: options.apiKey ? "present" : "missing"
|
|
2706
|
+
const { payload } = await jwtVerify(jwsFromHeader, await getJWKs(ctx, cacheKey, $api), { maxTokenAge: "5m" }).catch((e) => {
|
|
2707
|
+
ctx.context.logger.warn("[Dash] JWT verification failed:", e);
|
|
2708
|
+
throw ctx.error("UNAUTHORIZED", { message: "Invalid API key" });
|
|
2725
2709
|
});
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
}
|
|
2733
|
-
if (schema) {
|
|
2734
|
-
const parsed = schema.safeParse(payload);
|
|
2735
|
-
if (!parsed.success) {
|
|
2736
|
-
ctx.context.logger.warn("[Dash] JWT payload is invalid", parsed.error);
|
|
2710
|
+
const apiKeyHash = payload.apiKeyHash;
|
|
2711
|
+
if (typeof apiKeyHash !== "string" || !options.apiKey) {
|
|
2712
|
+
ctx.context.logger.warn("[Dash] API key hash is missing or invalid", {
|
|
2713
|
+
apiKeyHash,
|
|
2714
|
+
apiKey: options.apiKey ? "present" : "missing"
|
|
2715
|
+
});
|
|
2737
2716
|
throw ctx.error("UNAUTHORIZED", { message: "Invalid API key" });
|
|
2738
2717
|
}
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
});
|
|
2718
|
+
const expectedHash = await hash(options.apiKey);
|
|
2719
|
+
if (apiKeyHash !== expectedHash) {
|
|
2720
|
+
ctx.context.logger.warn("[Dash] API key hash is invalid", apiKeyHash, expectedHash);
|
|
2721
|
+
throw ctx.error("UNAUTHORIZED", { message: "Invalid API key" });
|
|
2722
|
+
}
|
|
2723
|
+
if (!isRecentlyIssued(payload)) {
|
|
2724
|
+
const { error, data } = await $api("/api/auth/check-jti", {
|
|
2725
|
+
method: "POST",
|
|
2726
|
+
body: {
|
|
2727
|
+
jti: payload.jti,
|
|
2728
|
+
expiresAt: payload.exp
|
|
2729
|
+
}
|
|
2730
|
+
});
|
|
2731
|
+
if (error || !data?.valid) {
|
|
2732
|
+
ctx.context.logger.warn("[Dash] JTI check failed with error", error, data?.valid);
|
|
2733
|
+
throw ctx.error("UNAUTHORIZED", { message: "Invalid API key" });
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2736
|
+
if (schema) {
|
|
2737
|
+
const parsed = schema.safeParse(payload);
|
|
2738
|
+
if (!parsed.success) {
|
|
2739
|
+
ctx.context.logger.warn("[Dash] JWT payload is invalid", parsed.error);
|
|
2740
|
+
throw ctx.error("UNAUTHORIZED", { message: "Invalid API key" });
|
|
2741
|
+
}
|
|
2742
|
+
return { payload: parsed.data };
|
|
2743
|
+
}
|
|
2744
|
+
return { payload };
|
|
2745
|
+
});
|
|
2746
|
+
};
|
|
2743
2747
|
/**
|
|
2744
2748
|
* Lightweight JWT middleware for /dash/validate. Verifies JWT signature and
|
|
2745
2749
|
* apiKeyHash only—no JTI check. Used during onboarding when the org doesn't
|
|
2746
2750
|
* exist yet.
|
|
2747
2751
|
*/
|
|
2748
|
-
const jwtValidateMiddleware = (options) =>
|
|
2749
|
-
const
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
ctx.context.logger.warn("[Dash] API key hash is missing or invalid", {
|
|
2761
|
-
apiKeyHash: typeof apiKeyHash,
|
|
2762
|
-
apiKey: options.apiKey ? "present" : "missing"
|
|
2752
|
+
const jwtValidateMiddleware = (options) => {
|
|
2753
|
+
const { $api } = options;
|
|
2754
|
+
const cacheKey = options.apiUrl;
|
|
2755
|
+
return createAuthMiddleware(async (ctx) => {
|
|
2756
|
+
const jwsFromHeader = ctx.headers?.get("Authorization")?.split(" ")[1];
|
|
2757
|
+
if (!jwsFromHeader) {
|
|
2758
|
+
ctx.context.logger.warn("[Dash] JWT is missing from header");
|
|
2759
|
+
throw ctx.error("UNAUTHORIZED", { message: "Invalid API key" });
|
|
2760
|
+
}
|
|
2761
|
+
const { payload } = await jwtVerify(jwsFromHeader, await getJWKs(ctx, cacheKey, $api), { maxTokenAge: "5m" }).catch((e) => {
|
|
2762
|
+
ctx.context.logger.error("[Dash] JWT verification failed:", e);
|
|
2763
|
+
throw ctx.error("UNAUTHORIZED", { message: "Invalid API key" });
|
|
2763
2764
|
});
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
}
|
|
2765
|
+
const apiKeyHash = payload.apiKeyHash;
|
|
2766
|
+
if (typeof apiKeyHash !== "string" || !options.apiKey) {
|
|
2767
|
+
ctx.context.logger.warn("[Dash] API key hash is missing or invalid", {
|
|
2768
|
+
apiKeyHash: typeof apiKeyHash,
|
|
2769
|
+
apiKey: options.apiKey ? "present" : "missing"
|
|
2770
|
+
});
|
|
2771
|
+
throw ctx.error("UNAUTHORIZED", { message: "Invalid API key" });
|
|
2772
|
+
}
|
|
2773
|
+
if (apiKeyHash !== await hash(options.apiKey)) {
|
|
2774
|
+
ctx.context.logger.warn("[Dash] API key hash mismatch");
|
|
2775
|
+
throw ctx.error("UNAUTHORIZED", { message: "Invalid API key" });
|
|
2776
|
+
}
|
|
2777
|
+
return { payload };
|
|
2778
|
+
});
|
|
2779
|
+
};
|
|
2772
2780
|
//#endregion
|
|
2773
2781
|
//#region src/version.ts
|
|
2774
|
-
const PLUGIN_VERSION = "0.2.
|
|
2782
|
+
const PLUGIN_VERSION = "0.2.7";
|
|
2775
2783
|
//#endregion
|
|
2776
2784
|
//#region src/routes/auth/config.ts
|
|
2777
2785
|
const PLUGIN_OPTIONS_EXCLUDE_KEYS = { stripe: new Set(["stripeClient"]) };
|
|
@@ -3257,10 +3265,7 @@ function transformEvent(raw) {
|
|
|
3257
3265
|
* ```
|
|
3258
3266
|
*/
|
|
3259
3267
|
const getUserEvents = (options) => {
|
|
3260
|
-
const $
|
|
3261
|
-
baseURL: options.apiUrl,
|
|
3262
|
-
headers: { "x-api-key": options.apiKey }
|
|
3263
|
-
});
|
|
3268
|
+
const { $api } = options;
|
|
3264
3269
|
return createAuthEndpoint("/events/list", {
|
|
3265
3270
|
method: "GET",
|
|
3266
3271
|
use: [sessionMiddleware],
|
|
@@ -3279,7 +3284,7 @@ const getUserEvents = (options) => {
|
|
|
3279
3284
|
const requestedLimit = ctx.query?.limit ?? 50;
|
|
3280
3285
|
const limit = Math.min(Math.max(1, requestedLimit), 100);
|
|
3281
3286
|
const offset = Math.max(0, ctx.query?.offset ?? 0);
|
|
3282
|
-
const { data, error } = await $
|
|
3287
|
+
const { data, error } = await $api("/events/user", {
|
|
3283
3288
|
method: "GET",
|
|
3284
3289
|
query: {
|
|
3285
3290
|
userId: session.user.id,
|
|
@@ -3329,10 +3334,7 @@ const getEventTypes = (options) => {
|
|
|
3329
3334
|
* results to the resolved user/identifier.
|
|
3330
3335
|
*/
|
|
3331
3336
|
const getAuditLogs = (options) => {
|
|
3332
|
-
const $
|
|
3333
|
-
baseURL: options.apiUrl,
|
|
3334
|
-
headers: { "x-api-key": options.apiKey }
|
|
3335
|
-
});
|
|
3337
|
+
const { $api } = options;
|
|
3336
3338
|
return createAuthEndpoint("/events/audit-logs", {
|
|
3337
3339
|
method: "GET",
|
|
3338
3340
|
use: [sessionMiddleware],
|
|
@@ -3364,7 +3366,7 @@ const getAuditLogs = (options) => {
|
|
|
3364
3366
|
if (!(sessionData.session?.activeOrganizationId === organizationId) && (!Array.isArray(sessionOrganizations) || !sessionOrganizations.some((org) => {
|
|
3365
3367
|
return org.id === organizationId;
|
|
3366
3368
|
}))) throw ctx.error("FORBIDDEN", { message: "Not allowed to access this organization" });
|
|
3367
|
-
const { data, error } = await $
|
|
3369
|
+
const { data, error } = await $api("/events/organization", {
|
|
3368
3370
|
method: "GET",
|
|
3369
3371
|
query: {
|
|
3370
3372
|
organizationId,
|
|
@@ -3381,7 +3383,7 @@ const getAuditLogs = (options) => {
|
|
|
3381
3383
|
responseLimit = data.limit;
|
|
3382
3384
|
responseOffset = data.offset;
|
|
3383
3385
|
} else {
|
|
3384
|
-
const { data, error } = await $
|
|
3386
|
+
const { data, error } = await $api("/events/user", {
|
|
3385
3387
|
method: "GET",
|
|
3386
3388
|
query: {
|
|
3387
3389
|
userId: resolvedUserId,
|
|
@@ -3428,10 +3430,7 @@ function isOwnerOrAdminRole(role) {
|
|
|
3428
3430
|
* @returns
|
|
3429
3431
|
*/
|
|
3430
3432
|
const getAllAuditLogs = (options) => {
|
|
3431
|
-
const $
|
|
3432
|
-
baseURL: options.apiUrl,
|
|
3433
|
-
headers: { "x-api-key": options.apiKey }
|
|
3434
|
-
});
|
|
3433
|
+
const { $api } = options;
|
|
3435
3434
|
const getUserOrganizationRole = async (adapter, orgId, userId) => {
|
|
3436
3435
|
return (await adapter.findOne({
|
|
3437
3436
|
model: "member",
|
|
@@ -3508,7 +3507,7 @@ const getAllAuditLogs = (options) => {
|
|
|
3508
3507
|
const identifierFilter = query.identifier?.trim();
|
|
3509
3508
|
if (eventTypeFilter) apiQuery.eventType = eventTypeFilter;
|
|
3510
3509
|
if (identifierFilter) apiQuery.identifier = identifierFilter;
|
|
3511
|
-
const { data, error } = await $
|
|
3510
|
+
const { data, error } = await $api("/events/activity", {
|
|
3512
3511
|
method: "GET",
|
|
3513
3512
|
query: apiQuery
|
|
3514
3513
|
});
|
|
@@ -3628,10 +3627,7 @@ const executeAdapter = (options) => {
|
|
|
3628
3627
|
* It creates the user in the auth database and sets up a session.
|
|
3629
3628
|
*/
|
|
3630
3629
|
const acceptInvitation = (options) => {
|
|
3631
|
-
const $api =
|
|
3632
|
-
baseURL: options.apiUrl || INFRA_API_URL,
|
|
3633
|
-
headers: { "x-api-key": options.apiKey }
|
|
3634
|
-
});
|
|
3630
|
+
const { $api } = options;
|
|
3635
3631
|
return createAuthEndpoint("/dash/accept-invitation", {
|
|
3636
3632
|
method: "GET",
|
|
3637
3633
|
query: z$1.object({ token: z$1.string() })
|
|
@@ -3711,10 +3707,7 @@ const acceptInvitation = (options) => {
|
|
|
3711
3707
|
* This creates the user in the auth database and sets up a session
|
|
3712
3708
|
*/
|
|
3713
3709
|
const completeInvitation = (options) => {
|
|
3714
|
-
const $api =
|
|
3715
|
-
baseURL: options.apiUrl || INFRA_API_URL,
|
|
3716
|
-
headers: { "x-api-key": options.apiKey }
|
|
3717
|
-
});
|
|
3710
|
+
const { $api } = options;
|
|
3718
3711
|
return createAuthEndpoint("/dash/complete-invitation", {
|
|
3719
3712
|
method: "POST",
|
|
3720
3713
|
body: z$1.object({
|
|
@@ -7541,6 +7534,11 @@ function createSMSSender(config) {
|
|
|
7541
7534
|
const apiUrl = baseUrl.endsWith("/api") ? baseUrl : `${baseUrl}/api`;
|
|
7542
7535
|
const apiKey = config?.apiKey || env.BETTER_AUTH_API_KEY || "";
|
|
7543
7536
|
if (!apiKey) logger.warn("[Dash] No API key provided for SMS sending. Set BETTER_AUTH_API_KEY environment variable or pass apiKey in config.");
|
|
7537
|
+
const $api = createFetch({
|
|
7538
|
+
baseURL: apiUrl,
|
|
7539
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
7540
|
+
timeout: config?.apiTimeout ?? 3e3
|
|
7541
|
+
});
|
|
7544
7542
|
/**
|
|
7545
7543
|
* Send an SMS with OTP code
|
|
7546
7544
|
*/
|
|
@@ -7550,25 +7548,25 @@ function createSMSSender(config) {
|
|
|
7550
7548
|
error: "API key not configured"
|
|
7551
7549
|
};
|
|
7552
7550
|
try {
|
|
7553
|
-
const
|
|
7551
|
+
const { data, error } = await $api("/v1/sms/send", {
|
|
7554
7552
|
method: "POST",
|
|
7555
|
-
|
|
7556
|
-
"Content-Type": "application/json",
|
|
7557
|
-
Authorization: `Bearer ${apiKey}`
|
|
7558
|
-
},
|
|
7559
|
-
body: JSON.stringify({
|
|
7553
|
+
body: {
|
|
7560
7554
|
to: options.to,
|
|
7561
7555
|
code: options.code,
|
|
7562
7556
|
template: options.template
|
|
7563
|
-
}
|
|
7557
|
+
}
|
|
7564
7558
|
});
|
|
7565
|
-
if (
|
|
7559
|
+
if (error) return {
|
|
7566
7560
|
success: false,
|
|
7567
|
-
error:
|
|
7561
|
+
error: error.message || `HTTP ${error.status}`
|
|
7562
|
+
};
|
|
7563
|
+
if (typeof data !== "object" || data === null || Array.isArray(data)) return {
|
|
7564
|
+
success: false,
|
|
7565
|
+
error: "Failed to parse JSON"
|
|
7568
7566
|
};
|
|
7569
7567
|
return {
|
|
7570
7568
|
success: true,
|
|
7571
|
-
messageId:
|
|
7569
|
+
messageId: data.messageId
|
|
7572
7570
|
};
|
|
7573
7571
|
} catch (error) {
|
|
7574
7572
|
logger.warn("[Dash] SMS send failed:", error);
|
|
@@ -7616,8 +7614,14 @@ async function sendSMS(options, config) {
|
|
|
7616
7614
|
const dash = (options) => {
|
|
7617
7615
|
const processedBulkOperationContexts = /* @__PURE__ */ new WeakSet();
|
|
7618
7616
|
const opts = resolveDashOptions(options);
|
|
7617
|
+
const $api = createAPI(opts);
|
|
7618
|
+
const settings = {
|
|
7619
|
+
...opts,
|
|
7620
|
+
$api
|
|
7621
|
+
};
|
|
7622
|
+
const $kv = createKV(opts);
|
|
7619
7623
|
const activityUpdateInterval = opts.activityTracking?.updateInterval ?? 3e5;
|
|
7620
|
-
const { tracker } = initTrackEvents(
|
|
7624
|
+
const { tracker } = initTrackEvents($api);
|
|
7621
7625
|
const { trackUserSignedUp, trackUserProfileUpdated, trackUserProfileImageUpdated, trackUserEmailVerified, trackUserBanned, trackUserUnBanned, trackUserDeleted } = initUserEvents(tracker);
|
|
7622
7626
|
const { trackEmailVerificationSent, trackEmailSignInAttempt, trackUserSignedIn, trackUserSignedOut, trackSessionCreated, trackSocialSignInAttempt, trackSocialSignInRedirectionAttempt, trackUserImpersonated, trackUserImpersonationStop, trackSessionRevoked, trackSessionRevokedAll } = initSessionEvents(tracker);
|
|
7623
7627
|
const { trackAccountLinking, trackAccountUnlink, trackAccountPasswordChange } = initAccountEvents(tracker);
|
|
@@ -7899,7 +7903,7 @@ const dash = (options) => {
|
|
|
7899
7903
|
const path = new URL(ctx.request.url).pathname;
|
|
7900
7904
|
return matchesAnyRoute(path, [routes.SIGN_IN_SOCIAL_CALLBACK, routes.SIGN_IN_OAUTH_CALLBACK]);
|
|
7901
7905
|
},
|
|
7902
|
-
handler: createIdentificationMiddleware(
|
|
7906
|
+
handler: createIdentificationMiddleware($kv)
|
|
7903
7907
|
}],
|
|
7904
7908
|
after: [{
|
|
7905
7909
|
matcher: (ctx) => {
|
|
@@ -7914,7 +7918,7 @@ const dash = (options) => {
|
|
|
7914
7918
|
const body = ctx.body;
|
|
7915
7919
|
if (matchesAnyRoute(ctx.path, [routes.SIGN_IN_EMAIL, routes.SIGN_IN_EMAIL_OTP]) && ctx.context.returned instanceof Error && body?.email) trackEmailSignInAttempt(ctx, trigger);
|
|
7916
7920
|
if (matchesAnyRoute(ctx.path, [routes.SIGN_IN_SOCIAL]) && ctx.context.returned instanceof Error && ctx.body.provider && ctx.body.idToken) trackSocialSignInAttempt(ctx, trigger);
|
|
7917
|
-
if (matchesAnyRoute(ctx.path, [routes.SIGN_IN_SOCIAL_CALLBACK]) && ctx.context.returned instanceof Error) trackSocialSignInRedirectionAttempt(ctx, trigger);
|
|
7921
|
+
if (matchesAnyRoute(ctx.path, [routes.SIGN_IN_SOCIAL_CALLBACK]) && ctx.request?.method === "GET" && ctx.context.returned instanceof Error && !ctx.context.newSession) trackSocialSignInRedirectionAttempt(ctx, trigger);
|
|
7918
7922
|
const headerRequestId = ctx.request?.headers.get("X-Request-Id");
|
|
7919
7923
|
if (headerRequestId) ctx.setCookie(IDENTIFICATION_COOKIE_NAME, headerRequestId, {
|
|
7920
7924
|
maxAge: 600,
|
|
@@ -7952,79 +7956,79 @@ const dash = (options) => {
|
|
|
7952
7956
|
}]
|
|
7953
7957
|
},
|
|
7954
7958
|
endpoints: {
|
|
7955
|
-
getDashConfig: getConfig(
|
|
7956
|
-
getDashValidate: getValidate(
|
|
7957
|
-
getDashUsers: getUsers(
|
|
7958
|
-
exportDashUsers: exportUsers(
|
|
7959
|
-
createDashUser: createUser(
|
|
7960
|
-
deleteDashUser: deleteUser(
|
|
7961
|
-
deleteManyDashUsers: deleteManyUsers(
|
|
7962
|
-
listDashOrganizations: listOrganizations(
|
|
7963
|
-
exportDashOrganizations: exportOrganizations(
|
|
7964
|
-
getDashOrganization: getOrganization(
|
|
7965
|
-
listDashOrganizationMembers: listOrganizationMembers(
|
|
7966
|
-
listDashOrganizationInvitations: listOrganizationInvitations(
|
|
7967
|
-
listDashOrganizationTeams: listOrganizationTeams(
|
|
7968
|
-
listDashOrganizationSsoProviders: listOrganizationSsoProviders(
|
|
7969
|
-
createDashSsoProvider: createSsoProvider(
|
|
7970
|
-
updateDashSsoProvider: updateSsoProvider(
|
|
7971
|
-
requestDashSsoVerificationToken: requestSsoVerificationToken(
|
|
7972
|
-
verifyDashSsoProviderDomain: verifySsoProviderDomain(
|
|
7973
|
-
deleteDashSsoProvider: deleteSsoProvider(
|
|
7974
|
-
markDashSsoProviderDomainVerified: markSsoProviderDomainVerified(
|
|
7975
|
-
listDashTeamMembers: listTeamMembers(
|
|
7976
|
-
createDashOrganization: createOrganization(
|
|
7977
|
-
deleteDashOrganization: deleteOrganization(
|
|
7978
|
-
deleteManyDashOrganizations: deleteManyOrganizations(
|
|
7979
|
-
getDashOrganizationOptions: getOrganizationOptions(
|
|
7980
|
-
getDashUser: getUserDetails(
|
|
7981
|
-
getDashUserOrganizations: getUserOrganizations(
|
|
7982
|
-
updateDashUser: updateUser(
|
|
7983
|
-
setDashPassword: setPassword(
|
|
7984
|
-
unlinkDashAccount: unlinkAccount(
|
|
7985
|
-
dashRevokeSession: revokeSession(
|
|
7986
|
-
dashRevokeAllSessions: revokeAllSessions(
|
|
7987
|
-
dashRevokeManySessions: revokeManySessions(
|
|
7988
|
-
dashImpersonateUser: impersonateUser(
|
|
7989
|
-
updateDashOrganization: updateOrganization(
|
|
7990
|
-
createDashTeam: createTeam(
|
|
7991
|
-
updateDashTeam: updateTeam(
|
|
7992
|
-
deleteDashTeam: deleteTeam(
|
|
7993
|
-
addDashTeamMember: addTeamMember(
|
|
7994
|
-
removeDashTeamMember: removeTeamMember(
|
|
7995
|
-
addDashMember: addMember(
|
|
7996
|
-
removeDashMember: removeMember(
|
|
7997
|
-
updateDashMemberRole: updateMemberRole(
|
|
7998
|
-
inviteDashMember: inviteMember(
|
|
7999
|
-
cancelDashInvitation: cancelInvitation(
|
|
8000
|
-
resendDashInvitation: resendInvitation(
|
|
8001
|
-
dashCheckUserByEmail: checkUserByEmail(
|
|
8002
|
-
dashGetUserStats: getUserStats(
|
|
8003
|
-
dashGetUserGraphData: getUserGraphData(
|
|
8004
|
-
dashGetUserRetentionData: getUserRetentionData(
|
|
8005
|
-
dashBanUser: banUser(
|
|
8006
|
-
dashBanManyUsers: banManyUsers(
|
|
8007
|
-
dashUnbanUser: unbanUser(
|
|
8008
|
-
dashSendVerificationEmail: sendVerificationEmail(
|
|
8009
|
-
dashSendManyVerificationEmails: sendManyVerificationEmails(
|
|
8010
|
-
dashSendResetPasswordEmail: sendResetPasswordEmail(
|
|
8011
|
-
dashEnableTwoFactor: enableTwoFactor(
|
|
8012
|
-
dashViewTwoFactorTotpUri: viewTwoFactorTotpUri(
|
|
8013
|
-
dashViewBackupCodes: viewBackupCodes(
|
|
8014
|
-
dashDisableTwoFactor: disableTwoFactor(
|
|
8015
|
-
dashGenerateBackupCodes: generateBackupCodes(
|
|
8016
|
-
getUserEvents: getUserEvents(
|
|
8017
|
-
getAuditLogs: getAuditLogs(
|
|
8018
|
-
getAllAuditLogs: getAllAuditLogs(
|
|
8019
|
-
getEventTypes: getEventTypes(
|
|
8020
|
-
dashAcceptInvitation: acceptInvitation(
|
|
8021
|
-
dashCompleteInvitation: completeInvitation(
|
|
8022
|
-
dashCheckUserExists: checkUserExists(
|
|
8023
|
-
listDashOrganizationDirectories: listOrganizationDirectories(
|
|
8024
|
-
createDashOrganizationDirectory: createOrganizationDirectory(
|
|
8025
|
-
deleteDashOrganizationDirectory: deleteOrganizationDirectory(
|
|
8026
|
-
regenerateDashDirectoryToken: regenerateDirectoryToken(
|
|
8027
|
-
dashExecuteAdapter: executeAdapter(
|
|
7959
|
+
getDashConfig: getConfig(settings),
|
|
7960
|
+
getDashValidate: getValidate(settings),
|
|
7961
|
+
getDashUsers: getUsers(settings),
|
|
7962
|
+
exportDashUsers: exportUsers(settings),
|
|
7963
|
+
createDashUser: createUser(settings),
|
|
7964
|
+
deleteDashUser: deleteUser(settings),
|
|
7965
|
+
deleteManyDashUsers: deleteManyUsers(settings),
|
|
7966
|
+
listDashOrganizations: listOrganizations(settings),
|
|
7967
|
+
exportDashOrganizations: exportOrganizations(settings),
|
|
7968
|
+
getDashOrganization: getOrganization(settings),
|
|
7969
|
+
listDashOrganizationMembers: listOrganizationMembers(settings),
|
|
7970
|
+
listDashOrganizationInvitations: listOrganizationInvitations(settings),
|
|
7971
|
+
listDashOrganizationTeams: listOrganizationTeams(settings),
|
|
7972
|
+
listDashOrganizationSsoProviders: listOrganizationSsoProviders(settings),
|
|
7973
|
+
createDashSsoProvider: createSsoProvider(settings),
|
|
7974
|
+
updateDashSsoProvider: updateSsoProvider(settings),
|
|
7975
|
+
requestDashSsoVerificationToken: requestSsoVerificationToken(settings),
|
|
7976
|
+
verifyDashSsoProviderDomain: verifySsoProviderDomain(settings),
|
|
7977
|
+
deleteDashSsoProvider: deleteSsoProvider(settings),
|
|
7978
|
+
markDashSsoProviderDomainVerified: markSsoProviderDomainVerified(settings),
|
|
7979
|
+
listDashTeamMembers: listTeamMembers(settings),
|
|
7980
|
+
createDashOrganization: createOrganization(settings),
|
|
7981
|
+
deleteDashOrganization: deleteOrganization(settings),
|
|
7982
|
+
deleteManyDashOrganizations: deleteManyOrganizations(settings),
|
|
7983
|
+
getDashOrganizationOptions: getOrganizationOptions(settings),
|
|
7984
|
+
getDashUser: getUserDetails(settings),
|
|
7985
|
+
getDashUserOrganizations: getUserOrganizations(settings),
|
|
7986
|
+
updateDashUser: updateUser(settings),
|
|
7987
|
+
setDashPassword: setPassword(settings),
|
|
7988
|
+
unlinkDashAccount: unlinkAccount(settings),
|
|
7989
|
+
dashRevokeSession: revokeSession(settings),
|
|
7990
|
+
dashRevokeAllSessions: revokeAllSessions(settings),
|
|
7991
|
+
dashRevokeManySessions: revokeManySessions(settings),
|
|
7992
|
+
dashImpersonateUser: impersonateUser(settings),
|
|
7993
|
+
updateDashOrganization: updateOrganization(settings),
|
|
7994
|
+
createDashTeam: createTeam(settings),
|
|
7995
|
+
updateDashTeam: updateTeam(settings),
|
|
7996
|
+
deleteDashTeam: deleteTeam(settings),
|
|
7997
|
+
addDashTeamMember: addTeamMember(settings),
|
|
7998
|
+
removeDashTeamMember: removeTeamMember(settings),
|
|
7999
|
+
addDashMember: addMember(settings),
|
|
8000
|
+
removeDashMember: removeMember(settings),
|
|
8001
|
+
updateDashMemberRole: updateMemberRole(settings),
|
|
8002
|
+
inviteDashMember: inviteMember(settings),
|
|
8003
|
+
cancelDashInvitation: cancelInvitation(settings),
|
|
8004
|
+
resendDashInvitation: resendInvitation(settings),
|
|
8005
|
+
dashCheckUserByEmail: checkUserByEmail(settings),
|
|
8006
|
+
dashGetUserStats: getUserStats(settings),
|
|
8007
|
+
dashGetUserGraphData: getUserGraphData(settings),
|
|
8008
|
+
dashGetUserRetentionData: getUserRetentionData(settings),
|
|
8009
|
+
dashBanUser: banUser(settings),
|
|
8010
|
+
dashBanManyUsers: banManyUsers(settings),
|
|
8011
|
+
dashUnbanUser: unbanUser(settings),
|
|
8012
|
+
dashSendVerificationEmail: sendVerificationEmail(settings),
|
|
8013
|
+
dashSendManyVerificationEmails: sendManyVerificationEmails(settings),
|
|
8014
|
+
dashSendResetPasswordEmail: sendResetPasswordEmail(settings),
|
|
8015
|
+
dashEnableTwoFactor: enableTwoFactor(settings),
|
|
8016
|
+
dashViewTwoFactorTotpUri: viewTwoFactorTotpUri(settings),
|
|
8017
|
+
dashViewBackupCodes: viewBackupCodes(settings),
|
|
8018
|
+
dashDisableTwoFactor: disableTwoFactor(settings),
|
|
8019
|
+
dashGenerateBackupCodes: generateBackupCodes(settings),
|
|
8020
|
+
getUserEvents: getUserEvents(settings),
|
|
8021
|
+
getAuditLogs: getAuditLogs(settings),
|
|
8022
|
+
getAllAuditLogs: getAllAuditLogs(settings),
|
|
8023
|
+
getEventTypes: getEventTypes(settings),
|
|
8024
|
+
dashAcceptInvitation: acceptInvitation(settings),
|
|
8025
|
+
dashCompleteInvitation: completeInvitation(settings),
|
|
8026
|
+
dashCheckUserExists: checkUserExists(settings),
|
|
8027
|
+
listDashOrganizationDirectories: listOrganizationDirectories(settings),
|
|
8028
|
+
createDashOrganizationDirectory: createOrganizationDirectory(settings),
|
|
8029
|
+
deleteDashOrganizationDirectory: deleteOrganizationDirectory(settings),
|
|
8030
|
+
regenerateDashDirectoryToken: regenerateDirectoryToken(settings),
|
|
8031
|
+
dashExecuteAdapter: executeAdapter(settings)
|
|
8028
8032
|
},
|
|
8029
8033
|
schema: opts.activityTracking?.enabled ? { user: { fields: { lastActiveAt: {
|
|
8030
8034
|
type: "date",
|