V0.2.1 - search scope bugfix (#56)
Co-authored-by: Graham Steffaniak <graham.steffaniak@autodesk.com>
This commit is contained in:
parent
4bab354c99
commit
47e1975c12
|
@ -5,33 +5,45 @@
|
||||||
? github.com/gtsteffaniak/filebrowser/auth [no test files]
|
? github.com/gtsteffaniak/filebrowser/auth [no test files]
|
||||||
? github.com/gtsteffaniak/filebrowser/cmd [no test files]
|
? github.com/gtsteffaniak/filebrowser/cmd [no test files]
|
||||||
PASS
|
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/errors [no test files]
|
||||||
? github.com/gtsteffaniak/filebrowser/files [no test files]
|
? github.com/gtsteffaniak/filebrowser/files [no test files]
|
||||||
PASS
|
PASS
|
||||||
ok github.com/gtsteffaniak/filebrowser/fileutils 0.003s
|
ok github.com/gtsteffaniak/filebrowser/fileutils 0.003s
|
||||||
2023/09/24 12:52:05 h: 401 <nil>
|
2023/10/18 10:19:52 Saving new user: username
|
||||||
2023/09/24 12:52:05 h: 401 <nil>
|
2023/10/18 10:19:52 Saving new user: username
|
||||||
2023/09/24 12:52:05 h: 401 <nil>
|
2023/10/18 10:19:52 Saving new user: username
|
||||||
2023/09/24 12:52:05 h: 401 <nil>
|
2023/10/18 10:19:52 Saving new user: username
|
||||||
2023/09/24 12:52:05 h: 401 <nil>
|
2023/10/18 10:19:52 Saving new user: username
|
||||||
2023/09/24 12:52:05 h: 401 <nil>
|
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 <nil>
|
||||||
|
2023/10/18 10:19:52 h: 401 <nil>
|
||||||
|
2023/10/18 10:19:52 h: 401 <nil>
|
||||||
|
2023/10/18 10:19:52 h: 401 <nil>
|
||||||
|
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 <nil>
|
||||||
|
2023/10/18 10:19:53 h: 401 <nil>
|
||||||
PASS
|
PASS
|
||||||
ok github.com/gtsteffaniak/filebrowser/http 0.094s
|
ok github.com/gtsteffaniak/filebrowser/http 0.208s
|
||||||
PASS
|
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
|
PASS
|
||||||
ok github.com/gtsteffaniak/filebrowser/rules 0.002s
|
ok github.com/gtsteffaniak/filebrowser/rules 0.002s
|
||||||
PASS
|
PASS
|
||||||
ok github.com/gtsteffaniak/filebrowser/runner 0.003s
|
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
|
PASS
|
||||||
ok github.com/gtsteffaniak/filebrowser/settings 0.005s
|
ok github.com/gtsteffaniak/filebrowser/settings 0.005s
|
||||||
? github.com/gtsteffaniak/filebrowser/share [no test files]
|
? github.com/gtsteffaniak/filebrowser/share [no test files]
|
||||||
|
|
|
@ -2,6 +2,7 @@ package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/gtsteffaniak/filebrowser/index"
|
"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")
|
query := r.URL.Query().Get("query")
|
||||||
// Retrieve the User-Agent and X-Auth headers from the request
|
// Retrieve the User-Agent and X-Auth headers from the request
|
||||||
sessionId := r.Header.Get("SessionId")
|
sessionId := r.Header.Get("SessionId")
|
||||||
|
userScope := r.Header.Get("UserScope")
|
||||||
index := *index.GetIndex()
|
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 {
|
for _, path := range results {
|
||||||
responseObj := map[string]interface{}{
|
responseObj := map[string]interface{}{
|
||||||
"path": path,
|
"path": path,
|
||||||
|
|
|
@ -8,7 +8,14 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var typeRegexp = regexp.MustCompile(`type:(\S+)`)
|
var typeRegexp = regexp.MustCompile(`type:(\S+)`)
|
||||||
|
var AllFiletypeOptions = []string{
|
||||||
|
"image",
|
||||||
|
"audio",
|
||||||
|
"archive",
|
||||||
|
"video",
|
||||||
|
"doc",
|
||||||
|
"dir",
|
||||||
|
}
|
||||||
var documentTypes = []string{
|
var documentTypes = []string{
|
||||||
".word",
|
".word",
|
||||||
".pdf",
|
".pdf",
|
||||||
|
|
|
@ -18,13 +18,18 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (si *Index) Search(search string, scope string, sourceSession string) ([]string, map[string]map[string]bool) {
|
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)
|
runningHash := generateRandomHash(4)
|
||||||
sessionInProgress.Store(sourceSession, runningHash) // Store the value in the sync.Map
|
sessionInProgress.Store(sourceSession, runningHash) // Store the value in the sync.Map
|
||||||
searchOptions := ParseSearch(search)
|
searchOptions := ParseSearch(search)
|
||||||
mutex.RLock()
|
mutex.RLock()
|
||||||
defer mutex.RUnlock()
|
defer mutex.RUnlock()
|
||||||
fileListTypes := make(map[string]map[string]bool)
|
fileListTypes := make(map[string]map[string]bool)
|
||||||
var matching []string
|
matching := []string{}
|
||||||
for _, searchTerm := range searchOptions.Terms {
|
for _, searchTerm := range searchOptions.Terms {
|
||||||
if searchTerm == "" {
|
if searchTerm == "" {
|
||||||
continue
|
continue
|
||||||
|
@ -42,7 +47,6 @@ func (si *Index) Search(search string, scope string, sourceSession string) ([]st
|
||||||
case "Files":
|
case "Files":
|
||||||
paths = si.Files
|
paths = si.Files
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
value, found := sessionInProgress.Load(sourceSession)
|
value, found := sessionInProgress.Load(sourceSession)
|
||||||
if !found || value != runningHash {
|
if !found || value != runningHash {
|
||||||
|
@ -55,7 +59,8 @@ func (si *Index) Search(search string, scope string, sourceSession string) ([]st
|
||||||
if pathName == "" {
|
if pathName == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
matches, fileType := containsSearchTerm(path, searchTerm, *searchOptions, isDir)
|
|
||||||
|
matches, fileType := containsSearchTerm(path, searchTerm, *searchOptions, isDir, fileTypes)
|
||||||
if !matches {
|
if !matches {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -80,24 +85,16 @@ func (si *Index) Search(search string, scope string, sourceSession string) ([]st
|
||||||
|
|
||||||
func scopedPathNameFilter(pathName string, scope string) string {
|
func scopedPathNameFilter(pathName string, scope string) string {
|
||||||
scope = strings.TrimPrefix(scope, "/")
|
scope = strings.TrimPrefix(scope, "/")
|
||||||
|
pathName = strings.TrimPrefix(pathName, "/")
|
||||||
if strings.HasPrefix(pathName, scope) {
|
if strings.HasPrefix(pathName, scope) {
|
||||||
pathName = strings.TrimPrefix(pathName, scope)
|
pathName = "/" + strings.TrimPrefix(pathName, scope)
|
||||||
} else {
|
} else {
|
||||||
pathName = ""
|
pathName = ""
|
||||||
}
|
}
|
||||||
return pathName
|
return pathName
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileTypes = map[string]bool{
|
func containsSearchTerm(pathName string, searchTerm string, options SearchOptions, isDir bool, fileTypes map[string]bool) (bool, 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) {
|
|
||||||
conditions := options.Conditions
|
conditions := options.Conditions
|
||||||
path := getLastPathComponent(pathName)
|
path := getLastPathComponent(pathName)
|
||||||
// Convert to lowercase once
|
// Convert to lowercase once
|
||||||
|
@ -110,11 +107,12 @@ func containsSearchTerm(pathName string, searchTerm string, options SearchOption
|
||||||
var fileSize int64
|
var fileSize int64
|
||||||
matchesAllConditions := true
|
matchesAllConditions := true
|
||||||
extension := filepath.Ext(path)
|
extension := filepath.Ext(path)
|
||||||
for k := range fileTypes {
|
for _, k := range AllFiletypeOptions {
|
||||||
fileTypes[k] = IsMatchingType(extension, k)
|
if IsMatchingType(extension, k) {
|
||||||
|
fileTypes[k] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fileTypes["dir"] = isDir
|
fileTypes["dir"] = isDir
|
||||||
|
|
||||||
for t, v := range conditions {
|
for t, v := range conditions {
|
||||||
if t == "exact" {
|
if t == "exact" {
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -3,6 +3,8 @@ package index
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BenchmarkSearchAllIndexes(b *testing.B) {
|
func BenchmarkSearchAllIndexes(b *testing.B) {
|
||||||
|
@ -75,27 +77,74 @@ func TestParseSearch(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSearchIndexes(t *testing.T) {
|
func TestSearchIndexes(t *testing.T) {
|
||||||
type args struct {
|
indexes = Index{
|
||||||
search string
|
Dirs: []string{
|
||||||
scope string
|
"/test",
|
||||||
sourceSession string
|
"/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 {
|
tests := []struct {
|
||||||
name string
|
search string
|
||||||
args args
|
scope string
|
||||||
want []string
|
expectedResult []string
|
||||||
want1 map[string]map[string]bool
|
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 {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.search, func(t *testing.T) {
|
||||||
got, got1 := indexes.Search(tt.args.search, tt.args.scope, tt.args.sourceSession)
|
actualResult, actualTypes := indexes.Search(tt.search, tt.scope, "")
|
||||||
if !reflect.DeepEqual(got, tt.want) {
|
assert.Equal(t, tt.expectedResult, actualResult)
|
||||||
t.Errorf("SearchAllIndexes() got = %v, want %v", got, tt.want)
|
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)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(got1, tt.want1) {
|
|
||||||
t.Errorf("SearchAllIndexes() got1 = %v, want %v", got1, tt.want1)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
func Test_isDoc(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
extension string
|
extension string
|
||||||
|
|
|
@ -15,6 +15,7 @@ export async function fetchURL(url, opts, auth = true) {
|
||||||
headers: {
|
headers: {
|
||||||
"X-Auth": store.state.jwt,
|
"X-Auth": store.state.jwt,
|
||||||
"sessionId": store.state.sessionId,
|
"sessionId": store.state.sessionId,
|
||||||
|
"userScope": store.state.user.scope,
|
||||||
...headers,
|
...headers,
|
||||||
},
|
},
|
||||||
...rest,
|
...rest,
|
||||||
|
|
Loading…
Reference in New Issue