Make user subdirs optional to allow admin access to the whole directory
This commit is contained in:
parent
6bd8f49b70
commit
07a719c03c
3 changed files with 30 additions and 24 deletions
|
@ -28,6 +28,7 @@ type TLS struct {
|
||||||
// UserInfo allows storing of a password and user directory.
|
// UserInfo allows storing of a password and user directory.
|
||||||
type UserInfo struct {
|
type UserInfo struct {
|
||||||
Password string
|
Password string
|
||||||
|
Subdir *string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseConfig parses the application configuration an sets defaults.
|
// 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)
|
fmt.Printf("Created base dir: %s\n", cfg.Dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
for username := range cfg.Users {
|
for _, user := range cfg.Users {
|
||||||
path := filepath.Join(cfg.Dir, username)
|
if user.Subdir != nil {
|
||||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
path := filepath.Join(cfg.Dir, *user.Subdir)
|
||||||
os.Mkdir(path, os.ModePerm)
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
fmt.Printf("Created user dir: %s\n", path)
|
os.Mkdir(path, os.ModePerm)
|
||||||
|
fmt.Printf("Created user dir: %s\n", path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
35
app/fs.go
35
app/fs.go
|
@ -12,36 +12,39 @@ import (
|
||||||
|
|
||||||
// This file is an extension of golang.org/x/net/webdav/file.go.
|
// This file is an extension of golang.org/x/net/webdav/file.go.
|
||||||
|
|
||||||
// UserDir is specialization of webdav.Dir with respect of an authenticated
|
// Dir is specialization of webdav.Dir with respect of an authenticated
|
||||||
// user to allow synthetic user directories
|
// user to allow configuration access.
|
||||||
type UserDir struct {
|
type Dir struct {
|
||||||
BaseDir string
|
Config *Config
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve tries to gain authentication information and suffixes the BaseDir with the
|
// resolve tries to gain authentication information and suffixes the BaseDir with the
|
||||||
// username of the authentication information. If none authentication information can
|
// username of the authentication information. If none authentication information can
|
||||||
// achieved during the process, the BaseDir is used
|
// 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.
|
// This implementation is based on Dir.Open's code in the standard net/http package.
|
||||||
if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 ||
|
if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 ||
|
||||||
strings.Contains(name, "\x00") {
|
strings.Contains(name, "\x00") {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
dir := string(d.BaseDir)
|
dir := string(d.Config.Dir)
|
||||||
if dir == "" {
|
if dir == "" {
|
||||||
dir = "."
|
dir = "."
|
||||||
}
|
}
|
||||||
|
|
||||||
authInfo := auth.FromContext(ctx)
|
authInfo := auth.FromContext(ctx)
|
||||||
if authInfo == nil || !authInfo.Authenticated {
|
if authInfo != nil && authInfo.Authenticated {
|
||||||
return filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name)))
|
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
|
// 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 == "" {
|
if name = d.resolve(ctx, name); name == "" {
|
||||||
return os.ErrNotExist
|
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
|
// 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 == "" {
|
if name = d.resolve(ctx, name); name == "" {
|
||||||
return nil, os.ErrNotExist
|
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
|
// 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 == "" {
|
if name = d.resolve(ctx, name); name == "" {
|
||||||
return os.ErrNotExist
|
return os.ErrNotExist
|
||||||
}
|
}
|
||||||
if name == filepath.Clean(string(d.BaseDir)) {
|
if name == filepath.Clean(string(d.Config.Dir)) {
|
||||||
// Prohibit removing the virtual root directory.
|
// Prohibit removing the virtual root directory.
|
||||||
return os.ErrInvalid
|
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
|
// 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 == "" {
|
if oldName = d.resolve(ctx, oldName); oldName == "" {
|
||||||
return os.ErrNotExist
|
return os.ErrNotExist
|
||||||
}
|
}
|
||||||
if newName = d.resolve(ctx, newName); newName == "" {
|
if newName = d.resolve(ctx, newName); newName == "" {
|
||||||
return os.ErrNotExist
|
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.
|
// Prohibit renaming from or to the virtual root directory.
|
||||||
return os.ErrInvalid
|
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
|
// 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 == "" {
|
if name = d.resolve(ctx, name); name == "" {
|
||||||
return nil, os.ErrNotExist
|
return nil, os.ErrNotExist
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,13 +13,13 @@ func main() {
|
||||||
|
|
||||||
wdHandler := &webdav.Handler{
|
wdHandler := &webdav.Handler{
|
||||||
Prefix: config.Prefix,
|
Prefix: config.Prefix,
|
||||||
FileSystem: &app.UserDir{
|
FileSystem: &app.Dir{
|
||||||
BaseDir: config.Dir,
|
Config: config,
|
||||||
},
|
},
|
||||||
LockSystem: webdav.NewMemLS(),
|
LockSystem: webdav.NewMemLS(),
|
||||||
}
|
}
|
||||||
|
|
||||||
wdHandler.Logger = app.ModificationLogHandler
|
//wdHandler.Logger = app.ModificationLogHandler
|
||||||
|
|
||||||
a := &app.App{
|
a := &app.App{
|
||||||
Config: config,
|
Config: config,
|
||||||
|
|
Loading…
Reference in a new issue