upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2024-11-25 12:31:50 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2024-11-25 12:31:50 +0000
commitb09cf3ef8bbb5d31e4c424ff28282f5029f95fb2 (patch)
tree7081e193a6dfa0dc076191dcd66ea974df69695b /src
parent264c6dfe4229cd73bf017f55be0178d596cf06eb (diff)
fix(login): handle git config save errors
to guide the users how to login dispite the git config errors
Diffstat (limited to 'src')
-rw-r--r--src/bin/ngit/sub_commands/login.rs56
-rw-r--r--src/lib/login/fresh.rs83
2 files changed, 133 insertions, 6 deletions
diff --git a/src/bin/ngit/sub_commands/login.rs b/src/bin/ngit/sub_commands/login.rs
index 1a70118..7bb0906 100644
--- a/src/bin/ngit/sub_commands/login.rs
+++ b/src/bin/ngit/sub_commands/login.rs
@@ -2,7 +2,7 @@ use anyhow::{Context, Result};
2use clap; 2use clap;
3use ngit::{ 3use ngit::{
4 cli_interactor::{Interactor, InteractorPrompt, PromptChoiceParms}, 4 cli_interactor::{Interactor, InteractorPrompt, PromptChoiceParms},
5 git::remove_git_config_item, 5 git::{get_git_config_item, remove_git_config_item},
6 login::{existing::load_existing_login, SignerInfoSource}, 6 login::{existing::load_existing_login, SignerInfoSource},
7}; 7};
8 8
@@ -101,14 +101,39 @@ async fn logout(git_repo: Option<&Repo>, local_only: bool) -> Result<(bool, bool
101 "nostr.bunker-uri", 101 "nostr.bunker-uri",
102 "nostr.bunker-app-key", 102 "nostr.bunker-app-key",
103 ] { 103 ] {
104 remove_git_config_item( 104 if let Err(error) = remove_git_config_item(
105 if source == SignerInfoSource::GitLocal { 105 if source == SignerInfoSource::GitLocal {
106 &git_repo 106 &git_repo
107 } else { 107 } else {
108 &None 108 &None
109 }, 109 },
110 item, 110 item,
111 )?; 111 ) {
112 eprintln!("{error:?}");
113
114 eprintln!(
115 "consider manually removing {} git config items: {}",
116 if source == SignerInfoSource::GitGlobal {
117 "global"
118 } else {
119 "local"
120 },
121 format_items_as_list(&get_global_login_config_items_set())
122 );
123 match Interactor::default().choice(
124 PromptChoiceParms::default().with_default(0).with_choices(
125 vec![
126 "continue with global login to reveal what git config items to manually set".to_string(),
127 "login to this local repository with a different account".to_string(),
128 "cancel".to_string(),
129 ]
130 ),
131 )? {
132 0 => return Ok((true, false)),
133 1 => return Ok((true, true)),
134 _ => return Ok((false, local_only)),
135 }
136 }
112 } 137 }
113 } 138 }
114 1 => return Ok((false, local_only)), 139 1 => return Ok((false, local_only)),
@@ -118,3 +143,28 @@ async fn logout(git_repo: Option<&Repo>, local_only: bool) -> Result<(bool, bool
118 } 143 }
119 Ok((true, local_only)) 144 Ok((true, local_only))
120} 145}
146
147fn get_global_login_config_items_set() -> Vec<&'static str> {
148 [
149 "nostr.nsec",
150 "nostr.npub",
151 "nostr.bunker-uri",
152 "nostr.bunker-app-key",
153 ]
154 .iter()
155 .copied()
156 .filter(|item| get_git_config_item(&None, item).is_ok_and(|item| item.is_some()))
157 .collect::<Vec<&str>>()
158}
159
160fn format_items_as_list(items: &[&str]) -> String {
161 match items.len() {
162 0 => String::new(),
163 1 => items[0].to_string(),
164 2 => format!("{} and {}", items[0], items[1]),
165 _ => {
166 let all_but_last = items[..items.len() - 1].join(", ");
167 format!("{}, and {}", all_but_last, items[items.len() - 1])
168 }
169 }
170}
diff --git a/src/lib/login/fresh.rs b/src/lib/login/fresh.rs
index e8cfcb8..194f638 100644
--- a/src/lib/login/fresh.rs
+++ b/src/lib/login/fresh.rs
@@ -93,7 +93,7 @@ pub async fn fresh_login_or_signup(
93 } 93 }
94 } 94 }
95 }; 95 };
96 let _ = save_to_git_config(git_repo, &signer_info, !save_local); 96 let _ = save_to_git_config(git_repo, &signer_info, !save_local).await;
97 let user_ref = get_user_details( 97 let user_ref = get_user_details(
98 &public_key, 98 &public_key,
99 client, 99 client,
@@ -483,7 +483,7 @@ fn generate_qr(data: &str) -> Result<Vec<String>> {
483 Ok(lines) 483 Ok(lines)
484} 484}
485 485
486fn save_to_git_config( 486async fn save_to_git_config(
487 git_repo: &Option<&Repo>, 487 git_repo: &Option<&Repo>,
488 signer_info: &SignerInfo, 488 signer_info: &SignerInfo,
489 global: bool, 489 global: bool,
@@ -516,7 +516,64 @@ fn save_to_git_config(
516 } 516 }
517 } 517 }
518 if global { 518 if global {
519 save_to_git_config(git_repo, signer_info, false)? 519 loop {
520 match Interactor::default().choice(
521 PromptChoiceParms::default()
522 .with_default(0)
523 .with_choices(vec![
524 "i'll update global git config manually with above values".to_string(),
525 "only log into local git repository (save to local git config)"
526 .to_string(),
527 "one time login".to_string(),
528 ]),
529 )? {
530 0 => {
531 // check
532 if let Ok((_, user_ref, _)) = load_existing_login(
533 git_repo,
534 &None,
535 &None,
536 &Some(SignerInfoSource::GitGlobal),
537 None,
538 true,
539 true,
540 )
541 .await
542 {
543 if user_ref.public_key == get_pubkey_from_signer_info(signer_info)? {
544 return Ok(());
545 } else {
546 eprintln!(
547 "global git config hasn't been updated with different npub"
548 );
549 }
550 } else {
551 eprintln!(
552 "global git config hasn't been updated with nostr login values"
553 );
554 }
555 }
556 1 => {
557 if let Err(error) =
558 silently_save_to_git_config(git_repo, signer_info, false).context(
559 format!(
560 "failed to save login details to {} git config",
561 if global { "global" } else { "local" }
562 ),
563 )
564 {
565 eprintln!("Error: {:?}", error);
566 eprintln!("login details were not saved");
567 } else {
568 eprintln!(
569 "saved login details to local git config. you are only logged in to this local repository."
570 );
571 }
572 return Ok(());
573 }
574 _ => return Ok(()),
575 }
576 }
520 } 577 }
521 Err(error) 578 Err(error)
522 } else { 579 } else {
@@ -532,6 +589,26 @@ fn save_to_git_config(
532 } 589 }
533} 590}
534 591
592fn get_pubkey_from_signer_info(signer_info: &SignerInfo) -> Result<PublicKey> {
593 let npub = match signer_info {
594 SignerInfo::Bunker {
595 bunker_uri: _,
596 bunker_app_key: _,
597 npub,
598 } => npub,
599 SignerInfo::Nsec {
600 nsec: _,
601 password: _,
602 npub,
603 } => npub,
604 };
605 if let Some(npub) = npub {
606 PublicKey::parse(npub).context("format of npub string in signer_info is invalid")
607 } else {
608 bail!("no npub in signer_info object");
609 }
610}
611
535fn silently_save_to_git_config( 612fn silently_save_to_git_config(
536 git_repo: &Option<&Repo>, 613 git_repo: &Option<&Repo>,
537 signer_info: &SignerInfo, 614 signer_info: &SignerInfo,