Lots of frontend stuff

- Passkey support on the way
- Add biome file
- added humans.txt
- tests
This commit is contained in:
Melody Becker 2024-10-15 16:18:21 +02:00
parent 79937b5325
commit 4f761c20c0
22 changed files with 509 additions and 175 deletions

View file

@ -0,0 +1,119 @@
import { action } from '@ember/object';
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import '@simplewebauthn/browser';
import {
startAuthentication,
startRegistration,
} from '@simplewebauthn/browser';
export interface PasskeySignature {
// The arguments accepted by the component
Args: {};
// Any blocks yielded by the component
Blocks: {
default: [];
};
// The element to which `...attributes` is applied in the component template
Element: null;
}
export default class Passkey extends Component<PasskeySignature> {
@tracked username: string = '';
@tracked error: string | undefined;
@action async startLogin() {
try {
// Get login options from your server. Here, we also receive the challenge.
const response = await fetch('/webauthn/passkey/loginBegin', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: this.username }),
});
// Check if the login options are ok.
if (!response.ok) {
const msg = await response.json();
throw new Error('Failed to get login options from server: ' + msg);
}
// Convert the login options to JSON.
const options = await response.json();
// This triggers the browser to display the passkey / WebAuthn modal (e.g. Face ID, Touch ID, Windows Hello).
// A new assertionResponse is created. This also means that the challenge has been signed.
const assertionResponse = await startAuthentication(options.publicKey);
// Send assertionResponse back to server for verification.
const verificationResponse = await fetch(
'/webauthn/passkey/loginFinish',
{
method: 'POST',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(assertionResponse),
},
);
const msg = await verificationResponse.json();
if (verificationResponse.ok) {
this.error = undefined;
} else {
this.error = msg;
}
} catch (error: any) {
this.error = 'Error: ' + error.message;
}
}
@action async startRegistration() {
try {
// Get registration options from your server. Here, we also receive the challenge.
const response = await fetch('/webauthn/passkey/registerBegin', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: this.username }),
});
// Check if the registration options are ok.
if (!response.ok) {
const msg = await response.json();
throw new Error(
'User already exists or failed to get registration options from server: ' +
msg,
);
}
// Convert the registration options to JSON.
const options = await response.json();
console.log('registration start', options);
// This triggers the browser to display the passkey / WebAuthn modal (e.g. Face ID, Touch ID, Windows Hello).
// A new attestation is created. This also means a new public-private-key pair is created.
const attestationResponse = await startRegistration(options.publicKey);
console.log('Attempting to complete registration', attestationResponse);
// Send attestationResponse back to server for verification and storage.
const verificationResponse = await fetch(
'/webauthn/passkey/registerFinish',
{
method: 'POST',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(attestationResponse),
},
);
const msg = await verificationResponse.json();
if (verificationResponse.ok) {
this.error = undefined;
} else {
this.error = msg;
}
} catch (error: any) {
this.error = 'Error: ' + error.message;
}
}
}

View file

@ -0,0 +1,13 @@
import Service from '@ember/service'
export default class AuthenticationService extends Service {}
// Don't remove this declaration: this is what enables TypeScript to resolve
// this service using `Owner.lookup('service:authentication')`, as well
// as to check when you pass the service name as an argument to the decorator,
// like `@service('authentication') declare altName: AuthenticationService;`.
declare module '@ember/service' {
interface Registry {
authentication: AuthenticationService
}
}

View file

@ -4,11 +4,7 @@
/* Copied from: https://stackoverflow.com/a/4407335 */
.noselect {
-webkit-touch-callout: none; /* iOS Safari */
user-select: none; /* Safari */
user-select: none; /* Konqueror HTML */
user-select: none; /* Old versions of Firefox */
user-select: none; /* Internet Explorer/Edge */
-webkit-touch-callout: none; /* iOS Safari */ /* Safari */ /* Konqueror HTML */ /* Old versions of Firefox */ /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently
supported by Chrome, Edge, Opera and Firefox */
}

View file

