mirror of
https://github.com/marcogll/TaxHacker_s23.git
synced 2026-01-13 21:35:19 +00:00
feat: storage and token limiting
This commit is contained in:
@@ -1,6 +1,12 @@
|
||||
import { stripeClient } from "@better-auth/stripe/client"
|
||||
import { createAuthClient } from "better-auth/client"
|
||||
import { emailOTPClient } from "better-auth/client/plugins"
|
||||
|
||||
export const authClient = createAuthClient({
|
||||
plugins: [emailOTPClient()],
|
||||
plugins: [
|
||||
emailOTPClient(),
|
||||
stripeClient({
|
||||
subscription: true,
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
10
lib/auth.ts
10
lib/auth.ts
@@ -1,6 +1,7 @@
|
||||
import config from "@/lib/config"
|
||||
import { createUserDefaults } from "@/models/defaults"
|
||||
import { getSelfHostedUser, getUserByEmail } from "@/models/users"
|
||||
import { stripe } from "@better-auth/stripe"
|
||||
import { User } from "@prisma/client"
|
||||
import { betterAuth } from "better-auth"
|
||||
import { prismaAdapter } from "better-auth/adapters/prisma"
|
||||
@@ -11,6 +12,7 @@ import { headers } from "next/headers"
|
||||
import { redirect } from "next/navigation"
|
||||
import { prisma } from "./db"
|
||||
import { resend, sendOTPCodeEmail } from "./email"
|
||||
import { isStripeEnabled, stripeClient } from "./stripe"
|
||||
|
||||
export type UserProfile = {
|
||||
id: string
|
||||
@@ -18,6 +20,7 @@ export type UserProfile = {
|
||||
email: string
|
||||
avatar?: string
|
||||
storageUsed?: number
|
||||
tokenBalance?: number
|
||||
}
|
||||
|
||||
export const auth = betterAuth({
|
||||
@@ -65,6 +68,13 @@ export const auth = betterAuth({
|
||||
await sendOTPCodeEmail({ email, otp })
|
||||
},
|
||||
}),
|
||||
isStripeEnabled(stripeClient)
|
||||
? stripe({
|
||||
stripeClient: stripeClient!,
|
||||
stripeWebhookSecret: config.stripe.webhookSecret,
|
||||
createCustomerOnSignUp: true,
|
||||
})
|
||||
: { id: "stripe", endpoints: {} },
|
||||
nextCookies(), // make sure this is the last plugin in the array
|
||||
],
|
||||
})
|
||||
|
||||
@@ -13,6 +13,8 @@ const envSchema = z.object({
|
||||
RESEND_API_KEY: z.string().default("please-set-your-resend-api-key-here"),
|
||||
RESEND_FROM_EMAIL: z.string().default("TaxHacker <user@localhost>"),
|
||||
RESEND_AUDIENCE_ID: z.string().default(""),
|
||||
STRIPE_SECRET_KEY: z.string().default(""),
|
||||
STRIPE_WEBHOOK_SECRET: z.string().default(""),
|
||||
})
|
||||
|
||||
const env = envSchema.parse(process.env)
|
||||
@@ -40,6 +42,10 @@ const config = {
|
||||
loginUrl: "/enter",
|
||||
disableSignup: env.DISABLE_SIGNUP === "true" || env.SELF_HOSTED_MODE === "true",
|
||||
},
|
||||
stripe: {
|
||||
secretKey: env.STRIPE_SECRET_KEY,
|
||||
webhookSecret: env.STRIPE_WEBHOOK_SECRET,
|
||||
},
|
||||
email: {
|
||||
apiKey: env.RESEND_API_KEY,
|
||||
from: env.RESEND_FROM_EMAIL,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { File, Transaction, User } from "@prisma/client"
|
||||
import { access, constants, readdir, stat } from "fs/promises"
|
||||
import path from "path"
|
||||
import config from "./config"
|
||||
|
||||
export const FILE_UPLOAD_PATH = path.resolve(process.env.UPLOAD_PATH || "./uploads")
|
||||
export const FILE_UNSORTED_DIRECTORY_NAME = "unsorted"
|
||||
@@ -70,3 +71,10 @@ export async function getDirectorySize(directoryPath: string) {
|
||||
await calculateSize(directoryPath)
|
||||
return totalSize
|
||||
}
|
||||
|
||||
export function isEnoughStorageToUploadFile(user: User, fileSize: number) {
|
||||
if (config.selfHosted.isEnabled || user.storageLimit < 0) {
|
||||
return true
|
||||
}
|
||||
return user.storageUsed + fileSize <= user.storageLimit
|
||||
}
|
||||
|
||||
13
lib/stripe.ts
Normal file
13
lib/stripe.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import Stripe from "stripe"
|
||||
import config from "./config"
|
||||
|
||||
export const stripeClient: Stripe | null = config.stripe.secretKey
|
||||
? new Stripe(config.stripe.secretKey, {
|
||||
apiVersion: "2025-03-31.basil",
|
||||
})
|
||||
: null
|
||||
|
||||
// Type guard to check if Stripe is initialized
|
||||
export const isStripeEnabled = (client: Stripe | null): client is Stripe => {
|
||||
return client !== null
|
||||
}
|
||||
10
lib/utils.ts
10
lib/utils.ts
@@ -2,12 +2,14 @@ import { clsx, type ClassValue } from "clsx"
|
||||
import slugify from "slugify"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
const LOCALE = "en-US"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
|
||||
export function formatCurrency(total: number, currency: string) {
|
||||
return new Intl.NumberFormat("en-US", {
|
||||
return new Intl.NumberFormat(LOCALE, {
|
||||
style: "currency",
|
||||
currency: currency,
|
||||
minimumFractionDigits: 2,
|
||||
@@ -28,6 +30,12 @@ export function formatBytes(bytes: number) {
|
||||
return `${parseFloat(value.toFixed(2))} ${sizes[i]}`
|
||||
}
|
||||
|
||||
export function formatNumber(number: number) {
|
||||
return new Intl.NumberFormat(LOCALE, {
|
||||
useGrouping: true,
|
||||
}).format(number)
|
||||
}
|
||||
|
||||
export function codeFromName(name: string, maxLength: number = 16) {
|
||||
const code = slugify(name, {
|
||||
replacement: "_",
|
||||
|
||||
Reference in New Issue
Block a user