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.user;
17  
18  import static org.codelibs.fess.app.web.admin.user.AdminUserAction.getUser;
19  import static org.codelibs.fess.app.web.admin.user.AdminUserAction.validateAttributes;
20  
21  import java.util.List;
22  import java.util.stream.Collectors;
23  
24  import org.apache.logging.log4j.LogManager;
25  import org.apache.logging.log4j.Logger;
26  import org.codelibs.fess.app.pager.UserPager;
27  import org.codelibs.fess.app.service.UserService;
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.admin.FessApiAdminAction;
31  import org.codelibs.fess.opensearch.user.exentity.User;
32  import org.lastaflute.web.Execute;
33  import org.lastaflute.web.response.JsonResponse;
34  
35  import jakarta.annotation.Resource;
36  
37  /**
38   * API action for admin user management.
39   */
40  public class ApiAdminUserAction extends FessApiAdminAction {
41  
42      /** The logger for this class. */
43      private static final Logger logger = LogManager.getLogger(ApiAdminUserAction.class);
44  
45      // ===================================================================================
46      //                                                                         Constructor
47      //                                                                         ===========
48      /**
49       * Default constructor.
50       */
51      public ApiAdminUserAction() {
52          super();
53      }
54  
55      // ===================================================================================
56      //                                                                           Attribute
57      //                                                                           =========
58  
59      /** The user service for managing user settings. */
60      @Resource
61      private UserService userService;
62  
63      /**
64       * Retrieves user settings with pagination.
65       *
66       * @param body the search parameters for filtering and pagination
67       * @return JSON response containing user settings list
68       */
69      // GET /api/admin/user/settings
70      // PUT /api/admin/user/settings
71      @Execute
72      public JsonResponse<ApiResult> settings(final SearchBody body) {
73          validateApi(body, messages -> {});
74          final UserPager pager = copyBeanToNewBean(body, UserPager.class);
75          final List<User> list = userService.getUserList(pager);
76          return asJson(
77                  new ApiResult.ApiConfigsResponse<EditBody>().settings(list.stream().map(this::createEditBody).collect(Collectors.toList()))
78                          .total(pager.getAllRecordCount())
79                          .status(ApiResult.Status.OK)
80                          .result());
81      }
82  
83      /**
84       * Retrieves a specific user setting by ID.
85       *
86       * @param id the ID of the user setting to retrieve
87       * @return JSON response containing the user setting
88       */
89      // GET /api/admin/user/setting/{id}
90      @Execute
91      public JsonResponse<ApiResult> get$setting(final String id) {
92          return asJson(new ApiResult.ApiConfigResponse().setting(userService.getUser(id).map(this::createEditBody).orElseGet(() -> {
93              throwValidationErrorApi(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id));
94              return null;
95          })).status(ApiResult.Status.OK).result());
96      }
97  
98      /**
99       * Creates a new user setting.
100      *
101      * @param body the user data to create
102      * @return JSON response containing the created user setting ID
103      */
104     // POST /api/admin/user/setting
105     @Execute
106     public JsonResponse<ApiResult> post$setting(final CreateBody body) {
107         validateApi(body, messages -> {});
108         body.crudMode = CrudMode.CREATE;
109         final User entity = getUser(body).orElseGet(() -> {
110             throwValidationErrorApi(messages -> {
111                 messages.addErrorsCrudFailedToCreateInstance(GLOBAL);
112             });
113             return null;
114         });
115         try {
116             userService.store(entity);
117             saveInfo(messages -> messages.addSuccessCrudCreateCrudTable(GLOBAL));
118         } catch (final Exception e) {
119             logger.warn("Failed to create user: username={}, error={}", body.name, e.getMessage(), e);
120             throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToCreateCrudTable(GLOBAL, buildThrowableMessage(e)));
121         }
122         return asJson(new ApiResult.ApiUpdateResponse().id(entity.getId()).created(true).status(ApiResult.Status.OK).result());
123     }
124 
125     /**
126      * Updates an existing user setting.
127      *
128      * @param body the user data to update
129      * @return JSON response containing the updated user setting ID
130      */
131     // PUT /api/admin/user/setting
132     @Execute
133     public JsonResponse<ApiResult> put$setting(final EditBody body) {
134         validateApi(body, messages -> {});
135         validateAttributes(body.attributes, this::throwValidationErrorApi);
136         body.crudMode = CrudMode.EDIT;
137         final User entity = getUser(body).orElseGet(() -> {
138             throwValidationErrorApi(messages -> {
139                 messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, body.id);
140             });
141             return null;
142         });
143         try {
144             userService.store(entity);
145         } catch (final Exception e) {
146             logger.warn("Failed to update user: id={}, username={}, error={}", body.id, body.name, e.getMessage(), e);
147             throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToUpdateCrudTable(GLOBAL, buildThrowableMessage(e)));
148         }
149         return asJson(new ApiResult.ApiUpdateResponse().id(entity.getId()).created(false).status(ApiResult.Status.OK).result());
150     }
151 
152     /**
153      * Deletes a user setting by ID.
154      *
155      * @param id the ID of the user setting to delete
156      * @return JSON response indicating success or failure
157      */
158     // DELETE /api/admin/user/setting/{id}
159     @Execute
160     public JsonResponse<ApiResult> delete$setting(final String id) {
161         final User entity = userService.getUser(id).orElseGet(() -> {
162             throwValidationErrorApi(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id));
163             return null;
164         });
165         getUserBean().ifPresent(u -> {
166             if (u.getFessUser() instanceof User && entity.getName().equals(u.getUserId())) {
167                 throwValidationErrorApi(messages -> messages.addErrorsCouldNotDeleteLoggedInUser(GLOBAL));
168             }
169         });
170         try {
171             userService.delete(entity);
172             saveInfo(messages -> messages.addSuccessCrudDeleteCrudTable(GLOBAL));
173         } catch (final Exception e) {
174             logger.warn("Failed to delete user: id={}, username={}, error={}", id, entity.getName(), e.getMessage(), e);
175             throwValidationErrorApi(messages -> messages.addErrorsCrudFailedToDeleteCrudTable(GLOBAL, buildThrowableMessage(e)));
176         }
177         return asJson(new ApiResult.ApiUpdateResponse().id(id).created(false).status(ApiResult.Status.OK).result());
178     }
179 
180     /**
181      * Creates an EditBody from a User entity.
182      *
183      * @param entity the user entity to convert
184      * @return the converted EditBody
185      */
186     protected EditBody createEditBody(final User entity) {
187         final EditBody body = new EditBody();
188         copyBeanToBean(entity, body, copyOp -> {
189             copyOp.excludeNull();
190         });
191         body.password = null;
192         body.confirmPassword = null;
193         return body;
194     }
195 }