diff options
| author | Julian Hurst <ark@mansus.space> | 2023-01-25 01:23:58 +0100 |
|---|---|---|
| committer | Julian Hurst <ark@mansus.space> | 2023-01-25 01:23:58 +0100 |
| commit | f416775268085c7fb7f90cf54ea2149267b960e6 (patch) | |
| tree | d7e38e94795368f39cda882cd61c16b01eb56dd3 | |
| parent | e7a3649280d20d9b4f68572721684a01049ec40f (diff) | |
| download | docspace-f416775268085c7fb7f90cf54ea2149267b960e6.tar.gz | |
Add user impersonation support for admins
| -rw-r--r-- | imgs.go | 14 | ||||
| -rw-r--r-- | main.go | 53 | ||||
| -rw-r--r-- | templates/createuser.html | 2 | ||||
| -rw-r--r-- | templates/imgs.html | 8 | ||||
| -rw-r--r-- | templates/imgs_page.html | 6 | ||||
| -rw-r--r-- | templates/nav_logged.html | 5 | ||||
| -rw-r--r-- | templates/user.html | 12 |
7 files changed, 87 insertions, 13 deletions
@@ -17,6 +17,13 @@ const pageSize = 5 func imgs(w http.ResponseWriter, r *http.Request) { u, err := checkSession(w, r) if u != nil && err == nil { + username := u.Username + if u.IsAdmin { + name := r.URL.Query().Get("user") + if name != "" { + username = name + } + } fragment := r.URL.Query().Has("fragment") pageQuery := r.URL.Query().Get("page") if pageQuery == "" { @@ -27,7 +34,7 @@ func imgs(w http.ResponseWriter, r *http.Request) { sendError(w, r, err.Error(), http.StatusInternalServerError) return } - userDocPath := filepath.Join(baseDocDir, u.Username) + userDocPath := filepath.Join(baseDocDir, username) err = os.Mkdir(userDocPath, 0750) if err != nil && !os.IsExist(err) { sendError(w, r, err.Error(), http.StatusInternalServerError) @@ -67,6 +74,7 @@ func imgs(w http.ResponseWriter, r *http.Request) { start = len(imgs) } flasherr := consumeFlash(w, r, "error") + userImpersonation := r.URL.Query().Get("user") data := struct { Imgs []Doc Start int @@ -74,6 +82,7 @@ func imgs(w http.ResponseWriter, r *http.Request) { NbFiles int Page int Error string + UserImpersonation string }{ imgs[start:end], start + 1, @@ -81,6 +90,7 @@ func imgs(w http.ResponseWriter, r *http.Request) { len(imgs), page, flasherr, + userImpersonation, } if fragment { //serveSimple(w, r, data, "templates/imgs_stub.html") @@ -92,7 +102,7 @@ func imgs(w http.ResponseWriter, r *http.Request) { } else if err != nil { log.Println(err) } - sendFlash(w, r, "redirect", "/imgs") + sendFlash(w, r, "redirect", r.URL.String()) http.Redirect(w, r, "/login", http.StatusSeeOther) } @@ -181,12 +181,19 @@ func humanize(i int64) string { func index(w http.ResponseWriter, r *http.Request) { u, err := checkSession(w, r) if u != nil && err == nil { - userDocPath := filepath.Join(baseDocDir, u.Username) + username := u.Username + if u.IsAdmin { + name := r.URL.Query().Get("user") + if name != "" { + username = name + } + } + userDocPath := filepath.Join(baseDocDir, username) err := os.Mkdir(userDocPath, 0750) if err != nil && !os.IsExist(err) { sendError(w, r, err.Error(), http.StatusInternalServerError) } - files, err := os.ReadDir(filepath.Join(baseDocDir, u.Username)) + files, err := os.ReadDir(filepath.Join(baseDocDir, username)) if err != nil { sendError(w, r, err.Error(), http.StatusInternalServerError) } @@ -212,23 +219,26 @@ func index(w http.ResponseWriter, r *http.Request) { file.Name(), humanize(info.Size()), info.ModTime(), - path.Join(baseDocDir, u.Username, file.Name()), + path.Join(baseDocDir, username, file.Name()), }) } flasherr := consumeFlash(w, r, "error") + userImpersonation := r.URL.Query().Get("user") data := struct { Docs []Doc Error string + UserImpersonation string }{ docs, flasherr, + userImpersonation, } serveTemplate(w, r, data, "templates/user.html") return } else if err != nil { log.Println(err) } - sendFlash(w, r, "redirect", "/") + sendFlash(w, r, "redirect", r.URL.String()) http.Redirect(w, r, "/login", http.StatusSeeOther) } @@ -278,6 +288,7 @@ func createuser(w http.ResponseWriter, r *http.Request) { email := r.FormValue("email") pass := r.FormValue("pass") cpass := r.FormValue("cpass") + isadmin := r.FormValue("isadmin") if len(pass) < 10 { 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) @@ -288,7 +299,7 @@ func createuser(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/createuser", http.StatusSeeOther) return } - user := User{-1, u, email, pass, false} + user := User{-1, u, email, pass, isadmin == "on"} user, err := CreateUser(db, user) if err != nil { sendError(w, r, err.Error(), http.StatusInternalServerError) @@ -405,7 +416,7 @@ func handleFileServer(dir, prefix string) http.HandlerFunc { if u != nil && err == nil { dir := filepath.Dir(r.URL.Path) username := filepath.Base(dir) - if u.Username == username { + if u.Username == username || u.IsAdmin { hdlr(w, r) return } @@ -417,6 +428,13 @@ func handleFileServer(dir, prefix string) http.HandlerFunc { func download(w http.ResponseWriter, r *http.Request) { u, err := checkSession(w, r) if u != nil && err == nil { + username := u.Username + if u.IsAdmin { + name := r.URL.Query().Get("user") + if name != "" { + username = name + } + } switch r.Method { case http.MethodPost: r.ParseForm() @@ -431,7 +449,7 @@ func download(w http.ResponseWriter, r *http.Request) { wr := zip.NewWriter(w) defer wr.Close() for _, sel := range selection { - if filepath.Base(filepath.Dir(sel)) == u.Username { + if filepath.Base(filepath.Dir(sel)) == username { wrc, err := wr.Create(filepath.Base(sel)) if err != nil { sendError(w, r, err.Error(), http.StatusInternalServerError) @@ -450,13 +468,13 @@ func download(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Disposition", contentDisposition) wr := zip.NewWriter(w) defer wr.Close() - files, err := os.ReadDir(filepath.Join(baseDocDir, u.Username)) + files, err := os.ReadDir(filepath.Join(baseDocDir, username)) if err != nil { sendError(w, r, err.Error(), http.StatusInternalServerError) return } for _, file := range files { - filePath := path.Join(baseDocDir, u.Username, file.Name()) + filePath := path.Join(baseDocDir, username, file.Name()) wrc, err := wr.Create(filepath.Base(filePath)) if err != nil { sendError(w, r, err.Error(), http.StatusInternalServerError) @@ -482,7 +500,16 @@ func upload(w http.ResponseWriter, r *http.Request) { case http.MethodPost: u, err := checkSession(w, r) if u != nil && err == nil { - userDocPath := filepath.Join(baseDocDir, u.Username) + userImpersonation := false + username := u.Username + if u.IsAdmin { + name := r.URL.Query().Get("user") + if name != "" { + username = name + userImpersonation = true + } + } + userDocPath := filepath.Join(baseDocDir, username) err := os.Mkdir(userDocPath, 0750) if err != nil && !os.IsExist(err) { sendError(w, r, err.Error(), http.StatusInternalServerError) @@ -509,7 +536,11 @@ func upload(w http.ResponseWriter, r *http.Request) { sendError(w, r, err.Error(), http.StatusInternalServerError) } } - http.Redirect(w, r, "/", http.StatusSeeOther) + if userImpersonation { + http.Redirect(w, r, fmt.Sprintf("/?user=%s", username), http.StatusSeeOther) + } else { + http.Redirect(w, r, "/", http.StatusSeeOther) + } } else { http.Redirect(w, r, "/login", http.StatusSeeOther) } diff --git a/templates/createuser.html b/templates/createuser.html index ee4858b..92a1b22 100644 --- a/templates/createuser.html +++ b/templates/createuser.html @@ -10,6 +10,8 @@ <input required type="email" name="email" id="email" placeholder="Email"><br/><br/> <input required type="password" name="pass" id="pass" placeholder="Mot de passe" minlength="10"><br/><br/> <input required type="password" name="cpass" id="cpass" placeholder="Confirmation du mot de passe" minlength="10"><br/><br/> + <label for="isadmin">Admin?</label> + <input type="checkbox" name="isadmin" id="isadmin"><br/><br/> <input type="submit" value="Créer"> </form> {{end}} diff --git a/templates/imgs.html b/templates/imgs.html index e747034..51b489d 100644 --- a/templates/imgs.html +++ b/templates/imgs.html @@ -4,13 +4,21 @@ {{template "imgspage" .}} <noscript> {{if ne .Page 0}} + {{if ne .UserImpersonation ""}} + <a href="/imgs?page={{add .Page -1}}&user={{.UserImpersonation}}">Previous page</a> + {{else}} <a href="/imgs?page={{add .Page -1}}">Previous page</a> + {{end}} {{if lt .End .NbFiles}} | {{end}} {{end}} {{if lt .End .NbFiles}} + {{if ne .UserImpersonation ""}} + <a href="/imgs?page={{add .Page 1}}&user={{.UserImpersonation}}">Next page</a> + {{else}} <a href="/imgs?page={{add .Page 1}}">Next page</a> + {{end}} {{end}} </noscript> <br/><span>{{.NbFiles}} images</span> diff --git a/templates/imgs_page.html b/templates/imgs_page.html index 665daf3..3f1ce58 100644 --- a/templates/imgs_page.html +++ b/templates/imgs_page.html @@ -1,9 +1,15 @@ {{define "imgspage"}} {{range $i, $img := .Imgs}} {{if eq (add $i $.Start) $.End}} + {{if ne $.UserImpersonation ""}} + <div hx-get="/imgs?page={{add $.Page 1}}&fragment&user={{$.UserImpersonation}}" + hx-trigger="revealed" + hx-swap="afterend"> + {{else}} <div hx-get="/imgs?page={{add $.Page 1}}&fragment" hx-trigger="revealed" hx-swap="afterend"> + {{end}} <span>{{$img.Name}}</span><br/> <a href="{{$img.Link}}"><img src="{{$img.Link}}" /></a><br/> {{else}} diff --git a/templates/nav_logged.html b/templates/nav_logged.html index 50e9a36..06c7a21 100644 --- a/templates/nav_logged.html +++ b/templates/nav_logged.html @@ -2,8 +2,13 @@ <nav> <ul class="navlogged"> <!--<li><a href="/admin">Admin</a></li>--> + {{if .UserImpersonation}} + <li><a href="/?user={{.UserImpersonation}}">Accueil</a></li> + <li><a href="/imgs?user={{.UserImpersonation}}">Images</a></li> + {{else}} <li><a href="/">Accueil</a></li> <li><a href="/imgs">Images</a></li> + {{end}} <li><a href="/logout">Se déconnecter</a></li> </ul> </nav> diff --git a/templates/user.html b/templates/user.html index cd0d98c..9a3a333 100644 --- a/templates/user.html +++ b/templates/user.html @@ -5,11 +5,19 @@ {{if .Error}} <p class="error">{{.Error}}</p> {{end}} + {{if ne .UserImpersonation ""}} + <form action="/upload?user={{.UserImpersonation}}" method="POST" enctype="multipart/form-data"> + {{else}} <form action="/upload" method="POST" enctype="multipart/form-data"> + {{end}} <input type="file" name="files" multiple /> <input type="submit" value="Upload" /> </form> + {{if ne .UserImpersonation ""}} + <form action="/download?user={{.UserImpersonation}}" method="POST" class="inline"> + {{else}} <form action="/download" method="POST" class="inline"> + {{end}} <div class="docs"> <table> <tr> @@ -39,7 +47,11 @@ <br/> <input type="submit" value="Télécharger les fichiers sélectionnés"> </form> + {{if ne .UserImpersonation ""}} + <form action="/download?user={{.UserImpersonation}}" method="GET" class="inlineblk"> + {{else}} <form action="/download" method="GET" class="inlineblk"> + {{end}} <input type="submit" value="Télécharger tous les fichiers"> </form> {{end}} |
