Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion apps/ocp-plugin/src/components/AppContext/AppContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion apps/ocp-plugin/src/utils/apiCalls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`;
Expand Down
6 changes: 4 additions & 2 deletions proxy/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Comment on lines +75 to +77

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Normalize IS_OCP_PLUGIN before gating this route.

This branch still depends on config.OcpPlugin == "true", but proxy/config/config.go defines OcpPlugin as a raw env string. Values like TRUE, 1, or yes leave /api/ui-settings unregistered, so the OCP plugin falls back to false and the RHEM fix never activates.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@proxy/app.go` around lines 75 - 77, The /ui-settings route gating in app.go
is using a raw string comparison on config.OcpPlugin, so normalize IS_OCP_PLUGIN
before this branch instead of checking only for "true". Update the config
handling in proxy/config/config.go or the route registration logic in app.go so
values like TRUE, 1, or yes are treated as enabled, and keep the change anchored
around the existing OcpPlugin and UISettingsHandler path registration.

// 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)
Expand Down
6 changes: 5 additions & 1 deletion proxy/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion proxy/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
29 changes: 29 additions & 0 deletions proxy/server/settings.go
Original file line number Diff line number Diff line change
@@ -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
Comment thread
celdrake marked this conversation as resolved.
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Loading