diff --git a/.env.example b/.env.example index 77dc817..d390755 100644 --- a/.env.example +++ b/.env.example @@ -90,9 +90,10 @@ FFMPEG_BIN= # NEXT_PUBLIC_ENABLE_DOCX_CONVERSION=true # NEXT_PUBLIC_ENABLE_DESTRUCTIVE_DELETE_ACTIONS=true # NEXT_PUBLIC_ENABLE_TTS_PROVIDERS_TAB=true +# NEXT_PUBLIC_ENABLE_USER_SIGNUPS=true # NEXT_PUBLIC_RESTRICT_USER_API_KEYS=true # NEXT_PUBLIC_DEFAULT_TTS_PROVIDER=custom-openai # NEXT_PUBLIC_CHANGELOG_FEED_URL=https://docs.openreader.richardr.dev/changelog/manifest.json # NEXT_PUBLIC_DEFAULT_TTS_MODEL=kokoro # NEXT_PUBLIC_ENABLE_AUDIOBOOK_EXPORT=true -# NEXT_PUBLIC_ENABLE_WORD_HIGHLIGHT=false +# NEXT_PUBLIC_ENABLE_WORD_HIGHLIGHT=true diff --git a/docs-site/docs/configure/admin-panel.md b/docs-site/docs/configure/admin-panel.md index 2bd5d15..7167962 100644 --- a/docs-site/docs/configure/admin-panel.md +++ b/docs-site/docs/configure/admin-panel.md @@ -66,6 +66,7 @@ Runtime-editable settings, one row per key: | --- | --- | | `defaultTtsProvider` | Default provider id new users start with (built-in id or shared slug). | | `changelogFeedUrl` | Public changelog manifest URL used by the Settings modal changelog panel. | +| `enableUserSignups` | Controls whether new accounts can be created. Existing accounts can still sign in when this is `false`. | | `restrictUserApiKeys` | Restrict user-supplied API keys/base URLs; when `true`, only admin shared providers are allowed. | | `enableTtsProvidersTab` | Whether the user-facing TTS Provider tab in Settings is shown. | | `showAllProviderModels` | When `false`, users are restricted to each provider's default model (shared provider `defaultModel` or built-in provider default). | diff --git a/docs-site/docs/configure/auth.md b/docs-site/docs/configure/auth.md index fcedf3f..630a29e 100644 --- a/docs-site/docs/configure/auth.md +++ b/docs-site/docs/configure/auth.md @@ -31,7 +31,7 @@ ADMIN_EMAILS=alice@example.com,bob@example.com Admins see a new **Admin** tab in **Settings** with two sub-tabs: - **Shared TTS providers** — server-managed TTS provider instances with encrypted keys, visible to all users. -- **Site features** — runtime overrides for what were previously `NEXT_PUBLIC_*` build-time flags (default TTS provider/model, word highlighting, audiobook export, etc.). +- **Site features** — runtime overrides for what were previously `NEXT_PUBLIC_*` build-time flags (including account signup availability, default TTS provider/model, word highlighting, audiobook export, etc.). Admin assignment is reconciled on every session resolution, so removing an email from `ADMIN_EMAILS` demotes the user on next login without a restart. See [Admin Panel](./admin-panel) for the full reference. diff --git a/docs-site/docs/deploy/vercel-deployment.md b/docs-site/docs/deploy/vercel-deployment.md index a32c0e3..88adbee 100644 --- a/docs-site/docs/deploy/vercel-deployment.md +++ b/docs-site/docs/deploy/vercel-deployment.md @@ -53,6 +53,7 @@ After the first successful deploy and admin login, open **Settings → Admin** a - `enableDocxConversion=false` on Vercel (`soffice` unavailable). - `enableDestructiveDeleteActions=false` for safer public deployments. - `enableTtsProvidersTab=false` if you want shared-provider-only UX. + - `enableUserSignups=true` unless you explicitly want an invite-only deployment. - `restrictUserApiKeys=true` to block user BYOK through the hosted server. - `defaultTtsProvider=replicate` (or your preferred shared slug). - `showAllProviderModels=false` if you want users locked to each provider's default model. diff --git a/docs-site/docs/reference/environment-variables.md b/docs-site/docs/reference/environment-variables.md index d2414de..ef79788 100644 --- a/docs-site/docs/reference/environment-variables.md +++ b/docs-site/docs/reference/environment-variables.md @@ -18,6 +18,7 @@ For auth-enabled deployments, use **Settings → Admin** as the primary source o | `API_KEY` | Legacy bootstrap seed | none | Optional first-boot seed into `default-openai`; then manage in Settings → Admin → Shared providers | | `NEXT_PUBLIC_*` runtime seeds | Legacy bootstrap seed | varies | Optional first-boot seeds for site features; then manage in Settings → Admin → Site features | | `NEXT_PUBLIC_CHANGELOG_FEED_URL` | Legacy bootstrap seed | `https://docs.openreader.richardr.dev/changelog/manifest.json` | Optional first-boot seed for changelog feed URL; then manage in Settings → Admin → Site features | +| `NEXT_PUBLIC_ENABLE_USER_SIGNUPS` | Legacy bootstrap seed | `true` | Optional first-boot seed for whether new accounts can be created; then manage in Settings → Admin → Site features | | `TTS_CACHE_MAX_SIZE_BYTES` | TTS caching | `268435456` (256 MB) | Tune in-memory TTS cache size | | `TTS_CACHE_TTL_MS` | TTS caching | `1800000` (30 min) | Tune in-memory TTS cache TTL | | `TTS_MAX_RETRIES` | TTS retry | `2` | Tune retry attempts for upstream 429/5xx | @@ -387,6 +388,15 @@ Controls whether the **TTS Provider** section appears in the user-facing Setting - Set `false` to hide provider/model/API controls in the per-user Settings modal (the admin panel is unaffected). - Runtime key: `enableTtsProvidersTab` +### NEXT_PUBLIC_ENABLE_USER_SIGNUPS + +Controls whether new user accounts can be created. + +- Default: `true` (enabled) +- When `false`, new account creation is blocked for email sign-up, first-time OAuth signup, and anonymous-to-account upgrades. +- Existing users can still sign in. +- Runtime key: `enableUserSignups` + ### NEXT_PUBLIC_RESTRICT_USER_API_KEYS Controls whether users can supply personal API keys/base URLs for built-in providers. diff --git a/src/app/(app)/signin/page.tsx b/src/app/(app)/signin/page.tsx index 4a26650..01aff67 100644 --- a/src/app/(app)/signin/page.tsx +++ b/src/app/(app)/signin/page.tsx @@ -6,6 +6,7 @@ import { useRouter, useSearchParams } from 'next/navigation'; import Link from 'next/link'; import { getAuthClient } from '@/lib/client/auth-client'; import { useAuthConfig, useAuthRateLimit } from '@/contexts/AuthRateLimitContext'; +import { useFeatureFlag } from '@/contexts/RuntimeConfigContext'; import { showPrivacyModal } from '@/components/PrivacyModal'; import { GithubIcon } from '@/components/icons/Icons'; import { LoadingSpinner } from '@/components/Spinner'; @@ -31,6 +32,7 @@ function SignInContent() { const [sessionExpired, setSessionExpired] = useState(false); const [error, setError] = useState(null); const { authEnabled, baseUrl, allowAnonymousAuthSessions, githubAuthEnabled } = useAuthConfig(); + const enableUserSignups = useFeatureFlag('enableUserSignups'); const { refresh: refreshRateLimit } = useAuthRateLimit(); const isAnyLoading = loadingEmail || loadingGithub || loadingAnonymous; @@ -240,12 +242,14 @@ function SignInContent() { {/* Footer */}
-

- Don't have an account?{' '} - - Sign up - -

+ {enableUserSignups && ( +

+ Don't have an account?{' '} + + Sign up + +

+ )}

By signing in, you agree to our{' '}