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 }