Skip to content

Commit 0d7054b

Browse files
committed
add forceEnableAnonymousAccess setting
1 parent 990782a commit 0d7054b

File tree

8 files changed

+92
-6
lines changed

8 files changed

+92
-6
lines changed

docs/snippets/schemas/v3/index.schema.mdx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@
6363
"type": "number",
6464
"description": "The timeout (in milliseconds) for a repo indexing to timeout. Defaults to 2 hours.",
6565
"minimum": 1
66+
},
67+
"forceEnableAnonymousAccess": {
68+
"type": "boolean",
69+
"description": "Force enable anonymous access. When set to true, anonymous access will be enabled and the UI toggle will be disabled."
6670
}
6771
},
6872
"additionalProperties": false
@@ -172,6 +176,10 @@
172176
"type": "number",
173177
"description": "The timeout (in milliseconds) for a repo indexing to timeout. Defaults to 2 hours.",
174178
"minimum": 1
179+
},
180+
"forceEnableAnonymousAccess": {
181+
"type": "boolean",
182+
"description": "Force enable anonymous access. When set to true, anonymous access will be enabled and the UI toggle will be disabled."
175183
}
176184
},
177185
"additionalProperties": false

packages/backend/src/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ export const DEFAULT_SETTINGS: Settings = {
1515
maxRepoGarbageCollectionJobConcurrency: 8,
1616
repoGarbageCollectionGracePeriodMs: 10 * 1000, // 10 seconds
1717
repoIndexTimeoutMs: 1000 * 60 * 60 * 2, // 2 hours
18+
forceEnableAnonymousAccess: false,
1819
}

packages/schemas/src/v3/index.schema.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ const schema = {
6262
"type": "number",
6363
"description": "The timeout (in milliseconds) for a repo indexing to timeout. Defaults to 2 hours.",
6464
"minimum": 1
65+
},
66+
"forceEnableAnonymousAccess": {
67+
"type": "boolean",
68+
"description": "Force enable anonymous access. When set to true, anonymous access will be enabled and the UI toggle will be disabled."
6569
}
6670
},
6771
"additionalProperties": false
@@ -171,6 +175,10 @@ const schema = {
171175
"type": "number",
172176
"description": "The timeout (in milliseconds) for a repo indexing to timeout. Defaults to 2 hours.",
173177
"minimum": 1
178+
},
179+
"forceEnableAnonymousAccess": {
180+
"type": "boolean",
181+
"description": "Force enable anonymous access. When set to true, anonymous access will be enabled and the UI toggle will be disabled."
174182
}
175183
},
176184
"additionalProperties": false

