1package service
2
3import (
4 "context"
5 "io/fs"
6 "net/url"
7 "path"
8 "strings"
9 "syscall"
10
11 "git.sr.ht/~gabrielgio/img/pkg/database/repository"
12 "git.sr.ht/~gabrielgio/img/pkg/list"
13)
14
15type (
16 FileSystemController struct {
17 fsRepository repository.FileSystemRepository
18 userRepository repository.UserRepository
19 }
20
21 DirectoryParam struct {
22 Name string
23 UrlEncodedPath string
24 }
25
26 FileParam struct {
27 UrlEncodedPath string
28 Info fs.FileInfo
29 }
30
31 Page struct {
32 History []*DirectoryParam
33 Files []*FileParam
34 }
35)
36
37func (f *FileParam) GetUid() int {
38 if stat, ok := f.Info.Sys().(*syscall.Stat_t); ok {
39 return int(stat.Uid)
40 }
41 return 0
42}
43
44func (f *FileParam) GetGid() int {
45 if stat, ok := f.Info.Sys().(*syscall.Stat_t); ok {
46 return int(stat.Gid)
47 }
48 return 0
49}
50
51func NewFileSystemController(
52 fsRepository repository.FileSystemRepository,
53 userRepository repository.UserRepository,
54) *FileSystemController {
55 return &FileSystemController{
56 fsRepository: fsRepository,
57 userRepository: userRepository,
58 }
59}
60
61func getHistory(filepath string) []*DirectoryParam {
62 var (
63 paths = strings.Split(filepath, "/")
64 result = make([]*DirectoryParam, 0, len(paths))
65 acc = ""
66 )
67
68 // add root folder
69 result = append(result, &DirectoryParam{
70 Name: "...",
71 UrlEncodedPath: "",
72 })
73
74 if len(paths) == 1 && paths[0] == "" {
75 return result
76 }
77
78 for _, p := range paths {
79 acc = path.Join(acc, p)
80 result = append(result, &DirectoryParam{
81 Name: p,
82 UrlEncodedPath: url.QueryEscape(acc),
83 })
84 }
85 return result
86}
87
88func (self *FileSystemController) GetPage(ctx context.Context, userID uint, filepath string) (*Page, error) {
89 userPath, err := self.userRepository.GetPathFromUserID(ctx, userID)
90 if err != nil {
91 return nil, err
92 }
93 decodedPath, err := url.QueryUnescape(filepath)
94 if err != nil {
95 return nil, err
96 }
97
98 fullPath := path.Join(userPath, decodedPath)
99 files, err := self.fsRepository.List(fullPath)
100 if err != nil {
101 return nil, err
102 }
103
104 params := list.Map(files, func(info fs.FileInfo) *FileParam {
105 fullPath := path.Join(decodedPath, info.Name())
106 scapedFullPath := url.QueryEscape(fullPath)
107 return &FileParam{
108 Info: info,
109 UrlEncodedPath: scapedFullPath,
110 }
111 })
112
113 return &Page{
114 Files: params,
115 History: getHistory(decodedPath),
116 }, nil
117}