fedipod-server 0.11.0 → 0.13.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/README.md +22 -6
- package/dist/claims.d.ts +8 -0
- package/dist/claims.js +10 -0
- package/dist/handler.d.ts +13 -0
- package/dist/handler.js +56 -11
- package/dist/handler.jsonld +8 -0
- package/dist/store-pod.js +18 -4
- package/lib/{c2s.mjs → client/c2s.mjs} +10 -3
- package/lib/{localapi.mjs → client/localapi.mjs} +2 -2
- package/lib/client/masto/accounts.mjs +264 -0
- package/lib/client/masto/body.mjs +69 -0
- package/lib/client/masto/index.mjs +183 -0
- package/lib/client/masto/instance.mjs +104 -0
- package/lib/client/masto/media.mjs +133 -0
- package/lib/client/masto/oauth.mjs +599 -0
- package/lib/client/masto/render.mjs +459 -0
- package/lib/client/masto/statuses.mjs +331 -0
- package/lib/client/masto/timelines.mjs +316 -0
- package/lib/{streaming.mjs → client/streaming.mjs} +1 -1
- package/lib/{acctfeed.mjs → connections/acctfeed.mjs} +1 -1
- package/lib/{atproto.mjs → connections/atproto.mjs} +15 -16
- package/lib/{bskygroup.mjs → connections/bskygroup.mjs} +1 -1
- package/lib/{fediacct.mjs → connections/fediacct.mjs} +31 -35
- package/lib/{import.mjs → connections/import.mjs} +1 -1
- package/lib/{tagfeed.mjs → connections/tagfeed.mjs} +3 -3
- package/lib/connections/vault.mjs +114 -0
- package/lib/core/as2.mjs +170 -0
- package/lib/core/contexts/activitystreams.json +379 -0
- package/lib/core/contexts/did-v1.json +57 -0
- package/lib/core/contexts/fep-5711.json +36 -0
- package/lib/core/contexts/gotosocial.json +86 -0
- package/lib/core/contexts/identity-v1.json +152 -0
- package/lib/core/contexts/index.mjs +45 -0
- package/lib/core/contexts/join-lemmy.json +33 -0
- package/lib/core/contexts/joinmastodon.json +28 -0
- package/lib/core/contexts/map.json +16 -0
- package/lib/core/contexts/miscellany.json +19 -0
- package/lib/core/contexts/schemaorg.json +8845 -0
- package/lib/core/contexts/security-data-integrity-v1.json +78 -0
- package/lib/core/contexts/security-data-integrity-v2.json +81 -0
- package/lib/core/contexts/security-multikey-v1.json +35 -0
- package/lib/core/contexts/security-v1.json +74 -0
- package/lib/core/contexts/webfinger.json +10 -0
- package/lib/{deliver.mjs → core/deliver.mjs} +2 -2
- package/lib/core/graphview.mjs +269 -0
- package/lib/core/intake/activities.mjs +437 -0
- package/lib/core/intake/activity.mjs +240 -0
- package/lib/core/intake/channel.mjs +144 -0
- package/lib/core/intake/group.mjs +222 -0
- package/lib/core/intake/index.mjs +629 -0
- package/lib/core/intake/notes.mjs +288 -0
- package/lib/core/intake/verify.mjs +142 -0
- package/lib/{keys.mjs → core/keys.mjs} +1 -1
- package/lib/core/publisher/collections.mjs +229 -0
- package/lib/core/publisher/index.mjs +421 -0
- package/lib/core/publisher/notes.mjs +188 -0
- package/lib/core/publisher/questions.mjs +233 -0
- package/lib/core/publisher/restore.mjs +199 -0
- package/lib/core/shapes/activitystreams.ttl +129 -0
- package/lib/core/shapes/index.mjs +107 -0
- package/lib/core/shapes/shapes-text.mjs +13 -0
- package/lib/{social.mjs → core/social.mjs} +2 -2
- package/lib/{store.mjs → core/store.mjs} +4 -0
- package/lib/{wire.mjs → core/wire.mjs} +2 -2
- package/lib/device/admin/index.mjs +13 -0
- package/lib/device/admin/origins.mjs +35 -0
- package/lib/device/admin/routes/connections.mjs +144 -0
- package/lib/device/admin/routes/gateway.mjs +199 -0
- package/lib/device/admin/routes/lifecycle.mjs +191 -0
- package/lib/device/admin/routes/owner.mjs +322 -0
- package/lib/device/admin/routes/setup.mjs +393 -0
- package/lib/device/admin/routes/social.mjs +188 -0
- package/lib/device/admin/server.mjs +95 -0
- package/lib/device/admin/static.mjs +244 -0
- package/lib/device/admin/surface.mjs +274 -0
- package/lib/device/cli/commands/account.mjs +586 -0
- package/lib/device/cli/commands/run.mjs +278 -0
- package/lib/device/cli/commands/service.mjs +221 -0
- package/lib/device/cli/commands/setup.mjs +410 -0
- package/lib/device/cli/commands/state.mjs +559 -0
- package/lib/device/cli/context.mjs +288 -0
- package/lib/{migrate.mjs → device/migrate.mjs} +1 -1
- package/lib/{remote.mjs → device/remote.mjs} +3 -3
- package/lib/{setup.mjs → device/setup.mjs} +3 -3
- package/lib/{update.mjs → device/update.mjs} +1 -1
- package/lib/{directory.mjs → gateway/directory.mjs} +1 -1
- package/lib/{front-core.mjs → gateway/front-core.mjs} +3 -3
- package/lib/{gateway-core.mjs → gateway/gateway-core.mjs} +1 -1
- package/lib/{httpsig.mjs → gateway/httpsig.mjs} +1 -1
- package/lib/server/embed.mjs +405 -0
- package/lib/{links.mjs → shared/links.mjs} +1 -1
- package/lib/{ua.mjs → shared/ua.mjs} +1 -1
- package/package.json +1 -1
- package/run-agent.mjs +33 -25
- package/web/admin/actors.js +145 -0
- package/web/admin/common.js +23 -0
- package/web/admin/connections.js +112 -0
- package/web/admin/gateway.js +111 -0
- package/web/admin/group.js +258 -0
- package/web/admin/index.html +7 -1
- package/web/admin/record.js +378 -0
- package/web/admin/setup/index.html +1 -0
- package/web/admin/setup/setup.js +2 -13
- package/web/admin/upkeep.js +170 -0
- package/web/app/README.md +6 -6
- package/web/app/admin-facade.mjs +3 -3
- package/web/app/agent.mjs +14 -16
- package/web/app/atproto-browser.mjs +1 -1
- package/web/app/boot.mjs +2 -3
- package/web/app/deliver-relay.mjs +1 -1
- package/web/app/dist/boot.js +22 -3
- package/web/app/dist/boot.js.map +2 -2
- package/web/app/dist/sw.js +21913 -5446
- package/web/app/dist/sw.js.map +4 -4
- package/web/app/fediacct-browser.mjs +1 -1
- package/web/app/keys-browser.mjs +27 -4
- package/web/app/shims/shapes-text.mjs +8 -0
- package/web/app/signup.mjs +2 -3
- package/web/app/site/admin/actors.js +145 -0
- package/web/app/site/admin/common.js +23 -0
- package/web/app/site/admin/connections.js +112 -0
- package/web/app/site/admin/gateway.js +111 -0
- package/web/app/site/admin/group.js +258 -0
- package/web/app/site/admin/index.html +7 -1
- package/web/app/site/admin/record.js +378 -0
- package/web/app/site/admin/setup/index.html +1 -0
- package/web/app/site/admin/setup/setup.js +2 -13
- package/web/app/site/admin/upkeep.js +170 -0
- package/web/app/site/boot.js +22 -3
- package/web/app/site/sw.js +21913 -5446
- package/web/app/sw-src.mjs +17 -2
- package/lib/admin.mjs +0 -1913
- package/lib/embed.mjs +0 -220
- package/lib/intake.mjs +0 -1981
- package/lib/mastoapi.mjs +0 -2284
- package/lib/publisher.mjs +0 -1192
- package/web/admin/admin.js +0 -1181
- package/web/app/site/admin/admin.js +0 -1181
- /package/lib/{oidc-auth.mjs → client/oidc-auth.mjs} +0 -0
- /package/lib/{webpush.mjs → client/webpush.mjs} +0 -0
- /package/lib/{bskyfeed.mjs → connections/bskyfeed.mjs} +0 -0
- /package/lib/{lease.mjs → core/lease.mjs} +0 -0
- /package/lib/{polls.mjs → core/polls.mjs} +0 -0
- /package/lib/{proof.mjs → core/proof.mjs} +0 -0
- /package/lib/{storage.mjs → core/storage.mjs} +0 -0
- /package/lib/{account.mjs → device/account.mjs} +0 -0
- /package/lib/{certs.mjs → device/certs.mjs} +0 -0
- /package/lib/{export-collections.mjs → device/export-collections.mjs} +0 -0
- /package/lib/{home.mjs → device/home.mjs} +0 -0
- /package/lib/{ports.mjs → device/ports.mjs} +0 -0
- /package/lib/{guard.mjs → shared/guard.mjs} +0 -0
- /package/lib/{safefetch.mjs → shared/safefetch.mjs} +0 -0
|
@@ -3,26 +3,15 @@
|
|
|
3
3
|
// at localhost:<port> or at <handle>.localhost:<port>.
|
|
4
4
|
//
|
|
5
5
|
// External file, not an inline script: the CSP allows 'self' plus the hashes
|
|
6
|
-
// of Phanpy's own inline bootstrap, and nothing else.
|
|
6
|
+
// of Phanpy's own inline bootstrap, and nothing else. `$`, `BASE`, `api` and
|
|
7
|
+
// `postJson` come from ../common.js, loaded first.
|
|
7
8
|
|
|
8
|
-
const $ = (id) => document.getElementById(id);
|
|
9
9
|
// Empty means gone, not a blank line where a sentence used to be.
|
|
10
10
|
const strap = (t) => { const el = $('strap'); el.textContent = t || ''; el.hidden = !t; };
|
|
11
11
|
// By id, not by position: these were `body > section` until a wrapper went
|
|
12
12
|
// round them for layout, and the selector then matched nothing — every pane
|
|
13
13
|
// kept whatever it started as and the page sat on "Reading this agent's state".
|
|
14
14
|
const show = (id) => { for (const s of document.querySelectorAll('section[id^="pane-"]')) s.hidden = s.id !== id; };
|
|
15
|
-
// The door this page is served behind: nothing when the agent runs on this
|
|
16
|
-
// machine, `/app` when the identity is hosted by its own pod server. Read from
|
|
17
|
-
// the page's own address, so one build serves both.
|
|
18
|
-
const BASE = location.pathname.replace(/\/admin\/.*$/u, '');
|
|
19
|
-
const api = async (path, init) => {
|
|
20
|
-
const res = await fetch(BASE + path, { ...init, headers: { ...(init?.headers || {}), 'x-fedipod-page': '1' } });
|
|
21
|
-
return { status: res.status, json: await res.json().catch(() => null) };
|
|
22
|
-
};
|
|
23
|
-
const postJson = (path, body) => api(path, {
|
|
24
|
-
method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body),
|
|
25
|
-
});
|
|
26
15
|
|
|
27
16
|
let state = null;
|
|
28
17
|
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// upkeep.js — upkeep and the lifecycle: the output pane, drain, recover,
|
|
2
|
+
// log and dead letters; the confirmations for rotate, retire and move; and
|
|
3
|
+
// the inbox backlog panel.
|
|
4
|
+
|
|
5
|
+
// Which button filled the output pane, so clicking that one again closes it
|
|
6
|
+
// rather than re-fetching the same thing under an already-open panel.
|
|
7
|
+
let outputSource = null;
|
|
8
|
+
|
|
9
|
+
const OUTPUT_TITLES = { log: 'Log', deadletter: 'Dead letters', drain: 'Inbox drain', rebuild: 'Recovered posts' };
|
|
10
|
+
const output = (obj, source = null) => {
|
|
11
|
+
closePanels('output');
|
|
12
|
+
outputSource = source;
|
|
13
|
+
solWindow.show('output', OUTPUT_TITLES[source] || 'Output');
|
|
14
|
+
$('output').textContent = typeof obj === 'string' ? obj : JSON.stringify(obj, null, 2);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const showingFrom = (source) => outputSource === source && solWindow.openId() === 'output';
|
|
18
|
+
|
|
19
|
+
// Drain is the one that does work rather than reveals it, so a second click
|
|
20
|
+
// re-runs instead of closing. It can take a while — the agent joins a sweep
|
|
21
|
+
// already in flight and queues another after it — and a button that looks dead
|
|
22
|
+
// for a minute reads as broken.
|
|
23
|
+
$('do-drain').addEventListener('click', async (ev) => {
|
|
24
|
+
const b = ev.currentTarget;
|
|
25
|
+
b.disabled = true;
|
|
26
|
+
b.textContent = 'draining…';
|
|
27
|
+
say('draining the inbox — if a sweep is already running this waits for it to finish');
|
|
28
|
+
const r = await write('/drain', {}, 'inbox drained');
|
|
29
|
+
b.disabled = false;
|
|
30
|
+
b.textContent = 'Drain the inbox';
|
|
31
|
+
if (r) {
|
|
32
|
+
const box = r.inbox || {};
|
|
33
|
+
say(`inbox drained — ${box.count ?? 0} still waiting`);
|
|
34
|
+
output(r, 'drain');
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Like the drain, this does work rather than reveals it, so a second click
|
|
39
|
+
// re-runs. Nothing here can lose anything: it only adds posts back.
|
|
40
|
+
$('do-rebuild').addEventListener('click', async (ev) => {
|
|
41
|
+
const b = ev.currentTarget;
|
|
42
|
+
b.disabled = true;
|
|
43
|
+
b.textContent = 'recovering…';
|
|
44
|
+
say('reading what the pod still holds — one request per post, so this takes a moment');
|
|
45
|
+
const r = await write('/rebuild', {}, 'checked');
|
|
46
|
+
b.disabled = false;
|
|
47
|
+
b.textContent = 'Recover posts';
|
|
48
|
+
if (!r) return;
|
|
49
|
+
if (r.why) { say(r.why, 'err'); return; }
|
|
50
|
+
if (!r.landed) { say('recovered posts could NOT be saved — see the log', 'err'); return; }
|
|
51
|
+
say(r.recovered
|
|
52
|
+
? `recovered ${r.recovered} post(s) the pod had and this machine did not`
|
|
53
|
+
: `nothing was missing — the pod indexed ${r.indexed} post(s), all of them already here`);
|
|
54
|
+
output(r, 'rebuild');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
$('do-log').addEventListener('click', async () => {
|
|
58
|
+
if (showingFrom('log')) { closePanels(); return; }
|
|
59
|
+
const { json } = await api('/log');
|
|
60
|
+
output((json?.lines || []).slice(-60).join('\n') || 'nothing logged yet', 'log');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
$('do-deadletter').addEventListener('click', async () => {
|
|
64
|
+
if (showingFrom('deadletter')) { closePanels(); return; }
|
|
65
|
+
const { json } = await api('/deadletter');
|
|
66
|
+
output(json?.items?.length ? json.items : 'no dead letters', 'deadletter');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// ---- lifecycle ----
|
|
70
|
+
// None of these can be taken back by clicking again, so the button only opens
|
|
71
|
+
// the matching warning in the markup; the second click is the one that acts.
|
|
72
|
+
// Retire also wants the handle typed, because a misclick cannot produce it.
|
|
73
|
+
|
|
74
|
+
const LIFECYCLE = {
|
|
75
|
+
'rotate-key': { path: '/rotate-key', title: 'Rotate the signing key', done: (r) => (r.changed ? 'rotated and republished' : 'no change — the key was already fresh') },
|
|
76
|
+
retire: { path: '/retire', title: 'Retire this identity', go: 'Retire it', danger: true, done: (r) => `retired ${r.deletedAt}: Delete delivered to ${r.inboxes} inbox(es)` },
|
|
77
|
+
move: { path: '/move', title: 'Transfer this account away', go: 'Transfer it', focus: 'move-target',
|
|
78
|
+
done: (r) => `transferred to ${r.target}: Move delivered to ${r.inboxes} inbox(es), unfollowed ${r.unfollowed}/${r.following}` },
|
|
79
|
+
};
|
|
80
|
+
let pending = null;
|
|
81
|
+
|
|
82
|
+
const closeConfirm = () => closePanels();
|
|
83
|
+
|
|
84
|
+
for (const btn of document.querySelectorAll('[data-confirm]')) {
|
|
85
|
+
btn.addEventListener('click', () => {
|
|
86
|
+
const what = btn.dataset.confirm;
|
|
87
|
+
// The same button again closes its question rather than re-asking it.
|
|
88
|
+
if (pending === what && solWindow.openId() === 'confirm-form') { closePanels(); return; }
|
|
89
|
+
closePanels(); // including whatever else was open
|
|
90
|
+
pending = what;
|
|
91
|
+
const spec = LIFECYCLE[what];
|
|
92
|
+
$(`warn-${what}`).hidden = false;
|
|
93
|
+
solWindow.show('confirm-form', spec.title);
|
|
94
|
+
$('confirm-go').className = spec.danger ? 'danger' : 'primary';
|
|
95
|
+
$('confirm-go').textContent = spec.go || 'Confirm';
|
|
96
|
+
if (spec.focus) $(spec.focus).focus();
|
|
97
|
+
else if (what === 'retire') $('confirm-handle').focus();
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Offered from inside the retire warning: someone reading it has already said
|
|
102
|
+
// what they want ("not this account, here, any more") and these are the two
|
|
103
|
+
// answers that are not destruction. Switching panels rather than closing means
|
|
104
|
+
// they do not have to go and find the button themselves.
|
|
105
|
+
const openConfirm = (what) => {
|
|
106
|
+
closePanels(); // or `show` toggles: same panel, different warning
|
|
107
|
+
document.querySelector(`[data-confirm="${what}"]`).click();
|
|
108
|
+
};
|
|
109
|
+
// Park lives on the status control now; from inside the retire warning it is
|
|
110
|
+
// still one click — close the question and park.
|
|
111
|
+
$('go-park').addEventListener('click', () => { closePanels(); setStatus(true); });
|
|
112
|
+
$('go-move').addEventListener('click', () => openConfirm('move'));
|
|
113
|
+
|
|
114
|
+
$('confirm-cancel').addEventListener('click', () => { closeConfirm(); say('nothing changed'); });
|
|
115
|
+
|
|
116
|
+
$('confirm-form').addEventListener('submit', async (ev) => {
|
|
117
|
+
ev.preventDefault();
|
|
118
|
+
if (!pending) return;
|
|
119
|
+
const what = pending;
|
|
120
|
+
const body = what === 'retire' ? { confirm: $('confirm-handle').value.trim() }
|
|
121
|
+
: what === 'move' ? { target: $('move-target').value.trim(), confirm: $('confirm-handle-move').value.trim() }
|
|
122
|
+
// Only where the field is shown (the browser build — see index.html).
|
|
123
|
+
// On the Node agent the row stays hidden and nothing is sent, which is
|
|
124
|
+
// what that agent expects.
|
|
125
|
+
: what === 'rotate-key' && !$('rotate-pw-row').hidden
|
|
126
|
+
? { password: $('rotate-password').value }
|
|
127
|
+
: {};
|
|
128
|
+
if (what === 'move' && !body.target) { say('name the account to transfer to', 'err'); return; }
|
|
129
|
+
$('confirm-go').disabled = true;
|
|
130
|
+
say(`${what} — this talks to the pod and to other servers, so it takes a moment`);
|
|
131
|
+
const r = await write(LIFECYCLE[what].path, body, what);
|
|
132
|
+
$('confirm-go').disabled = false;
|
|
133
|
+
if (!r) return; // write() already said why
|
|
134
|
+
closeConfirm();
|
|
135
|
+
say(LIFECYCLE[what].done(r));
|
|
136
|
+
load(); // mode, and whether it is retired, both changed
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// ---- inbox ----
|
|
140
|
+
// Only appears when there is enough waiting to be worth a decision. The agent
|
|
141
|
+
// drains oldest-first regardless; this exists to let the owner say "do not
|
|
142
|
+
// bother with that fortnight", which is not a call an agent should make on
|
|
143
|
+
// someone's mail by itself.
|
|
144
|
+
const INBOX_PROMPT_AT = 500;
|
|
145
|
+
let dismissed = false;
|
|
146
|
+
|
|
147
|
+
async function renderInbox() {
|
|
148
|
+
if (dismissed) return;
|
|
149
|
+
const { json: st } = await api('/status');
|
|
150
|
+
const box = st?.inbox;
|
|
151
|
+
const panel = $('pane-inbox');
|
|
152
|
+
if (!box || box.count < INBOX_PROMPT_AT) { panel.hidden = true; return; }
|
|
153
|
+
const mb = box.bytes >= 1048576
|
|
154
|
+
? `${(box.bytes / 1048576).toFixed(1)} MB` : `${Math.round(box.bytes / 1024)} kB`;
|
|
155
|
+
const since = box.oldest ? new Date(box.oldest).toLocaleDateString() : 'unknown';
|
|
156
|
+
$('inbox-summary').textContent =
|
|
157
|
+
`${box.count.toLocaleString()} deliveries waiting (${mb}), the oldest from ${since}.`;
|
|
158
|
+
// One request each to read and delete, and the agent holds itself to 60 a
|
|
159
|
+
// minute, so the honest number is minutes not seconds.
|
|
160
|
+
$('inbox-warn').hidden = box.count < 2000;
|
|
161
|
+
$('inbox-warn').textContent = box.count >= 2000
|
|
162
|
+
? `At 60 requests a minute this is roughly ${Math.ceil(box.count * 2 / 60)} minutes of `
|
|
163
|
+
+ 'draining if you keep everything. Discarding the old content is much quicker.'
|
|
164
|
+
: '';
|
|
165
|
+
panel.hidden = false;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// The gateway, as a facts row under software: attach through a multi-user
|
|
169
|
+
// front with this agent's own credential, detach back to the pod inbox. The
|
|
170
|
+
// forms live in the floating window, like every other disclosure.
|
package/web/app/site/boot.js
CHANGED
|
@@ -33231,6 +33231,26 @@ async function kvPut(key, val) {
|
|
|
33231
33231
|
}
|
|
33232
33232
|
|
|
33233
33233
|
// web/app/keys-browser.mjs
|
|
33234
|
+
var pemToDer = (pem) => Uint8Array.from(
|
|
33235
|
+
atob(pem.replace(/-----[^-]+-----/g, "").replace(/\s+/g, "")),
|
|
33236
|
+
(c) => c.charCodeAt(0)
|
|
33237
|
+
);
|
|
33238
|
+
async function importSigningKey(keysRecord) {
|
|
33239
|
+
const rsaPrivate = await crypto.subtle.importKey(
|
|
33240
|
+
"pkcs8",
|
|
33241
|
+
pemToDer(keysRecord.rsa.privatePem),
|
|
33242
|
+
{ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
|
|
33243
|
+
false,
|
|
33244
|
+
["sign"]
|
|
33245
|
+
);
|
|
33246
|
+
return { rsaPrivate, rsaPublicPem: keysRecord.rsa.publicPem, edPrivate: null, edPublicMultibase: null };
|
|
33247
|
+
}
|
|
33248
|
+
async function cacheOpenedKeys(actorUrl, keysRecord) {
|
|
33249
|
+
const keys = await importSigningKey(keysRecord);
|
|
33250
|
+
await kvPut(keyCacheKey(actorUrl), { rsaPrivate: keys.rsaPrivate, rsaPublicPem: keys.rsaPublicPem }).catch(() => {
|
|
33251
|
+
});
|
|
33252
|
+
return keys;
|
|
33253
|
+
}
|
|
33234
33254
|
var keyCacheKey = (actorUrl) => `signing-keys:${actorUrl}`;
|
|
33235
33255
|
|
|
33236
33256
|
// web/app/signup.mjs
|
|
@@ -33321,8 +33341,7 @@ async function signUp(answers, { onStep = () => {
|
|
|
33321
33341
|
} catch (e) {
|
|
33322
33342
|
throw new Error(`could not store the signing key on the pod (${e.message}). The credential is for ${credential.webId} \u2014 that WebID must own ${pod} and its ${AP_ROOT} must be writable by it.`);
|
|
33323
33343
|
}
|
|
33324
|
-
await
|
|
33325
|
-
});
|
|
33344
|
+
await cacheOpenedKeys(actorUrl, keys);
|
|
33326
33345
|
prog.keys = keys;
|
|
33327
33346
|
prog.keysStored = true;
|
|
33328
33347
|
keysStep.ok();
|
|
@@ -33668,7 +33687,7 @@ window.fedipodUnlock = async (password) => {
|
|
|
33668
33687
|
if (!isKeyEnvelope(doc)) throw new Error("this account's key is not locked \u2014 nothing to unlock");
|
|
33669
33688
|
const rec = await unwrapKeys(doc, password);
|
|
33670
33689
|
const actorUrl = `${cfg.remotePod}${cfg.root || AP_ROOT}ap/actor`;
|
|
33671
|
-
await
|
|
33690
|
+
await cacheOpenedKeys(actorUrl, rec);
|
|
33672
33691
|
await bootWorker();
|
|
33673
33692
|
};
|
|
33674
33693
|
window.fedipodSignup = async ({ onStep, ...answers }) => {
|