diff --git a/docs/content/getting-started.md b/docs/content/getting-started.md index 88bb7c73d..8faa2b391 100644 --- a/docs/content/getting-started.md +++ b/docs/content/getting-started.md @@ -80,6 +80,38 @@ PHOENIX_ASSET_PATH PHOENIX_WEB_CONFIG : Path to phoenix config, empty default value +PHOENIX_WEB_CONFIG_SERVER +: Server URL, defaults to `http://localhost:9135` + +PHOENIX_WEB_CONFIG_THEME +: Theme, defaults to `owncloud` + +PHOENIX_WEB_CONFIG_VERSION +: Version, defaults to `0.1.0` + +PHOENIX_APPS +: Use multiple times to provide multiple apps + +PHOENIX_EXTERNAL_APPS +: Not supported yet, specify a config.json file via `PHOENIX_WEB_CONFIG` + +PHOENIX_OIDC_METADATA_URL +: OpenID Connect metadata URL, defaults to `http://localhost:9130/.well-known/openid-configuration` + +PHOENIX_OIDC_AUTHORITY +: OpenID Connect authority, defaults to `http://localhost:9130` + +PHOENIX_OIDC_CLIENT_ID +: OpenID Connect client ID, defaults to `phoenix` + +PHOENIX_OIDC_RESPONSE_TYPE +: OpenID Connect response type, defaults to `code` + +PHOENIX_OIDC_SCOPE +: OpenID Connect scope, defaults to `openid profile email` + +In case you want to render any additional properties in the config.json you can provide a custom config.json using eg. `PHOENIX_WEB_CONFIG=/path/to/config.json ocis-phoenix server` + ##### Health PHOENIX_DEBUG_ADDR @@ -144,6 +176,35 @@ If you prefer to configure the service with commandline flags you can see the av --web-config : Path to phoenix config, empty default value +--web-config-server +: Server URL, defaults to `http://localhost:9135` + +--web-config-theme +: Theme, defaults to `owncloud` + +--web-config-version +: Version, defaults to `0.1.0` + +--web-config-apps +: Use multiple times to provide multiple apps + +--oidc-metadata-url +: OpenID Connect metadata URL, defaults to `http://localhost:9130/.well-known/openid-configuration` + +--oidc-authority +: OpenID Connect authority, defaults to `http://localhost:9130` + +--oidc-client-id +: OpenID Connect client ID, defaults to `phoenix` + +--oidc-response-type +: OpenID Connect response type, defaults to `code` + +--oidc-scope +: OpenID Connect scope, defaults to `openid profile email` + +In case you want to render any additional properties in the config.json you can provide a custom config.json using eg. `ocis-phoenix server --web-config=/path/to/config.json` + ##### Health --debug-addr diff --git a/pkg/config/config.go b/pkg/config/config.go index e3f050497..dd78e40a8 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -36,9 +36,50 @@ type Asset struct { Path string } -// Phoenix defines the available phoenic configuration. +// PhoenixConfig defines the available phoenix configuration for a dynamically rendered config.json. +type PhoenixConfig struct { + Server string `json:"server,omitempty"` + Theme string `json:"theme,omitempty"` + Version string `json:"version,omitempty"` // TODO what is version used for? + OpenIDConnect OIDC `json:"openIdConnect,omitempty"` + // TODO add nilasempty when https://go-review.googlesource.com/c/go/+/205897/ is released + Apps []string `json:"apps"` + ExternalApps []ExternalApp `json:"external_apps,omitempty"` +} + +// OIDC defines the available oidc configuration +type OIDC struct { + MetadataURL string `json:"metadata_url,omitempty"` + Authority string `json:"authority,omitempty"` + ClientID string `json:"client_id,omitempty"` + ResponseType string `json:"response_type,omitempty"` + Scope string `json:"scope,omitempty"` +} + +// ExternalApp defines an external phoenix app. +// { +// "name": "hello", +// "path": "http://localhost:9105/hello.js", +// "config": { +// "url": "http://localhost:9105" +// } +// } +type ExternalApp struct { + Name string `json:"name,omitempty"` + Path string `json:"path,omitempty"` + // Config is completely dynamic, because it depends on the extension + Config map[string]interface{} `json:"config,omitempty"` +} + +// ExternalAppConfig defines an external phoenix app configuration. +type ExternalAppConfig struct { + URL string `json:"url,omitempty"` +} + +// Phoenix defines the available phoenix configuration. type Phoenix struct { - Path string + Path string + Config PhoenixConfig } // Config combines all available configuration parts. @@ -49,6 +90,7 @@ type Config struct { HTTP HTTP Tracing Tracing Asset Asset + OIDC OIDC Phoenix Phoenix } diff --git a/pkg/flagset/flagset.go b/pkg/flagset/flagset.go index 455ddd090..ff4fd15c4 100644 --- a/pkg/flagset/flagset.go +++ b/pkg/flagset/flagset.go @@ -52,6 +52,7 @@ func HealthWithConfig(cfg *config.Config) []cli.Flag { // ServerWithConfig applies cfg to the root flagset func ServerWithConfig(cfg *config.Config) []cli.Flag { + apps := cli.StringSlice(cfg.Phoenix.Config.Apps) return []cli.Flag{ &cli.BoolFlag{ Name: "tracing-enabled", @@ -148,5 +149,68 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVar: "PHOENIX_WEB_CONFIG", Destination: &cfg.Phoenix.Path, }, + &cli.StringFlag{ + Name: "web-config-server", + Value: "http://localhost:9135", + Usage: "Server URL", + EnvVar: "PHOENIX_WEB_CONFIG_SERVER", + Destination: &cfg.Phoenix.Config.Server, + }, + &cli.StringFlag{ + Name: "web-config-theme", + Value: "owncloud", + Usage: "Theme", + EnvVar: "PHOENIX_WEB_CONFIG_THEME", + Destination: &cfg.Phoenix.Config.Theme, + }, + &cli.StringFlag{ + Name: "web-config-version", + Value: "0.1.0", + Usage: "Version", + EnvVar: "PHOENIX_WEB_CONFIG_VERSION", + Destination: &cfg.Phoenix.Config.Version, + }, + &cli.StringSliceFlag{ + Name: "web-config-apps", + Value: &apps, + Usage: "Use multiple times to provide multiple apps", + EnvVar: "PHOENIX_APPS", + }, + // TODO EXTERNAL APPS? + &cli.StringFlag{ + Name: "oidc-metadata-url", + Value: "http://localhost:9130/.well-known/openid-configuration", + Usage: "OpenID Connect metadata URL", + EnvVar: "PHOENIX_OIDC_METADATA_URL", + Destination: &cfg.Phoenix.Config.OpenIDConnect.MetadataURL, + }, + &cli.StringFlag{ + Name: "oidc-authority", + Value: "http://localhost:9130", + Usage: "OpenID Connect authority", // TODO rename to Issuer + EnvVar: "PHOENIX_OIDC_AUTHORITY", + Destination: &cfg.Phoenix.Config.OpenIDConnect.Authority, + }, + &cli.StringFlag{ + Name: "oidc-client-id", + Value: "phoenix", + Usage: "OpenID Connect client ID", + EnvVar: "PHOENIX_OIDC_CLIENT_ID", + Destination: &cfg.Phoenix.Config.OpenIDConnect.ClientID, + }, + &cli.StringFlag{ + Name: "oidc-response-type", + Value: "code", + Usage: "OpenID Connect response type", + EnvVar: "PHOENIX_OIDC_RESPONSE_TYPE", + Destination: &cfg.Phoenix.Config.OpenIDConnect.ResponseType, + }, + &cli.StringFlag{ + Name: "oidc-scope", + Value: "openid profile email", + Usage: "OpenID Connect scope", + EnvVar: "PHOENIX_OIDC_SCOPE", + Destination: &cfg.Phoenix.Config.OpenIDConnect.Scope, + }, } } diff --git a/pkg/service/v0/service.go b/pkg/service/v0/service.go index 902b9e439..5f0a52428 100644 --- a/pkg/service/v0/service.go +++ b/pkg/service/v0/service.go @@ -1,6 +1,7 @@ package svc import ( + "encoding/json" "io/ioutil" "net/http" "os" @@ -56,19 +57,30 @@ func (p Phoenix) ServeHTTP(w http.ResponseWriter, r *http.Request) { p.mux.ServeHTTP(w, r) } -// Config implements the Service interface. -func (p Phoenix) Config(w http.ResponseWriter, r *http.Request) { - if _, err := os.Stat(p.config.Phoenix.Path); os.IsNotExist(err) { +func (p Phoenix) getPayload() (payload []byte, err error) { + + if p.config.Phoenix.Path == "" { + // render dynamically using config + + // make apps render as empty array if it is empty + // TODO remove once https://github.com/golang/go/issues/27589 is fixed + if len(p.config.Phoenix.Config.Apps) == 0 { + p.config.Phoenix.Config.Apps = make([]string, 0) + } + + return json.Marshal(p.config.Phoenix.Config) + } + + // try loading from file + if _, err = os.Stat(p.config.Phoenix.Path); os.IsNotExist(err) { p.logger.Error(). Err(err). Str("config", p.config.Phoenix.Path). Msg("Phoenix config doesn't exist") - - http.Error(w, ErrConfigInvalid, http.StatusUnprocessableEntity) return } - payload, err := ioutil.ReadFile(p.config.Phoenix.Path) + payload, err = ioutil.ReadFile(p.config.Phoenix.Path) if err != nil { p.logger.Error(). @@ -76,6 +88,15 @@ func (p Phoenix) Config(w http.ResponseWriter, r *http.Request) { Str("config", p.config.Phoenix.Path). Msg("Failed to read custom config") + } + return +} + +// Config implements the Service interface. +func (p Phoenix) Config(w http.ResponseWriter, r *http.Request) { + + payload, err := p.getPayload() + if err != nil { http.Error(w, ErrConfigInvalid, http.StatusUnprocessableEntity) return }