diff --git a/apps/ocp-plugin/src/components/AppContext/AppContext.tsx b/apps/ocp-plugin/src/components/AppContext/AppContext.tsx index 517076359..d84519383 100644 --- a/apps/ocp-plugin/src/components/AppContext/AppContext.tsx +++ b/apps/ocp-plugin/src/components/AppContext/AppContext.tsx @@ -23,10 +23,34 @@ import { Prompt } from 'react-router-dom'; import { getUser } from '@openshift-console/dynamic-plugin-sdk/lib/app/core/reducers'; import { useSelector } from 'react-redux'; import { useFetch } from '../../hooks/useFetch'; +import { apiProxy } from '../../utils/apiCalls'; import '@flightctl/ui-components/src/styles/global.css'; import './AppContext.css'; +const useUiSettings = (): { isRHEM: boolean } => { + const [settings, setSettings] = React.useState({ isRHEM: window.isRHEM ?? false }); + + React.useEffect(() => { + const controller = new AbortController(); + + fetch(`${apiProxy}/ui-settings`, { signal: controller.signal }) + .then((response) => (response.ok ? response.json() : Promise.reject(new Error('Failed to load UI settings')))) + .then((data: { isRHEM?: boolean }) => { + const isRHEM = !!data.isRHEM; + window.isRHEM = isRHEM; + setSettings({ isRHEM }); + }) + .catch(() => { + // Keep defaults when settings cannot be loaded. + }); + + return () => controller.abort(); + }, []); + + return settings; +}; + /** * OCP Plugin App Context Provider * The OCP plugin system calls useValuesAppContext separately and passes the value as a prop @@ -78,10 +102,11 @@ const appRoutes = { export const useValuesAppContext = (): AppContextProps => { const fetch = useFetch(); const userInfo = useSelector(getUser); + const settings = useUiSettings(); return { appType: FlightCtlApp.OCP, - settings: {}, + settings, user: userInfo?.username || '', router: { Link, diff --git a/apps/ocp-plugin/src/utils/apiCalls.ts b/apps/ocp-plugin/src/utils/apiCalls.ts index 58aba8f73..af48a211a 100644 --- a/apps/ocp-plugin/src/utils/apiCalls.ts +++ b/apps/ocp-plugin/src/utils/apiCalls.ts @@ -43,7 +43,7 @@ const apiServer = `${window.location.hostname}${ window.FCTL_API_PORT ? `:${window.FCTL_API_PORT}` : '' }/api/proxy/plugin/flightctl-plugin/api-proxy`; -const uiProxy = `${window.location.protocol}//${apiServer}`; +export const uiProxy = `${window.location.protocol}//${apiServer}`; export const apiProxy = `${uiProxy}/api`; const alertsAPI = `${apiProxy}/alerts`; diff --git a/proxy/app.go b/proxy/app.go index 7c324a154..96eee50c6 100644 --- a/proxy/app.go +++ b/proxy/app.go @@ -72,8 +72,10 @@ func main() { // Viewing the login command is always available apiRouter.HandleFunc("/login-command", authHandler.GetLoginCommand) - // Login/logout actions are only available in the standalone UI - if config.OcpPlugin != "true" { + if config.OcpPlugin == "true" { + apiRouter.HandleFunc("/ui-settings", server.UISettingsHandler).Methods(http.MethodGet) + } else { + // Login/logout actions are only available in the standalone UI apiRouter.HandleFunc("/login", authHandler.Login) apiRouter.HandleFunc("/login/info", authHandler.GetUserInfo) apiRouter.HandleFunc("/login/refresh", authHandler.Refresh) diff --git a/proxy/config/config.go b/proxy/config/config.go index b1979803e..045830158 100644 --- a/proxy/config/config.go +++ b/proxy/config/config.go @@ -21,11 +21,15 @@ var ( BaseUiUrl = getEnvUrlVar("BASE_UI_URL", "http://localhost:9000") AuthInsecure = getEnvVar("AUTH_INSECURE_SKIP_VERIFY", "") OcpPlugin = getEnvVar("IS_OCP_PLUGIN", "false") - IsRHEM = getEnvVar("IS_RHEM", "") +) + +var ( // TrustXForwardedHeaders enables use of X-Forwarded-Proto and X-Forwarded-Host for request // origin (e.g. TLS termination at an ingress). When false, only r.TLS and r.Host are used. // Set to true when a trusted reverse proxy sets these headers; see also TrustedProxyNets. TrustXForwardedHeaders = parseBoolEnv("TRUST_X_FORWARDED_HEADERS", false) + // IsRHEM enables the RHEM mode for the UI. + IsRHEM = parseBoolEnv("IS_RHEM", false) ) // trustedProxyNets is parsed from TRUSTED_PROXY_CIDRS (comma-separated). When non-empty and diff --git a/proxy/server/server.go b/proxy/server/server.go index 1d270f4b2..30c4ad1ad 100644 --- a/proxy/server/server.go +++ b/proxy/server/server.go @@ -16,7 +16,7 @@ type SpaHandler struct{} func serveIndexPage(w http.ResponseWriter, r *http.Request) { indexName := "index" - if config.IsRHEM == "true" { + if config.IsRHEM { indexName = "index-rhem" } content, err := os.ReadFile(fmt.Sprintf("./dist/%s.html", indexName)) diff --git a/proxy/server/settings.go b/proxy/server/settings.go new file mode 100644 index 000000000..c8562c64a --- /dev/null +++ b/proxy/server/settings.go @@ -0,0 +1,29 @@ +package server + +import ( + "encoding/json" + "net/http" + + "github.com/flightctl/flightctl-ui/config" +) + +type uiSettings struct { + IsRHEM bool `json:"isRHEM"` +} + +// UISettingsHandler serves the UI configuration settings as JSON. +// It returns the current RHEM mode status and other UI-specific flags. +func UISettingsHandler(w http.ResponseWriter, _ *http.Request) { + settings := uiSettings{ + IsRHEM: config.IsRHEM, + } + payload, err := json.Marshal(settings) + if err != nil { + http.Error(w, "Failed to encode settings", http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/json") + if _, err := w.Write(payload); err != nil { + return + } +}