diff --git a/octoprint_mfa_totp/__init__.py b/octoprint_mfa_totp/__init__.py index d8a03ee..8046ccb 100644 --- a/octoprint_mfa_totp/__init__.py +++ b/octoprint_mfa_totp/__init__.py @@ -10,6 +10,7 @@ from flask_login import current_user from octoprint.plugin.types import WrongMfaCredentials from octoprint.schema import BaseModel +from octoprint.server.util.flask import ensure_credentials_checked_recently CLEANUP_CUTOFF = 60 * 30 # 30 minutes VALID_WINDOW = 1 # delay of one tick is ok @@ -149,6 +150,7 @@ def on_api_command(self, command, data): user = current_user if not user or not user.is_authenticated or not user.is_active: return abort(403) + ensure_credentials_checked_recently() userid = user.get_id() diff --git a/octoprint_mfa_totp/static/js/mfa_totp.js b/octoprint_mfa_totp/static/js/mfa_totp.js index 7b52a53..46e3fff 100644 --- a/octoprint_mfa_totp/static/js/mfa_totp.js +++ b/octoprint_mfa_totp/static/js/mfa_totp.js @@ -2,6 +2,8 @@ $(() => { function MfaTotpViewModel(parameters) { var self = this; + self.loginState = parameters[0]; + self.active = ko.observable(false); self.enrollmentKey = ko.observable(); @@ -37,55 +39,63 @@ $(() => { self.enroll = () => { self.verificationToken(""); - OctoPrint.plugins.mfa_totp.enroll().done((response) => { - self.enrollmentKey(response.key); - self.enrollmentUri(response.uri); - self.enrollmentDialog.modal("show"); - $("#mfa_totp_enrollment_token").focus(); + self.loginState.reauthenticateIfNecessary(() => { + OctoPrint.plugins.mfa_totp.enroll().done((response) => { + self.enrollmentKey(response.key); + self.enrollmentUri(response.uri); + self.enrollmentDialog.modal("show"); + $("#mfa_totp_enrollment_token").focus(); + }); }); }; self.finishEnrollment = () => { const token = self.verificationToken(); self.verificationToken(""); - OctoPrint.plugins.mfa_totp - .activate(token) - .done(() => { - self.verificationError(false); - self.mfaError(""); - self.enrollmentDialog.modal("hide"); - self.requestData(); - }) - .fail(() => { - self.verificationError(true); - }); + self.loginState.reauthenticateIfNecessary(() => { + OctoPrint.plugins.mfa_totp + .activate(token) + .done(() => { + self.verificationError(false); + self.mfaError(""); + self.enrollmentDialog.modal("hide"); + self.requestData(); + }) + .fail(() => { + self.verificationError(true); + }); + }); }; self.deactivate = () => { self.verificationToken(""); - self.verificationDialog.modal("show"); - $("#mfa_totp_verification_token").focus(); + self.loginState.reauthenticateIfNecessary(() => { + self.verificationDialog.modal("show"); + $("#mfa_totp_verification_token").focus(); + }); }; self.finishDeactivation = () => { const token = self.verificationToken(); self.verificationToken(""); self.mfaError(""); - OctoPrint.plugins.mfa_totp - .deactivate(token) - .done(() => { - self.verificationError(false); - self.mfaError(""); - self.verificationDialog.modal("hide"); - self.requestData(); - }) - .fail((xhr) => { - const response = xhrErrorJson(xhr); - if (response && response.mfa_error) { - self.mfaError(response.mfa_error); - } - self.verificationError(true); - }); + self.loginState.reauthenticateIfNecessary(() => { + OctoPrint.plugins.mfa_totp + .deactivate(token) + .done(() => { + self.verificationError(false); + self.mfaError(""); + self.verificationDialog.modal("hide"); + self.requestData(); + }) + .fail((xhr) => { + const response = xhrErrorJson(xhr); + if (response && response.mfa_error) { + self.mfaError(response.mfa_error); + } + self.verificationError(true); + }); + }); }; self.onUserSettingsShown = self.onUserLoggedIn = () => { @@ -104,7 +114,7 @@ $(() => { OCTOPRINT_VIEWMODELS.push({ construct: MfaTotpViewModel, - dependencies: [], + dependencies: ["loginStateViewModel"], elements: [ "#usersettings_mfa_plugin_mfa_totp", "#plugin_mfa_totp_enroll",