Update and refine schemas in Stripe and Team Accounts features
Refactored both Stripe and Team Accounts features' schemas for better data validation and added specificity to keys. Enhanced form validations with methods to ensure Stripe keys follow appropriate prefixes. Replaced generic string types with UUID for accountId attributes in different services. Also turned off autocomplete for destructive actions for improved security.
This commit is contained in:
@@ -5,7 +5,7 @@ import { LineItemUsageType, PaymentType } from '../create-billing-schema';
|
||||
export const CreateBillingCheckoutSchema = z
|
||||
.object({
|
||||
returnUrl: z.string().url(),
|
||||
accountId: z.string(),
|
||||
accountId: z.string().uuid(),
|
||||
paymentType: PaymentType,
|
||||
lineItems: z.array(
|
||||
z.object({
|
||||
@@ -16,7 +16,7 @@ export const CreateBillingCheckoutSchema = z
|
||||
),
|
||||
trialDays: z.number().optional(),
|
||||
customerId: z.string().optional(),
|
||||
customerEmail: z.string().optional(),
|
||||
customerEmail: z.string().email().optional(),
|
||||
})
|
||||
.refine(
|
||||
(schema) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const LeaveTeamAccountSchema = z.object({
|
||||
accountId: z.string(),
|
||||
accountId: z.string().uuid(),
|
||||
confirmation: z.custom((value) => value === 'LEAVE'),
|
||||
});
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
type Role = string;
|
||||
|
||||
export const UpdateInvitationSchema = z.object({
|
||||
invitationId: z.number(),
|
||||
role: z.custom<Role>(() => z.string().min(1)),
|
||||
role: z.string().min(1),
|
||||
});
|
||||
|
||||
@@ -7,8 +7,8 @@ import { Logger } from '@kit/shared/logger';
|
||||
import { Database } from '@kit/supabase/database';
|
||||
|
||||
const Schema = z.object({
|
||||
accountId: z.string(),
|
||||
userId: z.string(),
|
||||
accountId: z.string().uuid(),
|
||||
userId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export class LeaveTeamAccountService {
|
||||
|
||||
@@ -3,7 +3,9 @@ import { z } from 'zod';
|
||||
export const MailerSchema = z
|
||||
.object({
|
||||
to: z.string().email(),
|
||||
from: z.string().email(),
|
||||
// this is not necessarily formatted
|
||||
// as an email so we type it loosely
|
||||
from: z.string().min(1),
|
||||
subject: z.string(),
|
||||
})
|
||||
.and(
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import { useState } from 'react';
|
||||
|
||||
import { invariant } from '@epic-web/invariant';
|
||||
import {
|
||||
EmbeddedCheckout,
|
||||
EmbeddedCheckoutProvider,
|
||||
@@ -16,11 +15,13 @@ import {
|
||||
DialogTitle,
|
||||
} from '@kit/ui/dialog';
|
||||
|
||||
const STRIPE_PUBLISHABLE_KEY = process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY;
|
||||
import { StripeClientEnvSchema } from '../schema/stripe-client-env.schema';
|
||||
|
||||
invariant(STRIPE_PUBLISHABLE_KEY, 'Stripe publishable key is required');
|
||||
const { publishableKey } = StripeClientEnvSchema.parse({
|
||||
publishableKey: process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY,
|
||||
});
|
||||
|
||||
const stripePromise = loadStripe(STRIPE_PUBLISHABLE_KEY);
|
||||
const stripePromise = loadStripe(publishableKey);
|
||||
|
||||
export function StripeCheckout({
|
||||
checkoutToken,
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const StripeClientEnvSchema = z.object({
|
||||
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: z.string().min(1),
|
||||
});
|
||||
export const StripeClientEnvSchema = z
|
||||
.object({
|
||||
publishableKey: z.string().min(1),
|
||||
})
|
||||
.refine(
|
||||
(schema) => {
|
||||
return schema.publishableKey.startsWith('pk_');
|
||||
},
|
||||
{
|
||||
path: ['publishableKey'],
|
||||
message: `Stripe publishable key must start with 'pk_'`,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,6 +1,25 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const StripeServerEnvSchema = z.object({
|
||||
STRIPE_SECRET_KEY: z.string().min(1),
|
||||
STRIPE_WEBHOOK_SECRET: z.string().min(1),
|
||||
});
|
||||
export const StripeServerEnvSchema = z
|
||||
.object({
|
||||
secretKey: z.string().min(1),
|
||||
webhooksSecret: z.string().min(1),
|
||||
})
|
||||
.refine(
|
||||
(schema) => {
|
||||
return schema.secretKey.startsWith('sk_');
|
||||
},
|
||||
{
|
||||
path: ['STRIPE_SECRET_KEY'],
|
||||
message: `Stripe secret key must start with 'sk_'`,
|
||||
},
|
||||
)
|
||||
.refine(
|
||||
(schema) => {
|
||||
return schema.webhooksSecret.startsWith('whsec_');
|
||||
},
|
||||
{
|
||||
path: ['STRIPE_WEBHOOK_SECRET'],
|
||||
message: `Stripe webhook secret must start with 'whsec_'`,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -16,7 +16,7 @@ export async function createStripeClient() {
|
||||
STRIPE_WEBHOOK_SECRET: process.env.STRIPE_WEBHOOK_SECRET,
|
||||
});
|
||||
|
||||
return new Stripe(stripeServerEnv.STRIPE_SECRET_KEY, {
|
||||
return new Stripe(stripeServerEnv.secretKey, {
|
||||
apiVersion: STRIPE_API_VERSION,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -32,9 +32,9 @@ export class StripeWebhookHandlerService
|
||||
const signatureKey = `stripe-signature`;
|
||||
const signature = request.headers.get(signatureKey)!;
|
||||
|
||||
const { STRIPE_WEBHOOK_SECRET } = StripeServerEnvSchema.parse({
|
||||
STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
|
||||
STRIPE_WEBHOOK_SECRET: process.env.STRIPE_WEBHOOK_SECRET,
|
||||
const { webhooksSecret } = StripeServerEnvSchema.parse({
|
||||
secretKey: process.env.STRIPE_SECRET_KEY,
|
||||
webhooksSecret: process.env.STRIPE_WEBHOOK_SECRET,
|
||||
});
|
||||
|
||||
const stripe = await this.loadStripe();
|
||||
@@ -42,7 +42,7 @@ export class StripeWebhookHandlerService
|
||||
const event = stripe.webhooks.constructEvent(
|
||||
body,
|
||||
signature,
|
||||
STRIPE_WEBHOOK_SECRET,
|
||||
webhooksSecret,
|
||||
);
|
||||
|
||||
if (!event) {
|
||||
|
||||
Reference in New Issue
Block a user