diff --git a/src/components/voucher/forms/update-voucher-form.tsx b/src/components/voucher/forms/update-voucher-form.tsx index 4fb6479..84511e4 100644 --- a/src/components/voucher/forms/update-voucher-form.tsx +++ b/src/components/voucher/forms/update-voucher-form.tsx @@ -13,6 +13,7 @@ import { Loading } from "~/components/loading"; import { Alert } from "~/components/ui/alert"; import { Button } from "~/components/ui/button"; import { useAuth } from "~/hooks/useAuth"; +import { useIsOwner } from "~/hooks/useIsOwner"; import { type RouterOutput } from "~/server/api/root"; import { type UpdateVoucherInput } from "~/server/api/routers/voucher"; import { api } from "~/utils/api"; @@ -43,8 +44,14 @@ const UpdateVoucherForm = ({ onSuccess, voucher }: UpdateFormProps) => { const auth = useAuth(); const router = useRouter(); const utils = api.useContext(); - const { mutateAsync, isPending } = api.voucher.update.useMutation(); - const deleteMutation = api.voucher.remove.useMutation(); + const update = api.voucher.update.useMutation(); + const remove = api.voucher.remove.useMutation(); + + const isPending = update.isPending || remove.isPending; + + const isOwner = useIsOwner(voucher?.voucher_address as string); + const canUpdate = isOwner || auth?.isStaff; + const canDelete = isOwner || auth?.isAdmin; const form = useForm>({ resolver: zodResolver(formSchema), @@ -60,12 +67,12 @@ const UpdateVoucherForm = ({ onSuccess, voucher }: UpdateFormProps) => { }, }); - const handleMutate = async ( + const handleUpdate = async ( formData: Omit ) => { try { if (!voucher?.voucher_address) return; - await mutateAsync({ + await update.mutateAsync({ voucherAddress: voucher.voucher_address as `0x${string}`, ...formData, }); @@ -77,6 +84,29 @@ const UpdateVoucherForm = ({ onSuccess, voucher }: UpdateFormProps) => { toast.error("Error updating voucher"); } }; + const handleRemove = async () => { + const id = "remove-voucher"; + try { + if (!voucher?.voucher_address) return; + toast.loading("Removing voucher", { id, duration: 15000 }); + await remove.mutateAsync({ + voucherAddress: voucher.voucher_address as `0x${string}`, + }); + toast.success("Voucher removed successfully", { + id, + duration: undefined, + }); + void router.push("/vouchers"); + await utils.voucher.invalidate(); + onSuccess?.(); + } catch (error) { + console.error(error); + toast.error(`Error: ${(error as Error).message ?? "Removing voucher"}`, { + id, + duration: 4000, + }); + } + }; if (!isConnected || !address) { return ( @@ -86,7 +116,7 @@ const UpdateVoucherForm = ({ onSuccess, voucher }: UpdateFormProps) => { ); } - if (!auth || !auth.isStaff) { + if (!canUpdate) { return ( You are not Authorized to Update this Voucher @@ -97,7 +127,7 @@ const UpdateVoucherForm = ({ onSuccess, voucher }: UpdateFormProps) => { return (
@@ -159,16 +189,11 @@ const UpdateVoucherForm = ({ onSuccess, voucher }: UpdateFormProps) => { > {isPending ? : "Save Changes"} - {auth.isAdmin && voucher && ( + {canDelete && voucher && ( - deleteMutation.mutate( - { voucherAddress: voucher.voucher_address }, - { onSuccess: () => void router.push("/vouchers") } - ) - } + onYes={handleRemove} /> )}
diff --git a/src/server/api/routers/voucher.ts b/src/server/api/routers/voucher.ts index d85f659..41b5bbd 100644 --- a/src/server/api/routers/voucher.ts +++ b/src/server/api/routers/voucher.ts @@ -5,7 +5,6 @@ import { schemas } from "~/components/voucher/forms/create-voucher-form/schemas" import { VoucherIndex } from "~/contracts"; import { isOwner } from "~/contracts/helpers"; import { - adminProcedure, authenticatedProcedure, createTRPCRouter, publicProcedure, @@ -46,13 +45,21 @@ export const voucherRouter = createTRPCRouter({ list: publicProcedure.query(({ ctx }) => { return ctx.graphDB.selectFrom("vouchers").selectAll().execute(); }), - remove: adminProcedure + remove: authenticatedProcedure .input( z.object({ voucherAddress: z.string().refine(isAddress), }) ) .mutation(async ({ ctx, input }) => { + const isContractOwner = await isOwner( + ctx.user.account.blockchain_address, + input.voucherAddress + ); + const canDelete = isAdmin(ctx.user) || isContractOwner; + if (!canDelete) { + throw new Error("You are not allowed to remove this voucher"); + } const transactionResult = await ctx.graphDB .transaction() .execute(async (trx) => {