Files
LithosAnanke/site/org/inquiries/install.sh
T
Claude c2ff10015f
Build / Image MILKV (push) Canceled after 0s
Build / Image PC (push) Canceled after 0s
Build / Image RASPI (push) Canceled after 0s
Build / v4 tests (32- and 64-bit cells) (push) Canceled after 0s
site: the design's colours over the wikis' high-contrast theme; .org inquiries
- site/colorlock.py: both XWikis force black and white with !important (a
  HIGH CONTRAST DARK THEME block in the skin's cssVariablesInit.css). On our
  pages only, the design's colours win: each inline colour made !important,
  and a stylesheet scoped to the page root (.ssos) for the rest. Used by
  site/com/build.py and site/org/build.py; the .com reinstalled with it.
- site/org/inquiries (Captain Bob, 2026-11-07): the .com's inquiries go to an
  admin-only master/detail on the .org -- Inquiries.WebHome (Live Data
  table), one page per inquiry under Inquiries.Entries with a sheet and a
  status, PublicInquiry (public) filing them with its author's rights and
  echoing nothing a visitor sends; a hidden trap field for robots. The .com
  form posts there. Installed and tested: a guest's inquiry filed and
  deleted; one whose name and message were script macros was stored as
  text, nothing ran.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 13:47:37 +00:00

116 lines
5.9 KiB
Bash
Executable File

#!/bin/bash
# install.sh -- inquiries on the .org XWiki (Captain Bob, 2026-11-07: the .com's inquiries go to an
# admin-only page on the .org, master/detail):
#
# Inquiries.WebPreferences view, edit, comment, delete: $ADMIN_USER alone -- made first
# Inquiries.Code.InquiryClass the fields (made by Inquiries.Code.ClassSetup, viewed once as the
# administrator: the class has no REST API), bound to the sheet
# Inquiries.Code.InquirySheet the detail: one inquiry, its status set by editing the page
# Inquiries.WebHome the master: every inquiry, newest first (a Live Data table)
# Inquiries.Entries.I<time> one page per inquiry, made by PublicInquiry
# PublicInquiry.WebHome public: the .com's form posts here; it files the inquiry with its
# author's rights and thanks the visitor, echoing nothing they sent
#
# XWIKI_USER=rajames XWIKI_PASSWORD=... site/org/inquiries/install.sh [https://starshipos-f18.org]
#
# It ends by checking a guest's view, then sends one test inquiry as a guest, finds it as the
# administrator, and deletes it.
set -euo pipefail
cd "$(dirname "$0")"
base=${1:-https://starshipos-f18.org}
rest="$base/rest/wikis/xwiki"
user=${XWIKI_USER:?set XWIKI_USER}
pass=${XWIKI_PASSWORD:?set XWIKI_PASSWORD}
admin=${ADMIN_USER:-XWiki.$user}
auth=(-u "$user:$pass")
xml_page() { # xml_page <title> <file>
python3 -c '
import sys
from xml.sax.saxutils import escape
print("<page xmlns=\"http://www.xwiki.org\"><title>%s</title><syntax>xwiki/2.1</syntax>"
"<content>%s</content></page>" % (escape(sys.argv[1]), escape(open(sys.argv[2]).read())))' "$1" "$2"
}
page() { # page <space path, a/b> <name> <title> <file>
local spaces=${1//\//\/spaces\/}
curl -fsS -o /dev/null -w " page ${1//\//.}.$2: %{http_code}\n" "${auth[@]}" -X PUT \
-H 'Content-Type: application/xml' --data-binary "$(xml_page "$3" "$4")" "$rest/spaces/$spaces/pages/$2"
}
objects() { # objects <space path> <page> <class>: how many
local spaces=${1//\//\/spaces\/}
curl -fsS "${auth[@]}" -H 'Accept: application/json' "$rest/spaces/$spaces/pages/$2/objects/$3" |
python3 -c 'import json,sys; print(len(json.load(sys.stdin).get("objectSummaries") or []))'
}
object() { # object <space path> <page> <class> <property=value>...: add one, as XML
local spaces=${1//\//\/spaces\/} s=$1 p=$2 c=$3; shift 3
local body
body=$(python3 -c '
import sys
from xml.sax.saxutils import escape
props = "".join("<property name=\"%s\"><value>%s</value></property>" % (escape(k), escape(v))
for k, v in (a.split("=", 1) for a in sys.argv[2:]))
print("<object xmlns=\"http://www.xwiki.org\"><className>%s</className>%s</object>" % (escape(sys.argv[1]), props))' "$c" "$@")
curl -fsS -o /dev/null -w " ${s//\//.}.$p: $c added (%{http_code})\n" "${auth[@]}" -X POST \
-H 'Content-Type: application/xml' --data-binary "$body" "$rest/spaces/$spaces/pages/$p/objects"
}
echo "=== $base, as $user"
echo "=== rights first: Inquiries is the administrator's alone"
page Inquiries WebPreferences "Inquiries rights" /dev/null
if [ "$(objects Inquiries WebPreferences XWiki.XWikiGlobalRights)" = 0 ]; then
object Inquiries WebPreferences XWiki.XWikiGlobalRights \
"levels=view,edit,comment,delete" "users=$admin" "groups=" "allow=1"
else
echo " rights there already, left as they are"
fi
echo "=== the class, its sheet"
page Inquiries/Code InquiryClass "Inquiry class" /dev/null
page Inquiries/Code ClassSetup "Inquiry class setup" ClassSetup.xwiki
out=$(curl -fsS "${auth[@]}" "$base/bin/view/Inquiries/Code/ClassSetup?basicauth=1")
case "$out" in
*CLASS-SAVED*) echo " the class's fields: made";;
*CLASS-UNCHANGED*) echo " the class's fields: there already";;
*) echo "install: the class setup did not run (programming right?)" >&2; exit 1;;
esac
page Inquiries/Code InquirySheet "Inquiry sheet" InquirySheet.xwiki
if [ "$(objects Inquiries/Code InquiryClass XWiki.ClassSheetBinding)" = 0 ]; then
object Inquiries/Code InquiryClass XWiki.ClassSheetBinding "sheet=Inquiries.Code.InquirySheet"
else
echo " sheet bound already"
fi
echo "=== the master, and the public intake"
page Inquiries WebHome "Inquiries" Inquiries.WebHome.xwiki
page PublicInquiry WebHome "Inquiry" PublicInquiry.WebHome.xwiki
echo "=== as a guest"
bad=
for p in Inquiries:401 PublicInquiry:200; do
code=$(curl -s -o /dev/null -w '%{http_code}' -H 'Accept: application/json' "$rest/spaces/${p%%:*}/pages/WebHome")
if [ "$code" = "${p##*:}" ]; then echo " ${p%%:*}.WebHome: $code -- as it should be"
else echo " ${p%%:*}.WebHome: $code -- NOT as it should be"; bad=1; fi
done
[ -z "$bad" ] || { echo "install: a guest's view is wrong; see above" >&2; exit 1; }
echo "=== a test inquiry, sent as a guest"
reply=$(curl -fsS -X POST "$base/bin/view/PublicInquiry/" \
--data-urlencode "name=install.sh test" --data-urlencode "email=test@example.org" \
--data-urlencode "topic=General question" --data-urlencode "message=A test from site/org/inquiries/install.sh; it deletes this.")
case "$reply" in *"has been received"*) echo " thanked";; *) echo "install: no thanks for the test" >&2; exit 1;; esac
found=$(curl -fsS "${auth[@]}" -H 'Accept: application/json' "$rest/spaces/Inquiries/spaces/Entries/pages" |
python3 -c '
import json,sys
print(" ".join(p["name"] for p in json.load(sys.stdin)["pageSummaries"]))')
test_page=
for n in $found; do
if curl -fsS "${auth[@]}" -H 'Accept: application/json' \
"$rest/spaces/Inquiries/spaces/Entries/pages/$n/objects/Inquiries.Code.InquiryClass/0/properties/name" |
grep -q 'install.sh test'; then test_page=$n; fi
done
[ -n "$test_page" ] || { echo "install: the test inquiry was not filed" >&2; exit 1; }
echo " filed as Inquiries.Entries.$test_page"
curl -fsS -o /dev/null -w " deleted: %{http_code}\n" "${auth[@]}" -X DELETE \
"$rest/spaces/Inquiries/spaces/Entries/pages/$test_page"
echo "=== done: $base/bin/view/Inquiries/"