mirror of
https://github.com/filebrowser/filebrowser.git
synced 2024-06-07 23:00:43 +00:00
fa86894550
License: MIT
Signed-off-by: Henrique Dias <hacdias@gmail.com>
Former-commit-id: 984c56e0b9a9169b10c6017fbd68ab4fbd3868d7 [formerly 27c43314222c723a220b9b1d2141e1509ed05627] [formerly 0a9f6c47bff2d653035c93765ea08ade73ec450c [formerly b7fdcc3ee9
]]
Former-commit-id: c27e7fa41f20f433a9a0a97ecc40ab78968b43dc [formerly 185db4a17969cd4fb76cc2b06bd58221c9c6c100]
Former-commit-id: 9b26d1b0642c61cd38f7cdf422f95b2bf9a9614d
196 lines
4.4 KiB
Go
196 lines
4.4 KiB
Go
package http
|
|
|
|
import (
|
|
"encoding/json"
|
|
"log"
|
|
"net/http"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/filebrowser/filebrowser/v2/errors"
|
|
"github.com/filebrowser/filebrowser/v2/users"
|
|
"github.com/gorilla/mux"
|
|
)
|
|
|
|
type modifyUserRequest struct {
|
|
modifyRequest
|
|
Data *users.User `json:"data"`
|
|
}
|
|
|
|
func getUserID(r *http.Request) (uint, error) {
|
|
vars := mux.Vars(r)
|
|
i, err := strconv.ParseUint(vars["id"], 10, 0)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return uint(i), err
|
|
}
|
|
|
|
func getUser(w http.ResponseWriter, r *http.Request) (*modifyUserRequest, error) {
|
|
if r.Body == nil {
|
|
return nil, errors.ErrEmptyRequest
|
|
}
|
|
|
|
req := &modifyUserRequest{}
|
|
err := json.NewDecoder(r.Body).Decode(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if req.What != "user" {
|
|
return nil, errors.ErrInvalidDataType
|
|
}
|
|
|
|
return req, nil
|
|
}
|
|
|
|
func withSelfOrAdmin(fn handleFunc) handleFunc {
|
|
return withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
|
id, err := getUserID(r)
|
|
if err != nil {
|
|
return http.StatusInternalServerError, err
|
|
}
|
|
|
|
if d.user.ID != id && !d.user.Perm.Admin {
|
|
return http.StatusForbidden, nil
|
|
}
|
|
|
|
d.raw = id
|
|
return fn(w, r, d)
|
|
})
|
|
}
|
|
|
|
var usersGetHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
|
users, err := d.store.Users.Gets(d.server.Root)
|
|
if err != nil {
|
|
return http.StatusInternalServerError, err
|
|
}
|
|
|
|
for _, u := range users {
|
|
u.Password = ""
|
|
}
|
|
|
|
sort.Slice(users, func(i, j int) bool {
|
|
return users[i].ID < users[j].ID
|
|
})
|
|
|
|
return renderJSON(w, r, users)
|
|
})
|
|
|
|
var userGetHandler = withSelfOrAdmin(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
|
u, err := d.store.Users.Get(d.server.Root, d.raw.(uint))
|
|
if err == errors.ErrNotExist {
|
|
return http.StatusNotFound, err
|
|
}
|
|
|
|
if err != nil {
|
|
return http.StatusInternalServerError, err
|
|
}
|
|
|
|
u.Password = ""
|
|
return renderJSON(w, r, u)
|
|
})
|
|
|
|
var userDeleteHandler = withSelfOrAdmin(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
|
err := d.store.Users.Delete(d.raw.(uint))
|
|
if err == errors.ErrNotExist {
|
|
return http.StatusNotFound, err
|
|
}
|
|
|
|
return http.StatusOK, nil
|
|
})
|
|
|
|
var userPostHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
|
req, err := getUser(w, r)
|
|
if err != nil {
|
|
return http.StatusBadRequest, err
|
|
}
|
|
|
|
if len(req.Which) != 0 {
|
|
return http.StatusBadRequest, nil
|
|
}
|
|
|
|
if req.Data.Password == "" {
|
|
return http.StatusBadRequest, errors.ErrEmptyPassword
|
|
}
|
|
|
|
req.Data.Password, err = users.HashPwd(req.Data.Password)
|
|
if err != nil {
|
|
return http.StatusInternalServerError, err
|
|
}
|
|
|
|
userHome, err := d.settings.MakeUserDir(req.Data.Username, req.Data.Scope, d.server.Root)
|
|
if err != nil {
|
|
log.Printf("create user: failed to mkdir user home dir: [%s]", userHome)
|
|
return http.StatusInternalServerError, err
|
|
}
|
|
req.Data.Scope = userHome
|
|
log.Printf("user: %s, home dir: [%s].", req.Data.Username, userHome)
|
|
|
|
err = d.store.Users.Save(req.Data)
|
|
if err != nil {
|
|
return http.StatusInternalServerError, err
|
|
}
|
|
|
|
w.Header().Set("Location", "/settings/users/"+strconv.FormatUint(uint64(req.Data.ID), 10))
|
|
return http.StatusCreated, nil
|
|
})
|
|
|
|
var userPutHandler = withSelfOrAdmin(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
|
req, err := getUser(w, r)
|
|
if err != nil {
|
|
return http.StatusBadRequest, err
|
|
}
|
|
|
|
if req.Data.ID != d.raw.(uint) {
|
|
return http.StatusBadRequest, nil
|
|
}
|
|
|
|
if len(req.Which) == 1 && req.Which[0] == "all" {
|
|
if !d.user.Perm.Admin {
|
|
return http.StatusForbidden, err
|
|
}
|
|
|
|
if req.Data.Password != "" {
|
|
req.Data.Password, err = users.HashPwd(req.Data.Password)
|
|
} else {
|
|
var suser *users.User
|
|
suser, err = d.store.Users.Get(d.server.Root, d.raw.(uint))
|
|
req.Data.Password = suser.Password
|
|
}
|
|
|
|
if err != nil {
|
|
return http.StatusInternalServerError, err
|
|
}
|
|
|
|
req.Which = []string{}
|
|
}
|
|
|
|
for k, v := range req.Which {
|
|
if v == "password" {
|
|
if !d.user.Perm.Admin && d.user.LockPassword {
|
|
return http.StatusForbidden, nil
|
|
}
|
|
|
|
req.Data.Password, err = users.HashPwd(req.Data.Password)
|
|
if err != nil {
|
|
return http.StatusInternalServerError, err
|
|
}
|
|
}
|
|
|
|
if !d.user.Perm.Admin && (v == "scope" || v == "perm" || v == "username") {
|
|
return http.StatusForbidden, nil
|
|
}
|
|
|
|
req.Which[k] = strings.Title(v)
|
|
}
|
|
|
|
err = d.store.Users.Update(req.Data, req.Which...)
|
|
if err != nil {
|
|
return http.StatusInternalServerError, err
|
|
}
|
|
|
|
return http.StatusOK, nil
|
|
})
|