diff --git a/server/bundles/io.cloudbeaver.server/plugin.xml b/server/bundles/io.cloudbeaver.server/plugin.xml index 73656b40b7..9259eddd80 100644 --- a/server/bundles/io.cloudbeaver.server/plugin.xml +++ b/server/bundles/io.cloudbeaver.server/plugin.xml @@ -75,4 +75,12 @@ + + + + + + diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLEndpoint.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLEndpoint.java index 15506f79dd..d47612147b 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLEndpoint.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLEndpoint.java @@ -51,10 +51,7 @@ import java.io.Reader; import java.lang.reflect.InvocationTargetException; import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.CompletableFuture; public class GraphQLEndpoint extends HttpServlet { @@ -68,7 +65,6 @@ public class GraphQLEndpoint extends HttpServlet { private static final String HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials"; private static final String CORE_SCHEMA_FILE_NAME = "schema/schema.graphqls"; - private final GraphQL graphQL; private static final Gson gson = new GsonBuilder() @@ -253,10 +249,13 @@ private void executeQuery(HttpServletRequest request, HttpServletResponse respon // apiCall += " (" + variables + ")"; // } // } + String sessionId = GraphQLLoggerUtil.getSessionId(request); + String userId = GraphQLLoggerUtil.getUserId(request); + String loggerMessage = GraphQLLoggerUtil.buildLoggerMessage(sessionId, userId, variables); if (apiCall != null) { - log.debug("API > " + apiCall); + log.debug("API > " + apiCall + loggerMessage); } else if (DEBUG) { - log.debug("API > " + query); + log.debug("API > " + query + loggerMessage); } } ExecutionInput executionInput = contextBuilder.build(); diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLLoggerUtil.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLLoggerUtil.java new file mode 100644 index 0000000000..b42e1f28d9 --- /dev/null +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/graphql/GraphQLLoggerUtil.java @@ -0,0 +1,102 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.cloudbeaver.server.graphql; + +import io.cloudbeaver.model.session.WebSession; +import io.cloudbeaver.server.CBApplication; +import io.cloudbeaver.server.CBPlatform; +import jakarta.servlet.http.HttpServletRequest; +import org.jkiss.utils.CommonUtils; + +import java.util.Map; +import java.util.Set; + +public class GraphQLLoggerUtil { + + public static final String LOG_API_GRAPHQL_DEBUG_PARAMETER = "log.api.graphql.debug"; + private static final Set PROHIBITED_VARIABLES = + Set.of("password", "config", "parameters", "settings", "licenseText", "credentials", "username"); + + public static String getUserId(HttpServletRequest request) { + WebSession session = getWebSession(request); + if (session == null) { + return null; + } + String userId = session.getUserContext().getUserId(); + if (userId == null && session.getUserContext().isAuthorizedInSecurityManager()) { + return "anonymous"; + } + return userId; + } + + public static String getSessionId(HttpServletRequest request) { + WebSession session = getWebSession(request); + if (session == null) { + return null; + } + return session.getUserContext().getSmSessionId(); + } + + private static WebSession getWebSession(HttpServletRequest request) { + if (request.getSession() == null) { + return null; + } + return (WebSession) CBApplication.getInstance() + .getSessionManager() + .getSession(request.getSession().getId()); + } + + public static String buildLoggerMessage(String sessionId, String userId, Map variables) { + StringBuilder loggerMessage = new StringBuilder(" [user: ").append(userId) + .append(", sessionId: ").append(sessionId).append("]"); + + if (CBPlatform.getInstance().getPreferenceStore().getBoolean(LOG_API_GRAPHQL_DEBUG_PARAMETER) + && variables != null + ) { + loggerMessage.append(" [variables] "); + String parsedVariables = parseVarialbes(variables); + if (CommonUtils.isNotEmpty(parsedVariables)) { + loggerMessage.append(parseVarialbes(variables)); + } + } + return loggerMessage.toString(); + } + + private static String parseVarialbes(Map map) { + StringBuilder result = new StringBuilder(); + + for (Map.Entry entry : map.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + + boolean isProhibited = PROHIBITED_VARIABLES.stream() + .anyMatch(prohibitedKey -> key.toLowerCase().contains(prohibitedKey.toLowerCase())); + + if (isProhibited) { + result.append(key).append(": ").append("******** "); + continue; + } + + if (value instanceof Map) { + result.append(parseVarialbes((Map) value)); + } else { + result.append(key).append(": ").append(value).append(" "); + } + } + return result.toString().trim(); + } +}