diff --git a/src/components/GoToSpringboardModal.vue b/src/components/GoToSpringboardModal.vue index 4cb0660..f534f0b 100644 --- a/src/components/GoToSpringboardModal.vue +++ b/src/components/GoToSpringboardModal.vue @@ -1,5 +1,5 @@ diff --git a/src/services/hbs.js b/src/services/hbs.js index 24aa809..1bf9c97 100644 --- a/src/services/hbs.js +++ b/src/services/hbs.js @@ -1,46 +1,43 @@ import axios from 'axios' -import { AUTH_SERVICE_URL, AUTH_SERVICE_VERSION } from '../utils/hbsConfiguration' +import { authServiceUrl, authServiceVersion } from '../utils/hbsConfiguration' import { httpCall } from '../utils/httpProvider' -import { useHoloStore } from 'src/stores' -async function authCall(args) { +export const kycLevel1 = 'holo_kyc_1' +export const kycLevel2 = 'holo_kyc_2' + +async function authCall(args, envirionment, hbsServicePort) { return httpCall({ - serviceUrl: AUTH_SERVICE_URL, - version: AUTH_SERVICE_VERSION, + serviceUrl: authServiceUrl(envirionment), + version: authServiceVersion(hbsServicePort), method: 'post', ...args }) } - export async function authenticateAgent(email, public_key) { - console.log(`hbs->authenticateAgent - email: ${email} public_key: ${public_key}`) - - const holoStore = useHoloStore(); - const payload = { - "email": email, - "timestamp": Date.now() - (30 * 1000), // Subtract 30 sec to prevent "future" timestamp error from API - "pubKey": public_key - } - - const { _, signature } = await holoStore.signPayload(payload) - console.log(`authenticateAgent - signature: ${signature}`, payload) +export async function authenticateAgent(payload, signature, envirionment, hbsServicePort) { + try { + const result = await authCall({ + params: payload, + endpoint: 'holo-client', + headers: { + 'X-Signature': signature + }, + envirionment, + hbsServicePort + }) - try { - const result = await authCall({ - params: payload, - endpoint: 'holo-client', - headers: { - 'X-Signature': signature - } - }) - - return result.data - } catch (e) { - if (axios.isAxiosError(e)) { - return e.message - } else { - return 'unknown error' - } + return result.data + } catch (e) { + if (axios.isAxiosError(e)) { + return e.message + } else { + return 'unknown error' } } +} + +export async function fetchAgentKycLevel(payload, signature, envirionment, hbsServicePort) { + const authResult = await authenticateAgent(payload, signature, envirionment, hbsServicePort) + return (authResult && authResult.kyc) ? (authResult.kyc === kycLevel2) ? 2 : 1 : null +} \ No newline at end of file diff --git a/src/stores/useClientStore.js b/src/stores/useClientStore.js index a3825f5..aabe342 100644 --- a/src/stores/useClientStore.js +++ b/src/stores/useClientStore.js @@ -5,10 +5,12 @@ import { encodeAgentId } from '../utils/agent' const makeUseClientStore = ({ useInterfaceStore, onInit }) => defineStore('client', { state: () => ({ agentKey: null, // the Uint8Array of raw bytes. See also agentId in getters, below - isReady: false + isReady: false, + agentKyc: null }), getters: { - agentId: state => state.agentKey && encodeAgentId(state.agentKey) + agentId: state => state.agentKey && encodeAgentId(state.agentKey), + agentKycLevel: state => state.agentKyc }, actions: { async initialize() { @@ -45,6 +47,12 @@ const makeUseClientStore = ({ useInterfaceStore, onInit }) => defineStore('clien return result }, + + async loadAgentKycLevel(envirionment, hbsServicePort) { + const kycLevel = await useInterfaceStore().loadAgentKycLevel(envirionment, hbsServicePort) + this.agentKyc = kycLevel + return kycLevel + } } }) diff --git a/src/stores/useHoloBusinessServiceStore.js b/src/stores/useHoloBusinessServiceStore.js deleted file mode 100644 index e8e6b29..0000000 --- a/src/stores/useHoloBusinessServiceStore.js +++ /dev/null @@ -1,35 +0,0 @@ -import { defineStore } from 'pinia' -import { authenticateAgent } from "../services/hbs" - -const kycLevel1 = 'holo_kyc_1' -const kycLevel2 = 'holo_kyc_2' - -const useHoloBusinessServiceStore = defineStore('hbs', { - state: () => ({ - agentKeyLevel: null - }), - actions: { - async loadAgentKycLevel(email, public_key) { - - const authResult = await authenticateAgent(email, public_key) - if( authResult && authResult.kyc ) { - switch(authResult.kyc) { - case kycLevel1: { - this.agentKeyLevel = 1 - break - } - case kycLevel2: { - this.agentKeyLevel = 2 - break - } - default: { - this.agentKeyLevel = null - } - } - - } - } - } -}) - -export default useHoloBusinessServiceStore diff --git a/src/stores/useHoloStore.js b/src/stores/useHoloStore.js index 7aafdab..4611ce1 100644 --- a/src/stores/useHoloStore.js +++ b/src/stores/useHoloStore.js @@ -2,6 +2,7 @@ import WebSdk from '@holo-host/web-sdk' import { defineStore } from 'pinia' import useIsLoadingStore from './useIsLoadingStore' import useSignalStore from './useSignalStore' +import { fetchAgentKycLevel } from '../services/hbs' let client @@ -13,7 +14,8 @@ const makeUseHoloStore = ({ connectionArgs, MockWebSdk }) => defineStore('holo', isAuthFormOpen: false, // These two values are subscribed to by clientStore isReady: false, - appInfo: null + appInfo: null, + kycLevel: null }), getters: { isAnonymous: state => state.agentState && state.agentState.isAnonymous, @@ -22,7 +24,8 @@ const makeUseHoloStore = ({ connectionArgs, MockWebSdk }) => defineStore('holo', error: state => state.agentState && !state.agentState.isAvailable && (state.connectionError || state.agentState.unrecoverableError), agentKey: (state) => state.appInfo?.agent_pub_key, agentId: state => state.agentState?.id, - agentEmail: state => state.agentState?.email + agentEmail: state => state.agentState?.email, + agentKycLevel: state => state.kycLevel }, actions: { async initialize() { @@ -99,11 +102,18 @@ const makeUseHoloStore = ({ connectionArgs, MockWebSdk }) => defineStore('holo', this.appInfo = await client.appInfo() return this.appInfo }, + async loadAgentKycLevel(envirionment, hbsServicePort) { + const payload = { + "email": this.agentEmail, + "timestamp": Date.now() - (30 * 1000), // Subtract 30 sec to prevent "future" timestamp error from API + "pubKey": this.agentId + } - async signPayload(payload) { - return await client.signPayload(payload) + const { _, signature } = await client.signPayload(payload) + const kycLevel = await fetchAgentKycLevel(payload, signature, envirionment, hbsServicePort) + this.kycLevel = kycLevel + return kycLevel } - } }) diff --git a/src/stores/useHolochainStore.js b/src/stores/useHolochainStore.js index a8d7300..0e4eae9 100644 --- a/src/stores/useHolochainStore.js +++ b/src/stores/useHolochainStore.js @@ -1,5 +1,4 @@ import { inspect } from 'util' -import axios from 'axios' import { AdminWebsocket, AppWebsocket, generateSigningKeyPair, setSigningCredentials } from '@holochain/client' import { defineStore } from 'pinia' import { presentHcSignal, listify } from '../utils' @@ -105,79 +104,22 @@ const makeUseHolochainStore = ({ installed_app_id, app_ws_url, is_hpos_served, h return result }, - async zomeCall(args) { - const zomeCallArgs = { - appId: installed_app_id, - roleId: args.role_name, - zomeName: args.zome_name, - fnName: args.fn_name, - payload: args.payload - } - - const response = await this.hposHolochainCall({path: 'zome_call', headers: {}, params: zomeCallArgs}) - return response - }, setCredentials(cellId) { this.signingCredentials = new Promise(async (resolve, reject) => { - if( !is_hpos_served ) { // If running a raw holochain we need to authorize zome calls once - try { - const adminWs = await AdminWebsocket.connect(`ws:localhost:${hc_admin_port}`) - await adminWs.authorizeSigningCredentials(cellId) - } catch(e) { - console.log(`holochainCallZome error authorizeSigningCredentials AdminWebsocket: ws:localhost:${hc_admin_port}`, e) - reject() - } - - resolve() - } else { - try { - const [keyPair, signingKey] = await generateSigningKeyPair() - const params = { cellId, signingKey } - const cap_token = await this.hposHolochainCall({path: 'cap_token', headers: {}, params}) - - const signingCredentials = { - capSecret: new Uint8Array(listify(cap_token, (_, value) => (Number(value)))), - keyPair, - signingKey - } - - await setSigningCredentials(cellId, signingCredentials) - } catch (e) { - console.log(`Error setting signing credentials`, e) - reject() - } - - resolve() + try { + const adminWs = await AdminWebsocket.connect(`ws:localhost:${hc_admin_port}`) + await adminWs.authorizeSigningCredentials(cellId) + } catch(e) { + console.log(`holochainCallZome error authorizeSigningCredentials AdminWebsocket: ws:localhost:${hc_admin_port}`, e) + reject() } + + resolve() }) }, - async hposHolochainCall({ - path, - headers: userHeaders = {}, - params - }) { - const axiosConfig = { - headers: { - 'Content-Type': 'application/json', - 'Access-Control-Allow-Origin': '*' - } - } - - const HPOS_API_URL = `${window.location.protocol}//${window.location.host}` - const pathPrefix = '/holochain-api/v1/' - const fullUrl = `${HPOS_API_URL}${pathPrefix}${path}` - - const authToken = localStorage.getItem('authToken') - - const headers = { - 'X-Hpos-Auth-Token': authToken, - ...axiosConfig.headers, - ...userHeaders - } - - const response = await axios.post(fullUrl, params, { headers }) - return response.data - } + async loadAgentKycLevel(_, __) { + return null // raw holochain doesn't have a mechanism for fetching agent's kyc level + }, } }) diff --git a/src/stores/useHoloportAPIStore.js b/src/stores/useHoloportAPIStore.js new file mode 100644 index 0000000..3251ea9 --- /dev/null +++ b/src/stores/useHoloportAPIStore.js @@ -0,0 +1,104 @@ +import axios from 'axios' +import { generateSigningKeyPair, setSigningCredentials } from '@holochain/client' +import { defineStore } from 'pinia' +import { listify } from '../utils' +import { kycLevel2 } from '../services/hbs' + +const makeUseHoloportAPIStore = ({ useHolochainStore }) => defineStore('holoportAPI', { + state: () => ({ + client: useHolochainStore().client, + // These two values are subscribed to by clientStore + appInfo: useHolochainStore().appInfo, + isReady: useHolochainStore().isReady, + signingCredentials: useHolochainStore().signingCredentials + }), + actions: { + async initialize() { + useHolochainStore().initialize() + }, + + async loadAppInfo() { + useHolochainStore().loadAppInfo() + }, + + async callZome(args) { + useHolochainStore().callZome(args) + }, + setCredentials(cellId) { + this.signingCredentials = new Promise(async (resolve, reject) => { + try { + const [keyPair, signingKey] = await generateSigningKeyPair() + const params = { cellId, signingKey } + const cap_token = await this.hposHolochainCall({path: 'cap_token', headers: {}, params}) + + const signingCredentials = { + capSecret: new Uint8Array(listify(cap_token, (_, value) => (Number(value)))), + keyPair, + signingKey + } + + await setSigningCredentials(cellId, signingCredentials) + } catch (e) { + console.log(`Error setting signing credentials`, e) + reject() + } + + resolve() + }) + }, + async hposHolochainCall({ + path, + headers: userHeaders = {}, + params, + method = 'post', + }) { + const axiosConfig = { + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*' + } + } + + const HPOS_API_URL = `${window.location.protocol}//${window.location.host}` + const pathPrefix = '/holochain-api/v1/' + const fullUrl = `${HPOS_API_URL}${pathPrefix}${path}` + + const authToken = localStorage.getItem('authToken') + + const headers = { + 'X-Hpos-Auth-Token': authToken, + ...axiosConfig.headers, + ...userHeaders + } + + let response + + switch (method) { + case 'get': + response = await axios.get(fullUrl, { params, headers }) + return response.data + + case 'post': + response = await axios.post(fullUrl, params, { headers }) + return response.data + + case 'put': + response = await axios.put(fullUrl, params, { headers }) + return response.data + + case 'delete': + response = await axios.delete(fullUrl, { params, headers }) + return response.data + + default: + throw new Error(`No case in hposCall for ${method} method`) + } + }, + async loadAgentKycLevel(_, __) { + const kycLevel = await this.hposHolochainCall({path: 'kyc', headers: {}, params: {}, method: 'get'}) + return kycLevel ? (kycLevel === kycLevel2) ? 2 : 1 : null + }, + } +}) + +export default makeUseHoloportAPIStore diff --git a/src/utils/hbsConfiguration.js b/src/utils/hbsConfiguration.js index ee8e287..f17dd4c 100644 --- a/src/utils/hbsConfiguration.js +++ b/src/utils/hbsConfiguration.js @@ -24,21 +24,25 @@ const HbsServiceURL = (service, key, port) => { } } - export const AUTH_SERVICE_URL = HbsServiceURL( - 'auth', - process.env.VUE_ENV || Environment.localNoBackend, - process.env.VUE_OPS_SERVICE_PORT || '3003' - ) - const AuthServiceVersion = { [Environment.local]: 'v1', [Environment.development]: 'v1', [Environment.qa]: 'v1', [Environment.production]: 'v1' - } - - export const AUTH_SERVICE_VERSION = process.env.VUE_ENV - ? AuthServiceVersion[process.env.VUE_ENV] + } + + export const authServiceVersion = function(envirionment) { + return (envirionment) + ? AuthServiceVersion[envirionment] : AuthServiceVersion[Environment.local] + } + + export const authServiceUrl = function(envirionment, hbsServicePort) { + return HbsServiceURL( + 'auth', + envirionment || Environment.localNoBackend, + hbsServicePort || '3003' + ) + } \ No newline at end of file diff --git a/src/utils/springboardConfiguration.js b/src/utils/springboardConfiguration.js new file mode 100644 index 0000000..3641fdf --- /dev/null +++ b/src/utils/springboardConfiguration.js @@ -0,0 +1,16 @@ +import { Environment } from './consts' + +const SpringboardURL = { + [Environment.local]: 'https://local-springboard.holo.host:8081', + [Environment.localNoBackend]: 'https://local-springboard.holo.host:8081', + [Environment.development]: 'https://springboard.dev.holotest.net', + [Environment.qa]: 'https://springboard.qa.holotest.net', + [Environment.alpha]: 'https://springboard.holo.host', + [Environment.production]: 'https://springboard.holo.host' +} + +export const springBoardUrl = function(envirionment) { + return (envirionment) + ? SpringboardURL[envirionment] + : SpringboardURL[Environment.local] +} \ No newline at end of file