added startup function

This commit is contained in:
2026-06-04 17:08:02 +02:00
parent 98a8149300
commit 86dff12132
5 changed files with 157 additions and 14 deletions
+16 -3
View File
@@ -52,9 +52,22 @@ If you want to be always up to date, you can clone this repository by running:
git clone https://git.the1s.de/theis.gaedigk/stockhome.git
```
> **NOTE**: To do this, you must have git installed. [How to install git?](https://git-scm.com/install/)
> **NOTE:** To do this, you must have git installed. [How to install git?](https://git-scm.com/install/)
### 3. Run Stockhome
### 3. Create `.env` file
In the root directory of this repository create an .env file and enter the following records:
```txt
MYSQL_ROOT_PASSWORD=
AUTH_SIGNATURE=
```
Make sure that you have set an secure root password and a secure signature.
> **NOTE:** These two values cannot contain special characters.
### 4. Start Stockhome
First, navigate into the root directory of this repository and run:
@@ -64,7 +77,7 @@ docker compose up -d --build
The database and all necessary services are started and initialised automatically.
### 4. First login
### 5. First login
The default admin credentials are always:
+1 -1
View File
@@ -47,4 +47,4 @@ CREATE TABLE IF NOT EXISTS app_settings (
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
INSERT INTO app_settings (name, value) VALUES ("app-name", null), ("currency", null);
INSERT INTO app_settings (name, value) VALUES ("app-name", null), ("currency", null), ("first-startup", "true");
+110 -4
View File
@@ -1,16 +1,27 @@
import express from "express";
import cors from "cors";
import dotenv from "dotenv";
import mysql from "mysql2";
import { readFile } from "fs/promises";
dotenv.config();
const app = express();
const PORT = process.env.PORT;
app.set("view engine", "ejs");
const port = 8004;
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
const pool = mysql
.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
})
.promise();
// frontend routes
import userRouter from "./routes/app/users.route.js";
app.use("/users", userRouter);
@@ -21,10 +32,105 @@ app.use("/products", productRouter);
import storageRouter from "./routes/app/storage.route.js";
app.use("/storage", storageRouter);
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
app.listen(port, () => {
runStartup(port);
});
// Startup code
const runStartup = async (port) => {
// Check if database is configured; create schema if app_settings is missing.
let firstStartupValue = null;
try {
const [firstResponse] = await pool.query(
`SELECT value FROM app_settings WHERE name = "first-startup";`,
);
firstStartupValue = firstResponse[0]?.value ?? null;
} catch (err) {
if (err?.code !== "ER_NO_SUCH_TABLE") {
throw err;
}
}
if (firstStartupValue !== "false") {
const schemaPath = new URL("./database.scheme.sql", import.meta.url);
const schemaSql = await readFile(schemaPath, "utf8");
const statements = schemaSql
.split(";")
.map((statement) => statement.trim())
.filter((statement) => statement.length > 0);
for (const statement of statements) {
await pool.query(statement);
}
// create admin credentials
const [result] = await pool.query(
`SELECT value FROM app_settings WHERE name = "first-startup";`,
);
if (result[0]?.value === "true") {
const insertResult = await insertFirstData();
if (insertResult.affectedRows > 0) {
// print out admin credentials
console.log("Successfully created admin user!");
console.log("Username: admin");
console.log("Password: admin");
// Set startup variable to true if scheme insert was successfull
const [scndResponse] = await pool.query(
`UPDATE app_settings SET value = "false" WHERE name = "first-startup";`,
);
if (scndResponse.affectedRows > 0) {
console.log("Database settet up successfully!");
} else {
console.error("There was an error while setting up the database!");
}
} else {
console.error("Error while creating admin user.");
}
}
}
console.log("Everything is settet up successfully!");
console.log(`Server is running on http://localhost:${port}`);
};
const insertFirstData = async () => {
const [insertResult] = await pool.query(
`INSERT INTO users (username, first_name, last_name, email, password, is_admin) VALUES ("admin", "admin", "admin", "admin@example.com", "admin", 1)`,
);
await pool.query(
`INSERT INTO storage_locations (name, description) VALUES (?, ?);`,
["Default Storage", "Initial storage location"],
);
const [storageRows] = await pool.query(
`SELECT uuid FROM storage_locations WHERE name = ? LIMIT 1;`,
["Default Storage"],
);
const storageUuid = storageRows[0]?.uuid ?? null;
if (storageUuid) {
await pool.query(
`INSERT INTO products (name, description, price, amount, storage_location, picture) VALUES (?, ?, ?, ?, ?, ?);`,
[
"Welcome Product",
"Your first item in Stockhome",
"0.00",
1,
storageUuid,
null,
],
);
}
console.log("Welcome product is ready...")
return insertResult;
};
// error handling code
app.use((err, req, res, next) => {
console.error(err.stack);
+15 -4
View File
@@ -2,9 +2,9 @@ services:
database:
container_name: stockhome-mysql
image: mysql:8.0
restart: unless-stopped
ports:
- "3312:3306"
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: stockhome
@@ -12,16 +12,27 @@ services:
volumes:
- ./.docker/volumes/stockhome_mysql:/var/lib/mysql
- ./mysql-timezone.cnf:/etc/mysql/conf.d/timezone.cnf:ro
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 3s
retries: 20
backend:
container_name: stockhome-backend
ports:
- "8004:8004"
build:
context: ./backend
dockerfile: Dockerfile
ports:
- "8004:8004"
environment:
DB_HOST: stockhome-mysql
DB_USER: root
DB_NAME: stockhome
DB_PASSWORD: ${MYSQL_ROOT_PASSWORD}
SECRET_KEY: ${AUTH_SIGNATURE}
NODE_ENV: production
depends_on:
- database
database:
condition: service_healthy
restart: unless-stopped
+15 -2
View File
@@ -10,6 +10,11 @@ services:
volumes:
- ./.docker/volumes/stockhome_mysql:/var/lib/mysql
- ./mysql-timezone.cnf:/etc/mysql/conf.d/timezone.cnf:ro
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 3s
retries: 20
backend:
container_name: stockhome-backend
@@ -17,14 +22,22 @@ services:
context: ./backend
dockerfile: Dockerfile
environment:
DB_HOST: stockhome-mysql
DB_USER: root
DB_NAME: stockhome
DB_PASSWORD: ${MYSQL_ROOT_PASSWORD}
SECRET_KEY: ${AUTH_SIGNATURE}
NODE_ENV: production
depends_on:
- database
database:
condition: service_healthy
restart: unless-stopped
rontend:
frontend:
container_name: stockhome-frontend
build: ./frontend
environment:
VITE_BACKEND_URL: http://localhost:8004
depends_on:
- backend
restart: unless-stopped