This commit is contained in:
Mateusz Gruszczyński
2026-07-28 15:58:01 +02:00
parent b4ca59eca2
commit d722e8af71
9 changed files with 57 additions and 27 deletions
+33 -14
View File
@@ -154,7 +154,8 @@ pub struct PrivacyRequest {
pub struct ShareUsersRequest {
kind: String,
slug: String,
emails: String,
#[serde(alias = "emails")]
recipients: String,
permission: String,
}
#[derive(Deserialize)]
@@ -1188,26 +1189,29 @@ pub async fn share_resource_users(
"Share confirmation requires SMTP configuration.",
));
}
let emails: Vec<String> = req
.emails
.split(',')
.map(|v| normalize(v))
.filter(|v| !v.is_empty())
let recipients: Vec<String> = req
.recipients
.split([',', ';', '\n'])
.map(str::trim)
.filter(|value| !value.is_empty())
.map(ToOwned::to_owned)
.collect::<std::collections::HashSet<_>>()
.into_iter()
.collect();
if emails.is_empty() || emails.len() > 100 {
if recipients.is_empty() || recipients.len() > 100 {
return Err(AuthError::bad_request(
"Enter between 1 and 100 registered e-mail addresses.",
"Enter between 1 and 100 e-mail addresses or user names.",
));
}
let mut missing = Vec::new();
for email in emails {
let user = find_user_by_email(&state, &email).await?;
for recipient in recipients {
let user = find_user_by_share_identifier(&state, &recipient).await?;
let Some(user) = user else {
missing.push(email);
missing.push(recipient);
continue;
};
if user.confirmed_at.is_none() {
missing.push(format!("{} (account not activated)", email));
missing.push(format!("{} (account not activated)", recipient));
continue;
}
if user.id == owner.id {
@@ -1289,7 +1293,7 @@ pub async fn share_resource_users(
}
if !missing.is_empty() {
return Err(AuthError::bad_request(&format!(
"No registered account for: {}",
"No active registered account for: {}",
missing.join(", ")
)));
}
@@ -1426,7 +1430,7 @@ pub async fn resource_sharing(
.fetch_all(state.db.pool())
.await
.map_err(AuthError::database)?;
let pending: Vec<(String, String, String, String)> = sqlx::query_as(queries::get(
let pending: Vec<(String, String, String, Option<String>)> = sqlx::query_as(queries::get(
state.db.kind(),
queries::RESOURCE_SHARING_PENDING,
))
@@ -1870,6 +1874,21 @@ async fn find_user_by_external_id(
.map_err(AuthError::database)
}
async fn find_user_by_share_identifier(
state: &SharedState,
identifier: &str,
) -> Result<Option<User>, AuthError> {
sqlx::query_as::<_, User>(queries::get(
state.db.kind(),
queries::AUTH_USER_BY_SHARE_IDENTIFIER,
))
.bind(normalize(identifier))
.fetch_optional(state.db.pool())
.await
.map_err(AuthError::database)
}
async fn find_user_by_email(state: &SharedState, email: &str) -> Result<Option<User>, AuthError> {
sqlx::query_as::<_, User>(queries::get(state.db.kind(), queries::AUTH_USER_BY_EMAIL))
.bind(normalize(email))