Allow users of password auth to use subscriptions

This commit is contained in:
silverpill 2022-08-15 19:25:31 +00:00
parent 596871e6e3
commit a80c11b99c
5 changed files with 26 additions and 27 deletions

View file

@ -159,7 +159,7 @@ paths:
description: User's wallet address is not known or not verified
418:
description: Blockchain integration is not enabled
/api/v1/accounts/subscription_enabled:
/api/v1/accounts/subscriptions_enabled:
post:
summary: Notify server about subscription setup
responses:
@ -792,11 +792,6 @@ components:
type: array
items:
$ref: '#/components/schemas/Field'
wallet_address:
description: Ethereum wallet address (visibile only to the current user).
type: string
nullable: true
example: '0xd8da6bf...'
subscription_page_url:
description: Subscription page URL
type: string

View file

@ -57,7 +57,6 @@ pub struct Account {
pub source: Option<Source>,
pub wallet_address: Option<String>,
pub subscription_page_url: Option<String>,
}
@ -122,7 +121,6 @@ impl Account {
following_count: profile.following_count,
statuses_count: profile.post_count,
source: None,
wallet_address: None,
subscription_page_url,
}
}
@ -140,11 +138,8 @@ impl Account {
note: user.profile.bio_source.clone(),
fields: fields_sources,
};
// Expose login address only if it's verified
let wallet_address = user.public_wallet_address();
let mut account = Self::from_profile(user.profile, instance_url);
account.source = Some(source);
account.wallet_address = wallet_address;
account
}
}
@ -388,7 +383,6 @@ mod tests {
format!("{}/media/test", INSTANCE_URL),
);
assert!(account.source.is_none());
assert!(account.wallet_address.is_none());
}
#[test]
@ -410,6 +404,5 @@ mod tests {
account.source.unwrap().note.unwrap(),
bio_source,
);
assert_eq!(account.wallet_address, None);
}
}

View file

@ -300,9 +300,11 @@ async fn authorize_subscription(
.ok_or(HttpError::NotSupported)?
.ethereum_config()
.ok_or(HttpError::NotSupported)?;
// Wallet address must be public, because subscribers should be able
// The user must have a public wallet address,
// because subscribers should be able
// to verify that payments are actually sent to the recipient.
let wallet_address = current_user.public_wallet_address()
let wallet_address = current_user
.public_wallet_address(&config.default_currency())
.ok_or(HttpError::PermissionError)?;
let signature = create_subscription_signature(
ethereum_config,
@ -323,7 +325,8 @@ async fn subscriptions_enabled(
let mut current_user = get_current_user(db_client, auth.token()).await?;
let contract_set = maybe_blockchain.as_ref().as_ref()
.ok_or(HttpError::NotSupported)?;
let wallet_address = current_user.public_wallet_address()
let wallet_address = current_user
.public_wallet_address(&config.default_currency())
.ok_or(HttpError::PermissionError)?;
let is_registered = is_registered_recipient(contract_set, &wallet_address)
.await.map_err(|_| HttpError::InternalError)?;

View file

@ -429,8 +429,9 @@ async fn get_signature(
.ok_or(HttpError::NotSupported)?
.ethereum_config()
.ok_or(HttpError::NotSupported)?;
// Wallet address must be public because minting exposes it
let wallet_address = current_user.public_wallet_address()
// User must have a public wallet address
let wallet_address = current_user
.public_wallet_address(&config.default_currency())
.ok_or(HttpError::PermissionError)?;
let post = get_post_by_id(db_client, &status_id).await?;
if post.author.id != current_user.id || !post.is_public() || post.repost_of_id.is_some() {

View file

@ -5,6 +5,7 @@ use uuid::Uuid;
use crate::errors::ValidationError;
use crate::models::profiles::types::DbActorProfile;
use crate::utils::currencies::Currency;
#[allow(dead_code)]
#[derive(FromSql)]
@ -23,7 +24,7 @@ pub struct DbUser {
#[cfg_attr(test, derive(Default))]
pub struct User {
pub id: Uuid,
pub wallet_address: Option<String>,
pub wallet_address: Option<String>, // login address
pub password_hash: Option<String>,
pub private_key: String,
pub profile: DbActorProfile,
@ -44,12 +45,17 @@ impl User {
}
}
/// Returns login address if it is verified
pub fn public_wallet_address(&self) -> Option<String> {
let wallet_address = self.wallet_address.clone()?;
let is_verified = self.profile.identity_proofs.clone().into_inner().iter()
.any(|proof| proof.issuer.address == wallet_address);
if is_verified { Some(wallet_address) } else { None }
/// Returns wallet address if it is verified
pub fn public_wallet_address(&self, currency: &Currency) -> Option<String> {
for proof in self.profile.identity_proofs.clone().into_inner() {
// Return first match (it's safe if user is local)
if let Some(ref address_currency) = proof.issuer.currency() {
if address_currency == currency {
return Some(proof.issuer.address);
};
};
};
None
}
}
@ -76,12 +82,13 @@ mod tests {
use super::*;
#[test]
fn test_public_wallet_address_hidden_by_default() {
fn test_public_wallet_address_login_address_not_exposed() {
let user = User {
wallet_address: Some("0x1234".to_string()),
..Default::default()
};
assert_eq!(user.public_wallet_address(), None);
let ethereum = Currency::Ethereum;
assert_eq!(user.public_wallet_address(&ethereum), None);
}
#[test]