new bootstrap and login mechanisms

master
Niko PLP 2 days ago
parent d8de299ddf
commit 8275d9355f
  1. 6
      ng-app/package.json
  2. 95
      ng-app/src/lib/Login.svelte
  3. 394
      ng-app/src/routes/WalletCreate.svelte
  4. 78
      ng-app/src/routes/WalletLogin.svelte
  5. 16
      ng-app/src/store.ts
  6. 2
      ng-broker/Cargo.toml
  7. 37
      ng-broker/src/server_ws.rs
  8. 47
      ng-sdk-js/js/browser.js
  9. 22
      pnpm-lock.yaml

@ -47,6 +47,7 @@
"@milkdown/theme-nord": "7.4.0",
"@milkdown/transformer": "7.2.0",
"@milkdown/utils": "7.4.0",
"@nextgraph-monorepo/ng-sdk-js": "workspace:*",
"@popperjs/core": "^2.11.8",
"@replit/codemirror-lang-svelte": "^6.0.0",
"@sindresorhus/is": "4.6.0",
@ -67,12 +68,12 @@
"immutable-json-patch": "^6.0.1",
"katex": "^0.16.11",
"lodash.debounce": "4.0.8",
"@nextgraph-monorepo/ng-sdk-js": "workspace:*",
"prism-themes": "^1.9.0",
"prosemirror-model": "^1.7.1",
"prosemirror-state": "^1.2.3",
"prosemirror-svelte": "^0.2.4",
"prosemirror-view": "^1.9.10",
"remote-web-streams": "^0.2.0",
"skin-tone": "2.0.0",
"style-mod": "^4.1.2",
"svelte-codemirror-editor": "^1.4.0",
@ -85,8 +86,7 @@
"y-codemirror.next": "^0.3.5",
"y-prosemirror": "^1.2.10",
"y-protocols": "^1.0.1",
"yjs": "^13.6.18",
"remote-web-streams": "^0.2.0"
"yjs": "^13.6.18"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "2.0.0",

