153 lines
4.8 KiB
Bash
Executable File
153 lines
4.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
BASE_URL="${BASE_URL:-http://localhost:8888}"
|
|
EMAIL="${EMAIL:-admin@huapont.cn}"
|
|
PASSWORD="${PASSWORD:-admin123}"
|
|
STUDY_ID="${STUDY_ID:-aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa}"
|
|
|
|
echo "[1/6] login: $EMAIL"
|
|
TOKEN=$(BASE_URL="$BASE_URL" EMAIL="$EMAIL" PASSWORD="$PASSWORD" python3 - <<'PY'
|
|
import base64
|
|
import json
|
|
import os
|
|
import urllib.request
|
|
|
|
from cryptography.hazmat.primitives import hashes, serialization
|
|
from cryptography.hazmat.primitives.asymmetric import padding
|
|
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
|
|
|
base_url = os.environ["BASE_URL"]
|
|
email = os.environ["EMAIL"]
|
|
password = os.environ["PASSWORD"]
|
|
|
|
with urllib.request.urlopen(f"{base_url}/api/v1/auth/login-key", timeout=20) as resp:
|
|
login_key = json.loads(resp.read().decode())
|
|
|
|
public_key = serialization.load_pem_public_key(login_key["public_key"].encode("utf-8"))
|
|
plaintext = json.dumps(
|
|
{"email": email, "password": password, "challenge": login_key["challenge"]},
|
|
separators=(",", ":"),
|
|
).encode("utf-8")
|
|
aes_key = AESGCM.generate_key(bit_length=256)
|
|
iv = os.urandom(12)
|
|
encrypted_data = AESGCM(aes_key).encrypt(iv, plaintext, None)
|
|
encrypted_key = public_key.encrypt(
|
|
aes_key,
|
|
padding.OAEP(
|
|
mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
|
algorithm=hashes.SHA256(),
|
|
label=None,
|
|
),
|
|
)
|
|
payload = json.dumps(
|
|
{
|
|
"key_id": login_key["key_id"],
|
|
"challenge": login_key["challenge"],
|
|
"ciphertext": base64.b64encode(
|
|
json.dumps(
|
|
{
|
|
"encrypted_key": base64.b64encode(encrypted_key).decode("ascii"),
|
|
"iv": base64.b64encode(iv).decode("ascii"),
|
|
"data": base64.b64encode(encrypted_data).decode("ascii"),
|
|
},
|
|
separators=(",", ":"),
|
|
).encode("utf-8")
|
|
).decode("ascii"),
|
|
}
|
|
).encode()
|
|
req = urllib.request.Request(
|
|
f"{base_url}/api/v1/auth/login",
|
|
method="POST",
|
|
headers={"Content-Type": "application/json"},
|
|
data=payload,
|
|
)
|
|
with urllib.request.urlopen(req, timeout=20) as resp:
|
|
print(json.loads(resp.read().decode()).get("access_token", ""))
|
|
PY
|
|
)
|
|
|
|
if [[ -z "$TOKEN" ]]; then
|
|
echo "login failed: access_token empty"
|
|
exit 1
|
|
fi
|
|
|
|
AUTH=(-H "Authorization: Bearer $TOKEN")
|
|
|
|
echo "[2/6] get setup-config"
|
|
GET_RESP=$(curl -sS "$BASE_URL/api/v1/studies/$STUDY_ID/setup-config" "${AUTH[@]}")
|
|
VERSION=$(echo "$GET_RESP" | python3 -c 'import json,sys; print(json.load(sys.stdin).get("version",""))')
|
|
if [[ -z "$VERSION" ]]; then
|
|
echo "get setup-config failed"
|
|
echo "$GET_RESP"
|
|
exit 1
|
|
fi
|
|
echo "version=$VERSION"
|
|
|
|
echo "[3/6] save draft"
|
|
PUT_PAYLOAD=$(cat <<JSON
|
|
{
|
|
"expected_version": $VERSION,
|
|
"data": {
|
|
"projectMilestones": [],
|
|
"enrollmentPlan": {
|
|
"totalTarget": 123,
|
|
"startDate": "2026-02-01",
|
|
"endDate": "2026-12-31",
|
|
"monthlyGoalNote": "curl smoke",
|
|
"stageBreakdown": "phase-1"
|
|
},
|
|
"siteMilestones": [],
|
|
"siteEnrollmentPlans": [],
|
|
"monitoringStrategies": [],
|
|
"centerConfirm": []
|
|
}
|
|
}
|
|
JSON
|
|
)
|
|
PUT_RESP=$(curl -sS -X PUT "$BASE_URL/api/v1/studies/$STUDY_ID/setup-config" \
|
|
"${AUTH[@]}" -H 'Content-Type: application/json' -d "$PUT_PAYLOAD")
|
|
VERSION=$(echo "$PUT_RESP" | python3 -c 'import json,sys; print(json.load(sys.stdin).get("version",""))')
|
|
if [[ -z "$VERSION" ]]; then
|
|
echo "save draft failed"
|
|
echo "$PUT_RESP"
|
|
exit 1
|
|
fi
|
|
echo "saved version=$VERSION"
|
|
|
|
echo "[4/6] publish"
|
|
PUB_RESP=$(curl -sS -X POST "$BASE_URL/api/v1/studies/$STUDY_ID/setup-config/publish" \
|
|
"${AUTH[@]}" -H 'Content-Type: application/json' -d "{\"expected_version\":$VERSION}")
|
|
PUB_STATUS=$(echo "$PUB_RESP" | python3 -c 'import json,sys; print(json.load(sys.stdin).get("publish_status",""))')
|
|
VERSION=$(echo "$PUB_RESP" | python3 -c 'import json,sys; print(json.load(sys.stdin).get("version",""))')
|
|
if [[ "$PUB_STATUS" != "PUBLISHED" ]]; then
|
|
echo "publish failed"
|
|
echo "$PUB_RESP"
|
|
exit 1
|
|
fi
|
|
echo "publish_status=$PUB_STATUS version=$VERSION"
|
|
|
|
echo "[5/6] export excel"
|
|
EXCEL_FILE="/tmp/setup-config-export.xlsx"
|
|
curl -sS "$BASE_URL/api/v1/studies/$STUDY_ID/setup-config/export-excel" "${AUTH[@]}" -o "$EXCEL_FILE"
|
|
if [[ ! -s "$EXCEL_FILE" ]]; then
|
|
echo "export excel failed"
|
|
exit 1
|
|
fi
|
|
echo "export saved: $EXCEL_FILE"
|
|
|
|
echo "[6/6] import excel (re-import export file)"
|
|
IMP_RESP=$(curl -sS -X POST "$BASE_URL/api/v1/studies/$STUDY_ID/setup-config/import-excel" \
|
|
"${AUTH[@]}" \
|
|
-F "expected_version=$VERSION" \
|
|
-F "file=@$EXCEL_FILE;type=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
|
IMP_VER=$(echo "$IMP_RESP" | python3 -c 'import json,sys; print(json.load(sys.stdin).get("version",""))')
|
|
if [[ -z "$IMP_VER" ]]; then
|
|
echo "import failed"
|
|
echo "$IMP_RESP"
|
|
exit 1
|
|
fi
|
|
echo "import version=$IMP_VER"
|
|
|
|
echo "setup-config curl smoke passed"
|