edc_web_components/components/
create_policy.rs1mod atomic_constraint_edit;
2mod list_of_rules;
3mod operator_selector;
4mod rule;
5
6pub use self::atomic_constraint_edit::AtomicConstraintEdit;
7pub use self::list_of_rules::ListOfRules;
8pub use self::operator_selector::OperatorSelector;
9pub use self::rule::Rule;
10use crate::components::create_policy::atomic_constraint_edit::ConstraintMode;
11use crate::components::simple_or_id_field::SimpleOrIdField;
12use crate::contexts::use_edc_connector_context;
13use edc_connector_client::EdcConnectorApiVersion;
14use edc_connector_client::types::policy::{
15 Action, Constraint, NewPolicyDefinition, Obligation, Permission, Policy, PolicyKind, Prohibition,
16 Target,
17};
18use patternfly_yew::prelude::*;
19use yew::platform::spawn_local;
20use yew::prelude::*;
21
22#[derive(Copy, Clone, PartialEq, Eq, strum::Display)]
23enum Options {
24 Agreement,
25 Offer,
26 Set,
27}
28
29#[derive(Clone, Debug, PartialEq, Properties)]
30pub struct CreatePolicyProps {
31 #[prop_or_default]
32 pub on_create: Callback<()>,
33}
34
35#[component]
36pub fn CreatePolicy(props: &CreatePolicyProps) -> Html {
37 let edc_connector_context = use_edc_connector_context();
38
39 let identifier = use_state(String::new);
40 let kind = use_state(|| Options::Set);
41 let assignee = use_state(String::default);
42 let assigner = use_state(String::default);
43 let target = use_state(|| (true, String::default()));
44 let permissions = use_state(Vec::new);
45 let prohibitions = use_state(Vec::new);
46 let obligations = use_state(Vec::new);
47
48 let onsubmit = use_callback(
49 (
50 edc_connector_context,
51 identifier.clone(),
52 kind.clone(),
53 assignee.clone(),
54 assigner.clone(),
55 target.clone(),
56 permissions.clone(),
57 prohibitions.clone(),
58 obligations.clone(),
59 props.on_create.clone(),
60 ),
61 |event: SubmitEvent,
62 (
63 edc_connector_context,
64 identifier,
65 kind,
66 assignee,
67 assigner,
68 target,
69 permissions,
70 prohibitions,
71 obligations,
72 on_create,
73 )| {
74 event.prevent_default();
75
76 let edc_connector_context = edc_connector_context.clone();
77 let identifier = (**identifier).clone();
78 let kind = **kind;
79 let assignee = (**assignee).clone();
80 let assigner = (**assigner).clone();
81 let (is_simple_target, target) = (**target).clone();
82
83 let permissions = (**permissions)
84 .iter()
85 .map(
86 |(action, constraints): &(Action, Vec<(ConstraintMode, Constraint)>)| {
87 Permission::builder()
88 .action(action.clone())
89 .constraints(
90 constraints
91 .iter()
92 .map(|(_, constraint)| constraint.clone())
93 .collect(),
94 )
95 .build()
96 },
97 )
98 .collect();
99
100 let prohibitions = (**prohibitions)
101 .iter()
102 .map(
103 |(action, constraints): &(Action, Vec<(ConstraintMode, Constraint)>)| {
104 Prohibition::builder()
105 .action(action.clone())
106 .constraints(
107 constraints
108 .iter()
109 .map(|(_, constraint)| constraint.clone())
110 .collect(),
111 )
112 .build()
113 },
114 )
115 .collect();
116
117 let obligations = (**obligations)
118 .iter()
119 .map(
120 |(action, constraints): &(Action, Vec<(ConstraintMode, Constraint)>)| {
121 Obligation::builder()
122 .action(action.clone())
123 .constraints(
124 constraints
125 .iter()
126 .map(|(_, constraint)| constraint.clone())
127 .collect(),
128 )
129 .build()
130 },
131 )
132 .collect();
133
134 let on_create = on_create.clone();
135
136 spawn_local(async move {
137 let kind = match kind {
138 Options::Agreement => PolicyKind::Agreement,
139 Options::Offer => PolicyKind::Offer,
140 Options::Set => PolicyKind::Set,
141 };
142
143 let policy_builder = Policy::builder()
144 .kind(kind)
145 .permissions(permissions)
146 .prohibitions(prohibitions)
147 .obligations(obligations);
148
149 let policy_builder = if !assignee.is_empty() {
150 policy_builder.maybe_assignee(Some(assignee))
151 } else {
152 policy_builder.maybe_assignee(None::<String>)
153 };
154
155 let policy_builder = if !assigner.is_empty() {
156 policy_builder.maybe_assigner(Some(assigner))
157 } else {
158 policy_builder.maybe_assigner(None::<String>)
159 };
160
161 let policy_builder = if !target.is_empty() {
162 if is_simple_target {
163 policy_builder.target(Target::Simple(target))
164 } else {
165 policy_builder.target(Target::Id { id: target })
166 }
167 } else {
168 policy_builder.maybe_target(None::<Target>)
169 };
170
171 let policy = policy_builder.build();
172
173 let new_policy = NewPolicyDefinition::builder()
174 .id(&identifier)
175 .policy(policy)
176 .build();
177
178 if let Some(client) = edc_connector_context.get_client() {
179 let _ = client
180 .policies(EdcConnectorApiVersion::V4)
181 .create(&new_policy)
182 .await;
183 on_create.emit(());
184 }
185 })
186 },
187 );
188
189 let onchange_identifier =
190 use_callback(identifier.setter(), move |identifier, identifier_setter| {
191 identifier_setter.set(identifier);
192 });
193
194 let onselect_kind = use_callback(kind.setter(), move |kind, kind_setter| {
195 kind_setter.set(kind);
196 });
197
198 let onchange_assignee = use_callback(
199 assignee.setter(),
200 move |assignee: String, assignee_setter| {
201 assignee_setter.set(assignee);
202 },
203 );
204
205 let onchange_assigner = use_callback(
206 assigner.setter(),
207 move |assigner: String, assigner_setter| {
208 assigner_setter.set(assigner);
209 },
210 );
211
212 let onchange_target = use_callback(
213 target.setter(),
214 move |target: (bool, String), target_setter| {
215 target_setter.set(target);
216 },
217 );
218
219 let onchange_permissions = use_callback(
220 permissions.setter(),
221 move |permissions, permissions_setter| {
222 permissions_setter.set(permissions);
223 },
224 );
225
226 let onchange_prohibitions = use_callback(
227 prohibitions.setter(),
228 move |prohibitions, prohibitions_setter| {
229 prohibitions_setter.set(prohibitions);
230 },
231 );
232
233 let onchange_obligations = use_callback(
234 obligations.setter(),
235 move |obligations, obligations_setter| {
236 obligations_setter.set(obligations);
237 },
238 );
239
240 let (target_is_simple, target_value) = (*target).clone();
241
242 let disabled = false;
243
244 html!(
245 <Form {onsubmit}>
246 <FormGroup label="Identifier" required=true>
247 <TextInput required=true value={(*identifier).to_string()} onchange={onchange_identifier} />
248 </FormGroup>
249 <FormGroup label="Kind" required=true>
250 <SimpleSelect<Options>
251 selected={*kind}
252 onselect={onselect_kind}
253 entries={vec![Options::Agreement, Options::Offer, Options::Set]}
254 />
255 </FormGroup>
256 <FormGroup label="Permissions">
257 <ListOfRules list={(*permissions).clone()} onchange={onchange_permissions} />
258 </FormGroup>
259 <FormGroup label="Prohibitions">
260 <ListOfRules list={(*prohibitions).clone()} onchange={onchange_prohibitions} />
261 </FormGroup>
262 <FormGroup label="Obligations">
263 <ListOfRules list={(*obligations).clone()} onchange={onchange_obligations} />
264 </FormGroup>
265 <FormGroup label="Assignee">
266 <TextInput value={(*assignee).clone()} onchange={onchange_assignee} />
267 </FormGroup>
268 <FormGroup label="Assigner">
269 <TextInput value={(*assigner).clone()} onchange={onchange_assigner} />
270 </FormGroup>
271 <FormGroup label="Target">
272 <SimpleOrIdField
273 onchange={onchange_target}
274 is_simple={target_is_simple}
275 value={target_value}
276 />
277 </FormGroup>
278 <ActionGroup>
279 <Button
280 variant={ButtonVariant::Primary}
281 label="Submit"
282 r#type={ButtonType::Submit}
283 {disabled}
284 />
285 <Button variant={ButtonVariant::Secondary} label="Reset" r#type={ButtonType::Reset} />
286 </ActionGroup>
287 </Form>
288 )
289}