packages/schemas/src/v3/index.type.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ export interface Settings {
7979
* The timeout (in milliseconds) for a repo indexing to timeout. Defaults to 2 hours.
8080
*/
8181
repoIndexTimeoutMs?: number;
82+
/**
83+
* Force enable anonymous access. When set to true, anonymous access will be enabled and the UI toggle will be disabled.
84+
*/
85+
forceEnableAnonymousAccess?: boolean;
8286
}
8387
/**
8488
* Search context

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

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ import { useToast } from "@/components/hooks/use-toast"
1010
interface AnonymousAccessToggleProps {
1111
hasAnonymousAccessEntitlement: boolean;
1212
anonymousAccessEnabled: boolean
13+
forceEnableAnonymousAccess: boolean
1314
onToggleChange?: (checked: boolean) => void
1415
}
1516

16-
export function AnonymousAccessToggle({ hasAnonymousAccessEntitlement, anonymousAccessEnabled, onToggleChange }: AnonymousAccessToggleProps) {
17+
export function AnonymousAccessToggle({ hasAnonymousAccessEntitlement, anonymousAccessEnabled, forceEnableAnonymousAccess, onToggleChange }: AnonymousAccessToggleProps) {
1718
const [enabled, setEnabled] = useState(anonymousAccessEnabled)
1819
const [isLoading, setIsLoading] = useState(false)
1920
const { toast } = useToast()
@@ -45,9 +46,12 @@ export function AnonymousAccessToggle({ hasAnonymousAccessEntitlement, anonymous
4546
setIsLoading(false)
4647
}
4748
}
49+
const isDisabled = isLoading || !hasAnonymousAccessEntitlement || forceEnableAnonymousAccess;
50+
const showPlanMessage = !hasAnonymousAccessEntitlement;
51+
const showForceEnableMessage = !showPlanMessage && forceEnableAnonymousAccess;
4852

4953
return (
50-
<div className={`p-4 rounded-lg border border-[var(--border)] bg-[var(--card)] ${!hasAnonymousAccessEntitlement ? 'opacity-60' : ''}`}>
54+
<div className={`p-4 rounded-lg border border-[var(--border)] bg-[var(--card)] ${(!hasAnonymousAccessEntitlement || forceEnableAnonymousAccess) ? 'opacity-60' : ''}`}>
5155
<div className="flex items-start justify-between gap-4">
5256
<div className="flex-1 min-w-0">
5357
<h3 className="font-medium text-[var(--foreground)] mb-2">
@@ -65,7 +69,7 @@ export function AnonymousAccessToggle({ hasAnonymousAccessEntitlement, anonymous
6569
Learn More
6670
</a>
6771
</p>
68-
{!hasAnonymousAccessEntitlement && (
72+
{showPlanMessage && (
6973
<div className="mt-3 p-3 rounded-md bg-[var(--muted)] border border-[var(--border)]">
7074
<p className="text-sm text-[var(--foreground)] leading-relaxed flex items-center gap-2">
7175
<svg
@@ -96,13 +100,35 @@ export function AnonymousAccessToggle({ hasAnonymousAccessEntitlement, anonymous
96100
</p>
97101
</div>
98102
)}
103+
{showForceEnableMessage && (
104+
<div className="mt-3 p-3 rounded-md bg-[var(--muted)] border border-[var(--border)]">
105+
<p className="text-sm text-[var(--foreground)] leading-relaxed flex items-center gap-2">
106+
<svg
107+
className="w-4 h-4 flex-shrink-0 text-[var(--muted-foreground)]"
108+
fill="none"
109+
viewBox="0 0 24 24"
110+
stroke="currentColor"
111+
>
112+
<path
113+
strokeLinecap="round"
114+
strokeLinejoin="round"
115+
strokeWidth={2}
116+
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
117+
/>
118+
</svg>
119+
<span>
120+
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.
121+
</span>
122+
</p>
123+
</div>
124+
)}
99125
</div>
100126
</div>
101127
<div className="flex-shrink-0">
102128
<Switch
103129
checked={enabled}
104130
onCheckedChange={handleToggle}
105-
disabled={isLoading || !hasAnonymousAccessEntitlement}
131+
disabled={isDisabled}
106132
/>
107133
</div>
108134
</div>

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ import { getOrgFromDomain } from "@/data/org"
55
import { getOrgMetadata } from "@/types"
66
import { headers } from "next/headers"
77
import { SINGLE_TENANT_ORG_DOMAIN } from "@/lib/constants"
8-
import { hasEntitlement } from "@sourcebot/shared"
8+
import { hasEntitlement, loadConfig } from "@sourcebot/shared"
9+
import { env } from "@/env.mjs"
10+
import { createLogger } from "@sourcebot/logger";
11+
12+
const logger = createLogger("OrganizationAccessSettings");
913

1014
export async function OrganizationAccessSettings() {
1115
const org = await getOrgFromDomain(SINGLE_TENANT_ORG_DOMAIN);
@@ -22,11 +26,20 @@ export async function OrganizationAccessSettings() {
2226

2327
const hasAnonymousAccessEntitlement = hasEntitlement("anonymous-access");
2428

29+
let forceEnableAnonymousAccess = false;
30+
if (env.CONFIG_PATH) {
31+
const config = await loadConfig(env.CONFIG_PATH);
32+
forceEnableAnonymousAccess = config.settings?.forceEnableAnonymousAccess ?? false;
33+
} else {
34+
logger.warn("CONFIG_PATH is not set, so forceEnableAnonymousAccess will be false");
35+
}
36+
2537
return (
2638
<div className="space-y-6">
27-
<AnonymousAccessToggle
39+
<AnonymousAccessToggle
2840
hasAnonymousAccessEntitlement={hasAnonymousAccessEntitlement}
2941
anonymousAccessEnabled={anonymousAccessEnabled}
42+
forceEnableAnonymousAccess={forceEnableAnonymousAccess}
3043
/>
3144

3245
<OrganizationAccessSettingsWrapper

packages/web/src/initialize.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,28 @@ const syncConnections = async (connections?: { [key: string]: ConnectionConfig }
106106
const syncDeclarativeConfig = async (configPath: string) => {
107107
const config = await loadConfig(configPath);
108108

109+
if (config.settings?.forceEnableAnonymousAccess) {
110+
const hasAnonymousAccessEntitlement = hasEntitlement("anonymous-access");
111+
if (!hasAnonymousAccessEntitlement) {
112+
logger.warn(`forceEnableAnonymousAccess is set to true but anonymous access entitlement is not available. Setting will be ignored.`);
113+
} else {
114+
const org = await getOrgFromDomain(SINGLE_TENANT_ORG_DOMAIN);
115+
if (org) {
116+
const currentMetadata = org.metadata ? org.metadata as any : {};
117+
await prisma.org.update({
118+
where: { id: org.id },
119+
data: {
120+
metadata: {
121+
...currentMetadata,
122+
anonymousAccessEnabled: true
123+
}
124+
},
125+
});
126+
logger.info(`Anonymous access enabled via forceEnableAnonymousAccess setting`);
127+
}
128+
}
129+
}
130+
109131
await syncConnections(config.connections);
110132
await syncSearchContexts({
111133
contexts: config.contexts,

schemas/v3/index.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@
6161
"type": "number",
6262
"description": "The timeout (in milliseconds) for a repo indexing to timeout. Defaults to 2 hours.",
6363
"minimum": 1
64+
},
65+
"forceEnableAnonymousAccess": {
66+
"type": "boolean",
67+
"description": "Force enable anonymous access. When set to true, anonymous access will be enabled and the UI toggle will be disabled."
6468
}
6569
},
6670
"additionalProperties": false

0 commit comments

Comments
 (0)