1.0.2 - Validate that Tuitio's URL parameter is a valid URL

master
Tudor Stanciu 2023-02-11 17:42:05 +02:00
parent e39de52ed0
commit b743f3a90c
4 changed files with 66 additions and 17 deletions

View File

@ -1,18 +1,7 @@
import { getUrlTemplates } from "../config"; import { getUrlTemplates } from "../config";
import { combineUrls } from "../utils";
import { TuitioClient } from "../client"; import { TuitioClient } from "../client";
import type { TuitioAuthenticationResult, TuitioToken } from "../client"; import type { TuitioAuthenticationResult, TuitioToken } from "../client";
test("Combine urls with trailing slash", () => {
const result = combineUrls("https://test.com/api/", "/test");
expect(result).toBe("https://test.com/api/test");
});
test("Combine urls without trailing slash", () => {
const result = combineUrls("https://test.com/api", "/test");
expect(result).toBe("https://test.com/api/test");
});
test("Get url templates", () => { test("Get url templates", () => {
const result = getUrlTemplates("https://test.com/api"); const result = getUrlTemplates("https://test.com/api");
expect(result).toHaveProperty("authentication"); expect(result).toHaveProperty("authentication");
@ -23,7 +12,23 @@ test("Get url templates", () => {
test("Tuitio client initialization", () => { test("Tuitio client initialization", () => {
const client = new TuitioClient("https://test.com/api"); const client = new TuitioClient("https://test.com/api");
expect(client.baseUrl).toBe("https://test.com/api"); expect(client.tuitioUrl).toBe("https://test.com/api");
});
test("Tuitio client initialization with null URL", () => {
try {
new TuitioClient(null);
} catch (error: any) {
expect(error.message).toContain("is not a valid URL");
}
});
test("Tuitio client initialization with invalid URL", () => {
try {
new TuitioClient("test");
} catch (error: any) {
expect(error.message).toContain("is not a valid URL");
}
}); });
test("Tuitio client fake authentication", async () => { test("Tuitio client fake authentication", async () => {

View File

@ -0,0 +1,26 @@
import { combineUrls, isValidURL } from "../utils";
test("Combine urls with trailing slash", () => {
const result = combineUrls("https://test.com/api/", "/test");
expect(result).toBe("https://test.com/api/test");
});
test("Combine urls without trailing slash", () => {
const result = combineUrls("https://test.com/api", "/test");
expect(result).toBe("https://test.com/api/test");
});
test("Check valid https URL", () => {
const result = isValidURL("https://test.com/api");
expect(result).toBe(true);
});
test("Check valid http URL", () => {
const result = isValidURL("http://test.com/api");
expect(result).toBe(true);
});
test("Check invalid URL", () => {
const result = isValidURL("test/api");
expect(result).toBe(false);
});

View File

@ -2,6 +2,7 @@ import axios from "axios";
import { localStorage } from "@flare/js-utils"; import { localStorage } from "@flare/js-utils";
import { storageKeys } from "./constants"; import { storageKeys } from "./constants";
import { getUrlTemplates } from "./config"; import { getUrlTemplates } from "./config";
import { isValidURL } from "./utils";
const { setItem, getItem, removeItem } = localStorage; const { setItem, getItem, removeItem } = localStorage;
@ -25,14 +26,18 @@ export type TuitioToken = { raw: string; validFrom: Date; validUntil: Date };
export type TuitioAuthenticationResult = { token: TuitioToken; status: string }; export type TuitioAuthenticationResult = { token: TuitioToken; status: string };
class TuitioClient { class TuitioClient {
baseUrl: string; tuitioUrl: string;
constructor(baseUrl: string) { constructor(tuitioUrl: string | null) {
this.baseUrl = baseUrl; if (tuitioUrl === null || tuitioUrl === "" || isValidURL(tuitioUrl) === false) {
throw new Error(`TuitioClient: ${tuitioUrl} is not a valid URL.`);
}
this.tuitioUrl = tuitioUrl;
} }
async authenticate(userName: string, password: string): Promise<TuitioAuthenticationResult> { async authenticate(userName: string, password: string): Promise<TuitioAuthenticationResult> {
const templates = getUrlTemplates(this.baseUrl); const templates = getUrlTemplates(this.tuitioUrl);
const url = templates.authentication.replace("{username}", userName).replace("{password}", password); const url = templates.authentication.replace("{username}", userName).replace("{password}", password);
const response = await request(url, "post"); const response = await request(url, "post");

View File

@ -4,4 +4,17 @@ const combineUrls = (piece1: string, piece2: string): string => {
return baseElement + piece2; return baseElement + piece2;
}; };
export { combineUrls }; const isValidURL = (str: string): boolean => {
const pattern = new RegExp(
"^(https?:\\/\\/)?" + // protocol
"((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|" + // domain name
"((\\d{1,3}\\.){3}\\d{1,3}))" + // OR ip (v4) address
"(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*" + // port and path
"(\\?[;&a-z\\d%_.~+=-]*)?" + // query string
"(\\#[-a-z\\d_]*)?$",
"i"
); // fragment locater
return !!pattern.test(str);
};
export { combineUrls, isValidURL };