1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.client.console.events;
20
21 import java.util.Comparator;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Set;
25 import java.util.stream.Collectors;
26 import org.apache.commons.lang3.StringUtils;
27 import org.apache.commons.lang3.tuple.Pair;
28 import org.apache.syncope.client.console.events.SelectedEventsPanel.EventSelectionChanged;
29 import org.apache.syncope.client.console.events.SelectedEventsPanel.InspectSelectedEvent;
30 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
31 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
32 import org.apache.syncope.client.ui.commons.Constants;
33 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
34 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
35 import org.apache.syncope.common.lib.audit.EventCategory;
36 import org.apache.syncope.common.lib.types.AuditElements;
37 import org.apache.syncope.common.lib.types.AuditElements.EventCategoryType;
38 import org.apache.syncope.common.lib.types.AuditLoggerName;
39 import org.apache.wicket.ajax.AjaxRequestTarget;
40 import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
41 import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
42 import org.apache.wicket.event.Broadcast;
43 import org.apache.wicket.event.IEvent;
44 import org.apache.wicket.markup.html.WebMarkupContainer;
45 import org.apache.wicket.markup.html.basic.Label;
46 import org.apache.wicket.markup.html.form.IChoiceRenderer;
47 import org.apache.wicket.markup.html.panel.Panel;
48 import org.apache.wicket.model.IModel;
49 import org.apache.wicket.model.Model;
50 import org.apache.wicket.model.PropertyModel;
51 import org.apache.wicket.model.ResourceModel;
52
53 public abstract class EventCategoryPanel extends Panel {
54
55 private static final long serialVersionUID = 6429053774964787734L;
56
57 protected static class ChangeCategoryEvent {
58
59 protected final AjaxRequestTarget target;
60
61 protected final Panel changedPanel;
62
63 ChangeCategoryEvent(final AjaxRequestTarget target, final Panel changedPanel) {
64 this.target = target;
65 this.changedPanel = changedPanel;
66 }
67
68 public AjaxRequestTarget getTarget() {
69 return target;
70 }
71
72 public Panel getChangedPanel() {
73 return changedPanel;
74 }
75 }
76
77 protected static List<String> filter(
78 final List<EventCategory> categories,
79 final EventCategoryType type) {
80
81 return categories.stream().
82 filter(c -> type == c.getType() && StringUtils.isNotEmpty(c.getCategory())).
83 map(EventCategory::getCategory).
84 distinct().
85 sorted().
86 collect(Collectors.toList());
87 }
88
89 protected static List<String> filter(
90 final List<EventCategory> categories,
91 final EventCategoryType type,
92 final String category) {
93
94 return categories.stream().
95 filter(c -> type == c.getType() && StringUtils.equals(category, c.getCategory())).
96 map(EventCategory::getSubcategory).
97 distinct().
98 sorted().
99 collect(Collectors.toList());
100 }
101
102 private final List<EventCategory> eventCategories;
103
104 private final EventCategory eventCategory = new EventCategory();
105
106 private final WebMarkupContainer categoryContainer;
107
108 private final WebMarkupContainer eventsContainer;
109
110 private final SelectedEventsPanel selectedEventsPanel;
111
112 private final AjaxDropDownChoicePanel<EventCategoryType> type;
113
114 private final AjaxDropDownChoicePanel<String> category;
115
116 private final AjaxDropDownChoicePanel<String> subcategory;
117
118 private final AjaxTextFieldPanel custom;
119
120 private final ActionsPanel<EventCategory> actionsPanel;
121
122 private final IModel<List<String>> model;
123
124 public EventCategoryPanel(
125 final String id,
126 final List<EventCategory> eventCategories,
127 final IModel<List<String>> model) {
128
129 super(id);
130
131 this.model = model;
132 selectedEventsPanel = new SelectedEventsPanel("selectedEventsPanel", model);
133 add(selectedEventsPanel);
134
135 this.eventCategories = eventCategories;
136
137 categoryContainer = new WebMarkupContainer("categoryContainer");
138 categoryContainer.setOutputMarkupId(true);
139 add(categoryContainer);
140
141 eventsContainer = new WebMarkupContainer("eventsContainer");
142 eventsContainer.setOutputMarkupId(true);
143 add(eventsContainer);
144
145 authorizeList();
146 authorizeChanges();
147
148 type = new AjaxDropDownChoicePanel<>(
149 "type",
150 "type",
151 new PropertyModel<>(eventCategory, "type"),
152 false);
153 type.setChoices(eventCategories.stream().
154 map(EventCategory::getType).distinct().
155 sorted(Comparator.comparing(EventCategoryType::name)).
156 collect(Collectors.toList()));
157 type.setChoiceRenderer(new IChoiceRenderer<>() {
158
159 private static final long serialVersionUID = 2317134950949778735L;
160
161 @Override
162 public String getDisplayValue(final EventCategoryType eventCategoryType) {
163 return eventCategoryType.name();
164 }
165
166 @Override
167 public String getIdValue(final EventCategoryType eventCategoryType, final int i) {
168 return eventCategoryType.name();
169 }
170
171 @Override
172 public EventCategoryType getObject(
173 final String id,
174 final IModel<? extends List<? extends EventCategoryType>> choices) {
175
176 return choices.getObject().stream().filter(object -> object.name().equals(id)).findAny().orElse(null);
177 }
178 });
179 categoryContainer.add(type);
180
181 type.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
182
183 private static final long serialVersionUID = -1107858522700306810L;
184
185 @Override
186 protected void onUpdate(final AjaxRequestTarget target) {
187 send(EventCategoryPanel.this, Broadcast.EXACT, new ChangeCategoryEvent(target, type));
188 }
189 });
190
191 category = new AjaxDropDownChoicePanel<>(
192 "category",
193 "category",
194 new PropertyModel<>(eventCategory, "category"),
195 false);
196 category.setChoices(filter(eventCategories, type.getModelObject()));
197 categoryContainer.add(category);
198
199 category.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
200
201 private static final long serialVersionUID = -1107858522700306811L;
202
203 @Override
204 protected void onUpdate(final AjaxRequestTarget target) {
205 send(EventCategoryPanel.this, Broadcast.EXACT, new ChangeCategoryEvent(target, category));
206 }
207 });
208
209 subcategory = new AjaxDropDownChoicePanel<>(
210 "subcategory",
211 "subcategory",
212 new PropertyModel<>(eventCategory, "subcategory"),
213 false);
214 subcategory.setChoices(filter(eventCategories, type.getModelObject(), category.getModelObject()));
215 categoryContainer.add(subcategory);
216
217 subcategory.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
218
219 private static final long serialVersionUID = -1107858522700306812L;
220
221 @Override
222 protected void onUpdate(final AjaxRequestTarget target) {
223 send(EventCategoryPanel.this, Broadcast.EXACT, new ChangeCategoryEvent(target, subcategory));
224 }
225 });
226
227 categoryContainer.add(new Label("customLabel", new ResourceModel("custom", "custom")).setVisible(false));
228
229 custom = new AjaxTextFieldPanel("custom", "custom", new Model<>(null));
230 custom.setVisible(false);
231 custom.setEnabled(false);
232
233 categoryContainer.add(custom.hideLabel());
234
235 actionsPanel = new ActionsPanel<>("customActions", null);
236 actionsPanel.add(new ActionLink<>() {
237
238 private static final long serialVersionUID = -3722207913631435501L;
239
240 @Override
241 public void onClick(final AjaxRequestTarget target, final EventCategory ignore) {
242 if (StringUtils.isNotBlank(custom.getModelObject())) {
243 Pair<EventCategory, AuditElements.Result> parsed =
244 AuditLoggerName.parseEventCategory(custom.getModelObject());
245
246 AuditLoggerName auditLoggerName = new AuditLoggerName(
247 parsed.getLeft().getType(),
248 null,
249 null,
250 parsed.getLeft().getEvents().isEmpty()
251 ? StringUtils.EMPTY : parsed.getLeft().getEvents().iterator().next(),
252 parsed.getRight());
253
254 custom.setModelObject(StringUtils.EMPTY);
255 send(EventCategoryPanel.this.getPage(), Broadcast.BREADTH, new EventSelectionChanged(
256 target,
257 Set.of(auditLoggerName),
258 Set.of()));
259 target.add(categoryContainer);
260 }
261 }
262 }, ActionLink.ActionType.CREATE, StringUtils.EMPTY).hideLabel();
263 actionsPanel.add(new ActionLink<>() {
264
265 private static final long serialVersionUID = -3722207913631435521L;
266
267 @Override
268 public void onClick(final AjaxRequestTarget target, final EventCategory ignore) {
269 if (StringUtils.isNotBlank(custom.getModelObject())) {
270 Pair<EventCategory, AuditElements.Result> parsed =
271 AuditLoggerName.parseEventCategory(custom.getModelObject());
272
273 AuditLoggerName auditLoggerName = new AuditLoggerName(
274 parsed.getLeft().getType(),
275 null,
276 null,
277 parsed.getLeft().getEvents().isEmpty()
278 ? StringUtils.EMPTY : parsed.getLeft().getEvents().iterator().next(),
279 parsed.getRight());
280
281 custom.setModelObject(StringUtils.EMPTY);
282 send(EventCategoryPanel.this.getPage(), Broadcast.BREADTH, new EventSelectionChanged(
283 target,
284 Set.of(),
285 Set.of(auditLoggerName)));
286 target.add(categoryContainer);
287 }
288 }
289 }, ActionLink.ActionType.DELETE, StringUtils.EMPTY, true).hideLabel();
290
291 categoryContainer.add(actionsPanel);
292
293 actionsPanel.setVisible(false);
294 actionsPanel.setEnabled(false);
295 actionsPanel.setMarkupId("inline-actions");
296
297 eventsContainer.add(new EventSelectionPanel("eventsPanel", eventCategory, model) {
298
299 private static final long serialVersionUID = 3513194801190026082L;
300
301 @Override
302 protected void onEventAction(final IEvent<?> event) {
303 EventCategoryPanel.this.onEventAction(event);
304 }
305 });
306 }
307
308 @Override
309 public void onEvent(final IEvent<?> event) {
310 if (event.getPayload() instanceof ChangeCategoryEvent) {
311
312 eventCategory.getEvents().clear();
313
314 ChangeCategoryEvent change = (ChangeCategoryEvent) event.getPayload();
315
316 switch (change.getChangedPanel().getId()) {
317 case "type":
318 eventCategory.setType(type.getModelObject());
319 eventCategory.setCategory(null);
320 eventCategory.setSubcategory(null);
321 if (type.getModelObject() == EventCategoryType.CUSTOM
322 || type.getModelObject() == EventCategoryType.WA) {
323
324 category.setChoices(List.of());
325 subcategory.setChoices(List.of());
326 category.setEnabled(false);
327 subcategory.setEnabled(false);
328 custom.setVisible(true);
329 custom.setEnabled(true);
330 actionsPanel.setVisible(true);
331 actionsPanel.setEnabled(true);
332 } else {
333 category.setChoices(filter(eventCategories, type.getModelObject()));
334 subcategory.setChoices(List.of());
335 category.setEnabled(true);
336 subcategory.setEnabled(true);
337 custom.setVisible(false);
338 custom.setEnabled(false);
339 actionsPanel.setVisible(false);
340 actionsPanel.setEnabled(false);
341 }
342 change.getTarget().add(categoryContainer);
343 break;
344
345 case "category":
346 subcategory.setChoices(
347 filter(eventCategories, type.getModelObject(), category.getModelObject()));
348 eventCategory.setCategory(category.getModelObject());
349 eventCategory.setSubcategory(null);
350 change.getTarget().add(categoryContainer);
351 break;
352
353 default:
354 eventCategory.setSubcategory(subcategory.getModelObject());
355 break;
356 }
357
358 updateEventsContainer(change.getTarget());
359 } else if (event.getPayload() instanceof InspectSelectedEvent) {
360
361 eventCategory.getEvents().clear();
362
363 InspectSelectedEvent inspectSelectedEvent = (InspectSelectedEvent) event.getPayload();
364
365 Pair<EventCategory, AuditElements.Result> categoryEvent =
366 AuditLoggerName.parseEventCategory(inspectSelectedEvent.getEvent());
367
368 eventCategory.setType(categoryEvent.getLeft().getType());
369 category.setChoices(filter(eventCategories, type.getModelObject()));
370
371 eventCategory.setCategory(categoryEvent.getLeft().getCategory());
372 subcategory.setChoices(filter(eventCategories, type.getModelObject(), category.getModelObject()));
373
374 eventCategory.setSubcategory(categoryEvent.getLeft().getSubcategory());
375
376 if (categoryEvent.getLeft().getType() == EventCategoryType.CUSTOM
377 || categoryEvent.getLeft().getType() == EventCategoryType.WA) {
378
379 custom.setModelObject(AuditLoggerName.buildEvent(
380 categoryEvent.getLeft().getType(),
381 categoryEvent.getLeft().getCategory(),
382 categoryEvent.getLeft().getSubcategory(),
383 categoryEvent.getLeft().getEvents().isEmpty()
384 ? StringUtils.EMPTY : categoryEvent.getLeft().getEvents().iterator().next(),
385 categoryEvent.getRight()));
386
387 category.setEnabled(false);
388 subcategory.setEnabled(false);
389 custom.setVisible(true);
390 custom.setEnabled(true);
391 actionsPanel.setVisible(true);
392 actionsPanel.setEnabled(true);
393 } else {
394 category.setEnabled(true);
395 subcategory.setEnabled(true);
396 custom.setVisible(false);
397 custom.setEnabled(false);
398 actionsPanel.setVisible(false);
399 actionsPanel.setEnabled(false);
400 }
401
402 inspectSelectedEvent.getTarget().add(categoryContainer);
403 updateEventsContainer(inspectSelectedEvent.getTarget());
404 }
405 }
406
407
408
409
410
411
412 protected void onEventAction(final IEvent<?> event) {
413
414 }
415
416 protected abstract List<String> getListAuthRoles();
417
418 protected void authorizeList() {
419 getListAuthRoles().forEach(r -> MetaDataRoleAuthorizationStrategy.authorize(selectedEventsPanel, RENDER, r));
420 }
421
422 protected abstract List<String> getChangeAuthRoles();
423
424 protected void authorizeChanges() {
425 getChangeAuthRoles().forEach(r -> {
426 MetaDataRoleAuthorizationStrategy.authorize(categoryContainer, RENDER, r);
427 MetaDataRoleAuthorizationStrategy.authorize(eventsContainer, RENDER, r);
428 });
429 }
430
431 protected void updateEventsContainer(final AjaxRequestTarget target) {
432 for (Iterator<EventCategory> itor = eventCategories.iterator();
433 itor.hasNext() && eventCategory.getEvents().isEmpty();) {
434
435 EventCategory ec = itor.next();
436 if (ec.getType() == eventCategory.getType()
437 && StringUtils.equals(ec.getCategory(), eventCategory.getCategory())
438 && StringUtils.equals(ec.getSubcategory(), eventCategory.getSubcategory())) {
439
440 eventCategory.getEvents().addAll(ec.getEvents());
441 }
442 }
443
444 eventsContainer.addOrReplace(new EventSelectionPanel("eventsPanel", eventCategory, model) {
445
446 private static final long serialVersionUID = 3513194801190026082L;
447
448 @Override
449 public void onEventAction(final IEvent<?> event) {
450 EventCategoryPanel.this.onEventAction(event);
451 }
452 });
453 target.add(eventsContainer);
454 }
455 }