mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-04-07 00:15:23 +02:00
Merge 301be20806 into 8ed0bcf5ca
This commit is contained in:
commit
39d7bbc02e
5 changed files with 88 additions and 20 deletions
|
|
@ -6,6 +6,7 @@ import SocialLoginRender from './SocialLoginRender';
|
|||
import { BlinkAnimation } from './BlinkAnimation';
|
||||
import { Banner } from '../Banners';
|
||||
import Footer from './Footer';
|
||||
import MarkdownLite from '~/components/Chat/Messages/Content/MarkdownLite';
|
||||
|
||||
function AuthLayout({
|
||||
children,
|
||||
|
|
@ -55,19 +56,61 @@ function AuthLayout({
|
|||
}
|
||||
return null;
|
||||
};
|
||||
const logoUrl = startupConfig?.interface?.loginImageUrl;
|
||||
const logoText = startupConfig?.interface?.loginText;
|
||||
|
||||
return (
|
||||
<div className="relative flex min-h-screen flex-col bg-white dark:bg-gray-900">
|
||||
<Banner />
|
||||
<BlinkAnimation active={isFetching}>
|
||||
<div className="mt-6 h-10 w-full bg-cover">
|
||||
<img
|
||||
src="assets/logo.svg"
|
||||
className="h-full w-full object-contain"
|
||||
alt={localize('com_ui_logo', { 0: startupConfig?.appTitle ?? 'LibreChat' })}
|
||||
/>
|
||||
</div>
|
||||
{logoUrl ? (
|
||||
<div className="mt-6 flex w-full justify-center">
|
||||
<img
|
||||
src={logoUrl}
|
||||
className="max-h-64 w-auto object-contain"
|
||||
alt={localize('com_ui_logo', { 0: startupConfig?.appTitle ?? 'LibreChat' })}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="mt-6 flex w-full justify-center">
|
||||
<img
|
||||
src="assets/logo.svg"
|
||||
className="max-h-10 w-auto object-contain"
|
||||
alt={localize('com_ui_logo', { 0: startupConfig?.appTitle ?? 'LibreChat' })}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</BlinkAnimation>
|
||||
|
||||
{/* Welcome back header and login buttons below logo */}
|
||||
{!hasStartupConfigError && !isFetching && header && (
|
||||
<div className="mt-6 text-center">
|
||||
<h1
|
||||
className="mb-4 text-3xl font-semibold text-black dark:text-white"
|
||||
style={{ userSelect: 'none' }}
|
||||
>
|
||||
{header}
|
||||
</h1>
|
||||
{!pathname.includes('2fa') &&
|
||||
(pathname.includes('login') || pathname.includes('register')) && (
|
||||
<div className="mx-auto max-w-md">
|
||||
<SocialLoginRender startupConfig={startupConfig} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* ——— WELCOME SECTIONS ——— */}
|
||||
{logoText && (
|
||||
<section className="mx-auto w-full max-w-2xl space-y-8 p-6 text-black dark:text-white">
|
||||
<div>
|
||||
<div className="prose dark:prose-invert w-full max-w-none !text-text-primary">
|
||||
<MarkdownLite content={logoText} />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
{/* — end welcome sections — */}
|
||||
<DisplayError />
|
||||
<div className="absolute bottom-0 left-0 md:m-4">
|
||||
<ThemeSelector />
|
||||
|
|
@ -75,19 +118,7 @@ function AuthLayout({
|
|||
|
||||
<main className="flex flex-grow items-center justify-center">
|
||||
<div className="w-authPageWidth overflow-hidden bg-white px-6 py-4 dark:bg-gray-900 sm:max-w-md sm:rounded-lg">
|
||||
{!hasStartupConfigError && !isFetching && header && (
|
||||
<h1
|
||||
className="mb-4 text-center text-3xl font-semibold text-black dark:text-white"
|
||||
style={{ userSelect: 'none' }}
|
||||
>
|
||||
{header}
|
||||
</h1>
|
||||
)}
|
||||
{children}
|
||||
{!pathname.includes('2fa') &&
|
||||
(pathname.includes('login') || pathname.includes('register')) && (
|
||||
<SocialLoginRender startupConfig={startupConfig} />
|
||||
)}
|
||||
</div>
|
||||
</main>
|
||||
<Footer startupConfig={startupConfig} />
|
||||
|
|
|
|||
|
|
@ -131,7 +131,10 @@ interface:
|
|||
|
||||
# Temporary chat retention period in hours (default: 720, min: 1, max: 8760)
|
||||
# temporaryChatRetention: 1
|
||||
|
||||
loginImageUrl: 'https://librechat.ai/assets/logo.png'
|
||||
loginText: |
|
||||
## Welcome to LibreChat! Your AI companion for seamless conversations.
|
||||
|
||||
# Example Cloudflare turnstile (optional)
|
||||
#turnstile:
|
||||
# siteKey: "your-site-key-here"
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { fileConfigSchema } from './file-config';
|
|||
import { apiBaseUrl } from './api-endpoints';
|
||||
import { FileSources } from './types/files';
|
||||
import { MCPServersSchema } from './mcp';
|
||||
import { isSafeImageUrl } from './utils';
|
||||
|
||||
export const defaultSocialLogins = ['google', 'facebook', 'openid', 'github', 'discord', 'saml'];
|
||||
|
||||
|
|
@ -689,6 +690,14 @@ export const interfaceSchema = z
|
|||
.optional(),
|
||||
termsOfService: termsOfServiceSchema.optional(),
|
||||
customWelcome: z.string().optional(),
|
||||
loginImageUrl: z
|
||||
.string()
|
||||
.url()
|
||||
.refine(isSafeImageUrl, {
|
||||
message: 'loginImageUrl must be a valid HTTP, HTTPS, or data:image URL',
|
||||
})
|
||||
.optional(),
|
||||
loginText: z.string().optional(),
|
||||
mcpServers: mcpServersSchema.optional(),
|
||||
modelSelect: z.boolean().optional(),
|
||||
parameters: z.boolean().optional(),
|
||||
|
|
|
|||
|
|
@ -83,3 +83,26 @@ export function extractEnvVariable(value: string) {
|
|||
export function normalizeEndpointName(name = ''): string {
|
||||
return name.toLowerCase() === 'ollama' ? 'ollama' : name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a URL uses only safe protocols (http, https, or data:image/*)
|
||||
* @param url - The URL string to validate
|
||||
* @returns true if the URL is safe, false otherwise
|
||||
*/
|
||||
export const isSafeImageUrl = (url: string): boolean => {
|
||||
try {
|
||||
const parsedUrl = new URL(url);
|
||||
if (parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (parsedUrl.protocol !== 'data:') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Restrict data URLs to image payloads only.
|
||||
return /^data:image\/[a-z0-9.+-]+(?:;[a-z0-9=._+-]+)*(?:;base64)?,/i.test(url);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ export async function loadDefaultInterface({
|
|||
termsOfService: interfaceConfig?.termsOfService ?? defaults.termsOfService,
|
||||
mcpServers: interfaceConfig?.mcpServers ?? defaults.mcpServers,
|
||||
customWelcome: interfaceConfig?.customWelcome ?? defaults.customWelcome,
|
||||
loginImageUrl: interfaceConfig?.loginImageUrl ?? defaults.loginImageUrl,
|
||||
loginText: interfaceConfig?.loginText ?? defaults.loginText,
|
||||
|
||||
// Permissions - only include if explicitly configured
|
||||
bookmarks: interfaceConfig?.bookmarks,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue