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.accesstoken;
17  
18  import static org.codelibs.core.stream.StreamUtil.split;
19  import static org.codelibs.core.stream.StreamUtil.stream;
20  
21  import java.util.stream.Collectors;
22  
23  import javax.annotation.Resource;
24  
25  import org.codelibs.core.beans.util.BeanUtil;
26  import org.codelibs.core.lang.StringUtil;
27  import org.codelibs.fess.Constants;
28  import org.codelibs.fess.annotation.Secured;
29  import org.codelibs.fess.app.pager.AccessTokenPager;
30  import org.codelibs.fess.app.service.AccessTokenService;
31  import org.codelibs.fess.app.web.CrudMode;
32  import org.codelibs.fess.app.web.base.FessAdminAction;
33  import org.codelibs.fess.es.config.exentity.AccessToken;
34  import org.codelibs.fess.helper.PermissionHelper;
35  import org.codelibs.fess.helper.SystemHelper;
36  import org.codelibs.fess.util.ComponentUtil;
37  import org.codelibs.fess.util.RenderDataUtil;
38  import org.dbflute.optional.OptionalEntity;
39  import org.dbflute.optional.OptionalThing;
40  import org.lastaflute.web.Execute;
41  import org.lastaflute.web.response.HtmlResponse;
42  import org.lastaflute.web.response.render.RenderData;
43  import org.lastaflute.web.ruts.process.ActionRuntime;
44  
45  /**
46   * @author shinsuke
47   */
48  public class AdminAccesstokenAction extends FessAdminAction {
49  
50      public static final String ROLE = "admin-accesstoken";
51  
52      public static final String TOKEN = "token";
53  
54      public static final String EXPIRES = "expires";
55  
56      public static final String EXPIRED_TIME = "expiredTime";
57  
58      // ===================================================================================
59      //                                                                           Attribute
60      //                                                                           =========
61      @Resource
62      private AccessTokenService accessTokenService;
63      @Resource
64      private AccessTokenPager accessTokenPager;
65  
66      // ===================================================================================
67      //                                                                               Hook
68      //                                                                              ======
69      @Override
70      protected void setupHtmlData(final ActionRuntime runtime) {
71          super.setupHtmlData(runtime);
72          runtime.registerData("helpLink", systemHelper.getHelpLink(fessConfig.getOnlineHelpNameAccesstoken()));
73      }
74  
75      @Override
76      protected String getActionRole() {
77          return ROLE;
78      }
79  
80      // ===================================================================================
81      //                                                                      Search Execute
82      //                                                                      ==============
83      @Execute
84      @Secured({ ROLE, ROLE + VIEW })
85      public HtmlResponse index() {
86          return asListHtml();
87      }
88  
89      @Execute
90      @Secured({ ROLE, ROLE + VIEW })
91      public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
92          pageNumber.ifPresent(num -> {
93              accessTokenPager.setCurrentPageNumber(pageNumber.get());
94          }).orElse(() -> {
95              accessTokenPager.setCurrentPageNumber(0);
96          });
97          return asHtml(path_AdminAccesstoken_AdminAccesstokenJsp).renderWith(data -> {
98              searchPaging(data, form);
99          });
100     }
101 
102     @Execute
103     @Secured({ ROLE, ROLE + VIEW })
104     public HtmlResponse search(final SearchForm form) {
105         copyBeanToBean(form, accessTokenPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
106         return asHtml(path_AdminAccesstoken_AdminAccesstokenJsp).renderWith(data -> {
107             searchPaging(data, form);
108         });
109     }
110 
111     @Execute
112     @Secured({ ROLE, ROLE + VIEW })
113     public HtmlResponse reset(final SearchForm form) {
114         accessTokenPager.clear();
115         return asHtml(path_AdminAccesstoken_AdminAccesstokenJsp).renderWith(data -> {
116             searchPaging(data, form);
117         });
118     }
119 
120     protected void searchPaging(final RenderData data, final SearchForm form) {
121         RenderDataUtil.register(data, "accessTokenItems", accessTokenService.getAccessTokenList(accessTokenPager)); // page navi
122 
123         // restore from pager
124         copyBeanToBean(accessTokenPager, form, op -> op.include("id"));
125     }
126 
127     // ===================================================================================
128     //                                                                        Edit Execute
129     //                                                                        ============
130     // -----------------------------------------------------
131     //                                            Entry Page
132     //                                            ----------
133     @Execute
134     @Secured({ ROLE })
135     public HtmlResponse createnew() {
136         saveToken();
137         return asEditHtml().useForm(CreateForm.class, op -> {
138             op.setup(form -> {
139                 form.initialize();
140                 form.crudMode = CrudMode.CREATE;
141             });
142         });
143     }
144 
145     // -----------------------------------------------------
146     //                                               Details
147     //                                               -------
148     @Execute
149     @Secured({ ROLE, ROLE + VIEW })
150     public HtmlResponse details(final int crudMode, final String id) {
151         verifyCrudMode(crudMode, CrudMode.DETAILS);
152         saveToken();
153         return asDetailsHtml().useForm(EditForm.class, op -> {
154             op.setup(form -> {
155                 accessTokenService.getAccessToken(id).ifPresent(entity -> {
156                     copyBeanToBean(entity, form, copyOp -> copyOp.exclude(Constants.PERMISSIONS, EXPIRED_TIME).excludeNull()
157                             .dateConverter(Constants.DEFAULT_DATETIME_FORMAT, EXPIRES));
158                     final PermissionHelper permissionHelper = ComponentUtil.getPermissionHelper();
159                     form.permissions = stream(entity.getPermissions()).get(stream -> stream.map(permissionHelper::decode)
160                             .filter(StringUtil::isNotBlank).distinct().collect(Collectors.joining("\n")));
161                     form.crudMode = crudMode;
162                 }).orElse(() -> {
163                     throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), this::asListHtml);
164                 });
165             });
166         });
167     }
168 
169     @Execute
170     @Secured({ ROLE })
171     public HtmlResponse edit(final EditForm form) {
172         validate(form, messages -> {}, this::asListHtml);
173         final String id = form.id;
174         accessTokenService.getAccessToken(id).ifPresent(entity -> {
175             copyBeanToBean(entity, form,
176                     op -> op.exclude(Constants.PERMISSIONS, EXPIRED_TIME).dateConverter(Constants.DEFAULT_DATETIME_FORMAT, EXPIRES));
177             final PermissionHelper permissionHelper = ComponentUtil.getPermissionHelper();
178             form.permissions = stream(entity.getPermissions()).get(stream -> stream.map(permissionHelper::decode)
179                     .filter(StringUtil::isNotBlank).distinct().collect(Collectors.joining("\n")));
180         }).orElse(() -> {
181             throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), this::asListHtml);
182         });
183         saveToken();
184         if (form.crudMode.intValue() == CrudMode.EDIT) {
185             // back
186             form.crudMode = CrudMode.DETAILS;
187             return asDetailsHtml();
188         }
189         form.crudMode = CrudMode.EDIT;
190         return asEditHtml();
191     }
192 
193     // -----------------------------------------------------
194     //                                         Actually Crud
195     //                                         -------------
196     @Execute
197     @Secured({ ROLE })
198     public HtmlResponse create(final CreateForm form) {
199         verifyCrudMode(form.crudMode, CrudMode.CREATE);
200         validate(form, messages -> {}, this::asEditHtml);
201         verifyToken(this::asEditHtml);
202         getAccessToken(form).ifPresent(entity -> {
203             entity.setToken(accessTokenHelper.generateAccessToken());
204             try {
205                 accessTokenService.store(entity);
206                 saveInfo(messages -> messages.addSuccessCrudCreateCrudTable(GLOBAL));
207             } catch (final Exception e) {
208                 throwValidationError(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, buildThrowableMessage(e)),
209                         this::asEditHtml);
210             }
211         }).orElse(() -> {
212             throwValidationError(messages -> messages.addErrorsCrudFailedToCreateInstance(GLOBAL), this::asEditHtml);
213         });
214         return redirect(getClass());
215     }
216 
217     @Execute
218     @Secured({ ROLE })
219     public HtmlResponse update(final EditForm form) {
220         verifyCrudMode(form.crudMode, CrudMode.EDIT);
221         validate(form, messages -> {}, this::asEditHtml);
222         verifyToken(this::asEditHtml);
223         getAccessToken(form).ifPresent(entity -> {
224             try {
225                 accessTokenService.store(entity);
226                 saveInfo(messages -> messages.addSuccessCrudUpdateCrudTable(GLOBAL));
227             } catch (final Exception e) {
228                 throwValidationError(messages -> messages.addErrorsCrudFailedToUpdateCrudTable(GLOBAL, buildThrowableMessage(e)),
229                         this::asEditHtml);
230             }
231         }).orElse(() -> {
232             throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.id), this::asEditHtml);
233         });
234         return redirect(getClass());
235     }
236 
237     @Execute
238     @Secured({ ROLE })
239     public HtmlResponse delete(final EditForm form) {
240         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
241         validate(form, messages -> {}, this::asDetailsHtml);
242         verifyToken(this::asDetailsHtml);
243         final String id = form.id;
244         accessTokenService.getAccessToken(id).ifPresent(entity -> {
245             try {
246                 accessTokenService.delete(entity);
247                 saveInfo(messages -> messages.addSuccessCrudDeleteCrudTable(GLOBAL));
248             } catch (final Exception e) {
249                 throwValidationError(messages -> messages.addErrorsCrudFailedToDeleteCrudTable(GLOBAL, buildThrowableMessage(e)),
250                         this::asEditHtml);
251             }
252         }).orElse(() -> {
253             throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), this::asDetailsHtml);
254         });
255         return redirect(getClass());
256     }
257 
258     // ===================================================================================
259     //                                                                        Assist Logic
260     //                                                                        ============
261 
262     private static OptionalEntity<AccessToken> getEntity(final CreateForm form, final String username, final long currentTime) {
263         switch (form.crudMode) {
264         case CrudMode.CREATE:
265             return OptionalEntity.of(new AccessToken()).map(entity -> {
266                 entity.setCreatedBy(username);
267                 entity.setCreatedTime(currentTime);
268                 return entity;
269             });
270         case CrudMode.EDIT:
271             if (form instanceof EditForm) {
272                 return ComponentUtil.getComponent(AccessTokenService.class).getAccessToken(((EditForm) form).id);
273             }
274             break;
275         default:
276             break;
277         }
278         return OptionalEntity.empty();
279     }
280 
281     public static OptionalEntity<AccessToken> getAccessToken(final CreateForm form) {
282         final SystemHelper systemHelper = ComponentUtil.getSystemHelper();
283         final String username = systemHelper.getUsername();
284         final long currentTime = systemHelper.getCurrentTimeAsLong();
285         return getEntity(form, username, currentTime).map(entity -> {
286             entity.setUpdatedBy(username);
287             entity.setUpdatedTime(currentTime);
288             BeanUtil.copyBeanToBean(form, entity, op -> op.exclude(Constants.COMMON_CONVERSION_RULE)
289                     .exclude(TOKEN, Constants.PERMISSIONS, EXPIRED_TIME).dateConverter(Constants.DEFAULT_DATETIME_FORMAT, EXPIRES));
290             final PermissionHelper permissionHelper = ComponentUtil.getPermissionHelper();
291             entity.setPermissions(split(form.permissions, "\n").get(stream -> stream.map(s -> permissionHelper.encode(s))
292                     .filter(StringUtil::isNotBlank).distinct().toArray(n -> new String[n])));
293             return entity;
294         });
295     }
296 
297     // ===================================================================================
298     //                                                                        Small Helper
299     //                                                                        ============
300     protected void verifyCrudMode(final int crudMode, final int expectedMode) {
301         if (crudMode != expectedMode) {
302             throwValidationError(messages -> {
303                 messages.addErrorsCrudInvalidMode(GLOBAL, String.valueOf(expectedMode), String.valueOf(crudMode));
304             }, this::asListHtml);
305         }
306     }
307 
308     // ===================================================================================
309     //                                                                              JSP
310     //                                                                           =========
311 
312     private HtmlResponse asListHtml() {
313         return asHtml(path_AdminAccesstoken_AdminAccesstokenJsp).renderWith(data -> {
314             RenderDataUtil.register(data, "accessTokenItems", accessTokenService.getAccessTokenList(accessTokenPager));
315         }).useForm(SearchForm.class, setup -> {
316             setup.setup(form -> {
317                 copyBeanToBean(accessTokenPager, form, op -> op.include("id"));
318             });
319         });
320     }
321 
322     private HtmlResponse asEditHtml() {
323         return asHtml(path_AdminAccesstoken_AdminAccesstokenEditJsp);
324     }
325 
326     private HtmlResponse asDetailsHtml() {
327         return asHtml(path_AdminAccesstoken_AdminAccesstokenDetailsJsp);
328     }
329 
330 }