@replicated/portal-components 0.0.19 → 0.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/metadata/registry.json +2 -2
- package/components/metadata/registry.md +2 -2
- package/dist/actions/change-team.js +66 -7
- package/dist/actions/change-team.js.map +1 -1
- package/dist/actions/index.d.mts +3 -1
- package/dist/actions/index.d.ts +3 -1
- package/dist/actions/index.js +182 -465
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/install-actions.d.mts +3 -1
- package/dist/actions/install-actions.d.ts +3 -1
- package/dist/actions/install-actions.js +58 -5
- package/dist/actions/install-actions.js.map +1 -1
- package/dist/actions/service-account.d.mts +3 -1
- package/dist/actions/service-account.d.ts +3 -1
- package/dist/actions/service-account.js +58 -5
- package/dist/actions/service-account.js.map +1 -1
- package/dist/actions/support-bundles.d.mts +3 -1
- package/dist/actions/support-bundles.d.ts +3 -1
- package/dist/actions/support-bundles.js +58 -5
- package/dist/actions/support-bundles.js.map +1 -1
- package/dist/actions/team-settings.d.mts +3 -1
- package/dist/actions/team-settings.d.ts +3 -1
- package/dist/actions/team-settings.js +91 -27
- package/dist/actions/team-settings.js.map +1 -1
- package/dist/actions/trial-signup.d.mts +24 -0
- package/dist/actions/trial-signup.d.ts +24 -0
- package/dist/actions/trial-signup.js +482 -0
- package/dist/actions/trial-signup.js.map +1 -0
- package/dist/actions/user-settings.d.mts +3 -1
- package/dist/actions/user-settings.d.ts +3 -1
- package/dist/actions/user-settings.js +58 -5
- package/dist/actions/user-settings.js.map +1 -1
- package/dist/airgap-instances.d.mts +3 -1
- package/dist/airgap-instances.d.ts +3 -1
- package/dist/airgap-instances.js +41 -112
- package/dist/airgap-instances.js.map +1 -1
- package/dist/branding-BsMSywts.d.mts +36 -0
- package/dist/branding-BsMSywts.d.ts +36 -0
- package/dist/error-page.js +10 -2
- package/dist/error-page.js.map +1 -1
- package/dist/error.js +10 -2
- package/dist/error.js.map +1 -1
- package/dist/esm/actions/change-team.js +66 -7
- package/dist/esm/actions/change-team.js.map +1 -1
- package/dist/esm/actions/index.js +181 -462
- package/dist/esm/actions/index.js.map +1 -1
- package/dist/esm/actions/install-actions.js +58 -5
- package/dist/esm/actions/install-actions.js.map +1 -1
- package/dist/esm/actions/service-account.js +58 -5
- package/dist/esm/actions/service-account.js.map +1 -1
- package/dist/esm/actions/support-bundles.js +58 -5
- package/dist/esm/actions/support-bundles.js.map +1 -1
- package/dist/esm/actions/team-settings.js +91 -27
- package/dist/esm/actions/team-settings.js.map +1 -1
- package/dist/esm/actions/trial-signup.js +478 -0
- package/dist/esm/actions/trial-signup.js.map +1 -0
- package/dist/esm/actions/user-settings.js +58 -5
- package/dist/esm/actions/user-settings.js.map +1 -1
- package/dist/esm/airgap-instances.js +40 -112
- package/dist/esm/airgap-instances.js.map +1 -1
- package/dist/esm/error-page.js +10 -2
- package/dist/esm/error-page.js.map +1 -1
- package/dist/esm/error.js +10 -2
- package/dist/esm/error.js.map +1 -1
- package/dist/esm/helm-install-wizard.js +118 -79
- package/dist/esm/helm-install-wizard.js.map +1 -1
- package/dist/esm/index.js +706 -438
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/install-actions.js +40 -5
- package/dist/esm/install-actions.js.map +1 -1
- package/dist/esm/install-card.js +9 -6
- package/dist/esm/install-card.js.map +1 -1
- package/dist/esm/install-targets.js +9 -2
- package/dist/esm/install-targets.js.map +1 -1
- package/dist/esm/instance-card.js +39 -111
- package/dist/esm/instance-card.js.map +1 -1
- package/dist/esm/join-team.js +9 -3
- package/dist/esm/join-team.js.map +1 -1
- package/dist/esm/license-card.js +24 -22
- package/dist/esm/license-card.js.map +1 -1
- package/dist/esm/license-details.js +128 -334
- package/dist/esm/license-details.js.map +1 -1
- package/dist/esm/linux-install-wizard.js +95 -41
- package/dist/esm/linux-install-wizard.js.map +1 -1
- package/dist/esm/login.js +20 -4
- package/dist/esm/login.js.map +1 -1
- package/dist/esm/middleware.js +33 -0
- package/dist/esm/middleware.js.map +1 -0
- package/dist/esm/online-instance-list.js +40 -112
- package/dist/esm/online-instance-list.js.map +1 -1
- package/dist/esm/release-history-panel.js +27 -14
- package/dist/esm/release-history-panel.js.map +1 -1
- package/dist/esm/saml-callback-client.js +82 -0
- package/dist/esm/saml-callback-client.js.map +1 -0
- package/dist/esm/saml-handlers.js +138 -0
- package/dist/esm/saml-handlers.js.map +1 -0
- package/dist/esm/security-card.js +53 -38
- package/dist/esm/security-card.js.map +1 -1
- package/dist/esm/service-accounts-tab.js +800 -0
- package/dist/esm/service-accounts-tab.js.map +1 -0
- package/dist/esm/support-bundle-collection-card.js +48 -24
- package/dist/esm/support-bundle-collection-card.js.map +1 -1
- package/dist/esm/support-bundles-card.js +10 -5
- package/dist/esm/support-bundles-card.js.map +1 -1
- package/dist/esm/support-card.js +37 -5
- package/dist/esm/support-card.js.map +1 -1
- package/dist/esm/team-selection.js +5 -1
- package/dist/esm/team-selection.js.map +1 -1
- package/dist/esm/team-settings-card.js +5 -2
- package/dist/esm/team-settings-card.js.map +1 -1
- package/dist/esm/team-settings.js +7 -2
- package/dist/esm/team-settings.js.map +1 -1
- package/dist/esm/top-nav-user-menu.js +5 -1
- package/dist/esm/top-nav-user-menu.js.map +1 -1
- package/dist/esm/top-nav.js +175 -62
- package/dist/esm/top-nav.js.map +1 -1
- package/dist/esm/trial-signup.js +256 -0
- package/dist/esm/trial-signup.js.map +1 -0
- package/dist/esm/update-layout.js +175 -62
- package/dist/esm/update-layout.js.map +1 -1
- package/dist/esm/updates-card.js +15 -4
- package/dist/esm/updates-card.js.map +1 -1
- package/dist/esm/upload-support-bundle-modal.js +9 -4
- package/dist/esm/upload-support-bundle-modal.js.map +1 -1
- package/dist/esm/user-settings-card.js +5 -2
- package/dist/esm/user-settings-card.js.map +1 -1
- package/dist/esm/user-settings.js +12 -6
- package/dist/esm/user-settings.js.map +1 -1
- package/dist/esm/utils/index.js +204 -13
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/fetch-license-iTyF7_GY.d.mts +81 -0
- package/dist/fetch-license-iTyF7_GY.d.ts +81 -0
- package/dist/helm-install-wizard.d.mts +11 -3
- package/dist/helm-install-wizard.d.ts +11 -3
- package/dist/helm-install-wizard.js +118 -79
- package/dist/helm-install-wizard.js.map +1 -1
- package/dist/{index-BAiVrSSR.d.mts → index-DyzJ0yKD.d.mts} +48 -50
- package/dist/{index-DWt-N5od.d.ts → index-sMbq94M7.d.ts} +48 -50
- package/dist/index.d.mts +8 -2
- package/dist/index.d.ts +8 -2
- package/dist/index.js +726 -438
- package/dist/index.js.map +1 -1
- package/dist/install-actions.d.mts +4 -2
- package/dist/install-actions.d.ts +4 -2
- package/dist/install-actions.js +40 -5
- package/dist/install-actions.js.map +1 -1
- package/dist/install-card.d.mts +2 -3
- package/dist/install-card.d.ts +2 -3
- package/dist/install-card.js +9 -6
- package/dist/install-card.js.map +1 -1
- package/dist/install-targets.js +9 -2
- package/dist/install-targets.js.map +1 -1
- package/dist/instance-card.d.mts +3 -1
- package/dist/instance-card.d.ts +3 -1
- package/dist/instance-card.js +40 -111
- package/dist/instance-card.js.map +1 -1
- package/dist/join-team.js +9 -3
- package/dist/join-team.js.map +1 -1
- package/dist/license-card.d.mts +2 -3
- package/dist/license-card.d.ts +2 -3
- package/dist/license-card.js +24 -22
- package/dist/license-card.js.map +1 -1
- package/dist/license-details.js +128 -334
- package/dist/license-details.js.map +1 -1
- package/dist/linux-install-wizard.d.mts +9 -3
- package/dist/linux-install-wizard.d.ts +9 -3
- package/dist/linux-install-wizard.js +95 -41
- package/dist/linux-install-wizard.js.map +1 -1
- package/dist/login.d.mts +4 -0
- package/dist/login.d.ts +4 -0
- package/dist/login.js +20 -4
- package/dist/login.js.map +1 -1
- package/dist/middleware.d.mts +13 -0
- package/dist/middleware.d.ts +13 -0
- package/dist/middleware.js +35 -0
- package/dist/middleware.js.map +1 -0
- package/dist/online-instance-list.d.mts +3 -1
- package/dist/online-instance-list.d.ts +3 -1
- package/dist/online-instance-list.js +41 -112
- package/dist/online-instance-list.js.map +1 -1
- package/dist/pending-installations.d.mts +3 -1
- package/dist/pending-installations.d.ts +3 -1
- package/dist/release-history-panel.js +27 -14
- package/dist/release-history-panel.js.map +1 -1
- package/dist/saml-callback-client.d.mts +36 -0
- package/dist/saml-callback-client.d.ts +36 -0
- package/dist/saml-callback-client.js +88 -0
- package/dist/saml-callback-client.js.map +1 -0
- package/dist/saml-handlers.d.mts +50 -0
- package/dist/saml-handlers.d.ts +50 -0
- package/dist/saml-handlers.js +141 -0
- package/dist/saml-handlers.js.map +1 -0
- package/dist/security-card.d.mts +3 -1
- package/dist/security-card.d.ts +3 -1
- package/dist/security-card.js +53 -38
- package/dist/security-card.js.map +1 -1
- package/dist/service-accounts-tab.d.mts +51 -0
- package/dist/service-accounts-tab.d.ts +51 -0
- package/dist/service-accounts-tab.js +802 -0
- package/dist/service-accounts-tab.js.map +1 -0
- package/dist/styles.css +375 -127
- package/dist/support-bundle-collection-card.d.mts +1 -1
- package/dist/support-bundle-collection-card.d.ts +1 -1
- package/dist/support-bundle-collection-card.js +47 -23
- package/dist/support-bundle-collection-card.js.map +1 -1
- package/dist/support-bundles-card.d.mts +4 -2
- package/dist/support-bundles-card.d.ts +4 -2
- package/dist/support-bundles-card.js +10 -5
- package/dist/support-bundles-card.js.map +1 -1
- package/dist/support-card.js +37 -5
- package/dist/support-card.js.map +1 -1
- package/dist/team-selection.js +5 -1
- package/dist/team-selection.js.map +1 -1
- package/dist/team-settings-card.js +5 -2
- package/dist/team-settings-card.js.map +1 -1
- package/dist/team-settings.js +7 -2
- package/dist/team-settings.js.map +1 -1
- package/dist/{top-nav-IRIn66wS.d.ts → top-nav-BUQAGoG1.d.mts} +14 -2
- package/dist/{top-nav-IRIn66wS.d.mts → top-nav-CEqw0KpO.d.ts} +14 -2
- package/dist/top-nav-user-menu.js +5 -1
- package/dist/top-nav-user-menu.js.map +1 -1
- package/dist/top-nav.d.mts +2 -1
- package/dist/top-nav.d.ts +2 -1
- package/dist/top-nav.js +175 -62
- package/dist/top-nav.js.map +1 -1
- package/dist/trial-signup.d.mts +31 -0
- package/dist/trial-signup.d.ts +31 -0
- package/dist/trial-signup.js +258 -0
- package/dist/trial-signup.js.map +1 -0
- package/dist/update-layout.js +175 -62
- package/dist/update-layout.js.map +1 -1
- package/dist/updates-card.js +15 -4
- package/dist/updates-card.js.map +1 -1
- package/dist/upload-support-bundle-modal.js +9 -4
- package/dist/upload-support-bundle-modal.js.map +1 -1
- package/dist/user-settings-card.js +5 -2
- package/dist/user-settings-card.js.map +1 -1
- package/dist/user-settings.js +12 -6
- package/dist/user-settings.js.map +1 -1
- package/dist/utils/index.d.mts +74 -16
- package/dist/utils/index.d.ts +74 -16
- package/dist/utils/index.js +215 -12
- package/dist/utils/index.js.map +1 -1
- package/package.json +37 -2
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var react = require('react');
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
5
|
var buffer = require('buffer');
|
|
6
|
+
var headers = require('next/headers');
|
|
6
7
|
var Link = require('next/link');
|
|
7
8
|
|
|
8
9
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -13,10 +14,119 @@ var Link__default = /*#__PURE__*/_interopDefault(Link);
|
|
|
13
14
|
* Enterprise Portal Components
|
|
14
15
|
* This file is generated by tsup. Do not edit manually.
|
|
15
16
|
*/
|
|
17
|
+
var __defProp = Object.defineProperty;
|
|
18
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
19
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
20
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
21
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
22
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
23
|
+
}) : x)(function(x) {
|
|
24
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
25
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
26
|
+
});
|
|
27
|
+
var __esm = (fn, res) => function __init() {
|
|
28
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
29
|
+
};
|
|
30
|
+
var __export = (target, all) => {
|
|
31
|
+
for (var name in all)
|
|
32
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
33
|
+
};
|
|
34
|
+
var __copyProps = (to, from, except, desc) => {
|
|
35
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
36
|
+
for (let key of __getOwnPropNames(from))
|
|
37
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
38
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
39
|
+
}
|
|
40
|
+
return to;
|
|
41
|
+
};
|
|
42
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
43
|
+
|
|
44
|
+
// datadog/tracer.ts
|
|
45
|
+
var tracer_exports = {};
|
|
46
|
+
__export(tracer_exports, {
|
|
47
|
+
default: () => tracer_default
|
|
48
|
+
});
|
|
49
|
+
var rawFlag, isEnabled, tracer, getRoutePattern, tracer_default;
|
|
50
|
+
var init_tracer = __esm({
|
|
51
|
+
"datadog/tracer.ts"() {
|
|
52
|
+
rawFlag = String(process.env.USE_DATADOG_APM || "").toLowerCase();
|
|
53
|
+
isEnabled = rawFlag === "true";
|
|
54
|
+
process.env.DD_TRACE_ENABLED = isEnabled ? "1" : "0";
|
|
55
|
+
tracer = null;
|
|
56
|
+
if (isEnabled) {
|
|
57
|
+
const serviceName = process.env.DD_SERVICE || "enterprise-portal";
|
|
58
|
+
const environment = process.env.DD_ENV || process.env.NODE_ENV || "development";
|
|
59
|
+
const version = process.env.DD_VERSION || process.env.NEXT_PUBLIC_VERSION || "0.0.0-dev";
|
|
60
|
+
const agentHost = process.env.DD_AGENT_HOST || process.env.DATADOG_AGENT_HOST || "127.0.0.1";
|
|
61
|
+
const agentPort = process.env.DD_TRACE_AGENT_PORT || "8126";
|
|
62
|
+
process.env.DD_SERVICE = serviceName;
|
|
63
|
+
process.env.DD_ENV = environment;
|
|
64
|
+
{
|
|
65
|
+
process.env.DD_VERSION = version;
|
|
66
|
+
}
|
|
67
|
+
process.env.DD_AGENT_HOST = agentHost;
|
|
68
|
+
process.env.DD_TRACE_AGENT_PORT = agentPort;
|
|
69
|
+
const dbmPropagationMode = process.env.DD_DBM_PROPAGATION_MODE || "full";
|
|
70
|
+
process.env.DD_DBM_PROPAGATION_MODE = dbmPropagationMode;
|
|
71
|
+
try {
|
|
72
|
+
const ddTrace = __require("dd-trace");
|
|
73
|
+
tracer = ddTrace.init({
|
|
74
|
+
service: serviceName,
|
|
75
|
+
env: environment,
|
|
76
|
+
version,
|
|
77
|
+
logInjection: true,
|
|
78
|
+
runtimeMetrics: true,
|
|
79
|
+
appsec: false,
|
|
80
|
+
profiling: false,
|
|
81
|
+
startupLogs: true
|
|
82
|
+
// Enable for debugging
|
|
83
|
+
});
|
|
84
|
+
console.log(`[datadog] Tracer initialized: service=${serviceName}, env=${environment}, version=${version}, agent=${agentHost}:${agentPort}`);
|
|
85
|
+
tracer.use("dns", false);
|
|
86
|
+
tracer.use("net", false);
|
|
87
|
+
tracer.use("http", {
|
|
88
|
+
server: {
|
|
89
|
+
hooks: {
|
|
90
|
+
request: (span, req) => {
|
|
91
|
+
if (!span) return;
|
|
92
|
+
const url = req?.url || "";
|
|
93
|
+
const method = req?.method || "GET";
|
|
94
|
+
const path = url.split("?")[0];
|
|
95
|
+
if (path.startsWith("/_next/")) {
|
|
96
|
+
span.context()._trace.isRecording = false;
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const routePattern = getRoutePattern(path);
|
|
100
|
+
span.setTag("resource.name", `${method} ${routePattern}`);
|
|
101
|
+
span.setTag("http.route", routePattern);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
} catch (err) {
|
|
107
|
+
console.error("[datadog] failed to initialize tracing", err);
|
|
108
|
+
tracer = null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
getRoutePattern = (path) => {
|
|
112
|
+
const routePatterns = [
|
|
113
|
+
// Update instance routes - normalize dynamic segments (capture suffix to preserve sub-routes)
|
|
114
|
+
{ pattern: /^\/update\/instance\/[^/]+(.*)$/, replacement: "/update/instance/[instanceId]$1" }
|
|
115
|
+
];
|
|
116
|
+
for (const { pattern, replacement } of routePatterns) {
|
|
117
|
+
if (pattern.test(path)) {
|
|
118
|
+
return path.replace(pattern, replacement);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return path;
|
|
122
|
+
};
|
|
123
|
+
tracer_default = tracer;
|
|
124
|
+
}
|
|
125
|
+
});
|
|
16
126
|
|
|
17
127
|
// package.json
|
|
18
128
|
var package_default = {
|
|
19
|
-
version: "0.0.
|
|
129
|
+
version: "0.0.21"};
|
|
20
130
|
|
|
21
131
|
// src/tokens/index.ts
|
|
22
132
|
var baseTokens = {
|
|
@@ -132,6 +242,12 @@ var Button = react.forwardRef(
|
|
|
132
242
|
Button.displayName = "Button";
|
|
133
243
|
|
|
134
244
|
// src/utils/api-client.ts
|
|
245
|
+
var UnauthorizedError = class extends Error {
|
|
246
|
+
constructor(message = "Unauthorized") {
|
|
247
|
+
super(message);
|
|
248
|
+
this.name = "UnauthorizedError";
|
|
249
|
+
}
|
|
250
|
+
};
|
|
135
251
|
function isRedirectError(error) {
|
|
136
252
|
return typeof error === "object" && error !== null && "digest" in error && typeof error.digest === "string" && error.digest.startsWith("NEXT_REDIRECT");
|
|
137
253
|
}
|
|
@@ -157,8 +273,17 @@ async function handle401() {
|
|
|
157
273
|
const { redirect } = await import('next/navigation');
|
|
158
274
|
return redirect("/?expired=1");
|
|
159
275
|
}
|
|
276
|
+
function isErrorPage(url) {
|
|
277
|
+
try {
|
|
278
|
+
const urlObj = new URL(url);
|
|
279
|
+
return urlObj.pathname === "/error";
|
|
280
|
+
} catch {
|
|
281
|
+
return url === "/error" || url.startsWith("/error?");
|
|
282
|
+
}
|
|
283
|
+
}
|
|
160
284
|
async function handleServerError(statusCode) {
|
|
161
285
|
const { redirect } = await import('next/navigation');
|
|
286
|
+
const { cookies: cookies2 } = await import('next/headers');
|
|
162
287
|
let sourceUrl;
|
|
163
288
|
try {
|
|
164
289
|
const { headers } = await import('next/headers');
|
|
@@ -166,12 +291,20 @@ async function handleServerError(statusCode) {
|
|
|
166
291
|
const referer = headersList.get("referer");
|
|
167
292
|
const host = headersList.get("host");
|
|
168
293
|
const pathname = headersList.get("x-invoke-path") || headersList.get("x-forwarded-path");
|
|
169
|
-
if (referer) {
|
|
294
|
+
if (referer && !isErrorPage(referer)) {
|
|
170
295
|
sourceUrl = referer;
|
|
171
296
|
} else if (host && pathname) {
|
|
172
297
|
const protocol = headersList.get("x-forwarded-proto") || "https";
|
|
173
298
|
sourceUrl = `${protocol}://${host}${pathname}`;
|
|
174
299
|
}
|
|
300
|
+
if (!sourceUrl || isErrorPage(sourceUrl)) {
|
|
301
|
+
const cookieStore = await cookies2();
|
|
302
|
+
const preservedSource = cookieStore.get("portal_error_source");
|
|
303
|
+
if (preservedSource?.value) {
|
|
304
|
+
sourceUrl = decodeURIComponent(preservedSource.value);
|
|
305
|
+
cookieStore.delete("portal_error_source");
|
|
306
|
+
}
|
|
307
|
+
}
|
|
175
308
|
} catch (error) {
|
|
176
309
|
console.debug("[portal-components] Could not determine source URL", error);
|
|
177
310
|
}
|
|
@@ -182,6 +315,359 @@ async function handleServerError(statusCode) {
|
|
|
182
315
|
return redirect(`/error?${params.toString()}`);
|
|
183
316
|
}
|
|
184
317
|
|
|
318
|
+
// src/utils/observability/tracing.ts
|
|
319
|
+
var tracerCache = void 0;
|
|
320
|
+
function getTracer() {
|
|
321
|
+
if (tracerCache !== void 0) {
|
|
322
|
+
return tracerCache;
|
|
323
|
+
}
|
|
324
|
+
const rawFlag2 = String(process.env.USE_DATADOG_APM || "").toLowerCase();
|
|
325
|
+
const isEnabled2 = rawFlag2 === "true";
|
|
326
|
+
if (!isEnabled2) {
|
|
327
|
+
tracerCache = null;
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
try {
|
|
331
|
+
const tracerModule = (init_tracer(), __toCommonJS(tracer_exports));
|
|
332
|
+
const tracer2 = tracerModule.default || tracerModule;
|
|
333
|
+
if (tracer2 && typeof tracer2.trace === "function") {
|
|
334
|
+
tracerCache = tracer2;
|
|
335
|
+
return tracerCache;
|
|
336
|
+
}
|
|
337
|
+
} catch (err) {
|
|
338
|
+
console.warn("Failed to load tracer:", err);
|
|
339
|
+
}
|
|
340
|
+
tracerCache = null;
|
|
341
|
+
return null;
|
|
342
|
+
}
|
|
343
|
+
async function withTrace(name, fn) {
|
|
344
|
+
const activeTracer = getTracer();
|
|
345
|
+
if (!activeTracer) {
|
|
346
|
+
return fn(void 0);
|
|
347
|
+
}
|
|
348
|
+
return activeTracer.trace(name, async (span) => {
|
|
349
|
+
if (span) {
|
|
350
|
+
span.setTag("component", "application");
|
|
351
|
+
}
|
|
352
|
+
try {
|
|
353
|
+
const result = await fn(span);
|
|
354
|
+
return result;
|
|
355
|
+
} catch (error) {
|
|
356
|
+
if (span) {
|
|
357
|
+
span.setTag("error", error);
|
|
358
|
+
}
|
|
359
|
+
throw error;
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
function traceServerAction(name, fn) {
|
|
364
|
+
const spanName = name.startsWith("server.action.") ? name : `server.action.${name}`;
|
|
365
|
+
const traced = async (...args) => {
|
|
366
|
+
return withTrace(spanName, async (span) => {
|
|
367
|
+
if (span) {
|
|
368
|
+
span.setTag("component", "server-action");
|
|
369
|
+
}
|
|
370
|
+
const result = await fn(...args);
|
|
371
|
+
return result;
|
|
372
|
+
});
|
|
373
|
+
};
|
|
374
|
+
return traced;
|
|
375
|
+
}
|
|
376
|
+
var deriveInstallMethods = (licenseData) => {
|
|
377
|
+
const methods = [];
|
|
378
|
+
if (licenseData.isKotsInstallEnabled) {
|
|
379
|
+
methods.push("Replicated KOTS");
|
|
380
|
+
}
|
|
381
|
+
if (licenseData.isHelmInstallEnabled) {
|
|
382
|
+
methods.push("Helm");
|
|
383
|
+
}
|
|
384
|
+
if (licenseData.isHelmAirgapEnabled) {
|
|
385
|
+
methods.push("Helm Airgap");
|
|
386
|
+
}
|
|
387
|
+
if (licenseData.isEmbeddedClusterDownloadEnabled || licenseData.isEmbeddedClusterMultiNodeEnabled) {
|
|
388
|
+
methods.push("Embedded Cluster");
|
|
389
|
+
}
|
|
390
|
+
if (licenseData.isKurlInstallEnabled) {
|
|
391
|
+
methods.push("kURL");
|
|
392
|
+
}
|
|
393
|
+
if (licenseData.isGitopsSupported) {
|
|
394
|
+
methods.push("GitOps");
|
|
395
|
+
}
|
|
396
|
+
return Array.from(new Set(methods));
|
|
397
|
+
};
|
|
398
|
+
var convertEntitlementsToFields = (entitlementFields, entitlementValues) => {
|
|
399
|
+
const valuesMap = /* @__PURE__ */ new Map();
|
|
400
|
+
entitlementValues.forEach((ev) => {
|
|
401
|
+
valuesMap.set(ev.name, ev.value);
|
|
402
|
+
});
|
|
403
|
+
return entitlementFields.filter((field) => field.hidden === 0).map((field) => ({
|
|
404
|
+
key: field.name,
|
|
405
|
+
label: field.title || field.name,
|
|
406
|
+
value: valuesMap.get(field.name) || field.defaultVal || null,
|
|
407
|
+
isSecret: field.type === "Password"
|
|
408
|
+
}));
|
|
409
|
+
};
|
|
410
|
+
async function fetchLicenseCore() {
|
|
411
|
+
const sessionStore = await headers.cookies();
|
|
412
|
+
const session = sessionStore.get("portal_session");
|
|
413
|
+
const token = session?.value;
|
|
414
|
+
if (!token) {
|
|
415
|
+
throw new Error("No session found - user must be authenticated");
|
|
416
|
+
}
|
|
417
|
+
const endpoint = `${getApiOrigin()}/enterprise-portal/license`;
|
|
418
|
+
if (process.env.NODE_ENV !== "production") {
|
|
419
|
+
console.debug("[portal-components] fetching license via %s (Enterprise Portal API)", endpoint);
|
|
420
|
+
}
|
|
421
|
+
const response = await authenticatedFetch(endpoint, {
|
|
422
|
+
method: "GET",
|
|
423
|
+
token,
|
|
424
|
+
headers: {
|
|
425
|
+
Accept: "application/json"
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
if (!response.ok) {
|
|
429
|
+
throw new Error(
|
|
430
|
+
`License request failed (${response.status} ${response.statusText})`
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
const envelope = await response.json();
|
|
434
|
+
const licenseData = envelope.data;
|
|
435
|
+
const license = {
|
|
436
|
+
...licenseData,
|
|
437
|
+
// Alias fields for backward compatibility
|
|
438
|
+
expiresAt: licenseData.expireAt,
|
|
439
|
+
environment: licenseData.licenseType,
|
|
440
|
+
// Extract channel names from channels array
|
|
441
|
+
releaseChannels: (licenseData.channels || []).map((ch) => ch.channelName),
|
|
442
|
+
// Derive install methods from feature flags
|
|
443
|
+
installMethods: deriveInstallMethods(licenseData),
|
|
444
|
+
// Convert entitlements to fields format
|
|
445
|
+
fields: convertEntitlementsToFields(licenseData.entitlementFields || [], licenseData.entitlementValues || [])
|
|
446
|
+
};
|
|
447
|
+
return license;
|
|
448
|
+
}
|
|
449
|
+
var fetchLicenseImpl = react.cache(fetchLicenseCore);
|
|
450
|
+
var fetchLicense = fetchLicenseImpl;
|
|
451
|
+
|
|
452
|
+
// src/utils/constants.ts
|
|
453
|
+
var DEFAULT_FAVICON = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='1.5'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cellipse cx='12' cy='12' rx='4' ry='10'/%3E%3Cpath d='M2 12h20'/%3E%3C/svg%3E";
|
|
454
|
+
var DEFAULT_PRIMARY_COLOR = "#4f46e5";
|
|
455
|
+
var DEFAULT_SECONDARY_COLOR = "#6366f1";
|
|
456
|
+
var isHttpApiOrigin = () => {
|
|
457
|
+
return process.env.REPLICATED_APP_ORIGIN?.startsWith("http://") || false;
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
// src/utils/branding.ts
|
|
461
|
+
var normalizeColor = (color) => {
|
|
462
|
+
if (!color || typeof color !== "string") {
|
|
463
|
+
return void 0;
|
|
464
|
+
}
|
|
465
|
+
const trimmed = color.trim();
|
|
466
|
+
if (/^#?[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$/.test(trimmed)) {
|
|
467
|
+
return trimmed.startsWith("#") ? trimmed : `#${trimmed}`;
|
|
468
|
+
}
|
|
469
|
+
console.debug("[portal-components] Invalid color format rejected (only hex supported):", trimmed);
|
|
470
|
+
return void 0;
|
|
471
|
+
};
|
|
472
|
+
var sanitizeUrlForCss = (url) => {
|
|
473
|
+
if (!url || typeof url !== "string") {
|
|
474
|
+
return void 0;
|
|
475
|
+
}
|
|
476
|
+
const trimmed = url.trim();
|
|
477
|
+
try {
|
|
478
|
+
const urlObj = new URL(trimmed);
|
|
479
|
+
if (!["http:", "https:", "data:"].includes(urlObj.protocol)) {
|
|
480
|
+
console.debug("[portal-components] Invalid URL protocol for background image:", urlObj.protocol);
|
|
481
|
+
return void 0;
|
|
482
|
+
}
|
|
483
|
+
} catch {
|
|
484
|
+
console.debug("[portal-components] Invalid URL format for background image:", trimmed);
|
|
485
|
+
return void 0;
|
|
486
|
+
}
|
|
487
|
+
const escaped = trimmed.replace(/\\/g, "\\\\").replace(/\)/g, "\\)").replace(/"/g, '\\"').replace(/'/g, "\\'").replace(/[\x00-\x1F\x7F]/g, "");
|
|
488
|
+
return escaped;
|
|
489
|
+
};
|
|
490
|
+
var decodeBranding = ({ brandingData }) => {
|
|
491
|
+
if (!brandingData || typeof brandingData !== "string") {
|
|
492
|
+
return {
|
|
493
|
+
primaryColor: DEFAULT_PRIMARY_COLOR,
|
|
494
|
+
secondaryColor: DEFAULT_SECONDARY_COLOR
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
try {
|
|
498
|
+
const decoded = buffer.Buffer.from(brandingData, "base64").toString("utf-8");
|
|
499
|
+
const parsed = JSON.parse(decoded);
|
|
500
|
+
const logo = typeof parsed.logo === "string" ? parsed.logo : void 0;
|
|
501
|
+
const titleRaw = typeof parsed.title === "string" ? parsed.title.trim() : "";
|
|
502
|
+
const title = titleRaw ? titleRaw : void 0;
|
|
503
|
+
const favicon = typeof parsed.favicon === "string" ? parsed.favicon : void 0;
|
|
504
|
+
const primaryColorRaw = parsed.primaryColor ?? parsed.primary_color;
|
|
505
|
+
const secondaryColorRaw = parsed.secondaryColor ?? parsed.secondary_color;
|
|
506
|
+
const primaryColor = normalizeColor(primaryColorRaw);
|
|
507
|
+
const secondaryColor = normalizeColor(secondaryColorRaw);
|
|
508
|
+
const supportPortalLink = typeof parsed.supportPortalLink === "string" ? parsed.supportPortalLink : void 0;
|
|
509
|
+
const backgroundRaw = parsed.background;
|
|
510
|
+
const background = backgroundRaw === "minimal" || backgroundRaw === "custom" || backgroundRaw === "image" ? backgroundRaw : void 0;
|
|
511
|
+
const backgroundImage = sanitizeUrlForCss(parsed.backgroundImage);
|
|
512
|
+
const backgroundGradientStart = normalizeColor(parsed.customColor1);
|
|
513
|
+
const backgroundGradientEnd = normalizeColor(parsed.customColor2);
|
|
514
|
+
return {
|
|
515
|
+
logo,
|
|
516
|
+
title,
|
|
517
|
+
favicon,
|
|
518
|
+
primaryColor: primaryColor || DEFAULT_PRIMARY_COLOR,
|
|
519
|
+
secondaryColor: secondaryColor || DEFAULT_SECONDARY_COLOR,
|
|
520
|
+
supportPortalLink,
|
|
521
|
+
background,
|
|
522
|
+
backgroundImage,
|
|
523
|
+
backgroundGradientStart,
|
|
524
|
+
backgroundGradientEnd
|
|
525
|
+
};
|
|
526
|
+
} catch (error) {
|
|
527
|
+
console.debug("[portal-components] unable to parse branding JSON", error);
|
|
528
|
+
return {
|
|
529
|
+
primaryColor: DEFAULT_PRIMARY_COLOR,
|
|
530
|
+
secondaryColor: DEFAULT_SECONDARY_COLOR
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
// src/utils/session.ts
|
|
536
|
+
async function validateSession(token) {
|
|
537
|
+
if (!token || typeof token !== "string" || !token.trim()) {
|
|
538
|
+
return false;
|
|
539
|
+
}
|
|
540
|
+
try {
|
|
541
|
+
const endpoint = `${getApiOrigin()}/enterprise-portal/user`;
|
|
542
|
+
const response = await fetch(endpoint, {
|
|
543
|
+
method: "GET",
|
|
544
|
+
headers: {
|
|
545
|
+
authorization: `Bearer ${token}`
|
|
546
|
+
},
|
|
547
|
+
// Short timeout for validation
|
|
548
|
+
signal: AbortSignal.timeout(5e3)
|
|
549
|
+
});
|
|
550
|
+
if (response.status === 401) {
|
|
551
|
+
return false;
|
|
552
|
+
}
|
|
553
|
+
return response.ok;
|
|
554
|
+
} catch (error) {
|
|
555
|
+
console.warn("[portal-components] session validation error:", error);
|
|
556
|
+
return true;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
async function deleteSessionCookie() {
|
|
560
|
+
const { cookies: cookies2 } = await import('next/headers');
|
|
561
|
+
const cookieStore = await cookies2();
|
|
562
|
+
cookieStore.delete("portal_session");
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// src/utils/format.ts
|
|
566
|
+
function formatBytes(bytes, decimals = 1) {
|
|
567
|
+
if (bytes === 0) return "0 Bytes";
|
|
568
|
+
const k = 1024;
|
|
569
|
+
const dm = decimals < 0 ? 0 : decimals;
|
|
570
|
+
const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
|
|
571
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
572
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
|
|
573
|
+
}
|
|
574
|
+
function formatDateShort(dateString) {
|
|
575
|
+
if (!dateString) return "Never";
|
|
576
|
+
const date = new Date(dateString);
|
|
577
|
+
if (isNaN(date.getTime())) {
|
|
578
|
+
return dateString;
|
|
579
|
+
}
|
|
580
|
+
return date.toLocaleDateString("en-US", {
|
|
581
|
+
year: "numeric",
|
|
582
|
+
month: "2-digit",
|
|
583
|
+
day: "2-digit"
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
function formatDate(dateString) {
|
|
587
|
+
if (!dateString) return "Never";
|
|
588
|
+
const date = new Date(dateString);
|
|
589
|
+
if (isNaN(date.getTime())) {
|
|
590
|
+
return dateString;
|
|
591
|
+
}
|
|
592
|
+
return date.toLocaleDateString("en-US", {
|
|
593
|
+
month: "short",
|
|
594
|
+
day: "numeric",
|
|
595
|
+
year: "numeric",
|
|
596
|
+
hour: "numeric",
|
|
597
|
+
minute: "2-digit",
|
|
598
|
+
hour12: true
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
function formatDateTime(dateString) {
|
|
602
|
+
const date = new Date(dateString);
|
|
603
|
+
if (isNaN(date.getTime())) {
|
|
604
|
+
return dateString;
|
|
605
|
+
}
|
|
606
|
+
return date.toLocaleString("en-US", {
|
|
607
|
+
timeZone: "UTC",
|
|
608
|
+
year: "numeric",
|
|
609
|
+
month: "2-digit",
|
|
610
|
+
day: "2-digit",
|
|
611
|
+
hour: "2-digit",
|
|
612
|
+
minute: "2-digit",
|
|
613
|
+
second: "2-digit",
|
|
614
|
+
hour12: false
|
|
615
|
+
}) + " UTC";
|
|
616
|
+
}
|
|
617
|
+
function formatDateTimeLocal(dateString) {
|
|
618
|
+
if (!dateString) return "N/A";
|
|
619
|
+
try {
|
|
620
|
+
const date = new Date(dateString);
|
|
621
|
+
if (isNaN(date.getTime())) {
|
|
622
|
+
return dateString;
|
|
623
|
+
}
|
|
624
|
+
return date.toLocaleDateString("en-US", {
|
|
625
|
+
month: "numeric",
|
|
626
|
+
day: "numeric",
|
|
627
|
+
year: "numeric",
|
|
628
|
+
hour: "numeric",
|
|
629
|
+
minute: "2-digit",
|
|
630
|
+
hour12: true
|
|
631
|
+
});
|
|
632
|
+
} catch {
|
|
633
|
+
return "N/A";
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// src/utils/release-helpers.ts
|
|
638
|
+
function convertToReleaseEntry(release, channelName, options) {
|
|
639
|
+
const sections = [];
|
|
640
|
+
if (release.release_notes && release.release_notes.trim().length > 0) {
|
|
641
|
+
if (options.releaseNotesMode === "markdown") {
|
|
642
|
+
sections.push({
|
|
643
|
+
title: "Release Notes",
|
|
644
|
+
description: release.release_notes
|
|
645
|
+
});
|
|
646
|
+
} else {
|
|
647
|
+
const releaseNotesItems = release.release_notes.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
648
|
+
sections.push({
|
|
649
|
+
title: "Release Notes",
|
|
650
|
+
description: releaseNotesItems.length === 0 ? release.release_notes : void 0,
|
|
651
|
+
items: releaseNotesItems.length > 0 ? releaseNotesItems : void 0
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
const charts = release.helm_charts ? release.helm_charts.filter((chart) => !chart.is_kots_installer_only).map((chart) => `${chart.name} v${chart.version}`) : [];
|
|
656
|
+
if (charts.length > 0) {
|
|
657
|
+
sections.push({
|
|
658
|
+
title: "Helm Charts",
|
|
659
|
+
items: charts,
|
|
660
|
+
description: "Latest chart versions included in this release."
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
return {
|
|
664
|
+
version: release.label || `Release ${release.release_sequence}`,
|
|
665
|
+
channel: channelName || `Channel ${release.channel_sequence}`,
|
|
666
|
+
releasedAt: release.release_date,
|
|
667
|
+
sections
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
|
|
185
671
|
// src/actions/index.ts
|
|
186
672
|
var getApiOrigin = () => {
|
|
187
673
|
return (process.env.REPLICATED_APP_ORIGIN || "https://replicated.app").replace(/\/+$/, "");
|
|
@@ -321,11 +807,15 @@ var fetchCustomBrandingImpl = async () => {
|
|
|
321
807
|
const payload = await response.json();
|
|
322
808
|
const brandingObject = {
|
|
323
809
|
logo: payload.logoUrl,
|
|
324
|
-
title: payload.
|
|
325
|
-
|
|
326
|
-
|
|
810
|
+
title: payload.title,
|
|
811
|
+
primaryColor: payload.primaryColor,
|
|
812
|
+
secondaryColor: payload.secondaryColor,
|
|
327
813
|
favicon: payload.faviconUrl,
|
|
328
|
-
supportPortalLink: payload.supportPortalLink || ""
|
|
814
|
+
supportPortalLink: payload.supportPortalLink || "",
|
|
815
|
+
background: payload.background,
|
|
816
|
+
backgroundImage: payload.backgroundImage,
|
|
817
|
+
customColor1: payload.customColor1,
|
|
818
|
+
customColor2: payload.customColor2
|
|
329
819
|
};
|
|
330
820
|
const brandingData = buffer.Buffer.from(JSON.stringify(brandingObject)).toString("base64");
|
|
331
821
|
return {
|
|
@@ -588,353 +1078,38 @@ var uploadSupportBundle = defineServerAction({
|
|
|
588
1078
|
var getSupportBundleUploadUrl = (appId) => {
|
|
589
1079
|
return `${getApiOrigin()}/enterprise-portal/support-bundles/upload/${encodeURIComponent(appId)}`;
|
|
590
1080
|
};
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
console.debug("[portal-components] fetching releases via %s (Enterprise Portal API)", endpoint);
|
|
603
|
-
}
|
|
604
|
-
const response = await authenticatedFetch(endpoint, {
|
|
605
|
-
method: "GET",
|
|
606
|
-
token,
|
|
607
|
-
headers: {
|
|
608
|
-
accept: "application/json"
|
|
609
|
-
},
|
|
610
|
-
signal: context?.signal
|
|
611
|
-
});
|
|
612
|
-
const bodyText = await response.text().catch((error) => {
|
|
613
|
-
console.warn("[portal-components] listReleases read error", error);
|
|
614
|
-
return null;
|
|
615
|
-
});
|
|
616
|
-
if (!response.ok) {
|
|
617
|
-
throw new Error(
|
|
618
|
-
`List releases request failed (${response.status} ${response.statusText})`
|
|
619
|
-
);
|
|
620
|
-
}
|
|
621
|
-
return {
|
|
622
|
-
status: response.status,
|
|
623
|
-
body: bodyText
|
|
624
|
-
};
|
|
625
|
-
}
|
|
626
|
-
});
|
|
627
|
-
var asRecord = (value) => {
|
|
628
|
-
if (value && typeof value === "object") {
|
|
629
|
-
return value;
|
|
630
|
-
}
|
|
631
|
-
return void 0;
|
|
632
|
-
};
|
|
633
|
-
var getValue = (record, key) => record ? record[key] : void 0;
|
|
634
|
-
var getString = (record, key) => {
|
|
635
|
-
const value = getValue(record, key);
|
|
636
|
-
return typeof value === "string" ? value : void 0;
|
|
637
|
-
};
|
|
638
|
-
var getBoolean = (record, key) => {
|
|
639
|
-
const value = getValue(record, key);
|
|
640
|
-
if (typeof value === "boolean") {
|
|
641
|
-
return value;
|
|
642
|
-
}
|
|
643
|
-
if (typeof value === "number") {
|
|
644
|
-
return value === 1;
|
|
645
|
-
}
|
|
646
|
-
if (typeof value === "string") {
|
|
647
|
-
const normalized = value.trim().toLowerCase();
|
|
648
|
-
if (["true", "1", "yes"].includes(normalized)) {
|
|
649
|
-
return true;
|
|
650
|
-
}
|
|
651
|
-
if (["false", "0", "no"].includes(normalized)) {
|
|
652
|
-
return false;
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
return void 0;
|
|
656
|
-
};
|
|
657
|
-
var toDisplayValue = (value) => {
|
|
658
|
-
if (value === null || value === void 0) {
|
|
659
|
-
return null;
|
|
660
|
-
}
|
|
661
|
-
if (typeof value === "string") {
|
|
662
|
-
return value;
|
|
663
|
-
}
|
|
664
|
-
if (typeof value === "number" || typeof value === "boolean") {
|
|
665
|
-
return String(value);
|
|
666
|
-
}
|
|
667
|
-
try {
|
|
668
|
-
return JSON.stringify(value);
|
|
669
|
-
} catch {
|
|
670
|
-
return String(value);
|
|
671
|
-
}
|
|
672
|
-
};
|
|
673
|
-
var normalizeStringArray = (value) => {
|
|
674
|
-
if (Array.isArray(value)) {
|
|
675
|
-
const normalized = value.map(
|
|
676
|
-
(item) => typeof item === "string" ? item.trim() : ""
|
|
677
|
-
).filter((item) => item.length > 0);
|
|
678
|
-
return normalized.length ? normalized : void 0;
|
|
679
|
-
}
|
|
680
|
-
if (typeof value === "string") {
|
|
681
|
-
const normalized = value.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
|
|
682
|
-
return normalized.length ? normalized : void 0;
|
|
683
|
-
}
|
|
684
|
-
return void 0;
|
|
685
|
-
};
|
|
686
|
-
var normalizeLicenseFields = (input) => {
|
|
687
|
-
if (!input) {
|
|
688
|
-
return [];
|
|
689
|
-
}
|
|
690
|
-
if (Array.isArray(input)) {
|
|
691
|
-
return input.map((field, index) => {
|
|
692
|
-
if (!field || typeof field !== "object") {
|
|
693
|
-
return null;
|
|
694
|
-
}
|
|
695
|
-
const candidate = field;
|
|
696
|
-
const key = typeof candidate.key === "string" && candidate.key.trim().length ? candidate.key.trim() : typeof candidate.name === "string" && candidate.name.trim().length ? candidate.name.trim() : typeof candidate.label === "string" && candidate.label.trim().length ? candidate.label.trim() : `field-${index}`;
|
|
697
|
-
const label = typeof candidate.label === "string" && candidate.label.trim().length ? candidate.label.trim() : typeof candidate.name === "string" && candidate.name.trim().length ? candidate.name.trim() : key;
|
|
698
|
-
let value = candidate.value ?? candidate.data ?? candidate.content;
|
|
699
|
-
if ((value === void 0 || value === null) && typeof candidate.text === "string") {
|
|
700
|
-
value = candidate.text;
|
|
701
|
-
}
|
|
702
|
-
if ((value === void 0 || value === null) && typeof candidate.defaultValue === "string") {
|
|
703
|
-
value = candidate.defaultValue;
|
|
704
|
-
}
|
|
705
|
-
const isSecret = Boolean(
|
|
706
|
-
candidate.isSecret ?? candidate.secret ?? candidate.masked
|
|
707
|
-
);
|
|
708
|
-
const resolved = toDisplayValue(value);
|
|
709
|
-
return {
|
|
710
|
-
key,
|
|
711
|
-
label,
|
|
712
|
-
value: resolved,
|
|
713
|
-
isSecret
|
|
714
|
-
};
|
|
715
|
-
}).filter((field) => Boolean(field));
|
|
716
|
-
}
|
|
717
|
-
if (typeof input === "object") {
|
|
718
|
-
return Object.entries(input).map(
|
|
719
|
-
([key, value]) => {
|
|
720
|
-
let resolvedValue = value;
|
|
721
|
-
let isSecret = false;
|
|
722
|
-
if (value && typeof value === "object") {
|
|
723
|
-
const obj = value;
|
|
724
|
-
if ("value" in obj) {
|
|
725
|
-
resolvedValue = obj.value;
|
|
726
|
-
}
|
|
727
|
-
isSecret = Boolean(obj.isSecret ?? obj.secret ?? obj.masked);
|
|
728
|
-
}
|
|
729
|
-
const normalized = toDisplayValue(resolvedValue);
|
|
730
|
-
return {
|
|
731
|
-
key,
|
|
732
|
-
label: key,
|
|
733
|
-
value: normalized,
|
|
734
|
-
isSecret
|
|
735
|
-
};
|
|
736
|
-
}
|
|
737
|
-
);
|
|
738
|
-
}
|
|
739
|
-
return [];
|
|
740
|
-
};
|
|
741
|
-
var extractChannelNames = (input) => {
|
|
742
|
-
if (!Array.isArray(input)) {
|
|
743
|
-
return void 0;
|
|
1081
|
+
async function listReleasesImpl() {
|
|
1082
|
+
const { cookies: cookies2 } = await import('next/headers');
|
|
1083
|
+
const sessionStore = await cookies2();
|
|
1084
|
+
const session = sessionStore.get("portal_session");
|
|
1085
|
+
const token = session?.value;
|
|
1086
|
+
if (!token) {
|
|
1087
|
+
throw new Error("List releases requires a session token");
|
|
1088
|
+
}
|
|
1089
|
+
const endpoint = `${getApiOrigin()}/enterprise-portal/releases`;
|
|
1090
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1091
|
+
console.debug("[portal-components] fetching releases via %s (Enterprise Portal API)", endpoint);
|
|
744
1092
|
}
|
|
745
|
-
const
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
if (!record) {
|
|
751
|
-
return null;
|
|
752
|
-
}
|
|
753
|
-
return getString(record, "name") ?? getString(record, "channelName") ?? getString(record, "channel") ?? getString(record, "channelSlug") ?? getString(record, "slug") ?? void 0;
|
|
754
|
-
}).filter((name) => Boolean(name && name.length));
|
|
755
|
-
return names.length ? names : void 0;
|
|
756
|
-
};
|
|
757
|
-
var normalizeEntitlementFields = (fieldsInput, valuesInput) => {
|
|
758
|
-
const valuesMap = /* @__PURE__ */ new Map();
|
|
759
|
-
const assignValue = (key, value) => {
|
|
760
|
-
if (!key) {
|
|
761
|
-
return;
|
|
1093
|
+
const response = await authenticatedFetch(endpoint, {
|
|
1094
|
+
method: "GET",
|
|
1095
|
+
token,
|
|
1096
|
+
headers: {
|
|
1097
|
+
accept: "application/json"
|
|
762
1098
|
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
const record = asRecord(item);
|
|
768
|
-
if (!record) {
|
|
769
|
-
if (typeof item === "string") {
|
|
770
|
-
assignValue(item, item);
|
|
771
|
-
}
|
|
772
|
-
return;
|
|
773
|
-
}
|
|
774
|
-
const key = getString(record, "name") ?? getString(record, "field") ?? getString(record, "title") ?? getString(record, "label") ?? getString(record, "slug") ?? (() => {
|
|
775
|
-
const idValue = getValue(record, "id");
|
|
776
|
-
if (typeof idValue === "string" || typeof idValue === "number") {
|
|
777
|
-
return String(idValue);
|
|
778
|
-
}
|
|
779
|
-
return void 0;
|
|
780
|
-
})();
|
|
781
|
-
const value = getValue(record, "value") ?? getValue(record, "currentValue") ?? getValue(record, "entitlementValue") ?? getValue(record, "content") ?? getValue(record, "data") ?? getValue(record, "defaultVal") ?? getValue(record, "defaultValue");
|
|
782
|
-
assignValue(key, value);
|
|
783
|
-
});
|
|
784
|
-
} else if (valuesInput && typeof valuesInput === "object") {
|
|
785
|
-
Object.entries(valuesInput).forEach(
|
|
786
|
-
([key, value]) => assignValue(key, value)
|
|
1099
|
+
});
|
|
1100
|
+
if (!response.ok) {
|
|
1101
|
+
throw new Error(
|
|
1102
|
+
`List releases request failed (${response.status} ${response.statusText})`
|
|
787
1103
|
);
|
|
788
1104
|
}
|
|
789
|
-
const
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
return;
|
|
795
|
-
}
|
|
796
|
-
const baseKey = getString(record, "name") ?? getString(record, "field") ?? getString(record, "slug") ?? `entitlement-${index}`;
|
|
797
|
-
const key = `entitlement-${baseKey}`;
|
|
798
|
-
const label = getString(record, "title") ?? getString(record, "label") ?? baseKey;
|
|
799
|
-
const defaultValue = getString(record, "defaultVal") ?? getString(record, "default") ?? getString(record, "defaultValue");
|
|
800
|
-
const value = valuesMap.get(baseKey) ?? valuesMap.get(label) ?? defaultValue ?? null;
|
|
801
|
-
const isSecret = Boolean(
|
|
802
|
-
getBoolean(record, "secret") ?? getBoolean(record, "isSecret") ?? getBoolean(record, "masked")
|
|
803
|
-
);
|
|
804
|
-
normalized.push({
|
|
805
|
-
key,
|
|
806
|
-
label,
|
|
807
|
-
value,
|
|
808
|
-
isSecret
|
|
809
|
-
});
|
|
810
|
-
});
|
|
811
|
-
}
|
|
812
|
-
valuesMap.forEach((value, key) => {
|
|
813
|
-
const normalizedKey = `entitlement-${key}`;
|
|
814
|
-
if (!normalized.some((field) => field.key === normalizedKey)) {
|
|
815
|
-
normalized.push({
|
|
816
|
-
key: normalizedKey,
|
|
817
|
-
label: key,
|
|
818
|
-
value
|
|
819
|
-
});
|
|
820
|
-
}
|
|
821
|
-
});
|
|
822
|
-
return normalized;
|
|
823
|
-
};
|
|
824
|
-
var normalizeLicensePayload = (payload) => {
|
|
825
|
-
const payloadRecord = asRecord(payload);
|
|
826
|
-
const rootRecord = asRecord(getValue(payloadRecord, "license")) ?? asRecord(getValue(payloadRecord, "data")) ?? payloadRecord ?? {};
|
|
827
|
-
const sourceRecord = asRecord(getValue(rootRecord, "metadata")) ?? rootRecord;
|
|
828
|
-
const customer = asRecord(getValue(rootRecord, "customer")) ?? asRecord(getValue(sourceRecord, "customer")) ?? asRecord(getValue(payloadRecord, "customer")) ?? {};
|
|
829
|
-
let releaseChannels = normalizeStringArray(
|
|
830
|
-
getValue(rootRecord, "releaseChannels") ?? getValue(sourceRecord, "releaseChannels") ?? getValue(sourceRecord, "channels") ?? getValue(rootRecord, "channels") ?? getValue(sourceRecord, "channel") ?? getValue(rootRecord, "channel")
|
|
831
|
-
) ?? void 0;
|
|
832
|
-
if (!releaseChannels) {
|
|
833
|
-
releaseChannels = extractChannelNames(getValue(rootRecord, "channels")) ?? extractChannelNames(getValue(sourceRecord, "channels")) ?? void 0;
|
|
834
|
-
}
|
|
835
|
-
let installMethods = normalizeStringArray(
|
|
836
|
-
getValue(rootRecord, "installMethods") ?? getValue(sourceRecord, "installMethods") ?? getValue(sourceRecord, "install_options") ?? getValue(rootRecord, "install_options") ?? getValue(sourceRecord, "installOptions")
|
|
837
|
-
) ?? void 0;
|
|
838
|
-
if (!installMethods || installMethods.length === 0) {
|
|
839
|
-
const resolved = [];
|
|
840
|
-
const flag = (key) => getBoolean(rootRecord, key) ?? getBoolean(sourceRecord, key) ?? false;
|
|
841
|
-
if (flag("isKotsInstallEnabled")) {
|
|
842
|
-
resolved.push("Replicated KOTS");
|
|
843
|
-
}
|
|
844
|
-
if (flag("isHelmInstallEnabled")) {
|
|
845
|
-
resolved.push("Helm");
|
|
846
|
-
}
|
|
847
|
-
if (flag("isHelmAirgapEnabled")) {
|
|
848
|
-
resolved.push("Helm Airgap");
|
|
849
|
-
}
|
|
850
|
-
if (flag("isEmbeddedClusterDownloadEnabled") || flag("isEmbeddedClusterMultiNodeEnabled")) {
|
|
851
|
-
resolved.push("Embedded Cluster");
|
|
852
|
-
}
|
|
853
|
-
if (flag("isKurlInstallEnabled")) {
|
|
854
|
-
resolved.push("kURL");
|
|
855
|
-
}
|
|
856
|
-
if (flag("isGitopsSupported")) {
|
|
857
|
-
resolved.push("GitOps");
|
|
858
|
-
}
|
|
859
|
-
if (resolved.length) {
|
|
860
|
-
installMethods = Array.from(new Set(resolved));
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
const expiresAtSource = getValue(sourceRecord, "expiresAt") ?? getValue(sourceRecord, "expireAt") ?? getValue(sourceRecord, "expire_at") ?? getValue(sourceRecord, "expiration") ?? getValue(sourceRecord, "expirationDate") ?? getValue(sourceRecord, "expires_on") ?? getValue(rootRecord, "expiresAt") ?? getValue(rootRecord, "expireAt") ?? getValue(rootRecord, "expire_at") ?? getValue(rootRecord, "expiration");
|
|
864
|
-
const expiresAt = typeof expiresAtSource === "string" && expiresAtSource.trim().length ? expiresAtSource : expiresAtSource === null ? null : void 0;
|
|
865
|
-
const baseFields = normalizeLicenseFields(
|
|
866
|
-
getValue(rootRecord, "additionalFields") ?? getValue(sourceRecord, "additionalFields") ?? getValue(sourceRecord, "fields") ?? getValue(rootRecord, "fields") ?? getValue(payloadRecord, "fields") ?? getValue(payloadRecord, "additional_fields")
|
|
867
|
-
);
|
|
868
|
-
const entitlementFields = normalizeEntitlementFields(
|
|
869
|
-
getValue(rootRecord, "entitlementFields") ?? getValue(sourceRecord, "entitlementFields"),
|
|
870
|
-
getValue(rootRecord, "entitlementValues") ?? getValue(sourceRecord, "entitlementValues")
|
|
871
|
-
);
|
|
872
|
-
const fields = [
|
|
873
|
-
...baseFields,
|
|
874
|
-
...entitlementFields.filter(
|
|
875
|
-
(field) => !baseFields.some((existing) => existing.key === field.key)
|
|
876
|
-
)
|
|
877
|
-
];
|
|
878
|
-
const statusFromSource = getString(sourceRecord, "status") ?? getString(sourceRecord, "state");
|
|
879
|
-
const statusLabelFromSource = getString(sourceRecord, "statusLabel") ?? getString(sourceRecord, "stateLabel");
|
|
880
|
-
const expiredFlag = getBoolean(sourceRecord, "isExpired") ?? getBoolean(rootRecord, "isExpired");
|
|
881
|
-
const derivedStatus = statusFromSource ?? (typeof expiredFlag === "boolean" ? expiredFlag ? "expired" : "active" : void 0);
|
|
882
|
-
const statusLabel = statusLabelFromSource ?? (derivedStatus ? derivedStatus.charAt(0).toUpperCase() + derivedStatus.slice(1) : void 0);
|
|
883
|
-
const licenseType = getString(sourceRecord, "licenseType") ?? getString(rootRecord, "licenseType");
|
|
884
|
-
const status = derivedStatus;
|
|
885
|
-
const license = {
|
|
886
|
-
id: getString(rootRecord, "id") ?? getString(sourceRecord, "id") ?? getString(sourceRecord, "licenseId") ?? getString(customer, "licenseId") ?? void 0,
|
|
887
|
-
status,
|
|
888
|
-
statusLabel,
|
|
889
|
-
environment: getString(sourceRecord, "environment") ?? getString(sourceRecord, "tier") ?? licenseType ?? void 0,
|
|
890
|
-
expiresAt: expiresAt ?? null,
|
|
891
|
-
releaseChannels: releaseChannels ?? [
|
|
892
|
-
getString(rootRecord, "channelName") ?? getString(rootRecord, "channel") ?? void 0
|
|
893
|
-
].filter((value) => Boolean(value)),
|
|
894
|
-
installMethods,
|
|
895
|
-
installNotes: getString(sourceRecord, "installNotes"),
|
|
896
|
-
customerName: getString(sourceRecord, "customerName") ?? getString(customer, "name") ?? void 0,
|
|
897
|
-
customerId: getString(sourceRecord, "customerId") ?? getString(customer, "id") ?? getString(rootRecord, "customerId") ?? void 0,
|
|
898
|
-
customerOrganization: getString(customer, "organization") ?? getString(sourceRecord, "customerOrganization") ?? getString(rootRecord, "customerOrganization") ?? void 0,
|
|
899
|
-
fields
|
|
1105
|
+
const envelope = await response.json();
|
|
1106
|
+
const data = envelope.data;
|
|
1107
|
+
return {
|
|
1108
|
+
releases: Array.isArray(data?.releases) ? data.releases : [],
|
|
1109
|
+
totalCount: data?.totalCount || 0
|
|
900
1110
|
};
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
var fetchLicenseDetails = defineServerAction({
|
|
904
|
-
id: "license/fetch-details",
|
|
905
|
-
description: "Fetches the authenticated user's enterprise license details.",
|
|
906
|
-
visibility: "customer",
|
|
907
|
-
tags: ["license", "entitlements"],
|
|
908
|
-
async run({ token }, context) {
|
|
909
|
-
if (typeof token !== "string" || token.trim().length === 0) {
|
|
910
|
-
throw new Error("fetchLicenseDetails requires a non-empty token");
|
|
911
|
-
}
|
|
912
|
-
const endpoint = `${getApiOrigin()}/enterprise-portal/license`;
|
|
913
|
-
if (process.env.NODE_ENV !== "production") {
|
|
914
|
-
console.debug("[portal-components] fetching license via %s (Enterprise Portal API)", endpoint);
|
|
915
|
-
}
|
|
916
|
-
const response = await authenticatedFetch(endpoint, {
|
|
917
|
-
method: "GET",
|
|
918
|
-
token,
|
|
919
|
-
headers: {
|
|
920
|
-
accept: "application/json"
|
|
921
|
-
},
|
|
922
|
-
signal: context?.signal
|
|
923
|
-
});
|
|
924
|
-
if (!response.ok) {
|
|
925
|
-
throw new Error(
|
|
926
|
-
`License request failed (${response.status} ${response.statusText})`
|
|
927
|
-
);
|
|
928
|
-
}
|
|
929
|
-
const payload = await response.json();
|
|
930
|
-
const licenseData = payload.data;
|
|
931
|
-
const license = normalizeLicensePayload(licenseData);
|
|
932
|
-
return {
|
|
933
|
-
license,
|
|
934
|
-
raw: licenseData ?? null
|
|
935
|
-
};
|
|
936
|
-
}
|
|
937
|
-
});
|
|
1111
|
+
}
|
|
1112
|
+
var listReleases = traceServerAction("listReleases", listReleasesImpl);
|
|
938
1113
|
var getSecurityInfo = defineServerAction({
|
|
939
1114
|
id: "security/get-info",
|
|
940
1115
|
description: "Fetches CVE security scan results for a specific release",
|
|
@@ -1413,12 +1588,12 @@ var InfoRow = ({
|
|
|
1413
1588
|
icon,
|
|
1414
1589
|
title,
|
|
1415
1590
|
children
|
|
1416
|
-
}) => /* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
1417
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1418
|
-
|
|
1419
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-medium text-gray-900", children: title })
|
|
1420
|
-
|
|
1421
|
-
|
|
1591
|
+
}) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1592
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-2", children: [
|
|
1593
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-4 w-4 flex-shrink-0 items-center justify-center text-gray-900", children: icon }),
|
|
1594
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-medium leading-4 text-gray-900", children: title })
|
|
1595
|
+
] }),
|
|
1596
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pl-6", children })
|
|
1422
1597
|
] });
|
|
1423
1598
|
var renderInstallOrChannel = (values) => {
|
|
1424
1599
|
if (!values || values.length === 0) {
|
|
@@ -1433,12 +1608,12 @@ var buildPrimaryRows = (license) => {
|
|
|
1433
1608
|
node: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1434
1609
|
InfoRow,
|
|
1435
1610
|
{
|
|
1436
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(ShieldIcon, { className: "h-
|
|
1611
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(ShieldIcon, { className: "h-4 w-4" }),
|
|
1437
1612
|
title: "License Status",
|
|
1438
1613
|
children: [
|
|
1439
1614
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 flex items-center text-sm text-gray-600", children: [
|
|
1440
1615
|
/* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "mr-1.5 h-4 w-4 text-green-500" }),
|
|
1441
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: license.
|
|
1616
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: license.isExpired ? "Expired" : "Active" })
|
|
1442
1617
|
] }),
|
|
1443
1618
|
license.environment ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-gray-500", children: license.environment }) : null
|
|
1444
1619
|
]
|
|
@@ -1450,7 +1625,7 @@ var buildPrimaryRows = (license) => {
|
|
|
1450
1625
|
node: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1451
1626
|
InfoRow,
|
|
1452
1627
|
{
|
|
1453
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(CalendarIcon, { className: "h-
|
|
1628
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(CalendarIcon, { className: "h-4 w-4" }),
|
|
1454
1629
|
title: "Expiration Date",
|
|
1455
1630
|
children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-gray-500", children: formatExpiration(license.expiresAt) })
|
|
1456
1631
|
}
|
|
@@ -1461,7 +1636,7 @@ var buildPrimaryRows = (license) => {
|
|
|
1461
1636
|
node: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1462
1637
|
InfoRow,
|
|
1463
1638
|
{
|
|
1464
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(ShieldIcon, { className: "h-
|
|
1639
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(ShieldIcon, { className: "h-4 w-4" }),
|
|
1465
1640
|
title: "Release Channel(s)",
|
|
1466
1641
|
children: renderInstallOrChannel(license.releaseChannels)
|
|
1467
1642
|
}
|
|
@@ -1472,7 +1647,7 @@ var buildPrimaryRows = (license) => {
|
|
|
1472
1647
|
node: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1473
1648
|
InfoRow,
|
|
1474
1649
|
{
|
|
1475
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(DownloadIcon, { className: "h-
|
|
1650
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(DownloadIcon, { className: "h-4 w-4" }),
|
|
1476
1651
|
title: "Install Options",
|
|
1477
1652
|
children: renderInstallOrChannel(license.installMethods)
|
|
1478
1653
|
}
|
|
@@ -1483,7 +1658,7 @@ var buildPrimaryRows = (license) => {
|
|
|
1483
1658
|
node: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1484
1659
|
InfoRow,
|
|
1485
1660
|
{
|
|
1486
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(BuildingIcon, { className: "h-
|
|
1661
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(BuildingIcon, { className: "h-4 w-4" }),
|
|
1487
1662
|
title: "Customer Name",
|
|
1488
1663
|
children: [
|
|
1489
1664
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-gray-500", children: license.customerName ?? "Unknown customer" }),
|
|
@@ -1501,7 +1676,7 @@ var renderFields = (fields) => {
|
|
|
1501
1676
|
if (!fields.length) {
|
|
1502
1677
|
return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: "No additional fields available." });
|
|
1503
1678
|
}
|
|
1504
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2
|
|
1679
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2 xl:grid-cols-3", children: fields.map((field) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
1505
1680
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-900", children: field.label }),
|
|
1506
1681
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1507
1682
|
"p",
|
|
@@ -1522,9 +1697,7 @@ var LicenseDetails = async ({
|
|
|
1522
1697
|
if (typeof token !== "string" || token.trim().length === 0) {
|
|
1523
1698
|
throw new Error("LicenseDetails component requires a non-empty token");
|
|
1524
1699
|
}
|
|
1525
|
-
const
|
|
1526
|
-
console.debug("[portal-components] license response", response.raw);
|
|
1527
|
-
const { license } = response;
|
|
1700
|
+
const license = await fetchLicense();
|
|
1528
1701
|
const rows = buildPrimaryRows(license);
|
|
1529
1702
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded border border-gray-100 bg-white p-8 shadow-[0_18px_45px_rgba(17,24,39,0.08)]", children: [
|
|
1530
1703
|
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col border-b border-gray-100 pb-6", children: [
|
|
@@ -1532,7 +1705,7 @@ var LicenseDetails = async ({
|
|
|
1532
1705
|
description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-gray-600", children: description }) : null
|
|
1533
1706
|
] }),
|
|
1534
1707
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-6 space-y-6", children: [
|
|
1535
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-gray-100 bg-white p-6 sm:p-8", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2
|
|
1708
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-gray-100 bg-white p-6 sm:p-8", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 items-start gap-6 md:grid-cols-2 xl:grid-cols-3", children: rows.map((row) => /* @__PURE__ */ jsxRuntime.jsx("div", { children: row.node }, row.key)) }) }),
|
|
1536
1709
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-gray-100 bg-white p-6 sm:p-8", children: [
|
|
1537
1710
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "mb-4 text-lg font-medium text-gray-900", children: "Additional License Fields" }),
|
|
1538
1711
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: renderFields(license.fields ?? []) })
|
|
@@ -1725,57 +1898,49 @@ var TopNav = async ({
|
|
|
1725
1898
|
currentCustomerId,
|
|
1726
1899
|
onChangeTeam,
|
|
1727
1900
|
userMenuChildren,
|
|
1728
|
-
logoutButton
|
|
1901
|
+
logoutButton,
|
|
1902
|
+
branding: brandingProp
|
|
1729
1903
|
}) => {
|
|
1730
1904
|
const displayLabel = userMenuLabel || (customerName ? `Team: ${customerName}` : "Team: Example");
|
|
1731
1905
|
let logo;
|
|
1732
1906
|
let brandTitle;
|
|
1733
|
-
let
|
|
1734
|
-
let
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
if (
|
|
1741
|
-
|
|
1742
|
-
}
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
if (branding.brandingData) {
|
|
1748
|
-
const decoded = buffer.Buffer.from(branding.brandingData, "base64").toString(
|
|
1749
|
-
"utf-8"
|
|
1750
|
-
);
|
|
1751
|
-
try {
|
|
1752
|
-
const parsed = JSON.parse(decoded);
|
|
1753
|
-
if (parsed?.logo && typeof parsed.logo === "string") {
|
|
1754
|
-
logo = parsed.logo;
|
|
1755
|
-
}
|
|
1756
|
-
if (parsed?.title && typeof parsed.title === "string") {
|
|
1757
|
-
const normalizedTitle = parsed.title.trim();
|
|
1758
|
-
if (normalizedTitle) {
|
|
1759
|
-
brandTitle = normalizedTitle;
|
|
1760
|
-
}
|
|
1761
|
-
}
|
|
1762
|
-
if (parsed?.customColor1 && typeof parsed.customColor1 === "string") {
|
|
1763
|
-
customColor1 = normalizeColor(parsed.customColor1);
|
|
1764
|
-
}
|
|
1765
|
-
if (parsed?.customColor2 && typeof parsed.customColor2 === "string") {
|
|
1766
|
-
customColor2 = normalizeColor(parsed.customColor2);
|
|
1767
|
-
}
|
|
1768
|
-
} catch (error) {
|
|
1769
|
-
console.debug(
|
|
1770
|
-
"[portal-components] unable to parse branding JSON",
|
|
1771
|
-
error
|
|
1772
|
-
);
|
|
1907
|
+
let primaryColor;
|
|
1908
|
+
let secondaryColor;
|
|
1909
|
+
let background;
|
|
1910
|
+
let backgroundImageUrl;
|
|
1911
|
+
let backgroundGradientStart;
|
|
1912
|
+
let backgroundGradientEnd;
|
|
1913
|
+
if (brandingProp) {
|
|
1914
|
+
if (brandingProp.logo && typeof brandingProp.logo === "string") {
|
|
1915
|
+
logo = brandingProp.logo;
|
|
1916
|
+
}
|
|
1917
|
+
if (brandingProp.title && typeof brandingProp.title === "string") {
|
|
1918
|
+
const normalizedTitle = brandingProp.title.trim();
|
|
1919
|
+
if (normalizedTitle) {
|
|
1920
|
+
brandTitle = normalizedTitle;
|
|
1773
1921
|
}
|
|
1774
|
-
} else {
|
|
1775
|
-
console.debug("[portal-components] branding", branding);
|
|
1776
1922
|
}
|
|
1777
|
-
|
|
1778
|
-
|
|
1923
|
+
primaryColor = normalizeColor(brandingProp.primaryColor);
|
|
1924
|
+
secondaryColor = normalizeColor(brandingProp.secondaryColor);
|
|
1925
|
+
background = brandingProp.background;
|
|
1926
|
+
backgroundImageUrl = brandingProp.backgroundImage;
|
|
1927
|
+
backgroundGradientStart = normalizeColor(brandingProp.backgroundGradientStart);
|
|
1928
|
+
backgroundGradientEnd = normalizeColor(brandingProp.backgroundGradientEnd);
|
|
1929
|
+
} else {
|
|
1930
|
+
try {
|
|
1931
|
+
const brandingResponse = await fetchCustomBranding();
|
|
1932
|
+
const branding = decodeBranding({ brandingData: brandingResponse.brandingData });
|
|
1933
|
+
logo = branding.logo;
|
|
1934
|
+
brandTitle = branding.title;
|
|
1935
|
+
primaryColor = branding.primaryColor;
|
|
1936
|
+
secondaryColor = branding.secondaryColor;
|
|
1937
|
+
background = branding.background;
|
|
1938
|
+
backgroundImageUrl = branding.backgroundImage;
|
|
1939
|
+
backgroundGradientStart = branding.backgroundGradientStart;
|
|
1940
|
+
backgroundGradientEnd = branding.backgroundGradientEnd;
|
|
1941
|
+
} catch (error) {
|
|
1942
|
+
console.debug("[portal-components] branding fetch failed", error);
|
|
1943
|
+
}
|
|
1779
1944
|
}
|
|
1780
1945
|
const baseLinks = links ?? defaultTopNavLinks;
|
|
1781
1946
|
const hiddenSet = hiddenLabels ? new Set(hiddenLabels) : null;
|
|
@@ -1786,20 +1951,32 @@ var TopNav = async ({
|
|
|
1786
1951
|
resolvedLinks = [...resolvedLinks, ...additionalLinks];
|
|
1787
1952
|
}
|
|
1788
1953
|
resolvedLinks = orderLinks(resolvedLinks, order);
|
|
1789
|
-
const
|
|
1790
|
-
|
|
1954
|
+
const getHeaderBackgroundStyle = () => {
|
|
1955
|
+
if (background === "image" && backgroundImageUrl) {
|
|
1956
|
+
return {
|
|
1957
|
+
background: `url(${backgroundImageUrl})`,
|
|
1958
|
+
backgroundImage: `linear-gradient(to top, rgba(255, 255, 255, 0.3) 30%, rgba(255, 255, 255, 0)), url(${backgroundImageUrl})`,
|
|
1959
|
+
backgroundSize: "cover",
|
|
1960
|
+
backgroundPosition: "center",
|
|
1961
|
+
backgroundRepeat: "no-repeat"
|
|
1962
|
+
};
|
|
1963
|
+
}
|
|
1964
|
+
const gradientStart = background === "custom" && backgroundGradientStart ? backgroundGradientStart : primaryColor;
|
|
1965
|
+
const gradientEnd = background === "custom" && backgroundGradientEnd ? backgroundGradientEnd : secondaryColor;
|
|
1966
|
+
return {
|
|
1967
|
+
backgroundImage: `linear-gradient(to top, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0) 33%), linear-gradient(${gradientStart}, ${gradientEnd})`,
|
|
1968
|
+
backgroundRepeat: "no-repeat",
|
|
1969
|
+
backgroundSize: "100% 100%"
|
|
1970
|
+
};
|
|
1971
|
+
};
|
|
1791
1972
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1792
1973
|
"div",
|
|
1793
1974
|
{
|
|
1794
1975
|
className: "relative flex h-[280px] w-full items-start justify-center",
|
|
1795
|
-
style:
|
|
1796
|
-
|
|
1797
|
-
backgroundRepeat: "no-repeat",
|
|
1798
|
-
backgroundSize: "100% 100%"
|
|
1799
|
-
},
|
|
1800
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto mt-[30px] w-full max-w-[1248px] px-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-[135px] flex-col justify-between space-y-4 rounded bg-[#ffffffe6] px-6 pt-6 pb-4 shadow-[0_10px_60px_rgba(16,16,16,0.35)]", children: [
|
|
1976
|
+
style: getHeaderBackgroundStyle(),
|
|
1977
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto mt-[30px] w-full max-w-[1248px] px-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-[142px] flex-col justify-between space-y-4 rounded bg-[#ffffffe6] px-6 pt-6 pb-4 shadow-[0_10px_60px_rgba(16,16,16,0.35)]", children: [
|
|
1801
1978
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
1802
|
-
|
|
1979
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
1803
1980
|
logo ? (
|
|
1804
1981
|
// eslint-disable-next-line @next/next/no-img-element
|
|
1805
1982
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1814,9 +1991,24 @@ var TopNav = async ({
|
|
|
1814
1991
|
}
|
|
1815
1992
|
}
|
|
1816
1993
|
)
|
|
1817
|
-
) :
|
|
1818
|
-
|
|
1819
|
-
|
|
1994
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1995
|
+
"svg",
|
|
1996
|
+
{
|
|
1997
|
+
className: "h-8 w-8 text-gray-400",
|
|
1998
|
+
viewBox: "0 0 24 24",
|
|
1999
|
+
fill: "none",
|
|
2000
|
+
stroke: "currentColor",
|
|
2001
|
+
strokeWidth: "1.5",
|
|
2002
|
+
"aria-hidden": "true",
|
|
2003
|
+
children: [
|
|
2004
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
|
|
2005
|
+
/* @__PURE__ */ jsxRuntime.jsx("ellipse", { cx: "12", cy: "12", rx: "4", ry: "10" }),
|
|
2006
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 12h20" })
|
|
2007
|
+
]
|
|
2008
|
+
}
|
|
2009
|
+
),
|
|
2010
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xl font-bold text-gray-900", children: brandTitle || "Enterprise Portal" })
|
|
2011
|
+
] }),
|
|
1820
2012
|
/* @__PURE__ */ jsxRuntime.jsxs("details", { className: "group relative", children: [
|
|
1821
2013
|
/* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex cursor-pointer items-center gap-2 text-sm font-medium text-gray-600 hover:text-gray-900 list-none", children: [
|
|
1822
2014
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -1878,7 +2070,7 @@ var TopNav = async ({
|
|
|
1878
2070
|
] })
|
|
1879
2071
|
] })
|
|
1880
2072
|
] }),
|
|
1881
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex flex-wrap gap-3
|
|
2073
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex flex-wrap gap-3 pb-2 text-sm font-medium text-gray-500", children: resolvedLinks.map(({ label, icon, href }) => {
|
|
1882
2074
|
const isActive = activeLabel === label;
|
|
1883
2075
|
const className = `flex items-center gap-2 px-4 py-1 transition text-gray-500 ${isActive ? "underline underline-offset-8 decoration-2" : ""}`;
|
|
1884
2076
|
if (href) {
|
|
@@ -1931,9 +2123,17 @@ var headingClass = "text-lg font-semibold text-gray-900";
|
|
|
1931
2123
|
var contentClass = "mt-4 flex-1 space-y-3";
|
|
1932
2124
|
var itemClass = "flex items-center gap-3 text-sm text-gray-600";
|
|
1933
2125
|
var iconClass = "h-5 w-5 text-gray-500";
|
|
1934
|
-
var footerClass = "mt-6 flex justify-end text-sm font-semibold
|
|
1935
|
-
var badgeClass = "ml-2 inline-flex h-5 min-w-[20px] items-center justify-center rounded-full
|
|
1936
|
-
var Badge = ({ count }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2126
|
+
var footerClass = "mt-6 flex justify-end text-sm font-semibold hover:opacity-80";
|
|
2127
|
+
var badgeClass = "ml-2 inline-flex h-5 min-w-[20px] items-center justify-center rounded-full px-1.5 text-xs font-medium text-white";
|
|
2128
|
+
var Badge = ({ count }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2129
|
+
"span",
|
|
2130
|
+
{
|
|
2131
|
+
className: badgeClass,
|
|
2132
|
+
style: { backgroundColor: `var(--portal-branding-primary, ${DEFAULT_SECONDARY_COLOR})` },
|
|
2133
|
+
"aria-label": `${count} updates available`,
|
|
2134
|
+
children: count
|
|
2135
|
+
}
|
|
2136
|
+
);
|
|
1937
2137
|
var UpdatesCard = ({
|
|
1938
2138
|
onlineActiveCount = 0,
|
|
1939
2139
|
airgapCount = 0,
|
|
@@ -1961,7 +2161,7 @@ var UpdatesCard = ({
|
|
|
1961
2161
|
airgapUpdates > 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge, { count: airgapUpdates })
|
|
1962
2162
|
] })
|
|
1963
2163
|
] }),
|
|
1964
|
-
/* @__PURE__ */ jsxRuntime.jsx("footer", { className: footerClass, children: /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href: "/update", children: "View updates \u2192" }) })
|
|
2164
|
+
/* @__PURE__ */ jsxRuntime.jsx("footer", { className: footerClass, children: /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href: "/update", style: { color: `var(--portal-branding-secondary, ${DEFAULT_SECONDARY_COLOR})` }, children: "View updates \u2192" }) })
|
|
1965
2165
|
] });
|
|
1966
2166
|
UpdatesCard.displayName = "UpdatesCard";
|
|
1967
2167
|
var UploadIcon = (props) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2126,7 +2326,7 @@ var TeamsSection = ({
|
|
|
2126
2326
|
type: "button",
|
|
2127
2327
|
onClick: () => !isCurrentTeam && onTeamSwitch?.(team),
|
|
2128
2328
|
disabled: isCurrentTeam,
|
|
2129
|
-
className: `flex w-full items-center justify-between rounded-lg border p-4 text-left transition ${isCurrentTeam ? "cursor-default border-gray-300 bg-gray-50" : "cursor-pointer border-gray-200 hover:border-
|
|
2329
|
+
className: `flex w-full items-center justify-between rounded-lg border p-4 text-left transition ${isCurrentTeam ? "cursor-default border-gray-300 bg-gray-50" : "cursor-pointer border-gray-200 hover:border-gray-400"}`,
|
|
2130
2330
|
style: !isCurrentTeam && primaryColor ? { "--hover-border": primaryColor } : void 0,
|
|
2131
2331
|
children: [
|
|
2132
2332
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
@@ -2134,7 +2334,7 @@ var TeamsSection = ({
|
|
|
2134
2334
|
"svg",
|
|
2135
2335
|
{
|
|
2136
2336
|
className: "h-4 w-4",
|
|
2137
|
-
style: { color: primaryColor ||
|
|
2337
|
+
style: { color: primaryColor || DEFAULT_SECONDARY_COLOR },
|
|
2138
2338
|
fill: "none",
|
|
2139
2339
|
viewBox: "0 0 24 24",
|
|
2140
2340
|
stroke: "currentColor",
|
|
@@ -2158,7 +2358,7 @@ var TeamsSection = ({
|
|
|
2158
2358
|
"svg",
|
|
2159
2359
|
{
|
|
2160
2360
|
className: "h-4 w-4",
|
|
2161
|
-
style: { color: primaryColor ||
|
|
2361
|
+
style: { color: primaryColor || DEFAULT_SECONDARY_COLOR },
|
|
2162
2362
|
fill: "none",
|
|
2163
2363
|
viewBox: "0 0 24 24",
|
|
2164
2364
|
stroke: "currentColor",
|
|
@@ -2223,7 +2423,10 @@ var ProfileSection = ({
|
|
|
2223
2423
|
resetForm();
|
|
2224
2424
|
setIsEditing(true);
|
|
2225
2425
|
};
|
|
2226
|
-
const buttonStyle =
|
|
2426
|
+
const buttonStyle = {
|
|
2427
|
+
backgroundColor: primaryColor || DEFAULT_SECONDARY_COLOR,
|
|
2428
|
+
borderColor: primaryColor || DEFAULT_SECONDARY_COLOR
|
|
2429
|
+
};
|
|
2227
2430
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-2xl border border-gray-200 bg-white p-6 shadow-sm", children: [
|
|
2228
2431
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4", children: [
|
|
2229
2432
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
@@ -2250,7 +2453,7 @@ var ProfileSection = ({
|
|
|
2250
2453
|
onClick: handleSave,
|
|
2251
2454
|
disabled: isUpdating,
|
|
2252
2455
|
style: buttonStyle,
|
|
2253
|
-
className: "inline-flex items-center rounded-md
|
|
2456
|
+
className: "inline-flex items-center justify-center rounded-md px-4 py-2 text-sm font-medium text-white shadow-sm transition-opacity duration-200 hover:opacity-90 disabled:opacity-50 min-w-[70px]",
|
|
2254
2457
|
children: isUpdating ? "Saving..." : "Save"
|
|
2255
2458
|
}
|
|
2256
2459
|
)
|
|
@@ -2260,7 +2463,7 @@ var ProfileSection = ({
|
|
|
2260
2463
|
type: "button",
|
|
2261
2464
|
onClick: handleEdit,
|
|
2262
2465
|
style: buttonStyle,
|
|
2263
|
-
className: "inline-flex items-center rounded-md
|
|
2466
|
+
className: "inline-flex items-center justify-center rounded-md px-4 py-2 text-sm font-medium text-white shadow-sm transition-opacity duration-200 hover:opacity-90 min-w-[70px]",
|
|
2264
2467
|
children: "Edit"
|
|
2265
2468
|
}
|
|
2266
2469
|
)
|
|
@@ -2376,11 +2579,11 @@ UserSettings.displayName = "UserSettings";
|
|
|
2376
2579
|
var baseCardClass3 = "flex h-full flex-col rounded-xl border border-gray-200 bg-white p-6 shadow-[0_16px_32px_rgba(15,23,42,0.05)]";
|
|
2377
2580
|
var headingClass3 = "text-lg font-semibold text-gray-900";
|
|
2378
2581
|
var bodySpacerClass = "mt-4 flex-1";
|
|
2379
|
-
var footerClass3 = "mt-6 flex justify-end text-sm font-semibold
|
|
2582
|
+
var footerClass3 = "mt-6 flex justify-end text-sm font-semibold hover:opacity-80";
|
|
2380
2583
|
var UserSettingsCard = () => /* @__PURE__ */ jsxRuntime.jsxs("section", { className: baseCardClass3, "aria-labelledby": "user-settings-card-heading", children: [
|
|
2381
2584
|
/* @__PURE__ */ jsxRuntime.jsx("header", { children: /* @__PURE__ */ jsxRuntime.jsx("h2", { id: "user-settings-card-heading", className: headingClass3, children: "User Settings" }) }),
|
|
2382
2585
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: bodySpacerClass }),
|
|
2383
|
-
/* @__PURE__ */ jsxRuntime.jsx("footer", { className: footerClass3, children: /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href: "/user-settings", children: "View user settings \u2192" }) })
|
|
2586
|
+
/* @__PURE__ */ jsxRuntime.jsx("footer", { className: footerClass3, children: /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href: "/user-settings", style: { color: `var(--portal-branding-secondary, ${DEFAULT_SECONDARY_COLOR})` }, children: "View user settings \u2192" }) })
|
|
2384
2587
|
] });
|
|
2385
2588
|
UserSettingsCard.displayName = "UserSettingsCard";
|
|
2386
2589
|
var UsersIcon = (props) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2418,7 +2621,7 @@ var headingClass4 = "text-lg font-semibold text-gray-900";
|
|
|
2418
2621
|
var contentClass3 = "mt-4 flex-1 space-y-3";
|
|
2419
2622
|
var itemClass3 = "flex items-center gap-3 text-sm text-gray-600";
|
|
2420
2623
|
var iconClass3 = "h-5 w-5 text-gray-500";
|
|
2421
|
-
var footerClass4 = "mt-6 flex justify-end text-sm font-semibold
|
|
2624
|
+
var footerClass4 = "mt-6 flex justify-end text-sm font-semibold hover:opacity-80";
|
|
2422
2625
|
var TeamSettingsCard = ({
|
|
2423
2626
|
userCount = 0,
|
|
2424
2627
|
serviceAccountCount = 0
|
|
@@ -2442,7 +2645,7 @@ var TeamSettingsCard = ({
|
|
|
2442
2645
|
] })
|
|
2443
2646
|
] })
|
|
2444
2647
|
] }),
|
|
2445
|
-
/* @__PURE__ */ jsxRuntime.jsx("footer", { className: footerClass4, children: /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href: "/team-settings", children: "View team settings \u2192" }) })
|
|
2648
|
+
/* @__PURE__ */ jsxRuntime.jsx("footer", { className: footerClass4, children: /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href: "/team-settings", style: { color: `var(--portal-branding-secondary, ${DEFAULT_SECONDARY_COLOR})` }, children: "View team settings \u2192" }) })
|
|
2446
2649
|
] });
|
|
2447
2650
|
TeamSettingsCard.displayName = "TeamSettingsCard";
|
|
2448
2651
|
var UpdateLayout = ({ children }) => {
|
|
@@ -2453,43 +2656,128 @@ var UpdateLayout = ({ children }) => {
|
|
|
2453
2656
|
};
|
|
2454
2657
|
UpdateLayout.displayName = "UpdateLayout";
|
|
2455
2658
|
|
|
2659
|
+
// src/saml-handlers.ts
|
|
2660
|
+
async function setSamlSessionImpl(token) {
|
|
2661
|
+
try {
|
|
2662
|
+
if (!token) {
|
|
2663
|
+
return { success: false, message: "No token provided" };
|
|
2664
|
+
}
|
|
2665
|
+
const cleanToken = token.startsWith("Bearer ") ? token.slice(7) : token;
|
|
2666
|
+
const { cookies: cookies2 } = await import('next/headers');
|
|
2667
|
+
const cookieStore = await cookies2();
|
|
2668
|
+
const isHttpOrigin = process.env.REPLICATED_APP_ORIGIN?.startsWith("http://");
|
|
2669
|
+
const secure = true;
|
|
2670
|
+
const sameSiteValue = isHttpOrigin ? "none" : "lax";
|
|
2671
|
+
cookieStore.set("portal_session", cleanToken, {
|
|
2672
|
+
httpOnly: true,
|
|
2673
|
+
secure,
|
|
2674
|
+
sameSite: sameSiteValue,
|
|
2675
|
+
path: "/"
|
|
2676
|
+
});
|
|
2677
|
+
return { success: true };
|
|
2678
|
+
} catch (error) {
|
|
2679
|
+
console.error("[saml-handlers] Error setting session:", error);
|
|
2680
|
+
return {
|
|
2681
|
+
success: false,
|
|
2682
|
+
message: "Failed to establish session"
|
|
2683
|
+
};
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
async function handleSamlAcs(request) {
|
|
2687
|
+
try {
|
|
2688
|
+
const apiOrigin = getApiOrigin();
|
|
2689
|
+
const formData = await request.formData();
|
|
2690
|
+
const response = await fetch(`${apiOrigin}/saml/acs`, {
|
|
2691
|
+
method: "POST",
|
|
2692
|
+
body: formData,
|
|
2693
|
+
redirect: "manual"
|
|
2694
|
+
});
|
|
2695
|
+
if (response.status === 302 || response.status === 301) {
|
|
2696
|
+
const location = response.headers.get("Location");
|
|
2697
|
+
if (location) {
|
|
2698
|
+
return Response.redirect(location, response.status);
|
|
2699
|
+
}
|
|
2700
|
+
}
|
|
2701
|
+
console.error("[saml-acs] Error response from backend:", {
|
|
2702
|
+
status: response.status,
|
|
2703
|
+
statusText: response.statusText
|
|
2704
|
+
});
|
|
2705
|
+
let errorMessage = "SAML authentication failed";
|
|
2706
|
+
if (response.status === 401 || response.status === 403) {
|
|
2707
|
+
errorMessage = "Authentication failed. Please check your credentials or contact your administrator.";
|
|
2708
|
+
} else if (response.status === 400) {
|
|
2709
|
+
errorMessage = "Invalid SAML request. Please try again.";
|
|
2710
|
+
}
|
|
2711
|
+
return Response.redirect(
|
|
2712
|
+
new URL(`/error?code=${response.status}&message=${encodeURIComponent(errorMessage)}`, request.url),
|
|
2713
|
+
302
|
|
2714
|
+
);
|
|
2715
|
+
} catch (error) {
|
|
2716
|
+
console.error("[saml-acs] Error processing SAML response:", error);
|
|
2717
|
+
return Response.redirect(
|
|
2718
|
+
new URL(`/error?code=500&message=${encodeURIComponent("SAML authentication error")}`, request.url),
|
|
2719
|
+
302
|
|
2720
|
+
);
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
|
|
2456
2724
|
// src/index.ts
|
|
2457
2725
|
var portalComponentsVersion = package_default.version;
|
|
2458
2726
|
|
|
2459
2727
|
exports.Button = Button;
|
|
2728
|
+
exports.DEFAULT_FAVICON = DEFAULT_FAVICON;
|
|
2729
|
+
exports.DEFAULT_PRIMARY_COLOR = DEFAULT_PRIMARY_COLOR;
|
|
2730
|
+
exports.DEFAULT_SECONDARY_COLOR = DEFAULT_SECONDARY_COLOR;
|
|
2460
2731
|
exports.LicenseDetails = LicenseDetails;
|
|
2461
2732
|
exports.SupportCard = SupportCard;
|
|
2462
2733
|
exports.TeamSettingsCard = TeamSettingsCard;
|
|
2463
2734
|
exports.TopNav = TopNav;
|
|
2735
|
+
exports.UnauthorizedError = UnauthorizedError;
|
|
2464
2736
|
exports.UpdateLayout = UpdateLayout;
|
|
2465
2737
|
exports.UpdatesCard = UpdatesCard;
|
|
2466
2738
|
exports.UserSettings = UserSettings;
|
|
2467
2739
|
exports.UserSettingsCard = UserSettingsCard;
|
|
2740
|
+
exports.authenticatedFetch = authenticatedFetch;
|
|
2741
|
+
exports.convertToReleaseEntry = convertToReleaseEntry;
|
|
2468
2742
|
exports.createPortalTheme = createPortalTheme;
|
|
2743
|
+
exports.decodeBranding = decodeBranding;
|
|
2469
2744
|
exports.decodeJwtPayload = decodeJwtPayload;
|
|
2470
2745
|
exports.defaultTopNavLinks = defaultTopNavLinks;
|
|
2471
2746
|
exports.defineServerAction = defineServerAction;
|
|
2747
|
+
exports.deleteSessionCookie = deleteSessionCookie;
|
|
2472
2748
|
exports.deleteSupportBundle = deleteSupportBundle;
|
|
2473
2749
|
exports.downloadSecuritySBOM = downloadSecuritySBOM;
|
|
2474
2750
|
exports.downloadSupportBundle = downloadSupportBundle;
|
|
2475
2751
|
exports.fetchCurrentUser = fetchCurrentUser;
|
|
2476
2752
|
exports.fetchCustomBranding = fetchCustomBranding;
|
|
2477
2753
|
exports.fetchDashboardComposite = fetchDashboardComposite;
|
|
2478
|
-
exports.
|
|
2754
|
+
exports.fetchLicense = fetchLicense;
|
|
2479
2755
|
exports.fetchNotifications = fetchNotifications;
|
|
2756
|
+
exports.formatBytes = formatBytes;
|
|
2757
|
+
exports.formatDate = formatDate;
|
|
2758
|
+
exports.formatDateShort = formatDateShort;
|
|
2759
|
+
exports.formatDateTime = formatDateTime;
|
|
2760
|
+
exports.formatDateTimeLocal = formatDateTimeLocal;
|
|
2480
2761
|
exports.getCustomerIdFromToken = getCustomerIdFromToken;
|
|
2481
2762
|
exports.getSecurityInfo = getSecurityInfo;
|
|
2482
2763
|
exports.getSecurityInfoDiff = getSecurityInfoDiff;
|
|
2483
2764
|
exports.getSecurityInfoSBOM = getSecurityInfoSBOM;
|
|
2484
2765
|
exports.getSupportBundleUploadUrl = getSupportBundleUploadUrl;
|
|
2766
|
+
exports.handleSamlAcs = handleSamlAcs;
|
|
2485
2767
|
exports.initiateLogin = initiateLogin;
|
|
2768
|
+
exports.isHttpApiOrigin = isHttpApiOrigin;
|
|
2769
|
+
exports.isRedirectError = isRedirectError;
|
|
2486
2770
|
exports.listReleases = listReleases;
|
|
2487
2771
|
exports.listSupportBundles = listSupportBundles;
|
|
2772
|
+
exports.normalizeColor = normalizeColor;
|
|
2488
2773
|
exports.portalComponentsVersion = portalComponentsVersion;
|
|
2489
2774
|
exports.portalThemeTokens = portalThemeTokens;
|
|
2775
|
+
exports.sanitizeUrlForCss = sanitizeUrlForCss;
|
|
2776
|
+
exports.setSamlSessionImpl = setSamlSessionImpl;
|
|
2490
2777
|
exports.updateNotifications = updateNotifications;
|
|
2491
2778
|
exports.updateUser = updateUser;
|
|
2492
2779
|
exports.uploadSupportBundle = uploadSupportBundle;
|
|
2780
|
+
exports.validateSession = validateSession;
|
|
2493
2781
|
exports.verifyMagicLink = verifyMagicLink;
|
|
2494
2782
|
//# sourceMappingURL=index.js.map
|
|
2495
2783
|
//# sourceMappingURL=index.js.map
|