#!/usr/bin/env bash
# Gives the personal access token a new secret, and saves it in the token
# file, without printing it. The old secret stops working, like one pasted
# into a chat, and the token keeps its ID, abilities, limits and expiration.
# Its user is emailed about it.
#
#   EA_URL=https://your-team.example.com scripts/ea-rotate
#
# The token is read like scripts/ea reads it: from EA_TOKEN, or else the file
# EA_TOKEN_FILE names, ~/.config/engine-awesome/token unless it's set. The new
# secret is saved in that file, which only the user can read, so use the file
# from now on, rather than EA_TOKEN.
#
# It's for tokens kept in that file. Don't rotate a token the agent's platform
# keeps as a secret, as the secret would stop working: make a new token for the
# secret instead, and delete the old one.
#
# Works with the bash 3.2 macOS comes with.
set -eu

: "${EA_URL:?Set EA_URL to your team URL, like https://your-team.example.com}"
: "${EA_TOKEN_FILE:=$HOME/.config/engine-awesome/token}"

from_env=${EA_TOKEN:+1}

if [ -z "${EA_TOKEN:-}" ] && [ -r "$EA_TOKEN_FILE" ]; then
	EA_TOKEN=$(tr -d '[:space:]' <"$EA_TOKEN_FILE")
fi

if [ -z "${EA_TOKEN:-}" ]; then
	echo "There's no token in EA_TOKEN or $EA_TOKEN_FILE to rotate. A token kept as a secret by the agent's platform can't be rotated, as the secret would stop working: make a new token for it instead, and delete the old one." >&2
	exit 2
fi

umask 077
response=$(mktemp)
trap 'rm -f "$response"' EXIT

status=$(curl -sS -X POST -o "$response" -w '%{http_code}' \
	-H "Authorization: Bearer $EA_TOKEN" -H "Accept: application/json" \
	"${EA_URL%/}/api/v1/me/access-token/rotate")

if [ "$status" -ge 400 ]; then
	cat "$response" >&2
	echo >&2
	echo "HTTP $status" >&2
	exit 1
fi

# The secret is `<id>|<letters and numbers>`, so it's found without parsing JSON.
secret=$(grep -o '"plaintext":"[^"]*"' "$response" | sed 's/^"plaintext":"//; s/"$//')

if [ -z "$secret" ]; then
	echo "The response didn't have the new secret." >&2
	exit 1
fi

mkdir -p "$(dirname "$EA_TOKEN_FILE")"
printf '%s\n' "$secret" >"$EA_TOKEN_FILE"
chmod 600 "$EA_TOKEN_FILE"

echo "Gave token ${secret%%|*} a new secret, saved in $EA_TOKEN_FILE. Its old secret no longer works."

if [ -n "$from_env" ]; then
	echo "EA_TOKEN still has the old secret, so unset it, and use the file from now on." >&2
fi
