show credentials tab in oss

This commit is contained in:
miloschwartz
2025-12-06 13:11:53 -05:00
parent d714f7d52c
commit 22941c0653
6 changed files with 110 additions and 126 deletions

View File

@@ -138,6 +138,8 @@ export default function CredentialsPage() {
</SettingsSectionDescription> </SettingsSectionDescription>
</SettingsSectionHeader> </SettingsSectionHeader>
<SettingsSectionBody> <SettingsSectionBody>
<SecurityFeaturesAlert />
<InfoSections cols={3}> <InfoSections cols={3}>
<InfoSection> <InfoSection>
<InfoSectionTitle> <InfoSectionTitle>
@@ -194,29 +196,31 @@ export default function CredentialsPage() {
</Alert> </Alert>
)} )}
</SettingsSectionBody> </SettingsSectionBody>
<SettingsSectionFooter> {build !== "oss" && (
<div className="flex gap-2"> <SettingsSectionFooter>
<Button <div className="flex gap-2">
variant="outline" <Button
onClick={() => { variant="outline"
setShouldDisconnect(false); onClick={() => {
setModalOpen(true); setShouldDisconnect(false);
}} setModalOpen(true);
disabled={isSecurityFeatureDisabled()} }}
> disabled={isSecurityFeatureDisabled()}
{t("regenerateCredentialsButton")} >
</Button> {t("regenerateCredentialsButton")}
<Button </Button>
onClick={() => { <Button
setShouldDisconnect(true); onClick={() => {
setModalOpen(true); setShouldDisconnect(true);
}} setModalOpen(true);
disabled={isSecurityFeatureDisabled()} }}
> disabled={isSecurityFeatureDisabled()}
{t("remoteExitNodeRegenerateAndDisconnect")} >
</Button> {t("remoteExitNodeRegenerateAndDisconnect")}
</div> </Button>
</SettingsSectionFooter> </div>
</SettingsSectionFooter>
)}
</SettingsSection> </SettingsSection>
</SettingsContainer> </SettingsContainer>
@@ -236,19 +240,27 @@ export default function CredentialsPage() {
{shouldDisconnect ? ( {shouldDisconnect ? (
<> <>
<p> <p>
{t("remoteExitNodeRegenerateAndDisconnectConfirmation")} {t(
"remoteExitNodeRegenerateAndDisconnectConfirmation"
)}
</p> </p>
<p> <p>
{t("remoteExitNodeRegenerateAndDisconnectWarning")} {t(
"remoteExitNodeRegenerateAndDisconnectWarning"
)}
</p> </p>
</> </>
) : ( ) : (
<> <>
<p> <p>
{t("remoteExitNodeRegenerateCredentialsConfirmation")} {t(
"remoteExitNodeRegenerateCredentialsConfirmation"
)}
</p> </p>
<p> <p>
{t("remoteExitNodeRegenerateCredentialsWarning")} {t(
"remoteExitNodeRegenerateCredentialsWarning"
)}
</p> </p>
</> </>
)} )}

View File

@@ -44,12 +44,13 @@ export default function CredentialsPage() {
const [modalOpen, setModalOpen] = useState(false); const [modalOpen, setModalOpen] = useState(false);
const [clientDefaults, setClientDefaults] = const [clientDefaults, setClientDefaults] =
useState<PickClientDefaultsResponse | null>(null); useState<PickClientDefaultsResponse | null>(null);
const [currentOlmId, setCurrentOlmId] = useState<string | null>(client.olmId); const [currentOlmId, setCurrentOlmId] = useState<string | null>(
client.olmId
);
const [regeneratedSecret, setRegeneratedSecret] = useState<string | null>( const [regeneratedSecret, setRegeneratedSecret] = useState<string | null>(
null null
); );
const [showCredentialsAlert, setShowCredentialsAlert] = useState(false); const [showCredentialsAlert, setShowCredentialsAlert] = useState(false);
const [shouldDisconnect, setShouldDisconnect] = useState(true);
const { licenseStatus, isUnlocked } = useLicenseStatusContext(); const { licenseStatus, isUnlocked } = useLicenseStatusContext();
const subscription = useSubscriptionStatusContext(); const subscription = useSubscriptionStatusContext();
@@ -70,8 +71,7 @@ export default function CredentialsPage() {
const rekeyRes = await api.post( const rekeyRes = await api.post(
`/re-key/${client?.clientId}/regenerate-client-secret`, `/re-key/${client?.clientId}/regenerate-client-secret`,
{ {
secret: data.olmSecret, secret: data.olmSecret
disconnect: shouldDisconnect
} }
); );
@@ -125,6 +125,8 @@ export default function CredentialsPage() {
</SettingsSectionDescription> </SettingsSectionDescription>
</SettingsSectionHeader> </SettingsSectionHeader>
<SettingsSectionBody> <SettingsSectionBody>
<SecurityFeaturesAlert />
<InfoSections cols={3}> <InfoSections cols={3}>
<InfoSection> <InfoSection>
<InfoSectionTitle> <InfoSectionTitle>
@@ -156,7 +158,9 @@ export default function CredentialsPage() {
{displaySecret ? ( {displaySecret ? (
<CopyToClipboard text={displaySecret} /> <CopyToClipboard text={displaySecret} />
) : ( ) : (
<span>{"••••••••••••••••••••••••••••••••"}</span> <span>
{"••••••••••••••••••••••••••••••••"}
</span>
)} )}
</InfoSectionContent> </InfoSectionContent>
</InfoSection> </InfoSection>
@@ -174,29 +178,16 @@ export default function CredentialsPage() {
</Alert> </Alert>
)} )}
</SettingsSectionBody> </SettingsSectionBody>
<SettingsSectionFooter> {build !== "oss" && (
<div className="flex gap-2"> <SettingsSectionFooter>
<Button <Button
variant="outline" onClick={() => setModalOpen(true)}
onClick={() => {
setShouldDisconnect(false);
setModalOpen(true);
}}
disabled={isSecurityFeatureDisabled()} disabled={isSecurityFeatureDisabled()}
> >
{t("regenerateCredentialsButton")} {t("regenerateCredentialsButton")}
</Button> </Button>
<Button </SettingsSectionFooter>
onClick={() => { )}
setShouldDisconnect(true);
setModalOpen(true);
}}
disabled={isSecurityFeatureDisabled()}
>
{t("clientRegenerateAndDisconnect")}
</Button>
</div>
</SettingsSectionFooter>
</SettingsSection> </SettingsSection>
</SettingsContainer> </SettingsContainer>
@@ -213,32 +204,11 @@ export default function CredentialsPage() {
}} }}
dialog={ dialog={
<div className="space-y-2"> <div className="space-y-2">
{shouldDisconnect ? ( <p>{t("regenerateCredentialsConfirmation")}</p>
<> <p>{t("regenerateCredentialsWarning")}</p>
<p>
{t("clientRegenerateAndDisconnectConfirmation")}
</p>
<p>
{t("clientRegenerateAndDisconnectWarning")}
</p>
</>
) : (
<>
<p>
{t("clientRegenerateCredentialsConfirmation")}
</p>
<p>
{t("clientRegenerateCredentialsWarning")}
</p>
</>
)}
</div> </div>
} }
buttonText={ buttonText={t("regenerateCredentialsButton")}
shouldDisconnect
? t("clientRegenerateAndDisconnect")
: t("regenerateCredentialsButton")
}
onConfirm={handleConfirmRegenerate} onConfirm={handleConfirmRegenerate}
string={getConfirmationString()} string={getConfirmationString()}
title={t("regenerateCredentials")} title={t("regenerateCredentials")}

