Refactor create_account view

This commit is contained in:
silverpill 2022-01-06 19:06:35 +00:00
parent ba52cf0be1
commit 810e67f88e
4 changed files with 26 additions and 27 deletions

View file

@ -95,18 +95,23 @@ impl Account {
/// https://docs.joinmastodon.org/methods/accounts/ /// https://docs.joinmastodon.org/methods/accounts/
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct AccountCreateData { pub struct AccountCreateData {
username: String, pub username: String,
password: String, pub password: String,
wallet_address: Option<String>, pub wallet_address: Option<String>,
invite_code: Option<String>, pub invite_code: Option<String>,
} }
impl AccountCreateData { impl AccountCreateData {
pub fn into_user_data(self) -> UserCreateData { pub fn into_user_data(
self,
password_hash: String,
private_key_pem: String,
) -> UserCreateData {
UserCreateData { UserCreateData {
username: self.username, username: self.username,
password: self.password, password_hash,
private_key_pem,
wallet_address: self.wallet_address, wallet_address: self.wallet_address,
invite_code: self.invite_code, invite_code: self.invite_code,
} }

View file

@ -40,6 +40,7 @@ use crate::models::users::queries::{
is_valid_invite_code, is_valid_invite_code,
create_user, create_user,
}; };
use crate::models::users::types::UserCreateData;
use crate::utils::crypto::{ use crate::utils::crypto::{
hash_password, hash_password,
generate_private_key, generate_private_key,
@ -60,11 +61,10 @@ pub async fn create_account(
account_data: web::Json<AccountCreateData>, account_data: web::Json<AccountCreateData>,
) -> Result<HttpResponse, HttpError> { ) -> Result<HttpResponse, HttpError> {
let db_client = &mut **get_database_client(&db_pool).await?; let db_client = &mut **get_database_client(&db_pool).await?;
let user_data = account_data.into_inner().into_user_data();
// Validate // Validate
user_data.clean()?; UserCreateData::clean(&account_data.username)?;
if !config.registrations_open { if !config.registrations_open {
let invite_code = user_data.invite_code.as_ref() let invite_code = account_data.invite_code.as_ref()
.ok_or(ValidationError("invite code is required"))?; .ok_or(ValidationError("invite code is required"))?;
if !is_valid_invite_code(db_client, invite_code).await? { if !is_valid_invite_code(db_client, invite_code).await? {
return Err(ValidationError("invalid invite code").into()); return Err(ValidationError("invalid invite code").into());
@ -72,7 +72,7 @@ pub async fn create_account(
} }
if config.ethereum_contract.is_some() { if config.ethereum_contract.is_some() {
// Wallet address is required only if ethereum integration is enabled // Wallet address is required only if ethereum integration is enabled
let wallet_address = user_data.wallet_address.as_ref() let wallet_address = account_data.wallet_address.as_ref()
.ok_or(ValidationError("wallet address is required"))?; .ok_or(ValidationError("wallet address is required"))?;
let is_allowed = is_allowed_user(&config, wallet_address).await let is_allowed = is_allowed_user(&config, wallet_address).await
.map_err(|_| HttpError::InternalError)?; .map_err(|_| HttpError::InternalError)?;
@ -81,7 +81,7 @@ pub async fn create_account(
} }
} }
// Hash password and generate private key // Hash password and generate private key
let password_hash = hash_password(&user_data.password) let password_hash = hash_password(&account_data.password)
.map_err(|_| HttpError::InternalError)?; .map_err(|_| HttpError::InternalError)?;
let private_key = match web::block(generate_private_key).await { let private_key = match web::block(generate_private_key).await {
Ok(private_key) => private_key, Ok(private_key) => private_key,
@ -90,12 +90,9 @@ pub async fn create_account(
let private_key_pem = serialize_private_key(private_key) let private_key_pem = serialize_private_key(private_key)
.map_err(|_| HttpError::InternalError)?; .map_err(|_| HttpError::InternalError)?;
let user = create_user( let user_data = account_data.into_inner()
db_client, .into_user_data(password_hash, private_key_pem);
user_data, let user = create_user(db_client, user_data).await?;
password_hash,
private_key_pem,
).await?;
let account = Account::from_user(user, &config.instance_url()); let account = Account::from_user(user, &config.instance_url());
Ok(HttpResponse::Created().json(account)) Ok(HttpResponse::Created().json(account))
} }

View file

@ -56,8 +56,6 @@ pub async fn is_valid_invite_code(
pub async fn create_user( pub async fn create_user(
db_client: &mut impl GenericClient, db_client: &mut impl GenericClient,
user_data: UserCreateData, user_data: UserCreateData,
password_hash: String,
private_key_pem: String,
) -> Result<User, DatabaseError> { ) -> Result<User, DatabaseError> {
let transaction = db_client.transaction().await?; let transaction = db_client.transaction().await?;
// Use invite code // Use invite code
@ -98,8 +96,8 @@ pub async fn create_user(
&[ &[
&profile.id, &profile.id,
&user_data.wallet_address, &user_data.wallet_address,
&password_hash, &user_data.password_hash,
&private_key_pem, &user_data.private_key_pem,
&user_data.invite_code, &user_data.invite_code,
], ],
).await.map_err(catch_unique_violation("user"))?; ).await.map_err(catch_unique_violation("user"))?;

View file

@ -1,7 +1,6 @@
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use postgres_types::FromSql; use postgres_types::FromSql;
use regex::Regex; use regex::Regex;
use serde::Deserialize;
use uuid::Uuid; use uuid::Uuid;
use crate::errors::ValidationError; use crate::errors::ValidationError;
@ -46,10 +45,10 @@ impl User {
} }
} }
#[derive(Deserialize)]
pub struct UserCreateData { pub struct UserCreateData {
pub username: String, pub username: String,
pub password: String, pub password_hash: String,
pub private_key_pem: String,
pub wallet_address: Option<String>, pub wallet_address: Option<String>,
pub invite_code: Option<String>, pub invite_code: Option<String>,
} }
@ -65,9 +64,9 @@ fn validate_local_username(username: &str) -> Result<(), ValidationError> {
impl UserCreateData { impl UserCreateData {
/// Validate and clean. /// Validate and clean.
pub fn clean(&self) -> Result<(), ValidationError> { pub fn clean(username: &str) -> Result<(), ValidationError> {
validate_username(&self.username)?; validate_username(username)?;
validate_local_username(&self.username)?; validate_local_username(username)?;
Ok(()) Ok(())
} }
} }