Fix registration enumeration + contact detail panel name sync
M-01: Unify registration error messages to prevent username/email enumeration — both now return the same generic message. Bug fix: Contact detail panel header and initials now use shared_fields for umbral contacts instead of stale Person record first_name/last_name. The table list already did this via sf() helper; the detail panel header and getPersonInitialsName were bypassing it. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d22600ac19
commit
c8805ee4c4
@ -441,7 +441,7 @@ async def register(
|
|||||||
select(User).where(User.username == data.username)
|
select(User).where(User.username == data.username)
|
||||||
)
|
)
|
||||||
if existing.scalar_one_or_none():
|
if existing.scalar_one_or_none():
|
||||||
raise HTTPException(status_code=400, detail="Registration could not be completed. Please try a different username.")
|
raise HTTPException(status_code=400, detail="Registration could not be completed. Please check your details and try again.")
|
||||||
|
|
||||||
# Check email uniqueness (generic error to prevent enumeration)
|
# Check email uniqueness (generic error to prevent enumeration)
|
||||||
if data.email:
|
if data.email:
|
||||||
|
|||||||
@ -60,7 +60,11 @@ function StatCounter({
|
|||||||
// Helpers
|
// Helpers
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
function getPersonInitialsName(p: Person): string {
|
function getPersonInitialsName(p: Person): string {
|
||||||
const parts = [p.first_name, p.last_name].filter(Boolean);
|
const firstName = p.is_umbral_contact && p.shared_fields?.first_name
|
||||||
|
? String(p.shared_fields.first_name) : p.first_name;
|
||||||
|
const lastName = p.is_umbral_contact && p.shared_fields?.last_name
|
||||||
|
? String(p.shared_fields.last_name) : p.last_name;
|
||||||
|
const parts = [firstName, lastName].filter(Boolean);
|
||||||
return parts.length > 0 ? parts.join(' ') : p.name;
|
return parts.length > 0 ? parts.join(' ') : p.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,7 +432,11 @@ export default function PeoplePage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<h3 className="font-heading text-lg font-semibold truncate">{p.name}</h3>
|
<h3 className="font-heading text-lg font-semibold truncate">{
|
||||||
|
p.is_umbral_contact && p.shared_fields
|
||||||
|
? [sf(p, 'first_name'), sf(p, 'last_name')].filter(Boolean).join(' ') || p.name
|
||||||
|
: p.name
|
||||||
|
}</h3>
|
||||||
{p.is_umbral_contact && (
|
{p.is_umbral_contact && (
|
||||||
<Ghost className="h-4 w-4 text-violet-400 shrink-0" />
|
<Ghost className="h-4 w-4 text-violet-400 shrink-0" />
|
||||||
)}
|
)}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user