UNPKG

@uprtcl/http-provider

Version:

_Prtcl provider wrappers around the native fetch api

491 lines (479 loc) 16.4 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@uprtcl/evees'), require('ethers'), require('@auth0/auth0-spa-js')) : typeof define === 'function' && define.amd ? define(['exports', '@uprtcl/evees', 'ethers', '@auth0/auth0-spa-js'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global['uprtcl-http-provider'] = {}, global.evees, global.ethers, global.auth0SpaJs)); }(this, (function (exports, evees, ethers, auth0SpaJs) { 'use strict'; class AuthTokenStorage { constructor(tokenStorageId, userStorageId) { this.tokenStorageId = tokenStorageId; this.userStorageId = userStorageId; } get authToken() { const token = localStorage.getItem(this.tokenStorageId); if (token === null) return undefined; return token; } set authToken(token) { if (token !== undefined) { localStorage.setItem(this.tokenStorageId, token); } else { localStorage.removeItem(this.tokenStorageId); } } get userId() { const userId = localStorage.getItem(this.userStorageId); if (userId === null) return undefined; return userId; } set userId(userId) { if (this.userStorageId == null) { return; } if (userId !== undefined) { localStorage.setItem(this.userStorageId, userId); } else { localStorage.removeItem(this.userStorageId); } } } /** Exposes wrappers to FETCH methods, and injects the header authentication * credentials (provided by HttpAuthentication service) */ class HttpAuthenticatedConnectionImp { constructor(host, authentication, tokenStorageId, userStorageId) { this.host = host; this.authentication = authentication; this.logger = new evees.Logger('HTTP CONNECTION'); if (tokenStorageId && userStorageId) { this.tokenStore = new AuthTokenStorage(tokenStorageId, userStorageId); } } get userId() { return this.tokenStore.userId; } async login() { if (!this.authentication) throw new Error('Authentication service not defined'); const token = await this.authentication.obtainToken(); if (token.jwt && token.userId) { this.tokenStore.authToken = 'Bearer ' + token.jwt; this.tokenStore.userId = token.userId; const isValid = await this.get('/user/isAuthorized'); if (!isValid) { this.logout(); } } } async connect() { } async isConnected() { return true; } async disconnect() { } async isLogged() { return this.userId !== undefined; } async logout() { this.tokenStore.userId = undefined; this.tokenStore.authToken = undefined; } get headers() { const headers = { 'Content-Type': 'application/json', }; if (this.tokenStore && this.tokenStore.authToken) { headers['Authorization'] = this.tokenStore.authToken; } return headers; } async get(url) { return fetch(this.host + url, { method: 'GET', headers: this.headers, }) .then((response) => { if (!response.ok) { throw new Error(response.statusText); } return response.json(); }) .then((getResult) => { if (getResult.result === 'error') { throw new Error(`Error fetching url: ${url}`); } return getResult.data; }); } async getWithPut(url, body) { return fetch(this.host + url, { method: 'PUT', headers: this.headers, body: JSON.stringify(body), }) .then((response) => { if (!response.ok) { throw new Error(response.statusText); } return response.json(); }) .then((data) => { return data.data; }); } async put(url, body) { return this.putOrPost(url, body, 'PUT'); } async post(url, body) { return this.putOrPost(url, body, 'POST'); } async delete(url, body = {}) { return fetch(url, { method: 'DELETE', headers: { ...this.headers, Accept: 'application/json', }, body: JSON.stringify(body), }) .then((response) => { return response.json(); }) .then((data) => { return data; }); } async putOrPost(url, body, method) { return fetch(this.host + url, { method: method, headers: { ...this.headers, Accept: 'application/json', }, body: JSON.stringify(body), }) .then((response) => { return response.json(); }) .then((data) => { return data; }); } } class HttpMultiConnection { constructor(host, connections, selected) { this.host = host; this.connections = connections; this.selected = selected; } select(selected) { this.selected = selected; } connection() { if (this.selected) { const connection = this.connections.get(this.selected); if (!connection) throw new Error(`connection ${this.selected} not found.`); return connection; } throw new Error('Connection not selected'); } get userId() { return this.connection().userId; } connect() { return this.connection().connect(); } isConnected() { return this.connection().isConnected(); } disconnect() { return this.connection().disconnect(); } isLogged() { return this.connection().isLogged(); } login() { return this.connection().login(); } logout() { return this.connection().logout(); } get(url) { return this.connection().get(url); } getWithPut(url, body) { return this.connection().getWithPut(url, body); } put(url, body) { return this.connection().put(url, body); } post(url, body) { return this.connection().post(url, body); } delete(url, body) { return this.connection().delete(url, body); } putOrPost(url, body, method) { return this.connection().putOrPost(url, body, method); } } const loginMessage = (nonce) => { return `Login to Intercreativity \n\nnonce:${nonce}`; }; class HttpEthToken { constructor(host) { this.host = host; this.store = new AuthTokenStorage('ETH_AUTH_TOKEN', 'ETH_USER_ID'); this.connection = new HttpAuthenticatedConnectionImp(host); } async obtainToken() { await window['ethereum'].enable(); const provider = new ethers.ethers.providers.Web3Provider(window['ethereum']); const signer = provider.getSigner(); const userId = (await signer.getAddress()).toLocaleLowerCase(); const nonce = await this.connection.get(`/user/${userId}/nonce`); const signature = await signer.signMessage(loginMessage(nonce)); const result = await this.connection.getWithPut(`/user/${userId}/authorize`, { signature, }); return { userId, jwt: result.jwt, }; } } class HttpEthConnection extends HttpAuthenticatedConnectionImp { constructor(host) { super(host, new HttpEthToken(host), 'ETH_AUTH_TOKEN', 'ETH_USER_ID'); } } class HttpAuth0Token { constructor(auth0Config) { this.store = new AuthTokenStorage('ETH_AUTH_TOKEN', 'ETH_USER_ID'); this.auth0 = new auth0SpaJs.Auth0Client(auth0Config); } async obtainToken() { if (this.checkLoginCallback()) { return this.parseLoginResult(); } const url = window.location.origin + window.location.pathname; const options = { redirect_uri: url, appState: { targetUrl: url }, }; await this.auth0.loginWithRedirect(options); /** It should never reach this plint (Auth0 redirects) */ return { userId: '', jwt: '' }; } checkLoginCallback() { const query = window.location.search; return query.includes('code=') && query.includes('state='); } async parseLoginResult() { const result = await this.auth0.handleRedirectCallback(); if (result.appState && result.appState.targetUrl) { const user = await this.auth0.getUser(); if (!user) throw new Error('User undefined'); const auth0Claims = await this.auth0.getIdTokenClaims(); const url = window.location.origin + window.location.pathname; window.history.replaceState({}, document.title, url); if (!user.sub) throw new Error('user id undefined'); return { userId: user.sub, jwt: auth0Claims.__raw }; } throw new Error('Error parsing redirect'); } } class HttpAuth0Connection extends HttpAuthenticatedConnectionImp { constructor(host, auth0Config) { super(host, new HttpAuth0Token(auth0Config), 'AUTH0_AUTH_TOKEN', 'AUTH0_USER_ID'); } /** overide to check for auth0 callback and login from there */ async isLogged() { if (!this.authentication) return false; const auth0TokenService = this.authentication; if (auth0TokenService.checkLoginCallback()) { const token = await auth0TokenService.parseLoginResult(); if (token.jwt && token.userId) { this.tokenStore.authToken = 'Bearer ' + token.jwt; this.tokenStore.userId = token.userId; const isValid = await this.get('/user/isAuthorized'); if (!isValid) { await this.logout(); return false; } return true; } else { throw new Error('Token details not retrieved'); } } return super.isLogged(); } } class HttpTestToken { constructor(user) { this.user = user; } async obtainToken() { return { userId: this.user.userId, jwt: this.user.jwt, }; } } class HttpAuthenticatedTestConnectionImp { constructor(host, authentication, tokenStorageId, userStorageId) { this.host = host; this.authentication = authentication; this.userToken = tokenStorageId; this.userId = userStorageId; } async login() { } async connect() { } async isConnected() { return true; } async disconnect() { } async isLogged() { return this.userId !== undefined; } async logout() { } get headers() { const headers = { 'Content-Type': 'application/json', }; if (this.userToken) { headers['Authorization'] = this.userToken; } return headers; } async get(url) { return fetch(this.host + url, { method: 'GET', headers: this.headers, }) .then((response) => { if (!response.ok) { throw new Error(response.statusText); } return response.json(); }) .then((getResult) => { // this.logger.log('[HTTP GET RESULT] ', url, getResult); if (getResult.result === 'error') { throw new Error(`Error fetching url: ${url}`); } return getResult.data; }); } async getWithPut(url, body) { return fetch(this.host + url, { method: 'PUT', headers: this.headers, body: JSON.stringify(body), }) .then((response) => { if (!response.ok) { throw new Error(response.statusText); } return response.json(); }) .then((data) => { return data.data; }); } async put(url, body) { return this.putOrPost(url, body, 'PUT'); } async post(url, body) { return this.putOrPost(url, body, 'POST'); } async delete(url) { return fetch(url, { method: 'DELETE', headers: { ...this.headers, Accept: 'application/json', }, }) .then((response) => { return response.json(); }) .then((data) => { return data; }); } async putOrPost(url, body, method) { return fetch(this.host + url, { method: method, headers: { ...this.headers, Accept: 'application/json', }, body: JSON.stringify(body), }) .then((response) => { return response.json(); }) .then((data) => { return data; }); } } class HttpTestConnection extends HttpAuthenticatedTestConnectionImp { constructor(host, user) { super(host, new HttpTestToken(user), user.jwt, user.userId); } } class HttpSupertest { constructor(host, user) { this.host = host; this.user = user; } connection() { return new HttpTestConnection(this.host, this.user); } async connect() { } async isConnected() { return true; } async disconnect() { } async login() { } async isLogged() { return this.user.userId !== undefined; } async logout() { } get(url) { return this.connection().get(url); } getWithPut(url, body) { return this.connection().getWithPut(url, body); } put(url, body) { return this.connection().put(url, body); } post(url, body) { return this.connection().post(url, body); } delete(url) { return this.connection().delete(url); } putOrPost(url, body, method) { return this.connection().putOrPost(url, body, method); } } exports.HttpAuth0Connection = HttpAuth0Connection; exports.HttpAuth0Token = HttpAuth0Token; exports.HttpAuthenticatedConnectionImp = HttpAuthenticatedConnectionImp; exports.HttpEthConnection = HttpEthConnection; exports.HttpEthToken = HttpEthToken; exports.HttpMultiConnection = HttpMultiConnection; exports.HttpSupertest = HttpSupertest; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=uprtcl-http-provider.umd.js.map