fix broker choice when creating wallet on public BSP

pull/19/head
Niko PLP 1 year ago
parent b32b687951
commit b549e843ac
  1. 48
      ng-app/src/routes/WalletCreate.svelte
  2. 4
      ng-wallet/src/types.rs
  3. 75
      ngaccount/web/src/routes/Create.svelte
  4. 9
      ngd/README.md
  5. 2
      ngd/src/main.rs
  6. 17
      p2p-broker/src/server_ws.rs
  7. 74
      p2p-net/src/types.rs
  8. 17
      p2p-net/src/utils.rs

@ -109,6 +109,7 @@
let cloud_link; let cloud_link;
let animateDownload = true; let animateDownload = true;
let invitation; let invitation;
let pre_invitation;
let unsub_register_accepted; let unsub_register_accepted;
let unsub_register_error; let unsub_register_error;
@ -159,7 +160,10 @@
param.get("i") param.get("i")
); );
console.log(invitation); console.log(invitation);
if (!invitation) { if (invitation && invitation.V0.url) {
pre_invitation = invitation;
invitation = undefined;
} else if (!invitation) {
let redirect = await ng.get_ngone_url_of_invitation(param.get("i")); let redirect = await ng.get_ngone_url_of_invitation(param.get("i"));
if (redirect) { if (redirect) {
console.error("got an invitation for another broker. redirecting"); console.error("got an invitation for another broker. redirecting");
@ -169,6 +173,11 @@
console.error("invalid invitation. ignoring it"); console.error("invalid invitation. ignoring it");
} }
} }
} else {
pre_invitation = await ng.get_local_bootstrap_with_public(
location.href
);
console.log("pre_invitation", pre_invitation);
} }
} }
scrollToTop(); scrollToTop();
@ -176,10 +185,11 @@
function create_wallet() { function create_wallet() {
intro = false; intro = false;
if (invitation && invitation.V0.url) { // if (invitation && invitation.V0.url) {
// we redirect to the TOS url of the invitation. // // we redirect to the TOS url of the invitation.
window.location.href = invitation.V0.url; // wait = "Redirecting to TOS";
} // window.location.href = invitation.V0.url;
// }
scrollToTop(); scrollToTop();
} }
@ -890,6 +900,33 @@
<h2 class="mt-3 text-xl">Please choose one broker among the list</h2> <h2 class="mt-3 text-xl">Please choose one broker among the list</h2>
</div> </div>
</div> </div>
{#if pre_invitation}
<div class="row mt-5">
<button
on:click|once={async () => {
await select_bsp(pre_invitation.V0.url, pre_invitation.V0.name);
}}
class="choice-button text-white bg-primary-700 hover:bg-primary-700/90 focus:ring-4 focus:outline-none focus:ring-primary-700/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"
>
<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="mr-4 block h-10 w-10"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 21a9.004 9.004 0 008.716-6.747M12 21a9.004 9.004 0 01-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 017.843 4.582M12 3a8.997 8.997 0 00-7.843 4.582m15.686 0A11.953 11.953 0 0112 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0121 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0112 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 013 12c0-1.605.42-3.113 1.157-4.418"
/>
</svg>
Register with {pre_invitation.V0.name || "this broker"}
</button>
</div>
{:else}
<div class="row mt-5"> <div class="row mt-5">
<button <button
on:click|once={selectEU} on:click|once={selectEU}
@ -923,6 +960,7 @@
For the rest of the world For the rest of the world
</button> </button>
</div> </div>
{/if}
<div class="row mt-5"> <div class="row mt-5">
<button <button

@ -113,7 +113,7 @@ pub struct LocalWalletStorageV0 {
impl From<&CreateWalletResultV0> for LocalWalletStorageV0 { impl From<&CreateWalletResultV0> for LocalWalletStorageV0 {
fn from(res: &CreateWalletResultV0) -> Self { fn from(res: &CreateWalletResultV0) -> Self {
LocalWalletStorageV0 { LocalWalletStorageV0 {
bootstrap: BootstrapContent::V0(BootstrapContentV0 { servers: vec![] }), bootstrap: BootstrapContent::V0(BootstrapContentV0::new()),
wallet: res.wallet.clone(), wallet: res.wallet.clone(),
client: res.client.priv_key.to_pub(), client: res.client.priv_key.to_pub(),
} }
@ -123,7 +123,7 @@ impl From<&CreateWalletResultV0> for LocalWalletStorageV0 {
impl LocalWalletStorageV0 { impl LocalWalletStorageV0 {
pub fn new(wallet: Wallet, client: ClientV0) -> Self { pub fn new(wallet: Wallet, client: ClientV0) -> Self {
LocalWalletStorageV0 { LocalWalletStorageV0 {
bootstrap: BootstrapContent::V0(BootstrapContentV0 { servers: vec![] }), bootstrap: BootstrapContent::V0(BootstrapContentV0::new()),
wallet, wallet,
client: client.priv_key.to_pub(), client: client.priv_key.to_pub(),
} }

@ -22,6 +22,7 @@
const param = new URLSearchParams($querystring); const param = new URLSearchParams($querystring);
let ca = param.get("ca"); let ca = param.get("ca");
let go_back = true; let go_back = true;
let wait = false;
let top; let top;
const api_url = import.meta.env.PROD const api_url = import.meta.env.PROD
@ -29,6 +30,7 @@
: "http://192.168.192.2:3031/api/v1/"; : "http://192.168.192.2:3031/api/v1/";
async function register() { async function register() {
wait = true;
const opts = { const opts = {
method: "get", method: "get",
}; };
@ -46,6 +48,7 @@
await success(result); await success(result);
} }
} catch (e) { } catch (e) {
wait = false;
error = e.message; error = e.message;
} }
} }
@ -60,6 +63,7 @@
let window_api = await import("@tauri-apps/plugin-window"); let window_api = await import("@tauri-apps/plugin-window");
let main = window_api.Window.getByLabel("main"); let main = window_api.Window.getByLabel("main");
if (main) { if (main) {
wait = true;
await main.emit("error", result); await main.emit("error", result);
} else { } else {
await window_api.getCurrent().close(); await window_api.getCurrent().close();
@ -70,6 +74,7 @@
go_back = false; go_back = false;
window.location.href = result.url; window.location.href = result.url;
} else { } else {
wait = true;
window.history.go(-1); window.history.go(-1);
} }
} }
@ -103,7 +108,33 @@
}; };
</script> </script>
<main class="container3" bind:this={top}> {#if wait}
<div class=" max-w-6xl lg:px-8 mx-auto px-4 text-primary-700">
Please wait...
<svg
class="animate-spin mt-10 h-14 w-14 mx-auto"
xmlns="http://www.w3.org/2000/svg"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<circle
class="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
stroke-width="4"
/>
<path
class="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
/>
</svg>
</div>
{:else}
<main class="container3" bind:this={top}>
<div class="row"> <div class="row">
<Logo class="logo block h-24" alt="NextGraph Logo" /> <Logo class="logo block h-24" alt="NextGraph Logo" />
{#if domain == "nextgraph.eu"} {#if domain == "nextgraph.eu"}
@ -149,12 +180,14 @@
<div class=" max-w-6xl lg:px-8 mx-auto px-4"> <div class=" max-w-6xl lg:px-8 mx-auto px-4">
<p class="max-w-xl md:mx-auto lg:max-w-2xl"> <p class="max-w-xl md:mx-auto lg:max-w-2xl">
You would like to choose <b>{domain}</b> as your Broker Service You would like to choose <b>{domain}</b> as your Broker Service
Provider.<br />Please read carefully the Terms of Service here below, Provider.<br />Please read carefully the Terms of Service here
before accepting them. below, before accepting them.
</p> </p>
</div> </div>
{/if} {/if}
<div class="px-4 pt-5 mx-auto max-w-6xl lg:px-8 lg:pt-10 dark:bg-slate-800"> <div
class="px-4 pt-5 mx-auto max-w-6xl lg:px-8 lg:pt-10 dark:bg-slate-800"
>
<div class="max-w-xl md:mx-auto sm:text-center lg:max-w-2xl"> <div class="max-w-xl md:mx-auto sm:text-center lg:max-w-2xl">
<h2 class="pb-5 text-xl">{domain} Terms of Service</h2> <h2 class="pb-5 text-xl">{domain} Terms of Service</h2>
@ -177,8 +210,8 @@
/> />
</svg> </svg>
<span <span
>Our servers are located in Germany, and we comply with the GDPR >Our servers are located in Germany, and we comply with the
regulation.</span GDPR regulation.</span
> >
</li> </li>
<li class="flex space-x-3"> <li class="flex space-x-3">
@ -218,8 +251,9 @@
</svg> </svg>
<span <span
>All the data you exchange with us while using the broker is >All the data you exchange with us while using the broker is
end-to-end encrypted and we do not have access to your decryption end-to-end encrypted and we do not have access to your
keys, meaning that we cannot see the content of your documents.</span decryption keys, meaning that we cannot see the content of your
documents.</span
> >
</li> </li>
<li class="flex space-x-3"> <li class="flex space-x-3">
@ -241,16 +275,16 @@
<span <span
>We do not log any private information about you (nor IP, nor >We do not log any private information about you (nor IP, nor
country, nor statistics of any kind). Only your UserId is kept, country, nor statistics of any kind). Only your UserId is kept,
together with the list of devices (clientId) you use to connect to together with the list of devices (clientId) you use to connect
the broker. We collect general purpose information about your to the broker. We collect general purpose information about your
device (OS version, browser version, and if you use the app, the device (OS version, browser version, and if you use the app, the
version and date of last update). We do not have access to any version and date of last update). We do not have access to any
unique tracking identifier of your device (like Android MAID or unique tracking identifier of your device (like Android MAID or
iPhone IDFA). We could nevertheless be asked by law enforcement iPhone IDFA). We could nevertheless be asked by law enforcement
authorities, depending on the jurisdiction of the server, to log authorities, depending on the jurisdiction of the server, to log
the IP you use when connecting to the broker, and/or to provide the IP you use when connecting to the broker, and/or to provide
them with the encrypted content you have stored on our servers. If them with the encrypted content you have stored on our servers.
you prefer to avoid that eventually, please refrain from any If you prefer to avoid that eventually, please refrain from any
illegal activity while using this broker.</span illegal activity while using this broker.</span
> >
</li> </li>
@ -274,8 +308,8 @@
You can delete your account with us at any time by going to the You can delete your account with us at any time by going to the
link <a target="_blank" href="https://account.{domain}/#/delete" link <a target="_blank" href="https://account.{domain}/#/delete"
>https://account.{domain}/#/delete</a >https://account.{domain}/#/delete</a
> or by entering in your NextGraph application and selecting the menu, > or by entering in your NextGraph application and selecting the
then Accounts, then under broker "delete registration"</span menu, then Accounts, then under broker "delete registration"</span
> >
</li> </li>
<li class="flex space-x-3"> <li class="flex space-x-3">
@ -295,10 +329,12 @@
/> />
</svg> </svg>
<span <span
>Registration is free of charge. And it would be very nice of you >Registration is free of charge. And it would be very nice of
if you wanted to donate a small amount to help us cover the fees you if you wanted to donate a small amount to help us cover the
we have to pay for operating the servers. Here is the donation fees we have to pay for operating the servers. Here is the
link: <a target="_blank" href="https://nextgraph.org/donate" donation link: <a
target="_blank"
href="https://nextgraph.org/donate"
>https://nextgraph.org/donate</a >https://nextgraph.org/donate</a
> >
</span> </span>
@ -338,4 +374,5 @@
</div> </div>
{/if} {/if}
{/if} {/if}
</main> </main>
{/if}

@ -13,8 +13,13 @@ If you prefer to change the base directory, use the argument `--base [PATH]` whe
``` ```
ngcli gen-key ngcli gen-key
ngd --save-key -d <DOMAIN_NAME> -l 1440 --admin <THE_USER_ID_YOU_JUST_CREATED> ngd -v --save-key -d <DOMAIN_NAME> -l 1440 --admin <THE_USER_ID_YOU_JUST_CREATED>
// note the server peerID in the logs // note the server peerID from the logs
```
in another terminal:
```
ngcli --save-key -s 127.0.0.1,1440,<PEER_ID_OF_SERVER> -u <THE_PRIVATE_KEY_OF_THE_USER_YOU_JUST_CREATED> admin add-user <THE_USER_ID_YOU_JUST_CREATED> -a ngcli --save-key -s 127.0.0.1,1440,<PEER_ID_OF_SERVER> -u <THE_PRIVATE_KEY_OF_THE_USER_YOU_JUST_CREATED> admin add-user <THE_USER_ID_YOU_JUST_CREATED> -a
``` ```

@ -996,7 +996,7 @@ async fn main_inner() -> Result<(), ()> {
config_path.to_str().unwrap() config_path.to_str().unwrap()
); );
log_info!( log_info!(
"You not be able to use any Quick config options anymore on the command line at the next command-line start of the server. But you can go to modify the config file directly, or delete it.", "You will not be able to use any Quick config options anymore on the command line at the next command-line start of the server. But you can go to modify the config file directly, or delete it.",
); );
} }
} else { } else {

@ -656,6 +656,8 @@ pub async fn run_server_v0(
let mut servers: Vec<BrokerServerV0> = vec![]; let mut servers: Vec<BrokerServerV0> = vec![];
let registration_url = config.registration_url;
// Preparing the listeners addrs and infos // Preparing the listeners addrs and infos
for listener in config.listeners { for listener in config.listeners {
if !listener.accept_direct && listener.accept_forward_for == AcceptForwardForV0::No { if !listener.accept_direct && listener.accept_forward_for == AcceptForwardForV0::No {
@ -757,8 +759,13 @@ pub async fn run_server_v0(
log_warn!("There isn't any listener that accept clients. This is a misconfiguration as a core server that cannot receive client connections is useless"); log_warn!("There isn't any listener that accept clients. This is a misconfiguration as a core server that cannot receive client connections is useless");
} }
let bootstrap_v0 = BootstrapContentV0 { servers }; let bootstrap_v0 = BootstrapContentV0 { servers };
let bootstrap = BootstrapContent::V0(bootstrap_v0.clone()); let local_bootstrap_info = LocalBootstrapInfo::V0(LocalBootstrapInfoV0 {
BOOTSTRAP_STRING.set(json!(bootstrap).to_string()).unwrap(); bootstrap: bootstrap_v0.clone(),
registration_url: registration_url.clone(),
});
BOOTSTRAP_STRING
.set(json!(local_bootstrap_info).to_string())
.unwrap();
// saving the infos in the broker. This needs to happen before we start listening, as new incoming connections can happen anytime after that. // saving the infos in the broker. This needs to happen before we start listening, as new incoming connections can happen anytime after that.
// and we need those infos for permission checking. // and we need those infos for permission checking.
@ -772,7 +779,7 @@ pub async fn run_server_v0(
&mut path, &mut path,
wallet_master_key, wallet_master_key,
if admin_invite { if admin_invite {
Some(bootstrap_v0) Some(bootstrap_v0.clone())
} else { } else {
None None
}, },
@ -788,9 +795,9 @@ pub async fn run_server_v0(
overlays_configs: config.overlays_configs, overlays_configs: config.overlays_configs,
registration: config.registration, registration: config.registration,
admin_user: config.admin_user, admin_user: config.admin_user,
registration_url: config.registration_url, registration_url,
peer_id, peer_id,
bootstrap, bootstrap: BootstrapContent::V0(bootstrap_v0),
}; };
broker.set_server_config(server_config); broker.set_server_config(server_config);
} }

@ -546,6 +546,15 @@ impl BootstrapContentV0 {
pub fn get_first_peer_id(&self) -> Option<PubKey> { pub fn get_first_peer_id(&self) -> Option<PubKey> {
self.servers.first().map(|s| s.peer_id) self.servers.first().map(|s| s.peer_id)
} }
pub fn get_domain(&self) -> Option<String> {
for server in self.servers.iter() {
if let BrokerServerTypeV0::Domain(name) = &server.server_type {
return Some(name.clone());
}
}
None
}
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
@ -561,6 +570,43 @@ impl BootstrapContent {
} }
} }
/// Local Bootstrap info Version 0, served at /.ng_bootstrap
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct LocalBootstrapInfoV0 {
/// list of servers, in order of preference
pub bootstrap: BootstrapContentV0,
/// optional registration_url for public server that accept to be BSP for new clients
pub registration_url: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum LocalBootstrapInfo {
V0(LocalBootstrapInfoV0),
}
impl LocalBootstrapInfo {
pub fn servers(&self) -> &Vec<BrokerServerV0> {
match self {
Self::V0(v0) => &v0.bootstrap.servers,
}
}
}
impl From<LocalBootstrapInfo> for Invitation {
fn from(value: LocalBootstrapInfo) -> Self {
let LocalBootstrapInfo::V0(info) = value;
let name = info.bootstrap.get_domain();
let url = info.registration_url.clone();
Invitation::V0(InvitationV0 {
bootstrap: info.bootstrap,
code: None,
name,
url,
})
}
}
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub enum InvitationCode { pub enum InvitationCode {
Unique(SymKey), Unique(SymKey),
@ -609,7 +655,7 @@ impl InvitationV0 {
} }
pub fn empty(name: Option<String>) -> Self { pub fn empty(name: Option<String>) -> Self {
InvitationV0 { InvitationV0 {
bootstrap: BootstrapContentV0 { servers: vec![] }, bootstrap: BootstrapContentV0::new(),
code: None, code: None,
name, name,
url: None, url: None,
@ -668,7 +714,7 @@ impl Invitation {
pub fn intersects(&self, invite2: Invitation) -> Invitation { pub fn intersects(&self, invite2: Invitation) -> Invitation {
let Invitation::V0(v0) = self; let Invitation::V0(v0) = self;
let mut new_invite = InvitationV0 { let mut new_invite = InvitationV0 {
bootstrap: BootstrapContentV0 { servers: vec![] }, bootstrap: BootstrapContentV0::new(),
code: v0.code.clone(), code: v0.code.clone(),
name: v0.name.clone(), name: v0.name.clone(),
url: v0.url.clone(), url: v0.url.clone(),
@ -763,18 +809,18 @@ pub enum Invitation {
V0(InvitationV0), V0(InvitationV0),
} }
impl From<BootstrapContent> for Invitation { // impl From<BootstrapContent> for Invitation {
fn from(value: BootstrapContent) -> Self { // fn from(value: BootstrapContent) -> Self {
let BootstrapContent::V0(boot) = value; // let BootstrapContent::V0(boot) = value;
// let name = boot.get_domain();
Invitation::V0(InvitationV0 { // Invitation::V0(InvitationV0 {
bootstrap: boot, // bootstrap: boot,
code: None, // code: None,
name: None, // name,
url: None, // url: None,
}) // })
} // }
} // }
/// Create an account at a Broker Service Provider (BSP). /// Create an account at a Broker Service Provider (BSP).
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]

@ -115,7 +115,7 @@ pub fn check_is_local_url(bootstrap: &BrokerServerV0, location: &String) -> Opti
} }
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
async fn retrieve_ng_bootstrap(location: &String) -> Option<BootstrapContent> { async fn retrieve_ng_bootstrap(location: &String) -> Option<LocalBootstrapInfo> {
let prefix = if (APP_PREFIX == "") { let prefix = if (APP_PREFIX == "") {
let url = Url::parse(location).unwrap(); let url = Url::parse(location).unwrap();
url.origin().unicode_serialization() url.origin().unicode_serialization()
@ -126,7 +126,7 @@ async fn retrieve_ng_bootstrap(location: &String) -> Option<BootstrapContent> {
//log_info!("url {}", url); //log_info!("url {}", url);
let resp = reqwest::get(url).await; let resp = reqwest::get(url).await;
if resp.is_ok() { if resp.is_ok() {
let resp = resp.unwrap().json::<BootstrapContent>().await; let resp = resp.unwrap().json::<LocalBootstrapInfo>().await;
return Some(resp.unwrap()); return Some(resp.unwrap());
} else { } else {
//log_info!("err {}", resp.unwrap_err()); //log_info!("err {}", resp.unwrap_err());
@ -136,11 +136,11 @@ async fn retrieve_ng_bootstrap(location: &String) -> Option<BootstrapContent> {
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
pub async fn retrieve_local_url(location: String) -> Option<String> { pub async fn retrieve_local_url(location: String) -> Option<String> {
let bootstraps = retrieve_ng_bootstrap(&location).await; let info = retrieve_ng_bootstrap(&location).await;
if bootstraps.is_none() { if info.is_none() {
return None; return None;
} }
for bootstrap in bootstraps.unwrap().servers() { for bootstrap in info.unwrap().servers() {
let res = check_is_local_url(bootstrap, &location); let res = check_is_local_url(bootstrap, &location);
if res.is_some() { if res.is_some() {
return res; return res;
@ -165,12 +165,11 @@ pub async fn retrieve_local_bootstrap(
log_debug!("invite_String {:?} invite1{:?}", invite_string, invite1); log_debug!("invite_String {:?} invite1{:?}", invite_string, invite1);
let invite2: Option<Invitation> = { let invite2: Option<Invitation> = {
let bootstraps = retrieve_ng_bootstrap(&location_string).await; let info = retrieve_ng_bootstrap(&location_string).await;
if bootstraps.is_none() { if info.is_none() {
None None
} else { } else {
let mut inv: Invitation = bootstraps.unwrap().into(); let mut inv: Invitation = info.unwrap().into();
inv.set_url(BROKER.read().await.get_registration_url());
Some(inv) Some(inv)
} }
}; };

Loading…
Cancel
Save