feat: account menu, database roles, and single logout
Bundles the console work from the current branch: the header account control, database-backed roles and permissions, and signing out across the applications that share this sign-in. The account control replaces a separate identity chip and a separate sign-out button, which meant the header carried two controls describing one fact. web/account.js is mounted into every page by a placeholder and owns the keyboard handling, the outside-click behaviour and the sign-out form once. It also fills the trigger's name, which the previous markup left empty. Signing out revokes the hosted-login bearer sessions this installation issued, then redirects to the provider's end_session_endpoint when the discovery document advertises one. Applications that authenticate against this installation therefore lose their session too; one pointed straight at an identity provider is out of its reach and is unchanged. Roles and permissions become rows rather than a closed enum, so a tenant can extend the catalog without a migration, and a role can no longer be granted a capability that is not in it. requireSameOrigin now compares against the origin the request arrived on instead of the configured base URL, which defaulted to http://localhost:8080 and so rejected every write in a deployment that never set it. Two bugs found while verifying in a browser: - A profile picture never rendered. avatarURL built an absolute URL from the configured base URL, and the page's own img-src 'self' blocked it. The console's own pages now take a root-relative path; only /connect/userinfo, read from another origin, needs an absolute one, and it follows the request. - absoluteURL preferred the configuration over the request while its comment claimed the opposite, which also misdirected the logout redirect. Card layout: the footer was one two-column row shared between a label and a forty-character identifier, so the identifier took the width and crushed its label into three stacked words. Each pair is a line now, the value truncates with the full text in the title, and cards align their footers across a row.
This commit is contained in:
parent
3fdc8cb489
commit
c7c81fb65c
43 changed files with 2248 additions and 298 deletions
42
Makefile
42
Makefile
|
|
@ -10,10 +10,11 @@ GO_LOOSE_DEV_USER ?= admin@local.test
|
|||
GO_LOOSE_BOOTSTRAP_TENANT ?= nmbs
|
||||
GO_LOOSE_BOOTSTRAP_APP ?= guess
|
||||
GO_LOOSE_ALLOW_PRIVATE_CONTRACT_URLS ?= true
|
||||
GO_LOOSE_DEV_PORT ?= 8080
|
||||
|
||||
export
|
||||
|
||||
.PHONY: build test integration-test run compose-up compose-down fmt vet
|
||||
.PHONY: build test integration-db integration-test run compose-up compose-down compose-dev-up compose-dev-down compose-dev-logs fmt vet
|
||||
|
||||
build:
|
||||
go build ./...
|
||||
|
|
@ -21,11 +22,25 @@ build:
|
|||
test:
|
||||
go test -race ./...
|
||||
|
||||
# Integration tests truncate every table in the target database, so point them at
|
||||
# a scratch database rather than one holding real data.
|
||||
# Integration tests drop every table they touch, so they only run against scratch
|
||||
# databases. Both test helpers refuse any database whose name lacks "test", and
|
||||
# `make integration-db` creates the two they expect. Override the check with
|
||||
# GO_LOOSE_TEST_DATABASE_DESTRUCTIVE=1 only when you mean it.
|
||||
#
|
||||
# The store-backed tests in internal/server need a database of their own: Go runs
|
||||
# package tests in parallel and both packages drop every table, so sharing one
|
||||
# database makes them fight over the schema.
|
||||
GO_LOOSE_TEST_DATABASE_URL ?= postgres://goloose:goloose@localhost:5433/goloose_test?sslmode=disable
|
||||
GO_LOOSE_TEST_SERVER_DATABASE_URL ?= postgres://goloose:goloose@localhost:5433/goloose_server_test?sslmode=disable
|
||||
|
||||
# createdb is not idempotent, so ignore a database that is already there.
|
||||
integration-db:
|
||||
-docker compose exec -T postgres createdb -U goloose goloose_test
|
||||
-docker compose exec -T postgres createdb -U goloose goloose_server_test
|
||||
|
||||
integration-test:
|
||||
@test -n "$(GO_LOOSE_TEST_DATABASE_URL)" || { echo "set GO_LOOSE_TEST_DATABASE_URL to a scratch database"; exit 1; }
|
||||
go test -race ./internal/store/ -count=1
|
||||
go test -race ./internal/store/ ./internal/server/ -count=1
|
||||
|
||||
run:
|
||||
go run ./cmd/go-loose
|
||||
|
|
@ -40,8 +55,25 @@ compose-up:
|
|||
compose-down:
|
||||
docker compose down
|
||||
|
||||
# Air rebuilds into ./dist on every change.
|
||||
compose-dev-up:
|
||||
mkdir -p dist
|
||||
docker compose -f docker-compose.dev.yaml up --build
|
||||
|
||||
compose-dev-down:
|
||||
docker compose -f docker-compose.dev.yaml down --remove-orphans
|
||||
# Air writes dist/go-loose as root inside the container, so the host user
|
||||
# cannot delete it directly. Empty the directory through a container instead.
|
||||
-docker run --rm -v "$(CURDIR)/dist:/dist" alpine sh -c 'rm -rf /dist/*' 2>/dev/null || true
|
||||
|
||||
compose-dev-logs:
|
||||
docker compose -f docker-compose.dev.yaml logs -f go-loose
|
||||
|
||||
fmt:
|
||||
gofmt -w $$(find . -name '*.go' -not -path './vendor/*')
|
||||
# Prune directories that are not source and may be unreadable: vendored
|
||||
# code, build output, the PostgreSQL volume, and anything hidden or
|
||||
# underscore prefixed, which is how Go itself skips package trees.
|
||||
gofmt -w $$(find . -mindepth 1 -type d \( -name vendor -o -name dist -o -name '.*' -o -name '_*' \) -prune -o -name '*.go' -print)
|
||||
|
||||
vet:
|
||||
go vet ./...
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue