dpp/data_contract/change_control_rules/v0/
mod.rs

1use crate::data_contract::change_control_rules::authorized_action_takers::AuthorizedActionTakers;
2use crate::data_contract::group::Group;
3use crate::data_contract::GroupContractPosition;
4use crate::group::action_taker::{ActionGoal, ActionTaker};
5#[cfg(feature = "json-conversion")]
6use crate::serialization::json_safe_fields;
7use bincode::{Decode, Encode};
8use platform_value::Identifier;
9use serde::{Deserialize, Serialize};
10use std::collections::BTreeMap;
11use std::fmt;
12
13#[cfg_attr(feature = "json-conversion", json_safe_fields)]
14#[derive(Serialize, Deserialize, Decode, Encode, Debug, Clone, PartialEq, Eq, Default)]
15#[serde(rename_all = "camelCase")]
16pub struct ChangeControlRulesV0 {
17    /// This is who is authorized to make such a change
18    pub authorized_to_make_change: AuthorizedActionTakers,
19    /// This is who is authorized to make such a change to the people authorized to make a change
20    pub admin_action_takers: AuthorizedActionTakers,
21    /// Are we allowed to change to None in the future
22    pub changing_authorized_action_takers_to_no_one_allowed: bool,
23    /// Are we allowed to change the admin action takers to no one in the future
24    pub changing_admin_action_takers_to_no_one_allowed: bool,
25    /// Can the admin action takers change themselves
26    pub self_changing_admin_action_takers_allowed: bool,
27}
28
29impl ChangeControlRulesV0 {
30    pub fn can_make_change(
31        &self,
32        contract_owner_id: &Identifier,
33        main_group: Option<GroupContractPosition>,
34        groups: &BTreeMap<GroupContractPosition, Group>,
35        action_taker: &ActionTaker,
36        goal: ActionGoal,
37    ) -> bool {
38        self.authorized_to_make_change.allowed_for_action_taker(
39            contract_owner_id,
40            main_group,
41            groups,
42            action_taker,
43            goal,
44        )
45    }
46    pub fn can_change_authorized_action_takers(
47        &self,
48        controlling_action_takers: &AuthorizedActionTakers,
49        contract_owner_id: &Identifier,
50        main_group: Option<GroupContractPosition>,
51        groups: &BTreeMap<GroupContractPosition, Group>,
52        action_taker: &ActionTaker,
53        goal: ActionGoal,
54    ) -> bool {
55        if !self.changing_authorized_action_takers_to_no_one_allowed
56            && controlling_action_takers == &AuthorizedActionTakers::NoOne
57        {
58            return false;
59        }
60        self.admin_action_takers.allowed_for_action_taker(
61            contract_owner_id,
62            main_group,
63            groups,
64            action_taker,
65            goal,
66        )
67    }
68
69    pub fn can_change_admin_action_takers(
70        &self,
71        admin_action_takers: &AuthorizedActionTakers,
72        contract_owner_id: &Identifier,
73        main_group: Option<GroupContractPosition>,
74        groups: &BTreeMap<GroupContractPosition, Group>,
75        action_taker: &ActionTaker,
76        goal: ActionGoal,
77    ) -> bool {
78        if !self.self_changing_admin_action_takers_allowed {
79            return false;
80        }
81        if !self.changing_admin_action_takers_to_no_one_allowed
82            && admin_action_takers == &AuthorizedActionTakers::NoOne
83        {
84            return false;
85        }
86        self.admin_action_takers.allowed_for_action_taker(
87            contract_owner_id,
88            main_group,
89            groups,
90            action_taker,
91            goal,
92        )
93    }
94
95    pub fn can_change_to(
96        &self,
97        other: &ChangeControlRulesV0,
98        contract_owner_id: &Identifier,
99        main_group: Option<GroupContractPosition>,
100        groups: &BTreeMap<GroupContractPosition, Group>,
101        action_taker: &ActionTaker,
102        goal: ActionGoal,
103    ) -> bool {
104        // First, check if the action taker is allowed to make any changes at all
105        if !self.authorized_to_make_change.allowed_for_action_taker(
106            contract_owner_id,
107            main_group,
108            groups,
109            action_taker,
110            goal,
111        ) {
112            return false;
113        }
114
115        // Check if authorized_to_make_change is being modified
116        if self.authorized_to_make_change != other.authorized_to_make_change {
117            // Changing the authorized action takers requires the action_taker to be allowed by
118            // authorized_to_change_authorized_action_takers in the current rules
119            if !self.admin_action_takers.allowed_for_action_taker(
120                contract_owner_id,
121                main_group,
122                groups,
123                action_taker,
124                goal,
125            ) {
126                return false;
127            }
128
129            // If we are changing to NoOne, ensure it's allowed
130            if let AuthorizedActionTakers::NoOne = other.authorized_to_make_change {
131                if !self.changing_authorized_action_takers_to_no_one_allowed {
132                    return false;
133                }
134            }
135        }
136
137        // Check if authorized_to_change_authorized_action_takers is being modified
138        if self.admin_action_takers != other.admin_action_takers {
139            if !self.self_changing_admin_action_takers_allowed {
140                return false;
141            }
142
143            // Must be allowed by the current authorized_to_change_authorized_action_takers
144            if !self.admin_action_takers.allowed_for_action_taker(
145                contract_owner_id,
146                main_group,
147                groups,
148                action_taker,
149                goal,
150            ) {
151                return false;
152            }
153
154            // If we are changing to NoOne, ensure it's allowed
155            if let AuthorizedActionTakers::NoOne = other.admin_action_takers {
156                if !self.changing_admin_action_takers_to_no_one_allowed {
157                    return false;
158                }
159            }
160        }
161
162        // If we reach here, the changes are allowed
163        true
164    }
165}
166
167impl fmt::Display for ChangeControlRulesV0 {
168    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
169        write!(
170            f,
171            "ChangeControlRulesV0 {{\n  \
172            authorized_to_make_change: {},\n  \
173            admin_action_takers: {},\n  \
174            changing_authorized_action_takers_to_no_one_allowed: {},\n  \
175            changing_admin_action_takers_to_no_one_allowed: {},\n  \
176            self_changing_admin_action_takers_allowed: {}\n\
177            }}",
178            self.authorized_to_make_change,
179            self.admin_action_takers,
180            self.changing_authorized_action_takers_to_no_one_allowed,
181            self.changing_admin_action_takers_to_no_one_allowed,
182            self.self_changing_admin_action_takers_allowed
183        )
184    }
185}