View File

@@ -39,14 +39,10 @@ export default async function SettingsLayout(props: SettingsLayoutProps) {
title: t("general"), title: t("general"),
href: `/{orgId}/settings/clients/machine/{clientId}/general` href: `/{orgId}/settings/clients/machine/{clientId}/general`
}, },
...(build === "enterprise" {
? [ title: t("credentials"),
{ href: `/{orgId}/settings/clients/machine/{clientId}/credentials`
title: t("credentials"), }
href: `/{orgId}/settings/clients/machine/{clientId}/credentials`
}
]
: [])
]; ];
return ( return (

View File

@@ -202,6 +202,9 @@ export default function CredentialsPage() {
{t("siteNewtCredentialsDescription")} {t("siteNewtCredentialsDescription")}
</SettingsSectionDescription> </SettingsSectionDescription>
</SettingsSectionHeader> </SettingsSectionHeader>
<SecurityFeaturesAlert />
<SettingsSectionBody> <SettingsSectionBody>
<InfoSections cols={3}> <InfoSections cols={3}>
<InfoSection> <InfoSection>
@@ -260,29 +263,31 @@ export default function CredentialsPage() {
</Alert> </Alert>
)} )}
</SettingsSectionBody> </SettingsSectionBody>
<SettingsSectionFooter> {build !== "oss" && (
<div className="flex gap-2"> <SettingsSectionFooter>
<Button <div className="flex gap-2">
variant="outline" <Button
onClick={() => { variant="outline"
setShouldDisconnect(false); onClick={() => {
setModalOpen(true); setShouldDisconnect(false);
}} setModalOpen(true);
disabled={isSecurityFeatureDisabled()} }}
> disabled={isSecurityFeatureDisabled()}
{t("regenerateCredentialsButton")} >
</Button> {t("regenerateCredentialsButton")}
<Button </Button>
onClick={() => { <Button
setShouldDisconnect(true); onClick={() => {
setModalOpen(true); setShouldDisconnect(true);
}} setModalOpen(true);
disabled={isSecurityFeatureDisabled()} }}
> disabled={isSecurityFeatureDisabled()}
{t("siteRegenerateAndDisconnect")} >
</Button> {t("siteRegenerateAndDisconnect")}
</div> </Button>
</SettingsSectionFooter> </div>
</SettingsSectionFooter>
)}
</SettingsSection> </SettingsSection>
)} )}
@@ -367,14 +372,16 @@ export default function CredentialsPage() {
</> </>
)} )}
</SettingsSectionBody> </SettingsSectionBody>
<SettingsSectionFooter> {build === "enterprise" && (
<Button <SettingsSectionFooter>
onClick={() => setModalOpen(true)} <Button
disabled={isSecurityFeatureDisabled()} onClick={() => setModalOpen(true)}
> disabled={isSecurityFeatureDisabled()}
{t("siteRegenerateAndDisconnect")} >
</Button> {t("siteRegenerateAndDisconnect")}
</SettingsSectionFooter> </Button>
</SettingsSectionFooter>
)}
</SettingsSection> </SettingsSection>
)} )}
</SettingsContainer> </SettingsContainer>

