diff --git a/README.md b/README.md index ff01160..11a0fa2 100644 --- a/README.md +++ b/README.md @@ -34,11 +34,11 @@ For usage information regarding the CLI, run `webdav --help`. ### Docker -To use with Docker, you need to provide a configuration file and mount the data directories. For example, let's take the following configuration file that simply sets the port to `6060` and the scope to `/data`. +To use with Docker, you need to provide a configuration file and mount the data directories. For example, let's take the following configuration file that simply sets the port to `6060` and the directory to `/data`. ```yaml port: 6060 -scope: /data +directory: /data ``` You can now run with the following Docker command, where you mount the configuration file inside the container, and the data directory too, as well as forwarding the port 6060. You will need to change this to match your own configuration. @@ -71,9 +71,9 @@ prefix: / debug: false # The directory that will be able to be accessed by the users when connecting. -# This directory will be used by users unless they have their own 'scope' defined. +# This directory will be used by users unless they have their own 'directory' defined. # Default is "." (current directory). -scope: . +directory: . # Whether the users can, by default, modify the contents. Default is false. modify: true @@ -86,10 +86,10 @@ users: # Example 'admin' user with plaintext password. - username: admin password: admin - # Example 'john' user with bcrypt encrypted password, with custom scope. + # Example 'john' user with bcrypt encrypted password, with custom directory. - username: john password: "{bcrypt}$2y$10$zEP6oofmXFeHaeMfBNLnP.DO8m.H.Mwhd24/TOX2MWLxAExXi4qgi" - scope: /another/path + directory: /another/path # Example user whose details will be picked up from the environment. - username: "{env}ENV_USERNAME" password: "{env}ENV_PASSWORD" diff --git a/lib/config.go b/lib/config.go index ebd4f87..5099791 100644 --- a/lib/config.go +++ b/lib/config.go @@ -13,7 +13,7 @@ import ( ) const ( - DefaultScope = "." + DefaultDirectory = "." DefaultModify = false DefaultDebug = false DefaultNoSniff = false @@ -74,7 +74,7 @@ func ParseConfig(filename string, flags *pflag.FlagSet) (*Config, error) { // empty or false. // Defaults shared with flags - v.SetDefault("Scope", DefaultScope) + v.SetDefault("Directory", DefaultDirectory) v.SetDefault("Modify", DefaultModify) v.SetDefault("Debug", DefaultDebug) v.SetDefault("NoSniff", DefaultNoSniff) @@ -111,8 +111,8 @@ func ParseConfig(filename string, flags *pflag.FlagSet) (*Config, error) { // Cascade user settings for i := range cfg.Users { - if !v.IsSet(fmt.Sprintf("Users.%d.Scope", i)) { - cfg.Users[i].Scope = cfg.Scope + if !v.IsSet(fmt.Sprintf("Users.%d.Directory", i)) { + cfg.Users[i].Directory = cfg.Directory } if !v.IsSet(fmt.Sprintf("Users.%d.Modify", i)) { @@ -139,7 +139,7 @@ func (c *Config) Validate() error { zap.L().Warn("unprotected config: no users have been set, so no authentication will be used") } - c.Scope, err = filepath.Abs(c.Scope) + c.Directory, err = filepath.Abs(c.Directory) if err != nil { return fmt.Errorf("invalid config: %w", err) } diff --git a/lib/config_test.go b/lib/config_test.go index bd3b93c..7398f82 100644 --- a/lib/config_test.go +++ b/lib/config_test.go @@ -36,7 +36,7 @@ func TestConfigDefaults(t *testing.T) { dir, err := os.Getwd() require.NoError(t, err) - require.Equal(t, dir, cfg.Scope) + require.Equal(t, dir, cfg.Directory) require.EqualValues(t, []string{"*"}, cfg.CORS.AllowedHeaders) require.EqualValues(t, []string{"*"}, cfg.CORS.AllowedHosts) @@ -48,23 +48,23 @@ func TestConfigCascade(t *testing.T) { check := func(t *testing.T, cfg *Config) { require.True(t, cfg.Modify) - require.Equal(t, "/", cfg.Scope) + require.Equal(t, "/", cfg.Directory) require.Len(t, cfg.Rules, 1) require.Len(t, cfg.Users, 2) require.True(t, cfg.Users[0].Modify) - require.Equal(t, "/", cfg.Users[0].Scope) + require.Equal(t, "/", cfg.Users[0].Directory) require.Len(t, cfg.Users[0].Rules, 1) require.False(t, cfg.Users[1].Modify) - require.Equal(t, "/basic", cfg.Users[1].Scope) + require.Equal(t, "/basic", cfg.Users[1].Directory) require.Len(t, cfg.Users[1].Rules, 0) } t.Run("YAML", func(t *testing.T) { content := ` -scope: / +directory: / modify: true rules: - path: /public/access/ @@ -75,7 +75,7 @@ users: password: admin - username: basic password: basic - scope: /basic + directory: /basic modify: false rules: []` @@ -87,7 +87,7 @@ users: t.Run("JSON", func(t *testing.T) { content := `{ - "scope": "/", + "directory": "/", "modify": true, "rules": [ { @@ -103,7 +103,7 @@ users: { "username": "basic", "password": "basic", - "scope": "/basic", + "directory": "/basic", "modify": false, "rules": [] } @@ -118,7 +118,7 @@ users: t.Run("`TOML", func(t *testing.T) { content := ` -scope = "/" +directory = "/" modify = true [[rules]] @@ -132,7 +132,7 @@ password = "admin" [[users]] username = "basic" password = "basic" -scope = "/basic" +directory = "/basic" modify = false rules = [] ` @@ -172,7 +172,7 @@ cors: func TestConfigRules(t *testing.T) { content := ` -scope: / +directory: / modify: true rules: - regex: '^.+\.js$' @@ -198,13 +198,13 @@ func TestConfigEnv(t *testing.T) { require.NoError(t, os.Setenv("WD_PORT", "1234")) require.NoError(t, os.Setenv("WD_DEBUG", "true")) require.NoError(t, os.Setenv("WD_MODIFY", "true")) - require.NoError(t, os.Setenv("WD_SCOPE", "/test")) + require.NoError(t, os.Setenv("WD_DIRECTORY", "/test")) cfg, err := ParseConfig("", nil) require.NoError(t, err) assert.Equal(t, 1234, cfg.Port) - assert.Equal(t, "/test", cfg.Scope) + assert.Equal(t, "/test", cfg.Directory) assert.Equal(t, true, cfg.Debug) assert.Equal(t, true, cfg.Modify) @@ -212,5 +212,5 @@ func TestConfigEnv(t *testing.T) { require.NoError(t, os.Setenv("WD_PORT", "")) require.NoError(t, os.Setenv("WD_DEBUG", "")) require.NoError(t, os.Setenv("WD_MODIFY", "")) - require.NoError(t, os.Setenv("WD_SCOPE", "")) + require.NoError(t, os.Setenv("WD_DIRECTORY", "")) } diff --git a/lib/handler.go b/lib/handler.go index 5529123..f69005a 100644 --- a/lib/handler.go +++ b/lib/handler.go @@ -28,7 +28,7 @@ func NewHandler(c *Config) (http.Handler, error) { Handler: webdav.Handler{ Prefix: c.Prefix, FileSystem: Dir{ - Dir: webdav.Dir(c.Scope), + Dir: webdav.Dir(c.Directory), noSniff: c.NoSniff, }, LockSystem: webdav.NewMemLS(), @@ -43,7 +43,7 @@ func NewHandler(c *Config) (http.Handler, error) { Handler: webdav.Handler{ Prefix: c.Prefix, FileSystem: Dir{ - Dir: webdav.Dir(u.Scope), + Dir: webdav.Dir(u.Directory), noSniff: c.NoSniff, }, LockSystem: webdav.NewMemLS(), diff --git a/lib/handler_test.go b/lib/handler_test.go index 04a3c17..ebd7a19 100644 --- a/lib/handler_test.go +++ b/lib/handler_test.go @@ -50,7 +50,7 @@ func TestServerDefaults(t *testing.T) { "sub/bar.txt": []byte("bar"), }) - srv := makeTestServer(t, "scope: "+dir) + srv := makeTestServer(t, "directory: "+dir) client := gowebdav.NewClient(srv.URL, "", "") // By default, reading permissions. @@ -90,7 +90,7 @@ func TestServerAuthentication(t *testing.T) { }) srv := makeTestServer(t, fmt.Sprintf(` -scope: %s +directory: %s modify: true users: @@ -152,7 +152,7 @@ func TestServerRules(t *testing.T) { }) srv := makeTestServer(t, fmt.Sprintf(` -scope: %s +directory: %s modify: true users: @@ -194,16 +194,16 @@ func TestServerPermissions(t *testing.T) { }) srv := makeTestServer(t, fmt.Sprintf(` -scope: %s +directory: %s modify: true users: - username: a password: a - scope: %s/a + directory: %s/a - username: b password: b - scope: %s/b + directory: %s/b modify: false `, dir, dir, dir)) diff --git a/lib/permissions.go b/lib/permissions.go index 849fcf0..0276d08 100644 --- a/lib/permissions.go +++ b/lib/permissions.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "net/http" + "path/filepath" "regexp" "strings" ) @@ -40,9 +41,9 @@ func (r *Rule) Matches(path string) bool { } type Permissions struct { - Scope string - Modify bool - Rules []*Rule + Directory string + Modify bool + Rules []*Rule } // Allowed checks if the user has permission to access a directory/file @@ -69,6 +70,13 @@ func (p Permissions) Allowed(r *http.Request) bool { } func (p *Permissions) Validate() error { + var err error + + p.Directory, err = filepath.Abs(p.Directory) + if err != nil { + return fmt.Errorf("invalid permissions: %w", err) + } + for _, r := range p.Rules { if err := r.Validate(); err != nil { return fmt.Errorf("invalid permissions: %w", err)