fedipod-server 0.10.0 → 0.12.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.
- package/README.md +15 -6
- package/dist/claims.js +1 -1
- package/dist/handler.d.ts +7 -1
- package/dist/handler.js +58 -12
- package/dist/handler.jsonld +5 -1
- package/dist/store-pod.js +18 -4
- package/lib/{c2s.mjs → client/c2s.mjs} +8 -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} +2 -2
- package/lib/{tagfeed.mjs → connections/tagfeed.mjs} +21 -4
- package/lib/connections/vault.mjs +114 -0
- package/lib/core/as2.mjs +124 -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} +8 -2
- 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 +141 -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 +196 -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} +19 -10
- package/lib/{storage.mjs → core/storage.mjs} +2 -2
- package/lib/{store.mjs → core/store.mjs} +12 -1
- package/lib/{wire.mjs → core/wire.mjs} +48 -67
- 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/{export-collections.mjs → device/export-collections.mjs} +1 -1
- package/lib/{migrate.mjs → device/migrate.mjs} +5 -19
- package/lib/device/remote.mjs +54 -0
- 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} +272 -49
- package/lib/{gateway-core.mjs → gateway/gateway-core.mjs} +3 -7
- package/lib/{httpsig.mjs → gateway/httpsig.mjs} +34 -3
- package/lib/pod/README.md +61 -0
- package/lib/pod/actor.mjs +96 -0
- package/lib/pod/collection.mjs +77 -0
- package/lib/pod/containers.mjs +136 -0
- package/lib/pod/discovery.mjs +46 -0
- package/lib/pod/featured.mjs +18 -0
- package/lib/pod/followers.mjs +24 -0
- package/lib/pod/following.mjs +10 -0
- package/lib/pod/http.mjs +74 -0
- package/lib/pod/inbox.mjs +144 -0
- package/lib/{links.mjs → pod/links.mjs} +1 -1
- package/lib/pod/media.mjs +27 -0
- package/lib/pod/notes.mjs +80 -0
- package/lib/pod/notifications.mjs +89 -0
- package/lib/pod/outbox.mjs +18 -0
- package/lib/pod/package.json +19 -0
- package/lib/pod/policy.mjs +58 -0
- package/lib/pod/private.mjs +19 -0
- package/lib/pod/root.mjs +63 -0
- package/lib/pod/state.mjs +39 -0
- package/lib/{remote.mjs → pod/transport.mjs} +217 -159
- package/lib/pod/urls.mjs +71 -0
- package/lib/{embed.mjs → server/embed.mjs} +149 -22
- package/lib/shared/links.mjs +9 -0
- package/lib/{ua.mjs → shared/ua.mjs} +1 -1
- package/package.json +1 -1
- package/run-agent.mjs +47 -64
- package/web/admin/actors.js +145 -0
- package/web/admin/bar.css +9 -13
- package/web/admin/bar.js +2 -2
- package/web/admin/client/client.js +1 -1
- package/web/admin/client/index.html +5 -6
- 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 +60 -66
- package/web/admin/record.js +378 -0
- package/web/admin/setup/index.html +3 -1
- package/web/admin/setup/setup.js +2 -13
- package/web/admin/tokens.css +56 -0
- package/web/admin/upkeep.js +170 -0
- package/web/app/README.md +77 -0
- package/web/app/admin-facade.mjs +549 -0
- package/web/app/agent.mjs +490 -0
- package/web/app/atproto-browser.mjs +86 -0
- package/web/app/boot.mjs +340 -0
- package/web/app/deliver-relay.mjs +72 -0
- package/web/app/dist/boot.js +34067 -0
- package/web/app/dist/boot.js.map +7 -0
- package/web/app/dist/sw.js +70014 -0
- package/web/app/dist/sw.js.map +7 -0
- package/web/app/fediacct-browser.mjs +146 -0
- package/web/app/idb-kv.mjs +35 -0
- package/web/app/index.html +203 -0
- package/web/app/index.html~ +152 -0
- package/web/app/keys-browser.mjs +46 -0
- package/web/app/keystore.mjs +99 -0
- package/web/app/oidc-session.mjs +189 -0
- package/web/app/pod-auth.mjs +248 -0
- package/web/app/pod-remote.mjs +84 -0
- package/web/app/shims/_globals.mjs +2 -0
- package/web/app/shims/fedify-sig.mjs +77 -0
- package/web/app/shims/node-crypto.mjs +113 -0
- package/web/app/shims/node-fs.mjs +17 -0
- package/web/app/shims/node-path.mjs +19 -0
- package/web/app/shims/node-url.mjs +7 -0
- package/web/app/shims/prelude.js +58 -0
- package/web/app/shims/safefetch.mjs +58 -0
- package/web/app/shims/shapes-text.mjs +8 -0
- package/web/app/shims/web-push.mjs +14 -0
- package/web/app/signup.mjs +248 -0
- package/web/app/site/_headers +9 -0
- package/web/app/site/_redirects +21 -0
- package/web/app/site/admin/actors.js +145 -0
- package/web/app/site/admin/bar.css +60 -0
- package/web/app/site/admin/bar.js +61 -0
- package/web/app/site/admin/client/client.js +66 -0
- package/web/app/site/admin/client/index.html +43 -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 +562 -0
- package/web/app/site/admin/record.js +378 -0
- package/web/app/site/admin/setup/index.html +192 -0
- package/web/app/site/admin/setup/setup.js +297 -0
- package/web/app/site/admin/tokens.css +56 -0
- package/web/app/site/admin/upkeep.js +170 -0
- package/web/app/site/admin/window.css +55 -0
- package/web/app/site/admin/window.js +136 -0
- package/web/app/site/app/404.html +40 -0
- package/web/app/site/app/_headers +2 -0
- package/web/app/site/app/apple-touch-icon.png +0 -0
- package/web/app/site/app/assets/ICONS-DIPJeU0C.js +2 -0
- package/web/app/site/app/assets/ICONS-DIPJeU0C.js.map +1 -0
- package/web/app/site/app/assets/ScheduledAtField-D-Abfo4J.js +183 -0
- package/web/app/site/app/assets/ScheduledAtField-D-Abfo4J.js.map +1 -0
- package/web/app/site/app/assets/Temml-CCjoacWt.woff2 +0 -0
- package/web/app/site/app/assets/__vite-browser-external-C7iut881.js +2 -0
- package/web/app/site/app/assets/__vite-browser-external-C7iut881.js.map +1 -0
- package/web/app/site/app/assets/boosts-carousel-BiOaNdMT.jpg +0 -0
- package/web/app/site/app/assets/catch-up-O5q5C75Z.png +0 -0
- package/web/app/site/app/assets/chunk-aKtaBQYM.js +1 -0
- package/web/app/site/app/assets/compose-CFEx7wb4.js +2 -0
- package/web/app/site/app/assets/compose-CFEx7wb4.js.map +1 -0
- package/web/app/site/app/assets/compose-ZJN5xSb4.js +35 -0
- package/web/app/site/app/assets/compose-ZJN5xSb4.js.map +1 -0
- package/web/app/site/app/assets/debug.module-YFQgwnIr.js +52 -0
- package/web/app/site/app/assets/debug.module-YFQgwnIr.js.map +1 -0
- package/web/app/site/app/assets/dom-p1YcJ5Rw.js +2 -0
- package/web/app/site/app/assets/dom-p1YcJ5Rw.js.map +1 -0
- package/web/app/site/app/assets/home-mobile-dark@2x-Dc-J8-SM.png +0 -0
- package/web/app/site/app/assets/home-mobile-light@2x-Bd3fod8m.png +0 -0
- package/web/app/site/app/assets/home-tablet-dark@2x-BgcNI8le.png +0 -0
- package/web/app/site/app/assets/home-tablet-light@2x-BW2RV9T6.png +0 -0
- package/web/app/site/app/assets/icons/add-circle-line-WD0mwORD.js +1 -0
- package/web/app/site/app/assets/icons/alert-line-CpFUMf9s.js +1 -0
- package/web/app/site/app/assets/icons/android-2-line-Bzxnrd3S.js +1 -0
- package/web/app/site/app/assets/icons/announcement-line-5nwaJFJm.js +1 -0
- package/web/app/site/app/assets/icons/arrow-down-circle-line-a7Id9-Iv.js +1 -0
- package/web/app/site/app/assets/icons/arrow-down-line-B8uzXzq6.js +1 -0
- package/web/app/site/app/assets/icons/arrow-left-line-CGrGT9C-.js +1 -0
- package/web/app/site/app/assets/icons/arrow-right-line-CE-HERfX.js +1 -0
- package/web/app/site/app/assets/icons/arrow-to-up-line-CvdQjmcy.js +1 -0
- package/web/app/site/app/assets/icons/arrow-up-circle-line-DEparSNF.js +1 -0
- package/web/app/site/app/assets/icons/arrow-up-line-C7yBeugc.js +1 -0
- package/web/app/site/app/assets/icons/arrows-right-line-BtbXmJGP.js +1 -0
- package/web/app/site/app/assets/icons/at-line-CF66Bznk.js +1 -0
- package/web/app/site/app/assets/icons/attachment-line-BY8It-l9.js +1 -0
- package/web/app/site/app/assets/icons/blockquote-line-BS6pU_hm.js +1 -0
- package/web/app/site/app/assets/icons/board-line-C0UWXyA6.js +1 -0
- package/web/app/site/app/assets/icons/bookmark-line-1CtX5JLF.js +1 -0
- package/web/app/site/app/assets/icons/building-5-line-Dd59MzbO.js +1 -0
- package/web/app/site/app/assets/icons/bus-2-line-6_dvA0GG.js +1 -0
- package/web/app/site/app/assets/icons/calendar-day-line-Crpl_fmu.js +1 -0
- package/web/app/site/app/assets/icons/calendar-month-line-vommts2C.js +1 -0
- package/web/app/site/app/assets/icons/calendar-time-add-line-BU_DTlQk.js +1 -0
- package/web/app/site/app/assets/icons/camera-line-Cv69MEei.js +1 -0
- package/web/app/site/app/assets/icons/celebrate-line-B8DvIoi0.js +1 -0
- package/web/app/site/app/assets/icons/chart-bar-line-FK-QOmtF.js +1 -0
- package/web/app/site/app/assets/icons/chart-line-line-BGcJAFWw.js +1 -0
- package/web/app/site/app/assets/icons/chat-3-line-YFK2-hwz.js +1 -0
- package/web/app/site/app/assets/icons/check-circle-line-DsAxFr5-.js +1 -0
- package/web/app/site/app/assets/icons/clipboard-line-BBp364gJ.js +1 -0
- package/web/app/site/app/assets/icons/close-circle-line-CICdiuGz.js +1 -0
- package/web/app/site/app/assets/icons/close-line-DYrFWcjv.js +1 -0
- package/web/app/site/app/assets/icons/cloud-line-tiQAbah8.js +1 -0
- package/web/app/site/app/assets/icons/code-line-fAl8iiV3.js +1 -0
- package/web/app/site/app/assets/icons/comment-2-line-CR3g7WeB.js +1 -0
- package/web/app/site/app/assets/icons/copy-2-line-CLW69yF5.js +1 -0
- package/web/app/site/app/assets/icons/delete-2-line-B8xmbr4n.js +1 -0
- package/web/app/site/app/assets/icons/document-3-line-DBGNhAg2.js +1 -0
- package/web/app/site/app/assets/icons/document-line-C7mb9sb7.js +1 -0
- package/web/app/site/app/assets/icons/down-line-BGqSSThd.js +1 -0
- package/web/app/site/app/assets/icons/edit-4-line-DcgGaEhx.js +1 -0
- package/web/app/site/app/assets/icons/emoji-2-line-D8YgnM-y.js +1 -0
- package/web/app/site/app/assets/icons/exit-line-Dc07BS-x.js +1 -0
- package/web/app/site/app/assets/icons/external-link-line-BvpSkmjO.js +1 -0
- package/web/app/site/app/assets/icons/eye-2-line-CiWXx-f_.js +1 -0
- package/web/app/site/app/assets/icons/eye-close-line-BgTaSJ4P.js +1 -0
- package/web/app/site/app/assets/icons/filter-2-line-B_mR2usy.js +1 -0
- package/web/app/site/app/assets/icons/filter-line-C_nm-3cU.js +1 -0
- package/web/app/site/app/assets/icons/flag-1-line-C2HB05I0.js +1 -0
- package/web/app/site/app/assets/icons/forbid-circle-line-D3LTT9yd.js +1 -0
- package/web/app/site/app/assets/icons/formula-line-DLrt2d6j.js +1 -0
- package/web/app/site/app/assets/icons/grid-line-CgUmEikf.js +1 -0
- package/web/app/site/app/assets/icons/group-line-C5fnX0wU.js +1 -0
- package/web/app/site/app/assets/icons/hand-finger-2-line-BGgxbuL9.js +1 -0
- package/web/app/site/app/assets/icons/hashtag-line-CyTEEXBb.js +1 -0
- package/web/app/site/app/assets/icons/heart-crack-line-BZddbO2C.js +1 -0
- package/web/app/site/app/assets/icons/heart-line-CJ7K47J4.js +1 -0
- package/web/app/site/app/assets/icons/history-2-line-kWWvFzqv.js +1 -0
- package/web/app/site/app/assets/icons/history-line-bGQiwbTH.js +1 -0
- package/web/app/site/app/assets/icons/home-3-line-fRU1zeLG.js +1 -0
- package/web/app/site/app/assets/icons/information-line-iNk6-sOY.js +1 -0
- package/web/app/site/app/assets/icons/keyboard-line-DsCyuQNz.js +1 -0
- package/web/app/site/app/assets/icons/layout-4-line-CZkOX52Z.js +1 -0
- package/web/app/site/app/assets/icons/layout-5-line-B_znt5wO.js +1 -0
- package/web/app/site/app/assets/icons/left-line-eUw0tya4.js +1 -0
- package/web/app/site/app/assets/icons/lightning-line-DaKoDdix.js +1 -0
- package/web/app/site/app/assets/icons/link-2-line-DCqLmMA7.js +1 -0
- package/web/app/site/app/assets/icons/list-check-line-BAxosBh9.js +1 -0
- package/web/app/site/app/assets/icons/lock-line-CPoaXeUW.js +1 -0
- package/web/app/site/app/assets/icons/mail-line-B0P8aa1L.js +1 -0
- package/web/app/site/app/assets/icons/moon-line-CEqNAToP.js +1 -0
- package/web/app/site/app/assets/icons/more-1-fill-Dw2e5xab.js +1 -0
- package/web/app/site/app/assets/icons/more-3-line-BIiVjYTz.js +1 -0
- package/web/app/site/app/assets/icons/notification-line-BZZq2Gtu.js +1 -0
- package/web/app/site/app/assets/icons/pencil-line-CKh8-A1v.js +1 -0
- package/web/app/site/app/assets/icons/photo-album-line-Bnfg2u40.js +1 -0
- package/web/app/site/app/assets/icons/pin-line-DpTolyhs.js +1 -0
- package/web/app/site/app/assets/icons/play-fill-B0-G_8lX.js +1 -0
- package/web/app/site/app/assets/icons/qrcode-2-line-B6SPCaHn.js +1 -0
- package/web/app/site/app/assets/icons/quill-pen-line-B6LUrnCP.js +1 -0
- package/web/app/site/app/assets/icons/quote-left-fill-hQZ1cj_6.js +1 -0
- package/web/app/site/app/assets/icons/radar-line-CKyroTth.js +1 -0
- package/web/app/site/app/assets/icons/react-line-CoIKhhtK.js +1 -0
- package/web/app/site/app/assets/icons/refresh-2-line-D0mTF97S.js +1 -0
- package/web/app/site/app/assets/icons/right-line-B3KWJaqc.js +1 -0
- package/web/app/site/app/assets/icons/rocket-line-4KZl537D.js +1 -0
- package/web/app/site/app/assets/icons/round-fill-C69NTrZ0.js +1 -0
- package/web/app/site/app/assets/icons/round-line-B9k_1uo-.js +1 -0
- package/web/app/site/app/assets/icons/route-line-B28ReHcE.js +1 -0
- package/web/app/site/app/assets/icons/rows-4-line-CrBniagM.js +1 -0
- package/web/app/site/app/assets/icons/scan-line-DSf74YdP.js +1 -0
- package/web/app/site/app/assets/icons/search-2-line-B6geIU1z.js +1 -0
- package/web/app/site/app/assets/icons/settings-3-line-azJwK47w.js +1 -0
- package/web/app/site/app/assets/icons/settings-6-line-C_5zc5YR.js +1 -0
- package/web/app/site/app/assets/icons/share-2-line-D5MxWjrm.js +1 -0
- package/web/app/site/app/assets/icons/share-forward-line-Cp61fZzZ.js +1 -0
- package/web/app/site/app/assets/icons/sparkles-2-line-DYYyXTaW.js +1 -0
- package/web/app/site/app/assets/icons/sparkles-line-C2hY1s6I.js +1 -0
- package/web/app/site/app/assets/icons/time-line-BF3eet1v.js +1 -0
- package/web/app/site/app/assets/icons/transfer-4-line-oisfvTBw.js +1 -0
- package/web/app/site/app/assets/icons/translate-line-BFWol2Ce.js +1 -0
- package/web/app/site/app/assets/icons/unlock-line-X_x5vwv3.js +1 -0
- package/web/app/site/app/assets/icons/upload-3-line-DgzwUJeW.js +1 -0
- package/web/app/site/app/assets/icons/user-4-line-BVSynZCp.js +1 -0
- package/web/app/site/app/assets/icons/user-add-2-line-BlGS5Q8q.js +1 -0
- package/web/app/site/app/assets/icons/user-add-line-BbXdHG4z.js +1 -0
- package/web/app/site/app/assets/icons/user-edit-line-BFAHOV0X.js +1 -0
- package/web/app/site/app/assets/icons/user-follow-line-BXux0wSd.js +1 -0
- package/web/app/site/app/assets/icons/user-star-line-DdYlpHLU.js +1 -0
- package/web/app/site/app/assets/icons/user-warning-line-Cj43j0_E.js +1 -0
- package/web/app/site/app/assets/icons/user-x-line-DIDgNlPH.js +1 -0
- package/web/app/site/app/assets/icons/volume-line-Bs390KQt.js +1 -0
- package/web/app/site/app/assets/icons/volume-mute-line-DzlzIqFZ.js +1 -0
- package/web/app/site/app/assets/icons/walk-line-yNXfB-md.js +1 -0
- package/web/app/site/app/assets/icons/world-2-line-CenkGIwj.js +1 -0
- package/web/app/site/app/assets/icons/zoom-in-line-CaENUphf.js +1 -0
- package/web/app/site/app/assets/icons/zoom-out-line-BDNk0EWo.js +1 -0
- package/web/app/site/app/assets/instances-BNPptnn-.json +333 -0
- package/web/app/site/app/assets/locales/ar-SA-CfheRbCu.js +1 -0
- package/web/app/site/app/assets/locales/ca-ES-DHRW86Tz.js +1 -0
- package/web/app/site/app/assets/locales/cs-CZ-CKoqEuA1.js +1 -0
- package/web/app/site/app/assets/locales/de-DE-ByRPMRFy.js +1 -0
- package/web/app/site/app/assets/locales/eo-UY-CPC7wLCS.js +1 -0
- package/web/app/site/app/assets/locales/es-ES-dJa0Fd9t.js +1 -0
- package/web/app/site/app/assets/locales/eu-ES-C3djlPR2.js +1 -0
- package/web/app/site/app/assets/locales/fa-IR-DTT490Ck.js +1 -0
- package/web/app/site/app/assets/locales/fi-FI-B23MCPuz.js +1 -0
- package/web/app/site/app/assets/locales/fr-FR-BcaQsO5C.js +1 -0
- package/web/app/site/app/assets/locales/gl-ES-BR-CVKBN.js +1 -0
- package/web/app/site/app/assets/locales/he-IL-CfheRbCu.js +1 -0
- package/web/app/site/app/assets/locales/hu-HU-CfheRbCu.js +1 -0
- package/web/app/site/app/assets/locales/it-IT-C1136UFV.js +1 -0
- package/web/app/site/app/assets/locales/ja-JP-CRZmRAhD.js +1 -0
- package/web/app/site/app/assets/locales/kab-Cz8xH_TT.js +1 -0
- package/web/app/site/app/assets/locales/ko-KR-CG9UiY4o.js +1 -0
- package/web/app/site/app/assets/locales/lt-LT-CJcI6sHZ.js +1 -0
- package/web/app/site/app/assets/locales/nb-NO-CfheRbCu.js +1 -0
- package/web/app/site/app/assets/locales/nl-NL-DxN4Yc1t.js +1 -0
- package/web/app/site/app/assets/locales/oc-FR-CfheRbCu.js +1 -0
- package/web/app/site/app/assets/locales/pl-PL-DkwGXf6P.js +1 -0
- package/web/app/site/app/assets/locales/pseudo-LOCALE-CQ4XxkQ0.js +1 -0
- package/web/app/site/app/assets/locales/pt-BR-nGL0HdFS.js +1 -0
- package/web/app/site/app/assets/locales/pt-PT-Cp17aj2z.js +1 -0
- package/web/app/site/app/assets/locales/ru-RU-0Y8cIoaK.js +1 -0
- package/web/app/site/app/assets/locales/th-TH-CfheRbCu.js +1 -0
- package/web/app/site/app/assets/locales/tok-CfheRbCu.js +1 -0
- package/web/app/site/app/assets/locales/tr-TR-CfheRbCu.js +1 -0
- package/web/app/site/app/assets/locales/uk-UA-C5E3dFBf.js +1 -0
- package/web/app/site/app/assets/locales/zh-CN-BHJi7_et.js +1 -0
- package/web/app/site/app/assets/locales/zh-TW-CfheRbCu.js +1 -0
- package/web/app/site/app/assets/main-BdqNbG-a.js +26 -0
- package/web/app/site/app/assets/main-BdqNbG-a.js.map +1 -0
- package/web/app/site/app/assets/mock-home-DGhR__He.js +2 -0
- package/web/app/site/app/assets/mock-home-DGhR__He.js.map +1 -0
- package/web/app/site/app/assets/multi-column-ROck0NVt.jpg +0 -0
- package/web/app/site/app/assets/multi-hashtag-timeline-DH5INVHi.jpg +0 -0
- package/web/app/site/app/assets/nested-comments-thread-hv59kZLc.jpg +0 -0
- package/web/app/site/app/assets/polyfill-force-H8sUkLGp.js +2 -0
- package/web/app/site/app/assets/polyfill-force-H8sUkLGp.js.map +1 -0
- package/web/app/site/app/assets/pwa-viewport-ogKbF51K.js +20 -0
- package/web/app/site/app/assets/pwa-viewport-ogKbF51K.js.map +1 -0
- package/web/app/site/app/assets/style-B1iLPTPR.css +2 -0
- package/web/app/site/app/assets/temml-DuyIQMei.js +97 -0
- package/web/app/site/app/assets/temml-DuyIQMei.js.map +1 -0
- package/web/app/site/app/assets/tinyld.light.node-DtbBhLYC.js +2 -0
- package/web/app/site/app/assets/tinyld.light.node-DtbBhLYC.js.map +1 -0
- package/web/app/site/app/assets/year-in-posts-B2lywqdx.png +0 -0
- package/web/app/site/app/assets/year-in-posts-DJv_star.js +3 -0
- package/web/app/site/app/assets/year-in-posts-DJv_star.js.map +1 -0
- package/web/app/site/app/compose/index.html +20 -0
- package/web/app/site/app/favicon.ico +0 -0
- package/web/app/site/app/index.html +73 -0
- package/web/app/site/app/logo-192.png +0 -0
- package/web/app/site/app/logo-512.png +0 -0
- package/web/app/site/app/logo-badge-72.png +0 -0
- package/web/app/site/app/logo-maskable-512.png +0 -0
- package/web/app/site/app/logo-monochrome-512.png +0 -0
- package/web/app/site/app/logo-monochrome-maskable-512.png +0 -0
- package/web/app/site/app/manifest.webmanifest +1 -0
- package/web/app/site/app/og-image-2.jpg +0 -0
- package/web/app/site/app/og-image.png +0 -0
- package/web/app/site/app/robots.txt +2 -0
- package/web/app/site/app/version.json +1 -0
- package/web/app/site/boot.js +34067 -0
- package/web/app/site/index.html +203 -0
- package/web/app/site/sw.js +70014 -0
- package/web/app/sw-src.mjs +220 -0
- package/web/front/#new-account.html# +43 -0
- package/web/front/admin.html +1 -81
- package/web/front/admin.js +85 -0
- package/web/front/new-account.html +1 -9
- package/web/front/new-account.js +13 -0
- package/web/front/run.html +1 -92
- package/web/front/run.js +107 -0
- package/lib/admin.mjs +0 -1913
- package/lib/intake.mjs +0 -1764
- package/lib/mastoapi.mjs +0 -1947
- package/lib/podrdf.mjs +0 -132
- package/lib/publisher.mjs +0 -1263
- package/web/admin/admin.js +0 -1114
- /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/{account.mjs → device/account.mjs} +0 -0
- /package/lib/{certs.mjs → device/certs.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
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
// record.js — the record itself: what the page holds of the config, the
|
|
2
|
+
// messages it says, every write, the load, the panels, and the rows of the
|
|
3
|
+
// facts list with the identity rows and their controls.
|
|
4
|
+
// admin.js — the record, as a page. Everything here is an existing admin
|
|
5
|
+
// route; the CLI's own group commands are thin clients over the same ones.
|
|
6
|
+
//
|
|
7
|
+
// Two rules the routes enforce and this page respects: a write is a MERGE, so a
|
|
8
|
+
// form that never mentions a field cannot delete it; and anything on the wire is
|
|
9
|
+
// not real until the actor is republished, which POST /config does for itself.
|
|
10
|
+
//
|
|
11
|
+
// The UI password is deliberately not here — `fedipod passwd` sets it. It
|
|
12
|
+
// only gates /oauth/authorize, so it does nothing for a loopback-only agent.
|
|
13
|
+
|
|
14
|
+
let config = null;
|
|
15
|
+
// Held, because render() moves it into a generated row and empties that row's
|
|
16
|
+
// list on the next pass — after which getElementById would not find it again.
|
|
17
|
+
const MODERATION = $('moderation');
|
|
18
|
+
const STATUS = $('status-ctl');
|
|
19
|
+
const STATUS_PICK = $('status-pick'); // held: getElementById can't see it mid-render
|
|
20
|
+
const IDENT_CTL = $('ident-ctl');
|
|
21
|
+
const FOLLOWS_CTL = $('follows-ctl');
|
|
22
|
+
const FOLLOWS_PICK = $('follows-pick');
|
|
23
|
+
const UPDATE_CTL = $('update-ctl');
|
|
24
|
+
const UPDATE_WORD = $('update-word');
|
|
25
|
+
const UPDATE_GO = $('update-go');
|
|
26
|
+
|
|
27
|
+
// #say and #fatal live in the accessibility tree from load and hide by being
|
|
28
|
+
// empty (see the stylesheet). Unhiding a live region and filling it in the same
|
|
29
|
+
// task is the classic way to get no announcement at all.
|
|
30
|
+
function say(text, cls = 'ok') {
|
|
31
|
+
const el = $('say');
|
|
32
|
+
el.className = cls;
|
|
33
|
+
// Clear first, then set on the next task: a live region that is handed the
|
|
34
|
+
// same text it already holds announces nothing, so two identical messages in
|
|
35
|
+
// a row ("nothing changed", "nothing changed") would be silent the second time.
|
|
36
|
+
el.textContent = '';
|
|
37
|
+
setTimeout(() => { el.textContent = text; }, 30);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Every write goes through here, so nothing silently half-succeeds.
|
|
41
|
+
async function write(path, body, done) {
|
|
42
|
+
const { status, json } = await postJson(path, body);
|
|
43
|
+
if (status >= 400) { say(json?.error || `refused (HTTP ${status})`, 'err'); return null; }
|
|
44
|
+
say(done);
|
|
45
|
+
return json;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
UPDATE_GO.onclick = async () => {
|
|
49
|
+
UPDATE_GO.disabled = true;
|
|
50
|
+
const r = await write('/update', {}, 'updating — the agents restart when it finishes; reload in a moment');
|
|
51
|
+
if (!r) UPDATE_GO.disabled = false;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
async function load() {
|
|
55
|
+
const { status, json } = await api('/config');
|
|
56
|
+
if (status === 409) {
|
|
57
|
+
$('fatal').textContent = 'This agent has no identity yet.';
|
|
58
|
+
const a = document.createElement('a');
|
|
59
|
+
a.href = '/admin/setup/';
|
|
60
|
+
a.textContent = ' Set it up.';
|
|
61
|
+
$('fatal').appendChild(a);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (status !== 200 || !json) {
|
|
65
|
+
$('fatal').textContent = json?.error || `could not read the record (HTTP ${status})`;
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
config = json;
|
|
69
|
+
render();
|
|
70
|
+
if (new URLSearchParams(location.search).has('new')) openNewActor();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Every disclosure on the page — a form, the log, a lifecycle confirmation —
|
|
74
|
+
// is a panel declared inside the floating window and shown by window.js. It
|
|
75
|
+
// used to be an accordion at the foot of the page, which pushed whatever you
|
|
76
|
+
// were reading out from under you and could only ever show one thing.
|
|
77
|
+
//
|
|
78
|
+
// The reset lives here rather than in window.js: the window knows how to show a
|
|
79
|
+
// panel, not what any of them mean.
|
|
80
|
+
function resetConfirm() {
|
|
81
|
+
pending = null;
|
|
82
|
+
for (const k of Object.keys(LIFECYCLE)) $(`warn-${k}`)?.hidden !== undefined && ($(`warn-${k}`).hidden = true);
|
|
83
|
+
$('confirm-handle').value = '';
|
|
84
|
+
$('confirm-handle-move').value = '';
|
|
85
|
+
$('move-target').value = '';
|
|
86
|
+
$('rotate-password').value = '';
|
|
87
|
+
}
|
|
88
|
+
function closePanels(keep = null) {
|
|
89
|
+
if (!keep) solWindow.close();
|
|
90
|
+
if (keep !== 'output') outputSource = null;
|
|
91
|
+
if (keep !== 'confirm-form') resetConfirm();
|
|
92
|
+
}
|
|
93
|
+
// Closing it by the ✕ or by Escape has to clear the same state a Cancel does.
|
|
94
|
+
document.getElementById('win').addEventListener('win:closed', () => {
|
|
95
|
+
outputSource = null;
|
|
96
|
+
resetConfirm();
|
|
97
|
+
$('bsky-password').value = ''; // never leave a secret in a closed panel
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
// One row per identity connected elsewhere, indented under the row that adds
|
|
102
|
+
// them. Each carries its own way out: disconnecting one has nothing to do with
|
|
103
|
+
// the others.
|
|
104
|
+
function identityRows() {
|
|
105
|
+
const out = [];
|
|
106
|
+
const row = (label, ...nodes) => {
|
|
107
|
+
const dt = document.createElement('dt');
|
|
108
|
+
dt.className = 'under';
|
|
109
|
+
dt.textContent = label;
|
|
110
|
+
const dd = document.createElement('dd');
|
|
111
|
+
dd.append(...nodes);
|
|
112
|
+
out.push([dt, dd]);
|
|
113
|
+
};
|
|
114
|
+
// One descriptor shape for every connected account — Bluesky and each
|
|
115
|
+
// fediverse account — so the row and its Options menu build the same way.
|
|
116
|
+
const accounts = [];
|
|
117
|
+
if (config.atproto?.connected) accounts.push({
|
|
118
|
+
label: 'Bluesky', handle: `@${config.atproto.handle}`,
|
|
119
|
+
href: `https://bsky.app/profile/${config.atproto.handle}`,
|
|
120
|
+
storage: config.atproto.storage || null,
|
|
121
|
+
feedPaused: 'feedPaused' in config.atproto ? config.atproto.feedPaused : null,
|
|
122
|
+
crossPost: 'crossPost' in config.atproto ? config.atproto.crossPost : null,
|
|
123
|
+
feed: (paused) => ['/atproto', { feedPaused: paused }],
|
|
124
|
+
cross: (on) => ['/atproto', { crossPost: on }],
|
|
125
|
+
store: (w) => ['/atproto', { storage: w }],
|
|
126
|
+
off: () => ['/atproto/disconnect', {}],
|
|
127
|
+
});
|
|
128
|
+
for (const acct of config.fediAccounts || []) accounts.push({
|
|
129
|
+
label: acct.host,
|
|
130
|
+
handle: acct.needsReconnect ? `${acct.handle} — sign in again` : acct.handle,
|
|
131
|
+
warn: acct.needsReconnect,
|
|
132
|
+
storage: acct.storage || null,
|
|
133
|
+
feedPaused: !acct.enabled,
|
|
134
|
+
crossPost: null,
|
|
135
|
+
feed: (paused) => ['/fediacct', { id: acct.id, enabled: !paused }],
|
|
136
|
+
store: (w) => ['/fediacct', { id: acct.id, storage: w }],
|
|
137
|
+
off: () => ['/fediacct/disconnect', { id: acct.id }],
|
|
138
|
+
});
|
|
139
|
+
for (const acct of accounts) {
|
|
140
|
+
const name = document.createElement(acct.href ? 'a' : 'span');
|
|
141
|
+
name.textContent = acct.handle;
|
|
142
|
+
if (acct.href) { name.href = acct.href; name.target = '_blank'; name.rel = 'noopener'; name.title = ' Open this account elsewhere in a new tab'; }
|
|
143
|
+
if (acct.warn) name.className = 'warn';
|
|
144
|
+
// Where storage is a real choice (every browser-build account today), two
|
|
145
|
+
// dropdowns sit in the row itself. Where it isn't (the Node agent's
|
|
146
|
+
// Bluesky, which shows a cross-post toggle instead), the Options
|
|
147
|
+
// disclosure it always has is unchanged.
|
|
148
|
+
row(acct.label, name, ' ', ...(acct.storage ? connectionControls(acct) : [optionsMenu(acct)]));
|
|
149
|
+
}
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Connected, Paused or Disconnected, and where the key lives — one dropdown
|
|
154
|
+
// each, in the row. Replaces the separate feed and connect dropdowns that used
|
|
155
|
+
// to sit behind an Options disclosure; only reached where acct.storage is set.
|
|
156
|
+
function connectionControls(acct) {
|
|
157
|
+
const send = async ([path, payload], msg) => { if (await write(path, payload, msg)) await load(); };
|
|
158
|
+
const pick = (opts, current, onChange, title) => {
|
|
159
|
+
const el = document.createElement('select');
|
|
160
|
+
if (title) el.title = title;
|
|
161
|
+
for (const [v, t] of opts) { const o = document.createElement('option'); o.value = v; o.textContent = t; o.selected = v === current; el.appendChild(o); }
|
|
162
|
+
el.addEventListener('change', () => onChange(el.value));
|
|
163
|
+
return el;
|
|
164
|
+
};
|
|
165
|
+
const conn = pick(
|
|
166
|
+
[['connected', 'Connected'], ['paused', 'Paused'], ['disconnected', 'Disconnected']],
|
|
167
|
+
acct.feedPaused ? 'paused' : 'connected',
|
|
168
|
+
(v) => (v === 'disconnected'
|
|
169
|
+
? send(acct.off(), 'disconnected')
|
|
170
|
+
: send(acct.feed(v === 'paused'), v === 'paused' ? 'paused adding to your feed' : 'added to your home feed')),
|
|
171
|
+
' Connected feeds this account into your home feed here; Paused keeps the account but stops adding its posts; Disconnected removes it.');
|
|
172
|
+
const storage = pick(
|
|
173
|
+
[['pod', 'Store key on Pod'], ['browser', 'Store key in Browser']],
|
|
174
|
+
acct.storage,
|
|
175
|
+
(v) => {
|
|
176
|
+
if (v === 'pod' && !confirm('Store this account on your pod?\n\nIt will follow you to any browser you sign in from — but a full-access token to that account then lives on your pod.')) { load(); return; }
|
|
177
|
+
send(acct.store(v), v === 'pod' ? 'stored on your pod' : 'stored in this browser');
|
|
178
|
+
},
|
|
179
|
+
' On your pod the key follows you to any browser you sign in from, and a full-access token then lives there; in this browser the token never leaves this device.');
|
|
180
|
+
const wrap = document.createElement('span');
|
|
181
|
+
wrap.className = 'conn-controls';
|
|
182
|
+
wrap.append(conn, ' ', storage);
|
|
183
|
+
return [wrap];
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Every connected account without a storage choice carries an Options menu
|
|
187
|
+
// instead: pause its feed, its cross-post toggle (the Node agent's Bluesky),
|
|
188
|
+
// disconnect.
|
|
189
|
+
function optionsMenu(acct) {
|
|
190
|
+
const d = document.createElement('details');
|
|
191
|
+
d.className = 'opts';
|
|
192
|
+
const sum = document.createElement('summary');
|
|
193
|
+
sum.textContent = 'Options';
|
|
194
|
+
d.appendChild(sum);
|
|
195
|
+
const body = document.createElement('div');
|
|
196
|
+
d.appendChild(body);
|
|
197
|
+
|
|
198
|
+
// Each control is one dropdown whose options ARE the states, so it needs no
|
|
199
|
+
// separate label — the chosen option reads as the current state.
|
|
200
|
+
const pick = (opts, current, onChange) => {
|
|
201
|
+
const el = document.createElement('select');
|
|
202
|
+
for (const [v, t] of opts) { const o = document.createElement('option'); o.value = v; o.textContent = t; o.selected = v === current; el.appendChild(o); }
|
|
203
|
+
el.addEventListener('change', () => onChange(el.value));
|
|
204
|
+
body.appendChild(el);
|
|
205
|
+
};
|
|
206
|
+
const send = async ([path, payload], msg) => { if (await write(path, payload, msg)) await load(); };
|
|
207
|
+
|
|
208
|
+
// Feed: shown in / hidden from the feed you read here.
|
|
209
|
+
if (acct.feedPaused !== null) {
|
|
210
|
+
pick([['show', 'Add to home feed'], ['hide', 'Pause adding to home feed']], acct.feedPaused ? 'hide' : 'show',
|
|
211
|
+
(v) => send(acct.feed(v === 'hide'), v === 'hide' ? 'paused adding to your feed' : 'added to your home feed'));
|
|
212
|
+
}
|
|
213
|
+
// Storage where the browser offers the choice; the Node agent's Bluesky shows
|
|
214
|
+
// its cross-post toggle in the same slot instead.
|
|
215
|
+
if (acct.storage) {
|
|
216
|
+
pick([['browser', 'Store key in Browser'], ['pod', 'Store key on Pod']], acct.storage, (v) => {
|
|
217
|
+
if (v === 'pod' && !confirm('Store this account on your pod?\n\nIt will follow you to any browser you sign in from — but a full-access token to that account then lives on your pod.')) { load(); return; }
|
|
218
|
+
send(acct.store(v), v === 'pod' ? 'stored on your pod' : 'stored in this browser');
|
|
219
|
+
});
|
|
220
|
+
} else if (acct.crossPost !== null) {
|
|
221
|
+
pick([['on', 'Cross-post On'], ['off', 'Cross-post Off']], acct.crossPost ? 'on' : 'off',
|
|
222
|
+
(v) => send(acct.cross(v === 'on'), ''));
|
|
223
|
+
}
|
|
224
|
+
// Connection: staying connected, or disconnecting.
|
|
225
|
+
pick([['connected', 'Connected'], ['disconnect', 'Disconnect']], 'connected',
|
|
226
|
+
(v) => { if (v === 'disconnect') send(acct.off(), 'disconnected'); else load(); });
|
|
227
|
+
|
|
228
|
+
// The storage consequence, at the bottom of the box under every dropdown.
|
|
229
|
+
if (acct.storage) {
|
|
230
|
+
const hint = document.createElement('p'); hint.className = 'opt-hint';
|
|
231
|
+
hint.textContent = acct.storage === 'pod'
|
|
232
|
+
? 'Follows you to every browser you sign in from; a full-access token lives on your pod.'
|
|
233
|
+
: 'Stays in this browser; the token never leaves this device.';
|
|
234
|
+
body.appendChild(hint);
|
|
235
|
+
}
|
|
236
|
+
return d;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function render() {
|
|
240
|
+
// The bar names the actor, the same way on every page. Only the tab title is
|
|
241
|
+
// this page's own business.
|
|
242
|
+
document.title = `FediPod — ${config.handle}`;
|
|
243
|
+
const facts = $('facts');
|
|
244
|
+
facts.textContent = '';
|
|
245
|
+
// What this actor IS comes first. The handle is already in the address beside
|
|
246
|
+
// the heading; the pod, the issuer and the actor URL all read off the WebID;
|
|
247
|
+
// and where the private half sits is not something you act on from here.
|
|
248
|
+
const origins = config.origins || {};
|
|
249
|
+
// Two of these are addresses of things you can open, so they are links. The
|
|
250
|
+
// fediverse one goes to this actor's own page in the client, same origin, so
|
|
251
|
+
// it stays in the tab. The Solid one leaves for the pod, so it does not.
|
|
252
|
+
const rows = [
|
|
253
|
+
['kind', config.kind ? config.kind[0].toUpperCase() + config.kind.slice(1) : config.kind],
|
|
254
|
+
// The value is the select itself — what it shows IS the state, and
|
|
255
|
+
// changing the word is the whole action, like the moderation controls.
|
|
256
|
+
['status', 'ctl'],
|
|
257
|
+
['Fediverse identity', config.address || `@${config.handle} — no resolvable address`,
|
|
258
|
+
config.accountId && config.address ? { href: `/admin/client/#/a/${config.accountId}` } : null],
|
|
259
|
+
['Solid identity', config.webId, config.remotePod ? { href: config.remotePod, blank: true } : null],
|
|
260
|
+
['Other identities', 'ctl'],
|
|
261
|
+
['local store', config.home],
|
|
262
|
+
// The address you actually open, not the bare number — the named origin when
|
|
263
|
+
// there is one, since that is what the client and the OAuth redirect use. An
|
|
264
|
+
// agent with no local host of its own (embedded in a pod server, or in a
|
|
265
|
+
// browser) sends none, and then there is no row rather than a bare number.
|
|
266
|
+
['local host', (origins.named || origins.loopback || '').replace(/\/$/, '') || null],
|
|
267
|
+
];
|
|
268
|
+
if (config.version || config.update || config.pendingUpgrade?.length) rows.push(['software', 'ctl']);
|
|
269
|
+
rows.push(['gateway', 'ctl']);
|
|
270
|
+
if (config.quiescedAt) rows.push(['parked since', config.quiescedAt]);
|
|
271
|
+
if (config.movedTo) rows.push(['moved to', config.movedTo]);
|
|
272
|
+
// A person gates followers here; a group's gate is the joins control on its
|
|
273
|
+
// kind row, so the row would be a second switch for the same thing.
|
|
274
|
+
if (config.kind !== 'group') rows.splice(2, 0, ['new followers', 'ctl']);
|
|
275
|
+
// Rows that belong under the one being written, appended after it.
|
|
276
|
+
let kids = null;
|
|
277
|
+
for (const [k, v, link] of rows) {
|
|
278
|
+
if (!v) continue;
|
|
279
|
+
const dt = document.createElement('dt');
|
|
280
|
+
dt.textContent = k;
|
|
281
|
+
const dd = document.createElement('dd');
|
|
282
|
+
if (link) {
|
|
283
|
+
const a = document.createElement('a');
|
|
284
|
+
a.href = link.href;
|
|
285
|
+
a.textContent = v;
|
|
286
|
+
if (link.blank) {
|
|
287
|
+
a.target = '_blank';
|
|
288
|
+
// noopener because the pod is another origin: without it the page we
|
|
289
|
+
// open gets a handle on this one through window.opener.
|
|
290
|
+
a.rel = 'noopener';
|
|
291
|
+
a.title = ` Open ${link.href} in a new tab`;
|
|
292
|
+
} else {
|
|
293
|
+
a.title = ` This actor's page in our client`;
|
|
294
|
+
}
|
|
295
|
+
dd.appendChild(a);
|
|
296
|
+
} else {
|
|
297
|
+
dd.textContent = v;
|
|
298
|
+
}
|
|
299
|
+
// What a group can be moderated into is a property of BEING a group, so the
|
|
300
|
+
// controls sit on the row that says so. Moved rather than built here: the
|
|
301
|
+
// page still declares them, and `facts` is emptied on every render.
|
|
302
|
+
if (k === 'kind' && config.kind === 'group') dd.append(MODERATION);
|
|
303
|
+
if (k === 'status') {
|
|
304
|
+
dd.textContent = '';
|
|
305
|
+
dd.append(STATUS);
|
|
306
|
+
STATUS.hidden = false;
|
|
307
|
+
renderStatus();
|
|
308
|
+
}
|
|
309
|
+
if (k === 'new followers') {
|
|
310
|
+
dd.textContent = '';
|
|
311
|
+
dd.append(FOLLOWS_CTL);
|
|
312
|
+
FOLLOWS_CTL.hidden = false;
|
|
313
|
+
FOLLOWS_PICK.value = config.autoAcceptFollows ? 'auto' : 'approve';
|
|
314
|
+
}
|
|
315
|
+
if (k === 'gateway') {
|
|
316
|
+
dd.textContent = '';
|
|
317
|
+
dd.append(GATEWAY_CTL);
|
|
318
|
+
refreshGateway();
|
|
319
|
+
}
|
|
320
|
+
if (k === 'software') {
|
|
321
|
+
dd.textContent = '';
|
|
322
|
+
dd.append(UPDATE_CTL);
|
|
323
|
+
UPDATE_CTL.hidden = false;
|
|
324
|
+
const u = config.update;
|
|
325
|
+
// The version this agent is running, never the one sitting in the
|
|
326
|
+
// checkout — saying otherwise would name a version nobody is serving.
|
|
327
|
+
const running = config.version || u?.current || null;
|
|
328
|
+
const words = [];
|
|
329
|
+
if (running) words.push(u?.available ? `FediPod ${running} — ${u.latest} available` : `FediPod ${running}`);
|
|
330
|
+
if (config.versionOnDisk && running && config.versionOnDisk !== running)
|
|
331
|
+
words.push(`${config.versionOnDisk} is on disk — restart to run it`);
|
|
332
|
+
if (config.pendingUpgrade?.length) words.push('older data layout — run `fedipod upgrade` in a terminal');
|
|
333
|
+
UPDATE_WORD.textContent = words.join('; ');
|
|
334
|
+
UPDATE_GO.hidden = !u?.available;
|
|
335
|
+
}
|
|
336
|
+
// The way to add one. Each account already connected is a row of its own
|
|
337
|
+
// underneath, so this row stays the action and never becomes a list.
|
|
338
|
+
if (k === 'Other identities') {
|
|
339
|
+
dd.textContent = '';
|
|
340
|
+
dd.append(IDENT_CTL);
|
|
341
|
+
IDENT_CTL.hidden = false;
|
|
342
|
+
kids = identityRows();
|
|
343
|
+
}
|
|
344
|
+
facts.append(dt, dd);
|
|
345
|
+
if (kids) {
|
|
346
|
+
for (const [ckt, ckd] of kids) facts.append(ckt, ckd);
|
|
347
|
+
kids = null;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
if (!config.address) {
|
|
351
|
+
const p = document.createElement('p');
|
|
352
|
+
p.className = 'warn';
|
|
353
|
+
p.textContent = `${config.remotePod} is not the root of its own host, so this actor cannot be `
|
|
354
|
+
+ 'discovered as a handle by other servers. Posting and reading still work.';
|
|
355
|
+
$('pane-identity').appendChild(p);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// pane-others carries the create control too, so it appears even when this is
|
|
359
|
+
// the only actor and even if /profiles cannot be read.
|
|
360
|
+
for (const id of ['pane-others', 'pane-identity', 'rail']) $(id).hidden = false;
|
|
361
|
+
renderAliases();
|
|
362
|
+
renderOthers();
|
|
363
|
+
renderInbox();
|
|
364
|
+
if (config.kind === 'group') {
|
|
365
|
+
// Its lists have no bound, so this page scrolls — see body.group in the CSS.
|
|
366
|
+
document.body.classList.add('group');
|
|
367
|
+
$('pane-group').hidden = false;
|
|
368
|
+
MODERATION.hidden = false; // only a group has any
|
|
369
|
+
renderGroupToggles();
|
|
370
|
+
refreshGroup();
|
|
371
|
+
} else {
|
|
372
|
+
// A person has a follow-request queue too now: nothing binds an inbound
|
|
373
|
+
// Follow to the actor it names, so one that cannot be verified waits here
|
|
374
|
+
// rather than being accepted on the strength of who it claims to be.
|
|
375
|
+
refreshRequests();
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>FediPod — setup</title>
|
|
7
|
+
<link rel="stylesheet" href="../tokens.css">
|
|
8
|
+
<style>
|
|
9
|
+
/* 20px on the root, not on body, so every rem below scales with it. */
|
|
10
|
+
:root { color-scheme: light dark; font-size: 125%; --heading: #1a4f8a; }
|
|
11
|
+
body { font: 1rem/1.5 system-ui, sans-serif; margin: 0; }
|
|
12
|
+
/* The bar spans the window; the form stays in a centred column under it. */
|
|
13
|
+
/* The same 960 column the bar and the record use, so the three pages line up. */
|
|
14
|
+
#page { max-width: 960px; margin: 0 auto; padding: 1.75rem 1rem 4rem; box-sizing: border-box; }
|
|
15
|
+
h1, h2, h3 { color: var(--heading); }
|
|
16
|
+
h1 { font-size: 1.5rem; margin: 0 0 .25rem; }
|
|
17
|
+
h2 { font-size: 1.1rem; margin: 2rem 0 .5rem; }
|
|
18
|
+
p { margin: .5rem 0; }
|
|
19
|
+
.sub { color: #666; margin-top: 0; }
|
|
20
|
+
fieldset { border: 1px solid #bbb; border-radius: .4rem; margin: 1rem 0; padding: .75rem 1rem 1rem; }
|
|
21
|
+
legend { padding: 0 .3rem; font-weight: 600; }
|
|
22
|
+
label { display: block; margin: .75rem 0 .2rem; }
|
|
23
|
+
.hint { color: #666; font-size: .9rem; margin: .15rem 0 0; }
|
|
24
|
+
input[type=text], input[type=email], input[type=url], input[type=password], select, textarea {
|
|
25
|
+
font: inherit; width: 100%; padding: .5rem; box-sizing: border-box;
|
|
26
|
+
border: 1px solid #767676; border-radius: .3rem; background: Field; color: FieldText;
|
|
27
|
+
}
|
|
28
|
+
.choice { display: block; margin: .35rem 0; font-weight: normal; }
|
|
29
|
+
.choice input { margin-right: .4rem; }
|
|
30
|
+
button { font: inherit; padding: .6rem 1.2rem; border-radius: .3rem; border: 1px solid #666;
|
|
31
|
+
background: ButtonFace; color: ButtonText; cursor: pointer; }
|
|
32
|
+
button.primary { font-weight: 600; }
|
|
33
|
+
button:disabled { opacity: .5; cursor: default; }
|
|
34
|
+
.address { font-size: 1.2rem; font-weight: 600; word-break: break-all; }
|
|
35
|
+
.warn { border-left: .25rem solid #c60; padding-left: .75rem; }
|
|
36
|
+
.err { border-left: .25rem solid #b00020; padding-left: .75rem; color: #b00020; }
|
|
37
|
+
/* Announced, not shown: the step list beside it already says this visually. */
|
|
38
|
+
/* In the accessibility tree from load, hidden by being empty: a live region
|
|
39
|
+
added to the tree in the same task as its text does not announce. */
|
|
40
|
+
#form-error:empty, #run-error:empty { display: none; }
|
|
41
|
+
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
|
|
42
|
+
overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
|
|
43
|
+
.steps { list-style: none; padding: 0; }
|
|
44
|
+
.steps li { padding: .3rem 0; }
|
|
45
|
+
.steps .state { display: inline-block; width: 1.6rem; }
|
|
46
|
+
.note { color: #666; font-size: .9rem; word-break: break-all; }
|
|
47
|
+
.origins { font-family: ui-monospace, monospace; font-size: .95rem; word-break: break-all; }
|
|
48
|
+
@media (prefers-color-scheme: dark) { :root { --heading: #7fb3e8; }
|
|
49
|
+
.sub, .hint, .note { color: #aaa; } fieldset { border-color: #555; }
|
|
50
|
+
/* 2.40:1 without this — the record page has always had the override and
|
|
51
|
+
this page, where an error IS the whole message, did not. */
|
|
52
|
+
.err { color: #ff8a8a; border-left-color: #ff8a8a; } }
|
|
53
|
+
</style>
|
|
54
|
+
<link rel="stylesheet" href="../bar.css">
|
|
55
|
+
<style>#actor-pick{display:none!important}</style>
|
|
56
|
+
</head>
|
|
57
|
+
<body>
|
|
58
|
+
|
|
59
|
+
<nav id="bar" aria-label="Site">
|
|
60
|
+
<h1 class="name"><a href="/?add">FediPod</a></h1>
|
|
61
|
+
<span id="bar-handle"></span>
|
|
62
|
+
<a id="bar-fediverse" href="../client/" title=" Open the client and read your timeline">visit account</a>
|
|
63
|
+
<a id="bar-manage" href="../" title=" The record: what this actor is, and what you can do to it">manage account</a>
|
|
64
|
+
<a id="bar-signout" href="/?signout" title=" Sign out of FediPod and clear this browser">sign out</a>
|
|
65
|
+
<a id="bar-add" href="../?new=1" title=" Set up another actor on this machine, with its own pod" aria-current="page">add new account</a>
|
|
66
|
+
</nav>
|
|
67
|
+
<main id="page">
|
|
68
|
+
<p class="sub" id="strap">setting up…</p>
|
|
69
|
+
|
|
70
|
+
<!-- Nothing here is wired up by hand: setup.js reads /setup/state and shows
|
|
71
|
+
exactly one of these. -->
|
|
72
|
+
|
|
73
|
+
<section id="pane-loading">
|
|
74
|
+
<p>Reading this agent's state…</p>
|
|
75
|
+
</section>
|
|
76
|
+
|
|
77
|
+
<section id="pane-done" hidden>
|
|
78
|
+
<h2>Ready</h2>
|
|
79
|
+
<p class="address" id="done-address"></p>
|
|
80
|
+
<p id="done-note"></p>
|
|
81
|
+
<p id="done-links"></p>
|
|
82
|
+
</section>
|
|
83
|
+
|
|
84
|
+
<section id="pane-configured" hidden>
|
|
85
|
+
<h2>This agent is already set up</h2>
|
|
86
|
+
<p class="address" id="configured-address"></p>
|
|
87
|
+
<p>
|
|
88
|
+
<a href="../">Edit the record</a>
|
|
89
|
+
·
|
|
90
|
+
<a href="../../" id="configured-client">Open the client</a>
|
|
91
|
+
</p>
|
|
92
|
+
<p class="hint">For another actor, use <strong>add new account</strong> above.</p>
|
|
93
|
+
</section>
|
|
94
|
+
|
|
95
|
+
<section id="pane-run" hidden>
|
|
96
|
+
<h2 id="run-title">Setting up</h2>
|
|
97
|
+
<ul class="steps" id="run-steps"></ul>
|
|
98
|
+
<p class="sr-only" id="run-say" role="status"></p>
|
|
99
|
+
<p class="err" id="run-error" role="alert"></p>
|
|
100
|
+
<p><button id="run-again" title=" Try the step that failed again" hidden>Try again</button>
|
|
101
|
+
<button id="run-reenter" title=" Discard the credential and enter the account and pod again" hidden>Re-enter credentials</button></p>
|
|
102
|
+
</section>
|
|
103
|
+
|
|
104
|
+
<section id="pane-form" hidden>
|
|
105
|
+
<form id="form">
|
|
106
|
+
|
|
107
|
+
<fieldset>
|
|
108
|
+
<legend>What kind of Actor?</legend>
|
|
109
|
+
<label class="choice"><input type="radio" name="kind" value="person" checked>
|
|
110
|
+
A <strong>person</strong> — an account you read and post from</label>
|
|
111
|
+
<label class="choice"><input type="radio" name="kind" value="group">
|
|
112
|
+
A <strong>group</strong> of fediverse users you manage</label>
|
|
113
|
+
</fieldset>
|
|
114
|
+
|
|
115
|
+
<fieldset>
|
|
116
|
+
<legend>Actor's Handle</legend>
|
|
117
|
+
<input type="text" id="handle" name="handle" autocomplete="off" autofocus
|
|
118
|
+
placeholder="handle part of fediverse address: @HANDLE@server"
|
|
119
|
+
aria-label="Actor's Handle" aria-describedby="handle-hint">
|
|
120
|
+
<p class="hint" id="handle-hint">The name in your fediverse address. This is permanent. Letters, digits,
|
|
121
|
+
hyphens, and underscores only.</p>
|
|
122
|
+
</fieldset>
|
|
123
|
+
|
|
124
|
+
<fieldset id="fs-pod">
|
|
125
|
+
<legend>Actor's Pod</legend>
|
|
126
|
+
<label class="choice"><input type="radio" name="mode" value="new" checked>
|
|
127
|
+
Create a Solid account and pod for the Actor</label>
|
|
128
|
+
<label class="choice"><input type="radio" name="mode" value="existing">
|
|
129
|
+
Use a pod I already have</label>
|
|
130
|
+
|
|
131
|
+
<div id="row-issuer-new">
|
|
132
|
+
<label for="issuer-new">Solid pod provider</label>
|
|
133
|
+
<select id="issuer-new" name="issuerNew" aria-describedby="issuer-new-hint">
|
|
134
|
+
<option value="https://solidcommunity.net">solidcommunity.net</option>
|
|
135
|
+
</select>
|
|
136
|
+
<p class="hint" id="issuer-new-hint">Providers that give each pod its own subdomain, so the
|
|
137
|
+
Fediverse address works everywhere.</p>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
<div id="row-issuer-existing" hidden>
|
|
141
|
+
<label for="issuer">Solid identity provider</label>
|
|
142
|
+
<input type="url" id="issuer" name="issuer" value="https://solidcommunity.net" autocomplete="url">
|
|
143
|
+
</div>
|
|
144
|
+
|
|
145
|
+
<label for="email">Solid Account email/username</label>
|
|
146
|
+
<input type="email" id="email" name="email" autocomplete="email" placeholder="you@example.org">
|
|
147
|
+
|
|
148
|
+
<div id="row-password">
|
|
149
|
+
<label for="password">Solid Account password</label>
|
|
150
|
+
<input type="password" id="password" name="password" autocomplete="current-password"
|
|
151
|
+
aria-describedby="password-hint">
|
|
152
|
+
<p class="hint" id="password-hint">Password is sent once in return for a credential which is stored locally.
|
|
153
|
+
The password itself is never stored. You may revoke the credential without changing the
|
|
154
|
+
password.</p>
|
|
155
|
+
</div>
|
|
156
|
+
|
|
157
|
+
<div id="row-podname">
|
|
158
|
+
<label for="podName">Pod name</label>
|
|
159
|
+
<input type="text" id="podName" name="podName" autocomplete="off"
|
|
160
|
+
aria-describedby="podname-hint">
|
|
161
|
+
<p class="hint" id="podname-hint">The subdomain of your pod address, it will become
|
|
162
|
+
https://YOUR-POD-NAME.your-identity-provider</p>
|
|
163
|
+
</div>
|
|
164
|
+
|
|
165
|
+
<div id="row-pod" hidden>
|
|
166
|
+
<label for="pod">Pod address</label>
|
|
167
|
+
<input type="url" id="pod" name="pod" autocomplete="url" placeholder="https://you.solidcommunity.net/">
|
|
168
|
+
</div>
|
|
169
|
+
</fieldset>
|
|
170
|
+
|
|
171
|
+
<p id="row-reenter" class="warn" hidden>Finishing a setup that already has an account credential.
|
|
172
|
+
Wrong account or pod?
|
|
173
|
+
<button type="button" id="form-reenter" title=" Discard the credential and enter the account and pod again">Re-enter credentials</button></p>
|
|
174
|
+
|
|
175
|
+
<h2>You will be</h2>
|
|
176
|
+
<p class="address" id="preview">…</p>
|
|
177
|
+
<div id="preview-notes"></div>
|
|
178
|
+
<p>The handle and the pod cannot be changed afterwards. Everything else — display
|
|
179
|
+
name, bio, pictures — you set in the client.</p>
|
|
180
|
+
|
|
181
|
+
<p class="err" id="form-error" role="alert"></p>
|
|
182
|
+
<p><button type="submit" class="primary" id="submit" title=" Create it">Create it</button></p>
|
|
183
|
+
</form>
|
|
184
|
+
</section>
|
|
185
|
+
|
|
186
|
+
</main>
|
|
187
|
+
|
|
188
|
+
<script src="../bar.js"></script>
|
|
189
|
+
<script src="../common.js"></script>
|
|
190
|
+
<script src="setup.js"></script>
|
|
191
|
+
</body>
|
|
192
|
+
</html>
|