andromeda_std/ado_base/
permissioning.rs1use core::fmt;
2
3use cosmwasm_schema::cw_serde;
4use cosmwasm_std::Env;
5
6use crate::{amp::AndrAddr, common::MillisecondsExpiration, error::ContractError};
7
8#[cw_serde]
9pub enum PermissioningMessage {
10 SetPermission {
11 actor: AndrAddr,
12 action: String,
13 permission: Permission,
14 },
15 RemovePermission {
16 action: String,
17 actor: AndrAddr,
18 },
19 PermissionAction {
20 action: String,
21 },
22 DisableActionPermissioning {
23 action: String,
24 },
25}
26
27#[cw_serde]
28pub struct PermissionInfo {
29 pub permission: Permission,
30 pub action: String,
31 pub actor: String,
32}
33
34#[cw_serde]
35pub struct PermissionedActionsResponse {
36 pub actions: Vec<String>,
37}
38
39#[cw_serde]
47pub enum Permission {
48 Blacklisted(Option<MillisecondsExpiration>),
49 Limited {
50 expiration: Option<MillisecondsExpiration>,
51 uses: u32,
52 },
53 Whitelisted(Option<MillisecondsExpiration>),
54}
55
56impl std::default::Default for Permission {
57 fn default() -> Self {
58 Self::Whitelisted(None)
59 }
60}
61
62impl Permission {
63 pub fn blacklisted(expiration: Option<MillisecondsExpiration>) -> Self {
64 Self::Blacklisted(expiration)
65 }
66
67 pub fn whitelisted(expiration: Option<MillisecondsExpiration>) -> Self {
68 Self::Whitelisted(expiration)
69 }
70
71 pub fn limited(expiration: Option<MillisecondsExpiration>, uses: u32) -> Self {
72 Self::Limited { expiration, uses }
73 }
74
75 pub fn is_permissioned(&self, env: &Env, strict: bool) -> bool {
76 match self {
77 Self::Blacklisted(expiration) => {
78 if let Some(expiration) = expiration {
79 if expiration.is_expired(&env.block) {
80 return true;
81 }
82 }
83 false
84 }
85 Self::Limited { expiration, uses } => {
86 if let Some(expiration) = expiration {
87 if expiration.is_expired(&env.block) {
88 return !strict;
89 }
90 }
91 if *uses == 0 {
92 return !strict;
93 }
94 true
95 }
96 Self::Whitelisted(expiration) => {
97 if let Some(expiration) = expiration {
98 if expiration.is_expired(&env.block) {
99 return !strict;
100 }
101 }
102 true
103 }
104 }
105 }
106
107 pub fn get_expiration(&self) -> MillisecondsExpiration {
108 match self {
109 Self::Blacklisted(expiration) => expiration.unwrap_or_default(),
110 Self::Limited { expiration, .. } => expiration.unwrap_or_default(),
111 Self::Whitelisted(expiration) => expiration.unwrap_or_default(),
112 }
113 }
114
115 pub fn consume_use(&mut self) -> Result<(), ContractError> {
116 if let Self::Limited { uses, .. } = self {
117 if let Some(remaining_uses) = uses.checked_sub(1) {
118 *uses = remaining_uses;
119 Ok(())
120 } else {
121 Err(ContractError::Underflow {})
122 }
123 } else {
124 Ok(())
125 }
126 }
127}
128
129impl fmt::Display for Permission {
130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 let self_as_string = match self {
132 Self::Blacklisted(expiration) => {
133 if let Some(expiration) = expiration {
134 format!("blacklisted:{expiration}")
135 } else {
136 "blacklisted".to_string()
137 }
138 }
139 Self::Limited { expiration, uses } => {
140 if let Some(expiration) = expiration {
141 format!("limited:{expiration}:{uses}")
142 } else {
143 format!("limited:{uses}")
144 }
145 }
146 Self::Whitelisted(expiration) => {
147 if let Some(expiration) = expiration {
148 format!("whitelisted:{expiration}")
149 } else {
150 "whitelisted".to_string()
151 }
152 }
153 };
154 write!(f, "{self_as_string}")
155 }
156}