add validation for update organization

This commit is contained in:
Carl-Gerhard Lindesvärd
2023-10-28 23:24:22 +02:00
parent aa5c881ec6
commit 48becb23dc
4 changed files with 43 additions and 9 deletions

View File

@@ -8,30 +8,42 @@ import { SettingsLayout } from "@/components/layouts/SettingsLayout";
import { toast } from "@/components/ui/use-toast"; import { toast } from "@/components/ui/use-toast";
import { createServerSideProps } from "@/server/getServerSideProps"; import { createServerSideProps } from "@/server/getServerSideProps";
import { useOrganizationParams } from "@/hooks/useOrganizationParams"; import { useOrganizationParams } from "@/hooks/useOrganizationParams";
import { z } from "zod";
import { InputError } from "@/components/forms/InputError";
import { useRouter } from "next/router";
export const getServerSideProps = createServerSideProps(); export const getServerSideProps = createServerSideProps();
const validator = z.object({
id: z.string().min(2),
name: z.string().min(2),
});
type IForm = z.infer<typeof validator>;
export default function Organization() { export default function Organization() {
const router = useRouter()
const params = useOrganizationParams(); const params = useOrganizationParams();
const query = api.organization.get.useQuery({ const query = api.organization.get.useQuery({
slug: params.organization, slug: params.organization,
}); });
const mutation = api.organization.update.useMutation({ const mutation = api.organization.update.useMutation({
onSuccess() { onSuccess(res) {
toast({ toast({
title: "Organization updated", title: "Organization updated",
description: "Your organization has been updated.", description: "Your organization has been updated.",
}); });
query.refetch(); query.refetch();
router.replace(`/${res.slug}/settings/organization`)
}, },
onError: handleError, onError: handleError,
}); });
const data = query.data; const data = query.data;
const { register, handleSubmit, reset, formState, getValues } = useForm({ const { register, handleSubmit, reset, formState } = useForm<IForm>({
defaultValues: { defaultValues: {
id: "",
name: "", name: "",
slug: "",
}, },
}); });
@@ -45,7 +57,9 @@ export default function Organization() {
return ( return (
<SettingsLayout> <SettingsLayout>
<form <form
onSubmit={handleSubmit((values) => mutation.mutate(values))} onSubmit={handleSubmit((values) => {
mutation.mutate(values)
})}
className="flex flex-col divide-y divide-border" className="flex flex-col divide-y divide-border"
> >
<ContentHeader <ContentHeader
@@ -54,7 +68,7 @@ export default function Organization() {
> >
<Button type="submit" disabled={!formState.isDirty}>Save</Button> <Button type="submit" disabled={!formState.isDirty}>Save</Button>
</ContentHeader> </ContentHeader>
<ContentSection title="Name" text="The name of your organization."> <ContentSection title="Name" text={["Notice. Changing name will result in a url change as well.", <InputError key="error" {...formState.errors.name} />]}>
<Input {...register("name")} /> <Input {...register("name")} />
</ContentSection> </ContentSection>
<ContentSection <ContentSection

View File

@@ -35,7 +35,7 @@ export default function Profile() {
}); });
const data = query.data; const data = query.data;
const { register, handleSubmit, reset, formState } = useForm({ const { register, handleSubmit, reset, formState } = useForm<IForm>({
resolver: zodResolver(validator), resolver: zodResolver(validator),
defaultValues: { defaultValues: {
name: "", name: "",

View File

@@ -3,6 +3,7 @@ import { z } from "zod";
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc"; import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
import { db } from "@/server/db"; import { db } from "@/server/db";
import { getOrganizationBySlug } from "@/server/services/organization.service"; import { getOrganizationBySlug } from "@/server/services/organization.service";
import { slug } from "@/utils/slug";
export const organizationRouter = createTRPCRouter({ export const organizationRouter = createTRPCRouter({
first: protectedProcedure.query(({ ctx }) => { first: protectedProcedure.query(({ ctx }) => {
@@ -28,17 +29,18 @@ export const organizationRouter = createTRPCRouter({
update: protectedProcedure update: protectedProcedure
.input( .input(
z.object({ z.object({
id: z.string(),
name: z.string(), name: z.string(),
slug: z.string(),
}), }),
) )
.mutation(({ input }) => { .mutation(({ input }) => {
return db.organization.update({ return db.organization.update({
where: { where: {
slug: input.slug, id: input.id,
}, },
data: { data: {
name: input.name, name: input.name,
slug: slug(input.name)
}, },
}); });
}), }),

View File

@@ -3,6 +3,7 @@ import {
type GetServerSidePropsResult, type GetServerSidePropsResult,
} from "next"; } from "next";
import { getServerAuthSession } from "./auth"; import { getServerAuthSession } from "./auth";
import { db } from "./db";
export function createServerSideProps( export function createServerSideProps(
cb?: (context: GetServerSidePropsContext) => Promise<any>, cb?: (context: GetServerSidePropsContext) => Promise<any>,
@@ -21,6 +22,23 @@ export function createServerSideProps(
} }
} }
if(context.params?.organization) {
const organization = await db.user.findFirst({
where: {
id: session.user.id,
organization: {
slug: context.params.organization as string
}
}
})
if(!organization) {
return {
notFound: true,
}
}
}
const res = await (typeof cb === "function" const res = await (typeof cb === "function"
? cb(context) ? cb(context)
: Promise.resolve({})); : Promise.resolve({}));