Skip to content

Commit

Permalink
Merge pull request #11 from thestormforge/app-endpoints
Browse files Browse the repository at this point in the history
Add application configuration
  • Loading branch information
jgustie authored Nov 23, 2020
2 parents ed08ff4 + 64869f7 commit 4310d26
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 1 deletion.
19 changes: 18 additions & 1 deletion pkg/config/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ type Server struct {
API APIServer `json:"api"`
// Authorization contains the authorization server metadata necessary to access this server
Authorization AuthorizationServer `json:"authorization"`
// Application contains information about the public facing user interface.
Application ApplicationServer `json:"application"`
}

// APIServer is the API server metadata
Expand All @@ -69,6 +71,16 @@ type APIServer struct {
AccountsEndpoint string `json:"accounts_endpoint,omitempty"`
}

// ApplicationServer is the user facing application.
type ApplicationServer struct {
// BaseURL is the main entrypoint to the application.
BaseURL string `json:"base_url,omitempty"`
// AuthSuccessEndpoint is URL to direct the user to after a successful login.
AuthSuccessEndpoint string `json:"auth_success_endpoint,omitempty"`
// ExperimentsEndpoint is the URL of the experiments UI.
ExperimentsEndpoint string `json:"experiments_endpoint,omitempty"`
}

// NOTE: AuthorizationServer is defined by https://tools.ietf.org/html/rfc8414 do not add non-standard fields!

// AuthorizationServer is the authorization server metadata
Expand Down Expand Up @@ -278,9 +290,14 @@ func (srv *Server) MarshalJSON() ([]byte, error) {
if (APIServer{}) == srv.API {
api = nil
}
app := &srv.Application
if (ApplicationServer{}) == srv.Application {
app = nil
}
return json.Marshal(&struct {
*S
Authorization *AuthorizationServer `json:"authorization,omitempty"`
API *APIServer `json:"api,omitempty"`
}{S: (*S)(srv), Authorization: az, API: api})
Application *ApplicationServer `json:"application,omitempty"`
}{S: (*S)(srv), Authorization: az, API: api, Application: app})
}
26 changes: 26 additions & 0 deletions pkg/config/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,22 @@ func bootstrapClusterName() string {
return "default"
}

// applicationRoot returns the base URL of the UI.
func applicationRoot(baseURL string) (base string, err error) {
b, err := url.Parse(baseURL)
if err != nil {
return "", err
}
if b.RawQuery != "" {
return "", fmt.Errorf("query component is not allowed: %s", baseURL)
}
if b.Fragment != "" {
return "", fmt.Errorf("fragment component is not allowed: %s", baseURL)
}
b.Path = strings.TrimRight(b.Path, "/")
return b.String(), nil
}

// defaultString overwrites an empty s1 with the value of s2
func defaultString(s1 *string, s2 string) {
if *s1 == "" {
Expand All @@ -79,9 +95,11 @@ func defaultServerRoots(env string, srv *Server) error {
case "production":
defaultString(&srv.Identifier, "https://api.stormforge.io/v1/")
defaultString(&srv.Authorization.Issuer, "https://auth.carbonrelay.io/")
defaultString(&srv.Application.BaseURL, "https://app.stormforge.io/")
case "development":
defaultString(&srv.Identifier, "https://api.stormforge.dev/v1/")
defaultString(&srv.Authorization.Issuer, "https://auth.carbonrelay.dev/")
defaultString(&srv.Application.BaseURL, "https://app.stormforge.dev/")
default:
return fmt.Errorf("unknown environment: '%s'", env)
}
Expand All @@ -98,6 +116,10 @@ func defaultServerEndpoints(srv *Server) error {
if err != nil {
return err
}
base, err := applicationRoot(srv.Application.BaseURL)
if err != nil {
return err
}

// Apply the API defaults
defaultString(&srv.API.ExperimentsEndpoint, api+"/experiments/")
Expand All @@ -112,6 +134,10 @@ func defaultServerEndpoints(srv *Server) error {
defaultString(&srv.Authorization.DeviceAuthorizationEndpoint, issuer+"/oauth/device/code")
defaultString(&srv.Authorization.JSONWebKeySetURI, discovery.WellKnownURI(issuer, "jwks.json"))

// Apply the application defaults
defaultString(&srv.Application.AuthSuccessEndpoint, "https://docs.stormforge.io/api/auth_success/")
defaultString(&srv.Application.ExperimentsEndpoint, base+"/experiments")

// Special case for the registration service which is actually part of the accounts API
if u, err := url.Parse(srv.API.AccountsEndpoint); err != nil {
defaultString(&srv.Authorization.RegistrationEndpoint, api+"/accounts/clients")
Expand Down
3 changes: 3 additions & 0 deletions pkg/config/merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ func mergeServer(s1, s2 *Server) {
mergeString(&s1.Authorization.RegistrationEndpoint, s2.Authorization.RegistrationEndpoint)
mergeString(&s1.Authorization.DeviceAuthorizationEndpoint, s2.Authorization.DeviceAuthorizationEndpoint)
mergeString(&s1.Authorization.JSONWebKeySetURI, s2.Authorization.JSONWebKeySetURI)
mergeString(&s1.Application.BaseURL, s2.Application.BaseURL)
mergeString(&s1.Application.AuthSuccessEndpoint, s2.Application.AuthSuccessEndpoint)
mergeString(&s1.Application.ExperimentsEndpoint, s2.Application.ExperimentsEndpoint)
}

func mergeAuthorization(a1, a2 *Authorization) {
Expand Down

0 comments on commit 4310d26

Please sign in to comment.