1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.app.web.api.admin.badword;
17
18 import static org.codelibs.fess.app.web.admin.badword.AdminBadwordAction.getBadWord;
19
20 import java.io.BufferedReader;
21 import java.io.BufferedWriter;
22 import java.io.InputStream;
23 import java.io.InputStreamReader;
24 import java.io.OutputStreamWriter;
25 import java.io.Reader;
26 import java.io.Writer;
27 import java.nio.file.Files;
28 import java.nio.file.Path;
29 import java.util.List;
30 import java.util.stream.Collectors;
31
32 import org.apache.logging.log4j.LogManager;
33 import org.apache.logging.log4j.Logger;
34 import org.codelibs.core.concurrent.CommonPoolUtil;
35 import org.codelibs.fess.app.pager.BadWordPager;
36 import org.codelibs.fess.app.service.BadWordService;
37 import org.codelibs.fess.app.web.CrudMode;
38 import org.codelibs.fess.app.web.admin.badword.UploadForm;
39 import org.codelibs.fess.app.web.api.ApiResult;
40 import org.codelibs.fess.app.web.api.ApiResult.ApiUpdateResponse;
41 import org.codelibs.fess.app.web.api.ApiResult.Status;
42 import org.codelibs.fess.app.web.api.admin.FessApiAdminAction;
43 import org.codelibs.fess.exception.FessSystemException;
44 import org.codelibs.fess.helper.SuggestHelper;
45 import org.codelibs.fess.opensearch.config.exentity.BadWord;
46 import org.codelibs.fess.util.ComponentUtil;
47 import org.lastaflute.web.Execute;
48 import org.lastaflute.web.response.JsonResponse;
49 import org.lastaflute.web.response.StreamResponse;
50
51 import jakarta.annotation.Resource;
52
53
54
55
56
57 public class ApiAdminBadwordAction extends FessApiAdminAction {
58
59
60
61
62 public ApiAdminBadwordAction() {
63 super();
64 }
65
66 private static final Logger logger = LogManager.getLogger(ApiAdminBadwordAction.class);
67
68 @Resource
69 private BadWordService badWordService;
70
71
72 @Resource
73 protected SuggestHelper suggestHelper;
74
75
76
77
78
79
80
81
82
83 @Execute
84 public JsonResponse<ApiResult> settings(final SearchBody body) {
85 validateApi(body, messages -> {});
86 final BadWordPager pager = copyBeanToNewBean(body, BadWordPager.class);
87 final List<BadWord> list = badWordService.getBadWordList(pager);
88 return asJson(
89 new ApiResult.ApiConfigsResponse<EditBody>().settings(list.stream().map(this::createEditBody).collect(Collectors.toList()))
90 .total(pager.getAllRecordCount())
91 .status(ApiResult.Status.OK)
92 .result());
93 }
94
95
96
97
98
99
100
101
102 @Execute
103 public JsonResponse<ApiResult> get$setting(final String id) {
104
105 final BadWord entity = badWordService.getBadWord(id).orElseGet(() -> {
106 throwValidationErrorApi(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id));
107 return null;
108 });
109
110 final EditBody body = createEditBody(entity);
111 return asJson(new ApiResult.ApiConfigResponse().setting(body).status(ApiResult.Status.OK).result());
112 }
113
114
115
116
117
118
119
120
121 @Execute
122 public JsonResponse<ApiResult> post$setting(final CreateBody body) {
123 validateApi(body, messages -> {});
124 body.crudMode = CrudMode.CREATE;
125 final BadWord entity = getBadWord(body).orElseGet(() -> {
126 throwValidationErrorApi(messages -> {
127 messages.addErrorsCrudFailedToCreateInstance(GLOBAL);
128 });
129 return null;
130 });
131 try {
132 badWordService.store(entity);
133 suggestHelper.addBadWord(entity.getSuggestWord(), false);
134 } catch (final Exception e) {
135 logger.warn("Failed to process a request.", e);
136 throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, buildThrowableMessage(e)));
137 }
138 return asJson(new ApiResult.ApiUpdateResponse().id(entity.getId()).created(true).status(ApiResult.Status.OK).result());
139 }
140
141
142
143
144
145
146
147
148 @Execute
149 public JsonResponse<ApiResult> put$setting(final EditBody body) {
150 validateApi(body, messages -> {});
151 body.crudMode = CrudMode.EDIT;
152 final BadWord badWord = getBadWord(body).map(entity -> {
153 try {
154 badWordService.store(entity);
155 suggestHelper.storeAllBadWords(false);
156 } catch (final Exception e) {
157 logger.warn("Failed to process a request.", e);
158 throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToUpdateCrudTable(GLOBAL, buildThrowableMessage(e)));
159 }
160 return entity;
161 }).orElseGet(() -> {
162 throwValidationErrorApi(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, body.id));
163 return null;
164 });
165
166 return asJson(new ApiUpdateResponse().id(badWord.getId()).created(false).status(Status.OK).result());
167 }
168
169
170
171
172
173
174
175
176 @Execute
177 public JsonResponse<ApiResult> delete$setting(final String id) {
178 try {
179 badWordService.getBadWord(id).ifPresent(entity -> {
180 try {
181 badWordService.delete(entity);
182 suggestHelper.deleteBadWord(entity.getSuggestWord());
183 saveInfo(messages -> messages.addSuccessCrudDeleteCrudTable(GLOBAL));
184 } catch (final Exception e) {
185 logger.warn("Failed to process a request.", e);
186 throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToDeleteCrudTable(GLOBAL, buildThrowableMessage(e)));
187 }
188 }).orElse(() -> {
189 throwValidationErrorApi(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id));
190 });
191 } catch (final Exception e) {
192 logger.warn("Failed to process a request.", e);
193 throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToDeleteCrudTable(GLOBAL, buildThrowableMessage(e)));
194 }
195 return asJson(new ApiResult.ApiUpdateResponse().id(id).created(false).status(ApiResult.Status.OK).result());
196 }
197
198
199
200
201
202
203
204
205 @Execute
206 public JsonResponse<ApiResult> put$upload(final UploadForm body) {
207 validateApi(body, messages -> {});
208 CommonPoolUtil.execute(() -> {
209 try (Reader reader = new BufferedReader(new InputStreamReader(body.badWordFile.getInputStream(), getCsvEncoding()))) {
210 badWordService.importCsv(reader);
211 suggestHelper.storeAllBadWords(false);
212 } catch (final Exception e) {
213 throw new FessSystemException("Failed to import data.", e);
214 }
215 });
216 return asJson(new ApiResult.ApiResponse().status(ApiResult.Status.OK).result());
217 }
218
219
220
221
222
223
224
225
226 @Execute
227 public StreamResponse get$download(final DownloadBody body) {
228 validateApi(body, messages -> {});
229 return asStream("badword.csv").contentTypeOctetStream().stream(out -> {
230 final Path tempFile = ComponentUtil.getSystemHelper().createTempFile("fess-badword-", ".csv").toPath();
231 try {
232 try (Writer writer = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(tempFile), getCsvEncoding()))) {
233 badWordService.exportCsv(writer);
234 } catch (final Exception e) {
235 logger.warn("Failed to process a request.", e);
236 throwValidationErrorApi(messages -> messages.addErrorsFailedToDownloadBadwordFile(GLOBAL));
237 }
238 try (InputStream in = Files.newInputStream(tempFile)) {
239 out.write(in);
240 }
241 } finally {
242 Files.delete(tempFile);
243 }
244 });
245 }
246
247
248
249
250
251
252
253 protected EditBody createEditBody(final BadWord entity) {
254 final EditBody body = new EditBody();
255 copyBeanToBean(entity, body, copyOp -> {
256 copyOp.excludeNull();
257 });
258 return body;
259 }
260
261 private String getCsvEncoding() {
262 return fessConfig.getCsvFileEncoding();
263 }
264
265 }