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