| 1 | // De betaalmuur -- verplaatst uit inline script, shaer-bqr.
|
|---|
| 2 | //
|
|---|
| 3 | // Inline script wordt door de CSP geweigerd zodra deze pagina via een link
|
|---|
| 4 | // BINNEN de site binnenkomt (shaer-0i6). Servergegevens komen uit pageData();
|
|---|
| 5 | // interpolatie kan niet in een statisch bestand.
|
|---|
| 6 |
|
|---|
| 7 | import { pageData, loadWebAuthn } from './lib.js';
|
|---|
| 8 |
|
|---|
| 9 | // Element-bedrading leeft zo lang als de pagina; de bootstrap roept init()
|
|---|
| 10 | // aan bij elke paginawissel waarop deze module actief is (shaer-5s1).
|
|---|
| 11 | //
|
|---|
| 12 | // EERST de bibliotheek, dan pas bedraden (shaer-0i6): die stond als
|
|---|
| 13 | // `<script src>` in de pagina en overleefde een htmx-navigatie niet. Wacht
|
|---|
| 14 | // run() daar niet op, dan valt hij terug op "geen WebAuthn" en verbergt hij
|
|---|
| 15 | // de ontgrendelknop op een pagina waar ontgrendelen gewoon kan.
|
|---|
| 16 | export async function init() { await loadWebAuthn(); run(); }
|
|---|
| 17 |
|
|---|
| 18 | function run() {
|
|---|
| 19 | (function () {
|
|---|
| 20 | var _d = pageData();
|
|---|
| 21 | var base = _d.base || "";
|
|---|
| 22 | var slug = _d.slug || "";
|
|---|
| 23 | var hasPatron = !!_d.hasPatron;
|
|---|
| 24 | var I = _d.i18n || {};
|
|---|
| 25 | var btn = document.getElementById('pg-unlock');
|
|---|
| 26 | var status = document.getElementById('pg-status');
|
|---|
| 27 | function say(msg, err) { status.hidden = false; status.textContent = msg; status.classList.toggle('is-err', !!err); }
|
|---|
| 28 | function toLink() { location.href = base + '/paid/link?post=' + encodeURIComponent(slug); }
|
|---|
| 29 |
|
|---|
| 30 | // No WebAuthn here: an assertion is impossible. With a Patreon page there is
|
|---|
| 31 | // already a "Word supporter" button, so hide the (dead) unlock button rather
|
|---|
| 32 | // than turn it into a second "Word supporter". Without one, this IS the button.
|
|---|
| 33 | if (!window.SimpleWebAuthnBrowser || !window.PublicKeyCredential) {
|
|---|
| 34 | if (hasPatron) { btn.style.display = 'none'; }
|
|---|
| 35 | else { btn.textContent = I.join; btn.addEventListener('click', toLink); }
|
|---|
| 36 | return;
|
|---|
| 37 | }
|
|---|
| 38 |
|
|---|
| 39 | btn.addEventListener('click', function () {
|
|---|
| 40 | btn.disabled = true;
|
|---|
| 41 | say(I.confirm);
|
|---|
| 42 | fetch(base + '/paid/challenge?post=' + encodeURIComponent(slug))
|
|---|
| 43 | .then(function (r) { if (!r.ok) throw { link: true }; return r.json(); })
|
|---|
| 44 | .then(function (data) {
|
|---|
| 45 | return window.SimpleWebAuthnBrowser.startAuthentication({ optionsJSON: data.options })
|
|---|
| 46 | .then(function (response) {
|
|---|
| 47 | return fetch(base + '/paid/unlock', {
|
|---|
| 48 | method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|---|
| 49 | body: JSON.stringify({ response: response, blob: data.blob }),
|
|---|
| 50 | });
|
|---|
| 51 | });
|
|---|
| 52 | })
|
|---|
| 53 | .then(function (r) { return r.json().then(function (j) { return { status: r.status, j: j }; }); })
|
|---|
| 54 | .then(function (res) {
|
|---|
| 55 | if (res.j && res.j.ok && res.j.redirect) {
|
|---|
| 56 | // Reload the real post page via the one-shot unlock capability, so it
|
|---|
| 57 | // renders through its normal template (layout, styles, audio).
|
|---|
| 58 | location.href = res.j.redirect;
|
|---|
| 59 | } else if (res.status === 403) {
|
|---|
| 60 | toLink(); // no valid passkey yet (or lapsed tier): link via Patreon
|
|---|
| 61 | } else {
|
|---|
| 62 | btn.disabled = false; say(I.failed, true);
|
|---|
| 63 | }
|
|---|
| 64 | })
|
|---|
| 65 | .catch(function (e) {
|
|---|
| 66 | if (e && e.link) { toLink(); return; }
|
|---|
| 67 | if (e && e.name === 'NotAllowedError') { toLink(); return; } // cancelled / no passkey -> link
|
|---|
| 68 | btn.disabled = false; say(I.error, true);
|
|---|
| 69 | });
|
|---|
| 70 | });
|
|---|
| 71 | })();
|
|---|
| 72 | }
|
|---|