diff --git a/satellite/console/consoleweb/config.go b/satellite/console/consoleweb/config.go new file mode 100644 index 000000000..afda5f6ff --- /dev/null +++ b/satellite/console/consoleweb/config.go @@ -0,0 +1,87 @@ +// Copyright (C) 2023 Storj Labs, Inc. +// See LICENSE for copying information. + +package consoleweb + +import ( + "encoding/json" + + "storj.io/common/memory" + "storj.io/storj/satellite/console" +) + +// FrontendConfig holds the configuration for the satellite frontend. +type FrontendConfig struct { + ExternalAddress string `json:"externalAddress"` + SatelliteName string `json:"satelliteName"` + SatelliteNodeURL string `json:"satelliteNodeURL"` + StripePublicKey string `json:"stripePublicKey"` + PartneredSatellites []PartneredSatellite `json:"partneredSatellites"` + DefaultProjectLimit int `json:"defaultProjectLimit"` + GeneralRequestURL string `json:"generalRequestURL"` + ProjectLimitsIncreaseRequestURL string `json:"projectLimitsIncreaseRequestURL"` + GatewayCredentialsRequestURL string `json:"gatewayCredentialsRequestURL"` + IsBetaSatellite bool `json:"isBetaSatellite"` + BetaSatelliteFeedbackURL string `json:"betaSatelliteFeedbackURL"` + BetaSatelliteSupportURL string `json:"betaSatelliteSupportURL"` + DocumentationURL string `json:"documentationURL"` + CouponCodeBillingUIEnabled bool `json:"couponCodeBillingUIEnabled"` + CouponCodeSignupUIEnabled bool `json:"couponCodeSignupUIEnabled"` + FileBrowserFlowDisabled bool `json:"fileBrowserFlowDisabled"` + LinksharingURL string `json:"linksharingURL"` + PathwayOverviewEnabled bool `json:"pathwayOverviewEnabled"` + Captcha console.CaptchaConfig `json:"captcha"` + NewProjectDashboard bool `json:"newProjectDashboard"` + AllProjectsDashboard bool `json:"allProjectsDashboard"` + DefaultPaidStorageLimit memory.Size `json:"defaultPaidStorageLimit"` + DefaultPaidBandwidthLimit memory.Size `json:"defaultPaidBandwidthLimit"` + NewBillingScreen bool `json:"newBillingScreen"` + NewAccessGrantFlow bool `json:"newAccessGrantFlow"` + InactivityTimerEnabled bool `json:"inactivityTimerEnabled"` + InactivityTimerDuration int `json:"inactivityTimerDuration"` + InactivityTimerViewerEnabled bool `json:"inactivityTimerViewerEnabled"` + OptionalSignupSuccessURL string `json:"optionalSignupSuccessURL"` + HomepageURL string `json:"homepageURL"` + NativeTokenPaymentsEnabled bool `json:"nativeTokenPaymentsEnabled"` + PasswordMinimumLength int `json:"passwordMinimumLength"` + PasswordMaximumLength int `json:"passwordMaximumLength"` + ABTestingEnabled bool `json:"abTestingEnabled"` +} + +// Satellites is a configuration value that contains a list of satellite names and addresses. +// Format should be [{"name": "","address": ""],{"name": "","address": ""},...] in valid JSON format. +// +// Can be used as a flag. +type Satellites []PartneredSatellite + +// PartneredSatellite contains the name and web address of a satellite. +type PartneredSatellite struct { + Name string `json:"name"` + Address string `json:"address"` +} + +// Type implements pflag.Value. +func (Satellites) Type() string { return "consoleweb.Satellites" } + +// String is required for pflag.Value. +func (sl *Satellites) String() string { + satellites, err := json.Marshal(*sl) + if err != nil { + return "" + } + + return string(satellites) +} + +// Set does validation on the configured JSON. +func (sl *Satellites) Set(s string) (err error) { + satellites := make([]PartneredSatellite, 3) + + err = json.Unmarshal([]byte(s), &satellites) + if err != nil { + return err + } + + *sl = satellites + return +} diff --git a/satellite/console/consoleweb/server.go b/satellite/console/consoleweb/server.go index 945c706cc..b53e5c256 100644 --- a/satellite/console/consoleweb/server.go +++ b/satellite/console/consoleweb/server.go @@ -68,36 +68,36 @@ type Config struct { AuthToken string `help:"auth token needed for access to registration token creation endpoint" default:"" testDefault:"very-secret-token"` AuthTokenSecret string `help:"secret used to sign auth tokens" releaseDefault:"" devDefault:"my-suppa-secret-key"` - ContactInfoURL string `help:"url link to contacts page" default:"https://forum.storj.io"` - FrameAncestors string `help:"allow domains to embed the satellite in a frame, space separated" default:"tardigrade.io storj.io"` - LetUsKnowURL string `help:"url link to let us know page" default:"https://storjlabs.atlassian.net/servicedesk/customer/portals"` - SEO string `help:"used to communicate with web crawlers and other web robots" default:"User-agent: *\nDisallow: \nDisallow: /cgi-bin/"` - SatelliteName string `help:"used to display at web satellite console" default:"Storj"` - SatelliteOperator string `help:"name of organization which set up satellite" default:"Storj Labs" ` - TermsAndConditionsURL string `help:"url link to terms and conditions page" default:"https://www.storj.io/terms-of-service/"` - AccountActivationRedirectURL string `help:"url link for account activation redirect" default:""` - PartneredSatellites console.Satellites `help:"names and addresses of partnered satellites in JSON list format" default:"[{\"name\":\"US1\",\"address\":\"https://us1.storj.io\"},{\"name\":\"EU1\",\"address\":\"https://eu1.storj.io\"},{\"name\":\"AP1\",\"address\":\"https://ap1.storj.io\"}]"` - GeneralRequestURL string `help:"url link to general request page" default:"https://supportdcs.storj.io/hc/en-us/requests/new?ticket_form_id=360000379291"` - ProjectLimitsIncreaseRequestURL string `help:"url link to project limit increase request page" default:"https://supportdcs.storj.io/hc/en-us/requests/new?ticket_form_id=360000683212"` - GatewayCredentialsRequestURL string `help:"url link for gateway credentials requests" default:"https://auth.storjshare.io" devDefault:"http://localhost:8000"` - IsBetaSatellite bool `help:"indicates if satellite is in beta" default:"false"` - BetaSatelliteFeedbackURL string `help:"url link for for beta satellite feedback" default:""` - BetaSatelliteSupportURL string `help:"url link for for beta satellite support" default:""` - DocumentationURL string `help:"url link to documentation" default:"https://docs.storj.io/"` - CouponCodeBillingUIEnabled bool `help:"indicates if user is allowed to add coupon codes to account from billing" default:"false"` - CouponCodeSignupUIEnabled bool `help:"indicates if user is allowed to add coupon codes to account from signup" default:"false"` - FileBrowserFlowDisabled bool `help:"indicates if file browser flow is disabled" default:"false"` - CSPEnabled bool `help:"indicates if Content Security Policy is enabled" devDefault:"false" releaseDefault:"true"` - LinksharingURL string `help:"url link for linksharing requests" default:"https://link.storjshare.io" devDefault:"http://localhost:8001"` - PathwayOverviewEnabled bool `help:"indicates if the overview onboarding step should render with pathways" default:"true"` - NewProjectDashboard bool `help:"indicates if new project dashboard should be used" default:"true"` - AllProjectsDashboard bool `help:"indicates if all projects dashboard should be used" default:"false"` - NewBillingScreen bool `help:"indicates if new billing screens should be used" default:"true"` - NewAccessGrantFlow bool `help:"indicates if new access grant flow should be used" default:"false"` - GeneratedAPIEnabled bool `help:"indicates if generated console api should be used" default:"false"` - OptionalSignupSuccessURL string `help:"optional url to external registration success page" default:""` - HomepageURL string `help:"url link to storj.io homepage" default:"https://www.storj.io"` - NativeTokenPaymentsEnabled bool `help:"indicates if storj native token payments system is enabled" default:"false"` + ContactInfoURL string `help:"url link to contacts page" default:"https://forum.storj.io"` + FrameAncestors string `help:"allow domains to embed the satellite in a frame, space separated" default:"tardigrade.io storj.io"` + LetUsKnowURL string `help:"url link to let us know page" default:"https://storjlabs.atlassian.net/servicedesk/customer/portals"` + SEO string `help:"used to communicate with web crawlers and other web robots" default:"User-agent: *\nDisallow: \nDisallow: /cgi-bin/"` + SatelliteName string `help:"used to display at web satellite console" default:"Storj"` + SatelliteOperator string `help:"name of organization which set up satellite" default:"Storj Labs" ` + TermsAndConditionsURL string `help:"url link to terms and conditions page" default:"https://www.storj.io/terms-of-service/"` + AccountActivationRedirectURL string `help:"url link for account activation redirect" default:""` + PartneredSatellites Satellites `help:"names and addresses of partnered satellites in JSON list format" default:"[{\"name\":\"US1\",\"address\":\"https://us1.storj.io\"},{\"name\":\"EU1\",\"address\":\"https://eu1.storj.io\"},{\"name\":\"AP1\",\"address\":\"https://ap1.storj.io\"}]"` + GeneralRequestURL string `help:"url link to general request page" default:"https://supportdcs.storj.io/hc/en-us/requests/new?ticket_form_id=360000379291"` + ProjectLimitsIncreaseRequestURL string `help:"url link to project limit increase request page" default:"https://supportdcs.storj.io/hc/en-us/requests/new?ticket_form_id=360000683212"` + GatewayCredentialsRequestURL string `help:"url link for gateway credentials requests" default:"https://auth.storjshare.io" devDefault:"http://localhost:8000"` + IsBetaSatellite bool `help:"indicates if satellite is in beta" default:"false"` + BetaSatelliteFeedbackURL string `help:"url link for for beta satellite feedback" default:""` + BetaSatelliteSupportURL string `help:"url link for for beta satellite support" default:""` + DocumentationURL string `help:"url link to documentation" default:"https://docs.storj.io/"` + CouponCodeBillingUIEnabled bool `help:"indicates if user is allowed to add coupon codes to account from billing" default:"false"` + CouponCodeSignupUIEnabled bool `help:"indicates if user is allowed to add coupon codes to account from signup" default:"false"` + FileBrowserFlowDisabled bool `help:"indicates if file browser flow is disabled" default:"false"` + CSPEnabled bool `help:"indicates if Content Security Policy is enabled" devDefault:"false" releaseDefault:"true"` + LinksharingURL string `help:"url link for linksharing requests" default:"https://link.storjshare.io" devDefault:"http://localhost:8001"` + PathwayOverviewEnabled bool `help:"indicates if the overview onboarding step should render with pathways" default:"true"` + NewProjectDashboard bool `help:"indicates if new project dashboard should be used" default:"true"` + AllProjectsDashboard bool `help:"indicates if all projects dashboard should be used" default:"false"` + NewBillingScreen bool `help:"indicates if new billing screens should be used" default:"true"` + NewAccessGrantFlow bool `help:"indicates if new access grant flow should be used" default:"false"` + GeneratedAPIEnabled bool `help:"indicates if generated console api should be used" default:"false"` + OptionalSignupSuccessURL string `help:"optional url to external registration success page" default:""` + HomepageURL string `help:"url link to storj.io homepage" default:"https://www.storj.io"` + NativeTokenPaymentsEnabled bool `help:"indicates if storj native token payments system is enabled" default:"false"` OauthCodeExpiry time.Duration `help:"how long oauth authorization codes are issued for" default:"10m"` OauthAccessTokenExpiry time.Duration `help:"how long oauth access tokens are issued for" default:"24h"` @@ -252,6 +252,7 @@ func NewServer(logger *zap.Logger, config Config, service *console.Service, oidc server.withAuth(http.HandlerFunc(projectsController.GetSalt)), ).Methods(http.MethodGet) + router.HandleFunc("/config", server.frontendConfigHandler) router.HandleFunc("/registrationToken/", server.createRegistrationTokenHandler) router.HandleFunc("/robots.txt", server.seoHandler) @@ -645,6 +646,56 @@ func (server *Server) bucketUsageReportHandler(w http.ResponseWriter, r *http.Re } } +// frontendConfigHandler handles sending the frontend config to the client. +func (server *Server) frontendConfigHandler(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + defer mon.Task()(&ctx)(nil) + w.Header().Set(contentType, applicationJSON) + + cfg := FrontendConfig{ + ExternalAddress: server.config.ExternalAddress, + SatelliteName: server.config.SatelliteName, + SatelliteNodeURL: server.nodeURL.String(), + StripePublicKey: server.stripePublicKey, + PartneredSatellites: server.config.PartneredSatellites, + DefaultProjectLimit: server.config.DefaultProjectLimit, + GeneralRequestURL: server.config.GeneralRequestURL, + ProjectLimitsIncreaseRequestURL: server.config.ProjectLimitsIncreaseRequestURL, + GatewayCredentialsRequestURL: server.config.GatewayCredentialsRequestURL, + IsBetaSatellite: server.config.IsBetaSatellite, + BetaSatelliteFeedbackURL: server.config.BetaSatelliteFeedbackURL, + BetaSatelliteSupportURL: server.config.BetaSatelliteSupportURL, + DocumentationURL: server.config.DocumentationURL, + CouponCodeBillingUIEnabled: server.config.CouponCodeBillingUIEnabled, + CouponCodeSignupUIEnabled: server.config.CouponCodeSignupUIEnabled, + FileBrowserFlowDisabled: server.config.FileBrowserFlowDisabled, + LinksharingURL: server.config.LinksharingURL, + PathwayOverviewEnabled: server.config.PathwayOverviewEnabled, + DefaultPaidStorageLimit: server.config.UsageLimits.Storage.Paid, + DefaultPaidBandwidthLimit: server.config.UsageLimits.Bandwidth.Paid, + Captcha: server.config.Captcha, + NewProjectDashboard: server.config.NewProjectDashboard, + AllProjectsDashboard: server.config.AllProjectsDashboard, + NewBillingScreen: server.config.NewBillingScreen, + InactivityTimerEnabled: server.config.Session.InactivityTimerEnabled, + InactivityTimerDuration: server.config.Session.InactivityTimerDuration, + InactivityTimerViewerEnabled: server.config.Session.InactivityTimerViewerEnabled, + OptionalSignupSuccessURL: server.config.OptionalSignupSuccessURL, + HomepageURL: server.config.HomepageURL, + NativeTokenPaymentsEnabled: server.config.NativeTokenPaymentsEnabled, + PasswordMinimumLength: console.PasswordMinimumLength, + PasswordMaximumLength: console.PasswordMaximumLength, + ABTestingEnabled: server.config.ABTesting.Enabled, + NewAccessGrantFlow: server.config.NewAccessGrantFlow, + } + + err := json.NewEncoder(w).Encode(&cfg) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + server.log.Error("failed to write frontend config", zap.Error(err)) + } +} + // createRegistrationTokenHandler is web app http handler function. func (server *Server) createRegistrationTokenHandler(w http.ResponseWriter, r *http.Request) { ctx := r.Context() diff --git a/satellite/console/satellites.go b/satellite/console/satellites.go deleted file mode 100644 index 23c66e9a8..000000000 --- a/satellite/console/satellites.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (C) 2022 Storj Labs, Inc. -// See LICENSE for copying information. - -package console - -import ( - "encoding/json" -) - -// Satellites is a configuration value that contains a list of satellite names and addresses. -// Format should be [{"name": "","address": ""],{"name": "","address": ""},...] in valid JSON format. -// -// Can be used as a flag. -type Satellites []satellite - -type satellite struct { - Name string `json:"name"` - Address string `json:"address"` -} - -// Type implements pflag.Value. -func (Satellites) Type() string { return "console.Satellites" } - -// String is required for pflag.Value. -func (sl *Satellites) String() string { - satellites, err := json.Marshal(*sl) - if err != nil { - return "" - } - - return string(satellites) -} - -// Set does validation on the configured JSON. -func (sl *Satellites) Set(s string) (err error) { - satellites := make([]satellite, 3) - - err = json.Unmarshal([]byte(s), &satellites) - if err != nil { - return err - } - - *sl = satellites - return -} diff --git a/satellite/console/service.go b/satellite/console/service.go index 65484898a..5efe585ae 100644 --- a/satellite/console/service.go +++ b/satellite/console/service.go @@ -178,21 +178,21 @@ type Config struct { // CaptchaConfig contains configurations for login/registration captcha system. type CaptchaConfig struct { - Login MultiCaptchaConfig - Registration MultiCaptchaConfig + Login MultiCaptchaConfig `json:"login"` + Registration MultiCaptchaConfig `json:"registration"` } // MultiCaptchaConfig contains configurations for Recaptcha and Hcaptcha systems. type MultiCaptchaConfig struct { - Recaptcha SingleCaptchaConfig - Hcaptcha SingleCaptchaConfig + Recaptcha SingleCaptchaConfig `json:"recaptcha"` + Hcaptcha SingleCaptchaConfig `json:"hcaptcha"` } // SingleCaptchaConfig contains configurations abstract captcha system. type SingleCaptchaConfig struct { - Enabled bool `help:"whether or not captcha is enabled" default:"false"` - SiteKey string `help:"captcha site key"` - SecretKey string `help:"captcha secret key"` + Enabled bool `help:"whether or not captcha is enabled" default:"false" json:"enabled"` + SiteKey string `help:"captcha site key" json:"siteKey"` + SecretKey string `help:"captcha secret key" json:"-"` } // SessionConfig contains configurations for session management.