feat(ui): prevent password manager interference & improve service links (#3989)

pull/4047/head
soup 1 month ago committed by GitHub
parent 3242251927
commit ef18b5d1de
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -25,6 +25,10 @@ const SensitiveInput = ({ as = 'input', ...props }: SensitiveInputProps) => {
return ( return (
<> <>
<Component <Component
autoComplete="off"
data-1pignore="true"
data-lpignore="true"
data-bwignore="true"
{...componentProps} {...componentProps}
className={`rounded-l-only ${componentProps.className ?? ''}`} className={`rounded-l-only ${componentProps.className ?? ''}`}
type={ type={

@ -101,6 +101,9 @@ const LocalLogin = ({ revalidate }: LocalLoginProps) => {
type="password" type="password"
autoComplete="current-password" autoComplete="current-password"
data-testid="password" data-testid="password"
data-1pignore="false"
data-lpignore="false"
data-bwignore="false"
/> />
</div> </div>
{errors.password && {errors.password &&

@ -208,6 +208,10 @@ const NotificationsDiscord = () => {
name="botUsername" name="botUsername"
type="text" type="text"
placeholder={settings.currentSettings.applicationTitle} placeholder={settings.currentSettings.applicationTitle}
autoComplete="off"
data-1pignore="true"
data-lpignore="true"
data-bwignore="true"
/> />
</div> </div>
{errors.botUsername && {errors.botUsername &&

@ -103,7 +103,7 @@ const NotificationsEmail = () => {
otherwise: Yup.string().nullable(), otherwise: Yup.string().nullable(),
}) })
.matches( .matches(
/-----BEGIN PGP PRIVATE KEY BLOCK-----.+-----END PGP PRIVATE KEY BLOCK-----/s, /-----BEGIN PGP PRIVATE KEY BLOCK-----.+-----END PGP PRIVATE KEY BLOCK-----/,
intl.formatMessage(messages.validationPgpPrivateKey) intl.formatMessage(messages.validationPgpPrivateKey)
), ),
pgpPassword: Yup.string().when('pgpPrivateKey', { pgpPassword: Yup.string().when('pgpPrivateKey', {
@ -263,6 +263,10 @@ const NotificationsEmail = () => {
name="emailFrom" name="emailFrom"
type="text" type="text"
inputMode="email" inputMode="email"
autoComplete="off"
data-1pignore="true"
data-lpignore="true"
data-bwignore="true"
/> />
</div> </div>
{errors.emailFrom && {errors.emailFrom &&
@ -284,6 +288,10 @@ const NotificationsEmail = () => {
name="smtpHost" name="smtpHost"
type="text" type="text"
inputMode="url" inputMode="url"
autoComplete="off"
data-1pignore="true"
data-lpignore="true"
data-bwignore="true"
/> />
</div> </div>
{errors.smtpHost && {errors.smtpHost &&
@ -305,6 +313,10 @@ const NotificationsEmail = () => {
type="text" type="text"
inputMode="numeric" inputMode="numeric"
className="short" className="short"
autoComplete="off"
data-1pignore="true"
data-lpignore="true"
data-bwignore="true"
/> />
{errors.smtpPort && {errors.smtpPort &&
touched.smtpPort && touched.smtpPort &&
@ -358,7 +370,15 @@ const NotificationsEmail = () => {
</label> </label>
<div className="form-input-area"> <div className="form-input-area">
<div className="form-input-field"> <div className="form-input-field">
<Field id="authUser" name="authUser" type="text" /> <Field
id="authUser"
name="authUser"
type="text"
autoComplete="off"
data-1pignore="true"
data-lpignore="true"
data-bwignore="true"
/>
</div> </div>
</div> </div>
</div> </div>
@ -368,12 +388,7 @@ const NotificationsEmail = () => {
</label> </label>
<div className="form-input-area"> <div className="form-input-area">
<div className="form-input-field"> <div className="form-input-field">
<SensitiveInput <SensitiveInput as="field" id="authPass" name="authPass" />
as="field"
id="authPass"
name="authPass"
autoComplete="one-time-code"
/>
</div> </div>
</div> </div>
</div> </div>
@ -398,6 +413,10 @@ const NotificationsEmail = () => {
type="textarea" type="textarea"
rows="10" rows="10"
className="font-mono text-xs" className="font-mono text-xs"
autoComplete="off"
data-1pignore="true"
data-lpignore="true"
data-bwignore="true"
/> />
</div> </div>
{errors.pgpPrivateKey && {errors.pgpPrivateKey &&
@ -425,7 +444,10 @@ const NotificationsEmail = () => {
as="field" as="field"
id="pgpPassword" id="pgpPassword"
name="pgpPassword" name="pgpPassword"
autoComplete="one-time-code" autoComplete="off"
data-1pignore="true"
data-lpignore="true"
data-bwignore="true"
/> />
</div> </div>
{errors.pgpPassword && {errors.pgpPassword &&

@ -211,7 +211,7 @@ const NotificationsTelegram = () => {
as="field" as="field"
id="botAPI" id="botAPI"
name="botAPI" name="botAPI"
autoComplete="one-time-code" type="text"
/> />
</div> </div>
{errors.botAPI && {errors.botAPI &&
@ -230,7 +230,15 @@ const NotificationsTelegram = () => {
</label> </label>
<div className="form-input-area"> <div className="form-input-area">
<div className="form-input-field"> <div className="form-input-field">
<Field id="botUsername" name="botUsername" type="text" /> <Field
id="botUsername"
name="botUsername"
type="text"
autoComplete="off"
data-1pignore="true"
data-lpignore="true"
data-bwignore="true"
/>
</div> </div>
{errors.botUsername && {errors.botUsername &&
touched.botUsername && touched.botUsername &&
@ -260,7 +268,15 @@ const NotificationsTelegram = () => {
</label> </label>
<div className="form-input-area"> <div className="form-input-area">
<div className="form-input-field"> <div className="form-input-field">
<Field id="chatId" name="chatId" type="text" /> <Field
id="chatId"
name="chatId"
type="text"
autoComplete="off"
data-1pignore="true"
data-lpignore="true"
data-bwignore="true"
/>
</div> </div>
{errors.chatId && {errors.chatId &&
touched.chatId && touched.chatId &&

@ -377,6 +377,10 @@ const RadarrModal = ({ onClose, radarr, onSave }: RadarrModalProps) => {
id="name" id="name"
name="name" name="name"
type="text" type="text"
autoComplete="off"
data-1pignore="true"
data-lpignore="true"
data-bwignore="true"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => { onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setIsValidated(false); setIsValidated(false);
setFieldValue('name', e.target.value); setFieldValue('name', e.target.value);
@ -470,7 +474,6 @@ const RadarrModal = ({ onClose, radarr, onSave }: RadarrModalProps) => {
as="field" as="field"
id="apiKey" id="apiKey"
name="apiKey" name="apiKey"
autoComplete="one-time-code"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => { onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setIsValidated(false); setIsValidated(false);
setFieldValue('apiKey', e.target.value); setFieldValue('apiKey', e.target.value);

@ -824,6 +824,10 @@ const SettingsPlex = ({ onComplete }: SettingsPlexProps) => {
id="tautulliPort" id="tautulliPort"
name="tautulliPort" name="tautulliPort"
className="short" className="short"
autoComplete="off"
data-1pignore="true"
data-lpignore="true"
data-bwignore="true"
/> />
{errors.tautulliPort && {errors.tautulliPort &&
touched.tautulliPort && touched.tautulliPort &&
@ -861,6 +865,10 @@ const SettingsPlex = ({ onComplete }: SettingsPlexProps) => {
inputMode="url" inputMode="url"
id="tautulliUrlBase" id="tautulliUrlBase"
name="tautulliUrlBase" name="tautulliUrlBase"
autoComplete="off"
data-1pignore="true"
data-lpignore="true"
data-bwignore="true"
/> />
</div> </div>
{errors.tautulliUrlBase && {errors.tautulliUrlBase &&
@ -881,7 +889,6 @@ const SettingsPlex = ({ onComplete }: SettingsPlexProps) => {
as="field" as="field"
id="tautulliApiKey" id="tautulliApiKey"
name="tautulliApiKey" name="tautulliApiKey"
autoComplete="one-time-code"
/> />
</div> </div>
{errors.tautulliApiKey && {errors.tautulliApiKey &&
@ -902,6 +909,10 @@ const SettingsPlex = ({ onComplete }: SettingsPlexProps) => {
inputMode="url" inputMode="url"
id="tautulliExternalUrl" id="tautulliExternalUrl"
name="tautulliExternalUrl" name="tautulliExternalUrl"
autoComplete="off"
data-1pignore="true"
data-lpignore="true"
data-bwignore="true"
/> />
</div> </div>
{errors.tautulliExternalUrl && {errors.tautulliExternalUrl &&

@ -84,6 +84,8 @@ const ServerInstance = ({
<h3 className="truncate font-medium leading-5 text-white"> <h3 className="truncate font-medium leading-5 text-white">
<a <a
href={serviceUrl} href={serviceUrl}
target="_blank"
rel="noopener noreferrer"
className="transition duration-300 hover:text-white hover:underline" className="transition duration-300 hover:text-white hover:underline"
> >
{name} {name}
@ -112,6 +114,8 @@ const ServerInstance = ({
</span> </span>
<a <a
href={internalUrl} href={internalUrl}
target="_blank"
rel="noopener noreferrer"
className="transition duration-300 hover:text-white hover:underline" className="transition duration-300 hover:text-white hover:underline"
> >
{internalUrl} {internalUrl}
@ -124,7 +128,12 @@ const ServerInstance = ({
{profileName} {profileName}
</p> </p>
</div> </div>
<a href={serviceUrl} className="opacity-50 hover:opacity-100"> <a
href={serviceUrl}
target="_blank"
rel="noopener noreferrer"
className="opacity-50 hover:opacity-100"
>
{isSonarr ? ( {isSonarr ? (
<SonarrLogo className="h-10 w-10 flex-shrink-0" /> <SonarrLogo className="h-10 w-10 flex-shrink-0" />
) : ( ) : (

@ -412,6 +412,10 @@ const SonarrModal = ({ onClose, sonarr, onSave }: SonarrModalProps) => {
id="name" id="name"
name="name" name="name"
type="text" type="text"
autoComplete="off"
data-1pignore="true"
data-lpignore="true"
data-bwignore="true"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => { onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setIsValidated(false); setIsValidated(false);
setFieldValue('name', e.target.value); setFieldValue('name', e.target.value);
@ -505,7 +509,6 @@ const SonarrModal = ({ onClose, sonarr, onSave }: SonarrModalProps) => {
as="field" as="field"
id="apiKey" id="apiKey"
name="apiKey" name="apiKey"
autoComplete="one-time-code"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => { onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setIsValidated(false); setIsValidated(false);
setFieldValue('apiKey', e.target.value); setFieldValue('apiKey', e.target.value);

@ -372,6 +372,10 @@ const UserList = () => {
name="email" name="email"
type="text" type="text"
inputMode="email" inputMode="email"
autoComplete="off"
data-1pignore="true"
data-lpignore="true"
data-bwignore="true"
/> />
</div> </div>
{errors.email && {errors.email &&

Loading…
Cancel
Save