diff --git a/frontend/src/components/DashboardSettingsModal.jsx b/frontend/src/components/DashboardSettingsModal.jsx
index 4299b56..982109c 100644
--- a/frontend/src/components/DashboardSettingsModal.jsx
+++ b/frontend/src/components/DashboardSettingsModal.jsx
@@ -36,7 +36,9 @@ const SortableCardItem = ({ card, onToggle }) => {
transform,
transition,
isDragging,
- } = useSortable({ id: card.cardId });
+ } = useSortable({
+ id: card.cardId,
+ });
const style = {
transform: CSS.Transform.toString(transform),
diff --git a/frontend/src/pages/HostGroups.jsx b/frontend/src/pages/HostGroups.jsx
index 7be8bc7..6d4577e 100644
--- a/frontend/src/pages/HostGroups.jsx
+++ b/frontend/src/pages/HostGroups.jsx
@@ -496,8 +496,9 @@ const DeleteHostGroupModal = ({ group, onClose, onConfirm, isLoading }) => {
Warning: This group contains{" "}
- {group._count.hosts} host{group._count.hosts !== 1 ? "s" : ""}.
- You must move or remove these hosts before deleting the group.
+ {group._count.hosts} host
+ {group._count.hosts !== 1 ? "s" : ""}. You must move or remove
+ these hosts before deleting the group.
)}
diff --git a/frontend/src/pages/Hosts.jsx b/frontend/src/pages/Hosts.jsx
index a2f2c8c..905e395 100644
--- a/frontend/src/pages/Hosts.jsx
+++ b/frontend/src/pages/Hosts.jsx
@@ -292,7 +292,9 @@ const Hosts = () => {
newSearchParams.delete("action");
navigate(
`/hosts${newSearchParams.toString() ? `?${newSearchParams.toString()}` : ""}`,
- { replace: true },
+ {
+ replace: true,
+ },
);
}
@@ -306,7 +308,9 @@ const Hosts = () => {
newSearchParams.delete("selected");
navigate(
`/hosts${newSearchParams.toString() ? `?${newSearchParams.toString()}` : ""}`,
- { replace: true },
+ {
+ replace: true,
+ },
);
}
}, [searchParams, navigate]);
diff --git a/frontend/src/pages/Options.jsx b/frontend/src/pages/Options.jsx
index 1c623f7..e623b61 100644
--- a/frontend/src/pages/Options.jsx
+++ b/frontend/src/pages/Options.jsx
@@ -583,8 +583,9 @@ const DeleteHostGroupModal = ({ group, onClose, onConfirm, isLoading }) => {
Warning: This group contains{" "}
- {group._count.hosts} host{group._count.hosts !== 1 ? "s" : ""}.
- You must move or remove these hosts before deleting the group.
+ {group._count.hosts} host
+ {group._count.hosts !== 1 ? "s" : ""}. You must move or remove
+ these hosts before deleting the group.
)}
diff --git a/package.json b/package.json
index bf2d8ad..ff76059 100644
--- a/package.json
+++ b/package.json
@@ -1,47 +1,47 @@
{
- "name": "patchmon",
- "version": "1.2.6",
- "description": "Linux Patch Monitoring System",
- "private": true,
- "workspaces": [
- "backend",
- "frontend"
- ],
- "scripts": {
- "install:all": "npm install && npm run install:backend && npm run install:frontend",
- "install:backend": "cd backend && npm install",
- "install:frontend": "cd frontend && npm install",
- "dev:backend": "cd backend && npm run dev",
- "dev:frontend": "cd frontend && npm run dev",
- "dev": "concurrently \"npm run dev:backend\" \"npm run dev:frontend\"",
- "build:backend": "cd backend && npm run build",
- "build:frontend": "cd frontend && npm run build",
- "build": "npm run build:backend && npm run build:frontend",
- "format": "npx @biomejs/biome format --write .",
- "format:check": "npx @biomejs/biome format .",
- "lint": "npx @biomejs/biome check .",
- "lint:fix": "npx @biomejs/biome check --write ."
- },
- "devDependencies": {
- "@biomejs/biome": "2.2.4",
- "@commitlint/cli": "^20.0.0",
- "@commitlint/config-conventional": "^20.0.0",
- "concurrently": "^8.2.2",
- "husky": "^9.1.6",
- "lint-staged": "^15.2.10",
- "markdownlint-cli": "^0.41.0",
- "prettier": "^3.3.3",
- "prettier-plugin-tailwindcss": "^0.6.8"
- },
- "engines": {
- "node": ">=18.0.0"
- },
- "lint-staged": {
- "*.{js,jsx,ts,tsx,json}": [
- "npx @biomejs/biome check --write"
- ],
- "*.{md,yml,yaml,css,scss}": [
- "npx @biomejs/biome format --write"
- ]
- }
+ "name": "patchmon",
+ "version": "1.2.6",
+ "description": "Linux Patch Monitoring System",
+ "private": true,
+ "workspaces": [
+ "backend",
+ "frontend"
+ ],
+ "scripts": {
+ "install:all": "npm install && npm run install:backend && npm run install:frontend",
+ "install:backend": "cd backend && npm install",
+ "install:frontend": "cd frontend && npm install",
+ "dev:backend": "cd backend && npm run dev",
+ "dev:frontend": "cd frontend && npm run dev",
+ "dev": "concurrently \"npm run dev:backend\" \"npm run dev:frontend\"",
+ "build:backend": "cd backend && npm run build",
+ "build:frontend": "cd frontend && npm run build",
+ "build": "npm run build:backend && npm run build:frontend",
+ "format": "npx @biomejs/biome format --write .",
+ "format:check": "npx @biomejs/biome format .",
+ "lint": "npx @biomejs/biome check .",
+ "lint:fix": "npx @biomejs/biome check --write ."
+ },
+ "devDependencies": {
+ "@biomejs/biome": "2.2.4",
+ "@commitlint/cli": "^20.0.0",
+ "@commitlint/config-conventional": "^20.0.0",
+ "concurrently": "^8.2.2",
+ "husky": "^9.1.6",
+ "lint-staged": "^15.2.10",
+ "markdownlint-cli": "^0.41.0",
+ "prettier": "^3.3.3",
+ "prettier-plugin-tailwindcss": "^0.6.8"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "lint-staged": {
+ "*.{js,jsx,ts,tsx,json}": [
+ "npx @biomejs/biome check --write"
+ ],
+ "*.{md,yml,yaml,css,scss}": [
+ "npx @biomejs/biome format --write"
+ ]
+ }
}
diff --git a/setup-admin-user.js b/setup-admin-user.js
index 6e46690..59381d1 100644
--- a/setup-admin-user.js
+++ b/setup-admin-user.js
@@ -1,111 +1,123 @@
-const { PrismaClient } = require('@prisma/client');
-const bcrypt = require('bcryptjs');
-const readline = require('readline');
+const { PrismaClient } = require("@prisma/client");
+const bcrypt = require("bcryptjs");
+const readline = require("node:readline");
const prisma = new PrismaClient();
const rl = readline.createInterface({
- input: process.stdin,
- output: process.stdout
+ input: process.stdin,
+ output: process.stdout,
});
-const question = (query) => new Promise((resolve) => rl.question(query, resolve));
+const question = (query) =>
+ new Promise((resolve) => rl.question(query, resolve));
async function setupAdminUser() {
- try {
- console.log('š Setting up PatchMon Admin User');
- console.log('=====================================\n');
+ try {
+ console.log("š Setting up PatchMon Admin User");
+ console.log("=====================================\n");
- // Check if any users exist
- const existingUsers = await prisma.users.count();
- if (existingUsers > 0) {
- console.log('ā ļø Users already exist in the database.');
- const overwrite = await question('Do you want to create another admin user? (y/N): ');
- if (overwrite.toLowerCase() !== 'y' && overwrite.toLowerCase() !== 'yes') {
- console.log('ā Setup cancelled.');
- return;
- }
- }
+ // Check if any users exist
+ const existingUsers = await prisma.users.count();
+ if (existingUsers > 0) {
+ console.log("ā ļø Users already exist in the database.");
+ const overwrite = await question(
+ "Do you want to create another admin user? (y/N): ",
+ );
+ if (
+ overwrite.toLowerCase() !== "y" &&
+ overwrite.toLowerCase() !== "yes"
+ ) {
+ console.log("ā Setup cancelled.");
+ return;
+ }
+ }
- // Get user input
- const username = await question('Enter admin username: ');
- if (!username.trim()) {
- console.log('ā Username is required.');
- return;
- }
+ // Get user input
+ const username = await question("Enter admin username: ");
+ if (!username.trim()) {
+ console.log("ā Username is required.");
+ return;
+ }
- const email = await question('Enter admin email: ');
- if (!email.trim()) {
- console.log('ā Email is required.');
- return;
- }
+ const email = await question("Enter admin email: ");
+ if (!email.trim()) {
+ console.log("ā Email is required.");
+ return;
+ }
- const password = await question('Enter admin password (min 6 characters): ');
- if (password.length < 6) {
- console.log('ā Password must be at least 6 characters.');
- return;
- }
+ const password = await question(
+ "Enter admin password (min 6 characters): ",
+ );
+ if (password.length < 6) {
+ console.log("ā Password must be at least 6 characters.");
+ return;
+ }
- // Check if username or email already exists
- const existingUser = await prisma.users.findFirst({
- where: {
- OR: [
- { username: username.trim() },
- { email: email.trim() }
- ]
- }
- });
+ // Check if username or email already exists
+ const existingUser = await prisma.users.findFirst({
+ where: {
+ OR: [{ username: username.trim() }, { email: email.trim() }],
+ },
+ });
- if (existingUser) {
- console.log('ā Username or email already exists.');
- return;
- }
+ if (existingUser) {
+ console.log("ā Username or email already exists.");
+ return;
+ }
- // Hash password
- console.log('\nš Creating admin user...');
- const passwordHash = await bcrypt.hash(password, 12);
+ // Hash password
+ console.log("\nš Creating admin user...");
+ const passwordHash = await bcrypt.hash(password, 12);
- // Create admin user
- const user = await prisma.users.create({
- data: {
- id: require('crypto').randomUUID(),
- username: username.trim(),
- email: email.trim(),
- password_hash: passwordHash,
- role: 'admin',
- is_active: true,
- created_at: new Date(),
- updated_at: new Date()
- },
- select: {
- id: true,
- username: true,
- email: true,
- role: true,
- created_at: true
- }
- });
+ // Create admin user
+ const user = await prisma.users.create({
+ data: {
+ id: require("node:crypto").randomUUID(),
+ username: username.trim(),
+ email: email.trim(),
+ password_hash: passwordHash,
+ role: "admin",
+ is_active: true,
+ created_at: new Date(),
+ updated_at: new Date(),
+ },
+ select: {
+ id: true,
+ username: true,
+ email: true,
+ role: true,
+ created_at: true,
+ },
+ });
- console.log('ā
Admin user created successfully!');
- console.log('\nš User Details:');
- console.log(` Username: ${user.username}`);
- console.log(` Email: ${user.email}`);
- console.log(` Role: ${user.role}`);
- console.log(` Created: ${user.created_at.toISOString()}`);
+ console.log("ā
Admin user created successfully!");
+ console.log("\nš User Details:");
+ console.log(` Username: ${user.username}`);
+ console.log(` Email: ${user.email}`);
+ console.log(` Role: ${user.role}`);
+ console.log(` Created: ${user.created_at.toISOString()}`);
- console.log('\nš Setup complete!');
- console.log('\nNext steps:');
- console.log('1. The backend server is already running as a systemd service');
- console.log('2. The frontend is already built and served by Nginx');
- console.log('3. Visit https://' + process.env.FQDN + ' and login with your credentials');
- console.log('4. Use the management script: ./manage.sh {status|restart|logs|update|backup|credentials|reset-admin}');
-
- } catch (error) {
- console.error('ā Error setting up admin user:', error);
- } finally {
- rl.close();
- await prisma.$disconnect();
- }
+ console.log("\nš Setup complete!");
+ console.log("\nNext steps:");
+ console.log(
+ "1. The backend server is already running as a systemd service",
+ );
+ console.log("2. The frontend is already built and served by Nginx");
+ console.log(
+ "3. Visit https://" +
+ process.env.FQDN +
+ " and login with your credentials",
+ );
+ console.log(
+ "4. Use the management script: ./manage.sh {status|restart|logs|update|backup|credentials|reset-admin}",
+ );
+ } catch (error) {
+ console.error("ā Error setting up admin user:", error);
+ } finally {
+ rl.close();
+ await prisma.$disconnect();
+ }
}
// Run the setup