View Javadoc
1   /*
2    * Copyright 2012-2021 CodeLibs Project and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.codelibs.fess.app.web.admin.group;
17  
18  import java.util.Base64;
19  import java.util.Map;
20  import java.util.function.Consumer;
21  
22  import javax.annotation.Resource;
23  
24  import org.apache.logging.log4j.LogManager;
25  import org.apache.logging.log4j.Logger;
26  import org.codelibs.fess.Constants;
27  import org.codelibs.fess.annotation.Secured;
28  import org.codelibs.fess.app.pager.GroupPager;
29  import org.codelibs.fess.app.service.GroupService;
30  import org.codelibs.fess.app.web.CrudMode;
31  import org.codelibs.fess.app.web.base.FessAdminAction;
32  import org.codelibs.fess.es.user.exentity.Group;
33  import org.codelibs.fess.mylasta.action.FessMessages;
34  import org.codelibs.fess.util.ComponentUtil;
35  import org.codelibs.fess.util.RenderDataUtil;
36  import org.dbflute.optional.OptionalEntity;
37  import org.dbflute.optional.OptionalThing;
38  import org.lastaflute.web.Execute;
39  import org.lastaflute.web.response.HtmlResponse;
40  import org.lastaflute.web.response.render.RenderData;
41  import org.lastaflute.web.ruts.process.ActionRuntime;
42  import org.lastaflute.web.validation.VaMessenger;
43  
44  /**
45   * @author shinsuke
46   * @author Keiichi Watanabe
47   */
48  public class AdminGroupAction extends FessAdminAction {
49  
50      public static final String ROLE = "admin-group";
51  
52      private static final Logger logger = LogManager.getLogger(AdminGroupAction.class);
53  
54      // ===================================================================================
55      //                                                                           Attribute
56      //                                                                           =========
57      @Resource
58      private GroupService groupService;
59      @Resource
60      private GroupPager groupPager;
61  
62      // ===================================================================================
63      //                                                                               Hook
64      //                                                                              ======
65      @Override
66      protected void setupHtmlData(final ActionRuntime runtime) {
67          super.setupHtmlData(runtime);
68          runtime.registerData("helpLink", systemHelper.getHelpLink(fessConfig.getOnlineHelpNameGroup()));
69      }
70  
71      @Override
72      protected String getActionRole() {
73          return ROLE;
74      }
75  
76      // ===================================================================================
77      //                                                                      Search Execute
78      //                                                                      ==============
79      @Execute
80      @Secured({ ROLE, ROLE + VIEW })
81      public HtmlResponse index() {
82          return asListHtml();
83      }
84  
85      @Execute
86      @Secured({ ROLE, ROLE + VIEW })
87      public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
88          pageNumber.ifPresent(num -> {
89              groupPager.setCurrentPageNumber(pageNumber.get());
90          }).orElse(() -> {
91              groupPager.setCurrentPageNumber(0);
92          });
93          return asHtml(path_AdminGroup_AdminGroupJsp).renderWith(data -> {
94              searchPaging(data, form);
95          });
96      }
97  
98      @Execute
99      @Secured({ ROLE, ROLE + VIEW })
100     public HtmlResponse search(final SearchForm form) {
101         copyBeanToBean(form, groupPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
102         return asHtml(path_AdminGroup_AdminGroupJsp).renderWith(data -> {
103             searchPaging(data, form);
104         });
105     }
106 
107     @Execute
108     @Secured({ ROLE, ROLE + VIEW })
109     public HtmlResponse reset(final SearchForm form) {
110         groupPager.clear();
111         return asHtml(path_AdminGroup_AdminGroupJsp).renderWith(data -> {
112             searchPaging(data, form);
113         });
114     }
115 
116     protected void searchPaging(final RenderData data, final SearchForm form) {
117         RenderDataUtil.register(data, "groupItems", groupService.getGroupList(groupPager)); // page navi
118 
119         // restore from pager
120         copyBeanToBean(groupPager, form, op -> op.include("id"));
121     }
122 
123     // ===================================================================================
124     //                                                                        Edit Execute
125     //                                                                        ============
126     // -----------------------------------------------------
127     //                                            Entry Page
128     //                                            ----------
129     @Execute
130     @Secured({ ROLE })
131     public HtmlResponse createnew() {
132         saveToken();
133         return asHtml(path_AdminGroup_AdminGroupEditJsp).useForm(CreateForm.class, op -> {
134             op.setup(form -> {
135                 form.initialize();
136                 form.crudMode = CrudMode.CREATE;
137             });
138         });
139     }
140 
141     @Execute
142     @Secured({ ROLE })
143     public HtmlResponse edit(final EditForm form) {
144         validate(form, messages -> {}, this::asListHtml);
145         final String id = form.id;
146         groupService.getGroup(id).ifPresent(entity -> {
147             copyBeanToBean(entity, form, op -> {});
148         }).orElse(() -> {
149             throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), this::asListHtml);
150         });
151         saveToken();
152         if (form.crudMode.intValue() == CrudMode.EDIT) {
153             // back
154             form.crudMode = CrudMode.DETAILS;
155             return asDetailsHtml();
156         }
157         form.crudMode = CrudMode.EDIT;
158         return asEditHtml();
159     }
160 
161     // -----------------------------------------------------
162     //                                               Details
163     //                                               -------
164     @Execute
165     @Secured({ ROLE, ROLE + VIEW })
166     public HtmlResponse details(final int crudMode, final String id) {
167         verifyCrudMode(crudMode, CrudMode.DETAILS);
168         saveToken();
169         return asHtml(path_AdminGroup_AdminGroupDetailsJsp).useForm(EditForm.class, op -> {
170             op.setup(form -> {
171                 groupService.getGroup(id).ifPresent(entity -> {
172                     copyBeanToBean(entity, form, copyOp -> {
173                         copyOp.excludeNull();
174                     });
175                     form.crudMode = crudMode;
176                 }).orElse(() -> {
177                     throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), this::asListHtml);
178                 });
179             });
180         });
181     }
182 
183     // -----------------------------------------------------
184     //                                         Actually Crud
185     //                                         -------------
186     @Execute
187     @Secured({ ROLE })
188     public HtmlResponse create(final CreateForm form) {
189         verifyCrudMode(form.crudMode, CrudMode.CREATE);
190         validate(form, messages -> {}, this::asEditHtml);
191         validateAttributes(form.attributes, v -> throwValidationError(v, this::asEditHtml));
192         verifyToken(this::asEditHtml);
193         getGroup(form).ifPresent(entity -> {
194             try {
195                 groupService.store(entity);
196                 saveInfo(messages -> messages.addSuccessCrudCreateCrudTable(GLOBAL));
197             } catch (final Exception e) {
198                 logger.error("Failed to add {}", entity, e);
199                 throwValidationError(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, buildThrowableMessage(e)),
200                         this::asEditHtml);
201             }
202         }).orElse(() -> {
203             throwValidationError(messages -> messages.addErrorsCrudFailedToCreateInstance(GLOBAL), this::asEditHtml);
204         });
205         return redirect(getClass());
206     }
207 
208     @Execute
209     @Secured({ ROLE })
210     public HtmlResponse update(final EditForm form) {
211         verifyCrudMode(form.crudMode, CrudMode.EDIT);
212         validate(form, messages -> {}, this::asEditHtml);
213         validateAttributes(form.attributes, v -> throwValidationError(v, this::asEditHtml));
214         verifyToken(this::asEditHtml);
215         getGroup(form).ifPresent(entity -> {
216             try {
217                 groupService.store(entity);
218                 saveInfo(messages -> messages.addSuccessCrudUpdateCrudTable(GLOBAL));
219             } catch (final Exception e) {
220                 logger.error("Failed to update {}", entity, e);
221                 throwValidationError(messages -> messages.addErrorsCrudFailedToUpdateCrudTable(GLOBAL, buildThrowableMessage(e)),
222                         this::asEditHtml);
223             }
224         }).orElse(() -> {
225             throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.id), this::asEditHtml);
226         });
227         return redirect(getClass());
228     }
229 
230     @Execute
231     @Secured({ ROLE })
232     public HtmlResponse delete(final EditForm form) {
233         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
234         validate(form, messages -> {}, this::asDetailsHtml);
235         verifyToken(this::asDetailsHtml);
236         final String id = form.id;
237         groupService.getGroup(id).ifPresent(entity -> {
238             try {
239                 groupService.delete(entity);
240                 saveInfo(messages -> messages.addSuccessCrudDeleteCrudTable(GLOBAL));
241             } catch (final Exception e) {
242                 logger.error("Failed to delete {}", entity, e);
243                 throwValidationError(messages -> messages.addErrorsCrudFailedToDeleteCrudTable(GLOBAL, buildThrowableMessage(e)),
244                         this::asDetailsHtml);
245             }
246         }).orElse(() -> {
247             throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), this::asDetailsHtml);
248         });
249         return redirect(getClass());
250     }
251 
252     // ===================================================================================
253     //                                                                        Assist Logic
254     //                                                                        ============
255     private static OptionalEntity<Group> getEntity(final CreateForm form) {
256         switch (form.crudMode) {
257         case CrudMode.CREATE:
258             return OptionalEntity.of(new Group()).map(entity -> {
259                 entity.setId(Base64.getUrlEncoder().encodeToString(form.name.getBytes(Constants.CHARSET_UTF_8)));
260                 return entity;
261             });
262         case CrudMode.EDIT:
263             if (form instanceof EditForm) {
264                 return ComponentUtil.getComponent(GroupService.class).getGroup(((EditForm) form).id);
265             }
266             break;
267         default:
268             break;
269         }
270         return OptionalEntity.empty();
271     }
272 
273     public static OptionalEntity<Group> getGroup(final CreateForm form) {
274         return getEntity(form).map(entity -> {
275             copyMapToBean(form.attributes, entity, op -> op.exclude(Constants.COMMON_CONVERSION_RULE));
276             copyBeanToBean(form, entity, op -> op.exclude(Constants.COMMON_CONVERSION_RULE));
277             return entity;
278         });
279     }
280 
281     // ===================================================================================
282     //                                                                        Small Helper
283     //                                                                        ============
284     protected void verifyCrudMode(final int crudMode, final int expectedMode) {
285         if (crudMode != expectedMode) {
286             throwValidationError(messages -> {
287                 messages.addErrorsCrudInvalidMode(GLOBAL, String.valueOf(expectedMode), String.valueOf(crudMode));
288             }, this::asListHtml);
289         }
290     }
291 
292     public static void validateAttributes(final Map<String, String> attributes, final Consumer<VaMessenger<FessMessages>> throwError) {
293         ComponentUtil.getLdapManager().validateGroupAttributes(Long.class, attributes,
294                 s -> throwError.accept(messages -> messages.addErrorsPropertyTypeLong("attributes." + s, "attributes." + s)));
295     }
296 
297     // ===================================================================================
298     //                                                                              JSP
299     //                                                                           =========
300 
301     private HtmlResponse asListHtml() {
302         return asHtml(path_AdminGroup_AdminGroupJsp).renderWith(data -> {
303             RenderDataUtil.register(data, "groupItems", groupService.getGroupList(groupPager)); // page navi
304         }).useForm(SearchForm.class, setup -> {
305             setup.setup(form -> {
306                 copyBeanToBean(groupPager, form, op -> op.include("id"));
307             });
308         });
309     }
310 
311     private HtmlResponse asEditHtml() {
312         return asHtml(path_AdminGroup_AdminGroupEditJsp);
313     }
314 
315     private HtmlResponse asDetailsHtml() {
316         return asHtml(path_AdminGroup_AdminGroupDetailsJsp);
317     }
318 }