/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.eas.server.handlers; import com.eas.server.RequestHandler; import com.eas.client.SqlQuery; import com.eas.client.login.AnonymousPlatypusPrincipal; import com.eas.client.login.PlatypusPrincipal; import com.eas.client.metadata.Parameter; import com.eas.client.metadata.Parameters; import com.eas.client.queries.LocalQueriesProxy; import com.eas.client.threetier.requests.ExecuteQueryRequest; import com.eas.script.Scripts; import com.eas.server.PlatypusServerCore; import com.eas.server.Session; import java.security.AccessControlException; import java.util.Set; import java.util.function.Consumer; import javax.security.auth.AuthPermission; import jdk.nashorn.api.scripting.JSObject; /** * * @author pk, mg refactoring */ public class ExecuteQueryRequestHandler extends RequestHandler<ExecuteQueryRequest, ExecuteQueryRequest.Response> { public static final String PUBLIC_ACCESS_DENIED_MSG = "Public access to query %s is denied."; public static final String ACCESS_DENIED_MSG = "Access denied to query %s for user %s"; public static final String MISSING_QUERY_MSG = "Query %s not found neither in application database, nor in hand-constructed queries."; public ExecuteQueryRequestHandler(PlatypusServerCore aServerCore, ExecuteQueryRequest aRequest) { super(aServerCore, aRequest); } @Override public void handle(Session aSession, Consumer<ExecuteQueryRequest.Response> onSuccess, Consumer<Exception> onFailure) { try { ((LocalQueriesProxy) getServerCore().getQueries()).getQuery(getRequest().getQueryName(), Scripts.getSpace(), (SqlQuery query) -> { try { if (query == null || query.getEntityName() == null) { throw new Exception(String.format(MISSING_QUERY_MSG, getRequest().getQueryName())); } if (!query.isPublicAccess()) { throw new AccessControlException(String.format(PUBLIC_ACCESS_DENIED_MSG, getRequest().getQueryName()));//NOI18N } Set<String> rolesAllowed = query.getReadRoles(); PlatypusPrincipal principal = (PlatypusPrincipal) Scripts.getContext().getPrincipal(); if (rolesAllowed != null && !principal.hasAnyRole(rolesAllowed)) { throw new AccessControlException(String.format(ACCESS_DENIED_MSG, query.getEntityName(), principal.getName()), principal instanceof AnonymousPlatypusPrincipal ? new AuthPermission("*") : null); } handleQuery(query.copy(), (JSObject aResult) -> { if (onSuccess != null) { onSuccess.accept(new ExecuteQueryRequest.Response(Scripts.getSpace().toJson(aResult))); } }, onFailure, Scripts.getSpace()); } catch (Exception ex) { if (onFailure != null) { onFailure.accept(ex); } } }, onFailure); } catch (Exception ex) { if (onFailure != null) { onFailure.accept(ex); } } } public void handleQuery(SqlQuery aQuery, Consumer<JSObject> onSuccess, Consumer<Exception> onFailure, Scripts.Space aSpace) throws Exception { Parameters queryParams = aQuery.getParameters(); assert queryParams.getParametersCount() == getRequest().getParamsJsons().size(); for (int i = 1; i <= queryParams.getParametersCount(); i++) { Parameter p = queryParams.get(i); String pJson = getRequest().getParamsJsons().get(p.getName()); p.setValue(aSpace.toJava(aSpace.parseJsonWithDates(pJson))); } aQuery.execute(aSpace, onSuccess, onFailure); // SqlCompiledQuery.executeUpdate/Client.enqueueUpdate is prohibited here, because no security check is performed in it. // Stored procedures can't be called directly from three-tier clients for security reasons // and out parameters can't pass through the network. /* if (aQuery.isProcedure()) { for (int i = 1; i <= queryParams.getParametersCount(); i++) { Parameter queryParam = queryParams.get(i); if (queryParam.getMode() == ParameterMetaData.parameterModeOut || queryParam.getMode() == ParameterMetaData.parameterModeInOut) { Parameter executedParam = compiledQuery.getParameters().get(queryParam.getName()); if (executedParam != null) { queryParam.setValue(executedParam.getValue()); } } } } */ } }