added startup function
This commit is contained in:
@@ -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:
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user