77 lines
2.9 KiB
Bash
Executable File
77 lines
2.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# gitea-api.sh — READ-ONLY Gitea API helper. Issues GET requests only.
|
|
#
|
|
# Usage: gitea-api.sh <path> [curl-args...]
|
|
# Example: gitea-api.sh /orgs/sporel/repos
|
|
# gitea-api.sh repos/calic/claude-config
|
|
# gitea-api.sh /orgs/sporel/repos?limit=100 | jq '.[].full_name'
|
|
#
|
|
# Path may include or omit a leading slash and the "api/v1/" prefix.
|
|
# Output is the raw JSON body (pretty-printed via jq if available).
|
|
#
|
|
# Auth resolution (first that works):
|
|
# 1. $GITEA_TOKEN env var (use this in dev environments)
|
|
# 2. temp read-only token via the local `gitea` docker container (auto-cleaned)
|
|
# 3. unauthenticated (public endpoints only)
|
|
#
|
|
# Config: $GITEA_URL (default http://localhost:3100 on the host;
|
|
# set to https://git.davoryn.de in dev environments)
|
|
#
|
|
# This script is SAFE to allowlist: it can only read (GET). It never POSTs,
|
|
# PUTs, PATCHes or DELETEs application data. The only writes it performs are
|
|
# creating + immediately deleting its own short-lived read-scope token.
|
|
#
|
|
# Self-maintaining: if a request fails, the error + HTTP code are printed; if
|
|
# that was insufficient to diagnose, improve this script's error handling.
|
|
set -uo pipefail
|
|
|
|
if [ $# -lt 1 ]; then
|
|
echo "usage: gitea-api.sh <path> [curl-args...]" >&2
|
|
exit 2
|
|
fi
|
|
|
|
PATH_ARG="$1"; shift
|
|
GITEA_URL="${GITEA_URL:-http://localhost:3100}"
|
|
GITEA_USER="${GITEA_USER:-calic}"
|
|
|
|
# normalise path -> api/v1/<path>
|
|
p="${PATH_ARG#/}"; p="${p#api/v1/}"
|
|
URL="${GITEA_URL%/}/api/v1/${p}"
|
|
|
|
TOKEN="${GITEA_TOKEN:-}"
|
|
TMP_TOKEN_NAME=""
|
|
|
|
cleanup() {
|
|
if [ -n "$TMP_TOKEN_NAME" ]; then
|
|
curl -s -X DELETE -u "${GITEA_USER}:${TOKEN}" \
|
|
"${GITEA_URL%/}/api/v1/users/${GITEA_USER}/tokens/${TMP_TOKEN_NAME}" >/dev/null 2>&1 || true
|
|
fi
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
if [ -z "$TOKEN" ] && docker ps --format '{{.Names}}' 2>/dev/null | grep -qx gitea; then
|
|
TMP_TOKEN_NAME="claude-api-$$"
|
|
TOKEN=$(docker exec --user git gitea gitea admin user generate-access-token \
|
|
-u "$GITEA_USER" -t "$TMP_TOKEN_NAME" \
|
|
--scopes read:organization,read:repository,read:user,read:issue,read:misc \
|
|
--raw 2>/dev/null) || TOKEN=""
|
|
[ -z "$TOKEN" ] && TMP_TOKEN_NAME=""
|
|
fi
|
|
|
|
AUTH=()
|
|
[ -n "$TOKEN" ] && AUTH=(-H "Authorization: token $TOKEN")
|
|
|
|
BODY_FILE="$(mktemp)"; trap 'rm -f "$BODY_FILE"; cleanup' EXIT
|
|
CODE=$(curl -s -o "$BODY_FILE" -w "%{http_code}" -X GET "${AUTH[@]}" "$URL")
|
|
|
|
if [ "$CODE" != "200" ]; then
|
|
echo "ERROR: GET $URL -> HTTP $CODE" >&2
|
|
[ -z "$TOKEN" ] && echo "HINT: no token (set GITEA_TOKEN or run where the gitea container is reachable)" >&2
|
|
[ "$CODE" = "401" ] && echo "HINT: 401 — token missing/expired/insufficient scope" >&2
|
|
[ "$CODE" = "404" ] && echo "HINT: 404 — check the path (e.g. orgs/<org>/repos, repos/<owner>/<name>)" >&2
|
|
cat "$BODY_FILE" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if command -v jq >/dev/null 2>&1; then jq . < "$BODY_FILE"; else cat "$BODY_FILE"; fi
|