account type is permanent and password registration is now working at checkout
This commit is contained in:
@@ -24,6 +24,21 @@ pub struct RegisterParams {
|
||||
pub email: String,
|
||||
pub password: String,
|
||||
pub name: String,
|
||||
/// "personal" or "company"; permanent for the account. Optional on the wire
|
||||
/// (older/JSON callers omit it) and normalized via [`normalize_account_type`].
|
||||
#[serde(default)]
|
||||
pub account_type: Option<String>,
|
||||
}
|
||||
|
||||
/// Normalize an account type to one of the two permanent values, defaulting to
|
||||
/// "personal" for anything missing or unexpected. An account's type is chosen
|
||||
/// once at registration and never changes.
|
||||
#[must_use]
|
||||
pub fn normalize_account_type(value: Option<&str>) -> String {
|
||||
match value.map(str::trim) {
|
||||
Some("company") => "company".to_string(),
|
||||
_ => "personal".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Validate, Deserialize)]
|
||||
@@ -216,6 +231,13 @@ impl Model {
|
||||
hash::verify_password(password, &self.password)
|
||||
}
|
||||
|
||||
/// Whether this is a company account (vs a personal one). Fixed at
|
||||
/// registration.
|
||||
#[must_use]
|
||||
pub fn is_company(&self) -> bool {
|
||||
self.account_type == "company"
|
||||
}
|
||||
|
||||
/// Asynchronously creates a user with a password and saves it to the
|
||||
/// database.
|
||||
///
|
||||
@@ -247,6 +269,7 @@ impl Model {
|
||||
email: ActiveValue::set(params.email.to_string()),
|
||||
password: ActiveValue::set(password_hash),
|
||||
name: ActiveValue::set(params.name.to_string()),
|
||||
account_type: ActiveValue::set(normalize_account_type(params.account_type.as_deref())),
|
||||
..Default::default()
|
||||
}
|
||||
.insert(&txn)
|
||||
@@ -257,6 +280,41 @@ impl Model {
|
||||
Ok(user)
|
||||
}
|
||||
|
||||
/// Creates an account on behalf of a checkout guest. The user never picks a
|
||||
/// password here (a strong random one satisfies the NOT NULL column, as in
|
||||
/// the OAuth path); they receive a "set your password" link by email. Errors
|
||||
/// with [`ModelError::EntityAlreadyExists`] if the email is already taken.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// When the email already exists or the insert fails.
|
||||
pub async fn create_guest_account(
|
||||
db: &DatabaseConnection,
|
||||
email: &str,
|
||||
name: &str,
|
||||
account_type: &str,
|
||||
) -> ModelResult<Self> {
|
||||
let password = PasswordGenerator::new()
|
||||
.length(16)
|
||||
.numbers(true)
|
||||
.lowercase_letters(true)
|
||||
.uppercase_letters(true)
|
||||
.symbols(true)
|
||||
.strict(true)
|
||||
.generate_one()
|
||||
.map_err(|e| ModelError::Any(e.into()))?;
|
||||
Self::create_with_password(
|
||||
db,
|
||||
&RegisterParams {
|
||||
email: email.to_string(),
|
||||
password,
|
||||
name: name.to_string(),
|
||||
account_type: Some(account_type.to_string()),
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Creates a JWT
|
||||
///
|
||||
/// # Errors
|
||||
|
||||
Reference in New Issue
Block a user