Add support for multiple users \o/

Create a webdav and file handler for each user, lock them into a
directory that is their user name.
This commit is contained in:
Aaron Bieber 2021-05-19 20:30:45 -06:00
parent b3b8aa563d
commit 490a1a757a

71
main.go
View File

@ -26,16 +26,23 @@ var twFile = "empty-5.1.23.html"
//go:embed empty-5.1.23.html //go:embed empty-5.1.23.html
var tiddly embed.FS var tiddly embed.FS
type userHandlers struct {
dav *webdav.Handler
fs http.Handler
}
var ( var (
davDir string davDir string
listen string listen string
auth bool auth bool
passPath string passPath string
users map[string]string users map[string]string
handlers map[string]userHandlers
) )
func init() { func init() {
users = make(map[string]string) users = make(map[string]string)
handlers = make(map[string]userHandlers)
dir, err := filepath.Abs(filepath.Dir(os.Args[0])) dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil { if err != nil {
log.Fatalln(err) log.Fatalln(err)
@ -123,44 +130,64 @@ func createEmpty(path string) error {
} }
func main() { func main() {
wdav := &webdav.Handler{ if auth {
LockSystem: webdav.NewMemLS(), for u := range users {
FileSystem: webdav.Dir(davDir), uPath := path.Join(davDir, u)
handlers[u] = userHandlers{
dav: &webdav.Handler{
LockSystem: webdav.NewMemLS(),
FileSystem: webdav.Dir(uPath),
},
fs: http.FileServer(http.Dir(uPath)),
}
}
} else {
handlers[""] = userHandlers{
dav: &webdav.Handler{
LockSystem: webdav.NewMemLS(),
FileSystem: webdav.Dir(davDir),
},
fs: http.FileServer(http.Dir(davDir)),
}
} }
idxHandler := http.FileServer(http.Dir(davDir))
mux := http.NewServeMux() mux := http.NewServeMux()
mux.HandleFunc("/", logger(func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/", logger(func(w http.ResponseWriter, r *http.Request) {
user, pass := "", ""
var ok bool
if strings.Contains(r.URL.Path, ".htpasswd") { if strings.Contains(r.URL.Path, ".htpasswd") {
http.Error(w, "Unauthorized", http.StatusUnauthorized) http.NotFound(w, r)
return
}
// Prevent directory traversal
if strings.Contains(r.URL.Path, "..") {
http.NotFound(w, r)
return return
} }
if auth { if auth {
user, pass, ok := r.BasicAuth() user, pass, ok = r.BasicAuth()
if !(ok && authenticate(user, pass)) { if !(ok && authenticate(user, pass)) {
w.Header().Set("WWW-Authenticate", `Basic realm="davfs"`) w.Header().Set("WWW-Authenticate", `Basic realm="widdler"`)
http.Error(w, "Unauthorized", http.StatusUnauthorized) http.Error(w, "Unauthorized", http.StatusUnauthorized)
return return
} }
} }
//wdav.Prefix = user handler := handlers[user]
up := path.Join(davDir, user)
fp := path.Join(davDir, user, r.URL.Path)
fp := path.Join(davDir, r.URL.Path) _, dErr := os.Stat(up)
/* if os.IsNotExist(dErr) {
fp := path.Join(davDir, user, r.URL.Path) mErr := os.Mkdir(up, 0700)
_, dErr := os.Stat(user) if mErr != nil {
if os.IsNotExist(dErr) { http.Error(w, mErr.Error(), http.StatusInternalServerError)
mErr := os.Mkdir(path.Join(davDir, user), 0700) return
if mErr != nil {
http.Error(w, mErr.Error(), http.StatusInternalServerError)
return
}
} }
*/ }
isHTML, err := regexp.Match(`\.html$`, []byte(r.URL.Path)) isHTML, err := regexp.Match(`\.html$`, []byte(r.URL.Path))
if err != nil { if err != nil {
@ -176,10 +203,10 @@ func main() {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
wdav.ServeHTTP(w, r) handler.dav.ServeHTTP(w, r)
} else { } else {
// Everything else is browsable // Everything else is browsable
idxHandler.ServeHTTP(w, r) handler.fs.ServeHTTP(w, r)
return return
} }
})) }))