summaryrefslogtreecommitdiff
path: root/controller
diff options
context:
space:
mode:
Diffstat (limited to 'controller')
-rw-r--r--controller/app.go39
-rw-r--r--controller/controller.go8
-rw-r--r--controller/file.go79
-rw-r--r--controller/index.go13
-rw-r--r--controller/template/404.html7
-rw-r--r--controller/template/base.html49
-rw-r--r--controller/template/index.html28
-rw-r--r--controller/template/uploaded.html10
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}}