@uprtcl/http-provider
Version:
_Prtcl provider wrappers around the native fetch api
491 lines (479 loc) • 16.4 kB
JavaScript
(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