120 lines
3.1 KiB
Bash
Executable File
120 lines
3.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
|
||
# ===== CONFIG =====
|
||
BACKEND_DIR="${BACKEND_DIR:-sociowire-backend}"
|
||
|
||
cd "$BACKEND_DIR"
|
||
|
||
echo "[1/2] Write auth_refresh.go"
|
||
cat > auth_refresh.go <<'GO'
|
||
package main
|
||
|
||
import (
|
||
"encoding/json"
|
||
"io"
|
||
"net/http"
|
||
"net/url"
|
||
"os"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
func refreshHandler(w http.ResponseWriter, r *http.Request) {
|
||
setCommonHeaders(w)
|
||
|
||
if r.Method == http.MethodOptions {
|
||
w.WriteHeader(http.StatusNoContent)
|
||
return
|
||
}
|
||
if r.Method != http.MethodPost {
|
||
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
||
return
|
||
}
|
||
|
||
type req struct {
|
||
RefreshToken string `json:"refresh_token"`
|
||
}
|
||
var body req
|
||
_ = json.NewDecoder(r.Body).Decode(&body)
|
||
|
||
rt := strings.TrimSpace(body.RefreshToken)
|
||
if rt == "" {
|
||
http.Error(w, "refresh_token required", http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
kcURL := strings.TrimRight(strings.TrimSpace(os.Getenv("KEYCLOAK_URL")), "/")
|
||
realm := strings.TrimSpace(os.Getenv("KEYCLOAK_REALM"))
|
||
clientID := strings.TrimSpace(os.Getenv("KC_PUBLIC_CLIENT_ID"))
|
||
clientSecret := strings.TrimSpace(os.Getenv("KC_PUBLIC_CLIENT_SECRET"))
|
||
|
||
if kcURL == "" || realm == "" || clientID == "" {
|
||
http.Error(w, "keycloak env missing", http.StatusBadGateway)
|
||
return
|
||
}
|
||
|
||
tokenURL := kcURL + "/realms/" + realm + "/protocol/openid-connect/token"
|
||
|
||
form := url.Values{}
|
||
form.Set("grant_type", "refresh_token")
|
||
form.Set("client_id", clientID)
|
||
form.Set("refresh_token", rt)
|
||
if clientSecret != "" {
|
||
form.Set("client_secret", clientSecret)
|
||
}
|
||
|
||
req2, _ := http.NewRequest("POST", tokenURL, strings.NewReader(form.Encode()))
|
||
req2.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||
|
||
client := &http.Client{Timeout: 8 * time.Second}
|
||
resp, err := client.Do(req2)
|
||
if err != nil {
|
||
http.Error(w, "keycloak refresh error", http.StatusBadGateway)
|
||
return
|
||
}
|
||
defer resp.Body.Close()
|
||
|
||
raw, _ := io.ReadAll(resp.Body)
|
||
if resp.StatusCode != 200 {
|
||
w.Header().Set("Content-Type", "application/json")
|
||
w.WriteHeader(http.StatusUnauthorized)
|
||
_, _ = w.Write(raw)
|
||
return
|
||
}
|
||
|
||
w.Header().Set("Content-Type", "application/json")
|
||
_, _ = w.Write(raw)
|
||
}
|
||
GO
|
||
|
||
echo "[2/2] Patch main.go to add /api/refresh route"
|
||
if ! grep -q '"/api/refresh"' main.go; then
|
||
# Insert after /api/login line if present, else near auth routes block
|
||
# This is a simple awk insert.
|
||
awk '
|
||
{print}
|
||
/mux\.HandleFunc\("\/api\/login", loginHandler\)/ {
|
||
print "\tmux.HandleFunc(\"/api/refresh\", refreshHandler)"
|
||
}
|
||
' main.go > main.go.tmp
|
||
|
||
# If insertion didn’t happen (no match), append under auth routes area:
|
||
if ! grep -q '"/api/refresh"' main.go.tmp; then
|
||
awk '
|
||
{print}
|
||
/mux\.HandleFunc\("\/api\/login", loginHandler\)/==0 && /\/\/ Auth\/debug/ {
|
||
# no-op marker
|
||
}
|
||
' main.go.tmp > /dev/null 2>&1 || true
|
||
# fallback: append near other routes (safe)
|
||
sed -i 's|mux.HandleFunc("/api/login", loginHandler)|mux.HandleFunc("/api/login", loginHandler)\n\tmux.HandleFunc("/api/refresh", refreshHandler)|' main.go.tmp || true
|
||
fi
|
||
|
||
mv main.go.tmp main.go
|
||
else
|
||
echo "main.go already has /api/refresh"
|
||
fi
|
||
|
||
echo "DONE backend patch."
|