refactor: merge vendor user into saas-admin
All checks were successful
CI / build (push) Successful in 1m8s
CI / docker (push) Successful in 17s

The admin user IS the platform admin — no separate vendor user needed.
The saas-vendor role is now always assigned to the admin user during
bootstrap. Removes VENDOR_ENABLED, VENDOR_USER, VENDOR_PASS from all
config, prompts, compose templates, and bootstrap script.

In multi-tenant mode: admin logs in with saas-admin credentials, gets
platform:admin scope via saas-vendor role, manages tenants directly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-13 20:36:52 +02:00
parent 4e553a6c42
commit 012c866594
3 changed files with 39 additions and 190 deletions

View File

@@ -28,13 +28,7 @@ API_RESOURCE_NAME="Cameleer SaaS API"
SAAS_ADMIN_USER="${SAAS_ADMIN_USER:-admin}"
SAAS_ADMIN_PASS="${SAAS_ADMIN_PASS:-admin}"
# Vendor seed (optional — creates saas-vendor role + vendor user)
VENDOR_SEED_ENABLED="${VENDOR_SEED_ENABLED:-false}"
VENDOR_USER="${VENDOR_USER:-vendor}"
VENDOR_PASS="${VENDOR_PASS:-vendor}"
VENDOR_NAME="${VENDOR_NAME:-SaaS Vendor}"
# No server config — servers are provisioned dynamically by the vendor console
# No server config — servers are provisioned dynamically by the admin console
# Redirect URIs (derived from PUBLIC_HOST and PUBLIC_PROTOCOL)
HOST="${PUBLIC_HOST:-localhost}"
@@ -92,7 +86,7 @@ for i in $(seq 1 60); do
sleep 1
done
# No server wait — servers are provisioned dynamically by the vendor console
# No server wait — servers are provisioned dynamically by the admin console
# ============================================================
# PHASE 2: Get Management API token
@@ -345,8 +339,7 @@ fi
# ============================================================
# --- Organization roles: owner, operator, viewer ---
# Note: platform-admin / saas-vendor global role is NOT created here.
# It is injected via docker/vendor-seed.sh on the hosted SaaS environment only.
# Note: saas-vendor global role is created in Phase 12 and assigned to the admin user.
log "Creating organization roles..."
EXISTING_ORG_ROLES=$(api_get "/api/organization-roles")
@@ -491,8 +484,8 @@ fi
fi # end: ADMIN_TOKEN check
fi # end: M_ADMIN_SECRET check
# No viewer user — tenant users are created by the vendor during tenant provisioning.
# No example organization — tenants are created via the vendor console.
# No viewer user — tenant users are created by the admin during tenant provisioning.
# No example organization — tenants are created via the admin console.
# No server OIDC config — each provisioned server gets OIDC from env vars.
ORG_ID=""
@@ -583,118 +576,44 @@ EOF
chmod 644 "$BOOTSTRAP_FILE"
# ============================================================
# Phase 12: Vendor Seed (optional)
# Phase 12: SaaS Admin Role
# ============================================================
if [ "$VENDOR_SEED_ENABLED" = "true" ]; then
log ""
log "=== Phase 12a: Vendor Seed ==="
log ""
log "=== Phase 12: SaaS Admin Role ==="
# Create saas-vendor global role with all API scopes
log "Checking for saas-vendor role..."
EXISTING_ROLES=$(api_get "/api/roles")
VENDOR_ROLE_ID=$(echo "$EXISTING_ROLES" | jq -r '.[] | select(.name == "saas-vendor" and .type == "User") | .id')
# Create saas-vendor global role with all API scopes
log "Checking for saas-vendor role..."
EXISTING_ROLES=$(api_get "/api/roles")
VENDOR_ROLE_ID=$(echo "$EXISTING_ROLES" | jq -r '.[] | select(.name == "saas-vendor" and .type == "User") | .id')
if [ -z "$VENDOR_ROLE_ID" ]; then
ALL_SCOPE_IDS=$(api_get "/api/resources/$API_RESOURCE_ID/scopes" | jq '[.[].id]')
log "Creating saas-vendor role with all scopes..."
VENDOR_ROLE_RESPONSE=$(api_post "/api/roles" "{
\"name\": \"saas-vendor\",
\"description\": \"SaaS vendor — full platform control across all tenants\",
\"type\": \"User\",
\"scopeIds\": $ALL_SCOPE_IDS
}")
VENDOR_ROLE_ID=$(echo "$VENDOR_ROLE_RESPONSE" | jq -r '.id')
log "Created saas-vendor role: $VENDOR_ROLE_ID"
else
log "saas-vendor role exists: $VENDOR_ROLE_ID"
fi
# Assign vendor role to admin user
if [ -n "$VENDOR_ROLE_ID" ] && [ "$VENDOR_ROLE_ID" != "null" ] && [ -n "$ADMIN_USER_ID" ]; then
api_post "/api/users/$ADMIN_USER_ID/roles" "{\"roleIds\": [\"$VENDOR_ROLE_ID\"]}" >/dev/null 2>&1
log "Assigned saas-vendor role to admin user."
fi
# Create separate vendor user if credentials provided
if [ -n "$VENDOR_USER" ] && [ "$VENDOR_USER" != "$SAAS_ADMIN_USER" ]; then
log "Checking for vendor user '$VENDOR_USER'..."
VENDOR_USER_ID=$(api_get "/api/users?search=$VENDOR_USER" | jq -r ".[] | select(.username == \"$VENDOR_USER\") | .id")
if [ -z "$VENDOR_USER_ID" ]; then
log "Creating vendor user '$VENDOR_USER'..."
VENDOR_RESPONSE=$(api_post "/api/users" "{
\"username\": \"$VENDOR_USER\",
\"password\": \"$VENDOR_PASS\",
\"name\": \"$VENDOR_NAME\"
}")
VENDOR_USER_ID=$(echo "$VENDOR_RESPONSE" | jq -r '.id')
log "Created vendor user: $VENDOR_USER_ID"
else
log "Vendor user exists: $VENDOR_USER_ID"
fi
# Assign saas-vendor role to vendor user
if [ -n "$VENDOR_ROLE_ID" ] && [ "$VENDOR_ROLE_ID" != "null" ]; then
api_post "/api/users/$VENDOR_USER_ID/roles" "{\"roleIds\": [\"$VENDOR_ROLE_ID\"]}" >/dev/null 2>&1
log "Assigned saas-vendor role to vendor user."
fi
# Add vendor to all existing organizations with owner role
log "Adding vendor to all organizations..."
ORG_OWNER_ROLE_ID=$(api_get "/api/organization-roles" | jq -r '.[] | select(.name == "owner") | .id')
ORGS=$(api_get "/api/organizations")
ORG_COUNT=$(echo "$ORGS" | jq 'length')
for i in $(seq 0 $((ORG_COUNT - 1))); do
SEED_ORG_ID=$(echo "$ORGS" | jq -r ".[$i].id")
SEED_ORG_NAME=$(echo "$ORGS" | jq -r ".[$i].name")
api_post "/api/organizations/$SEED_ORG_ID/users" "{\"userIds\": [\"$VENDOR_USER_ID\"]}" >/dev/null 2>&1
if [ -n "$ORG_OWNER_ROLE_ID" ] && [ "$ORG_OWNER_ROLE_ID" != "null" ]; then
curl -s -X PUT -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" $HOST_ARGS \
-d "{\"organizationRoleIds\": [\"$ORG_OWNER_ROLE_ID\"]}" \
"${LOGTO_ENDPOINT}/api/organizations/$SEED_ORG_ID/users/$VENDOR_USER_ID/roles" >/dev/null 2>&1
fi
log " Added to org '$SEED_ORG_NAME' with owner role."
done
# Grant vendor user Logto console access
if [ -n "$ADMIN_TOKEN" ] && [ "$ADMIN_TOKEN" != "null" ]; then
log "Granting vendor Logto console access..."
VENDOR_CONSOLE_USER_ID=$(admin_api_get "/api/users?search=$VENDOR_USER" | jq -r ".[] | select(.username == \"$VENDOR_USER\") | .id" 2>/dev/null)
if [ -z "$VENDOR_CONSOLE_USER_ID" ] || [ "$VENDOR_CONSOLE_USER_ID" = "null" ]; then
VENDOR_CONSOLE_RESPONSE=$(admin_api_post "/api/users" "{
\"username\": \"$VENDOR_USER\",
\"password\": \"$VENDOR_PASS\",
\"name\": \"$VENDOR_NAME\"
}")
VENDOR_CONSOLE_USER_ID=$(echo "$VENDOR_CONSOLE_RESPONSE" | jq -r '.id')
log "Created vendor console user: $VENDOR_CONSOLE_USER_ID"
else
log "Vendor console user exists: $VENDOR_CONSOLE_USER_ID"
fi
if [ -n "$VENDOR_CONSOLE_USER_ID" ] && [ "$VENDOR_CONSOLE_USER_ID" != "null" ]; then
ADMIN_USER_ROLE_ID=$(admin_api_get "/api/roles" | jq -r '.[] | select(.name == "user") | .id')
ADMIN_ROLE_ID=$(admin_api_get "/api/roles" | jq -r '.[] | select(.name == "default:admin") | .id')
V_ROLE_IDS="[]"
[ -n "$ADMIN_USER_ROLE_ID" ] && [ "$ADMIN_USER_ROLE_ID" != "null" ] && V_ROLE_IDS=$(echo "$V_ROLE_IDS" | jq ". + [\"$ADMIN_USER_ROLE_ID\"]")
[ -n "$ADMIN_ROLE_ID" ] && [ "$ADMIN_ROLE_ID" != "null" ] && V_ROLE_IDS=$(echo "$V_ROLE_IDS" | jq ". + [\"$ADMIN_ROLE_ID\"]")
[ "$V_ROLE_IDS" != "[]" ] && admin_api_post "/api/users/$VENDOR_CONSOLE_USER_ID/roles" "{\"roleIds\": $V_ROLE_IDS}" >/dev/null 2>&1
log "Vendor granted Logto console access."
fi
fi
fi
log "Vendor seed complete."
if [ -z "$VENDOR_ROLE_ID" ]; then
ALL_SCOPE_IDS=$(api_get "/api/resources/$API_RESOURCE_ID/scopes" | jq '[.[].id]')
log "Creating saas-vendor role with all scopes..."
VENDOR_ROLE_RESPONSE=$(api_post "/api/roles" "{
\"name\": \"saas-vendor\",
\"description\": \"SaaS vendor — full platform control across all tenants\",
\"type\": \"User\",
\"scopeIds\": $ALL_SCOPE_IDS
}")
VENDOR_ROLE_ID=$(echo "$VENDOR_ROLE_RESPONSE" | jq -r '.id')
log "Created saas-vendor role: $VENDOR_ROLE_ID"
else
log "saas-vendor role exists: $VENDOR_ROLE_ID"
fi
# Assign vendor role to admin user
if [ -n "$VENDOR_ROLE_ID" ] && [ "$VENDOR_ROLE_ID" != "null" ] && [ -n "$ADMIN_USER_ID" ]; then
api_post "/api/users/$ADMIN_USER_ID/roles" "{\"roleIds\": [\"$VENDOR_ROLE_ID\"]}" >/dev/null 2>&1
log "Assigned saas-vendor role to admin user."
fi
log "SaaS admin role configured."
log ""
log "=== Bootstrap complete! ==="
# dev only — remove credential logging in production
log " SPA Client ID: $SPA_ID"
if [ "$VENDOR_SEED_ENABLED" = "true" ]; then
log " Vendor: $VENDOR_USER / $VENDOR_PASS (role: saas-vendor)"
fi
log ""
log " No tenants created — use the vendor console to create tenants."
log " No tenants created — use the admin console to create tenants."
log ""