diff options
Diffstat (limited to 'controller')
| -rw-r--r-- | controller/app.go | 39 | ||||
| -rw-r--r-- | controller/controller.go | 8 | ||||
| -rw-r--r-- | controller/file.go | 79 | ||||
| -rw-r--r-- | controller/index.go | 13 | ||||
| -rw-r--r-- | controller/template/404.html | 7 | ||||
| -rw-r--r-- | controller/template/base.html | 49 | ||||
| -rw-r--r-- | controller/template/index.html | 28 | ||||
| -rw-r--r-- | controller/template/uploaded.html | 10 |
8 files changed, 233 insertions, 0 deletions
diff --git a/controller/app.go b/controller/app.go new file mode 100644 index 0000000..f145ce2 --- /dev/null +++ b/controller/app.go @@ -0,0 +1,39 @@ +package controller + +import ( + "embed" + "html/template" + "net/http" + + "drop.janw.name/config" + "drop.janw.name/storage" +) + +//go:embed template/* +var templateFs embed.FS + +type App struct { + storage *storage.Storage + tmpl *template.Template + config config.Configuration +} + +func NewApp(configFilename string) *App { + return &App{ + storage: storage.NewStorage(), + tmpl: template.Must(template.ParseFS(templateFs, "template/*.html")), + config: config.Must(config.Open(configFilename)), + } +} + +func (app App) requireAuth(res http.ResponseWriter, req *http.Request) bool { + username, password, ok := req.BasicAuth() + if ok && username == app.config.Authentication.Username && password == app.config.Authentication.Password { + return true + } + + res.Header().Add("WWW-Authenticate", "Basic realm=\"Authentication Required\", charset=\"UTF-8\"") + res.WriteHeader(http.StatusUnauthorized) + + return false +} diff --git a/controller/controller.go b/controller/controller.go new file mode 100644 index 0000000..1f28562 --- /dev/null +++ b/controller/controller.go @@ -0,0 +1,8 @@ +package controller + +import "net/http" + +type Controller struct { + GET http.HandlerFunc + POST http.HandlerFunc +} diff --git a/controller/file.go b/controller/file.go new file mode 100644 index 0000000..53121d5 --- /dev/null +++ b/controller/file.go @@ -0,0 +1,79 @@ +package controller + +import ( + "fmt" + "io" + "net/http" + "time" + + "drop.janw.name/storage" +) + +const MAX_FILESIZE = (1 << 19) * 100 + +func (app App) FilePost(res http.ResponseWriter, req *http.Request) { + if !app.requireAuth(res, req) { + return + } + + if err := req.ParseMultipartForm(MAX_FILESIZE); err != nil { + panic(err) + } + + formFile, formFileHeader, err := req.FormFile("file") + if err != nil { + panic(err) + } + + protected := req.FormValue("protect") == "on" + + fileData, err := io.ReadAll(formFile) + if err != nil { + panic(err) + } + + file := storage.File{ + Protected: protected, + Filename: formFileHeader.Filename, + Data: fileData, + AvailableUntil: time.Now().Add(time.Hour * 2), + } + + key, err := app.storage.Put(file) + if err != nil { + panic(err) + } + + app.tmpl.ExecuteTemplate(res, "uploaded", struct { + DownloadURL string + }{ + DownloadURL: fmt.Sprintf("%s/%s", app.config.Http.BaseAddress, key), + }) +} + +func (app App) FileGet(res http.ResponseWriter, req *http.Request) { + fileId := req.PathValue("file") + + file, _ := app.storage.Get(fileId) + + if file == nil || !file.IsAvailable() { + if !app.requireAuth(res, req) { + return + } + + res.WriteHeader(http.StatusNotFound) + app.tmpl.ExecuteTemplate(res, "404", nil) + return + } + + if file.Protected && !app.requireAuth(res, req) { + return + } + + res.Header().Add("Content-Type", "application/octet-stream") + res.Header().Add("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", file.Filename)) + + if _, err := res.Write(file.Data); err != nil { + panic(err) + } +} diff --git a/controller/index.go b/controller/index.go new file mode 100644 index 0000000..6f927ed --- /dev/null +++ b/controller/index.go @@ -0,0 +1,13 @@ +package controller + +import ( + "net/http" +) + +func (app App) Index(res http.ResponseWriter, req *http.Request) { + if !app.requireAuth(res, req) { + return + } + + app.tmpl.ExecuteTemplate(res, "index", nil) +} diff --git a/controller/template/404.html b/controller/template/404.html new file mode 100644 index 0000000..fa19547 --- /dev/null +++ b/controller/template/404.html @@ -0,0 +1,7 @@ +{{define "404"}} +{{template "header" .}} +<main> + <h1>no such file</h1> +</main> +{{template "footer" .}} +{{end}} diff --git a/controller/template/base.html b/controller/template/base.html new file mode 100644 index 0000000..c91245d --- /dev/null +++ b/controller/template/base.html @@ -0,0 +1,49 @@ +{{define "header"}} +<!DOCTYPE html> +<html lang="en"> + <head> + <title>drop.janw.name</title> + <meta charset="UTF-8"> + <meta name="author" content="Jan Wolff"> + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> + <link href="data:," rel="icon"> + <style> + html, body { + padding: 0; + margin: 0; + width: 100%; + height: 100%; + } + + body { + display: flex; + justify-content: center; + align-items: center; + background: #ebebeb; + font-family: sans-serif; + } + + main { + padding: 2rem; + border-radius: 2rem; + background: #fefefe; + } + + form { + display: flex; + flex-direction: column; + gap: 1rem; + } + + progress { + width: 100%; + } + </style> + </head> + <body> +{{end}} + +{{define "footer"}} + </body> +</html> +{{end}} diff --git a/controller/template/index.html b/controller/template/index.html new file mode 100644 index 0000000..f50be97 --- /dev/null +++ b/controller/template/index.html @@ -0,0 +1,28 @@ +{{define "index"}} +{{template "header" .}} +<main> + <h1>drop.janw.name</h1> + <form method="POST" action="/" enctype="multipart/form-data"> + <div> + <label for="file"> + File: + </label> + <input id="file" type="file" name="file"> + </div> + <div> + <label for="protect"> + Password Protect: + </label> + <input id="protect" type="checkbox" name="protect"> + </div> + <div> + <label for="until"> + Available Until: + </label> + <input id="until" type="datetime-local" name="until"> + </div> + <input type="submit" id="upload" value="Upload"> + </form> +</main> +{{template "footer" .}} +{{end}} diff --git a/controller/template/uploaded.html b/controller/template/uploaded.html new file mode 100644 index 0000000..1324082 --- /dev/null +++ b/controller/template/uploaded.html @@ -0,0 +1,10 @@ +{{define "uploaded"}} +{{template "header" .}} +<main> + <h1>File uploaded successfully</h1> + <p> + <a href="{{.DownloadURL}}">{{.DownloadURL}}</a> + </p> +</main> +{{template "footer" .}} +{{end}} |
