mirror of
https://github.com/louislam/uptime-kuma.git
synced 2026-08-07 11:24:59 +00:00
Implement migrate user
This commit is contained in:
+37
-11
@@ -10,6 +10,9 @@ import { Socket } from "socket.io";
|
||||
import { haveIBeenPwned } from "better-auth/plugins";
|
||||
import { twoFactor } from "better-auth/plugins";
|
||||
import { createAuthMiddleware, APIError } from "better-auth/api";
|
||||
// @ts-ignore
|
||||
import * as oldAuth from "./auth.js";
|
||||
import { hasUser } from "./routers/better-auth-router";
|
||||
|
||||
export type BetterAuthUser = ReturnType<typeof createAuthInstance>["$Infer"]["Session"]["user"];
|
||||
|
||||
@@ -61,12 +64,6 @@ function createAuthInstance() {
|
||||
revokeSessionsOnPasswordReset: true,
|
||||
enabled: true,
|
||||
disableSignUp: false,
|
||||
sendResetPassword: async ({ user, url, token }, request) => {
|
||||
// TODO
|
||||
},
|
||||
onPasswordReset: async ({ user }, request) => {
|
||||
// TODO
|
||||
},
|
||||
},
|
||||
rateLimit: {
|
||||
// Seconds
|
||||
@@ -111,10 +108,12 @@ function createAuthInstance() {
|
||||
|
||||
hooks: {
|
||||
before: createAuthMiddleware(async (ctx) => {
|
||||
// God Kuma is not allowed to login from the outside, only for internal usage
|
||||
if (ctx.path.startsWith("/sign-in/")) {
|
||||
const username = ctx.body?.username;
|
||||
const password = ctx.body?.password;
|
||||
const email = ctx.body?.email;
|
||||
|
||||
// God Kuma is not allowed to login from the outside, only for internal usage
|
||||
if (username?.startsWith("god_kuma_") || email?.endsWith("@god.uptime-kuma.internal")) {
|
||||
if (!godKumaInitSecret || ctx.headers?.get("god-kuma-init-secret") != godKumaInitSecret) {
|
||||
throw new APIError("BAD_REQUEST", {
|
||||
@@ -122,6 +121,12 @@ function createAuthInstance() {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate legacy user from old user table to better-auth
|
||||
// Only do this when there is no user in better-auth
|
||||
if (!(await hasUser())) {
|
||||
await migrateUser(username, password);
|
||||
}
|
||||
}
|
||||
}),
|
||||
},
|
||||
@@ -247,11 +252,32 @@ export async function doubleCheckPassword(cookie: string, currentPassword: strin
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* Migrate a legacy user from the old `user` table to better-auth tables.
|
||||
* @param username Legacy username
|
||||
* @param password Plain-text password from the login form
|
||||
*/
|
||||
export async function migrateUser() {
|
||||
// TODO: User have to input pwd one time to migrate, or we can not get the original password hash to create a better-auth user
|
||||
// TODO: Disable Auth may need to directly create a user in the database
|
||||
export async function migrateUser(username: string, password: string) {
|
||||
const legacyUser = await oldAuth.login(username, password);
|
||||
if (legacyUser) {
|
||||
try {
|
||||
await auth().api.createUser({
|
||||
body: {
|
||||
name: username,
|
||||
email: `${username}@noreply.uptime-kuma.internal`,
|
||||
password,
|
||||
role: "admin",
|
||||
data: {
|
||||
username,
|
||||
},
|
||||
},
|
||||
});
|
||||
log.info("auth", `Migrated legacy user: ${username}`);
|
||||
} catch (e) {
|
||||
log.error("auth", `Failed to migrate legacy user ${username}:`, e);
|
||||
}
|
||||
} else {
|
||||
log.info("auth", `No legacy user found for username: ${username}, do not migrate.`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,7 +9,7 @@ import { allowDevOrigin } from "../util-server.js";
|
||||
import { generalErrorResponse } from "../util2";
|
||||
|
||||
let processingSetup = false;
|
||||
let hasUser = false;
|
||||
let _hasUser = false;
|
||||
let expired = false;
|
||||
|
||||
const expiredMsg = "Setup has expired. Please restart the server to try again.";
|
||||
@@ -71,7 +71,7 @@ export async function createBetterAuthRouter() {
|
||||
|
||||
log.debug("auth", "First user created:", user);
|
||||
|
||||
hasUser = true;
|
||||
_hasUser = true;
|
||||
res.json({ ok: true });
|
||||
} finally {
|
||||
processingSetup = false;
|
||||
@@ -85,6 +85,16 @@ export async function createBetterAuthRouter() {
|
||||
return betterAuthRouter;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export async function hasUser() {
|
||||
if (_hasUser) {
|
||||
return true;
|
||||
}
|
||||
return (await R.knex("better_auth_user").count("id as count").first()).count !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns Whether setup is needed.
|
||||
*/
|
||||
@@ -95,9 +105,13 @@ export async function needSetup() {
|
||||
if (processingSetup) {
|
||||
return false;
|
||||
}
|
||||
if (hasUser) {
|
||||
|
||||
if (await hasUser()) {
|
||||
return false;
|
||||
}
|
||||
hasUser = (await R.knex("better_auth_user").count("id as count").first()).count !== 0;
|
||||
return !hasUser;
|
||||
|
||||
// The user may be in the old user table, check that as well
|
||||
const hasOldUser = (await R.knex("user").count("id as count").first()).count !== 0;
|
||||
|
||||
return !hasOldUser;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user