mirror of
https://github.com/zadam/trilium.git
synced 2026-05-06 17:17:37 +02:00
feat(options/password): use modals for changing the password
This commit is contained in:
@@ -1491,7 +1491,11 @@
|
||||
"new_password": "New password",
|
||||
"new_password_confirmation": "New password confirmation",
|
||||
"change_password": "Change password",
|
||||
"protected_session_timeout": "Protected Session Timeout",
|
||||
"change_password_description": "Update your current password",
|
||||
"reset_password": "Reset password",
|
||||
"reset_password_description": "Permanently lose access to protected notes",
|
||||
"cancel": "Cancel",
|
||||
"protected_session_timeout": "Protected Session",
|
||||
"protected_session_timeout_description": "Time of inactivity before the session is cleared from browser memory. See",
|
||||
"wiki": "wiki",
|
||||
"for_more_info": "for more info.",
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { useState } from "preact/hooks"
|
||||
import { t } from "../../../services/i18n"
|
||||
import server from "../../../services/server"
|
||||
import toast from "../../../services/toast"
|
||||
import Alert from "../../react/Alert"
|
||||
import Button from "../../react/Button"
|
||||
import FormGroup from "../../react/FormGroup"
|
||||
import FormTextBox from "../../react/FormTextBox"
|
||||
import LinkButton from "../../react/LinkButton"
|
||||
import OptionsSection from "./components/OptionsSection"
|
||||
import OptionsRow from "./components/OptionsRow"
|
||||
import protected_session_holder from "../../../services/protected_session_holder"
|
||||
import { ChangePasswordResponse } from "@triliumnext/commons"
|
||||
import dialog from "../../../services/dialog"
|
||||
import TimeSelector from "./components/TimeSelector"
|
||||
import { useState } from "preact/hooks";
|
||||
import { createPortal } from "preact/compat";
|
||||
import { t } from "../../../services/i18n";
|
||||
import server from "../../../services/server";
|
||||
import toast from "../../../services/toast";
|
||||
import Button from "../../react/Button";
|
||||
import FormGroup from "../../react/FormGroup";
|
||||
import FormTextBox from "../../react/FormTextBox";
|
||||
import OptionsSection from "./components/OptionsSection";
|
||||
import OptionsRow, { OptionsRowWithButton } from "./components/OptionsRow";
|
||||
import protected_session_holder from "../../../services/protected_session_holder";
|
||||
import { ChangePasswordResponse } from "@triliumnext/commons";
|
||||
import dialog from "../../../services/dialog";
|
||||
import TimeSelector from "./components/TimeSelector";
|
||||
import Modal from "../../react/Modal";
|
||||
|
||||
export default function PasswordSettings() {
|
||||
return (
|
||||
@@ -20,86 +20,125 @@ export default function PasswordSettings() {
|
||||
<ChangePassword />
|
||||
<ProtectedSessionTimeout />
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function ChangePassword() {
|
||||
const [ oldPassword, setOldPassword ] = useState("");
|
||||
const [ newPassword1, setNewPassword1 ] = useState("");
|
||||
const [ newPassword2, setNewPassword2 ] = useState("");
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
|
||||
return (
|
||||
<OptionsSection title={t("password.heading")}>
|
||||
<Alert type="warning">
|
||||
{t("password.alert_message")}
|
||||
|
||||
<LinkButton
|
||||
text={t("password.reset_link")}
|
||||
onClick={async () => {
|
||||
if (!confirm(t("password.reset_confirmation"))) {
|
||||
return;
|
||||
}
|
||||
<OptionsRowWithButton
|
||||
label={t("password.change_password")}
|
||||
description={t("password.change_password_description")}
|
||||
icon="bx bx-chevron-right"
|
||||
onClick={() => setShowModal(true)}
|
||||
/>
|
||||
|
||||
await server.post("password/reset?really=yesIReallyWantToResetPasswordAndLoseAccessToMyProtectedNotes");
|
||||
toast.showError(t("password.reset_success_message"));
|
||||
}}
|
||||
/>
|
||||
</Alert>
|
||||
<OptionsRowWithButton
|
||||
label={t("password.reset_password")}
|
||||
description={t("password.reset_password_description")}
|
||||
icon="bx bx-chevron-right"
|
||||
onClick={async () => {
|
||||
if (!await dialog.confirm(t("password.reset_confirmation"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
<form onSubmit={async (e) => {
|
||||
e.preventDefault();
|
||||
await server.post("password/reset?really=yesIReallyWantToResetPasswordAndLoseAccessToMyProtectedNotes");
|
||||
toast.showError(t("password.reset_success_message"));
|
||||
}}
|
||||
/>
|
||||
|
||||
setOldPassword("");
|
||||
setNewPassword1("");
|
||||
setNewPassword2("");
|
||||
|
||||
if (newPassword1 !== newPassword2) {
|
||||
toast.showError(t("password.password_mismatch"));
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await server
|
||||
.post<ChangePasswordResponse>("password/change", {
|
||||
current_password: oldPassword,
|
||||
new_password: newPassword1
|
||||
})
|
||||
if (result.success) {
|
||||
await dialog.info(t("password.password_changed_success"));
|
||||
|
||||
// password changed so current protected session is invalid and needs to be cleared
|
||||
protected_session_holder.resetProtectedSession();
|
||||
} else if (result.message) {
|
||||
toast.showError(result.message);
|
||||
}
|
||||
}}>
|
||||
<FormGroup name="old-password" label={t("password.old_password")}>
|
||||
<FormTextBox
|
||||
type="password"
|
||||
currentValue={oldPassword} onChange={setOldPassword}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup name="new-password1" label={t("password.new_password")}>
|
||||
<FormTextBox
|
||||
type="password"
|
||||
currentValue={newPassword1} onChange={setNewPassword1}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup name="new-password2" label={t("password.new_password_confirmation")}>
|
||||
<FormTextBox
|
||||
type="password"
|
||||
currentValue={newPassword2} onChange={setNewPassword2}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<Button
|
||||
text={t("password.change_password")}
|
||||
kind="primary"
|
||||
/>
|
||||
</form>
|
||||
{createPortal(
|
||||
<ChangePasswordModal show={showModal} onHidden={() => setShowModal(false)} />,
|
||||
document.body
|
||||
)}
|
||||
</OptionsSection>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
interface ChangePasswordModalProps {
|
||||
show: boolean;
|
||||
onHidden: () => void;
|
||||
}
|
||||
|
||||
function ChangePasswordModal({ show, onHidden }: ChangePasswordModalProps) {
|
||||
const [oldPassword, setOldPassword] = useState("");
|
||||
const [newPassword1, setNewPassword1] = useState("");
|
||||
const [newPassword2, setNewPassword2] = useState("");
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (newPassword1 !== newPassword2) {
|
||||
toast.showError(t("password.password_mismatch"));
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await server.post<ChangePasswordResponse>("password/change", {
|
||||
current_password: oldPassword,
|
||||
new_password: newPassword1
|
||||
});
|
||||
|
||||
if (result.success) {
|
||||
onHidden();
|
||||
setOldPassword("");
|
||||
setNewPassword1("");
|
||||
setNewPassword2("");
|
||||
await dialog.info(t("password.password_changed_success"));
|
||||
|
||||
// password changed so current protected session is invalid and needs to be cleared
|
||||
protected_session_holder.resetProtectedSession();
|
||||
} else if (result.message) {
|
||||
toast.showError(result.message);
|
||||
}
|
||||
};
|
||||
|
||||
const handleHidden = () => {
|
||||
setOldPassword("");
|
||||
setNewPassword1("");
|
||||
setNewPassword2("");
|
||||
onHidden();
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
show={show}
|
||||
onHidden={handleHidden}
|
||||
onSubmit={handleSubmit}
|
||||
title={t("password.change_password_heading")}
|
||||
className="change-password-modal"
|
||||
size="md"
|
||||
footer={
|
||||
<>
|
||||
<Button text={t("password.cancel")} onClick={handleHidden} />
|
||||
<Button text={t("password.change_password")} kind="primary" />
|
||||
</>
|
||||
}
|
||||
>
|
||||
<FormGroup name="old-password" label={t("password.old_password")}>
|
||||
<FormTextBox
|
||||
type="password"
|
||||
currentValue={oldPassword}
|
||||
onChange={setOldPassword}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup name="new-password1" label={t("password.new_password")}>
|
||||
<FormTextBox
|
||||
type="password"
|
||||
currentValue={newPassword1}
|
||||
onChange={setNewPassword1}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup name="new-password2" label={t("password.new_password_confirmation")}>
|
||||
<FormTextBox
|
||||
type="password"
|
||||
currentValue={newPassword2}
|
||||
onChange={setNewPassword2}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
function ProtectedSessionTimeout() {
|
||||
@@ -112,10 +151,11 @@ function ProtectedSessionTimeout() {
|
||||
>
|
||||
<TimeSelector
|
||||
name="protected-session-timeout"
|
||||
optionValueId="protectedSessionTimeout" optionTimeScaleId="protectedSessionTimeoutTimeScale"
|
||||
optionValueId="protectedSessionTimeout"
|
||||
optionTimeScaleId="protectedSessionTimeoutTimeScale"
|
||||
minimumSeconds={60}
|
||||
/>
|
||||
</OptionsRow>
|
||||
</OptionsSection>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user