@spfn/auth 0.2.0-beta.32 → 0.2.0-beta.33
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/{authenticate-Brx2N-Ip.d.ts → authenticate-CGslXjZb.d.ts} +1 -1
- package/dist/config.d.ts +40 -0
- package/dist/config.js +16 -0
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/server.d.ts +51 -51
- package/dist/server.js +32 -13
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -6822,7 +6822,7 @@ init_types();
|
|
|
6822
6822
|
|
|
6823
6823
|
// src/server/services/auth.service.ts
|
|
6824
6824
|
init_repositories();
|
|
6825
|
-
import { ValidationError } from "@spfn/core/errors";
|
|
6825
|
+
import { ValidationError as ValidationError2 } from "@spfn/core/errors";
|
|
6826
6826
|
import {
|
|
6827
6827
|
InvalidCredentialsError,
|
|
6828
6828
|
AccountDisabledError,
|
|
@@ -7047,6 +7047,7 @@ async function revokeKeyService(params) {
|
|
|
7047
7047
|
|
|
7048
7048
|
// src/server/services/user.service.ts
|
|
7049
7049
|
init_repositories();
|
|
7050
|
+
import { ValidationError } from "@spfn/core/errors";
|
|
7050
7051
|
import { ReservedUsernameError, UsernameAlreadyTakenError } from "@spfn/auth/errors";
|
|
7051
7052
|
import { env as env4 } from "@spfn/auth/config";
|
|
7052
7053
|
async function getUserByIdService(userId) {
|
|
@@ -7076,7 +7077,24 @@ function getReservedUsernames() {
|
|
|
7076
7077
|
function isReservedUsername(username) {
|
|
7077
7078
|
return getReservedUsernames().has(username.toLowerCase());
|
|
7078
7079
|
}
|
|
7080
|
+
function validateUsernameLength(username) {
|
|
7081
|
+
const min = env4.SPFN_AUTH_USERNAME_MIN_LENGTH ?? 3;
|
|
7082
|
+
const max = env4.SPFN_AUTH_USERNAME_MAX_LENGTH ?? 30;
|
|
7083
|
+
if (username.length < min) {
|
|
7084
|
+
throw new ValidationError({
|
|
7085
|
+
message: `Username must be at least ${min} characters`,
|
|
7086
|
+
details: { minLength: min, actual: username.length }
|
|
7087
|
+
});
|
|
7088
|
+
}
|
|
7089
|
+
if (username.length > max) {
|
|
7090
|
+
throw new ValidationError({
|
|
7091
|
+
message: `Username must be at most ${max} characters`,
|
|
7092
|
+
details: { maxLength: max, actual: username.length }
|
|
7093
|
+
});
|
|
7094
|
+
}
|
|
7095
|
+
}
|
|
7079
7096
|
async function checkUsernameAvailableService(username) {
|
|
7097
|
+
validateUsernameLength(username);
|
|
7080
7098
|
if (isReservedUsername(username)) {
|
|
7081
7099
|
return false;
|
|
7082
7100
|
}
|
|
@@ -7086,6 +7104,7 @@ async function checkUsernameAvailableService(username) {
|
|
|
7086
7104
|
async function updateUsernameService(userId, username) {
|
|
7087
7105
|
const userIdNum = typeof userId === "string" ? Number(userId) : Number(userId);
|
|
7088
7106
|
if (username !== null) {
|
|
7107
|
+
validateUsernameLength(username);
|
|
7089
7108
|
if (isReservedUsername(username)) {
|
|
7090
7109
|
throw new ReservedUsernameError({ username });
|
|
7091
7110
|
}
|
|
@@ -7139,7 +7158,7 @@ async function checkAccountExistsService(params) {
|
|
|
7139
7158
|
identifierType = "phone";
|
|
7140
7159
|
user = await usersRepository.findByPhone(phone);
|
|
7141
7160
|
} else {
|
|
7142
|
-
throw new
|
|
7161
|
+
throw new ValidationError2({ message: "Either email or phone must be provided" });
|
|
7143
7162
|
}
|
|
7144
7163
|
return {
|
|
7145
7164
|
exists: !!user,
|
|
@@ -7207,7 +7226,7 @@ async function loginService(params) {
|
|
|
7207
7226
|
const { email, phone, password, publicKey, keyId, fingerprint, oldKeyId, algorithm } = params;
|
|
7208
7227
|
const user = await usersRepository.findByEmailOrPhone(email, phone);
|
|
7209
7228
|
if (!email && !phone) {
|
|
7210
|
-
throw new
|
|
7229
|
+
throw new ValidationError2({ message: "Either email or phone must be provided" });
|
|
7211
7230
|
}
|
|
7212
7231
|
if (!user || !user.passwordHash) {
|
|
7213
7232
|
throw new InvalidCredentialsError();
|
|
@@ -7264,12 +7283,12 @@ async function changePasswordService(params) {
|
|
|
7264
7283
|
} else {
|
|
7265
7284
|
const user = await usersRepository.findById(userId);
|
|
7266
7285
|
if (!user) {
|
|
7267
|
-
throw new
|
|
7286
|
+
throw new ValidationError2({ message: "User not found" });
|
|
7268
7287
|
}
|
|
7269
7288
|
passwordHash = user.passwordHash;
|
|
7270
7289
|
}
|
|
7271
7290
|
if (!passwordHash) {
|
|
7272
|
-
throw new
|
|
7291
|
+
throw new ValidationError2({ message: "No password set for this account" });
|
|
7273
7292
|
}
|
|
7274
7293
|
const isValid = await verifyPassword(currentPassword, passwordHash);
|
|
7275
7294
|
if (!isValid) {
|
|
@@ -7780,7 +7799,7 @@ async function updateUserProfileService(userId, params) {
|
|
|
7780
7799
|
// src/server/services/oauth.service.ts
|
|
7781
7800
|
init_repositories();
|
|
7782
7801
|
import { env as env8 } from "@spfn/auth/config";
|
|
7783
|
-
import { ValidationError as
|
|
7802
|
+
import { ValidationError as ValidationError3 } from "@spfn/core/errors";
|
|
7784
7803
|
|
|
7785
7804
|
// src/server/lib/oauth/google.ts
|
|
7786
7805
|
import { env as env6 } from "@spfn/auth/config";
|
|
@@ -7922,7 +7941,7 @@ async function oauthStartService(params) {
|
|
|
7922
7941
|
const { provider, returnUrl, publicKey, keyId, fingerprint, algorithm } = params;
|
|
7923
7942
|
if (provider === "google") {
|
|
7924
7943
|
if (!isGoogleOAuthEnabled()) {
|
|
7925
|
-
throw new
|
|
7944
|
+
throw new ValidationError3({
|
|
7926
7945
|
message: "Google OAuth is not configured. Set SPFN_AUTH_GOOGLE_CLIENT_ID and SPFN_AUTH_GOOGLE_CLIENT_SECRET."
|
|
7927
7946
|
});
|
|
7928
7947
|
}
|
|
@@ -7937,7 +7956,7 @@ async function oauthStartService(params) {
|
|
|
7937
7956
|
const authUrl = getGoogleAuthUrl(state);
|
|
7938
7957
|
return { authUrl };
|
|
7939
7958
|
}
|
|
7940
|
-
throw new
|
|
7959
|
+
throw new ValidationError3({
|
|
7941
7960
|
message: `Unsupported OAuth provider: ${provider}`
|
|
7942
7961
|
});
|
|
7943
7962
|
}
|
|
@@ -7945,14 +7964,14 @@ async function oauthCallbackService(params) {
|
|
|
7945
7964
|
const { provider, code, state } = params;
|
|
7946
7965
|
const stateData = await verifyOAuthState(state);
|
|
7947
7966
|
if (stateData.provider !== provider) {
|
|
7948
|
-
throw new
|
|
7967
|
+
throw new ValidationError3({
|
|
7949
7968
|
message: "OAuth state provider mismatch"
|
|
7950
7969
|
});
|
|
7951
7970
|
}
|
|
7952
7971
|
if (provider === "google") {
|
|
7953
7972
|
return handleGoogleCallback(code, stateData);
|
|
7954
7973
|
}
|
|
7955
|
-
throw new
|
|
7974
|
+
throw new ValidationError3({
|
|
7956
7975
|
message: `Unsupported OAuth provider: ${provider}`
|
|
7957
7976
|
});
|
|
7958
7977
|
}
|
|
@@ -8019,7 +8038,7 @@ async function createOrLinkUser(googleUser, tokens) {
|
|
|
8019
8038
|
let isNewUser = false;
|
|
8020
8039
|
if (existingUser) {
|
|
8021
8040
|
if (!googleUser.verified_email) {
|
|
8022
|
-
throw new
|
|
8041
|
+
throw new ValidationError3({
|
|
8023
8042
|
message: "Cannot link to existing account with unverified email. Please verify your email with Google first."
|
|
8024
8043
|
});
|
|
8025
8044
|
}
|
|
@@ -8096,7 +8115,7 @@ var TOKEN_EXPIRY_BUFFER_MS = 5 * 60 * 1e3;
|
|
|
8096
8115
|
async function getGoogleAccessToken(userId) {
|
|
8097
8116
|
const account = await socialAccountsRepository.findByUserIdAndProvider(userId, "google");
|
|
8098
8117
|
if (!account) {
|
|
8099
|
-
throw new
|
|
8118
|
+
throw new ValidationError3({
|
|
8100
8119
|
message: "No Google account linked. User must sign in with Google first."
|
|
8101
8120
|
});
|
|
8102
8121
|
}
|
|
@@ -8105,7 +8124,7 @@ async function getGoogleAccessToken(userId) {
|
|
|
8105
8124
|
return account.accessToken;
|
|
8106
8125
|
}
|
|
8107
8126
|
if (!account.refreshToken) {
|
|
8108
|
-
throw new
|
|
8127
|
+
throw new ValidationError3({
|
|
8109
8128
|
message: "Google refresh token not available. User must re-authenticate with Google."
|
|
8110
8129
|
});
|
|
8111
8130
|
}
|