@ -0,0 +1,156 @@
{
"$schema": "https://biomejs.dev/schemas/1.9.3/schema.json",
"vcs": { "enabled": false, "clientKind": "git", "useIgnoreFile": false },
"files": { "ignoreUnknown": false, "ignore": [] },
"formatter": {
"enabled": true,
"useEditorconfig": true,
"formatWithErrors": false,
"indentStyle": "space",
"indentWidth": 2,
"lineEnding": "lf",
"lineWidth": 80,
"attributePosition": "auto",
"bracketSpacing": true,
"ignore": [
"./blueprints/*/files/",
"./dist/",
"./coverage/",
"**/.*/",
"./.node_modules.ember-try/"
]
},
"organizeImports": { "enabled": true },
"linter": {
"enabled": true,
"rules": {
"recommended": false,
"complexity": {
"noExtraBooleanCast": "error",
"noMultipleSpacesInRegularExpressionLiterals": "error",
"noUselessCatch": "error",
"noWith": "error",
"useArrowFunction": "off"
},
"correctness": {
"noConstAssign": "error",
"noConstantCondition": "error",
"noEmptyCharacterClassInRegex": "error",
"noEmptyPattern": "error",
"noGlobalObjectCalls": "error",
"noInnerDeclarations": "error",
"noInvalidConstructorSuper": "error",
"noNewSymbol": "error",
"noNonoctalDecimalEscape": "error",
"noPrecisionLoss": "error",
"noSelfAssign": "error",
"noSetterReturn": "error",
"noSwitchDeclarations": "error",
"noUndeclaredVariables": "error",
"noUnreachable": "error",
"noUnreachableSuper": "error",
"noUnsafeFinally": "error",
"noUnsafeOptionalChaining": "error",
"noUnusedLabels": "error",
"noUnusedVariables": "error",
"useIsNan": "error",
"useValidForDirection": "error",
"useYield": "error"
},
"style": { "useBlockStatements": "off" },
"suspicious": {
"noAssignInExpressions": "error",
"noAsyncPromiseExecutor": "error",
"noCatchAssign": "error",
"noClassAssign": "error",
"noCompareNegZero": "error",
"noControlCharactersInRegex": "error",
"noDebugger": "error",
"noDuplicateCase": "error",
"noDuplicateClassMembers": "error",
"noDuplicateObjectKeys": "error",
"noDuplicateParameters": "error",
"noEmptyBlockStatements": "error",
"noFallthroughSwitchClause": "error",
"noFunctionAssign": "error",
"noGlobalAssign": "error",
"noImportAssign": "error",
"noMisleadingCharacterClass": "error",
"noPrototypeBuiltins": "error",
"noRedeclare": "error",
"noShadowRestrictedNames": "error",
"noSparseArray": "error",
"noUnsafeNegation": "error",
"useGetterReturn": "error",
"useValidTypeof": "error"
}
},
"ignore": [
"./blueprints/*/files/",
"./declarations/",
"./dist/",
"./coverage/",
"**/.*/",
"./.node_modules.ember-try/"
]
},
"javascript": {
"formatter": {
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"trailingCommas": "all",
"semicolons": "asNeeded",
"arrowParentheses": "always",
"bracketSameLine": false,
"quoteStyle": "single",
"attributePosition": "auto",
"bracketSpacing": true
}
},
"overrides": [
{ "include": ["**/*.ts"] },
{
"include": [
"./.eslintrc.js",
"./.prettierrc.js",
"./.stylelintrc.js",
"./.template-lintrc.js",
"./ember-cli-build.js",
"./testem.js",
"./blueprints/*/index.js",
"./config/**/*.js",
"./lib/*/index.js",
"./server/**/*.js"
]
},
{ "include": ["tests/**/*-test.{js,ts}"] },
{
"include": ["**/*.gjs", "**/*.gts"],
"javascript": { "globals": ["__GLIMMER_TEMPLATE"] }
},
{ "include": ["**/*.ts"] },
{
"include": [
"./.eslintrc.js",
"./.prettierrc.js",
"./.stylelintrc.js",
"./.template-lintrc.js",
"./ember-cli-build.js",
"./testem.js",
"./blueprints/*/index.js",
"./config/**/*.js",
"./lib/*/index.js",
"./server/**/*.js"
]
},
{ "include": ["tests/**/*-test.{js,ts}"] },
{
"include": ["**/*.gjs", "**/*.gts"],
"javascript": { "globals": ["__GLIMMER_TEMPLATE"] }
},
{
"include": ["*.{js,ts}"],
"javascript": { "formatter": { "quoteStyle": "single" } }
}
]
}

Binary file not shown.

View file

@ -116,6 +116,7 @@
"edition": "octane"
},
"dependencies": {
"@simplewebauthn/browser": "^11.0.0",
"moment": "^2.30.1"
}
}

View file

@ -0,0 +1 @@
Linstrom, made my Melody/m*

View file

@ -1,18 +1,18 @@
import { module, test } from "qunit";
import { setupRenderingTest } from "frontend-reactive/tests/helpers";
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from 'qunit';
import { setupRenderingTest } from 'frontend-reactive/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module("Integration | Component | global/general-sidebar", function (hooks) {
module('Integration | Component | global/general-sidebar', function (hooks) {
setupRenderingTest(hooks);
test("it renders", async function (assert) {
test('it renders', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });
await render(hbs`<Global::GeneralSidebar />`);
assert.dom().hasText("");
assert.dom().hasText('');
// TODO: Add tests once design exists
});
});

View file

@ -1,19 +1,19 @@
import { module, test } from "qunit";
import { setupRenderingTest } from "frontend-reactive/tests/helpers";
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from 'qunit';
import { setupRenderingTest } from 'frontend-reactive/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module("Integration | Component | note", function (hooks) {
module('Integration | Component | note', function (hooks) {
setupRenderingTest(hooks);
test("it renders", async function (assert) {
test('it renders', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });
this.set("note", {
displayname: "bob",
username: "alice",
server: "example.com",
content: "some content",
this.set('note', {
displayname: 'bob',
username: 'alice',
server: 'example.com',
content: 'some content',
createdAt: Date.now(),
});
@ -21,9 +21,9 @@ module("Integration | Component | note", function (hooks) {
<Note @note={{this.note}}/>
`);
assert.dom("p.note-user-displayname").hasText("bob");
assert.dom("p.note-user-handle").hasText("@alice@example.com");
assert.dom("p.note-content-text").hasText("some content");
assert.dom('p.note-user-displayname').hasText('bob');
assert.dom('p.note-user-handle').hasText('@alice@example.com');
assert.dom('p.note-content-text').hasText('some content');
// TODO: Fix tests
});
});

View file

@ -1,41 +1,41 @@
import { module, test } from "qunit";
import { setupRenderingTest } from "frontend-reactive/tests/helpers";
import { render, click } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { setupIntl } from "ember-intl/test-support";
import { module, test } from 'qunit';
import { setupRenderingTest } from 'frontend-reactive/tests/helpers';
import { render, click } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
import { setupIntl } from 'ember-intl/test-support';
module("Integration | Component | note/content", function (hooks) {
module('Integration | Component | note/content', function (hooks) {
setupRenderingTest(hooks);
setupIntl(hooks, "en-us");
setupIntl(hooks, 'en-us');
test("keep short content as is", async function (assert) {
test('keep short content as is', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });
const shortContent = "Lorem ipsum odor amet, consectetuer adipiscing elit.";
this.set("shortContent", shortContent);
const shortContent = 'Lorem ipsum odor amet, consectetuer adipiscing elit.';
this.set('shortContent', shortContent);
await render(hbs`<Note::Content @content="{{this.shortContent}}"/>`);
assert.dom(".note-content-text").hasText(shortContent);
assert.dom('.note-content-text').hasText(shortContent);
});
test("long content cutoff and correct expansion", async function (assert) {
test('long content cutoff and correct expansion', async function (assert) {
const longContent =
"Grapple keel reef fathom haul wind bilge rat swing the lead belay line pink. Man-of-war mizzenmast killick lookout yo-ho-ho Sail ho gabion careen sutler stern. Draught wherry lookout schooner prow hail-shot spanker Letter of Marque lateen sail strike colors.\n\nLad heave to topgallant scallywag scuppers Spanish Main poop deck spike hulk broadside. Snow take a caulk hornswaggle gaff swab quarter lugger spanker bilge provost. Man-of-war measured fer yer chains lugger cable loaded to the gunwalls prow piracy snow doubloon furl.\n\nDead men tell no tales jib chase guns gunwalls Gold Road smartly nipperkin topsail bilge water Pirate Round. Gaff gunwalls bilged on her anchor bilge water scourge of the seven seas parley ho sheet chase guns squiffy. Scuppers fathom ho quarter gally heave to yardarm coxswain red ensign pink.";
this.set("longContent", longContent);
'Grapple keel reef fathom haul wind bilge rat swing the lead belay line pink. Man-of-war mizzenmast killick lookout yo-ho-ho Sail ho gabion careen sutler stern. Draught wherry lookout schooner prow hail-shot spanker Letter of Marque lateen sail strike colors.\n\nLad heave to topgallant scallywag scuppers Spanish Main poop deck spike hulk broadside. Snow take a caulk hornswaggle gaff swab quarter lugger spanker bilge provost. Man-of-war measured fer yer chains lugger cable loaded to the gunwalls prow piracy snow doubloon furl.\n\nDead men tell no tales jib chase guns gunwalls Gold Road smartly nipperkin topsail bilge water Pirate Round. Gaff gunwalls bilged on her anchor bilge water scourge of the seven seas parley ho sheet chase guns squiffy. Scuppers fathom ho quarter gally heave to yardarm coxswain red ensign pink.';
this.set('longContent', longContent);
await render(hbs`<Note::Content @content="{{this.longContent}}"/>`);
assert
.dom(".note-content-text")
.dom('.note-content-text')
.hasText(
"Grapple keel reef fathom haul wind bilge rat swing the lead belay line pink. Man-of-war mizzenmast killick lookout yo-ho-ho Sail ho gabion careen sutler stern. Draught wherry lookout schooner prow hail-shot ...",
'Grapple keel reef fathom haul wind bilge rat swing the lead belay line pink. Man-of-war mizzenmast killick lookout yo-ho-ho Sail ho gabion careen sutler stern. Draught wherry lookout schooner prow hail-shot ...',
);
assert.dom(".note-content-toggle").hasText("Expand");
assert.dom('.note-content-toggle').hasText('Expand');
await click(".note-content-toggle");
assert.dom(".note-content-toggle").hasText("Collapse");
assert.dom(".note-content-text").hasText(longContent);
await click('.note-content-toggle');
assert.dom('.note-content-toggle').hasText('Collapse');
assert.dom('.note-content-text').hasText(longContent);
});
});

View file

@ -1,18 +1,18 @@
import { module, test } from "qunit";
import { setupRenderingTest } from "frontend-reactive/tests/helpers";
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from 'qunit';
import { setupRenderingTest } from 'frontend-reactive/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module("Integration | Component | note/interactions", function (hooks) {
module('Integration | Component | note/interactions', function (hooks) {
setupRenderingTest(hooks);
test("it renders", async function (assert) {
test('it renders', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });
await render(hbs`<Note::Interactions />`);
assert.dom().hasText("");
assert.dom().hasText('');
// TODO: Add tests
});
});

View file

@ -1,12 +1,12 @@
import { module, test } from "qunit";
import { setupRenderingTest } from "frontend-reactive/tests/helpers";
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from 'qunit';
import { setupRenderingTest } from 'frontend-reactive/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module("Integration | Component | note/user-header", function (hooks) {
module('Integration | Component | note/user-header', function (hooks) {
setupRenderingTest(hooks);
test("it renders", async function (assert) {
test('it renders', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });
@ -14,8 +14,8 @@ module("Integration | Component | note/user-header", function (hooks) {
hbs`<Note::UserHeader @displayname="bob" @handle="@alice@example.com"/>`,
);
assert.dom("p.note-user-displayname").hasText("bob");
assert.dom("p.note-user-handle").hasText("@alice@example.com");
assert.dom('p.note-user-displayname').hasText('bob');
assert.dom('p.note-user-handle').hasText('@alice@example.com');
// TODO: Expand tests to include profile picture
});
});

View file

@ -1,18 +1,18 @@
import { module, test } from "qunit";
import { setupRenderingTest } from "frontend-reactive/tests/helpers";
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from 'qunit';
import { setupRenderingTest } from 'frontend-reactive/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module("Integration | Component | page", function (hooks) {
module('Integration | Component | page', function (hooks) {
setupRenderingTest(hooks);
test("it renders", async function (assert) {
test('it renders', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });
await render(hbs`<Page />`);
assert.dom().hasText("");
assert.dom().hasText('');
// TODO: Add tests
});
});

View file

@ -1,18 +1,18 @@
import { module, test } from "qunit";
import { setupRenderingTest } from "frontend-reactive/tests/helpers";
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from 'qunit';
import { setupRenderingTest } from 'frontend-reactive/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module("Integration | Component | page/header", function (hooks) {
module('Integration | Component | page/header', function (hooks) {
setupRenderingTest(hooks);
test("it renders", async function (assert) {
test('it renders', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });
await render(hbs`<Page::Header />`);
assert.dom().hasText("");
assert.dom().hasText('');
// TODO: Add tests
});
});

View file

@ -1,18 +1,18 @@
import { module, test } from "qunit";
import { setupRenderingTest } from "frontend-reactive/tests/helpers";
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from 'qunit';
import { setupRenderingTest } from 'frontend-reactive/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module("Integration | Component | page/left-sidebar", function (hooks) {
module('Integration | Component | page/left-sidebar', function (hooks) {
setupRenderingTest(hooks);
test("it renders", async function (assert) {
test('it renders', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });
await render(hbs`<Page::LeftSidebar />`);
assert.dom().hasText("");
assert.dom().hasText('');
// TODO: Add tests
});
});

View file

@ -0,0 +1,26 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'frontend-reactive/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | passkey', function (hooks) {
setupRenderingTest(hooks);
test('it renders', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });
await render(hbs`<Passkey />`);
assert.dom().hasText('');
// Template block usage:
await render(hbs`
<Passkey>
template block text
</Passkey>
`);
assert.dom().hasText('template block text');
});
});

View file

@ -1,18 +1,18 @@
import { module, test } from "qunit";
import { setupRenderingTest } from "frontend-reactive/tests/helpers";
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from 'qunit';
import { setupRenderingTest } from 'frontend-reactive/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module("Integration | Component | timeline", function (hooks) {
module('Integration | Component | timeline', function (hooks) {
setupRenderingTest(hooks);
test("it renders", async function (assert) {
test('it renders', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });
await render(hbs`<Timeline />`);
assert.dom().hasText("");
assert.dom().hasText('');
// TODO: Add tests
});
});

View file

@ -1,18 +1,18 @@
import { module, test } from "qunit";
import { setupRenderingTest } from "frontend-reactive/tests/helpers";
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { module, test } from 'qunit';
import { setupRenderingTest } from 'frontend-reactive/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module("Integration | Component | timeline/header", function (hooks) {
module('Integration | Component | timeline/header', function (hooks) {
setupRenderingTest(hooks);
test("it renders", async function (assert) {
test('it renders', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });
await render(hbs`<Timeline::Header />`);
assert.dom().hasText("");
assert.dom().hasText('');
// TODO: Add tests
});
});

View file

@ -1,10 +1,10 @@
import { module, test } from "qunit";
import { setupTest } from "frontend-reactive/tests/helpers";
import { module, test } from 'qunit';
import { setupTest } from 'frontend-reactive/tests/helpers';
module("Unit | Route | notes/:note_id", function (hooks) {
module('Unit | Route | notes/:note_id', function (hooks) {
setupTest(hooks);
test("it exists", function (assert) {
test('it exists', function (assert) {
assert.ok(true);
// const route = this.owner.lookup("route:notes/:note-id");
// assert.ok(route);

View file

@ -0,0 +1,12 @@
import { module, test } from 'qunit';
import { setupTest } from 'frontend-reactive/tests/helpers';
module('Unit | Service | authentication', function (hooks) {
setupTest(hooks);
// TODO: Replace this with your real tests.
test('it exists', function (assert) {
const service = this.owner.lookup('service:authentication');
assert.ok(service);
});
});

View file

@ -2,6 +2,7 @@ document.getElementById("registerButton").addEventListener("click", register);
document.getElementById("loginButton").addEventListener("click", login);
function showMessage(message, isError = false) {
console.log("got message", message);
const messageElement = document.getElementById("message");
messageElement.textContent = message;
messageElement.style.color = isError ? "red" : "green";
@ -52,13 +53,18 @@ async function register() {
},
);
console.log("Registration finish");
const msg = await verificationResponse.json();
console.log("register full response", verificationResponse);
console.log("register body", msg);
if (verificationResponse.ok) {
showMessage(msg, false);
} else {
showMessage(msg, true);
}
} catch (error) {
console.log("Received error", error);
showMessage("Error: " + error.message, true);
}
}
@ -98,13 +104,17 @@ async function login() {
body: JSON.stringify(assertionResponse),
});
console.log("login done");
const msg = await verificationResponse.json();
console.log("login-response", verificationResponse);
console.log("login-body", msg);
if (verificationResponse.ok) {
showMessage(msg, false);
} else {
showMessage(msg, true);
}
} catch (error) {
console.log("received error", error);
showMessage("Error: " + error.message, true);
}
}