mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-30 10:19:51 -06:00
fix: add authorization to actions for Profile (#908)
* feat: authzn and limit sensitive info from profile actions * fix: work on suggested changes
This commit is contained in:
committed by
GitHub
parent
bcaf2337c4
commit
a9c8e99cd4
@@ -3,14 +3,13 @@
|
||||
import DeleteDialog from "@/components/shared/DeleteDialog";
|
||||
import AvatarPlaceholder from "@/images/avatar-placeholder.png";
|
||||
import { formbricksLogout } from "@/lib/formbricks";
|
||||
import { TProfile } from "@formbricks/types/v1/profile";
|
||||
import { Button, Input, ProfileAvatar } from "@formbricks/ui";
|
||||
import { Session } from "next-auth";
|
||||
import { signOut } from "next-auth/react";
|
||||
import Image from "next/image";
|
||||
import { Dispatch, SetStateAction, useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { profileDeleteAction } from "./actions";
|
||||
import { deleteProfileAction } from "./actions";
|
||||
|
||||
export function EditAvatar({ session }) {
|
||||
return (
|
||||
@@ -38,10 +37,9 @@ interface DeleteAccountModalProps {
|
||||
open: boolean;
|
||||
setOpen: Dispatch<SetStateAction<boolean>>;
|
||||
session: Session;
|
||||
profile: TProfile;
|
||||
}
|
||||
|
||||
function DeleteAccountModal({ setOpen, open, session, profile }: DeleteAccountModalProps) {
|
||||
function DeleteAccountModal({ setOpen, open, session }: DeleteAccountModalProps) {
|
||||
const [deleting, setDeleting] = useState(false);
|
||||
const [inputValue, setInputValue] = useState("");
|
||||
|
||||
@@ -52,7 +50,7 @@ function DeleteAccountModal({ setOpen, open, session, profile }: DeleteAccountMo
|
||||
const deleteAccount = async () => {
|
||||
try {
|
||||
setDeleting(true);
|
||||
await profileDeleteAction(profile.id);
|
||||
await deleteProfileAction();
|
||||
await signOut();
|
||||
await formbricksLogout();
|
||||
} catch (error) {
|
||||
@@ -105,7 +103,7 @@ function DeleteAccountModal({ setOpen, open, session, profile }: DeleteAccountMo
|
||||
);
|
||||
}
|
||||
|
||||
export function DeleteAccount({ session, profile }: { session: Session | null; profile: TProfile }) {
|
||||
export function DeleteAccount({ session }: { session: Session | null }) {
|
||||
const [isModalOpen, setModalOpen] = useState(false);
|
||||
|
||||
if (!session) {
|
||||
@@ -114,7 +112,7 @@ export function DeleteAccount({ session, profile }: { session: Session | null; p
|
||||
|
||||
return (
|
||||
<div>
|
||||
<DeleteAccountModal open={isModalOpen} setOpen={setModalOpen} session={session} profile={profile} />
|
||||
<DeleteAccountModal open={isModalOpen} setOpen={setModalOpen} session={session} />
|
||||
<p className="text-sm text-slate-700">
|
||||
Delete your account with all personal data. <strong>This cannot be undone!</strong>
|
||||
</p>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { Button, Input, Label } from "@formbricks/ui";
|
||||
import { useForm } from "react-hook-form";
|
||||
import toast from "react-hot-toast";
|
||||
import { profileEditAction } from "./actions";
|
||||
import { updateProfileAction } from "./actions";
|
||||
import { TProfile } from "@formbricks/types/v1/profile";
|
||||
|
||||
export function EditName({ profile }: { profile: TProfile }) {
|
||||
@@ -19,7 +19,7 @@ export function EditName({ profile }: { profile: TProfile }) {
|
||||
className="w-full max-w-sm items-center"
|
||||
onSubmit={handleSubmit(async (data) => {
|
||||
try {
|
||||
await profileEditAction(profile.id, data);
|
||||
await updateProfileAction(data);
|
||||
toast.success("Your name was updated successfully.");
|
||||
} catch (error) {
|
||||
toast.error(`Error: ${error.message}`);
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
"use server";
|
||||
|
||||
import { authOptions } from "@/app/api/auth/[...nextauth]/authOptions";
|
||||
import { updateProfile, deleteProfile } from "@formbricks/lib/services/profile";
|
||||
import { TProfileUpdateInput } from "@formbricks/types/v1/profile";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { AuthorizationError } from "@formbricks/types/v1/errors";
|
||||
|
||||
export async function profileEditAction(userId: string, data: Partial<TProfileUpdateInput>) {
|
||||
return await updateProfile(userId, data);
|
||||
export async function updateProfileAction(data: Partial<TProfileUpdateInput>) {
|
||||
const session = await getServerSession(authOptions);
|
||||
if (!session) throw new AuthorizationError("Not authorized");
|
||||
|
||||
return await updateProfile(session.user.id, data);
|
||||
}
|
||||
|
||||
export async function profileDeleteAction(userId: string) {
|
||||
return await deleteProfile(userId);
|
||||
export async function deleteProfileAction() {
|
||||
const session = await getServerSession(authOptions);
|
||||
if (!session) throw new AuthorizationError("Not authorized");
|
||||
|
||||
return await deleteProfile(session.user.id);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ export default async function ProfileSettingsPage() {
|
||||
<SettingsCard
|
||||
title="Delete account"
|
||||
description="Delete your account with all of your personal information and data.">
|
||||
<DeleteAccount session={session} profile={profile} />
|
||||
<DeleteAccount session={session} />
|
||||
</SettingsCard>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
"use server";
|
||||
|
||||
import { authOptions } from "@/app/api/auth/[...nextauth]/authOptions";
|
||||
import { updateProduct } from "@formbricks/lib/services/product";
|
||||
import { updateProfile } from "@formbricks/lib/services/profile";
|
||||
import { TProductUpdateInput } from "@formbricks/types/v1/product";
|
||||
import { TProfileUpdateInput } from "@formbricks/types/v1/profile";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { AuthorizationError } from "@formbricks/types/v1/errors";
|
||||
|
||||
export async function updateProfileAction(personId: string, updatedProfile: Partial<TProfileUpdateInput>) {
|
||||
return await updateProfile(personId, updatedProfile);
|
||||
export async function updateProfileAction(updatedProfile: Partial<TProfileUpdateInput>) {
|
||||
const session = await getServerSession(authOptions);
|
||||
if (!session) throw new AuthorizationError("Not authorized");
|
||||
|
||||
return await updateProfile(session.user.id, updatedProfile);
|
||||
}
|
||||
|
||||
export async function updateProductAction(productId: string, updatedProduct: Partial<TProductUpdateInput>) {
|
||||
|
||||
@@ -42,7 +42,7 @@ const Objective: React.FC<ObjectiveProps> = ({ next, skip, formbricksResponseId,
|
||||
try {
|
||||
setIsProfileUpdating(true);
|
||||
const updatedProfile = { ...profile, objective: selectedObjective.id };
|
||||
await updateProfileAction(profile.id, updatedProfile);
|
||||
await updateProfileAction(updatedProfile);
|
||||
setIsProfileUpdating(false);
|
||||
} catch (e) {
|
||||
setIsProfileUpdating(false);
|
||||
|
||||
@@ -54,7 +54,7 @@ export default function Onboarding({ session, environmentId, profile, product }:
|
||||
|
||||
try {
|
||||
const updatedProfile = { ...profile, onboardingCompleted: true };
|
||||
await updateProfileAction(profile.id, updatedProfile);
|
||||
await updateProfileAction(updatedProfile);
|
||||
|
||||
if (environmentId) {
|
||||
router.push(`/environments/${environmentId}/surveys`);
|
||||
|
||||
@@ -40,7 +40,7 @@ const Role: React.FC<RoleProps> = ({ next, skip, setFormbricksResponseId, profil
|
||||
try {
|
||||
setIsUpdating(true);
|
||||
const updatedProfile = { ...profile, role: selectedRole.id };
|
||||
await updateProfileAction(profile.id, updatedProfile);
|
||||
await updateProfileAction(updatedProfile);
|
||||
setIsUpdating(false);
|
||||
} catch (e) {
|
||||
setIsUpdating(false);
|
||||
|
||||
@@ -116,6 +116,7 @@ export const updateProfile = async (
|
||||
id: personId,
|
||||
},
|
||||
data: data,
|
||||
select: responseSelection,
|
||||
});
|
||||
|
||||
revalidateTag(getProfileByEmailCacheTag(updatedProfile.email));
|
||||
@@ -137,6 +138,7 @@ const deleteUser = async (userId: string): Promise<TProfile> => {
|
||||
where: {
|
||||
id: userId,
|
||||
},
|
||||
select: responseSelection,
|
||||
});
|
||||
revalidateTag(getProfileByEmailCacheTag(profile.email));
|
||||
revalidateTag(getProfileCacheTag(userId));
|
||||
|
||||
Reference in New Issue
Block a user