Change path of user creation endpoint

This commit is contained in:
silverpill 2021-10-05 20:57:24 +00:00
parent b39733beb7
commit 9519786788
6 changed files with 43 additions and 24 deletions

View file

@ -81,7 +81,6 @@ async fn main() -> std::io::Result<()> {
config.contract_dir.clone(), config.contract_dir.clone(),
)) ))
.service(oauth_api_scope()) .service(oauth_api_scope())
.service(user_api::create_user_view)
.service(user_api::login_view) .service(user_api::login_view)
.service(user_api::current_user_view) .service(user_api::current_user_view)
.service(user_api::logout_view) .service(user_api::logout_view)

View file

@ -9,7 +9,7 @@ use crate::models::profiles::types::{
ExtraField, ExtraField,
ProfileUpdateData, ProfileUpdateData,
}; };
use crate::models::users::types::User; use crate::models::users::types::{User, UserCreateData};
use crate::utils::files::{FileError, save_validated_b64_file, get_file_url}; use crate::utils::files::{FileError, save_validated_b64_file, get_file_url};
#[derive(Serialize)] #[derive(Serialize)]
@ -96,6 +96,26 @@ impl Account {
} }
/// https://docs.joinmastodon.org/methods/accounts/ /// https://docs.joinmastodon.org/methods/accounts/
#[derive(Deserialize)]
pub struct AccountCreateData {
username: String,
password: String,
wallet_address: String,
invite_code: Option<String>,
}
impl AccountCreateData {
pub fn into_user_data(self) -> UserCreateData {
UserCreateData {
username: self.username,
password: self.password,
wallet_address: self.wallet_address,
invite_code: self.invite_code,
}
}
}
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct AccountUpdateData { pub struct AccountUpdateData {
pub display_name: Option<String>, pub display_name: Option<String>,

View file

@ -16,6 +16,7 @@ use crate::errors::HttpError;
use crate::mastodon_api::statuses::types::Status; use crate::mastodon_api::statuses::types::Status;
use crate::mastodon_api::oauth::auth::get_current_user as get_current_user_; use crate::mastodon_api::oauth::auth::get_current_user as get_current_user_;
use crate::mastodon_api::users::auth::get_current_user; use crate::mastodon_api::users::auth::get_current_user;
use crate::mastodon_api::users::views::create_user_view;
use crate::models::posts::queries::get_posts_by_author; use crate::models::posts::queries::get_posts_by_author;
use crate::models::profiles::queries::{ use crate::models::profiles::queries::{
get_profile_by_id, get_profile_by_id,
@ -210,6 +211,7 @@ async fn get_account_statuses(
pub fn account_api_scope() -> Scope { pub fn account_api_scope() -> Scope {
web::scope("/api/v1/accounts") web::scope("/api/v1/accounts")
// Routes without account ID // Routes without account ID
.service(create_user_view)
.service(get_relationships) .service(get_relationships)
.service(verify_credentials) .service(verify_credentials)
.service(update_credentials) .service(update_credentials)

View file

@ -7,16 +7,13 @@ use actix_web::{
use crate::config::Config; use crate::config::Config;
use crate::database::{Pool, get_database_client}; use crate::database::{Pool, get_database_client};
use crate::errors::{HttpError, ValidationError}; use crate::errors::{HttpError, ValidationError};
use crate::mastodon_api::accounts::types::Account; use crate::mastodon_api::accounts::types::{Account, AccountCreateData};
use crate::models::users::queries::{ use crate::models::users::queries::{
is_valid_invite_code, is_valid_invite_code,
create_user, create_user,
get_user_by_wallet_address, get_user_by_wallet_address,
}; };
use crate::models::users::types::{ use crate::models::users::types::UserLoginData;
UserRegistrationData,
UserLoginData,
};
use crate::utils::crypto::{ use crate::utils::crypto::{
hash_password, hash_password,
verify_password, verify_password,
@ -26,25 +23,26 @@ use crate::utils::crypto::{
use super::auth::get_current_user; use super::auth::get_current_user;
// /api/v1/accounts // /api/v1/accounts
#[post("/api/v0/create")] #[post("")]
async fn create_user_view( pub async fn create_user_view(
config: web::Data<Config>, config: web::Data<Config>,
db_pool: web::Data<Pool>, db_pool: web::Data<Pool>,
form: web::Json<UserRegistrationData>, account_data: web::Json<AccountCreateData>,
session: Session, session: Session,
) -> 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
form.clean()?; user_data.clean()?;
if !config.registrations_open { if !config.registrations_open {
let invite_code = form.invite_code.as_ref() let invite_code = user_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? {
Err(ValidationError("invalid invite code"))?; Err(ValidationError("invalid invite code"))?;
} }
} }
// Hash password and generate private key // Hash password and generate private key
let password_hash = hash_password(&form.signature) let password_hash = hash_password(&user_data.password)
.map_err(|_| HttpError::InternalError)?; .map_err(|_| HttpError::InternalError)?;
let private_key = match web::block(move || generate_private_key()).await { let private_key = match web::block(move || generate_private_key()).await {
Ok(private_key) => private_key, Ok(private_key) => private_key,
@ -55,7 +53,7 @@ async fn create_user_view(
let user = create_user( let user = create_user(
db_client, db_client,
form.into_inner(), user_data,
password_hash, password_hash,
private_key_pem, private_key_pem,
).await?; ).await?;

View file

@ -4,7 +4,7 @@ use uuid::Uuid;
use crate::errors::DatabaseError; use crate::errors::DatabaseError;
use crate::models::profiles::queries::create_profile; use crate::models::profiles::queries::create_profile;
use crate::models::profiles::types::{DbActorProfile, ProfileCreateData}; use crate::models::profiles::types::{DbActorProfile, ProfileCreateData};
use super::types::{DbUser, User, UserRegistrationData}; use super::types::{DbUser, User, UserCreateData};
use super::utils::generate_invite_code; use super::utils::generate_invite_code;
pub async fn create_invite_code( pub async fn create_invite_code(
@ -118,13 +118,13 @@ pub async fn is_registered_user(
pub async fn create_user( pub async fn create_user(
db_client: &mut impl GenericClient, db_client: &mut impl GenericClient,
form: UserRegistrationData, user_data: UserCreateData,
password_hash: String, password_hash: String,
private_key_pem: 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
if let Some(ref invite_code) = form.invite_code { if let Some(ref invite_code) = user_data.invite_code {
let updated_count = transaction.execute( let updated_count = transaction.execute(
" "
UPDATE user_invite_code UPDATE user_invite_code
@ -139,9 +139,9 @@ pub async fn create_user(
} }
// Create profile // Create profile
let profile_data = ProfileCreateData { let profile_data = ProfileCreateData {
username: form.username.clone(), username: user_data.username.clone(),
display_name: None, display_name: None,
acct: form.username.clone(), acct: user_data.username.clone(),
bio: None, bio: None,
avatar: None, avatar: None,
banner: None, banner: None,
@ -160,10 +160,10 @@ pub async fn create_user(
", ",
&[ &[
&profile.id, &profile.id,
&form.wallet_address, &user_data.wallet_address,
&password_hash, &password_hash,
&private_key_pem, &private_key_pem,
&form.invite_code, &user_data.invite_code,
], ],
).await; ).await;
match result { match result {

View file

@ -29,9 +29,9 @@ pub struct User {
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct UserRegistrationData { pub struct UserCreateData {
pub username: String, pub username: String,
pub signature: String, pub password: String,
pub wallet_address: String, pub wallet_address: String,
pub invite_code: Option<String>, pub invite_code: Option<String>,
} }
@ -44,7 +44,7 @@ fn validate_username(username: &str) -> Result<(), ValidationError> {
Ok(()) Ok(())
} }
impl UserRegistrationData { impl UserCreateData {
/// Validate and clean. /// Validate and clean.
pub fn clean(&self) -> Result<(), ValidationError> { pub fn clean(&self) -> Result<(), ValidationError> {
validate_username(&self.username)?; validate_username(&self.username)?;