WebClient/HTTP API: ensure to check home dir, when needed, in multi-node setups
Behind a load balancer with no sticky sessions enabled is not enough to check the home dir only when the client logs in Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
parent
3ebdfa9b2d
commit
63e3891808
5 changed files with 9 additions and 2 deletions
|
@ -57,7 +57,7 @@ The configuration file contains the following sections:
|
||||||
|
|
||||||
- **"common"**, configuration parameters shared among all the supported protocols
|
- **"common"**, configuration parameters shared among all the supported protocols
|
||||||
- `idle_timeout`, integer. Time in minutes after which an idle client will be disconnected. 0 means disabled. Default: 15
|
- `idle_timeout`, integer. Time in minutes after which an idle client will be disconnected. 0 means disabled. Default: 15
|
||||||
- `upload_mode` integer. 0 means standard: the files are uploaded directly to the requested path. 1 means atomic: files are uploaded to a temporary path and renamed to the requested path when the client ends the upload. Atomic mode avoids problems such as a web server that serves partial files when the files are being uploaded. In atomic mode, if there is an upload error, the temporary file is deleted and so the requested upload path will not contain a partial file. 2 means atomic with resume support: same as atomic but if there is an upload error, the temporary file is renamed to the requested path and not deleted. This way, a client can reconnect and resume the upload. Default: 0
|
- `upload_mode` integer. 0 means standard: the files are uploaded directly to the requested path. 1 means atomic: files are uploaded to a temporary path and renamed to the requested path when the client ends the upload. Atomic mode avoids problems such as a web server that serves partial files when the files are being uploaded. In atomic mode, if there is an upload error, the temporary file is deleted and so the requested upload path will not contain a partial file. 2 means atomic with resume support: same as atomic but if there is an upload error, the temporary file is renamed to the requested path and not deleted. This way, a client can reconnect and resume the upload. Ignored for cloud-based storage backends (uploads are always atomic and resume is not supported for these backends) and for SFTP backend if buffering is enabled. Default: 0
|
||||||
- `actions`, struct. It contains the command to execute and/or the HTTP URL to notify and the trigger conditions. See [Custom Actions](./custom-actions.md) for more details
|
- `actions`, struct. It contains the command to execute and/or the HTTP URL to notify and the trigger conditions. See [Custom Actions](./custom-actions.md) for more details
|
||||||
- `execute_on`, list of strings. Valid values are `pre-download`, `download`, `pre-upload`, `upload`, `pre-delete`, `delete`, `rename`, `mkdir`, `rmdir`, `ssh_cmd`. Leave empty to disable actions.
|
- `execute_on`, list of strings. Valid values are `pre-download`, `download`, `pre-upload`, `upload`, `pre-delete`, `delete`, `rename`, `mkdir`, `rmdir`, `ssh_cmd`. Leave empty to disable actions.
|
||||||
- `execute_sync`, list of strings. Actions, defined in the `execute_on` list above, to be performed synchronously. The `pre-*` actions are always executed synchronously while the other ones are asynchronous. Executing an action synchronously means that SFTPGo will not return a result code to the client (which is waiting for it) until your hook have completed its execution. Leave empty to execute only the defined `pre-*` hook synchronously
|
- `execute_sync`, list of strings. Actions, defined in the `execute_on` list above, to be performed synchronously. The `pre-*` actions are always executed synchronously while the other ones are asynchronous. Executing an action synchronously means that SFTPGo will not return a result code to the client (which is waiting for it) until your hook have completed its execution. Leave empty to execute only the defined `pre-*` hook synchronously
|
||||||
|
|
|
@ -462,7 +462,8 @@ type Config struct {
|
||||||
BackupsPath string `json:"backups_path" mapstructure:"backups_path"`
|
BackupsPath string `json:"backups_path" mapstructure:"backups_path"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetShared returns the provider share mode
|
// GetShared returns the provider share mode.
|
||||||
|
// This method is called before the provider is initialized
|
||||||
func (c *Config) GetShared() int {
|
func (c *Config) GetShared() int {
|
||||||
if !util.Contains(sharedProviders, c.Driver) {
|
if !util.Contains(sharedProviders, c.Driver) {
|
||||||
return 0
|
return 0
|
||||||
|
|
|
@ -96,6 +96,7 @@ func createUserDir(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
connection.User.CheckFsRoot(connection.ID) //nolint:errcheck
|
||||||
err = connection.CreateDir(name, true)
|
err = connection.CreateDir(name, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sendAPIResponse(w, r, err, fmt.Sprintf("Unable to create directory %#v", name), getMappedStatusCode(err))
|
sendAPIResponse(w, r, err, fmt.Sprintf("Unable to create directory %#v", name), getMappedStatusCode(err))
|
||||||
|
@ -225,6 +226,7 @@ func uploadUserFile(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func doUploadFile(w http.ResponseWriter, r *http.Request, connection *Connection, filePath string) error {
|
func doUploadFile(w http.ResponseWriter, r *http.Request, connection *Connection, filePath string) error {
|
||||||
|
connection.User.CheckFsRoot(connection.ID) //nolint:errcheck
|
||||||
writer, err := connection.getFileWriter(filePath)
|
writer, err := connection.getFileWriter(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sendAPIResponse(w, r, err, fmt.Sprintf("Unable to write file %#v", filePath), getMappedStatusCode(err))
|
sendAPIResponse(w, r, err, fmt.Sprintf("Unable to write file %#v", filePath), getMappedStatusCode(err))
|
||||||
|
@ -294,6 +296,7 @@ func uploadUserFiles(w http.ResponseWriter, r *http.Request) {
|
||||||
func doUploadFiles(w http.ResponseWriter, r *http.Request, connection *Connection, parentDir string,
|
func doUploadFiles(w http.ResponseWriter, r *http.Request, connection *Connection, parentDir string,
|
||||||
files []*multipart.FileHeader,
|
files []*multipart.FileHeader,
|
||||||
) int {
|
) int {
|
||||||
|
connection.User.CheckFsRoot(connection.ID) //nolint:errcheck
|
||||||
uploaded := 0
|
uploaded := 0
|
||||||
connection.User.UploadBandwidth = 0
|
connection.User.UploadBandwidth = 0
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
|
|
|
@ -232,6 +232,7 @@ func getCompressedFileName(username string, files []string) string {
|
||||||
func renderCompressedFiles(w http.ResponseWriter, conn *Connection, baseDir string, files []string,
|
func renderCompressedFiles(w http.ResponseWriter, conn *Connection, baseDir string, files []string,
|
||||||
share *dataprovider.Share,
|
share *dataprovider.Share,
|
||||||
) {
|
) {
|
||||||
|
conn.User.CheckFsRoot(conn.ID) //nolint:errcheck
|
||||||
w.Header().Set("Content-Type", "application/zip")
|
w.Header().Set("Content-Type", "application/zip")
|
||||||
w.Header().Set("Accept-Ranges", "none")
|
w.Header().Set("Accept-Ranges", "none")
|
||||||
w.Header().Set("Content-Transfer-Encoding", "binary")
|
w.Header().Set("Content-Transfer-Encoding", "binary")
|
||||||
|
@ -326,6 +327,7 @@ func checkDownloadFileFromShare(share *dataprovider.Share, info os.FileInfo) err
|
||||||
func downloadFile(w http.ResponseWriter, r *http.Request, connection *Connection, name string,
|
func downloadFile(w http.ResponseWriter, r *http.Request, connection *Connection, name string,
|
||||||
info os.FileInfo, inline bool, share *dataprovider.Share,
|
info os.FileInfo, inline bool, share *dataprovider.Share,
|
||||||
) (int, error) {
|
) (int, error) {
|
||||||
|
connection.User.CheckFsRoot(connection.ID) //nolint:errcheck
|
||||||
err := checkDownloadFileFromShare(share, info)
|
err := checkDownloadFileFromShare(share, info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return http.StatusBadRequest, err
|
return http.StatusBadRequest, err
|
||||||
|
|
|
@ -954,6 +954,7 @@ func (s *httpdServer) handleClientEditFile(w http.ResponseWriter, r *http.Reques
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connection.User.CheckFsRoot(connection.ID) //nolint:errcheck
|
||||||
reader, err := connection.getFileReader(name, 0, r.Method)
|
reader, err := connection.getFileReader(name, 0, r.Method)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.renderClientMessagePage(w, r, fmt.Sprintf("Unable to get a reader for the file %#v", name), "",
|
s.renderClientMessagePage(w, r, fmt.Sprintf("Unable to get a reader for the file %#v", name), "",
|
||||||
|
|
Loading…
Reference in a new issue