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.enduser.panels;
20  
21  import java.util.List;
22  import org.apache.syncope.client.enduser.SyncopeWebApplication;
23  import org.apache.syncope.client.enduser.commons.EnduserConstants;
24  import org.apache.syncope.client.enduser.layout.UserFormLayoutInfo;
25  import org.apache.syncope.client.enduser.panels.any.DerAttrs;
26  import org.apache.syncope.client.enduser.panels.any.Details;
27  import org.apache.syncope.client.enduser.panels.any.Groups;
28  import org.apache.syncope.client.enduser.panels.any.PlainAttrs;
29  import org.apache.syncope.client.enduser.panels.any.Resources;
30  import org.apache.syncope.client.enduser.panels.captcha.CaptchaPanel;
31  import org.apache.syncope.client.ui.commons.panels.CardPanel;
32  import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
33  import org.apache.syncope.common.lib.Attr;
34  import org.apache.syncope.common.lib.to.AnyTO;
35  import org.apache.syncope.common.lib.to.GroupableRelatableTO;
36  import org.apache.syncope.common.lib.to.UserTO;
37  import org.apache.wicket.PageReference;
38  
39  public abstract class AnyFormPanel extends AbstractAnyFormPanel<UserWrapper> {
40  
41      private static final long serialVersionUID = -2720486919461006370L;
42  
43      protected final List<String> anyTypeClasses;
44  
45      protected CaptchaPanel<Void> captcha;
46  
47      protected UserFormLayoutInfo formLayoutInfo;
48  
49      public AnyFormPanel(final String id,
50              final UserTO anyTO,
51              final List<String> anyTypeClasses,
52              final UserFormLayoutInfo formLayoutInfo,
53              final PageReference pageReference) {
54  
55          super(id, new UserWrapper(anyTO), pageReference);
56  
57          this.formLayoutInfo = formLayoutInfo;
58          this.anyTypeClasses = anyTypeClasses;
59      }
60  
61      public AnyFormPanel(final String id,
62              final UserWrapper wrapper,
63              final List<String> anyTypeClasses,
64              final UserFormLayoutInfo formLayoutInfo,
65              final PageReference pageReference) {
66  
67          super(id, wrapper, pageReference);
68  
69          this.formLayoutInfo = formLayoutInfo;
70          this.anyTypeClasses = anyTypeClasses;
71      }
72  
73      protected Details<UserTO> addOptionalDetailsPanel(final UserWrapper modelObject) {
74          Details<UserTO> details = new Details<>(EnduserConstants.CONTENT_PANEL, pageRef);
75          details.setOutputMarkupId(true);
76          return details;
77      }
78  
79      @Override
80      protected void buildLayout(final UserWrapper modelObject) {
81          form.add(new CardPanel.Builder<>()
82                  .setName("details")
83                  .setComponent(addOptionalDetailsPanel(modelObject))
84                  .isVisible(formLayoutInfo.isDetailsManagement()).build("userDetailsPanelCard"));
85  
86          Groups groups = new Groups(EnduserConstants.CONTENT_PANEL, modelObject);
87          setOutputMarkupId(true);
88  
89          form.add(new CardPanel.Builder<Groups>()
90                  .setName("groups")
91                  .setComponent(groups)
92                  .isVisible(formLayoutInfo.isGroups()).build("groupsPanelCard"));
93  
94          PlainAttrs plainAttrs = new PlainAttrs(EnduserConstants.CONTENT_PANEL,
95                  modelObject, anyTypeClasses, formLayoutInfo.getWhichPlainAttrs());
96          plainAttrs.setOutputMarkupId(true);
97  
98          form.add(new CardPanel.Builder<PlainAttrs>()
99                  .setName("attributes.plain")
100                 .setComponent(plainAttrs)
101                 .isVisible(formLayoutInfo.isPlainAttrs() && plainAttrs.isPanelVisible()).build("plainAttrsPanelCard"));
102 
103         DerAttrs derAttrs = new DerAttrs(EnduserConstants.CONTENT_PANEL,
104                 modelObject, anyTypeClasses, formLayoutInfo.getWhichDerAttrs());
105         derAttrs.setOutputMarkupId(true);
106 
107         form.add(new CardPanel.Builder<DerAttrs>()
108                 .setName("attributes.derived")
109                 .setComponent(derAttrs)
110                 .isVisible(formLayoutInfo.isDerAttrs() && derAttrs.isPanelVisible()).build("derAttrsPanelCard"));
111 
112         Resources resources = new Resources(EnduserConstants.CONTENT_PANEL, modelObject);
113         resources.setOutputMarkupId(true);
114 
115         form.add(new CardPanel.Builder<Resources>()
116                 .setName("resources")
117                 .setComponent(resources)
118                 .isVisible(formLayoutInfo.isResources()).build("resourcesPanelCard"));
119 
120         // add captcha
121         captcha = new CaptchaPanel<>(EnduserConstants.CONTENT_PANEL);
122         captcha.setOutputMarkupPlaceholderTag(true);
123 
124         form.add(new CardPanel.Builder<CaptchaPanel<Void>>()
125                 .setName("captcha")
126                 .setComponent(captcha)
127                 .isVisible(SyncopeWebApplication.get().isCaptchaEnabled()).build("captchaPanelCard"));
128     }
129 
130     protected void fixPlainAttrs(final AnyTO updated, final AnyTO original) {
131         // re-add to the updated object any missing plain attribute (compared to original): this to cope with
132         // form layout, which might have not included some plain attributes
133         for (Attr plainAttr : original.getPlainAttrs()) {
134             if (updated.getPlainAttr(plainAttr.getSchema()).isEmpty()) {
135                 updated.getPlainAttrs().add(plainAttr);
136             }
137         }
138 
139         if (updated instanceof GroupableRelatableTO updatedTO && original instanceof GroupableRelatableTO originalTO) {
140             originalTO.getMemberships().forEach(oMemb -> updatedTO.getMembership(oMemb.getGroupKey()).
141                     ifPresent(uMemb -> oMemb.getPlainAttrs().stream().
142                     filter(attr -> uMemb.getPlainAttr(attr.getSchema()).isEmpty()).
143                     forEach(attr -> uMemb.getPlainAttrs().add(attr))));
144         }
145 
146         // remove from the updated object any plain attribute without values, thus triggering for removal in
147         // the generated patch
148         updated.getPlainAttrs().removeIf(attr -> attr.getValues().isEmpty());
149         if (updated instanceof GroupableRelatableTO updatedTO) {
150             updatedTO.getMemberships().
151                     forEach(memb -> memb.getPlainAttrs().removeIf(attr -> attr.getValues().isEmpty()));
152         }
153     }
154 }