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
3 changes: 2 additions & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@
"hubspotSignupFormId": "$NETBIRD_HUBSPOT_SIGNUP_FORM_ID",
"hubspotOnboardingFormId": "$NETBIRD_HUBSPOT_ONBOARDING_FORM_ID",
"hubspotSurveyFormId": "$NETBIRD_HUBSPOT_SURVEY_FORM_ID",
"analyticsExcludedEmails": "$NETBIRD_ANALYTICS_EXCLUDED_EMAILS"
"analyticsExcludedEmails": "$NETBIRD_ANALYTICS_EXCLUDED_EMAILS",
"announcement": "$NETBIRD_ANNOUNCEMENT"
}
4 changes: 3 additions & 1 deletion docker/init_react_envs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ export NETBIRD_HUBSPOT_SIGNUP_FORM_ID=${NETBIRD_HUBSPOT_SIGNUP_FORM_ID}
export NETBIRD_HUBSPOT_ONBOARDING_FORM_ID=${NETBIRD_HUBSPOT_ONBOARDING_FORM_ID}
export NETBIRD_HUBSPOT_SURVEY_FORM_ID=${NETBIRD_HUBSPOT_SURVEY_FORM_ID}
export NETBIRD_ANALYTICS_EXCLUDED_EMAILS=${NETBIRD_ANALYTICS_EXCLUDED_EMAILS}
# A permanent banner for this deployment, shown to every user; empty for none.
export NETBIRD_ANNOUNCEMENT=${NETBIRD_ANNOUNCEMENT}

echo "NetBird latest version: ${NETBIRD_LATEST_VERSION}"

Expand Down Expand Up @@ -163,7 +165,7 @@ sed -i "s|add_header Content-Security-Policy \"[^\"]*\" always;|$CSP_HEADER|g" /
}

# replace ENVs in the config
ENV_STR="\$\$USE_AUTH0 \$\$AUTH_AUDIENCE \$\$AUTH_AUTHORITY \$\$AUTH_CLIENT_ID \$\$AUTH_CLIENT_SECRET \$\$AUTH_SUPPORTED_SCOPES \$\$NETBIRD_MGMT_API_ENDPOINT \$\$NETBIRD_MGMT_GRPC_API_ENDPOINT \$\$NETBIRD_HOTJAR_TRACK_ID \$\$NETBIRD_GOOGLE_ANALYTICS_ID \$\$NETBIRD_GOOGLE_TAG_MANAGER_ID \$\$AUTH_REDIRECT_URI \$\$AUTH_SILENT_REDIRECT_URI \$\$NETBIRD_TOKEN_SOURCE \$\$NETBIRD_DRAG_QUERY_PARAMS \$\$NETBIRD_AUTH_SERVICE_URL \$\$NETBIRD_WASM_PATH \$\$NETBIRD_LICENSED \$\$NETBIRD_CLOUD \$\$NETBIRD_AGENT_NETWORK_ONLY \$\$NETBIRD_AGENT_NETWORK_ENABLED \$\$NETBIRD_HUBSPOT_PORTAL_ID \$\$NETBIRD_HUBSPOT_SIGNUP_FORM_ID \$\$NETBIRD_HUBSPOT_ONBOARDING_FORM_ID \$\$NETBIRD_HUBSPOT_SURVEY_FORM_ID \$\$NETBIRD_ANALYTICS_EXCLUDED_EMAILS"
ENV_STR="\$\$USE_AUTH0 \$\$AUTH_AUDIENCE \$\$AUTH_AUTHORITY \$\$AUTH_CLIENT_ID \$\$AUTH_CLIENT_SECRET \$\$AUTH_SUPPORTED_SCOPES \$\$NETBIRD_MGMT_API_ENDPOINT \$\$NETBIRD_MGMT_GRPC_API_ENDPOINT \$\$NETBIRD_HOTJAR_TRACK_ID \$\$NETBIRD_GOOGLE_ANALYTICS_ID \$\$NETBIRD_GOOGLE_TAG_MANAGER_ID \$\$AUTH_REDIRECT_URI \$\$AUTH_SILENT_REDIRECT_URI \$\$NETBIRD_TOKEN_SOURCE \$\$NETBIRD_DRAG_QUERY_PARAMS \$\$NETBIRD_AUTH_SERVICE_URL \$\$NETBIRD_WASM_PATH \$\$NETBIRD_LICENSED \$\$NETBIRD_CLOUD \$\$NETBIRD_AGENT_NETWORK_ONLY \$\$NETBIRD_AGENT_NETWORK_ENABLED \$\$NETBIRD_HUBSPOT_PORTAL_ID \$\$NETBIRD_HUBSPOT_SIGNUP_FORM_ID \$\$NETBIRD_HUBSPOT_ONBOARDING_FORM_ID \$\$NETBIRD_HUBSPOT_SURVEY_FORM_ID \$\$NETBIRD_ANALYTICS_EXCLUDED_EMAILS \$\$NETBIRD_ANNOUNCEMENT"

