Skip to content

Commit

Permalink
feat: add clear role and system check for execution
Browse files Browse the repository at this point in the history
  • Loading branch information
ftupas committed Jun 12, 2023
1 parent d425c9d commit f6a6319
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 0 deletions.
2 changes: 2 additions & 0 deletions crates/dojo-core/src/interfaces.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ trait IWorld {
fn set_executor(contract_address: ContractAddress);
fn is_authorized(system: ShortString, component: ShortString, execution_role: AuthRole) -> bool;
fn is_account_admin() -> bool;
fn is_system_for_execution(system: ShortString) -> bool;
fn delete_entity(context: Context, component: ShortString, query: Query);
fn assume_role(role_id: u250, systems: Array<ShortString>);
fn clear_role(systems: Array<ShortString>);
fn execution_role() -> u250;
fn system_components(system: ShortString) -> Array<(ShortString, bool)>;
}
Expand Down
39 changes: 39 additions & 0 deletions crates/dojo-core/src/world.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,30 @@ mod World {
_execution_role::write(caller, role_id);
}

/// Clear the execution role and systems for execution
///
/// # Arguments
///
/// * `systems` - The systems to be cleared
#[external]
fn clear_role(systems: Array<ShortString>) {
// Clear the execution role
let caller = get_tx_info().unbox().account_contract_address;
_execution_role::write(caller, 0.into());

// Clear systems for execution
let mut index = 0;
let len = systems.len();
loop {
if index == len {
break ();
}
let system = *systems[index];
systems_for_execution::write((caller, system), false);
index += 1;
};
}

/// Get the assumed execution role
///
/// # Arguments
Expand Down Expand Up @@ -446,6 +470,21 @@ mod World {
ISystemLibraryDispatcher { class_hash }.dependencies()
}

/// Check if the system is part of the systems for execution
///
/// # Arguments
///
/// * `system` - The system to be retrieved
///
/// # Returns
///
/// * `bool` - True if the system is part of the systems for execution
#[view]
fn is_system_for_execution(system: ShortString) -> bool {
let caller = get_tx_info().unbox().account_contract_address;
systems_for_execution::read((caller, system))
}

/// Internals

/// If no role is set, check if the system's default scoped permission to write to the component is authorized
Expand Down
86 changes: 86 additions & 0 deletions crates/dojo-core/tests/src/world.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use array::ArrayTrait;
use array::SpanTrait;
use clone::Clone;
use core::result::ResultTrait;
use traits::Into;
use traits::TryInto;
Expand Down Expand Up @@ -132,6 +133,91 @@ fn test_system_components() {
assert(write_foo == true, 'Buzz should write Foo');
}

#[test]
#[available_gas(9000000)]
fn test_assume_role() {
// Spawn empty world
let world = spawn_empty_world();

world.register_system(Bar::TEST_CLASS_HASH.try_into().unwrap());
world.register_component(FooComponent::TEST_CLASS_HASH.try_into().unwrap());

// Prepare route
let mut route = ArrayTrait::new();
let target_id = 'Bar'.into();
let role_id = 'FooWriter'.into();
let resource_id = 'Foo'.into();
let r = Route { target_id, role_id, resource_id, };
route.append(r);

// Initialize world
world.initialize(route);

// Assume FooWriter role
let mut systems = ArrayTrait::new();
systems.append('Bar'.into());
world.assume_role('FooWriter'.into(), systems);

// Get execution role
let role = world.execution_role();
assert(role == 'FooWriter'.into(), 'role not assumed');

// Get systems for execution
let is_system_for_execution = world.is_system_for_execution('Bar'.into());
assert(is_system_for_execution == true, 'system not for execution');

// Admin assumes Admin role
let mut systems = ArrayTrait::new();
systems.append('Bar'.into());
world.assume_role('Admin'.into(), systems);
}

#[test]
#[available_gas(9000000)]
fn test_clear_role() {
// Spawn empty world
let world = spawn_empty_world();

world.register_system(Bar::TEST_CLASS_HASH.try_into().unwrap());
world.register_component(FooComponent::TEST_CLASS_HASH.try_into().unwrap());

// Prepare route
let mut route = ArrayTrait::new();
let target_id = 'Bar'.into();
let role_id = 'FooWriter'.into();
let resource_id = 'Foo'.into();
let r = Route { target_id, role_id, resource_id, };
route.append(r);

// Initialize world
world.initialize(route);

// Assume FooWriter role
let mut systems = ArrayTrait::new();
systems.append('Bar'.into());
let cloned_systems = systems.clone();
world.assume_role('FooWriter'.into(), systems);

// Get execution role
let role = world.execution_role();
assert(role == 'FooWriter'.into(), 'role not assumed');

// Get systems for execution
let is_system_for_execution = world.is_system_for_execution('Bar'.into());
assert(is_system_for_execution == true, 'system not for execution');

// Clear role
world.clear_role(cloned_systems);

// Get execution role
let role = world.execution_role();
assert(role == 0.into(), 'role not cleared');

// Get systems for execution
let is_system_for_execution = world.is_system_for_execution('Bar'.into());
assert(is_system_for_execution == false, 'system still for execution');
}

#[test]
#[available_gas(9000000)]
fn test_initialize() {
Expand Down

0 comments on commit f6a6319

Please sign in to comment.