radix_engine_interface/blueprints/resource/
role_assignment.rs

1use crate::internal_prelude::*;
2use crate::object_modules::role_assignment::ToRoleEntry;
3
4use radix_common::define_untyped_manifest_type_wrapper;
5
6use super::AccessRule;
7
8pub const SELF_ROLE: &str = "_self_";
9pub const OWNER_ROLE: &str = "_owner_";
10
11#[cfg_attr(feature = "fuzzing", derive(::arbitrary::Arbitrary))]
12#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, ScryptoSbor, ManifestSbor)]
13#[sbor(transparent)]
14pub struct MethodKey {
15    pub ident: String,
16}
17
18impl MethodKey {
19    pub fn new<S: ToString>(method_ident: S) -> Self {
20        Self {
21            ident: method_ident.to_string(),
22        }
23    }
24}
25
26impl From<&str> for MethodKey {
27    fn from(value: &str) -> Self {
28        MethodKey::new(value)
29    }
30}
31
32#[cfg_attr(feature = "fuzzing", derive(::arbitrary::Arbitrary))]
33#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, ScryptoSbor, ManifestSbor)]
34pub enum MethodAccessibility {
35    /// Method is accessible to all
36    Public,
37    /// Only outer objects have access to a given method. Currently used by Validator blueprint
38    /// to only allow ConsensusManager to access some methods.
39    OuterObjectOnly,
40    /// Method is only accessible by any role in the role list
41    RoleProtected(RoleList),
42    /// Only the package this method is a part of may access this method
43    OwnPackageOnly,
44}
45
46impl MethodAccessibility {
47    pub fn nobody() -> Self {
48        MethodAccessibility::RoleProtected(RoleList::none())
49    }
50}
51
52impl<const N: usize> From<[&str; N]> for MethodAccessibility {
53    fn from(value: [&str; N]) -> Self {
54        MethodAccessibility::RoleProtected(value.into())
55    }
56}
57
58impl From<RoleList> for MethodAccessibility {
59    fn from(value: RoleList) -> Self {
60        Self::RoleProtected(value)
61    }
62}
63
64#[cfg_attr(feature = "fuzzing", derive(::arbitrary::Arbitrary))]
65#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, ScryptoSbor, ManifestSbor)]
66pub struct ModuleRoleKey {
67    pub module: ModuleId,
68    pub key: RoleKey,
69}
70
71impl ModuleRoleKey {
72    pub fn new<K: Into<RoleKey>>(module: ModuleId, key: K) -> Self {
73        Self {
74            module,
75            key: key.into(),
76        }
77    }
78}
79
80#[cfg_attr(
81    feature = "fuzzing",
82    derive(::arbitrary::Arbitrary, ::serde::Serialize, ::serde::Deserialize)
83)]
84#[derive(
85    Debug,
86    Clone,
87    PartialEq,
88    Eq,
89    Hash,
90    Ord,
91    PartialOrd,
92    ManifestSbor,
93    ScryptoCategorize,
94    ScryptoDecode,
95    ScryptoEncode,
96)]
97#[sbor(transparent)]
98pub struct RoleKey {
99    pub key: String,
100}
101
102impl Describe<ScryptoCustomTypeKind> for RoleKey {
103    const TYPE_ID: RustTypeId =
104        RustTypeId::WellKnown(well_known_scrypto_custom_types::ROLE_KEY_TYPE);
105
106    fn type_data() -> ScryptoTypeData<RustTypeId> {
107        well_known_scrypto_custom_types::role_key_type_data()
108    }
109}
110
111impl From<String> for RoleKey {
112    fn from(s: String) -> Self {
113        Self::new(s)
114    }
115}
116
117impl From<&str> for RoleKey {
118    fn from(s: &str) -> Self {
119        Self::new(s)
120    }
121}
122
123impl RoleKey {
124    pub fn new<S: Into<String>>(key: S) -> Self {
125        RoleKey { key: key.into() }
126    }
127}
128
129#[cfg_attr(
130    feature = "fuzzing",
131    derive(::arbitrary::Arbitrary, ::serde::Serialize, ::serde::Deserialize)
132)]
133#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, ScryptoSbor, ManifestSbor)]
134pub enum OwnerRoleUpdater {
135    /// Owner is fixed and cannot be updated by anyone
136    None,
137    /// Owner role may only be updated by the owner themself
138    Owner,
139    /// Owner role may be updated by the object containing the access rules.
140    /// This is currently primarily used for Presecurified objects
141    Object,
142}
143
144#[cfg_attr(
145    feature = "fuzzing",
146    derive(::arbitrary::Arbitrary, ::serde::Serialize, ::serde::Deserialize)
147)]
148#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, ScryptoSbor, ManifestSbor)]
149pub struct OwnerRoleEntry {
150    pub rule: AccessRule,
151    pub updater: OwnerRoleUpdater,
152}
153
154impl OwnerRoleEntry {
155    pub fn new<A: Into<AccessRule>>(rule: A, updater: OwnerRoleUpdater) -> Self {
156        Self {
157            rule: rule.into(),
158            updater,
159        }
160    }
161}
162
163#[cfg_attr(
164    feature = "fuzzing",
165    derive(::arbitrary::Arbitrary, ::serde::Serialize, ::serde::Deserialize)
166)]
167#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
168pub struct ManifestOwnerRoleEntry {
169    pub rule: ManifestAccessRule,
170    pub updater: OwnerRoleUpdater,
171}
172
173impl From<OwnerRoleEntry> for ManifestOwnerRoleEntry {
174    fn from(value: OwnerRoleEntry) -> Self {
175        Self {
176            rule: value.rule.into(),
177            updater: value.updater,
178        }
179    }
180}
181
182#[cfg_attr(feature = "fuzzing", derive(::arbitrary::Arbitrary))]
183#[derive(
184    Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, ScryptoSbor, ManifestSbor, Default,
185)]
186#[sbor(transparent)]
187pub struct RoleList {
188    pub list: Vec<RoleKey>,
189}
190
191impl RoleList {
192    pub fn none() -> Self {
193        Self { list: vec![] }
194    }
195
196    pub fn insert<R: Into<RoleKey>>(&mut self, role: R) {
197        self.list.push(role.into());
198    }
199
200    pub fn to_list(self) -> Vec<String> {
201        self.list.into_iter().map(|k| k.key).collect()
202    }
203}
204
205impl From<Vec<&str>> for RoleList {
206    fn from(value: Vec<&str>) -> Self {
207        Self {
208            list: value.into_iter().map(RoleKey::new).collect(),
209        }
210    }
211}
212
213impl From<Vec<String>> for RoleList {
214    fn from(value: Vec<String>) -> Self {
215        Self {
216            list: value.into_iter().map(RoleKey::new).collect(),
217        }
218    }
219}
220
221impl<const N: usize> From<[&str; N]> for RoleList {
222    fn from(value: [&str; N]) -> Self {
223        Self {
224            list: value.into_iter().map(RoleKey::new).collect(),
225        }
226    }
227}
228
229/// Front end data structure for specifying owner role
230#[cfg_attr(feature = "fuzzing", derive(::arbitrary::Arbitrary))]
231#[derive(
232    Default,
233    Debug,
234    Clone,
235    PartialEq,
236    Eq,
237    Hash,
238    ScryptoCategorize,
239    ScryptoDecode,
240    ScryptoEncode,
241    ManifestSbor,
242)]
243pub enum OwnerRole {
244    /// No owner role
245    #[default]
246    None,
247    /// Rule protected Owner role which may not be updated
248    Fixed(AccessRule),
249    /// Rule protected Owner role which may only be updated by the owner themself
250    Updatable(AccessRule),
251}
252
253impl Describe<ScryptoCustomTypeKind> for OwnerRole {
254    const TYPE_ID: RustTypeId =
255        RustTypeId::WellKnown(well_known_scrypto_custom_types::OWNER_ROLE_TYPE);
256
257    fn type_data() -> ScryptoTypeData<RustTypeId> {
258        well_known_scrypto_custom_types::owner_role_type_data()
259    }
260}
261
262impl From<OwnerRole> for OwnerRoleEntry {
263    fn from(val: OwnerRole) -> Self {
264        match val {
265            OwnerRole::None => OwnerRoleEntry::new(AccessRule::DenyAll, OwnerRoleUpdater::None),
266            OwnerRole::Fixed(rule) => OwnerRoleEntry::new(rule, OwnerRoleUpdater::None),
267            OwnerRole::Updatable(rule) => OwnerRoleEntry::new(rule, OwnerRoleUpdater::Owner),
268        }
269    }
270}
271
272define_untyped_manifest_type_wrapper!(
273    OwnerRole => ManifestOwnerRole(EnumVariantValue<ManifestCustomValueKind, ManifestCustomValue>)
274);
275
276#[cfg_attr(
277    feature = "fuzzing",
278    derive(::arbitrary::Arbitrary, ::serde::Serialize, ::serde::Deserialize)
279)]
280#[derive(Default, Debug, Clone, PartialEq, Eq, ScryptoSbor, ManifestSbor)]
281#[sbor(transparent)]
282pub struct RoleAssignmentInit {
283    pub data: IndexMap<RoleKey, Option<AccessRule>>,
284}
285
286impl RoleAssignmentInit {
287    pub fn new() -> Self {
288        RoleAssignmentInit {
289            data: index_map_new(),
290        }
291    }
292
293    pub fn define_role<K: Into<RoleKey>, R: ToRoleEntry>(&mut self, role: K, access_rule: R) {
294        self.data.insert(role.into(), access_rule.to_role_entry());
295    }
296}
297
298#[cfg_attr(
299    feature = "fuzzing",
300    derive(::arbitrary::Arbitrary, ::serde::Serialize, ::serde::Deserialize)
301)]
302#[derive(Default, Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
303#[sbor(transparent)]
304pub struct ManifestRoleAssignmentInit {
305    pub data: IndexMap<RoleKey, Option<ManifestAccessRule>>,
306}
307
308impl ManifestRoleAssignmentInit {
309    pub fn new() -> Self {
310        ManifestRoleAssignmentInit {
311            data: index_map_new(),
312        }
313    }
314
315    pub fn define_role<K: Into<RoleKey>, R: ToRoleEntry>(&mut self, role: K, access_rule: R) {
316        self.data
317            .insert(role.into(), access_rule.to_role_entry().map(Into::into));
318    }
319}
320
321impl From<RoleAssignmentInit> for ManifestRoleAssignmentInit {
322    fn from(value: RoleAssignmentInit) -> Self {
323        Self {
324            data: value
325                .data
326                .into_iter()
327                .map(|(key, value)| (key, value.map(Into::into)))
328                .collect(),
329        }
330    }
331}