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
47
internal/database/migrations/0007_permission_catalog.sql
Normal file
47
internal/database/migrations/0007_permission_catalog.sql
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
-- +goose Up
|
||||
-- Permissions become rows so the catalog can be extended without a migration.
|
||||
-- The nine names the application enforces in SQL are seeded here; a tenant may
|
||||
-- add further names, which are grantable and reported through /connect/userinfo
|
||||
-- but are not checked by the console itself.
|
||||
CREATE TABLE permissions (
|
||||
name text PRIMARY KEY CHECK (name ~ '^[a-z0-9][a-z0-9]*(?:[.-][a-z0-9]+)*$'),
|
||||
label text NOT NULL CHECK (length(btrim(label)) BETWEEN 1 AND 100),
|
||||
description text NOT NULL DEFAULT '',
|
||||
is_system boolean NOT NULL DEFAULT false,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
INSERT INTO permissions (name, label, description, is_system) VALUES
|
||||
('tenants.manage', 'Manage tenants', 'Create tenants and administer the installation.', true),
|
||||
('roles.manage', 'Manage roles', 'Create and edit the roles of this tenant.', true),
|
||||
('users.manage', 'Manage members', 'Invite members and change their roles and application grants.', true),
|
||||
('applications.manage', 'Manage applications', 'Register applications and configure client credentials.', true),
|
||||
('keys.manage', 'Manage API keys', 'Issue and revoke API keys.', true),
|
||||
('contracts.manage', 'Manage contracts', 'Import OpenAPI contracts and their endpoints.', true),
|
||||
('users.read', 'Read members', 'List the members of a tenant and the roles they hold.', true),
|
||||
('console.read', 'Read console', 'Open the management console and pick tenants.', true),
|
||||
('profile.edit', 'Edit own profile', 'Change one''s own display name and picture.', true);
|
||||
|
||||
-- The closed list becomes a foreign key, so a role can no longer be granted a
|
||||
-- capability that is not in the catalog. Granting one is now a matter of
|
||||
-- inserting the permission first rather than editing a check constraint.
|
||||
ALTER TABLE role_permissions DROP CONSTRAINT role_permissions_permission_check;
|
||||
ALTER TABLE role_permissions
|
||||
ADD CONSTRAINT role_permissions_permission_fkey
|
||||
FOREIGN KEY (permission) REFERENCES permissions(name) ON DELETE RESTRICT;
|
||||
|
||||
-- +goose Down
|
||||
DELETE FROM role_permissions WHERE permission NOT IN (
|
||||
'tenants.manage', 'roles.manage', 'users.manage', 'applications.manage',
|
||||
'keys.manage', 'contracts.manage', 'users.read', 'console.read', 'profile.edit'
|
||||
);
|
||||
|
||||
ALTER TABLE role_permissions DROP CONSTRAINT role_permissions_permission_fkey;
|
||||
ALTER TABLE role_permissions
|
||||
ADD CONSTRAINT role_permissions_permission_check CHECK (permission IN (
|
||||
'tenants.manage', 'roles.manage', 'users.manage', 'applications.manage',
|
||||
'keys.manage', 'contracts.manage', 'users.read', 'console.read', 'profile.edit'
|
||||
));
|
||||
|
||||
DROP TABLE permissions;
|
||||
5
internal/database/migrations/0008_oidc_redirect_url.sql
Normal file
5
internal/database/migrations/0008_oidc_redirect_url.sql
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
-- +goose Up
|
||||
ALTER TABLE installation_settings ADD COLUMN oidc_redirect_url text NOT NULL DEFAULT '';
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE installation_settings DROP COLUMN IF EXISTS oidc_redirect_url;
|
||||
Loading…
Add table
Add a link
Reference in a new issue