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;
17  
18  import java.util.Locale;
19  import java.util.stream.Collectors;
20  
21  import org.codelibs.fess.app.service.AccessTokenService;
22  import org.codelibs.fess.app.web.api.ApiResult.ApiErrorResponse;
23  import org.codelibs.fess.app.web.api.ApiResult.Status;
24  import org.codelibs.fess.app.web.base.FessBaseAction;
25  import org.codelibs.fess.mylasta.action.FessMessages;
26  import org.dbflute.optional.OptionalThing;
27  import org.lastaflute.core.message.MessageManager;
28  import org.lastaflute.web.login.LoginManager;
29  import org.lastaflute.web.response.ActionResponse;
30  import org.lastaflute.web.ruts.process.ActionRuntime;
31  import org.lastaflute.web.validation.VaMessenger;
32  
33  import jakarta.annotation.Resource;
34  import jakarta.servlet.http.HttpServletRequest;
35  
36  /**
37   * Abstract base class for Fess API actions that provides common functionality
38   * for API endpoints including authentication, message handling, and access control.
39   *
40   * This class extends FessBaseAction and provides specialized behavior for API requests,
41   * including token-based authentication and JSON response handling.
42   */
43  public abstract class FessApiAction extends FessBaseAction {
44  
45      /**
46       * Default constructor.
47       */
48      public FessApiAction() {
49          super();
50      }
51  
52      /**
53       * Message manager for handling internationalized messages and validation errors.
54       * Used to convert validation messages to localized text for API responses.
55       */
56      @Resource
57      protected MessageManager messageManager;
58  
59      /**
60       * Service for managing API access tokens including validation and authentication.
61       * Used to verify token-based authentication for API requests.
62       */
63      @Resource
64      protected AccessTokenService accessTokenService;
65  
66      /**
67       * HTTP servlet request object providing access to request parameters, headers,
68       * and other request-specific information needed for API processing.
69       */
70      @Resource
71      protected HttpServletRequest request;
72  
73      /**
74       * Returns an empty OptionalThing for login manager since API actions
75       * use token-based authentication instead of traditional session-based login.
76       *
77       * @return empty OptionalThing indicating no login manager is used
78       */
79      @Override
80      protected OptionalThing<LoginManager> myLoginManager() {
81          return OptionalThing.empty();
82      }
83  
84      /**
85       * Pre-processes API requests by checking access authorization before executing the action.
86       * If access is not allowed, returns an unauthorized error response.
87       *
88       * @param runtime the action runtime context containing request information
89       * @return ActionResponse with unauthorized error if access denied, otherwise delegates to parent
90       */
91      @Override
92      public ActionResponse godHandPrologue(final ActionRuntime runtime) {
93          if (!isAccessAllowed()) {
94              return asJson(new ApiErrorResponse().message(getMessage(messages -> messages.addErrorsUnauthorizedRequest(GLOBAL)))
95                      .status(Status.UNAUTHORIZED)
96                      .result());
97          }
98          return super.godHandPrologue(runtime);
99      }
100 
101     /**
102      * Converts validation messages to a localized string representation for API responses.
103      * Uses the request locale if available, otherwise defaults to English.
104      *
105      * @param validationMessagesLambda lambda function that adds validation messages
106      * @return concatenated string of localized validation messages separated by spaces
107      */
108     protected String getMessage(final VaMessenger<FessMessages> validationMessagesLambda) {
109         final FessMessages messages = new FessMessages();
110         validationMessagesLambda.message(messages);
111         return messageManager.toMessageList(request.getLocale() == null ? Locale.ENGLISH : request.getLocale(), messages)
112                 .stream()
113                 .collect(Collectors.joining(" "));
114     }
115 
116     /**
117      * Determines whether the current request is authorized to access the API endpoint.
118      * This default implementation returns false, requiring subclasses to override
119      * and implement proper access control logic.
120      *
121      * @return true if access is allowed, false otherwise
122      */
123     protected boolean isAccessAllowed() {
124         return false;
125     }
126 }