secure webdav

This commit is contained in:
julien 2025-06-19 10:36:38 +02:00
parent f49082592f
commit 4490a6618e

View File

@ -19,7 +19,48 @@ import (
"golang.org/x/net/webdav" "golang.org/x/net/webdav"
"gorm.io/gorm" "gorm.io/gorm"
) )
func setupWebdavRoute(r *mux.Router, db *gorm.DB) {
webdavHandler := &webdav.Handler{
Prefix: "/webdav/",
FileSystem: webdav.Dir("/app/upload"),
LockSystem: webdav.NewMemLS(),
}
// Middleware HTTP Basic qui interroge la DB
authHandler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
user, pass, ok := req.BasicAuth()
if !ok || !checkUserCredentials(db, user, pass) {
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
// Lecture seule
if req.Method != "GET" && req.Method != "HEAD" && req.Method != "OPTIONS" && req.Method != "PROPFIND" {
http.Error(w, "Read-Only", http.StatusForbidden)
return
}
w.Header().Set("DAV", "1,2")
w.Header().Set("MS-Author-Via", "DAV")
webdavHandler.ServeHTTP(w, req)
})
r.PathPrefix("/webdav/").Handler(authHandler)
}
func checkUserCredentials(db *gorm.DB, email string, password string) bool {
var user models.User
// On cherche l'utilisateur par email
result := db.Where("email = ?", email).First(&user)
if result.Error != nil {
return false
}
// On vérifie le mot de passe via bcrypt comme dans ton LoginHandler
err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
return err == nil
}
type spaHandler struct { type spaHandler struct {
staticPath string staticPath string
indexPath string indexPath string
@ -80,39 +121,40 @@ func RoutesPublic(r *mux.Router, bd *gorm.DB) {
http.Error(w, "Erreur lors de la génération de la playlist", http.StatusInternalServerError) http.Error(w, "Erreur lors de la génération de la playlist", http.StatusInternalServerError)
} }
}) })
setupWebdavRoute(r, bd)
// WebDAV sécurisé // WebDAV sécurisé
username := "tonuser" // ton login // username := "tonuser" // ton login
password := "tonpassword" // ton password // password := "tonpassword" // ton password
webdavHandler := &webdav.Handler{ // webdavHandler := &webdav.Handler{
Prefix: "/webdav/", // Prefix: "/webdav/",
FileSystem: webdav.Dir("/app/upload"), // FileSystem: webdav.Dir("/app/upload"),
LockSystem: webdav.NewMemLS(), // LockSystem: webdav.NewMemLS(),
} // }
r.PathPrefix("/webdav/").Handler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { // r.PathPrefix("/webdav/").Handler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
// Authentification // // Authentification
auth := req.Header.Get("Authorization") // auth := req.Header.Get("Authorization")
if auth == "" || !checkAuth(auth, username, password) { // if auth == "" || !checkAuth(auth, username, password) {
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`) // w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
http.Error(w, "Unauthorized", http.StatusUnauthorized) // http.Error(w, "Unauthorized", http.StatusUnauthorized)
return // return
} // }
// Protection lecture seule // // Protection lecture seule
if req.Method != "GET" && req.Method != "HEAD" && req.Method != "OPTIONS" && req.Method != "PROPFIND" { // if req.Method != "GET" && req.Method != "HEAD" && req.Method != "OPTIONS" && req.Method != "PROPFIND" {
http.Error(w, "Read-Only", http.StatusForbidden) // http.Error(w, "Read-Only", http.StatusForbidden)
return // return
} // }
log.Printf("WebDAV request: %s %s", req.Method, req.URL.Path) // log.Printf("WebDAV request: %s %s", req.Method, req.URL.Path)
// Headers WebDAV que VLC attend // // Headers WebDAV que VLC attend
w.Header().Set("DAV", "1,2") // w.Header().Set("DAV", "1,2")
w.Header().Set("MS-Author-Via", "DAV") // w.Header().Set("MS-Author-Via", "DAV")
webdavHandler.ServeHTTP(w, req) // webdavHandler.ServeHTTP(w, req)
})) // }))
} }
// Routes protégées // Routes protégées