mirror of
https://github.com/hacdias/webdav.git
synced 2025-04-18 15:44:00 +03:00
438 lines
10 KiB
Go
438 lines
10 KiB
Go
package lib
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/studio-b12/gowebdav"
|
|
)
|
|
|
|
func makeTestDirectory(t *testing.T, m map[string][]byte) string {
|
|
dir := t.TempDir()
|
|
|
|
for path, data := range m {
|
|
filename := filepath.Join(dir, path)
|
|
|
|
if data == nil {
|
|
err := os.MkdirAll(filename, 0775)
|
|
require.NoError(t, err)
|
|
} else {
|
|
err := os.MkdirAll(filepath.Dir(filename), 0775)
|
|
require.NoError(t, err)
|
|
|
|
err = os.WriteFile(filename, data, 0664)
|
|
require.NoError(t, err)
|
|
}
|
|
}
|
|
|
|
return dir
|
|
}
|
|
|
|
func makeTestServer(t *testing.T, yamlConfig string) *httptest.Server {
|
|
cfg := writeAndParseConfig(t, yamlConfig, ".yml")
|
|
require.NoError(t, cfg.Validate())
|
|
|
|
handler, err := NewHandler(cfg)
|
|
require.NoError(t, err)
|
|
|
|
return httptest.NewServer(handler)
|
|
}
|
|
|
|
func TestServerDefaults(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
dir := makeTestDirectory(t, map[string][]byte{
|
|
"foo.txt": []byte("foo"),
|
|
"sub/bar.txt": []byte("bar"),
|
|
})
|
|
|
|
srv := makeTestServer(t, "directory: "+dir)
|
|
client := gowebdav.NewClient(srv.URL, "", "")
|
|
|
|
// By default, reading permissions.
|
|
files, err := client.ReadDir("/")
|
|
require.NoError(t, err)
|
|
require.Len(t, files, 2)
|
|
|
|
data, err := client.Read("/foo.txt")
|
|
require.NoError(t, err)
|
|
require.EqualValues(t, []byte("foo"), data)
|
|
|
|
files, err = client.ReadDir("/sub")
|
|
require.NoError(t, err)
|
|
require.Len(t, files, 1)
|
|
require.Equal(t, "bar.txt", files[0].Name())
|
|
|
|
data, err = client.Read("/sub/bar.txt")
|
|
require.NoError(t, err)
|
|
require.EqualValues(t, []byte("bar"), data)
|
|
|
|
// By default, no modification permissions.
|
|
require.ErrorContains(t, client.Mkdir("/dir", 0666), "403")
|
|
require.ErrorContains(t, client.MkdirAll("/dir/path", 0666), "403")
|
|
require.ErrorContains(t, client.Remove("/foo.txt"), "403")
|
|
require.ErrorContains(t, client.RemoveAll("/foo.txt"), "403")
|
|
require.ErrorContains(t, client.Rename("/foo.txt", "/file2.txt", false), "403")
|
|
require.ErrorContains(t, client.Copy("/foo.txt", "/file2.txt", false), "403")
|
|
require.ErrorContains(t, client.Write("/foo.txt", []byte("hello world 2"), 0666), "403")
|
|
}
|
|
|
|
func TestServerListingCharacters(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
dir := makeTestDirectory(t, map[string][]byte{
|
|
"富/foo.txt": []byte("foo"),
|
|
"你好.txt": []byte("bar"),
|
|
"z*.txt": []byte("zbar"),
|
|
"foo.txt": []byte("foo"),
|
|
"🌹.txt": []byte("foo"),
|
|
})
|
|
|
|
srv := makeTestServer(t, "directory: "+dir)
|
|
client := gowebdav.NewClient(srv.URL, "", "")
|
|
|
|
// By default, reading permissions.
|
|
files, err := client.ReadDir("/")
|
|
require.NoError(t, err)
|
|
require.Len(t, files, 5)
|
|
|
|
names := []string{
|
|
files[0].Name(),
|
|
files[1].Name(),
|
|
files[2].Name(),
|
|
files[3].Name(),
|
|
files[4].Name(),
|
|
}
|
|
sort.Strings(names)
|
|
|
|
require.Equal(t, []string{
|
|
"foo.txt",
|
|
"z*.txt",
|
|
"你好.txt",
|
|
"富",
|
|
"🌹.txt",
|
|
}, names)
|
|
|
|
data, err := client.Read("/z*.txt")
|
|
require.NoError(t, err)
|
|
require.EqualValues(t, []byte("zbar"), data)
|
|
}
|
|
|
|
func TestServerAuthentication(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
dir := makeTestDirectory(t, map[string][]byte{
|
|
"foo.txt": []byte("foo"),
|
|
"sub/bar.txt": []byte("bar"),
|
|
})
|
|
|
|
srv := makeTestServer(t, fmt.Sprintf(`
|
|
directory: %s
|
|
permissions: CRUD
|
|
|
|
users:
|
|
- username: basic
|
|
password: basic
|
|
- username: bcrypt
|
|
password: "{bcrypt}$2a$12$222dfz8Nweoyvy8OwI8.me9nfaRfuz8lqGkiiYSMH1lLMHO26qWom"
|
|
`, dir))
|
|
|
|
t.Run("Basic Auth (Plaintext)", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
client := gowebdav.NewClient(srv.URL, "basic", "basic")
|
|
|
|
files, err := client.ReadDir("/")
|
|
require.NoError(t, err)
|
|
require.Len(t, files, 2)
|
|
})
|
|
|
|
t.Run("Basic Auth (BCrypt)", func(t *testing.T) {
|
|
t.Parallel()
|
|
client := gowebdav.NewClient(srv.URL, "bcrypt", "bcrypt")
|
|
|
|
files, err := client.ReadDir("/")
|
|
require.NoError(t, err)
|
|
require.Len(t, files, 2)
|
|
})
|
|
|
|
t.Run("Unauthorized (No Credentials)", func(t *testing.T) {
|
|
t.Parallel()
|
|
client := gowebdav.NewClient(srv.URL, "", "")
|
|
_, err := client.ReadDir("/")
|
|
require.ErrorContains(t, err, "401")
|
|
})
|
|
|
|
t.Run("Unauthorized (Wrong User)", func(t *testing.T) {
|
|
t.Parallel()
|
|
client := gowebdav.NewClient(srv.URL, "wrong", "basic")
|
|
_, err := client.ReadDir("/")
|
|
require.ErrorContains(t, err, "401")
|
|
})
|
|
|
|
t.Run("Unauthorized (Wrong Password)", func(t *testing.T) {
|
|
t.Parallel()
|
|
client := gowebdav.NewClient(srv.URL, "basic", "wrong")
|
|
_, err := client.ReadDir("/")
|
|
require.ErrorContains(t, err, "401")
|
|
})
|
|
}
|
|
|
|
func TestServerAuthenticationNoPassword(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
dir := makeTestDirectory(t, map[string][]byte{
|
|
"foo.txt": []byte("foo"),
|
|
"sub/bar.txt": []byte("bar"),
|
|
})
|
|
|
|
srv := makeTestServer(t, fmt.Sprintf(`
|
|
directory: %s
|
|
noPassword: true
|
|
permissions: CRUD
|
|
|
|
users:
|
|
- username: basic
|
|
`, dir))
|
|
|
|
t.Run("Basic Auth", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
client := gowebdav.NewClient(srv.URL, "basic", "")
|
|
files, err := client.ReadDir("/")
|
|
require.NoError(t, err)
|
|
require.Len(t, files, 2)
|
|
})
|
|
|
|
t.Run("Unauthorized Wrong User", func(t *testing.T) {
|
|
t.Parallel()
|
|
client := gowebdav.NewClient(srv.URL, "wrong", "")
|
|
_, err := client.ReadDir("/")
|
|
require.ErrorContains(t, err, "401")
|
|
})
|
|
}
|
|
|
|
func TestServerRules(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
dir := makeTestDirectory(t, map[string][]byte{
|
|
"foo.txt": []byte("foo"),
|
|
"bar.js": []byte("foo js"),
|
|
"a/foo.js": []byte("foo js"),
|
|
"a/foo.txt": []byte("foo txt"),
|
|
"b/foo.txt": []byte("foo b"),
|
|
"c/a.txt": []byte("b"),
|
|
"c/b.txt": []byte("b"),
|
|
"c/c.txt": []byte("b"),
|
|
})
|
|
|
|
srv := makeTestServer(t, fmt.Sprintf(`
|
|
directory: %s
|
|
permissions: CRUD
|
|
|
|
users:
|
|
- username: basic
|
|
password: basic
|
|
rules:
|
|
- regex: "^.+.js$"
|
|
permissions: R
|
|
- path: "/b/"
|
|
permissions: R
|
|
- path: "/a/foo.txt"
|
|
permissions: none
|
|
- path: "/c/"
|
|
permissions: none
|
|
`, dir))
|
|
|
|
client := gowebdav.NewClient(srv.URL, "basic", "basic")
|
|
|
|
files, err := client.ReadDir("/")
|
|
require.NoError(t, err)
|
|
require.Len(t, files, 5)
|
|
|
|
err = client.Write("/foo.txt", []byte("new"), 0666)
|
|
require.NoError(t, err)
|
|
|
|
err = client.Write("/new.txt", []byte("new"), 0666)
|
|
require.NoError(t, err)
|
|
|
|
err = client.Copy("/bar.js", "/b/bar.js", false)
|
|
require.ErrorContains(t, err, "403")
|
|
|
|
err = client.Copy("/bar.js", "/bar.jsx", false)
|
|
require.NoError(t, err)
|
|
|
|
err = client.Copy("/b/foo.txt", "/foo1.txt", false)
|
|
require.NoError(t, err)
|
|
|
|
err = client.Rename("/b/foo.txt", "/foo2.txt", false)
|
|
require.ErrorContains(t, err, "403")
|
|
|
|
_, err = client.Read("/a/foo.txt")
|
|
require.ErrorContains(t, err, "403")
|
|
|
|
err = client.Write("/a/foo.js", []byte("new"), 0666)
|
|
require.ErrorContains(t, err, "403")
|
|
|
|
err = client.Write("/b/foo.txt", []byte("new"), 0666)
|
|
require.ErrorContains(t, err, "403")
|
|
|
|
_, err = client.ReadDir("/c")
|
|
require.ErrorContains(t, err, "403")
|
|
|
|
_, err = client.Read("/c/a.txt")
|
|
require.ErrorContains(t, err, "403")
|
|
|
|
err = client.Write("/c/b.txt", []byte("new"), 0666)
|
|
require.ErrorContains(t, err, "403")
|
|
}
|
|
|
|
func TestServerRulesPrefix(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
dir := makeTestDirectory(t, map[string][]byte{
|
|
"foo.txt": []byte("foo"),
|
|
"bar.js": []byte("foo js"),
|
|
"a/foo.js": []byte("foo js"),
|
|
"a/foo.txt": []byte("foo txt"),
|
|
"b/foo.txt": []byte("foo b"),
|
|
"c/a.txt": []byte("b"),
|
|
"c/b.txt": []byte("b"),
|
|
"c/c.txt": []byte("b"),
|
|
})
|
|
|
|
srv := makeTestServer(t, fmt.Sprintf(`
|
|
directory: %s
|
|
permissions: CRUD
|
|
prefix: /prefix
|
|
|
|
users:
|
|
- username: basic
|
|
password: basic
|
|
rules:
|
|
- regex: "^.+.js$"
|
|
permissions: R
|
|
- path: "/b/"
|
|
permissions: R
|
|
- path: "/a/foo.txt"
|
|
permissions: none
|
|
- path: "/c/"
|
|
permissions: none
|
|
`, dir))
|
|
|
|
client := gowebdav.NewClient(srv.URL, "basic", "basic")
|
|
|
|
files, err := client.ReadDir("/prefix")
|
|
require.NoError(t, err)
|
|
require.Len(t, files, 5)
|
|
|
|
err = client.Write("/prefix/foo.txt", []byte("new"), 0666)
|
|
require.NoError(t, err)
|
|
|
|
err = client.Write("/prefix/new.txt", []byte("new"), 0666)
|
|
require.NoError(t, err)
|
|
|
|
err = client.Copy("/prefix/bar.js", "/prefix/b/bar.js", false)
|
|
require.ErrorContains(t, err, "403")
|
|
|
|
err = client.Copy("/prefix/bar.js", "/prefix/bar.jsx", false)
|
|
require.NoError(t, err)
|
|
|
|
err = client.Copy("/prefix/b/foo.txt", "/prefix/foo1.txt", false)
|
|
require.NoError(t, err)
|
|
|
|
err = client.Rename("/prefix/b/foo.txt", "/prefix/foo2.txt", false)
|
|
require.ErrorContains(t, err, "403")
|
|
|
|
_, err = client.Read("/prefix/a/foo.txt")
|
|
require.ErrorContains(t, err, "403")
|
|
|
|
err = client.Write("/prefix/a/foo.js", []byte("new"), 0666)
|
|
require.ErrorContains(t, err, "403")
|
|
|
|
err = client.Write("/prefix/b/foo.txt", []byte("new"), 0666)
|
|
require.ErrorContains(t, err, "403")
|
|
|
|
_, err = client.ReadDir("/prefix/c")
|
|
require.ErrorContains(t, err, "403")
|
|
|
|
_, err = client.Read("/prefix/c/a.txt")
|
|
require.ErrorContains(t, err, "403")
|
|
|
|
err = client.Write("/prefix/c/b.txt", []byte("new"), 0666)
|
|
require.ErrorContains(t, err, "403")
|
|
}
|
|
|
|
func TestServerPermissions(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
dir := makeTestDirectory(t, map[string][]byte{
|
|
"foo.txt": []byte("foo"),
|
|
"a/foo.txt": []byte("foo a"),
|
|
"b/foo.txt": []byte("foo b"),
|
|
})
|
|
|
|
srv := makeTestServer(t, fmt.Sprintf(`
|
|
directory: %s
|
|
permissions: CR
|
|
|
|
users:
|
|
- username: a
|
|
password: a
|
|
directory: %s/a
|
|
- username: b
|
|
password: b
|
|
directory: %s/b
|
|
permissions: R
|
|
`, dir, dir, dir))
|
|
|
|
t.Run("User A", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
client := gowebdav.NewClient(srv.URL, "a", "a")
|
|
|
|
files, err := client.ReadDir("/")
|
|
require.NoError(t, err)
|
|
require.Len(t, files, 1)
|
|
|
|
data, err := client.Read("/foo.txt")
|
|
require.NoError(t, err)
|
|
require.EqualValues(t, []byte("foo a"), data)
|
|
|
|
err = client.Copy("/foo.txt", "/copy.txt", false)
|
|
require.NoError(t, err)
|
|
|
|
err = client.Copy("/foo.txt", "/copy.txt", true)
|
|
require.ErrorContains(t, err, "403")
|
|
|
|
err = client.Rename("/foo.txt", "/copy.txt", true)
|
|
require.ErrorContains(t, err, "403")
|
|
|
|
data, err = client.Read("/copy.txt")
|
|
require.NoError(t, err)
|
|
require.EqualValues(t, []byte("foo a"), data)
|
|
})
|
|
|
|
t.Run("User B", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
client := gowebdav.NewClient(srv.URL, "b", "b")
|
|
|
|
files, err := client.ReadDir("/")
|
|
require.NoError(t, err)
|
|
require.Len(t, files, 1)
|
|
|
|
data, err := client.Read("/foo.txt")
|
|
require.NoError(t, err)
|
|
require.EqualValues(t, []byte("foo b"), data)
|
|
|
|
err = client.Copy("/foo.txt", "/copy.txt", false)
|
|
require.ErrorContains(t, err, "403")
|
|
})
|
|
}
|