fixes
This commit is contained in:
+33
-14
@@ -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))
|
||||
|
||||
@@ -54,6 +54,7 @@ pub enum Query {
|
||||
AUTH_INSERT_SESSION,
|
||||
AUTH_USER_BY_NICKNAME,
|
||||
AUTH_USER_BY_EMAIL,
|
||||
AUTH_USER_BY_SHARE_IDENTIFIER,
|
||||
USER_ATTACH_WORKSPACE,
|
||||
USER_ATTACH_PAD,
|
||||
USER_LIST_WORKSPACES,
|
||||
@@ -188,6 +189,7 @@ pub const AUTH_USER_BY_SESSION: Query = Query::AUTH_USER_BY_SESSION;
|
||||
pub const AUTH_INSERT_SESSION: Query = Query::AUTH_INSERT_SESSION;
|
||||
pub const AUTH_USER_BY_NICKNAME: Query = Query::AUTH_USER_BY_NICKNAME;
|
||||
pub const AUTH_USER_BY_EMAIL: Query = Query::AUTH_USER_BY_EMAIL;
|
||||
pub const AUTH_USER_BY_SHARE_IDENTIFIER: Query = Query::AUTH_USER_BY_SHARE_IDENTIFIER;
|
||||
pub const USER_ATTACH_WORKSPACE: Query = Query::USER_ATTACH_WORKSPACE;
|
||||
pub const USER_ATTACH_PAD: Query = Query::USER_ATTACH_PAD;
|
||||
pub const USER_LIST_WORKSPACES: Query = Query::USER_LIST_WORKSPACES;
|
||||
|
||||
@@ -49,6 +49,7 @@ pub fn get(query: Query) -> &'static str {
|
||||
Query::AUTH_INSERT_SESSION => r#"INSERT INTO user_sessions (token, user_id, expires_at) VALUES (?, ?, ?)"#,
|
||||
Query::AUTH_USER_BY_NICKNAME => r#"SELECT id, nickname, email, CAST(password_hash AS CHAR CHARACTER SET utf8mb4) AS password_hash, confirmed_at, CAST(CASE WHEN is_active THEN 1 ELSE 0 END AS SIGNED) AS is_active FROM users WHERE nickname_key = ?"#,
|
||||
Query::AUTH_USER_BY_EMAIL => r#"SELECT id, nickname, email, CAST(password_hash AS CHAR CHARACTER SET utf8mb4) AS password_hash, confirmed_at, CAST(CASE WHEN is_active THEN 1 ELSE 0 END AS SIGNED) AS is_active FROM users WHERE email_key = ?"#,
|
||||
Query::AUTH_USER_BY_SHARE_IDENTIFIER => r#"SELECT id, nickname, email, CAST(password_hash AS CHAR CHARACTER SET utf8mb4) AS password_hash, confirmed_at, CAST(CASE WHEN is_active THEN 1 ELSE 0 END AS SIGNED) AS is_active FROM users JOIN (SELECT ? AS identifier) lookup ON 1 = 1 WHERE is_active = 1 AND (email_key = lookup.identifier OR nickname_key = lookup.identifier OR LOWER(external_id) = lookup.identifier) LIMIT 1"#,
|
||||
Query::USER_ATTACH_WORKSPACE => r#"INSERT INTO user_workspaces (user_id, workspace_id) SELECT ?, id FROM workspaces WHERE slug = ?"#,
|
||||
Query::USER_ATTACH_PAD => r#"INSERT INTO user_pads (user_id, pad_id) SELECT ?, id FROM pads WHERE slug = ?"#,
|
||||
Query::USER_LIST_WORKSPACES => r#"SELECT w.slug, CAST(w.title AS CHAR CHARACTER SET utf8mb4) AS title, CASE WHEN w.password_hash IS NULL THEN 0 ELSE 1 END AS protected, w.updated_at, CASE WHEN w.is_private THEN 1 ELSE 0 END AS private, 1 AS owned, 'rw' AS permission, '' AS shared_by FROM user_workspaces uw JOIN workspaces w ON w.id = uw.workspace_id WHERE uw.user_id = ? UNION SELECT w.slug, CAST(w.title AS CHAR CHARACTER SET utf8mb4) AS title, CASE WHEN w.password_hash IS NULL THEN 0 ELSE 1 END, w.updated_at, CASE WHEN w.is_private THEN 1 ELSE 0 END, 0, rp.permission, COALESCE((SELECT u.nickname FROM user_workspaces owner_uw JOIN users u ON u.id = owner_uw.user_id WHERE owner_uw.workspace_id = w.id LIMIT 1), 'Unknown user') AS shared_by FROM resource_permissions rp JOIN workspaces w ON w.slug = rp.resource_slug WHERE rp.resource_kind = 'workspace' AND rp.user_id = ? ORDER BY updated_at DESC"#,
|
||||
|
||||
@@ -49,6 +49,7 @@ pub fn get(query: Query) -> &'static str {
|
||||
Query::AUTH_INSERT_SESSION => r#"INSERT INTO user_sessions (token, user_id, expires_at) VALUES ($1, $2, $3)"#,
|
||||
Query::AUTH_USER_BY_NICKNAME => r#"SELECT id, nickname, email, password_hash, confirmed_at, CAST(CASE WHEN is_active THEN 1 ELSE 0 END AS BIGINT) AS is_active FROM users WHERE nickname_key = $1"#,
|
||||
Query::AUTH_USER_BY_EMAIL => r#"SELECT id, nickname, email, password_hash, confirmed_at, CAST(CASE WHEN is_active THEN 1 ELSE 0 END AS BIGINT) AS is_active FROM users WHERE email_key = $1"#,
|
||||
Query::AUTH_USER_BY_SHARE_IDENTIFIER => r#"SELECT id, nickname, email, password_hash, confirmed_at, CAST(CASE WHEN is_active THEN 1 ELSE 0 END AS BIGINT) AS is_active FROM users WHERE is_active = TRUE AND (email_key = $1 OR nickname_key = $1 OR LOWER(external_id) = $1) LIMIT 1"#,
|
||||
Query::USER_ATTACH_WORKSPACE => r#"INSERT INTO user_workspaces (user_id, workspace_id) SELECT $1, id FROM workspaces WHERE slug = $2"#,
|
||||
Query::USER_ATTACH_PAD => r#"INSERT INTO user_pads (user_id, pad_id) SELECT $1, id FROM pads WHERE slug = $2"#,
|
||||
Query::USER_LIST_WORKSPACES => r#"SELECT w.slug, w.title, CAST(CASE WHEN w.password_hash IS NULL THEN 0 ELSE 1 END AS BIGINT) AS protected, w.updated_at, CAST(CASE WHEN w.is_private THEN 1 ELSE 0 END AS BIGINT) AS private, CAST(1 AS BIGINT) AS owned, 'rw' AS permission, '' AS shared_by FROM user_workspaces uw JOIN workspaces w ON w.id = uw.workspace_id WHERE uw.user_id = $1 UNION SELECT w.slug, w.title, CAST(CASE WHEN w.password_hash IS NULL THEN 0 ELSE 1 END AS BIGINT), w.updated_at, CAST(CASE WHEN w.is_private THEN 1 ELSE 0 END AS BIGINT), CAST(0 AS BIGINT), rp.permission, COALESCE((SELECT u.nickname FROM user_workspaces owner_uw JOIN users u ON u.id = owner_uw.user_id WHERE owner_uw.workspace_id = w.id LIMIT 1), 'Unknown user') AS shared_by FROM resource_permissions rp JOIN workspaces w ON w.slug = rp.resource_slug WHERE rp.resource_kind = 'workspace' AND rp.user_id = $2 ORDER BY updated_at DESC"#,
|
||||
|
||||
@@ -49,6 +49,7 @@ pub fn get(query: Query) -> &'static str {
|
||||
Query::AUTH_INSERT_SESSION => r#"INSERT INTO user_sessions (token, user_id, expires_at) VALUES (?, ?, ?)"#,
|
||||
Query::AUTH_USER_BY_NICKNAME => r#"SELECT id, nickname, email, password_hash, confirmed_at, is_active FROM users WHERE nickname_key = ?"#,
|
||||
Query::AUTH_USER_BY_EMAIL => r#"SELECT id, nickname, email, password_hash, confirmed_at, is_active FROM users WHERE email_key = ?"#,
|
||||
Query::AUTH_USER_BY_SHARE_IDENTIFIER => r#"SELECT id, nickname, email, password_hash, confirmed_at, CASE WHEN is_active THEN 1 ELSE 0 END AS is_active FROM users WHERE is_active = 1 AND (email_key = ?1 OR nickname_key = ?1 OR LOWER(external_id) = ?1) LIMIT 1"#,
|
||||
Query::USER_ATTACH_WORKSPACE => r#"INSERT INTO user_workspaces (user_id, workspace_id) SELECT ?, id FROM workspaces WHERE slug = ?"#,
|
||||
Query::USER_ATTACH_PAD => r#"INSERT INTO user_pads (user_id, pad_id) SELECT ?, id FROM pads WHERE slug = ?"#,
|
||||
Query::USER_LIST_WORKSPACES => r#"SELECT w.slug, w.title, CASE WHEN w.password_hash IS NULL THEN 0 ELSE 1 END AS protected, w.updated_at, CASE WHEN w.is_private THEN 1 ELSE 0 END AS private, 1 AS owned, 'rw' AS permission, '' AS shared_by FROM user_workspaces uw JOIN workspaces w ON w.id = uw.workspace_id WHERE uw.user_id = ? UNION SELECT w.slug, w.title, CASE WHEN w.password_hash IS NULL THEN 0 ELSE 1 END, w.updated_at, CASE WHEN w.is_private THEN 1 ELSE 0 END, 0, rp.permission, COALESCE((SELECT u.nickname FROM user_workspaces owner_uw JOIN users u ON u.id = owner_uw.user_id WHERE owner_uw.workspace_id = w.id LIMIT 1), 'Unknown user') AS shared_by FROM resource_permissions rp JOIN workspaces w ON w.slug = rp.resource_slug WHERE rp.resource_kind = 'workspace' AND rp.user_id = ? ORDER BY updated_at DESC"#,
|
||||
|
||||
Reference in New Issue
Block a user