From 7bb93a5edfedc140634641fb23c9799fdbdaeb94 Mon Sep 17 00:00:00 2001 From: Philipp Kunz Date: Sat, 19 Feb 2022 01:34:07 +0100 Subject: [PATCH] fix(core): update --- test/test.nonci.ts | 16 ++-- ts/tink.classes.tinkaccount.ts | 143 ++++++++++++++++++++++++++------- ts/tink.classes.tinkuser.ts | 18 ++--- 3 files changed, 130 insertions(+), 47 deletions(-) diff --git a/test/test.nonci.ts b/test/test.nonci.ts index fd006e2..37d56e7 100644 --- a/test/test.nonci.ts +++ b/test/test.nonci.ts @@ -7,16 +7,6 @@ import * as tink from '../ts/index'; let tinkTestAccount: tink.TinkAccount; -tap.preTask('should delete existing users', async () => { - const preTinkAccount = tinkTestAccount = new tink.TinkAccount( - testQenv.getEnvVarOnDemand('TINK_CLIENT_ID'), - testQenv.getEnvVarOnDemand('TINK_CLIENT_SECRET') - ); - expect(tinkTestAccount).toBeInstanceOf(tink.TinkAccount); - const tinkUser = new tink.TinkUser(preTinkAccount, null, 'user_1234_abc'); - await tinkUser.delete(); -}) - tap.test('should create a valid tink account', async () => { tinkTestAccount = new tink.TinkAccount( testQenv.getEnvVarOnDemand('TINK_CLIENT_ID'), @@ -33,4 +23,10 @@ tap.test('should create a valid request', async () => { await tinkTestAccount.createTinkUser("user_1234_abc"); }) +tap.test('should delete existing users', async () => { + expect(tinkTestAccount).toBeInstanceOf(tink.TinkAccount); + const tinkUser = new tink.TinkUser(tinkTestAccount, null, 'user_1234_abc'); + await tinkUser.delete(); +}) + tap.start(); diff --git a/ts/tink.classes.tinkaccount.ts b/ts/tink.classes.tinkaccount.ts index af5e1a6..6697e28 100644 --- a/ts/tink.classes.tinkaccount.ts +++ b/ts/tink.classes.tinkaccount.ts @@ -1,9 +1,9 @@ import * as plugins from './tink.plugins'; -import { TinkUser } from './tink.classes.tinkuser' +import { TinkUser } from './tink.classes.tinkuser'; export class TinkAccount { - private clientId: string; + public clientId: string; private clientSecret: string; private apiBaseUrl: string = 'https://api.tink.com'; @@ -21,21 +21,7 @@ export class TinkAccount { return response.body === 'ok'; } - // the request method for tink respecting platform specific stuff - // e.g. certain headers if needed - public async request(optionsArg: { - urlArg: string, - methodArg: 'POST' | 'GET', - scopeArg: string, - payloadArg: any, - externalUserId: string - }) { - // check health - if (!(await this.getTinkHealthyBoolean())) { - throw new Error('TINK is not healthy right now. Please try again later.'); - } else { - console.log('tink is healthy, continuing...'); - } + public async getClientAccessTokenForScope(scopeArg: string): Promise { // lets get an accessToken for the request const response = await plugins.smartrequest.postFormDataUrlEncoded( `${this.apiBaseUrl}/api/v1/oauth/token`, @@ -55,28 +41,131 @@ export class TinkAccount { }, { key: 'scope', - content: optionsArg.scopeArg, + content: scopeArg, }, ] ); if (response.statusCode !== 200) { throw new Error('there was an error aquiring an access token.'); } - const accessToken = response.body.access_token; - - const response2 = await plugins.smartrequest.request(`${this.apiBaseUrl}${optionsArg.urlArg}`, { + const clientAccessToken = response.body.access_token; + return clientAccessToken; + } + + public async getUserAuthroizationCode( + externalUserIdArg: string, + actorCLientIdArg: string, + scopeArg: string + ) { + const accessToken = await this.getClientAccessTokenForScope('authorization:grant'); + const response = await plugins.smartrequest.postFormDataUrlEncoded( + `${this.apiBaseUrl}/api/v1/oauth/authorization-grant/delegate`, + { + headers: { + Authorization: `Bearer ${accessToken}`, + }, + }, + [ + { + key: 'response_type', + content: 'code', + }, + { + key: 'actor_client_id', + content: actorCLientIdArg, + }, + { + key: 'external_user_id', + content: externalUserIdArg, + }, + { + key: 'id_hint', + content: 'Hello there', + }, + { + key: 'scope', + content: scopeArg, + }, + ] + ); + + if (response.statusCode !== 200) { + console.log(response.body); + throw new Error('there was an error aquiring an access token.'); + } + const userAuthorizationCode = response.body.code; + return userAuthorizationCode; + } + + public async getUserAccessToken(authorizationCode: string): Promise { + const accessToken = await this.getClientAccessTokenForScope('authorization:grant'); + const response = await plugins.smartrequest.postFormDataUrlEncoded( + `${this.apiBaseUrl}/api/v1/oauth/token`, + {}, + [ + { + key: 'code', + content: authorizationCode, + }, + { + key: 'client_id', + content: this.clientId, + }, + { + key: 'client_secret', + content: this.clientSecret, + }, + { + key: 'grant_type', + content: 'authorization_code', + }, + ] + ); + + if (response.statusCode !== 200) { + console.log(response.body); + throw new Error('there was an error aquiring an access token.'); + } + const userAccessToken = response.body.access_token; + return userAccessToken; + } + + public async getTinkLinkCode(externalUserIdArg: string) { + const authorizationCode = this.getUserAuthroizationCode( + externalUserIdArg, + 'df05e4b379934cd09963197cc855bfe9', + 'authorization:read,authorization:grant,credentials:refresh,credentials:read,credentials:write,providers:read,user:read' + ); + } + + // the request method for tink respecting platform specific stuff + // e.g. certain headers if needed + public async request(optionsArg: { + urlArg: string; + methodArg: 'POST' | 'GET'; + accessToken: string; + payloadArg: any; + }) { + // check health + if (!(await this.getTinkHealthyBoolean())) { + throw new Error('TINK is not healthy right now. Please try again later.'); + } else { + console.log('tink is healthy, continuing...'); + } + const response = await plugins.smartrequest.request(`${this.apiBaseUrl}${optionsArg.urlArg}`, { headers: { - 'Authorization': `Bearer ${accessToken}`, - 'Content-Type': 'application/json' + Authorization: `Bearer ${optionsArg.accessToken}`, + 'Content-Type': 'application/json', }, method: optionsArg.methodArg, - requestBody: JSON.stringify(optionsArg.payloadArg) - }) - console.log(response2.statusCode); - return response2.body; + requestBody: JSON.stringify(optionsArg.payloadArg), + }); + console.log(response.statusCode); + return response.body; } public async createTinkUser(externalUserIdArg: string) { const tinkuser = await TinkUser.createNewTinkUser(this, externalUserIdArg); + return tinkuser; } } diff --git a/ts/tink.classes.tinkuser.ts b/ts/tink.classes.tinkuser.ts index 1226c22..59a3f0c 100644 --- a/ts/tink.classes.tinkuser.ts +++ b/ts/tink.classes.tinkuser.ts @@ -5,11 +5,11 @@ import { TinkAccount } from './tink.classes.tinkaccount'; export class TinkUser { // STATIC public static async createNewTinkUser (tinkaccountArg: TinkAccount, externalUserIdArg: string) { + const accessToken = await tinkaccountArg.getClientAccessTokenForScope('user:create'); const response = await tinkaccountArg.request({ - externalUserId: null, urlArg: '/api/v1/user/create', + accessToken, methodArg: 'POST', - scopeArg: 'user:create', payloadArg: { "external_user_id": externalUserIdArg, "market": "GB", @@ -17,7 +17,8 @@ export class TinkUser { } }); - console.log(response); + const newTinkUser = new TinkUser (tinkaccountArg, response.user_id, response.external_user_id); + return newTinkUser; } // INSTANCE @@ -33,21 +34,18 @@ export class TinkUser { this.externalUserIdArg = externalUserIdArg; } - public async authorize() { - - } - /** * deletes the user */ public async delete() { + const authorizationCode = await this.tinkAccountRef.getUserAuthroizationCode(this.externalUserIdArg, this.tinkAccountRef.clientId, 'user:delete'); + const accessToken = await this.tinkAccountRef.getUserAccessToken(authorizationCode); const response = await this.tinkAccountRef.request({ - externalUserId: this.externalUserIdArg, methodArg: 'POST', + accessToken, payloadArg: {}, - scopeArg: 'user:delete', urlArg: '/api/v1/user/delete' }); - console.log(response); + console.log(`successfully deleted user with externalId ${this.externalUserIdArg}`); } } \ No newline at end of file