Until now every account could do the same, and managing accounts meant running make-user.php on the server. Accounts now carry a role, and admins get a tab in the editor to create, rename, re-role, reset and delete accounts. Both issues share the same server files, so they land in one commit. #180 Roles: - Every account is admin or user. A missing or unknown role counts as user, on the server and in the client. - auth/session and auth/login return {user, role}. - Auth::requireAdmin() answers everyone else with 403. - make-user.php takes the role as a third argument. Without it an existing account keeps its role, so a password reset from the CLI never demotes an admin. - Admins see and save other users' projects like their own. Saving keeps the original owner. #179 User management: - The account menu gets "User management" (admins only) and "Plugins" (everyone). Both open the same closable tab, accounts on top and plugins below. The fixed Plugins tab is gone. - Per account: Rename, Role, Password (no old password needed) and Delete with a confirmation. "New user..." creates one. - Each account lists its projects with an Open button. - Delete is refused while the account still owns projects. - Renaming moves the projects along and ends every session of the account. transfer takes the same lock as save. - On their own row an admin can only set the password. The last admin cannot be demoted or deleted. The server enforces both. - The account rules live in AccountRules.php and accountRules.ts as pure functions, so they are testable without a server. Findings: - At 1280 px the Delete button reached past the column edge and was not clickable. The name column is flexible now, and module 49 checks the layout. - The server lets an admin delete other users' projects, but the editor has no button for it yet. Left open in the issue. Tests: - ./check.sh: 148 files, 2214 tests, exit 0 (was 147 / 2204). - New tests/php/accounts.test.php, 51 checks, plain PHP. CI runs it as its own step in the gate job, the host has no PHP. - New e2e module 49 with 18 checks. CI creates the e2e-admin account in serve.sh. Modules 14, 38, 46 and the scaffold follow the new tab. - e2e 1-16,37,38,45,46,49: all passed, 581 checks. - Counter-checks: owner on save, admin view, default role and self delete in PHP fail 7, 5, 5 and 1 checks. Unchecked requireAdmin, a wider column and the caller as owner each fail exactly their e2e check. - Check sum 1314 -> 1333 (+1 in 38, +18 in 49), computed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
54 lines
2.3 KiB
Bash
54 lines
2.3 KiB
Bash
#!/bin/bash
|
||
# Sourced, not run: it leaves the PHP server in the caller's background and exports
|
||
# GAME_MAKER_BASE_URL, which every tool reads.
|
||
#
|
||
# The build wires its assets absolutely under /game-maker/dist/, so the checkout has to be
|
||
# served under that path segment – hence the symlink into /srv rather than `-t .`.
|
||
|
||
export GAME_MAKER_BASE_URL=http://127.0.0.1:8080/game-maker/
|
||
|
||
game_maker_serve() {
|
||
local root
|
||
root=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
|
||
|
||
mkdir -p "$root/data/projects" "$root/data/textures"
|
||
node "$root/tools/ci/project-shells.mjs"
|
||
|
||
# Since #177 the API needs a session, and the check tools sign in as `e2e`. A fresh checkout has
|
||
# no accounts at all, so the job makes the one it needs, with a password of its own.
|
||
if [ ! -f "$root/data/e2e-password.txt" ]; then
|
||
head -c 24 /dev/urandom | base64 | tr -d '\n' >"$root/data/e2e-password.txt"
|
||
echo >>"$root/data/e2e-password.txt"
|
||
fi
|
||
php "$root/tools/make-user.php" e2e "$(cat "$root/data/e2e-password.txt")"
|
||
# The user management step (#179) needs an administrator of its own; it owns no project.
|
||
if [ ! -f "$root/data/e2e-admin-password.txt" ]; then
|
||
head -c 24 /dev/urandom | base64 | tr -d '\n' >"$root/data/e2e-admin-password.txt"
|
||
echo >>"$root/data/e2e-admin-password.txt"
|
||
fi
|
||
php "$root/tools/make-user.php" e2e-admin "$(cat "$root/data/e2e-admin-password.txt")" admin
|
||
|
||
# A server from an earlier step of the same job is fine to keep. Asked of the one route that
|
||
# answers without a session, so "is it up" does not depend on being signed in.
|
||
if curl -sf "${GAME_MAKER_BASE_URL}api/index.php?r=auth/session" >/dev/null 2>&1; then
|
||
echo "server already up at $GAME_MAKER_BASE_URL"
|
||
return 0
|
||
fi
|
||
|
||
mkdir -p /srv && ln -sfn "$root" /srv/game-maker
|
||
# Without workers the single-threaded dev server stalls: the editor fetches project and
|
||
# textures in parallel.
|
||
PHP_CLI_SERVER_WORKERS=8 php -S 0.0.0.0:8080 -t /srv >/tmp/php-server.log 2>&1 &
|
||
|
||
for _ in $(seq 60); do
|
||
curl -sf "${GAME_MAKER_BASE_URL}api/index.php?r=auth/session" >/dev/null 2>&1 && break
|
||
sleep 0.5
|
||
done
|
||
if ! curl -sf "${GAME_MAKER_BASE_URL}api/index.php?r=auth/session" >/dev/null 2>&1; then
|
||
echo "the server never came up" >&2
|
||
tail -20 /tmp/php-server.log >&2
|
||
return 1
|
||
fi
|
||
echo "serving $root at $GAME_MAKER_BASE_URL"
|
||
}
|