aiai.ai.launchpad.server.ServerController.java Source code

Java tutorial

Introduction

Here is the source code for aiai.ai.launchpad.server.ServerController.java

Source

/*
 * AiAi, Copyright (C) 2017-2018  Serge Maslyukov
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package aiai.ai.launchpad.server;

import aiai.ai.Enums;
import aiai.ai.Globals;
import aiai.ai.comm.ExchangeData;
import aiai.ai.exceptions.BinaryDataNotFoundException;
import aiai.ai.launchpad.beans.Snippet;
import aiai.ai.launchpad.beans.Task;
import aiai.ai.launchpad.binary_data.BinaryDataService;
import aiai.ai.launchpad.repositories.TaskRepository;
import aiai.ai.launchpad.snippet.SnippetCache;
import aiai.ai.launchpad.snippet.SnippetService;
import aiai.ai.station.AssetFile;
import aiai.ai.station.StationResourceUtils;
import aiai.ai.utils.checksum.ChecksumWithSignatureService;
import aiai.ai.yaml.task.TaskParamYaml;
import aiai.ai.yaml.task.TaskParamYamlUtils;
import aiai.apps.commons.utils.DirUtils;
import aiai.apps.commons.yaml.snippet.SnippetVersion;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.context.annotation.Profile;
import org.springframework.core.io.AbstractResource;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

/**
 * User: Serg
 * Date: 13.07.2017
 * Time: 19:19
 */
@RestController
@Slf4j
@Profile("launchpad")
public class ServerController {

    private static final UploadResult OK_UPLOAD_RESULT = new UploadResult(true, null);

    private final Globals globals;
    private final ServerService serverService;
    private final BinaryDataService binaryDataService;
    private final SnippetCache snippetCache;
    private final SnippetService snippetService;
    private final ChecksumWithSignatureService checksumWithSignatureService;
    private final TaskRepository taskRepository;
    private final TaskParamYamlUtils taskParamYamlUtils;

    public ServerController(Globals globals, ServerService serverService, BinaryDataService binaryDataService,
            SnippetCache snippetCache, SnippetService snippetService,
            ChecksumWithSignatureService checksumWithSignatureService, TaskRepository taskRepository,
            TaskParamYamlUtils taskParamYamlUtils) {
        this.globals = globals;
        this.serverService = serverService;
        this.binaryDataService = binaryDataService;
        this.snippetCache = snippetCache;
        this.snippetService = snippetService;
        this.checksumWithSignatureService = checksumWithSignatureService;
        this.taskRepository = taskRepository;
        this.taskParamYamlUtils = taskParamYamlUtils;
    }

    @PostMapping("/rest-anon/srv")
    public ExchangeData processRequestAnon(HttpServletResponse response, @RequestBody ExchangeData data,
            HttpServletRequest request) throws IOException {
        log.debug("processRequestAnon(), globals.isSecureRestUrl: {}, data: {}", globals.isSecureRestUrl, data);
        if (globals.isSecureRestUrl) {
            response.sendError(HttpServletResponse.SC_FORBIDDEN);
            return null;
        }
        return serverService.processRequest(data, request.getRemoteAddr());
    }

    @PostMapping("/rest-auth/srv")
    public ExchangeData processRequestAuth(@RequestBody ExchangeData data, HttpServletRequest request) {
        log.debug("processRequestAnon(), globals.isSecureRestUrl: {}, data: {}", globals.isSecureRestUrl, data);
        return serverService.processRequest(data, request.getRemoteAddr());
    }

    @GetMapping("/rest-anon/payload/resource/{type}/{code}")
    public HttpEntity<AbstractResource> deliverResourceAnon(HttpServletResponse response,
            @PathVariable("type") String typeAsStr, @PathVariable("code") String code) throws IOException {
        log.debug("deliverResourceAnon(), globals.isSecureRestUrl: {}, typeAsStr: {}, code: {}",
                globals.isSecureRestUrl, typeAsStr, code);
        if (globals.isSecureRestUrl) {
            response.sendError(HttpServletResponse.SC_FORBIDDEN);
            return null;
        }
        return deliverResource(response, typeAsStr, code);
    }

    @GetMapping("/rest-auth/payload/resource/{type}/{code}")
    public HttpEntity<AbstractResource> deliverResourceAuth(HttpServletResponse response,
            @PathVariable("type") String typeAsStr, @PathVariable("code") String code) throws IOException {
        log.debug("deliverResourceAuth(), globals.isSecureRestUrl: {}, typeAsStr: {}, code: {}",
                globals.isSecureRestUrl, typeAsStr, code);
        return deliverResource(response, typeAsStr, code);
    }

    @GetMapping("/rest-anon/upload/{taskId}")
    public UploadResult uploadResourceAnon(MultipartFile file, HttpServletResponse response,
            @PathVariable("taskId") Long taskId) throws IOException {
        log.debug("uploadResourceAnon(), globals.isSecureRestUrl: {}, taskId: {}", globals.isSecureRestUrl, taskId);
        if (globals.isSecureRestUrl) {
            response.sendError(HttpServletResponse.SC_FORBIDDEN);
            return null;
        }
        return uploadResource(file, taskId);
    }

    @PostMapping("/rest-auth/upload/{taskId}")
    public UploadResult uploadResourceAuth(MultipartFile file, @PathVariable("taskId") Long taskId) {
        log.debug("uploadResourceAuth(), globals.isSecureRestUrl: {}, taskId: {}", globals.isSecureRestUrl, taskId);
        return uploadResource(file, taskId);
    }

