edc_web_ui/components/
create_policy.rs1use 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}