package service import ( "context" "io/fs" "net/url" "path" "strings" "syscall" "git.sr.ht/~gabrielgio/img/pkg/database/repository" "git.sr.ht/~gabrielgio/img/pkg/list" ) type ( FileSystemController struct { fsRepository repository.FileSystemRepository userRepository repository.UserRepository } DirectoryParam struct { Name string UrlEncodedPath string } FileParam struct { UrlEncodedPath string Info fs.FileInfo } Page struct { History []*DirectoryParam Files []*FileParam } ) func (f *FileParam) GetUid() int { if stat, ok := f.Info.Sys().(*syscall.Stat_t); ok { return int(stat.Uid) } return 0 } func (f *FileParam) GetGid() int { if stat, ok := f.Info.Sys().(*syscall.Stat_t); ok { return int(stat.Gid) } return 0 } func NewFileSystemController( fsRepository repository.FileSystemRepository, userRepository repository.UserRepository, ) *FileSystemController { return &FileSystemController{ fsRepository: fsRepository, userRepository: userRepository, } } func getHistory(filepath string) []*DirectoryParam { var ( paths = strings.Split(filepath, "/") result = make([]*DirectoryParam, 0, len(paths)) acc = "" ) // add root folder result = append(result, &DirectoryParam{ Name: "...", UrlEncodedPath: "", }) if len(paths) == 1 && paths[0] == "" { return result } for _, p := range paths { acc = path.Join(acc, p) result = append(result, &DirectoryParam{ Name: p, UrlEncodedPath: url.QueryEscape(acc), }) } return result } func (f *FileSystemController) GetFullpath(ctx context.Context, userID uint, filepath string) (string, error) { userPath, err := f.userRepository.GetPathFromUserID(ctx, userID) if err != nil { return "", err } return path.Join(userPath, filepath), nil } func (f *FileSystemController) IsFile(ctx context.Context, fullPath string) (bool, error) { inf, err := f.fsRepository.Stat(fullPath) if err != nil { return false, err } return !inf.IsDir(), nil } func (f *FileSystemController) GetPage(ctx context.Context, filename string, fullPath string) (*Page, error) { files, err := f.fsRepository.List(fullPath) if err != nil { return nil, err } params := list.Map(files, func(info fs.FileInfo) *FileParam { fullPath := path.Join(filename, info.Name()) scapedFullPath := url.QueryEscape(fullPath) return &FileParam{ Info: info, UrlEncodedPath: scapedFullPath, } }) return &Page{ Files: params, History: getHistory(filename), }, nil }