Skip to content

Commit fdf0256

Browse files
remove anonymous-access entitlement
1 parent 37317e0 commit fdf0256

File tree

13 files changed

+168
-120
lines changed

13 files changed

+168
-120
lines changed

packages/shared/src/entitlements.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ type LicenseKeyPayload = z.infer<typeof eeLicenseKeyPayloadSchema>;
2323
// eslint-disable-next-line @typescript-eslint/no-unused-vars
2424
const ALL_ENTITLEMENTS = [
2525
"search-contexts",
26-
"anonymous-access",
2726
"sso",
2827
"code-nav",
2928
"audit",
@@ -84,6 +83,16 @@ export const hasEntitlement = (entitlement: Entitlement, license: License | null
8483
return entitlements.includes(entitlement);
8584
}
8685

86+
export const isAnonymousAccessAvailable = (license: License | null): boolean => {
87+
if (getOfflineLicenseKey()) {
88+
return false;
89+
}
90+
if (license && isLicenseActive(license)) {
91+
return false;
92+
}
93+
return true;
94+
}
95+
8796
export const getEntitlements = (license: License | null): Entitlement[] => {
8897
const licenseKey = getOfflineLicenseKey();
8998
if (licenseKey) {

packages/shared/src/index.server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export {
22
hasEntitlement,
33
getOfflineLicenseKey,
44
getEntitlements,
5+
isAnonymousAccessAvailable as isAnonymousAccessEnabled,
56
} from "./entitlements.js";
67
export type {
78
Entitlement,

packages/web/src/actions.ts

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { createLogger } from "@sourcebot/shared";
1414
import { GiteaConnectionConfig } from "@sourcebot/schemas/v3/gitea.type";
1515
import { GithubConnectionConfig } from "@sourcebot/schemas/v3/github.type";
1616
import { GitlabConnectionConfig } from "@sourcebot/schemas/v3/gitlab.type";
17-
import { hasEntitlement } from "@/lib/entitlements";
17+
import { isAnonymousAccessAvailable } from "@/lib/entitlements";
1818
import { StatusCodes } from "http-status-codes";
1919
import { cookies } from "next/headers";
2020
import { createTransport } from "nodemailer";
@@ -1158,40 +1158,11 @@ export const getRepoImage = async (repoId: number): Promise<ArrayBuffer | Servic
11581158
})
11591159
});
11601160

