From c63307fe4cad4124f960ea02c009c2728344867d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Poizat?= Date: Thu, 7 Nov 2024 17:36:24 +0100 Subject: [PATCH] feat: Check if both Cozy blue or Cozy gl exists Also refactored a little the CozySanitizeUrlService. --- apps/browser/src/_locales/en/messages.json | 8 +---- apps/browser/src/_locales/fr/messages.json | 8 +---- apps/browser/src/auth/popup/home.component.ts | 34 ++++++++++++++----- .../auth/popup/login.component.functions.ts | 21 ------------ .../cozySanitizeUrl.service.spec.ts} | 29 ++++++++-------- .../popup/services/cozySanitizeUrl.service.ts | 17 ++++++++++ 6 files changed, 58 insertions(+), 59 deletions(-) delete mode 100644 apps/browser/src/auth/popup/login.component.functions.ts rename apps/browser/src/popup/{accounts/login.component.spec.ts => services/cozySanitizeUrl.service.spec.ts} (70%) diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index e263c68d771..12ea49b6194 100755 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -759,13 +759,7 @@ "message": "Woops, the address is not correct. Try with \"cozy\" with a \"z\"!" }, "noCozyFound": { - "message": "Unable to connect to address $VALUE$, please check that this is the address of your Cozy", - "placeholders": { - "value": { - "content": "$1", - "example": "https://alice.mycozy.cloud" - } - } + "message": "Unable to connect to given address, please check that this is the address of your Cozy" }, "masterPassRequired": { "message": "Master password is required." diff --git a/apps/browser/src/_locales/fr/messages.json b/apps/browser/src/_locales/fr/messages.json index b7369e13de4..97601035548 100755 --- a/apps/browser/src/_locales/fr/messages.json +++ b/apps/browser/src/_locales/fr/messages.json @@ -759,13 +759,7 @@ "message": "Oups, ce n'est pas la bonne adresse. Essayez d'écrire \"cozy\" avec un \"z\" !" }, "noCozyFound": { - "message": "Impossible de se connecter à l'adresse $VALUE$, veuillez vérifier que c’est bien l’adresse de votre Cozy", - "placeholders": { - "value": { - "content": "$1", - "example": "https://alice.mycozy.cloud" - } - } + "message": "Impossible de se connecter à l'adresse donnée, veuillez vérifier que c’est bien l’adresse de votre Cozy" }, "masterPassRequired": { "message": "Le mot de passe principal est requis." diff --git a/apps/browser/src/auth/popup/home.component.ts b/apps/browser/src/auth/popup/home.component.ts index e26cce2a7bd..84878cff898 100644 --- a/apps/browser/src/auth/popup/home.component.ts +++ b/apps/browser/src/auth/popup/home.component.ts @@ -14,7 +14,6 @@ import { ToastService } from "@bitwarden/components"; import { BrowserApi } from "../../platform/browser/browser-api"; import { CozySanitizeUrlService } from "../../popup/services/cozySanitizeUrl.service"; import { AccountSwitcherService } from "./account-switching/services/account-switcher.service"; -import { sanitizeUrlInput } from "./login.component.functions"; /* eslint-enable */ /* end Cozy imports */ @@ -102,20 +101,38 @@ export class HomeComponent implements OnInit, OnDestroy { } // Cozy customization; check if Cozy exists before navigating to login page - const cozyUrl = sanitizeUrlInput(this.formGroup.value.email, this.cozySanitizeUrlService); + const cozyUrl = this.cozySanitizeUrlService.sanitizeUrlInput(this.formGroup.value.email); + const glUrl = this.cozySanitizeUrlService.sanitizeUrlInput( + this.formGroup.value.email, + ".cozygrandlyon.cloud", + ); + let selectedUrl = null; + + const cozyExist = await this.cozyExist(cozyUrl); + if (cozyExist) { + selectedUrl = cozyUrl; + } else { + const glExist = await this.cozyExist(glUrl); + if (glExist) { + selectedUrl = glUrl; + } + } - if (await this.cozyDoesNotExist(cozyUrl)) { + if (!selectedUrl) { this.toastService.showToast({ variant: "error", title: this.i18nService.t("errorOccured"), - message: this.i18nService.t("noCozyFound", cozyUrl), + message: this.i18nService.t("noCozyFound"), }); return; } + // Cozy customization end await this.setLoginEmailValues(); - await this.router.navigate(["login"], { queryParams: { email: this.formGroup.value.email, cozyUrl } }); + await this.router.navigate(["login"], { + queryParams: { email: this.formGroup.value.email, cozyUrl: selectedUrl }, + }); } async setLoginEmailValues() { @@ -132,19 +149,18 @@ export class HomeComponent implements OnInit, OnDestroy { /* end custo */ // Cozy customization; check if Cozy exists before navigating to login page - async cozyDoesNotExist(cozyUrl: string) { + async cozyExist(cozyUrl: string) { const preloginCozyUrl = new URL("/public/prelogin", cozyUrl).toString(); try { const preloginCozyResponse = await fetch(preloginCozyUrl); - return preloginCozyResponse.status === 404; + return preloginCozyResponse.status === 200; } catch { // If the request fails, we assume the Cozy does not exist. // It happens if the user enter a valid URL but that does not answer. - return true; + return false; } - } // Cozy customization end } diff --git a/apps/browser/src/auth/popup/login.component.functions.ts b/apps/browser/src/auth/popup/login.component.functions.ts deleted file mode 100644 index b41bf9e754a..00000000000 --- a/apps/browser/src/auth/popup/login.component.functions.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { CozySanitizeUrlService } from "../../popup/services/cozySanitizeUrl.service"; - -export const sanitizeUrlInput = ( - inputUrl: string, - cozySanitizeUrlService: CozySanitizeUrlService, -): string => { - // Prevent empty url - if (!inputUrl) { - throw new Error("cozyUrlRequired"); - } - // Prevent email input - if (inputUrl.includes("@")) { - throw new Error("noEmailAsCozyUrl"); - } - - if (cozySanitizeUrlService.hasMispelledCozy(inputUrl)) { - throw new Error("hasMispelledCozy"); - } - - return cozySanitizeUrlService.normalizeURL(inputUrl, cozySanitizeUrlService.cozyDomain); -}; diff --git a/apps/browser/src/popup/accounts/login.component.spec.ts b/apps/browser/src/popup/services/cozySanitizeUrl.service.spec.ts similarity index 70% rename from apps/browser/src/popup/accounts/login.component.spec.ts rename to apps/browser/src/popup/services/cozySanitizeUrl.service.spec.ts index 9f28aa9d725..91ba22e0886 100644 --- a/apps/browser/src/popup/accounts/login.component.spec.ts +++ b/apps/browser/src/popup/services/cozySanitizeUrl.service.spec.ts @@ -1,5 +1,4 @@ -import { sanitizeUrlInput } from "../../auth/popup/login.component.functions"; -import { CozySanitizeUrlService } from "../services/cozySanitizeUrl.service"; +import { CozySanitizeUrlService } from "./cozySanitizeUrl.service"; describe("url input", () => { const cozySanitizeUrlService = new CozySanitizeUrlService(); @@ -7,69 +6,69 @@ describe("url input", () => { it("should return undefined if the input is empty", () => { const inputUrl = ""; expect(() => { - sanitizeUrlInput(inputUrl, cozySanitizeUrlService); + cozySanitizeUrlService.sanitizeUrlInput(inputUrl); }).toThrow(new Error("cozyUrlRequired")); }); it("should return undefined if the input is an email", () => { const inputUrl = "claude@cozycloud.cc"; expect(() => { - sanitizeUrlInput(inputUrl, cozySanitizeUrlService); + cozySanitizeUrlService.sanitizeUrlInput(inputUrl); }).toThrow(new Error("noEmailAsCozyUrl")); }); it("should return the url without the app slug if present", () => { const inputUrl = "claude-drive.mycozy.cloud"; - const url = sanitizeUrlInput(inputUrl, cozySanitizeUrlService); + const url = cozySanitizeUrlService.sanitizeUrlInput(inputUrl); expect(url).toEqual("https://claude.mycozy.cloud"); }); it("should return the url with the default domain if missing", () => { const inputUrl = "claude-drive"; - const url = sanitizeUrlInput(inputUrl, cozySanitizeUrlService); + const url = cozySanitizeUrlService.sanitizeUrlInput(inputUrl); expect(url).toEqual("https://claude.mycozy.cloud"); }); it("should return the url with the default scheme if missing", () => { const inputUrl = "claude.mycozy.cloud"; - const url = sanitizeUrlInput(inputUrl, cozySanitizeUrlService); + const url = cozySanitizeUrlService.sanitizeUrlInput(inputUrl); expect(url).toEqual("https://claude.mycozy.cloud"); }); it("should return the url if the input is correct", () => { const inputUrl = "https://claude.mycozy.cloud"; - const url = sanitizeUrlInput(inputUrl, cozySanitizeUrlService); + const url = cozySanitizeUrlService.sanitizeUrlInput(inputUrl); expect(url).toEqual("https://claude.mycozy.cloud"); }); it("should accept local url", () => { const inputUrl = "http://claude.cozy.tools:8080"; - const url = sanitizeUrlInput(inputUrl, cozySanitizeUrlService); + const url = cozySanitizeUrlService.sanitizeUrlInput(inputUrl); expect(url).toEqual("http://claude.cozy.tools:8080"); }); it("should not try to remove slug if present and url has a custom domain", () => { const inputUrl = "claude-drive.on-premise.cloud"; - const url = sanitizeUrlInput(inputUrl, cozySanitizeUrlService); + const url = cozySanitizeUrlService.sanitizeUrlInput(inputUrl); expect(url).toEqual("https://claude-drive.on-premise.cloud"); }); it("should return the correct url if domains contains a dash", () => { const inputUrl = "claude.on-premise.cloud"; - const url = sanitizeUrlInput(inputUrl, cozySanitizeUrlService); + const url = cozySanitizeUrlService.sanitizeUrlInput(inputUrl); expect(url).toEqual("https://claude.on-premise.cloud"); }); it("should return the correct url if domains contains a dash and cozy is installed on domain root", () => { const inputUrl = "https://on-premise.cloud"; - const url = sanitizeUrlInput(inputUrl, cozySanitizeUrlService); + const url = cozySanitizeUrlService.sanitizeUrlInput(inputUrl); expect(url).toEqual("https://on-premise.cloud"); }); it(`should throw if user write 'mycosy' instead of 'mycozy'`, () => { const inputUrl = "https://claude.mycosy.cloud"; expect(() => { - sanitizeUrlInput(inputUrl, cozySanitizeUrlService); + cozySanitizeUrlService.sanitizeUrlInput(inputUrl); }).toThrow(new Error("hasMispelledCozy")); }); it(`should accept real '*cosy*' url`, () => { const inputUrl = "https://claude.realdomaincosy.cloud"; - const url = sanitizeUrlInput(inputUrl, cozySanitizeUrlService); + const url = cozySanitizeUrlService.sanitizeUrlInput(inputUrl); expect(url).toEqual("https://claude.realdomaincosy.cloud"); }); it(`should remove trailing / in url`, () => { const inputUrl = "https://claude.realdomaincosy.cloud/"; - const url = sanitizeUrlInput(inputUrl, cozySanitizeUrlService); + const url = cozySanitizeUrlService.sanitizeUrlInput(inputUrl); expect(url).toEqual("https://claude.realdomaincosy.cloud"); }); }); diff --git a/apps/browser/src/popup/services/cozySanitizeUrl.service.ts b/apps/browser/src/popup/services/cozySanitizeUrl.service.ts index 53bf2fa921b..c1de0c823d4 100644 --- a/apps/browser/src/popup/services/cozySanitizeUrl.service.ts +++ b/apps/browser/src/popup/services/cozySanitizeUrl.service.ts @@ -31,4 +31,21 @@ export class CozySanitizeUrlService { }; protected removeTrailingSlash = (value: string) => value.replace(/\/$/, ""); + + sanitizeUrlInput = (inputUrl: string, domain: string = this.cozyDomain): string => { + // Prevent empty url + if (!inputUrl) { + throw new Error("cozyUrlRequired"); + } + // Prevent email input + if (inputUrl.includes("@")) { + throw new Error("noEmailAsCozyUrl"); + } + + if (this.hasMispelledCozy(inputUrl)) { + throw new Error("hasMispelledCozy"); + } + + return this.normalizeURL(inputUrl, domain); + }; }