diff --git a/src/db.rs b/src/db.rs index 3eddc1f..14e70b0 100644 --- a/src/db.rs +++ b/src/db.rs @@ -22,6 +22,7 @@ pub(crate) trait DBConnection { fn set_invoice_state(&self, invoice: Invoice, s: i32) -> anyhow::Result<()>; fn get_user_by_name(&self, name: String) -> anyhow::Result>; fn get_user_by_id(&self, id: i32) -> anyhow::Result>; + fn get_user_by_pubkey(&self, pubkey: String) -> anyhow::Result>; fn get_user_and_increment_counter(&self, name: &str) -> anyhow::Result>; fn insert_new_zap(&self, new_zap: Zap) -> anyhow::Result; fn get_zap_by_id(&self, id: i32) -> anyhow::Result>; @@ -71,6 +72,11 @@ impl DBConnection for PostgresConnection { AppUser::get_by_name(conn, name) } + fn get_user_by_pubkey(&self, pubkey: String) -> anyhow::Result> { + let conn = &mut self.db.get()?; + AppUser::get_by_pubkey(conn, pubkey) + } + fn get_user_by_id(&self, id: i32) -> anyhow::Result> { let conn = &mut self.db.get()?; AppUser::get_by_id(conn, id) diff --git a/src/main.rs b/src/main.rs index d1ba5b2..924c1d0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,8 +17,9 @@ use crate::{ invoice::handle_pending_invoices, mint::{setup_multimint, MultiMintWrapperTrait}, routes::{ - check_pubkey, check_username, health_check, lnurl_callback_route, lnurl_verify_route, - register_route, root, validate_cors, well_known_lnurlp_route, well_known_nip5_route, + check_pubkey, check_registration_info, check_username, health_check, lnurl_callback_route, + lnurl_verify_route, register_route, root, validate_cors, well_known_lnurlp_route, + well_known_nip5_route, }, }; @@ -168,7 +169,8 @@ async fn main() -> anyhow::Result<()> { .route("/", get(root)) .route("/health-check", get(health_check)) .route("/v1/check-username/:username", get(check_username)) - .route("/v1/check-pubkey/:pubkey", get(check_pubkey)) + .route("/v1/check-pubkey/:pubkey", get(check_pubkey)) // DEPRECATED for check-registration + .route("/v1/check-registration", post(check_registration_info)) .route("/v1/register", post(register_route)) .route("/.well-known/nostr.json", get(well_known_nip5_route)) .route( diff --git a/src/register.rs b/src/register.rs index 2e74570..884aa57 100644 --- a/src/register.rs +++ b/src/register.rs @@ -1,7 +1,7 @@ use std::str::FromStr; use crate::{ - models::app_user::NewAppUser, + models::app_user::{AppUser, NewAppUser}, routes::{RegisterRequest, RegisterResponse}, State, }; @@ -35,6 +35,10 @@ pub fn check_registered_pubkey(state: &State, pubkey: String) -> anyhow::Result< state.db.check_registered_pubkey(pubkey) } +pub fn get_user_by_pubkey(state: &State, pubkey: String) -> anyhow::Result> { + state.db.get_user_by_pubkey(pubkey) +} + pub fn generate_random_name(state: &State) -> anyhow::Result { loop { let new_name = Generator::with_naming(names::Name::Numbered) diff --git a/src/routes.rs b/src/routes.rs index 6245c33..12cacc7 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -1,7 +1,7 @@ use crate::{ lnurlp::{lnurl_callback, verify, well_known_lnurlp}, nostr::well_known_nip5, - register::{check_available, check_registered_pubkey, register}, + register::{check_available, check_registered_pubkey, get_user_by_pubkey, register}, State, ALLOWED_LOCALHOST, ALLOWED_ORIGINS, ALLOWED_SUBDOMAIN, API_VERSION, }; use axum::extract::{Path, Query}; @@ -13,6 +13,7 @@ use axum::{Json, TypedHeader}; use fedimint_core::Amount; use fedimint_ln_common::lightning_invoice::Bolt11Invoice; use log::{error, info}; +use nostr::Event; use serde::{de, Deserialize, Deserializer, Serialize}; use serde_json::{json, Value}; use std::{collections::HashMap, fmt::Display, str::FromStr}; @@ -70,6 +71,54 @@ pub async fn check_pubkey( } } +#[derive(Serialize, Deserialize, Clone)] +pub struct RegistrationInfo { + pub name: Option, + pub federation_id: Option, +} + +pub async fn check_registration_info( + origin: Option>, + Extension(state): Extension, + Json(event): Json, +) -> Result, (StatusCode, String)> { + validate_cors(origin)?; + + let pubkey = event.author(); + info!("check_registration_info: {}", pubkey); + + if event.verify().is_err() { + error!("error in check_registration_info: bad event"); + return Err((StatusCode::BAD_REQUEST, "Bad event".to_string())); + } + + // make sure it was made in the last 30 seconds + if event.created_at() < nostr::Timestamp::now() - 30_i64 { + error!("error in check_registration_info: event expired"); + return Err((StatusCode::BAD_REQUEST, "Event expired".to_string())); + } + + match get_user_by_pubkey(&state, pubkey.to_string()) { + Ok(Some(u)) => { + info!("check_pubkey finished: {}", pubkey); + + Ok(Json(RegistrationInfo { + name: Some(u.name), + federation_id: Some(u.federation_id), + })) + } + Ok(None) => { + info!("check_pubkey not found: {}", pubkey); + + Ok(Json(RegistrationInfo { + name: None, + federation_id: None, + })) + } + Err(e) => Err(handle_anyhow_error("check_pubkey", e)), + } +} + #[derive(Deserialize, Clone)] pub struct RegisterRequest { pub name: Option,