1161-
export const getAnonymousAccessStatus = async (): Promise<boolean | ServiceError> => sew(async () => {
1162-
const org = await __unsafePrisma.org.findUnique({
1163-
where: { id: SINGLE_TENANT_ORG_ID },
1164-
});
1165-
if (!org) {
1166-
return {
1167-
statusCode: StatusCodes.NOT_FOUND,
1168-
errorCode: ErrorCode.NOT_FOUND,
1169-
message: "Organization not found",
1170-
} satisfies ServiceError;
1171-
}
1172-
1173-
// If no metadata is set we don't try to parse it since it'll result in a parse error
1174-
if (org.metadata === null) {
1175-
return false;
1176-
}
1177-
1178-
const orgMetadata = getOrgMetadata(org);
1179-
if (!orgMetadata) {
1180-
return {
1181-
statusCode: StatusCodes.INTERNAL_SERVER_ERROR,
1182-
errorCode: ErrorCode.INVALID_ORG_METADATA,
1183-
message: "Invalid organization metadata",
1184-
} satisfies ServiceError;
1185-
}
1186-
1187-
return !!orgMetadata.anonymousAccessEnabled;
1188-
});
1189-
11901161
export const setAnonymousAccessStatus = async (enabled: boolean): Promise<ServiceError | boolean> => sew(async () => {
11911162
return await withAuth(async ({ org, role, prisma }) => {
11921163
return await withMinimumOrgRole(role, OrgRole.OWNER, async () => {
1193-
const hasAnonymousAccessEntitlement = await hasEntitlement("anonymous-access");
1194-
if (!hasAnonymousAccessEntitlement) {
1164+
const anonymousAccessAvailable = await isAnonymousAccessAvailable();
1165+
if (!anonymousAccessAvailable) {
11951166
console.error(`Anonymous access isn't supported in your current plan. For support, contact ${SOURCEBOT_SUPPORT_EMAIL}.`);
11961167
return {
11971168
statusCode: StatusCodes.FORBIDDEN,

packages/web/src/app/(app)/layout.tsx

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ import { notFound, redirect } from "next/navigation";
1919
import { PendingApprovalCard } from "./components/pendingApproval";
2020
import { SubmitJoinRequest } from "./components/submitJoinRequest";
2121
import { env } from "@sourcebot/shared";
22-
import { hasEntitlement } from "@/lib/entitlements";
22+
import { hasEntitlement, isAnonymousAccessEnabled } from "@/lib/entitlements";
2323
import { GcpIapAuth } from "./components/gcpIapAuth";
24-
import { getAnonymousAccessStatus, getMemberApprovalRequired } from "@/actions";
24+
import { getMemberApprovalRequired } from "@/actions";
2525
import { JoinOrganizationCard } from "@/app/components/joinOrganizationCard";
2626
import { LogoutEscapeHatch } from "@/app/components/logoutEscapeHatch";
2727
import { GitHubStarToast } from "./components/githubStarToast";
@@ -53,18 +53,7 @@ export default async function Layout(props: LayoutProps) {
5353
}
5454

5555
const session = await auth();
56-
const anonymousAccessEnabled = await (async () => {
57-
if (!await hasEntitlement("anonymous-access")) {
58-
return false;
59-
}
60-
61-
const status = await getAnonymousAccessStatus();
62-
if (isServiceError(status)) {
63-
return false;
64-
}
65-
66-
return status;
67-
})();
56+
const anonymousAccessEnabled = await isAnonymousAccessEnabled();
6857

6958
// If the user is authenticated, we must check if they're a member of the org
7059
if (session) {

packages/web/src/app/components/anonymousAccessToggle.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import { isServiceError } from "@/lib/utils"
77
import { useToast } from "@/components/hooks/use-toast"
88

99
interface AnonymousAccessToggleProps {
10-
hasAnonymousAccessEntitlement: boolean;
10+
anonymousAccessAvailable: boolean;
1111
anonymousAccessEnabled: boolean
1212
forceEnableAnonymousAccess: boolean
1313
onToggleChange?: (checked: boolean) => void
1414
}
1515

16-
export function AnonymousAccessToggle({ hasAnonymousAccessEntitlement, anonymousAccessEnabled, forceEnableAnonymousAccess, onToggleChange }: AnonymousAccessToggleProps) {
16+
export function AnonymousAccessToggle({ anonymousAccessAvailable, anonymousAccessEnabled, forceEnableAnonymousAccess, onToggleChange }: AnonymousAccessToggleProps) {
1717
const [enabled, setEnabled] = useState(anonymousAccessEnabled)
1818
const [isLoading, setIsLoading] = useState(false)
1919
const { toast } = useToast()
@@ -45,12 +45,12 @@ export function AnonymousAccessToggle({ hasAnonymousAccessEntitlement, anonymous
4545
setIsLoading(false)
4646
}
4747
}
48-
const isDisabled = isLoading || !hasAnonymousAccessEntitlement || forceEnableAnonymousAccess;
49-
const showPlanMessage = !hasAnonymousAccessEntitlement;
48+
const isDisabled = isLoading || !anonymousAccessAvailable || forceEnableAnonymousAccess;
49+
const showPlanMessage = !anonymousAccessAvailable;
5050
const showForceEnableMessage = !showPlanMessage && forceEnableAnonymousAccess;
5151

5252
return (
53-
<div className={`p-4 rounded-lg border border-[var(--border)] bg-[var(--card)] ${(!hasAnonymousAccessEntitlement || forceEnableAnonymousAccess) ? 'opacity-60' : ''}`}>
53+
<div className={`p-4 rounded-lg border border-[var(--border)] bg-[var(--card)] ${(!anonymousAccessAvailable || forceEnableAnonymousAccess) ? 'opacity-60' : ''}`}>
5454
<div className="flex items-start justify-between gap-4">
5555
<div className="flex-1 min-w-0">
5656
<h3 className="font-medium text-[var(--foreground)] mb-2">
@@ -108,7 +108,7 @@ export function AnonymousAccessToggle({ hasAnonymousAccessEntitlement, anonymous
108108
/>
109109
</svg>
110110
<span>
111-
The <code className="bg-[var(--secondary)] px-1 py-0.5 rounded text-xs font-mono">forceEnableAnonymousAccess</code> is set, so this cannot be changed from the UI.
111+
<code className="bg-[var(--secondary)] px-1 py-0.5 rounded text-xs font-mono">FORCE_ENABLE_ANONYMOUS_ACCESS</code> is set, so this cannot be changed from the UI.
112112
</span>
113113
</p>
114114
</div>

packages/web/src/app/components/organizationAccessSettings.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,30 @@
11
import { createInviteLink } from "@/lib/utils"
22
import { AnonymousAccessToggle } from "./anonymousAccessToggle"
33
import { OrganizationAccessSettingsWrapper } from "./organizationAccessSettingsWrapper"
4-
import { getOrgMetadata } from "@/lib/utils"
54
import { SINGLE_TENANT_ORG_ID } from "@/lib/constants"
65
import { __unsafePrisma } from "@/prisma"
76
import { env } from "@sourcebot/shared"
8-
import { hasEntitlement } from "@/lib/entitlements"
7+
import { isAnonymousAccessAvailable, isAnonymousAccessEnabled } from "@/lib/entitlements"
98

109
export async function OrganizationAccessSettings() {
1110
const org = await __unsafePrisma.org.findUnique({ where: { id: SINGLE_TENANT_ORG_ID } });
1211
if (!org) {
1312
return <div>Error loading organization</div>
1413
}
1514

16-
const metadata = getOrgMetadata(org);
17-
const anonymousAccessEnabled = metadata?.anonymousAccessEnabled ?? false;
18-
1915
const baseUrl = env.AUTH_URL;
2016
const inviteLink = createInviteLink(baseUrl, org.inviteLinkId)
2117

22-
const hasAnonymousAccessEntitlement = await hasEntitlement("anonymous-access");
18+
const anonymousAccessEnabled = await isAnonymousAccessEnabled();
19+
const anonymousAccessAvailable = await isAnonymousAccessAvailable();
2320

2421
const forceEnableAnonymousAccess = env.FORCE_ENABLE_ANONYMOUS_ACCESS === 'true';
2522
const memberApprovalEnvVarSet = env.REQUIRE_APPROVAL_NEW_MEMBERS !== undefined;
2623

2724
return (
2825
<div className="space-y-6">
2926
<AnonymousAccessToggle
30-
hasAnonymousAccessEntitlement={hasAnonymousAccessEntitlement}
27+
anonymousAccessAvailable={anonymousAccessAvailable}
3128
anonymousAccessEnabled={anonymousAccessEnabled}
3229
forceEnableAnonymousAccess={forceEnableAnonymousAccess}
3330
/>

packages/web/src/app/login/page.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ import { Footer } from "@/app/components/footer";
55
import { getIdentityProviderMetadata } from "@/lib/identityProviders";
66
import { SINGLE_TENANT_ORG_ID } from "@/lib/constants";
77
import { __unsafePrisma } from "@/prisma";
8-
import { getAnonymousAccessStatus } from "@/actions";
9-
import { isServiceError } from "@/lib/utils";
108
import { env } from "@sourcebot/shared";
9+
import { isAnonymousAccessEnabled } from "@/lib/entitlements";
1110

1211
interface LoginProps {
1312
searchParams: Promise<{
@@ -29,8 +28,7 @@ export default async function Login(props: LoginProps) {
2928
}
3029

3130
const providers = await getIdentityProviderMetadata();
32-
const anonymousAccessStatus = await getAnonymousAccessStatus();
33-
const isAnonymousAccessEnabled = !isServiceError(anonymousAccessStatus) && anonymousAccessStatus;
31+
const anonymousAccessEnabled = await isAnonymousAccessEnabled();
3432

3533
return (
3634
<div className="flex flex-col min-h-screen bg-backgroundSecondary">
@@ -40,7 +38,7 @@ export default async function Login(props: LoginProps) {
4038
error={searchParams.error}
4139
providers={providers}
4240
context="login"
43-
isAnonymousAccessEnabled={isAnonymousAccessEnabled}
41+
isAnonymousAccessEnabled={anonymousAccessEnabled}
4442
hideSecurityNotice={env.EXPERIMENT_ASK_GH_ENABLED === 'true'}
4543
/>
4644
</div>

packages/web/src/app/signup/page.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ import { getIdentityProviderMetadata } from "@/lib/identityProviders";
66
import { createLogger, env } from "@sourcebot/shared";
77
import { SINGLE_TENANT_ORG_ID } from "@/lib/constants";
88
import { __unsafePrisma } from "@/prisma";
9-
import { getAnonymousAccessStatus } from "@/actions";
10-
import { isServiceError } from "@/lib/utils";
9+
import { isAnonymousAccessEnabled } from "@/lib/entitlements";
1110

1211
const logger = createLogger('signup-page');
1312

@@ -32,8 +31,7 @@ export default async function Signup(props: LoginProps) {
3231
}
3332

3433
const providers = await getIdentityProviderMetadata();
35-
const anonymousAccessStatus = await getAnonymousAccessStatus();
36-
const isAnonymousAccessEnabled = !isServiceError(anonymousAccessStatus) && anonymousAccessStatus;
34+
const anonymousAccessEnabled = await isAnonymousAccessEnabled();
3735

3836
return (
3937
<div className="flex flex-col min-h-screen bg-backgroundSecondary">
@@ -43,7 +41,7 @@ export default async function Signup(props: LoginProps) {
4341
error={searchParams.error}
4442
providers={providers}
4543
context="signup"
46-
isAnonymousAccessEnabled={isAnonymousAccessEnabled}
44+
isAnonymousAccessEnabled={anonymousAccessEnabled}
4745
hideSecurityNotice={env.EXPERIMENT_ASK_GH_ENABLED === 'true'}
4846
/>
4947
</div>

packages/web/src/initialize.ts

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,12 @@
11
import { __unsafePrisma } from "@/prisma";
22
import { startServicePingCronJob } from '@/ee/features/lighthouse/servicePing';
3-
import { createLogger, env, loadConfig } from "@sourcebot/shared";
3+
import { createLogger, env } from "@sourcebot/shared";
44
import { hasEntitlement } from '@/lib/entitlements';
55
import { SINGLE_TENANT_ORG_ID } from './lib/constants';
6-
import { getOrgMetadata } from './lib/utils';
76

87
const logger = createLogger('web-initialize');
98

109
const init = async () => {
11-
const hasAnonymousAccessEntitlement = await hasEntitlement("anonymous-access");
12-
if (!hasAnonymousAccessEntitlement) {
13-
// If anonymous access entitlement is not enabled, set the flag to false in the org on init
14-
const org = await __unsafePrisma.org.findUnique({ where: { id: SINGLE_TENANT_ORG_ID } });
15-
if (org) {
16-
const currentMetadata = getOrgMetadata(org);
17-
const mergedMetadata = {
18-
...(currentMetadata ?? {}),
19-
anonymousAccessEnabled: false,
20-
};
21-
await __unsafePrisma.org.update({
22-
where: { id: org.id },
23-
data: { metadata: mergedMetadata },
24-
});
25-
}
26-
}
27-
2810
// If we don't have the search context entitlement then wipe any existing
2911
// search contexts that may be present in the DB. This could happen if a deployment had
3012
// the entitlement, synced search contexts, and then no longer had the entitlement
@@ -37,33 +19,6 @@ const init = async () => {
3719
});
3820
}
3921

40-
// Sync anonymous access config from the config file
41-
const config = await loadConfig(env.CONFIG_PATH);
42-
const forceEnableAnonymousAccess = config.settings?.enablePublicAccess ?? env.FORCE_ENABLE_ANONYMOUS_ACCESS === 'true';
43-
44-
if (forceEnableAnonymousAccess) {
45-
if (!hasAnonymousAccessEntitlement) {
46-
logger.warn(`FORCE_ENABLE_ANONYMOUS_ACCESS env var is set to true but anonymous access entitlement is not available. Setting will be ignored.`);
47-
} else {
48-
const org = await __unsafePrisma.org.findUnique({ where: { id: SINGLE_TENANT_ORG_ID } });
49-
if (org) {
50-
const currentMetadata = getOrgMetadata(org);
51-
const mergedMetadata = {
52-
...(currentMetadata ?? {}),
53-
anonymousAccessEnabled: true,
54-
};
55-
56-
await __unsafePrisma.org.update({
57-
where: { id: org.id },
58-
data: {
59-
metadata: mergedMetadata,
60-
},
61-
});
62-
logger.info(`Anonymous access enabled via FORCE_ENABLE_ANONYMOUS_ACCESS environment variable`);
63-
}
64-
}
65-
}
66-
6722
// Sync member approval setting from env var (only if explicitly set)
6823
if (env.REQUIRE_APPROVAL_NEW_MEMBERS !== undefined) {
6924
const requireApprovalNewMembers = env.REQUIRE_APPROVAL_NEW_MEMBERS === 'true';

0 commit comments

Comments
 (0)