mirror of
https://github.com/louislam/uptime-kuma.git
synced 2026-08-07 10:14:59 +00:00
Implement reset password, and add an internal betterAuth user for internal operations
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
import { APIError } from "better-auth";
|
||||
|
||||
console.log("== Uptime Kuma Reset Password Tool ==");
|
||||
|
||||
import { loadEnvFile } from "node:process";
|
||||
import { auth, BetterAuthUser, getGodKumaHeaders, removeOtherGodKumaUsers } from "../server/better-auth";
|
||||
import { input, password as passwordInput, select } from "@inquirer/prompts";
|
||||
import { ExitPromptError } from "@inquirer/core";
|
||||
import { genSecret, isDevEnv } from "../src/util";
|
||||
|
||||
// @ts-ignore
|
||||
import Database from "../server/database.js";
|
||||
|
||||
// @ts-ignore No type package is available
|
||||
import parseArgs from "args-parser";
|
||||
|
||||
let kumaGodHeader: Headers;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
async function main() {
|
||||
const args = parseArgs(process.argv);
|
||||
try {
|
||||
loadEnvFile();
|
||||
} catch {}
|
||||
|
||||
console.log("Dev Environment:", isDevEnv());
|
||||
|
||||
Database.initDataDir(args);
|
||||
await Database.connect();
|
||||
|
||||
kumaGodHeader = await getGodKumaHeaders(false);
|
||||
|
||||
const result = await auth().api.listUsers({
|
||||
query: {},
|
||||
headers: kumaGodHeader,
|
||||
});
|
||||
|
||||
const choices = result.users.map((user) => {
|
||||
const email = user.email;
|
||||
const username = (user as BetterAuthUser).username || email;
|
||||
|
||||
return {
|
||||
name: username,
|
||||
value: email,
|
||||
description: "",
|
||||
};
|
||||
});
|
||||
|
||||
let email: string;
|
||||
|
||||
while (true) {
|
||||
const selectEmail = await select({
|
||||
message: "Select a username:",
|
||||
choices,
|
||||
});
|
||||
|
||||
if (!selectEmail) {
|
||||
console.log("Invalid choice");
|
||||
continue;
|
||||
}
|
||||
|
||||
email = selectEmail;
|
||||
break;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
const password = await passwordInput({
|
||||
message: "Enter new password:",
|
||||
mask: "*",
|
||||
});
|
||||
|
||||
try {
|
||||
const ok = await auth().api.setUserPassword({
|
||||
body: {
|
||||
userId: email,
|
||||
newPassword: password,
|
||||
},
|
||||
headers: kumaGodHeader,
|
||||
});
|
||||
|
||||
if (ok) {
|
||||
console.log("Password reset succesfully!");
|
||||
break;
|
||||
}
|
||||
} catch (_) {
|
||||
// Better Auth shows Cli error message in cli already, we don't need to
|
||||
}
|
||||
}
|
||||
|
||||
await cleanUp();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
async function cleanUp() {
|
||||
if (kumaGodHeader) {
|
||||
// Better Auth is not allow to remove current user, so leave it as is first...
|
||||
}
|
||||
await Database.close();
|
||||
}
|
||||
|
||||
// Gracefully handle Ctrl+C
|
||||
process.on("SIGINT", async () => {
|
||||
console.log("\nGracefully shutting down from SIGINT (Ctrl+C)");
|
||||
await cleanUp();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
try {
|
||||
await main();
|
||||
} catch (e) {
|
||||
// Ignore prompt exit errors
|
||||
if (!(e instanceof ExitPromptError)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
console.log("== Uptime Kuma Reset Password Tool ==");
|
||||
Generated
+405
@@ -10,6 +10,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@grpc/grpc-js": "~1.8.22",
|
||||
"@inquirer/prompts": "~8.5.2",
|
||||
"@louislam/ping": "~0.4.4-mod.1",
|
||||
"@louislam/sqlite3": "15.1.6",
|
||||
"@vvo/tzdb": "~6.198.0",
|
||||
@@ -1259,6 +1260,368 @@
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@inquirer/ansi": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-2.0.7.tgz",
|
||||
"integrity": "sha512-3eTuUO1vH2cZm2ZKHeQxnOqlTi9EfZDGgIe3BL3I4u+rJHocr9Fz86M4fjYABPvFnQG/gGK551HqDiIcETwU6Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=23.5.0 || ^22.13.0 || ^20.17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@inquirer/checkbox": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-5.2.1.tgz",
|
||||
"integrity": "sha512-b6xmA/VlTe0ZgDQHDui+Nav470u7u49nRd8/iuhOcQPO9Ch7lGuogydhi2VOmNlZ+zXcM8IcPuNSwQcdJaF/kw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@inquirer/ansi": "^2.0.7",
|
||||
"@inquirer/core": "^11.2.1",
|
||||
"@inquirer/figures": "^2.0.7",
|
||||
"@inquirer/type": "^4.0.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=23.5.0 || ^22.13.0 || ^20.17.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": ">=18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@inquirer/confirm": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-6.1.1.tgz",
|
||||
"integrity": "sha512-eb8DBZcz/2qHWQda4rk2JiQk5h9QV/cVHi1yjt0f69WFZMRFn0sJTye3EAP8icut8UDMjQPsaH5KbcOogefrFQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@inquirer/core": "^11.2.1",
|
||||
"@inquirer/type": "^4.0.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=23.5.0 || ^22.13.0 || ^20.17.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": ">=18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@inquirer/core": {
|
||||
"version": "11.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@inquirer/core/-/core-11.2.1.tgz",
|
||||
"integrity": "sha512-Qd6GJT1yVyrZZCfN8W2qKF5ApmqryXRhRKCuip8h01x2w/esJQ2XIYc6f9abMIHgKQdBfFTSOdbHRLAhuM09UA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@inquirer/ansi": "^2.0.7",
|
||||
"@inquirer/figures": "^2.0.7",
|
||||
"@inquirer/type": "^4.0.7",
|
||||
"cli-width": "^4.1.0",
|
||||
"fast-wrap-ansi": "^0.2.0",
|
||||
"mute-stream": "^3.0.0",
|
||||
"signal-exit": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=23.5.0 || ^22.13.0 || ^20.17.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": ">=18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@inquirer/core/node_modules/signal-exit": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
|
||||
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@inquirer/editor": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-5.2.2.tgz",
|
||||
"integrity": "sha512-ZRVd/oD+sYsUd5zVm0NflqEzlqfYCyHNsqkHl2oWXEUHs12tCbcSFi+wVFEvD8+LGRaMUsVrE7qeo6lSG/S1Vg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@inquirer/core": "^11.2.1",
|
||||
"@inquirer/external-editor": "^3.0.3",
|
||||
"@inquirer/type": "^4.0.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=23.5.0 || ^22.13.0 || ^20.17.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": ">=18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@inquirer/expand": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-5.1.1.tgz",
|
||||
"integrity": "sha512-YmQpenjbFSHAK3sOd44puHh3V1KXXr+JiNpUztoSQ4drLh2rTVzTap/YtlAVu/5xavifIlBfNEzJ/neZJ1a/1g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@inquirer/core": "^11.2.1",
|
||||
"@inquirer/type": "^4.0.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=23.5.0 || ^22.13.0 || ^20.17.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": ">=18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@inquirer/external-editor": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-3.0.3.tgz",
|
||||
"integrity": "sha512-6thf5I8q7lZwzGLAxPaaGEREEkZ3nyePPDQ1oyobblxmEE8mqTLguScP7pDjUTAibiyb4hfXl+qjUEJ+di/aNA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chardet": "^2.1.1",
|
||||
"iconv-lite": "^0.7.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=23.5.0 || ^22.13.0 || ^20.17.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": ">=18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@inquirer/external-editor/node_modules/chardet": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/chardet/-/chardet-2.2.0.tgz",
|
||||
"integrity": "sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@inquirer/external-editor/node_modules/iconv-lite": {
|
||||
"version": "0.7.2",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
|
||||
"integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/@inquirer/figures": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-2.0.7.tgz",
|
||||
"integrity": "sha512-aJ8TBPOGB6f/2qziPfElISTCEd5XOYTFckA2SGjhNmiKzfK/u4ot3v0DUzGVdUnKjN10EqnnEPck36BkyfLnJw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=23.5.0 || ^22.13.0 || ^20.17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@inquirer/input": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@inquirer/input/-/input-5.1.2.tgz",
|
||||
"integrity": "sha512-9K/DDBSQpOyZSkt6sOVP9Vo0TR7atX2kuILsUu0x3wVcVbe97lJwIJKMLdMw25tDYuXl/qp6erT0Xs1rfmcfZg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@inquirer/core": "^11.2.1",
|
||||
"@inquirer/type": "^4.0.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=23.5.0 || ^22.13.0 || ^20.17.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": ">=18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@inquirer/number": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@inquirer/number/-/number-4.1.1.tgz",
|
||||
"integrity": "sha512-XF4IXAbPnGPgw0wsbC/i2tPcyfdZgDpUlhsqU0SfT4IRIGWha6Xm9VRgN5yYxJq+jnyXlfXI/nQ3ulfk0iEICA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@inquirer/core": "^11.2.1",
|
||||
"@inquirer/type": "^4.0.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=23.5.0 || ^22.13.0 || ^20.17.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": ">=18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@inquirer/password": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@inquirer/password/-/password-5.1.1.tgz",
|
||||
"integrity": "sha512-3XBfF7DAsp5qeDsvN5Rd1HmbNokVvEQoUM0QLrRcybC9nX96w3Pbmu7qUsb3IT3J3jBvs2+mTXaKHOUsgHMLzg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@inquirer/ansi": "^2.0.7",
|
||||
"@inquirer/core": "^11.2.1",
|
||||
"@inquirer/type": "^4.0.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=23.5.0 || ^22.13.0 || ^20.17.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": ">=18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@inquirer/prompts": {
|
||||
"version": "8.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-8.5.2.tgz",
|
||||
"integrity": "sha512-IYR/3C/paEVVQYQvdDlFZVjRCJVYHHON0XXMH91KO9GSxs0TdKYWlUdvfQl2EfAHDxUaN3IBffkE/BDTh5nJ6g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@inquirer/checkbox": "^5.2.1",
|
||||
"@inquirer/confirm": "^6.1.1",
|
||||
"@inquirer/editor": "^5.2.2",
|
||||
"@inquirer/expand": "^5.1.1",
|
||||
"@inquirer/input": "^5.1.2",
|
||||
"@inquirer/number": "^4.1.1",
|
||||
"@inquirer/password": "^5.1.1",
|
||||
"@inquirer/rawlist": "^5.3.1",
|
||||
"@inquirer/search": "^4.2.1",
|
||||
"@inquirer/select": "^5.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=23.5.0 || ^22.13.0 || ^20.17.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": ">=18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@inquirer/rawlist": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-5.3.1.tgz",
|
||||
"integrity": "sha512-QqdTqQddL3qPX/PPrjobpsO25NZ4dWXgTLenrR445L2ptLEYE6Z+PD5c5CNDJNx4ugRgELAIpSIJxZaO2jJ2Og==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@inquirer/core": "^11.2.1",
|
||||
"@inquirer/type": "^4.0.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=23.5.0 || ^22.13.0 || ^20.17.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": ">=18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@inquirer/search": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@inquirer/search/-/search-4.2.1.tgz",
|
||||
"integrity": "sha512-xJj8QWKRSrfKoBIITLZK61dD3zwo0Rz11fgDImku30/Oe81zMdIdGgrLY2h6RkJ+KZ/GhNYIRMKnH/62qBTA5g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@inquirer/core": "^11.2.1",
|
||||
"@inquirer/figures": "^2.0.7",
|
||||
"@inquirer/type": "^4.0.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=23.5.0 || ^22.13.0 || ^20.17.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": ">=18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@inquirer/select": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@inquirer/select/-/select-5.2.1.tgz",
|
||||
"integrity": "sha512-FlDndEUww8m7BfukO2nJa25vhD+H5jxxCv4oGioKqzyWz3nPHhhw4LKdYRSlXuAx7DsdWia7iyaBPKKS95Evfw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@inquirer/ansi": "^2.0.7",
|
||||
"@inquirer/core": "^11.2.1",
|
||||
"@inquirer/figures": "^2.0.7",
|
||||
"@inquirer/type": "^4.0.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=23.5.0 || ^22.13.0 || ^20.17.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": ">=18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@inquirer/type": {
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@inquirer/type/-/type-4.0.7.tgz",
|
||||
"integrity": "sha512-t28inv14nMQ1PhKpsJPY+kEs/c00qzeCOS2gTNRyTjG5d6qsVA2fItxW4hkvGZ5lvanGLdtCzVIx5dwdRpN1+g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=23.5.0 || ^22.13.0 || ^20.17.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": ">=18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@intlify/core-base": {
|
||||
"version": "11.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-11.2.8.tgz",
|
||||
@@ -5217,6 +5580,15 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/cli-width": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz",
|
||||
"integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||
@@ -7383,6 +7755,21 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-string-truncated-width": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz",
|
||||
"integrity": "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-string-width": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-3.0.2.tgz",
|
||||
"integrity": "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-string-truncated-width": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-unique-numbers": {
|
||||
"version": "8.0.13",
|
||||
"resolved": "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-8.0.13.tgz",
|
||||
@@ -7414,6 +7801,15 @@
|
||||
],
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/fast-wrap-ansi": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.2.2.tgz",
|
||||
"integrity": "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-string-width": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-xml-parser": {
|
||||
"version": "5.2.5",
|
||||
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz",
|
||||
@@ -10583,6 +10979,15 @@
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/mute-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-3.0.0.tgz",
|
||||
"integrity": "sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": "^20.17.0 || >=22.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mysql2": {
|
||||
"version": "3.11.5",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.11.5.tgz",
|
||||
|
||||
+3
-2
@@ -43,7 +43,7 @@
|
||||
"setup": "git checkout 2.4.0 && npm ci --omit dev --no-audit && node --run download-dist",
|
||||
"download-dist": "node extra/download-dist.js",
|
||||
"mark-as-nightly": "node extra/mark-as-nightly.js",
|
||||
"reset-password": "tsx extra/reset-password.ts",
|
||||
"reset-password": "tsx extra/reset-password.mts",
|
||||
"remove-2fa": "node extra/remove-2fa.js",
|
||||
"simple-dns-server": "node extra/simple-dns-server.js",
|
||||
"simple-mqtt-server": "node extra/simple-mqtt-server.js",
|
||||
@@ -64,6 +64,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@grpc/grpc-js": "~1.8.22",
|
||||
"@inquirer/prompts": "~8.5.2",
|
||||
"@louislam/ping": "~0.4.4-mod.1",
|
||||
"@louislam/sqlite3": "15.1.6",
|
||||
"@vvo/tzdb": "~6.198.0",
|
||||
@@ -142,9 +143,9 @@
|
||||
"tcp-ping": "~0.1.1",
|
||||
"tldts": "~7.0.23",
|
||||
"tough-cookie": "~4.1.4",
|
||||
"tsx": "~4.22.3",
|
||||
"validator": "~13.15.26",
|
||||
"web-push": "~3.6.7",
|
||||
"tsx": "~4.22.3",
|
||||
"ws": "~8.19.0",
|
||||
"zod": "~4.4.3"
|
||||
},
|
||||
|
||||
@@ -7,6 +7,7 @@ const { Settings } = require("./settings");
|
||||
const dayjs = require("dayjs");
|
||||
|
||||
/**
|
||||
* @deprecated Use Better Auth
|
||||
* Login to web app
|
||||
* @param {string} username Username to login with
|
||||
* @param {string} password Password to login with
|
||||
|
||||
+114
-1
@@ -9,10 +9,13 @@ import { admin } from "better-auth/plugins";
|
||||
import { Socket } from "socket.io";
|
||||
import { haveIBeenPwned } from "better-auth/plugins";
|
||||
import { twoFactor } from "better-auth/plugins";
|
||||
import { createAuthMiddleware, APIError } from "better-auth/api";
|
||||
|
||||
type BetterAuthUser = ReturnType<typeof createAuthInstance>["$Infer"]["Session"]["user"];
|
||||
export type BetterAuthUser = ReturnType<typeof createAuthInstance>["$Infer"]["Session"]["user"];
|
||||
|
||||
let authInstance: ReturnType<typeof createAuthInstance>;
|
||||
let godKumaHeaders: Headers;
|
||||
let godKumaInitSecret: string = "";
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -46,6 +49,11 @@ function createAuthInstance() {
|
||||
|
||||
return betterAuth({
|
||||
database,
|
||||
|
||||
// Just want to silent the warning message
|
||||
// As we don't use callback/redirect, it is not used
|
||||
baseURL: "http://localhost:3000",
|
||||
|
||||
secret: getAuthSecret(),
|
||||
// Should be handled in Express.js, check better-auth-router.ts
|
||||
trustedOrigins: ["*"],
|
||||
@@ -100,6 +108,23 @@ function createAuthInstance() {
|
||||
verification: {
|
||||
modelName: "better_auth_verification",
|
||||
},
|
||||
|
||||
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 email = ctx.body?.email;
|
||||
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", {
|
||||
message: "God Kuma is not allowed to login from the outside.",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -228,3 +253,91 @@ 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
|
||||
}
|
||||
|
||||
/**
|
||||
* Because there is no way to do admin operations without admin session
|
||||
* We have to create a god admin user to do operations
|
||||
* @param removeExistingGodKuma For server restart, remove previous god kuma user. But for short time scripts like reset password, you probably don't want to remove.
|
||||
* @returns Headers for the temp admin user
|
||||
*/
|
||||
export async function getGodKumaHeaders(removeExistingGodKuma = true): Promise<Headers> {
|
||||
if (!godKumaHeaders) {
|
||||
const username = "god_kuma_" + genSecret(16);
|
||||
const password = genSecret();
|
||||
const email = `${username}@god.uptime-kuma.internal`;
|
||||
|
||||
await auth().api.createUser({
|
||||
body: {
|
||||
name: "God Kuma (Temp)",
|
||||
email: email,
|
||||
password,
|
||||
role: "admin",
|
||||
data: {
|
||||
username,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
godKumaInitSecret = genSecret();
|
||||
|
||||
// Sign in
|
||||
const response = await auth().api.signInEmail({
|
||||
body: {
|
||||
email,
|
||||
password,
|
||||
},
|
||||
headers: {
|
||||
"god-kuma-init-secret": godKumaInitSecret,
|
||||
},
|
||||
asResponse: true,
|
||||
});
|
||||
|
||||
const header = new Headers();
|
||||
header.set("cookie", response.headers.get("set-cookie") || "");
|
||||
header.set("god-kuma-email", email);
|
||||
|
||||
godKumaHeaders = header;
|
||||
|
||||
if (removeExistingGodKuma) {
|
||||
await removeOtherGodKumaUsers();
|
||||
}
|
||||
}
|
||||
|
||||
return godKumaHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove other god kuma users
|
||||
*/
|
||||
export async function removeOtherGodKumaUsers() {
|
||||
let searchValue = "@god.uptime-kuma.internal";
|
||||
let email = godKumaHeaders.get("god-kuma-email");
|
||||
|
||||
if (!email) {
|
||||
throw new Error("Unexpected error: God Kuma email not found in headers.");
|
||||
}
|
||||
|
||||
const result = await auth().api.listUsers({
|
||||
query: {
|
||||
searchField: "email",
|
||||
searchValue,
|
||||
searchOperator: "ends_with",
|
||||
},
|
||||
headers: godKumaHeaders,
|
||||
});
|
||||
|
||||
for (const user of result.users) {
|
||||
if (user.email === email) {
|
||||
continue;
|
||||
}
|
||||
|
||||
log.debug("auth", "Removing existing god kuma user:", user.email);
|
||||
// Delete the user
|
||||
await auth().api.removeUser({
|
||||
body: {
|
||||
userId: user.id,
|
||||
},
|
||||
headers: godKumaHeaders,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@ const fs = require("fs");
|
||||
const fsAsync = fs.promises;
|
||||
const { R } = require("redbean-node");
|
||||
const { setSetting, setting } = require("./util-server");
|
||||
const { log, sleep, isDev } = require("../src/util");
|
||||
const { log, sleep, isDevEnv } = require("../src/util");
|
||||
const knex = require("knex");
|
||||
const path = require("path");
|
||||
const { EmbeddedMariaDB } = require("./embedded-mariadb");
|
||||
@@ -171,7 +171,7 @@ class Database {
|
||||
* @returns {string} The dev data dir, empty string if not in dev mode or in master branch
|
||||
*/
|
||||
static getDevDataDir() {
|
||||
if (isDev) {
|
||||
if (isDevEnv()) {
|
||||
const gitBranch = this.getCurrentGitBranch();
|
||||
|
||||
// HEAD means detached head. Don't handle this case, becasuse it is not common.
|
||||
|
||||
+12
@@ -13,7 +13,19 @@ import * as utc from "dayjs/plugin/utc";
|
||||
|
||||
import jsonata from "jsonata";
|
||||
|
||||
/**
|
||||
* @deprecated Use isDevEnv, because NODE_ENV could be set after this
|
||||
*/
|
||||
export const isDev = process.env.NODE_ENV === "development";
|
||||
|
||||
/**
|
||||
* Check if NODE_ENV is development
|
||||
* @returns yes or no
|
||||
*/
|
||||
export function isDevEnv() {
|
||||
return process.env.NODE_ENV === "development";
|
||||
}
|
||||
|
||||
export const isNode = typeof process !== "undefined" && process?.versions?.node;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user