server: split up update_user_with_transaction

This commit is contained in:
Copilot
2025-10-10 09:01:52 +02:00
committed by GitHub
parent 9a83e68667
commit 0f8f9e1244
@@ -2,7 +2,11 @@ use crate::sql_backend_handler::SqlBackendHandler;
use async_trait::async_trait; use async_trait::async_trait;
use lldap_domain::{ use lldap_domain::{
requests::{CreateUserRequest, UpdateUserRequest}, requests::{CreateUserRequest, UpdateUserRequest},
types::{AttributeName, GroupDetails, GroupId, Serialized, User, UserAndGroups, UserId, Uuid}, schema::Schema,
types::{
Attribute, AttributeName, GroupDetails, GroupId, Serialized, User, UserAndGroups, UserId,
Uuid,
},
}; };
use lldap_domain_handlers::handler::{ use lldap_domain_handlers::handler::{
ReadSchemaBackendHandler, UserBackendHandler, UserListerBackendHandler, UserRequestFilter, ReadSchemaBackendHandler, UserBackendHandler, UserListerBackendHandler, UserRequestFilter,
@@ -185,20 +189,12 @@ impl UserListerBackendHandler for SqlBackendHandler {
} }
impl SqlBackendHandler { impl SqlBackendHandler {
async fn update_user_with_transaction( fn compute_user_attribute_changes(
transaction: &DatabaseTransaction, user_id: &UserId,
request: UpdateUserRequest, insert_attributes: Vec<Attribute>,
) -> Result<()> { delete_attributes: Vec<AttributeName>,
let lower_email = request.email.as_ref().map(|s| s.as_str().to_lowercase()); schema: &Schema,
let now = chrono::Utc::now().naive_utc(); ) -> Result<(Vec<model::user_attributes::ActiveModel>, Vec<AttributeName>)> {
let update_user = model::users::ActiveModel {
user_id: ActiveValue::Set(request.user_id.clone()),
email: request.email.map(ActiveValue::Set).unwrap_or_default(),
lowercase_email: lower_email.map(ActiveValue::Set).unwrap_or_default(),
display_name: to_value(&request.display_name),
modified_date: ActiveValue::Set(now),
..Default::default()
};
let mut update_user_attributes = Vec::new(); let mut update_user_attributes = Vec::new();
let mut remove_user_attributes = Vec::new(); let mut remove_user_attributes = Vec::new();
let mut process_serialized = let mut process_serialized =
@@ -208,24 +204,20 @@ impl SqlBackendHandler {
} }
ActiveValue::Set(_) => { ActiveValue::Set(_) => {
update_user_attributes.push(model::user_attributes::ActiveModel { update_user_attributes.push(model::user_attributes::ActiveModel {
user_id: Set(request.user_id.clone()), user_id: Set(user_id.clone()),
attribute_name: Set(attribute_name), attribute_name: Set(attribute_name),
value, value,
}) })
} }
_ => unreachable!(), _ => unreachable!(),
}; };
let schema = Self::get_schema_with_transaction(transaction).await?; for attribute in insert_attributes {
for attribute in request.insert_attributes {
if schema if schema
.user_attributes .user_attributes
.get_attribute_type(&attribute.name) .get_attribute_type(&attribute.name)
.is_some() .is_some()
{ {
process_serialized( process_serialized(ActiveValue::Set(attribute.value.into()), attribute.name);
ActiveValue::Set(attribute.value.into()),
attribute.name.clone(),
);
} else { } else {
return Err(DomainError::InternalError(format!( return Err(DomainError::InternalError(format!(
"User attribute name {} doesn't exist in the schema, yet was attempted to be inserted in the database", "User attribute name {} doesn't exist in the schema, yet was attempted to be inserted in the database",
@@ -233,7 +225,7 @@ impl SqlBackendHandler {
))); )));
} }
} }
for attribute in request.delete_attributes { for attribute in delete_attributes {
if schema if schema
.user_attributes .user_attributes
.get_attribute_type(&attribute) .get_attribute_type(&attribute)
@@ -246,6 +238,31 @@ impl SqlBackendHandler {
))); )));
} }
} }
Ok((update_user_attributes, remove_user_attributes))
}
async fn update_user_with_transaction(
transaction: &DatabaseTransaction,
request: UpdateUserRequest,
) -> Result<()> {
let schema = Self::get_schema_with_transaction(transaction).await?;
let (update_user_attributes, remove_user_attributes) =
Self::compute_user_attribute_changes(
&request.user_id,
request.insert_attributes,
request.delete_attributes,
&schema,
)?;
let lower_email = request.email.as_ref().map(|s| s.as_str().to_lowercase());
let now = chrono::Utc::now().naive_utc();
let update_user = model::users::ActiveModel {
user_id: ActiveValue::Set(request.user_id.clone()),
email: request.email.map(ActiveValue::Set).unwrap_or_default(),
lowercase_email: lower_email.map(ActiveValue::Set).unwrap_or_default(),
display_name: to_value(&request.display_name),
modified_date: ActiveValue::Set(now),
..Default::default()
};
update_user.update(transaction).await?; update_user.update(transaction).await?;
if !remove_user_attributes.is_empty() { if !remove_user_attributes.is_empty() {
model::UserAttributes::delete_many() model::UserAttributes::delete_many()