From 13083aecf71465fa263ef379dd3daa7ce1f69194 Mon Sep 17 00:00:00 2001 From: Tudor Stanciu Date: Tue, 28 Mar 2023 19:20:32 +0300 Subject: [PATCH] 1.2.0 - Has been implemented the "user-info" method exposed by the Tuitio API. --- README.md | 3 +- package-lock.json | 4 +- package.json | 2 +- src/__tests__/TuitioClient.test.ts | 2 +- src/__tests__/TuitioLogin.test.ts | 3 +- src/__tests__/TuitioLogout.test.ts | 3 +- src/__tests__/TuitioStorage.test.ts | 2 +- .../Validations.test.ts} | 2 +- src/client.ts | 47 ++++--------------- src/config.ts | 6 ++- src/index.ts | 7 +-- src/state.ts | 23 +++++++++ src/types.ts | 25 ++++++++++ src/utils/axios.ts | 34 ++++++++++++++ src/{utils.ts => utils/validations.ts} | 0 15 files changed, 112 insertions(+), 51 deletions(-) rename src/__tests__/{Utils.test.ts => utils/Validations.test.ts} (91%) create mode 100644 src/state.ts create mode 100644 src/types.ts create mode 100644 src/utils/axios.ts rename src/{utils.ts => utils/validations.ts} (100%) diff --git a/README.md b/README.md index ec4eed0..1481f42 100644 --- a/README.md +++ b/README.md @@ -38,4 +38,5 @@ All tests in the package can be executed by running: `npm test`. 1.0.2 - Validate that Tuitio's URL parameter is a valid URL 1.0.3 - Added LICENSE file 1.0.4 - TuitioState's token property can be null -1.1.0 - In this version, the account logout method and the latest changes published by Tuitio were implemented. +1.1.0 - In this version, the account logout method and the latest changes published by Tuitio were implemented. +1.2.0 - Has been implemented the "user-info" method exposed by the Tuitio API. diff --git a/package-lock.json b/package-lock.json index 029dd7e..c7b0ce5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@flare/tuitio-client", - "version": "1.1.0", + "version": "1.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@flare/tuitio-client", - "version": "1.1.0", + "version": "1.2.0", "license": "MIT", "dependencies": { "@flare/js-utils": "^1.0.3", diff --git a/package.json b/package.json index 84e3200..b7ec3c5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@flare/tuitio-client", - "version": "1.1.0", + "version": "1.2.0", "description": "Tuitio client is an npm package written in typescript that facilitates the integration of a javascript application with Tuitio.", "main": "./lib/index.js", "types": "./lib/index.d.ts", diff --git a/src/__tests__/TuitioClient.test.ts b/src/__tests__/TuitioClient.test.ts index 72e4f67..21e036b 100644 --- a/src/__tests__/TuitioClient.test.ts +++ b/src/__tests__/TuitioClient.test.ts @@ -2,7 +2,7 @@ import { getUrlTemplates } from "../config"; import { TuitioClient } from "../client"; -import type { TuitioLoginResponse } from "../client"; +import type { TuitioLoginResponse } from "../types"; test("Get url templates", () => { const result = getUrlTemplates("https://test.com/api"); diff --git a/src/__tests__/TuitioLogin.test.ts b/src/__tests__/TuitioLogin.test.ts index 64602b6..91b8e1b 100644 --- a/src/__tests__/TuitioLogin.test.ts +++ b/src/__tests__/TuitioLogin.test.ts @@ -5,7 +5,8 @@ // Copyright (c) 2023 Tudor Stanciu import axios from "axios"; -import { TuitioClient, fetch } from "../client"; +import { TuitioClient } from "../client"; +import { fetch } from "../state"; jest.mock("axios"); diff --git a/src/__tests__/TuitioLogout.test.ts b/src/__tests__/TuitioLogout.test.ts index 3ba8ee8..8d81659 100644 --- a/src/__tests__/TuitioLogout.test.ts +++ b/src/__tests__/TuitioLogout.test.ts @@ -5,7 +5,8 @@ // Copyright (c) 2023 Tudor Stanciu import axios from "axios"; -import { TuitioClient, fetch } from "../client"; +import { TuitioClient } from "../client"; +import { fetch } from "../state"; import { localStorage } from "@flare/js-utils"; import { storageKeys } from "../constants"; diff --git a/src/__tests__/TuitioStorage.test.ts b/src/__tests__/TuitioStorage.test.ts index cc83994..3931332 100644 --- a/src/__tests__/TuitioStorage.test.ts +++ b/src/__tests__/TuitioStorage.test.ts @@ -4,7 +4,7 @@ // Copyright (c) 2023 Tudor Stanciu -import { fetch } from "../client"; +import { fetch } from "../state"; test("Tuitio empty storage", () => { const result = fetch(); diff --git a/src/__tests__/Utils.test.ts b/src/__tests__/utils/Validations.test.ts similarity index 91% rename from src/__tests__/Utils.test.ts rename to src/__tests__/utils/Validations.test.ts index b5b9ca1..0684473 100644 --- a/src/__tests__/Utils.test.ts +++ b/src/__tests__/utils/Validations.test.ts @@ -1,6 +1,6 @@ // Copyright (c) 2023 Tudor Stanciu -import { combineUrls, isValidURL } from "../utils"; +import { combineUrls, isValidURL } from "../../utils/validations"; test("Combine urls with trailing slash", () => { const result = combineUrls("https://test.com/api/", "/test"); diff --git a/src/client.ts b/src/client.ts index ba07bbf..39e04eb 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,33 +1,15 @@ // Copyright (c) 2023 Tudor Stanciu -import axios from "axios"; +import { request } from "./utils/axios"; import { localStorage } from "@flare/js-utils"; import { storageKeys } from "./constants"; import { getUrlTemplates } from "./config"; -import { isValidURL } from "./utils"; +import { isValidURL } from "./utils/validations"; import type { UrlTemplates } from "./config"; +import type { TuitioLoginResponse, TuitioLogoutResponse, TuitioUserInfoResponse } from "./types"; const { setItem, getItem, removeItem } = localStorage; -async function request(url: string, method: string) { - try { - const res = await axios.request({ url, method }); - return res.data; - } catch (error: any) { - if (error.response && error.response.data) { - const { detail, title } = error.response.data; - throw { - ...error.response.data, - message: detail || title - }; - } - throw error; - } -} - -export type TuitioLoginResponse = { result: { token: string; expiresIn: number; validUntil: Date } | null; error: string | null }; -export type TuitioLogoutResponse = { result: { userId: number; userName: string; logoutDate: Date } | null; error: string }; - class TuitioClient { tuitioUrl: string; urlTemplates: UrlTemplates; @@ -67,22 +49,13 @@ class TuitioClient { } return response; } + + async getUserInfo(): Promise { + const url = this.urlTemplates.userInfo; + const response = await request(url, "get"); + return response; + } } -export type TuitioState = { token: string | null; validUntil: Date | null; userName: string | null }; -const defaultTuitioState: TuitioState = { token: null, validUntil: null, userName: null }; - -const fetch = (): TuitioState => { - const authData = getItem(storageKeys.AUTH_DATA); - if (!authData) return defaultTuitioState; - const { token, validUntil, userName } = authData; - const data: TuitioState = { - token, - validUntil, - userName - }; - return data; -}; - -export { TuitioClient, fetch }; +export { TuitioClient }; export default TuitioClient; diff --git a/src/config.ts b/src/config.ts index 6e57115..a426354 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,15 +1,17 @@ // Copyright (c) 2023 Tudor Stanciu -import { combineUrls } from "./utils"; +import { combineUrls } from "./utils/validations"; export type UrlTemplates = { login: string; logout: string; + userInfo: string; }; const getUrlTemplates = (tuitioUrl: string): UrlTemplates => ({ login: combineUrls(tuitioUrl, "/account/login?UserName={username}&Password={password}"), - logout: combineUrls(tuitioUrl, "/account/logout?Token={token}") + logout: combineUrls(tuitioUrl, "/account/logout?Token={token}"), + userInfo: combineUrls(tuitioUrl, "/connect/user-info") }); export { getUrlTemplates }; diff --git a/src/index.ts b/src/index.ts index 164987f..78f8717 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,9 @@ // Copyright (c) 2023 Tudor Stanciu -import { TuitioClient, fetch } from "./client"; -import type { TuitioLoginResponse, TuitioLogoutResponse, TuitioState } from "./client"; +import { TuitioClient } from "./client"; +import { fetch } from "./state"; + +export * from "./types"; export { TuitioClient, fetch }; -export type { TuitioLoginResponse, TuitioLogoutResponse, TuitioState }; export default TuitioClient; diff --git a/src/state.ts b/src/state.ts new file mode 100644 index 0000000..e1fe971 --- /dev/null +++ b/src/state.ts @@ -0,0 +1,23 @@ +// Copyright (c) 2023 Tudor Stanciu + +import { localStorage } from "@flare/js-utils"; +import { storageKeys } from "./constants"; +import type { TuitioState } from "./types"; + +const { getItem } = localStorage; + +const defaultTuitioState: TuitioState = { token: null, validUntil: null, userName: null }; + +const fetch = (): TuitioState => { + const authData = getItem(storageKeys.AUTH_DATA); + if (!authData) return defaultTuitioState; + const { token, validUntil, userName } = authData; + const data: TuitioState = { + token, + validUntil, + userName + }; + return data; +}; + +export { fetch }; diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..f0dc4e4 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,25 @@ +export type TuitioLoginResponse = { result: { token: string; expiresIn: number; validUntil: Date } | null; error: string | null }; +export type TuitioLogoutResponse = { result: { userId: number; userName: string; logoutDate: Date } | null; error: string }; +export type TuitioState = { token: string | null; validUntil: Date | null; userName: string | null }; + +export type TuitioUserContactOption = { + id: number; + contactTypeCode: string; + contactTypeName: string; + contactValue: string; +}; + +export type TuitioUserInfoResponse = { + userId: number; + userName: string; + firstName: string; + lastName: string; + email: string; + profilePictureUrl: string; + securityStamp: string; + creationDate: Date; + failedLoginAttempts: number; + lastLoginDate: Date; + claim?: object; + contactOptions?: [TuitioUserContactOption]; +}; diff --git a/src/utils/axios.ts b/src/utils/axios.ts new file mode 100644 index 0000000..a1275cc --- /dev/null +++ b/src/utils/axios.ts @@ -0,0 +1,34 @@ +// Copyright (c) 2023 Tudor Stanciu + +import axios, { AxiosHeaders } from "axios"; +import { fetch } from "../state"; + +function getHeaders(): AxiosHeaders { + const { token } = fetch(); + const headers = new AxiosHeaders({ + "Content-Type": "application/json" + }); + if (token) { + headers["Authorization"] = `Tuitio ${token}`; + } + return headers; +} + +async function request(url: string, method: string) { + const headers = getHeaders(); + try { + const res = await axios.request({ url, method, headers }); + return res.data; + } catch (error: any) { + if (error.response && error.response.data) { + const { detail, title } = error.response.data; + throw { + ...error.response.data, + message: detail || title + }; + } + throw error; + } +} + +export { request }; diff --git a/src/utils.ts b/src/utils/validations.ts similarity index 100% rename from src/utils.ts rename to src/utils/validations.ts