Major additions across backend, frontend, and infrastructure: Backend: - IoT collector framework (Modbus TCP, MQTT, HTTP) with manager - Realistic Beijing solar/weather simulator with cloud transients - Alarm auto-checker with demo anomaly injection (3-4 events/hour) - Report generation (PDF/Excel) with sync fallback and E2E testing - Energy data CSV/XLSX export endpoint - WebSocket real-time broadcast at /ws/realtime - Alembic initial migration for all 14 tables - 77 pytest tests across 9 API routers Frontend: - Live notification badge with alarm count (was hardcoded 0) - Sankey energy flow diagram on dashboard - Device photos (SVG illustrations) on all device pages - Report download with status icons - Energy data export buttons (CSV/Excel) - WebSocket hook with auto-reconnect and polling fallback - BigScreen 2D responsive CSS (tablet/mobile) - Error handling improvements across pages Infrastructure: - PostgreSQL + TimescaleDB as primary database - Production docker-compose with nginx reverse proxy - Comprehensive Chinese README - .env.example with documentation - quick-start.sh deployment script - nginx config with gzip, caching, security headers Data: - 30-day realistic backfill (47K rows, weather-correlated) - 18 devices, 6 alarm rules, 15 historical alarm events - Beijing solar position model with seasonal variation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
270 lines
8.9 KiB
Bash
270 lines
8.9 KiB
Bash
#!/bin/bash
|
|
# ============================================================
|
|
# Gitea Organization & Team Setup Script
|
|
# Run this after Gitea is back online (currently 502)
|
|
#
|
|
# Usage:
|
|
# 1. Edit the USERS array below with your colleagues' info
|
|
# 2. Generate an admin API token from Gitea Web UI:
|
|
# -> Profile -> Settings -> Applications -> Generate Token
|
|
# 3. Run: bash scripts/gitea_setup_team.sh
|
|
# ============================================================
|
|
|
|
GITEA_URL="http://100.108.180.60:3300"
|
|
ADMIN_TOKEN="" # <-- Paste your admin token here
|
|
|
|
ORG_NAME="tianpu"
|
|
ORG_DISPLAY="天普零碳园区"
|
|
REPO_NAME="tianpu-ems"
|
|
|
|
# ============================================================
|
|
# Define your colleagues here
|
|
# Format: "username:email:fullname:team"
|
|
# team = developers | readonly
|
|
# ============================================================
|
|
USERS=(
|
|
"zhangsan:zhangsan@example.com:张三:developers"
|
|
"lisi:lisi@example.com:李四:developers"
|
|
"wangwu:wangwu@example.com:王五:developers"
|
|
"zhaoliu:zhaoliu@example.com:赵六:readonly"
|
|
# Add more as needed...
|
|
)
|
|
|
|
DEFAULT_PASSWORD="Tianpu@2026" # Users must change on first login
|
|
|
|
# ============================================================
|
|
# Color output helpers
|
|
# ============================================================
|
|
GREEN='\033[0;32m'
|
|
RED='\033[0;31m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
info() { echo -e "${GREEN}[OK]${NC} $1"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
|
|
API="$GITEA_URL/api/v1"
|
|
AUTH="Authorization: token $ADMIN_TOKEN"
|
|
|
|
# ============================================================
|
|
# Pre-flight check
|
|
# ============================================================
|
|
if [ -z "$ADMIN_TOKEN" ]; then
|
|
error "Please set ADMIN_TOKEN first!"
|
|
echo ""
|
|
echo " Steps to get a token:"
|
|
echo " 1. Open $GITEA_URL in your browser"
|
|
echo " 2. Login as admin (tianpu)"
|
|
echo " 3. Go to: Settings -> Applications -> Generate New Token"
|
|
echo " 4. Name: 'admin-setup', Scopes: check ALL"
|
|
echo " 5. Copy the token and paste it into this script"
|
|
exit 1
|
|
fi
|
|
|
|
echo "============================================"
|
|
echo " Gitea Team Setup - $ORG_DISPLAY"
|
|
echo "============================================"
|
|
echo ""
|
|
|
|
# Check Gitea is alive
|
|
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 "$GITEA_URL")
|
|
if [ "$HTTP_CODE" != "200" ]; then
|
|
error "Gitea returned HTTP $HTTP_CODE. Is it running?"
|
|
exit 1
|
|
fi
|
|
info "Gitea is online"
|
|
|
|
# ============================================================
|
|
# Step 1: Create Organization (idempotent)
|
|
# ============================================================
|
|
echo ""
|
|
echo "--- Step 1: Organization ---"
|
|
|
|
ORG_CHECK=$(curl -s -w "\n%{http_code}" -H "$AUTH" "$API/orgs/$ORG_NAME")
|
|
ORG_HTTP=$(echo "$ORG_CHECK" | tail -1)
|
|
|
|
if [ "$ORG_HTTP" = "200" ]; then
|
|
info "Organization '$ORG_NAME' already exists"
|
|
else
|
|
RESULT=$(curl -s -w "\n%{http_code}" -X POST "$API/orgs" \
|
|
-H "$AUTH" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"username\": \"$ORG_NAME\",
|
|
\"full_name\": \"$ORG_DISPLAY\",
|
|
\"description\": \"天普零碳园区智慧能源管理\",
|
|
\"visibility\": \"private\"
|
|
}")
|
|
HTTP=$(echo "$RESULT" | tail -1)
|
|
if [ "$HTTP" = "201" ]; then
|
|
info "Created organization '$ORG_NAME'"
|
|
else
|
|
error "Failed to create org (HTTP $HTTP)"
|
|
echo "$RESULT" | head -1
|
|
fi
|
|
fi
|
|
|
|
# ============================================================
|
|
# Step 2: Create Teams
|
|
# ============================================================
|
|
echo ""
|
|
echo "--- Step 2: Teams ---"
|
|
|
|
create_team() {
|
|
local TEAM_NAME=$1
|
|
local PERMISSION=$2
|
|
local DESCRIPTION=$3
|
|
|
|
TEAM_CHECK=$(curl -s -w "\n%{http_code}" -H "$AUTH" "$API/orgs/$ORG_NAME/teams")
|
|
EXISTING=$(echo "$TEAM_CHECK" | head -1 | python3 -c "
|
|
import sys, json
|
|
try:
|
|
teams = json.load(sys.stdin)
|
|
for t in teams:
|
|
if t['name'] == '$TEAM_NAME':
|
|
print(t['id'])
|
|
break
|
|
except: pass
|
|
" 2>/dev/null)
|
|
|
|
if [ -n "$EXISTING" ]; then
|
|
info "Team '$TEAM_NAME' already exists (id=$EXISTING)"
|
|
echo "$EXISTING"
|
|
return
|
|
fi
|
|
|
|
RESULT=$(curl -s -w "\n%{http_code}" -X POST "$API/orgs/$ORG_NAME/teams" \
|
|
-H "$AUTH" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"name\": \"$TEAM_NAME\",
|
|
\"description\": \"$DESCRIPTION\",
|
|
\"permission\": \"$PERMISSION\",
|
|
\"includes_all_repositories\": true,
|
|
\"units\": [\"repo.code\", \"repo.issues\", \"repo.pulls\", \"repo.releases\", \"repo.wiki\"]
|
|
}")
|
|
HTTP=$(echo "$RESULT" | tail -1)
|
|
TEAM_ID=$(echo "$RESULT" | head -1 | python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" 2>/dev/null)
|
|
|
|
if [ "$HTTP" = "201" ]; then
|
|
info "Created team '$TEAM_NAME' (id=$TEAM_ID)"
|
|
echo "$TEAM_ID"
|
|
else
|
|
error "Failed to create team '$TEAM_NAME' (HTTP $HTTP)"
|
|
echo "$RESULT" | head -1
|
|
fi
|
|
}
|
|
|
|
DEV_TEAM_ID=$(create_team "developers" "write" "开发团队 - 可读写代码、提PR、管理Issues")
|
|
RO_TEAM_ID=$(create_team "readonly" "read" "只读团队 - 仅可查看代码和Issues")
|
|
|
|
# ============================================================
|
|
# Step 3: Fork/transfer repo to org (or add repo to teams)
|
|
# ============================================================
|
|
echo ""
|
|
echo "--- Step 3: Repository ---"
|
|
|
|
# Check if repo already exists under org
|
|
REPO_CHECK=$(curl -s -w "\n%{http_code}" -H "$AUTH" "$API/repos/$ORG_NAME/$REPO_NAME")
|
|
REPO_HTTP=$(echo "$REPO_CHECK" | tail -1)
|
|
|
|
if [ "$REPO_HTTP" = "200" ]; then
|
|
info "Repo '$ORG_NAME/$REPO_NAME' already exists under organization"
|
|
else
|
|
warn "Repo not found under org. You have two options:"
|
|
echo ""
|
|
echo " Option A: Transfer existing repo to org (recommended)"
|
|
echo " Go to: $GITEA_URL/tianpu/$REPO_NAME/settings"
|
|
echo " -> Danger Zone -> Transfer Repository -> new owner: $ORG_NAME"
|
|
echo ""
|
|
echo " Option B: Change remote URL after transfer:"
|
|
echo " git remote set-url origin $GITEA_URL/$ORG_NAME/$REPO_NAME.git"
|
|
echo ""
|
|
echo " After transfer, re-run this script to add repo to teams."
|
|
fi
|
|
|
|
# Add repo to teams (if repo exists under org)
|
|
if [ "$REPO_HTTP" = "200" ]; then
|
|
for TEAM_ID in $DEV_TEAM_ID $RO_TEAM_ID; do
|
|
if [ -n "$TEAM_ID" ] && [[ "$TEAM_ID" =~ ^[0-9]+$ ]]; then
|
|
curl -s -X PUT "$API/teams/$TEAM_ID/repos/$ORG_NAME/$REPO_NAME" \
|
|
-H "$AUTH" > /dev/null 2>&1
|
|
info "Added repo to team id=$TEAM_ID"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# ============================================================
|
|
# Step 4: Create Users & Add to Teams
|
|
# ============================================================
|
|
echo ""
|
|
echo "--- Step 4: Users ---"
|
|
|
|
for USER_ENTRY in "${USERS[@]}"; do
|
|
IFS=':' read -r USERNAME EMAIL FULLNAME TEAM <<< "$USER_ENTRY"
|
|
|
|
# Create user
|
|
USER_CHECK=$(curl -s -w "\n%{http_code}" -H "$AUTH" "$API/users/$USERNAME")
|
|
USER_HTTP=$(echo "$USER_CHECK" | tail -1)
|
|
|
|
if [ "$USER_HTTP" = "200" ]; then
|
|
info "User '$USERNAME' already exists"
|
|
else
|
|
RESULT=$(curl -s -w "\n%{http_code}" -X POST "$API/admin/users" \
|
|
-H "$AUTH" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"username\": \"$USERNAME\",
|
|
\"email\": \"$EMAIL\",
|
|
\"full_name\": \"$FULLNAME\",
|
|
\"password\": \"$DEFAULT_PASSWORD\",
|
|
\"must_change_password\": true,
|
|
\"visibility\": \"private\"
|
|
}")
|
|
HTTP=$(echo "$RESULT" | tail -1)
|
|
if [ "$HTTP" = "201" ]; then
|
|
info "Created user '$USERNAME' ($FULLNAME)"
|
|
else
|
|
error "Failed to create user '$USERNAME' (HTTP $HTTP)"
|
|
echo "$RESULT" | head -1
|
|
fi
|
|
fi
|
|
|
|
# Add to team
|
|
if [ "$TEAM" = "developers" ] && [ -n "$DEV_TEAM_ID" ] && [[ "$DEV_TEAM_ID" =~ ^[0-9]+$ ]]; then
|
|
curl -s -X PUT "$API/teams/$DEV_TEAM_ID/members/$USERNAME" -H "$AUTH" > /dev/null 2>&1
|
|
info " -> Added '$USERNAME' to 'developers' team"
|
|
elif [ "$TEAM" = "readonly" ] && [ -n "$RO_TEAM_ID" ] && [[ "$RO_TEAM_ID" =~ ^[0-9]+$ ]]; then
|
|
curl -s -X PUT "$API/teams/$RO_TEAM_ID/members/$USERNAME" -H "$AUTH" > /dev/null 2>&1
|
|
info " -> Added '$USERNAME' to 'readonly' team"
|
|
fi
|
|
done
|
|
|
|
# ============================================================
|
|
# Summary
|
|
# ============================================================
|
|
echo ""
|
|
echo "============================================"
|
|
echo " Setup Complete!"
|
|
echo "============================================"
|
|
echo ""
|
|
echo " Organization: $GITEA_URL/$ORG_NAME"
|
|
echo " Repository: $GITEA_URL/$ORG_NAME/$REPO_NAME"
|
|
echo ""
|
|
echo " Teams:"
|
|
echo " developers (write) - can push, create PRs, manage issues"
|
|
echo " readonly (read) - can view code and issues only"
|
|
echo ""
|
|
echo " Default password: $DEFAULT_PASSWORD"
|
|
echo " (Users must change on first login)"
|
|
echo ""
|
|
echo " Each colleague clones with:"
|
|
echo " git clone $GITEA_URL/$ORG_NAME/$REPO_NAME.git"
|
|
echo ""
|
|
echo " Recommended workflow:"
|
|
echo " 1. Each dev creates a feature branch"
|
|
echo " 2. Push branch, create Pull Request"
|
|
echo " 3. Code review, then merge to main"
|
|
echo "============================================"
|