initiatehandler.go (108 lines of code) (raw):
package main
import (
"encoding/json"
"errors"
"github.com/go-redis/redis/v8"
"gitlab.com/codmill/customer-projects/guardian/deliverable-receiver/helpers"
"gitlab.com/codmill/customer-projects/guardian/deliverable-receiver/models"
"io/ioutil"
"log"
"net/http"
"regexp"
"strings"
)
type InitiateHandler struct {
redisClient *redis.Client
config *helpers.Config
}
type InitiateRequest struct {
ProjectId int `json:"project_id"`
DropFolderPath string `json:"drop_folder"`
}
func makeRelativePath(inputPath string, config *helpers.Config) (string, error) {
serverSidePathConverter := regexp.MustCompile("^/Volumes")
potentialPaths := []string{inputPath, serverSidePathConverter.ReplaceAllString(inputPath, "/srv")}
for _, path := range potentialPaths {
if strings.HasPrefix(path, config.StoragePrefix.LocalPath) {
return path[len(config.StoragePrefix.LocalPath):], nil
}
}
return "", errors.New("invalid destination path, please check the settings")
}
func (h InitiateHandler) ServeHTTP(w http.ResponseWriter, request *http.Request) {
defer request.Body.Close()
bodyContent, readErr := ioutil.ReadAll(request.Body)
if readErr != nil {
log.Printf("ERROR InitiateHandler could not read request from client: %s", readErr)
return
}
if !helpers.AssertHttpMethod(request, w, "POST") {
return //error has already been written
}
username, validationErr := helpers.ValidateLogin(request, h.config)
if validationErr != nil {
log.Printf("ERROR InitiateHandler could not validate request: %s", validationErr)
response := helpers.GenericErrorResponse{
Status: "forbidden",
Detail: validationErr.Error(),
}
helpers.WriteJsonContent(response, w, 403)
return
}
log.Printf("INFO InitiateHandler upload initiate request from %s", username)
var requestContent InitiateRequest
unmarshalErr := json.Unmarshal(bodyContent, &requestContent)
if unmarshalErr != nil {
log.Printf("ERROR InitiateHandler could not parse request body: %s", unmarshalErr)
response := helpers.GenericErrorResponse{
Status: "error",
Detail: "could not parse request, see logs",
}
helpers.WriteJsonContent(response, w, 400)
return
}
relPath, relPathErr := makeRelativePath(requestContent.DropFolderPath, h.config)
if relPathErr != nil {
response := helpers.GenericErrorResponse{
Status: "error",
Detail: "invalid dropfolder path",
}
helpers.WriteJsonContent(response, w, 400)
return
}
ttl, configErr := h.config.UploadSlotTTLDuration()
if configErr != nil {
log.Print("ERROR InitiateHandler could not determine upload slot TTL: ", configErr)
response := helpers.GenericErrorResponse{
Status: "config_error",
Detail: "could not determine upload slot TTL",
}
helpers.WriteJsonContent(response, w, 500)
return
}
newSlot, newSlotErr := models.NewUploadSlot(requestContent.ProjectId, relPath, ttl)
if newSlotErr != nil {
log.Print("ERROR InitiateHandler could not create new upload slot: ", newSlotErr)
response := helpers.GenericErrorResponse{
Status: "server_error",
Detail: newSlotErr.Error(),
}
helpers.WriteJsonContent(response, w, 500)
return
}
writErr := models.WriteUploadSlot(&newSlot, h.redisClient)
if writErr != nil {
log.Print("ERROR InitiateHandler could not write upload slot to storage: ", writErr)
response := helpers.GenericErrorResponse{
Status: "db_error",
Detail: writErr.Error(),
}
helpers.WriteJsonContent(response, w, 500)
return
}
response := map[string]interface{}{
"status": "ok",
"result": newSlot,
}
helpers.WriteJsonContent(response, w, 200)
}