mirror of
https://github.com/formbricks/formbricks.git
synced 2026-05-20 03:07:53 -05:00
chore: update sso deletion backport
This commit is contained in:
+3
@@ -22,6 +22,7 @@ interface DeleteAccountProps {
|
||||
accountDeletionError?: string | string[];
|
||||
isMultiOrgEnabled: boolean;
|
||||
requiresPasswordConfirmation: boolean;
|
||||
isSsoIdentityConfirmationDisabled: boolean;
|
||||
}
|
||||
|
||||
export const DeleteAccount = ({
|
||||
@@ -32,6 +33,7 @@ export const DeleteAccount = ({
|
||||
accountDeletionError,
|
||||
isMultiOrgEnabled,
|
||||
requiresPasswordConfirmation,
|
||||
isSsoIdentityConfirmationDisabled,
|
||||
}: Readonly<DeleteAccountProps>) => {
|
||||
const [isModalOpen, setModalOpen] = useState(false);
|
||||
const isDeleteDisabled = !isMultiOrgEnabled && organizationsWithSingleOwner.length > 0;
|
||||
@@ -73,6 +75,7 @@ export const DeleteAccount = ({
|
||||
user={user}
|
||||
isFormbricksCloud={IS_FORMBRICKS_CLOUD}
|
||||
organizationsWithSingleOwner={organizationsWithSingleOwner}
|
||||
isSsoIdentityConfirmationDisabled={isSsoIdentityConfirmationDisabled}
|
||||
/>
|
||||
<p className="text-sm text-slate-700">
|
||||
<strong>{t("environments.settings.profile.warning_cannot_undo")}</strong>
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import { AuthenticationError } from "@formbricks/types/errors";
|
||||
import { AccountSettingsNavbar } from "@/app/(app)/environments/[environmentId]/settings/(account)/components/AccountSettingsNavbar";
|
||||
import { AccountSecurity } from "@/app/(app)/environments/[environmentId]/settings/(account)/profile/components/AccountSecurity";
|
||||
import { EMAIL_VERIFICATION_DISABLED, IS_FORMBRICKS_CLOUD, PASSWORD_RESET_DISABLED } from "@/lib/constants";
|
||||
import {
|
||||
DISABLE_ACCOUNT_DELETION_SSO_CONFIRMATION,
|
||||
EMAIL_VERIFICATION_DISABLED,
|
||||
IS_FORMBRICKS_CLOUD,
|
||||
PASSWORD_RESET_DISABLED,
|
||||
} from "@/lib/constants";
|
||||
import { getOrganizationsWhereUserIsSingleOwner } from "@/lib/organization/service";
|
||||
import { getUser } from "@/lib/user/service";
|
||||
import { getTranslate } from "@/lingodotdev/server";
|
||||
@@ -98,6 +103,7 @@ const Page = async (props: {
|
||||
isMultiOrgEnabled={isMultiOrgEnabled}
|
||||
accountDeletionError={searchParams.accountDeletionError}
|
||||
requiresPasswordConfirmation={requiresPasswordConfirmation}
|
||||
isSsoIdentityConfirmationDisabled={DISABLE_ACCOUNT_DELETION_SSO_CONFIRMATION}
|
||||
/>
|
||||
</SettingsCard>
|
||||
<IdBadge id={user.id} label={t("common.profile_id")} variant="column" />
|
||||
|
||||
@@ -7,7 +7,6 @@ import { Trans, useTranslation } from "react-i18next";
|
||||
import { logger } from "@formbricks/logger";
|
||||
import { TOrganization } from "@formbricks/types/organizations";
|
||||
import { TUser } from "@formbricks/types/user";
|
||||
import { FORMBRICKS_ENVIRONMENT_ID_LS } from "@/lib/localStorage";
|
||||
import { getFormattedErrorMessage } from "@/lib/utils/helper";
|
||||
import {
|
||||
ACCOUNT_DELETION_CONFIRMATION_REQUIRED_ERROR_CODE,
|
||||
@@ -16,6 +15,7 @@ import {
|
||||
DELETE_ACCOUNT_WRONG_PASSWORD_ERROR,
|
||||
FORMBRICKS_CLOUD_ACCOUNT_DELETION_SURVEY_URL,
|
||||
} from "@/modules/account/constants";
|
||||
import { useSignOut } from "@/modules/auth/hooks/use-sign-out";
|
||||
import { DeleteDialog } from "@/modules/ui/components/delete-dialog";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { PasswordInput } from "@/modules/ui/components/password-input";
|
||||
@@ -28,6 +28,7 @@ interface DeleteAccountModalProps {
|
||||
user: TUser;
|
||||
isFormbricksCloud: boolean;
|
||||
organizationsWithSingleOwner: TOrganization[];
|
||||
isSsoIdentityConfirmationDisabled: boolean;
|
||||
}
|
||||
|
||||
export const DeleteAccountModal = ({
|
||||
@@ -37,11 +38,13 @@ export const DeleteAccountModal = ({
|
||||
user,
|
||||
isFormbricksCloud,
|
||||
organizationsWithSingleOwner,
|
||||
isSsoIdentityConfirmationDisabled,
|
||||
}: Readonly<DeleteAccountModalProps>) => {
|
||||
const { t } = useTranslation();
|
||||
const [deleting, setDeleting] = useState(false);
|
||||
const [inputValue, setInputValue] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const { signOut: signOutWithAudit } = useSignOut({ id: user.id, email: user.email });
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setInputValue(e.target.value);
|
||||
};
|
||||
@@ -121,7 +124,15 @@ export const DeleteAccountModal = ({
|
||||
return;
|
||||
}
|
||||
|
||||
globalThis.localStorage.removeItem(FORMBRICKS_ENVIRONMENT_ID_LS);
|
||||
try {
|
||||
await signOutWithAudit({
|
||||
clearEnvironmentId: true,
|
||||
reason: "account_deletion",
|
||||
redirect: false,
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error({ error }, "Failed to sign out after account deletion");
|
||||
}
|
||||
|
||||
if (isFormbricksCloud) {
|
||||
globalThis.location.replace(FORMBRICKS_CLOUD_ACCOUNT_DELETION_SURVEY_URL);
|
||||
@@ -192,7 +203,7 @@ export const DeleteAccountModal = ({
|
||||
id="deleteAccountConfirmation"
|
||||
name="deleteAccountConfirmation"
|
||||
/>
|
||||
{!requiresPasswordConfirmation && (
|
||||
{!requiresPasswordConfirmation && !isSsoIdentityConfirmationDisabled && (
|
||||
<p className="mt-2 text-sm text-slate-600">
|
||||
{t("environments.settings.profile.sso_identity_confirmation_may_be_required_for_deletion")}
|
||||
</p>
|
||||
|
||||
@@ -60,13 +60,6 @@ const NEXT_AUTH_PROVIDER_BY_IDENTITY_PROVIDER = {
|
||||
saml: "saml",
|
||||
} as const satisfies Record<TSsoIdentityProvider, string>;
|
||||
|
||||
const INTERACTIVE_SSO_CONFIRMATION_PROVIDERS = new Set<TSsoIdentityProvider>([
|
||||
"azuread",
|
||||
"google",
|
||||
"openid",
|
||||
"saml",
|
||||
]);
|
||||
|
||||
const getAccountDeletionSsoReauthIntentKey = (intentId: string) =>
|
||||
createCacheKey.custom("account_deletion", "sso_reauth_intent", intentId);
|
||||
|
||||
@@ -95,7 +88,7 @@ const getAccountDeletionSsoReauthAuthorizationParams = (
|
||||
// the account after verifying the signed deletion intent, making the inbox the confirmation factor.
|
||||
if (provider === "saml") {
|
||||
return {
|
||||
...(INTERACTIVE_SSO_CONFIRMATION_PROVIDERS.has(provider) ? { forceAuthn: "true" } : {}),
|
||||
forceAuthn: "true",
|
||||
product: SAML_PRODUCT,
|
||||
provider: "saml",
|
||||
tenant: SAML_TENANT,
|
||||
@@ -111,12 +104,10 @@ const getAccountDeletionSsoReauthAuthorizationParams = (
|
||||
|
||||
return {
|
||||
login_hint: email,
|
||||
...(INTERACTIVE_SSO_CONFIRMATION_PROVIDERS.has(provider) ? { prompt: "login" } : {}),
|
||||
prompt: "login",
|
||||
};
|
||||
};
|
||||
|
||||
const getAccountDeletionSsoReauthErrorCode = () => ACCOUNT_DELETION_SSO_REAUTH_FAILED_ERROR_CODE;
|
||||
|
||||
const createAccountDeletionSsoReauthCallbackUrl = (intentToken: string) => {
|
||||
const callbackUrl = new URL(ACCOUNT_DELETION_SSO_REAUTH_CALLBACK_PATH, WEBAPP_URL);
|
||||
callbackUrl.searchParams.set("intent", intentToken);
|
||||
@@ -159,7 +150,7 @@ export const getAccountDeletionSsoReauthFailureRedirectUrl = ({
|
||||
const redirectUrl = new URL(validatedReturnToUrl);
|
||||
redirectUrl.searchParams.set(
|
||||
ACCOUNT_DELETION_SSO_REAUTH_ERROR_QUERY_PARAM,
|
||||
getAccountDeletionSsoReauthErrorCode()
|
||||
ACCOUNT_DELETION_SSO_REAUTH_FAILED_ERROR_CODE
|
||||
);
|
||||
return redirectUrl.toString();
|
||||
} catch (redirectError) {
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Button } from "@/modules/ui/components/button";
|
||||
|
||||
interface RemovedFromOrganizationProps {
|
||||
isFormbricksCloud: boolean;
|
||||
isSsoIdentityConfirmationDisabled: boolean;
|
||||
requiresPasswordConfirmation: boolean;
|
||||
user: TUser;
|
||||
}
|
||||
@@ -16,6 +17,7 @@ interface RemovedFromOrganizationProps {
|
||||
export const RemovedFromOrganization = ({
|
||||
user,
|
||||
isFormbricksCloud,
|
||||
isSsoIdentityConfirmationDisabled,
|
||||
requiresPasswordConfirmation,
|
||||
}: Readonly<RemovedFromOrganizationProps>) => {
|
||||
const { t } = useTranslation();
|
||||
@@ -35,6 +37,7 @@ export const RemovedFromOrganization = ({
|
||||
user={user}
|
||||
isFormbricksCloud={isFormbricksCloud}
|
||||
organizationsWithSingleOwner={[]}
|
||||
isSsoIdentityConfirmationDisabled={isSsoIdentityConfirmationDisabled}
|
||||
/>
|
||||
<Button
|
||||
onClick={() => {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Metadata } from "next";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { notFound } from "next/navigation";
|
||||
import { AuthenticationError } from "@formbricks/types/errors";
|
||||
import { IS_FORMBRICKS_CLOUD } from "@/lib/constants";
|
||||
import { DISABLE_ACCOUNT_DELETION_SSO_CONFIRMATION, IS_FORMBRICKS_CLOUD } from "@/lib/constants";
|
||||
import { gethasNoOrganizations } from "@/lib/instance/service";
|
||||
import { getOrganizationsByUserId } from "@/lib/organization/service";
|
||||
import { getUser } from "@/lib/user/service";
|
||||
@@ -43,6 +43,7 @@ export const CreateOrganizationPage = async () => {
|
||||
<RemovedFromOrganization
|
||||
user={user}
|
||||
isFormbricksCloud={IS_FORMBRICKS_CLOUD}
|
||||
isSsoIdentityConfirmationDisabled={DISABLE_ACCOUNT_DELETION_SSO_CONFIRMATION}
|
||||
requiresPasswordConfirmation={requiresPasswordConfirmationForAccountDeletion(user)}
|
||||
/>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user