From 54d7373b7cb2217908eec06356538b9a990f4cff Mon Sep 17 00:00:00 2001 From: Erik Berlin Date: Sun, 11 Feb 2024 10:27:07 +0200 Subject: [PATCH] add changes for read from 2 paths --- cmd/config.go | 1 - cmd/config_init.go | 11 +- cmd/config_set.go | 2 - cmd/root.go | 5 + files/file.go | 137 ++++++-- fileutils/file.go | 6 +- frontend/package-lock.json | 8 +- frontend/package.json | 2 +- frontend/public/index.html | 2 - frontend/src/components/Shell.vue | 2 +- frontend/src/components/files/ListingItem.vue | 9 +- frontend/src/components/prompts/Copy.vue | 4 +- frontend/src/components/prompts/Info.vue | 9 +- frontend/src/components/prompts/Move.vue | 4 +- frontend/src/components/prompts/Prompts.vue | 15 +- frontend/src/components/prompts/Share.vue | 2 +- frontend/src/css/dashboard.css | 4 - frontend/src/i18n/en.json | 6 +- frontend/src/i18n/he.json | 22 +- frontend/src/i18n/ja.json | 312 ++++++++---------- frontend/src/store/mutations.js | 2 +- frontend/src/views/Share.vue | 2 +- frontend/src/views/files/Editor.vue | 16 +- frontend/src/views/settings/Shares.vue | 2 +- go.mod | 2 + healthcheck.sh | 4 +- http/resource.go | 110 +++--- settings/settings.go | 1 + 28 files changed, 380 insertions(+), 322 deletions(-) diff --git a/cmd/config.go b/cmd/config.go index 5c7efbba..ed3cc772 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -31,7 +31,6 @@ func addConfigFlags(flags *pflag.FlagSet) { addServerFlags(flags) addUserFlags(flags) flags.BoolP("signup", "s", false, "allow users to signup") - flags.Bool("create-user-dir", false, "generate user's home directory automatically") flags.String("shell", "", "shell command to which other commands should be appended") flags.String("auth.method", string(auth.MethodJSONAuth), "authentication type") diff --git a/cmd/config_init.go b/cmd/config_init.go index 611e6c50..7d183368 100644 --- a/cmd/config_init.go +++ b/cmd/config_init.go @@ -29,12 +29,11 @@ override the options.`, authMethod, auther := getAuthentication(flags) s := &settings.Settings{ - Key: generateKey(), - Signup: mustGetBool(flags, "signup"), - CreateUserDir: mustGetBool(flags, "create-user-dir"), - Shell: convertCmdStrToCmdArray(mustGetString(flags, "shell")), - AuthMethod: authMethod, - Defaults: defaults, + Key: generateKey(), + Signup: mustGetBool(flags, "signup"), + Shell: convertCmdStrToCmdArray(mustGetString(flags, "shell")), + AuthMethod: authMethod, + Defaults: defaults, Branding: settings.Branding{ Name: mustGetString(flags, "branding.name"), DisableExternal: mustGetBool(flags, "branding.disableExternal"), diff --git a/cmd/config_set.go b/cmd/config_set.go index 9dbea9dc..ba800adb 100644 --- a/cmd/config_set.go +++ b/cmd/config_set.go @@ -49,8 +49,6 @@ you want to change. Other options will remain unchanged.`, hasAuth = true case "shell": set.Shell = convertCmdStrToCmdArray(mustGetString(flags, flag.Name)) - case "create-user-dir": - set.CreateUserDir = mustGetBool(flags, flag.Name) case "branding.name": set.Branding.Name = mustGetString(flags, flag.Name) case "branding.color": diff --git a/cmd/root.go b/cmd/root.go index 7ec4d441..5f2b6738 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -60,6 +60,7 @@ func addServerFlags(flags *pflag.FlagSet) { flags.StringP("cert", "t", "", "tls certificate") flags.StringP("key", "k", "", "tls key") flags.StringP("root", "r", ".", "root to prepend to relative paths") + flags.StringP("anotherPath", "R", "", "another path to use") flags.String("socket", "", "socket to listen to (cannot be used with address, port, cert nor key flags)") flags.Uint32("socket-perm", 0666, "unix socket file permissions") //nolint:gomnd flags.StringP("baseurl", "b", "", "base url") @@ -205,6 +206,10 @@ func getRunParams(flags *pflag.FlagSet, st *storage.Storage) *settings.Server { server.Root = val } + if val, set := getParamB(flags, "anotherPath"); set { + server.AnotherPath = val + } + if val, set := getParamB(flags, "baseurl"); set { server.BaseURL = val } diff --git a/files/file.go b/files/file.go index 4d7c8f9f..e63cbef1 100644 --- a/files/file.go +++ b/files/file.go @@ -16,15 +16,15 @@ import ( "path" "path/filepath" "strings" + "sync" "time" - "github.com/spf13/afero" - "github.com/filebrowser/filebrowser/v2/errors" "github.com/filebrowser/filebrowser/v2/rules" + "github.com/spf13/afero" ) -const PermFile = 0644 +const PermFile = 0664 const PermDir = 0755 // FileInfo describes a file. @@ -50,14 +50,17 @@ type FileInfo struct { // FileOptions are the options when getting a file info. type FileOptions struct { - Fs afero.Fs - Path string - Modify bool - Expand bool - ReadHeader bool - Token string - Checker rules.Checker - Content bool + Fs afero.Fs + Path string + Modify bool + Expand bool + ReadHeader bool + FolderSize bool + Token string + Checker rules.Checker + Content bool + RootPath string + AnotherPath string } type ImageResolution struct { @@ -65,10 +68,25 @@ type ImageResolution struct { Height int `json:"height"` } +// function that checks if given full path exists or not +// it helps to determine to which NFS we need to go IDC or KFS +func CheckIfExistsInPath(pathToCheck string) bool { + _, pathExistsErr := os.Stat(pathToCheck) + return !os.IsNotExist(pathExistsErr) +} + // NewFileInfo creates a File object from a path and a given user. This File // object will be automatically filled depending on if it is a directory // or a file. If it's a video file, it will also detect any subtitles. func NewFileInfo(opts FileOptions) (*FileInfo, error) { + log.Printf("ROOT PATH - %v:", opts.RootPath) + log.Printf("ANOTHER PATH - %v:", opts.AnotherPath) + rootFilePath := opts.RootPath + opts.Path + if !CheckIfExistsInPath(rootFilePath) { + opts.Fs = afero.NewBasePathFs(afero.NewOsFs(), opts.AnotherPath) + } else { + opts.Fs = afero.NewBasePathFs(afero.NewOsFs(), opts.RootPath) + } if !opts.Checker.Check(opts.Path) { return nil, os.ErrPermission } @@ -77,10 +95,16 @@ func NewFileInfo(opts FileOptions) (*FileInfo, error) { if err != nil { return nil, err } - + if file.IsDir && opts.FolderSize { + size, err := getFolderSize(file.RealPath()) + if err != nil { + return nil, err + } + file.Size = size + } if opts.Expand { if file.IsDir { - if err := file.readListing(opts.Checker, opts.ReadHeader); err != nil { //nolint:govet + if err := file.readListing(opts.Checker, opts.ReadHeader, opts.RootPath, opts.AnotherPath); err != nil { //nolint:govet return nil, err } return file, nil @@ -95,12 +119,31 @@ func NewFileInfo(opts FileOptions) (*FileInfo, error) { return file, err } +func getFolderSize(path string) (int64, error) { + var size int64 + err := filepath.WalkDir(path, func(_ string, d os.DirEntry, err error) error { + if err != nil { + return err + } + if !d.IsDir() { + info, err := d.Info() + if err != nil { + return err + } + size += info.Size() + } + return err + }) + return size, err +} + func stat(opts FileOptions) (*FileInfo, error) { var file *FileInfo if lstaterFs, ok := opts.Fs.(afero.Lstater); ok { info, _, err := lstaterFs.LstatIfPossible(opts.Path) if err != nil { + log.Printf("stat current path error - %v:", err) return nil, err } file = &FileInfo{ @@ -349,11 +392,60 @@ func (i *FileInfo) detectSubtitles() { } } -func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error { - afs := &afero.Afero{Fs: i.Fs} - dir, err := afs.ReadDir(i.Path) +// async read dir and append the data to given FileInfo slice +func readDirAsync(fs afero.Fs, fullPath string, wg *sync.WaitGroup, resultSlice *[]os.FileInfo) { + defer wg.Done() + + dir, err := afero.ReadDir(fs, fullPath) if err != nil { - return err + log.Printf("Error reading directory: %v", err) + return + } + + // Append the result to the slice + *resultSlice = append(*resultSlice, dir...) +} + +func (i *FileInfo) readListing(checker rules.Checker, readHeader bool, rootPath, anotherPath string) error { + var wg sync.WaitGroup + var rootDir []os.FileInfo + var anotherDir []os.FileInfo + var finalDir []os.FileInfo + useAnotherDir := false + anotherFullPath := anotherPath + i.Path + rootFullPath := rootPath + i.Path + existsInRootPath := CheckIfExistsInPath(rootFullPath) + existsInAnotherPath := CheckIfExistsInPath(anotherFullPath) + log.Printf("%v %v %v %v", anotherFullPath, existsInAnotherPath, rootFullPath, existsInRootPath) + // if we aren't in home scenario use idcSite only because we are messing with opth.Path + // in some cases it can go to KFS site instead of going to IDC, so just to be sure... + if existsInRootPath && existsInAnotherPath && i.Path != "/" { + useAnotherDir = true + } + if existsInRootPath && !useAnotherDir { + wg.Add(1) + go readDirAsync(afero.NewOsFs(), rootFullPath, &wg, &rootDir) + } + if existsInAnotherPath { + wg.Add(1) + go readDirAsync(afero.NewOsFs(), anotherFullPath, &wg, &anotherDir) + } + + // Wait for all goroutines to finish + wg.Wait() + + if len(rootDir) > 0 && len(anotherDir) > 0 { + log.Printf("combining results") + finalDir = append(rootDir, anotherDir...) + } else if len(rootDir) > 0 { + finalDir = rootDir + } else { + finalDir = anotherDir + } + + //in case of somehow the path exists in both paths due to some mess with opts.path use idc site + if useAnotherDir { + finalDir = anotherDir } listing := &Listing{ @@ -362,14 +454,12 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error { NumFiles: 0, } - for _, f := range dir { + for _, f := range finalDir { name := f.Name() fPath := path.Join(i.Path, name) - if !checker.Check(fPath) { continue } - isSymlink, isInvalidLink := false, false if IsSymlink(f.Mode()) { isSymlink = true @@ -382,7 +472,6 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error { isInvalidLink = true } } - file := &FileInfo{ Fs: i.Fs, Name: name, @@ -393,9 +482,8 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error { IsSymlink: isSymlink, Extension: filepath.Ext(name), Path: fPath, - currentDir: dir, + currentDir: finalDir, } - if !file.IsDir && strings.HasPrefix(mime.TypeByExtension(file.Extension), "image/") { resolution, err := calculateImageResolution(file.Fs, file.Path) if err != nil { @@ -404,7 +492,6 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error { file.Resolution = resolution } } - if file.IsDir { listing.NumDirs++ } else { @@ -419,10 +506,8 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error { } } } - listing.Items = append(listing.Items, file) } - i.Listing = listing return nil } diff --git a/fileutils/file.go b/fileutils/file.go index fdf11225..81aeffeb 100644 --- a/fileutils/file.go +++ b/fileutils/file.go @@ -7,8 +7,6 @@ import ( "path/filepath" "github.com/spf13/afero" - - "github.com/filebrowser/filebrowser/v2/files" ) // MoveFile moves file from src to dst. @@ -42,13 +40,13 @@ func CopyFile(fs afero.Fs, source, dest string) error { // Makes the directory needed to create the dst // file. - err = fs.MkdirAll(filepath.Dir(dest), files.PermDir) + err = fs.MkdirAll(filepath.Dir(dest), 0666) //nolint:gomnd if err != nil { return err } // Create the destination file. - dst, err := fs.OpenFile(dest, os.O_RDWR|os.O_CREATE|os.O_TRUNC, files.PermFile) + dst, err := fs.OpenFile(dest, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0775) //nolint:gomnd if err != nil { return err } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 0b3ec184..d898e595 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -46,7 +46,7 @@ "postcss": "^8.4.31", "prettier": "^3.0.1", "terser": "^5.19.2", - "vite": "^4.5.2", + "vite": "^4.4.12", "vite-plugin-compression2": "^0.10.3", "vite-plugin-rewrite-all": "^1.0.1" } @@ -5663,9 +5663,9 @@ "dev": true }, "node_modules/vite": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz", - "integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==", + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.12.tgz", + "integrity": "sha512-KtPlUbWfxzGVul8Nut8Gw2Qe8sBzWY+8QVc5SL8iRFnpnrcoCaNlzO40c1R6hPmcdTwIPEDkq0Y9+27a5tVbdQ==", "dev": true, "dependencies": { "esbuild": "^0.18.10", diff --git a/frontend/package.json b/frontend/package.json index b0ff7612..4449a5f5 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -52,7 +52,7 @@ "postcss": "^8.4.31", "prettier": "^3.0.1", "terser": "^5.19.2", - "vite": "^4.5.2", + "vite": "^4.4.12", "vite-plugin-compression2": "^0.10.3", "vite-plugin-rewrite-all": "^1.0.1" }, diff --git a/frontend/public/index.html b/frontend/public/index.html index 530da7cf..39d926d8 100644 --- a/frontend/public/index.html +++ b/frontend/public/index.html @@ -16,8 +16,6 @@ [{[ if .Name -]}][{[ .Name ]}][{[ else ]}]File Browser[{[ end ]}] - -