diff --git a/backend/benchmark_results.txt b/backend/benchmark_results.txt index 5c7697d9..029e0805 100644 --- a/backend/benchmark_results.txt +++ b/backend/benchmark_results.txt @@ -5,33 +5,45 @@ ? github.com/gtsteffaniak/filebrowser/auth [no test files] ? github.com/gtsteffaniak/filebrowser/cmd [no test files] PASS -ok github.com/gtsteffaniak/filebrowser/diskcache 0.003s +ok github.com/gtsteffaniak/filebrowser/diskcache 0.004s ? github.com/gtsteffaniak/filebrowser/errors [no test files] ? github.com/gtsteffaniak/filebrowser/files [no test files] PASS ok github.com/gtsteffaniak/filebrowser/fileutils 0.003s -2023/09/24 12:52:05 h: 401 -2023/09/24 12:52:05 h: 401 -2023/09/24 12:52:05 h: 401 -2023/09/24 12:52:05 h: 401 -2023/09/24 12:52:05 h: 401 -2023/09/24 12:52:05 h: 401 +2023/10/18 10:19:52 Saving new user: username +2023/10/18 10:19:52 Saving new user: username +2023/10/18 10:19:52 Saving new user: username +2023/10/18 10:19:52 Saving new user: username +2023/10/18 10:19:52 Saving new user: username +2023/10/18 10:19:52 Saving new user: username +2023/10/18 10:19:52 Saving new user: username +2023/10/18 10:19:52 Saving new user: username +2023/10/18 10:19:52 h: 401 +2023/10/18 10:19:52 h: 401 +2023/10/18 10:19:52 h: 401 +2023/10/18 10:19:52 h: 401 +2023/10/18 10:19:52 Saving new user: username +2023/10/18 10:19:52 Saving new user: username +2023/10/18 10:19:52 Saving new user: username +2023/10/18 10:19:52 Saving new user: username +2023/10/18 10:19:53 h: 401 +2023/10/18 10:19:53 h: 401 PASS -ok github.com/gtsteffaniak/filebrowser/http 0.094s +ok github.com/gtsteffaniak/filebrowser/http 0.208s PASS -ok github.com/gtsteffaniak/filebrowser/img 0.144s +ok github.com/gtsteffaniak/filebrowser/img 0.124s +goos: linux +goarch: amd64 +pkg: github.com/gtsteffaniak/filebrowser/index +cpu: 11th Gen Intel(R) Core(TM) i5-11320H @ 3.20GHz +BenchmarkFillIndex-8 10 3239196 ns/op 11289 B/op 448 allocs/op +BenchmarkSearchAllIndexes-8 10 6645964 ns/op 3176834 B/op 59104 allocs/op +PASS +ok github.com/gtsteffaniak/filebrowser/index 0.126s PASS ok github.com/gtsteffaniak/filebrowser/rules 0.002s PASS ok github.com/gtsteffaniak/filebrowser/runner 0.003s -goos: linux -goarch: amd64 -pkg: github.com/gtsteffaniak/filebrowser/search -cpu: 11th Gen Intel(R) Core(TM) i5-11320H @ 3.20GHz -BenchmarkSearchAllIndexes-8 10 5912685 ns/op 3003976 B/op 46139 allocs/op -BenchmarkFillIndex-8 10 3157995 ns/op 18370 B/op 449 allocs/op -PASS -ok github.com/gtsteffaniak/filebrowser/search 0.116s PASS ok github.com/gtsteffaniak/filebrowser/settings 0.005s ? github.com/gtsteffaniak/filebrowser/share [no test files] diff --git a/backend/http/search.go b/backend/http/search.go index 3ce8cc33..08908fbf 100644 --- a/backend/http/search.go +++ b/backend/http/search.go @@ -2,6 +2,7 @@ package http import ( "net/http" + "strings" "github.com/gtsteffaniak/filebrowser/index" ) @@ -11,8 +12,11 @@ var searchHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *dat query := r.URL.Query().Get("query") // Retrieve the User-Agent and X-Auth headers from the request sessionId := r.Header.Get("SessionId") + userScope := r.Header.Get("UserScope") index := *index.GetIndex() - results, fileTypes := index.Search(query, r.URL.Path, sessionId) + combinedScope := strings.TrimPrefix(userScope+r.URL.Path, ".") + combinedScope = strings.TrimPrefix(combinedScope, "/") + results, fileTypes := index.Search(query, combinedScope, sessionId) for _, path := range results { responseObj := map[string]interface{}{ "path": path, diff --git a/backend/index/conditions.go b/backend/index/conditions.go index 61c174c7..ed7a3cae 100644 --- a/backend/index/conditions.go +++ b/backend/index/conditions.go @@ -8,7 +8,14 @@ import ( ) var typeRegexp = regexp.MustCompile(`type:(\S+)`) - +var AllFiletypeOptions = []string{ + "image", + "audio", + "archive", + "video", + "doc", + "dir", +} var documentTypes = []string{ ".word", ".pdf", diff --git a/backend/index/search_index.go b/backend/index/search_index.go index d3ace10e..65a0942b 100644 --- a/backend/index/search_index.go +++ b/backend/index/search_index.go @@ -18,13 +18,18 @@ var ( ) func (si *Index) Search(search string, scope string, sourceSession string) ([]string, map[string]map[string]bool) { + if scope == "" { + scope = "/" + } + fileTypes := map[string]bool{} + runningHash := generateRandomHash(4) sessionInProgress.Store(sourceSession, runningHash) // Store the value in the sync.Map searchOptions := ParseSearch(search) mutex.RLock() defer mutex.RUnlock() fileListTypes := make(map[string]map[string]bool) - var matching []string + matching := []string{} for _, searchTerm := range searchOptions.Terms { if searchTerm == "" { continue @@ -42,7 +47,6 @@ func (si *Index) Search(search string, scope string, sourceSession string) ([]st case "Files": paths = si.Files } - for _, path := range paths { value, found := sessionInProgress.Load(sourceSession) if !found || value != runningHash { @@ -55,7 +59,8 @@ func (si *Index) Search(search string, scope string, sourceSession string) ([]st if pathName == "" { continue } - matches, fileType := containsSearchTerm(path, searchTerm, *searchOptions, isDir) + + matches, fileType := containsSearchTerm(path, searchTerm, *searchOptions, isDir, fileTypes) if !matches { continue } @@ -80,24 +85,16 @@ func (si *Index) Search(search string, scope string, sourceSession string) ([]st func scopedPathNameFilter(pathName string, scope string) string { scope = strings.TrimPrefix(scope, "/") + pathName = strings.TrimPrefix(pathName, "/") if strings.HasPrefix(pathName, scope) { - pathName = strings.TrimPrefix(pathName, scope) + pathName = "/" + strings.TrimPrefix(pathName, scope) } else { pathName = "" } return pathName } -var fileTypes = map[string]bool{ - "audio": false, - "image": false, - "video": false, - "doc": false, - "archive": false, - "dir": false, -} - -func containsSearchTerm(pathName string, searchTerm string, options SearchOptions, isDir bool) (bool, map[string]bool) { +func containsSearchTerm(pathName string, searchTerm string, options SearchOptions, isDir bool, fileTypes map[string]bool) (bool, map[string]bool) { conditions := options.Conditions path := getLastPathComponent(pathName) // Convert to lowercase once @@ -110,11 +107,12 @@ func containsSearchTerm(pathName string, searchTerm string, options SearchOption var fileSize int64 matchesAllConditions := true extension := filepath.Ext(path) - for k := range fileTypes { - fileTypes[k] = IsMatchingType(extension, k) + for _, k := range AllFiletypeOptions { + if IsMatchingType(extension, k) { + fileTypes[k] = true + } } fileTypes["dir"] = isDir - for t, v := range conditions { if t == "exact" { continue diff --git a/backend/index/search_index_test.go b/backend/index/search_index_test.go index 1069a264..19df1c02 100644 --- a/backend/index/search_index_test.go +++ b/backend/index/search_index_test.go @@ -3,6 +3,8 @@ package index import ( "reflect" "testing" + + "github.com/stretchr/testify/assert" ) func BenchmarkSearchAllIndexes(b *testing.B) { @@ -75,27 +77,74 @@ func TestParseSearch(t *testing.T) { } func TestSearchIndexes(t *testing.T) { - type args struct { - search string - scope string - sourceSession string + indexes = Index{ + Dirs: []string{ + "/test", + "/test/path", + "/new/test/path", + }, + Files: []string{ + "/test/path/file.txt", + "/test/audio1.wav", + "/new/test/audio.wav", + "/new/test/video.mp4", + "/new/test/video.MP4", + "/new/test/path/archive.zip", + }, } tests := []struct { - name string - args args - want []string - want1 map[string]map[string]bool + search string + scope string + expectedResult []string + expectedTypes map[string]map[string]bool }{ - // TODO: Add test cases. + { + search: "audio", + scope: "/new/", + expectedResult: []string{"/test/audio.wav"}, + expectedTypes: map[string]map[string]bool{ + "/test/audio.wav": map[string]bool{"audio": true, "dir": false}, + }, + }, + { + search: "test", + scope: "/", + expectedResult: []string{"/test"}, + expectedTypes: map[string]map[string]bool{ + "/test/": map[string]bool{"dir": true}, + }, + }, + { + search: "archive", + scope: "/", + expectedResult: []string{"/new/test/path/archive.zip"}, + expectedTypes: map[string]map[string]bool{ + "/new/test/path/archive.zip": map[string]bool{"archive": true, "dir": false}, + }, + }, + { + search: "video", + scope: "/", + expectedResult: []string{ + "/new/test/video.mp4", + "/new/test/video.MP4", + }, + expectedTypes: map[string]map[string]bool{ + "/new/test/video.MP4": map[string]bool{"video": true, "dir": false}, + "/new/test/video.mp4": map[string]bool{"video": true, "dir": false}, + }, + }, } for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, got1 := indexes.Search(tt.args.search, tt.args.scope, tt.args.sourceSession) - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("SearchAllIndexes() got = %v, want %v", got, tt.want) - } - if !reflect.DeepEqual(got1, tt.want1) { - t.Errorf("SearchAllIndexes() got1 = %v, want %v", got1, tt.want1) + t.Run(tt.search, func(t *testing.T) { + actualResult, actualTypes := indexes.Search(tt.search, tt.scope, "") + assert.Equal(t, tt.expectedResult, actualResult) + if len(tt.expectedTypes) > 0 { + for key, value := range tt.expectedTypes { + actualValue, exists := actualTypes[key] + assert.True(t, exists, "Expected type key '%s' not found in actual types", key) + assert.Equal(t, value, actualValue, "Type value mismatch for key '%s'", key) + } } }) } @@ -122,34 +171,6 @@ func Test_scopedPathNameFilter(t *testing.T) { } } -func Test_containsSearchTerm(t *testing.T) { - type args struct { - pathName string - searchTerm string - options SearchOptions - isDir bool - } - tests := []struct { - name string - args args - want bool - want1 map[string]bool - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, got1 := containsSearchTerm(tt.args.pathName, tt.args.searchTerm, tt.args.options, tt.args.isDir) - if got != tt.want { - t.Errorf("containsSearchTerm() got = %v, want %v", got, tt.want) - } - if !reflect.DeepEqual(got1, tt.want1) { - t.Errorf("containsSearchTerm() got1 = %v, want %v", got1, tt.want1) - } - }) - } -} - func Test_isDoc(t *testing.T) { type args struct { extension string diff --git a/frontend/src/api/utils.js b/frontend/src/api/utils.js index 63debcd5..226cb454 100644 --- a/frontend/src/api/utils.js +++ b/frontend/src/api/utils.js @@ -15,6 +15,7 @@ export async function fetchURL(url, opts, auth = true) { headers: { "X-Auth": store.state.jwt, "sessionId": store.state.sessionId, + "userScope": store.state.user.scope, ...headers, }, ...rest,