-
Notifications
You must be signed in to change notification settings - Fork 285
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ability to set approvers on views in sdf
This commit adds the ability to set approvers on the views with a new set of sdf routes, backed by a new integration test among existing ones. To support this change, we now divide ApprovalRequirements into two separate categories: explicit and virtual. - Explicit requirements are derived from ApprovalRequirementDefinition nodes (new to WorkspaceSnapshotGraphV4!) on the graph from any node with an outgoing HasApprovalRequirement edge - Virtual requirements are derived from examining a list of changes on the fly and are useful for determining if meta changes to permissions require approvals themselves (e.g. if you add a ApprovalRequirementDefinition, we need to determine who can approve that change) Both types of requirements share an inner "rule" type with covers the universal elements of all approval requirements: - The ID of the entity requiring an approval - The kind of entity requiring an approval - The minimum number of approvals for this rule - The approvers of this rule, which can either be individual users or a "permission lookup" bag used to query SpiceDB for who can approve the requirement Back to virtual requirements: not only are they useful for determining meta changes to permissions, but also for creating requirements when nodes are deleted and creating the checksum for new approvals involving deleted nodes. In fact, that is why checksum calculatation now requires the hashes alongside the IDs... you can't get the merkle tree hash for a deleted node! As a result of these changes, detecting changes between two graphs is now fallible (we need to get the node weight in order to get the merkle tree hash). Other changes in this commit include, but are not limited to, the following: - Use UserPk instead of String for return type involving frontend approvals - Re-order enum variants and their discriminants where possible when dealing with ApprovalRequirementDefinition and HasApprovalRequirement - Rename "geometry" dummy data to "view" in deserialize graph integration test because it could be confusing (although it is entirely cosmetic for the purposes of the test) Co-authored-by: Jacob Helwig <[email protected]> Signed-off-by: Nick Gerace <[email protected]>
- Loading branch information
1 parent
8c08d1e
commit 6e97c1a
Showing
42 changed files
with
1,699 additions
and
274 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
//! This module provides functionality for creating, updating, deleting, getting and listing | ||
//! approval requirements when applying a change set. | ||
#![warn( | ||
bad_style, | ||
clippy::missing_panics_doc, | ||
clippy::panic, | ||
clippy::panic_in_result_fn, | ||
clippy::unwrap_in_result, | ||
clippy::unwrap_used, | ||
dead_code, | ||
improper_ctypes, | ||
missing_debug_implementations, | ||
// TODO(nick): restore this and clean up the mess. | ||
// missing_docs, | ||
no_mangle_generic_items, | ||
non_shorthand_field_patterns, | ||
overflowing_literals, | ||
path_statements, | ||
patterns_in_fns_without_body, | ||
unconditional_recursion, | ||
unreachable_pub, | ||
unused, | ||
unused_allocation, | ||
unused_comparisons, | ||
unused_parens, | ||
while_true | ||
)] | ||
|
||
use std::collections::{HashMap, HashSet}; | ||
|
||
use si_events::merkle_tree_hash::MerkleTreeHash; | ||
use si_id::{ulid::Ulid, ApprovalRequirementDefinitionId, EntityId, UserPk}; | ||
use telemetry::prelude::*; | ||
use thiserror::Error; | ||
|
||
use crate::{ | ||
workspace_snapshot::{ | ||
graph::detector::Change, traits::approval_requirement::ApprovalRequirementExt, | ||
}, | ||
DalContext, WorkspaceSnapshotError, | ||
}; | ||
|
||
pub use crate::workspace_snapshot::traits::approval_requirement::{ | ||
ApprovalRequirementApprover, ApprovalRequirementRule, | ||
}; | ||
|
||
#[allow(missing_docs)] | ||
#[derive(Debug, Error)] | ||
pub enum ApprovalRequirementError { | ||
#[error("workspace snapshot error: {0}")] | ||
WorkspaceSnapshot(#[from] WorkspaceSnapshotError), | ||
} | ||
|
||
type Result<T> = std::result::Result<T, ApprovalRequirementError>; | ||
|
||
#[derive(Debug)] | ||
pub struct ApprovalRequirementExplicit { | ||
pub id: ApprovalRequirementDefinitionId, | ||
pub rule: ApprovalRequirementRule, | ||
} | ||
|
||
#[derive(Debug)] | ||
pub enum ApprovalRequirement { | ||
Explicit(ApprovalRequirementExplicit), | ||
Virtual(ApprovalRequirementRule), | ||
} | ||
|
||
impl ApprovalRequirement { | ||
#[instrument( | ||
name = "approval_requirement.new_definition", | ||
level = "debug", | ||
skip_all | ||
)] | ||
pub async fn new_definition( | ||
ctx: &DalContext, | ||
entity_id: impl Into<Ulid>, | ||
minimum_approvers_count: usize, | ||
approvers: HashSet<ApprovalRequirementApprover>, | ||
) -> Result<ApprovalRequirementDefinitionId> { | ||
ctx.workspace_snapshot()? | ||
.new_definition(ctx, entity_id.into(), minimum_approvers_count, approvers) | ||
.await | ||
.map_err(Into::into) | ||
} | ||
|
||
#[instrument( | ||
name = "approval_requirement.remove_definition", | ||
level = "debug", | ||
skip_all | ||
)] | ||
pub async fn remove_definition( | ||
ctx: &DalContext, | ||
id: ApprovalRequirementDefinitionId, | ||
) -> Result<()> { | ||
ctx.workspace_snapshot()? | ||
.remove_definition(id) | ||
.await | ||
.map_err(Into::into) | ||
} | ||
|
||
#[instrument( | ||
name = "approval_requirement.add_individual_approver_for_definition", | ||
level = "debug", | ||
skip_all | ||
)] | ||
pub async fn add_individual_approver_for_definition( | ||
ctx: &DalContext, | ||
id: ApprovalRequirementDefinitionId, | ||
user_id: UserPk, | ||
) -> Result<()> { | ||
ctx.workspace_snapshot()? | ||
.add_individual_approver_for_definition(ctx, id, user_id) | ||
.await | ||
.map_err(Into::into) | ||
} | ||
|
||
#[instrument( | ||
name = "approval_requirement.remove_individual_approver_for_definition", | ||
level = "debug", | ||
skip_all | ||
)] | ||
pub async fn remove_individual_approver_for_definition( | ||
ctx: &DalContext, | ||
id: ApprovalRequirementDefinitionId, | ||
user_id: UserPk, | ||
) -> Result<()> { | ||
ctx.workspace_snapshot()? | ||
.remove_individual_approver_for_definition(ctx, id, user_id) | ||
.await | ||
.map_err(Into::into) | ||
} | ||
|
||
#[instrument(name = "approval_requirement.list", level = "debug", skip_all)] | ||
pub async fn list( | ||
ctx: &DalContext, | ||
changes: &[Change], | ||
) -> Result<(Vec<Self>, HashMap<EntityId, MerkleTreeHash>)> { | ||
ctx.workspace_snapshot()? | ||
.approval_requirements_for_changes(ctx, changes) | ||
.await | ||
.map_err(Into::into) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.