refactor(auth): remove redundant authEnabled flag from contexts and components
Eliminate the unused authEnabled property from context providers, hooks, components, and API responses. All logic and UI now assume authentication is required, simplifying prop signatures and reducing branching. Update related types, context values, and function calls to reflect this change. This streamlines the authentication flow and removes unnecessary configuration.
This commit is contained in:
parent
936aa50f9a
commit
eebb54b018
14 changed files with 36 additions and 64 deletions
|
|
@ -18,7 +18,6 @@ import { EpubRenderedLocationCloneManager } from '@/lib/client/epub/rendered-loc
|
|||
import { canonicalizeEpubSegmentAgainstSpineText } from '@/lib/client/epub/canonicalize-epub-segment';
|
||||
import { buildEpubLocator, getSpineItemPlainText } from '@/lib/client/epub/spine-coordinates';
|
||||
import { useTTS, type EpubLocatorResolver } from '@/contexts/TTSContext';
|
||||
import { useAuthConfig } from '@/contexts/AuthRateLimitContext';
|
||||
import { createRangeCfi } from '@/lib/client/epub';
|
||||
import { normalizeTtsLocationKey } from '@/lib/shared/tts-locator';
|
||||
import { useConfig } from '@/contexts/ConfigContext';
|
||||
|
|
@ -94,7 +93,6 @@ export interface EpubDocumentState {
|
|||
*/
|
||||
export function useEpubDocument(documentId?: string): EpubDocumentState {
|
||||
const { setText: setTTSText, currDocPage, currDocPages, setCurrDocPages, stop, skipToLocation, setIsEPUB } = useTTS();
|
||||
const { authEnabled } = useAuthConfig();
|
||||
// Configuration context to get TTS settings
|
||||
const {
|
||||
apiKey,
|
||||
|
|
@ -372,7 +370,6 @@ export function useEpubDocument(documentId?: string): EpubDocumentState {
|
|||
|
||||
const handleLocationChanged = useEPUBLocationController({
|
||||
documentId,
|
||||
authEnabled,
|
||||
isEpubSetOnceRef: isEPUBSetOnce,
|
||||
shouldPauseRef,
|
||||
setIsEpub: setIsEPUB,
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ export default function AppLayout({ children }: { children: ReactNode }) {
|
|||
|
||||
return (
|
||||
<Providers
|
||||
authEnabled
|
||||
authBaseUrl={authBaseUrl}
|
||||
allowAnonymousAuthSessions={allowAnonymousAuthSessions}
|
||||
githubAuthEnabled={githubAuthEnabled}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ function SignInContent() {
|
|||
const [rememberMe, setRememberMe] = useState(true);
|
||||
const [sessionExpired, setSessionExpired] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const { authEnabled, baseUrl, allowAnonymousAuthSessions, githubAuthEnabled } = useAuthConfig();
|
||||
const { baseUrl, allowAnonymousAuthSessions, githubAuthEnabled } = useAuthConfig();
|
||||
const enableUserSignups = useFeatureFlag('enableUserSignups');
|
||||
const { refresh: refreshRateLimit } = useAuthRateLimit();
|
||||
|
||||
|
|
@ -242,7 +242,7 @@ function SignInContent() {
|
|||
<p className="text-xs text-muted">
|
||||
By signing in, you agree to our{' '}
|
||||
<button
|
||||
onClick={() => showPrivacyModal({ authEnabled })}
|
||||
onClick={() => showPrivacyModal()}
|
||||
className="underline hover:text-foreground"
|
||||
>
|
||||
Privacy Policy
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export default function SignUpPage() {
|
|||
const [showPassword, setShowPassword] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const { authEnabled, baseUrl } = useAuthConfig();
|
||||
const { baseUrl } = useAuthConfig();
|
||||
const enableUserSignups = useFeatureFlag('enableUserSignups');
|
||||
const { refresh: refreshRateLimit } = useAuthRateLimit();
|
||||
|
||||
|
|
@ -251,7 +251,7 @@ export default function SignUpPage() {
|
|||
<p className="text-xs text-muted">
|
||||
By creating an account, you agree to our{' '}
|
||||
<button
|
||||
onClick={() => showPrivacyModal({ authEnabled })}
|
||||
onClick={() => showPrivacyModal()}
|
||||
className="underline hover:text-foreground"
|
||||
>
|
||||
Privacy Policy
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ export async function GET(req: NextRequest) {
|
|||
remainingChars: ttsRateLimitEnabled ? limits.anonymous : Number.MAX_SAFE_INTEGER,
|
||||
resetTimeMs,
|
||||
userType: 'unauthenticated',
|
||||
authEnabled: true
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -72,7 +71,6 @@ export async function GET(req: NextRequest) {
|
|||
remainingChars: result.remainingChars,
|
||||
resetTimeMs: result.resetTimeMs,
|
||||
userType: isAnonymous ? 'anonymous' : 'authenticated',
|
||||
authEnabled: true
|
||||
});
|
||||
|
||||
if (device?.didCreate) {
|
||||
|
|
|
|||
|
|
@ -10,13 +10,12 @@ import { AuthLoader } from '@/components/auth/AuthLoader';
|
|||
|
||||
interface ProvidersProps {
|
||||
children: ReactNode;
|
||||
authEnabled: boolean;
|
||||
authBaseUrl: string | null;
|
||||
allowAnonymousAuthSessions: boolean;
|
||||
githubAuthEnabled: boolean;
|
||||
}
|
||||
|
||||
export function Providers({ children, authEnabled, authBaseUrl, allowAnonymousAuthSessions, githubAuthEnabled }: ProvidersProps) {
|
||||
export function Providers({ children, authBaseUrl, allowAnonymousAuthSessions, githubAuthEnabled }: ProvidersProps) {
|
||||
const [queryClient] = useState(() => new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
|
|
@ -30,7 +29,6 @@ export function Providers({ children, authEnabled, authBaseUrl, allowAnonymousAu
|
|||
<QueryClientProvider client={queryClient}>
|
||||
<RuntimeConfigProvider>
|
||||
<AuthRateLimitProvider
|
||||
authEnabled={authEnabled}
|
||||
authBaseUrl={authBaseUrl}
|
||||
allowAnonymousAuthSessions={allowAnonymousAuthSessions}
|
||||
githubAuthEnabled={githubAuthEnabled}
|
||||
|
|
|
|||
|
|
@ -150,15 +150,13 @@ export function PrivacyModal({ isOpen, onAccept, onDismiss }: PrivacyModalProps)
|
|||
* Function to programmatically show the privacy popup
|
||||
* This can be called from signin/signup components
|
||||
*/
|
||||
export function showPrivacyModal(options?: { authEnabled?: boolean }): void {
|
||||
export function showPrivacyModal(): void {
|
||||
// Create a temporary container for the popup
|
||||
const container = document.createElement('div');
|
||||
container.id = 'privacy-modal-container';
|
||||
document.body.appendChild(container);
|
||||
|
||||
const origin = typeof window !== 'undefined' ? window.location.origin : '';
|
||||
void options;
|
||||
|
||||
// Import React and render the popup
|
||||
import('react-dom/client').then(({ createRoot }) => {
|
||||
import('react').then((React) => {
|
||||
|
|
|
|||
|
|
@ -556,7 +556,7 @@ export function SettingsModal({
|
|||
</div>
|
||||
<div className="flex items-center">
|
||||
<Button
|
||||
onClick={() => showPrivacyModal({ authEnabled: true })}
|
||||
onClick={() => showPrivacyModal()}
|
||||
className="text-sm font-medium text-muted hover:text-accent transition-colors"
|
||||
>
|
||||
Privacy
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ function isRateLimited(info: ErrorInfo | null): boolean {
|
|||
}
|
||||
|
||||
export function AuthLoader({ children }: { children: ReactNode }) {
|
||||
const { authEnabled, baseUrl, allowAnonymousAuthSessions } = useAuthConfig();
|
||||
const { baseUrl, allowAnonymousAuthSessions } = useAuthConfig();
|
||||
const { refresh: refreshRateLimit } = useAuthRateLimit();
|
||||
const { data: session, isPending, error: sessionError, refetch: refetchSession } = useAuthSession();
|
||||
const router = useRouter();
|
||||
|
|
@ -109,7 +109,7 @@ export function AuthLoader({ children }: { children: ReactNode }) {
|
|||
attemptedForNullSessionRef.current = false;
|
||||
setBootstrapError(null);
|
||||
setIsRedirecting(false);
|
||||
}, [authEnabled, baseUrl, allowAnonymousAuthSessions, pathname]);
|
||||
}, [baseUrl, allowAnonymousAuthSessions, pathname]);
|
||||
|
||||
useEffect(() => {
|
||||
const checkStatus = async () => {
|
||||
|
|
@ -224,7 +224,6 @@ export function AuthLoader({ children }: { children: ReactNode }) {
|
|||
}, [
|
||||
session,
|
||||
isPending,
|
||||
authEnabled,
|
||||
baseUrl,
|
||||
allowAnonymousAuthSessions,
|
||||
refreshRateLimit,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export function RateLimitBanner({ className = '' }: RateLimitBannerProps) {
|
|||
const { status, isAtLimit, timeUntilReset } = useAuthRateLimit();
|
||||
const enableUserSignups = useFeatureFlag('enableUserSignups');
|
||||
|
||||
if (!status?.authEnabled || !isAtLimit) {
|
||||
if (!status || !isAtLimit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ export function RateLimitBanner({ className = '' }: RateLimitBannerProps) {
|
|||
export function RateLimitIndicator({ className = '' }: RateLimitBannerProps) {
|
||||
const { status, isAtLimit } = useAuthRateLimit();
|
||||
|
||||
if (!status?.authEnabled) {
|
||||
if (!status) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,12 +11,10 @@ export interface RateLimitStatus {
|
|||
remainingChars: number;
|
||||
resetTimeMs: number;
|
||||
userType: 'anonymous' | 'authenticated' | 'unauthenticated';
|
||||
authEnabled: boolean;
|
||||
}
|
||||
|
||||
interface AuthRateLimitContextType {
|
||||
// Auth Config
|
||||
authEnabled: boolean;
|
||||
authBaseUrl: string | null;
|
||||
allowAnonymousAuthSessions: boolean;
|
||||
githubAuthEnabled: boolean;
|
||||
|
|
@ -45,8 +43,8 @@ export function useAuthRateLimit(): AuthRateLimitContextType {
|
|||
}
|
||||
|
||||
export function useAuthConfig() {
|
||||
const { authEnabled, authBaseUrl, allowAnonymousAuthSessions, githubAuthEnabled } = useAuthRateLimit();
|
||||
return { authEnabled, baseUrl: authBaseUrl, allowAnonymousAuthSessions, githubAuthEnabled };
|
||||
const { authBaseUrl, allowAnonymousAuthSessions, githubAuthEnabled } = useAuthRateLimit();
|
||||
return { baseUrl: authBaseUrl, allowAnonymousAuthSessions, githubAuthEnabled };
|
||||
}
|
||||
|
||||
export function useRateLimit() {
|
||||
|
|
@ -87,7 +85,6 @@ function parseRateLimitStatus(raw: unknown): RateLimitStatus | null {
|
|||
remainingChars: Number(data.remainingChars ?? 0),
|
||||
resetTimeMs: coerceTimestampMs(data.resetTimeMs ?? data.resetTime, nextUtcMidnightTimestampMs()),
|
||||
userType,
|
||||
authEnabled: Boolean(data.authEnabled),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -105,7 +102,6 @@ export function formatCharCount(count: number): string {
|
|||
|
||||
interface AuthRateLimitProviderProps {
|
||||
children: ReactNode;
|
||||
authEnabled: boolean;
|
||||
authBaseUrl: string | null;
|
||||
allowAnonymousAuthSessions: boolean;
|
||||
githubAuthEnabled: boolean;
|
||||
|
|
@ -115,7 +111,6 @@ const RATE_LIMIT_QUERY_KEY = ['rate-limit-status'] as const;
|
|||
|
||||
export function AuthRateLimitProvider({
|
||||
children,
|
||||
authEnabled,
|
||||
authBaseUrl,
|
||||
allowAnonymousAuthSessions,
|
||||
githubAuthEnabled,
|
||||
|
|
@ -210,7 +205,6 @@ export function AuthRateLimitProvider({
|
|||
}, []);
|
||||
|
||||
const contextValue: AuthRateLimitContextType = {
|
||||
authEnabled,
|
||||
authBaseUrl,
|
||||
allowAnonymousAuthSessions,
|
||||
githubAuthEnabled,
|
||||
|
|
|
|||
|
|
@ -406,7 +406,6 @@ export function TTSProvider({ children }: { children: ReactNode }): ReactElement
|
|||
configTTSModel,
|
||||
);
|
||||
const {
|
||||
authEnabled,
|
||||
onTTSStart,
|
||||
onTTSComplete,
|
||||
refresh: refreshRateLimit,
|
||||
|
|
@ -3229,19 +3228,17 @@ export function TTSProvider({ children }: { children: ReactNode }): ReactElement
|
|||
};
|
||||
|
||||
const load = async () => {
|
||||
if (authEnabled) {
|
||||
try {
|
||||
const remote = await getDocumentProgress(docId);
|
||||
if (!cancelled && remote?.location) {
|
||||
await setLastDocumentLocation(docId, remote.location).catch((error) => {
|
||||
console.warn('Error caching remote location locally:', error);
|
||||
});
|
||||
applyLocation(remote.location);
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Error loading remote progress:', error);
|
||||
try {
|
||||
const remote = await getDocumentProgress(docId);
|
||||
if (!cancelled && remote?.location) {
|
||||
await setLastDocumentLocation(docId, remote.location).catch((error) => {
|
||||
console.warn('Error caching remote location locally:', error);
|
||||
});
|
||||
applyLocation(remote.location);
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Error loading remote progress:', error);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -3259,7 +3256,7 @@ export function TTSProvider({ children }: { children: ReactNode }): ReactElement
|
|||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [id, isEPUB, currentReaderType, authEnabled]);
|
||||
}, [id, isEPUB, currentReaderType]);
|
||||
|
||||
// Save current position periodically for non-EPUB readers.
|
||||
useEffect(() => {
|
||||
|
|
@ -3271,18 +3268,16 @@ export function TTSProvider({ children }: { children: ReactNode }): ReactElement
|
|||
setLastDocumentLocation(id as string, location).catch(error => {
|
||||
console.warn('Error saving non-EPUB location:', error);
|
||||
});
|
||||
if (authEnabled) {
|
||||
scheduleDocumentProgressSync({
|
||||
documentId: id as string,
|
||||
readerType: currentReaderType,
|
||||
location,
|
||||
});
|
||||
}
|
||||
scheduleDocumentProgressSync({
|
||||
documentId: id as string,
|
||||
readerType: currentReaderType,
|
||||
location,
|
||||
});
|
||||
}, 1000); // Debounce saves by 1 second
|
||||
|
||||
return () => clearTimeout(timeoutId);
|
||||
}
|
||||
}, [id, isEPUB, currDocPage, currDocPageNumber, currentIndex, sentences.length, currentReaderType, authEnabled]);
|
||||
}, [id, isEPUB, currDocPage, currDocPageNumber, currentIndex, sentences.length, currentReaderType]);
|
||||
|
||||
/**
|
||||
* Renders the TTS context provider with its children
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ export function shouldPersistEpubLocation(
|
|||
|
||||
type UseEpubLocationControllerParams = {
|
||||
documentId?: string;
|
||||
authEnabled: boolean;
|
||||
isEpubSetOnceRef: MutableRefObject<boolean>;
|
||||
shouldPauseRef: MutableRefObject<boolean>;
|
||||
setIsEpub: (isEpub: boolean) => void;
|
||||
|
|
@ -46,7 +45,6 @@ type UseEpubLocationControllerParams = {
|
|||
|
||||
export function useEPUBLocationController({
|
||||
documentId,
|
||||
authEnabled,
|
||||
isEpubSetOnceRef,
|
||||
shouldPauseRef,
|
||||
setIsEpub,
|
||||
|
|
@ -138,13 +136,11 @@ export function useEPUBLocationController({
|
|||
// Save the location to IndexedDB if not initial
|
||||
if (shouldPersistEpubLocation(documentId, locationRef.current)) {
|
||||
setLastDocumentLocation(documentId, location.toString());
|
||||
if (authEnabled) {
|
||||
scheduleDocumentProgressSync({
|
||||
documentId,
|
||||
readerType: 'epub',
|
||||
location: location.toString(),
|
||||
});
|
||||
}
|
||||
scheduleDocumentProgressSync({
|
||||
documentId,
|
||||
readerType: 'epub',
|
||||
location: location.toString(),
|
||||
});
|
||||
}
|
||||
|
||||
skipToLocation(location);
|
||||
|
|
@ -155,7 +151,6 @@ export function useEPUBLocationController({
|
|||
shouldPauseRef.current = true;
|
||||
}
|
||||
}, [
|
||||
authEnabled,
|
||||
bookRef,
|
||||
documentId,
|
||||
extractPageText,
|
||||
|
|
|
|||
|
|
@ -320,7 +320,6 @@ export type User = AuthSessionUser & {
|
|||
};
|
||||
|
||||
export type AuthContext = {
|
||||
authEnabled: true;
|
||||
session: Session | null;
|
||||
user: User | null;
|
||||
userId: string | null;
|
||||
|
|
@ -342,7 +341,7 @@ export async function getAuthContext(request: Pick<NextRequest, 'headers'>): Pro
|
|||
}
|
||||
}
|
||||
|
||||
return { authEnabled: true, session, user, userId };
|
||||
return { session, user, userId };
|
||||
}
|
||||
|
||||
export async function requireAuthContext(
|
||||
|
|
|
|||
Loading…
Reference in a new issue