restyle client regen credentials

This commit is contained in:
miloschwartz
2025-12-06 11:47:50 -05:00
parent 3f4fae8f09
commit 1d303feca2

View File

@@ -1,27 +1,37 @@
"use client";
import RegenerateCredentialsModal from "@app/components/RegenerateCredentialsModal";
import { SecurityFeaturesAlert } from "@app/components/SecurityFeaturesAlert";
import { useState } from "react";
import {
SettingsContainer,
SettingsSection,
SettingsSectionBody,
SettingsSectionDescription,
SettingsSectionFooter,
SettingsSectionHeader,
SettingsSectionTitle
} from "@app/components/Settings";
import { Button } from "@app/components/ui/button";
import { useClientContext } from "@app/hooks/useClientContext";
import { createApiClient, formatAxiosError } from "@app/lib/api";
import { useEnvContext } from "@app/hooks/useEnvContext";
import { toast } from "@app/hooks/useToast";
import { useParams, useRouter } from "next/navigation";
import { useTranslations } from "next-intl";
import { PickClientDefaultsResponse } from "@server/routers/client";
import { useClientContext } from "@app/hooks/useClientContext";
import ConfirmDeleteDialog from "@app/components/ConfirmDeleteDialog";
import { useLicenseStatusContext } from "@app/hooks/useLicenseStatusContext";
import { useSubscriptionStatusContext } from "@app/hooks/useSubscriptionStatusContext";
import { toast } from "@app/hooks/useToast";
import { createApiClient } from "@app/lib/api";
import { build } from "@server/build";
import { PickClientDefaultsResponse } from "@server/routers/client";
import { useTranslations } from "next-intl";
import { useParams, useRouter } from "next/navigation";
import { useState } from "react";
import { SecurityFeaturesAlert } from "@app/components/SecurityFeaturesAlert";
import {
InfoSection,
InfoSectionContent,
InfoSections,
InfoSectionTitle
} from "@app/components/InfoSection";
import CopyToClipboard from "@app/components/CopyToClipboard";
import { Alert, AlertDescription, AlertTitle } from "@app/components/ui/alert";
import { InfoIcon } from "lucide-react";
export default function CredentialsPage() {
const { env } = useEnvContext();
@@ -34,6 +44,11 @@ export default function CredentialsPage() {
const [modalOpen, setModalOpen] = useState(false);
const [clientDefaults, setClientDefaults] =
useState<PickClientDefaultsResponse | null>(null);
const [currentOlmId, setCurrentOlmId] = useState<string | null>(null);
const [regeneratedSecret, setRegeneratedSecret] = useState<string | null>(
null
);
const [showCredentialsAlert, setShowCredentialsAlert] = useState(false);
const { licenseStatus, isUnlocked } = useLicenseStatusContext();
const subscription = useSubscriptionStatusContext();
@@ -46,76 +61,150 @@ export default function CredentialsPage() {
};
const handleConfirmRegenerate = async () => {
const res = await api.get(`/org/${orgId}/pick-client-defaults`);
if (res && res.status === 200) {
const data = res.data.data;
try {
const res = await api.get(`/org/${orgId}/pick-client-defaults`);
if (res && res.status === 200) {
const data = res.data.data;
const rekeyRes = await api.post(
`/re-key/${client?.clientId}/regenerate-client-secret`,
{
secret: data.olmSecret
const rekeyRes = await api.post(
`/re-key/${client?.clientId}/regenerate-client-secret`,
{
secret: data.olmSecret
}
);
if (rekeyRes && rekeyRes.status === 200) {
const rekeyData = rekeyRes.data.data;
if (rekeyData && rekeyData.olmId) {
setCurrentOlmId(rekeyData.olmId);
setRegeneratedSecret(data.olmSecret);
setClientDefaults({
...data,
olmId: rekeyData.olmId
});
setShowCredentialsAlert(true);
}
}
);
if (rekeyRes && rekeyRes.status === 200) {
const rekeyData = rekeyRes.data.data;
setClientDefaults({
...data,
olmId: rekeyData.olmId,
toast({
title: t("credentialsSaved"),
description: t("credentialsSavedDescription")
});
}
} catch (error) {
toast({
title: t("credentialsSaved"),
description: t("credentialsSavedDescription")
variant: "destructive",
title: t("error") || "Error",
description:
formatAxiosError(error) ||
t("credentialsRegenerateError") ||
"Failed to regenerate credentials"
});
router.refresh();
}
};
const getCredentials = () => {
if (clientDefaults) {
return {
Id: clientDefaults.olmId,
Secret: clientDefaults.olmSecret
};
}
return undefined;
const getConfirmationString = () => {
return client?.name || client?.clientId?.toString() || "My client";
};
const displayOlmId = currentOlmId || clientDefaults?.olmId || null;
const displaySecret = regeneratedSecret || null;
return (
<>
<SettingsContainer>
<SettingsSection>
<SettingsSectionHeader>
<SettingsSectionTitle>
{t("generatedcredentials")}
{t("clientOlmCredentials")}
</SettingsSectionTitle>
<SettingsSectionDescription>
{t("regenerateCredentials")}
{t("clientOlmCredentialsDescription")}
</SettingsSectionDescription>
</SettingsSectionHeader>
<SettingsSectionBody>
<SecurityFeaturesAlert />
<InfoSections cols={3}>
<InfoSection>
<InfoSectionTitle>
{t("olmEndpoint")}
</InfoSectionTitle>
<InfoSectionContent>
<CopyToClipboard
text={env.app.dashboardUrl}
/>
</InfoSectionContent>
</InfoSection>
<InfoSection>
<InfoSectionTitle>
{t("olmId")}
</InfoSectionTitle>
<InfoSectionContent>
{displayOlmId ? (
<CopyToClipboard text={displayOlmId} />
) : (
<span>{"••••••••••••••••"}</span>
)}
</InfoSectionContent>
</InfoSection>
<InfoSection>
<InfoSectionTitle>
{t("olmSecretKey")}
</InfoSectionTitle>
<InfoSectionContent>
{displaySecret ? (
<CopyToClipboard text={displaySecret} />
) : (
<span>{"••••••••••••••••"}</span>
)}
</InfoSectionContent>
</InfoSection>
</InfoSections>
{showCredentialsAlert && displaySecret && (
<Alert variant="neutral" className="mt-4">
<InfoIcon className="h-4 w-4" />
<AlertTitle className="font-semibold">
{t("clientCredentialsSave")}
</AlertTitle>
<AlertDescription>
{t("clientCredentialsSaveDescription")}
</AlertDescription>
</Alert>
)}
</SettingsSectionBody>
<SettingsSectionFooter>
<Button
onClick={() => setModalOpen(true)}
disabled={isSecurityFeatureDisabled()}
>
{t("regeneratecredentials")}
{t("regenerateCredentialsButton")}
</Button>
</SettingsSectionBody>
</SettingsSectionFooter>
</SettingsSection>
</SettingsContainer>
<RegenerateCredentialsModal
<ConfirmDeleteDialog
open={modalOpen}
onOpenChange={setModalOpen}
type="client-olm"
onConfirmRegenerate={handleConfirmRegenerate}
dashboardUrl={env.app.dashboardUrl}
credentials={getCredentials()}
setOpen={(val) => {
setModalOpen(val);
// Prevent modal from reopening during refresh
if (!val) {
setTimeout(() => {
router.refresh();
}, 150);
}
}}
dialog={
<div className="space-y-2">
<p>{t("regenerateCredentialsConfirmation")}</p>
<p>{t("regenerateCredentialsWarning")}</p>
</div>
}
buttonText={t("regenerateCredentialsButton")}
onConfirm={handleConfirmRegenerate}
string={getConfirmationString()}
title={t("regenerateCredentials")}
warningText={t("cannotbeUndone")}
/>
</>
);