aboutsummaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
authorJulian Hurst <ark@mansus.space>2023-01-15 02:16:35 +0100
committerJulian Hurst <ark@mansus.space>2023-01-15 02:16:35 +0100
commit09a34dda989df0f74bbfcd11ac63254d61b92a18 (patch)
treea62769481ceea1cd235b60c930a50e7a7c5a49e0 /main.go
parent7d502441a6bd210aff8a8625ee87ea5a1fbbd7ee (diff)
downloaddocspace-09a34dda989df0f74bbfcd11ac63254d61b92a18.tar.gz
Add images support (inf scroll via htmx of images taken from user docs)
This commit also includes a migration from css to scss, some improvements to the redirection workflow when no session is found and refactors concerning flash cookies.
Diffstat (limited to 'main.go')
-rw-r--r--main.go90
1 files changed, 59 insertions, 31 deletions
diff --git a/main.go b/main.go
index 4ece388..42377a3 100644
--- a/main.go
+++ b/main.go
@@ -8,7 +8,6 @@ import (
"path"
"path/filepath"
"sort"
- "errors"
"net/http"
"html/template"
"flag"
@@ -16,6 +15,7 @@ import (
"encoding/json"
"encoding/base64"
"sync"
+ "time"
"archive/zip"
"github.com/satori/go.uuid"
@@ -31,7 +31,7 @@ var sessionIds sync.Map
type Doc struct {
Name string
Size string
- ModTime string
+ ModTime time.Time
Link string
}
@@ -40,16 +40,36 @@ type UserSession struct {
SessionId string
}
-func serveTemplate(w http.ResponseWriter, r *http.Request, view string, data interface{}) {
+var fmap template.FuncMap = template.FuncMap {
+ "add": func(i, j int) int {
+ return i + j
+ },
+ "formatmodtime": func(i time.Time) string {
+ return i.Format("2006-01-02")
+ },
+}
+
+func serveTemplate(w http.ResponseWriter, r *http.Request, data interface{}, view ...string) {
var nav string = "templates/nav.html"
if u, err := checkSession(w, r); u != nil && err == nil {
nav = "templates/nav_logged.html"
}
- t, err := template.New("base.html").Funcs(template.FuncMap {
- "add": func(i, j int) int {
- return i + j
- },
- }).ParseFiles("templates/base.html", nav, view)
+ views := []string {"templates/base.html", nav}
+ views = append(views, view...)
+ t, err := template.New("base.html").Funcs(fmap).ParseFiles(views...)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if err := t.Execute(w, data); err != nil {
+ log.Fatal(err)
+ }
+}
+
+func serveSimple(w http.ResponseWriter, r *http.Request, data interface{}, view string, xviews ...string) {
+ views := []string {view}
+ views = append(views, xviews...)
+ fp := filepath.Base(views[len(views)-1])
+ t, err := template.New(fp).Funcs(fmap).ParseFiles(views...)
if err != nil {
log.Fatal(err)
}
@@ -150,11 +170,11 @@ func index(w http.ResponseWriter, r *http.Request) {
docs = append(docs, Doc {
file.Name(),
humanize(info.Size()),
- info.ModTime().Format("2006-01-02"),
+ info.ModTime(),
path.Join(baseDocDir, u.User, file.Name()),
})
}
- flasherr := consumeFlashError(w, r)
+ flasherr := consumeFlash(w, r, "error")
data := struct {
Docs []Doc
Error string
@@ -162,19 +182,20 @@ func index(w http.ResponseWriter, r *http.Request) {
docs,
flasherr,
}
- serveTemplate(w, r, "templates/user.html", data)
+ serveTemplate(w, r, data, "templates/user.html")
return
} else if err != nil {
sendError(w, r, err.Error(), http.StatusInternalServerError)
return
}
+ sendFlash(w, r, "redirect", "/")
http.Redirect(w, r, "/login", http.StatusSeeOther)
}
func admin(w http.ResponseWriter, r *http.Request) {
u, err := checkSession(w, r)
if u != nil && err == nil && u.IsAdmin {
- serveTemplate(w, r, "templates/admin.html", nil)
+ serveTemplate(w, r, nil, "templates/admin.html")
} else if err != nil {
sendError(w, r, err.Error(), http.StatusInternalServerError)
} else {
@@ -190,11 +211,11 @@ func adminUsers(w http.ResponseWriter, r *http.Request) {
sendError(w, r, err.Error(), http.StatusInternalServerError)
return
}
- serveTemplate(w, r, "templates/admin/users.html", struct {
+ serveTemplate(w, r, struct {
Users []User
}{
users,
- })
+ }, "templates/admin/users.html")
} else if err != nil {
sendError(w, r, err.Error(), http.StatusInternalServerError)
} else {
@@ -205,24 +226,26 @@ func adminUsers(w http.ResponseWriter, r *http.Request) {
func createuser(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
- err := consumeFlashError(w, r)
+ err := consumeFlash(w, r, "error")
data := struct {
Error string
}{
err,
}
- serveTemplate(w, r, "templates/createuser.html", data)
+ serveTemplate(w, r, data, "templates/createuser.html")
case http.MethodPost:
u := r.FormValue("user")
email := r.FormValue("email")
pass := r.FormValue("pass")
cpass := r.FormValue("cpass")
if len(pass) < 10 {
- sendFlashError(w, r, "/createuser", errors.New("Le mot de passe doit avoir une longeur supérieure ou égale à 10 caractères."))
+ sendFlash(w, r, "error", "Le mot de passe doit avoir une longeur supérieure ou égale à 10 caractères.")
+ http.Redirect(w, r, "/createuser", http.StatusSeeOther)
return
}
if pass != cpass {
- sendFlashError(w, r, "/createuser", errors.New("Le mot de passe et la confirmation du mot de passe ne sont pas les mêmes."))
+ sendFlash(w, r, "error", "Le mot de passe et la confirmation du mot de passe ne sont pas les mêmes.")
+ http.Redirect(w, r, "/createuser", http.StatusSeeOther)
return
}
user := User{-1, u, email, pass, false}
@@ -237,8 +260,8 @@ func createuser(w http.ResponseWriter, r *http.Request) {
}
}
-func consumeFlashError(w http.ResponseWriter, r *http.Request) string {
- cookie, err := r.Cookie("flasherror")
+func consumeFlash(w http.ResponseWriter, r *http.Request, name string) string {
+ cookie, err := r.Cookie(name)
if err != nil {
if err == http.ErrNoCookie {
return ""
@@ -247,7 +270,7 @@ func consumeFlashError(w http.ResponseWriter, r *http.Request) string {
}
}
http.SetCookie(w, &http.Cookie{
- Name: "flasherror",
+ Name: name,
Value: "",
MaxAge: -1,
})
@@ -258,10 +281,10 @@ func consumeFlashError(w http.ResponseWriter, r *http.Request) string {
return string(s)
}
-func sendFlashError(w http.ResponseWriter, r *http.Request, url string, err error) {
- str := base64.StdEncoding.EncodeToString([]byte(err.Error()))
+func sendFlash(w http.ResponseWriter, r *http.Request, name, s string) {
+ str := base64.StdEncoding.EncodeToString([]byte(s))
cookie := http.Cookie {
- Name: "flasherror",
+ Name: name,
Value: str,
MaxAge: 0,
// Only https on qutebrowser
@@ -270,7 +293,6 @@ func sendFlashError(w http.ResponseWriter, r *http.Request, url string, err erro
SameSite: http.SameSiteStrictMode,
}
http.SetCookie(w, &cookie)
- http.Redirect(w, r, url, http.StatusSeeOther)
}
func logout(w http.ResponseWriter, r *http.Request) {
@@ -294,19 +316,20 @@ func logout(w http.ResponseWriter, r *http.Request) {
func login(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
- err := consumeFlashError(w, r)
+ err := consumeFlash(w, r, "error")
data := struct {
Error string
}{
err,
}
- serveTemplate(w, r, "templates/login.html", data)
+ serveTemplate(w, r, data, "templates/login.html")
case http.MethodPost:
u := r.FormValue("user")
pass := r.FormValue("pass")
user, err := CheckUserPass(db, User{-1, u, "", pass, false})
if err != nil {
- sendFlashError(w, r, "/login", err)
+ sendFlash(w, r, "error", err.Error())
+ http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
user.Pass = ""
@@ -318,7 +341,8 @@ func login(w http.ResponseWriter, r *http.Request) {
}
jsonData, err := json.Marshal(us)
if err != nil {
- sendFlashError(w, r, "/login", err)
+ sendFlash(w, r, "error", err.Error())
+ http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
bStr := base64.StdEncoding.EncodeToString(jsonData)
@@ -332,7 +356,9 @@ func login(w http.ResponseWriter, r *http.Request) {
SameSite: http.SameSiteStrictMode,
}
http.SetCookie(w, &cookie)
- http.Redirect(w, r, "/", http.StatusSeeOther)
+ redirectflash := consumeFlash(w, r, "redirect")
+ log.Printf("read redirect: %s\n", redirectflash)
+ http.Redirect(w, r, redirectflash, http.StatusSeeOther)
default:
sendInvalidMethod(w, r)
}
@@ -363,7 +389,8 @@ func download(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
selection := r.Form["selection"]
if len(selection) == 0 {
- sendFlashError(w, r, "/", errors.New("Aucun fichier sélectionné"))
+ sendFlash(w, r, "error", "Aucun fichier sélectionné")
+ http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
contentDisposition := fmt.Sprintf("attachment; filename=\"Documents.zip\"")
@@ -477,6 +504,7 @@ func main() {
http.HandleFunc("/logout", logout)
http.HandleFunc("/upload", upload)
http.HandleFunc("/download", download)
+ http.HandleFunc("/imgs", imgs)
http.HandleFunc("/admin", admin)
http.HandleFunc("/admin/users", adminUsers)
log.Printf("Serving http://localhost:%d\n", *p)