Skip to main content

edc_web_ui/components/
create_policy.rs

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