mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-19 09:50:15 +01:00
🔒 feat: Add Content Security Policy using Helmet middleware (#7377)
* 🔒 feat: Add Content Security Policy using Helmet middleware * 🔒 feat: Set trust proxy and refine Content Security Policy directives * 🎨 feat: add `copy-tex` to improve copying KaTeX (#7308) When selecting equations and using copy paste, uses the correct latex code. Co-authored-by: Ruben Talstra <RubenTalstra1211@outlook.com> * 🔃 refactor: `AgentFooter` to conditionally render buttons based on `activePanel` (#7306) * 🚀 feat: Add `Cloudflare Turnstile` support (#5987) * 🚀 feat: Add @marsidev/react-turnstile dependency to package.json and package-lock.json * 🚀 feat: Integrate Cloudflare Turnstile configuration support in AppService and add schema validation * 🚀 feat: Implemented Cloudflare Turnstile integration in Login and Registration forms * 🚀 feat: Enhance AppService tests with additional mocks and configuration setups * 🚀 feat: Comment out outdated config version warning tests in AppService.spec.js * 🚀 feat: Remove outdated warning tests and add new checks for environment variables and API health * 🔧 test: Update AppService.spec.js to use expect.anything() for paths validation * 🔧 test: Refactor AppService.spec.js to streamline mocks and enhance clarity * 🔧 chore: removed not needed test * Potential fix for code scanning alert no. 5638: Ensure code is properly formatted, use insertion, deletion, or replacement to obtain desired formatting. Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * Potential fix for code scanning alert no. 5629: Ensure code is properly formatted, use insertion, deletion, or replacement to obtain desired formatting. Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * Potential fix for code scanning alert no. 5642: Ensure code is properly formatted, use insertion, deletion, or replacement to obtain desired formatting. Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * Update turnstile.js * Potential fix for code scanning alert no. 5634: Ensure code is properly formatted, use insertion, deletion, or replacement to obtain desired formatting. Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * Potential fix for code scanning alert no. 5646: Ensure code is properly formatted, use insertion, deletion, or replacement to obtain desired formatting. Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * Potential fix for code scanning alert no. 5647: Ensure code is properly formatted, use insertion, deletion, or replacement to obtain desired formatting. Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --------- Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * 🔒 feat: Refactor Content Security Policy setup to use Helmet middleware with custom directives * 🔒 feat: Enhance Content Security Policy to include Sandpack Bundler URL * 🔒 feat: Update Content Security Policy and integrate Turnstile captcha support --------- Co-authored-by: andresgit <9771158+andresgit@users.noreply.github.com> Co-authored-by: matt burnett <mawburn@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
This commit is contained in:
parent
fe311df969
commit
7a91f6ca62
6 changed files with 93 additions and 60 deletions
|
|
@ -16,6 +16,7 @@ type TLoginFormProps = {
|
|||
const LoginForm: React.FC<TLoginFormProps> = ({ onSubmit, startupConfig, error, setError }) => {
|
||||
const localize = useLocalize();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
const {
|
||||
register,
|
||||
getValues,
|
||||
|
|
@ -28,6 +29,7 @@ const LoginForm: React.FC<TLoginFormProps> = ({ onSubmit, startupConfig, error,
|
|||
const { data: config } = useGetStartupConfig();
|
||||
const useUsernameLogin = config?.ldap?.username;
|
||||
const validTheme = theme === 'dark' ? 'dark' : 'light';
|
||||
const requireCaptcha = Boolean(startupConfig.turnstile?.siteKey);
|
||||
|
||||
useEffect(() => {
|
||||
if (error && error.includes('422') && !showResendLink) {
|
||||
|
|
@ -100,20 +102,12 @@ const LoginForm: React.FC<TLoginFormProps> = ({ onSubmit, startupConfig, error,
|
|||
},
|
||||
})}
|
||||
aria-invalid={!!errors.email}
|
||||
className="
|
||||
webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light
|
||||
bg-surface-primary px-3.5 pb-2.5 pt-3 text-text-primary duration-200 focus:border-green-500 focus:outline-none
|
||||
"
|
||||
className="peer w-full rounded-2xl border border-border-light bg-surface-primary px-3.5 pb-2.5 pt-3 text-text-primary transition-colors duration-200 focus:border-green-500 focus:outline-none"
|
||||
placeholder=" "
|
||||
/>
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="
|
||||
absolute start-3 top-1.5 z-10 origin-[0] -translate-y-4 scale-75 transform bg-surface-primary px-2 text-sm text-text-secondary-alt duration-200
|
||||
peer-placeholder-shown:top-1/2 peer-placeholder-shown:-translate-y-1/2 peer-placeholder-shown:scale-100
|
||||
peer-focus:top-1.5 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:px-2 peer-focus:text-green-600 dark:peer-focus:text-green-500
|
||||
rtl:peer-focus:left-auto rtl:peer-focus:translate-x-1/4
|
||||
"
|
||||
className="absolute start-3 top-1.5 z-10 origin-[0] -translate-y-4 scale-75 transform bg-surface-primary px-2 text-sm text-text-secondary-alt duration-200 peer-placeholder-shown:top-1/2 peer-placeholder-shown:-translate-y-1/2 peer-placeholder-shown:scale-100 peer-focus:top-1.5 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:px-2 peer-focus:text-green-600 dark:peer-focus:text-green-500"
|
||||
>
|
||||
{useUsernameLogin
|
||||
? localize('com_auth_username').replace(/ \(.*$/, '')
|
||||
|
|
@ -135,20 +129,12 @@ const LoginForm: React.FC<TLoginFormProps> = ({ onSubmit, startupConfig, error,
|
|||
maxLength: { value: 128, message: localize('com_auth_password_max_length') },
|
||||
})}
|
||||
aria-invalid={!!errors.password}
|
||||
className="
|
||||
webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light
|
||||
bg-surface-primary px-3.5 pb-2.5 pt-3 text-text-primary duration-200 focus:border-green-500 focus:outline-none
|
||||
"
|
||||
className="peer w-full rounded-2xl border border-border-light bg-surface-primary px-3.5 pb-2.5 pt-3 text-text-primary transition-colors duration-200 focus:border-green-500 focus:outline-none"
|
||||
placeholder=" "
|
||||
/>
|
||||
<label
|
||||
htmlFor="password"
|
||||
className="
|
||||
absolute start-3 top-1.5 z-10 origin-[0] -translate-y-4 scale-75 transform bg-surface-primary px-2 text-sm text-text-secondary-alt duration-200
|
||||
peer-placeholder-shown:top-1/2 peer-placeholder-shown:-translate-y-1/2 peer-placeholder-shown:scale-100
|
||||
peer-focus:top-1.5 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:px-2 peer-focus:text-green-600 dark:peer-focus:text-green-500
|
||||
rtl:peer-focus:left-auto rtl:peer-focus:translate-x-1/4
|
||||
"
|
||||
className="absolute start-3 top-1.5 z-10 origin-[0] -translate-y-4 scale-75 transform bg-surface-primary px-2 text-sm text-text-secondary-alt duration-200 peer-placeholder-shown:top-1/2 peer-placeholder-shown:-translate-y-1/2 peer-placeholder-shown:scale-100 peer-focus:top-1.5 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:px-2 peer-focus:text-green-600 dark:peer-focus:text-green-500"
|
||||
>
|
||||
{localize('com_auth_password')}
|
||||
</label>
|
||||
|
|
@ -164,16 +150,15 @@ const LoginForm: React.FC<TLoginFormProps> = ({ onSubmit, startupConfig, error,
|
|||
</a>
|
||||
)}
|
||||
|
||||
{/* Render Turnstile only if enabled in startupConfig */}
|
||||
{startupConfig.turnstile && (
|
||||
{requireCaptcha && (
|
||||
<div className="my-4 flex justify-center">
|
||||
<Turnstile
|
||||
siteKey={startupConfig.turnstile.siteKey}
|
||||
siteKey={startupConfig.turnstile!.siteKey}
|
||||
options={{
|
||||
...startupConfig.turnstile.options,
|
||||
...startupConfig.turnstile!.options,
|
||||
theme: validTheme,
|
||||
}}
|
||||
onSuccess={(token) => setTurnstileToken(token)}
|
||||
onSuccess={setTurnstileToken}
|
||||
onError={() => setTurnstileToken(null)}
|
||||
onExpire={() => setTurnstileToken(null)}
|
||||
/>
|
||||
|
|
@ -185,11 +170,8 @@ const LoginForm: React.FC<TLoginFormProps> = ({ onSubmit, startupConfig, error,
|
|||
aria-label={localize('com_auth_continue')}
|
||||
data-testid="login-button"
|
||||
type="submit"
|
||||
disabled={startupConfig.turnstile ? !turnstileToken : false}
|
||||
className="
|
||||
w-full rounded-2xl bg-green-600 px-4 py-3 text-sm font-medium text-white
|
||||
transition-colors hover:bg-green-700 dark:bg-green-600 dark:hover:bg-green-700
|
||||
"
|
||||
disabled={requireCaptcha && !turnstileToken}
|
||||
className="w-full rounded-2xl bg-green-600 px-4 py-3 text-sm font-medium text-white transition-colors hover:bg-green-700 disabled:opacity-50 disabled:hover:bg-green-600 dark:bg-green-600 dark:hover:bg-green-700"
|
||||
>
|
||||
{localize('com_auth_continue')}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@ const Registration: React.FC = () => {
|
|||
const token = queryParams.get('token');
|
||||
const validTheme = theme === 'dark' ? 'dark' : 'light';
|
||||
|
||||
// only require captcha if we have a siteKey
|
||||
const requireCaptcha = Boolean(startupConfig?.turnstile?.siteKey);
|
||||
|
||||
const registerUser = useRegisterUserMutation({
|
||||
onMutate: () => {
|
||||
setIsSubmitting(true);
|
||||
|
|
@ -73,21 +76,13 @@ const Registration: React.FC = () => {
|
|||
validation,
|
||||
)}
|
||||
aria-invalid={!!errors[id]}
|
||||
className="
|
||||
webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light
|
||||
bg-surface-primary px-3.5 pb-2.5 pt-3 text-text-primary duration-200 focus:border-green-500 focus:outline-none
|
||||
"
|
||||
className="webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light bg-surface-primary px-3.5 pb-2.5 pt-3 text-text-primary duration-200 focus:border-green-500 focus:outline-none"
|
||||
placeholder=" "
|
||||
data-testid={id}
|
||||
/>
|
||||
<label
|
||||
htmlFor={id}
|
||||
className="
|
||||
absolute start-3 top-1.5 z-10 origin-[0] -translate-y-4 scale-75 transform bg-surface-primary px-2 text-sm text-text-secondary-alt duration-200
|
||||
peer-placeholder-shown:top-1/2 peer-placeholder-shown:-translate-y-1/2 peer-placeholder-shown:scale-100
|
||||
peer-focus:top-1.5 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:px-2 peer-focus:text-green-500
|
||||
rtl:peer-focus:left-auto rtl:peer-focus:translate-x-1/4
|
||||
"
|
||||
className="absolute start-3 top-1.5 z-10 origin-[0] -translate-y-4 scale-75 transform bg-surface-primary px-2 text-sm text-text-secondary-alt duration-200 peer-placeholder-shown:top-1/2 peer-placeholder-shown:-translate-y-1/2 peer-placeholder-shown:scale-100 peer-focus:top-1.5 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:px-2 peer-focus:text-green-500 rtl:peer-focus:left-auto rtl:peer-focus:translate-x-1/4"
|
||||
>
|
||||
{localize(label)}
|
||||
</label>
|
||||
|
|
@ -183,8 +178,7 @@ const Registration: React.FC = () => {
|
|||
value === password || localize('com_auth_password_not_match'),
|
||||
})}
|
||||
|
||||
{/* Render Turnstile only if enabled in startupConfig */}
|
||||
{startupConfig?.turnstile && (
|
||||
{startupConfig?.turnstile?.siteKey && (
|
||||
<div className="my-4 flex justify-center">
|
||||
<Turnstile
|
||||
siteKey={startupConfig.turnstile.siteKey}
|
||||
|
|
@ -204,16 +198,11 @@ const Registration: React.FC = () => {
|
|||
disabled={
|
||||
Object.keys(errors).length > 0 ||
|
||||
isSubmitting ||
|
||||
(startupConfig?.turnstile ? !turnstileToken : false)
|
||||
(requireCaptcha && !turnstileToken)
|
||||
}
|
||||
type="submit"
|
||||
aria-label="Submit registration"
|
||||
className="
|
||||
w-full rounded-2xl bg-green-600 px-4 py-3 text-sm font-medium text-white
|
||||
transition-colors hover:bg-green-700 focus:outline-none focus:ring-2
|
||||
focus:ring-green-500 focus:ring-offset-2 disabled:opacity-50
|
||||
disabled:hover:bg-green-600 dark:bg-green-600 dark:hover:bg-green-700
|
||||
"
|
||||
className="w-full rounded-2xl bg-green-600 px-4 py-3 text-sm font-medium text-white transition-colors hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 disabled:opacity-50 disabled:hover:bg-green-600 dark:bg-green-600 dark:hover:bg-green-700"
|
||||
>
|
||||
{isSubmitting ? <Spinner /> : localize('com_auth_continue')}
|
||||
</button>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue