From 5be80b908e4dd50e0d3c8ad5a1dd4774bf60f83c Mon Sep 17 00:00:00 2001 From: Samer Date: Tue, 17 Oct 2023 20:58:32 +0200 Subject: [PATCH] Feat: authenticated calls in Candid UI (#475) * initial setup * feat: II login * test: add allowed principal setter and getter in target canister * fix: deactivate idle timeout Co-authored-by: Ryan Vandersmith * add: domain form * change default identity provider * comments and cleanup * fix: remove target test canister from dfx.json * remove target_test_canister --------- Co-authored-by: Ryan Vandersmith Co-authored-by: Yan Chen <48968912+chenyan-dfinity@users.noreply.github.com> --- tools/ui/Cargo.lock | 2 +- tools/ui/package-lock.json | 270 ++++++++++++++++++++++++-- tools/ui/package.json | 2 + tools/ui/src/auth/auth.ts | 155 +++++++++++++++ tools/ui/src/auth/icons.ts | 21 ++ tools/ui/src/auth/identityProvider.ts | 1 + tools/ui/src/candid.css | 6 +- tools/ui/src/candid.html | 5 +- tools/ui/src/candid.ts | 16 ++ tools/ui/src/index.ts | 11 +- 10 files changed, 473 insertions(+), 16 deletions(-) create mode 100644 tools/ui/src/auth/auth.ts create mode 100644 tools/ui/src/auth/icons.ts create mode 100644 tools/ui/src/auth/identityProvider.ts diff --git a/tools/ui/Cargo.lock b/tools/ui/Cargo.lock index 411743aa..7e687c39 100644 --- a/tools/ui/Cargo.lock +++ b/tools/ui/Cargo.lock @@ -111,7 +111,7 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "candid" -version = "0.9.8" +version = "0.9.9" dependencies = [ "anyhow", "binread", diff --git a/tools/ui/package-lock.json b/tools/ui/package-lock.json index acc77dce..b3412d41 100644 --- a/tools/ui/package-lock.json +++ b/tools/ui/package-lock.json @@ -9,7 +9,9 @@ "version": "0.1.0", "devDependencies": { "@dfinity/agent": "0.19.2", + "@dfinity/auth-client": "0.19.2", "@dfinity/candid": "0.19.2", + "@dfinity/identity": "0.19.2", "@dfinity/principal": "0.19.2", "buffer": "6.0.3", "copy-webpack-plugin": "^9.0.1", @@ -40,6 +42,20 @@ "@dfinity/principal": "^0.19.2" } }, + "node_modules/@dfinity/auth-client": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@dfinity/auth-client/-/auth-client-0.19.2.tgz", + "integrity": "sha512-aQQ60Y6fuV8849ZzXDwSfJlHO5mWEnzscYVEqveCSDTbRCMw0RV/PKGmbNuM2mIes3ep+LWpq3IQRR56lYZWUA==", + "dev": true, + "dependencies": { + "idb": "^7.0.2" + }, + "peerDependencies": { + "@dfinity/agent": "^0.19.2", + "@dfinity/identity": "^0.19.2", + "@dfinity/principal": "^0.19.2" + } + }, "node_modules/@dfinity/candid": { "version": "0.19.2", "resolved": "https://registry.npmjs.org/@dfinity/candid/-/candid-0.19.2.tgz", @@ -49,6 +65,22 @@ "@dfinity/principal": "^0.19.2" } }, + "node_modules/@dfinity/identity": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@dfinity/identity/-/identity-0.19.2.tgz", + "integrity": "sha512-0EwZd8lVfXzHLl5flRysRbjV181b2Xh9loV7QUrt5fE+lP5hgF4f+odFB1YajHQaSyCY1t+v7DA6R9+ICZK9AQ==", + "dev": true, + "dependencies": { + "@noble/hashes": "^1.3.1", + "borc": "^2.1.1", + "tweetnacl": "^1.0.1" + }, + "peerDependencies": { + "@dfinity/agent": "^0.19.2", + "@dfinity/principal": "^0.19.2", + "@peculiar/webcrypto": "^1.4.0" + } + }, "node_modules/@dfinity/principal": { "version": "0.19.2", "resolved": "https://registry.npmjs.org/@dfinity/principal/-/principal-0.19.2.tgz", @@ -145,6 +177,48 @@ "node": ">= 8" } }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.6.tgz", + "integrity": "sha512-izNRxPoaeJeg/AyH8hER6s+H7p4itk+03QCa4sbxI3lNdseQYCuxzgsuNK8bTXChtLTjpJz6NmXKA73qLa3rCA==", + "dev": true, + "peer": true, + "dependencies": { + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "dev": true, + "peer": true, + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@peculiar/webcrypto": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.3.tgz", + "integrity": "sha512-VtaY4spKTdN5LjJ04im/d/joXuvLbQdgy5Z4DXF4MFZhQ+MTrejbNMkfZBp1Bs3O5+bFqnJgyGdPuZQflvIa5A==", + "dev": true, + "peer": true, + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.2", + "tslib": "^2.5.0", + "webcrypto-core": "^1.7.7" + }, + "engines": { + "node": ">=10.12.0" + } + }, "node_modules/@types/eslint": { "version": "8.21.2", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.2.tgz", @@ -435,6 +509,21 @@ "node": ">=8" } }, + "node_modules/asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "dev": true, + "peer": true, + "dependencies": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/base64-arraybuffer": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz", @@ -1321,6 +1410,12 @@ "postcss": "^8.1.0" } }, + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", + "dev": true + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -1850,9 +1945,9 @@ } }, "node_modules/postcss": { - "version": "8.4.24", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", - "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "dev": true, "funding": [ { @@ -1974,6 +2069,26 @@ "node": ">=6" } }, + "node_modules/pvtsutils": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.5.tgz", + "integrity": "sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==", + "dev": true, + "peer": true, + "dependencies": { + "tslib": "^2.6.1" + } + }, + "node_modules/pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -2524,9 +2639,15 @@ } }, "node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", "dev": true }, "node_modules/typescript": { @@ -2582,6 +2703,20 @@ "node": ">=10.13.0" } }, + "node_modules/webcrypto-core": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.7.tgz", + "integrity": "sha512-7FjigXNsBfopEj+5DV2nhNpfic2vumtjjgPmeDKk45z+MJwXKKfhPB7118Pfzrmh4jqOMST6Ch37iPAHoImg5g==", + "dev": true, + "peer": true, + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/json-schema": "^1.1.12", + "asn1js": "^3.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, "node_modules/webpack": { "version": "5.76.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", @@ -2797,6 +2932,15 @@ "simple-cbor": "^0.4.1" } }, + "@dfinity/auth-client": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@dfinity/auth-client/-/auth-client-0.19.2.tgz", + "integrity": "sha512-aQQ60Y6fuV8849ZzXDwSfJlHO5mWEnzscYVEqveCSDTbRCMw0RV/PKGmbNuM2mIes3ep+LWpq3IQRR56lYZWUA==", + "dev": true, + "requires": { + "idb": "^7.0.2" + } + }, "@dfinity/candid": { "version": "0.19.2", "resolved": "https://registry.npmjs.org/@dfinity/candid/-/candid-0.19.2.tgz", @@ -2804,6 +2948,17 @@ "dev": true, "requires": {} }, + "@dfinity/identity": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@dfinity/identity/-/identity-0.19.2.tgz", + "integrity": "sha512-0EwZd8lVfXzHLl5flRysRbjV181b2Xh9loV7QUrt5fE+lP5hgF4f+odFB1YajHQaSyCY1t+v7DA6R9+ICZK9AQ==", + "dev": true, + "requires": { + "@noble/hashes": "^1.3.1", + "borc": "^2.1.1", + "tweetnacl": "^1.0.1" + } + }, "@dfinity/principal": { "version": "0.19.2", "resolved": "https://registry.npmjs.org/@dfinity/principal/-/principal-0.19.2.tgz", @@ -2879,6 +3034,42 @@ "fastq": "^1.6.0" } }, + "@peculiar/asn1-schema": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.6.tgz", + "integrity": "sha512-izNRxPoaeJeg/AyH8hER6s+H7p4itk+03QCa4sbxI3lNdseQYCuxzgsuNK8bTXChtLTjpJz6NmXKA73qLa3rCA==", + "dev": true, + "peer": true, + "requires": { + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "dev": true, + "peer": true, + "requires": { + "tslib": "^2.0.0" + } + }, + "@peculiar/webcrypto": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.3.tgz", + "integrity": "sha512-VtaY4spKTdN5LjJ04im/d/joXuvLbQdgy5Z4DXF4MFZhQ+MTrejbNMkfZBp1Bs3O5+bFqnJgyGdPuZQflvIa5A==", + "dev": true, + "peer": true, + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.2", + "tslib": "^2.5.0", + "webcrypto-core": "^1.7.7" + } + }, "@types/eslint": { "version": "8.21.2", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.2.tgz", @@ -3140,6 +3331,18 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, + "asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "dev": true, + "peer": true, + "requires": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + } + }, "base64-arraybuffer": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz", @@ -3773,6 +3976,12 @@ "dev": true, "requires": {} }, + "idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", + "dev": true + }, "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -4158,9 +4367,9 @@ } }, "postcss": { - "version": "8.4.24", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", - "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "dev": true, "requires": { "nanoid": "^3.3.6", @@ -4236,6 +4445,23 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, + "pvtsutils": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.5.tgz", + "integrity": "sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==", + "dev": true, + "peer": true, + "requires": { + "tslib": "^2.6.1" + } + }, + "pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", + "dev": true, + "peer": true + }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -4604,9 +4830,15 @@ } }, "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", "dev": true }, "typescript": { @@ -4652,6 +4884,20 @@ "graceful-fs": "^4.1.2" } }, + "webcrypto-core": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.7.tgz", + "integrity": "sha512-7FjigXNsBfopEj+5DV2nhNpfic2vumtjjgPmeDKk45z+MJwXKKfhPB7118Pfzrmh4jqOMST6Ch37iPAHoImg5g==", + "dev": true, + "peer": true, + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/json-schema": "^1.1.12", + "asn1js": "^3.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, "webpack": { "version": "5.76.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", diff --git a/tools/ui/package.json b/tools/ui/package.json index 43dcc4be..3c86ce2b 100644 --- a/tools/ui/package.json +++ b/tools/ui/package.json @@ -9,6 +9,8 @@ "devDependencies": { "@dfinity/agent": "0.19.2", "@dfinity/candid": "0.19.2", + "@dfinity/auth-client": "0.19.2", + "@dfinity/identity": "0.19.2", "@dfinity/principal": "0.19.2", "buffer": "6.0.3", "copy-webpack-plugin": "^9.0.1", diff --git a/tools/ui/src/auth/auth.ts b/tools/ui/src/auth/auth.ts new file mode 100644 index 00000000..d6bdfe09 --- /dev/null +++ b/tools/ui/src/auth/auth.ts @@ -0,0 +1,155 @@ +import { Principal } from "@dfinity/principal" +import { authClient } from "../candid" +import { refresh_actor } from "../index" +import { dfinity_logo, copy_icon } from "./icons" +import { identityProvider } from "./identityProvider" + +export async function renderAuth() { + ;(await authClient?.isAuthenticated()) ? insertLogout() : insertLoginForm() +} + +type DerivationOriginOptions = { + canisterId: Principal + domain: string + raw: boolean +} + +function insertLoginForm() { + const params = new URLSearchParams(window.location.search) + const cid = params.get("id") + if (!cid) { + throw new Error("No canister ID available for authentication") + } else { + const auth = document.getElementById("authentication") + + const buttonLogin = document.createElement("button") + buttonLogin.className = "btn" + buttonLogin.style.margin = "10px" + buttonLogin.innerHTML = `${dfinity_logo} Login with Internet Identity` + + const canisterId = Principal.fromText(cid) + + buttonLogin.addEventListener("click", async () => { + const options: DerivationOriginOptions = { + canisterId, + domain: (document.getElementById("domain") as HTMLInputElement).checked + ? "icp0.io" + : "ic0.app", + raw: (document.getElementById("raw") as HTMLInputElement).checked, + } + await login(options) + }) + + const { raw, raw_label, domain, domain_label } = domainForm() + + auth!.innerHTML = "" + auth!.appendChild(raw) + auth!.appendChild(raw_label) + auth!.appendChild(domain) + auth!.appendChild(domain_label) + auth!.appendChild(buttonLogin) + } +} + +function domainForm() { + const raw = document.createElement("input") + raw.id = "raw" + raw.type = "checkbox" + raw.checked = true + + const raw_label = document.createElement("label") + raw_label.innerText = "raw" + raw_label.style.marginRight = "10px" + + const domain = document.createElement("input") + domain.id = "domain" + domain.type = "checkbox" + domain.checked = true + + const domain_label = document.createElement("label") + domain_label.innerText = "icp0.io" + + return { raw, raw_label, domain, domain_label } +} + +function insertLogout() { + const auth = document.getElementById("authentication") + auth!.innerHTML = "" + + CopyId() + LogoutButton() +} + +function LogoutButton() { + const auth = document.getElementById("authentication") + + const buttonLogout = document.createElement("button") + buttonLogout.className = "btn random" + buttonLogout.style.margin = "10px" + buttonLogout.innerText = "Logout" + + buttonLogout.addEventListener("click", async () => { + await logout() + }) + + auth!.appendChild(buttonLogout) +} + +function CopyId() { + if (!authClient) { + return + } + + const auth = document.getElementById("authentication") + + const copyText = document.createElement("span") + + const id = authClient.getIdentity().getPrincipal().toString() + const idShort = id.slice(0, 5) + "..." + id.slice(-5) + copyText.innerText = idShort + + const copyButton = document.createElement("button") + copyButton.id = "copyButton" + copyButton.style.cursor = "pointer" + copyButton.innerHTML = `${copy_icon}` + + copyButton.addEventListener("click", function () { + navigator.clipboard.writeText(id).catch((err) => { + console.error(err) + }) + copyText.innerText = "Copied!" + setTimeout(() => { + copyText.innerText = idShort + }, 2000) + }) + + auth?.appendChild(copyButton) + auth?.appendChild(copyText) +} + +async function login(options: DerivationOriginOptions) { + authClient?.login({ + identityProvider, + derivationOrigin: derivationOrigin(options), + onSuccess: async () => { + refresh_actor(options.canisterId) + insertLogout() + }, + onError: (err) => console.error(err), + }) +} + +async function logout() { + authClient?.logout() + window.location.reload() +} + +function derivationOrigin(options: DerivationOriginOptions): string { + if (options.domain !== "icp0.io" && options.domain !== "ic0.app") { + throw new Error("Invalid domain") + } + + return options.raw + ? "https://" + options.canisterId.toString() + ".raw." + options.domain + : "https://" + options.canisterId.toString() + "." + options.domain +} diff --git a/tools/ui/src/auth/icons.ts b/tools/ui/src/auth/icons.ts new file mode 100644 index 00000000..a40efc70 --- /dev/null +++ b/tools/ui/src/auth/icons.ts @@ -0,0 +1,21 @@ +export const dfinity_logo = ` + + + + + + + + + + + + + +` + +export const copy_icon = ` + + + +` diff --git a/tools/ui/src/auth/identityProvider.ts b/tools/ui/src/auth/identityProvider.ts new file mode 100644 index 00000000..1cc090aa --- /dev/null +++ b/tools/ui/src/auth/identityProvider.ts @@ -0,0 +1 @@ +export const identityProvider = "https://identity.internetcomputer.org" diff --git a/tools/ui/src/candid.css b/tools/ui/src/candid.css index 4aac24eb..a4c62720 100644 --- a/tools/ui/src/candid.css +++ b/tools/ui/src/candid.css @@ -47,9 +47,12 @@ width: 100%; text-align: center; font-size: var(--font-md); - line-height: var(--header-height); color: var(--darkest); border-bottom: 1px solid var(--dark); + + display: flex; + justify-content: space-between; + align-items: center; } #title-card { @@ -184,6 +187,7 @@ input[type='checkbox'] ~ .popup-form { border: none; text-transform: uppercase; flex: 1; + cursor: pointer; } .btn:not(:last-child) { margin-right: var(--pad-md); diff --git a/tools/ui/src/candid.html b/tools/ui/src/candid.html index 451c9514..7161ecbb 100644 --- a/tools/ui/src/candid.html +++ b/tools/ui/src/candid.html @@ -16,7 +16,10 @@ Loading Candid UI...