Eine moderne Login-Anwendung mit Docker-Containerisierung.
- Benutzerauthentifizierung
- Registrierung und Login
- Token-basierte Authentifizierung
- Docker-Containerisierung für einfache Deployment
- Klonen Sie das Repository:
git clone [repository-url]
cd loginv1- Starten Sie die Docker-Container:
docker-compose up -dDie Anwendung ist dann unter folgenden URLs erreichbar:
- Frontend: http://localhost:3000
- Backend: http://localhost:8000
- Docker
- Docker Compose
- Node.js (für lokale Entwicklung)
- Installieren Sie die Abhängigkeiten:
npm install- Starten Sie die Entwicklungsserver:
# Frontend
cd src/frontend
npm run dev
# Backend
cd src/backend
npm run devloginv1/
├── src/
│ ├── frontend/ # Frontend-Anwendung
│ └── backend/ # Backend-API
├── docker-compose.yml
├── Dockerfile.frontend
└── Dockerfile.backend
MIT
This project is configured for automated Docker image builds and publishing to the GitHub Container Registry (GHCR) using GitHub Actions. The provided docker-compose.yaml file allows you to run the application using these pre-built, publicly accessible images without needing to build them locally or log in to Docker.
-
GitHub Actions Workflow (
.github/workflows/docker-publish.yml):- Automatically triggers on every push to the
mainbranch. - Builds Docker images for
nginx,frontend,backend, andtestapi. - Pushes these images to GHCR, tagged with
latestand the commit SHA. - Images are stored at
ghcr.io/YOUR_GITHUB_USERNAME_LOWERCASE/SERVICE_NAME:tag.
- Automatically triggers on every push to the
-
Docker Images on GHCR:
ghcr.io/YOUR_GITHUB_USERNAME_LOWERCASE/nginx:latestghcr.io/YOUR_GITHUB_USERNAME_LOWERCASE/frontend:latestghcr.io/YOUR_GITHUB_USERNAME_LOWERCASE/backend:latestghcr.io/YOUR_GITHUB_USERNAME_LOWERCASE/testapi:latest(You will need to replaceYOUR_GITHUB_USERNAME_LOWERCASEwith your actual GitHub username in lowercase).
-
docker-compose.yaml:- Uses the public images from GHCR.
- Simplifies deployment to a single
docker compose up -dcommand.
For the GitHub Actions workflow to publish images to your GHCR, it needs permission. You must create a Personal Access Token (PAT) and add it as a secret to your GitHub repository.
A. Create a Personal Access Token (PAT):
- Go to your GitHub settings:
- Click your profile picture in the top-right corner.
- Go to Settings.
- Navigate to Developer settings:
- In the left sidebar, scroll down and click Developer settings.
- Go to Personal access tokens:
- Click Personal access tokens, then Tokens (classic).
- Alternatively, you can try Fine-grained tokens, but Tokens (classic) are simpler for this scope.
- Generate a new token:
- Click Generate new token (and then Generate new token (classic) if prompted).
- Configure the token:
- Note: Give your token a descriptive name (e.g.,
GHCR_PUBLISH_PACKAGES). - Expiration: Choose an appropriate expiration period.
- Scopes: Select the following scopes:
write:packages(Crucial: Allows uploading packages/Docker images to GHCR)read:packages(Usually included withwrite:packages, good to have for completeness)- It's good practice to grant only the necessary permissions.
- Note: Give your token a descriptive name (e.g.,
- Generate token:
- Click Generate token.
- Copy the token immediately! This is your only chance to see it. Store it securely for the next step.
B. Add the PAT as a GitHub Repository Secret:
- Go to your GitHub repository.
- Click the Settings tab.
- In the left sidebar, under "Security", click Secrets and variables, then Actions.
- Click New repository secret.
- Name: Enter
GH_PAT(this exact name is used in thedocker-publish.ymlworkflow). - Secret/Value: Paste the PAT you copied in the previous step.
- Click Add secret.
Once this secret is added, the GitHub Actions workflow will have the necessary permissions to push images to GHCR. The first push to main after adding the workflow file and this secret will trigger the image building and publishing process.
After the GitHub Action successfully runs for the first time and pushes the packages (images) to GHCR, you need to ensure these packages are publicly visible.
- Go to your GitHub profile page (not the repository).
- Click on the Packages tab.
- You should see the newly published packages (e.g.,
nginx,frontend,backend,testapi). - For each package:
- Click on the package name.
- On the package's page, find Package settings (usually on the right sidebar).
- Under "Danger Zone" or "Visibility settings", ensure the package visibility is set to Public. If it's private, change it to public.
This makes the images pullable by anyone without requiring a docker login to GHCR.
-
Clone the Repository (if you haven't already):
git clone https://github.com/YOUR_GITHUB_USERNAME/YOUR_REPOSITORY_NAME.git cd YOUR_REPOSITORY_NAME -
Prepare
docker-compose.yaml:- Open the
docker-compose.yamlfile. - Replace all instances of
YOUR_GITHUB_USERNAME_LOWERCASEwith your actual GitHub username (in lowercase letters). - Crucially, replace the
!!!YOUR_STRONG_JWT_SECRET_HERE!!!placeholders for theJWT_SECRETin both thebackendandtestapiservices with the same, strong, unique secret key. - Optionally, change the
POSTGRES_PASSWORDfor thedbservice frompostgres_CHANGE_MEto a more secure password. Ensure theDATABASE_URLin thebackendservice reflects this if you change the user/password (though the default setup usespostgres:postgres_CHANGE_ME).
- Open the
-
Start the Application:
docker compose up -d
(Note: some systems might still use
docker-composeinstead ofdocker compose)This command will:
- Pull the pre-built public images from GHCR for
nginx,frontend,backend, andtestapi. - Start all services in detached mode.
- Pull the pre-built public images from GHCR for
-
Accessing the Application:
- Once the containers are running (check with
docker compose ps), open your web browser and navigate tohttp://localhost. - Nginx will serve the frontend, and API calls will be routed to the backend.
- Once the containers are running (check with
JWT_SECRET: Must be set indocker-compose.yamlforbackendandtestapiservices.TMDB_API_KEY&TMDB_ACCESS_TOKEN: These are pre-filled indocker-compose.yamlas per your earlier provision but ensure they are correct.CORS_ALLOWED_ORIGINS: Configured indocker-compose.yamlfor thebackendservice. The defaulthttp://localhostshould work when accessing Nginx on port 80 of your host.- Database Credentials: The
dbservice usespostgresas the user andpostgres_CHANGE_MEas the password by default. Thebackend'sDATABASE_URLis configured to use these. ChangePOSTGRES_PASSWORDfor better security.
- To stop all services:
docker compose down
- To stop and remove volumes (e.g., to reset the database):
docker compose down -v
- Image Not Found:
- Ensure the GitHub Actions workflow has run successfully after your latest push to
main. - Verify the image names in
docker-compose.yamlexactly match those on GHCR (including your lowercase GitHub username). - Check that the packages on GHCR are set to public visibility.
- Ensure the GitHub Actions workflow has run successfully after your latest push to
- Application Errors:
- Check container logs:
docker compose logs nginx docker compose logs frontend docker compose logs backend docker compose logs db docker compose logs testapi
- Check container logs:
- PAT Issues:
- If GitHub Actions fail with authentication errors when pushing to GHCR, double-check your
GH_PATsecret in the repository settings and ensure the PAT has thewrite:packagesscope.
- If GitHub Actions fail with authentication errors when pushing to GHCR, double-check your
Diese App bietet eine moderne Watchlist-Verwaltung mit Social-Features (Freunde, Multiplayer, Privatsphäre). Nutzer können Filme/Serien verwalten, bewerten, taggen, privat stellen und mit Freunden interagieren. Die Daten werden in einer PostgreSQL-Datenbank gespeichert und über ein Node.js/Express-Backend bereitgestellt. Das Frontend ist in React umgesetzt.
-
Tabelle
movies- Jeder Filmeintrag gehört zu einer Watchlist (Fremdschlüssel
watchlist_id). - Felder:
id,title,year,poster_url, ...is_private(BOOLEAN): Gibt an, ob der Film/Serie privat ist (nur für den Besitzer sichtbar).tags(JSONB): Array von Tag-Objekten, z.B.[ { label: "Horror", color: "#ff0000", is_private: true }, ... ]
- Jeder Filmeintrag gehört zu einer Watchlist (Fremdschlüssel
-
Tabelle
watchlists- Zentrale Verwaltung der Watchlist eines Users.
- Felder
private_tagsundprivate_titleswerden nur noch als Hilfsfelder genutzt, die eigentliche Privatsphäre wird direkt inmoviesund den Tag-Objekten gespeichert.
- Das Feld
is_privatein der Tabellemoviessteuert, ob ein Titel privat ist. - Wird im Detail-Modal (Bearbeitungsdialog) oder in den Einstellungen (Tab "Ausnahmen") gesetzt/entfernt.
- Synchronisation:
- Änderungen im Modal oder in den Einstellungen werden direkt in der DB gespeichert.
- Beim Öffnen der Einstellungen werden alle Titel mit
is_private: trueautomatisch als privat angezeigt.
- Jeder Tag im Feld
tagseines Films kann das Feldis_private: truehaben. - Wird im Detail-Modal (beim Bearbeiten eines Films) oder in den Einstellungen gesetzt/entfernt.
- Synchronisation:
- Änderungen im Modal oder in den Einstellungen werden auf alle Filme angewendet, die diesen Tag enthalten.
- Beim Öffnen der Einstellungen werden alle Tags, die in irgendeinem Film
is_private: truehaben, als privat angezeigt.
- Ein Film/Serie wird für andere User nicht angezeigt, wenn:
is_privatefür den Film/Serie auftruesteht oder- einer der Tags im Feld
tagsdas Feldis_private: truehat.
- Ein einziger privater Tag reicht aus, damit der gesamte Film für andere User nicht sichtbar ist.
- Beim Öffnen des Einstellungsfensters werden die privaten Titel und Tags immer aus der Datenbank geladen (echter Stand).
- Änderungen im Einstellungsfenster werden direkt in der Tabelle
moviesübernommen (PUT-Requests für alle betroffenen Filme). - Das Detail-Modal und die Einstellungen greifen auf dieselbe Datenbasis zu und sind immer synchron.
{
"id": 27,
"title": "One Piece",
"is_private": false,
"tags": [
{ "label": "Horror", "color": "#ff0000", "is_private": true },
{ "label": "Action", "color": "#00ff00", "is_private": false }
]
}- In diesem Beispiel ist der Film öffentlich, aber der Tag "Horror" ist privat. Für andere User ist der gesamte Film nicht sichtbar.
GET /api/watchlist/movies– Gibt alle Filme/Serien des eingeloggten Users zurück (inkl. Privat-Status und Tags)PUT /api/watchlist/movies/:id– Aktualisiert einen Filmeintrag (inkl. is_private und Tags)PUT /api/watchlist/settings– Speichert zentrale Einstellungen, synchronisiert aber auch alle betroffenen Filme/TagsGET /api/watchlist/user/:username– Gibt die Watchlist eines anderen Users zurück (filtert private Titel/Tags heraus)
- Das Detail-Modal (Bearbeiten eines Titels) und das Einstellungsfenster (Tab "Ausnahmen") sind immer synchron mit der Datenbank.
- Änderungen an Privatsphäre-Einstellungen werden sofort übernommen und wirken sich auf die Anzeige für andere User aus.
- Die Filter- und Suchfunktionen sind identisch für eigene und fremde Watchlists.
- Die Privatsphäre-Logik ist zentralisiert: Es gibt keine doppelten oder verteilten Privatsphäre-Informationen mehr.
- Änderungen an privaten Titeln oder Tags müssen immer über die Felder
is_privateinmoviesbzw. im Tag-Objekt erfolgen. - Die Synchronisation zwischen Einstellungen und Detail-Modal ist über einen
useEffectaufsettingsOpenim Frontend gelöst. - Die Backend-Logik filtert für andere User immer korrekt nach diesen Feldern.
- Neue Privatsphäre-Features können einfach durch Erweiterung der Felder in
moviesoder im Tag-Objekt umgesetzt werden. - Die Filter- und Synchronisationslogik ist modular und kann leicht angepasst werden.
Letzter Stand: Alle Privatsphäre-Features sind konsistent, synchron und direkt in der Datenbank abgebildet.