Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions Frontend/src/pages/AdminSignup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,20 @@ function AdminSignup() {
return null; // valid
};

const validateFullName = (name) => {
if (!name || !name.trim()) return null;
if (name.trim().length < 2) return 'Full Name must be at least 2 characters long.';
if (!/^[\p{L}\s'-]+$/u.test(name)) return 'Full Name can only contain letters, spaces, hyphens, and apostrophes.';
if (/\s{2,}|^['\s-]|['\s-]$/.test(name)) return 'Full Name contains invalid spacing or punctuation.';
Comment on lines +67 to +68

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Restrict Full Name separators to spaces.

The \s character class accepts tabs, line breaks, and other whitespace. A value such as "Grace\tHopper" passes the allowed-character check because the spacing rule only rejects repeated whitespace or boundary punctuation. Use a literal space or explicitly define the accepted Unicode separators.

Suggested fix
-        if (!/^[\p{L}\s'-]+$/u.test(name)) return 'Full Name can only contain letters, spaces, hyphens, and apostrophes.';
-        if (/\s{2,}|^['\s-]|['\s-]$/.test(name)) return 'Full Name contains invalid spacing or punctuation.';
+        if (!/^[\p{L} '-]+$/u.test(name)) return 'Full Name can only contain letters, spaces, hyphens, and apostrophes.';
+        if (/ {2,}|^[' -]|[' -]$/.test(name)) return 'Full Name contains invalid spacing or punctuation.';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!/^[\p{L}\s'-]+$/u.test(name)) return 'Full Name can only contain letters, spaces, hyphens, and apostrophes.';
if (/\s{2,}|^['\s-]|['\s-]$/.test(name)) return 'Full Name contains invalid spacing or punctuation.';
if (!/^[\p{L} '-]+$/u.test(name)) return 'Full Name can only contain letters, spaces, hyphens, and apostrophes.';
if (/ {2,}|^[' -]|[' -]$/.test(name)) return 'Full Name contains invalid spacing or punctuation.';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Frontend/src/pages/AdminSignup.jsx` around lines 67 - 68, Update the Full
Name validation in the name-checking logic to restrict separators to literal
spaces instead of \s, including both repeated-spacing and boundary-punctuation
checks. Preserve acceptance of letters, hyphens, and apostrophes while rejecting
tabs, line breaks, and other whitespace characters.

return null;
};

const validateEmail = (email) => {
if (!email || !email.trim()) return null;
if (!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email)) return 'Please enter a valid work email (e.g. name@company.com).';
Comment on lines +65 to +74

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject whitespace-only values.

validateFullName and validateEmail return null when .trim() is empty. The required check in nextStep tests the untrimmed values, so " " passes and the form advances without an error. This violates the requirement to reject invalid Full Name and Work Email values.

Return a required-field error for trimmed-empty values, or trim the values in the required check.

Suggested fix
     const validateFullName = (name) => {
-        if (!name || !name.trim()) return null;
+        if (!name || !name.trim()) return 'Full Name is required.';
         if (name.trim().length < 2) return 'Full Name must be at least 2 characters long.';
         if (!/^[\p{L}\s'-]+$/u.test(name)) return 'Full Name can only contain letters, spaces, hyphens, and apostrophes.';
         if (/\s{2,}|^['\s-]|['\s-]$/.test(name)) return 'Full Name contains invalid spacing or punctuation.';
         return null;
     };

     const validateEmail = (email) => {
-        if (!email || !email.trim()) return null;
+        if (!email || !email.trim()) return 'Work Email is required.';
         if (!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email)) return 'Please enter a valid work email (e.g. name@company.com).';
         return null;
     };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!name || !name.trim()) return null;
if (name.trim().length < 2) return 'Full Name must be at least 2 characters long.';
if (!/^[\p{L}\s'-]+$/u.test(name)) return 'Full Name can only contain letters, spaces, hyphens, and apostrophes.';
if (/\s{2,}|^['\s-]|['\s-]$/.test(name)) return 'Full Name contains invalid spacing or punctuation.';
return null;
};
const validateEmail = (email) => {
if (!email || !email.trim()) return null;
if (!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email)) return 'Please enter a valid work email (e.g. name@company.com).';
if (!name || !name.trim()) return 'Full Name is required.';
if (name.trim().length < 2) return 'Full Name must be at least 2 characters long.';
if (!/^[\p{L}\s'-]+$/u.test(name)) return 'Full Name can only contain letters, spaces, hyphens, and apostrophes.';
if (/\s{2,}|^['\s-]|['\s-]$/.test(name)) return 'Full Name contains invalid spacing or punctuation.';
return null;
};
const validateEmail = (email) => {
if (!email || !email.trim()) return 'Work Email is required.';
if (!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email)) return 'Please enter a valid work email (e.g. name@company.com).';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Frontend/src/pages/AdminSignup.jsx` around lines 65 - 74, Update
validateFullName and validateEmail so trimmed-empty input returns the
appropriate required-field error instead of null, or ensure nextStep performs
required checks against trimmed values. Preserve existing format validation for
non-empty values and prevent whitespace-only names or emails from advancing the
form.

return null;
Comment on lines +72 to +75

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject malformed dot and hyphen placement in email addresses.

The current pattern accepts .alice@example.com, alice..smith@example.com, alice@-example.com, and alice@example..com. These values do not match a valid local@domain.tld format, but nextStep accepts them. Add local-part dot rules and validate each domain label.

Suggested structured validation
     const validateEmail = (email) => {
         if (!email || !email.trim()) return null;
-        if (!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email)) return 'Please enter a valid work email (e.g. name@company.com).';
+        const parts = email.split("@");
+        const [local, domain] = parts;
+        const labels = domain?.split(".") ?? [];
+        const isValid =
+            parts.length === 2 &&
+            /^[a-zA-Z0-9._%+-]+$/.test(local) &&
+            !local.startsWith(".") &&
+            !local.endsWith(".") &&
+            !local.includes("..") &&
+            labels.length >= 2 &&
+            labels.every((label) => /^[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/.test(label)) &&
+            /^[a-zA-Z]{2,}$/.test(labels[labels.length - 1]);
+        if (!isValid) return 'Please enter a valid work email (e.g. name@company.com).';
         return null;
     };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const validateEmail = (email) => {
if (!email || !email.trim()) return null;
if (!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email)) return 'Please enter a valid work email (e.g. name@company.com).';
return null;
const validateEmail = (email) => {
if (!email || !email.trim()) return null;
const parts = email.split("@");
const [local, domain] = parts;
const labels = domain?.split(".") ?? [];
const isValid =
parts.length === 2 &&
/^[a-zA-Z0-9._%+-]+$/.test(local) &&
!local.startsWith(".") &&
!local.endsWith(".") &&
!local.includes("..") &&
labels.length >= 2 &&
labels.every((label) => /^[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/.test(label)) &&
/^[a-zA-Z]{2,}$/.test(labels[labels.length - 1]);
if (!isValid) return 'Please enter a valid work email (e.g. name@company.com).';
return null;
};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Frontend/src/pages/AdminSignup.jsx` around lines 72 - 75, Update
validateEmail to reject local parts that start or end with a dot or contain
consecutive dots, and validate each domain label so labels cannot start or end
with a hyphen or contain consecutive dots. Preserve the existing empty-input
behavior and valid local@domain.tld acceptance while ensuring nextStep receives
null only for structurally valid addresses.

};

// Password strength calculation
useEffect(() => {
const pw = formData.password;
Expand All @@ -87,6 +101,16 @@ function AdminSignup() {
setError("Please fill in all required personal information.");
return;
}
const nameError = validateFullName(formData.fullName);
if (nameError) {
setError(nameError);
return;
}
const emailError = validateEmail(formData.email);
if (emailError) {
setError(emailError);
return;
}
Comment on lines +104 to +113

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Guard the form submission path, not only nextStep.

The new checks run only in nextStep, but the form still submits through handleSubmit on every step. A user can complete step three, return to step one, change fullName or email, and press Enter. Because the agreement flags remain checked, handleSubmit can call signup without running these validators.

Route non-final submissions through nextStep, or extract shared step validators and call them from both handlers.

Suggested fix
     const handleSubmit = async (e) => {
         e.preventDefault();
+        if (step !== 3) {
+            nextStep();
+            return;
+        }
         if (!formData.agreedToTerms || !formData.isAuthorized) {
             setError("You must agree to the terms and authorize company registration.");
             return;
🧰 Tools
🪛 ast-grep (0.45.0)

[warning] 105-105: Avoid using the initial state variable in setState
Context: setError(nameError)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(setstate-same-var)


[warning] 110-110: Avoid using the initial state variable in setState
Context: setError(emailError)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(setstate-same-var)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Frontend/src/pages/AdminSignup.jsx` around lines 104 - 113, Ensure the form
submission handler handleSubmit applies the fullName and email validation before
calling signup, including when users return to earlier steps and submit with
Enter. Reuse the existing validation logic from nextStep or route non-final
submissions through nextStep, while preserving the current agreement checks and
final-step signup behavior.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the signup implementation and downstream handlers.
while IFS= read -r file; do
  rg -n -C 8 '\bsignup\b|auth\.signUp|fullName|email' "$file" || true
done < <(fd -t f -i 'authStore' .)

rg -n -C 6 \
  'auth\.signUp|signUp\s*\(|fullName|full_name|email|profiles|admin' \
  --glob '*.js' \
  --glob '*.jsx' \
  --glob '*.ts' \
  --glob '*.tsx' \
  --glob '*.sql' \
  . || true

# Expected: server-side validation rejects invalid names and emails before persistence.

Repository: riteshbonthalakoti/HELPDESK.AI

Length of output: 220


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## files matching auth/admin signup"
git ls-files | rg -n 'AdminSignup|App\.jsx|auth|signup|AuthStore|supabase|schema|profiles|admin' || true

echo
echo "## AdminSignup relevant lines"
if [ -f Frontend/src/pages/AdminSignup.jsx ]; then
  nl -ba Frontend/src/pages/AdminSignup.jsx | sed -n '1,220p'
fi

echo
echo "## App signup route lines"
if [ -f Frontend/src/App.jsx ]; then
  nl -ba Frontend/src/App.jsx | sed -n '1,220p'
fi

echo
echo "## target identifiers in tracked files"
python3 - <<'PY'
import subprocess
files = subprocess.check_output(['git','ls-files'], text=True).splitlines()
terms = ['signup','signUp','auth.signUp','fullName','full_name','email','profiles','admin']
for term in terms:
    matches = []
    for f,fname in zip(files,files):
        if fname.endswith(('.js','.jsx','.ts','.tsx','.sql','.json','.env*','.md'))):
            try:
                text = open(f,'r',errors='ignore').read()
            except Exception:
                continue
            if term in text:
                matches.append(fname)
    print(f"\n# {term}")
    for m in matches[:200]:
        print(m)
PY

Repository: riteshbonthalakoti/HELPDESK.AI

Length of output: 2899


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## frontend lines"
for f in Frontend/src/pages/AdminSignup.jsx Frontend/src/App.jsx Frontend/src/store/authStore.js Frontend/src/store/adminStore.js Frontend/src/lib/supabaseClient.js; do
  if [ -f "$f" ]; then
    echo "--- $f"
    awk '{printf "%6d\t%s\n", NR, $0}' "$f" | sed -n '1,240p'
  fi
done

echo
echo "## backend/auth/relevant lines"
for f in supabase/functions/ai-proxy/index.ts supabase/functions/email-notifier/index.ts supabase/functions/send-user-approval-email/index.ts supabase/migrations/20260330231301_knowledge_base.sql supabase/migrations/20260330231302_webhook-trigger.sql supabase/migrations/20260331000000_resolve_vault_sync.sql supabase/migrations/20260331000001_sync_vault.sql; do
  if [ -f "$f" ]; then
    echo "--- $f"
    awk '{printf "%6d\t%s\n", NR, $0}' "$f" | sed -n '1,220p'
  fi
done

echo
echo "## search exact identifiers"
python3 - <<'PY'
import subprocess, re
files = subprocess.check_output(['git','ls-files'], text=True).splitlines()
terms = [r'\bsignup\b', r'/admin-signup', r'\bauth\.signUp\b', r'\bsignUp\s*\(', r'\bfullName\b', r'\bfull_name\b', r'\bemail\b', r'\bprofiles\b', r'\badmin\b']
for term in terms:
    print(f"\n# {term}")
    pat = re.compile(term)
    count = 0
    for f in files:
        if f.endswith(('.js','.jsx','.ts','.tsx','.sql','.json','.env','.md'))):
            try:
                text = open(f,'r',errors='ignore').read()
            except Exception:
                continue
            for i,line in enumerate(text.splitlines(),1):
                if pat.search(line):
                    print(f"{f}:{i}:{line.strip()}")
                    count += 1
    print(f"totalCount={count}")
PY

Repository: riteshbonthalakoti/HELPDESK.AI

Length of output: 50386


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## supabase migration files list"
git ls-files supabase/migrations | awk '{printf "%6d\t%s\n", NR, $0}' | sed -n '1,120p'

echo
echo "## migrations containing profiles/auth hooks/email validation"
for f in $(git ls-files supabase/migrations); do
  if rg -q 'CREATE TABLE "profiles"|FULL NAME|full_name|user_details|auth\.users|security\s+definer|check\(|is_email|email' "$f"; then
    echo "--- $f"
    rg -n -C 5 'profiles|full_name|security\s+definer|check\(|is_email|email|admin|role' "$f" || true
  fi
done

echo
echo "## Supabase Edge functions signup/profile handling"
git ls-files supabase/functions | while read -r f; do
  if rg -q 'auth\.signUp|insert\(|profiles|full_name|send-user-approval|approval|after.*auth' "$f" 2>/dev/null; then
    echo "--- $f"
    rg -n -C 4 'auth\.signUp|insert\(|profiles|full_name|send-user-approval|approval|after.*auth|RECORD' "$f" || true
  fi
done

echo
echo "## exact targeted references (limited)"
python3 - <<'PY'
import subprocess, re
files = subprocess.check_output(['git','ls-files'], text=True).splitlines()
terms=[
    r'\bsignup\b', r'/admin-signup', r'\bauth\.signUp\b',
    r'auth\.signUp\s*\(', 
    r'\bfullName\b', r'\bfull_name\b',
    r'\bemail\b', r'profiles',
    r'(create\s+trigger|CREATE\s+TRIGGER|security\s+definer|RECORD\.full_name|record\.full_name|new\.full_name|old\.full_name)',
]
for term in terms:
    print(f"\n# {term}")
    pat=re.compile(term, re.I)
    for f in files:
        if f.endswith(('.js','.jsx','.ts','.tsx','.sql','.json','.env','.md')) and (f.startswith('Frontend/src') or f.startswith('supabase') or f.startswith('backend')):
            try: text=open(f,errors='ignore').read()
            except Exception: continue
            try: lines=text.splitlines()
            except Exception: continue
            for i,line in enumerate(lines,1):
                if pat.search(line) and not f.endswith(('.tmp','.lock','package-lock.json')):
                    print(f"{f}:{i}:{line.strip()}")
PY

Repository: riteshbonthalakoti/HELPDESK.AI

Length of output: 50386


Reject invalid admin signup values server-side.

AdminSignup.jsx only skips the client-side validator when full Name is empty, then authStore.js still calls supabase.auth.signUp and passes fullName as auth metadata. Add an Edge Function/database trigger check for full_name and email before creating the user/profile so bypasses cannot create invalid records.

🧰 Tools
🪛 ast-grep (0.45.0)

[warning] 105-105: Avoid using the initial state variable in setState
Context: setError(nameError)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(setstate-same-var)


[warning] 110-110: Avoid using the initial state variable in setState
Context: setError(emailError)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(setstate-same-var)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Frontend/src/pages/AdminSignup.jsx` around lines 104 - 113, Enforce
server-side validation before user/profile creation in the admin signup backend
flow, rather than relying on the client validators in AdminSignup.jsx. Add
checks for full_name and email before supabase.auth.signUp or the corresponding
profile insert, rejecting empty or invalid values and preventing any record from
being created; reuse the existing Edge Function/database trigger entry point and
validation conventions.

const pwError = validatePassword(formData.password);
if (pwError) {
setError(pwError);
Expand Down
Loading