fedipod-server 0.21.0 → 0.28.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 +5 -4
- package/dist/claims.d.ts +3 -1
- package/dist/claims.js +20 -7
- package/dist/components/context.jsonld +6 -0
- package/dist/handler.d.ts +29 -1
- package/dist/handler.js +89 -4
- package/dist/handler.jsonld +36 -1
- package/lib/client/c2s.mjs +100 -3
- package/lib/client/masto/accounts.mjs +44 -4
- package/lib/client/masto/body.mjs +90 -3
- package/lib/client/masto/index.mjs +5 -1
- package/lib/client/masto/instance.mjs +11 -3
- package/lib/client/masto/media.mjs +3 -57
- package/lib/client/masto/oauth.mjs +66 -9
- package/lib/client/masto/render.mjs +62 -5
- package/lib/client/masto/statuses.mjs +25 -1
- package/lib/client/masto/timelines.mjs +128 -6
- package/lib/connections/tagfeed.mjs +42 -5
- package/lib/core/as2.mjs +36 -5
- package/lib/core/contexts/index.mjs +14 -0
- package/lib/core/contexts/litepub-0.1.json +60 -0
- package/lib/core/contexts/map.json +3 -1
- package/lib/core/contexts/quotes.json +18 -0
- package/lib/core/graphview.mjs +41 -3
- package/lib/core/intake/activities.mjs +136 -2
- package/lib/core/intake/activity.mjs +79 -1
- package/lib/core/intake/group.mjs +37 -3
- package/lib/core/intake/index.mjs +32 -2
- package/lib/core/intake/notes.mjs +60 -3
- package/lib/core/lease.mjs +12 -2
- package/lib/core/profile-page.mjs +104 -0
- package/lib/core/publisher/collections.mjs +6 -1
- package/lib/core/publisher/index.mjs +35 -17
- package/lib/core/publisher/notes.mjs +104 -3
- package/lib/core/shapes/activitystreams.ttl +28 -0
- package/lib/core/shapes/index.mjs +26 -1
- package/lib/core/wire-quotes.mjs +71 -0
- package/lib/core/wire.mjs +59 -103
- package/lib/device/admin/routes/lifecycle.mjs +9 -0
- package/lib/device/admin/static.mjs +4 -1
- package/lib/device/admin/surface.mjs +26 -2
- package/lib/device/certs.mjs +18 -2
- package/lib/device/cli/commands/setup.mjs +6 -2
- package/lib/device/cli/commands/state.mjs +3 -1
- package/lib/device/gateway-move.mjs +58 -0
- package/lib/device/migrate.mjs +3 -1
- package/lib/device/setup.mjs +67 -7
- package/lib/gateway/front-core.mjs +307 -36
- package/lib/gateway/gateway-core.mjs +15 -6
- package/lib/gateway/notices.mjs +84 -0
- package/lib/gateway/quiet.mjs +184 -0
- package/lib/pod/root.mjs +6 -3
- package/lib/pod/state.mjs +8 -7
- package/lib/pod/transport.mjs +5 -1
- package/lib/session/README.md +123 -0
- package/lib/session/demo.html +94 -0
- package/lib/session/fedi-account.mjs +346 -0
- package/lib/session/fedi-login.mjs +123 -0
- package/lib/session/oidc-session.mjs +233 -0
- package/lib/session/package.json +41 -0
- package/package.json +1 -1
- package/run-agent.mjs +28 -0
- package/vendor/gate.cjs +6 -3
- package/web/admin/bar.css +66 -0
- package/web/admin/bar.js +38 -0
- package/web/admin/client/index.html +31 -3
- package/web/admin/client-pick.js +79 -0
- package/web/admin/gateway.js +22 -0
- package/web/admin/index.html +54 -13
- package/web/admin/notices-bar.js +90 -0
- package/web/admin/oauth-signin.mjs +37 -0
- package/web/admin/record.js +13 -1
- package/web/admin/setup/index.html +31 -3
- package/web/admin/tokens.css +15 -3
- package/web/admin/upkeep.js +4 -5
- package/web/app/README.md +14 -10
- package/web/app/admin-facade.mjs +51 -12
- package/web/app/agent.mjs +157 -19
- package/web/app/authorize_interaction.html +56 -0
- package/web/app/authorize_interaction.js +69 -0
- package/web/app/boot.mjs +233 -95
- package/web/app/dist/boot.js +477 -569
- package/web/app/dist/boot.js.map +4 -4
- package/web/app/dist/sw.js +1861 -532
- package/web/app/dist/sw.js.map +4 -4
- package/web/app/gateway-move.mjs +60 -0
- package/web/app/index.html +40 -49
- package/web/app/keys-browser.mjs +12 -15
- package/web/app/keystore.mjs +19 -36
- package/web/app/oidc-session.mjs +5 -188
- package/web/app/signup.mjs +172 -132
- package/web/app/sw-src.mjs +1 -1
- package/web/app/update.js +66 -0
- package/web/front/admin.html +5 -3
- package/web/front/new-account.html +2 -2
- package/web/front/notices.html +69 -0
- package/web/front/notices.js +107 -0
- package/web/front/run.html +15 -8
- package/web/front/run.js +124 -36
- package/web/icons/forum.svg +11 -0
- package/web/icons/gateway.svg +14 -0
- package/web/icons/local.svg +11 -0
- package/web/app/index.html~ +0 -152
- package/web/app/site/_headers +0 -9
- package/web/app/site/_redirects +0 -22
- package/web/app/site/admin/actors.js +0 -145
- package/web/app/site/admin/bar.css +0 -60
- package/web/app/site/admin/bar.js +0 -61
- package/web/app/site/admin/client/client.js +0 -66
- package/web/app/site/admin/client/index.html +0 -43
- package/web/app/site/admin/common.js +0 -23
- package/web/app/site/admin/connections.js +0 -112
- package/web/app/site/admin/gateway.js +0 -111
- package/web/app/site/admin/group.js +0 -258
- package/web/app/site/admin/index.html +0 -564
- package/web/app/site/admin/record.js +0 -378
- package/web/app/site/admin/setup/index.html +0 -215
- package/web/app/site/admin/setup/setup.js +0 -326
- package/web/app/site/admin/tokens.css +0 -56
- package/web/app/site/admin/upkeep.js +0 -178
- package/web/app/site/admin/window.css +0 -55
- package/web/app/site/admin/window.js +0 -136
- package/web/app/site/app/404.html +0 -40
- package/web/app/site/app/_headers +0 -2
- package/web/app/site/app/apple-touch-icon.png +0 -0
- package/web/app/site/app/assets/ICONS-DIPJeU0C.js +0 -2
- package/web/app/site/app/assets/ICONS-DIPJeU0C.js.map +0 -1
- package/web/app/site/app/assets/ScheduledAtField-D-Abfo4J.js +0 -183
- package/web/app/site/app/assets/ScheduledAtField-D-Abfo4J.js.map +0 -1
- package/web/app/site/app/assets/Temml-CCjoacWt.woff2 +0 -0
- package/web/app/site/app/assets/__vite-browser-external-C7iut881.js +0 -2
- package/web/app/site/app/assets/__vite-browser-external-C7iut881.js.map +0 -1
- 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 +0 -1
- package/web/app/site/app/assets/compose-CFEx7wb4.js +0 -2
- package/web/app/site/app/assets/compose-CFEx7wb4.js.map +0 -1
- package/web/app/site/app/assets/compose-ZJN5xSb4.js +0 -35
- package/web/app/site/app/assets/compose-ZJN5xSb4.js.map +0 -1
- package/web/app/site/app/assets/debug.module-YFQgwnIr.js +0 -52
- package/web/app/site/app/assets/debug.module-YFQgwnIr.js.map +0 -1
- package/web/app/site/app/assets/dom-p1YcJ5Rw.js +0 -2
- package/web/app/site/app/assets/dom-p1YcJ5Rw.js.map +0 -1
- 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 +0 -1
- package/web/app/site/app/assets/icons/alert-line-CpFUMf9s.js +0 -1
- package/web/app/site/app/assets/icons/android-2-line-Bzxnrd3S.js +0 -1
- package/web/app/site/app/assets/icons/announcement-line-5nwaJFJm.js +0 -1
- package/web/app/site/app/assets/icons/arrow-down-circle-line-a7Id9-Iv.js +0 -1
- package/web/app/site/app/assets/icons/arrow-down-line-B8uzXzq6.js +0 -1
- package/web/app/site/app/assets/icons/arrow-left-line-CGrGT9C-.js +0 -1
- package/web/app/site/app/assets/icons/arrow-right-line-CE-HERfX.js +0 -1
- package/web/app/site/app/assets/icons/arrow-to-up-line-CvdQjmcy.js +0 -1
- package/web/app/site/app/assets/icons/arrow-up-circle-line-DEparSNF.js +0 -1
- package/web/app/site/app/assets/icons/arrow-up-line-C7yBeugc.js +0 -1
- package/web/app/site/app/assets/icons/arrows-right-line-BtbXmJGP.js +0 -1
- package/web/app/site/app/assets/icons/at-line-CF66Bznk.js +0 -1
- package/web/app/site/app/assets/icons/attachment-line-BY8It-l9.js +0 -1
- package/web/app/site/app/assets/icons/blockquote-line-BS6pU_hm.js +0 -1
- package/web/app/site/app/assets/icons/board-line-C0UWXyA6.js +0 -1
- package/web/app/site/app/assets/icons/bookmark-line-1CtX5JLF.js +0 -1
- package/web/app/site/app/assets/icons/building-5-line-Dd59MzbO.js +0 -1
- package/web/app/site/app/assets/icons/bus-2-line-6_dvA0GG.js +0 -1
- package/web/app/site/app/assets/icons/calendar-day-line-Crpl_fmu.js +0 -1
- package/web/app/site/app/assets/icons/calendar-month-line-vommts2C.js +0 -1
- package/web/app/site/app/assets/icons/calendar-time-add-line-BU_DTlQk.js +0 -1
- package/web/app/site/app/assets/icons/camera-line-Cv69MEei.js +0 -1
- package/web/app/site/app/assets/icons/celebrate-line-B8DvIoi0.js +0 -1
- package/web/app/site/app/assets/icons/chart-bar-line-FK-QOmtF.js +0 -1
- package/web/app/site/app/assets/icons/chart-line-line-BGcJAFWw.js +0 -1
- package/web/app/site/app/assets/icons/chat-3-line-YFK2-hwz.js +0 -1
- package/web/app/site/app/assets/icons/check-circle-line-DsAxFr5-.js +0 -1
- package/web/app/site/app/assets/icons/clipboard-line-BBp364gJ.js +0 -1
- package/web/app/site/app/assets/icons/close-circle-line-CICdiuGz.js +0 -1
- package/web/app/site/app/assets/icons/close-line-DYrFWcjv.js +0 -1
- package/web/app/site/app/assets/icons/cloud-line-tiQAbah8.js +0 -1
- package/web/app/site/app/assets/icons/code-line-fAl8iiV3.js +0 -1
- package/web/app/site/app/assets/icons/comment-2-line-CR3g7WeB.js +0 -1
- package/web/app/site/app/assets/icons/copy-2-line-CLW69yF5.js +0 -1
- package/web/app/site/app/assets/icons/delete-2-line-B8xmbr4n.js +0 -1
- package/web/app/site/app/assets/icons/document-3-line-DBGNhAg2.js +0 -1
- package/web/app/site/app/assets/icons/document-line-C7mb9sb7.js +0 -1
- package/web/app/site/app/assets/icons/down-line-BGqSSThd.js +0 -1
- package/web/app/site/app/assets/icons/edit-4-line-DcgGaEhx.js +0 -1
- package/web/app/site/app/assets/icons/emoji-2-line-D8YgnM-y.js +0 -1
- package/web/app/site/app/assets/icons/exit-line-Dc07BS-x.js +0 -1
- package/web/app/site/app/assets/icons/external-link-line-BvpSkmjO.js +0 -1
- package/web/app/site/app/assets/icons/eye-2-line-CiWXx-f_.js +0 -1
- package/web/app/site/app/assets/icons/eye-close-line-BgTaSJ4P.js +0 -1
- package/web/app/site/app/assets/icons/filter-2-line-B_mR2usy.js +0 -1
- package/web/app/site/app/assets/icons/filter-line-C_nm-3cU.js +0 -1
- package/web/app/site/app/assets/icons/flag-1-line-C2HB05I0.js +0 -1
- package/web/app/site/app/assets/icons/forbid-circle-line-D3LTT9yd.js +0 -1
- package/web/app/site/app/assets/icons/formula-line-DLrt2d6j.js +0 -1
- package/web/app/site/app/assets/icons/grid-line-CgUmEikf.js +0 -1
- package/web/app/site/app/assets/icons/group-line-C5fnX0wU.js +0 -1
- package/web/app/site/app/assets/icons/hand-finger-2-line-BGgxbuL9.js +0 -1
- package/web/app/site/app/assets/icons/hashtag-line-CyTEEXBb.js +0 -1
- package/web/app/site/app/assets/icons/heart-crack-line-BZddbO2C.js +0 -1
- package/web/app/site/app/assets/icons/heart-line-CJ7K47J4.js +0 -1
- package/web/app/site/app/assets/icons/history-2-line-kWWvFzqv.js +0 -1
- package/web/app/site/app/assets/icons/history-line-bGQiwbTH.js +0 -1
- package/web/app/site/app/assets/icons/home-3-line-fRU1zeLG.js +0 -1
- package/web/app/site/app/assets/icons/information-line-iNk6-sOY.js +0 -1
- package/web/app/site/app/assets/icons/keyboard-line-DsCyuQNz.js +0 -1
- package/web/app/site/app/assets/icons/layout-4-line-CZkOX52Z.js +0 -1
- package/web/app/site/app/assets/icons/layout-5-line-B_znt5wO.js +0 -1
- package/web/app/site/app/assets/icons/left-line-eUw0tya4.js +0 -1
- package/web/app/site/app/assets/icons/lightning-line-DaKoDdix.js +0 -1
- package/web/app/site/app/assets/icons/link-2-line-DCqLmMA7.js +0 -1
- package/web/app/site/app/assets/icons/list-check-line-BAxosBh9.js +0 -1
- package/web/app/site/app/assets/icons/lock-line-CPoaXeUW.js +0 -1
- package/web/app/site/app/assets/icons/mail-line-B0P8aa1L.js +0 -1
- package/web/app/site/app/assets/icons/moon-line-CEqNAToP.js +0 -1
- package/web/app/site/app/assets/icons/more-1-fill-Dw2e5xab.js +0 -1
- package/web/app/site/app/assets/icons/more-3-line-BIiVjYTz.js +0 -1
- package/web/app/site/app/assets/icons/notification-line-BZZq2Gtu.js +0 -1
- package/web/app/site/app/assets/icons/pencil-line-CKh8-A1v.js +0 -1
- package/web/app/site/app/assets/icons/photo-album-line-Bnfg2u40.js +0 -1
- package/web/app/site/app/assets/icons/pin-line-DpTolyhs.js +0 -1
- package/web/app/site/app/assets/icons/play-fill-B0-G_8lX.js +0 -1
- package/web/app/site/app/assets/icons/qrcode-2-line-B6SPCaHn.js +0 -1
- package/web/app/site/app/assets/icons/quill-pen-line-B6LUrnCP.js +0 -1
- package/web/app/site/app/assets/icons/quote-left-fill-hQZ1cj_6.js +0 -1
- package/web/app/site/app/assets/icons/radar-line-CKyroTth.js +0 -1
- package/web/app/site/app/assets/icons/react-line-CoIKhhtK.js +0 -1
- package/web/app/site/app/assets/icons/refresh-2-line-D0mTF97S.js +0 -1
- package/web/app/site/app/assets/icons/right-line-B3KWJaqc.js +0 -1
- package/web/app/site/app/assets/icons/rocket-line-4KZl537D.js +0 -1
- package/web/app/site/app/assets/icons/round-fill-C69NTrZ0.js +0 -1
- package/web/app/site/app/assets/icons/round-line-B9k_1uo-.js +0 -1
- package/web/app/site/app/assets/icons/route-line-B28ReHcE.js +0 -1
- package/web/app/site/app/assets/icons/rows-4-line-CrBniagM.js +0 -1
- package/web/app/site/app/assets/icons/scan-line-DSf74YdP.js +0 -1
- package/web/app/site/app/assets/icons/search-2-line-B6geIU1z.js +0 -1
- package/web/app/site/app/assets/icons/settings-3-line-azJwK47w.js +0 -1
- package/web/app/site/app/assets/icons/settings-6-line-C_5zc5YR.js +0 -1
- package/web/app/site/app/assets/icons/share-2-line-D5MxWjrm.js +0 -1
- package/web/app/site/app/assets/icons/share-forward-line-Cp61fZzZ.js +0 -1
- package/web/app/site/app/assets/icons/sparkles-2-line-DYYyXTaW.js +0 -1
- package/web/app/site/app/assets/icons/sparkles-line-C2hY1s6I.js +0 -1
- package/web/app/site/app/assets/icons/time-line-BF3eet1v.js +0 -1
- package/web/app/site/app/assets/icons/transfer-4-line-oisfvTBw.js +0 -1
- package/web/app/site/app/assets/icons/translate-line-BFWol2Ce.js +0 -1
- package/web/app/site/app/assets/icons/unlock-line-X_x5vwv3.js +0 -1
- package/web/app/site/app/assets/icons/upload-3-line-DgzwUJeW.js +0 -1
- package/web/app/site/app/assets/icons/user-4-line-BVSynZCp.js +0 -1
- package/web/app/site/app/assets/icons/user-add-2-line-BlGS5Q8q.js +0 -1
- package/web/app/site/app/assets/icons/user-add-line-BbXdHG4z.js +0 -1
- package/web/app/site/app/assets/icons/user-edit-line-BFAHOV0X.js +0 -1
- package/web/app/site/app/assets/icons/user-follow-line-BXux0wSd.js +0 -1
- package/web/app/site/app/assets/icons/user-star-line-DdYlpHLU.js +0 -1
- package/web/app/site/app/assets/icons/user-warning-line-Cj43j0_E.js +0 -1
- package/web/app/site/app/assets/icons/user-x-line-DIDgNlPH.js +0 -1
- package/web/app/site/app/assets/icons/volume-line-Bs390KQt.js +0 -1
- package/web/app/site/app/assets/icons/volume-mute-line-DzlzIqFZ.js +0 -1
- package/web/app/site/app/assets/icons/walk-line-yNXfB-md.js +0 -1
- package/web/app/site/app/assets/icons/world-2-line-CenkGIwj.js +0 -1
- package/web/app/site/app/assets/icons/zoom-in-line-CaENUphf.js +0 -1
- package/web/app/site/app/assets/icons/zoom-out-line-BDNk0EWo.js +0 -1
- package/web/app/site/app/assets/instances-BNPptnn-.json +0 -333
- package/web/app/site/app/assets/locales/ar-SA-CfheRbCu.js +0 -1
- package/web/app/site/app/assets/locales/ca-ES-DHRW86Tz.js +0 -1
- package/web/app/site/app/assets/locales/cs-CZ-CKoqEuA1.js +0 -1
- package/web/app/site/app/assets/locales/de-DE-ByRPMRFy.js +0 -1
- package/web/app/site/app/assets/locales/eo-UY-CPC7wLCS.js +0 -1
- package/web/app/site/app/assets/locales/es-ES-dJa0Fd9t.js +0 -1
- package/web/app/site/app/assets/locales/eu-ES-C3djlPR2.js +0 -1
- package/web/app/site/app/assets/locales/fa-IR-DTT490Ck.js +0 -1
- package/web/app/site/app/assets/locales/fi-FI-B23MCPuz.js +0 -1
- package/web/app/site/app/assets/locales/fr-FR-BcaQsO5C.js +0 -1
- package/web/app/site/app/assets/locales/gl-ES-BR-CVKBN.js +0 -1
- package/web/app/site/app/assets/locales/he-IL-CfheRbCu.js +0 -1
- package/web/app/site/app/assets/locales/hu-HU-CfheRbCu.js +0 -1
- package/web/app/site/app/assets/locales/it-IT-C1136UFV.js +0 -1
- package/web/app/site/app/assets/locales/ja-JP-CRZmRAhD.js +0 -1
- package/web/app/site/app/assets/locales/kab-Cz8xH_TT.js +0 -1
- package/web/app/site/app/assets/locales/ko-KR-CG9UiY4o.js +0 -1
- package/web/app/site/app/assets/locales/lt-LT-CJcI6sHZ.js +0 -1
- package/web/app/site/app/assets/locales/nb-NO-CfheRbCu.js +0 -1
- package/web/app/site/app/assets/locales/nl-NL-DxN4Yc1t.js +0 -1
- package/web/app/site/app/assets/locales/oc-FR-CfheRbCu.js +0 -1
- package/web/app/site/app/assets/locales/pl-PL-DkwGXf6P.js +0 -1
- package/web/app/site/app/assets/locales/pseudo-LOCALE-CQ4XxkQ0.js +0 -1
- package/web/app/site/app/assets/locales/pt-BR-nGL0HdFS.js +0 -1
- package/web/app/site/app/assets/locales/pt-PT-Cp17aj2z.js +0 -1
- package/web/app/site/app/assets/locales/ru-RU-0Y8cIoaK.js +0 -1
- package/web/app/site/app/assets/locales/th-TH-CfheRbCu.js +0 -1
- package/web/app/site/app/assets/locales/tok-CfheRbCu.js +0 -1
- package/web/app/site/app/assets/locales/tr-TR-CfheRbCu.js +0 -1
- package/web/app/site/app/assets/locales/uk-UA-C5E3dFBf.js +0 -1
- package/web/app/site/app/assets/locales/zh-CN-BHJi7_et.js +0 -1
- package/web/app/site/app/assets/locales/zh-TW-CfheRbCu.js +0 -1
- package/web/app/site/app/assets/main-BdqNbG-a.js +0 -26
- package/web/app/site/app/assets/main-BdqNbG-a.js.map +0 -1
- package/web/app/site/app/assets/mock-home-DGhR__He.js +0 -2
- package/web/app/site/app/assets/mock-home-DGhR__He.js.map +0 -1
- 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 +0 -2
- package/web/app/site/app/assets/polyfill-force-H8sUkLGp.js.map +0 -1
- package/web/app/site/app/assets/pwa-viewport-ogKbF51K.js +0 -20
- package/web/app/site/app/assets/pwa-viewport-ogKbF51K.js.map +0 -1
- package/web/app/site/app/assets/style-B1iLPTPR.css +0 -2
- package/web/app/site/app/assets/temml-DuyIQMei.js +0 -97
- package/web/app/site/app/assets/temml-DuyIQMei.js.map +0 -1
- package/web/app/site/app/assets/tinyld.light.node-DtbBhLYC.js +0 -2
- package/web/app/site/app/assets/tinyld.light.node-DtbBhLYC.js.map +0 -1
- 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 +0 -3
- package/web/app/site/app/assets/year-in-posts-DJv_star.js.map +0 -1
- package/web/app/site/app/compose/index.html +0 -20
- package/web/app/site/app/favicon.ico +0 -0
- package/web/app/site/app/index.html +0 -73
- 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 +0 -1
- 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 +0 -2
- package/web/app/site/app/version.json +0 -1
- package/web/app/site/boot.js +0 -34277
- package/web/app/site/index.html +0 -251
- package/web/app/site/sw.js +0 -71331
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// notices.js — the notices page's script: the admin signs in, then writes,
|
|
2
|
+
// changes and removes the notices every account here sees behind the bell.
|
|
3
|
+
// Served by the front at /notices.js, like admin.js for the roster.
|
|
4
|
+
const $ = (id) => document.getElementById(id);
|
|
5
|
+
const note = (text) => { const n = $('notices-note'); n.hidden = !text; n.textContent = text || ''; };
|
|
6
|
+
|
|
7
|
+
let session = null;
|
|
8
|
+
try {
|
|
9
|
+
const { SessionCore } = await import('/solid-oidc-client.js');
|
|
10
|
+
session = new SessionCore({ redirect_uris: [location.origin + '/notices'], client_name: 'FediPod admin' });
|
|
11
|
+
} catch { /* leave null — the "did not load" note fires */ }
|
|
12
|
+
|
|
13
|
+
$('notices-issuer').addEventListener('input', () => {
|
|
14
|
+
$('notices-signin').disabled = !/^https?:\/\/\S+/.test($('notices-issuer').value.trim());
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
$('notices-form').addEventListener('submit', (ev) => {
|
|
18
|
+
ev.preventDefault();
|
|
19
|
+
if (!session) { note('the sign-in library did not load — reload and try again'); return; }
|
|
20
|
+
session.login($('notices-issuer').value.trim(), location.origin + '/notices')
|
|
21
|
+
.catch((e) => note('sign-in failed to start: ' + e.message));
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
(async () => {
|
|
25
|
+
if (!session) return;
|
|
26
|
+
await session.handleRedirectFromLogin().catch(() => {});
|
|
27
|
+
if (!session.isActive) return;
|
|
28
|
+
const webId = session.webId;
|
|
29
|
+
let editing = null; // the notice being changed, or null for a new one
|
|
30
|
+
|
|
31
|
+
const when = (iso) => { try { return new Date(iso).toLocaleString(); } catch { return iso; } };
|
|
32
|
+
|
|
33
|
+
const send = async (body) => {
|
|
34
|
+
let res;
|
|
35
|
+
try {
|
|
36
|
+
res = await session.authFetch(location.origin + '/api/notices', {
|
|
37
|
+
method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body),
|
|
38
|
+
});
|
|
39
|
+
} catch (e) { note('the request failed: ' + e.message); return null; }
|
|
40
|
+
const d = await res.json().catch(() => ({}));
|
|
41
|
+
if (res.status === 403) { note('signed in as ' + webId + ', which is not this server’s admin'); return null; }
|
|
42
|
+
if (res.status === 501) { note('this server keeps no notices'); return null; }
|
|
43
|
+
if (res.status >= 400) { note('refused: ' + (d.error || 'HTTP ' + res.status)); return null; }
|
|
44
|
+
return d;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const startEdit = (n) => {
|
|
48
|
+
editing = n;
|
|
49
|
+
$('editor-title').textContent = n ? 'Change this notice' : 'New notice';
|
|
50
|
+
$('notice-title').value = n ? n.title : '';
|
|
51
|
+
$('notice-body').value = n ? n.body : '';
|
|
52
|
+
$('notice-save').textContent = n ? 'Save changes' : 'Publish';
|
|
53
|
+
$('notice-cancel').hidden = !n;
|
|
54
|
+
$('notice-title').focus();
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const load = async () => {
|
|
58
|
+
let res;
|
|
59
|
+
try { res = await fetch(location.origin + '/api/notices', { headers: { accept: 'application/json' }, cache: 'no-store' }); }
|
|
60
|
+
catch (e) { note('the notices could not be read: ' + e.message); return; }
|
|
61
|
+
if (res.status === 501) { note('this server keeps no notices'); return; }
|
|
62
|
+
const d = await res.json().catch(() => ({}));
|
|
63
|
+
const ul = $('notices-list');
|
|
64
|
+
ul.textContent = '';
|
|
65
|
+
for (const n of d.notices || []) {
|
|
66
|
+
const li = document.createElement('li');
|
|
67
|
+
const head = document.createElement('div');
|
|
68
|
+
const t = document.createElement('span'); t.className = 'title'; t.textContent = n.title;
|
|
69
|
+
const w = document.createElement('span'); w.className = 'when';
|
|
70
|
+
w.textContent = when(n.at) + (n.updatedAt && n.updatedAt !== n.at ? ' (changed ' + when(n.updatedAt) + ')' : '');
|
|
71
|
+
head.append(t, w);
|
|
72
|
+
const b = document.createElement('p'); b.className = 'body'; b.textContent = n.body;
|
|
73
|
+
const acts = document.createElement('p'); acts.className = 'actions';
|
|
74
|
+
const edit = document.createElement('button'); edit.type = 'button'; edit.textContent = 'Change';
|
|
75
|
+
edit.onclick = () => startEdit(n);
|
|
76
|
+
const rm = document.createElement('button'); rm.type = 'button'; rm.textContent = 'Remove'; rm.className = 'danger';
|
|
77
|
+
rm.onclick = async () => {
|
|
78
|
+
if (!confirm('Remove the notice “' + n.title + '”? Everyone stops seeing it.')) return;
|
|
79
|
+
if (await send({ action: 'delete', id: n.id })) { note('removed “' + n.title + '”'); await load(); }
|
|
80
|
+
};
|
|
81
|
+
acts.append(edit, rm);
|
|
82
|
+
li.append(head, b, acts);
|
|
83
|
+
ul.append(li);
|
|
84
|
+
}
|
|
85
|
+
if (!(d.notices || []).length) { const li = document.createElement('li'); li.textContent = 'No notices yet.'; ul.append(li); }
|
|
86
|
+
$('notices-editor').hidden = false;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
$('editor-form').addEventListener('submit', async (ev) => {
|
|
90
|
+
ev.preventDefault();
|
|
91
|
+
const title = $('notice-title').value.trim();
|
|
92
|
+
const body = $('notice-body').value.trim();
|
|
93
|
+
if (!title || !body) { note('a title and a text are both needed'); return; }
|
|
94
|
+
$('notice-save').disabled = true;
|
|
95
|
+
const r = await send(editing ? { action: 'update', id: editing.id, title, body } : { action: 'create', title, body });
|
|
96
|
+
$('notice-save').disabled = false;
|
|
97
|
+
if (!r) return;
|
|
98
|
+
note(editing ? 'changed “' + title + '”' : 'published “' + title + '” — everyone sees it within a minute');
|
|
99
|
+
startEdit(null);
|
|
100
|
+
await load();
|
|
101
|
+
});
|
|
102
|
+
$('notice-cancel').addEventListener('click', () => startEdit(null));
|
|
103
|
+
|
|
104
|
+
note('signed in as ' + webId);
|
|
105
|
+
$('notices-form').hidden = true;
|
|
106
|
+
await load();
|
|
107
|
+
})();
|
package/web/front/run.html
CHANGED
|
@@ -3,31 +3,39 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
-
<title>FediPod —
|
|
6
|
+
<title>FediPod — turn your pod into a Fediverse account</title>
|
|
7
|
+
<link rel="icon" href="/icons/gateway.svg" type="image/svg+xml">
|
|
7
8
|
<style>
|
|
8
9
|
:root { color-scheme: light dark; --line:#d9d4c7; --dim:#45443d; --accent:#6a8a5a; }
|
|
9
10
|
@media (prefers-color-scheme: dark) { :root { --dim:#c2c0b4; } }
|
|
10
|
-
body { font:
|
|
11
|
+
body { font: 20px/1.6 Arial, Helvetica, sans-serif; max-width: 44rem; margin: 2rem auto; padding: 0 1.1rem; }
|
|
11
12
|
h1 { font-size: 1.7rem; margin: 0 0 .2rem; }
|
|
12
13
|
p.lede { color: var(--dim); margin-top: 0; }
|
|
13
14
|
label { display: block; font-weight: 600; margin: .8rem 0 .2rem; }
|
|
14
15
|
input[type=text], input[type=url] { width: 100%; padding: .5rem .6rem; font: inherit;
|
|
15
16
|
border: 1px solid var(--line); border-radius: 8px; box-sizing: border-box; }
|
|
16
17
|
.hint { color: var(--dim); font-size: .95rem; }
|
|
18
|
+
.pod { border: 1px solid var(--line); border-radius: 9px; padding: .9rem 1.1rem; margin: .8rem 0; }
|
|
19
|
+
.pod p { margin: .3rem 0; }
|
|
20
|
+
.pod .actions { margin-top: .8rem; }
|
|
17
21
|
.primary { background: var(--accent); color: #fff; border: none; border-radius: 9px;
|
|
18
22
|
padding: .6rem 1.1rem; font: inherit; cursor: pointer; }
|
|
19
23
|
button { font: inherit; }
|
|
20
24
|
.primary[disabled], button[disabled] { opacity: .5; cursor: not-allowed; }
|
|
21
25
|
[hidden] { display: none !important; }
|
|
22
26
|
code { background: rgba(120,120,120,.12); padding: .05em .35em; border-radius: 4px; }
|
|
27
|
+
.pod code { background: #fff3c4; color: #1a1a1a; font-size: 16px; }
|
|
28
|
+
@media (prefers-color-scheme: dark) { .pod code { background: #5a4a00; color: #fff; } }
|
|
23
29
|
pre { background: rgba(120,120,120,.12); padding: .7rem .9rem; border-radius: 8px; overflow-x: auto; }
|
|
24
30
|
</style>
|
|
25
31
|
</head>
|
|
26
32
|
<body>
|
|
27
|
-
<h1>
|
|
28
|
-
<p class="lede">
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
<h1>Turn your pod into a Fediverse account</h1>
|
|
34
|
+
<p class="lede">Users with pods on this server may opt-in below to create a Fediverse account
|
|
35
|
+
that stores your data on your pod. You'll be able to interact with Mastodon and users of other
|
|
36
|
+
Fediverse services straight from your pod.</p>
|
|
37
|
+
|
|
38
|
+
<section id="run-known" hidden aria-live="polite"></section>
|
|
31
39
|
|
|
32
40
|
<form id="run-form">
|
|
33
41
|
<p class="field">
|
|
@@ -42,10 +50,9 @@ you to keep running. Sign in with your pod to prove it is yours.</p>
|
|
|
42
50
|
<button type="button" id="run-continue" class="primary" disabled>Sign in with your pod & opt in</button>
|
|
43
51
|
<button type="button" id="run-leave">Stop running it here</button>
|
|
44
52
|
</p>
|
|
45
|
-
<p class="hint" id="run-note" hidden></p>
|
|
46
53
|
</form>
|
|
54
|
+
<p class="hint" id="run-note" hidden></p>
|
|
47
55
|
|
|
48
56
|
<script type="module" src="/run.js"></script>
|
|
49
|
-
<i>(cc) 4.0 By, Jeff Zucker, 2026</i>
|
|
50
57
|
</body>
|
|
51
58
|
</html>
|
package/web/front/run.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// It lived inline in run.html until 2026-09-09. Out here the page can be served
|
|
4
4
|
// under `script-src 'self'`, which is what stops a stray bit of markup from
|
|
5
5
|
// becoming running code; inline script cannot be told apart from injected
|
|
6
|
-
// script by any policy. Served by the front
|
|
6
|
+
// script by any policy. Served by the front beside the page it belongs to.
|
|
7
7
|
//
|
|
8
8
|
// A module, because it awaits an import of /solid-oidc-client.js at the top
|
|
9
9
|
// level — which is itself the proof this mechanism works: that file has been
|
|
@@ -13,28 +13,90 @@ const $ = (id) => document.getElementById(id);
|
|
|
13
13
|
// The Solid-OIDC client for the sign-in round trip. Constructed once; the
|
|
14
14
|
// redirect state (PKCE, csrf) lives in this tab's sessionStorage, so the same
|
|
15
15
|
// session finishes the login on the way back.
|
|
16
|
+
// This page's own address. The identity provider is told it and sends the
|
|
17
|
+
// reader back to it, so a hard-coded name would end the sign-in on a page that
|
|
18
|
+
// does not exist wherever the operator put this one.
|
|
19
|
+
const HERE = location.origin + location.pathname.replace(/\/$/u, '');
|
|
16
20
|
let session = null;
|
|
17
21
|
try {
|
|
18
22
|
const { SessionCore } = await import('/solid-oidc-client.js');
|
|
19
|
-
session = new SessionCore({ redirect_uris: [
|
|
23
|
+
session = new SessionCore({ redirect_uris: [HERE], client_name: 'FediPod gateway' });
|
|
20
24
|
} catch { /* leave null — the "did not load" notes below fire */ }
|
|
21
25
|
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
26
|
+
// What this server knows before anything is typed. 501: it runs no
|
|
27
|
+
// identities. A pod server that issued the reader's session names their pod
|
|
28
|
+
// and its address, and the page shows one button per pod. Not signed in
|
|
29
|
+
// there: one button, to its login. A Gateway knows nothing: the form below.
|
|
25
30
|
let offered = true;
|
|
31
|
+
const say = (tag, text) => { const e = document.createElement(tag); e.textContent = text; return e; };
|
|
26
32
|
(async () => {
|
|
27
|
-
const res = await fetch('/api/agent', {
|
|
28
|
-
|
|
33
|
+
const res = await fetch('/api/agent', { credentials: 'same-origin', headers: { accept: 'application/json' } }).catch(() => null);
|
|
34
|
+
const d = res && res.ok ? await res.json().catch(() => ({})) : {};
|
|
35
|
+
const n = $('run-note');
|
|
29
36
|
if (!res || res.status === 501) {
|
|
30
37
|
offered = false;
|
|
31
|
-
const n = $('run-note');
|
|
32
38
|
n.hidden = false;
|
|
33
39
|
n.textContent = 'This server does not run identities. Your agent stays where it is.';
|
|
34
|
-
|
|
40
|
+
} else if (d.session === 'none') {
|
|
41
|
+
$('run-form').hidden = true;
|
|
42
|
+
showSignIn(d.loginUrl);
|
|
43
|
+
} else if (d.session === 'ok' && Array.isArray(d.pods) && d.pods.length) {
|
|
44
|
+
$('run-form').hidden = true;
|
|
45
|
+
showPods(d.pods);
|
|
35
46
|
}
|
|
47
|
+
runFormCheck();
|
|
36
48
|
})();
|
|
37
49
|
|
|
50
|
+
async function refreshKnown() {
|
|
51
|
+
const res = await fetch('/api/agent', { credentials: 'same-origin', headers: { accept: 'application/json' } }).catch(() => null);
|
|
52
|
+
const d = res && res.ok ? await res.json().catch(() => ({})) : {};
|
|
53
|
+
if (d.session === 'ok' && Array.isArray(d.pods) && d.pods.length) showPods(d.pods);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function showSignIn(loginUrl) {
|
|
57
|
+
const k = $('run-known');
|
|
58
|
+
k.hidden = false;
|
|
59
|
+
k.replaceChildren();
|
|
60
|
+
k.append(say('p', 'You are not signed in at this server.'));
|
|
61
|
+
if (loginUrl) {
|
|
62
|
+
const go = say('button', 'Sign in');
|
|
63
|
+
go.type = 'button'; go.className = 'primary';
|
|
64
|
+
go.onclick = () => { location.href = loginUrl; };
|
|
65
|
+
const p = document.createElement('p'); p.className = 'actions'; p.append(go);
|
|
66
|
+
k.append(p, say('p', 'Sign in, then come back to this page.'));
|
|
67
|
+
k.lastChild.className = 'hint';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function showPods(pods) {
|
|
72
|
+
const k = $('run-known');
|
|
73
|
+
k.hidden = false;
|
|
74
|
+
k.replaceChildren();
|
|
75
|
+
for (const pod of pods) {
|
|
76
|
+
const box = document.createElement('div'); box.className = 'pod';
|
|
77
|
+
// The names stand out from the sentences around them.
|
|
78
|
+
const line = (before, id, after = '.') => { const p = say('p', before); p.append(say('code', id), after); return p; };
|
|
79
|
+
box.append(line('Solid Identity (WebID): ', pod.webId, ''));
|
|
80
|
+
const actions = document.createElement('p'); actions.className = 'actions';
|
|
81
|
+
box.append(line('Fediverse Identity: ', pod.address, ''));
|
|
82
|
+
if (pod.running) {
|
|
83
|
+
const links = say('p', 'Manage your account: ');
|
|
84
|
+
const m = say('a', pod.manage.split('?')[0]); m.href = pod.manage;
|
|
85
|
+
links.append(m);
|
|
86
|
+
box.append(links);
|
|
87
|
+
const stop = say('button', 'Close this Fediverse account'); stop.type = 'button'; stop.className = 'primary';
|
|
88
|
+
stop.onclick = () => runStart('opt-out', pod.podBase);
|
|
89
|
+
actions.append(stop);
|
|
90
|
+
} else {
|
|
91
|
+
const go = say('button', 'Create a Fediverse account'); go.type = 'button'; go.className = 'primary';
|
|
92
|
+
go.onclick = () => runStart('opt-in', pod.podBase);
|
|
93
|
+
actions.append(go);
|
|
94
|
+
}
|
|
95
|
+
box.append(actions);
|
|
96
|
+
k.append(box);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
38
100
|
function runFormCheck() {
|
|
39
101
|
let ok = false;
|
|
40
102
|
try { ok = /^https?:$/.test(new URL($('run-pod-url').value.trim()).protocol); } catch { /* not yet */ }
|
|
@@ -53,22 +115,67 @@ $('run-pod-url').addEventListener('input', () => {
|
|
|
53
115
|
runFormCheck();
|
|
54
116
|
});
|
|
55
117
|
$('run-issuer').addEventListener('input', runFormCheck);
|
|
118
|
+
// A browser that puts back what was in these boxes — a reload, the back
|
|
119
|
+
// button, its own remembered values — fills them without anybody typing, and
|
|
120
|
+
// no typing meant the button was never asked to wake up. It stayed grey over
|
|
121
|
+
// a filled-in form, with nothing to say why.
|
|
122
|
+
runFormCheck();
|
|
56
123
|
|
|
57
|
-
const runStart = (action) => {
|
|
124
|
+
const runStart = async (action, podBase = null) => {
|
|
58
125
|
const n = $('run-note');
|
|
59
|
-
|
|
60
|
-
const u = new URL($('run-pod-url').value.trim());
|
|
126
|
+
const u = new URL(podBase || $('run-pod-url').value.trim());
|
|
61
127
|
if (u.pathname === '') u.pathname = '/';
|
|
62
128
|
if (!u.pathname.endsWith('/')) u.pathname += '/';
|
|
63
129
|
u.search = ''; u.hash = '';
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
130
|
+
const p = { podBase: u.href, action };
|
|
131
|
+
|
|
132
|
+
// A pod server issued the session this page is being read with, so ask it
|
|
133
|
+
// first: where it knows who you are, there is nothing to sign in to again.
|
|
134
|
+
// A Gateway fronting somebody else's pod answers 401 here and the login
|
|
135
|
+
// below is the only way.
|
|
136
|
+
n.hidden = false;
|
|
137
|
+
n.textContent = 'asking the server…';
|
|
138
|
+
const known = await fetch('/api/agent', {
|
|
139
|
+
method: 'POST', credentials: 'same-origin',
|
|
140
|
+
headers: { 'content-type': 'application/json' },
|
|
141
|
+
body: JSON.stringify(p),
|
|
142
|
+
}).catch(() => null);
|
|
143
|
+
if (known && known.status !== 401) { await showReply(known, p); return; }
|
|
144
|
+
|
|
145
|
+
if (!session) { n.textContent = 'the sign-in library did not load — reload and try again'; return; }
|
|
146
|
+
sessionStorage.setItem('fp-run', JSON.stringify(p));
|
|
147
|
+
session.login($('run-issuer').value.trim(), HERE)
|
|
148
|
+
.catch((e) => { n.textContent = 'sign-in failed to start: ' + e.message; });
|
|
67
149
|
};
|
|
68
150
|
$('run-continue').onclick = () => runStart('opt-in');
|
|
69
151
|
$('run-leave').onclick = () => runStart('opt-out');
|
|
70
152
|
|
|
71
|
-
//
|
|
153
|
+
// What came of it, however the server was satisfied — the session it already
|
|
154
|
+
// had, or a login proved afterwards.
|
|
155
|
+
async function showReply(res, p) {
|
|
156
|
+
const n = $('run-note');
|
|
157
|
+
n.hidden = false;
|
|
158
|
+
const d = res ? await res.json().catch(() => ({})) : {};
|
|
159
|
+
if (res && res.status === 201 && d.doorSecret) {
|
|
160
|
+
// Built as nodes, not as a string of HTML. Three of the pieces below come
|
|
161
|
+
// back from the server and one comes from sessionStorage, and pasting any
|
|
162
|
+
// of them into innerHTML means whatever markup they contain is rendered.
|
|
163
|
+
// Only the fixed wording is markup here; everything variable is text.
|
|
164
|
+
const manage = `${p.podBase.replace(/\/$/, '')}${d.doorPath}?dk-token=${encodeURIComponent(d.doorSecret)}`;
|
|
165
|
+
n.textContent = 'Your Fediverse account is ready. Manage it at ';
|
|
166
|
+
const a = say('a', p.podBase.replace(/\/$/, '') + d.doorPath); a.href = manage;
|
|
167
|
+
n.append(a, '.');
|
|
168
|
+
refreshKnown();
|
|
169
|
+
} else if (res && res.status === 200) {
|
|
170
|
+
n.textContent = 'Your Fediverse account is closed. Your pod and its data are untouched.';
|
|
171
|
+
refreshKnown();
|
|
172
|
+
} else {
|
|
173
|
+
n.textContent = (p.action === 'opt-in' ? 'opt-in' : 'opt-out') + ' failed: '
|
|
174
|
+
+ (d.error || (res ? 'HTTP ' + res.status : 'no response'));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Back from the identity provider: finish with the proven login.
|
|
72
179
|
(async () => {
|
|
73
180
|
if (!session) return;
|
|
74
181
|
await session.handleRedirectFromLogin().catch(() => {});
|
|
@@ -84,24 +191,5 @@ $('run-leave').onclick = () => runStart('opt-out');
|
|
|
84
191
|
method: 'POST', headers: { 'content-type': 'application/json' },
|
|
85
192
|
body: JSON.stringify({ action: p.action, podBase: p.podBase }),
|
|
86
193
|
}).catch(() => null);
|
|
87
|
-
|
|
88
|
-
if (res && res.status === 201 && d.doorSecret) {
|
|
89
|
-
// Built as nodes, not as a string of HTML. Three of the pieces below come
|
|
90
|
-
// back from the server and one comes from sessionStorage, and pasting any
|
|
91
|
-
// of them into innerHTML means whatever markup they contain is rendered.
|
|
92
|
-
// Only the fixed wording is markup here; everything variable is text.
|
|
93
|
-
const say = (tag, text) => { const e = document.createElement(tag); e.textContent = text; return e; };
|
|
94
|
-
n.textContent = 'Your identity runs here now. This is your door secret — ';
|
|
95
|
-
n.append(say('b', 'save it now'));
|
|
96
|
-
n.append(', it is shown only this once. It opens your admin pages at ');
|
|
97
|
-
n.append(say('code', p.podBase.replace(/\/$/, '') + d.doorPath));
|
|
98
|
-
n.append(':', say('pre', d.doorSecret));
|
|
99
|
-
n.append('To check it works:', say('pre', d.command));
|
|
100
|
-
n.append('Lost it? Opt in again — that mints a fresh one and retires this one.');
|
|
101
|
-
} else if (res && res.status === 200) {
|
|
102
|
-
n.textContent = 'Done — this server no longer runs that identity. Your pod and its data are untouched.';
|
|
103
|
-
} else {
|
|
104
|
-
n.textContent = (p.action === 'opt-in' ? 'opt-in' : 'opt-out') + ' failed: '
|
|
105
|
-
+ (d.error || (res ? 'HTTP ' + res.status : 'no response'));
|
|
106
|
-
}
|
|
194
|
+
await showReply(res, p);
|
|
107
195
|
})();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
|
2
|
+
<!-- The forum: more than one person talking. Icon "messages-square" from
|
|
3
|
+
Lucide (lucide.dev), ISC licence, © Lucide Contributors. -->
|
|
4
|
+
<title>Federated Solid Forum</title>
|
|
5
|
+
<rect width="32" height="32" rx="7" fill="#3b5bb5"/>
|
|
6
|
+
<g transform="translate(4 4)" fill="none" stroke="#ffffff" stroke-width="2"
|
|
7
|
+
stroke-linecap="round" stroke-linejoin="round">
|
|
8
|
+
<path d="M16 10a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 14.286V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/>
|
|
9
|
+
<path d="M20 9a2 2 0 0 1 2 2v10.286a.71.71 0 0 1-1.212.502l-2.202-2.202A2 2 0 0 0 17.172 19H10a2 2 0 0 1-2-2v-1"/>
|
|
10
|
+
</g>
|
|
11
|
+
</svg>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
|
2
|
+
<!-- The gateway: the door your mail comes through. Icon "door-open" from
|
|
3
|
+
Lucide (lucide.dev), ISC licence, © Lucide Contributors. -->
|
|
4
|
+
<title>FediPod gateway</title>
|
|
5
|
+
<rect width="32" height="32" rx="7" fill="#b4531a"/>
|
|
6
|
+
<g transform="translate(4 4)" fill="none" stroke="#ffffff" stroke-width="2"
|
|
7
|
+
stroke-linecap="round" stroke-linejoin="round">
|
|
8
|
+
<path d="M10 21H2"/>
|
|
9
|
+
<path d="M10 3H7a2 2 0 00-2 2v16"/>
|
|
10
|
+
<path d="M14 12h.01"/>
|
|
11
|
+
<path d="M19 21V5a2 2 0 00-1.675-1.974l-6.163-1.013A1 1 0 0010 3v18a1 1 0 001.124.992z"/>
|
|
12
|
+
<path d="M22 21h-3"/>
|
|
13
|
+
</g>
|
|
14
|
+
</svg>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
|
2
|
+
<!-- Your own pod and your own posts. Icon "house" from Lucide (lucide.dev),
|
|
3
|
+
ISC licence, © Lucide Contributors. -->
|
|
4
|
+
<title>FediPod</title>
|
|
5
|
+
<rect width="32" height="32" rx="7" fill="#2f7d4f"/>
|
|
6
|
+
<g transform="translate(4 4)" fill="none" stroke="#ffffff" stroke-width="2"
|
|
7
|
+
stroke-linecap="round" stroke-linejoin="round">
|
|
8
|
+
<path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"/>
|
|
9
|
+
<path d="M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
|
|
10
|
+
</g>
|
|
11
|
+
</svg>
|
package/web/app/index.html~
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
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
|
-
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' https://solidcommunity.net https://*.solidcommunity.net; form-action 'self' https://solidcommunity.net https://*.solidcommunity.net; base-uri 'none'">
|
|
7
|
-
<title>FediPod</title>
|
|
8
|
-
<style>
|
|
9
|
-
:root { color-scheme: light dark; font-size: 112.5%; --heading: #1a4f8a; --sub: #666; --line: #bbb; --accent: #1a4f8a; }
|
|
10
|
-
@media (prefers-color-scheme: dark) { :root { --heading: #7fb3e8; --sub: #aaa; --line: #555; --accent: #7fb3e8; } }
|
|
11
|
-
body { font: 1rem/1.5 system-ui, sans-serif; margin: 0; }
|
|
12
|
-
#page { max-width: 42rem; margin: 0 auto; padding: 1.75rem 1rem 4rem; box-sizing: border-box; }
|
|
13
|
-
h1, h2, h3 { color: var(--heading); }
|
|
14
|
-
h1 { font-size: 1.5rem; margin: 0 0 .5rem; }
|
|
15
|
-
#brand { margin: 0 0 1.25rem; }
|
|
16
|
-
h2 { font-size: 1.1rem; margin: 2rem 0 .5rem; }
|
|
17
|
-
p { margin: .6rem 0; }
|
|
18
|
-
code { background: rgba(120,120,120,.14); padding: .05em .35em; border-radius: 4px; }
|
|
19
|
-
.sub { color: var(--sub); margin-top: 0; }
|
|
20
|
-
.hint { color: var(--sub); font-size: .9rem; margin: .15rem 0 0; }
|
|
21
|
-
fieldset { border: 1px solid var(--line); border-radius: .4rem; margin: 1rem 0; padding: .75rem 1rem 1rem; }
|
|
22
|
-
legend { padding: 0 .3rem; font-weight: 600; }
|
|
23
|
-
label { display: block; margin: .75rem 0 .2rem; }
|
|
24
|
-
input[type=text], input[type=email], input[type=url], input[type=password], select {
|
|
25
|
-
font: inherit; width: 100%; padding: .5rem; box-sizing: border-box;
|
|
26
|
-
border: 1px solid #767676; border-radius: .3rem; background: Field; color: FieldText; }
|
|
27
|
-
.choice { display: block; margin: .35rem 0; font-weight: normal; }
|
|
28
|
-
.choice input { margin-right: .4rem; width: auto; }
|
|
29
|
-
button { font: inherit; padding: .6rem 1.2rem; border-radius: .3rem; border: 1px solid #666;
|
|
30
|
-
background: ButtonFace; color: ButtonText; cursor: pointer; }
|
|
31
|
-
button.primary { font-weight: 600; }
|
|
32
|
-
button:disabled { opacity: .5; cursor: default; }
|
|
33
|
-
.row { display: flex; gap: .5rem; align-items: center; }
|
|
34
|
-
.row input { flex: 1; }
|
|
35
|
-
.row button { white-space: nowrap; }
|
|
36
|
-
.address { font-size: 1.2rem; font-weight: 600; word-break: break-all; }
|
|
37
|
-
.warn { border-left: .25rem solid #c60; padding-left: .75rem; }
|
|
38
|
-
.err { border-left: .25rem solid #b00020; padding-left: .75rem; color: #b00020; }
|
|
39
|
-
@media (prefers-color-scheme: dark) { .err { color: #ff8a8a; border-left-color: #ff8a8a; } }
|
|
40
|
-
#form-error:empty, #signin-error:empty { display: none; }
|
|
41
|
-
.steps { list-style: none; padding: 0; }
|
|
42
|
-
.steps li { padding: .3rem 0; }
|
|
43
|
-
a { color: var(--accent); }
|
|
44
|
-
[hidden] { display: none !important; }
|
|
45
|
-
</style>
|
|
46
|
-
</head>
|
|
47
|
-
<body>
|
|
48
|
-
<main id="page">
|
|
49
|
-
|
|
50
|
-
<!-- The marketing hero: shown on the landing, hidden once a form is up. -->
|
|
51
|
-
<header id="hero">
|
|
52
|
-
<h1>FediPod - join the Fediverse from a Solid pod.</h1>
|
|
53
|
-
<p>Welcome to <b>fedipod.net</b>! By creating an account here, you can get a free Solid pod
|
|
54
|
-
and Fediverse identity or link to your existing pod/identity. Your <code>fedipod.net</code>
|
|
55
|
-
account provides you a portal to the Fediverse and filters unverified mail but does not tie
|
|
56
|
-
you to anything. All of your data lives on your pod and your Fediverse identity is yours
|
|
57
|
-
forever regardless of what happens to fedipod.net.</p>
|
|
58
|
-
<p>There is nothing to install, once you've setup an account, just point any browser at
|
|
59
|
-
<code>https://fedipod.net</code> and sign in.</p>
|
|
60
|
-
</header>
|
|
61
|
-
|
|
62
|
-
<!-- The short brand: shown only when a form is up, so the form stands alone. -->
|
|
63
|
-
<h1 id="brand" hidden>FediPod</h1>
|
|
64
|
-
|
|
65
|
-
<p id="loading">Loading…</p>
|
|
66
|
-
|
|
67
|
-
<section id="landing" hidden>
|
|
68
|
-
<h2>Already have an account?</h2>
|
|
69
|
-
<p class="row">
|
|
70
|
-
<input type="text" id="signin-address" autocapitalize="off" spellcheck="false" placeholder="@me@mypod">
|
|
71
|
-
<button type="button" class="primary" id="signin">sign in</button>
|
|
72
|
-
</p>
|
|
73
|
-
<p class="err" id="signin-error" role="alert"></p>
|
|
74
|
-
<h2>New user?</h2>
|
|
75
|
-
<p><button type="button" class="primary" id="create">create an account</button></p>
|
|
76
|
-
<p class="hint">For more information, see
|
|
77
|
-
<a href="https://github.com/jeff-zucker/FediPod">github.com/jeff-zucker/FediPod</a></p>
|
|
78
|
-
</section>
|
|
79
|
-
|
|
80
|
-
<section id="pane-form" hidden>
|
|
81
|
-
<form id="form">
|
|
82
|
-
|
|
83
|
-
<!-- Screen 1: Your Solid Pod -->
|
|
84
|
-
<div class="step" id="step-1">
|
|
85
|
-
<fieldset>
|
|
86
|
-
<legend>Your Solid Pod</legend>
|
|
87
|
-
|
|
88
|
-
<label>Pod type</label>
|
|
89
|
-
<label class="choice"><input type="radio" name="mode" value="existing"> An existing pod</label>
|
|
90
|
-
<label class="choice"><input type="radio" name="mode" value="new" checked> A new pod</label>
|
|
91
|
-
|
|
92
|
-
<label for="provider">Pod provider</label>
|
|
93
|
-
<input type="url" id="provider" name="provider" autocomplete="url" placeholder="https://solidcommunity.net">
|
|
94
|
-
|
|
95
|
-
<label for="podName">Pod username/subdomain</label>
|
|
96
|
-
<input type="text" id="podName" name="podName" autocomplete="off" aria-describedby="podname-hint">
|
|
97
|
-
<p class="hint" id="podname-hint">The subdomain of your pod: your pod address becomes
|
|
98
|
-
https://YOUR-USERNAME.your-provider.</p>
|
|
99
|
-
|
|
100
|
-
<label for="email">Pod email</label>
|
|
101
|
-
<input type="email" id="email" name="email" autocomplete="email" placeholder="you@example.org">
|
|
102
|
-
|
|
103
|
-
<label for="password">Pod password</label>
|
|
104
|
-
<input type="password" id="password" name="password" autocomplete="current-password"
|
|
105
|
-
aria-describedby="password-hint">
|
|
106
|
-
<p class="hint" id="password-hint">The password is sent once in return for a credential stored
|
|
107
|
-
in this browser. The password itself is never stored, and you can revoke the credential
|
|
108
|
-
without changing it.</p>
|
|
109
|
-
</fieldset>
|
|
110
|
-
<p class="err" id="err-1" role="alert"></p>
|
|
111
|
-
<p>
|
|
112
|
-
<button type="button" id="cancel">Cancel</button>
|
|
113
|
-
<button type="button" class="primary" id="to-2">Continue</button>
|
|
114
|
-
</p>
|
|
115
|
-
</div>
|
|
116
|
-
|
|
117
|
-
<!-- Screen 2: Your Fediverse Identity -->
|
|
118
|
-
<div class="step" id="step-2" hidden>
|
|
119
|
-
<fieldset>
|
|
120
|
-
<legend>Your Fediverse Identity</legend>
|
|
121
|
-
|
|
122
|
-
<label for="handle">Fediverse handle</label>
|
|
123
|
-
<input type="text" id="handle" name="handle" autocomplete="off"
|
|
124
|
-
placeholder="the handle part of your address: @HANDLE@server" aria-describedby="handle-hint">
|
|
125
|
-
<p class="hint" id="handle-hint">The name in your Fediverse address. This is permanent.
|
|
126
|
-
Letters, digits, and hyphens only.</p>
|
|
127
|
-
|
|
128
|
-
<label>Your Fediverse address</label>
|
|
129
|
-
<p class="address" id="preview">@…@…</p>
|
|
130
|
-
</fieldset>
|
|
131
|
-
<p class="hint">The handle and the pod cannot be changed afterwards. Everything else — display
|
|
132
|
-
name, bio, pictures — you set later in the client.</p>
|
|
133
|
-
<p class="err" id="form-error" role="alert"></p>
|
|
134
|
-
<p>
|
|
135
|
-
<button type="button" id="back-1">Back</button>
|
|
136
|
-
<button type="submit" class="primary" id="submit">Create Pod and Fediverse accounts</button>
|
|
137
|
-
</p>
|
|
138
|
-
</div>
|
|
139
|
-
|
|
140
|
-
</form>
|
|
141
|
-
</section>
|
|
142
|
-
|
|
143
|
-
<section id="running" hidden>
|
|
144
|
-
<h2>Setting up…</h2>
|
|
145
|
-
<ul class="steps" id="steps"></ul>
|
|
146
|
-
<p class="err" id="run-error" role="alert"></p>
|
|
147
|
-
</section>
|
|
148
|
-
|
|
149
|
-
</main>
|
|
150
|
-
<script type="module" src="/boot.js"></script>
|
|
151
|
-
</body>
|
|
152
|
-
</html>
|
package/web/app/site/_headers
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/app/*
|
|
2
|
-
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' https: data: blob:; media-src 'self' https: blob:; connect-src 'self' https:; font-src 'self' data:; object-src 'none'; base-uri 'none'; frame-ancestors 'self'; form-action 'self'
|
|
3
|
-
X-Content-Type-Options: nosniff
|
|
4
|
-
Referrer-Policy: same-origin
|
|
5
|
-
|
|
6
|
-
/admin/*
|
|
7
|
-
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' https: data: blob:; connect-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'self'; form-action 'self'
|
|
8
|
-
X-Content-Type-Options: nosniff
|
|
9
|
-
Referrer-Policy: same-origin
|
package/web/app/site/_redirects
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# gateway + front API → the function
|
|
2
|
-
/api/handle /.netlify/functions/front 200
|
|
3
|
-
/api/attach /.netlify/functions/front 200
|
|
4
|
-
/api/relay /.netlify/functions/front 200
|
|
5
|
-
/api/roster /.netlify/functions/front 200
|
|
6
|
-
/api/revoke /.netlify/functions/front 200
|
|
7
|
-
/api/agent /.netlify/functions/front 200
|
|
8
|
-
/u/* /.netlify/functions/front 200
|
|
9
|
-
/.well-known/* /.netlify/functions/front 200
|
|
10
|
-
/@* /.netlify/functions/front 200
|
|
11
|
-
/install /.netlify/functions/front 200
|
|
12
|
-
/run /.netlify/functions/front 200
|
|
13
|
-
/roster /.netlify/functions/front 200
|
|
14
|
-
/solid-oidc-client.js /.netlify/functions/front 200
|
|
15
|
-
# the in-browser app, served static (these win over the project catch-all)
|
|
16
|
-
/ /index.html 200
|
|
17
|
-
/sw.js /sw.js 200
|
|
18
|
-
/boot.js /boot.js 200
|
|
19
|
-
/app /app/ 301
|
|
20
|
-
/app/* /app/:splat 200
|
|
21
|
-
/admin /admin/ 301
|
|
22
|
-
/admin/* /admin/:splat 200
|