// Copyright (C) 2019 Marius Schellenberger

package authdav

import (
	"golang.org/x/net/webdav"
	"net/http"
)

// DefaultRealm is the HTTP Basic Auth default realm
const DefaultRealm = "WebDav"

// Authenticator is the interface for Webdav HTTP Basic Auth
type Authenticator interface {
	BasicAuth(username string, password string) bool
}

// WebdavBasicAuth is a WebDav wrapper for HTTP Basic Auth and implements the http.Handler interface
type WebdavBasicAuth struct {
	dav   *webdav.Handler
	auth  Authenticator
	realm string
}

// NewWebdavBasicAuth returns a new WebdavBasicAuth wrapper
// prefix can be empty
// ls and log can be nil
// an empty authenticator disables HTTP Basic Auth
// realm can be empty and defaults to authdav.DefaultRealm
func NewWebdavBasicAuth(prefix string, fs webdav.FileSystem, ls webdav.LockSystem, log func(*http.Request, error), auth Authenticator, realm string) *WebdavBasicAuth {
	if ls == nil {
		ls = webdav.NewMemLS()
	}
	if realm == "" {
		realm = DefaultRealm
	}
	dav := &webdav.Handler{
		Prefix:     prefix,
		FileSystem: fs,
		LockSystem: ls,
		Logger:     log,
	}
	return &WebdavBasicAuth{dav, auth, `Basic realm="` + realm + `"`}
}

func (h *WebdavBasicAuth) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if h.auth != nil {
		u, p, ok := r.BasicAuth()
		if !ok || !h.auth.BasicAuth(u, p) {
			w.Header().Set("WWW-Authenticate", h.realm)
			w.WriteHeader(http.StatusUnauthorized)
			w.Write([]byte("Unauthorised\n"))
			return
		}
	}
	h.dav.ServeHTTP(w, r)
}
