CORS: add support for more parameters
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
parent
455bb550ee
commit
fdc10aa6c7
10 changed files with 89 additions and 52 deletions
|
@ -194,6 +194,9 @@ The configuration file contains the following sections:
|
|||
- `exposed_headers`, list of strings.
|
||||
- `allow_credentials` boolean.
|
||||
- `max_age`, integer.
|
||||
- `options_passthrough`, boolean.
|
||||
- `options_success_status`, integer.
|
||||
- `allow_private_network`, boolean.
|
||||
- `cache` struct containing cache configuration for the authenticated users.
|
||||
- `enabled`, boolean, set to true to enable user caching. Default: true.
|
||||
- `expiration_time`, integer. Expiration time, in minutes, for the cached users. 0 means unlimited. Default: 0.
|
||||
|
@ -326,6 +329,9 @@ The configuration file contains the following sections:
|
|||
- `exposed_headers`, list of strings.
|
||||
- `allow_credentials` boolean.
|
||||
- `max_age`, integer.
|
||||
- `options_passthrough`, boolean.
|
||||
- `options_success_status`, integer.
|
||||
- `allow_private_network`, boolean.
|
||||
- `setup` struct containing configurations for the initial setup screen
|
||||
- `installation_code`, string. If set, this installation code will be required when creating the first admin account. Please note that even if set using an environment variable this field is read at SFTPGo startup and not at runtime. This is not a license key or similar, the purpose here is to prevent anyone who can access to the initial setup screen from creating an admin user. Default: blank.
|
||||
- `installation_code_hint`, string. Description for the installation code input field. Default: `Installation code`.
|
||||
|
|
4
go.mod
4
go.mod
|
@ -48,7 +48,7 @@ require (
|
|||
github.com/pquerna/otp v1.3.0
|
||||
github.com/prometheus/client_golang v1.12.2
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/rs/cors v1.8.2
|
||||
github.com/rs/cors v1.8.3-0.20220619195839-da52b0701de5
|
||||
github.com/rs/xid v1.4.0
|
||||
github.com/rs/zerolog v1.27.0
|
||||
github.com/sftpgo/sdk v0.1.2-0.20220727164210-06723ba7ce9a
|
||||
|
@ -155,7 +155,7 @@ require (
|
|||
golang.org/x/tools v0.1.12 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f // indirect
|
||||
google.golang.org/genproto v0.0.0-20220802133213-ce4fa296bf78 // indirect
|
||||
google.golang.org/grpc v1.48.0 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/ini.v1 v1.66.6 // indirect
|
||||
|
|
8
go.sum
8
go.sum
|
@ -696,8 +696,8 @@ github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzG
|
|||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||
github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U=
|
||||
github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||
github.com/rs/cors v1.8.3-0.20220619195839-da52b0701de5 h1:7PcjxKTsfGXpTMiTNNa1VllbsYSZJN5nhvVEWQMdX8Y=
|
||||
github.com/rs/cors v1.8.3-0.20220619195839-da52b0701de5/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY=
|
||||
|
@ -1225,8 +1225,8 @@ google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljW
|
|||
google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||
google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||
google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||
google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f h1:XVHpVMvPs4MtH3h6cThzKs2snNexcfd35vQx2T3IuIY=
|
||||
google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc=
|
||||
google.golang.org/genproto v0.0.0-20220802133213-ce4fa296bf78 h1:QntLWYqZeuBtJkth3m/6DLznnI0AHJr+AgJXvVh/izw=
|
||||
google.golang.org/genproto v0.0.0-20220802133213-ce4fa296bf78/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
|
|
|
@ -747,6 +747,11 @@ func (j *eventCronJob) Run() {
|
|||
ticker := time.NewTicker(updateInterval)
|
||||
done := make(chan bool)
|
||||
|
||||
defer func() {
|
||||
done <- true
|
||||
ticker.Stop()
|
||||
}()
|
||||
|
||||
go func(taskName string) {
|
||||
eventManagerLog(logger.LevelDebug, "update task %q timestamp worker started", taskName)
|
||||
for {
|
||||
|
@ -762,9 +767,6 @@ func (j *eventCronJob) Run() {
|
|||
}(task.Name)
|
||||
|
||||
executeRuleAsyncActions(rule, EventParams{}, nil)
|
||||
|
||||
done <- true
|
||||
ticker.Stop()
|
||||
} else {
|
||||
executeRuleAsyncActions(rule, EventParams{}, nil)
|
||||
}
|
||||
|
|
|
@ -285,13 +285,16 @@ func Init() {
|
|||
CACertificates: []string{},
|
||||
CARevocationLists: []string{},
|
||||
Cors: webdavd.CorsConfig{
|
||||
Enabled: false,
|
||||
AllowedOrigins: []string{},
|
||||
AllowedMethods: []string{},
|
||||
AllowedHeaders: []string{},
|
||||
ExposedHeaders: []string{},
|
||||
AllowCredentials: false,
|
||||
MaxAge: 0,
|
||||
Enabled: false,
|
||||
AllowedOrigins: []string{},
|
||||
AllowedMethods: []string{},
|
||||
AllowedHeaders: []string{},
|
||||
ExposedHeaders: []string{},
|
||||
AllowCredentials: false,
|
||||
MaxAge: 0,
|
||||
OptionsPassthrough: false,
|
||||
OptionsSuccessStatus: 0,
|
||||
AllowPrivateNetwork: false,
|
||||
},
|
||||
Cache: webdavd.Cache{
|
||||
Users: webdavd.UsersCacheConfig{
|
||||
|
@ -373,13 +376,16 @@ func Init() {
|
|||
TokenValidation: 0,
|
||||
MaxUploadFileSize: 1048576000,
|
||||
Cors: httpd.CorsConfig{
|
||||
Enabled: false,
|
||||
AllowedOrigins: []string{},
|
||||
AllowedMethods: []string{},
|
||||
AllowedHeaders: []string{},
|
||||
ExposedHeaders: []string{},
|
||||
AllowCredentials: false,
|
||||
MaxAge: 0,
|
||||
Enabled: false,
|
||||
AllowedOrigins: []string{},
|
||||
AllowedMethods: []string{},
|
||||
AllowedHeaders: []string{},
|
||||
ExposedHeaders: []string{},
|
||||
AllowCredentials: false,
|
||||
MaxAge: 0,
|
||||
OptionsPassthrough: false,
|
||||
OptionsSuccessStatus: 0,
|
||||
AllowPrivateNetwork: false,
|
||||
},
|
||||
Setup: httpd.SetupConfig{
|
||||
InstallationCode: "",
|
||||
|
@ -1899,6 +1905,9 @@ func setViperDefaults() {
|
|||
viper.SetDefault("webdavd.cors.allowed_headers", globalConf.WebDAVD.Cors.AllowedHeaders)
|
||||
viper.SetDefault("webdavd.cors.exposed_headers", globalConf.WebDAVD.Cors.ExposedHeaders)
|
||||
viper.SetDefault("webdavd.cors.allow_credentials", globalConf.WebDAVD.Cors.AllowCredentials)
|
||||
viper.SetDefault("webdavd.cors.options_passthrough", globalConf.WebDAVD.Cors.OptionsPassthrough)
|
||||
viper.SetDefault("webdavd.cors.options_success_status", globalConf.WebDAVD.Cors.OptionsSuccessStatus)
|
||||
viper.SetDefault("webdavd.cors.allow_private_network", globalConf.WebDAVD.Cors.AllowPrivateNetwork)
|
||||
viper.SetDefault("webdavd.cors.max_age", globalConf.WebDAVD.Cors.MaxAge)
|
||||
viper.SetDefault("webdavd.cache.users.expiration_time", globalConf.WebDAVD.Cache.Users.ExpirationTime)
|
||||
viper.SetDefault("webdavd.cache.users.max_size", globalConf.WebDAVD.Cache.Users.MaxSize)
|
||||
|
@ -1961,6 +1970,9 @@ func setViperDefaults() {
|
|||
viper.SetDefault("httpd.cors.exposed_headers", globalConf.HTTPDConfig.Cors.ExposedHeaders)
|
||||
viper.SetDefault("httpd.cors.allow_credentials", globalConf.HTTPDConfig.Cors.AllowCredentials)
|
||||
viper.SetDefault("httpd.cors.max_age", globalConf.HTTPDConfig.Cors.MaxAge)
|
||||
viper.SetDefault("httpd.cors.options_passthrough", globalConf.HTTPDConfig.Cors.OptionsPassthrough)
|
||||
viper.SetDefault("httpd.cors.options_success_status", globalConf.HTTPDConfig.Cors.OptionsSuccessStatus)
|
||||
viper.SetDefault("httpd.cors.allow_private_network", globalConf.HTTPDConfig.Cors.AllowPrivateNetwork)
|
||||
viper.SetDefault("httpd.setup.installation_code", globalConf.HTTPDConfig.Setup.InstallationCode)
|
||||
viper.SetDefault("httpd.setup.installation_code_hint", globalConf.HTTPDConfig.Setup.InstallationCodeHint)
|
||||
viper.SetDefault("httpd.hide_support_link", globalConf.HTTPDConfig.HideSupportLink)
|
||||
|
|
|
@ -639,13 +639,16 @@ type SetupConfig struct {
|
|||
|
||||
// CorsConfig defines the CORS configuration
|
||||
type CorsConfig struct {
|
||||
AllowedOrigins []string `json:"allowed_origins" mapstructure:"allowed_origins"`
|
||||
AllowedMethods []string `json:"allowed_methods" mapstructure:"allowed_methods"`
|
||||
AllowedHeaders []string `json:"allowed_headers" mapstructure:"allowed_headers"`
|
||||
ExposedHeaders []string `json:"exposed_headers" mapstructure:"exposed_headers"`
|
||||
AllowCredentials bool `json:"allow_credentials" mapstructure:"allow_credentials"`
|
||||
Enabled bool `json:"enabled" mapstructure:"enabled"`
|
||||
MaxAge int `json:"max_age" mapstructure:"max_age"`
|
||||
AllowedOrigins []string `json:"allowed_origins" mapstructure:"allowed_origins"`
|
||||
AllowedMethods []string `json:"allowed_methods" mapstructure:"allowed_methods"`
|
||||
AllowedHeaders []string `json:"allowed_headers" mapstructure:"allowed_headers"`
|
||||
ExposedHeaders []string `json:"exposed_headers" mapstructure:"exposed_headers"`
|
||||
AllowCredentials bool `json:"allow_credentials" mapstructure:"allow_credentials"`
|
||||
Enabled bool `json:"enabled" mapstructure:"enabled"`
|
||||
MaxAge int `json:"max_age" mapstructure:"max_age"`
|
||||
OptionsPassthrough bool `json:"options_passthrough" mapstructure:"options_passthrough"`
|
||||
OptionsSuccessStatus int `json:"options_success_status" mapstructure:"options_success_status"`
|
||||
AllowPrivateNetwork bool `json:"allow_private_network" mapstructure:"allow_private_network"`
|
||||
}
|
||||
|
||||
// Conf httpd daemon configuration
|
||||
|
|
|
@ -1138,12 +1138,15 @@ func (s *httpdServer) initializeRouter() {
|
|||
}
|
||||
if s.cors.Enabled {
|
||||
c := cors.New(cors.Options{
|
||||
AllowedOrigins: util.RemoveDuplicates(s.cors.AllowedOrigins, true),
|
||||
AllowedMethods: util.RemoveDuplicates(s.cors.AllowedMethods, true),
|
||||
AllowedHeaders: util.RemoveDuplicates(s.cors.AllowedHeaders, true),
|
||||
ExposedHeaders: util.RemoveDuplicates(s.cors.ExposedHeaders, true),
|
||||
MaxAge: s.cors.MaxAge,
|
||||
AllowCredentials: s.cors.AllowCredentials,
|
||||
AllowedOrigins: util.RemoveDuplicates(s.cors.AllowedOrigins, true),
|
||||
AllowedMethods: util.RemoveDuplicates(s.cors.AllowedMethods, true),
|
||||
AllowedHeaders: util.RemoveDuplicates(s.cors.AllowedHeaders, true),
|
||||
ExposedHeaders: util.RemoveDuplicates(s.cors.ExposedHeaders, true),
|
||||
MaxAge: s.cors.MaxAge,
|
||||
AllowCredentials: s.cors.AllowCredentials,
|
||||
OptionsPassthrough: s.cors.OptionsPassthrough,
|
||||
OptionsSuccessStatus: s.cors.OptionsSuccessStatus,
|
||||
AllowPrivateNetwork: s.cors.AllowPrivateNetwork,
|
||||
})
|
||||
s.router.Use(c.Handler)
|
||||
}
|
||||
|
|
|
@ -57,13 +57,15 @@ func (s *webDavServer) listenAndServe(compressor *middleware.Compressor) error {
|
|||
}
|
||||
if s.config.Cors.Enabled {
|
||||
c := cors.New(cors.Options{
|
||||
AllowedOrigins: util.RemoveDuplicates(s.config.Cors.AllowedOrigins, true),
|
||||
AllowedMethods: util.RemoveDuplicates(s.config.Cors.AllowedMethods, true),
|
||||
AllowedHeaders: util.RemoveDuplicates(s.config.Cors.AllowedHeaders, true),
|
||||
ExposedHeaders: util.RemoveDuplicates(s.config.Cors.ExposedHeaders, true),
|
||||
MaxAge: s.config.Cors.MaxAge,
|
||||
AllowCredentials: s.config.Cors.AllowCredentials,
|
||||
OptionsPassthrough: true,
|
||||
AllowedOrigins: util.RemoveDuplicates(s.config.Cors.AllowedOrigins, true),
|
||||
AllowedMethods: util.RemoveDuplicates(s.config.Cors.AllowedMethods, true),
|
||||
AllowedHeaders: util.RemoveDuplicates(s.config.Cors.AllowedHeaders, true),
|
||||
ExposedHeaders: util.RemoveDuplicates(s.config.Cors.ExposedHeaders, true),
|
||||
MaxAge: s.config.Cors.MaxAge,
|
||||
AllowCredentials: s.config.Cors.AllowCredentials,
|
||||
OptionsPassthrough: s.config.Cors.OptionsPassthrough,
|
||||
OptionsSuccessStatus: s.config.Cors.OptionsSuccessStatus,
|
||||
AllowPrivateNetwork: s.config.Cors.AllowPrivateNetwork,
|
||||
})
|
||||
handler = c.Handler(handler)
|
||||
}
|
||||
|
|
|
@ -52,13 +52,16 @@ type ServiceStatus struct {
|
|||
|
||||
// CorsConfig defines the CORS configuration
|
||||
type CorsConfig struct {
|
||||
AllowedOrigins []string `json:"allowed_origins" mapstructure:"allowed_origins"`
|
||||
AllowedMethods []string `json:"allowed_methods" mapstructure:"allowed_methods"`
|
||||
AllowedHeaders []string `json:"allowed_headers" mapstructure:"allowed_headers"`
|
||||
ExposedHeaders []string `json:"exposed_headers" mapstructure:"exposed_headers"`
|
||||
AllowCredentials bool `json:"allow_credentials" mapstructure:"allow_credentials"`
|
||||
Enabled bool `json:"enabled" mapstructure:"enabled"`
|
||||
MaxAge int `json:"max_age" mapstructure:"max_age"`
|
||||
AllowedOrigins []string `json:"allowed_origins" mapstructure:"allowed_origins"`
|
||||
AllowedMethods []string `json:"allowed_methods" mapstructure:"allowed_methods"`
|
||||
AllowedHeaders []string `json:"allowed_headers" mapstructure:"allowed_headers"`
|
||||
ExposedHeaders []string `json:"exposed_headers" mapstructure:"exposed_headers"`
|
||||
AllowCredentials bool `json:"allow_credentials" mapstructure:"allow_credentials"`
|
||||
Enabled bool `json:"enabled" mapstructure:"enabled"`
|
||||
MaxAge int `json:"max_age" mapstructure:"max_age"`
|
||||
OptionsPassthrough bool `json:"options_passthrough" mapstructure:"options_passthrough"`
|
||||
OptionsSuccessStatus int `json:"options_success_status" mapstructure:"options_success_status"`
|
||||
AllowPrivateNetwork bool `json:"allow_private_network" mapstructure:"allow_private_network"`
|
||||
}
|
||||
|
||||
// UsersCacheConfig defines the cache configuration for users
|
||||
|
|
10
sftpgo.json
10
sftpgo.json
|
@ -165,7 +165,10 @@
|
|||
"allowed_headers": [],
|
||||
"exposed_headers": [],
|
||||
"allow_credentials": false,
|
||||
"max_age": 0
|
||||
"max_age": 0,
|
||||
"options_passthrough": false,
|
||||
"options_success_status": 0,
|
||||
"allow_private_network": false
|
||||
},
|
||||
"cache": {
|
||||
"users": {
|
||||
|
@ -330,7 +333,10 @@
|
|||
"allowed_headers": [],
|
||||
"exposed_headers": [],
|
||||
"allow_credentials": false,
|
||||
"max_age": 0
|
||||
"max_age": 0,
|
||||
"options_passthrough": false,
|
||||
"options_success_status": 0,
|
||||
"allow_private_network": false
|
||||
},
|
||||
"setup": {
|
||||
"installation_code": "",
|
||||
|
|
Loading…
Reference in a new issue