Skip to content

Commit e670785

Browse files
Fix: Implement email masking functionality for privacy in ForgotInfo component
1 parent b588c0b commit e670785

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

src/frontend/pages/ForgotInfo.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Card } from '../components/Card';
44
import { Select } from '../components/Select';
55
import { Input } from '../components/Input';
66
import { Button } from '../components/Button';
7+
import { maskEmail } from '../utils/auth';
78

89
interface ForgotInfoProps {
910
onNavigate: (page: string) => void;
@@ -15,6 +16,7 @@ export function ForgotInfo({ onNavigate }: ForgotInfoProps) {
1516
const [isLoading, setIsLoading] = useState(false);
1617
const [success, setSuccess] = useState(false);
1718
const [error, setError] = useState('');
19+
const [submittedEmail, setSubmittedEmail] = useState('');
1820

1921
const typeOptions = [
2022
{ value: 'email', label: 'البريد الإلكتروني' },
@@ -27,6 +29,7 @@ export function ForgotInfo({ onNavigate }: ForgotInfoProps) {
2729
setIsLoading(true);
2830
setError('');
2931
setSuccess(false);
32+
setSubmittedEmail('');
3033

3134
try {
3235
const response = await fetch('/api/auth/forgot-password', {
@@ -43,6 +46,10 @@ export function ForgotInfo({ onNavigate }: ForgotInfoProps) {
4346
const data = await response.json();
4447

4548
if (data.success) {
49+
// Store the email for masking in success message if type is email
50+
if (type === 'email') {
51+
setSubmittedEmail(value);
52+
}
4653
setSuccess(true);
4754
} else {
4855
setError(data.error || 'Request failed');
@@ -87,7 +94,15 @@ export function ForgotInfo({ onNavigate }: ForgotInfoProps) {
8794
<div className="mb-4 p-4 bg-green-100 border border-green-400 text-green-700 rounded">
8895
<h3 className="font-medium mb-2">تم إرسال الطلب</h3>
8996
<p className="text-sm">
90-
إذا كانت المعلومات المقدمة صحيحة، سيتم إرسال تفاصيل العضوية إلى عنوان بريدك الإلكتروني.
97+
إذا كانت المعلومات المقدمة صحيحة، سيتم إرسال تفاصيل العضوية إلى عنوان بريدك الإلكتروني
98+
{submittedEmail && (
99+
<>
100+
<br />
101+
<span className="font-mono text-xs mt-1 block">
102+
{maskEmail(submittedEmail)}
103+
</span>
104+
</>
105+
)}
91106
</p>
92107
</div>
93108

src/frontend/utils/auth.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,24 @@ export function getMemberInfo(): any {
5050
const state = loadAuthState();
5151
return state?.memberInfo || null;
5252
}
53+
54+
/**
55+
* Masks an email address for privacy while keeping it recognizable
56+
* Example: john.doe@gmail.com -> joh****oe@gmail.com
57+
*/
58+
export function maskEmail(email: string): string {
59+
if (!email || !email.includes('@')) {
60+
return email;
61+
}
62+
63+
const [localPart, domain] = email.split('@');
64+
65+
if (localPart.length <= 3) {
66+
// For very short emails, show first and last character
67+
return `${localPart[0]}****${localPart[localPart.length - 1]}@${domain}`;
68+
}
69+
70+
// For longer emails, show first 3 and last 2 characters
71+
const maskedLocal = `${localPart.slice(0, 3)}****${localPart.slice(-2)}`;
72+
return `${maskedLocal}@${domain}`;
73+
}

0 commit comments

Comments
 (0)