@lamalibre/create-lamaste 4.6.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 +22 -3
- 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/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 +15 -5
- 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 +17 -13
- 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 +35 -7
- 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 +5 -0
- package/vendor/docs/04-api-reference/tunnels.md +15 -10
- 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 +6 -6
- package/vendor/docs/06-reference/config-files.md +1 -1
- 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/cli/index.js +0 -0
- 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/server/index.d.ts +5 -1
- package/vendor/gatekeeper/dist/server/index.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/server/index.js +28 -2
- 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 +225 -36
- 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/plugins.js +112 -8
- package/vendor/server/src/commands/registry-credential.js +10 -3
- package/vendor/server/src/commands/sites.js +3 -0
- 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-ui/dist/assets/index-B8Tv_ocF.js +84 -0
- package/vendor/server-ui/dist/assets/{index-BZwQ_aQc.css → index-Cb-ADsbB.css} +1 -1
- package/vendor/server-ui/dist/index.html +2 -2
- package/vendor/serverd/package.json +2 -2
- package/vendor/serverd/src/index.js +42 -16
- 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/directory.js +67 -52
- package/vendor/serverd/src/lib/domains.js +1792 -0
- package/vendor/serverd/src/lib/gatekeeper-client.js +20 -4
- package/vendor/serverd/src/lib/identity-sync.js +35 -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 +318 -140
- 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-lifecycle.js +1 -0
- package/vendor/serverd/src/lib/plugin-oidc.js +144 -42
- package/vendor/serverd/src/lib/plugins.js +45 -5
- 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 +11 -0
- package/vendor/serverd/src/lib/tunnel-deps.js +2 -4
- package/vendor/serverd/src/lib/user-surface.js +29 -4
- package/vendor/serverd/src/lib/users-lock.js +23 -0
- package/vendor/serverd/src/lib/vhost-reconcile.js +149 -41
- package/vendor/serverd/src/lib/web-surface.js +49 -32
- 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/plugins.js +4 -2
- package/vendor/serverd/src/routes/management/registry-credential.js +86 -57
- package/vendor/serverd/src/routes/management/sites.js +50 -11
- package/vendor/serverd/src/routes/management/tunnels.js +29 -5
- package/vendor/serverd/src/routes/management/users.js +184 -64
- package/vendor/serverd/src/routes/management.js +2 -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-BvEfCZYS.js +0 -84
|
@@ -14,15 +14,16 @@
|
|
|
14
14
|
*
|
|
15
15
|
* users.yml is never written from here. Every write of it goes through
|
|
16
16
|
* {@link changeUsers}: one in-process lock around the read-modify-write,
|
|
17
|
-
* then the directory is reconciled against the file, then
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
17
|
+
* then the directory is reconciled against the file, then the domains are
|
|
18
|
+
* rendered (the groups Lamaste owns in users.yml among them — Authelia
|
|
19
|
+
* watches the file and applies a change at each user's next request, with
|
|
20
|
+
* no restart: no session ends), then the plugins' audiences are
|
|
21
|
+
* recomputed. The reconcile ({@link reconcileDirectory}) also runs at
|
|
22
|
+
* start, every minute and after onboarding — read only. It adopts what
|
|
23
|
+
* changed outside Lamaste (Authelia's own password reset rewrites the file;
|
|
24
|
+
* an operator may edit it), and only after reading the file twice does it
|
|
25
|
+
* take a user for deleted outside — Authelia rewrites the file in place,
|
|
26
|
+
* and a read that met a half-written file must not tombstone anyone.
|
|
26
27
|
*
|
|
27
28
|
* Gatekeeper keys users by username too: the grants naming a user and
|
|
28
29
|
* their memberships of Lamaste groups would pass to anyone who later holds
|
|
@@ -56,21 +57,32 @@
|
|
|
56
57
|
* Authelia second factors go; Gatekeeper's cached session verdicts are
|
|
57
58
|
* dropped. Every reconcile offboards exactly the users it saw change.
|
|
58
59
|
*
|
|
60
|
+
* **Domains** (lib/domains.js): a user created here becomes a member of
|
|
61
|
+
* the domains they are created with (`changeUsers`' `domains`) — or, while
|
|
62
|
+
* the relay has one domain, of that one, whoever created them; a removed
|
|
63
|
+
* user's memberships end in the same transaction. Every `changeUsers`
|
|
64
|
+
* renders the domains' members into users.yml's owned groups, Gatekeeper's
|
|
65
|
+
* projection and Authelia's configuration.
|
|
66
|
+
*
|
|
59
67
|
* Audit entries name users by their id alone: never a username, a name or
|
|
60
68
|
* an address.
|
|
61
69
|
*/
|
|
62
70
|
|
|
63
71
|
import crypto from 'node:crypto';
|
|
64
|
-
import { PromiseChainMutex } from '@lamalibre/lamaste';
|
|
65
72
|
import { httpError } from './app-error.js';
|
|
66
73
|
import { recordAuditBestEffort } from './audit.js';
|
|
67
74
|
import {
|
|
68
75
|
autheliaHoldsOidcIdentity,
|
|
69
76
|
purgeAutheliaUserSecondFactors,
|
|
70
77
|
readUsersRaw,
|
|
71
|
-
reloadAuthelia,
|
|
72
78
|
} from './authelia.js';
|
|
73
79
|
import { bumpUserEpoch } from './config.js';
|
|
80
|
+
import {
|
|
81
|
+
deleteMembershipsSync,
|
|
82
|
+
domainsForNewUser,
|
|
83
|
+
insertMembershipsSync,
|
|
84
|
+
syncDomainAccess,
|
|
85
|
+
} from './domains.js';
|
|
74
86
|
import {
|
|
75
87
|
bustGatekeeperSessions,
|
|
76
88
|
purgeAccessLogForUser,
|
|
@@ -80,6 +92,7 @@ import { revokeUserRegistryTokens } from './registry-credential.js';
|
|
|
80
92
|
import { getStateDb } from './state-db.js';
|
|
81
93
|
import { readInvitations, withInvitationsLock, writeInvitations } from './state.js';
|
|
82
94
|
import { removeGrantsForUser } from './user-access.js';
|
|
95
|
+
import { withUsersLock } from './users-lock.js';
|
|
83
96
|
|
|
84
97
|
/** How long the reconcile waits before reading users.yml again to confirm a user is gone. */
|
|
85
98
|
const DIRECTORY_CONFIRM_DELAY_MS = 500;
|
|
@@ -118,25 +131,6 @@ export const ADMIN_GROUP = 'admins';
|
|
|
118
131
|
* @property {string[]} disabled the ids of users this reconcile saw become disabled
|
|
119
132
|
*/
|
|
120
133
|
|
|
121
|
-
// ---------------------------------------------------------------------------
|
|
122
|
-
// The users lock
|
|
123
|
-
// ---------------------------------------------------------------------------
|
|
124
|
-
|
|
125
|
-
const usersMutex = new PromiseChainMutex();
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Run `fn` holding the users lock — the one lock around every
|
|
129
|
-
* read-modify-write of users.yml and every change of the directory in this
|
|
130
|
-
* process (core's users functions take none).
|
|
131
|
-
*
|
|
132
|
-
* @template T
|
|
133
|
-
* @param {() => Promise<T>} fn
|
|
134
|
-
* @returns {Promise<T>}
|
|
135
|
-
*/
|
|
136
|
-
function withUsersLock(fn) {
|
|
137
|
-
return usersMutex.run(fn);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
134
|
// ---------------------------------------------------------------------------
|
|
141
135
|
// Reading
|
|
142
136
|
// ---------------------------------------------------------------------------
|
|
@@ -533,9 +527,11 @@ function assertNotEmpty(snapshot, live) {
|
|
|
533
527
|
}
|
|
534
528
|
|
|
535
529
|
/**
|
|
536
|
-
* {@link reconcileDirectory} with the users lock already held.
|
|
530
|
+
* {@link reconcileDirectory} with the users lock already held. A user it
|
|
531
|
+
* creates becomes a member of `domains[username]` when given, else of the
|
|
532
|
+
* relay's one domain (none with two or more).
|
|
537
533
|
*
|
|
538
|
-
* @param {{ actor: string, logger?: import('pino').Logger, deleted?: string[], confirmDelayMs?: number }} opts
|
|
534
|
+
* @param {{ actor: string, logger?: import('pino').Logger, deleted?: string[], confirmDelayMs?: number, domains?: Readonly<Record<string, readonly string[]>> }} opts
|
|
539
535
|
* @returns {Promise<DirectoryReconcileResult>}
|
|
540
536
|
*/
|
|
541
537
|
async function reconcileUnlocked({
|
|
@@ -543,6 +539,7 @@ async function reconcileUnlocked({
|
|
|
543
539
|
logger,
|
|
544
540
|
deleted = [],
|
|
545
541
|
confirmDelayMs = DIRECTORY_CONFIRM_DELAY_MS,
|
|
542
|
+
domains = {},
|
|
546
543
|
}) {
|
|
547
544
|
const db = await getStateDb();
|
|
548
545
|
const live = db
|
|
@@ -566,6 +563,12 @@ async function reconcileUnlocked({
|
|
|
566
563
|
const missing = live.filter((u) => absentFirst.has(u.username) && !snapshot.has(u.username));
|
|
567
564
|
|
|
568
565
|
const now = new Date().toISOString();
|
|
566
|
+
// The domains of a user this reconcile creates without being told theirs:
|
|
567
|
+
// read only when it creates one.
|
|
568
|
+
const creating = [...snapshot.keys()].some(
|
|
569
|
+
(username) => !Object.hasOwn(domains, username) && !live.some((u) => u.username === username),
|
|
570
|
+
);
|
|
571
|
+
const defaultDomains = creating ? await domainsForNewUser(undefined) : [];
|
|
569
572
|
const events = [];
|
|
570
573
|
const result = { created: 0, updated: 0, removed: [], disabled: [] };
|
|
571
574
|
const selectLive = db.prepare(
|
|
@@ -594,6 +597,7 @@ async function reconcileUnlocked({
|
|
|
594
597
|
remove.run(reason, now, now, user.userId);
|
|
595
598
|
result.removed.push({ userId: user.userId, username: user.username, reason });
|
|
596
599
|
events.push({ action: 'directory.user.removed', details: { userId: user.userId, reason } });
|
|
600
|
+
events.push(...deleteMembershipsSync(db, user.userId, reason));
|
|
597
601
|
}
|
|
598
602
|
for (const [username, attrs] of snapshot) {
|
|
599
603
|
const row = selectLive.get(username);
|
|
@@ -605,6 +609,8 @@ async function reconcileUnlocked({
|
|
|
605
609
|
action: 'directory.user.created',
|
|
606
610
|
details: { userId, status: attrs.status },
|
|
607
611
|
});
|
|
612
|
+
const memberOf = Object.hasOwn(domains, username) ? domains[username] : defaultDomains;
|
|
613
|
+
events.push(...insertMembershipsSync(db, userId, memberOf, { actor, now }));
|
|
608
614
|
continue;
|
|
609
615
|
}
|
|
610
616
|
const changed = [];
|
|
@@ -654,7 +660,7 @@ async function reconcileUnlocked({
|
|
|
654
660
|
* before the username is given to anyone). Each step is best effort; what
|
|
655
661
|
* failed comes back as `warnings` (`{ step, message }`, never naming the
|
|
656
662
|
* user). Gatekeeper's cached session verdicts are not dropped here: the
|
|
657
|
-
* caller does that once, after
|
|
663
|
+
* caller does that once, after the domains were rendered.
|
|
658
664
|
*
|
|
659
665
|
* @param {string} userId
|
|
660
666
|
* @param {{ kind: 'disabled' | 'deleted', actor: string, logger?: import('pino').Logger }} opts
|
|
@@ -798,16 +804,21 @@ export function reconcileDirectory({ actor = 'lamaste', logger, confirmDelayMs }
|
|
|
798
804
|
* that cannot be done: a new user never inherits an earlier one's grants,
|
|
799
805
|
* groups or second factors);
|
|
800
806
|
* 3. `mutate`, then reconcile the directory (`deleted` names the usernames
|
|
801
|
-
* `mutate` deletes: removed as `deleted`
|
|
807
|
+
* `mutate` deletes: removed as `deleted`; `domains` the domains of the
|
|
808
|
+
* users it creates — lib/domains.js), offboarding every user that
|
|
802
809
|
* reconcile saw removed or newly disabled ({@link offboardUserUnlocked});
|
|
803
|
-
* 4.
|
|
804
|
-
*
|
|
805
|
-
* session verdicts
|
|
810
|
+
* 4. render the domains' members (lib/domains.js `syncDomainAccess`: the
|
|
811
|
+
* owned groups in users.yml, the projection, Authelia's configuration)
|
|
812
|
+
* and drop Gatekeeper's cached session verdicts. Authelia is not
|
|
813
|
+
* restarted: it watches users.yml, and every user's next request sees
|
|
814
|
+
* the change — a disabled or deleted user's session ends there. With
|
|
815
|
+
* `renderDomains: false` (onboarding, before any domain or Gatekeeper
|
|
816
|
+
* exists) neither happens: the caller renders;
|
|
806
817
|
* 5. with `expect` (`(users) => boolean` over users.yml's `users` map: does
|
|
807
818
|
* the file hold the intended change?), read users.yml again: Authelia's
|
|
808
|
-
* own password reset rewrites the file from what it read
|
|
809
|
-
* write made
|
|
810
|
-
* there it is made once more (steps 3 and 4); when it is still not
|
|
819
|
+
* own password reset rewrites the file from what it last read, so a
|
|
820
|
+
* write made within its reload cooldown can be lost. When the change is
|
|
821
|
+
* not there it is made once more (steps 3 and 4); when it is still not
|
|
811
822
|
* there, `persisted` is false and a `persist` warning says so.
|
|
812
823
|
*
|
|
813
824
|
* Then the plugins' audiences are recomputed. A refusal `mutate` (or step
|
|
@@ -818,7 +829,7 @@ export function reconcileDirectory({ actor = 'lamaste', logger, confirmDelayMs }
|
|
|
818
829
|
*
|
|
819
830
|
* @template T
|
|
820
831
|
* @param {() => Promise<T>} mutate
|
|
821
|
-
* @param {{ actor: string, logger?: import('pino').Logger, creates?: string[], deleted?: string[],
|
|
832
|
+
* @param {{ actor: string, logger?: import('pino').Logger, creates?: string[], deleted?: string[], domains?: Readonly<Record<string, ReadonlyArray<string | { name: string, kind: 'member' | 'external' }>>>, renderDomains?: boolean, autheliaStorage?: boolean, confirmDelayMs?: number, expect?: (users: Record<string, unknown>) => boolean }} opts
|
|
822
833
|
* @returns {Promise<{ result: T, directory: DirectoryReconcileResult | null, warnings: Array<{ step: string, message: string }>, persisted: boolean }>}
|
|
823
834
|
*/
|
|
824
835
|
export async function changeUsers(
|
|
@@ -828,7 +839,8 @@ export async function changeUsers(
|
|
|
828
839
|
logger,
|
|
829
840
|
creates = [],
|
|
830
841
|
deleted = [],
|
|
831
|
-
|
|
842
|
+
domains = {},
|
|
843
|
+
renderDomains = true,
|
|
832
844
|
autheliaStorage = true,
|
|
833
845
|
confirmDelayMs,
|
|
834
846
|
expect,
|
|
@@ -840,7 +852,7 @@ export async function changeUsers(
|
|
|
840
852
|
const settle = async () => {
|
|
841
853
|
let reconciled = null;
|
|
842
854
|
try {
|
|
843
|
-
reconciled = await reconcileUnlocked({ actor, logger, deleted, confirmDelayMs });
|
|
855
|
+
reconciled = await reconcileUnlocked({ actor, logger, deleted, confirmDelayMs, domains });
|
|
844
856
|
} catch (err) {
|
|
845
857
|
logger?.error({ err: err.message }, 'Could not bring the user directory in line');
|
|
846
858
|
warnings.push({
|
|
@@ -868,13 +880,16 @@ export async function changeUsers(
|
|
|
868
880
|
return reconciled;
|
|
869
881
|
};
|
|
870
882
|
|
|
871
|
-
const
|
|
872
|
-
if (!
|
|
883
|
+
const render = async () => {
|
|
884
|
+
if (!renderDomains) return;
|
|
873
885
|
try {
|
|
874
|
-
await
|
|
886
|
+
await syncDomainAccess({ logger });
|
|
875
887
|
} catch (err) {
|
|
876
|
-
logger?.
|
|
877
|
-
warnings.push({
|
|
888
|
+
logger?.error({ err: err.message }, 'Rendering domain access after a users change failed');
|
|
889
|
+
warnings.push({
|
|
890
|
+
step: 'domains',
|
|
891
|
+
message: `Who may reach each domain was not rendered (${err.message}); the panel renders it again within a minute`,
|
|
892
|
+
});
|
|
878
893
|
}
|
|
879
894
|
warnings.push(...(await bustCachedSessions(logger)));
|
|
880
895
|
};
|
|
@@ -907,13 +922,13 @@ export async function changeUsers(
|
|
|
907
922
|
}
|
|
908
923
|
let value = await mutate();
|
|
909
924
|
let reconciled = await settle();
|
|
910
|
-
await
|
|
925
|
+
await render();
|
|
911
926
|
|
|
912
927
|
let persisted = true;
|
|
913
928
|
if (expect && !(await holds())) {
|
|
914
929
|
// Authelia rewrote users.yml over the change (its own password reset
|
|
915
|
-
// writes the file from what it read
|
|
916
|
-
logger?.warn('users.yml lost a change
|
|
930
|
+
// writes the file from what it last read): make it once more.
|
|
931
|
+
logger?.warn('users.yml lost a change to a write of Authelia — making it again');
|
|
917
932
|
try {
|
|
918
933
|
value = await mutate();
|
|
919
934
|
const again = await settle();
|
|
@@ -927,7 +942,7 @@ export async function changeUsers(
|
|
|
927
942
|
}
|
|
928
943
|
: again;
|
|
929
944
|
}
|
|
930
|
-
await
|
|
945
|
+
await render();
|
|
931
946
|
persisted = await holds();
|
|
932
947
|
} catch (err) {
|
|
933
948
|
logger?.warn({ err: err.message }, 'Making a lost users change again failed');
|