Add pre-create hook for validation before upload creation

This commit is contained in:
Marius 2016-07-11 22:40:19 +02:00
parent bad81737b0
commit 3530ffd925
3 changed files with 48 additions and 11 deletions

8
.hooks/pre-create Executable file
View File

@ -0,0 +1,8 @@
#!/bin/bash
filename=$(cat /dev/stdin | jq .MetaData.filename)
if [ -n "$filename" ]; then
echo "Error: no filename provided"
exit 1
fi

View File

@ -3,6 +3,7 @@ package cli
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt"
"os" "os"
"os/exec" "os/exec"
"strconv" "strconv"
@ -15,9 +16,27 @@ type HookType string
const ( const (
HookPostFinish HookType = "post-finish" HookPostFinish HookType = "post-finish"
HookPostTerminate HookType = "post-terminate" HookPostTerminate HookType = "post-terminate"
HookPreCreate HookType = "pre-create"
) )
func SetupHooks(handler *tusd.Handler) { type hookDataStore struct {
tusd.DataStore
}
func (store hookDataStore) NewUpload(info tusd.FileInfo) (id string, err error) {
if output, err := invokeHookSync(HookPreCreate, info, true); err != nil {
return "", fmt.Errorf("pre-create hook failed: %s\n%s", err, string(output))
}
return store.DataStore.NewUpload(info)
}
func SetupPreHooks(composer *tusd.StoreComposer) {
composer.UseCore(hookDataStore{
DataStore: composer.Core,
})
}
func SetupPostHooks(handler *tusd.Handler) {
go func() { go func() {
for { for {
select { select {
@ -31,6 +50,15 @@ func SetupHooks(handler *tusd.Handler) {
} }
func invokeHook(typ HookType, info tusd.FileInfo) { func invokeHook(typ HookType, info tusd.FileInfo) {
go func() {
_, err := invokeHookSync(typ, info, false)
if err != nil {
stderr.Printf("Error running %s hook for %s: %s", string(typ), info.ID, err)
}
}()
}
func invokeHookSync(typ HookType, info tusd.FileInfo, captureOutput bool) ([]byte, error) {
switch typ { switch typ {
case HookPostFinish: case HookPostFinish:
stdout.Printf("Upload %s (%d bytes) finished\n", info.ID, info.Size) stdout.Printf("Upload %s (%d bytes) finished\n", info.ID, info.Size)
@ -39,7 +67,7 @@ func invokeHook(typ HookType, info tusd.FileInfo) {
} }
if !Flags.HooksInstalled { if !Flags.HooksInstalled {
return return nil, nil
} }
name := string(typ) name := string(typ)
@ -52,7 +80,7 @@ func invokeHook(typ HookType, info tusd.FileInfo) {
jsonInfo, err := json.Marshal(info) jsonInfo, err := json.Marshal(info)
if err != nil { if err != nil {
stderr.Printf("Error encoding JSON for hook: %s", err) return nil, err
} }
reader := bytes.NewReader(jsonInfo) reader := bytes.NewReader(jsonInfo)
@ -60,13 +88,12 @@ func invokeHook(typ HookType, info tusd.FileInfo) {
cmd.Env = env cmd.Env = env
cmd.Dir = Flags.HooksDir cmd.Dir = Flags.HooksDir
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
go func() { if !captureOutput {
err := cmd.Run() cmd.Stdout = os.Stdout
if err != nil { return nil, cmd.Run()
stderr.Printf("Error running %s hook for %s: %s", name, info.ID, err) } else {
return cmd.Output()
} }
}()
} }

View File

@ -8,6 +8,8 @@ import (
) )
func Serve() { func Serve() {
SetupPreHooks(Composer)
handler, err := tusd.NewHandler(tusd.Config{ handler, err := tusd.NewHandler(tusd.Config{
MaxSize: Flags.MaxSize, MaxSize: Flags.MaxSize,
BasePath: Flags.Basepath, BasePath: Flags.Basepath,
@ -27,7 +29,7 @@ func Serve() {
stdout.Printf("Using %s as the base path.\n", basepath) stdout.Printf("Using %s as the base path.\n", basepath)
stdout.Printf(Composer.Capabilities()) stdout.Printf(Composer.Capabilities())
SetupHooks(handler) SetupPostHooks(handler)
if Flags.ExposeMetrics { if Flags.ExposeMetrics {
SetupMetrics(handler) SetupMetrics(handler)