2022-03-09 19:52:47 +03:00
|
|
|
import { UserDto } from '@thornbill/jellyfin-sdk/dist/generated-client';
|
2022-03-03 03:37:56 +03:00
|
|
|
import React, { FunctionComponent, useCallback, useEffect, useRef } from 'react';
|
2022-04-10 02:22:13 -04:00
|
|
|
import Dashboard from '../../../utils/dashboard';
|
2022-01-05 20:35:58 +03:00
|
|
|
import globalize from '../../../scripts/globalize';
|
|
|
|
import LibraryMenu from '../../../scripts/libraryMenu';
|
|
|
|
import confirm from '../../confirm/confirm';
|
|
|
|
import loading from '../../loading/loading';
|
|
|
|
import toast from '../../toast/toast';
|
2022-06-29 02:17:10 +03:00
|
|
|
import ButtonElement from '../elements/ButtonElement';
|
|
|
|
import CheckBoxElement from '../elements/CheckBoxElement';
|
|
|
|
import InputElement from '../elements/InputElement';
|
2022-01-05 20:35:58 +03:00
|
|
|
|
|
|
|
type IProps = {
|
2022-03-03 03:37:56 +03:00
|
|
|
userId: string;
|
2022-01-05 20:35:58 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
const UserPasswordForm: FunctionComponent<IProps> = ({userId}: IProps) => {
|
2022-03-03 03:37:56 +03:00
|
|
|
const element = useRef<HTMLDivElement>(null);
|
|
|
|
|
|
|
|
const loadUser = useCallback(() => {
|
|
|
|
const page = element.current;
|
|
|
|
|
|
|
|
if (!page) {
|
|
|
|
console.error('Unexpected null reference');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
window.ApiClient.getUser(userId).then(function (user) {
|
2022-03-09 19:52:47 +03:00
|
|
|
Dashboard.getCurrentUser().then(function (loggedInUser: UserDto) {
|
2022-03-03 03:37:56 +03:00
|
|
|
if (!user.Policy) {
|
|
|
|
throw new Error('Unexpected null user.Policy');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!user.Configuration) {
|
|
|
|
throw new Error('Unexpected null user.Configuration');
|
|
|
|
}
|
2022-01-05 20:35:58 +03:00
|
|
|
|
|
|
|
LibraryMenu.setTitle(user.Name);
|
|
|
|
|
|
|
|
let showLocalAccessSection = false;
|
|
|
|
|
2022-03-03 03:37:56 +03:00
|
|
|
if (user.HasConfiguredPassword) {
|
2022-06-29 04:16:20 +03:00
|
|
|
(page.querySelector('#btnResetPassword') as HTMLDivElement).classList.remove('hide');
|
2022-03-03 03:37:56 +03:00
|
|
|
(page.querySelector('#fldCurrentPassword') as HTMLDivElement).classList.remove('hide');
|
2022-01-05 20:35:58 +03:00
|
|
|
showLocalAccessSection = true;
|
|
|
|
} else {
|
2022-06-29 04:16:20 +03:00
|
|
|
(page.querySelector('#btnResetPassword') as HTMLDivElement).classList.add('hide');
|
2022-03-03 03:37:56 +03:00
|
|
|
(page.querySelector('#fldCurrentPassword') as HTMLDivElement).classList.add('hide');
|
2022-01-05 20:35:58 +03:00
|
|
|
}
|
|
|
|
|
2022-03-09 19:52:47 +03:00
|
|
|
if (loggedInUser?.Policy?.IsAdministrator || user.Policy.EnableUserPreferenceAccess) {
|
2022-03-03 03:37:56 +03:00
|
|
|
(page.querySelector('.passwordSection') as HTMLDivElement).classList.remove('hide');
|
2022-01-05 20:35:58 +03:00
|
|
|
} else {
|
2022-03-03 03:37:56 +03:00
|
|
|
(page.querySelector('.passwordSection') as HTMLDivElement).classList.add('hide');
|
2022-01-05 20:35:58 +03:00
|
|
|
}
|
|
|
|
|
2022-03-09 19:52:47 +03:00
|
|
|
if (showLocalAccessSection && (loggedInUser?.Policy?.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) {
|
2022-03-03 03:37:56 +03:00
|
|
|
(page.querySelector('.localAccessSection') as HTMLDivElement).classList.remove('hide');
|
2022-01-05 20:35:58 +03:00
|
|
|
} else {
|
2022-03-03 03:37:56 +03:00
|
|
|
(page.querySelector('.localAccessSection') as HTMLDivElement).classList.add('hide');
|
2022-01-05 20:35:58 +03:00
|
|
|
}
|
|
|
|
|
2022-03-03 03:37:56 +03:00
|
|
|
const txtEasyPassword = page.querySelector('#txtEasyPassword') as HTMLInputElement;
|
2022-01-05 20:35:58 +03:00
|
|
|
txtEasyPassword.value = '';
|
|
|
|
|
|
|
|
if (user.HasConfiguredEasyPassword) {
|
|
|
|
txtEasyPassword.placeholder = '******';
|
2022-06-29 04:16:20 +03:00
|
|
|
(page.querySelector('#btnResetEasyPassword') as HTMLDivElement).classList.remove('hide');
|
2022-01-05 20:35:58 +03:00
|
|
|
} else {
|
|
|
|
txtEasyPassword.removeAttribute('placeholder');
|
|
|
|
txtEasyPassword.placeholder = '';
|
2022-06-29 04:16:20 +03:00
|
|
|
(page.querySelector('#btnResetEasyPassword') as HTMLDivElement).classList.add('hide');
|
2022-01-05 20:35:58 +03:00
|
|
|
}
|
|
|
|
|
2022-03-03 03:37:56 +03:00
|
|
|
const chkEnableLocalEasyPassword = page.querySelector('.chkEnableLocalEasyPassword') as HTMLInputElement;
|
|
|
|
|
|
|
|
chkEnableLocalEasyPassword.checked = user.Configuration.EnableLocalPassword || false;
|
2022-01-05 20:35:58 +03:00
|
|
|
|
|
|
|
import('../../autoFocuser').then(({default: autoFocuser}) => {
|
2022-03-03 03:37:56 +03:00
|
|
|
autoFocuser.autoFocus(page);
|
2022-01-05 20:35:58 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2022-03-03 03:37:56 +03:00
|
|
|
(page.querySelector('#txtCurrentPassword') as HTMLInputElement).value = '';
|
|
|
|
(page.querySelector('#txtNewPassword') as HTMLInputElement).value = '';
|
|
|
|
(page.querySelector('#txtNewPasswordConfirm') as HTMLInputElement).value = '';
|
|
|
|
}, [userId]);
|
2022-01-05 20:35:58 +03:00
|
|
|
|
|
|
|
useEffect(() => {
|
2022-03-03 03:37:56 +03:00
|
|
|
const page = element.current;
|
2022-01-05 20:35:58 +03:00
|
|
|
|
2022-03-03 03:37:56 +03:00
|
|
|
if (!page) {
|
|
|
|
console.error('Unexpected null reference');
|
|
|
|
return;
|
|
|
|
}
|
2022-01-05 20:35:58 +03:00
|
|
|
|
2022-03-03 03:37:56 +03:00
|
|
|
loadUser();
|
|
|
|
|
|
|
|
const onSubmit = (e: Event) => {
|
|
|
|
if ((page.querySelector('#txtNewPassword') as HTMLInputElement).value != (page.querySelector('#txtNewPasswordConfirm') as HTMLInputElement).value) {
|
2022-01-05 20:35:58 +03:00
|
|
|
toast(globalize.translate('PasswordMatchError'));
|
|
|
|
} else {
|
|
|
|
loading.show();
|
|
|
|
savePassword();
|
|
|
|
}
|
|
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
const savePassword = () => {
|
2022-03-03 03:37:56 +03:00
|
|
|
let currentPassword = (page.querySelector('#txtCurrentPassword') as HTMLInputElement).value;
|
|
|
|
const newPassword = (page.querySelector('#txtNewPassword') as HTMLInputElement).value;
|
2022-01-05 20:35:58 +03:00
|
|
|
|
2022-03-03 03:37:56 +03:00
|
|
|
if ((page.querySelector('#fldCurrentPassword') as HTMLDivElement).classList.contains('hide')) {
|
2022-01-05 20:35:58 +03:00
|
|
|
// Firefox does not respect autocomplete=off, so clear it if the field is supposed to be hidden (and blank)
|
|
|
|
// This should only happen when user.HasConfiguredPassword is false, but this information is not passed on
|
|
|
|
currentPassword = '';
|
|
|
|
}
|
|
|
|
|
|
|
|
window.ApiClient.updateUserPassword(userId, currentPassword, newPassword).then(function () {
|
|
|
|
loading.hide();
|
|
|
|
toast(globalize.translate('PasswordSaved'));
|
|
|
|
|
2022-03-03 03:37:56 +03:00
|
|
|
loadUser();
|
2022-01-05 20:35:58 +03:00
|
|
|
}, function () {
|
|
|
|
loading.hide();
|
|
|
|
Dashboard.alert({
|
|
|
|
title: globalize.translate('HeaderLoginFailure'),
|
|
|
|
message: globalize.translate('MessageInvalidUser')
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2022-03-03 03:37:56 +03:00
|
|
|
const onLocalAccessSubmit = (e: Event) => {
|
2022-01-05 20:35:58 +03:00
|
|
|
loading.show();
|
|
|
|
saveEasyPassword();
|
|
|
|
e.preventDefault();
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
const saveEasyPassword = () => {
|
2022-03-03 03:37:56 +03:00
|
|
|
const easyPassword = (page.querySelector('#txtEasyPassword') as HTMLInputElement).value;
|
2022-01-05 20:35:58 +03:00
|
|
|
|
|
|
|
if (easyPassword) {
|
|
|
|
window.ApiClient.updateEasyPassword(userId, easyPassword).then(function () {
|
2022-03-03 03:37:56 +03:00
|
|
|
onEasyPasswordSaved();
|
2022-01-05 20:35:58 +03:00
|
|
|
});
|
|
|
|
} else {
|
2022-03-03 03:37:56 +03:00
|
|
|
onEasyPasswordSaved();
|
2022-01-05 20:35:58 +03:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-03-03 03:37:56 +03:00
|
|
|
const onEasyPasswordSaved = () => {
|
|
|
|
window.ApiClient.getUser(userId).then(function (user) {
|
|
|
|
if (!user.Configuration) {
|
|
|
|
throw new Error('Unexpected null user.Configuration');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!user.Id) {
|
|
|
|
throw new Error('Unexpected null user.Id');
|
|
|
|
}
|
|
|
|
|
|
|
|
user.Configuration.EnableLocalPassword = (page.querySelector('.chkEnableLocalEasyPassword') as HTMLInputElement).checked;
|
2022-01-05 20:35:58 +03:00
|
|
|
window.ApiClient.updateUserConfiguration(user.Id, user.Configuration).then(function () {
|
|
|
|
loading.hide();
|
|
|
|
toast(globalize.translate('SettingsSaved'));
|
|
|
|
|
2022-03-03 03:37:56 +03:00
|
|
|
loadUser();
|
2022-01-05 20:35:58 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const resetEasyPassword = () => {
|
|
|
|
const msg = globalize.translate('PinCodeResetConfirmation');
|
|
|
|
|
|
|
|
confirm(msg, globalize.translate('HeaderPinCodeReset')).then(function () {
|
|
|
|
loading.show();
|
|
|
|
window.ApiClient.resetEasyPassword(userId).then(function () {
|
|
|
|
loading.hide();
|
|
|
|
Dashboard.alert({
|
|
|
|
message: globalize.translate('PinCodeResetComplete'),
|
|
|
|
title: globalize.translate('HeaderPinCodeReset')
|
|
|
|
});
|
2022-03-03 03:37:56 +03:00
|
|
|
loadUser();
|
2022-01-05 20:35:58 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const resetPassword = () => {
|
|
|
|
const msg = globalize.translate('PasswordResetConfirmation');
|
|
|
|
confirm(msg, globalize.translate('ResetPassword')).then(function () {
|
|
|
|
loading.show();
|
|
|
|
window.ApiClient.resetUserPassword(userId).then(function () {
|
|
|
|
loading.hide();
|
|
|
|
Dashboard.alert({
|
|
|
|
message: globalize.translate('PasswordResetComplete'),
|
|
|
|
title: globalize.translate('ResetPassword')
|
|
|
|
});
|
2022-03-03 03:37:56 +03:00
|
|
|
loadUser();
|
2022-01-05 20:35:58 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2022-03-03 03:37:56 +03:00
|
|
|
(page.querySelector('.updatePasswordForm') as HTMLFormElement).addEventListener('submit', onSubmit);
|
|
|
|
(page.querySelector('.localAccessForm') as HTMLFormElement).addEventListener('submit', onLocalAccessSubmit);
|
2022-01-05 20:35:58 +03:00
|
|
|
|
2022-06-29 02:17:10 +03:00
|
|
|
(page.querySelector('#btnResetEasyPassword') as HTMLButtonElement).addEventListener('click', resetEasyPassword);
|
|
|
|
(page.querySelector('#btnResetPassword') as HTMLButtonElement).addEventListener('click', resetPassword);
|
2022-03-03 03:37:56 +03:00
|
|
|
}, [loadUser, userId]);
|
2022-01-05 20:35:58 +03:00
|
|
|
|
|
|
|
return (
|
|
|
|
<div ref={element}>
|
|
|
|
<form
|
|
|
|
className='updatePasswordForm passwordSection hide'
|
|
|
|
style={{margin: '0 auto 2em'}}
|
|
|
|
>
|
|
|
|
<div className='detailSection'>
|
|
|
|
<div id='fldCurrentPassword' className='inputContainer hide'>
|
|
|
|
<InputElement
|
|
|
|
type='password'
|
|
|
|
id='txtCurrentPassword'
|
|
|
|
label='LabelCurrentPassword'
|
|
|
|
options={'autoComplete="off"'}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
<div className='inputContainer'>
|
|
|
|
<InputElement
|
|
|
|
type='password'
|
|
|
|
id='txtNewPassword'
|
|
|
|
label='LabelNewPassword'
|
|
|
|
options={'autoComplete="off"'}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
<div className='inputContainer'>
|
|
|
|
<InputElement
|
|
|
|
type='password'
|
|
|
|
id='txtNewPasswordConfirm'
|
|
|
|
label='LabelNewPasswordConfirm'
|
|
|
|
options={'autoComplete="off"'}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
<br />
|
|
|
|
<div>
|
|
|
|
<ButtonElement
|
|
|
|
type='submit'
|
|
|
|
className='raised button-submit block'
|
|
|
|
title='Save'
|
|
|
|
/>
|
|
|
|
<ButtonElement
|
|
|
|
type='button'
|
2022-06-29 02:17:10 +03:00
|
|
|
id='btnResetPassword'
|
|
|
|
className='raised button-cancel block hide'
|
2022-01-05 20:35:58 +03:00
|
|
|
title='ResetPassword'
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</form>
|
|
|
|
<br />
|
|
|
|
<form
|
|
|
|
className='localAccessForm localAccessSection'
|
|
|
|
style={{margin: '0 auto'}}
|
|
|
|
>
|
|
|
|
<div className='detailSection'>
|
|
|
|
<div className='detailSectionHeader'>
|
|
|
|
{globalize.translate('HeaderEasyPinCode')}
|
|
|
|
</div>
|
|
|
|
<br />
|
|
|
|
<div>
|
|
|
|
{globalize.translate('EasyPasswordHelp')}
|
|
|
|
</div>
|
|
|
|
<br />
|
|
|
|
<div className='inputContainer'>
|
|
|
|
<InputElement
|
|
|
|
type='number'
|
|
|
|
id='txtEasyPassword'
|
|
|
|
label='LabelEasyPinCode'
|
|
|
|
options={'autoComplete="off" pattern="[0-9]*" step="1" maxlength="5"'}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
<br />
|
|
|
|
<div className='checkboxContainer checkboxContainer-withDescription'>
|
|
|
|
<CheckBoxElement
|
|
|
|
className='chkEnableLocalEasyPassword'
|
|
|
|
title='LabelInNetworkSignInWithEasyPassword'
|
|
|
|
/>
|
|
|
|
<div className='fieldDescription checkboxFieldDescription'>
|
|
|
|
{globalize.translate('LabelInNetworkSignInWithEasyPasswordHelp')}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<ButtonElement
|
|
|
|
type='submit'
|
|
|
|
className='raised button-submit block'
|
|
|
|
title='Save'
|
|
|
|
/>
|
|
|
|
<ButtonElement
|
|
|
|
type='button'
|
2022-06-29 02:17:10 +03:00
|
|
|
id='btnResetEasyPassword'
|
|
|
|
className='raised button-cancel block hide'
|
2022-01-05 20:35:58 +03:00
|
|
|
title='ButtonResetEasyPassword'
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</form>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default UserPasswordForm;
|