View File

@@ -35,25 +35,24 @@ export default async function SettingsLayout(props: SettingsLayoutProps) {
const navItems = [ const navItems = [
{ {
title: t('general'), title: t("general"),
href: `/${params.orgId}/settings/sites/${params.niceId}/general`, href: `/${params.orgId}/settings/sites/${params.niceId}/general`
}, },
...(site.type !== 'local' && build === 'enterprise' ...(site.type !== "local"
? [ ? [
{ {
title: t('credentials'), title: t("credentials"),
href: `/${params.orgId}/settings/sites/${params.niceId}/credentials`, href: `/${params.orgId}/settings/sites/${params.niceId}/credentials`
}, }
] ]
: []), : [])
]; ];
return ( return (
<> <>
<SettingsSectionTitle <SettingsSectionTitle
title={t('siteSetting', { siteName: site?.name })} title={t("siteSetting", { siteName: site?.name })}
description={t('siteSettingDescription')} description={t("siteSettingDescription")}
/> />
<SiteProvider site={site}> <SiteProvider site={site}>

View File

@@ -14,7 +14,7 @@ const alertVariants = cva(
"border-destructive/50 border bg-destructive/10 text-destructive dark:border-destructive [&>svg]:text-destructive", "border-destructive/50 border bg-destructive/10 text-destructive dark:border-destructive [&>svg]:text-destructive",
success: success:
"border-green-500/50 border bg-green-500/10 text-green-500 dark:border-success [&>svg]:text-green-500", "border-green-500/50 border bg-green-500/10 text-green-500 dark:border-success [&>svg]:text-green-500",
info: "border-blue-500/50 border bg-blue-500/10 text-blue-800 dark:border-blue-400 [&>svg]:text-blue-500", info: "border-blue-500/50 border bg-blue-500/10 text-blue-800 dark:text-blue-400 dark:border-blue-400 [&>svg]:text-blue-500",
warning: warning:
"border-yellow-500 border text-yellow-800 bg-yellow-500/20 dark:bg-yellow-800/20 dark:text-yellow-100 dark:border-yellow-700 [&>svg]:text-yellow-500" "border-yellow-500 border text-yellow-800 bg-yellow-500/20 dark:bg-yellow-800/20 dark:text-yellow-100 dark:border-yellow-700 [&>svg]:text-yellow-500"
} }