# NetOps To-Do (Node-versjon) Sanntids oppgavetavle for et nettverksdrift-team. Node + Express + WebSockets. Endringer fra én bruker dukker opp hos alle andre umiddelbart — ingen polling, ingen manuell refresh. ## Kom i gang ```bash npm install npm start # → http://localhost:3000 ``` Utvikling med auto-restart ved kodeendring: ```bash npm run dev ``` Tester: ```bash npm test ``` ## Miljøvariabler | Variabel | Default | Beskrivelse | |---|---|---| | `PORT` | `3000` | HTTP-port | | `HOST` | `0.0.0.0` | Lytteadresse | | `DATA_DIR` | `./data` | Katalog for tasks.json / activity.json / users.json | | `DISABLE_COOKIE_AUTH` | (av) | Sett til `1` for å skru av selvvalgt navn via cookie — da gjelder kun proxy-headere | ## Autentisering Påloggingslogikk er bevisst holdt utenfor appen. Brukernavn hentes fra, i prioritert rekkefølge: 1. `X-Remote-User`-header — satt av reverse proxy (oauth2-proxy, Authelia, …) 2. `Authorization: Basic` — Basic Auth terminert i proxy, brukernavnet gjenbrukes 3. `netops_user`-cookie — selvvalgt navn via "Sett navn"-knappen (hjemme/dev-bruk) 4. `anon` For team-bruk bak proxy: sett `DISABLE_COOKIE_AUTH=1` så ingen kan velge navn selv. ## Rask installasjon på Debian 13 (LXC/VM) ```bash # Som root i containeren: apt-get update && apt-get install -y git git clone /opt/netops bash /opt/netops/netops-todo-node/setup-debian13.sh ``` `setup-debian13.sh` installerer Node fra apt, kjører `npm ci` og setter opp systemd-tjenesten (`DynamicUser` + `StateDirectory`, data i `/var/lib/netops-todo`). Kjør skriptet på nytt etter `git pull` for å oppgradere. Med proxy-auth: `DISABLE_COOKIE_AUTH=1 bash setup-debian13.sh`. ## Bak reverse proxy WebSocket-endepunktet er `/ws` og krever upgrade-støtte i proxyen. Appen må ligge på **rota av et (sub)domene** (f.eks. `todo.hjemme.lan`) — frontend bruker absolutte stier, så sti-prefiks (`proxy.lan/todo/`) fungerer ikke. ### Nginx Proxy Manager 1. **Hosts → Proxy Hosts → Add Proxy Host** - *Domain Names:* `todo.dittdomene.no` - *Scheme:* `http` · *Forward Hostname/IP:* LXC-ens IP · *Forward Port:* `3000` - **Websockets Support: PÅ** (påkrevd — sanntidssynken bruker `/ws`) - *Cache Assets:* AV (ellers kan gammel `app.js` serveres etter oppgradering) - *Block Common Exploits:* valgfritt, fungerer fint sammen med appen 2. **SSL-fanen:** *Request a new SSL Certificate* (Let's Encrypt) + *Force SSL*. Frontend bytter selv til `wss:` når siden er https. 3. **Auth (valgfritt):** *Access Lists* → lag liste med brukere (Basic Auth) og knytt den til proxy-hosten. NPM/nginx sender `Authorization`-headeren videre, og appen bruker brukernavnet derfra — da får hver kollega riktig attribusjon. Sett i så fall `DISABLE_COOKIE_AUTH=1` på tjenesten. Uten access list velger folk navn selv i UI-et (cookie). **nginx:** ```nginx location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Remote-User $remote_user; # ved basic auth i nginx } ``` **Apache** (`mod_proxy_wstunnel`): ```apache ProxyPass /ws ws://127.0.0.1:3000/ws ProxyPassReverse /ws ws://127.0.0.1:3000/ws ProxyPass / http://127.0.0.1:3000/ ProxyPassReverse / http://127.0.0.1:3000/ RequestHeader set X-Remote-User %{REMOTE_USER}s ``` ## Kjør som tjeneste (systemd) ```ini # /etc/systemd/system/netops-todo.service [Unit] Description=NetOps To-Do After=network.target [Service] # DynamicUser + StateDirectory: systemd lager bruker og /var/lib/netops-todo # med riktige rettigheter automatisk — ingen useradd/chown nødvendig. DynamicUser=yes StateDirectory=netops-todo WorkingDirectory=/opt/netops-todo ExecStart=/usr/bin/node server.js Environment=PORT=3000 # HOST=127.0.0.1 hvis proxyen kjører på samme maskin. Står proxyen i en annen # container/host: fjern linjen (lytt på alt) og brannmur port 3000 til kun proxyen. Environment=HOST=127.0.0.1 Environment=DATA_DIR=/var/lib/netops-todo Environment=DISABLE_COOKIE_AUTH=1 Restart=on-failure [Install] WantedBy=multi-user.target ``` ## Funksjoner - **Sanntidssynk** — alle endringer pushes til alle åpne faner via WebSocket - **Presence** — se hvem som er pålogget akkurat nå - **Kanban-tavle** med drag & drop mellom statuskolonner, pluss klassisk tabellvisning - **Dagsplan** — plukk oppgaver fra lista og bygg en ordnet plan for dagen (dra for å sortere, kapasitet i timer, datovelger). Planen er personlig og synkes mellom dine egne faner. - **Kommentar ved statusbytte** — når du markerer ferdig eller blokkert (via knapp, kanban-drag eller modal) tilbys du å skrive en kommentar som festes til oppgaven og vises i aktivitetsloggen - **Hurtig-registrering** med tokens: `Bytt SFP #l1 p2 @me !imorgen ~1h loc:DC-OSL-1` - **Kommentarer** per oppgave - **Aktivitetslogg** — hvem gjorde hva, når (sidepanel) - **Konfliktdeteksjon** — versjonsnummer per oppgave; lagring fra utdatert versjon avvises med tydelig varsel i stedet for stille overskriving - **"Redigerer nå"-indikator** — ser om en kollega har samme oppgave åpen - **Angre sletting** direkte fra toast - KPI-er, grafer (kategori/prioritet/eier), filtre, sortering, søk - Eksport/import av JSON, eksempeldata for demo - Tastatursnarveier: `n` ny · `/` søk · `v` bytt visning · `p` dagsplan · `a` aktivitet · `esc` lukk ## API Alle endepunkt under `/api/`, JSON inn/ut. `v` er versjonsnummer for optimistisk låsing — send med ved update, få 409 hvis noen andre har lagret. | Metode | Endepunkt | Beskrivelse | |---|---|---| | GET | `/api/state` | Bruker, oppgaver, aktivitet, kjente brukere, online, og dagens plan | | POST | `/api/tasks` | Opprett oppgave (`title` påkrevd) | | PUT | `/api/tasks/:id` | Oppdater (delvis OK; send `v` for konfliktsjekk; valgfri `comment` festes som status-kommentar) | | DELETE | `/api/tasks/:id` | Slett | | POST | `/api/tasks/:id/comments` | Legg til kommentar `{ text }` | | DELETE | `/api/tasks/:id/comments/:cid` | Slett egen kommentar | | GET | `/api/plan?date=YYYY-MM-DD` | Hent egen dagsplan (ordnet liste av task-ids) | | PUT | `/api/plan` | Lagre egen dagsplan `{ date, items: [id…] }` | | POST | `/api/replace` | Erstatt hele listen (import) | | POST | `/api/seed` | Last eksempeldata (kun hvis tomt) | | POST | `/api/login` | Sett navn-cookie (hvis cookie-auth er på) | | GET | `/healthz` | Helsesjekk | Eksempel: ```bash curl -s -X POST localhost:3000/api/tasks \ -H 'Content-Type: application/json' \ -H 'X-Remote-User: jon' \ -d '{"title":"Sjekk BGP-sesjon mot AS2119","category":"BGP","priority":"P1"}' ``` ## Lagring JSON-filer i `DATA_DIR` (atomisk skriv via tmp-fil + rename, serialisert i prosessen): `tasks.json`, `activity.json`, `users.json` og `plans.json` (dagsplaner per bruker per dato; planer eldre enn 30 dager ryddes ved oppstart). Én node-prosess per datakatalog. Holder fint til tusenvis av oppgaver; blir det trangt er SQLite (`node:sqlite`) neste naturlige steg.