feat(cloud): fix upgrade/downgrade and migrate webhook handler

This commit is contained in:
Henry
2026-05-16 22:23:56 +01:00
parent 7d52e4eb88
commit f38533590d
2 changed files with 21 additions and 15 deletions

View File

@@ -87,6 +87,8 @@ export default withApiLogging(
const { event, license_key, license_status, tier, prev_license_key } = const { event, license_key, license_status, tier, prev_license_key } =
payload; payload;
log.info({ headers: req.headers, payload }, "partner webhook received");
const { db } = await createNextApiContext(req); const { db } = await createNextApiContext(req);
switch (event) { switch (event) {
@@ -141,7 +143,7 @@ export default withApiLogging(
const cfg = tierConfig(tier); const cfg = tierConfig(tier);
await subscriptionRepo.upsertByPartnerLicenseKey(db, license_key, { await subscriptionRepo.upsertByPartnerLicenseKey(db, license_key, {
plan: cfg.plan, plan: cfg.plan,
status: license_status, status: "active",
partnerTier: tier, partnerTier: tier,
seats: cfg.seats, seats: cfg.seats,
unlimitedSeats: cfg.unlimitedSeats, unlimitedSeats: cfg.unlimitedSeats,
@@ -163,7 +165,7 @@ export default withApiLogging(
const cfg = tierConfig(tier); const cfg = tierConfig(tier);
await subscriptionRepo.upsertByPartnerLicenseKey(db, license_key, { await subscriptionRepo.upsertByPartnerLicenseKey(db, license_key, {
plan: cfg.plan, plan: cfg.plan,
status: sub.status, status: "active",
partnerTier: tier, partnerTier: tier,
seats: cfg.seats, seats: cfg.seats,
unlimitedSeats: cfg.unlimitedSeats, unlimitedSeats: cfg.unlimitedSeats,

View File

@@ -27,8 +27,8 @@ import { useWorkspace } from "~/providers/workspace";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { getAvatarUrl } from "~/utils/helpers"; import { getAvatarUrl } from "~/utils/helpers";
import { DeleteMemberConfirmation } from "./components/DeleteMemberConfirmation"; import { DeleteMemberConfirmation } from "./components/DeleteMemberConfirmation";
import { InviteMemberForm } from "./components/InviteMemberForm";
import { EditMemberPermissionsModal } from "./components/EditMemberPermissionsModal"; import { EditMemberPermissionsModal } from "./components/EditMemberPermissionsModal";
import { InviteMemberForm } from "./components/InviteMemberForm";
export default function MembersPage() { export default function MembersPage() {
const { modalContentType, openModal, isOpen } = useModal(); const { modalContentType, openModal, isOpen } = useModal();
@@ -76,6 +76,13 @@ export default function MembersPage() {
const unlimitedSeats = hasUnlimitedSeats(subscriptions); const unlimitedSeats = hasUnlimitedSeats(subscriptions);
const isProPlan =
!!proSubscription ||
workspace.plan === "pro" ||
workspace.plan === "enterprise";
const isTeamPlan = !!teamSubscription || workspace.plan === "team";
const isPaidPlan = isProPlan || isTeamPlan;
const TableRow = ({ const TableRow = ({
memberPublicId, memberPublicId,
memberId, memberId,
@@ -144,8 +151,8 @@ export default function MembersPage() {
{memberName} {memberName}
</p> </p>
</div> </div>
{((workspace.role === "admin" || {(workspace.role === "admin" ||
data?.showEmailsToMembers === true) || data?.showEmailsToMembers === true ||
showSkeleton) && ( showSkeleton) && (
<p <p
className={twMerge( className={twMerge(
@@ -180,8 +187,7 @@ export default function MembersPage() {
<div className="relative inline-flex items-center"> <div className="relative inline-flex items-center">
<span className="inline-flex items-center gap-1 rounded-md bg-emerald-500/10 px-1.5 py-0.5 text-[10px] font-medium text-emerald-400 ring-1 ring-inset ring-emerald-500/20 sm:text-[11px]"> <span className="inline-flex items-center gap-1 rounded-md bg-emerald-500/10 px-1.5 py-0.5 text-[10px] font-medium text-emerald-400 ring-1 ring-inset ring-emerald-500/20 sm:text-[11px]">
{memberRole && {memberRole &&
memberRole.charAt(0).toUpperCase() + memberRole.charAt(0).toUpperCase() + memberRole.slice(1)}
memberRole.slice(1)}
{canEditMember && session?.user.id !== memberId && ( {canEditMember && session?.user.id !== memberId && (
<HiChevronDown className="h-3 w-3" /> <HiChevronDown className="h-3 w-3" />
)} )}
@@ -266,32 +272,30 @@ export default function MembersPage() {
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
{env("NEXT_PUBLIC_KAN_ENV") === "cloud" && ( {env("NEXT_PUBLIC_KAN_ENV") === "cloud" && (
<> <>
{!proSubscription && !teamSubscription && ( {!isPaidPlan && (
<Link <Link
href="/settings/workspace?upgrade=pro" href="/settings/workspace?upgrade=pro"
className="hidden items-center rounded-full border border-emerald-300 bg-emerald-50 px-3 py-1 text-center text-xs text-emerald-400 dark:border-emerald-700 dark:bg-emerald-950 dark:text-emerald-400 lg:flex" className="hidden items-center rounded-full border border-emerald-300 bg-emerald-50 px-3 py-1 text-center text-xs text-emerald-400 dark:border-emerald-700 dark:bg-emerald-950 dark:text-emerald-400 lg:flex"
> >
<HiBolt /> <HiBolt />
<span className="ml-1 font-medium"> <span className="ml-1 font-medium">{t`Upgrade`}</span>
{t`Launch offer: Get unlimited members with Pro`}
</span>
</Link> </Link>
)} )}
<div <div
className={twMerge( className={twMerge(
"flex items-center rounded-full border px-3 py-1 text-center text-xs", "flex items-center rounded-full border px-3 py-1 text-center text-xs",
teamSubscription || proSubscription isPaidPlan
? "border-emerald-300 bg-emerald-50 text-emerald-400 dark:border-emerald-700 dark:bg-emerald-950 dark:text-emerald-400" ? "border-emerald-300 bg-emerald-50 text-emerald-400 dark:border-emerald-700 dark:bg-emerald-950 dark:text-emerald-400"
: "border-light-300 bg-light-50 text-light-1000 dark:border-dark-300 dark:bg-dark-50 dark:text-dark-900", : "border-light-300 bg-light-50 text-light-1000 dark:border-dark-300 dark:bg-dark-50 dark:text-dark-900",
)} )}
> >
<span className="font-medium"> <span className="font-medium">
{proSubscription {isProPlan
? t`Pro Plan` ? t`Pro Plan`
: teamSubscription : isTeamPlan
? t`Team Plan` ? t`Team Plan`
: t`Free Plan`} : t`Free Plan`}
{proSubscription && unlimitedSeats && ( {isProPlan && unlimitedSeats && (
<span className="ml-1 text-xs"></span> <span className="ml-1 text-xs"></span>
)} )}
</span> </span>