fix: version 2.8.3 -- PIN de Contraseñas ya no dispara el gestor de contraseñas de Chrome
Los campos de PIN (desbloqueo, crear, cambiar, resetear) usaban type="password", lo que hacia que Chrome ofreciera guardar/actualizar una "contraseña de sitio" cada vez que se ingresaba. Un PIN de 4 digitos no es una credencial de login, asi que se cambia a type="text" con enmascarado puramente visual (-webkit-text-security), sin perder el aspecto de puntos. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,12 @@
|
|||||||
# Changelog - project.linkedcorp.net
|
# Changelog - project.linkedcorp.net
|
||||||
|
|
||||||
|
## [2.8.3] - 2026-10-01
|
||||||
|
### Fixed
|
||||||
|
- El PIN de "Contraseñas" (acceso y cambio de PIN) ya no usa `type="password"` en el campo —
|
||||||
|
Chrome lo detectaba como una credencial de sitio y ofrecía "¿Quieres actualizar la contraseña?"
|
||||||
|
cada vez que se desbloqueaba el candado. Ahora se enmascara solo visualmente (sigue viéndose
|
||||||
|
como puntos) sin disparar el gestor de contraseñas del navegador.
|
||||||
|
|
||||||
## [2.8.2] - 2026-10-01
|
## [2.8.2] - 2026-10-01
|
||||||
### Added
|
### Added
|
||||||
- Al aplicar una actualización desde Configuración → Actualizaciones, ahora se bloquea toda la
|
- Al aplicar una actualización desde Configuración → Actualizaciones, ahora se bloquea toda la
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "project-linkedcorp-backend",
|
"name": "project-linkedcorp-backend",
|
||||||
"version": "2.8.2",
|
"version": "2.8.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/server.js",
|
"main": "src/server.js",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "project-linkedcorp-frontend",
|
"name": "project-linkedcorp-frontend",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2.8.2",
|
"version": "2.8.3",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -268,7 +268,8 @@ export default function ContrasenasPage() {
|
|||||||
{!hasPinSet && <p className="text-muted" style={{ fontSize: '.8rem' }}>{t('vault_create_pin_hint')}</p>}
|
{!hasPinSet && <p className="text-muted" style={{ fontSize: '.8rem' }}>{t('vault_create_pin_hint')}</p>}
|
||||||
<Field label={t('vault_pin_label')}>
|
<Field label={t('vault_pin_label')}>
|
||||||
<input
|
<input
|
||||||
className="input" type="password" inputMode="numeric" maxLength={4} autoFocus
|
className="input pin-input" type="text" inputMode="numeric" maxLength={4} autoFocus
|
||||||
|
autoComplete="off" data-lpignore="true" data-1p-ignore="true"
|
||||||
value={pin} onChange={(e) => setPin(e.target.value.replace(/\D/g, ''))}
|
value={pin} onChange={(e) => setPin(e.target.value.replace(/\D/g, ''))}
|
||||||
onKeyDown={(e) => { if (e.key === 'Enter') submitPin(); }}
|
onKeyDown={(e) => { if (e.key === 'Enter') submitPin(); }}
|
||||||
/>
|
/>
|
||||||
@@ -276,7 +277,8 @@ export default function ContrasenasPage() {
|
|||||||
{!hasPinSet && (
|
{!hasPinSet && (
|
||||||
<Field label={t('vault_pin_confirm_label')}>
|
<Field label={t('vault_pin_confirm_label')}>
|
||||||
<input
|
<input
|
||||||
className="input" type="password" inputMode="numeric" maxLength={4}
|
className="input pin-input" type="text" inputMode="numeric" maxLength={4}
|
||||||
|
autoComplete="off" data-lpignore="true" data-1p-ignore="true"
|
||||||
value={pinConfirm} onChange={(e) => setPinConfirm(e.target.value.replace(/\D/g, ''))}
|
value={pinConfirm} onChange={(e) => setPinConfirm(e.target.value.replace(/\D/g, ''))}
|
||||||
onKeyDown={(e) => { if (e.key === 'Enter') submitPin(); }}
|
onKeyDown={(e) => { if (e.key === 'Enter') submitPin(); }}
|
||||||
/>
|
/>
|
||||||
@@ -426,13 +428,13 @@ export default function ContrasenasPage() {
|
|||||||
|
|
||||||
<DetailPopup open={changingPin} title={t('vault_change_pin')} onClose={() => setChangingPin(false)} width={360} height={360}>
|
<DetailPopup open={changingPin} title={t('vault_change_pin')} onClose={() => setChangingPin(false)} width={360} height={360}>
|
||||||
<Field label={t('vault_pin_current_label')}>
|
<Field label={t('vault_pin_current_label')}>
|
||||||
<input className="input" type="password" inputMode="numeric" maxLength={4} value={pinChangeForm.current} onChange={(e) => setPinChangeForm((f) => ({ ...f, current: e.target.value.replace(/\D/g, '') }))} />
|
<input className="input pin-input" type="text" inputMode="numeric" maxLength={4} autoComplete="off" data-lpignore="true" data-1p-ignore="true" value={pinChangeForm.current} onChange={(e) => setPinChangeForm((f) => ({ ...f, current: e.target.value.replace(/\D/g, '') }))} />
|
||||||
</Field>
|
</Field>
|
||||||
<Field label={t('vault_pin_label')}>
|
<Field label={t('vault_pin_label')}>
|
||||||
<input className="input" type="password" inputMode="numeric" maxLength={4} value={pinChangeForm.next} onChange={(e) => setPinChangeForm((f) => ({ ...f, next: e.target.value.replace(/\D/g, '') }))} />
|
<input className="input pin-input" type="text" inputMode="numeric" maxLength={4} autoComplete="off" data-lpignore="true" data-1p-ignore="true" value={pinChangeForm.next} onChange={(e) => setPinChangeForm((f) => ({ ...f, next: e.target.value.replace(/\D/g, '') }))} />
|
||||||
</Field>
|
</Field>
|
||||||
<Field label={t('vault_pin_confirm_label')}>
|
<Field label={t('vault_pin_confirm_label')}>
|
||||||
<input className="input" type="password" inputMode="numeric" maxLength={4} value={pinChangeForm.next2} onChange={(e) => setPinChangeForm((f) => ({ ...f, next2: e.target.value.replace(/\D/g, '') }))} />
|
<input className="input pin-input" type="text" inputMode="numeric" maxLength={4} autoComplete="off" data-lpignore="true" data-1p-ignore="true" value={pinChangeForm.next2} onChange={(e) => setPinChangeForm((f) => ({ ...f, next2: e.target.value.replace(/\D/g, '') }))} />
|
||||||
</Field>
|
</Field>
|
||||||
{pinChangeError && <div className="login-error">{pinChangeError}</div>}
|
{pinChangeError && <div className="login-error">{pinChangeError}</div>}
|
||||||
<div style={{ display: 'flex', gap: 8, marginTop: 8 }}>
|
<div style={{ display: 'flex', gap: 8, marginTop: 8 }}>
|
||||||
|
|||||||
@@ -51,11 +51,13 @@ export default function ResetVaultPinPage() {
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Field label={t('vault_pin_label')}>
|
<Field label={t('vault_pin_label')}>
|
||||||
<input className="input" type="password" inputMode="numeric" maxLength={4} autoFocus
|
<input className="input pin-input" type="text" inputMode="numeric" maxLength={4} autoFocus
|
||||||
|
autoComplete="off" data-lpignore="true" data-1p-ignore="true"
|
||||||
value={pin} onChange={(e) => setPin(e.target.value.replace(/\D/g, ''))} required />
|
value={pin} onChange={(e) => setPin(e.target.value.replace(/\D/g, ''))} required />
|
||||||
</Field>
|
</Field>
|
||||||
<Field label={t('vault_pin_confirm_label')}>
|
<Field label={t('vault_pin_confirm_label')}>
|
||||||
<input className="input" type="password" inputMode="numeric" maxLength={4}
|
<input className="input pin-input" type="text" inputMode="numeric" maxLength={4}
|
||||||
|
autoComplete="off" data-lpignore="true" data-1p-ignore="true"
|
||||||
value={confirm} onChange={(e) => setConfirm(e.target.value.replace(/\D/g, ''))} required />
|
value={confirm} onChange={(e) => setConfirm(e.target.value.replace(/\D/g, ''))} required />
|
||||||
</Field>
|
</Field>
|
||||||
<Button variant="accent" icon={KeyRound} type="submit" disabled={loading || !token} style={{ width: '100%', justifyContent: 'center' }}>
|
<Button variant="accent" icon={KeyRound} type="submit" disabled={loading || !token} style={{ width: '100%', justifyContent: 'center' }}>
|
||||||
|
|||||||
@@ -378,6 +378,13 @@ table.list-table { width: 100%; border-collapse: collapse; font-size: .8rem; }
|
|||||||
font-size: .72rem; color: rgb(var(--muted)); max-width: 100%; overflow: hidden;
|
font-size: .72rem; color: rgb(var(--muted)); max-width: 100%; overflow: hidden;
|
||||||
text-overflow: ellipsis; white-space: nowrap;
|
text-overflow: ellipsis; white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
/* PIN de 4 digitos: NO es type="password" a proposito -- Chrome ofrece "guardar contraseña"
|
||||||
|
(como si fuera login de un sitio) apenas detecta un input password con valor + una llamada de
|
||||||
|
red despues, molestando cada vez que se desbloquea el candado. Un PIN no es una credencial de
|
||||||
|
sitio, asi que se enmascara solo visualmente con -webkit-text-security (soportado en
|
||||||
|
Chrome/Edge/Safari; en Firefox se ve el numero en texto plano, degradacion aceptable). */
|
||||||
|
.pin-input { -webkit-text-security: disc; letter-spacing: 4px; }
|
||||||
|
|
||||||
.vault-icon-picker { display: flex; flex-wrap: wrap; gap: 8px; }
|
.vault-icon-picker { display: flex; flex-wrap: wrap; gap: 8px; }
|
||||||
.vault-icon-picker-brands { max-height: 150px; overflow-y: auto; padding-top: 8px; margin-top: 4px; border-top: 1px dashed rgb(var(--line)); }
|
.vault-icon-picker-brands { max-height: 150px; overflow-y: auto; padding-top: 8px; margin-top: 4px; border-top: 1px dashed rgb(var(--line)); }
|
||||||
.vault-icon-option {
|
.vault-icon-option {
|
||||||
|
|||||||
Reference in New Issue
Block a user