feat(auth): add email verification to registration flow
Some checks failed
CI / Test backend (pull_request) Failing after 11s
CI / Check ui (pull_request) Failing after 11s
CI / Docker / backend (pull_request) Has been skipped
CI / Docker / runner (pull_request) Has been skipped
CI / Docker / ui (pull_request) Has been skipped
CI / Docker / caddy (pull_request) Successful in 2m53s
Release / Test backend (push) Successful in 19s
Release / Check ui (push) Successful in 33s
Release / Docker / caddy (push) Failing after 1m26s
Release / Docker / ui (push) Failing after 11s
Release / Docker / backend (push) Successful in 2m2s
Release / Docker / runner (push) Successful in 2m24s
Release / Gitea Release (push) Has been skipped
Some checks failed
CI / Test backend (pull_request) Failing after 11s
CI / Check ui (pull_request) Failing after 11s
CI / Docker / backend (pull_request) Has been skipped
CI / Docker / runner (pull_request) Has been skipped
CI / Docker / ui (pull_request) Has been skipped
CI / Docker / caddy (pull_request) Successful in 2m53s
Release / Test backend (push) Successful in 19s
Release / Check ui (push) Successful in 33s
Release / Docker / caddy (push) Failing after 1m26s
Release / Docker / ui (push) Failing after 11s
Release / Docker / backend (push) Successful in 2m2s
Release / Docker / runner (push) Successful in 2m24s
Release / Gitea Release (push) Has been skipped
- Add email/email_verified/verification_token/verification_token_exp fields
to app_users PocketBase schema (pb-init-v3.sh)
- Add SMTP env vars to UI service in docker-compose.yml
- New email.ts: raw TLS SMTP mailer via Node tls module, sendVerificationEmail()
- createUser() now takes email param, stores verification token (24h TTL)
- loginUser() throws 'Email not verified' when email_verified is false
- New /verify-email route: validates token, verifies user, auto-logs in
- Login page: email field in register form, check-inbox state after register
- /api/auth/register (iOS): returns { pending_verification, email } instead of token
- Add pb.libnovel.cc and storage.libnovel.cc Caddy virtual hosts for homelab runner
- Add homelab runner docker-compose and libnovel.sh helper script
This commit is contained in:
100
scripts/libnovel.sh
Normal file
100
scripts/libnovel.sh
Normal file
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# ── LibNovel — production management script ───────────────────────────────────
|
||||
# Prerequisites on the server:
|
||||
# - docker + docker compose plugin
|
||||
# - doppler CLI authenticated (doppler setup run once in the repo directory)
|
||||
# - docker-compose.yml present in the same directory as this script
|
||||
#
|
||||
# Usage: ./libnovel.sh <command> [service]
|
||||
#
|
||||
# up Start all services (detached)
|
||||
# down Stop all services
|
||||
# restart Stop then start all services
|
||||
# restart <svc> Restart a single service
|
||||
# pull Pull latest images from Docker Hub (uses GIT_TAG from Doppler)
|
||||
# update Pull images then recreate containers
|
||||
# logs Tail all logs
|
||||
# logs <svc> Tail a specific service
|
||||
# ps Show running containers
|
||||
# shell <svc> Open a shell in a running container
|
||||
# init Run one-shot init containers
|
||||
# secrets Print all Doppler secrets (debug)
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
DC="doppler run -- docker compose"
|
||||
CMD="${1:-help}"
|
||||
SVC="${2:-}"
|
||||
|
||||
case "$CMD" in
|
||||
up)
|
||||
$DC up -d
|
||||
;;
|
||||
|
||||
down)
|
||||
$DC down
|
||||
;;
|
||||
|
||||
restart)
|
||||
if [[ -n "$SVC" ]]; then
|
||||
$DC restart "$SVC"
|
||||
else
|
||||
$DC down
|
||||
$DC up -d
|
||||
fi
|
||||
;;
|
||||
|
||||
pull)
|
||||
$DC pull backend runner ui caddy
|
||||
;;
|
||||
|
||||
update)
|
||||
$DC pull backend runner ui caddy
|
||||
$DC up -d
|
||||
;;
|
||||
|
||||
logs)
|
||||
if [[ -n "$SVC" ]]; then
|
||||
$DC logs -f --tail=100 "$SVC"
|
||||
else
|
||||
$DC logs -f --tail=50
|
||||
fi
|
||||
;;
|
||||
|
||||
ps)
|
||||
$DC ps
|
||||
;;
|
||||
|
||||
shell)
|
||||
[[ -z "$SVC" ]] && { echo "Usage: $0 shell <service>"; exit 1; }
|
||||
$DC exec "$SVC" sh
|
||||
;;
|
||||
|
||||
init)
|
||||
$DC run --rm minio-init
|
||||
$DC run --rm pb-init
|
||||
$DC run --rm postgres-init
|
||||
;;
|
||||
|
||||
secrets)
|
||||
doppler secrets --project libnovel --config prd
|
||||
;;
|
||||
|
||||
help|*)
|
||||
echo "Usage: $0 <command> [service]"
|
||||
echo ""
|
||||
echo " up Start all services"
|
||||
echo " down Stop all services"
|
||||
echo " restart Full restart"
|
||||
echo " restart <svc> Restart one service"
|
||||
echo " pull Pull latest images from Docker Hub"
|
||||
echo " update Pull + recreate containers"
|
||||
echo " logs Tail all logs"
|
||||
echo " logs <svc> Tail one service"
|
||||
echo " ps Show running containers"
|
||||
echo " shell <svc> Shell into a container"
|
||||
echo " init Run init containers (first-time setup)"
|
||||
echo " secrets Print Doppler secrets"
|
||||
;;
|
||||
esac
|
||||
@@ -177,11 +177,15 @@ create "audio_jobs" '{
|
||||
|
||||
create "app_users" '{
|
||||
"name":"app_users","type":"base","fields":[
|
||||
{"name":"username", "type":"text","required":true},
|
||||
{"name":"password_hash","type":"text"},
|
||||
{"name":"role", "type":"text"},
|
||||
{"name":"avatar_url", "type":"text"},
|
||||
{"name":"created", "type":"text"}
|
||||
{"name":"username", "type":"text","required":true},
|
||||
{"name":"password_hash", "type":"text"},
|
||||
{"name":"role", "type":"text"},
|
||||
{"name":"avatar_url", "type":"text"},
|
||||
{"name":"created", "type":"text"},
|
||||
{"name":"email", "type":"text"},
|
||||
{"name":"email_verified", "type":"bool"},
|
||||
{"name":"verification_token", "type":"text"},
|
||||
{"name":"verification_token_exp","type":"text"}
|
||||
]}'
|
||||
|
||||
create "user_sessions" '{
|
||||
@@ -240,11 +244,15 @@ create "comment_votes" '{
|
||||
]}'
|
||||
|
||||
# ── 5. Field migrations (idempotent — adds fields missing from older installs) ─
|
||||
add_field "scraping_tasks" "heartbeat_at" "date"
|
||||
add_field "audio_jobs" "heartbeat_at" "date"
|
||||
add_field "progress" "user_id" "text"
|
||||
add_field "progress" "audio_time" "number"
|
||||
add_field "progress" "updated" "text"
|
||||
add_field "books" "meta_updated" "text"
|
||||
add_field "scraping_tasks" "heartbeat_at" "date"
|
||||
add_field "audio_jobs" "heartbeat_at" "date"
|
||||
add_field "progress" "user_id" "text"
|
||||
add_field "progress" "audio_time" "number"
|
||||
add_field "progress" "updated" "text"
|
||||
add_field "books" "meta_updated" "text"
|
||||
add_field "app_users" "email" "text"
|
||||
add_field "app_users" "email_verified" "bool"
|
||||
add_field "app_users" "verification_token" "text"
|
||||
add_field "app_users" "verification_token_exp" "text"
|
||||
|
||||
log "done"
|
||||
|
||||
Reference in New Issue
Block a user