@absolutejs/auth 0.57.8 → 0.58.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.
- package/README.md +33 -0
- package/dist/agents/index.d.ts +1 -1
- package/dist/agents/index.js +66 -35
- package/dist/agents/index.js.map +3 -3
- package/dist/agents/postgresStores.d.ts +586 -1
- package/dist/cli/migrate.js +46 -14
- package/dist/cli/migrate.js.map +5 -5
- package/dist/index.d.ts +11 -5
- package/dist/index.js +286 -58
- package/dist/index.js.map +14 -13
- package/dist/manifest.js +8 -1
- package/dist/manifest.js.map +3 -3
- package/dist/manifest.json +9 -0
- package/dist/mfa/challenge.d.ts +4 -2
- package/dist/mfa/config.d.ts +6 -0
- package/dist/mfa/postgresMfaStore.d.ts +45 -0
- package/dist/mfa/routes.d.ts +9 -4
- package/dist/mfa/sms.d.ts +38 -5
- package/dist/mfa/types.d.ts +4 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +280 -59
- package/dist/server.js.map +15 -14
- package/dist/types.d.ts +5 -1
- package/dist/verification/types.d.ts +47 -0
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -6849,6 +6849,7 @@ var DEFAULT_SMS_CODE_LENGTH = 6;
|
|
|
6849
6849
|
var SMS_CODE_TTL_MINUTES = 5;
|
|
6850
6850
|
var DEFAULT_SMS_CODE_TTL_MS = SMS_CODE_TTL_MINUTES * SECONDS_IN_A_MINUTE * MILLISECONDS_IN_A_SECOND;
|
|
6851
6851
|
var DEFAULT_SMS_MAX_ATTEMPTS = 3;
|
|
6852
|
+
var DEFAULT_SMS_RESEND_COOLDOWN_MS = 30 * MILLISECONDS_IN_A_SECOND;
|
|
6852
6853
|
var DEFAULT_TOTP_MAX_ATTEMPTS = 5;
|
|
6853
6854
|
|
|
6854
6855
|
// src/mfa/secret.ts
|
|
@@ -6859,6 +6860,20 @@ var encryptTotpSecret = (secret, encryptionKey) => encryptionKey ? encryptSecret
|
|
|
6859
6860
|
// src/mfa/sms.ts
|
|
6860
6861
|
init_crypto();
|
|
6861
6862
|
import { Elysia as Elysia17, t as t11 } from "elysia";
|
|
6863
|
+
|
|
6864
|
+
// src/verification/types.ts
|
|
6865
|
+
class VerificationProviderError extends Error {
|
|
6866
|
+
kind;
|
|
6867
|
+
provider;
|
|
6868
|
+
constructor(input) {
|
|
6869
|
+
super(input.message, { cause: input.cause });
|
|
6870
|
+
this.name = "VerificationProviderError";
|
|
6871
|
+
this.kind = input.kind;
|
|
6872
|
+
this.provider = input.provider;
|
|
6873
|
+
}
|
|
6874
|
+
}
|
|
6875
|
+
|
|
6876
|
+
// src/mfa/sms.ts
|
|
6862
6877
|
var DECIMAL_RADIX2 = 10;
|
|
6863
6878
|
var MASK_VISIBLE_DIGITS = 4;
|
|
6864
6879
|
var E164_PATTERN = /^\+[1-9]\d{7,14}$/u;
|
|
@@ -6873,28 +6888,83 @@ var issueSmsCode = async (codeLength, ttlMs) => {
|
|
|
6873
6888
|
const expiresAt = Date.now() + ttlMs;
|
|
6874
6889
|
return { code, expiresAt, hash };
|
|
6875
6890
|
};
|
|
6891
|
+
var checkWithVerificationProvider = async (provider, input) => {
|
|
6892
|
+
try {
|
|
6893
|
+
return { result: await provider.check(input) };
|
|
6894
|
+
} catch (error) {
|
|
6895
|
+
const mapped = mapVerificationProviderError(error);
|
|
6896
|
+
if (mapped === undefined)
|
|
6897
|
+
throw error;
|
|
6898
|
+
return { error: mapped };
|
|
6899
|
+
}
|
|
6900
|
+
};
|
|
6876
6901
|
var isE164Phone = (phone) => E164_PATTERN.test(phone);
|
|
6877
6902
|
var issueAndStoreSmsCode = async ({
|
|
6878
6903
|
codeLength,
|
|
6879
6904
|
enrollment,
|
|
6880
6905
|
mfaStore,
|
|
6881
6906
|
onSendSmsCode,
|
|
6882
|
-
|
|
6907
|
+
purpose,
|
|
6908
|
+
verificationProvider,
|
|
6909
|
+
ttlMs,
|
|
6910
|
+
userId
|
|
6883
6911
|
}) => {
|
|
6884
6912
|
const phone = enrollment.smsPhone;
|
|
6885
6913
|
if (phone === undefined)
|
|
6886
6914
|
return;
|
|
6915
|
+
if (verificationProvider !== undefined) {
|
|
6916
|
+
const started = await verificationProvider.start({
|
|
6917
|
+
channel: "sms",
|
|
6918
|
+
purpose,
|
|
6919
|
+
subject: userId,
|
|
6920
|
+
to: phone
|
|
6921
|
+
});
|
|
6922
|
+
await mfaStore.saveEnrollment({
|
|
6923
|
+
...enrollment,
|
|
6924
|
+
smsCodeSentAt: Date.now(),
|
|
6925
|
+
smsFailedAttempts: 0,
|
|
6926
|
+
smsPendingCodeExpiresAt: started.expiresAt,
|
|
6927
|
+
smsPendingCodeHash: undefined,
|
|
6928
|
+
smsPendingPurpose: purpose,
|
|
6929
|
+
smsProviderReference: started.reference,
|
|
6930
|
+
updatedAt: Date.now()
|
|
6931
|
+
});
|
|
6932
|
+
return started.expiresAt;
|
|
6933
|
+
}
|
|
6887
6934
|
const { code, expiresAt, hash } = await issueSmsCode(codeLength, ttlMs);
|
|
6888
6935
|
await mfaStore.saveEnrollment({
|
|
6889
6936
|
...enrollment,
|
|
6937
|
+
smsCodeSentAt: Date.now(),
|
|
6890
6938
|
smsFailedAttempts: 0,
|
|
6891
6939
|
smsPendingCodeExpiresAt: expiresAt,
|
|
6892
6940
|
smsPendingCodeHash: hash,
|
|
6941
|
+
smsPendingPurpose: purpose,
|
|
6942
|
+
smsProviderReference: undefined,
|
|
6893
6943
|
updatedAt: Date.now()
|
|
6894
6944
|
});
|
|
6895
|
-
await onSendSmsCode?.({ code, expiresAt, phone });
|
|
6945
|
+
await onSendSmsCode?.({ code, expiresAt, phone, purpose, userId });
|
|
6896
6946
|
return expiresAt;
|
|
6897
6947
|
};
|
|
6948
|
+
var mapVerificationProviderError = (error) => {
|
|
6949
|
+
if (!(error instanceof VerificationProviderError))
|
|
6950
|
+
return;
|
|
6951
|
+
if (error.kind === "rate_limited") {
|
|
6952
|
+
return {
|
|
6953
|
+
message: "Verification provider rate limit reached",
|
|
6954
|
+
status: "Too Many Requests"
|
|
6955
|
+
};
|
|
6956
|
+
}
|
|
6957
|
+
if (error.kind === "invalid_destination") {
|
|
6958
|
+
return {
|
|
6959
|
+
message: "Phone number cannot receive verification codes",
|
|
6960
|
+
status: "Bad Request"
|
|
6961
|
+
};
|
|
6962
|
+
}
|
|
6963
|
+
return {
|
|
6964
|
+
message: "Verification provider unavailable",
|
|
6965
|
+
status: "Service Unavailable"
|
|
6966
|
+
};
|
|
6967
|
+
};
|
|
6898
6968
|
var maskPhone = (phone) => {
|
|
6899
6969
|
const visible = phone.slice(-MASK_VISIBLE_DIGITS);
|
|
6900
6970
|
const maskedLength = Math.max(phone.length - MASK_VISIBLE_DIGITS, 0);
|
|
@@ -6906,9 +6976,11 @@ var mfaSmsRoutes = ({
|
|
|
6906
6976
|
mfaStore,
|
|
6907
6977
|
onMfaEnrolled,
|
|
6908
6978
|
onSendSmsCode,
|
|
6979
|
+
verificationProvider,
|
|
6909
6980
|
smsCodeLength = DEFAULT_SMS_CODE_LENGTH,
|
|
6910
6981
|
smsCodeTtlMs = DEFAULT_SMS_CODE_TTL_MS,
|
|
6911
6982
|
smsMaxAttempts = DEFAULT_SMS_MAX_ATTEMPTS,
|
|
6983
|
+
smsResendCooldownMs = DEFAULT_SMS_RESEND_COOLDOWN_MS,
|
|
6912
6984
|
smsSetupRoute = "/auth/mfa/sms/setup",
|
|
6913
6985
|
smsVerifyRoute = "/auth/mfa/sms/verify"
|
|
6914
6986
|
}) => new Elysia17().use(sessionStore()).post(smsSetupRoute, async ({
|
|
@@ -6917,7 +6989,7 @@ var mfaSmsRoutes = ({
|
|
|
6917
6989
|
status,
|
|
6918
6990
|
store: { session }
|
|
6919
6991
|
}) => {
|
|
6920
|
-
if (onSendSmsCode === undefined) {
|
|
6992
|
+
if (onSendSmsCode === undefined && verificationProvider === undefined) {
|
|
6921
6993
|
return status("Not Implemented", "SMS MFA is not configured");
|
|
6922
6994
|
}
|
|
6923
6995
|
const userSession = await loadSessionFromSource({
|
|
@@ -6934,21 +7006,51 @@ var mfaSmsRoutes = ({
|
|
|
6934
7006
|
const userId = getUserId(userSession.user);
|
|
6935
7007
|
const existing = await mfaStore.getEnrollment(userId);
|
|
6936
7008
|
const now = Date.now();
|
|
6937
|
-
|
|
7009
|
+
if (existing?.smsCodeSentAt !== undefined && now - existing.smsCodeSentAt < smsResendCooldownMs) {
|
|
7010
|
+
return status("Too Many Requests", "SMS resend cooldown active");
|
|
7011
|
+
}
|
|
7012
|
+
let started;
|
|
7013
|
+
try {
|
|
7014
|
+
started = verificationProvider ? await verificationProvider.start({
|
|
7015
|
+
channel: "sms",
|
|
7016
|
+
purpose: "mfa_enrollment",
|
|
7017
|
+
subject: userId,
|
|
7018
|
+
to: phone
|
|
7019
|
+
}) : undefined;
|
|
7020
|
+
} catch (error) {
|
|
7021
|
+
const mapped = mapVerificationProviderError(error);
|
|
7022
|
+
if (mapped === undefined)
|
|
7023
|
+
throw error;
|
|
7024
|
+
return status(mapped.status, mapped.message);
|
|
7025
|
+
}
|
|
7026
|
+
const local = started ? undefined : await issueSmsCode(smsCodeLength, smsCodeTtlMs);
|
|
6938
7027
|
await mfaStore.saveEnrollment({
|
|
6939
7028
|
backupCodeHashes: existing?.backupCodeHashes ?? [],
|
|
6940
7029
|
createdAt: existing?.createdAt ?? now,
|
|
7030
|
+
lastUsedAt: existing?.lastUsedAt,
|
|
7031
|
+
smsCodeSentAt: now,
|
|
6941
7032
|
smsFailedAttempts: 0,
|
|
6942
|
-
smsPendingCodeExpiresAt: expiresAt,
|
|
6943
|
-
smsPendingCodeHash: hash,
|
|
7033
|
+
smsPendingCodeExpiresAt: started?.expiresAt ?? local?.expiresAt,
|
|
7034
|
+
smsPendingCodeHash: local?.hash,
|
|
7035
|
+
smsPendingPurpose: "mfa_enrollment",
|
|
6944
7036
|
smsPhone: phone,
|
|
7037
|
+
smsProviderReference: started?.reference,
|
|
6945
7038
|
smsVerified: false,
|
|
7039
|
+
totpFailedAttempts: existing?.totpFailedAttempts ?? 0,
|
|
6946
7040
|
totpSecretCiphertext: existing?.totpSecretCiphertext,
|
|
6947
7041
|
totpVerified: existing?.totpVerified ?? false,
|
|
6948
7042
|
updatedAt: now,
|
|
6949
7043
|
userId
|
|
6950
7044
|
});
|
|
6951
|
-
|
|
7045
|
+
if (local !== undefined && onSendSmsCode !== undefined) {
|
|
7046
|
+
await onSendSmsCode({
|
|
7047
|
+
code: local.code,
|
|
7048
|
+
expiresAt: local.expiresAt,
|
|
7049
|
+
phone,
|
|
7050
|
+
purpose: "mfa_enrollment",
|
|
7051
|
+
userId
|
|
7052
|
+
});
|
|
7053
|
+
}
|
|
6952
7054
|
return status("OK", { phone: maskPhone(phone) });
|
|
6953
7055
|
}, {
|
|
6954
7056
|
body: t11.Object({ phone: t11.String() }),
|
|
@@ -6969,29 +7071,58 @@ var mfaSmsRoutes = ({
|
|
|
6969
7071
|
}
|
|
6970
7072
|
const userId = getUserId(userSession.user);
|
|
6971
7073
|
const enrollment = await mfaStore.getEnrollment(userId);
|
|
6972
|
-
if (!enrollment?.
|
|
7074
|
+
if (!enrollment?.smsPhone) {
|
|
7075
|
+
return status("Bad Request", "No SMS enrollment in progress");
|
|
7076
|
+
}
|
|
7077
|
+
const localCodeHash = enrollment.smsPendingCodeHash;
|
|
7078
|
+
const localCodeExpiresAt = enrollment.smsPendingCodeExpiresAt;
|
|
7079
|
+
const providerReference = enrollment.smsProviderReference;
|
|
7080
|
+
if (enrollment.smsPendingPurpose !== "mfa_enrollment" || localCodeExpiresAt === undefined) {
|
|
7081
|
+
return status("Bad Request", "No SMS enrollment in progress");
|
|
7082
|
+
}
|
|
7083
|
+
if (verificationProvider === undefined && localCodeHash === undefined) {
|
|
6973
7084
|
return status("Bad Request", "No SMS enrollment in progress");
|
|
6974
7085
|
}
|
|
6975
|
-
if (Date.now() >
|
|
7086
|
+
if (Date.now() > localCodeExpiresAt) {
|
|
6976
7087
|
return status("Bad Request", "SMS code expired");
|
|
6977
7088
|
}
|
|
6978
7089
|
if ((enrollment.smsFailedAttempts ?? 0) >= smsMaxAttempts) {
|
|
6979
7090
|
return status("Too Many Requests", "Too many attempts");
|
|
6980
7091
|
}
|
|
6981
|
-
|
|
7092
|
+
let providerResult;
|
|
7093
|
+
if (verificationProvider !== undefined) {
|
|
7094
|
+
if (providerReference === undefined) {
|
|
7095
|
+
return status("Bad Request", "No SMS enrollment in progress");
|
|
7096
|
+
}
|
|
7097
|
+
const checked = await checkWithVerificationProvider(verificationProvider, {
|
|
7098
|
+
channel: "sms",
|
|
7099
|
+
code,
|
|
7100
|
+
purpose: "mfa_enrollment",
|
|
7101
|
+
reference: providerReference,
|
|
7102
|
+
subject: userId,
|
|
7103
|
+
to: enrollment.smsPhone
|
|
7104
|
+
});
|
|
7105
|
+
if (checked.error !== undefined) {
|
|
7106
|
+
return status(checked.error.status, checked.error.message);
|
|
7107
|
+
}
|
|
7108
|
+
providerResult = checked.result;
|
|
7109
|
+
}
|
|
7110
|
+
const codeValid = providerResult ? providerResult.status === "approved" : localCodeHash !== undefined && await constantTimeEqual(await hashToken(code), localCodeHash);
|
|
6982
7111
|
if (!codeValid) {
|
|
6983
7112
|
await mfaStore.saveEnrollment({
|
|
6984
7113
|
...enrollment,
|
|
6985
7114
|
smsFailedAttempts: (enrollment.smsFailedAttempts ?? 0) + 1,
|
|
6986
7115
|
updatedAt: Date.now()
|
|
6987
7116
|
});
|
|
6988
|
-
return status("Bad Request", "Invalid SMS code");
|
|
7117
|
+
return status(providerResult?.status === "max_attempts_reached" ? "Too Many Requests" : "Bad Request", providerResult?.status === "expired" ? "SMS code expired" : "Invalid SMS code");
|
|
6989
7118
|
}
|
|
6990
7119
|
await mfaStore.saveEnrollment({
|
|
6991
7120
|
...enrollment,
|
|
6992
7121
|
smsFailedAttempts: 0,
|
|
6993
7122
|
smsPendingCodeExpiresAt: undefined,
|
|
6994
7123
|
smsPendingCodeHash: undefined,
|
|
7124
|
+
smsPendingPurpose: undefined,
|
|
7125
|
+
smsProviderReference: undefined,
|
|
6995
7126
|
smsVerified: true,
|
|
6996
7127
|
updatedAt: Date.now()
|
|
6997
7128
|
});
|
|
@@ -7014,10 +7145,12 @@ var mfaChallenge = ({
|
|
|
7014
7145
|
onMfaChallengeError,
|
|
7015
7146
|
onMfaChallengeSuccess,
|
|
7016
7147
|
onSendSmsCode,
|
|
7148
|
+
verificationProvider,
|
|
7017
7149
|
sessionDurationMs = DEFAULT_MFA_SESSION_TTL_MS,
|
|
7018
7150
|
smsCodeLength = DEFAULT_SMS_CODE_LENGTH,
|
|
7019
7151
|
smsCodeTtlMs = DEFAULT_SMS_CODE_TTL_MS,
|
|
7020
7152
|
smsMaxAttempts = DEFAULT_SMS_MAX_ATTEMPTS,
|
|
7153
|
+
smsResendCooldownMs = DEFAULT_SMS_RESEND_COOLDOWN_MS,
|
|
7021
7154
|
totpMaxAttempts = DEFAULT_TOTP_MAX_ATTEMPTS
|
|
7022
7155
|
}) => new Elysia18().use(sessionStore()).post(challengeRoute, async ({
|
|
7023
7156
|
body: { action, code, factor },
|
|
@@ -7059,27 +7192,48 @@ var mfaChallenge = ({
|
|
|
7059
7192
|
await onMfaChallengeSuccess?.({ user, userSessionId });
|
|
7060
7193
|
return status("OK", { status: "authenticated" });
|
|
7061
7194
|
};
|
|
7062
|
-
const
|
|
7063
|
-
if (
|
|
7064
|
-
return status("
|
|
7195
|
+
const sendSmsChallenge = async () => {
|
|
7196
|
+
if (enrollment.smsCodeSentAt !== undefined && Date.now() - enrollment.smsCodeSentAt < smsResendCooldownMs) {
|
|
7197
|
+
return status("Too Many Requests", "SMS resend cooldown active");
|
|
7065
7198
|
}
|
|
7066
|
-
|
|
7199
|
+
try {
|
|
7067
7200
|
await issueAndStoreSmsCode({
|
|
7068
7201
|
codeLength: smsCodeLength,
|
|
7069
7202
|
enrollment,
|
|
7070
7203
|
mfaStore,
|
|
7071
7204
|
onSendSmsCode,
|
|
7072
|
-
|
|
7205
|
+
purpose: "mfa_challenge",
|
|
7206
|
+
ttlMs: smsCodeTtlMs,
|
|
7207
|
+
userId: getUserId(user),
|
|
7208
|
+
verificationProvider
|
|
7073
7209
|
});
|
|
7074
|
-
|
|
7210
|
+
} catch (error) {
|
|
7211
|
+
const mapped = mapVerificationProviderError(error);
|
|
7212
|
+
if (mapped === undefined)
|
|
7213
|
+
throw error;
|
|
7214
|
+
return status(mapped.status, mapped.message);
|
|
7075
7215
|
}
|
|
7216
|
+
return status("OK", { status: "sent" });
|
|
7217
|
+
};
|
|
7218
|
+
const runSmsChallenge = async () => {
|
|
7219
|
+
if (!enrollment.smsVerified || !enrollment.smsPhone) {
|
|
7220
|
+
return status("Unauthorized", "No MFA challenge in progress");
|
|
7221
|
+
}
|
|
7222
|
+
if (action === "send")
|
|
7223
|
+
return sendSmsChallenge();
|
|
7076
7224
|
if (code === undefined) {
|
|
7077
7225
|
return status("Bad Request", "SMS code required");
|
|
7078
7226
|
}
|
|
7079
|
-
|
|
7227
|
+
const localCodeHash = enrollment.smsPendingCodeHash;
|
|
7228
|
+
const localCodeExpiresAt = enrollment.smsPendingCodeExpiresAt;
|
|
7229
|
+
const providerReference = enrollment.smsProviderReference;
|
|
7230
|
+
if (enrollment.smsPendingPurpose !== "mfa_challenge" || localCodeExpiresAt === undefined) {
|
|
7080
7231
|
return status("Bad Request", "No SMS code in progress");
|
|
7081
7232
|
}
|
|
7082
|
-
if (
|
|
7233
|
+
if (verificationProvider === undefined && localCodeHash === undefined) {
|
|
7234
|
+
return status("Bad Request", "No SMS code in progress");
|
|
7235
|
+
}
|
|
7236
|
+
if (Date.now() > localCodeExpiresAt) {
|
|
7083
7237
|
return status("Unauthorized", "SMS code expired");
|
|
7084
7238
|
}
|
|
7085
7239
|
if ((enrollment.smsFailedAttempts ?? 0) >= smsMaxAttempts) {
|
|
@@ -7089,7 +7243,25 @@ var mfaChallenge = ({
|
|
|
7089
7243
|
});
|
|
7090
7244
|
return status("Unauthorized", "Too many attempts");
|
|
7091
7245
|
}
|
|
7092
|
-
|
|
7246
|
+
let providerResult;
|
|
7247
|
+
if (verificationProvider !== undefined) {
|
|
7248
|
+
if (providerReference === undefined) {
|
|
7249
|
+
return status("Bad Request", "No SMS code in progress");
|
|
7250
|
+
}
|
|
7251
|
+
const checked = await checkWithVerificationProvider(verificationProvider, {
|
|
7252
|
+
channel: "sms",
|
|
7253
|
+
code,
|
|
7254
|
+
purpose: "mfa_challenge",
|
|
7255
|
+
reference: providerReference,
|
|
7256
|
+
subject: getUserId(user),
|
|
7257
|
+
to: enrollment.smsPhone
|
|
7258
|
+
});
|
|
7259
|
+
if (checked.error !== undefined) {
|
|
7260
|
+
return status(checked.error.status, checked.error.message);
|
|
7261
|
+
}
|
|
7262
|
+
providerResult = checked.result;
|
|
7263
|
+
}
|
|
7264
|
+
const smsValid = providerResult ? providerResult.status === "approved" : localCodeHash !== undefined && await constantTimeEqual(await hashToken(code), localCodeHash);
|
|
7093
7265
|
if (!smsValid) {
|
|
7094
7266
|
await mfaStore.saveEnrollment({
|
|
7095
7267
|
...enrollment,
|
|
@@ -7100,7 +7272,7 @@ var mfaChallenge = ({
|
|
|
7100
7272
|
error: new Error("invalid_mfa_code"),
|
|
7101
7273
|
userId: getUserId(user)
|
|
7102
7274
|
});
|
|
7103
|
-
return status("Unauthorized", "Invalid MFA code");
|
|
7275
|
+
return status(providerResult?.status === "max_attempts_reached" ? "Too Many Requests" : "Unauthorized", providerResult?.status === "expired" ? "SMS code expired" : "Invalid MFA code");
|
|
7104
7276
|
}
|
|
7105
7277
|
await mfaStore.saveEnrollment({
|
|
7106
7278
|
...enrollment,
|
|
@@ -7108,6 +7280,8 @@ var mfaChallenge = ({
|
|
|
7108
7280
|
smsFailedAttempts: 0,
|
|
7109
7281
|
smsPendingCodeExpiresAt: undefined,
|
|
7110
7282
|
smsPendingCodeHash: undefined,
|
|
7283
|
+
smsPendingPurpose: undefined,
|
|
7284
|
+
smsProviderReference: undefined,
|
|
7111
7285
|
updatedAt: Date.now()
|
|
7112
7286
|
});
|
|
7113
7287
|
return promote();
|
|
@@ -32836,12 +33010,15 @@ var mfaEnrollmentsTable = pgTable("auth_mfa_enrollments", {
|
|
|
32836
33010
|
backup_code_hashes: jsonb("backup_code_hashes").$type().notNull().default([]),
|
|
32837
33011
|
created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
|
|
32838
33012
|
last_used_at_ms: bigint("last_used_at_ms", { mode: "number" }),
|
|
33013
|
+
sms_code_sent_at_ms: bigint("sms_code_sent_at_ms", { mode: "number" }),
|
|
32839
33014
|
sms_failed_attempts: smallint("sms_failed_attempts").notNull().default(0),
|
|
32840
33015
|
sms_pending_code_expires_at_ms: bigint("sms_pending_code_expires_at_ms", {
|
|
32841
33016
|
mode: "number"
|
|
32842
33017
|
}),
|
|
32843
33018
|
sms_pending_code_hash: text("sms_pending_code_hash"),
|
|
33019
|
+
sms_pending_purpose: text("sms_pending_purpose").$type(),
|
|
32844
33020
|
sms_phone: varchar("sms_phone", { length: PHONE_LENGTH }),
|
|
33021
|
+
sms_provider_reference: text("sms_provider_reference"),
|
|
32845
33022
|
sms_verified: boolean("sms_verified").notNull().default(false),
|
|
32846
33023
|
totp_failed_attempts: smallint("totp_failed_attempts").notNull().default(0),
|
|
32847
33024
|
totp_secret_ciphertext: text("totp_secret_ciphertext"),
|
|
@@ -32853,10 +33030,13 @@ var toEnrollment = (row) => ({
|
|
|
32853
33030
|
backupCodeHashes: row.backup_code_hashes,
|
|
32854
33031
|
createdAt: row.created_at_ms,
|
|
32855
33032
|
lastUsedAt: row.last_used_at_ms ?? undefined,
|
|
33033
|
+
smsCodeSentAt: row.sms_code_sent_at_ms ?? undefined,
|
|
32856
33034
|
smsFailedAttempts: row.sms_failed_attempts,
|
|
32857
33035
|
smsPendingCodeExpiresAt: row.sms_pending_code_expires_at_ms ?? undefined,
|
|
32858
33036
|
smsPendingCodeHash: row.sms_pending_code_hash ?? undefined,
|
|
33037
|
+
smsPendingPurpose: row.sms_pending_purpose ?? undefined,
|
|
32859
33038
|
smsPhone: row.sms_phone ?? undefined,
|
|
33039
|
+
smsProviderReference: row.sms_provider_reference ?? undefined,
|
|
32860
33040
|
smsVerified: row.sms_verified,
|
|
32861
33041
|
totpFailedAttempts: row.totp_failed_attempts,
|
|
32862
33042
|
totpSecretCiphertext: row.totp_secret_ciphertext ?? undefined,
|
|
@@ -32882,10 +33062,13 @@ var createPostgresMfaStore = (db) => ({
|
|
|
32882
33062
|
backup_code_hashes: enrollment.backupCodeHashes,
|
|
32883
33063
|
created_at_ms: enrollment.createdAt,
|
|
32884
33064
|
last_used_at_ms: enrollment.lastUsedAt ?? null,
|
|
33065
|
+
sms_code_sent_at_ms: enrollment.smsCodeSentAt ?? null,
|
|
32885
33066
|
sms_failed_attempts: enrollment.smsFailedAttempts ?? 0,
|
|
32886
33067
|
sms_pending_code_expires_at_ms: enrollment.smsPendingCodeExpiresAt ?? null,
|
|
32887
33068
|
sms_pending_code_hash: enrollment.smsPendingCodeHash ?? null,
|
|
33069
|
+
sms_pending_purpose: enrollment.smsPendingPurpose ?? null,
|
|
32888
33070
|
sms_phone: enrollment.smsPhone ?? null,
|
|
33071
|
+
sms_provider_reference: enrollment.smsProviderReference ?? null,
|
|
32889
33072
|
sms_verified: enrollment.smsVerified,
|
|
32890
33073
|
totp_failed_attempts: enrollment.totpFailedAttempts ?? 0,
|
|
32891
33074
|
totp_secret_ciphertext: enrollment.totpSecretCiphertext ?? null,
|
|
@@ -34639,23 +34822,28 @@ var portableJsonb = customType({
|
|
|
34639
34822
|
fromDriver: (value) => typeof value === "string" ? JSON.parse(value) : value,
|
|
34640
34823
|
toDriver: (value) => JSON.stringify(value)
|
|
34641
34824
|
});
|
|
34642
|
-
var
|
|
34825
|
+
var bunSqlJsonb = customType({
|
|
34826
|
+
dataType: () => "jsonb",
|
|
34827
|
+
fromDriver: (value) => typeof value === "string" ? JSON.parse(value) : value,
|
|
34828
|
+
toDriver: (value) => value
|
|
34829
|
+
});
|
|
34830
|
+
var createAgentDelegationsTable = (json5) => pgTable("auth_agent_delegations", {
|
|
34643
34831
|
agent_id: varchar("agent_id", { length: ID_LENGTH7 }).notNull(),
|
|
34644
|
-
authorization_details:
|
|
34832
|
+
authorization_details: json5("authorization_details").$type(),
|
|
34645
34833
|
created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
|
|
34646
34834
|
delegation_id: varchar("delegation_id", {
|
|
34647
34835
|
length: ID_LENGTH7
|
|
34648
34836
|
}).primaryKey(),
|
|
34649
34837
|
expires_at_ms: bigint("expires_at_ms", { mode: "number" }),
|
|
34650
34838
|
organization_id: varchar("organization_id", { length: ID_LENGTH7 }),
|
|
34651
|
-
scopes:
|
|
34839
|
+
scopes: json5("scopes").$type().notNull().default([]),
|
|
34652
34840
|
status: varchar("status", { length: STATUS_LENGTH2 }).$type().notNull(),
|
|
34653
34841
|
updated_at_ms: bigint("updated_at_ms", { mode: "number" }).notNull(),
|
|
34654
34842
|
user_id: varchar("user_id", { length: ID_LENGTH7 }).notNull()
|
|
34655
34843
|
});
|
|
34656
|
-
var
|
|
34844
|
+
var createAgentIdentityRegistrationsTable = (json5) => pgTable("auth_agent_identity_registrations", {
|
|
34657
34845
|
agent_id: varchar("agent_id", { length: ID_LENGTH7 }).notNull().unique(),
|
|
34658
|
-
claim_attempt:
|
|
34846
|
+
claim_attempt: json5("claim_attempt").$type(),
|
|
34659
34847
|
claim_attempt_token_hash: varchar("claim_attempt_token_hash", {
|
|
34660
34848
|
length: ID_LENGTH7
|
|
34661
34849
|
}).unique(),
|
|
@@ -34665,8 +34853,12 @@ var agentIdentityRegistrationsTable = pgTable("auth_agent_identity_registrations
|
|
|
34665
34853
|
claim_token_hash: varchar("claim_token_hash", {
|
|
34666
34854
|
length: ID_LENGTH7
|
|
34667
34855
|
}).notNull().unique(),
|
|
34668
|
-
created_at_ms: bigint("created_at_ms", {
|
|
34669
|
-
|
|
34856
|
+
created_at_ms: bigint("created_at_ms", {
|
|
34857
|
+
mode: "number"
|
|
34858
|
+
}).notNull(),
|
|
34859
|
+
expires_at_ms: bigint("expires_at_ms", {
|
|
34860
|
+
mode: "number"
|
|
34861
|
+
}).notNull(),
|
|
34670
34862
|
kind: varchar("kind", { length: 32 }).$type().notNull(),
|
|
34671
34863
|
last_polled_at_ms: bigint("last_polled_at_ms", { mode: "number" }),
|
|
34672
34864
|
login_hint: varchar("login_hint", { length: ID_LENGTH7 }),
|
|
@@ -34674,27 +34866,37 @@ var agentIdentityRegistrationsTable = pgTable("auth_agent_identity_registrations
|
|
|
34674
34866
|
length: ID_LENGTH7
|
|
34675
34867
|
}).primaryKey(),
|
|
34676
34868
|
status: varchar("status", { length: STATUS_LENGTH2 }).$type().notNull(),
|
|
34677
|
-
updated_at_ms: bigint("updated_at_ms", {
|
|
34869
|
+
updated_at_ms: bigint("updated_at_ms", {
|
|
34870
|
+
mode: "number"
|
|
34871
|
+
}).notNull(),
|
|
34678
34872
|
upstream_client_id: varchar("upstream_client_id", {
|
|
34679
34873
|
length: ID_LENGTH7
|
|
34680
34874
|
}),
|
|
34681
34875
|
upstream_issuer: varchar("upstream_issuer", { length: ID_LENGTH7 }),
|
|
34682
|
-
upstream_subject: varchar("upstream_subject", {
|
|
34876
|
+
upstream_subject: varchar("upstream_subject", {
|
|
34877
|
+
length: ID_LENGTH7
|
|
34878
|
+
}),
|
|
34683
34879
|
user_id: varchar("user_id", { length: ID_LENGTH7 }),
|
|
34684
34880
|
version: integer("version").notNull()
|
|
34685
34881
|
}, (table) => [
|
|
34686
34882
|
uniqueIndex("auth_agent_identity_upstream_unique").on(table.upstream_issuer, table.upstream_subject, table.upstream_client_id)
|
|
34687
34883
|
]);
|
|
34688
|
-
var
|
|
34884
|
+
var createAgentRegistrationsTable = (json5) => pgTable("auth_agent_registrations", {
|
|
34689
34885
|
agent_id: varchar("agent_id", { length: ID_LENGTH7 }).primaryKey(),
|
|
34690
|
-
allowed_scopes:
|
|
34886
|
+
allowed_scopes: json5("allowed_scopes").$type().notNull().default([]),
|
|
34691
34887
|
client_id: varchar("client_id", { length: ID_LENGTH7 }).unique(),
|
|
34692
34888
|
created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
|
|
34693
|
-
metadata:
|
|
34889
|
+
metadata: json5("metadata").$type(),
|
|
34694
34890
|
name: varchar("name", { length: NAME_LENGTH }).notNull(),
|
|
34695
34891
|
status: varchar("status", { length: STATUS_LENGTH2 }).$type().notNull(),
|
|
34696
34892
|
updated_at_ms: bigint("updated_at_ms", { mode: "number" }).notNull()
|
|
34697
34893
|
});
|
|
34894
|
+
var agentDelegationsBunSqlTable = createAgentDelegationsTable(bunSqlJsonb);
|
|
34895
|
+
var agentDelegationsTable = createAgentDelegationsTable(portableJsonb);
|
|
34896
|
+
var agentIdentityRegistrationsBunSqlTable = createAgentIdentityRegistrationsTable(bunSqlJsonb);
|
|
34897
|
+
var agentIdentityRegistrationsTable = createAgentIdentityRegistrationsTable(portableJsonb);
|
|
34898
|
+
var agentRegistrationsBunSqlTable = createAgentRegistrationsTable(bunSqlJsonb);
|
|
34899
|
+
var agentRegistrationsTable = createAgentRegistrationsTable(portableJsonb);
|
|
34698
34900
|
var toRegistration = (row) => ({
|
|
34699
34901
|
agentId: row.agent_id,
|
|
34700
34902
|
allowedScopes: row.allowed_scopes,
|
|
@@ -34761,24 +34963,24 @@ var identityRegistrationValues = (registration) => ({
|
|
|
34761
34963
|
var createNeonAgentDelegationStore = (databaseUrl) => createDrizzleAgentDelegationStore(createNeonDatabase(databaseUrl));
|
|
34762
34964
|
var createNeonAgentIdentityRegistrationStore = (databaseUrl) => createPostgresAgentIdentityRegistrationStore(createNeonDatabase(databaseUrl));
|
|
34763
34965
|
var createNeonAgentRegistrationStore = (databaseUrl) => createPostgresAgentRegistrationStore(createNeonDatabase(databaseUrl));
|
|
34764
|
-
var
|
|
34966
|
+
var createDrizzleAgentDelegationStoreFor = (db, table) => ({
|
|
34765
34967
|
findActiveDelegation: async ({
|
|
34766
34968
|
agentId,
|
|
34767
34969
|
now = Date.now(),
|
|
34768
34970
|
organizationId,
|
|
34769
34971
|
userId
|
|
34770
34972
|
}) => {
|
|
34771
|
-
const organizationCondition = organizationId === undefined ? isNull(
|
|
34772
|
-
const [row] = await db.select().from(
|
|
34973
|
+
const organizationCondition = organizationId === undefined ? isNull(table.organization_id) : eq(table.organization_id, organizationId);
|
|
34974
|
+
const [row] = await db.select().from(table).where(and(eq(table.agent_id, agentId), eq(table.user_id, userId), organizationCondition, eq(table.status, "active"), or(isNull(table.expires_at_ms), gt(table.expires_at_ms, now)))).orderBy(desc(table.updated_at_ms)).limit(1);
|
|
34773
34975
|
return row === undefined ? undefined : toDelegation(row);
|
|
34774
34976
|
},
|
|
34775
34977
|
findByDelegationId: async (delegationId) => {
|
|
34776
|
-
const [row] = await db.select().from(
|
|
34978
|
+
const [row] = await db.select().from(table).where(eq(table.delegation_id, delegationId)).limit(1);
|
|
34777
34979
|
return row === undefined ? undefined : toDelegation(row);
|
|
34778
34980
|
},
|
|
34779
34981
|
listDelegations: async (agentId) => {
|
|
34780
|
-
const base = db.select().from(
|
|
34781
|
-
const rows = await (agentId === undefined ? base.orderBy(desc(
|
|
34982
|
+
const base = db.select().from(table);
|
|
34983
|
+
const rows = await (agentId === undefined ? base.orderBy(desc(table.created_at_ms)) : base.where(eq(table.agent_id, agentId)).orderBy(desc(table.created_at_ms)));
|
|
34782
34984
|
return rows.map(toDelegation);
|
|
34783
34985
|
},
|
|
34784
34986
|
saveDelegation: async (delegation) => {
|
|
@@ -34794,36 +34996,38 @@ var createDrizzleAgentDelegationStore = (db) => ({
|
|
|
34794
34996
|
updated_at_ms: delegation.updatedAt,
|
|
34795
34997
|
user_id: delegation.userId
|
|
34796
34998
|
};
|
|
34797
|
-
await db.insert(
|
|
34999
|
+
await db.insert(table).values(values).onConflictDoUpdate({
|
|
34798
35000
|
set: values,
|
|
34799
|
-
target:
|
|
35001
|
+
target: table.delegation_id
|
|
34800
35002
|
});
|
|
34801
35003
|
}
|
|
34802
35004
|
});
|
|
35005
|
+
var createDrizzleAgentDelegationStore = (db) => createDrizzleAgentDelegationStoreFor(db, agentDelegationsTable);
|
|
35006
|
+
var createBunSqlDrizzleAgentDelegationStore = (db) => createDrizzleAgentDelegationStoreFor(db, agentDelegationsBunSqlTable);
|
|
34803
35007
|
var createPostgresAgentDelegationStore = createDrizzleAgentDelegationStore;
|
|
34804
|
-
var
|
|
35008
|
+
var createPostgresAgentIdentityRegistrationStoreFor = (db, table) => ({
|
|
34805
35009
|
create: async (registration) => {
|
|
34806
|
-
const rows = await db.insert(
|
|
35010
|
+
const rows = await db.insert(table).values(identityRegistrationValues(registration)).onConflictDoNothing().returning({ id: table.registration_id });
|
|
34807
35011
|
return rows.length === 1;
|
|
34808
35012
|
},
|
|
34809
35013
|
findByAgentId: async (agentId) => {
|
|
34810
|
-
const [row] = await db.select().from(
|
|
35014
|
+
const [row] = await db.select().from(table).where(eq(table.agent_id, agentId)).limit(1);
|
|
34811
35015
|
return row === undefined ? undefined : toIdentityRegistration(row);
|
|
34812
35016
|
},
|
|
34813
35017
|
findByAttemptTokenHash: async (attemptTokenHash) => {
|
|
34814
|
-
const [row] = await db.select().from(
|
|
35018
|
+
const [row] = await db.select().from(table).where(eq(table.claim_attempt_token_hash, attemptTokenHash)).limit(1);
|
|
34815
35019
|
return row === undefined ? undefined : toIdentityRegistration(row);
|
|
34816
35020
|
},
|
|
34817
35021
|
findByClaimTokenHash: async (claimTokenHash) => {
|
|
34818
|
-
const [row] = await db.select().from(
|
|
35022
|
+
const [row] = await db.select().from(table).where(eq(table.claim_token_hash, claimTokenHash)).limit(1);
|
|
34819
35023
|
return row === undefined ? undefined : toIdentityRegistration(row);
|
|
34820
35024
|
},
|
|
34821
35025
|
findByRegistrationId: async (registrationId) => {
|
|
34822
|
-
const [row] = await db.select().from(
|
|
35026
|
+
const [row] = await db.select().from(table).where(eq(table.registration_id, registrationId)).limit(1);
|
|
34823
35027
|
return row === undefined ? undefined : toIdentityRegistration(row);
|
|
34824
35028
|
},
|
|
34825
35029
|
findByUpstreamIdentity: async ({ clientId, issuer, subject }) => {
|
|
34826
|
-
const [row] = await db.select().from(
|
|
35030
|
+
const [row] = await db.select().from(table).where(and(eq(table.upstream_client_id, clientId), eq(table.upstream_issuer, issuer), eq(table.upstream_subject, subject))).limit(1);
|
|
34827
35031
|
return row === undefined ? undefined : toIdentityRegistration(row);
|
|
34828
35032
|
},
|
|
34829
35033
|
replace: async (registration, expectedVersion) => {
|
|
@@ -34832,21 +35036,23 @@ var createPostgresAgentIdentityRegistrationStore = (db) => ({
|
|
|
34832
35036
|
version: expectedVersion + 1
|
|
34833
35037
|
};
|
|
34834
35038
|
const values = identityRegistrationValues(next);
|
|
34835
|
-
const rows = await db.update(
|
|
35039
|
+
const rows = await db.update(table).set(values).where(and(eq(table.registration_id, registration.registrationId), eq(table.version, expectedVersion))).returning({ id: table.registration_id });
|
|
34836
35040
|
return rows.length === 1;
|
|
34837
35041
|
}
|
|
34838
35042
|
});
|
|
34839
|
-
var
|
|
35043
|
+
var createBunSqlDrizzleAgentIdentityRegistrationStore = (db) => createPostgresAgentIdentityRegistrationStoreFor(db, agentIdentityRegistrationsBunSqlTable);
|
|
35044
|
+
var createPostgresAgentIdentityRegistrationStore = (db) => createPostgresAgentIdentityRegistrationStoreFor(db, agentIdentityRegistrationsTable);
|
|
35045
|
+
var createPostgresAgentRegistrationStoreFor = (db, table) => ({
|
|
34840
35046
|
findByAgentId: async (agentId) => {
|
|
34841
|
-
const [row] = await db.select().from(
|
|
35047
|
+
const [row] = await db.select().from(table).where(eq(table.agent_id, agentId)).limit(1);
|
|
34842
35048
|
return row === undefined ? undefined : toRegistration(row);
|
|
34843
35049
|
},
|
|
34844
35050
|
findByClientId: async (clientId) => {
|
|
34845
|
-
const [row] = await db.select().from(
|
|
35051
|
+
const [row] = await db.select().from(table).where(eq(table.client_id, clientId)).limit(1);
|
|
34846
35052
|
return row === undefined ? undefined : toRegistration(row);
|
|
34847
35053
|
},
|
|
34848
35054
|
listRegistrations: async () => {
|
|
34849
|
-
const rows = await db.select().from(
|
|
35055
|
+
const rows = await db.select().from(table).orderBy(desc(table.created_at_ms));
|
|
34850
35056
|
return rows.map(toRegistration);
|
|
34851
35057
|
},
|
|
34852
35058
|
saveRegistration: async (registration) => {
|
|
@@ -34860,12 +35066,14 @@ var createPostgresAgentRegistrationStore = (db) => ({
|
|
|
34860
35066
|
status: registration.status,
|
|
34861
35067
|
updated_at_ms: registration.updatedAt
|
|
34862
35068
|
};
|
|
34863
|
-
await db.insert(
|
|
35069
|
+
await db.insert(table).values(values).onConflictDoUpdate({
|
|
34864
35070
|
set: values,
|
|
34865
|
-
target:
|
|
35071
|
+
target: table.agent_id
|
|
34866
35072
|
});
|
|
34867
35073
|
}
|
|
34868
35074
|
});
|
|
35075
|
+
var createBunSqlDrizzleAgentRegistrationStore = (db) => createPostgresAgentRegistrationStoreFor(db, agentRegistrationsBunSqlTable);
|
|
35076
|
+
var createPostgresAgentRegistrationStore = (db) => createPostgresAgentRegistrationStoreFor(db, agentRegistrationsTable);
|
|
34869
35077
|
// src/apikeys/inMemoryStores.ts
|
|
34870
35078
|
var createInMemoryAccessTokenStore = () => {
|
|
34871
35079
|
const tokens = new Map;
|
|
@@ -37209,6 +37417,15 @@ var mfaTotpLockoutMigration = {
|
|
|
37209
37417
|
id: "0003_totp_lockout",
|
|
37210
37418
|
sql: 'ALTER TABLE "auth_mfa_enrollments" ADD COLUMN IF NOT EXISTS "totp_failed_attempts" smallint NOT NULL DEFAULT 0;'
|
|
37211
37419
|
};
|
|
37420
|
+
var mfaSmsDeliveryPolicyMigration = {
|
|
37421
|
+
id: "0004_sms_delivery_policy",
|
|
37422
|
+
sql: [
|
|
37423
|
+
'ALTER TABLE "auth_mfa_enrollments" ADD COLUMN IF NOT EXISTS "sms_code_sent_at_ms" bigint;',
|
|
37424
|
+
'ALTER TABLE "auth_mfa_enrollments" ADD COLUMN IF NOT EXISTS "sms_pending_purpose" text;',
|
|
37425
|
+
'ALTER TABLE "auth_mfa_enrollments" ADD COLUMN IF NOT EXISTS "sms_provider_reference" text;'
|
|
37426
|
+
].join(`
|
|
37427
|
+
`)
|
|
37428
|
+
};
|
|
37212
37429
|
var oidcResourceAudienceMigration = {
|
|
37213
37430
|
id: "0002_resource_audience",
|
|
37214
37431
|
sql: [
|
|
@@ -37263,7 +37480,8 @@ var blockMigrations = {
|
|
|
37263
37480
|
migrations: [
|
|
37264
37481
|
...initMigration("mfa", [mfaEnrollmentsTable]).migrations,
|
|
37265
37482
|
mfaSmsColumnsMigration,
|
|
37266
|
-
mfaTotpLockoutMigration
|
|
37483
|
+
mfaTotpLockoutMigration,
|
|
37484
|
+
mfaSmsDeliveryPolicyMigration
|
|
37267
37485
|
]
|
|
37268
37486
|
},
|
|
37269
37487
|
oidc: {
|
|
@@ -37776,6 +37994,7 @@ var buildAuthApplications = async (configuration) => {
|
|
|
37776
37994
|
credentials,
|
|
37777
37995
|
customProviders,
|
|
37778
37996
|
mfa,
|
|
37997
|
+
verificationProvider,
|
|
37779
37998
|
passwordless,
|
|
37780
37999
|
lockout,
|
|
37781
38000
|
sessions,
|
|
@@ -38008,7 +38227,8 @@ var buildAuthApplications = async (configuration) => {
|
|
|
38008
38227
|
auditedMfa ? mfaRoutes({
|
|
38009
38228
|
...auditedMfa,
|
|
38010
38229
|
authSessionStore,
|
|
38011
|
-
cookieSecure: resolvedCookieSecure
|
|
38230
|
+
cookieSecure: resolvedCookieSecure,
|
|
38231
|
+
verificationProvider
|
|
38012
38232
|
}) : new Elysia45,
|
|
38013
38233
|
passwordless ? passwordlessRoutes({
|
|
38014
38234
|
...passwordless,
|
|
@@ -38255,8 +38475,9 @@ export {
|
|
|
38255
38475
|
createPostgresScimTokenStore,
|
|
38256
38476
|
createNodeSamlAdapter,
|
|
38257
38477
|
createAuthContext,
|
|
38258
|
-
auth2 as auth
|
|
38478
|
+
auth2 as auth,
|
|
38479
|
+
VerificationProviderError
|
|
38259
38480
|
};
|
|
38260
38481
|
|
|
38261
|
-
//# debugId=
|
|
38482
|
+
//# debugId=AAFF3B14FB3E90D564756E2164756E21
|
|
38262
38483
|
//# sourceMappingURL=server.js.map
|