Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Response handler submessages and Role management improvements #9

Closed
wants to merge 15 commits into from
33 changes: 33 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ ripemd = "0.1.3"
serde = { version = "1.0.145", default-features = false, features = ["derive"] }
tiny-keccak = { version = "2.0.2", features = ["keccak"] }
hex = "0.4.3"
base64 = "0.21.7"
base64 = "0.21.7"
strum = "0.26"
strum_macros = "0.26.4"
98 changes: 98 additions & 0 deletions src/access_control/contract.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use crate::access_control::AccessControl;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, Deps, DepsMut, Env, MessageInfo, Response, StdResult};
use strum::IntoEnumIterator;

#[cw_serde]
pub struct QueryAllAddressesWithRoleResponse {
pub addresses: Vec<Addr>,
}

#[cw_serde]
pub struct QueryRolesResponse<T> {
pub roles: Vec<T>,
}

pub fn query_all_addresses_with_role<T: AsRef<str>>(
deps: Deps,
role: T,
) -> StdResult<QueryAllAddressesWithRoleResponse> {
let addresses_with_role: StdResult<Vec<Addr>> =
AccessControl::get_all_addresses_with_role(deps.storage, &role).collect();

Ok(QueryAllAddressesWithRoleResponse {
addresses: addresses_with_role?,
})
}

pub fn query_roles<T: IntoEnumIterator + AsRef<str>>(
deps: Deps,
addr: Addr,
) -> StdResult<QueryRolesResponse<T>> {
let roles = T::iter() // Automatically iterate over all roles
.filter(|role| AccessControl::has_role(deps.storage, role, &addr))
.collect();

Ok(QueryRolesResponse { roles })
}

pub fn execute_grant_role_by_admin_role<T: AsRef<str>>(
deps: DepsMut,
env: Env,
info: MessageInfo,
role: T,
addr: Addr,
required_sender_role: T,
) -> StdResult<Response> {
AccessControl::ensure_has_role_or_superadmin(
&deps.as_ref(),
&env,
&required_sender_role,
&info.sender,
)?;
AccessControl::storage_set_role(deps.storage, &role, &addr)?;

Ok(Response::new()
.add_attribute("action", "grant_role")
.add_attribute("sender", info.sender)
.add_attribute("role", role.as_ref())
.add_attribute("addr", addr.to_string()))
}

pub fn execute_revoke_role_by_admin_role<T: AsRef<str>>(
deps: DepsMut,
env: Env,
info: MessageInfo,
role: T,
addr: Addr,
required_sender_role: T,
) -> StdResult<Response> {
AccessControl::ensure_has_role_or_superadmin(
&deps.as_ref(),
&env,
&required_sender_role,
&info.sender,
)?;
AccessControl::storage_remove_role(deps.storage, &role, &addr)?;

Ok(Response::new()
.add_attribute("action", "revoke_role")
.add_attribute("sender", info.sender)
.add_attribute("role", role.as_ref())
.add_attribute("addr", addr.to_string()))
}

pub fn execute_renounce_role<T: AsRef<str>>(
deps: DepsMut,
_env: Env,
info: MessageInfo,
role: T,
) -> StdResult<Response> {
AccessControl::ensure_has_role(&deps.as_ref(), &role, &info.sender)?;
AccessControl::storage_remove_role(deps.storage, &role, &info.sender)?;

Ok(Response::new()
.add_attribute("action", "renounce_role")
.add_attribute("sender", info.sender)
.add_attribute("role", role.as_ref()))
}
20 changes: 20 additions & 0 deletions src/access_control/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use cosmwasm_std::{Addr, StdError};

pub fn no_role_error<T: AsRef<str>>(address: &Addr, role: &T) -> StdError {
StdError::generic_err(format!(
"Address {} does not have role {}",
address,
role.as_ref()
))
}
pub fn insufficient_permissions_error() -> StdError {
StdError::generic_err("Insufficient permissions")
}

pub fn role_already_exist_error<T: AsRef<str>>(role: &T) -> StdError {
StdError::generic_err(format!("Role {} already exist", role.as_ref()))
}

pub fn sender_is_not_role_admin_error<T: AsRef<str>>(role: &T) -> StdError {
StdError::generic_err(format!("Sender is not admin of role {}", role.as_ref()))
}
3 changes: 3 additions & 0 deletions src/access_control/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
mod contract;
pub mod error;
mod role;

pub use contract::*;
pub use role::AccessControl;
Loading