OIDC_TRUSTED_DOMAINS="/usr/share/nginx/html/OidcTrustedDomains.js"
envsubst "$ENV_STR" < "$OIDC_TRUSTED_DOMAINS".tmpl > "$OIDC_TRUSTED_DOMAINS"
Expand Down
18 changes: 17 additions & 1 deletion src/contexts/AnnouncementProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { AnnouncementVariant } from "@components/ui/AnnouncementBanner";
import { deploymentAnnouncement } from "@utils/announcement";
import loadConfig from "@utils/config";
import { isNetBirdCloud } from "@utils/netbird";
import md5 from "crypto-js/md5";
import React, {
createContext,
Expand All @@ -10,7 +13,8 @@ import React, {
import { useMSP } from "@/cloud/msp/contexts/MSPProvider";
import { trialExpiresInfo, usageLimitInfo } from "@/contexts/BillingProvider";
import { usePermissions } from "@/contexts/PermissionsProvider";
import { isNetBirdCloud } from "@utils/netbird";

const config = loadConfig();

const ANNOUNCEMENTS_URL =
"https://raw.githubusercontent.com/netbirdio/dashboard/main/announcements.json";
Expand Down Expand Up @@ -179,6 +183,18 @@ export default function AnnouncementProvider({ children }: Readonly<Props>) {
allAnnouncements.unshift(...mspAnnouncements);
}

// The operator's own announcement for this deployment
// (NETBIRD_ANNOUNCEMENT) stays up ahead of the remote and MSP ones;
// only the billing warnings below, when they open, come before it.
const deployment = deploymentAnnouncement(config.announcement);
if (deployment) {
allAnnouncements.unshift({
...deployment,
hash: md5(deployment.text).toString(),
isOpen: true,
});
}

// Add billing announcements (initially closed, opened by BillingProvider)
allAnnouncements.unshift({
...trialExpiresInfo,
Expand Down
23 changes: 23 additions & 0 deletions src/utils/announcement.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { describe, expect, it } from "vitest";
import { deploymentAnnouncement } from "./announcement";

describe("deploymentAnnouncement", () => {
it.each([undefined, "", " ", "\n"])(
"is absent for blank text (%j)",
(text) => {
expect(deploymentAnnouncement(text)).toBeUndefined();
},
);

it("is a permanent, prominent announcement for every edition", () => {
expect(
deploymentAnnouncement(" Connected to management replica mgmt-1 "),
).toEqual({
tag: "",
text: "Connected to management replica mgmt-1",
variant: "important",
closeable: false,
isCloudOnly: false,
});
});
});
21 changes: 21 additions & 0 deletions src/utils/announcement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { Announcement } from "@/contexts/AnnouncementProvider";

// deploymentAnnouncement turns the text an operator sets through
// NETBIRD_ANNOUNCEMENT into the announcement the banner shows for it: up for
// good (not closeable), for every edition, and in the prominent variant,
// since its job is to tell one deployment apart from another at a glance. A
// development cluster uses it to say which management instance each of its
// dashboards talks to. Blank text means no announcement.
export const deploymentAnnouncement = (
text?: string,
): Announcement | undefined => {
const trimmed = text?.trim();
if (!trimmed) return undefined;
return {
tag: "",
text: trimmed,
variant: "important",
closeable: false,
isCloudOnly: false,
};
};
5 changes: 5 additions & 0 deletions src/utils/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ interface Config {
hubspotOnboardingFormId?: string;
hubspotSurveyFormId?: string;
analyticsExcludedEmails: string[];
// announcement: text the operator wants every user of this deployment to
// see in a permanent banner (NETBIRD_ANNOUNCEMENT), e.g. which environment
// or backend instance a dashboard belongs to. Unset for none.
announcement?: string;
}

/**
Expand Down Expand Up @@ -95,6 +99,7 @@ const loadConfig = (): Config => {
.split(",")
.map((email: string) => email.trim())
.filter(Boolean),
announcement: configJson?.announcement || undefined,
} as Config;
};

Expand Down
Loading