Refactor layout and home page for improved localization and session handling

- Updated RootLayout to include locale support and integrated ThemeProvider and LocaleProvider for better internationalization.
- Replaced static home page content with a redirect based on user session status, enhancing user experience by directing to the appropriate dashboard or login page.
- Switched font from Geist to Inter for improved typography consistency.
This commit is contained in:
smueller
2026-07-22 14:01:09 +02:00
parent 04e04eb11d
commit 84476e6277
30 changed files with 1073 additions and 128 deletions

View File

@@ -0,0 +1,60 @@
import type { SessionUser } from '@nexumi/shared';
import { type NextRequest, NextResponse } from 'next/server';
import { exchangeCodeForToken, fetchDiscordUser } from '@/lib/discord-oauth';
import { env } from '@/lib/env';
import { redis } from '@/lib/redis';
import { createSession } from '@/lib/session';
function oauthStateKey(state: string): string {
return `webui:oauth:state:${state}`;
}
function loginRedirect(error: string): NextResponse {
const url = new URL('/login', env.WEBUI_URL);
url.searchParams.set('error', error);
return NextResponse.redirect(url);
}
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const code = searchParams.get('code');
const state = searchParams.get('state');
const oauthError = searchParams.get('error');
if (oauthError) {
return loginRedirect('access_denied');
}
if (!code || !state) {
return loginRedirect('invalid_request');
}
const stateKey = oauthStateKey(state);
const stateExists = await redis.get(stateKey);
if (!stateExists) {
return loginRedirect('invalid_state');
}
await redis.del(stateKey);
try {
const token = await exchangeCodeForToken(code);
const discordUser = await fetchDiscordUser(token.access_token);
const user: SessionUser = {
id: discordUser.id,
username: discordUser.username,
globalName: discordUser.global_name ?? null,
avatar: discordUser.avatar ?? null
};
await createSession({
user,
accessToken: token.access_token,
tokenExpiresAt: Date.now() + token.expires_in * 1000
});
} catch {
return loginRedirect('oauth_failed');
}
return NextResponse.redirect(new URL('/dashboard', env.WEBUI_URL));
}