@ofidj/generator-fidj 3.17.0 → 3.18.1
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.
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"privacy:rehearse": "npm run build && node --test test/server.test.mjs"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@ofidj/entry": "^3.
|
|
19
|
-
"@ofidj/node": "^3.
|
|
18
|
+
"@ofidj/entry": "^3.18.0",
|
|
19
|
+
"@ofidj/node": "^3.18.1"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/node": "^22.0.0",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {signInErrorMessage, formatDate,
|
|
2
|
-
import {agreementScreen, bindAgreementScreen, bindPasswordReveal, acceptedAgreement, verificationWait, providerEntry, showEmailEntry, showVersionBadge, escape, masthead, highlightCells, badgeStrip, credentialFields, accountForm, passkeySupported, passkeyAssertion, walletDoor, oidcInteractionMarkup, oidcInteractionStyles, bindOidcInteraction} from "@ofidj/entry/dom";
|
|
1
|
+
import {signInErrorMessage, formatDate, agreementRequired, agreementFromRefusal, verificationPending, pollVerification, rememberSignIn, forgetSignIn, signInHint, type SigninShape} from "@ofidj/entry";
|
|
2
|
+
import {agreementScreen, bindAgreementScreen, bindPasswordReveal, acceptedAgreement, verificationWait, providerEntry, showEmailEntry, showVersionBadge, escape, masthead, highlightCells, badgeStrip, credentialFields, accountForm, passkeySupported, passkeyAssertion, walletDoor, memberCard, oidcInteractionMarkup, oidcInteractionStyles, bindOidcInteraction} from "@ofidj/entry/dom";
|
|
3
3
|
import {openProviderWindow, relayProviderAnswer, type ProviderWindow} from "@ofidj/entry/window";
|
|
4
4
|
import { FidjNodeService, FidjOidcClient } from "@ofidj/node";
|
|
5
5
|
import config from "../app.config.json";
|
|
@@ -167,7 +167,10 @@ async function request(path: string, method = "GET", data?: unknown) {
|
|
|
167
167
|
});
|
|
168
168
|
const result = await response.json();
|
|
169
169
|
if (!response.ok) {
|
|
170
|
-
|
|
170
|
+
// Only a 401 means the session is gone; a 403 refuses one action to
|
|
171
|
+
// somebody still signed in, and signing them out for it ended the console's
|
|
172
|
+
// session on the first forbidden request.
|
|
173
|
+
if (response.status === 401) {
|
|
171
174
|
signedIn = false;
|
|
172
175
|
await sdk.logout(true);
|
|
173
176
|
}
|
|
@@ -412,16 +415,16 @@ function signInThroughProvider(
|
|
|
412
415
|
void action(async () => {
|
|
413
416
|
let url: string;
|
|
414
417
|
try {
|
|
415
|
-
//
|
|
416
|
-
//
|
|
417
|
-
//
|
|
418
|
-
//
|
|
419
|
-
//
|
|
420
|
-
//
|
|
418
|
+
// Somebody who has just signed out of this app did not ask to be walked
|
|
419
|
+
// straight back in: the provider still knows the browser and would answer
|
|
420
|
+
// with a code and no screen. So the door asks which account — the consent
|
|
421
|
+
// screen names the one Fidj recognises and offers another. It does not ask
|
|
422
|
+
// for a password: prompt=login told Fidj "this is not me" and ended the
|
|
423
|
+
// Fidj session along with the app's.
|
|
421
424
|
url = await oidc.beginLogin(
|
|
422
425
|
options.prompt || options.silent || !oidc.signedOutHere()
|
|
423
426
|
? options
|
|
424
|
-
: {...options, prompt: "
|
|
427
|
+
: {...options, prompt: "consent"},
|
|
425
428
|
);
|
|
426
429
|
} catch (error) {
|
|
427
430
|
providerWindow?.giveUp();
|
|
@@ -917,7 +920,7 @@ function wirePrivacy() {
|
|
|
917
920
|
navigate("signin");
|
|
918
921
|
}),
|
|
919
922
|
);
|
|
920
|
-
element("terms")?.addEventListener(
|
|
923
|
+
element("accept-terms")?.addEventListener(
|
|
921
924
|
"click",
|
|
922
925
|
() =>
|
|
923
926
|
void action(async () => {
|
|
@@ -1001,36 +1004,15 @@ function accountRows() {
|
|
|
1001
1004
|
}
|
|
1002
1005
|
|
|
1003
1006
|
function privacyBlock() {
|
|
1004
|
-
const
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
:
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
)
|
|
1014
|
-
.join("");
|
|
1015
|
-
const entries = history.length
|
|
1016
|
-
? history
|
|
1017
|
-
.slice()
|
|
1018
|
-
.reverse()
|
|
1019
|
-
.map(
|
|
1020
|
-
(entry) =>
|
|
1021
|
-
`<p>${escape(formatDate(entry.changedAt, "datetime"))} · ${escape(entry.type)} ${entry.granted ? "given" : "withdrawn"}</p>`,
|
|
1022
|
-
)
|
|
1023
|
-
.join("")
|
|
1024
|
-
: "<p>No changes yet.</p>";
|
|
1025
|
-
const leave = roles.includes("Owner")
|
|
1026
|
-
? "<small>You own this app: hand it over or delete it on Fidj before leaving.</small>"
|
|
1027
|
-
: leaving
|
|
1028
|
-
? '<p>Your membership and what this app holds for you will be erased. Your other apps remain available.</p><button id="confirm-leave" class="danger">Leave & erase</button><button id="cancel-leave">Keep my membership</button>'
|
|
1029
|
-
: '<button id="leave" class="danger">Leave & erase</button>';
|
|
1030
|
-
return `<h2>Your membership</h2><div class="member-rows">${agreementRow}${choices}</div>
|
|
1031
|
-
<details class="member-history"><summary>History</summary>${entries}</details>
|
|
1032
|
-
<div class="member-actions"><button id="export">Export</button>${leave}</div>
|
|
1033
|
-
<p class="leaving"><a href="${escape(config.dashboardUrl)}/#/my/gdpr" target="_blank" rel="noopener noreferrer">Open Fidj to manage every app you use ↗</a></p>`;
|
|
1007
|
+
const version = String((consent as Record<string, unknown>).termsVersion || "");
|
|
1008
|
+
return memberCard({
|
|
1009
|
+
consent,
|
|
1010
|
+
history,
|
|
1011
|
+
agreementHref: `${config.apiEndpoint}/apps/${encodeURIComponent(config.appId)}/agreements/${encodeURIComponent(version)}`,
|
|
1012
|
+
owner: roles.includes("Owner"),
|
|
1013
|
+
leaving,
|
|
1014
|
+
manageHref: `${config.dashboardUrl}/#/my/gdpr`,
|
|
1015
|
+
});
|
|
1034
1016
|
}
|
|
1035
1017
|
|
|
1036
1018
|
// ------------------------------------------------ signing in, for the provider
|
|
@@ -1059,6 +1041,8 @@ type Interaction = {
|
|
|
1059
1041
|
recognisedEmail?: string;
|
|
1060
1042
|
// The passkey door's challenge, on the login step.
|
|
1061
1043
|
passkey?: {ticket: string; options: unknown};
|
|
1044
|
+
// The recognised person's agreement is on file at the version in force.
|
|
1045
|
+
agreementAccepted?: boolean;
|
|
1062
1046
|
action: string;
|
|
1063
1047
|
};
|
|
1064
1048
|
let interactionId = "";
|
|
@@ -1184,6 +1168,7 @@ function interactionScreen() {
|
|
|
1184
1168
|
agreementHref: details.termsUri || undefined,
|
|
1185
1169
|
recognisedEmail: details.recognisedEmail || undefined,
|
|
1186
1170
|
passkey: details.passkey,
|
|
1171
|
+
agreementAccepted: details.agreementAccepted,
|
|
1187
1172
|
logoSrc: "./fidj-logo.png",
|
|
1188
1173
|
})}`;
|
|
1189
1174
|
bindOidcInteraction(root);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {agreementRequired, agreementFromRefusal, signInErrorMessage, rememberSignIn, forgetSignIn, formatDate, type SigninShape} from "@ofidj/entry";
|
|
2
|
-
import {acceptedAgreement, agreementScreen, bindAgreementScreen, bindPasswordReveal, providerEntry, showEmailEntry, showVersionBadge} from "@ofidj/entry/dom";
|
|
2
|
+
import {acceptedAgreement, agreementScreen, memberCard, bindAgreementScreen, bindPasswordReveal, providerEntry, showEmailEntry, showVersionBadge} from "@ofidj/entry/dom";
|
|
3
3
|
import {openProviderWindow, relayProviderAnswer, type ProviderWindow} from "@ofidj/entry/window";
|
|
4
4
|
import { FidjNodeService, FidjOidcClient } from "@ofidj/node";
|
|
5
5
|
import "@ofidj/entry/style.css";
|
|
@@ -224,18 +224,18 @@ function render() {
|
|
|
224
224
|
${
|
|
225
225
|
view === "workspace"
|
|
226
226
|
? `<section class="workspace"><div><div class="section-heading"><h2>Your notes</h2><span>${notes.length} saved</span></div>${notes.length ? notes.map((note) => `<article class="card note"><small>${escape(formatDate(note.createdAt, "datetime"))}</small><h3>${escape(note.title)}</h3><p>${escape(note.body)}</p></article>`).join("") : `<article class="card empty"><span>✳</span><h3>Room for your next idea.</h3><p>Your saved notes will appear here. Only you can read your notes.</p></article>`}</div><form id="note" class="card"><p class="eyebrow">CAPTURE SOMETHING</p><h2>A fresh note</h2><p>${canWrite ? "You have permission to save notes." : "Ask your app owner for Editor access to save notes."}</p><label for="note-title">Title</label><input id="note-title" maxlength="120" required ${!canWrite ? "disabled" : ""}><label for="note-body">Your note</label><textarea id="note-body" rows="6" maxlength="5000" ${!canWrite ? "disabled" : ""}></textarea><button class="primary" type="submit" ${!canWrite ? "disabled" : ""}>Save note</button><small>Your notes are saved by this app and survive a server restart.</small></form></section>`
|
|
227
|
-
: `<section class="
|
|
228
|
-
privacy?.
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}
|
|
227
|
+
: `<section class="card privacy-card">${memberCard({
|
|
228
|
+
consent: privacy?.consent || {},
|
|
229
|
+
history: privacy?.history || [],
|
|
230
|
+
agreementHref: privacy?.consent.termsVersion
|
|
231
|
+
? `${settings.apiEndpoint}/apps/${encodeURIComponent(settings.appId)}/agreements/${encodeURIComponent(String(privacy.consent.termsVersion))}`
|
|
232
|
+
: undefined,
|
|
233
|
+
owner: session.roles.includes("Owner"),
|
|
234
|
+
leaving,
|
|
235
|
+
leaveScope:
|
|
236
|
+
"Your membership, your choices and your notes in this app will be erased. Your Fidj account and other apps remain available.",
|
|
237
|
+
manageHref: `${settings.dashboardUrl}/#/my/gdpr`,
|
|
238
|
+
})}</section>`
|
|
239
239
|
}`
|
|
240
240
|
}
|
|
241
241
|
<footer>Built with Fidj · One identity. Separate choices for every app.</footer></main>`;
|
|
@@ -348,7 +348,7 @@ function render() {
|
|
|
348
348
|
void action(async () => {
|
|
349
349
|
await api("privacy", "PUT", { terms: true });
|
|
350
350
|
await load();
|
|
351
|
-
notice = "
|
|
351
|
+
notice = "Service agreement accepted.";
|
|
352
352
|
}),
|
|
353
353
|
);
|
|
354
354
|
el("export")?.addEventListener(
|