2021-05-22 22:24:28 +08:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2021-05-23 00:46:15 +08:00
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
2021-05-23 18:10:08 +08:00
|
|
|
"fmt"
|
2021-05-22 23:53:00 +08:00
|
|
|
"html/template"
|
2021-05-23 15:36:41 +08:00
|
|
|
"io"
|
2021-05-22 22:24:28 +08:00
|
|
|
"net/http"
|
|
|
|
"os"
|
2021-05-23 18:10:08 +08:00
|
|
|
"strconv"
|
2021-05-23 00:46:15 +08:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/gorilla/mux"
|
2021-05-23 18:10:08 +08:00
|
|
|
gonanoid "github.com/matoous/go-nanoid/v2"
|
2021-05-22 22:24:28 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
var globalStore store
|
|
|
|
|
|
|
|
func setupHandlers() {
|
|
|
|
var err error
|
|
|
|
globalStore, err = newRedisStore(os.Getenv("REDIS_CONNECTION"))
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2021-05-23 15:36:41 +08:00
|
|
|
|
|
|
|
if debug {
|
2021-05-23 17:00:48 +08:00
|
|
|
assetsServer = http.FileServer(http.FS(os.DirFS("web")))
|
2021-05-23 15:36:41 +08:00
|
|
|
}
|
2021-05-22 22:24:28 +08:00
|
|
|
}
|
|
|
|
|
2021-05-23 17:00:48 +08:00
|
|
|
/* assets */
|
|
|
|
|
|
|
|
var assetsServer = http.FileServer(http.FS(assetsWeb))
|
|
|
|
|
|
|
|
func handleAssets(w http.ResponseWriter, req *http.Request) {
|
|
|
|
assetsServer.ServeHTTP(w, req)
|
|
|
|
}
|
|
|
|
|
|
|
|
/* templates */
|
|
|
|
|
|
|
|
var tmpl = template.Must(template.ParseFS(assets, "web/*.tmpl"))
|
|
|
|
|
|
|
|
func executeTemplate(w io.Writer, name string, data interface{}) error {
|
|
|
|
if debug {
|
|
|
|
tmpl = template.Must(template.ParseGlob("web/*.tmpl"))
|
|
|
|
}
|
|
|
|
return tmpl.ExecuteTemplate(w, name, nil)
|
|
|
|
}
|
|
|
|
|
2021-05-23 00:46:15 +08:00
|
|
|
/* credentials */
|
|
|
|
|
2021-05-23 18:10:08 +08:00
|
|
|
var idAlphabet = "0123456789abcdefghijklmnopqrstuvwxyz"
|
|
|
|
|
2021-05-23 00:46:15 +08:00
|
|
|
func getCredential(id string) (credential, error) {
|
|
|
|
cred := credential{}
|
|
|
|
|
|
|
|
b, err := globalStore.get(id)
|
|
|
|
if err != nil {
|
|
|
|
return cred, err
|
|
|
|
}
|
|
|
|
|
|
|
|
err = json.Unmarshal(b, &cred)
|
|
|
|
if err != nil {
|
|
|
|
return cred, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return cred, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func setCredential(id string, cred credential, expire time.Duration) error {
|
|
|
|
b, err := json.Marshal(cred)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
err = globalStore.put(id, b, expire)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-05-22 23:53:00 +08:00
|
|
|
/* upload template */
|
2021-05-22 22:24:28 +08:00
|
|
|
|
2021-05-22 23:53:00 +08:00
|
|
|
func handleUpload(w http.ResponseWriter, req *http.Request) {
|
2021-05-23 00:46:15 +08:00
|
|
|
vars := mux.Vars(req)
|
|
|
|
_, err := getCredential(vars["id"])
|
|
|
|
if errors.Is(err, errNotFound) {
|
|
|
|
errorResponseStatus(w, req, err)
|
2021-05-23 15:36:41 +08:00
|
|
|
executeTemplate(w, "upload-not-found.tmpl", nil)
|
2021-05-23 00:46:15 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
errorResponse(w, req, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-05-23 15:36:41 +08:00
|
|
|
executeTemplate(w, "upload.tmpl", nil)
|
2021-05-22 22:24:28 +08:00
|
|
|
}
|
2021-05-23 00:46:15 +08:00
|
|
|
|
|
|
|
/* create template */
|
|
|
|
|
|
|
|
func handleCreate(w http.ResponseWriter, req *http.Request) {
|
2021-05-23 15:36:41 +08:00
|
|
|
executeTemplate(w, "create.tmpl", nil)
|
2021-05-23 00:46:15 +08:00
|
|
|
}
|
2021-05-23 18:10:08 +08:00
|
|
|
|
|
|
|
/* create form */
|
|
|
|
|
|
|
|
type createReq struct {
|
|
|
|
credential
|
|
|
|
Expires time.Duration
|
|
|
|
}
|
|
|
|
|
|
|
|
func handleCreateForm(w http.ResponseWriter, req *http.Request) {
|
2021-05-23 23:32:44 +08:00
|
|
|
cred := newCredential(
|
|
|
|
req.PostFormValue("Endpoint"),
|
|
|
|
req.PostFormValue("Region"),
|
|
|
|
req.PostFormValue("AccessKey"),
|
|
|
|
req.PostFormValue("SecretKey"),
|
|
|
|
req.PostFormValue("Prefix"),
|
|
|
|
req.PostFormValue("ACL"),
|
|
|
|
)
|
2021-05-23 18:10:08 +08:00
|
|
|
if err := cred.validate(); err != nil {
|
2021-05-23 23:32:44 +08:00
|
|
|
errorResponse(w, req, err)
|
2021-05-23 18:10:08 +08:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2021-05-24 02:28:50 +08:00
|
|
|
id := gonanoid.MustGenerate(idAlphabet, 12)
|
2021-05-23 18:10:08 +08:00
|
|
|
|
|
|
|
err = setCredential(id, cred, expires)
|
|
|
|
if err != nil {
|
|
|
|
errorResponse(w, req, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
w.Write([]byte(id))
|
|
|
|
}
|