mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-16 20:19:39 +02:00
fix(mana-auth): /api/v1/auth/login mints JWT via auth.handler instead of api.signInEmail
Previous attempt (commit 55cc75e7d) tried to fix the broken JWT mint
in /api/v1/auth/login by switching the cookie name from
`mana.session_token` to `__Secure-mana.session_token` for production.
That was necessary but not sufficient: Better Auth's session cookie
value isn't just the raw session token, it's `<token>.<HMAC>` where
the HMAC is derived from the better-auth secret. Reconstructing the
cookie from auth.api.signInEmail's JSON response only gave us the raw
token, so /api/auth/token's get-session middleware still couldn't
validate it and the JWT mint kept silently failing.
Real fix: do the sign-in via auth.handler (the HTTP path) rather than
auth.api.signInEmail (the SDK path). The handler returns a real fetch
Response with a Set-Cookie header containing the fully signed cookie
envelope. We capture that header verbatim and forward it as the cookie
on the /api/auth/token request, which now passes validation and mints
the JWT correctly.
Verified end-to-end on auth.mana.how:
$ curl -X POST https://auth.mana.how/api/v1/auth/login \
-d '{"email":"...","password":"..."}'
{
"user": {...},
"token": "<session token>",
"accessToken": "eyJhbGciOiJFZERTQSI...", ← real JWT now
"refreshToken": "<session token>"
}
Side benefits:
- The email-not-verified path is now handled by checking
signInResponse.status === 403 directly, no more catching APIError
with the comment-noted async-stream footgun.
- X-Forwarded-For is forwarded explicitly so Better Auth's rate limiter
and our security log see the real client IP.
- The leftover catch block now only handles unexpected exceptions
(network errors etc); the FORBIDDEN-checking logic in it is dead but
harmless and left in for defense in depth.
This commit is contained in:
parent
4eb5dfe4a0
commit
bfa8a0a773
254 changed files with 88 additions and 29437 deletions
|
|
@ -50,7 +50,6 @@ const WORKSPACE_SCOPES = new Set([
|
|||
'@clock',
|
||||
'@contacts',
|
||||
'@context',
|
||||
'@matrix',
|
||||
'@music',
|
||||
'@nutriphi',
|
||||
'@photos',
|
||||
|
|
|
|||
|
|
@ -146,7 +146,6 @@ if [ $# -eq 0 ]; then
|
|||
echo " $0 todo-web todo-backend # Build & restart both"
|
||||
echo " $0 --base # Rebuild base images"
|
||||
echo " $0 --all-web # Rebuild all web apps"
|
||||
echo " $0 mana-matrix-bot # Build & restart consolidated Matrix bot (Go)"
|
||||
echo " $0 --force-free todo-web # Force stop monitoring before build"
|
||||
exit 1
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
# Deploys the complete Mana stack:
|
||||
# - Infrastructure: PostgreSQL, Redis, MinIO, SearXNG
|
||||
# - Core Services: mana-auth, mana-credits, mana-user, mana-subscriptions, mana-analytics
|
||||
# - Go Services: mana-sync, mana-search, mana-crawler, mana-api-gateway, mana-notify, mana-matrix-bot
|
||||
# - Go Services: mana-sync, mana-search, mana-crawler, mana-api-gateway, mana-notify
|
||||
# - Python AI: mana-llm, mana-stt, mana-tts, mana-image-gen
|
||||
# - App Frontends: 19 SvelteKit web apps
|
||||
#
|
||||
|
|
|
|||
|
|
@ -174,10 +174,6 @@ for container in $ALL_PROBLEM_CONTAINERS; do
|
|||
mana-infra-postgres) SERVICE_NAME="postgres" ;;
|
||||
mana-infra-redis) SERVICE_NAME="redis" ;;
|
||||
mana-infra-minio) SERVICE_NAME="minio" ;;
|
||||
mana-matrix-synapse) SERVICE_NAME="synapse" ;;
|
||||
mana-matrix-element) SERVICE_NAME="element-web" ;;
|
||||
mana-matrix-web) SERVICE_NAME="matrix-web" ;;
|
||||
mana-matrix-bot-*) SERVICE_NAME="${container#mana-matrix-bot-}"; SERVICE_NAME="matrix-${SERVICE_NAME}-bot" ;;
|
||||
mana-mon-*) SERVICE_NAME="${container#mana-mon-}" ;;
|
||||
mana-auto-*) SERVICE_NAME="${container#mana-auto-}" ;;
|
||||
mana-service-*) SERVICE_NAME="${container#mana-service-}" ;;
|
||||
|
|
|
|||
|
|
@ -79,17 +79,15 @@ get_category_mem() {
|
|||
|
||||
infra=$(get_category_mem "mana-infra")
|
||||
core=$(get_category_mem "mana-core\|mana-auth\|mana-credits\|mana-user\|mana-subscriptions\|mana-analytics\|mana-api-gateway\|mana-crawler\|mana-service")
|
||||
matrix=$(get_category_mem "mana-matrix")
|
||||
apps=$(get_category_mem "mana-app")
|
||||
monitoring=$(get_category_mem "mana-mon")
|
||||
games=$(get_category_mem "mana-game")
|
||||
auto=$(get_category_mem "mana-auto")
|
||||
|
||||
total=$((infra + core + matrix + apps + monitoring + games + auto))
|
||||
total=$((infra + core + apps + monitoring + games + auto))
|
||||
|
||||
printf "%-25s %8s MiB\n" "Infrastructure:" "$infra"
|
||||
printf "%-25s %8s MiB\n" "Core Services:" "$core"
|
||||
printf "%-25s %8s MiB\n" "Matrix Stack:" "$matrix"
|
||||
printf "%-25s %8s MiB\n" "Web Apps:" "$apps"
|
||||
printf "%-25s %8s MiB\n" "Monitoring:" "$monitoring"
|
||||
printf "%-25s %8s MiB\n" "Games:" "$games"
|
||||
|
|
|
|||
|
|
@ -118,7 +118,6 @@ NAMED_VOLUMES=(
|
|||
"mana-grafana-data"
|
||||
"mana-analytics-data"
|
||||
"mana-loki-data"
|
||||
"mana-matrix-bots-data"
|
||||
)
|
||||
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
|
|
|
|||
|
|
@ -1,123 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Setup Matrix Synapse on Mac Mini
|
||||
# Run this script once to initialize Matrix
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
MATRIX_DIR="$PROJECT_DIR/docker/matrix"
|
||||
|
||||
echo "============================================"
|
||||
echo " Mana Matrix Setup"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Check if postgres is running
|
||||
echo "Checking PostgreSQL..."
|
||||
if ! docker exec mana-postgres pg_isready -U postgres > /dev/null 2>&1; then
|
||||
echo -e "${RED}Error: PostgreSQL is not running.${NC}"
|
||||
echo "Start it with: docker compose -f docker-compose.macmini.yml up -d postgres"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}PostgreSQL is running${NC}"
|
||||
|
||||
# Create matrix database
|
||||
echo ""
|
||||
echo "Creating Matrix database..."
|
||||
if docker exec mana-postgres psql -U postgres -lqt | cut -d \| -f 1 | grep -qw matrix; then
|
||||
echo -e "${YELLOW}Database 'matrix' already exists${NC}"
|
||||
else
|
||||
docker exec mana-postgres psql -U postgres -c "CREATE DATABASE matrix;"
|
||||
echo -e "${GREEN}Database 'matrix' created${NC}"
|
||||
fi
|
||||
|
||||
# Create synapse user
|
||||
echo ""
|
||||
echo "Creating Synapse database user..."
|
||||
if docker exec mana-postgres psql -U postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='synapse'" | grep -q 1; then
|
||||
echo -e "${YELLOW}User 'synapse' already exists${NC}"
|
||||
else
|
||||
# Generate a random password if not set
|
||||
SYNAPSE_DB_PASSWORD=${SYNAPSE_DB_PASSWORD:-$(openssl rand -base64 24)}
|
||||
docker exec mana-postgres psql -U postgres -c "CREATE USER synapse WITH PASSWORD '$SYNAPSE_DB_PASSWORD';"
|
||||
docker exec mana-postgres psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE matrix TO synapse;"
|
||||
docker exec mana-postgres psql -U postgres -c "ALTER DATABASE matrix OWNER TO synapse;"
|
||||
echo -e "${GREEN}User 'synapse' created${NC}"
|
||||
echo ""
|
||||
echo -e "${YELLOW}IMPORTANT: Add this to your .env file:${NC}"
|
||||
echo "SYNAPSE_DB_PASSWORD=$SYNAPSE_DB_PASSWORD"
|
||||
fi
|
||||
|
||||
# Create logs directory in volume
|
||||
echo ""
|
||||
echo "Creating logs directory..."
|
||||
mkdir -p "$MATRIX_DIR/logs" 2>/dev/null || true
|
||||
|
||||
# Generate signing key if not exists
|
||||
echo ""
|
||||
echo "Checking signing key..."
|
||||
if docker volume ls | grep -q mana-synapse; then
|
||||
echo -e "${YELLOW}Synapse volume already exists - signing key should be present${NC}"
|
||||
else
|
||||
echo "Signing key will be generated on first Synapse start"
|
||||
fi
|
||||
|
||||
# Generate secrets if not set
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " Required Environment Variables"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo "Add these to your .env file (generate secure values!):"
|
||||
echo ""
|
||||
|
||||
# Generate random secrets for display
|
||||
echo "SYNAPSE_DB_PASSWORD=$(openssl rand -base64 24)"
|
||||
echo "SYNAPSE_PASSWORD_PEPPER=$(openssl rand -base64 32)"
|
||||
echo "SYNAPSE_FORM_SECRET=$(openssl rand -base64 32)"
|
||||
echo "SYNAPSE_MACAROON_SECRET=$(openssl rand -base64 32)"
|
||||
echo "SYNAPSE_REGISTRATION_SECRET=$(openssl rand -base64 32)"
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " Cloudflare Tunnel Configuration"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo "Add these ingress rules to ~/.cloudflared/config.yml:"
|
||||
echo ""
|
||||
echo " - hostname: matrix.mana.how"
|
||||
echo " service: http://localhost:8008"
|
||||
echo ""
|
||||
echo " - hostname: element.mana.how"
|
||||
echo " service: http://localhost:8087"
|
||||
echo ""
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " Next Steps"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo "1. Add environment variables to .env file"
|
||||
echo "2. Update Cloudflare Tunnel config"
|
||||
echo "3. Start Matrix services:"
|
||||
echo " docker compose -f docker-compose.macmini.yml up -d synapse element-web"
|
||||
echo ""
|
||||
echo "4. Wait for Synapse to start (check logs):"
|
||||
echo " docker logs -f mana-synapse"
|
||||
echo ""
|
||||
echo "5. Create admin user:"
|
||||
echo " docker exec -it mana-synapse register_new_matrix_user \\"
|
||||
echo " -c /data/homeserver.yaml http://localhost:8008 -a"
|
||||
echo ""
|
||||
echo "6. Test endpoints:"
|
||||
echo " curl https://matrix.mana.how/health"
|
||||
echo " open https://element.mana.how"
|
||||
echo ""
|
||||
echo -e "${GREEN}Setup complete!${NC}"
|
||||
|
|
@ -1,160 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Register and setup Matrix TTS Bot
|
||||
# Run this after Matrix Synapse is running
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
echo "============================================"
|
||||
echo " Matrix TTS Bot Setup"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
|
||||
# Default values
|
||||
HOMESERVER_URL="${MATRIX_HOMESERVER_URL:-http://localhost:8008}"
|
||||
BOT_USERNAME="tts"
|
||||
BOT_DISPLAY_NAME="TTS"
|
||||
|
||||
# Check if Synapse is running
|
||||
echo "Checking Synapse..."
|
||||
if ! curl -s "${HOMESERVER_URL}/health" > /dev/null 2>&1; then
|
||||
echo -e "${RED}Error: Synapse is not reachable at ${HOMESERVER_URL}${NC}"
|
||||
echo "Start it with: docker compose -f docker-compose.macmini.yml up -d synapse"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}Synapse is running${NC}"
|
||||
echo ""
|
||||
|
||||
# Check if registration secret is available
|
||||
if [ -z "$SYNAPSE_REGISTRATION_SECRET" ]; then
|
||||
echo -e "${YELLOW}SYNAPSE_REGISTRATION_SECRET not set.${NC}"
|
||||
echo "Please provide the registration secret from your .env file:"
|
||||
read -sp "Registration Secret: " SYNAPSE_REGISTRATION_SECRET
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Generate bot password
|
||||
BOT_PASSWORD=$(openssl rand -base64 24)
|
||||
|
||||
echo "Registering bot user @${BOT_USERNAME}..."
|
||||
|
||||
# Generate HMAC for registration
|
||||
generate_mac() {
|
||||
local nonce=$1
|
||||
local user=$2
|
||||
local password=$3
|
||||
local user_type=$4
|
||||
local admin=$5
|
||||
|
||||
local mac_input="${nonce}\x00${user}\x00${password}\x00${user_type}\x00${admin}"
|
||||
echo -n "$mac_input" | openssl dgst -sha1 -hmac "$SYNAPSE_REGISTRATION_SECRET" | cut -d' ' -f2
|
||||
}
|
||||
|
||||
# Get nonce
|
||||
NONCE=$(curl -s "${HOMESERVER_URL}/_synapse/admin/v1/register" | jq -r '.nonce')
|
||||
|
||||
if [ -z "$NONCE" ] || [ "$NONCE" = "null" ]; then
|
||||
echo -e "${RED}Failed to get registration nonce. Is admin registration enabled?${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Calculate MAC
|
||||
MAC=$(generate_mac "$NONCE" "$BOT_USERNAME" "$BOT_PASSWORD" "bot" "false")
|
||||
|
||||
# Register user
|
||||
REGISTER_RESPONSE=$(curl -s -X POST "${HOMESERVER_URL}/_synapse/admin/v1/register" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"nonce\": \"${NONCE}\",
|
||||
\"username\": \"${BOT_USERNAME}\",
|
||||
\"password\": \"${BOT_PASSWORD}\",
|
||||
\"displayname\": \"${BOT_DISPLAY_NAME}\",
|
||||
\"user_type\": \"bot\",
|
||||
\"admin\": false,
|
||||
\"mac\": \"${MAC}\"
|
||||
}")
|
||||
|
||||
# Check if registration was successful
|
||||
if echo "$REGISTER_RESPONSE" | jq -e '.access_token' > /dev/null 2>&1; then
|
||||
ACCESS_TOKEN=$(echo "$REGISTER_RESPONSE" | jq -r '.access_token')
|
||||
USER_ID=$(echo "$REGISTER_RESPONSE" | jq -r '.user_id')
|
||||
|
||||
echo -e "${GREEN}Bot registered successfully!${NC}"
|
||||
echo ""
|
||||
echo -e "${CYAN}User ID:${NC} ${USER_ID}"
|
||||
echo ""
|
||||
else
|
||||
ERROR=$(echo "$REGISTER_RESPONSE" | jq -r '.error // .errcode // "Unknown error"')
|
||||
|
||||
# Check if user already exists
|
||||
if echo "$ERROR" | grep -qi "user.*exists\|already.*registered\|M_USER_IN_USE"; then
|
||||
echo -e "${YELLOW}User @${BOT_USERNAME} already exists. Getting access token via login...${NC}"
|
||||
|
||||
echo "Please enter the existing bot password:"
|
||||
read -sp "Password: " EXISTING_PASSWORD
|
||||
echo ""
|
||||
|
||||
LOGIN_RESPONSE=$(curl -s -X POST "${HOMESERVER_URL}/_matrix/client/r0/login" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"type\": \"m.login.password\",
|
||||
\"user\": \"${BOT_USERNAME}\",
|
||||
\"password\": \"${EXISTING_PASSWORD}\"
|
||||
}")
|
||||
|
||||
if echo "$LOGIN_RESPONSE" | jq -e '.access_token' > /dev/null 2>&1; then
|
||||
ACCESS_TOKEN=$(echo "$LOGIN_RESPONSE" | jq -r '.access_token')
|
||||
USER_ID=$(echo "$LOGIN_RESPONSE" | jq -r '.user_id')
|
||||
echo -e "${GREEN}Login successful!${NC}"
|
||||
else
|
||||
echo -e "${RED}Login failed. Please check the password.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo -e "${RED}Registration failed: ${ERROR}${NC}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " Add to .env file"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo -e "${CYAN}# Matrix TTS Bot${NC}"
|
||||
echo "MATRIX_TTS_BOT_TOKEN=${ACCESS_TOKEN}"
|
||||
echo ""
|
||||
|
||||
# Optional: Set display name and avatar
|
||||
echo "Setting display name..."
|
||||
curl -s -X PUT "${HOMESERVER_URL}/_matrix/client/r0/profile/${USER_ID}/displayname" \
|
||||
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"displayname\": \"🔊 ${BOT_DISPLAY_NAME}\"}" > /dev/null
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " Next Steps"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo "1. Add the MATRIX_TTS_BOT_TOKEN to your .env file"
|
||||
echo ""
|
||||
echo "2. Build the bot image:"
|
||||
echo " docker build -t matrix-tts-bot ./services/matrix-tts-bot"
|
||||
echo ""
|
||||
echo "3. Start the bot:"
|
||||
echo " docker compose -f docker-compose.macmini.yml up -d matrix-tts-bot"
|
||||
echo ""
|
||||
echo "4. Invite the bot to a room in Element:"
|
||||
echo " /invite @tts:mana.how"
|
||||
echo ""
|
||||
echo -e "${GREEN}Setup complete!${NC}"
|
||||
|
|
@ -110,7 +110,7 @@ log "Docker CLI connected"
|
|||
|
||||
# ─── Restore named volumes if missing ───
|
||||
BACKUP_DIR="/Volumes/ManaData/backups/docker-migration-20260328"
|
||||
for vol in mana-redis-data mana-victoria-data mana-alertmanager-data mana-grafana-data mana-analytics-data mana-loki-data mana-matrix-bots-data; do
|
||||
for vol in mana-redis-data mana-victoria-data mana-alertmanager-data mana-grafana-data mana-analytics-data mana-loki-data; do
|
||||
if ! docker volume inspect "$vol" >/dev/null 2>&1; then
|
||||
BACKUP_FILE="$BACKUP_DIR/${vol}.tar.gz"
|
||||
if [ -f "$BACKUP_FILE" ]; then
|
||||
|
|
@ -137,11 +137,6 @@ log "Starting Docker containers..."
|
|||
cd "$PROJECT_ROOT"
|
||||
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d --no-build 2>&1 | tee -a "$LOG_FILE"
|
||||
|
||||
# ─── Force-recreate stateful containers that cache config ───
|
||||
# synapse copies homeserver.yaml at startup; stale container uses old cached config
|
||||
log "Force-recreating config-sensitive containers..."
|
||||
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d --no-build --force-recreate synapse 2>&1 | tee -a "$LOG_FILE"
|
||||
|
||||
# ─── Wait and verify ───
|
||||
log "Waiting 45s for services to initialize..."
|
||||
sleep 45
|
||||
|
|
@ -155,12 +150,4 @@ for db in mana_auth mana_credits chat todo calendar clock contacts storage umami
|
|||
docker exec mana-infra-postgres psql -U postgres -c "CREATE DATABASE $db;" 2>/dev/null || true
|
||||
done
|
||||
|
||||
# Matrix Synapse: needs its own user and C-locale database
|
||||
docker exec mana-infra-postgres psql -U postgres -c \
|
||||
"DO \$\$ BEGIN IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname='synapse') THEN CREATE USER synapse WITH PASSWORD 'synapse-secure-password'; END IF; END \$\$;" \
|
||||
2>/dev/null || true
|
||||
docker exec mana-infra-postgres psql -U postgres -c \
|
||||
"CREATE DATABASE matrix OWNER synapse ENCODING UTF8 LC_COLLATE='C' LC_CTYPE='C' TEMPLATE template0;" \
|
||||
2>/dev/null || true
|
||||
|
||||
log "=== Startup Complete ($RUNNING containers running) ==="
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue