login now username+password based
This commit is contained in:
@@ -1,52 +1,19 @@
|
||||
import {
|
||||
admin,
|
||||
customSession,
|
||||
magicLink,
|
||||
multiSession,
|
||||
username,
|
||||
} from "better-auth/plugins";
|
||||
import { getUserController, UserController } from "../user/controller";
|
||||
import { AuthController, getAuthController } from "./controller";
|
||||
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
||||
import { FlowExecCtx } from "@/core/flow.execution.context";
|
||||
import { UserRoleMap } from "@domains/user/data";
|
||||
import { getRedisInstance } from "@pkg/keystore";
|
||||
import { APIError } from "better-auth/api";
|
||||
import { settings } from "@core/settings";
|
||||
import { betterAuth } from "better-auth";
|
||||
import { logger } from "@pkg/logger";
|
||||
import { db, schema } from "@pkg/db";
|
||||
import { nanoid } from "nanoid";
|
||||
|
||||
// Constants
|
||||
const EMAIL_EXPIRES_IN_MINS = 10;
|
||||
const EMAIL_EXPIRES_IN_SECONDS = 60 * EMAIL_EXPIRES_IN_MINS;
|
||||
const COOKIE_CACHE_MAX_AGE = 60 * 5;
|
||||
|
||||
// Helper to create flow context for better-auth callbacks
|
||||
function createAuthFlowContext(contextLabel: string): FlowExecCtx {
|
||||
return {
|
||||
flowId: `auth:${contextLabel}:${nanoid(10)}`,
|
||||
};
|
||||
}
|
||||
|
||||
// Singleton controller instances
|
||||
let authControllerInstance: AuthController | null = null;
|
||||
let userControllerInstance: UserController | null = null;
|
||||
|
||||
function getAuthControllerInstance(): AuthController {
|
||||
if (!authControllerInstance) {
|
||||
authControllerInstance = getAuthController();
|
||||
}
|
||||
return authControllerInstance;
|
||||
}
|
||||
|
||||
function getUserControllerInstance(): UserController {
|
||||
if (!userControllerInstance) {
|
||||
userControllerInstance = getUserController();
|
||||
}
|
||||
return userControllerInstance;
|
||||
}
|
||||
const USERNAME_REGEX = /^[a-zA-Z0-9_]+$/;
|
||||
|
||||
export const auth = betterAuth({
|
||||
trustedOrigins: ["http://localhost:5173", settings.betterAuthUrl],
|
||||
@@ -66,48 +33,7 @@ export const auth = betterAuth({
|
||||
minUsernameLength: 5,
|
||||
maxUsernameLength: 20,
|
||||
usernameValidator: async (username) => {
|
||||
const fctx = createAuthFlowContext("username-check");
|
||||
const uc = getUserControllerInstance();
|
||||
|
||||
const result = await uc
|
||||
.isUsernameAvailable(fctx, username)
|
||||
.match(
|
||||
(isAvailable) => ({ success: true, isAvailable }),
|
||||
(error) => {
|
||||
logger.error(
|
||||
`[${fctx.flowId}] Failed to check username availability`,
|
||||
error,
|
||||
);
|
||||
return { success: false, isAvailable: false };
|
||||
},
|
||||
);
|
||||
|
||||
return result.isAvailable;
|
||||
},
|
||||
}),
|
||||
magicLink({
|
||||
expiresIn: EMAIL_EXPIRES_IN_SECONDS,
|
||||
rateLimit: { window: 60, max: 4 },
|
||||
sendMagicLink: async ({ email, token, url }, request) => {
|
||||
const fctx = createAuthFlowContext("magic-link");
|
||||
const ac = getAuthControllerInstance();
|
||||
|
||||
const result = await ac
|
||||
.sendMagicLink(fctx, email, token, url)
|
||||
.match(
|
||||
() => ({ success: true, error: undefined }),
|
||||
(error) => ({ success: false, error }),
|
||||
);
|
||||
|
||||
if (!result.success || result?.error) {
|
||||
logger.error(
|
||||
`[${fctx.flowId}] Failed to send magic link`,
|
||||
result.error,
|
||||
);
|
||||
throw new APIError("INTERNAL_SERVER_ERROR", {
|
||||
message: result.error?.message,
|
||||
});
|
||||
}
|
||||
return USERNAME_REGEX.test(username);
|
||||
},
|
||||
}),
|
||||
admin({
|
||||
@@ -157,38 +83,6 @@ export const auth = betterAuth({
|
||||
},
|
||||
},
|
||||
user: {
|
||||
changeEmail: {
|
||||
enabled: true,
|
||||
sendChangeEmailVerification: async (
|
||||
{ user, newEmail, url, token },
|
||||
request,
|
||||
) => {
|
||||
const fctx = createAuthFlowContext("email-change");
|
||||
const ac = getAuthControllerInstance();
|
||||
|
||||
const result = await ac
|
||||
.sendEmailChangeVerificationEmail(
|
||||
fctx,
|
||||
newEmail,
|
||||
token,
|
||||
url,
|
||||
)
|
||||
.match(
|
||||
() => ({ success: true, error: undefined }),
|
||||
(error) => ({ success: false, error }),
|
||||
);
|
||||
|
||||
if (!result.success || result?.error) {
|
||||
logger.error(
|
||||
`[${fctx.flowId}] Failed to send email change verification`,
|
||||
result.error,
|
||||
);
|
||||
throw new APIError("INTERNAL_SERVER_ERROR", {
|
||||
message: result.error?.message,
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
modelName: "user",
|
||||
additionalFields: {
|
||||
onboardingDone: {
|
||||
|
||||
Reference in New Issue
Block a user