Refactor schemas, enhance data validation

Implemented improvements in the data validation methods used in Stripe and Team Account features by refining the schemas. Adapted string types to UUID for accountId attributes in various services and ensured that Stripe keys follow appropriate prefixes. Autocomplete was turned off for destructive actions for enhanced security.
This commit is contained in:
giancarlo
2024-03-29 18:21:12 +08:00
parent 59c08c59d7
commit 65e970424f
13 changed files with 44 additions and 25 deletions

View File

@@ -25,7 +25,7 @@ import {
import { If } from '@kit/ui/if';
import { Trans } from '@kit/ui/trans';
import { UpdateMemberRoleSchema } from '../../schema/update-member-role-schema';
import { UpdateMemberRoleSchema } from '../../schema/update-member-role.schema';
import { updateInvitationAction } from '../../server/actions/team-invitations-server-actions';
import { MembershipRoleSelector } from '../members/membership-role-selector';
import { RolesDataProvider } from '../members/roles-data-provider';

View File

@@ -25,7 +25,7 @@ import {
import { If } from '@kit/ui/if';
import { Trans } from '@kit/ui/trans';
import { RoleSchema } from '../../schema/update-member-role-schema';
import { RoleSchema } from '../../schema/update-member-role.schema';
import { updateMemberRoleAction } from '../../server/actions/team-members-server-actions';
import { MembershipRoleSelector } from './membership-role-selector';
import { RolesDataProvider } from './roles-data-provider';

View File

@@ -4,7 +4,6 @@ import { useTransition } from 'react';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { Button } from '@kit/ui/button';
import {
@@ -17,12 +16,9 @@ import {
import { Input } from '@kit/ui/input';
import { Trans } from '@kit/ui/trans';
import { TeamNameFormSchema } from '../../schema/update-team-name.schema';
import { updateTeamAccountName } from '../../server/actions/team-details-server-actions';
const Schema = z.object({
name: z.string().min(1).max(255),
});
export const UpdateTeamAccountNameForm = (props: {
account: {
name: string;
@@ -34,7 +30,7 @@ export const UpdateTeamAccountNameForm = (props: {
const [pending, startTransition] = useTransition();
const form = useForm({
resolver: zodResolver(Schema),
resolver: zodResolver(TeamNameFormSchema),
defaultValues: {
name: props.account.name,
},

View File

@@ -0,0 +1,5 @@
import { z } from 'zod';
export const RenewInvitationSchema = z.object({
invitationId: z.number().positive(),
});

View File

@@ -0,0 +1,12 @@
import { z } from 'zod';
export const TeamNameFormSchema = z.object({
name: z.string().min(1).max(255),
});
export const UpdateTeamNameSchema = TeamNameFormSchema.merge(
z.object({
slug: z.string().min(1).max(255),
path: z.string().min(1).max(255),
}),
);

View File

@@ -12,8 +12,8 @@ import { LeaveTeamAccountService } from '../services/leave-team-account.service'
export async function leaveTeamAccountAction(formData: FormData) {
const body = Object.fromEntries(formData.entries());
const params = LeaveTeamAccountSchema.parse(body);
const client = getSupabaseServerActionClient();
const client = getSupabaseServerActionClient();
const auth = await requireUser(client);
if (auth.error) {

View File

@@ -2,23 +2,26 @@
import { redirect } from 'next/navigation';
import { z } from 'zod';
import { getSupabaseServerComponentClient } from '@kit/supabase/server-component-client';
export async function updateTeamAccountName(params: {
name: string;
slug: string;
path: string;
}) {
import { UpdateTeamNameSchema } from '../../schema/update-team-name.schema';
export async function updateTeamAccountName(
params: z.infer<typeof UpdateTeamNameSchema>,
) {
const client = getSupabaseServerComponentClient();
const { name, slug, path } = UpdateTeamNameSchema.parse(params);
const { error, data } = await client
.from('accounts')
.update({
name: params.name,
slug: params.slug,
name,
slug,
})
.match({
slug: params.slug,
slug,
})
.select('slug')
.single();
@@ -30,9 +33,9 @@ export async function updateTeamAccountName(params: {
const newSlug = data.slug;
if (newSlug) {
const path = params.path.replace('[account]', newSlug);
const nextPath = path.replace('[account]', newSlug);
redirect(path);
redirect(nextPath);
}
return { success: true };

View File

@@ -14,7 +14,8 @@ import { getSupabaseServerActionClient } from '@kit/supabase/server-actions-clie
import { AcceptInvitationSchema } from '../../schema/accept-invitation.schema';
import { DeleteInvitationSchema } from '../../schema/delete-invitation.schema';
import { InviteMembersSchema } from '../../schema/invite-members.schema';
import { UpdateInvitationSchema } from '../../schema/update-invitation-schema';
import { RenewInvitationSchema } from '../../schema/renew-invitation.schema';
import { UpdateInvitationSchema } from '../../schema/update-invitation.schema';
import { AccountInvitationsService } from '../services/account-invitations.service';
/**
@@ -107,9 +108,11 @@ export async function acceptInvitationAction(data: FormData) {
return redirect(nextPath);
}
export async function renewInvitationAction(params: { invitationId: number }) {
export async function renewInvitationAction(
params: z.infer<typeof RenewInvitationSchema>,
) {
const client = getSupabaseServerActionClient();
const { invitationId } = params;
const { invitationId } = RenewInvitationSchema.parse(params);
await assertSession(client);

View File

@@ -11,7 +11,7 @@ import { getSupabaseServerActionClient } from '@kit/supabase/server-actions-clie
import { RemoveMemberSchema } from '../../schema/remove-member.schema';
import { TransferOwnershipConfirmationSchema } from '../../schema/transfer-ownership-confirmation.schema';
import { UpdateMemberRoleSchema } from '../../schema/update-member-role-schema';
import { UpdateMemberRoleSchema } from '../../schema/update-member-role.schema';
import { AccountMembersService } from '../services/account-members.service';
export async function removeMemberFromAccountAction(

View File

@@ -11,7 +11,7 @@ import { requireUser } from '@kit/supabase/require-user';
import { DeleteInvitationSchema } from '../../schema/delete-invitation.schema';
import { InviteMembersSchema } from '../../schema/invite-members.schema';
import { UpdateInvitationSchema } from '../../schema/update-invitation-schema';
import { UpdateInvitationSchema } from '../../schema/update-invitation.schema';
const invitePath = process.env.INVITATION_PAGE_PATH;
const siteURL = process.env.NEXT_PUBLIC_SITE_URL;

View File

@@ -8,7 +8,7 @@ import { Database } from '@kit/supabase/database';
import { RemoveMemberSchema } from '../../schema/remove-member.schema';
import { TransferOwnershipConfirmationSchema } from '../../schema/transfer-ownership-confirmation.schema';
import { UpdateMemberRoleSchema } from '../../schema/update-member-role-schema';
import { UpdateMemberRoleSchema } from '../../schema/update-member-role.schema';
export class AccountMembersService {
private readonly namespace = 'account-members';