Skip to content

Commit 99e0b81

Browse files
improvement(org): remove dead seats get endpoint (#2247)
* improvement(org): remove dead seats get endpoint * remove more dead code * remove fallback limit
1 parent c197b04 commit 99e0b81

File tree

3 files changed

+1
-147
lines changed

3 files changed

+1
-147
lines changed

apps/sim/app/api/organizations/[id]/seats/route.ts

Lines changed: 0 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -224,74 +224,3 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{
224224
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
225225
}
226226
}
227-
228-
/**
229-
* GET /api/organizations/[id]/seats
230-
* Get current seat information for an organization
231-
*/
232-
export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
233-
try {
234-
const session = await getSession()
235-
236-
if (!session?.user?.id) {
237-
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
238-
}
239-
240-
const { id: organizationId } = await params
241-
242-
// Verify user has access to this organization
243-
const memberEntry = await db
244-
.select()
245-
.from(member)
246-
.where(and(eq(member.organizationId, organizationId), eq(member.userId, session.user.id)))
247-
.limit(1)
248-
249-
if (memberEntry.length === 0) {
250-
return NextResponse.json(
251-
{ error: 'Forbidden - Not a member of this organization' },
252-
{ status: 403 }
253-
)
254-
}
255-
256-
// Get subscription data
257-
const subscriptionRecord = await db
258-
.select()
259-
.from(subscription)
260-
.where(and(eq(subscription.referenceId, organizationId), eq(subscription.status, 'active')))
261-
.limit(1)
262-
263-
if (subscriptionRecord.length === 0) {
264-
return NextResponse.json({ error: 'No active subscription found' }, { status: 404 })
265-
}
266-
267-
// Get member count
268-
const memberCount = await db
269-
.select({ userId: member.userId })
270-
.from(member)
271-
.where(eq(member.organizationId, organizationId))
272-
273-
const orgSubscription = subscriptionRecord[0]
274-
const maxSeats = orgSubscription.seats || 1
275-
const usedSeats = memberCount.length
276-
const availableSeats = Math.max(0, maxSeats - usedSeats)
277-
278-
return NextResponse.json({
279-
success: true,
280-
data: {
281-
maxSeats,
282-
usedSeats,
283-
availableSeats,
284-
plan: orgSubscription.plan,
285-
canModifySeats: orgSubscription.plan === 'team',
286-
},
287-
})
288-
} catch (error) {
289-
const { id: organizationId } = await params
290-
logger.error('Failed to get organization seats', {
291-
organizationId,
292-
error,
293-
})
294-
295-
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
296-
}
297-
}

apps/sim/lib/auth/auth.ts

Lines changed: 1 addition & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,11 @@ import {
1313
oneTimeToken,
1414
organization,
1515
} from 'better-auth/plugins'
16-
import { and, eq } from 'drizzle-orm'
16+
import { eq } from 'drizzle-orm'
1717
import { headers } from 'next/headers'
1818
import Stripe from 'stripe'
1919
import {
2020
getEmailSubject,
21-
renderInvitationEmail,
2221
renderOTPEmail,
2322
renderPasswordResetEmail,
2423
} from '@/components/emails/render-email'
@@ -2068,79 +2067,6 @@ export const auth = betterAuth({
20682067

20692068
return hasTeamPlan
20702069
},
2071-
// Set a fixed membership limit of 50, but the actual limit will be enforced in the invitation flow
2072-
membershipLimit: 50,
2073-
// Validate seat limits before sending invitations
2074-
beforeInvite: async ({ organization }: { organization: { id: string } }) => {
2075-
const subscriptions = await db
2076-
.select()
2077-
.from(schema.subscription)
2078-
.where(
2079-
and(
2080-
eq(schema.subscription.referenceId, organization.id),
2081-
eq(schema.subscription.status, 'active')
2082-
)
2083-
)
2084-
2085-
const teamOrEnterpriseSubscription = subscriptions.find(
2086-
(sub) => sub.plan === 'team' || sub.plan === 'enterprise'
2087-
)
2088-
2089-
if (!teamOrEnterpriseSubscription) {
2090-
throw new Error('No active team or enterprise subscription for this organization')
2091-
}
2092-
2093-
const members = await db
2094-
.select()
2095-
.from(schema.member)
2096-
.where(eq(schema.member.organizationId, organization.id))
2097-
2098-
const pendingInvites = await db
2099-
.select()
2100-
.from(schema.invitation)
2101-
.where(
2102-
and(
2103-
eq(schema.invitation.organizationId, organization.id),
2104-
eq(schema.invitation.status, 'pending')
2105-
)
2106-
)
2107-
2108-
const totalCount = members.length + pendingInvites.length
2109-
const seatLimit = teamOrEnterpriseSubscription.seats || 1
2110-
2111-
if (totalCount >= seatLimit) {
2112-
throw new Error(`Organization has reached its seat limit of ${seatLimit}`)
2113-
}
2114-
},
2115-
sendInvitationEmail: async (data: any) => {
2116-
try {
2117-
const { invitation, organization, inviter } = data
2118-
2119-
const inviteUrl = `${getBaseUrl()}/invite/${invitation.id}`
2120-
const inviterName = inviter.user?.name || 'A team member'
2121-
2122-
const html = await renderInvitationEmail(
2123-
inviterName,
2124-
organization.name,
2125-
inviteUrl,
2126-
invitation.email
2127-
)
2128-
2129-
const result = await sendEmail({
2130-
to: invitation.email,
2131-
subject: `${inviterName} has invited you to join ${organization.name} on Sim`,
2132-
html,
2133-
from: getFromEmailAddress(),
2134-
emailType: 'transactional',
2135-
})
2136-
2137-
if (!result.success) {
2138-
logger.error('Failed to send organization invitation email:', result.message)
2139-
}
2140-
} catch (error) {
2141-
logger.error('Error sending invitation email', { error })
2142-
}
2143-
},
21442070
organizationCreation: {
21452071
afterCreate: async ({ organization, user }) => {
21462072
logger.info('[organizationCreation.afterCreate] Organization created', {

bun.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)