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.panels;
20  
21  import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.stream.Collectors;
27  import org.apache.syncope.client.console.SyncopeConsoleSession;
28  import org.apache.syncope.client.console.commons.DirectoryDataProvider;
29  import org.apache.syncope.client.console.commons.IdRepoConstants;
30  import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
31  import org.apache.syncope.client.console.panels.ApplicationDirectoryPanel.ApplicationDataProvider;
32  import org.apache.syncope.client.console.rest.ApplicationRestClient;
33  import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
34  import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
35  import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
36  import org.apache.syncope.client.console.wizards.WizardMgtPanel;
37  import org.apache.syncope.client.ui.commons.Constants;
38  import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
39  import org.apache.syncope.common.lib.SyncopeClientException;
40  import org.apache.syncope.common.lib.to.ApplicationTO;
41  import org.apache.syncope.common.lib.to.PrivilegeTO;
42  import org.apache.syncope.common.lib.types.IdRepoEntitlement;
43  import org.apache.wicket.MarkupContainer;
44  import org.apache.wicket.PageReference;
45  import org.apache.wicket.ajax.AjaxRequestTarget;
46  import org.apache.wicket.ajax.markup.html.AjaxLink;
47  import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
48  import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
49  import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
50  import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
51  import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
52  import org.apache.wicket.markup.html.basic.Label;
53  import org.apache.wicket.markup.repeater.Item;
54  import org.apache.wicket.model.CompoundPropertyModel;
55  import org.apache.wicket.model.IModel;
56  import org.apache.wicket.model.Model;
57  import org.apache.wicket.model.ResourceModel;
58  import org.apache.wicket.model.StringResourceModel;
59  
60  public class ApplicationDirectoryPanel extends
61          DirectoryPanel<ApplicationTO, ApplicationTO, ApplicationDataProvider, ApplicationRestClient> {
62  
63      private static final long serialVersionUID = -5491515010207202168L;
64  
65      protected final BaseModal<PrivilegeTO> privilegeModal = new BaseModal<>(Constants.OUTER) {
66  
67          private static final long serialVersionUID = 389935548143327858L;
68  
69          @Override
70          protected void onConfigure() {
71              super.onConfigure();
72              setFooterVisible(false);
73          }
74      };
75  
76      protected ApplicationDirectoryPanel(final String id, final Builder builder) {
77          super(id, builder);
78          MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, IdRepoEntitlement.APPLICATION_CREATE);
79          setReadOnly(!SyncopeConsoleSession.get().owns(IdRepoEntitlement.APPLICATION_UPDATE));
80  
81          disableCheckBoxes();
82          setShowResultPanel(true);
83  
84          modal.size(Modal.Size.Default);
85          modal.addSubmitButton();
86          modal.setWindowClosedCallback(target -> {
87              updateResultTable(target);
88              modal.show(false);
89          });
90          setFooterVisibility(true);
91  
92          privilegeModal.size(Modal.Size.Large);
93          privilegeModal.setWindowClosedCallback(target -> {
94              updateResultTable(target);
95              modal.show(false);
96          });
97          addOuterObject(privilegeModal);
98  
99          AjaxLink<Void> newApplLink = new AjaxLink<>("add") {
100 
101             private static final long serialVersionUID = -7978723352517770644L;
102 
103             @Override
104             public void onClick(final AjaxRequestTarget target) {
105                 modal.header(new StringResourceModel("any.new"));
106                 modal.setContent(new ApplicationModalPanel(new ApplicationTO(), true, modal, pageRef));
107                 modal.show(true);
108                 target.add(modal);
109             }
110         };
111         ((MarkupContainer) get("container:content")).addOrReplace(newApplLink);
112         MetaDataRoleAuthorizationStrategy.authorize(newApplLink, RENDER, IdRepoEntitlement.APPLICATION_CREATE);
113 
114         initResultTable();
115     }
116 
117     @Override
118     protected ApplicationDataProvider dataProvider() {
119         return new ApplicationDataProvider(rows);
120     }
121 
122     @Override
123     protected String paginatorRowsKey() {
124         return IdRepoConstants.PREF_APPLICATION_PAGINATOR_ROWS;
125     }
126 
127     @Override
128     protected List<IColumn<ApplicationTO, String>> getColumns() {
129         final List<IColumn<ApplicationTO, String>> columns = new ArrayList<>();
130 
131         columns.add(new PropertyColumn<>(
132                 new ResourceModel(Constants.KEY_FIELD_NAME), Constants.KEY_FIELD_NAME, Constants.KEY_FIELD_NAME));
133         columns.add(new PropertyColumn<>(new ResourceModel(Constants.DESCRIPTION_FIELD_NAME),
134                 Constants.DESCRIPTION_FIELD_NAME, Constants.DESCRIPTION_FIELD_NAME));
135         columns.add(new AbstractColumn<>(new ResourceModel("privileges")) {
136 
137             private static final long serialVersionUID = 2054811145491901166L;
138 
139             @Override
140             public void populateItem(
141                     final Item<ICellPopulator<ApplicationTO>> item,
142                     final String componentId,
143                     final IModel<ApplicationTO> rowModel) {
144 
145                 item.add(new Label(componentId, '[' + rowModel.getObject().getPrivileges().stream().
146                         map(PrivilegeTO::getKey).collect(Collectors.joining(", ")) + ']'));
147             }
148         });
149 
150         return columns;
151     }
152 
153     @Override
154     public ActionsPanel<ApplicationTO> getActions(final IModel<ApplicationTO> model) {
155         final ActionsPanel<ApplicationTO> panel = super.getActions(model);
156 
157         panel.add(new ActionLink<>() {
158 
159             private static final long serialVersionUID = -7978723352517770644L;
160 
161             @Override
162             public void onClick(final AjaxRequestTarget target, final ApplicationTO ignore) {
163                 modal.header(new StringResourceModel("any.edit", model));
164                 modal.setContent(new ApplicationModalPanel(model.getObject(), false, modal, pageRef));
165                 modal.show(true);
166                 target.add(modal);
167             }
168         }, ActionLink.ActionType.EDIT, IdRepoEntitlement.APPLICATION_UPDATE);
169 
170         panel.add(new ActionLink<>() {
171 
172             private static final long serialVersionUID = -7978723352517770644L;
173 
174             @Override
175             public void onClick(final AjaxRequestTarget target, final ApplicationTO ignore) {
176                 target.add(privilegeModal.setContent(new PrivilegeDirectoryPanel(
177                         privilegeModal, restClient, model.getObject(), pageRef)));
178 
179                 privilegeModal.header(new StringResourceModel(
180                         "application.privileges", ApplicationDirectoryPanel.this, Model.of(model.getObject())));
181 
182                 MetaDataRoleAuthorizationStrategy.authorize(
183                         privilegeModal.getForm(), ENABLE, IdRepoEntitlement.APPLICATION_UPDATE);
184 
185                 privilegeModal.show(true);
186             }
187         }, ActionLink.ActionType.COMPOSE, IdRepoEntitlement.APPLICATION_UPDATE);
188 
189         panel.add(new ActionLink<>() {
190 
191             private static final long serialVersionUID = 3766262567901552032L;
192 
193             @Override
194             public void onClick(final AjaxRequestTarget target, final ApplicationTO ignore) {
195                 try {
196                     restClient.delete(model.getObject().getKey());
197 
198                     SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
199                     target.add(container);
200                 } catch (SyncopeClientException e) {
201                     LOG.error("While deleting application {}", model.getObject().getKey(), e);
202                     SyncopeConsoleSession.get().onException(e);
203                 }
204                 ((BaseWebPage) pageRef.getPage()).getNotificationPanel().refresh(target);
205             }
206         }, ActionLink.ActionType.DELETE, IdRepoEntitlement.APPLICATION_DELETE, true);
207 
208         return panel;
209     }
210 
211     @Override
212     protected Collection<ActionLink.ActionType> getBatches() {
213         return List.of();
214     }
215 
216     protected class ApplicationDataProvider extends DirectoryDataProvider<ApplicationTO> {
217 
218         private static final long serialVersionUID = 3124431855954382273L;
219 
220         private final SortableDataProviderComparator<ApplicationTO> comparator;
221 
222         public ApplicationDataProvider(final int paginatorRows) {
223             super(paginatorRows);
224             this.comparator = new SortableDataProviderComparator<>(this);
225         }
226 
227         @Override
228         public Iterator<ApplicationTO> iterator(final long first, final long count) {
229             List<ApplicationTO> result = restClient.list();
230             result.sort(comparator);
231             return result.subList((int) first, (int) first + (int) count).iterator();
232         }
233 
234         @Override
235         public long size() {
236             return restClient.list().size();
237         }
238 
239         @Override
240         public IModel<ApplicationTO> model(final ApplicationTO object) {
241             return new CompoundPropertyModel<>(object);
242         }
243     }
244 
245     public abstract static class Builder
246             extends DirectoryPanel.Builder<ApplicationTO, ApplicationTO, ApplicationRestClient> {
247 
248         private static final long serialVersionUID = 5530948153889495221L;
249 
250         public Builder(final ApplicationRestClient restClient, final PageReference pageRef) {
251             super(restClient, pageRef);
252         }
253 
254         @Override
255         protected WizardMgtPanel<ApplicationTO> newInstance(final String id, final boolean wizardInModal) {
256             return new ApplicationDirectoryPanel(id, this);
257         }
258     }
259 }