From 2d4633d298edb1fcc6847818e38982b89f524119 Mon Sep 17 00:00:00 2001 From: Debanjum Date: Sun, 19 Jan 2025 13:05:15 +0700 Subject: [PATCH] Use encoded email, otp in login URL in email & web app sign-in flow Previously emails with url special characters would not get successfully identified for login. Account creation was fine due to email being in POST request body. But login with such emails did not work due to query params not being escaped before being sent to server This change escapes both the code and email in login URL sent to server. So login with emails containing special characters like `email+khoj@gmail.com' works. It fixes both the URL web app sent by web app directly and the magic link sent to users to their email This change also fixes accessibility issue of having a DialogTitle in DialogContent for screen readers. Resolves #1090 --- .../web/app/components/loginPrompt/loginPrompt.tsx | 8 ++++++-- src/khoj/database/admin.py | 6 ++++-- src/khoj/routers/email.py | 3 ++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/interface/web/app/components/loginPrompt/loginPrompt.tsx b/src/interface/web/app/components/loginPrompt/loginPrompt.tsx index 5cda444a..633d7b41 100644 --- a/src/interface/web/app/components/loginPrompt/loginPrompt.tsx +++ b/src/interface/web/app/components/loginPrompt/loginPrompt.tsx @@ -2,7 +2,7 @@ import styles from "./loginPrompt.module.css"; import { Button } from "@/components/ui/button"; -import { Dialog, DialogContent } from "@/components/ui/dialog"; +import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import Autoplay from "embla-carousel-autoplay"; import { @@ -27,6 +27,7 @@ import { } from "@/components/ui/carousel"; import { Card, CardContent } from "@/components/ui/card"; import { InputOTP, InputOTPGroup, InputOTPSlot } from "@/components/ui/input-otp"; +import * as VisuallyHidden from "@radix-ui/react-visually-hidden"; export interface LoginPromptProps { onOpenChange: (open: boolean) => void; @@ -181,6 +182,9 @@ export default function LoginPrompt(props: LoginPromptProps) { + + Login Dialog +
{useEmailSignIn ? ( = ALLOWED_OTP_ATTEMPTS) { setOTPError("Too many failed attempts. Please try again tomorrow."); diff --git a/src/khoj/database/admin.py b/src/khoj/database/admin.py index a90a339e..322b3afd 100644 --- a/src/khoj/database/admin.py +++ b/src/khoj/database/admin.py @@ -1,6 +1,7 @@ import csv import json from datetime import datetime, timedelta +from urllib.parse import quote from apscheduler.job import Job from django.contrib import admin, messages @@ -154,8 +155,9 @@ class KhojUserAdmin(UserAdmin, unfold_admin.ModelAdmin): for user in queryset: if user.email: host = request.get_host() - unique_id = user.email_verification_code - login_url = f"{host}/auth/magic?code={unique_id}&email={user.email}" + otp = quote(user.email_verification_code) + encoded_email = quote(user.email) + login_url = f"{host}/auth/magic?code={otp}&email={encoded_email}" messages.info(request, f"Email login URL for {user.email}: {login_url}") get_email_login_url.short_description = "Get email login URL" # type: ignore diff --git a/src/khoj/routers/email.py b/src/khoj/routers/email.py index 701db0a6..ce9e0ae6 100644 --- a/src/khoj/routers/email.py +++ b/src/khoj/routers/email.py @@ -1,5 +1,6 @@ import logging import os +from urllib.parse import quote import markdown_it import resend @@ -29,7 +30,7 @@ def is_resend_enabled(): async def send_magic_link_email(email, unique_id, host): - sign_in_link = f"{host}auth/magic?code={unique_id}&email={email}" + sign_in_link = f"{host}auth/magic?code={quote(unique_id)}&email={quote(email)}" if not is_resend_enabled(): logger.debug(f"Email sending disabled. Share this sign-in link with the user: {sign_in_link}")