View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.client.console.wizards.any;
20  
21  import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.checkbox.bootstraptoggle.BootstrapToggle;
22  import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.checkbox.bootstraptoggle.BootstrapToggleConfig;
23  import java.util.ArrayList;
24  import java.util.regex.Matcher;
25  import java.util.regex.Pattern;
26  import org.apache.commons.lang3.StringUtils;
27  import org.apache.syncope.client.console.SyncopeWebApplication;
28  import org.apache.syncope.client.console.panels.search.AnySelectionDirectoryPanel;
29  import org.apache.syncope.client.console.panels.search.GroupSearchPanel;
30  import org.apache.syncope.client.console.panels.search.GroupSelectionDirectoryPanel;
31  import org.apache.syncope.client.console.panels.search.SearchClausePanel;
32  import org.apache.syncope.client.console.panels.search.SearchUtils;
33  import org.apache.syncope.client.console.panels.search.UserSearchPanel;
34  import org.apache.syncope.client.console.panels.search.UserSelectionDirectoryPanel;
35  import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
36  import org.apache.syncope.client.console.rest.AnyTypeRestClient;
37  import org.apache.syncope.client.console.rest.GroupRestClient;
38  import org.apache.syncope.client.console.rest.UserRestClient;
39  import org.apache.syncope.client.lib.SyncopeClient;
40  import org.apache.syncope.client.ui.commons.Constants;
41  import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
42  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
43  import org.apache.syncope.common.lib.to.AnyTO;
44  import org.apache.syncope.common.lib.to.AnyTypeTO;
45  import org.apache.syncope.common.lib.to.GroupTO;
46  import org.apache.syncope.common.lib.to.UserTO;
47  import org.apache.syncope.common.lib.types.AnyTypeKind;
48  import org.apache.syncope.common.lib.types.IdRepoEntitlement;
49  import org.apache.wicket.PageReference;
50  import org.apache.wicket.ajax.AjaxRequestTarget;
51  import org.apache.wicket.authroles.authorization.strategies.role.Roles;
52  import org.apache.wicket.authroles.authorization.strategies.role.metadata.ActionPermissions;
53  import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
54  import org.apache.wicket.event.Broadcast;
55  import org.apache.wicket.event.IEvent;
56  import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxLink;
57  import org.apache.wicket.extensions.wizard.WizardModel.ICondition;
58  import org.apache.wicket.extensions.wizard.WizardStep;
59  import org.apache.wicket.markup.html.WebMarkupContainer;
60  import org.apache.wicket.markup.html.form.CheckBox;
61  import org.apache.wicket.markup.html.panel.Fragment;
62  import org.apache.wicket.model.IModel;
63  import org.apache.wicket.model.Model;
64  import org.apache.wicket.model.PropertyModel;
65  import org.apache.wicket.model.ResourceModel;
66  import org.apache.wicket.model.util.ListModel;
67  import org.apache.wicket.spring.injection.annot.SpringBean;
68  
69  public class Ownership extends WizardStep implements ICondition {
70  
71      private static final long serialVersionUID = 855618618337931784L;
72  
73      @SpringBean
74      protected AnyTypeRestClient anyTypeRestClient;
75  
76      @SpringBean
77      protected AnyTypeClassRestClient anyTypeClassRestClient;
78  
79      @SpringBean
80      private UserRestClient userRestClient;
81  
82      @SpringBean
83      private GroupRestClient groupRestClient;
84  
85      private final Pattern owner = Pattern.compile("\\[\\(\\d+\\)\\] .*");
86  
87      private final GroupWrapper wrapper;
88  
89      private final WebMarkupContainer ownerContainer;
90  
91      private final GroupSearchPanel groupSearchPanel;
92  
93      private final Fragment groupSearchFragment;
94  
95      private final GroupSelectionDirectoryPanel groupDirectoryPanel;
96  
97      private final UserSearchPanel userSearchPanel;
98  
99      private final Fragment userSearchFragment;
100 
101     private final UserSelectionDirectoryPanel userDirectoryPanel;
102 
103     private final Model<Boolean> isGroupOwnership;
104 
105     public Ownership(final GroupWrapper groupWrapper, final PageReference pageRef) {
106         super();
107 
108         // -----------------------------------------------------------------
109         // Pre-Authorizations
110         // -----------------------------------------------------------------
111         ActionPermissions permissions = new ActionPermissions();
112         setMetaData(MetaDataRoleAuthorizationStrategy.ACTION_PERMISSIONS, permissions);
113         permissions.authorize(RENDER, new Roles(IdRepoEntitlement.USER_SEARCH));
114         // -----------------------------------------------------------------
115 
116         setTitleModel(new ResourceModel("group.ownership"));
117         this.wrapper = groupWrapper;
118 
119         isGroupOwnership = Model.of(groupWrapper.getInnerObject().getGroupOwner() != null);
120 
121         BootstrapToggleConfig config = new BootstrapToggleConfig().
122                 withOnStyle(BootstrapToggleConfig.Style.info).
123                 withOffStyle(BootstrapToggleConfig.Style.warning).
124                 withSize(BootstrapToggleConfig.Size.mini);
125 
126         add(new BootstrapToggle("ownership", new Model<>() {
127 
128             private static final long serialVersionUID = 6062041315055645807L;
129 
130             @Override
131             public Boolean getObject() {
132                 return isGroupOwnership.getObject();
133             }
134         }, config) {
135 
136             private static final long serialVersionUID = 2969634208049189343L;
137 
138             @Override
139             protected IModel<String> getOffLabel() {
140                 return Model.of("USER Owner");
141             }
142 
143             @Override
144             protected IModel<String> getOnLabel() {
145                 return Model.of("GROUP Owner");
146             }
147 
148             @Override
149             protected CheckBox newCheckBox(final String id, final IModel<Boolean> model) {
150                 final CheckBox checkBox = super.newCheckBox(id, model);
151                 checkBox.add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
152 
153                     private static final long serialVersionUID = 18235445704320L;
154 
155                     @Override
156                     protected void onUpdate(final AjaxRequestTarget target) {
157                         isGroupOwnership.setObject(!isGroupOwnership.getObject());
158                         if (isGroupOwnership.getObject()) {
159                             ownerContainer.addOrReplace(groupSearchFragment);
160                             groupDirectoryPanel.search(null, target);
161                         } else {
162                             ownerContainer.addOrReplace(userSearchFragment);
163                             userDirectoryPanel.search(null, target);
164                         }
165                         target.add(ownerContainer);
166                     }
167                 });
168                 return checkBox;
169             }
170         });
171 
172         ownerContainer = new WebMarkupContainer("ownerContainer");
173         ownerContainer.setOutputMarkupId(true);
174         add(ownerContainer);
175 
176         groupSearchFragment = new Fragment("search", "groupSearchFragment", this);
177         groupSearchPanel = new GroupSearchPanel.Builder(
178                 new ListModel<>(new ArrayList<>()), pageRef).required(false).enableSearch(Ownership.this).
179                 build("groupsearch");
180         groupSearchFragment.add(groupSearchPanel.setRenderBodyOnly(true));
181 
182         AnyTypeTO anyTypeTO = anyTypeRestClient.read(AnyTypeKind.GROUP.name());
183         groupDirectoryPanel = GroupSelectionDirectoryPanel.class.cast(new GroupSelectionDirectoryPanel.Builder(
184                 anyTypeClassRestClient.list(anyTypeTO.getClasses()),
185                 groupRestClient,
186                 anyTypeTO.getKey(),
187                 pageRef).build("searchResult"));
188         groupSearchFragment.add(groupDirectoryPanel);
189 
190         userSearchFragment = new Fragment("search", "userSearchFragment", this);
191         userSearchPanel = UserSearchPanel.class.cast(new UserSearchPanel.Builder(
192                 new ListModel<>(new ArrayList<>()), pageRef).required(false).enableSearch(Ownership.this).
193                 build("usersearch"));
194         userSearchFragment.add(userSearchPanel.setRenderBodyOnly(true));
195 
196         anyTypeTO = anyTypeRestClient.read(AnyTypeKind.USER.name());
197         userDirectoryPanel = UserSelectionDirectoryPanel.class.cast(new UserSelectionDirectoryPanel.Builder(
198                 anyTypeClassRestClient.list(anyTypeTO.getClasses()), userRestClient, anyTypeTO.getKey(), pageRef).
199                 build("searchResult"));
200         userSearchFragment.add(userDirectoryPanel);
201 
202         if (isGroupOwnership.getObject()) {
203             ownerContainer.add(groupSearchFragment);
204         } else {
205             ownerContainer.add(userSearchFragment);
206         }
207 
208         AjaxTextFieldPanel userOwner = new AjaxTextFieldPanel(
209                 "userOwner", "userOwner", new PropertyModel<>(groupWrapper.getInnerObject(), "userOwner") {
210 
211             private static final long serialVersionUID = -3743432456095828573L;
212 
213             @Override
214             public String getObject() {
215                 if (groupWrapper.getInnerObject().getUserOwner() == null) {
216                     return StringUtils.EMPTY;
217                 }
218 
219                 UserTO userTO = userRestClient.read(groupWrapper.getInnerObject().getUserOwner());
220                 if (userTO == null) {
221                     return StringUtils.EMPTY;
222                 }
223 
224                 return String.format("[%s] %s", userTO.getKey(), userTO.getUsername());
225             }
226 
227             @Override
228             public void setObject(final String object) {
229                 if (StringUtils.isBlank(object)) {
230                     groupWrapper.getInnerObject().setUserOwner(null);
231                 } else {
232                     Matcher matcher = owner.matcher(object);
233                     if (matcher.matches()) {
234                         groupWrapper.getInnerObject().setUserOwner(matcher.group(1));
235                     }
236                 }
237             }
238         }, false);
239         userOwner.setPlaceholder("userOwner");
240         userOwner.hideLabel();
241         userOwner.setReadOnly(true).setOutputMarkupId(true);
242         userSearchFragment.add(userOwner);
243 
244         IndicatingAjaxLink<Void> userOwnerReset = new IndicatingAjaxLink<>("userOwnerReset") {
245 
246             private static final long serialVersionUID = -7978723352517770644L;
247 
248             @Override
249             public void onClick(final AjaxRequestTarget target) {
250                 send(Ownership.this, Broadcast.EXACT, new GroupSelectionDirectoryPanel.ItemSelection<>(target, null));
251             }
252 
253             @Override
254             public String getAjaxIndicatorMarkupId() {
255                 return Constants.VEIL_INDICATOR_MARKUP_ID;
256             }
257 
258         };
259         userSearchFragment.add(userOwnerReset);
260 
261         AjaxTextFieldPanel groupOwner = new AjaxTextFieldPanel(
262                 "groupOwner", "groupOwner", new PropertyModel<>(groupWrapper.getInnerObject(), "groupOwner") {
263 
264             private static final long serialVersionUID = -3743432456095828573L;
265 
266             @Override
267             public String getObject() {
268                 if (groupWrapper.getInnerObject().getGroupOwner() == null) {
269                     return StringUtils.EMPTY;
270                 } else {
271                     GroupTO groupTO = groupRestClient.read(groupWrapper.getInnerObject().getGroupOwner());
272                     if (groupTO == null) {
273                         return StringUtils.EMPTY;
274                     } else {
275                         return String.format("[%s] %s", groupTO.getKey(), groupTO.getName());
276                     }
277                 }
278             }
279 
280             @Override
281             public void setObject(final String object) {
282                 if (StringUtils.isBlank(object)) {
283                     groupWrapper.getInnerObject().setGroupOwner(null);
284                 } else {
285                     final Matcher matcher = owner.matcher(object);
286                     if (matcher.matches()) {
287                         groupWrapper.getInnerObject().setGroupOwner(matcher.group(1));
288                     }
289                 }
290             }
291         }, false);
292         groupOwner.setPlaceholder("groupOwner");
293         groupOwner.hideLabel();
294         groupOwner.setReadOnly(true).setOutputMarkupId(true);
295         groupSearchFragment.add(groupOwner);
296 
297         IndicatingAjaxLink<Void> groupOwnerReset = new IndicatingAjaxLink<>("groupOwnerReset") {
298 
299             private static final long serialVersionUID = -7978723352517770644L;
300 
301             @Override
302             public void onClick(final AjaxRequestTarget target) {
303                 send(Ownership.this, Broadcast.EXACT, new GroupSelectionDirectoryPanel.ItemSelection<>(target, null));
304             }
305 
306             @Override
307             public String getAjaxIndicatorMarkupId() {
308                 return Constants.VEIL_INDICATOR_MARKUP_ID;
309             }
310 
311         };
312         groupSearchFragment.add(groupOwnerReset);
313     }
314 
315     @Override
316     public void onEvent(final IEvent<?> event) {
317         if (event.getPayload() instanceof SearchClausePanel.SearchEvent) {
318             AjaxRequestTarget target = SearchClausePanel.SearchEvent.class.cast(event.getPayload()).getTarget();
319             if (Ownership.this.isGroupOwnership.getObject()) {
320                 String fiql = SearchUtils.buildFIQL(
321                         groupSearchPanel.getModel().getObject(), SyncopeClient.getGroupSearchConditionBuilder());
322                 groupDirectoryPanel.search(fiql, target);
323             } else {
324                 String fiql = SearchUtils.buildFIQL(
325                         userSearchPanel.getModel().getObject(), SyncopeClient.getUserSearchConditionBuilder());
326                 userDirectoryPanel.search(fiql, target);
327             }
328         } else if (event.getPayload() instanceof AnySelectionDirectoryPanel.ItemSelection) {
329             AnyTO sel = ((AnySelectionDirectoryPanel.ItemSelection) event.getPayload()).getSelection();
330             if (sel == null) {
331                 wrapper.getInnerObject().setUserOwner(null);
332                 wrapper.getInnerObject().setGroupOwner(null);
333             } else if (sel instanceof UserTO) {
334                 wrapper.getInnerObject().setUserOwner(sel.getKey());
335                 wrapper.getInnerObject().setGroupOwner(null);
336             } else if (sel instanceof GroupTO) {
337                 wrapper.getInnerObject().setGroupOwner(sel.getKey());
338                 wrapper.getInnerObject().setUserOwner(null);
339             }
340             ((AnySelectionDirectoryPanel.ItemSelection) event.getPayload()).getTarget().add(ownerContainer);
341         } else {
342             super.onEvent(event);
343         }
344     }
345 
346     @Override
347     public boolean evaluate() {
348         return SyncopeWebApplication.get().getSecuritySettings().getAuthorizationStrategy().
349                 isActionAuthorized(this, RENDER);
350     }
351 }