| 1 | <section class="pk">
|
|---|
| 2 | <div class="pk-card">
|
|---|
| 3 | <div class="pk-ic">🔑</div>
|
|---|
| 4 | <h1 class="pk-h1"><%= t('ppk.h') %></h1>
|
|---|
| 5 | <p class="pk-sub">
|
|---|
| 6 | <%= t('ppk.sub') %>
|
|---|
| 7 | </p>
|
|---|
| 8 | <button type="button" id="pk-go" class="pk-btn"><%= t('ppk.make') %></button>
|
|---|
| 9 | <p id="pk-status" class="pk-status" hidden></p>
|
|---|
| 10 | </div>
|
|---|
| 11 | </section>
|
|---|
| 12 |
|
|---|
| 13 | <script src="/assets/vendor/simplewebauthn-browser.umd.min.js"></script>
|
|---|
| 14 | <script>
|
|---|
| 15 | (function () {
|
|---|
| 16 | var options = <%- optionsJson %>;
|
|---|
| 17 | var blob = "<%= regBlob %>";
|
|---|
| 18 | var I = { unsupported: "<%= t('ppk.unsupported') %>", follow: "<%= t('ppk.follow') %>", done: "<%= t('ppk.done') %>", failed: "<%= t('ppk.failed') %>", cancelled: "<%= t('ppk.cancelled') %>", error: "<%= t('pgate.error') %>" };
|
|---|
| 19 | var postUrl = "<%= (typeof siteUrlBase !== 'undefined' && siteUrlBase ? siteUrlBase : '') %>/<%= postSlug %>";
|
|---|
| 20 | var btn = document.getElementById('pk-go');
|
|---|
| 21 | var status = document.getElementById('pk-status');
|
|---|
| 22 | function say(msg, err) { status.hidden = false; status.textContent = msg; status.classList.toggle('is-err', !!err); }
|
|---|
| 23 |
|
|---|
| 24 | if (!window.SimpleWebAuthnBrowser || !window.PublicKeyCredential) {
|
|---|
| 25 | btn.disabled = true;
|
|---|
| 26 | say(I.unsupported, true);
|
|---|
| 27 | return;
|
|---|
| 28 | }
|
|---|
| 29 | btn.addEventListener('click', function () {
|
|---|
| 30 | btn.disabled = true;
|
|---|
| 31 | say(I.follow);
|
|---|
| 32 | window.SimpleWebAuthnBrowser.startRegistration({ optionsJSON: options })
|
|---|
| 33 | .then(function (response) {
|
|---|
| 34 | return fetch('/paid/register', {
|
|---|
| 35 | method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|---|
| 36 | body: JSON.stringify({ response: response, blob: blob }),
|
|---|
| 37 | });
|
|---|
| 38 | })
|
|---|
| 39 | .then(function (r) { return r.json(); })
|
|---|
| 40 | .then(function (j) {
|
|---|
| 41 | if (j && j.ok) { say(I.done); setTimeout(function () { location.href = postUrl; }, 900); }
|
|---|
| 42 | else { btn.disabled = false; say(I.failed.replace('{err}', (j && j.error) || '?'), true); }
|
|---|
| 43 | })
|
|---|
| 44 | .catch(function (e) { btn.disabled = false; say(e && e.name === 'NotAllowedError' ? I.cancelled : I.error, true); });
|
|---|
| 45 | });
|
|---|
| 46 | })();
|
|---|
| 47 | </script>
|
|---|
| 48 |
|
|---|
| 49 | <style>
|
|---|
| 50 | .pk { max-width: 480px; margin: 0 auto; padding: 56px 18px; text-align: center; }
|
|---|
| 51 | .pk-card { border: 1px solid color-mix(in srgb, var(--ink,#000) 16%, transparent); border-radius: 18px; padding: 34px 26px; }
|
|---|
| 52 | .pk-ic { font-size: 40px; margin-bottom: 8px; }
|
|---|
| 53 | .pk-h1 { font-size: 24px; margin: 0 0 6px; }
|
|---|
| 54 | .pk-sub { opacity: .85; line-height: 1.6; margin: 0 0 20px; }
|
|---|
| 55 | .pk-btn { padding: 12px 24px; border: none; border-radius: 10px; background: var(--accent,#6b8f71); color: #fff; font-weight: 600; font: inherit; font-weight: 600; cursor: pointer; }
|
|---|
| 56 | .pk-btn:disabled { opacity: .6; cursor: default; }
|
|---|
| 57 | .pk-status { margin: 14px 0 0; opacity: .9; }
|
|---|
| 58 | .pk-status.is-err { color: #c0392b; }
|
|---|
| 59 | </style>
|
|---|