@ -32,7 +32,7 @@
} from "svelte-heros-v2";
import PasswordInput from "./components/PasswordInput.svelte";
import Spinner from "./components/Spinner.svelte";
import { display_error, test_bootstrap, NG_BOOTSTRAP_IFRAME_SRC } from "../store";
import { display_error } from "../store";
//import Worker from "../worker.js?worker&inline";
export let wallet;
export let for_import = false;
@ -46,24 +46,6 @@
const dispatch = createEventDispatcher();
async function test_local_storage() {
if (!tauri_platform) {
if ((await ng.get_bowser())=="Safari") return;
await tick();
let iframe: HTMLIFrameElement = <HTMLIFrameElement>window.document.getElementById('nextgraph-bootstrap-iframe');
return new Promise(async (resolve) => {
iframe.addEventListener("load", async function() {
if (!await test_bootstrap()){
trusted = false;
no_local_storage = true;
}
resolve(null);
});
iframe.src=NG_BOOTSTRAP_IFRAME_SRC as string;
});
}
}
onMount(async () => {
loaded = false;
if (for_import) {
@ -79,9 +61,8 @@
} catch (e) {
trusted = false;
no_local_storage = true;
console.log("no access to localStorage")
console.log("no access to localStorage");
}
await test_local_storage();
}
});
@ -285,7 +266,11 @@
}
} catch (e) {
console.error(e);
if (e.message && e.message.includes("constructor") || (typeof e === "string" && e.includes("constructor") )) e = "BrowserTooOld";
if (
(e.message && e.message.includes("constructor")) ||
(typeof e === "string" && e.includes("constructor"))
)
e = "BrowserTooOld";
error = e;
step = "end";
dispatch("error", { error: e });
@ -301,7 +286,10 @@
async function on_pin_key(val) {
pin_code = [...pin_code, val];
if (pin_code.length == 4) {
setTimeout(()=>window.document.getElementById("confirm_pin_btn").focus(),50);
setTimeout(
() => window.document.getElementById("confirm_pin_btn").focus(),
50
);
}
}
@ -372,12 +360,6 @@
}
</script>
{#if NG_BOOTSTRAP_IFRAME_SRC}
<iframe title="bootstrap" id="nextgraph-bootstrap-iframe" scrolling="no" frameborder="0"
style="width:0; height:0; visibility: hidden;"
></iframe>
{/if}
<div
class="flex-col justify-center md:max-w-2xl py-4 sm:px-8"
class:h-screen={step !== "load" && height > 640}
@ -426,29 +408,32 @@
<!-- Save wallet? -->
{#if for_import}
{#if no_local_storage}
<div class="max-w-xl lg:px-8 mx-auto px-4 mb-2">
<Alert color="orange" class="">
Access to local storage is denied. <br/>You won't be able to save your wallet in this browser.<br/>
If you wanted to save it, please allow storing local data<br/> for the websites {location.origin} <br/>
and https://nextgraph.net and then reload the page. <br/> You might need to all third-party cookies too.
</Alert>
</div>
<div class="max-w-xl lg:px-8 mx-auto px-4 mb-2">
<Alert color="orange" class="">
Access to local storage is denied. <br />You won't be able to save
your wallet in this browser.<br />
If you wanted to save it, please allow storing local data<br />
for the websites {location.origin} <br />
and https://nextgraph.net and then reload the page. <br /> You might
need to all third-party cookies too.
</Alert>
</div>
{:else}
<div class="max-w-xl lg:px-8 mx-auto px-4 mb-2">
<span class="text-xl"
>{$t("pages.wallet_create.save_wallet_options.trust")}
</span> <br />
<p class="text-sm">
{$t("pages.wallet_create.save_wallet_options.trust_description")}
{#if !tauri_platform}
{$t("pages.login.trust_device_allow_cookies")}{/if}<br />
</p>
<div class="flex justify-center items-center my-4">
<Toggle class="" bind:checked={trusted}
>{$t("pages.login.trust_device_yes")}</Toggle
>
<div class="max-w-xl lg:px-8 mx-auto px-4 mb-2">
<span class="text-xl"
>{$t("pages.wallet_create.save_wallet_options.trust")}
</span> <br />
<p class="text-sm">
{$t("pages.wallet_create.save_wallet_options.trust_description")}
{#if !tauri_platform}
{$t("pages.login.trust_device_allow_cookies")}{/if}<br />
</p>
<div class="flex justify-center items-center my-4">
<Toggle class="" bind:checked={trusted}
>{$t("pages.login.trust_device_yes")}</Toggle
>
</div>
</div>
</div>
{/if}
{/if}
@ -635,7 +620,10 @@
class:h-[160px]={!mobile}
class:h-[93px]={mobile}
class:text-8xl={!mobile}
on:click={async () => {window.document.activeElement.blur(); await on_pin_key(num)}}
on:click={async () => {
window.document.activeElement.blur();
await on_pin_key(num);
}}
disabled={pin_code.length >= 4}
>
<span>{num}</span>
@ -651,7 +639,10 @@
class:h-[160px]={!mobile}
class:h-[93px]={mobile}
class:text-8xl={!mobile}
on:click={async () => {window.document.activeElement.blur();await on_pin_key(shuffle_pin[9])}}
on:click={async () => {
window.document.activeElement.blur();
await on_pin_key(shuffle_pin[9]);
}}
disabled={pin_code.length >= 4}
>
<span>{shuffle_pin[9]}</span>

@ -45,11 +45,21 @@
} from "../wallet_emojis";
import { onMount, onDestroy, tick } from "svelte";
import { wallets, has_wallets, display_error, register_bootstrap, NG_BOOTSTRAP_IFRAME_SRC, test_bootstrap } from "../store";
import {
wallets,
has_wallets,
display_error,
register_bootstrap,
} from "../store";
import Spinner from "../lib/components/Spinner.svelte";
const param = new URLSearchParams($querystring);
function base64UrlEncode(str) {
const base64 = btoa(str); // Standard Base64 encoding
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}
let tauri_platform = import.meta.env.TAURI_PLATFORM;
let mobile = tauri_platform == "android" || tauri_platform == "ios";
let is_touch_device =
@ -152,29 +162,28 @@
function validate_pin() {
// check for same digit doesnt appear 3 times
if ((pin[0] == pin[1] && pin[0] == pin[2])
|| (pin[0] == pin[1] && pin[0] == pin[3])
|| (pin[0] == pin[2] && pin[0] == pin[3])
|| (pin[1] == pin[2] && pin[1] == pin[3]))
{
return false;
if (
(pin[0] == pin[1] && pin[0] == pin[2]) ||
(pin[0] == pin[1] && pin[0] == pin[3]) ||
(pin[0] == pin[2] && pin[0] == pin[3]) ||
(pin[1] == pin[2] && pin[1] == pin[3])
) {
return false;
}
// check for ascending series
if (pin[1] == pin[0] + 1
&& pin[2] == pin[1] + 1
&& pin[3] == pin[2] + 1)
{
return false;
if (pin[1] == pin[0] + 1 && pin[2] == pin[1] + 1 && pin[3] == pin[2] + 1) {
return false;
}
// check for descending series
if (pin[3] >= 3
&& pin[2] == pin[3] - 1
&& pin[1] == pin[2] - 1
&& pin[0] == pin[1] - 1)
{
return false;
if (
pin[3] >= 3 &&
pin[2] == pin[3] - 1 &&
pin[1] == pin[2] - 1 &&
pin[0] == pin[1] - 1
) {
return false;
}
return true;
}
@ -201,28 +210,17 @@
? "api/v1/"
: "http://localhost:3030/api/v1/";
async function test_local_storage() {
if (!tauri_platform) {
if ((await ng.get_bowser())=="Safari") return;
await tick();
let iframe: HTMLIFrameElement = <HTMLIFrameElement>window.document.getElementById('nextgraph-bootstrap-iframe');
return new Promise(async (resolve) => {
iframe.addEventListener("load", async function() {
if (!await test_bootstrap()){
registration_error = "NoLocalStorage";
}
resolve(null);
});
iframe.src=NG_BOOTSTRAP_IFRAME_SRC as string;
});
}
}
const bootstrap_redirect = import.meta.env.DEV
? "http://localhost:14403/#/?b="
: import.meta.env.NG_DEV
? "http://localhost:1421/bootstrap.html#/?b="
: "https://nextgraph.net/bootstrap/#/?b=";
// to test ngnet
//const bootstrap_redirect = "http://127.0.0.1:3033/bootstrap/#/?b=";
async function bootstrap() {
//console.log(await ng.client_info());
if (!tauri_platform || tauri_platform == "android") {
if (!tauri_platform) {
try {
sessionStorage.getItem("test");
@ -240,7 +238,7 @@
}
}
if (param.get("skipintro") || param.get("rs")) {
if (param.get("skipintro") || param.get("rs") || param.get("ab")) {
// if (!tauri_platform) {
// setTimeout(async ()=>{
// if (!await test_bootstrap()){
@ -248,13 +246,39 @@
// }
// },1);
// }
await test_local_storage();
intro = false;
}
if (param.get("re")) {
registration_error = param.get("re");
}
if (param.get("rs")) {
} else if (
(param.get("rs") || param.get("i")) &&
!tauri_platform &&
!param.get("ab")
) {
registration_success = param.get("rs");
// doing the bootstrap recording at nextgraph.net
let i = param.get("i");
invitation = await ng.decode_invitation(i);
let bootstrap_iframe_msgs = await ng.bootstrap_to_iframe_msgs(
invitation.V0.bootstrap
);
let local_invitation = await ng.get_local_bootstrap(location.href);
if (local_invitation) {
bootstrap_iframe_msgs.push(
...(await ng.bootstrap_to_iframe_msgs(
local_invitation.V0.bootstrap
))
);
}
let encoded = base64UrlEncode(JSON.stringify(bootstrap_iframe_msgs));
window.location.href =
bootstrap_redirect +
encoded +
"&m=add&ab=" +
encodeURIComponent(window.location.href);
return;
} else if (param.get("rs")) {
registration_success = param.get("rs");
invitation = await ng.decode_invitation(param.get("i"));
window.location.replace(window.location.href.split("?")[0]);
@ -294,8 +318,6 @@
}
async function create_wallet() {
await test_local_storage();
intro = false;
// if (invitation && invitation.V0.url) {
// // we redirect to the TOS url of the invitation.
@ -323,12 +345,16 @@
async function do_wallet() {
creating = true;
let bootstrap_iframe_msgs = await ng.bootstrap_to_iframe_msgs(invitation.V0.bootstrap);
// let bootstrap_iframe_msgs = await ng.bootstrap_to_iframe_msgs(
// invitation.V0.bootstrap
// );
let local_invitation = await ng.get_local_bootstrap(location.href);
let additional_bootstrap;
if (local_invitation) {
additional_bootstrap = local_invitation.V0.bootstrap;
bootstrap_iframe_msgs.push(...await ng.bootstrap_to_iframe_msgs(additional_bootstrap));
// bootstrap_iframe_msgs.push(
// ...(await ng.bootstrap_to_iframe_msgs(additional_bootstrap))
// );
}
let core_registration;
if (invitation.V0.code) {
@ -347,18 +373,20 @@
core_registration,
additional_bootstrap,
device_name,
pdf: options.pdf
pdf: options.pdf,
};
//console.log("do wallet with params", params);
try {
ready = await ng.wallet_create(params);
if (!tauri_platform && (await ng.get_bowser())!=="Safari") {
let res = await register_bootstrap(bootstrap_iframe_msgs);
if (res !== true) {
error = "We could not save your bootstrap information at nextgraph.net. This is needed for links and third party webapps to work properly. so we are stopping here. Reason: " + res;
return;
}
}
// if (!tauri_platform) {
// let res = await register_bootstrap(bootstrap_iframe_msgs);
// if (res !== true) {
// error =
// "We could not save your bootstrap information at nextgraph.net. This is needed for links and third party webapps to work properly. so we are stopping here. Reason: " +
// res;
// return;
// }
// }
wallets.set(await ng.get_wallets());
if (!options.trusted && !tauri_platform) {
let lws = $wallets[ready.wallet_name];
@ -627,12 +655,6 @@
</script>
<svelte:window bind:innerWidth={width} bind:innerHeight={height} />
{#if NG_BOOTSTRAP_IFRAME_SRC}
<iframe title="bootstrap" id="nextgraph-bootstrap-iframe" scrolling="no" frameborder="0"
style="width:0; height:0; visibility: hidden;"
>
</iframe>
{/if}
<CenteredLayout>
<div class="max-w-2xl lg:px-8 mx-auto mb-20">
{#if wait}
@ -760,12 +782,24 @@
<span>{@html $t("pages.wallet_create.wallet_about.2")}</span>
</li>
<li class="flex space-x-3">
<LockOpen class="flex-shrink-0 w-5 h-5 text-green-500 dark:text-green-400"></LockOpen>
<span>{@html $t("pages.wallet_create.wallet_about.password")}</span>
<LockOpen
class="flex-shrink-0 w-5 h-5 text-green-500 dark:text-green-400"
></LockOpen>
<span
>{@html $t(
"pages.wallet_create.wallet_about.password"
)}</span
>
</li>
<li class="flex space-x-3">
<FingerPrint class="flex-shrink-0 w-5 h-5 text-green-500 dark:text-green-400"></FingerPrint>
<span>{@html $t("pages.wallet_create.wallet_about.mnemonic")}</span>
<FingerPrint
class="flex-shrink-0 w-5 h-5 text-green-500 dark:text-green-400"
></FingerPrint>
<span
>{@html $t(
"pages.wallet_create.wallet_about.mnemonic"
)}</span
>
</li>
<li class="flex space-x-3">
<!-- Icon -->
@ -784,7 +818,9 @@
d="M14.25 6.087c0-.355.186-.676.401-.959.221-.29.349-.634.349-1.003 0-1.036-1.007-1.875-2.25-1.875s-2.25.84-2.25 1.875c0 .369.128.713.349 1.003.215.283.401.604.401.959v0a.64.64 0 01-.657.643 48.39 48.39 0 01-4.163-.3c.186 1.613.293 3.25.315 4.907a.656.656 0 01-.658.663v0c-.355 0-.676-.186-.959-.401a1.647 1.647 0 00-1.003-.349c-1.036 0-1.875 1.007-1.875 2.25s.84 2.25 1.875 2.25c.369 0 .713-.128 1.003-.349.283-.215.604-.401.959-.401v0c.31 0 .555.26.532.57a48.039 48.039 0 01-.642 5.056c1.518.19 3.058.309 4.616.354a.64.64 0 00.657-.643v0c0-.355-.186-.676-.401-.959a1.647 1.647 0 01-.349-1.003c0-1.035 1.008-1.875 2.25-1.875 1.243 0 2.25.84 2.25 1.875 0 .369-.128.713-.349 1.003-.215.283-.4.604-.4.959v0c0 .333.277.599.61.58a48.1 48.1 0 005.427-.63 48.05 48.05 0 00.582-4.717.532.532 0 00-.533-.57v0c-.355 0-.676.186-.959.401-.29.221-.634.349-1.003.349-1.035 0-1.875-1.007-1.875-2.25s.84-2.25 1.875-2.25c.37 0 .713.128 1.003.349.283.215.604.401.96.401v0a.656.656 0 00.658-.663 48.422 48.422 0 00-.37-5.36c-1.886.342-3.81.574-5.766.689a.578.578 0 01-.61-.58v0z"
/>
</svg>
<span>{@html $t("pages.wallet_create.wallet_about.pazzle")}</span>
<span
>{@html $t("pages.wallet_create.wallet_about.pazzle")}</span
>
</li>
<li class="flex space-x-3">
<!-- Icon -->
@ -883,7 +919,9 @@
<span>{@html $t("pages.wallet_create.wallet_about.8")}</span>
</li>
<li class="flex space-x-3">
<ExclamationTriangle class="flex-shrink-0 w-5 h-5 text-green-500 dark:text-green-400"></ExclamationTriangle>
<ExclamationTriangle
class="flex-shrink-0 w-5 h-5 text-green-500 dark:text-green-400"
></ExclamationTriangle>
<span>{@html $t("pages.wallet_create.wallet_about.9")}</span>
</li>
</ul>
@ -925,9 +963,7 @@
<h2 class="pb-5 text-xl">
{$t("pages.wallet_create.broker_about.title")}<span
class="text-sm"
>&nbsp{@html $t(
"pages.wallet_create.please_read"
)}</span
>&nbsp{@html $t("pages.wallet_create.please_read")}</span
>
</h2>
<ul
@ -1077,7 +1113,11 @@
/>
</svg>
{$t("pages.wallet_create.register_with_broker", {
values: { broker: pre_invitation.V0.name || $t("pages.wallet_create.this_broker") },
values: {
broker:
pre_invitation.V0.name ||
$t("pages.wallet_create.this_broker"),
},
})}
</button>
</div>
@ -1200,100 +1240,117 @@
</button>
</div> -->
{#if import.meta.env.NG_APP_WEB}
<div class="flex space-x-3 px-4 pt-3 lg:px-8 lg:pt-10 max-w-xl text-left text-gray-500 dark:text-gray-400">
<svg class="flex-shrink-0 w-5 h-5 text-green-500 dark:text-green-400" fill="none" stroke-width="1.5" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M21 11.25v8.25a1.5 1.5 0 0 1-1.5 1.5H5.25a1.5 1.5 0 0 1-1.5-1.5v-8.25M12 4.875A2.625 2.625 0 1 0 9.375 7.5H12m0-2.625V7.5m0-2.625A2.625 2.625 0 1 1 14.625 7.5H12m0 0V21m-8.625-9.75h18c.621 0 1.125-.504 1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125h-18c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125Z"></path>
</svg>
<span>
{@html $t("pages.wallet_create.broker_about.8")}
</span>
</div>
<div class="row mt-5">
<a href="/install" use:link>
<button
tabindex="-1"
class="choice-button text-primary-700 bg-primary-100 hover:bg-primary-100/90 focus:ring-4 focus:ring-primary-100/50 font-medium rounded-lg text-lg px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-primary-100/55 mb-2"
<div
class="flex space-x-3 px-4 pt-3 lg:px-8 lg:pt-10 max-w-xl text-left text-gray-500 dark:text-gray-400"
>
<svg
class="flex-shrink-0 w-5 h-5 text-green-500 dark:text-green-400"
fill="none"
stroke-width="1.5"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
>
<svg
fill="none"
stroke="currentColor"
stroke-width="1.5"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
class=" block h-10 w-10"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M10.5 1.5H8.25A2.25 2.25 0 006 3.75v16.5a2.25 2.25 0 002.25 2.25h7.5A2.25 2.25 0 0018 20.25V3.75a2.25 2.25 0 00-2.25-2.25H13.5m-3 0V3h3V1.5m-3 0h3m-3 18.75h3"
/>
</svg>
or
<svg
class="mr-4 ml-2 block h-10 w-10"
stroke="currentColor"
stroke-width="1.5"
viewBox="0 0 64 50"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M21 11.25v8.25a1.5 1.5 0 0 1-1.5 1.5H5.25a1.5 1.5 0 0 1-1.5-1.5v-8.25M12 4.875A2.625 2.625 0 1 0 9.375 7.5H12m0-2.625V7.5m0-2.625A2.625 2.625 0 1 1 14.625 7.5H12m0 0V21m-8.625-9.75h18c.621 0 1.125-.504 1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125h-18c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125Z"
></path>
</svg>
<span>
{@html $t("pages.wallet_create.broker_about.8")}
</span>
</div>
<div class="row mt-5">
<a href="/install" use:link>
<button
tabindex="-1"
class="choice-button text-primary-700 bg-primary-100 hover:bg-primary-100/90 focus:ring-4 focus:ring-primary-100/50 font-medium rounded-lg text-lg px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-primary-100/55 mb-2"
>
<defs />
<g id="Page-1" stroke-width="1" fill="none" fill-rule="evenodd">
<svg
fill="none"
stroke="currentColor"
stroke-width="1.5"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
class=" block h-10 w-10"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M10.5 1.5H8.25A2.25 2.25 0 006 3.75v16.5a2.25 2.25 0 002.25 2.25h7.5A2.25 2.25 0 0018 20.25V3.75a2.25 2.25 0 00-2.25-2.25H13.5m-3 0V3h3V1.5m-3 0h3m-3 18.75h3"
/>
</svg>
or
<svg
class="mr-4 ml-2 block h-10 w-10"
stroke="currentColor"
stroke-width="1.5"
viewBox="0 0 64 50"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<defs />
<g
id="Laptop"
transform="translate(1.000000, 1.000000)"
stroke-width="2"
id="Page-1"
stroke-width="1"
fill="none"
fill-rule="evenodd"
>
<path
d="M56,27 C56,28.1 55.1,29 54,29 L8,29 C6.9,29 6,28.1 6,27 L6,2 C6,0.9 6.9,0 8,0 L54,0 C55.1,0 56,0.9 56,2 L56,26.5 L56,27 L56,27 Z"
id="Shape"
/>
<path
d="M57,31 C57,29.9 56.1,29 55,29 L7,29 C5.9,29 5,29.9 5,31 L0,46 C0,47.1 0.9,48 2,48 L60,48 C61.1,48 62,47.1 62,46 L57,31 L57,31 Z"
id="Shape"
/>
<path d="M2,42.9 L61,42.9" id="Shape" />
<path
d="M52.1,24 C52.1,25.1 51.2,26 50.1,26 L12,26 C10.9,26 10,25.1 10,24 L10,6 C10,4.9 10.9,4 12,4 L50,4 C51.1,4 52,4.9 52,6 L52.1,24 L52.1,24 Z"
id="Shape"
/>
<path d="M22,39 L40,39" id="Shape" />
<path d="M17.2,39 L20,39" id="Shape" />
<path d="M12.1,39 L15,39" id="Shape" />
<path d="M7,39 L10,39" id="Shape" />
<path d="M9.2,35 L12,35" id="Shape" />
<path d="M14,35 L17,35" id="Shape" />
<path d="M19,35 L22,35" id="Shape" />
<path d="M24,35 L27,35" id="Shape" />
<path d="M29,35 L32,35" id="Shape" />
<path d="M34,35 L37,35" id="Shape" />
<path d="M39,35 L42,35" id="Shape" />
<path d="M45,35 L48,35" id="Shape" />
<path d="M50,35 L53,35" id="Shape" />
<path d="M47,32 L50,32" id="Shape" />
<path d="M42,32 L45,32" id="Shape" />
<path d="M37,32 L40,32" id="Shape" />
<path d="M32,32 L35,32" id="Shape" />
<path d="M27,32 L30,32" id="Shape" />
<path d="M22,32 L25,32" id="Shape" />
<path d="M17.1,32 L20,32" id="Shape" />
<path d="M12,32 L15,32" id="Shape" />
<path d="M42,39 L44.8,39" id="Shape" />
<path d="M47,39 L49.9,39" id="Shape" />
<path d="M52,39 L55,39" id="Shape" />
<g
id="Laptop"
transform="translate(1.000000, 1.000000)"
stroke-width="2"
>
<path
d="M56,27 C56,28.1 55.1,29 54,29 L8,29 C6.9,29 6,28.1 6,27 L6,2 C6,0.9 6.9,0 8,0 L54,0 C55.1,0 56,0.9 56,2 L56,26.5 L56,27 L56,27 Z"
id="Shape"
/>
<path
d="M57,31 C57,29.9 56.1,29 55,29 L7,29 C5.9,29 5,29.9 5,31 L0,46 C0,47.1 0.9,48 2,48 L60,48 C61.1,48 62,47.1 62,46 L57,31 L57,31 Z"
id="Shape"
/>
<path d="M2,42.9 L61,42.9" id="Shape" />
<path
d="M52.1,24 C52.1,25.1 51.2,26 50.1,26 L12,26 C10.9,26 10,25.1 10,24 L10,6 C10,4.9 10.9,4 12,4 L50,4 C51.1,4 52,4.9 52,6 L52.1,24 L52.1,24 Z"
id="Shape"
/>
<path d="M22,39 L40,39" id="Shape" />
<path d="M17.2,39 L20,39" id="Shape" />
<path d="M12.1,39 L15,39" id="Shape" />
<path d="M7,39 L10,39" id="Shape" />
<path d="M9.2,35 L12,35" id="Shape" />
<path d="M14,35 L17,35" id="Shape" />
<path d="M19,35 L22,35" id="Shape" />
<path d="M24,35 L27,35" id="Shape" />
<path d="M29,35 L32,35" id="Shape" />
<path d="M34,35 L37,35" id="Shape" />
<path d="M39,35 L42,35" id="Shape" />
<path d="M45,35 L48,35" id="Shape" />
<path d="M50,35 L53,35" id="Shape" />
<path d="M47,32 L50,32" id="Shape" />
<path d="M42,32 L45,32" id="Shape" />
<path d="M37,32 L40,32" id="Shape" />
<path d="M32,32 L35,32" id="Shape" />
<path d="M27,32 L30,32" id="Shape" />
<path d="M22,32 L25,32" id="Shape" />
<path d="M17.1,32 L20,32" id="Shape" />
<path d="M12,32 L15,32" id="Shape" />
<path d="M42,39 L44.8,39" id="Shape" />
<path d="M47,39 L49.9,39" id="Shape" />
<path d="M52,39 L55,39" id="Shape" />
</g>
</g>
</g>
</svg>
{$t("pages.wallet_create.install_app")}
</button>
</a>
</div>
</svg>
{$t("pages.wallet_create.install_app")}
</button>
</a>
</div>
{/if}
<!-- <div class="row mt-5 mb-12">
<button
@ -1519,7 +1576,7 @@
)}
</li>
</ul>
<input
bind:this={phrase}
class="mt-10 mr-0"
@ -1559,9 +1616,7 @@
{/if}
{#if security_phrase_error}
<Alert color="red" class="mt-5">
{@html $t(
"pages.wallet_create.security_phrase_invalid"
)}
{@html $t("pages.wallet_create.security_phrase_invalid")}
</Alert>
{/if}
<Dropzone
@ -1644,7 +1699,11 @@
{#if !tauri_platform}{@html $t(
"pages.login.trust_device_allow_cookies"
)}{/if}<br /><br />
<Toggle bind:checked={options.trusted} on:change={()=> {if (!options.trusted) options.pdf=false;}}
<Toggle
bind:checked={options.trusted}
on:change={() => {
if (!options.trusted) options.pdf = false;
}}
>{@html $t(
"pages.wallet_create.save_wallet_options.trust_toggle"
)}</Toggle
@ -1845,14 +1904,9 @@
})}
{/if}
{#if pdf_link}
{@html $t(
"pages.wallet_create.download_pdf_description"
)}<br />
<a
href={pdf_link}
target="_blank"
download={pdf_name}
>
{@html $t("pages.wallet_create.download_pdf_description")}<br
/>
<a href={pdf_link} target="_blank" download={pdf_name}>
<button
tabindex="-1"
class:animate-bounce={animatePdf}

@ -36,10 +36,14 @@
wallet_from_import,
redirect_after_login,
redirect_if_wallet_is,
NG_BOOTSTRAP_IFRAME_SRC,
register_bootstrap
register_bootstrap,
} from "../store";
import { CheckBadge, ExclamationTriangle, QrCode, Cloud } from "svelte-heros-v2";
import {
CheckBadge,
ExclamationTriangle,
QrCode,
Cloud,
} from "svelte-heros-v2";
let tauri_platform = import.meta.env.TAURI_PLATFORM;
@ -108,21 +112,23 @@
wallet = $wallet_from_import;
importing = true;
}
});
async function loggedin() {
step = "loggedin";
if ($redirect_after_login) {
if (!$redirect_if_wallet_is || $redirect_if_wallet_is == $active_wallet?.id) {
let redir=$redirect_after_login;
$redirect_after_login=undefined;
$redirect_if_wallet_is=undefined;
push("#"+redir);
if (
!$redirect_if_wallet_is ||
$redirect_if_wallet_is == $active_wallet?.id
) {
let redir = $redirect_after_login;
$redirect_after_login = undefined;
$redirect_if_wallet_is = undefined;
push("#" + redir);
} else {
$redirect_after_login=undefined;
$redirect_if_wallet_is=undefined;
$redirect_after_login = undefined;
$redirect_if_wallet_is = undefined;
push("#/");
}
} else {
@ -150,17 +156,24 @@
try {
if (importing) {
step = "loggedin";
$redirect_after_login=undefined;
$redirect_if_wallet_is=undefined;
$redirect_after_login = undefined;
$redirect_if_wallet_is = undefined;
let in_memory = !event.detail.trusted;
//console.log("IMPORTING", in_memory, event.detail.wallet, wallet);
if (!in_memory && !tauri_platform && (await ng.get_bowser())!=="Safari") {
let bootstrap_iframe_msgs = await ng.get_bootstrap_iframe_msgs_for_brokers(event.detail.wallet.V0.brokers);
let res = await register_bootstrap(bootstrap_iframe_msgs);
if (res !== true) {
throw new Error("We could not save your bootstrap information at nextgraph.net. This is needed for links and third-party webapps to work properly. so we are stopping here. Reason: " + res);
}
}
// TODO : register bootstrap when importing
// if (!in_memory && !tauri_platform) {
// let bootstrap_iframe_msgs =
// await ng.get_bootstrap_iframe_msgs_for_brokers(
// event.detail.wallet.V0.brokers
// );
// let res = await register_bootstrap(bootstrap_iframe_msgs);
// if (res !== true) {
// throw new Error(
// "We could not save your bootstrap information at nextgraph.net. This is needed for links and third-party webapps to work properly. so we are stopping here. Reason: " +
// res
// );
// }
// }
let client = await ng.wallet_import(
wallet,
event.detail.wallet,
@ -197,11 +210,13 @@
event.detail.wallet.V0.client = client;
}
} catch (e) {
if (importing) {wallet = undefined;}
importing = false;
error = e;
step = "open";
return;
if (importing) {
wallet = undefined;
}
importing = false;
error = e;
step = "open";
return;
}
//await tick();
active_wallet.set(event.detail);
@ -244,11 +259,6 @@
onMount(() => scrollToTop());
</script>
{#if NG_BOOTSTRAP_IFRAME_SRC}
<iframe title="bootstrap" id="nextgraph-bootstrap-iframe" scrolling="no" frameborder="0"
style="width:0; height:0; visibility: hidden;"
></iframe>
{/if}
<div bind:this={top}>
<CenteredLayout displayFooter={!wallet && !selected}>
{#if error}
@ -332,7 +342,7 @@
<div>
<button
class="mt-1 text-white bg-primary-700 hover:bg-primary-700/90 focus:ring-4 focus:ring-primary-100/50 font-medium rounded-lg text-lg px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-primary-700/55 mb-2"
class="mt-1 text-white bg-primary-700 hover:bg-primary-700/90 focus:ring-4 focus:ring-primary-100/50 font-medium rounded-lg text-lg px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-primary-700/55 mb-2"
on:click={start_login_from_import}
>
{$t("buttons.login")}
@ -383,7 +393,7 @@
tabindex="-1"
class="mt-2.5 text-primary-700 bg-primary-100 hover:bg-primary-100/90 focus:ring-4 focus:ring-primary-700/50 font-medium rounded-lg text-lg px-5 py-1.5 text-center inline-flex items-center justify-center dark:focus:ring-primary-100/55 mb-2"
>
<Cloud class="w-8 h-8 mr-2 -ml-1" tabindex="-1"/>
<Cloud class="w-8 h-8 mr-2 -ml-1" tabindex="-1" />
{$t("pages.wallet_login.with_username")}
</button>
</a>
@ -422,7 +432,7 @@
tabindex="-1"
class="mt-1 text-primary-700 bg-primary-100 hover:bg-primary-100/90 focus:ring-4 focus:ring-primary-700/50 font-medium rounded-lg text-lg px-5 py-1.5 text-center inline-flex items-center justify-center dark:focus:ring-primary-100/55 mb-2"
>
<QrCode class="w-8 h-8 mr-2 -ml-1" tabindex="-1"/>
<QrCode class="w-8 h-8 mr-2 -ml-1" tabindex="-1" />
{$t("pages.wallet_login.import_qr")}
</button>
</a>

@ -39,21 +39,9 @@ export const register_bootstrap = async function (bootstrap_iframe_msgs) {
return ret.value.error
}
export const test_bootstrap = async function () {
let iframe = (<HTMLIFrameElement>window.document.getElementById('nextgraph-bootstrap-iframe'))?.contentWindow;
if (!iframe) return false;
const { readable, writablePort } = new RemoteReadableStream();
iframe.postMessage({method:"test", port:writablePort}, NG_BOOTSTRAP_IFRAME_ORIGIN, [writablePort]);
const reader = readable.getReader();
let ret = await reader.read();
await reader.read(); // the close
if (ret.value.status=="ok") return true;
else return false;
}
export const NG_BOOTSTRAP_IFRAME_SRC = import.meta.env.TAURI_PLATFORM ? false : import.meta.env.PROD
? "https://nextgraph.net/bootstrap/?o=" + encodeURIComponent(location.origin)
: "/bootstrap.html?o=" + encodeURIComponent(location.origin);
? "https://nextgraph.net/bootstrap/#/?o=" + encodeURIComponent(location.origin)
: "/bootstrap.html#/?o=" + encodeURIComponent(location.origin);
export const NG_BOOTSTRAP_IFRAME_ORIGIN = import.meta.env.TAURI_PLATFORM ? "" : import.meta.env.PROD
? "https://nextgraph.net"

@ -23,7 +23,7 @@ once_cell = "1.17.1"
either = { version = "1.8.1", features=["serde"] }
async-std = { version = "1.12.0", features = ["attributes"] }
async-trait = "0.1.64"
rust-embed= { version = "6.7.0", features=["include-exclude"] }
rust-embed= { version = "6.7.0", features=["include-exclude", "debug-embed"] }
urlencoding = "2.1.3"
blake3 = "1.3.1"
ng-async-tungstenite = { version = "0.22.2", git = "https://git.nextgraph.org/NextGraph/async-tungstenite.git", branch = "nextgraph", features = ["async-std-runtime"] }

@ -282,15 +282,13 @@ fn upgrade_ws_or_serve_app(
if query.starts_with("o=") {
match decode(&query.chars().skip(2).collect::<String>()) {
Err(_) => return Err(make_error(StatusCode::BAD_REQUEST)),
Ok(cow) => {
cow.into_owned()
}
Ok(cow) => cow.into_owned(),
}
} else {
return Err(make_error(StatusCode::BAD_REQUEST))
return Err(make_error(StatusCode::BAD_REQUEST));
}
},
None => {return Err(make_error(StatusCode::BAD_REQUEST))}
}
None => return Err(make_error(StatusCode::BAD_REQUEST)),
};
let sha_file = AppAuth::get("index.sha256").unwrap();
let sha = format!(
@ -303,15 +301,22 @@ fn upgrade_ws_or_serve_app(
.status(StatusCode::NOT_MODIFIED)
.header("Cache-Control", "max-age=31536000, must-revalidate")
.header("ETag", sha)
.header("Content-Security-Policy", format!("frame-ancestors 'self' https://nextgraph.net {webapp_origin};"))
.header(
"Content-Security-Policy",
format!("frame-ancestors 'self' https://nextgraph.net {webapp_origin};"),
)
.header("X-Frame-Options", format!("ALLOW-FROM {webapp_origin}"))
.body(None)
.unwrap();
return Err(res);
}
let file = AppAuth::get("index.gzip").unwrap();
let res = Response::builder().status(StatusCode::OK)
.header("Content-Security-Policy", format!("frame-ancestors 'self' https://nextgraph.net {webapp_origin};"))
let res = Response::builder()
.status(StatusCode::OK)
.header(
"Content-Security-Policy",
format!("frame-ancestors 'self' https://nextgraph.net {webapp_origin};"),
)
.header("X-Frame-Options", format!("ALLOW-FROM {webapp_origin}"))
.header("Content-Type", "text/html")
.header("Cache-Control", "max-age=31536000, must-revalidate")
@ -438,7 +443,7 @@ impl Callback for SecurityCallback {
uri,
last_etag,
None,
referer
referer,
);
}
InterfaceType::Loopback => {
@ -474,7 +479,7 @@ impl Callback for SecurityCallback {
Some(val)
}
}),
referer
referer,
);
} else if listener.config.accept_forward_for.is_private_domain() {
let (hosts_str, urls_str) =
@ -490,7 +495,7 @@ impl Callback for SecurityCallback {
uri,
last_etag,
origin.map(|or| or.to_str().unwrap()),
referer
referer,
);
} else if listener.config.accept_forward_for == AcceptForwardForV0::No {
check_host(host, local_hosts)?;
@ -505,7 +510,7 @@ impl Callback for SecurityCallback {
uri,
last_etag,
origin.map(|or| or.to_str().unwrap()),
referer
referer,
);
}
}
@ -548,7 +553,7 @@ impl Callback for SecurityCallback {
uri,
last_etag,
origin.map(|or| or.to_str().unwrap()),
referer
referer,
);
} else if listener.config.accept_forward_for.is_public_domain() {
if !remote.is_private() {
@ -588,7 +593,7 @@ impl Callback for SecurityCallback {
Some(val)
}
}),
referer
referer,
);
} else if listener.config.accept_forward_for == AcceptForwardForV0::No {
if !remote.is_private() {
@ -609,7 +614,7 @@ impl Callback for SecurityCallback {
uri,
last_etag,
origin.map(|or| or.to_str().unwrap()),
referer
referer,
);
}
}

@ -7,39 +7,6 @@
// notice may not be copied, modified, or distributed except
// according to those terms.
let ls;
let ss;
let no_local_storage; false;
(async () => {
try {
ls = localStorage;
ss = sessionStorage;
try {
let ret = await document.requestStorageAccess({ localStorage: true, sessionStorage: true });
ls = ret.localStorage;
ss = ret.sessionStorage;
console.log("REQUEST STORAGE ACCESS GRANTED by chrome");
}
catch(e) {
console.warn("requestStorageAccess of chrome failed. falling back to previous api", e)
try {
await document.requestStorageAccess();
localStorage;
console.log("REQUEST STORAGE ACCESS GRANTED");
} catch (e) {
console.error("REQUEST STORAGE ACCESS DENIED",e);
no_local_storage = true;
}
}
} catch (e) {
no_local_storage = true;
console.log("no access to localStorage")
}
})();
export function client_details() {
return window.navigator.userAgent;
}
@ -56,7 +23,7 @@ export function client_details2(obj,version) {
export function session_save(key,value) {
try {
ss.setItem(key, value);
sessionStorage.setItem(key, value);
} catch(e) {
console.error(e);
@ -85,7 +52,7 @@ function convert_error(e) {
export function session_get(key) {
try {
return ss.getItem(key);
return sessionStorage.getItem(key);
} catch(e) {
console.error(e);
@ -96,7 +63,7 @@ export function session_get(key) {
export function session_remove(key) {
try {
return ss.removeItem(key);
return sessionStorage.removeItem(key);
} catch(e) {
console.error(e);
@ -106,7 +73,7 @@ export function session_remove(key) {
export function local_save(key,value) {
try {
ls.setItem(key, value);
localStorage.setItem(key, value);
} catch(e) {
console.error(e);
@ -116,8 +83,8 @@ export function local_save(key,value) {
export function storage_clear() {
try {
ls.clear();
ss.clear();
localStorage.clear();
sessionStorage.clear();
} catch(e) {
console.error(e);
@ -127,7 +94,7 @@ export function storage_clear() {
export function local_get(key) {
try {
return ls.getItem(key);
return localStorage.getItem(key);
} catch(e) {
console.error(e);

@ -703,7 +703,7 @@ importers:
version: 3.3.0
vite-plugin-top-level-await:
specifier: 1.3.1
version: 1.3.1(rollup@3.29.5)(vite@4.2.1(@types/node@18.19.76)(sass@1.85.0))
version: 1.3.1(rollup@4.39.0)(vite@4.2.1(@types/node@18.19.76)(sass@1.85.0))
xml-beautifier:
specifier: ^0.5.0
version: 0.5.0
@ -800,7 +800,7 @@ importers:
version: 4.2.1(@types/node@18.19.76)(sass@1.85.0)
vite-plugin-singlefile:
specifier: 0.13.5
version: 0.13.5(rollup@3.29.5)(vite@4.2.1(@types/node@18.19.76)(sass@1.85.0))
version: 0.13.5(rollup@4.39.0)(vite@4.2.1(@types/node@18.19.76)(sass@1.85.0))
vite-plugin-svelte-svg:
specifier: 2.2.1
version: 2.2.1(svelte@3.59.2)(vite@4.2.1(@types/node@18.19.76)(sass@1.85.0))
@ -7002,10 +7002,6 @@ snapshots:
'@lezer/javascript': 1.4.21
'@lezer/lr': 1.4.2
'@rollup/plugin-virtual@3.0.2(rollup@3.29.5)':
optionalDependencies:
rollup: 3.29.5
'@rollup/plugin-virtual@3.0.2(rollup@4.39.0)':
optionalDependencies:
rollup: 4.39.0
@ -10371,10 +10367,10 @@ snapshots:
- rollup
- supports-color
vite-plugin-singlefile@0.13.5(rollup@3.29.5)(vite@4.2.1(@types/node@18.19.76)(sass@1.85.0)):
vite-plugin-singlefile@0.13.5(rollup@4.39.0)(vite@4.2.1(@types/node@18.19.76)(sass@1.85.0)):
dependencies:
micromatch: 4.0.8
rollup: 3.29.5
rollup: 4.39.0
vite: 4.2.1(@types/node@18.19.76)(sass@1.85.0)
vite-plugin-singlefile@0.13.5(rollup@4.39.0)(vite@4.5.9(@types/node@18.19.76)(sass@1.85.0)):
@ -10395,16 +10391,6 @@ snapshots:
svgo: 3.3.2
vite: 4.5.9(@types/node@18.19.76)(sass@1.85.0)
vite-plugin-top-level-await@1.3.1(rollup@3.29.5)(vite@4.2.1(@types/node@18.19.76)(sass@1.85.0)):
dependencies:
'@rollup/plugin-virtual': 3.0.2(rollup@3.29.5)
'@swc/core': 1.6.13
uuid: 9.0.1
vite: 4.2.1(@types/node@18.19.76)(sass@1.85.0)
transitivePeerDependencies:
- '@swc/helpers'
- rollup
vite-plugin-top-level-await@1.3.1(rollup@4.39.0)(vite@4.2.1(@types/node@18.19.76)(sass@1.85.0)):
dependencies:
'@rollup/plugin-virtual': 3.0.2(rollup@4.39.0)

Loading…
Cancel
Save