Auth: add iframe hint (#14051)
This commit is contained in:
parent
ae6cfbe10b
commit
fbf59d123e
4 changed files with 59 additions and 5 deletions
|
|
@ -26,6 +26,15 @@
|
|||
</div>
|
||||
|
||||
<p v-if="error" class="text-danger my-4">{{ $t("loginModal.error") }}{{ error }}</p>
|
||||
<a
|
||||
v-if="iframeHint"
|
||||
class="text-muted my-4 d-block text-center"
|
||||
:href="evccUrl"
|
||||
target="_blank"
|
||||
data-testid="login-iframe-hint"
|
||||
>
|
||||
{{ $t("loginModal.iframeHint") }}
|
||||
</a>
|
||||
|
||||
<button type="submit" class="btn btn-primary w-100 mb-3" :disabled="loading">
|
||||
<span
|
||||
|
|
@ -52,7 +61,7 @@
|
|||
import GenericModal from "./GenericModal.vue";
|
||||
import Modal from "bootstrap/js/dist/modal";
|
||||
import api from "../api";
|
||||
import { updateAuthStatus, getAndClearNextUrl } from "../auth";
|
||||
import { updateAuthStatus, getAndClearNextUrl, isLoggedIn } from "../auth";
|
||||
import { docsPrefix } from "../i18n";
|
||||
|
||||
export default {
|
||||
|
|
@ -64,6 +73,7 @@ export default {
|
|||
password: "",
|
||||
loading: false,
|
||||
resetHint: false,
|
||||
iframeHint: false,
|
||||
error: "",
|
||||
};
|
||||
},
|
||||
|
|
@ -71,6 +81,9 @@ export default {
|
|||
resetUrl() {
|
||||
return `${docsPrefix()}/docs/faq#password-reset`;
|
||||
},
|
||||
evccUrl() {
|
||||
return window.location.href;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
|
|
@ -82,6 +95,7 @@ export default {
|
|||
this.loading = false;
|
||||
this.error = "";
|
||||
this.resetHint = false;
|
||||
this.iframeHint = false;
|
||||
},
|
||||
focus() {
|
||||
console.log(this.$refs.password);
|
||||
|
|
@ -99,13 +113,20 @@ export default {
|
|||
validateStatus: (code) => [200, 401].includes(code),
|
||||
});
|
||||
this.resetHint = false;
|
||||
this.iframeHint = false;
|
||||
this.error = "";
|
||||
if (res.status === 200) {
|
||||
this.closeModal();
|
||||
await updateAuthStatus();
|
||||
const target = getAndClearNextUrl();
|
||||
if (target) this.$router.push(target);
|
||||
this.password = "";
|
||||
if (isLoggedIn()) {
|
||||
this.closeModal();
|
||||
const target = getAndClearNextUrl();
|
||||
if (target) this.$router.push(target);
|
||||
this.password = "";
|
||||
} else {
|
||||
// login successful but auth cookie doesnt work
|
||||
this.error = this.$t("loginModal.iframeIssue");
|
||||
this.iframeHint = true;
|
||||
}
|
||||
}
|
||||
if (res.status === 401) {
|
||||
this.error = this.$t("loginModal.invalid");
|
||||
|
|
|
|||
|
|
@ -234,6 +234,8 @@ update = "Aktualisieren"
|
|||
[loginModal]
|
||||
cancel = "Abbrechen"
|
||||
error = "Login fehlgeschlagen: "
|
||||
iframeHint = "Öffne evcc in einem neuen Tab."
|
||||
iframeIssue = "Das Passwort ist korrekt, aber dein Browser hat das Authentifizierungscookie abgelehnt. Dies kann passieren, wenn du evcc in einem iframe über HTTP verwendest."
|
||||
invalid = "Passwort ist ungültig."
|
||||
login = "Anmelden"
|
||||
password = "Passwort"
|
||||
|
|
|
|||
|
|
@ -233,6 +233,8 @@ update = "Auto update"
|
|||
[loginModal]
|
||||
cancel = "Cancel"
|
||||
error = "Login failed: "
|
||||
iframeHint = "Open evcc in a new tab."
|
||||
iframeIssue = "Your password is correct, but your browser seems to have dropped the authentication cookie. This can happen if you run evcc in an iframe via HTTP."
|
||||
invalid = "Password is invalid."
|
||||
login = "Login"
|
||||
password = "Password"
|
||||
|
|
|
|||
|
|
@ -63,6 +63,35 @@ test("login", async ({ page }) => {
|
|||
await expect(page.getByRole("heading", { name: "Configuration" })).toBeVisible();
|
||||
});
|
||||
|
||||
test("http iframe hint", async ({ page }) => {
|
||||
// set initial password
|
||||
const modal = page.getByTestId("password-modal");
|
||||
await modal.getByLabel("New password").fill("secret");
|
||||
await modal.getByLabel("Repeat password").fill("secret");
|
||||
await modal.getByRole("button", { name: "Create Password" }).click();
|
||||
|
||||
// go to config
|
||||
await page.getByTestId("topnavigation-button").click();
|
||||
await page.getByRole("link", { name: "Configuration" }).click();
|
||||
|
||||
// login modal
|
||||
const login = page.getByTestId("login-modal");
|
||||
await expect(login).toBeVisible();
|
||||
await expect(login.getByRole("heading", { name: "Authentication" })).toBeVisible();
|
||||
|
||||
// rewrite api call to simulate lost auth cookie
|
||||
await page.route("**/api/auth/status", (route) => {
|
||||
route.fulfill({ status: 200, body: "false" });
|
||||
});
|
||||
|
||||
// enter correct password
|
||||
await login.getByLabel("Password").fill("secret");
|
||||
await login.getByRole("button", { name: "Login" }).click();
|
||||
|
||||
// iframe hint visible (login-iframe-hint)
|
||||
await expect(login.getByTestId("login-iframe-hint")).toBeVisible();
|
||||
});
|
||||
|
||||
test("update password", async ({ page }) => {
|
||||
const oldPassword = "secret";
|
||||
const newPassword = "newsecret";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue