// @ts-ignore import TrueVaultClient from 'truevault' // @ts-ignore import FormData from 'form-data' import axios from 'axios' import get from 'lodash/get' import * as types from './types/sdk' interface TvCreds { accountId: string groupIds?: string passwordResetFlowId?: string registerToken: string scopedAccessToken?: string vaultId: string appointmentVaultId?: string sentryApiKey?: string googleApiKey?: string } interface MakeTruevault { env: types.Env tvKeys: TvCreds } const makeTruevault = function({ env, tvKeys }: MakeTruevault) { if (!tvKeys) { throw new Error( 'Please provide a valid "tvKeys" object when initializing the API', ) } const baseURL = `https://api.truevault.com` const _tvAuth: types.TvAuth = { access_token: undefined, tv_uid: undefined, user_id: undefined, tv_api_key: undefined, // providers will use this } let _tvUser: any = null const _creds: any = tvKeys const _tvReq = axios.create({ baseURL, maxRedirects: 5, // default method: 'post', // default }) return { // A manual way to create a user since the truevault client does not use the register token in the headers // TODO: unit test async createTvUser( username: string, password: string, attributes: object = {}, ) { try { const buffedToken = Buffer.from(_creds.registerToken + ':') const base64Token = buffedToken.toString('base64') const buffedAttributes = Buffer.from(JSON.stringify(attributes)) const base64Attributes = buffedAttributes.toString('base64') const url = '/v1/users' const method = 'post' const headers = { Authorization: `Basic ${base64Token}` } const account_id = this.getAccountId() const group_ids = this.makeTvGroupIds() const formData = new FormData() formData.append('username', username) if (password) formData.append('password', password) formData.append('attributes', base64Attributes) formData.append('group_ids', group_ids) formData.append('account_id', account_id) const response = await _tvReq({ data: formData, headers, method, url, }) return get(response, 'data.user', null) } catch (error) { throw error } }, async fetchTvBlob(blobId: string): Promise { try { const vaultId = this.getTvVaultId() // @ts-ignore const blob = await this.tvClient.getBlob(vaultId, blobId) return blob } catch (error) { throw error } }, async fetchTvDocument(tvApiKey: string, id: string) { const vaultId = this.getTvVaultId() const url = `/v2/vaults/${vaultId}/documents/${id}` const tvApiKeyBuffer = Buffer.from(tvApiKey + ':') const base64Key = tvApiKeyBuffer.toString('base64') const response = await _tvReq({ method: 'get', url, headers: { Authorization: `Basic ${base64Key}`, }, }) return response }, getAccountId() { return _creds.accountId }, getTvCreds() { return _creds }, getCurrentTvCreds() { return this.getTvAuth() }, getGroupIds() { return _creds.groupIds }, getTvApiKey() { return _tvAuth.tv_api_key }, getTvAuth() { return _tvAuth }, getTvResetFlowId() { return _creds.passwordResetFlowId }, getTvScopedAccessToken() { return _creds.scopedAccessToken }, getTvUser() { return _tvUser }, getTvVaultId() { return _creds.vaultId }, async initTruevault( username?: string, pw?: string, cb?: (any: any) => any, ) { try { if (!username || !pw) throw new Error( 'Cannot login to truevault, the username/password is invalid.', ) this.tvClient = await TrueVaultClient.login( _creds.accountId, username, pw, ) // @ts-ignore const tvUser = await this.tvClient.readCurrentUser(true) _tvUser = tvUser // @ts-ignore _tvAuth.access_token = this.tvClient.accessToken _tvAuth.tv_uid = tvUser.id _tvAuth.user_id = tvUser.user_id if (cb) return cb(_tvAuth) else return _tvAuth } catch (err) { throw err } }, async initTruevaultHttpBasic() { try { const httpBasic = this.getTvScopedAccessToken() this.tvClient = await new TrueVaultClient({ httpBasic }) return this.tvClient } catch (err) { throw err } }, async initTruevaultApiKey(apiKey: string) { try { if (!apiKey) throw new TypeError('The apiKey parameter is invalid') this.tvClient = await new TrueVaultClient({ apiKey }) return this.tvClient } catch (err) { throw err } }, async initTruevaultAccessToken(accessToken: string) { try { this.tvClient = await new TrueVaultClient({ accessToken }) return this.tvClient } catch (err) { throw err } }, async loginTruevault(...args: any[]) { return this.initTruevault(...args) }, // TODO: unit test makeTvGroupIds(groupIds: string[] = []): string { let ids: string[] = [] if (groupIds.length) ids = groupIds const _groupIds = Array.isArray(_creds.groupIds) ? _creds.groupIds : [] return [..._groupIds, ...ids].join(',') }, setTvApiKey(key: string) { if (key) _tvAuth.tv_api_key = key return this }, tvClient: null, } } export default makeTruevault