    private UploadResult uploadResource(MultipartFile file, Long taskId) {
        String originFilename = file.getOriginalFilename();
        if (originFilename == null) {
            return new UploadResult(false, "#442.01 name of uploaded file is null");
        }
        if (taskId == null) {
            return new UploadResult(false, "#442.87 taskId is null");
        }
        Task task = taskRepository.findById(taskId).orElse(null);
        if (task == null) {
            return new UploadResult(false, "#442.83 taskId is null");
        }

        final TaskParamYaml taskParamYaml = taskParamYamlUtils.toTaskYaml(task.getParams());

        try {
            File tempDir = DirUtils.createTempDir("upload-resource-");
            if (tempDir == null || tempDir.isFile()) {
                final String location = System.getProperty("java.io.tmpdir");
                return new UploadResult(false, "#442.04 can't create temporary directory in " + location);
            }
            final File resFile = new File(tempDir, "resource.");
            log.debug("Start storing an uploaded resource data to disk");
            try (OutputStream os = new FileOutputStream(resFile)) {
                IOUtils.copy(file.getInputStream(), os, 64000);
            }
            try (InputStream is = new FileInputStream(resFile)) {
                binaryDataService.save(is, resFile.length(), Enums.BinaryDataType.DATA,
                        taskParamYaml.outputResourceCode, taskParamYaml.outputResourceCode, false, null);
            }
        } catch (Throwable th) {
            log.error("Error", th);
            return new UploadResult(false, "#442.05 can't load snippets, Error: " + th.toString());
        }
        task.resultReceived = true;
        taskRepository.save(task);
        return OK_UPLOAD_RESULT;
    }

    private HttpEntity<AbstractResource> deliverResource(HttpServletResponse response, String typeAsStr,
            String code) throws IOException {
        Enums.BinaryDataType binaryDataType = Enums.BinaryDataType.valueOf(typeAsStr.toUpperCase());
        AssetFile assetFile = StationResourceUtils.prepareResourceFile(globals.launchpadResourcesDir,
                binaryDataType, code, null);

        if (assetFile == null) {
            return returnEmptyAsGone(response);
        }
        try {
            binaryDataService.storeToFile(code, assetFile.file);
        } catch (BinaryDataNotFoundException e) {
            return returnEmptyAsGone(response);
        }
        return new HttpEntity<>(new FileSystemResource(assetFile.file.toPath()),
                getHeader(assetFile.file.length()));
    }

    private HttpEntity<AbstractResource> returnEmptyAsGone(HttpServletResponse response) throws IOException {
        response.sendError(HttpServletResponse.SC_GONE);
        return new HttpEntity<>(new ByteArrayResource(new byte[0]), getHeader(0));
    }

    private HttpEntity<AbstractResource> returnEmptyAsConflict(HttpServletResponse response) throws IOException {
        response.sendError(HttpServletResponse.SC_CONFLICT);
        return new HttpEntity<>(new ByteArrayResource(new byte[0]), getHeader(0));
    }

    @GetMapping("/rest-auth/payload/snippet-checksum/{name}")
    public HttpEntity<String> snippetChecksum(HttpServletResponse response,
            @PathVariable("name") String snippetCode) throws IOException {

        SnippetVersion snippetVersion = SnippetVersion.from(snippetCode);
        Snippet snippet = snippetCache.findByNameAndSnippetVersion(snippetVersion.name, snippetVersion.version);
        if (snippet == null) {
            log.warn("Snippet wasn't found for name {}", snippetCode);
            return returnEmptyStringWithStatus(response, HttpServletResponse.SC_GONE);
        }
        /*
                File snippetFile;
                AssetFile assetFile = StationResourceUtils.prepareResourceFile(globals.launchpadResourcesDir, Enums.BinaryDataType.SNIPPET, snippetCode);
                if (assetFile==null) {
        log.warn("Snippet wasn't found for name {}", snippetCode);
        return returnEmptyStringWithStatus(response, HttpServletResponse.SC_GONE);
                }
                try {
        binaryDataService.storeToFile(snippetCode, assetFile.file);
                } catch (BinaryDataNotFoundException e) {
        log.error("Error store data to file", e);
        return returnEmptyStringWithStatus(response, HttpServletResponse.SC_GONE);
                }
            
                Checksum checksum = Checksum.fromJson(snippet.getChecksum());
                try (InputStream is = new FileInputStream(assetFile.file)) {
        CheckSumAndSignatureStatus status = checksumWithSignatureService.verifyChecksumAndSignature(
                checksum, snippetCode, is, false
        );
        if (!status.isOk) {
            return returnEmptyStringWithStatus(response, HttpServletResponse.SC_CONFLICT);
        }
                }*/
        final int length = snippet.getChecksum().length();
        log.info("Send checksum for snippet {}, length: {}", snippet.getSnippetCode(), length);

        return new HttpEntity<>(snippet.getChecksum(), getHeader(length));
    }

    private HttpEntity<String> returnEmptyStringWithStatus(HttpServletResponse response, int status)
            throws IOException {
        response.sendError(status);
        return new HttpEntity<>("", getHeader(0));
    }

    private static HttpHeaders getHeader(long length) {
        HttpHeaders header = new HttpHeaders();
        header.setContentLength(length);
        header.setCacheControl("max-age=0");
        header.setExpires(0);
        header.setPragma("no-cache");

        return header;
    }

    /**
     * This endpoint is only for testing security. Do not delete
     * @return String
     */
    @GetMapping("/rest-anon/test")
    public String getMessage_1() {
        return "Ok";
    }

    /**
     * This endpoint is only for testing security. Do not delete
     * @return String
     */
    @GetMapping("/rest-auth/test")
    public String getMessage_2() {
        return "Ok";
    }

}