mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-21 08:02:38 +00:00
feat: improve premissioned audit logs (#3793)
* feat: improve premissioned audit logs * chore: update ee ref * fix: build * fix: sqlx
This commit is contained in:
@@ -34,7 +34,7 @@ use itertools::Itertools;
|
||||
use regex::Regex;
|
||||
|
||||
use uuid::Uuid;
|
||||
use windmill_audit::audit_ee::audit_log;
|
||||
use windmill_audit::audit_ee::{audit_log, AuditAuthor, AuditAuthorable};
|
||||
use windmill_audit::ActionKind;
|
||||
use windmill_common::db::UserDB;
|
||||
use windmill_common::s3_helpers::LargeFileStorage;
|
||||
@@ -448,7 +448,7 @@ async fn edit_slack_command(
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed.username,
|
||||
&authed,
|
||||
"workspaces.edit_command_script",
|
||||
ActionKind::Update,
|
||||
&w_id,
|
||||
@@ -533,7 +533,7 @@ async fn edit_deploy_to(
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed.username,
|
||||
&authed,
|
||||
"workspaces.edit_deploy_to",
|
||||
ActionKind::Update,
|
||||
&w_id,
|
||||
@@ -571,7 +571,8 @@ async fn auto_add_user(
|
||||
w_id: &str,
|
||||
operator: &bool,
|
||||
tx: &mut Transaction<'_, Postgres>,
|
||||
) -> Result<()> {
|
||||
authorable: &impl AuditAuthorable,
|
||||
) -> Result<String> {
|
||||
let automate_username_creation = sqlx::query_scalar!(
|
||||
"SELECT value FROM global_settings WHERE name = $1",
|
||||
AUTOMATE_USERNAME_CREATION_SETTING,
|
||||
@@ -645,9 +646,24 @@ async fn auto_add_user(
|
||||
)
|
||||
.execute(&mut **tx)
|
||||
.await?;
|
||||
let audit_author = if authorable.username() == authorable.email() && authorable.email() == email
|
||||
{
|
||||
// if the user is auto adding themselves (e.g. by joining the instance), we use their newly created workspace username for audit logs
|
||||
AuditAuthor {
|
||||
username: username.clone(),
|
||||
email: email.to_string(),
|
||||
username_override: None,
|
||||
}
|
||||
} else {
|
||||
AuditAuthor {
|
||||
username: authorable.username().to_string(),
|
||||
email: authorable.email().to_string(),
|
||||
username_override: authorable.username_override().map(|x| x.to_string()),
|
||||
}
|
||||
};
|
||||
audit_log(
|
||||
&mut **tx,
|
||||
&username,
|
||||
&audit_author,
|
||||
"users.auto_invite_add",
|
||||
ActionKind::Create,
|
||||
&w_id,
|
||||
@@ -655,7 +671,7 @@ async fn auto_add_user(
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
Ok(username)
|
||||
}
|
||||
|
||||
async fn edit_auto_invite(
|
||||
@@ -720,7 +736,7 @@ async fn edit_auto_invite(
|
||||
.fetch_all(&mut *tx).await?);
|
||||
|
||||
for user in users_to_auto_add.as_ref().unwrap() {
|
||||
auto_add_user(&user.email, &w_id, &operator, &mut tx).await?;
|
||||
auto_add_user(&user.email, &w_id, &operator, &mut tx, &authed).await?;
|
||||
send_email_if_possible(
|
||||
&format!("Added to Windmill's workspace: {w_id}"),
|
||||
&format!(
|
||||
@@ -757,7 +773,7 @@ async fn edit_auto_invite(
|
||||
}
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed.username,
|
||||
&authed,
|
||||
"workspaces.edit_auto_invite_domain",
|
||||
ActionKind::Update,
|
||||
&w_id,
|
||||
@@ -818,7 +834,7 @@ async fn edit_webhook(
|
||||
}
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed.username,
|
||||
&authed,
|
||||
"workspaces.edit_webhook",
|
||||
ActionKind::Update,
|
||||
&w_id,
|
||||
@@ -862,7 +878,7 @@ async fn edit_copilot_config(
|
||||
}
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed.username,
|
||||
&authed,
|
||||
"workspaces.edit_copilot_config",
|
||||
ActionKind::Update,
|
||||
&w_id,
|
||||
@@ -926,7 +942,7 @@ async fn edit_large_file_storage_config(
|
||||
let args_for_audit = format!("{:?}", new_config.large_file_storage);
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed.username,
|
||||
&authed,
|
||||
"workspaces.edit_large_file_storage_config",
|
||||
ActionKind::Update,
|
||||
&w_id,
|
||||
@@ -994,7 +1010,7 @@ async fn edit_git_sync_config(
|
||||
let args_for_audit = format!("{:?}", new_config.git_sync_settings);
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed.username,
|
||||
&authed,
|
||||
"workspaces.edit_git_sync_config",
|
||||
ActionKind::Update,
|
||||
&w_id,
|
||||
@@ -1058,7 +1074,7 @@ async fn edit_default_scripts(
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed.username,
|
||||
&authed,
|
||||
"workspaces.edit_default_scripts",
|
||||
ActionKind::Update,
|
||||
&w_id,
|
||||
@@ -1128,7 +1144,7 @@ async fn edit_default_app(
|
||||
let args_for_audit = format!("{:?}", new_config.default_app_path);
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed.username,
|
||||
&authed,
|
||||
"workspaces.edit_default_app",
|
||||
ActionKind::Update,
|
||||
&w_id,
|
||||
@@ -1221,7 +1237,7 @@ async fn edit_error_handler(
|
||||
}
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed.username,
|
||||
&authed,
|
||||
"workspaces.edit_error_handler",
|
||||
ActionKind::Update,
|
||||
&w_id,
|
||||
@@ -1263,7 +1279,7 @@ async fn set_environment_variable(
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed.username,
|
||||
&authed,
|
||||
"workspace.set_environment_variable",
|
||||
ActionKind::Create,
|
||||
&w_id,
|
||||
@@ -1285,7 +1301,7 @@ async fn set_environment_variable(
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed.username,
|
||||
&authed,
|
||||
"workspace.delete_environment_variable",
|
||||
ActionKind::Delete,
|
||||
&w_id,
|
||||
@@ -1611,7 +1627,7 @@ async fn create_workspace(
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed.username,
|
||||
&authed,
|
||||
"workspaces.create",
|
||||
ActionKind::Create,
|
||||
&nw.id,
|
||||
@@ -1643,7 +1659,7 @@ async fn edit_workspace(
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed.username,
|
||||
&authed,
|
||||
"workspaces.update",
|
||||
ActionKind::Update,
|
||||
&w_id,
|
||||
@@ -1659,9 +1675,9 @@ async fn edit_workspace(
|
||||
async fn archive_workspace(
|
||||
Extension(db): Extension<DB>,
|
||||
Path(w_id): Path<String>,
|
||||
ApiAuthed { is_admin, username, email, .. }: ApiAuthed,
|
||||
authed: ApiAuthed,
|
||||
) -> Result<String> {
|
||||
require_admin(is_admin, &username)?;
|
||||
require_admin(authed.is_admin, &authed.username)?;
|
||||
let mut tx = db.begin().await?;
|
||||
sqlx::query!("UPDATE workspace SET deleted = true WHERE id = $1", &w_id)
|
||||
.execute(&mut *tx)
|
||||
@@ -1669,11 +1685,11 @@ async fn archive_workspace(
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&username,
|
||||
&authed,
|
||||
"workspaces.archive",
|
||||
ActionKind::Update,
|
||||
&w_id,
|
||||
Some(&email),
|
||||
Some(&authed.email),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
@@ -1685,24 +1701,24 @@ async fn archive_workspace(
|
||||
async fn leave_workspace(
|
||||
Extension(db): Extension<DB>,
|
||||
Path(w_id): Path<String>,
|
||||
ApiAuthed { email, username, .. }: ApiAuthed,
|
||||
authed: ApiAuthed,
|
||||
) -> Result<String> {
|
||||
let mut tx = db.begin().await?;
|
||||
sqlx::query!(
|
||||
"DELETE FROM usr WHERE workspace_id = $1 AND email = $2",
|
||||
&w_id,
|
||||
&email
|
||||
&authed.email
|
||||
)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&username,
|
||||
&authed,
|
||||
"workspaces.leave",
|
||||
ActionKind::Delete,
|
||||
&w_id,
|
||||
Some(&email),
|
||||
Some(&authed.email),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
@@ -1714,9 +1730,9 @@ async fn leave_workspace(
|
||||
async fn unarchive_workspace(
|
||||
Extension(db): Extension<DB>,
|
||||
Path(w_id): Path<String>,
|
||||
ApiAuthed { is_admin, username, email, .. }: ApiAuthed,
|
||||
authed: ApiAuthed,
|
||||
) -> Result<String> {
|
||||
require_admin(is_admin, &username)?;
|
||||
require_admin(authed.is_admin, &authed.username)?;
|
||||
let mut tx = db.begin().await?;
|
||||
sqlx::query!("UPDATE workspace SET deleted = false WHERE id = $1", &w_id)
|
||||
.execute(&mut *tx)
|
||||
@@ -1724,11 +1740,11 @@ async fn unarchive_workspace(
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&username,
|
||||
&authed,
|
||||
"workspaces.unarchive",
|
||||
ActionKind::Update,
|
||||
&w_id,
|
||||
Some(&email),
|
||||
Some(&authed.email),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
@@ -1740,7 +1756,7 @@ async fn unarchive_workspace(
|
||||
async fn delete_workspace(
|
||||
Extension(db): Extension<DB>,
|
||||
Path(w_id): Path<String>,
|
||||
ApiAuthed { username, email, .. }: ApiAuthed,
|
||||
authed: ApiAuthed,
|
||||
) -> Result<String> {
|
||||
let w_id = match w_id.as_str() {
|
||||
"starter" => Err(Error::BadRequest(
|
||||
@@ -1752,7 +1768,7 @@ async fn delete_workspace(
|
||||
_ => Ok(w_id),
|
||||
}?;
|
||||
let mut tx = db.begin().await?;
|
||||
require_super_admin(&db, &email).await?;
|
||||
require_super_admin(&db, &authed.email).await?;
|
||||
|
||||
sqlx::query!("DELETE FROM dependency_map WHERE workspace_id = $1", &w_id)
|
||||
.execute(&mut *tx)
|
||||
@@ -1859,11 +1875,11 @@ async fn delete_workspace(
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&username,
|
||||
&authed,
|
||||
"workspaces.delete",
|
||||
ActionKind::Delete,
|
||||
&w_id,
|
||||
Some(&email),
|
||||
Some(&authed.email),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
@@ -1876,6 +1892,7 @@ pub async fn invite_user_to_all_auto_invite_worspaces(
|
||||
db: &DB,
|
||||
email: &str,
|
||||
rsmq: Option<rsmq_async::MultiplexedRsmq>,
|
||||
authorable: &impl AuditAuthorable,
|
||||
) -> Result<()> {
|
||||
let mut tx = db.begin().await?;
|
||||
let domain = email.split('@').last().unwrap();
|
||||
@@ -1890,14 +1907,8 @@ pub async fn invite_user_to_all_auto_invite_worspaces(
|
||||
for r in workspaces {
|
||||
if r.auto_add.is_some() && r.auto_add.unwrap() {
|
||||
let operator = r.auto_invite_operator.unwrap_or(false);
|
||||
auto_add_user(email, &r.workspace_id, &operator, &mut tx).await?;
|
||||
let username = sqlx::query_scalar!(
|
||||
"SELECT username FROM usr WHERE workspace_id = $1 AND email = $2",
|
||||
r.workspace_id,
|
||||
email
|
||||
)
|
||||
.fetch_one(&mut *tx)
|
||||
.await?;
|
||||
let username =
|
||||
auto_add_user(email, &r.workspace_id, &operator, &mut tx, authorable).await?;
|
||||
auto_added_workspace_usernames.push((r.workspace_id, username));
|
||||
} else {
|
||||
sqlx::query!(
|
||||
@@ -1999,14 +2010,14 @@ If you do not have an account on {}, login with SSO or ask an admin to create an
|
||||
}
|
||||
|
||||
async fn add_user(
|
||||
ApiAuthed { username, email, is_admin, .. }: ApiAuthed,
|
||||
authed: ApiAuthed,
|
||||
Extension(db): Extension<DB>,
|
||||
Extension(webhook): Extension<WebhookShared>,
|
||||
Extension(rsmq): Extension<Option<rsmq_async::MultiplexedRsmq>>,
|
||||
Path(w_id): Path<String>,
|
||||
Json(mut nu): Json<NewWorkspaceUser>,
|
||||
) -> Result<(StatusCode, String)> {
|
||||
require_admin(is_admin, &username)?;
|
||||
require_admin(authed.is_admin, &authed.username)?;
|
||||
nu.email = nu.email.to_lowercase();
|
||||
|
||||
let mut tx = db.begin().await?;
|
||||
@@ -2023,7 +2034,7 @@ async fn add_user(
|
||||
if already_exists_email {
|
||||
return Err(Error::BadRequest(format!(
|
||||
"user with email {} already exists in workspace {}",
|
||||
email, w_id
|
||||
nu.email, w_id
|
||||
)));
|
||||
}
|
||||
|
||||
@@ -2091,11 +2102,11 @@ async fn add_user(
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&username,
|
||||
&authed,
|
||||
"users.add_to_workspace",
|
||||
ActionKind::Create,
|
||||
&w_id,
|
||||
Some(&email),
|
||||
Some(&nu.email),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
@@ -2103,8 +2114,8 @@ async fn add_user(
|
||||
tx.commit().await?;
|
||||
|
||||
handle_deployment_metadata(
|
||||
&email,
|
||||
&username,
|
||||
&authed.email,
|
||||
&authed.username,
|
||||
&db,
|
||||
&w_id,
|
||||
windmill_git_sync::DeployedObject::User { email: nu.email.clone() },
|
||||
@@ -2117,9 +2128,10 @@ async fn add_user(
|
||||
send_email_if_possible(
|
||||
&format!("Added to Windmill's workspace: {w_id}"),
|
||||
&format!(
|
||||
"You have been granted access to Windmill's workspace {w_id} by {email}
|
||||
"You have been granted access to Windmill's workspace {w_id} by {}
|
||||
|
||||
If you do not have an account on {}, login with SSO or ask an admin to create an account for you.",
|
||||
authed.email,
|
||||
BASE_URL.read().await.clone()
|
||||
),
|
||||
&nu.email,
|
||||
@@ -2810,7 +2822,7 @@ async fn change_workspace_name(
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed.username,
|
||||
&authed,
|
||||
"workspace.change_workspace_name",
|
||||
ActionKind::Update,
|
||||
&w_id,
|
||||
@@ -3135,7 +3147,7 @@ async fn change_workspace_id(
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed.username,
|
||||
&authed,
|
||||
"workspace.change_workspace_id",
|
||||
ActionKind::Update,
|
||||
&rw.new_id,
|
||||
|
||||
Reference in New Issue
Block a user