Umbenennung Pantry -> Project-Good; README mit echter Clone-URL
- Anzeigename, Paketname, Token-Key, DB-/Volume-Namen auf project_good - README Clone-Abschnitt mit git.scarriffle.com/Scarriffle/project-good Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
11
README.md
11
README.md
@@ -1,4 +1,4 @@
|
|||||||
# 🥫 Pantry – Selfhostbare Lebensmittel-Lagerverwaltung
|
# 🥫 Project-Good – Selfhostbare Lebensmittel-Lagerverwaltung
|
||||||
|
|
||||||
Ein selbst gehosteter Dienst zur Verwaltung deines Lebensmittelvorrats:
|
Ein selbst gehosteter Dienst zur Verwaltung deines Lebensmittelvorrats:
|
||||||
Ein-/Auslagern per Barcode, MHD-/Ablaufverwaltung mit Chargen, Mindestbestände,
|
Ein-/Auslagern per Barcode, MHD-/Ablaufverwaltung mit Chargen, Mindestbestände,
|
||||||
@@ -44,14 +44,17 @@ Voraussetzung: eine Linux-Maschine (Server, NAS, Raspberry Pi …). Docker wird
|
|||||||
Bedarf automatisch installiert.
|
Bedarf automatisch installiert.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone <dieses-repo> pantry
|
git clone https://git.scarriffle.com/Scarriffle/project-good.git
|
||||||
cd pantry/deploy
|
cd project-good/deploy
|
||||||
chmod +x install.sh
|
chmod +x install.sh
|
||||||
./install.sh # interaktiv – fragt Port & Admin-Passwort
|
./install.sh # interaktiv – fragt Port & Admin-Passwort
|
||||||
# oder vollautomatisch mit generiertem Admin-Passwort:
|
# oder vollautomatisch mit generiertem Admin-Passwort:
|
||||||
# ./install.sh --yes
|
# ./install.sh --yes
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> Ist das Gitea-Repo privat, fragt `git clone` nach Benutzername + Access-Token.
|
||||||
|
> Falls `git` fehlt: `apt update && apt install -y git`.
|
||||||
|
|
||||||
Nach dem Start:
|
Nach dem Start:
|
||||||
- Web-UI: `http://<server-ip>:8080` (Port konfigurierbar)
|
- Web-UI: `http://<server-ip>:8080` (Port konfigurierbar)
|
||||||
- Anmeldung mit dem im Installer angezeigten Admin-Benutzer/Passwort.
|
- Anmeldung mit dem im Installer angezeigten Admin-Benutzer/Passwort.
|
||||||
@@ -74,7 +77,7 @@ cd backend
|
|||||||
python -m venv .venv && source .venv/bin/activate
|
python -m venv .venv && source .venv/bin/activate
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
# lokale SQLite-DB nutzen:
|
# lokale SQLite-DB nutzen:
|
||||||
export DATABASE_URL="sqlite:///./pantry.db"
|
export DATABASE_URL="sqlite:///./project_good.db"
|
||||||
uvicorn app.main:app --reload
|
uvicorn app.main:app --reload
|
||||||
```
|
```
|
||||||
API-Doku dann unter `http://localhost:8000/docs`.
|
API-Doku dann unter `http://localhost:8000/docs`.
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ class Settings(BaseSettings):
|
|||||||
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
|
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
database_url: str = "postgresql+psycopg2://pantry:pantry@localhost:5432/pantry"
|
database_url: str = "postgresql+psycopg2://project_good:project_good@localhost:5432/project_good"
|
||||||
|
|
||||||
# Auth / JWT
|
# Auth / JWT
|
||||||
jwt_secret: str = "change-me-in-production"
|
jwt_secret: str = "change-me-in-production"
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ async def lifespan(app: FastAPI):
|
|||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
app = FastAPI(title="Pantry – Lebensmittel-Lagerverwaltung", version="1.0.0", lifespan=lifespan)
|
app = FastAPI(title="Project-Good – Lebensmittel-Lagerverwaltung", version="1.0.0", lifespan=lifespan)
|
||||||
|
|
||||||
origins = ["*"] if settings.cors_origins.strip() == "*" else [
|
origins = ["*"] if settings.cors_origins.strip() == "*" else [
|
||||||
o.strip() for o in settings.cors_origins.split(",") if o.strip()
|
o.strip() for o in settings.cors_origins.split(",") if o.strip()
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ def lookup_barcode(barcode: str) -> dict | None:
|
|||||||
resp = httpx.get(
|
resp = httpx.get(
|
||||||
url,
|
url,
|
||||||
timeout=settings.off_timeout_seconds,
|
timeout=settings.off_timeout_seconds,
|
||||||
headers={"User-Agent": "Pantry-Selfhosted/1.0 (github: pantry)"},
|
headers={"User-Agent": "Project-Good-Selfhosted/1.0"},
|
||||||
)
|
)
|
||||||
except httpx.HTTPError:
|
except httpx.HTTPError:
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
WEB_PORT=8080
|
WEB_PORT=8080
|
||||||
|
|
||||||
# Datenbank
|
# Datenbank
|
||||||
POSTGRES_USER=pantry
|
POSTGRES_USER=project_good
|
||||||
POSTGRES_PASSWORD=pantry
|
POSTGRES_PASSWORD=project_good
|
||||||
POSTGRES_DB=pantry
|
POSTGRES_DB=project_good
|
||||||
|
|
||||||
# Sicherheit – im Betrieb unbedingt ändern!
|
# Sicherheit – im Betrieb unbedingt ändern!
|
||||||
JWT_SECRET=change-me-please
|
JWT_SECRET=change-me-please
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ services:
|
|||||||
image: postgres:16-alpine
|
image: postgres:16-alpine
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_USER: ${POSTGRES_USER:-pantry}
|
POSTGRES_USER: ${POSTGRES_USER:-project_good}
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-pantry}
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-project_good}
|
||||||
POSTGRES_DB: ${POSTGRES_DB:-pantry}
|
POSTGRES_DB: ${POSTGRES_DB:-project_good}
|
||||||
volumes:
|
volumes:
|
||||||
- pantry_db:/var/lib/postgresql/data
|
- project_good_db:/var/lib/postgresql/data
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-pantry}"]
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-project_good}"]
|
||||||
interval: 5s
|
interval: 5s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 10
|
retries: 10
|
||||||
@@ -21,7 +21,7 @@ services:
|
|||||||
db:
|
db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
environment:
|
environment:
|
||||||
DATABASE_URL: postgresql+psycopg2://${POSTGRES_USER:-pantry}:${POSTGRES_PASSWORD:-pantry}@db:5432/${POSTGRES_DB:-pantry}
|
DATABASE_URL: postgresql+psycopg2://${POSTGRES_USER:-project_good}:${POSTGRES_PASSWORD:-project_good}@db:5432/${POSTGRES_DB:-project_good}
|
||||||
JWT_SECRET: ${JWT_SECRET:-change-me}
|
JWT_SECRET: ${JWT_SECRET:-change-me}
|
||||||
ADMIN_USERNAME: ${ADMIN_USERNAME:-admin}
|
ADMIN_USERNAME: ${ADMIN_USERNAME:-admin}
|
||||||
ADMIN_PASSWORD: ${ADMIN_PASSWORD:-changeme}
|
ADMIN_PASSWORD: ${ADMIN_PASSWORD:-changeme}
|
||||||
@@ -38,4 +38,4 @@ services:
|
|||||||
- "${WEB_PORT:-8080}:80"
|
- "${WEB_PORT:-8080}:80"
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
pantry_db:
|
project_good_db:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
#
|
#
|
||||||
# Pantry – Installer für selfhostbare Lebensmittel-Lagerverwaltung.
|
# Project-Good – Installer für selfhostbare Lebensmittel-Lagerverwaltung.
|
||||||
# Installiert bei Bedarf Docker und startet den kompletten Stack via Docker Compose.
|
# Installiert bei Bedarf Docker und startet den kompletten Stack via Docker Compose.
|
||||||
#
|
#
|
||||||
# Nutzung:
|
# Nutzung:
|
||||||
@@ -84,9 +84,9 @@ create_env() {
|
|||||||
|
|
||||||
cat > "$ENV_FILE" <<EOF
|
cat > "$ENV_FILE" <<EOF
|
||||||
WEB_PORT=$web_port
|
WEB_PORT=$web_port
|
||||||
POSTGRES_USER=pantry
|
POSTGRES_USER=project_good
|
||||||
POSTGRES_PASSWORD=$(rand 24)
|
POSTGRES_PASSWORD=$(rand 24)
|
||||||
POSTGRES_DB=pantry
|
POSTGRES_DB=project_good
|
||||||
JWT_SECRET=$(rand 48)
|
JWT_SECRET=$(rand 48)
|
||||||
ADMIN_USERNAME=$admin_user
|
ADMIN_USERNAME=$admin_user
|
||||||
ADMIN_PASSWORD=$admin_pass
|
ADMIN_PASSWORD=$admin_pass
|
||||||
@@ -101,7 +101,7 @@ EOF
|
|||||||
|
|
||||||
# --- Start --------------------------------------------------------------------
|
# --- Start --------------------------------------------------------------------
|
||||||
main() {
|
main() {
|
||||||
info "Pantry-Installer startet …"
|
info "Project-Good-Installer startet …"
|
||||||
ensure_docker
|
ensure_docker
|
||||||
create_env
|
create_env
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Pantry – Roadmap
|
# Project-Good – Roadmap
|
||||||
|
|
||||||
Selfhostbare Lebensmittel-Lagerverwaltung. Aufbau in mehreren Schritten.
|
Selfhostbare Lebensmittel-Lagerverwaltung. Aufbau in mehreren Schritten.
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Pantry – Lagerverwaltung</title>
|
<title>Project-Good – Lagerverwaltung</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "pantry-web",
|
"name": "project-good-web",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ function Layout({ children }) {
|
|||||||
return (
|
return (
|
||||||
<div className="app">
|
<div className="app">
|
||||||
<header className="topbar">
|
<header className="topbar">
|
||||||
<div className="brand">🥫 Pantry</div>
|
<div className="brand">🥫 Project-Good</div>
|
||||||
<nav className="nav">
|
<nav className="nav">
|
||||||
<NavLink to="/" end className={link}>Übersicht</NavLink>
|
<NavLink to="/" end className={link}>Übersicht</NavLink>
|
||||||
<NavLink to="/checkin" className={link}>Einlagern</NavLink>
|
<NavLink to="/checkin" className={link}>Einlagern</NavLink>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
const API_BASE = "/api";
|
const API_BASE = "/api";
|
||||||
|
|
||||||
const TOKEN_KEY = "pantry_token";
|
const TOKEN_KEY = "project_good_token";
|
||||||
|
|
||||||
export function getToken() {
|
export function getToken() {
|
||||||
return localStorage.getItem(TOKEN_KEY);
|
return localStorage.getItem(TOKEN_KEY);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export default function Login() {
|
|||||||
return (
|
return (
|
||||||
<div className="login-wrap">
|
<div className="login-wrap">
|
||||||
<form className="card login-card" onSubmit={onSubmit}>
|
<form className="card login-card" onSubmit={onSubmit}>
|
||||||
<div className="brand big">🥫 Pantry</div>
|
<div className="brand big">🥫 Project-Good</div>
|
||||||
<p className="muted">Lebensmittel-Lagerverwaltung</p>
|
<p className="muted">Lebensmittel-Lagerverwaltung</p>
|
||||||
{error && <div className="alert error">{error}</div>}
|
{error && <div className="alert error">{error}</div>}
|
||||||
<label>
|
<label>
|
||||||
|
|||||||
Reference in New Issue
Block a user