diff --git a/go.mod b/go.mod index e430c4e..62742e9 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.16 require ( github.com/gorilla/mux v1.8.0 // indirect + github.com/matoous/go-nanoid/v2 v2.0.0 // indirect github.com/mediocregopher/radix/v4 v4.0.0-beta.1 // indirect github.com/minio/minio-go/v7 v7.0.10 // indirect ) diff --git a/go.sum b/go.sum index 32ea56e..250fdd2 100644 --- a/go.sum +++ b/go.sum @@ -15,6 +15,10 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/matoous/go-nanoid v1.5.0 h1:VRorl6uCngneC4oUQqOYtO3S0H5QKFtKuKycFG3euek= +github.com/matoous/go-nanoid v1.5.0/go.mod h1:zyD2a71IubI24efhpvkJz+ZwfwagzgSO6UNiFsZKN7U= +github.com/matoous/go-nanoid/v2 v2.0.0 h1:d19kur2QuLeHmJBkvYkFdhFBzLoo1XVm2GgTpL+9Tj0= +github.com/matoous/go-nanoid/v2 v2.0.0/go.mod h1:FtS4aGPVfEkxKxhdWPAspZpZSh1cOjtM7Ej/So3hR0g= github.com/mediocregopher/radix/v4 v4.0.0-beta.1 h1:RDgQ4wCQ6f+pUsX20CIzjNJnI5P9KDw4j1sjOVHxo7Y= github.com/mediocregopher/radix/v4 v4.0.0-beta.1/go.mod h1:Z74pilm773ghbGV4EEoPvi6XWgkAfr0VCNkfa8gI1PU= github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw= @@ -39,6 +43,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tilinna/clock v1.0.2 h1:6BO2tyAC9JbPExKH/z9zl44FLu1lImh3nDNKA0kgrkI= github.com/tilinna/clock v1.0.2/go.mod h1:ZsP7BcY7sEEz7ktc0IVy8Us6boDrK8VradlKRUGfOao= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -64,3 +69,4 @@ gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/handlers.go b/handlers.go index d32c326..2ef5e47 100644 --- a/handlers.go +++ b/handlers.go @@ -3,13 +3,16 @@ package main import ( "encoding/json" "errors" + "fmt" "html/template" "io" "net/http" "os" + "strconv" "time" "github.com/gorilla/mux" + gonanoid "github.com/matoous/go-nanoid/v2" ) var globalStore store @@ -47,6 +50,8 @@ func executeTemplate(w io.Writer, name string, data interface{}) error { /* credentials */ +var idAlphabet = "0123456789abcdefghijklmnopqrstuvwxyz" + func getCredential(id string) (credential, error) { cred := credential{} @@ -100,3 +105,45 @@ func handleUpload(w http.ResponseWriter, req *http.Request) { func handleCreate(w http.ResponseWriter, req *http.Request) { executeTemplate(w, "create.tmpl", nil) } + +/* create form */ + +type createReq struct { + credential + Expires time.Duration +} + +func handleCreateForm(w http.ResponseWriter, req *http.Request) { + cred := credential{ + Endpoint: req.PostFormValue("Endpoint"), + Region: req.PostFormValue("Region"), + AccessKey: req.PostFormValue("AccessKey"), + SecretKey: req.PostFormValue("SecretKey"), + Prefix: req.PostFormValue("Prefix"), + } + if err := cred.validate(); err != nil { + errorResponse(w, req, fmt.Errorf("%w: %s", errBadRequest, err)) + return + } + + expiresN, err := strconv.ParseUint(req.PostFormValue("Expires"), 10, 64) + if err != nil { + errorResponse(w, req, fmt.Errorf("%w: %s", errBadRequest, err)) + return + } + expires := time.Duration(expiresN) + if expires < 10*time.Minute || expires > 90*24*time.Hour { + errorResponse(w, req, fmt.Errorf("%w: time must be between 10 minutes and 90 days", errBadRequest)) + return + } + + id := gonanoid.MustGenerate(idAlphabet, 20) + + err = setCredential(id, cred, expires) + if err != nil { + errorResponse(w, req, err) + return + } + + w.Write([]byte(id)) +} diff --git a/main.go b/main.go index b941251..05a09e5 100644 --- a/main.go +++ b/main.go @@ -27,6 +27,7 @@ func main() { router.Methods(http.MethodGet).PathPrefix("/assets").HandlerFunc(handleAssets) router.Methods(http.MethodGet).Path("/create").HandlerFunc(handleCreate) + router.Methods(http.MethodPost).Path("/create").HandlerFunc(handleCreateForm) uploadRouter := router.PathPrefix("/{id}").Subrouter() uploadTemplateRouter := uploadRouter.Path("").Subrouter() diff --git a/store.go b/store.go index b9b8a0f..ee16d36 100644 --- a/store.go +++ b/store.go @@ -82,7 +82,7 @@ func (s *redisStore) put(key string, data []byte, expire time.Duration) error { } expireS := int64(expire / time.Second) - err = s.client.Do(ctx, radix.FlatCmd(nil, "SETEX", key, expireS, data)) + err = s.client.Do(ctx, radix.FlatCmd(nil, "SETEX", "upl:"+key, expireS, data)) if err != nil { return err } diff --git a/web/create.tmpl b/web/create.tmpl index adfaa9c..270a1cb 100644 --- a/web/create.tmpl +++ b/web/create.tmpl @@ -1,5 +1,7 @@ -{{template "head.tmpl" "Create Dropbox"}} -