diff --git a/app/config.go b/app/config.go index be98ad3..a5e89cc 100644 --- a/app/config.go +++ b/app/config.go @@ -28,6 +28,7 @@ type TLS struct { // UserInfo allows storing of a password and user directory. type UserInfo struct { Password string + Subdir *string } // ParseConfig parses the application configuration an sets defaults. @@ -116,11 +117,13 @@ func (cfg *Config) ensureUserDirs() { fmt.Printf("Created base dir: %s\n", cfg.Dir) } - for username := range cfg.Users { - path := filepath.Join(cfg.Dir, username) - if _, err := os.Stat(path); os.IsNotExist(err) { - os.Mkdir(path, os.ModePerm) - fmt.Printf("Created user dir: %s\n", path) + for _, user := range cfg.Users { + if user.Subdir != nil { + path := filepath.Join(cfg.Dir, *user.Subdir) + if _, err := os.Stat(path); os.IsNotExist(err) { + os.Mkdir(path, os.ModePerm) + fmt.Printf("Created user dir: %s\n", path) + } } } } diff --git a/app/fs.go b/app/fs.go index c877afe..124e79d 100644 --- a/app/fs.go +++ b/app/fs.go @@ -12,36 +12,39 @@ import ( // This file is an extension of golang.org/x/net/webdav/file.go. -// UserDir is specialization of webdav.Dir with respect of an authenticated -// user to allow synthetic user directories -type UserDir struct { - BaseDir string +// Dir is specialization of webdav.Dir with respect of an authenticated +// user to allow configuration access. +type Dir struct { + Config *Config } // resolve tries to gain authentication information and suffixes the BaseDir with the // username of the authentication information. If none authentication information can // achieved during the process, the BaseDir is used -func (d UserDir) resolve(ctx context.Context, name string) string { +func (d Dir) resolve(ctx context.Context, name string) string { // This implementation is based on Dir.Open's code in the standard net/http package. if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 || strings.Contains(name, "\x00") { return "" } - dir := string(d.BaseDir) + dir := string(d.Config.Dir) if dir == "" { dir = "." } authInfo := auth.FromContext(ctx) - if authInfo == nil || !authInfo.Authenticated { - return filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name))) + if authInfo != nil && authInfo.Authenticated { + userInfo := d.Config.Users[authInfo.Username] + if userInfo != nil && userInfo.Subdir != nil { + return filepath.Join(dir, authInfo.Username, filepath.FromSlash(path.Clean("/"+name))) + } } - return filepath.Join(dir, authInfo.Username, filepath.FromSlash(path.Clean("/"+name))) + return filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name))) } // Mkdir resolves the physical file and delegates this to an os.Mkdir execution -func (d UserDir) Mkdir(ctx context.Context, name string, perm os.FileMode) error { +func (d Dir) Mkdir(ctx context.Context, name string, perm os.FileMode) error { if name = d.resolve(ctx, name); name == "" { return os.ErrNotExist } @@ -49,7 +52,7 @@ func (d UserDir) Mkdir(ctx context.Context, name string, perm os.FileMode) error } // OpenFile resolves the physical file and delegates this to an os.OpenFile execution -func (d UserDir) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) { +func (d Dir) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) { if name = d.resolve(ctx, name); name == "" { return nil, os.ErrNotExist } @@ -61,11 +64,11 @@ func (d UserDir) OpenFile(ctx context.Context, name string, flag int, perm os.Fi } // RemoveAll resolves the physical file and delegates this to an os.RemoveAll execution -func (d UserDir) RemoveAll(ctx context.Context, name string) error { +func (d Dir) RemoveAll(ctx context.Context, name string) error { if name = d.resolve(ctx, name); name == "" { return os.ErrNotExist } - if name == filepath.Clean(string(d.BaseDir)) { + if name == filepath.Clean(string(d.Config.Dir)) { // Prohibit removing the virtual root directory. return os.ErrInvalid } @@ -73,14 +76,14 @@ func (d UserDir) RemoveAll(ctx context.Context, name string) error { } // Rename resolves the physical file and delegates this to an os.Rename execution -func (d UserDir) Rename(ctx context.Context, oldName, newName string) error { +func (d Dir) Rename(ctx context.Context, oldName, newName string) error { if oldName = d.resolve(ctx, oldName); oldName == "" { return os.ErrNotExist } if newName = d.resolve(ctx, newName); newName == "" { return os.ErrNotExist } - if root := filepath.Clean(string(d.BaseDir)); root == oldName || root == newName { + if root := filepath.Clean(string(d.Config.Dir)); root == oldName || root == newName { // Prohibit renaming from or to the virtual root directory. return os.ErrInvalid } @@ -88,7 +91,7 @@ func (d UserDir) Rename(ctx context.Context, oldName, newName string) error { } // Stat resolves the physical file and delegates this to an os.Stat execution -func (d UserDir) Stat(ctx context.Context, name string) (os.FileInfo, error) { +func (d Dir) Stat(ctx context.Context, name string) (os.FileInfo, error) { if name = d.resolve(ctx, name); name == "" { return nil, os.ErrNotExist } diff --git a/cmd/swd/main.go b/cmd/swd/main.go index f777f22..cd640b4 100644 --- a/cmd/swd/main.go +++ b/cmd/swd/main.go @@ -13,13 +13,13 @@ func main() { wdHandler := &webdav.Handler{ Prefix: config.Prefix, - FileSystem: &app.UserDir{ - BaseDir: config.Dir, + FileSystem: &app.Dir{ + Config: config, }, LockSystem: webdav.NewMemLS(), } - wdHandler.Logger = app.ModificationLogHandler + //wdHandler.Logger = app.ModificationLogHandler a := &app.App{ Config: config,