bug fixes

This commit is contained in:
daniel31x13 2024-10-30 16:47:40 -04:00
parent fa1f9873d5
commit 508844dd9d
9 changed files with 82 additions and 30 deletions

View File

@ -6,6 +6,8 @@ import { signOut } from "next-auth/react";
import { useTranslation } from "next-i18next"; import { useTranslation } from "next-i18next";
import { useUser } from "@/hooks/store/user"; import { useUser } from "@/hooks/store/user";
const stripeEnabled = process.env.NEXT_PUBLIC_STRIPE === "true";
export default function ProfileDropdown() { export default function ProfileDropdown() {
const { t } = useTranslation(); const { t } = useTranslation();
const { settings, updateSettings } = useLocalSettingsStore(); const { settings, updateSettings } = useLocalSettingsStore();
@ -73,7 +75,7 @@ export default function ProfileDropdown() {
</Link> </Link>
</li> </li>
)} )}
{!user.parentSubscriptionId && ( {!user.parentSubscriptionId && stripeEnabled && (
<li> <li>
<Link <Link
href="/settings/billing" href="/settings/billing"

View File

@ -2,11 +2,14 @@ import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useTranslation } from "next-i18next"; import { useTranslation } from "next-i18next";
import { useUser } from "@/hooks/store/user";
export default function SettingsSidebar({ className }: { className?: string }) { export default function SettingsSidebar({ className }: { className?: string }) {
const { t } = useTranslation(); const { t } = useTranslation();
const LINKWARDEN_VERSION = process.env.version; const LINKWARDEN_VERSION = process.env.version;
const { data: user } = useUser();
const router = useRouter(); const router = useRouter();
const [active, setActive] = useState(""); const [active, setActive] = useState("");
@ -73,7 +76,7 @@ export default function SettingsSidebar({ className }: { className?: string }) {
</div> </div>
</Link> </Link>
{process.env.NEXT_PUBLIC_STRIPE && ( {process.env.NEXT_PUBLIC_STRIPE && !user.parentSubscriptionId && (
<Link href="/settings/billing"> <Link href="/settings/billing">
<div <div
className={`${ className={`${

View File

@ -15,7 +15,16 @@ export default async function deleteUserById(
const user = await prisma.user.findUnique({ const user = await prisma.user.findUnique({
where: { id: userId }, where: { id: userId },
include: { include: {
subscriptions: true, subscriptions: {
include: {
user: true,
},
},
parentSubscription: {
include: {
user: true,
},
},
}, },
}); });
@ -178,24 +187,36 @@ export default async function deleteUserById(
}); });
try { try {
const listByEmail = await stripe.customers.list({ if (user.subscriptions?.id) {
email: user.email?.toLowerCase(), const listByEmail = await stripe.customers.list({
expand: ["data.subscriptions"], email: user.email?.toLowerCase(),
}); expand: ["data.subscriptions"],
});
if (listByEmail.data[0].subscriptions?.data[0].id) { if (listByEmail.data[0].subscriptions?.data[0].id) {
const deleted = await stripe.subscriptions.cancel( const deleted = await stripe.subscriptions.cancel(
listByEmail.data[0].subscriptions?.data[0].id, listByEmail.data[0].subscriptions?.data[0].id,
{ {
cancellation_details: { cancellation_details: {
comment: body.cancellation_details?.comment, comment: body.cancellation_details?.comment,
feedback: body.cancellation_details?.feedback, feedback: body.cancellation_details?.feedback,
}, },
} }
);
return {
response: deleted,
status: 200,
};
}
} else if (user.parentSubscription?.id) {
await updateSeats(
user.parentSubscription.stripeSubscriptionId,
user.parentSubscription.quantity - 1
); );
return { return {
response: deleted, response: "User account and all related data deleted successfully.",
status: 200, status: 200,
}; };
} }

View File

@ -8,7 +8,15 @@ export const hasPassedLimit = async (
numberOfImports: number numberOfImports: number
) => { ) => {
if (!stripeEnabled) { if (!stripeEnabled) {
return false; const totalLinks = await prisma.link.count({
where: {
createdBy: {
id: userId,
},
},
});
return MAX_LINKS_PER_USER - (numberOfImports + totalLinks) < 0;
} }
const user = await prisma.user.findUnique({ const user = await prisma.user.findUnique({

View File

@ -28,12 +28,13 @@ export default function Billing() {
const router = useRouter(); const router = useRouter();
const { t } = useTranslation(); const { t } = useTranslation();
useEffect(() => {
if (!process.env.NEXT_PUBLIC_STRIPE) router.push("/settings/profile");
}, []);
const { data: users = [] } = useUsers();
const { data: account } = useUser(); const { data: account } = useUser();
const { data: users = [] } = useUsers();
useEffect(() => {
if (!process.env.NEXT_PUBLIC_STRIPE || account.parentSubscriptionId)
router.push("/settings/account");
}, []);
const [searchQuery, setSearchQuery] = useState(""); const [searchQuery, setSearchQuery] = useState("");
const [filteredUsers, setFilteredUsers] = useState<User[]>(); const [filteredUsers, setFilteredUsers] = useState<User[]>();

View File

@ -7,6 +7,7 @@ import Link from "next/link";
import Button from "@/components/ui/Button"; import Button from "@/components/ui/Button";
import { useTranslation } from "next-i18next"; import { useTranslation } from "next-i18next";
import getServerSideProps from "@/lib/client/getServerSideProps"; import getServerSideProps from "@/lib/client/getServerSideProps";
import { useUser } from "@/hooks/store/user";
export default function Delete() { export default function Delete() {
const [password, setPassword] = useState(""); const [password, setPassword] = useState("");
@ -15,6 +16,7 @@ export default function Delete() {
const [submitLoader, setSubmitLoader] = useState(false); const [submitLoader, setSubmitLoader] = useState(false);
const { data } = useSession(); const { data } = useSession();
const { t } = useTranslation(); const { t } = useTranslation();
const { data: user } = useUser();
const submit = async () => { const submit = async () => {
const body = { const body = {
@ -83,7 +85,7 @@ export default function Delete() {
/> />
</div> </div>
{process.env.NEXT_PUBLIC_STRIPE && ( {process.env.NEXT_PUBLIC_STRIPE && !user.parentSubscriptionId && (
<fieldset className="border rounded-md p-2 border-primary"> <fieldset className="border rounded-md p-2 border-primary">
<legend className="px-3 py-1 text-sm sm:text-base border rounded-md border-primary"> <legend className="px-3 py-1 text-sm sm:text-base border rounded-md border-primary">
<b>{t("optional")}</b> <i>{t("feedback_help")}</i> <b>{t("optional")}</b> <i>{t("feedback_help")}</i>

View File

@ -9,8 +9,6 @@ import getServerSideProps from "@/lib/client/getServerSideProps";
import { Trans, useTranslation } from "next-i18next"; import { Trans, useTranslation } from "next-i18next";
import { useUser } from "@/hooks/store/user"; import { useUser } from "@/hooks/store/user";
const stripeEnabled = process.env.NEXT_PUBLIC_STRIPE === "true";
export default function Subscribe() { export default function Subscribe() {
const { t } = useTranslation(); const { t } = useTranslation();
const [submitLoader, setSubmitLoader] = useState(false); const [submitLoader, setSubmitLoader] = useState(false);

View File

@ -0,0 +1,17 @@
-- DropForeignKey
ALTER TABLE "Collection" DROP CONSTRAINT "Collection_createdById_fkey";
-- DropForeignKey
ALTER TABLE "Link" DROP CONSTRAINT "Link_createdById_fkey";
-- AlterTable
ALTER TABLE "Collection" ALTER COLUMN "createdById" DROP NOT NULL;
-- AlterTable
ALTER TABLE "Link" ALTER COLUMN "createdById" DROP NOT NULL;
-- AddForeignKey
ALTER TABLE "Collection" ADD CONSTRAINT "Collection_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Link" ADD CONSTRAINT "Link_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;

View File

@ -108,8 +108,8 @@ model Collection {
owner User @relation(fields: [ownerId], references: [id]) owner User @relation(fields: [ownerId], references: [id])
ownerId Int ownerId Int
members UsersAndCollections[] members UsersAndCollections[]
createdBy User @relation("CreatedCollections", fields: [createdById], references: [id]) createdBy User? @relation("CreatedCollections", fields: [createdById], references: [id])
createdById Int createdById Int?
links Link[] links Link[]
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt updatedAt DateTime @default(now()) @updatedAt
@ -138,8 +138,8 @@ model Link {
type String @default("url") type String @default("url")
description String @default("") description String @default("")
pinnedBy User[] @relation("PinnedLinks") pinnedBy User[] @relation("PinnedLinks")
createdBy User @relation("CreatedLinks", fields: [createdById], references: [id]) createdBy User? @relation("CreatedLinks", fields: [createdById], references: [id])
createdById Int createdById Int?
collection Collection @relation(fields: [collectionId], references: [id]) collection Collection @relation(fields: [collectionId], references: [id])
collectionId Int collectionId Int
tags Tag[] tags Tag[]