fix: licenses in community edition & improve messaging (#7456)

Enhance platform to handle cloud, self-hosted, community, and enterprise user types with tailored routing, error handling, and feature access.
This commit is contained in:
Yunus M 2025-04-02 01:12:42 +05:30 committed by GitHub
parent 07a244f569
commit 597752a4bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 226 additions and 158 deletions

View File

@ -1,3 +1,4 @@
import * as Sentry from '@sentry/react';
import { ConfigProvider } from 'antd'; import { ConfigProvider } from 'antd';
import getLocalStorageApi from 'api/browser/localstorage/get'; import getLocalStorageApi from 'api/browser/localstorage/get';
import setLocalStorageApi from 'api/browser/localstorage/set'; import setLocalStorageApi from 'api/browser/localstorage/set';
@ -15,6 +16,7 @@ import { LICENSE_PLAN_KEY } from 'hooks/useLicense';
import { NotificationProvider } from 'hooks/useNotifications'; import { NotificationProvider } from 'hooks/useNotifications';
import { ResourceProvider } from 'hooks/useResourceAttribute'; import { ResourceProvider } from 'hooks/useResourceAttribute';
import history from 'lib/history'; import history from 'lib/history';
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
import posthog from 'posthog-js'; import posthog from 'posthog-js';
import AlertRuleProvider from 'providers/Alert'; import AlertRuleProvider from 'providers/Alert';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
@ -46,7 +48,6 @@ function App(): JSX.Element {
activeLicenseV3, activeLicenseV3,
isFetchingActiveLicenseV3, isFetchingActiveLicenseV3,
userFetchError, userFetchError,
licensesFetchError,
featureFlagsFetchError, featureFlagsFetchError,
isLoggedIn: isLoggedInState, isLoggedIn: isLoggedInState,
featureFlags, featureFlags,
@ -56,10 +57,7 @@ function App(): JSX.Element {
const { hostname, pathname } = window.location; const { hostname, pathname } = window.location;
const { const { isCloudUser, isEnterpriseSelfHostedUser } = useGetTenantLicense();
isCloudUser: isCloudUserVal,
isEECloudUser: isEECloudUserVal,
} = useGetTenantLicense();
const enableAnalytics = useCallback( const enableAnalytics = useCallback(
(user: IUser): void => { (user: IUser): void => {
@ -169,7 +167,7 @@ function App(): JSX.Element {
let updatedRoutes = defaultRoutes; let updatedRoutes = defaultRoutes;
// if the user is a cloud user // if the user is a cloud user
if (isCloudUserVal || isEECloudUserVal) { if (isCloudUser || isEnterpriseSelfHostedUser) {
// if the user is on basic plan then remove billing // if the user is on basic plan then remove billing
if (isOnBasicPlan) { if (isOnBasicPlan) {
updatedRoutes = updatedRoutes.filter( updatedRoutes = updatedRoutes.filter(
@ -191,10 +189,10 @@ function App(): JSX.Element {
isLoggedInState, isLoggedInState,
user, user,
licenses, licenses,
isCloudUserVal, isCloudUser,
isEnterpriseSelfHostedUser,
isFetchingLicenses, isFetchingLicenses,
isFetchingUser, isFetchingUser,
isEECloudUserVal,
]); ]);
useEffect(() => { useEffect(() => {
@ -209,6 +207,7 @@ function App(): JSX.Element {
} }
}, [pathname]); }, [pathname]);
// eslint-disable-next-line sonarjs/cognitive-complexity
useEffect(() => { useEffect(() => {
// feature flag shouldn't be loading and featureFlags or fetchError any one of this should be true indicating that req is complete // feature flag shouldn't be loading and featureFlags or fetchError any one of this should be true indicating that req is complete
// licenses should also be present. there is no check for licenses for loading and error as that is mandatory if not present then routing // licenses should also be present. there is no check for licenses for loading and error as that is mandatory if not present then routing
@ -234,7 +233,12 @@ function App(): JSX.Element {
const showAddCreditCardModal = const showAddCreditCardModal =
!isPremiumSupportEnabled && !trialInfo?.trialConvertedToSubscription; !isPremiumSupportEnabled && !trialInfo?.trialConvertedToSubscription;
if (isLoggedInState && isChatSupportEnabled && !showAddCreditCardModal) { if (
isLoggedInState &&
isChatSupportEnabled &&
!showAddCreditCardModal &&
(isCloudUser || isEnterpriseSelfHostedUser)
) {
window.Intercom('boot', { window.Intercom('boot', {
app_id: process.env.INTERCOM_APP_ID, app_id: process.env.INTERCOM_APP_ID,
email: user?.email || '', email: user?.email || '',
@ -253,13 +257,53 @@ function App(): JSX.Element {
licenses, licenses,
activeLicenseV3, activeLicenseV3,
trialInfo, trialInfo,
isCloudUser,
isEnterpriseSelfHostedUser,
]); ]);
useEffect(() => { useEffect(() => {
if (!isFetchingUser && isCloudUserVal && user && user.email) { if (!isFetchingUser && isCloudUser && user && user.email) {
enableAnalytics(user); enableAnalytics(user);
} }
}, [user, isFetchingUser, isCloudUserVal, enableAnalytics]); }, [user, isFetchingUser, isCloudUser, enableAnalytics]);
useEffect(() => {
if (isCloudUser || isEnterpriseSelfHostedUser) {
if (process.env.POSTHOG_KEY) {
posthog.init(process.env.POSTHOG_KEY, {
api_host: 'https://us.i.posthog.com',
person_profiles: 'identified_only', // or 'always' to create profiles for anonymous users as well
});
}
Sentry.init({
dsn: process.env.SENTRY_DSN,
tunnel: process.env.TUNNEL_URL,
environment: 'production',
integrations: [
Sentry.browserTracingIntegration(),
Sentry.replayIntegration({
maskAllText: false,
blockAllMedia: false,
}),
],
// Performance Monitoring
tracesSampleRate: 1.0, // Capture 100% of the transactions
// Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled
tracePropagationTargets: [],
// Session Replay
replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.
});
} else {
posthog.reset();
Sentry.close();
if (window.cioanalytics && typeof window.cioanalytics.reset === 'function') {
window.cioanalytics.reset();
}
}
}, [isCloudUser, isEnterpriseSelfHostedUser]);
// if the user is in logged in state // if the user is in logged in state
if (isLoggedInState) { if (isLoggedInState) {
@ -271,24 +315,18 @@ function App(): JSX.Element {
// if the required calls fails then return a something went wrong error // if the required calls fails then return a something went wrong error
// this needs to be on top of data missing error because if there is an error, data will never be loaded and it will // this needs to be on top of data missing error because if there is an error, data will never be loaded and it will
// move to indefinitive loading // move to indefinitive loading
if ( if (userFetchError && pathname !== ROUTES.SOMETHING_WENT_WRONG) {
(userFetchError || licensesFetchError) &&
pathname !== ROUTES.SOMETHING_WENT_WRONG
) {
history.replace(ROUTES.SOMETHING_WENT_WRONG); history.replace(ROUTES.SOMETHING_WENT_WRONG);
} }
// if all of the data is not set then return a spinner, this is required because there is some gap between loading states and data setting // if all of the data is not set then return a spinner, this is required because there is some gap between loading states and data setting
if ( if ((!licenses || !user.email || !featureFlags) && !userFetchError) {
(!licenses || !user.email || !featureFlags) &&
!userFetchError &&
!licensesFetchError
) {
return <Spinner tip="Loading..." />; return <Spinner tip="Loading..." />;
} }
} }
return ( return (
<Sentry.ErrorBoundary fallback={<ErrorBoundaryFallback />}>
<ConfigProvider theme={themeConfig}> <ConfigProvider theme={themeConfig}>
<Router history={history}> <Router history={history}>
<CompatRouter> <CompatRouter>
@ -310,7 +348,6 @@ function App(): JSX.Element {
component={component} component={component}
/> />
))} ))}
<Route exact path="/" component={Home} /> <Route exact path="/" component={Home} />
<Route path="*" component={NotFound} /> <Route path="*" component={NotFound} />
</Switch> </Switch>
@ -326,6 +363,7 @@ function App(): JSX.Element {
</CompatRouter> </CompatRouter>
</Router> </Router>
</ConfigProvider> </ConfigProvider>
</Sentry.ErrorBoundary>
); );
} }

View File

@ -61,7 +61,7 @@ export default function CustomDomainSettings(): JSX.Element {
isLoading: isLoadingDeploymentsData, isLoading: isLoadingDeploymentsData,
isFetching: isFetchingDeploymentsData, isFetching: isFetchingDeploymentsData,
refetch: refetchDeploymentsData, refetch: refetchDeploymentsData,
} = useGetDeploymentsData(); } = useGetDeploymentsData(true);
const { const {
mutate: updateSubDomain, mutate: updateSubDomain,

View File

@ -23,10 +23,13 @@ function DataSourceInfo({
const notSendingData = !dataSentToSigNoz; const notSendingData = !dataSentToSigNoz;
const isEnabled =
activeLicenseV3 && activeLicenseV3.platform === LicensePlatform.CLOUD;
const { const {
data: deploymentsData, data: deploymentsData,
isError: isErrorDeploymentsData, isError: isErrorDeploymentsData,
} = useGetDeploymentsData(); } = useGetDeploymentsData(isEnabled || false);
const [region, setRegion] = useState<string>(''); const [region, setRegion] = useState<string>('');
const [url, setUrl] = useState<string>(''); const [url, setUrl] = useState<string>('');

View File

@ -293,7 +293,7 @@ function MultiIngestionSettings(): JSX.Element {
isLoading: isLoadingDeploymentsData, isLoading: isLoadingDeploymentsData,
isFetching: isFetchingDeploymentsData, isFetching: isFetchingDeploymentsData,
isError: isErrorDeploymentsData, isError: isErrorDeploymentsData,
} = useGetDeploymentsData(); } = useGetDeploymentsData(true);
const { const {
mutate: createIngestionKey, mutate: createIngestionKey,

View File

@ -63,7 +63,7 @@ export default function OnboardingIngestionDetails(): JSX.Element {
isLoading: isLoadingDeploymentsData, isLoading: isLoadingDeploymentsData,
isFetching: isFetchingDeploymentsData, isFetching: isFetchingDeploymentsData,
isError: isDeploymentsDataError, isError: isDeploymentsDataError,
} = useGetDeploymentsData(); } = useGetDeploymentsData(true);
const handleCopyKey = (text: string): void => { const handleCopyKey = (text: string): void => {
handleCopyToClipboard(text); handleCopyToClipboard(text);

View File

@ -69,6 +69,12 @@
opacity: 1; opacity: 1;
transition: all 0.2s; transition: all 0.2s;
} }
&.community-enterprise-user {
color: var(--bg-sakura-500);
background: rgba(255, 113, 113, 0.1);
border: 1px solid var(--bg-sakura-500);
}
} }
.dockBtn { .dockBtn {

View File

@ -3,7 +3,7 @@
import './SideNav.styles.scss'; import './SideNav.styles.scss';
import { Color } from '@signozhq/design-tokens'; import { Color } from '@signozhq/design-tokens';
import { Button } from 'antd'; import { Button, Tooltip } from 'antd';
import logEvent from 'api/common/logEvent'; import logEvent from 'api/common/logEvent';
import cx from 'classnames'; import cx from 'classnames';
import { FeatureKeys } from 'constants/features'; import { FeatureKeys } from 'constants/features';
@ -75,7 +75,7 @@ function SideNav(): JSX.Element {
const [userManagementMenuItems, setUserManagementMenuItems] = useState< const [userManagementMenuItems, setUserManagementMenuItems] = useState<
UserManagementMenuItems[] UserManagementMenuItems[]
>([manageLicenseMenuItem]); >([]);
const onClickSlackHandler = (): void => { const onClickSlackHandler = (): void => {
window.open('https://signoz.io/slack', '_blank'); window.open('https://signoz.io/slack', '_blank');
@ -88,8 +88,10 @@ function SideNav(): JSX.Element {
const { registerShortcut, deregisterShortcut } = useKeyboardHotkeys(); const { registerShortcut, deregisterShortcut } = useKeyboardHotkeys();
const { const {
isCloudUser: isCloudUserVal, isCloudUser,
isEECloudUser: isEECloudUserVal, isEnterpriseSelfHostedUser,
isCommunityUser,
isCommunityEnterpriseUser,
} = useGetTenantLicense(); } = useGetTenantLicense();
const { t } = useTranslation(''); const { t } = useTranslation('');
@ -103,11 +105,6 @@ function SideNav(): JSX.Element {
licenseStatus?.toLocaleLowerCase() === licenseStatus?.toLocaleLowerCase() ===
LICENSE_PLAN_STATUS.VALID.toLocaleLowerCase(); LICENSE_PLAN_STATUS.VALID.toLocaleLowerCase();
const isEnterprise = licenses?.licenses?.some(
(license: License) =>
license.isCurrent && license.planKey === LICENSE_PLAN_KEY.ENTERPRISE_PLAN,
);
const onClickSignozCloud = (): void => { const onClickSignozCloud = (): void => {
window.open( window.open(
'https://signoz.io/oss-to-cloud/?utm_source=product_navbar&utm_medium=frontend&utm_campaign=oss_users', 'https://signoz.io/oss-to-cloud/?utm_source=product_navbar&utm_medium=frontend&utm_campaign=oss_users',
@ -201,14 +198,21 @@ function SideNav(): JSX.Element {
}; };
useEffect(() => { useEffect(() => {
if (isCloudUserVal) { if (isCloudUser) {
setLicenseTag('Cloud'); setLicenseTag('Cloud');
} else if (isEnterprise) { } else if (isEnterpriseSelfHostedUser) {
setLicenseTag('Enterprise'); setLicenseTag('Enterprise');
} else { } else if (isCommunityEnterpriseUser) {
setLicenseTag('Free'); setLicenseTag('Enterprise');
} else if (isCommunityUser) {
setLicenseTag('Community');
} }
}, [isCloudUserVal, isEnterprise]); }, [
isCloudUser,
isEnterpriseSelfHostedUser,
isCommunityEnterpriseUser,
isCommunityUser,
]);
const [isCurrentOrgSettings] = useComponentPermission( const [isCurrentOrgSettings] = useComponentPermission(
['current_org_settings'], ['current_org_settings'],
@ -290,7 +294,7 @@ function SideNav(): JSX.Element {
); );
} }
if (isCloudUserVal || isEECloudUserVal) { if (isCloudUser || isEnterpriseSelfHostedUser) {
const isOnboardingEnabled = const isOnboardingEnabled =
featureFlags?.find((feature) => feature.name === FeatureKeys.ONBOARDING) featureFlags?.find((feature) => feature.name === FeatureKeys.ONBOARDING)
?.active || false; ?.active || false;
@ -317,6 +321,11 @@ function SideNav(): JSX.Element {
} }
updatedUserManagementItems = [helpSupportMenuItem]; updatedUserManagementItems = [helpSupportMenuItem];
// Show manage license menu item for EE cloud users with a active license
if (isEnterpriseSelfHostedUser) {
updatedUserManagementItems.push(manageLicenseMenuItem);
}
} else { } else {
updatedMenuItems = updatedMenuItems.filter( updatedMenuItems = updatedMenuItems.filter(
(item) => item.key !== ROUTES.INTEGRATIONS && item.key !== ROUTES.BILLING, (item) => item.key !== ROUTES.INTEGRATIONS && item.key !== ROUTES.BILLING,
@ -332,20 +341,21 @@ function SideNav(): JSX.Element {
onClick: onClickVersionHandler, onClick: onClickVersionHandler,
}; };
updatedUserManagementItems = [ updatedUserManagementItems = [versionMenuItem, slackSupportMenuItem];
versionMenuItem,
slackSupportMenuItem, if (isCommunityEnterpriseUser) {
manageLicenseMenuItem, updatedUserManagementItems.push(manageLicenseMenuItem);
]; }
} }
setMenuItems(updatedMenuItems); setMenuItems(updatedMenuItems);
setUserManagementMenuItems(updatedUserManagementItems); setUserManagementMenuItems(updatedUserManagementItems);
}, [ }, [
isCommunityEnterpriseUser,
currentVersion, currentVersion,
featureFlags, featureFlags,
isCloudUserVal, isCloudUser,
isEnterpriseSelfHostedUser,
isCurrentVersionError, isCurrentVersionError,
isEECloudUserVal,
isLatestVersion, isLatestVersion,
licenses?.licenses, licenses?.licenses,
onClickVersionHandler, onClickVersionHandler,
@ -372,12 +382,31 @@ function SideNav(): JSX.Element {
</div> </div>
{licenseTag && ( {licenseTag && (
<div className="license tag nav-item-label">{licenseTag}</div> <Tooltip
title={
// eslint-disable-next-line no-nested-ternary
isCommunityUser
? 'You are running the community version of SigNoz. You have to install the Enterprise edition in order enable Enterprise features.'
: isCommunityEnterpriseUser
? 'You do not have an active license present. Add an active license to enable Enterprise features.'
: ''
}
placement="bottomRight"
>
<div
className={cx(
'license tag nav-item-label',
isCommunityEnterpriseUser && 'community-enterprise-user',
)}
>
{licenseTag}
</div>
</Tooltip>
)} )}
</div> </div>
</div> </div>
{isCloudUserVal && user?.role !== USER_ROLES.VIEWER && ( {isCloudUser && user?.role !== USER_ROLES.VIEWER && (
<div className="get-started-nav-items"> <div className="get-started-nav-items">
<Button <Button
className="get-started-btn" className="get-started-btn"
@ -396,7 +425,7 @@ function SideNav(): JSX.Element {
</div> </div>
)} )}
<div className={cx(`nav-wrapper`, isCloudUserVal && 'nav-wrapper-cloud')}> <div className={cx(`nav-wrapper`, isCloudUser && 'nav-wrapper-cloud')}>
<div className="primary-nav-items"> <div className="primary-nav-items">
{menuItems.map((item, index) => ( {menuItems.map((item, index) => (
<NavItem <NavItem

View File

@ -3,11 +3,11 @@ import { AxiosError, AxiosResponse } from 'axios';
import { useQuery, UseQueryResult } from 'react-query'; import { useQuery, UseQueryResult } from 'react-query';
import { DeploymentsDataProps } from 'types/api/customDomain/types'; import { DeploymentsDataProps } from 'types/api/customDomain/types';
export const useGetDeploymentsData = (): UseQueryResult< export const useGetDeploymentsData = (
AxiosResponse<DeploymentsDataProps>, isEnabled: boolean,
AxiosError ): UseQueryResult<AxiosResponse<DeploymentsDataProps>, AxiosError> =>
> =>
useQuery<AxiosResponse<DeploymentsDataProps>, AxiosError>({ useQuery<AxiosResponse<DeploymentsDataProps>, AxiosError>({
queryKey: ['getDeploymentsData'], queryKey: ['getDeploymentsData'],
queryFn: () => getDeploymentsData(), queryFn: () => getDeploymentsData(),
enabled: isEnabled,
}); });

View File

@ -1,15 +1,36 @@
import { AxiosError } from 'axios';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { LicensePlatform } from 'types/api/licensesV3/getActive'; import { LicensePlatform } from 'types/api/licensesV3/getActive';
export const useGetTenantLicense = (): { export const useGetTenantLicense = (): {
isCloudUser: boolean; isCloudUser: boolean;
isEECloudUser: boolean; isEnterpriseSelfHostedUser: boolean;
isCommunityUser: boolean;
isCommunityEnterpriseUser: boolean;
} => { } => {
const { activeLicenseV3 } = useAppContext(); const { activeLicenseV3, activeLicenseV3FetchError } = useAppContext();
return { const responsePayload = {
isCloudUser: activeLicenseV3?.platform === LicensePlatform.CLOUD || false, isCloudUser: activeLicenseV3?.platform === LicensePlatform.CLOUD || false,
isEECloudUser: isEnterpriseSelfHostedUser:
activeLicenseV3?.platform === LicensePlatform.SELF_HOSTED || false, activeLicenseV3?.platform === LicensePlatform.SELF_HOSTED || false,
isCommunityUser: false,
isCommunityEnterpriseUser: false,
}; };
if (
activeLicenseV3FetchError &&
(activeLicenseV3FetchError as AxiosError)?.response?.status === 404
) {
responsePayload.isCommunityEnterpriseUser = true;
}
if (
activeLicenseV3FetchError &&
(activeLicenseV3FetchError as AxiosError)?.response?.status === 501
) {
responsePayload.isCommunityUser = true;
}
return responsePayload;
}; };

View File

@ -1,12 +1,9 @@
import './ReactI18'; import './ReactI18';
import 'styles.scss'; import 'styles.scss';
import * as Sentry from '@sentry/react';
import AppRoutes from 'AppRoutes'; import AppRoutes from 'AppRoutes';
import { AxiosError } from 'axios'; import { AxiosError } from 'axios';
import { ThemeProvider } from 'hooks/useDarkMode'; import { ThemeProvider } from 'hooks/useDarkMode';
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
import posthog from 'posthog-js';
import { AppProvider } from 'providers/App/App'; import { AppProvider } from 'providers/App/App';
import TimezoneProvider from 'providers/Timezone'; import TimezoneProvider from 'providers/Timezone';
import { createRoot } from 'react-dom/client'; import { createRoot } from 'react-dom/client';
@ -37,38 +34,10 @@ const queryClient = new QueryClient({
const container = document.getElementById('root'); const container = document.getElementById('root');
if (process.env.POSTHOG_KEY) {
posthog.init(process.env.POSTHOG_KEY, {
api_host: 'https://us.i.posthog.com',
person_profiles: 'identified_only', // or 'always' to create profiles for anonymous users as well
});
}
Sentry.init({
dsn: process.env.SENTRY_DSN,
tunnel: process.env.TUNNEL_URL,
environment: 'production',
integrations: [
Sentry.browserTracingIntegration(),
Sentry.replayIntegration({
maskAllText: false,
blockAllMedia: false,
}),
],
// Performance Monitoring
tracesSampleRate: 1.0, // Capture 100% of the transactions
// Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled
tracePropagationTargets: [],
// Session Replay
replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.
});
if (container) { if (container) {
const root = createRoot(container); const root = createRoot(container);
root.render( root.render(
<Sentry.ErrorBoundary fallback={<ErrorBoundaryFallback />}>
<HelmetProvider> <HelmetProvider>
<ThemeProvider> <ThemeProvider>
<TimezoneProvider> <TimezoneProvider>
@ -84,7 +53,6 @@ if (container) {
</QueryClientProvider> </QueryClientProvider>
</TimezoneProvider> </TimezoneProvider>
</ThemeProvider> </ThemeProvider>
</HelmetProvider> </HelmetProvider>,
</Sentry.ErrorBoundary>,
); );
} }

View File

@ -13,10 +13,7 @@ import { getRoutes } from './utils';
function SettingsPage(): JSX.Element { function SettingsPage(): JSX.Element {
const { pathname } = useLocation(); const { pathname } = useLocation();
const { user, featureFlags, trialInfo } = useAppContext(); const { user, featureFlags, trialInfo } = useAppContext();
const { const { isCloudUser, isEnterpriseSelfHostedUser } = useGetTenantLicense();
isCloudUser: isCloudAccount,
isEECloudUser: isEECloudAccount,
} = useGetTenantLicense();
const isWorkspaceBlocked = trialInfo?.workSpaceBlock || false; const isWorkspaceBlocked = trialInfo?.workSpaceBlock || false;
@ -37,8 +34,8 @@ function SettingsPage(): JSX.Element {
isCurrentOrgSettings, isCurrentOrgSettings,
isGatewayEnabled, isGatewayEnabled,
isWorkspaceBlocked, isWorkspaceBlocked,
isCloudAccount, isCloudUser,
isEECloudAccount, isEnterpriseSelfHostedUser,
t, t,
), ),
[ [
@ -46,8 +43,8 @@ function SettingsPage(): JSX.Element {
isCurrentOrgSettings, isCurrentOrgSettings,
isGatewayEnabled, isGatewayEnabled,
isWorkspaceBlocked, isWorkspaceBlocked,
isCloudAccount, isCloudUser,
isEECloudAccount, isEnterpriseSelfHostedUser,
t, t,
], ],
); );

View File

@ -17,8 +17,8 @@ export const getRoutes = (
isCurrentOrgSettings: boolean, isCurrentOrgSettings: boolean,
isGatewayEnabled: boolean, isGatewayEnabled: boolean,
isWorkspaceBlocked: boolean, isWorkspaceBlocked: boolean,
isCloudAccount: boolean, isCloudUser: boolean,
isEECloudAccount: boolean, isEnterpriseSelfHostedUser: boolean,
t: TFunction, t: TFunction,
): RouteTabProps['routes'] => { ): RouteTabProps['routes'] => {
const settings = []; const settings = [];
@ -42,17 +42,17 @@ export const getRoutes = (
settings.push(...multiIngestionSettings(t)); settings.push(...multiIngestionSettings(t));
} }
if (isCloudAccount && !isGatewayEnabled) { if (isCloudUser && !isGatewayEnabled) {
settings.push(...ingestionSettings(t)); settings.push(...ingestionSettings(t));
} }
settings.push(...alertChannels(t)); settings.push(...alertChannels(t));
if ((isCloudAccount || isEECloudAccount) && isAdmin) { if ((isCloudUser || isEnterpriseSelfHostedUser) && isAdmin) {
settings.push(...apiKeys(t)); settings.push(...apiKeys(t));
} }
if (isCloudAccount && isAdmin) { if (isCloudUser && isAdmin) {
settings.push(...customDomainSettings(t)); settings.push(...customDomainSettings(t));
} }

View File

@ -56,6 +56,8 @@ func Error(rw http.ResponseWriter, cause error) {
httpCode = http.StatusConflict httpCode = http.StatusConflict
case errors.TypeUnauthenticated: case errors.TypeUnauthenticated:
httpCode = http.StatusUnauthorized httpCode = http.StatusUnauthorized
case errors.TypeUnsupported:
httpCode = http.StatusNotImplemented
} }
rea := make([]responseerroradditional, len(a)) rea := make([]responseerroradditional, len(a))

View File

@ -614,6 +614,13 @@ func (aH *APIHandler) RegisterRoutes(router *mux.Router, am *AuthMiddleware) {
router.HandleFunc("/api/v1/getResetPasswordToken/{id}", am.AdminAccess(aH.getResetPasswordToken)).Methods(http.MethodGet) router.HandleFunc("/api/v1/getResetPasswordToken/{id}", am.AdminAccess(aH.getResetPasswordToken)).Methods(http.MethodGet)
router.HandleFunc("/api/v1/resetPassword", am.OpenAccess(aH.resetPassword)).Methods(http.MethodPost) router.HandleFunc("/api/v1/resetPassword", am.OpenAccess(aH.resetPassword)).Methods(http.MethodPost)
router.HandleFunc("/api/v1/changePassword/{id}", am.SelfAccess(aH.changePassword)).Methods(http.MethodPost) router.HandleFunc("/api/v1/changePassword/{id}", am.SelfAccess(aH.changePassword)).Methods(http.MethodPost)
router.HandleFunc("/api/v3/licenses", am.ViewAccess(func(rw http.ResponseWriter, req *http.Request) {
render.Success(rw, http.StatusOK, []any{})
})).Methods(http.MethodGet)
router.HandleFunc("/api/v3/licenses/active", am.ViewAccess(func(rw http.ResponseWriter, req *http.Request) {
render.Error(rw, errorsV2.New(errorsV2.TypeUnsupported, errorsV2.CodeUnsupported, "not implemented"))
})).Methods(http.MethodGet)
} }
func (ah *APIHandler) MetricExplorerRoutes(router *mux.Router, am *AuthMiddleware) { func (ah *APIHandler) MetricExplorerRoutes(router *mux.Router, am *AuthMiddleware) {

View File

@ -113,8 +113,6 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
// initiate feature manager // initiate feature manager
fm := featureManager.StartManager() fm := featureManager.StartManager()
readerReady := make(chan bool)
fluxIntervalForTraceDetail, err := time.ParseDuration(serverOptions.FluxIntervalForTraceDetail) fluxIntervalForTraceDetail, err := time.ParseDuration(serverOptions.FluxIntervalForTraceDetail)
if err != nil { if err != nil {
return nil, err return nil, err
@ -150,7 +148,6 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
c = cache.NewCache(cacheOpts) c = cache.NewCache(cacheOpts)
} }
<-readerReady
rm, err := makeRulesManager( rm, err := makeRulesManager(
serverOptions.RuleRepoURL, serverOptions.RuleRepoURL,
serverOptions.SigNoz.SQLStore.SQLxDB(), serverOptions.SigNoz.SQLStore.SQLxDB(),