Skip to content

Commit

Permalink
feat(audit-logs): Extending the audit logs api
Browse files Browse the repository at this point in the history
Including things like RunAction and ChangeSet manipulation in the audidt logs
  • Loading branch information
stack72 committed Nov 4, 2024
1 parent 6cc2983 commit 5c05eb4
Show file tree
Hide file tree
Showing 14 changed files with 254 additions and 20 deletions.
2 changes: 1 addition & 1 deletion app/web/src/components/AuditLogHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
header.id !== 'json' &&
'cursor-pointer hover:underline',
header.id === 'json' && 'w-8 px-2xs',
themeClasses('bg-shade-0', 'bg-shade-100'),
themeClasses('bg-neutral-400 text-black', 'bg-shade-100'),
)
"
@mousedown="startActive"
Expand Down
10 changes: 6 additions & 4 deletions app/web/src/components/Workspace/WorkspaceAuditLog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,10 @@
clsx(
'h-lg text-sm',
rowCollapseState[Number(row.id)]
? 'bg-action-300'
? themeClasses('bg-action-200', 'bg-action-900')
: themeClasses(
'odd:bg-neutral-200 even:bg-neutral-100 hover:bg-action-200',
'odd:bg-neutral-700 even:bg-neutral-800 hover:bg-action-200',
'odd:bg-neutral-200 even:bg-neutral-100 hover:border hover:border-action-500',
'odd:bg-neutral-700 even:bg-neutral-800 hover:border hover:border-action-300',
),
)
"
Expand Down Expand Up @@ -190,7 +190,9 @@ const DEFAULT_FILTERS = {
excludeSystemUser: false,
kindFilter: [],
serviceFilter: [],
changeSetFilter: [changeSetsStore.selectedChangeSetId],
changeSetFilter: changeSetsStore.headSelected
? []
: [changeSetsStore.selectedChangeSetId],
userFilter: [],
} as LogFilters;
const currentFilters = ref<LogFilters>({ ...DEFAULT_FILTERS });
Expand Down
7 changes: 3 additions & 4 deletions lib/dal/src/audit_logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,13 +226,12 @@ async fn assemble_for_list(
.map_err(Box::new)?
.ok_or(AuditLoggingError::ChangeSetNotFound(change_set_id.into()))?;
match change_set.status {
ChangeSetStatus::Abandoned
| ChangeSetStatus::Failed
| ChangeSetStatus::Rejected => {
ChangeSetStatus::Failed | ChangeSetStatus::Rejected => {
trace!(?change_set.status, ?change_set.id, "skipping change set for audit log assembly due to status");
return Ok(None);
}
ChangeSetStatus::Applied
ChangeSetStatus::Abandoned
| ChangeSetStatus::Applied
| ChangeSetStatus::Approved
| ChangeSetStatus::NeedsAbandonApproval
| ChangeSetStatus::NeedsApproval
Expand Down
5 changes: 5 additions & 0 deletions lib/dal/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,11 @@ impl DalContext {
}

pub async fn commit_no_rebase(&self) -> TransactionsResult<()> {
// Since we are not rebasing, we need to write the final message and flush all
// pending audit logs.
self.write_audit_log_final_message().await?;
self.publish_pending_audit_logs(None, None).await?;

if self.blocking {
self.blocking_commit_internal(DelayedRebaseWithReply::NoUpdates)
.await?;
Expand Down
3 changes: 3 additions & 0 deletions lib/dal/src/job/consumer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::billing_publish::BillingPublishError;
use crate::diagram::DiagramError;
use crate::prop::PropError;
use crate::validation::ValidationError;
use crate::FuncError;
use crate::{
action::prototype::ActionPrototypeError, action::ActionError,
attribute::value::AttributeValueError,
Expand Down Expand Up @@ -49,6 +50,8 @@ pub enum JobConsumerError {
DependentValueUpdate(#[from] DependentValueUpdateError),
#[error("diagram error: {0}")]
Diagram(#[from] DiagramError),
#[error("func error: {0}")]
Func(#[from] FuncError),
#[error("Invalid job arguments. Expected: {0} Actual: {1:?}")]
InvalidArguments(String, Vec<Value>),
#[error("std io error: {0}")]
Expand Down
23 changes: 21 additions & 2 deletions lib/dal/src/job/definition/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{

use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use si_events::{ActionResultState, FuncRunId};
use si_events::{audit_log::AuditLogKind, ActionResultState, FuncRunId};
use telemetry::prelude::*;
use telemetry_utils::metric;
use veritech_client::{ActionRunResultSuccess, ResourceStatus};
Expand All @@ -24,7 +24,8 @@ use crate::{
},
producer::{JobProducer, JobProducerResult},
},
AccessBuilder, ActionPrototypeId, Component, ComponentId, DalContext, Visibility, WsEvent,
AccessBuilder, ActionPrototypeId, Component, ComponentId, DalContext, Func, Visibility,
WsEvent,
};

#[derive(Debug, Deserialize, Serialize)]
Expand Down Expand Up @@ -212,11 +213,14 @@ async fn process_execution(
) -> JobConsumerResult<()> {
let prototype_id = Action::prototype_id(ctx, action_id).await?;
let prototype = ActionPrototype::get_by_id(ctx, prototype_id).await?;
let func_id = ActionPrototype::func_id(ctx, prototype_id).await?;
let func = Func::get_by_id_or_error(ctx, func_id).await?;

let component_id = Action::component_id(ctx, action_id)
.await?
.ok_or(ActionError::ComponentNotFoundForAction(action_id))?;
let component = Component::get_by_id(ctx, component_id).await?;
let mut success = false;
if let Some(run_result) = action_run_result {
// Set the resource if we have a payload, regardless of status *and* assemble a
// summary
Expand All @@ -235,6 +239,8 @@ async fn process_execution(
}

if run_result.status == ResourceStatus::Ok {
success = true;

// Remove `ActionId` from graph as the execution succeeded
Action::remove_by_id(ctx, action_id).await?;

Expand Down Expand Up @@ -294,6 +300,19 @@ async fn process_execution(
.publish_on_commit(ctx)
.await?;

ctx.write_audit_log(
AuditLogKind::ActionRun {
prototype_id: prototype_id.into(),
action_kind: prototype.kind.into(),
func_id: func.id.into(),
func_name: func.name.clone(),
func_display_name: func.display_name,
run_status: success,
},
func.name,
)
.await?;

// Send the rebase request with the resource updated (if applicable)
ctx.commit().await?;
ctx.update_snapshot_to_visibility().await?;
Expand Down
19 changes: 19 additions & 0 deletions lib/sdf-server/src/service/action/cancel.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use axum::Json;
use dal::action::prototype::ActionPrototype;
use dal::action::Action;
use dal::Func;
use dal::{action::ActionId, Visibility, WsEvent};
use serde::{Deserialize, Serialize};
use si_events::audit_log::AuditLogKind;

use super::ActionResult;
use crate::extract::{AccessBuilder, HandlerContext};
Expand All @@ -21,6 +24,22 @@ pub async fn cancel(
) -> ActionResult<()> {
let ctx = builder.build(request_ctx.build(request.visibility)).await?;
for action_id in request.ids {
let prototype_id = Action::prototype_id(&ctx, action_id).await?;
let prototype = ActionPrototype::get_by_id(&ctx, prototype_id).await?;
let func_id = ActionPrototype::func_id(&ctx, prototype_id).await?;
let func = Func::get_by_id_or_error(&ctx, func_id).await?;
ctx.write_audit_log(
AuditLogKind::CancelAction {
prototype_id: prototype_id.into(),
action_kind: prototype.kind.into(),
func_id: func_id.into(),
func_display_name: func.display_name,
func_name: func.name.clone(),
},
func.name,
)
.await?;

Action::remove_by_id(&ctx, action_id).await?;
}
WsEvent::action_list_updated(&ctx)
Expand Down
22 changes: 20 additions & 2 deletions lib/sdf-server/src/service/action/put_on_hold.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use axum::Json;
use dal::{
action::{Action, ActionId, ActionState},
Visibility, WsEvent,
action::{prototype::ActionPrototype, Action, ActionId, ActionState},
Func, Visibility, WsEvent,
};
use serde::{Deserialize, Serialize};
use si_events::audit_log::AuditLogKind;

use super::ActionResult;
use crate::{
Expand Down Expand Up @@ -36,6 +37,23 @@ pub async fn put_on_hold(
}

Action::set_state(&ctx, action.id(), ActionState::OnHold).await?;

let prototype_id = Action::prototype_id(&ctx, action.id()).await?;
let prototype = ActionPrototype::get_by_id(&ctx, prototype_id).await?;
let func_id = ActionPrototype::func_id(&ctx, prototype_id).await?;
let func = Func::get_by_id_or_error(&ctx, func_id).await?;

ctx.write_audit_log(
AuditLogKind::PutActionOnHold {
prototype_id: prototype.id().into(),
action_kind: prototype.kind.into(),
func_id: func_id.into(),
func_display_name: func.display_name,
func_name: func.name.clone(),
},
func.name,
)
.await?;
}
WsEvent::action_list_updated(&ctx)
.await?
Expand Down
6 changes: 6 additions & 0 deletions lib/sdf-server/src/service/change_set/abandon_change_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use axum::{
};
use dal::{change_set::ChangeSet, ChangeSetId};
use serde::{Deserialize, Serialize};
use si_events::audit_log::AuditLogKind;

use super::ChangeSetResult;
use crate::{
Expand Down Expand Up @@ -41,6 +42,8 @@ pub async fn abandon_change_set(
.await?
.ok_or(ChangeSetError::ChangeSetNotFound)?;

let name = change_set.clone().name;

ctx.update_visibility_and_snapshot_to_visibility(change_set.id)
.await?;
change_set.abandon(&ctx).await?;
Expand All @@ -56,6 +59,9 @@ pub async fn abandon_change_set(
}),
);

ctx.write_audit_log(AuditLogKind::AbandonChangeset {}, name)
.await?;

ctx.commit_no_rebase().await?;

Ok(())
Expand Down
16 changes: 15 additions & 1 deletion lib/sdf-server/src/service/change_set/add_action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ use dal::{
prototype::{ActionKind, ActionPrototype},
Action,
},
ActionPrototypeId, ChangeSet, Component, ComponentId, Visibility,
ActionPrototypeId, ChangeSet, Component, ComponentId, Func, Visibility,
};
use serde::{Deserialize, Serialize};
use si_events::audit_log::AuditLogKind;

use super::ChangeSetResult;
use crate::{
Expand Down Expand Up @@ -53,6 +54,8 @@ pub async fn add_action(

let component = Component::get_by_id(&ctx, request.component_id).await?;
let action = Action::new(&ctx, request.prototype_id, Some(request.component_id)).await?;
let func_id = ActionPrototype::func_id(&ctx, prototype.id).await?;
let func = Func::get_by_id_or_error(&ctx, func_id).await?;
track(
&posthog_client,
&ctx,
Expand All @@ -68,6 +71,17 @@ pub async fn add_action(
}),
);
// todo add ws event here
ctx.write_audit_log(
AuditLogKind::AddAction {
prototype_id: prototype.id().into(),
action_kind: prototype.kind.into(),
func_id: func_id.into(),
func_display_name: func.display_name,
func_name: func.name.clone(),
},
func.name,
)
.await?;

ctx.commit().await?;

Expand Down
4 changes: 4 additions & 0 deletions lib/sdf-server/src/service/change_set/apply_change_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use axum::{
};
use dal::{change_set::ChangeSet, Func, Schema, SchemaVariant, Visibility};
use serde::{Deserialize, Serialize};
use si_events::audit_log::AuditLogKind;

use crate::{
extract::{AccessBuilder, HandlerContext, PosthogClient},
Expand Down Expand Up @@ -85,6 +86,9 @@ pub async fn apply_change_set(
}),
);

ctx.write_audit_log(AuditLogKind::ApplyChangeset {}, "-".to_string())
.await?;

// // If anything fails with uploading the workspace backup module, just log it. We shouldn't
// // have the change set apply itself fail because of this.
// tokio::task::spawn(
Expand Down
9 changes: 8 additions & 1 deletion lib/sdf-server/src/service/change_set/create_change_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use axum::Json;
use dal::change_set::ChangeSet;
use dal::WsEvent;
use serde::{Deserialize, Serialize};
use si_events::audit_log::AuditLogKind;

use super::ChangeSetResult;
use crate::{
Expand Down Expand Up @@ -45,10 +46,16 @@ pub async fn create_change_set(
&host_name,
"create_change_set",
serde_json::json!({
"change_set_name": change_set_name,
"change_set_name": change_set_name.clone(),
}),
);

ctx.write_audit_log(
AuditLogKind::CreateChangeset {},
change_set_name.to_string(),
)
.await?;

WsEvent::change_set_created(&ctx, change_set.id)
.await?
.publish_on_commit(&ctx)
Expand Down
37 changes: 36 additions & 1 deletion lib/si-events-rs/src/audit_log/v2.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use serde::{Deserialize, Serialize};
use strum::Display;

use crate::{Actor, AttributeValueId, ChangeSetId, ComponentId, PropId, SchemaVariantId, SecretId};
use crate::{
ActionKind, ActionPrototypeId, Actor, AttributeValueId, ChangeSetId, ComponentId, FuncId,
PropId, SchemaVariantId, SecretId,
};

#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct AuditLogV2 {
Expand Down Expand Up @@ -50,4 +53,36 @@ pub enum AuditLogKindV2 {
after_secret_name: Option<String>,
after_secret_id: Option<SecretId>,
},
ApplyChangeset,
AddAction {
prototype_id: ActionPrototypeId,
action_kind: ActionKind,
func_id: FuncId,
func_display_name: Option<String>,
func_name: String,
},
PutActionOnHold {
prototype_id: ActionPrototypeId,
action_kind: ActionKind,
func_id: FuncId,
func_display_name: Option<String>,
func_name: String,
},
CancelAction {
prototype_id: ActionPrototypeId,
action_kind: ActionKind,
func_id: FuncId,
func_display_name: Option<String>,
func_name: String,
},
CreateChangeset,
AbandonChangeset,
ActionRun {
prototype_id: ActionPrototypeId,
action_kind: ActionKind,
func_id: FuncId,
func_display_name: Option<String>,
func_name: String,
run_status: bool,
},
}
Loading

0 comments on commit 5c05eb4

Please sign in to comment.