Skip to main content

edc_web_components/components/
create_policy.rs

1mod 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}