Skip to content

Commit 39db1a4

Browse files
move things to ee
1 parent 661ece2 commit 39db1a4

File tree

7 files changed

+78
-20
lines changed

7 files changed

+78
-20
lines changed

packages/shared/src/entitlements.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,14 @@ const entitlements = [
3838
"audit",
3939
"analytics",
4040
"permission-syncing",
41-
"github-app"
41+
"github-app",
42+
"chat-sharing"
4243
] as const;
4344
export type Entitlement = (typeof entitlements)[number];
4445

4546
const entitlementsByPlan: Record<Plan, Entitlement[]> = {
4647
oss: [
47-
"anonymous-access"
48+
"anonymous-access",
4849
],
4950
"self-hosted:enterprise": [
5051
"search-contexts",
@@ -53,17 +54,19 @@ const entitlementsByPlan: Record<Plan, Entitlement[]> = {
5354
"audit",
5455
"analytics",
5556
"permission-syncing",
56-
"github-app"
57+
"github-app",
58+
"chat-sharing",
5759
],
5860
"self-hosted:enterprise-unlimited": [
61+
"anonymous-access",
5962
"search-contexts",
6063
"sso",
6164
"code-nav",
6265
"audit",
6366
"analytics",
6467
"permission-syncing",
6568
"github-app",
66-
"anonymous-access"
69+
"chat-sharing",
6770
],
6871
} as const;
6972

packages/web/src/app/[domain]/chat/[id]/page.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { getOrgFromDomain } from '@/data/org';
1717
import { ChatVisibility } from '@sourcebot/db';
1818
import { Metadata } from 'next';
1919
import { SBChatMessage } from '@/features/chat/types';
20+
import { env, hasEntitlement } from '@sourcebot/shared';
2021

2122
interface PageProps {
2223
params: Promise<{
@@ -126,6 +127,8 @@ export default async function Page(props: PageProps) {
126127

127128
const indexedRepos = repos.filter((repo) => repo.indexedAt !== undefined);
128129

130+
const hasChatSharingEntitlement = hasEntitlement('chat-sharing');
131+
129132
return (
130133
<div className="flex flex-col h-screen w-screen">
131134
<TopBar
@@ -145,6 +148,10 @@ export default async function Page(props: PageProps) {
145148
visibility={visibility}
146149
currentUser={session?.user}
147150
sharedWithUsers={sharedWithUsers}
151+
isChatSharingEnabledInCurrentPlan={hasChatSharingEntitlement}
152+
// Disable chat sharing for the askgh experiment since we
153+
// don't want to allow users to search other members.
154+
isChatSharingEnabled={env.EXPERIMENT_ASK_GH_ENABLED === 'false'}
148155
/>
149156
) : undefined}
150157
/>

packages/web/src/app/[domain]/chat/components/shareChatPopover/invitePanel.tsx renamed to packages/web/src/app/[domain]/chat/components/shareChatPopover/ee/invitePanel.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client';
22

33
import { searchChatShareableMembers } from "@/app/api/(client)/client";
4-
import { SearchChatShareableMembersResponse } from "@/app/api/(server)/chat/[chatId]/searchMembers/route";
4+
import { SearchChatShareableMembersResponse } from "@/app/api/(server)/ee/chat/[chatId]/searchMembers/route";
55
import { SessionUser } from "@/auth";
66
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
77
import { Badge } from "@/components/ui/badge";

packages/web/src/app/[domain]/chat/components/shareChatPopover/index.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ import { useToast } from "@/components/hooks/use-toast";
1414
import { isServiceError } from "@/lib/utils";
1515
import { Link2Icon, LockIcon } from "lucide-react";
1616
import { SessionUser } from "@/auth";
17-
import { InvitePanel } from "./invitePanel";
17+
import { InvitePanel } from "./ee/invitePanel";
1818

1919
interface ShareChatPopoverProps {
2020
chatId: string;
2121
visibility: ChatVisibility;
2222
currentUser?: SessionUser;
2323
sharedWithUsers: SessionUser[];
24+
isChatSharingEnabledInCurrentPlan: boolean;
25+
isChatSharingEnabled: boolean;
2426
}
2527

2628
type View = 'main' | 'invite';
@@ -29,7 +31,9 @@ export const ShareChatPopover = ({
2931
chatId,
3032
visibility: _visibility,
3133
currentUser,
32-
sharedWithUsers: _sharedWithUsers
34+
sharedWithUsers: _sharedWithUsers,
35+
isChatSharingEnabledInCurrentPlan,
36+
isChatSharingEnabled,
3337
}: ShareChatPopoverProps) => {
3438
const [visibility, setVisibility] = useState(_visibility);
3539
const [sharedWithUsers, setSharedWithUsers] = useState(_sharedWithUsers);
@@ -131,14 +135,16 @@ export const ShareChatPopover = ({
131135
currentUser={currentUser}
132136
sharedWithUsers={sharedWithUsers}
133137
onOpenInviteView={() => setView('invite')}
138+
isChatSharingEnabledInCurrentPlan={isChatSharingEnabledInCurrentPlan}
139+
isChatSharingEnabled={isChatSharingEnabled}
134140
/>
135-
) : (
141+
) : (isChatSharingEnabledInCurrentPlan && isChatSharingEnabled)? (
136142
<InvitePanel
137143
chatId={chatId}
138144
onBack={() => setView('main')}
139145
onShareChatWithUsers={onShareChatWithUsers}
140146
/>
141-
)}
147+
) : null}
142148
</PopoverContent>
143149
</Popover>
144150
);

packages/web/src/app/[domain]/chat/components/shareChatPopover/shareSettings.tsx

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
SelectValue,
1313
} from "@/components/ui/select";
1414
import { Separator } from "@/components/ui/separator";
15+
import { cn } from "@/lib/utils";
1516
import placeholderAvatar from "@/public/placeholder_avatar.png";
1617
import { ChatVisibility } from "@sourcebot/db";
1718
import { Info, Link2Icon, Loader2, Lock, X } from "lucide-react";
@@ -26,6 +27,8 @@ interface ShareSettingsProps {
2627
onOpenInviteView: () => void;
2728
currentUser?: SessionUser;
2829
sharedWithUsers: SessionUser[];
30+
isChatSharingEnabledInCurrentPlan: boolean;
31+
isChatSharingEnabled: boolean;
2932
}
3033

3134
export const ShareSettings = ({
@@ -35,6 +38,8 @@ export const ShareSettings = ({
3538
onOpenInviteView,
3639
currentUser,
3740
sharedWithUsers,
41+
isChatSharingEnabledInCurrentPlan,
42+
isChatSharingEnabled,
3843
}: ShareSettingsProps) => {
3944
const [isVisibilityUpdating, setIsVisibilityUpdating] = useState(false);
4045
const [removingUserIds, setRemovingUserIds] = useState<Set<string>>(new Set());
@@ -65,18 +70,26 @@ export const ShareSettings = ({
6570
<Separator className="-mx-4 w-auto mt-2 mb-4" />
6671

6772
{/* Fake Search Bar - Click to open invite view */}
68-
{isAuthenticated && (
73+
{(isAuthenticated && isChatSharingEnabled) && (
6974
<>
70-
<Button
71-
variant="outline"
72-
className="w-full justify-start text-muted-foreground font-normal"
73-
onClick={onOpenInviteView}
74-
>
75-
Search for a user
76-
</Button>
75+
<span className={cn({ "cursor-not-allowed": !isChatSharingEnabledInCurrentPlan })}>
76+
<Button
77+
variant="outline"
78+
className={cn("w-full justify-start text-muted-foreground font-normal", {
79+
"opacity-50 pointer-events-none": !isChatSharingEnabledInCurrentPlan,
80+
})}
81+
onClick={onOpenInviteView}
82+
disabled={!isChatSharingEnabledInCurrentPlan}
83+
>
84+
Search for a user
85+
</Button>
86+
</span>
7787

7888
{/* People with access */}
79-
<div className="mt-4">
89+
<div className={cn("mt-4", {
90+
"opacity-50 cursor-not-allowed": !isChatSharingEnabledInCurrentPlan,
91+
"[&_*]:pointer-events-none": !isChatSharingEnabledInCurrentPlan,
92+
})}>
8093
<label className="text-sm text-muted-foreground mb-2 block">
8194
People with access
8295
</label>
@@ -143,6 +156,13 @@ export const ShareSettings = ({
143156
</div>
144157
</div>
145158

159+
{!isChatSharingEnabledInCurrentPlan && (
160+
<p className="text-xs text-muted-foreground mt-2.5">
161+
<Info className="h-3 w-3 inline-block mr-1.5 align-middle" />
162+
<span className="align-middle">Sharing with specific users is not available on your current <Link href={'https://sourcebot.dev/pricing'} target="_blank" rel="noopener noreferrer" className="underline">plan</Link>.</span>
163+
</p>
164+
)}
165+
146166
<Separator className="-mx-4 w-auto my-4" />
147167
</>
148168
)}

packages/web/src/app/api/(client)/client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { PermissionSyncStatusResponse } from "../(server)/ee/permissionSyncStatu
2323
import {
2424
SearchChatShareableMembersQueryParams,
2525
SearchChatShareableMembersResponse,
26-
} from "../(server)/chat/[chatId]/searchMembers/route";
26+
} from "../(server)/ee/chat/[chatId]/searchMembers/route";
2727

2828
export const search = async (body: SearchRequest): Promise<SearchResponse | ServiceError> => {
2929
const result = await fetch("/api/search", {
@@ -144,7 +144,7 @@ export const searchChatShareableMembers = async (
144144
params: SearchChatShareableMembersQueryParams & { chatId: string },
145145
signal?: AbortSignal
146146
): Promise<SearchChatShareableMembersResponse | ServiceError> => {
147-
const url = new URL(`/api/chat/${params.chatId}/searchMembers`, window.location.origin);
147+
const url = new URL(`/api/ee/chat/${params.chatId}/searchMembers`, window.location.origin);
148148
if (params.query) {
149149
url.searchParams.set('query', params.query);
150150
}

packages/web/src/app/api/(server)/chat/[chatId]/searchMembers/route.ts renamed to packages/web/src/app/api/(server)/ee/chat/[chatId]/searchMembers/route.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import { apiHandler } from "@/lib/apiHandler";
22
import { SOURCEBOT_GUEST_USER_ID } from "@/lib/constants";
3+
import { ErrorCode } from "@/lib/errorCodes";
34
import { notFound, queryParamsSchemaValidationError, serviceErrorResponse } from "@/lib/serviceError";
45
import { isServiceError } from "@/lib/utils";
56
import { withAuthV2 } from "@/withAuthV2";
7+
import { env, hasEntitlement } from "@sourcebot/shared";
8+
import { StatusCodes } from "http-status-codes";
69
import { NextRequest } from "next/server";
710
import { z } from "zod";
811

@@ -28,6 +31,24 @@ export const GET = apiHandler(async (
2831
request: NextRequest,
2932
{ params }: { params: Promise<{ chatId: string }> }
3033
) => {
34+
// Disable this API for the askgh experiment since we
35+
// don't want to allow users to search other members.
36+
if (env.EXPERIMENT_ASK_GH_ENABLED === 'true') {
37+
return serviceErrorResponse({
38+
statusCode: StatusCodes.FORBIDDEN,
39+
errorCode: ErrorCode.NOT_FOUND,
40+
message: "This API is not enabled with this experiment.",
41+
})
42+
}
43+
44+
if (!hasEntitlement('chat-sharing')) {
45+
return serviceErrorResponse({
46+
statusCode: StatusCodes.FORBIDDEN,
47+
errorCode: ErrorCode.NOT_FOUND,
48+
message: "Chat sharing is not enabled for your license",
49+
})
50+
}
51+
3152
const { chatId } = await params;
3253

3354
const rawParams = Object.fromEntries(
@@ -46,6 +67,7 @@ export const GET = apiHandler(async (
4667

4768
const { query } = parsed.data;
4869

70+
4971
const result = await withAuthV2(async ({ org, user, prisma }) => {
5072
const chat = await prisma.chat.findUnique({
5173
where: {

0 commit comments

Comments
 (0)