diff --git a/filemanager.go b/filemanager.go index 6343d7e5..0be50ccf 100644 --- a/filemanager.go +++ b/filemanager.go @@ -1,6 +1,7 @@ package filemanager import ( + "errors" "net/http" "regexp" "strings" @@ -11,7 +12,7 @@ import ( // FileManager is a file manager instance. type FileManager struct { - *User + *user Assets *assets // PrefixURL is a part of the URL that is trimmed from the http.Request.URL before @@ -28,26 +29,18 @@ type FileManager struct { // a trailing slash. WebDavURL string - scopes map[string]*scope - // Users is a map with the different configurations for each user. - Users map[string]*User + Users map[string]*user // TODO: event-based? BeforeSave CommandFunc AfterSave CommandFunc } -type scope struct { - path string - fileSystem webdav.FileSystem - handler *webdav.Handler -} - -// User contains the configuration for each user. -type User struct { +// user contains the configuration for each user. +type user struct { // scope is the physical path the user has access to. - scope *scope + scope string // fileSystem is the virtual file system the user has access. fileSystem webdav.FileSystem @@ -93,12 +86,11 @@ type Rule struct { Regexp *regexp.Regexp } -// CommandFunc ... -type CommandFunc func(r *http.Request, c *FileManager, u *User) error +type CommandFunc func(r *http.Request, c *FileManager, u *user) error func New() *FileManager { m := &FileManager{ - User: &User{ + user: &user{ AllowCommands: true, AllowEdit: true, AllowNew: true, @@ -109,9 +101,9 @@ func New() *FileManager { Regexp: regexp.MustCompile("\\/\\..+"), }}, }, - Users: map[string]*User{}, - BeforeSave: func(r *http.Request, c *FileManager, u *User) error { return nil }, - AfterSave: func(r *http.Request, c *FileManager, u *User) error { return nil }, + Users: map[string]*user{}, + BeforeSave: func(r *http.Request, c *FileManager, u *user) error { return nil }, + AfterSave: func(r *http.Request, c *FileManager, u *user) error { return nil }, Assets: &assets{ Templates: rice.MustFindBox("./_assets/templates"), CSS: rice.MustFindBox("./_assets/css"), @@ -119,7 +111,7 @@ func New() *FileManager { }, } - m.SetScope(".") + m.SetScope(".", "") m.SetBaseURL("/") m.SetWebDavURL("/webdav") @@ -154,21 +146,58 @@ func (m *FileManager) SetWebDavURL(url string) { url = strings.TrimSuffix(url, "/") m.WebDavURL = m.BaseURL + "/" + url - m.User.handler = &webdav.Handler{ + + // update base user webdav handler + m.handler = &webdav.Handler{ Prefix: m.WebDavURL, FileSystem: m.fileSystem, LockSystem: webdav.NewMemLS(), } + + // update other users' handlers to match + // the new URL + for _, u := range m.Users { + u.handler = &webdav.Handler{ + Prefix: m.WebDavURL, + FileSystem: u.fileSystem, + LockSystem: webdav.NewMemLS(), + } + } } // SetScope updates a user scope and its virtual file system. -func (m *FileManager) SetScope(scope string, user string) { - m.scope = strings.TrimSuffix(scope, "/") - m.fileSystem = webdav.Dir(m.scope) +// If the user string is blank, it will change the base scope. +func (m *FileManager) SetScope(scope string, username string) error { + var u *user + + if username == "" { + u = m.user + } else { + var ok bool + u, ok = m.Users[username] + if !ok { + return errors.New("Inexistent user") + } + } + + u.scope = strings.TrimSuffix(scope, "/") + u.fileSystem = webdav.Dir(u.scope) + + u.handler = &webdav.Handler{ + Prefix: m.WebDavURL, + FileSystem: u.fileSystem, + LockSystem: webdav.NewMemLS(), + } + + return nil +} + +func (m *FileManager) NewUser(name string) { + } // Allowed checks if the user has permission to access a directory/file. -func (u User) Allowed(url string) bool { +func (u user) Allowed(url string) bool { var rule *Rule i := len(u.Rules) - 1 diff --git a/http.go b/http.go index e1e870d5..606f0960 100644 --- a/http.go +++ b/http.go @@ -21,7 +21,7 @@ func (c *FileManager) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, er fi *FileInfo code int err error - user *User + user *user ) // Checks if the URL matches the Assets URL. Returns the asset if the @@ -38,7 +38,7 @@ func (c *FileManager) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, er if _, ok := c.Users[username]; ok { user = c.Users[username] } else { - user = c.User + user = c.user } // Checks if the request URL is for the WebDav server diff --git a/http_command.go b/http_command.go index e95071b7..1124903c 100644 --- a/http_command.go +++ b/http_command.go @@ -22,7 +22,7 @@ var ( ) // command handles the requests for VCS related commands: git, svn and mercurial -func command(w http.ResponseWriter, r *http.Request, c *FileManager, u *User) (int, error) { +func command(w http.ResponseWriter, r *http.Request, c *FileManager, u *user) (int, error) { // Upgrades the connection to a websocket and checks for errors. conn, err := upgrader.Upgrade(w, r, nil) if err != nil { diff --git a/http_listing.go b/http_listing.go index 5b2a663b..327adccb 100644 --- a/http_listing.go +++ b/http_listing.go @@ -10,7 +10,7 @@ import ( ) // serveListing presents the user with a listage of a directory folder. -func serveListing(w http.ResponseWriter, r *http.Request, c *FileManager, u *User, i *FileInfo) (int, error) { +func serveListing(w http.ResponseWriter, r *http.Request, c *FileManager, u *user, i *FileInfo) (int, error) { var err error // Loads the content of the directory diff --git a/http_put.go b/http_put.go index 67164119..360e4b74 100644 --- a/http_put.go +++ b/http_put.go @@ -14,7 +14,7 @@ import ( ) // put is used to update a file that was edited -func put(w http.ResponseWriter, r *http.Request, c *FileManager, u *User) (err error) { +func put(w http.ResponseWriter, r *http.Request, c *FileManager, u *user) (err error) { var ( data = map[string]interface{}{} file []byte diff --git a/http_search.go b/http_search.go index 5cf27699..183331b8 100644 --- a/http_search.go +++ b/http_search.go @@ -43,7 +43,7 @@ func parseSearch(value string) *searchOptions { } // search searches for a file or directory. -func search(w http.ResponseWriter, r *http.Request, c *FileManager, u *User) (int, error) { +func search(w http.ResponseWriter, r *http.Request, c *FileManager, u *user) (int, error) { // Upgrades the connection to a websocket and checks for errors. conn, err := upgrader.Upgrade(w, r, nil) if err != nil { diff --git a/http_single.go b/http_single.go index 87f01315..77a0a410 100644 --- a/http_single.go +++ b/http_single.go @@ -7,7 +7,7 @@ import ( // serveSingle serves a single file in an editor (if it is editable), shows the // plain file, or downloads it if it can't be shown. -func serveSingle(w http.ResponseWriter, r *http.Request, c *FileManager, u *User, i *FileInfo) (int, error) { +func serveSingle(w http.ResponseWriter, r *http.Request, c *FileManager, u *user, i *FileInfo) (int, error) { var err error if err = i.RetrieveFileType(); err != nil { diff --git a/info.go b/info.go index 335ccbc3..382b23a6 100644 --- a/info.go +++ b/info.go @@ -33,7 +33,7 @@ type FileInfo struct { // GetInfo gets the file information and, in case of error, returns the // respective HTTP error code -func GetInfo(url *url.URL, c *FileManager, u *User) (*FileInfo, error) { +func GetInfo(url *url.URL, c *FileManager, u *user) (*FileInfo, error) { var err error i := &FileInfo{URL: c.PrefixURL + url.Path} diff --git a/listing.go b/listing.go index 5cb0d878..7a176d4f 100644 --- a/listing.go +++ b/listing.go @@ -33,7 +33,7 @@ type Listing struct { } // GetListing gets the information about a specific directory and its files. -func GetListing(u *User, filePath string, baseURL string) (*Listing, error) { +func GetListing(u *user, filePath string, baseURL string) (*Listing, error) { // Gets the directory information using the Virtual File System of // the user configuration. file, err := u.fileSystem.OpenFile(context.TODO(), filePath, os.O_RDONLY, 0) diff --git a/page.go b/page.go index b65a7365..571bc5c4 100644 --- a/page.go +++ b/page.go @@ -23,7 +23,7 @@ type PageInfo struct { Name string Path string IsDir bool - User *User + User *user Config *FileManager Data interface{} Editor bool