diff --git a/cmd_serve.go b/cmd_serve.go index cec3265..db0ee71 100644 --- a/cmd_serve.go +++ b/cmd_serve.go @@ -82,10 +82,11 @@ func (cmd *CmdServe) Run(app *app) error { return } - // TODO determine permissions + readonly := share.ReadOnly || share.Role == ShareRoleReader directoryMapping := DirectoryMapping{ DataDirName: share.UUID.String(), + ReadOnly: readonly, } // Use the WebDAV handler to actually serve the request. Also enhance the context diff --git a/filesystem.go b/filesystem.go index 9f1fc70..f1614bf 100644 --- a/filesystem.go +++ b/filesystem.go @@ -35,6 +35,7 @@ package main import ( "context" + "fmt" "os" "path" "path/filepath" @@ -45,6 +46,7 @@ import ( type DirectoryMapping struct { DataDirName string + ReadOnly bool } // slashClean is equivalent to but slightly more efficient than @@ -74,6 +76,11 @@ func (d BaseDir) resolve(ctx context.Context, name string) string { } func (d BaseDir) Mkdir(ctx context.Context, name string, perm os.FileMode) error { + directoryMapping := ctx.Value("mapping").(*DirectoryMapping) + if directoryMapping.ReadOnly { + return fmt.Errorf("forbidden") + } + if name = d.resolve(ctx, name); name == "" { return os.ErrNotExist } @@ -81,6 +88,13 @@ func (d BaseDir) Mkdir(ctx context.Context, name string, perm os.FileMode) error } func (d BaseDir) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) { + directoryMapping := ctx.Value("mapping").(*DirectoryMapping) + + const writeFlags = os.O_APPEND | os.O_CREATE | os.O_RDWR | os.O_WRONLY | os.O_TRUNC + if flag&writeFlags != 0 && directoryMapping.ReadOnly { + return nil, fmt.Errorf("forbidden") + } + if name = d.resolve(ctx, name); name == "" { return nil, os.ErrNotExist } @@ -92,6 +106,11 @@ func (d BaseDir) OpenFile(ctx context.Context, name string, flag int, perm os.Fi } func (d BaseDir) RemoveAll(ctx context.Context, name string) error { + directoryMapping := ctx.Value("mapping").(*DirectoryMapping) + if directoryMapping.ReadOnly { + return fmt.Errorf("forbidden") + } + if name = d.resolve(ctx, name); name == "" { return os.ErrNotExist } @@ -103,6 +122,11 @@ func (d BaseDir) RemoveAll(ctx context.Context, name string) error { } func (d BaseDir) Rename(ctx context.Context, oldName, newName string) error { + directoryMapping := ctx.Value("mapping").(*DirectoryMapping) + if directoryMapping.ReadOnly { + return fmt.Errorf("forbidden") + } + if oldName = d.resolve(ctx, oldName); oldName == "" { return os.ErrNotExist }