/*
 * Copyright 2020 Netflix, Inc.
 *
 * 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 com.netflix.spinnaker.front50.controllers;

import static java.lang.String.format;

import com.google.common.hash.Hashing;
import com.netflix.spinnaker.front50.plugins.PluginBinaryStorageService;
import com.netflix.spinnaker.kork.exceptions.SystemException;
import java.util.Optional;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/pluginBinaries")
public class PluginBinaryController {

  private final Optional<PluginBinaryStorageService> pluginBinaryStorageService;

  public PluginBinaryController(Optional<PluginBinaryStorageService> pluginBinaryStorageService) {
    this.pluginBinaryStorageService = pluginBinaryStorageService;
  }

  @PostMapping("/{id}/{version}")
  @ResponseStatus(HttpStatus.CREATED)
  void upload(
      @PathVariable String id,
      @PathVariable String version,
      @RequestParam("sha512sum") String sha512sum,
      @RequestBody byte[] body) {
    verifyChecksum(body, sha512sum);
    storageService().store(getKey(id, version), body);
  }

  @GetMapping("/{id}/{version}")
  ResponseEntity<byte[]> getBinary(@PathVariable String id, @PathVariable String version) {
    return ResponseEntity.ok()
        .header("Content-Type", "application/octet-stream")
        .body(storageService().load(getKey(id, version)));
  }

  private static String getKey(String id, String version) {
    return format("%s/%s.zip", id, version);
  }

  private void verifyChecksum(byte[] body, String sha512sum) {
    String sha = Hashing.sha512().hashBytes(body).toString();
    if (!sha.equals(sha512sum)) {
      throw new SystemException("Plugin binary checksum does not match expected checksum value")
          .setRetryable(true);
    }
  }

  private PluginBinaryStorageService storageService() {
    return pluginBinaryStorageService.orElseThrow(
        () ->
            new IllegalArgumentException(
                "Plugin binary storage service is yet not available for your persistence backend"));
  }
}

@@ -719,16 +719,57 @@
 ashing;%0A
+import com.google.common.io.ByteStreams;%0A
 import c
@@ -911,21 +911,77 @@
 ava.
-util.Optional
+io.InputStream;%0Aimport java.util.Optional;%0Aimport lombok.SneakyThrows
 ;%0Aim
@@ -1463,16 +1463,32 @@
 e;%0A  %7D%0A%0A
+  @SneakyThrows%0A
   @PostM
@@ -1694,35 +1694,77 @@
     
-@RequestBody byte%5B%5D 
+InputStream body) %7B%0A    byte%5B%5D bytes = ByteStreams.toByteArray(
 body)
- %7B
+;
 %0A   
@@ -1780,19 +1780,20 @@
 ecksum(b
-ody
+ytes
 , sha512
@@ -1847,19 +1847,20 @@
 sion), b
-ody
+ytes
 );%0A  %7D%0A%0A

Use InputStream for plugin binary body (#722)