upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/lib/git/nostr_url.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2024-12-09 09:34:08 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2024-12-10 11:55:01 +0000
commit6d3a4eb870cd344b11ccda13e1339584ed4e4d17 (patch)
tree37cb5787bb62c519a235d5a8b0c5c0985d8b4977 /src/lib/git/nostr_url.rs
parentf0d0e1ba1cba11d3a98a5ab0c7f1dc72b6bc4e17 (diff)
feat(NostrUrlDecoded) add nip05 support
replace `NostrUrlDecoded::from_str` with `NostrUrlDecoded::parse_and_resolve` store nip05 pubkey mapping in git cache
Diffstat (limited to 'src/lib/git/nostr_url.rs')
-rw-r--r--src/lib/git/nostr_url.rs81
1 files changed, 72 insertions, 9 deletions
diff --git a/src/lib/git/nostr_url.rs b/src/lib/git/nostr_url.rs
index c26bb2e..ac57538 100644
--- a/src/lib/git/nostr_url.rs
+++ b/src/lib/git/nostr_url.rs
@@ -2,9 +2,11 @@ use core::fmt;
2use std::str::FromStr; 2use std::str::FromStr;
3 3
4use anyhow::{anyhow, bail, Context, Error, Result}; 4use anyhow::{anyhow, bail, Context, Error, Result};
5use nostr::nips::nip01::Coordinate; 5use nostr::nips::{nip01::Coordinate, nip05};
6use nostr_sdk::{PublicKey, RelayUrl, ToBech32, Url}; 6use nostr_sdk::{PublicKey, RelayUrl, ToBech32, Url};
7 7
8use super::{get_git_config_item, save_git_config_item, Repo};
9
8#[derive(Debug, PartialEq, Default, Clone)] 10#[derive(Debug, PartialEq, Default, Clone)]
9pub enum ServerProtocol { 11pub enum ServerProtocol {
10 Ssh, 12 Ssh,
@@ -59,6 +61,7 @@ pub struct NostrUrlDecoded {
59 pub coordinate: Coordinate, 61 pub coordinate: Coordinate,
60 pub protocol: Option<ServerProtocol>, 62 pub protocol: Option<ServerProtocol>,
61 pub user: Option<String>, 63 pub user: Option<String>,
64 pub nip05: Option<String>,
62} 65}
63 66
64impl fmt::Display for NostrUrlDecoded { 67impl fmt::Display for NostrUrlDecoded {
@@ -89,10 +92,8 @@ impl fmt::Display for NostrUrlDecoded {
89 92
90static INCORRECT_NOSTR_URL_FORMAT_ERROR: &str = "incorrect nostr git url format. try nostr://naddr123 or nostr://npub123/my-repo or nostr://ssh/npub123/relay.damus.io/my-repo"; 93static INCORRECT_NOSTR_URL_FORMAT_ERROR: &str = "incorrect nostr git url format. try nostr://naddr123 or nostr://npub123/my-repo or nostr://ssh/npub123/relay.damus.io/my-repo";
91 94
92impl std::str::FromStr for NostrUrlDecoded { 95impl NostrUrlDecoded {
93 type Err = anyhow::Error; 96 pub async fn parse_and_resolve(url: &str, git_repo: &Option<&Repo>) -> Result<Self> {
94
95 fn from_str(url: &str) -> Result<Self> {
96 let mut protocol = None; 97 let mut protocol = None;
97 let mut user = None; 98 let mut user = None;
98 let mut relays = vec![]; 99 let mut relays = vec![];
@@ -154,6 +155,7 @@ impl std::str::FromStr for NostrUrlDecoded {
154 } 155 }
155 // extract naddr npub/<optional-relays>/identifer 156 // extract naddr npub/<optional-relays>/identifer
156 let part = parts.first().context(INCORRECT_NOSTR_URL_FORMAT_ERROR)?; 157 let part = parts.first().context(INCORRECT_NOSTR_URL_FORMAT_ERROR)?;
158 let mut nip05 = None;
157 // naddr used 159 // naddr used
158 let coordinate = if let Ok(coordinate) = Coordinate::parse(part) { 160 let coordinate = if let Ok(coordinate) = Coordinate::parse(part) {
159 if coordinate.kind.eq(&nostr_sdk::Kind::GitRepoAnnouncement) { 161 if coordinate.kind.eq(&nostr_sdk::Kind::GitRepoAnnouncement) {
@@ -161,8 +163,9 @@ impl std::str::FromStr for NostrUrlDecoded {
161 } else { 163 } else {
162 bail!("naddr doesnt point to a git repository announcement"); 164 bail!("naddr doesnt point to a git repository announcement");
163 } 165 }
164 // npub/<optional-relays>/identifer used 166 // <npub|nip05_address>/<optional-relays>/identifer used
165 } else if let Ok(public_key) = PublicKey::parse(part) { 167 } else {
168 let npub_or_nip05 = part.to_owned();
166 parts.remove(0); 169 parts.remove(0);
167 let identifier = parts 170 let identifier = parts
168 .pop() 171 .pop()
@@ -179,14 +182,41 @@ impl std::str::FromStr for NostrUrlDecoded {
179 RelayUrl::parse(&decoded).context("could not parse relays in nostr git url")?; 182 RelayUrl::parse(&decoded).context("could not parse relays in nostr git url")?;
180 relays.push(url); 183 relays.push(url);
181 } 184 }
185 let public_key = match PublicKey::parse(npub_or_nip05) {
186 Ok(public_key) => public_key,
187 Err(_) => {
188 nip05 = Some(npub_or_nip05.to_string());
189 if let Ok(public_key) =
190 resolve_nip05_from_git_config_cache(npub_or_nip05, git_repo)
191 {
192 public_key
193 } else {
194 // TODO eprint loading message
195 let res = nip05::profile(npub_or_nip05, None)
196 .await
197 .context(INCORRECT_NOSTR_URL_FORMAT_ERROR)?;
198 // TODO clear loading message
199 nip05 = Some(npub_or_nip05.to_string());
200 let _ = save_nip05_to_git_config_cache(
201 npub_or_nip05,
202 &res.public_key,
203 git_repo,
204 );
205 if relays.is_empty() {
206 for r in res.relays {
207 relays.push(r);
208 }
209 }
210 res.public_key
211 }
212 }
213 };
182 Coordinate { 214 Coordinate {
183 identifier, 215 identifier,
184 public_key, 216 public_key,
185 kind: nostr_sdk::Kind::GitRepoAnnouncement, 217 kind: nostr_sdk::Kind::GitRepoAnnouncement,
186 relays, 218 relays,
187 } 219 }
188 } else {
189 bail!(INCORRECT_NOSTR_URL_FORMAT_ERROR);
190 }; 220 };
191 221
192 Ok(Self { 222 Ok(Self {
@@ -194,10 +224,43 @@ impl std::str::FromStr for NostrUrlDecoded {
194 coordinate, 224 coordinate,
195 protocol, 225 protocol,
196 user, 226 user,
227 nip05,
197 }) 228 })
198 } 229 }
199} 230}
200 231
232fn resolve_nip05_from_git_config_cache(nip05: &str, git_repo: &Option<&Repo>) -> Result<PublicKey> {
233 let stored_value = get_git_config_item(
234 git_repo,
235 &format!("nostr.nip05.{}", urlencoding::encode(nip05)),
236 )?
237 .context("not in cache")?;
238 PublicKey::parse(stored_value)
239 .context("stored nip05 resolution value did not parse as public key")
240}
241
242fn save_nip05_to_git_config_cache(
243 nip05: &str,
244 public_key: &PublicKey,
245 git_repo: &Option<&Repo>,
246) -> Result<()> {
247 if save_git_config_item(
248 git_repo,
249 &format!("nostr.nip05.{}", urlencoding::encode(nip05)),
250 &public_key.to_bech32()?,
251 )
252 .is_err()
253 {
254 save_git_config_item(
255 &None,
256 &format!("nostr.nip05.{}", urlencoding::encode(nip05)),
257 &public_key.to_bech32()?,
258 )
259 } else {
260 Ok(())
261 }
262}
263
201#[derive(Debug, PartialEq, Default)] 264#[derive(Debug, PartialEq, Default)]
202pub struct CloneUrl { 265pub struct CloneUrl {
203 original_string: String, 266 original_string: String,