View Javadoc
1   /*
2    * Copyright 2012-2025 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.api.admin.fileauth;
17  
18  import static org.codelibs.fess.app.web.admin.fileauth.AdminFileauthAction.getFileAuthentication;
19  
20  import java.util.List;
21  import java.util.stream.Collectors;
22  
23  import org.apache.logging.log4j.LogManager;
24  import org.apache.logging.log4j.Logger;
25  import org.codelibs.fess.app.pager.FileAuthPager;
26  import org.codelibs.fess.app.service.FileAuthenticationService;
27  import org.codelibs.fess.app.service.FileConfigService;
28  import org.codelibs.fess.app.web.CrudMode;
29  import org.codelibs.fess.app.web.api.ApiResult;
30  import org.codelibs.fess.app.web.api.ApiResult.ApiConfigResponse;
31  import org.codelibs.fess.app.web.api.ApiResult.ApiErrorResponse;
32  import org.codelibs.fess.app.web.api.ApiResult.ApiResponse;
33  import org.codelibs.fess.app.web.api.ApiResult.ApiUpdateResponse;
34  import org.codelibs.fess.app.web.api.ApiResult.Status;
35  import org.codelibs.fess.app.web.api.admin.FessApiAdminAction;
36  import org.codelibs.fess.opensearch.config.exentity.FileAuthentication;
37  import org.lastaflute.web.Execute;
38  import org.lastaflute.web.response.JsonResponse;
39  
40  import jakarta.annotation.Resource;
41  
42  /**
43   * API action for admin file authentication management.
44   * Provides RESTful API endpoints for managing file authentication settings in the Fess search engine.
45   * File authentication settings define access credentials and permissions for file-based crawling.
46   *
47   */
48  public class ApiAdminFileauthAction extends FessApiAdminAction {
49  
50      private static final Logger logger = LogManager.getLogger(ApiAdminFileauthAction.class);
51  
52      // ===================================================================================
53      //                                                                         Constructor
54      //                                                                         ===========
55      /**
56       * Default constructor.
57       */
58      public ApiAdminFileauthAction() {
59          super();
60      }
61  
62      // ===================================================================================
63      //                                                                           Attribute
64      //                                                                           =========
65      /** Service for managing file authentication configurations */
66      @Resource
67      private FileAuthenticationService fileAuthService;
68      /** Service for managing file configuration settings */
69      @Resource
70      private FileConfigService fileConfigService;
71  
72      // ===================================================================================
73      //                                                                      Search Execute
74      //                                                                      ==============
75  
76      // GET /api/admin/fileauth/settings
77      // PUT /api/admin/fileauth/settings
78      /**
79       * Returns list of file authentication settings.
80       * Supports both GET and PUT requests for retrieving paginated file authentication configurations.
81       *
82       * @param body search parameters for filtering and pagination
83       * @return JSON response containing file authentication settings list with pagination info
84       */
85      @Execute
86      public JsonResponse<ApiResult> settings(final SearchBody body) {
87          validateApi(body, messages -> {});
88          final FileAuthPager pager = copyBeanToNewBean(body, FileAuthPager.class);
89          final List<FileAuthentication> list = fileAuthService.getFileAuthenticationList(pager);
90          return asJson(
91                  new ApiResult.ApiConfigsResponse<EditBody>().settings(list.stream().map(this::createEditBody).collect(Collectors.toList()))
92                          .total(pager.getAllRecordCount())
93                          .status(ApiResult.Status.OK)
94                          .result());
95      }
96  
97      // GET /api/admin/fileauth/setting/{id}
98      /**
99       * Returns specific file authentication setting by ID.
100      *
101      * @param id the file authentication setting ID
102      * @return JSON response containing the file authentication setting details
103      */
104     @Execute
105     public JsonResponse<ApiResult> get$setting(final String id) {
106         return asJson(new ApiConfigResponse().setting(fileAuthService.getFileAuthentication(id).map(this::createEditBody).orElseGet(() -> {
107             throwValidationErrorApi(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id));
108             return null;
109         })).status(Status.OK).result());
110     }
111 
112     // POST /api/admin/fileauth/setting
113     /**
114      * Creates a new file authentication setting.
115      * Validates that the associated file config ID is valid before creation.
116      *
117      * @param body file authentication setting data to create
118      * @return JSON response with created setting ID and status
119      */
120     @Execute
121     public JsonResponse<ApiResult> post$setting(final CreateBody body) {
122         validateApi(body, messages -> {});
123         if (!isValidFileConfigId(body.fileConfigId)) {
124             return asJson(new ApiErrorResponse().message("invalid fileConfigId").status(Status.BAD_REQUEST).result());
125         }
126 
127         body.crudMode = CrudMode.CREATE;
128         final FileAuthentication fileAuth = getFileAuthentication(body).map(entity -> {
129             try {
130                 fileAuthService.store(entity);
131             } catch (final Exception e) {
132                 logger.warn("Failed to process a request.", e);
133                 throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, buildThrowableMessage(e)));
134             }
135             return entity;
136         }).orElseGet(() -> {
137             throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToCreateInstance(GLOBAL));
138             return null;
139         });
140 
141         return asJson(new ApiUpdateResponse().id(fileAuth.getId()).created(true).status(Status.OK).result());
142     }
143 
144     // PUT /api/admin/fileauth/setting
145     /**
146      * Updates an existing file authentication setting.
147      *
148      * @param body file authentication setting data to update
149      * @return JSON response with updated setting ID and status
150      */
151     @Execute
152     public JsonResponse<ApiResult> put$setting(final EditBody body) {
153         validateApi(body, messages -> {});
154         body.crudMode = CrudMode.EDIT;
155         final FileAuthentication fileAuth = getFileAuthentication(body).map(entity -> {
156             try {
157                 fileAuthService.store(entity);
158             } catch (final Exception e) {
159                 logger.warn("Failed to process a request.", e);
160                 throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToUpdateCrudTable(GLOBAL, buildThrowableMessage(e)));
161             }
162             return entity;
163         }).orElseGet(() -> {
164             throwValidationErrorApi(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, body.id));
165             return null;
166         });
167         return asJson(new ApiUpdateResponse().id(fileAuth.getId()).created(false).status(Status.OK).result());
168     }
169 
170     // DELETE /api/admin/fileauth/setting/{id}
171     /**
172      * Deletes a specific file authentication setting.
173      *
174      * @param id the file authentication setting ID to delete
175      * @return JSON response with deletion status
176      */
177     @Execute
178     public JsonResponse<ApiResult> delete$setting(final String id) {
179         fileAuthService.getFileAuthentication(id).ifPresent(entity -> {
180             try {
181                 fileAuthService.delete(entity);
182                 saveInfo(messages -> messages.addSuccessCrudDeleteCrudTable(GLOBAL));
183             } catch (final Exception e) {
184                 logger.warn("Failed to process a request.", e);
185                 throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToDeleteCrudTable(GLOBAL, buildThrowableMessage(e)));
186             }
187         }).orElse(() -> {
188             throwValidationErrorApi(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id));
189         });
190         return asJson(new ApiResponse().status(Status.OK).result());
191     }
192 
193     /**
194      * Creates an edit body from a file authentication entity for API responses.
195      *
196      * @param entity the file authentication entity to convert
197      * @return edit body containing the entity data
198      */
199     protected EditBody createEditBody(final FileAuthentication entity) {
200         final EditBody body = new EditBody();
201         copyBeanToBean(entity, body, copyOp -> {
202             copyOp.excludeNull();
203         });
204         return body;
205     }
206 
207     /**
208      * Validates whether a file configuration ID exists.
209      *
210      * @param fileconfigId the file configuration ID to validate
211      * @return true if the file configuration exists, false otherwise
212      */
213     protected Boolean isValidFileConfigId(final String fileconfigId) {
214         return fileConfigService.getFileConfig(fileconfigId).isPresent();
215     }
216 }