@lamalibre/create-lamaste 4.5.0 → 4.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/scripts/bundle-vendor.js +20 -3
- package/scripts/lamaste-priv +56 -5
- package/scripts/pin-release.js +98 -0
- package/src/index.js +8 -1
- package/src/lib/env.js +19 -0
- package/src/lib/service-config.js +7 -0
- package/src/tasks/redeploy.js +8 -0
- package/vendor/docs/00-introduction/how-it-works.md +2 -2
- package/vendor/docs/00-introduction/quickstart.md +5 -5
- package/vendor/docs/00-introduction/what-is-lamaste.md +5 -5
- package/vendor/docs/01-concepts/authentication.md +6 -2
- package/vendor/docs/01-concepts/authorization.md +4 -0
- package/vendor/docs/01-concepts/certificates.md +3 -3
- package/vendor/docs/01-concepts/dns-and-domains.md +9 -0
- package/vendor/docs/01-concepts/mtls.md +2 -2
- package/vendor/docs/01-concepts/security-model.md +28 -3
- package/vendor/docs/01-concepts/tickets.md +2 -2
- package/vendor/docs/01-concepts/tunneling.md +4 -4
- package/vendor/docs/02-guides/agent-setup.md +5 -5
- package/vendor/docs/02-guides/certificate-management.md +2 -2
- package/vendor/docs/02-guides/cloud-provisioning.md +3 -3
- package/vendor/docs/02-guides/desktop-app-setup.md +10 -10
- package/vendor/docs/02-guides/installation.md +3 -3
- package/vendor/docs/02-guides/managing-users.md +5 -11
- package/vendor/docs/02-guides/onboarding.md +2 -2
- package/vendor/docs/02-guides/second-domain.md +82 -0
- package/vendor/docs/02-guides/standalone-plugin-with-tickets.md +2 -2
- package/vendor/docs/02-guides/static-sites.md +4 -0
- package/vendor/docs/03-architecture/installer-flow.md +2 -2
- package/vendor/docs/03-architecture/installer.md +4 -4
- package/vendor/docs/03-architecture/management-flow.md +1 -1
- package/vendor/docs/03-architecture/nginx-configuration.md +80 -12
- package/vendor/docs/03-architecture/overview.md +5 -5
- package/vendor/docs/03-architecture/panel-client.md +6 -6
- package/vendor/docs/03-architecture/panel-server.md +2 -2
- package/vendor/docs/03-architecture/state-management.md +3 -3
- package/vendor/docs/03-architecture/system-overview.md +1 -1
- package/vendor/docs/04-api-reference/agent-hosted-plugins.md +116 -37
- package/vendor/docs/04-api-reference/app-host.md +3 -3
- package/vendor/docs/04-api-reference/domains.md +192 -0
- package/vendor/docs/04-api-reference/gatekeeper.md +54 -8
- package/vendor/docs/04-api-reference/lifecycle-hooks.md +4 -4
- package/vendor/docs/04-api-reference/onboarding.md +1 -1
- package/vendor/docs/04-api-reference/overview.md +9 -0
- package/vendor/docs/04-api-reference/registry-and-oidc.md +26 -13
- package/vendor/docs/04-api-reference/sites.md +9 -0
- package/vendor/docs/04-api-reference/tunnels.md +35 -28
- package/vendor/docs/04-api-reference/users.md +41 -29
- package/vendor/docs/05-operations/backup-and-restore.md +1 -1
- package/vendor/docs/05-operations/uninstalling.md +1 -1
- package/vendor/docs/05-operations/upgrades.md +15 -6
- package/vendor/docs/06-reference/config-files.md +19 -15
- package/vendor/docs/06-reference/glossary.md +3 -3
- package/vendor/docs/06-reference/installer-flags.md +13 -13
- package/vendor/docs/06-reference/ports-and-services.md +1 -1
- package/vendor/docs/06-reference/troubleshooting.md +8 -8
- package/vendor/docs/_index.json +105 -19
- package/vendor/docs/external-members-design.md +816 -0
- package/vendor/docs/gatekeeper-design.md +8 -8
- package/vendor/docs/identity-directory-design.md +3 -3
- package/vendor/docs/multi-domain-relay-design.md +836 -0
- package/vendor/docs/package.json +1 -1
- package/vendor/docs/todo/lib-cli-desktop-refactor.md +27 -27
- package/vendor/gatekeeper/dist/index.d.ts +3 -3
- package/vendor/gatekeeper/dist/index.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/index.js +2 -2
- package/vendor/gatekeeper/dist/index.js.map +1 -1
- package/vendor/gatekeeper/dist/lib/authz.d.ts +9 -0
- package/vendor/gatekeeper/dist/lib/authz.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/lib/authz.js +31 -0
- package/vendor/gatekeeper/dist/lib/authz.js.map +1 -1
- package/vendor/gatekeeper/dist/lib/constants.d.ts +5 -2
- package/vendor/gatekeeper/dist/lib/constants.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/lib/constants.js +5 -2
- package/vendor/gatekeeper/dist/lib/constants.js.map +1 -1
- package/vendor/gatekeeper/dist/lib/grants.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/lib/grants.js +20 -13
- package/vendor/gatekeeper/dist/lib/grants.js.map +1 -1
- package/vendor/gatekeeper/dist/lib/migrations/gatekeeper/0004_unconsume_access_grants.sql +8 -0
- package/vendor/gatekeeper/dist/lib/secret.d.ts +6 -0
- package/vendor/gatekeeper/dist/lib/secret.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/secret.js +12 -0
- package/vendor/gatekeeper/dist/lib/secret.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/templates.d.ts +20 -0
- package/vendor/gatekeeper/dist/lib/templates.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/lib/templates.js +80 -14
- package/vendor/gatekeeper/dist/lib/templates.js.map +1 -1
- package/vendor/gatekeeper/dist/lib/tunnels.d.ts +3 -6
- package/vendor/gatekeeper/dist/lib/tunnels.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/lib/tunnels.js +4 -16
- package/vendor/gatekeeper/dist/lib/tunnels.js.map +1 -1
- package/vendor/gatekeeper/dist/lib/types.d.ts +0 -19
- package/vendor/gatekeeper/dist/lib/types.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/server/index.d.ts +6 -1
- package/vendor/gatekeeper/dist/server/index.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/server/index.js +56 -11
- package/vendor/gatekeeper/dist/server/index.js.map +1 -1
- package/vendor/gatekeeper/dist/server/routes/authz.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/server/routes/authz.js +325 -55
- package/vendor/gatekeeper/dist/server/routes/authz.js.map +1 -1
- package/vendor/gatekeeper/dist/server/routes/diagnostic.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/server/routes/diagnostic.js +5 -2
- package/vendor/gatekeeper/dist/server/routes/diagnostic.js.map +1 -1
- package/vendor/gatekeeper/package.json +2 -2
- package/vendor/server/bin/lamaste-server.js +7 -0
- package/vendor/server/package.json +2 -2
- package/vendor/server/src/commands/domains.js +214 -0
- package/vendor/server/src/commands/plugin-identity.js +2 -16
- package/vendor/server/src/commands/plugin-web-surface.js +269 -0
- package/vendor/server/src/commands/plugins.js +175 -14
- package/vendor/server/src/commands/registry-credential.js +10 -3
- package/vendor/server/src/commands/sites.js +18 -1
- package/vendor/server/src/commands/status.js +19 -0
- package/vendor/server/src/commands/tunnels.js +4 -1
- package/vendor/server/src/commands/users.js +8 -19
- package/vendor/server/src/domains.js +92 -0
- package/vendor/server/src/fail.js +21 -0
- package/vendor/server/src/oidc-client-grants.js +63 -0
- package/vendor/server/src/panel-api.js +15 -0
- package/vendor/server/src/plugin-approval.js +80 -1
- package/vendor/server/src/plugin-web-surface.js +307 -0
- package/vendor/server-ui/dist/assets/index-B8Tv_ocF.js +84 -0
- package/vendor/server-ui/dist/assets/index-Cb-ADsbB.css +1 -0
- package/vendor/server-ui/dist/index.html +2 -2
- package/vendor/serverd/package.json +2 -2
- package/vendor/serverd/src/index.js +50 -19
- package/vendor/serverd/src/lib/app-error.js +24 -0
- package/vendor/serverd/src/lib/audience.js +12 -3
- package/vendor/serverd/src/lib/authelia.js +341 -35
- package/vendor/serverd/src/lib/chisel-runtime.js +18 -6
- package/vendor/serverd/src/lib/chisel.js +10 -2
- package/vendor/serverd/src/lib/directory.js +67 -52
- package/vendor/serverd/src/lib/domains.js +1792 -0
- package/vendor/serverd/src/lib/gatekeeper-client.js +34 -7
- package/vendor/serverd/src/lib/hook-pipelines.js +8 -3
- package/vendor/serverd/src/lib/identity-sync.js +35 -0
- package/vendor/serverd/src/lib/migrations/state/0015_plugin_web_surface.sql +14 -0
- package/vendor/serverd/src/lib/migrations/state/0016_domains.sql +53 -0
- package/vendor/serverd/src/lib/migrations/state/0017_membership_kind.sql +15 -0
- package/vendor/serverd/src/lib/migrations/state/0018_domain_group_keys.sql +23 -0
- package/vendor/serverd/src/lib/nginx.js +576 -131
- package/vendor/serverd/src/lib/owned-groups.js +326 -0
- package/vendor/serverd/src/lib/plugin-domain.js +86 -0
- package/vendor/serverd/src/lib/plugin-hooks.js +40 -11
- package/vendor/serverd/src/lib/plugin-lifecycle.js +129 -5
- package/vendor/serverd/src/lib/plugin-oidc.js +144 -42
- package/vendor/serverd/src/lib/plugin-packages.js +74 -2
- package/vendor/serverd/src/lib/plugins.js +82 -9
- package/vendor/serverd/src/lib/registry-credential.js +39 -6
- package/vendor/serverd/src/lib/services.js +9 -1
- package/vendor/serverd/src/lib/state.js +29 -0
- package/vendor/serverd/src/lib/tunnel-deps.js +2 -4
- package/vendor/serverd/src/lib/user-surface.js +77 -31
- package/vendor/serverd/src/lib/users-lock.js +23 -0
- package/vendor/serverd/src/lib/vhost-reconcile.js +151 -41
- package/vendor/serverd/src/lib/web-surface.js +783 -0
- package/vendor/serverd/src/middleware/user-access-session.js +11 -4
- package/vendor/serverd/src/routes/invite.js +15 -5
- package/vendor/serverd/src/routes/management/domains.js +154 -0
- package/vendor/serverd/src/routes/management/gatekeeper-proxy.js +44 -8
- package/vendor/serverd/src/routes/management/identity.js +21 -7
- package/vendor/serverd/src/routes/management/invitations.js +33 -4
- package/vendor/serverd/src/routes/management/plugin-web-surface.js +151 -0
- package/vendor/serverd/src/routes/management/plugins.js +6 -2
- package/vendor/serverd/src/routes/management/registry-credential.js +86 -57
- package/vendor/serverd/src/routes/management/sites.js +188 -71
- package/vendor/serverd/src/routes/management/tunnels.js +37 -22
- package/vendor/serverd/src/routes/management/users.js +184 -64
- package/vendor/serverd/src/routes/management.js +4 -0
- package/vendor/serverd/src/routes/onboarding/dns.js +3 -17
- package/vendor/serverd/src/routes/onboarding/provision.js +22 -13
- package/vendor/serverd/src/routes/user-access.js +13 -1
- package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0001_groups.sql +0 -7
- package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0002_access_grants.sql +0 -14
- package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0003_access_request_log.sql +0 -9
- package/vendor/server-ui/dist/assets/index-D-fer5ef.css +0 -1
- package/vendor/server-ui/dist/assets/index-DSaDPJaw.js +0 -84
|
@@ -225,26 +225,53 @@ function groupOf(raw) {
|
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
/**
|
|
228
|
-
* Every grant on
|
|
229
|
-
* <route>`) — with roles or without.
|
|
228
|
+
* Every grant on one resource (`resourceType`, `resourceId`).
|
|
230
229
|
*
|
|
231
|
-
* @param {string}
|
|
230
|
+
* @param {string} resourceType
|
|
231
|
+
* @param {string} resourceId
|
|
232
|
+
* @returns {Promise<{ ok: true, grants: GatekeeperGrant[] } | Extract<GatekeeperResult, { ok: false }>>}
|
|
233
|
+
*/
|
|
234
|
+
export function listResourceGrants(resourceType, resourceId) {
|
|
235
|
+
return listGrantsMatching({ resourceType, resourceId });
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Every grant on resources of `resourceType` (`tunnel`, `site`,
|
|
240
|
+
* `oidc-client`, …).
|
|
241
|
+
*
|
|
242
|
+
* @param {string} resourceType
|
|
232
243
|
* @returns {Promise<{ ok: true, grants: GatekeeperGrant[] } | Extract<GatekeeperResult, { ok: false }>>}
|
|
233
244
|
*/
|
|
234
|
-
export
|
|
235
|
-
|
|
245
|
+
export function listGrantsOfType(resourceType) {
|
|
246
|
+
return listGrantsMatching({ resourceType });
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/** The grants matching `filter` (its fields are Gatekeeper's query filters). */
|
|
250
|
+
async function listGrantsMatching(filter) {
|
|
251
|
+
const qs = new URLSearchParams(filter).toString();
|
|
236
252
|
const result = await gatekeeperRequest('GET', `/api/grants?${qs}`);
|
|
237
253
|
if (!result.ok) return result;
|
|
238
254
|
if (!isRecord(result.data) || !Array.isArray(result.data.grants)) return malformed('its grants');
|
|
239
255
|
const grants = result.data.grants.map(grantOf);
|
|
240
256
|
if (grants.some((g) => g === null)) return malformed('its grants');
|
|
241
|
-
// Gatekeeper filters by the query; a grant on anything else is not
|
|
257
|
+
// Gatekeeper filters by the query; a grant on anything else is not one asked for.
|
|
242
258
|
return {
|
|
243
259
|
ok: true,
|
|
244
|
-
grants: grants.filter((g) =>
|
|
260
|
+
grants: grants.filter((g) => Object.entries(filter).every(([key, value]) => g[key] === value)),
|
|
245
261
|
};
|
|
246
262
|
}
|
|
247
263
|
|
|
264
|
+
/**
|
|
265
|
+
* Every grant on plugin `route` (`resourceType: 'plugin'`, `resourceId:
|
|
266
|
+
* <route>`) — with roles or without.
|
|
267
|
+
*
|
|
268
|
+
* @param {string} route
|
|
269
|
+
* @returns {Promise<{ ok: true, grants: GatekeeperGrant[] } | Extract<GatekeeperResult, { ok: false }>>}
|
|
270
|
+
*/
|
|
271
|
+
export function listPluginGrants(route) {
|
|
272
|
+
return listResourceGrants('plugin', route);
|
|
273
|
+
}
|
|
274
|
+
|
|
248
275
|
/**
|
|
249
276
|
* Every Lamaste group with its members.
|
|
250
277
|
*
|
|
@@ -871,8 +871,10 @@ export async function runUninstallPipeline(op, ctx, { force = false } = {}) {
|
|
|
871
871
|
/**
|
|
872
872
|
* The install pipeline around an upgrade of the relay package (the agent
|
|
873
873
|
* half is already running; its stages go through the tunnel). `apply` is
|
|
874
|
-
* Lamaste's step — install the new package and its hook module; `
|
|
875
|
-
*
|
|
874
|
+
* Lamaste's step — install the new package and its hook module; `serve`,
|
|
875
|
+
* when given, is the last step (the new version's web tree served, once
|
|
876
|
+
* every stage passed);
|
|
877
|
+
* `revert` restores the previous ones. Agent and relay stages see `phase: "upgrade"`.
|
|
876
878
|
*
|
|
877
879
|
* A hosted plugin whose agent half Lamaste installs gets the new version of
|
|
878
880
|
* it first (after the agent's pre stage): the agent's helper installs it
|
|
@@ -880,7 +882,7 @@ export async function runUninstallPipeline(op, ctx, { force = false } = {}) {
|
|
|
880
882
|
* tunnel. A failure after that switch activates the version that ran
|
|
881
883
|
* before (`ctx.previousAgentHalfVersion`).
|
|
882
884
|
*/
|
|
883
|
-
export async function runUpgradePipeline(op, ctx, { apply, revert, hosted }) {
|
|
885
|
+
export async function runUpgradePipeline(op, ctx, { apply, serve, revert, hosted }) {
|
|
884
886
|
let applied = false;
|
|
885
887
|
try {
|
|
886
888
|
if (hosted) {
|
|
@@ -906,6 +908,9 @@ export async function runUpgradePipeline(op, ctx, { apply, revert, hosted }) {
|
|
|
906
908
|
await agentStageOrSkip(op, ctx, 'install:post-tunnel', 'upgrade', 'tunnel');
|
|
907
909
|
await relayStageOrSkip(op, ctx, 'install:post-tunnel', 'upgrade');
|
|
908
910
|
}
|
|
911
|
+
// What the new version serves its users from the relay (its web tree):
|
|
912
|
+
// the last step, once every stage passed — a failure still reverts.
|
|
913
|
+
if (serve) await op.step('serve the new web tree', serve);
|
|
909
914
|
} catch (err) {
|
|
910
915
|
op.warn(`Reverting: ${String(err.message ?? err).slice(0, 300)}`);
|
|
911
916
|
try {
|
|
@@ -77,6 +77,7 @@ import {
|
|
|
77
77
|
} from './audience.js';
|
|
78
78
|
import { getConfig } from './config.js';
|
|
79
79
|
import { clearPendingPrincipals, getDirectoryId, reconcileDirectory } from './directory.js';
|
|
80
|
+
import { ensurePrimaryDomain, syncDomainAccess } from './domains.js';
|
|
80
81
|
import { installedVersionApproved } from './plugin-hooks.js';
|
|
81
82
|
import { findPlugin, findPluginByRoute, readPlugins } from './plugins.js';
|
|
82
83
|
import { retainedIdentityPositions } from './retained-data.js';
|
|
@@ -859,6 +860,9 @@ async function syncDuePlugins(logger) {
|
|
|
859
860
|
let tickTimer = null;
|
|
860
861
|
let ticking = false;
|
|
861
862
|
|
|
863
|
+
/** The OIDC sync failure the tick last logged — logged again only when it changes. */
|
|
864
|
+
let lastOidcSyncError = null;
|
|
865
|
+
|
|
862
866
|
/**
|
|
863
867
|
* One tick: reconcile the directory with users.yml (once onboarding is
|
|
864
868
|
* done), clear the Gatekeeper principals of removed users still pending,
|
|
@@ -875,6 +879,37 @@ export async function identityTick(logger) {
|
|
|
875
879
|
} catch (err) {
|
|
876
880
|
logger?.warn({ err: err.message }, 'Could not reconcile the user directory');
|
|
877
881
|
}
|
|
882
|
+
// Who may reach each domain, as the directory now says: users adopted
|
|
883
|
+
// or removed outside Lamaste, and a rendering a failure left behind.
|
|
884
|
+
try {
|
|
885
|
+
await ensurePrimaryDomain({ logger });
|
|
886
|
+
await syncDomainAccess({ logger });
|
|
887
|
+
} catch (err) {
|
|
888
|
+
logger?.warn({ err: err.message }, 'Could not render domain access');
|
|
889
|
+
}
|
|
890
|
+
// users.yml touched once a minute: a reload Authelia skipped (its
|
|
891
|
+
// cooldown) or that a restart of the panel cut short is never missing
|
|
892
|
+
// for longer, and a hand edit gets Lamaste's groups back.
|
|
893
|
+
try {
|
|
894
|
+
const { touchUsersFile } = await import('./authelia.js');
|
|
895
|
+
await touchUsersFile();
|
|
896
|
+
} catch (err) {
|
|
897
|
+
logger?.warn({ err: err.message }, 'Could not touch users.yml');
|
|
898
|
+
}
|
|
899
|
+
// The OIDC provider too, as the plugins and the members now say: a
|
|
900
|
+
// plugin moved to another domain whose sync failed is healed here.
|
|
901
|
+
// Compare-first, so a steady relay writes nothing.
|
|
902
|
+
try {
|
|
903
|
+
const { syncOidcClients } = await import('./plugin-oidc.js');
|
|
904
|
+
await syncOidcClients(logger);
|
|
905
|
+
lastOidcSyncError = null;
|
|
906
|
+
} catch (err) {
|
|
907
|
+
// Once per distinct failure, not every minute.
|
|
908
|
+
if (err.message !== lastOidcSyncError) {
|
|
909
|
+
logger?.warn({ err: err.message }, 'Could not sync the OIDC clients');
|
|
910
|
+
}
|
|
911
|
+
lastOidcSyncError = err.message;
|
|
912
|
+
}
|
|
878
913
|
}
|
|
879
914
|
await clearPendingPrincipals({ logger });
|
|
880
915
|
await recomputeAudiences({ logger });
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
-- A plugin's web surface (4.6, slice 7).
|
|
2
|
+
--
|
|
3
|
+
-- user_surface is the manifest's `userSurface` block as the installed
|
|
4
|
+
-- version declares it (JSON; NULL when it declares none): its `web` names
|
|
5
|
+
-- the default subdomain and access mode Lamaste offers for the plugin's own
|
|
6
|
+
-- site and the directory of the server package that holds the shell.
|
|
7
|
+
--
|
|
8
|
+
-- web_tree_sha256 is the digest of that directory's web tree (core
|
|
9
|
+
-- `webTreeManifest`), read from the installed package: it enters the
|
|
10
|
+
-- approval digest, and the relay serves a copy of the tree only when the
|
|
11
|
+
-- copy's own digest equals it. NULL when the version declares no web
|
|
12
|
+
-- surface.
|
|
13
|
+
ALTER TABLE plugins ADD COLUMN user_surface TEXT;
|
|
14
|
+
ALTER TABLE plugins ADD COLUMN web_tree_sha256 TEXT;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
-- The relay's base domains and who is a member of each (the multi-domain
|
|
2
|
+
-- relay, packages/core/docs/multi-domain-relay-design.md; lib/domains.js).
|
|
3
|
+
--
|
|
4
|
+
-- One domain is the primary: the panel's (panel.json `domain`), inserted at
|
|
5
|
+
-- the first start after onboarding together with every user the directory
|
|
6
|
+
-- holds as its members (lib/domains.js `ensurePrimaryDomain`) — an upgraded
|
|
7
|
+
-- single-domain relay keeps letting everyone in.
|
|
8
|
+
|
|
9
|
+
-- A base domain:
|
|
10
|
+
-- name lower case, two labels at least; domains never overlap
|
|
11
|
+
-- is_primary 1 for exactly one row: the panel's domain
|
|
12
|
+
-- status pending (added, auth.<domain> not yet issued) | active
|
|
13
|
+
-- (its sign-in, session cookie and members rendered)
|
|
14
|
+
CREATE TABLE domains (
|
|
15
|
+
name TEXT PRIMARY KEY,
|
|
16
|
+
is_primary INTEGER NOT NULL DEFAULT 0 CHECK (is_primary IN (0, 1)),
|
|
17
|
+
status TEXT NOT NULL CHECK (status IN ('pending', 'active')),
|
|
18
|
+
created_at TEXT NOT NULL,
|
|
19
|
+
activated_at TEXT,
|
|
20
|
+
CHECK (is_primary = 0 OR status = 'active'),
|
|
21
|
+
CHECK ((status = 'active') = (activated_at IS NOT NULL))
|
|
22
|
+
);
|
|
23
|
+
CREATE UNIQUE INDEX domains_one_primary ON domains (is_primary) WHERE is_primary = 1;
|
|
24
|
+
|
|
25
|
+
-- Who may reach a domain: one row per domain and user, by user id (a
|
|
26
|
+
-- re-created username is a new user with no membership). Rows go when the
|
|
27
|
+
-- user is deleted or the domain removed; a disabled user keeps theirs but
|
|
28
|
+
-- is never rendered as a member. Changes take the directory's store-wide
|
|
29
|
+
-- sequence, as plugin audiences do.
|
|
30
|
+
CREATE TABLE domain_members (
|
|
31
|
+
domain TEXT NOT NULL REFERENCES domains (name),
|
|
32
|
+
user_id TEXT NOT NULL REFERENCES directory_users (user_id),
|
|
33
|
+
added_at TEXT NOT NULL,
|
|
34
|
+
added_by TEXT NOT NULL,
|
|
35
|
+
seq INTEGER NOT NULL DEFAULT 0,
|
|
36
|
+
PRIMARY KEY (domain, user_id)
|
|
37
|
+
);
|
|
38
|
+
CREATE INDEX domain_members_user ON domain_members (user_id);
|
|
39
|
+
|
|
40
|
+
CREATE TRIGGER domain_members_stamp_insert AFTER INSERT ON domain_members
|
|
41
|
+
BEGIN
|
|
42
|
+
UPDATE directory_counter SET seq = seq + 1 WHERE id = 1;
|
|
43
|
+
UPDATE domain_members SET seq = (SELECT seq FROM directory_counter WHERE id = 1)
|
|
44
|
+
WHERE domain = NEW.domain AND user_id = NEW.user_id;
|
|
45
|
+
END;
|
|
46
|
+
CREATE TRIGGER domain_members_stamp_delete AFTER DELETE ON domain_members
|
|
47
|
+
BEGIN
|
|
48
|
+
UPDATE directory_counter SET seq = seq + 1 WHERE id = 1;
|
|
49
|
+
END;
|
|
50
|
+
|
|
51
|
+
-- The domain a plugin belongs to — its OIDC clients' `{domain}` and sign-in,
|
|
52
|
+
-- its user and web surfaces, its audience. NULL: the primary domain.
|
|
53
|
+
ALTER TABLE plugins ADD COLUMN domain TEXT;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
-- The kind of a domain membership (packages/core/docs/external-members-design.md;
|
|
2
|
+
-- lib/domains.js): a `member` reaches what the domain gives its members, an
|
|
3
|
+
-- `external` member only what names them (a grant, a site's listed users, an
|
|
4
|
+
-- OIDC client granted to them). Every membership from before is a member.
|
|
5
|
+
ALTER TABLE domain_members ADD COLUMN kind TEXT NOT NULL DEFAULT 'member'
|
|
6
|
+
CHECK (kind IN ('member', 'external'));
|
|
7
|
+
|
|
8
|
+
-- A change of kind takes the directory's store-wide sequence, as an insert does.
|
|
9
|
+
CREATE TRIGGER domain_members_stamp_kind AFTER UPDATE OF kind ON domain_members
|
|
10
|
+
WHEN OLD.kind IS NOT NEW.kind
|
|
11
|
+
BEGIN
|
|
12
|
+
UPDATE directory_counter SET seq = seq + 1 WHERE id = 1;
|
|
13
|
+
UPDATE domain_members SET seq = (SELECT seq FROM directory_counter WHERE id = 1)
|
|
14
|
+
WHERE domain = NEW.domain AND user_id = NEW.user_id;
|
|
15
|
+
END;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
-- Opaque names for the Authelia groups Lamaste owns
|
|
2
|
+
-- (packages/core/docs/external-members-design.md, security review): a
|
|
3
|
+
-- domain's members and external members are `lamaste:m:<key>` and
|
|
4
|
+
-- `lamaste:x:<key>`, with a random key per domain, so an OIDC relying party
|
|
5
|
+
-- that asks for the `groups` claim learns no domain's name. The panel gives
|
|
6
|
+
-- a new domain its key when it inserts it; the trigger is the fallback, and
|
|
7
|
+
-- existing domains get one here.
|
|
8
|
+
ALTER TABLE domains ADD COLUMN group_key TEXT;
|
|
9
|
+
UPDATE domains SET group_key = lower(hex(randomblob(8))) WHERE group_key IS NULL;
|
|
10
|
+
CREATE UNIQUE INDEX domains_group_key ON domains(group_key);
|
|
11
|
+
CREATE TRIGGER domains_group_key_fill AFTER INSERT ON domains
|
|
12
|
+
WHEN NEW.group_key IS NULL
|
|
13
|
+
BEGIN
|
|
14
|
+
UPDATE domains SET group_key = lower(hex(randomblob(8))) WHERE name = NEW.name;
|
|
15
|
+
END;
|
|
16
|
+
|
|
17
|
+
-- Domains removed from the relay: hostnames under them are still Lamaste's
|
|
18
|
+
-- groups (a host group left on a user is stripped at the next rendering,
|
|
19
|
+
-- never taken for an administrator's group).
|
|
20
|
+
CREATE TABLE retired_domains (
|
|
21
|
+
name TEXT PRIMARY KEY,
|
|
22
|
+
removed_at TEXT NOT NULL
|
|
23
|
+
);
|