1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.app.web.admin.webconfig;
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 import java.util.stream.Stream;
23
24 import org.apache.logging.log4j.LogManager;
25 import org.apache.logging.log4j.Logger;
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.WebConfigPager;
30 import org.codelibs.fess.app.service.LabelTypeService;
31 import org.codelibs.fess.app.service.RoleTypeService;
32 import org.codelibs.fess.app.service.ScheduledJobService;
33 import org.codelibs.fess.app.service.WebConfigService;
34 import org.codelibs.fess.app.web.CrudMode;
35 import org.codelibs.fess.app.web.base.FessAdminAction;
36 import org.codelibs.fess.helper.PermissionHelper;
37 import org.codelibs.fess.helper.SystemHelper;
38 import org.codelibs.fess.opensearch.config.exentity.CrawlingConfig.ConfigType;
39 import org.codelibs.fess.opensearch.config.exentity.WebConfig;
40 import org.codelibs.fess.util.ComponentUtil;
41 import org.codelibs.fess.util.RenderDataUtil;
42 import org.dbflute.optional.OptionalEntity;
43 import org.dbflute.optional.OptionalThing;
44 import org.lastaflute.web.Execute;
45 import org.lastaflute.web.response.HtmlResponse;
46 import org.lastaflute.web.response.render.RenderData;
47 import org.lastaflute.web.ruts.process.ActionRuntime;
48
49 import jakarta.annotation.Resource;
50
51
52
53
54
55 public class AdminWebconfigAction extends FessAdminAction {
56
57
58
59
60 public AdminWebconfigAction() {
61 super();
62 }
63
64
65 public static final String ROLE = "admin-webconfig";
66
67 private static final Logger logger = LogManager.getLogger(AdminWebconfigAction.class);
68
69
70
71
72 @Resource
73 private WebConfigService webConfigService;
74 @Resource
75 private ScheduledJobService scheduledJobService;
76 @Resource
77 private WebConfigPager webConfigPager;
78 @Resource
79 private RoleTypeService roleTypeService;
80 @Resource
81 private LabelTypeService labelTypeService;
82
83
84
85
86 @Override
87 protected void setupHtmlData(final ActionRuntime runtime) {
88 super.setupHtmlData(runtime);
89 runtime.registerData("helpLink", systemHelper.getHelpLink(fessConfig.getOnlineHelpNameWebconfig()));
90 }
91
92 @Override
93 protected String getActionRole() {
94 return ROLE;
95 }
96
97
98
99
100
101
102
103
104
105
106 @Execute
107 @Secured({ ROLE, ROLE + VIEW })
108 public HtmlResponse index(final SearchForm form) {
109 return asListHtml();
110 }
111
112
113
114
115
116
117
118
119 @Execute
120 @Secured({ ROLE, ROLE + VIEW })
121 public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
122 pageNumber.ifPresent(num -> {
123 webConfigPager.setCurrentPageNumber(pageNumber.get());
124 }).orElse(() -> {
125 webConfigPager.setCurrentPageNumber(0);
126 });
127 return asHtml(path_AdminWebconfig_AdminWebconfigJsp).renderWith(data -> {
128 searchPaging(data, form);
129 });
130 }
131
132
133
134
135
136
137
138 @Execute
139 @Secured({ ROLE, ROLE + VIEW })
140 public HtmlResponse search(final SearchForm form) {
141 copyBeanToBean(form, webConfigPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
142 return asHtml(path_AdminWebconfig_AdminWebconfigJsp).renderWith(data -> {
143 searchPaging(data, form);
144 });
145 }
146
147
148
149
150
151
152
153 @Execute
154 @Secured({ ROLE, ROLE + VIEW })
155 public HtmlResponse reset(final SearchForm form) {
156 webConfigPager.clear();
157 return asHtml(path_AdminWebconfig_AdminWebconfigJsp).renderWith(data -> {
158 searchPaging(data, form);
159 });
160 }
161
162
163
164
165
166
167
168
169 protected void searchPaging(final RenderData data, final SearchForm form) {
170 RenderDataUtil.register(data, "webConfigItems", webConfigService.getWebConfigList(webConfigPager));
171
172
173 copyBeanToBean(webConfigPager, form, op -> op.include("id", "name", "urls", "description"));
174 }
175
176
177
178
179
180
181
182
183
184
185
186
187 @Execute
188 @Secured({ ROLE })
189 public HtmlResponse createnew() {
190 saveToken();
191 return asEditHtml().useForm(CreateForm.class, op -> {
192 op.setup(form -> {
193 form.initialize();
194 ComponentUtil.getCrawlingConfigHelper().getDefaultConfig(ConfigType.WEB).ifPresent(entity -> {
195 copyBeanToBean(entity, form, copyOp -> {
196 copyOp.excludeNull();
197 copyOp.exclude(Stream.concat(Stream.of(Constants.COMMON_CONVERSION_RULE),
198 Stream.of(Constants.PERMISSIONS, Constants.VIRTUAL_HOSTS)).toArray(n -> new String[n]));
199 });
200 final PermissionHelper permissionHelper = ComponentUtil.getPermissionHelper();
201 form.permissions = stream(entity.getPermissions()).get(stream -> stream.map(s -> permissionHelper.decode(s))
202 .filter(StringUtil::isNotBlank)
203 .distinct()
204 .collect(Collectors.joining("\n")));
205 form.virtualHosts = stream(entity.getVirtualHosts())
206 .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).collect(Collectors.joining("\n")));
207 form.name = null;
208 });
209 form.crudMode = CrudMode.CREATE;
210 });
211 });
212 }
213
214
215
216
217
218
219
220 @Execute
221 @Secured({ ROLE })
222 public HtmlResponse duplicate(final String id) {
223 saveToken();
224 return asEditHtml().useForm(CreateForm.class, op -> {
225 op.setup(form -> {
226 form.initialize();
227 webConfigService.getWebConfig(id).ifPresent(entity -> {
228 copyBeanToBean(entity, form, copyOp -> {
229 copyOp.excludeNull();
230 copyOp.exclude(Stream.concat(Stream.of(Constants.COMMON_CONVERSION_RULE),
231 Stream.of(Constants.PERMISSIONS, Constants.VIRTUAL_HOSTS)).toArray(n -> new String[n]));
232 });
233 final PermissionHelper permissionHelper = ComponentUtil.getPermissionHelper();
234 form.permissions = stream(entity.getPermissions()).get(stream -> stream.map(s -> permissionHelper.decode(s))
235 .filter(StringUtil::isNotBlank)
236 .distinct()
237 .collect(Collectors.joining("\n")));
238 form.virtualHosts = stream(entity.getVirtualHosts())
239 .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).collect(Collectors.joining("\n")));
240 form.name = null;
241 }).orElse(() -> {
242 throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), this::asListHtml);
243 });
244 form.crudMode = CrudMode.CREATE;
245 });
246 });
247 }
248
249
250
251
252
253
254
255 @Execute
256 @Secured({ ROLE })
257 public HtmlResponse edit(final EditForm form) {
258 validate(form, messages -> {}, this::asListHtml);
259 final String id = form.id;
260 webConfigService.getWebConfig(id).ifPresent(entity -> {
261 copyBeanToBean(entity, form, copyOp -> {
262 copyOp.excludeNull();
263 copyOp.exclude(Constants.PERMISSIONS, Constants.VIRTUAL_HOSTS);
264 });
265 final PermissionHelper permissionHelper = ComponentUtil.getPermissionHelper();
266 form.permissions = stream(entity.getPermissions()).get(stream -> stream.map(s -> permissionHelper.decode(s))
267 .filter(StringUtil::isNotBlank)
268 .distinct()
269 .collect(Collectors.joining("\n")));
270 form.virtualHosts = stream(entity.getVirtualHosts())
271 .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).collect(Collectors.joining("\n")));
272 }).orElse(() -> {
273 throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), this::asListHtml);
274 });
275 saveToken();
276 if (form.crudMode.intValue() == CrudMode.EDIT) {
277
278 form.crudMode = CrudMode.DETAILS;
279 return asDetailsHtml();
280 }
281 form.crudMode = CrudMode.EDIT;
282 return asEditHtml();
283 }
284
285
286
287
288
289
290
291
292
293
294
295 @Execute
296 @Secured({ ROLE, ROLE + VIEW })
297 public HtmlResponse details(final int crudMode, final String id) {
298 verifyCrudMode(crudMode, CrudMode.DETAILS, this::asListHtml);
299 saveToken();
300 return asDetailsHtml().useForm(EditForm.class, op -> {
301 op.setup(form -> {
302 webConfigService.getWebConfig(id).ifPresent(entity -> {
303 copyBeanToBean(entity, form, copyOp -> {
304 copyOp.excludeNull();
305 copyOp.exclude(Constants.PERMISSIONS, Constants.VIRTUAL_HOSTS);
306 });
307 final PermissionHelper permissionHelper = ComponentUtil.getPermissionHelper();
308 form.permissions = stream(entity.getPermissions()).get(stream -> stream.map(s -> permissionHelper.decode(s))
309 .filter(StringUtil::isNotBlank)
310 .distinct()
311 .collect(Collectors.joining("\n")));
312 form.virtualHosts = stream(entity.getVirtualHosts())
313 .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).collect(Collectors.joining("\n")));
314 form.crudMode = crudMode;
315 }).orElse(() -> {
316 throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), this::asListHtml);
317 });
318 });
319 });
320 }
321
322
323
324
325
326
327
328
329
330
331 @Execute
332 @Secured({ ROLE })
333 public HtmlResponse create(final CreateForm form) {
334 verifyCrudMode(form.crudMode, CrudMode.CREATE, this::asListHtml);
335 validate(form, messages -> {}, this::asEditHtml);
336 verifyToken(this::asEditHtml);
337 getWebConfig(form).ifPresent(entity -> {
338 try {
339 webConfigService.store(entity);
340 saveInfo(messages -> messages.addSuccessCrudCreateCrudTable(GLOBAL));
341 logger.info("Created web config: {}", entity.getName());
342 } catch (final Exception e) {
343 logger.warn("Failed to create web config: {}", form.name, e);
344 throwValidationError(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, buildThrowableMessage(e)),
345 this::asEditHtml);
346 }
347 }).orElse(() -> {
348 throwValidationError(messages -> messages.addErrorsCrudFailedToCreateInstance(GLOBAL), this::asEditHtml);
349 });
350 return redirect(getClass());
351 }
352
353
354
355
356
357
358
359 @Execute
360 @Secured({ ROLE })
361 public HtmlResponse update(final EditForm form) {
362 verifyCrudMode(form.crudMode, CrudMode.EDIT, this::asListHtml);
363 validate(form, messages -> {}, this::asEditHtml);
364 verifyToken(this::asEditHtml);
365 getWebConfig(form).ifPresent(entity -> {
366 try {
367 webConfigService.store(entity);
368 saveInfo(messages -> messages.addSuccessCrudUpdateCrudTable(GLOBAL));
369 logger.info("Updated web config: {}", entity.getName());
370 } catch (final Exception e) {
371 logger.warn("Failed to update web config: {}", form.name, e);
372 throwValidationError(messages -> messages.addErrorsCrudFailedToUpdateCrudTable(GLOBAL, buildThrowableMessage(e)),
373 this::asEditHtml);
374 }
375 }).orElse(() -> {
376 throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.id), this::asEditHtml);
377 });
378 return redirect(getClass());
379 }
380
381
382
383
384
385
386
387 @Execute
388 @Secured({ ROLE })
389 public HtmlResponse delete(final EditForm form) {
390 verifyCrudMode(form.crudMode, CrudMode.DETAILS, this::asListHtml);
391 validate(form, messages -> {}, this::asDetailsHtml);
392 verifyToken(this::asDetailsHtml);
393 final String id = form.id;
394 webConfigService.getWebConfig(id).ifPresent(entity -> {
395 try {
396 webConfigService.delete(entity);
397 saveInfo(messages -> messages.addSuccessCrudDeleteCrudTable(GLOBAL));
398 logger.info("Deleted web config: {}", entity.getName());
399 } catch (final Exception e) {
400 logger.warn("Failed to delete web config: {}", form.name, e);
401 throwValidationError(messages -> messages.addErrorsCrudFailedToDeleteCrudTable(GLOBAL, buildThrowableMessage(e)),
402 this::asEditHtml);
403 }
404 }).orElse(() -> {
405 throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), this::asDetailsHtml);
406 });
407 return redirect(getClass());
408 }
409
410
411
412
413
414
415
416
417
418
419
420
421 public static OptionalEntity<WebConfig> getEntity(final CreateForm form, final String username, final long currentTime) {
422 switch (form.crudMode) {
423 case CrudMode.CREATE:
424 return OptionalEntity.of(new WebConfig()).map(entity -> {
425 entity.setCreatedBy(username);
426 entity.setCreatedTime(currentTime);
427 return entity;
428 });
429 case CrudMode.EDIT:
430 if (form instanceof EditForm) {
431 return ComponentUtil.getComponent(WebConfigService.class).getWebConfig(((EditForm) form).id);
432 }
433 break;
434 default:
435 break;
436 }
437 return OptionalEntity.empty();
438 }
439
440
441
442
443
444
445
446
447 public static OptionalEntity<WebConfig> getWebConfig(final CreateForm form) {
448 final SystemHelper systemHelper = ComponentUtil.getSystemHelper();
449 final String username = systemHelper.getUsername();
450 final long currentTime = systemHelper.getCurrentTimeAsLong();
451 return getEntity(form, username, currentTime).map(entity -> {
452 entity.setUpdatedBy(username);
453 entity.setUpdatedTime(currentTime);
454 copyBeanToBean(form, entity,
455 op -> op.exclude(Stream
456 .concat(Stream.of(Constants.COMMON_CONVERSION_RULE), Stream.of(Constants.PERMISSIONS, Constants.VIRTUAL_HOSTS))
457 .toArray(n -> new String[n])));
458 entity.setPermissions(encodePermissions(form.permissions));
459 entity.setVirtualHosts(split(form.virtualHosts, "\n")
460 .get(stream -> stream.filter(StringUtil::isNotBlank).distinct().map(String::trim).toArray(n -> new String[n])));
461 return entity;
462 });
463 }
464
465
466
467
468
469
470
471 protected void registerRolesAndLabels(final RenderData data) {
472 RenderDataUtil.register(data, "labelSettingEnabled", fessConfig.isFormAdminLabelInConfigEnabled());
473 RenderDataUtil.register(data, "roleTypeItems", roleTypeService.getRoleTypeList());
474 RenderDataUtil.register(data, "labelTypeItems", labelTypeService.getLabelTypeList());
475 }
476
477
478
479
480
481
482
483 private HtmlResponse asListHtml() {
484 return asHtml(path_AdminWebconfig_AdminWebconfigJsp).renderWith(data -> {
485 RenderDataUtil.register(data, "webConfigItems", webConfigService.getWebConfigList(webConfigPager));
486 }).useForm(SearchForm.class, setup -> {
487 setup.setup(form -> {
488 copyBeanToBean(webConfigPager, form, op -> op.include("id", "name", "urls", "description"));
489 });
490 });
491 }
492
493 private HtmlResponse asEditHtml() {
494 return asHtml(path_AdminWebconfig_AdminWebconfigEditJsp).renderWith(data -> {
495 registerRolesAndLabels(data);
496 });
497 }
498
499 private HtmlResponse asDetailsHtml() {
500 return asHtml(path_AdminWebconfig_AdminWebconfigDetailsJsp).renderWith(data -> {
501 registerRolesAndLabels(data);
502 });
503 }
504 }