Files
platform/scripts/provision-existing-users.sh
T
pastilhas e43f738a52 fix: update provision-existing-users.sh to use chmod 775 (was 770)
Consistency fix with src/servers/api/users/provision.ts which was updated to use:
- chmod 775 (rwxrwxr-x) instead of 770 (rwxrwx---)
- Recursive chmod to fix all subdirectories

This allows the service user (in the user's group) to read/write files
for background jobs like email sync.

Also added helpful comment explaining the permission choice.
2026-03-04 02:59:06 +00:00

183 lines
5.8 KiB
Bash
Executable File

#!/bin/bash
# One-time migration: provision Linux users for existing database members.
# Reads users from PostgreSQL, skips Super Admins (they use the service account),
# and creates Linux users + seeds shell configs for everyone else.
#
# Usage: bash scripts/provision-existing-users.sh
# Requires: sudoers entry from setup.sh, POSTGRES_URL in .env
set -euo pipefail
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
ok() { echo -e " ${GREEN}${NC} $1"; }
warn() { echo -e " ${YELLOW}!${NC} $1"; }
fail() { echo -e " ${RED}${NC} $1"; }
skip() { echo -e " - $1 (skipped)"; }
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
ENV_FILE="$PROJECT_DIR/.env"
TEMPLATE_DIR="$PROJECT_DIR/src/servers/api/terminal/templates"
# Load .env
if [ ! -f "$ENV_FILE" ]; then
fail ".env not found at $ENV_FILE"
exit 1
fi
source <(grep -E '^[A-Z_]+=.*' "$ENV_FILE" | sed 's/^/export /')
# Resolve DATA_PATH
DATA_PATH="${DATA_PATH:-$PROJECT_DIR/data}"
# Parse POSTGRES_URL for psql
if [ -z "${POSTGRES_URL:-}" ]; then
fail "POSTGRES_URL not set in .env"
exit 1
fi
# Extract components from postgresql://user:pass@host:port/dbname
PG_USER=$(echo "$POSTGRES_URL" | sed -n 's|.*://\([^:]*\):.*|\1|p')
PG_PASS=$(echo "$POSTGRES_URL" | sed -n 's|.*://[^:]*:\([^@]*\)@.*|\1|p')
PG_HOST=$(echo "$POSTGRES_URL" | sed -n 's|.*@\([^:]*\):.*|\1|p')
PG_PORT=$(echo "$POSTGRES_URL" | sed -n 's|.*:\([0-9]*\)/.*|\1|p')
PG_DB=$(echo "$POSTGRES_URL" | sed -n 's|.*/\([^?]*\).*|\1|p')
echo ""
echo "═══════════════════════════════════════════"
echo " Provision existing users"
echo "═══════════════════════════════════════════"
echo ""
echo "DATA_PATH: $DATA_PATH"
echo "Database: $PG_DB @ $PG_HOST:$PG_PORT"
echo ""
# Query non-Super Admin active users
USERS=$(PGPASSWORD="$PG_PASS" psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d "$PG_DB" -t -A -F '|' \
-c "SELECT email, COALESCE(username, '') FROM users WHERE role != 'Super Admin' AND status = 'Active';" 2>&1)
if [ $? -ne 0 ]; then
fail "Failed to query database: $USERS"
exit 1
fi
if [ -z "$USERS" ]; then
echo "No non-admin active users found. Nothing to do."
exit 0
fi
echo "── Found users ──"
echo "$USERS" | while IFS='|' read -r email username; do
echo " $email (username: ${username:-<from email>})"
done
echo ""
echo "── Provisioning ──"
while IFS='|' read -r email username; do
# Derive shell username (same logic as toShellUsername in data-path.ts)
if [ -n "$username" ]; then
shell_user=$(echo "$username" | sed 's/@.*$//' | sed 's/[^a-zA-Z0-9._-]/_/g' | tr '[:upper:]' '[:lower:]' | cut -c1-32)
else
shell_user=$(echo "$email" | sed 's/@.*$//' | sed 's/[^a-zA-Z0-9._-]/_/g' | tr '[:upper:]' '[:lower:]' | cut -c1-32)
fi
USER_ROOT="$DATA_PATH/$email"
HOME_DIR="$USER_ROOT/home"
echo ""
echo " [$email$shell_user]"
# Ensure data dirs exist (sudo in case dir is owned by a previous provisioning run)
sudo mkdir -p "$USER_ROOT" "$HOME_DIR"
# Create Linux user if needed
if id "$shell_user" &>/dev/null; then
skip "Linux user $shell_user already exists"
else
if sudo useradd -d "$HOME_DIR" -s /bin/zsh -M "$shell_user"; then
ok "Created Linux user $shell_user"
else
fail "Failed to create Linux user $shell_user"
continue
fi
fi
# Seed shell configs (only if not already present)
if [ ! -f "$HOME_DIR/.zshenv" ] && [ -f "$TEMPLATE_DIR/.zshenv" ]; then
sudo cp "$TEMPLATE_DIR/.zshenv" "$HOME_DIR/.zshenv"
ok "Seeded .zshenv"
else
skip ".zshenv"
fi
if [ ! -f "$HOME_DIR/.zshrc" ] && [ -f "$TEMPLATE_DIR/.zshrc" ]; then
sudo cp "$TEMPLATE_DIR/.zshrc" "$HOME_DIR/.zshrc"
ok "Seeded .zshrc"
else
skip ".zshrc"
fi
if [ ! -f "$HOME_DIR/.tmux.conf" ] && [ -f "$TEMPLATE_DIR/.tmux.conf" ]; then
sudo cp "$TEMPLATE_DIR/.tmux.conf" "$HOME_DIR/.tmux.conf"
ok "Seeded .tmux.conf"
else
skip ".tmux.conf"
fi
sudo mkdir -p "$HOME_DIR/.config"
if [ ! -f "$HOME_DIR/.config/starship-officer.toml" ] && [ -f "$TEMPLATE_DIR/starship-officer.toml" ]; then
sudo cp "$TEMPLATE_DIR/starship-officer.toml" "$HOME_DIR/.config/starship-officer.toml"
ok "Seeded starship config"
else
skip "starship config"
fi
# Oh My Zsh
if [ ! -d "$HOME_DIR/.oh-my-zsh" ]; then
if [ -d "$HOME/.oh-my-zsh" ]; then
sudo cp -r "$HOME/.oh-my-zsh" "$HOME_DIR/.oh-my-zsh"
ok "Copied oh-my-zsh from host"
fi
else
skip "oh-my-zsh"
fi
# LazyVim
sudo mkdir -p "$HOME_DIR/.config"
if [ ! -d "$HOME_DIR/.config/nvim" ]; then
if [ -d "$HOME/.config/nvim" ]; then
sudo cp -r "$HOME/.config/nvim" "$HOME_DIR/.config/nvim"
ok "Copied nvim config from host"
fi
else
skip "nvim config"
fi
# Ensure dirs
sudo mkdir -p "$HOME_DIR/.local/bin"
sudo mkdir -p "$HOME_DIR/.pi/agent/sessions"
# Set ownership and permissions last
# chmod 775 so the service user (in the user's group) can read/write for background jobs
sudo chown -R "$shell_user:$shell_user" "$USER_ROOT"
sudo chmod -R 775 "$USER_ROOT"
# Add service user to this user's group so server jobs can access user data
SERVICE_USER="${SUDO_USER:-$(whoami)}"
if [ "$SERVICE_USER" != "$shell_user" ]; then
sudo usermod -aG "$shell_user" "$SERVICE_USER"
ok "Added $SERVICE_USER to group $shell_user"
fi
ok "Provisioning complete"
done <<< "$USERS"
echo ""
echo "═══════════════════════════════════════════"
echo " Done!"
echo "═══════════════════════════════════════════"
echo ""