All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.devbench.uibuilder.data.common.dataprovidersupport.DataProviderRequestHandler Maven / Gradle / Ivy

/*
 *
 * Copyright © 2018 Webvalto Ltd.
 *
 * 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.devbench.uibuilder.data.common.dataprovidersupport;

import com.google.gson.GsonBuilder;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.server.*;
import com.vaadin.flow.shared.JsonConstants;
import io.devbench.uibuilder.data.api.DataErrorEvent;
import io.devbench.uibuilder.data.common.dataprovidersupport.requestresponse.DataProviderRequest;
import io.devbench.uibuilder.data.common.dataprovidersupport.requestresponse.DataResponse;
import io.devbench.uibuilder.data.common.exceptions.UINotFoundException;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;

import java.nio.charset.StandardCharsets;
import java.util.Optional;

@Slf4j
public class DataProviderRequestHandler implements RequestHandler {

    public static final String CSRF_TOKEN_ERROR = "WRONG CSRF TOKEN";

    @Override
    public boolean handleRequest(VaadinSession session, VaadinRequest request, VaadinResponse response) {
        String pathInfo = request.getPathInfo();
        if (pathInfo != null && pathInfo.startsWith("/datasource-api")) {
            String endpointId = pathInfo.substring(pathInfo.lastIndexOf("/") + 1);
            try {
                UI currentUI = findUI(session, request);
                DataProviderRequest dataProviderRequest = new GsonBuilder().create().fromJson(request.getReader(), DataProviderRequest.class);
                dataProviderRequest.setEndpointId(endpointId);
                response.setHeader("Cache-Control", "no-cache");
                byte[] responseContent;
                if (isCsrfTokenValid(currentUI, dataProviderRequest)) {
                    responseContent = handleValidRequest(session, response, dataProviderRequest);
                } else {
                    response.setContentType("text/plain");
                    responseContent = CSRF_TOKEN_ERROR.getBytes(StandardCharsets.UTF_8);
                    getLog().warn("Invalid security key received from {}, on endpoint: {}", request.getRemoteHost(), pathInfo);
                }

                response.setContentLength(responseContent.length);
                response.getOutputStream().write(responseContent);
                response.getOutputStream().flush();

            } catch (Throwable ex) {
                handleExceptionUsingEndpointId(ex);
            }
            return true;
        }

        return false;
    }

    private UI findUI(VaadinSession session, VaadinRequest request) throws UINotFoundException {
        session.lock();
        try {
            UI ui = session.getService().findUI(request);
            if (ui == null) {
                throw new UINotFoundException("UI cannot be found by request");
            }
            UI.setCurrent(ui);
            return ui;
        } finally {
            session.unlock();
        }
    }

    private void handleExceptionUsingEndpointId(Throwable throwable) {
        Optional ui = Optional.ofNullable(UI.getCurrent());
        if (ui.isPresent()) {
            ui.get().access(() -> handleExceptionWithErrorHandler(throwable));
        } else {
            getLog().error("Cannot access UI", throwable);
        }
    }

    private void handleExceptionWithErrorHandler(Throwable throwable) {
        VaadinSession session = UI.getCurrent().getSession();
        ErrorHandler errorHandler;

        try {
            session.lock();
            errorHandler = session.getErrorHandler();
        } finally {
            session.unlock();
        }

        if (errorHandler != null) {
            errorHandler.error(new DataErrorEvent(throwable));
        }
    }

    private boolean isCsrfTokenValid(UI ui, DataProviderRequest dataProviderRequest) {
        VaadinSession session = ui.getSession();
        try {
            session.lock();
            return VaadinService.isCsrfTokenValid(ui, dataProviderRequest.getCsrfId());
        } finally {
            session.unlock();
        }
    }

    /**
     * For easier log testing.
     */
    protected Logger getLog() {
        return log;
    }

    private byte[] handleValidRequest(VaadinSession session, VaadinResponse response, DataProviderRequest dataProviderRequest) {
        byte[] responseContent;
        synchronized (session) {
            try {
                session.lock();
                switch (dataProviderRequest.getRequestType()) {
                    case FETCH_DATA:
                        response.setContentType(JsonConstants.JSON_CONTENT_TYPE);
                        DataResponse dataResponse = DataProviderEndpointManager.getInstance().processFetchDataRequest(dataProviderRequest);
                        responseContent = dataResponse.asString().getBytes(StandardCharsets.UTF_8);
                        break;
                    case FETCH_SIZE:
                        response.setContentType("text/plain");
                        Long size = DataProviderEndpointManager.getInstance().processFetchSizeRequest(dataProviderRequest);
                        String sizeString = size == null ? "0" : String.valueOf(size);
                        responseContent = sizeString.getBytes();
                        break;
                    default:
                        responseContent = new byte[0]; //TODO error handling?
                        break;
                }
            } finally {
                session.unlock();
            }
        }
        return responseContent;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy