61 lines
2.0 KiB
TypeScript
61 lines
2.0 KiB
TypeScript
import { AuthContext, MiddlewareContext, MiddlewareOptions } from "better-auth";
|
|
import { AccountRepository } from "../user/account.repository";
|
|
import { FlowExecCtx } from "@/core/flow.execution.context";
|
|
import { ResultAsync } from "neverthrow";
|
|
import { authErrors } from "./errors";
|
|
import { logger } from "@pkg/logger";
|
|
import { nanoid } from "nanoid";
|
|
import { db } from "@pkg/db";
|
|
|
|
export class AuthController {
|
|
constructor(private accountRepo: AccountRepository) {}
|
|
|
|
swapAccountPasswordForTwoFactor(
|
|
fctx: FlowExecCtx,
|
|
ctx: MiddlewareContext<
|
|
MiddlewareOptions,
|
|
AuthContext & { returned?: unknown; responseHeaders?: Headers }
|
|
>,
|
|
) {
|
|
logger.info("Swapping account password for 2FA", {
|
|
...fctx,
|
|
});
|
|
|
|
if (!ctx.path.includes("two-factor")) {
|
|
return ResultAsync.fromSafePromise(Promise.resolve(ctx));
|
|
}
|
|
|
|
if (!ctx.body.password || ctx.body.password.length === 0) {
|
|
return ResultAsync.fromSafePromise(Promise.resolve(ctx));
|
|
}
|
|
|
|
logger.info("Rotating password for 2FA setup for user", {
|
|
...fctx,
|
|
userId: ctx.body.userId,
|
|
});
|
|
|
|
return this.accountRepo
|
|
.rotatePassword(fctx, ctx.body.userId, nanoid())
|
|
.mapErr((err) => {
|
|
logger.error("Failed to rotate password for 2FA", {
|
|
...fctx,
|
|
error: err,
|
|
});
|
|
return authErrors.passwordRotationFailed(fctx, err.detail);
|
|
})
|
|
.map((newPassword) => {
|
|
logger.info("Password rotated successfully for 2FA setup", {
|
|
...fctx,
|
|
});
|
|
return {
|
|
...ctx,
|
|
body: { ...ctx.body, password: newPassword },
|
|
};
|
|
});
|
|
}
|
|
}
|
|
|
|
export function getAuthController(): AuthController {
|
|
return new AuthController(new AccountRepository(db));
|
|
}
|