From 66f7217537073219c9a021655bb60a0c23fc5030 Mon Sep 17 00:00:00 2001 From: Nathan Lie Date: Wed, 28 Aug 2024 10:05:00 +0300 Subject: [PATCH 01/24] feat(backend): create operator kratos identity on backend startup --- localenv/admin-auth/docker-compose.yml | 1 + packages/backend/src/app.ts | 1 + packages/backend/src/index.ts | 3 +++ 3 files changed, 5 insertions(+) diff --git a/localenv/admin-auth/docker-compose.yml b/localenv/admin-auth/docker-compose.yml index f53d1e7f40..6b57e326fb 100644 --- a/localenv/admin-auth/docker-compose.yml +++ b/localenv/admin-auth/docker-compose.yml @@ -12,6 +12,7 @@ services: KRATOS_CONTAINER_PUBLIC_URL: 'http://cloud-nine-kratos:4433' KRATOS_BROWSER_PUBLIC_URL: 'http://localhost:4433' KRATOS_ADMIN_URL: 'http://cloud-nine-kratos:4434/admin' + KRATOS_ADMIN_EMAIL: 'admin@mail.com' depends_on: - cloud-nine-backend - cloud-nine-kratos diff --git a/packages/backend/src/app.ts b/packages/backend/src/app.ts index dfce21d541..3f95a20822 100644 --- a/packages/backend/src/app.ts +++ b/packages/backend/src/app.ts @@ -1,6 +1,7 @@ import { join } from 'path' import http, { Server } from 'http' import { ParsedUrlQuery } from 'querystring' +import axios from 'axios' import { Client as TigerbeetleClient } from 'tigerbeetle-node' import { IocContract } from '@adonisjs/fold' diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index 554a931ea4..f01973c40c 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -758,6 +758,9 @@ export const start = async ( `Auto-peering server listening on ${config.autoPeeringServerPort}` ) } + + await app.createOperatorIdentity() + logger.info('Operator identity created on Kratos') } // If this script is run directly, start the server From bc6f18654a8b05dff9571be2d3b17faf287a7038 Mon Sep 17 00:00:00 2001 From: Nathan Lie Date: Wed, 28 Aug 2024 10:42:00 +0300 Subject: [PATCH 02/24] chore: formatting --- localenv/admin-auth/docker-compose.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/localenv/admin-auth/docker-compose.yml b/localenv/admin-auth/docker-compose.yml index 6b57e326fb..f53d1e7f40 100644 --- a/localenv/admin-auth/docker-compose.yml +++ b/localenv/admin-auth/docker-compose.yml @@ -12,7 +12,6 @@ services: KRATOS_CONTAINER_PUBLIC_URL: 'http://cloud-nine-kratos:4433' KRATOS_BROWSER_PUBLIC_URL: 'http://localhost:4433' KRATOS_ADMIN_URL: 'http://cloud-nine-kratos:4434/admin' - KRATOS_ADMIN_EMAIL: 'admin@mail.com' depends_on: - cloud-nine-backend - cloud-nine-kratos From f1138cde7c828dfc22ddae6b7ff1fe81a2173fb9 Mon Sep 17 00:00:00 2001 From: Nathan Lie Date: Wed, 28 Aug 2024 11:39:59 +0300 Subject: [PATCH 03/24] fix: handle new cases --- packages/backend/src/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index f01973c40c..57e295c04e 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -760,7 +760,6 @@ export const start = async ( } await app.createOperatorIdentity() - logger.info('Operator identity created on Kratos') } // If this script is run directly, start the server From a462f0f5380009679a7354980521d0d707272b9c Mon Sep 17 00:00:00 2001 From: bsanduc Date: Tue, 27 Aug 2024 16:27:37 +0300 Subject: [PATCH 04/24] Add migration files --- ...20240827131401_create_tenants_tables.js.js | 21 ++++++ ...27131417_update_grants_with_tenantId.js.js | 25 +++++++ ...20240827115808_create_tenants_tables.js.js | 21 ++++++ ...15832_update_resources_with_tenantId.js.js | 75 +++++++++++++++++++ 4 files changed, 142 insertions(+) create mode 100644 packages/auth/migrations/20240827131401_create_tenants_tables.js.js create mode 100644 packages/auth/migrations/20240827131417_update_grants_with_tenantId.js.js create mode 100644 packages/backend/migrations/20240827115808_create_tenants_tables.js.js create mode 100644 packages/backend/migrations/20240827115832_update_resources_with_tenantId.js.js diff --git a/packages/auth/migrations/20240827131401_create_tenants_tables.js.js b/packages/auth/migrations/20240827131401_create_tenants_tables.js.js new file mode 100644 index 0000000000..aef995843a --- /dev/null +++ b/packages/auth/migrations/20240827131401_create_tenants_tables.js.js @@ -0,0 +1,21 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = function (knex) { + return knex.schema.createTable('tenants', function (table) { + table.uuid('id').primary() + table.string('kratosUrl').notNullable() + table.timestamp('createdAt').defaultTo(knex.fn.now()) + table.timestamp('updatedAt').defaultTo(knex.fn.now()) + table.timestamp('deletedAt').nullable().defaultTo(null) + }) +} + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = function (knex) { + return knex.schema.dropTable('tenants') +} diff --git a/packages/auth/migrations/20240827131417_update_grants_with_tenantId.js.js b/packages/auth/migrations/20240827131417_update_grants_with_tenantId.js.js new file mode 100644 index 0000000000..758d187419 --- /dev/null +++ b/packages/auth/migrations/20240827131417_update_grants_with_tenantId.js.js @@ -0,0 +1,25 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = function (knex) { + return knex.schema.table('grants', function (table) { + table.uuid('tenantId').notNullable() + table + .foreign('tenantId') + .references('id') + .inTable('tenants') + .onDelete('CASCADE') + }) +} + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = function (knex) { + return knex.schema.table('grants', function (table) { + table.dropForeign(['tenantId']) + table.dropColumn('tenantId') + }) +} diff --git a/packages/backend/migrations/20240827115808_create_tenants_tables.js.js b/packages/backend/migrations/20240827115808_create_tenants_tables.js.js new file mode 100644 index 0000000000..aef995843a --- /dev/null +++ b/packages/backend/migrations/20240827115808_create_tenants_tables.js.js @@ -0,0 +1,21 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = function (knex) { + return knex.schema.createTable('tenants', function (table) { + table.uuid('id').primary() + table.string('kratosUrl').notNullable() + table.timestamp('createdAt').defaultTo(knex.fn.now()) + table.timestamp('updatedAt').defaultTo(knex.fn.now()) + table.timestamp('deletedAt').nullable().defaultTo(null) + }) +} + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = function (knex) { + return knex.schema.dropTable('tenants') +} diff --git a/packages/backend/migrations/20240827115832_update_resources_with_tenantId.js.js b/packages/backend/migrations/20240827115832_update_resources_with_tenantId.js.js new file mode 100644 index 0000000000..aa1adde645 --- /dev/null +++ b/packages/backend/migrations/20240827115832_update_resources_with_tenantId.js.js @@ -0,0 +1,75 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = function (knex) { + return knex.schema + .table('quotes', function (table) { + table.uuid('tenantId').notNullable() + table + .foreign('tenantId') + .references('id') + .inTable('tenants') + .onDelete('CASCADE') + }) + .table('incomingPayments', function (table) { + table.uuid('tenantId').notNullable() + table + .foreign('tenantId') + .references('id') + .inTable('tenants') + .onDelete('CASCADE') + }) + .table('outgoingPayments', function (table) { + table.uuid('tenantId').notNullable() + table + .foreign('tenantId') + .references('id') + .inTable('tenants') + .onDelete('CASCADE') + }) + .table('walletAddresses', function (table) { + table.uuid('tenantId').notNullable() + table + .foreign('tenantId') + .references('id') + .inTable('tenants') + .onDelete('CASCADE') + }) + .table('grants', function (table) { + table.uuid('tenantId').notNullable() + table + .foreign('tenantId') + .references('id') + .inTable('tenants') + .onDelete('CASCADE') + }) +} + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = function (knex) { + return knex.schema + .table('quotes', function (table) { + table.dropForeign(['tenantId']) + table.dropColumn('tenantId') + }) + .table('incomingPayments', function (table) { + table.dropForeign(['tenantId']) + table.dropColumn('tenantId') + }) + .table('outgoingPayments', function (table) { + table.dropForeign(['tenantId']) + table.dropColumn('tenantId') + }) + .table('walletAddresses', function (table) { + table.dropForeign(['tenantId']) + table.dropColumn('tenantId') + }) + .table('grants', function (table) { + table.dropForeign(['tenantId']) + table.dropColumn('tenantId') + }) +} From bb8d2a4bb7d9308a159426018fdcdd77f802738a Mon Sep 17 00:00:00 2001 From: bsanduc Date: Tue, 27 Aug 2024 16:56:56 +0300 Subject: [PATCH 05/24] Update migration files --- .../auth/migrations/20240827131401_create_tenants_tables.js.js | 3 ++- .../migrations/20240827115808_create_tenants_tables.js.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/auth/migrations/20240827131401_create_tenants_tables.js.js b/packages/auth/migrations/20240827131401_create_tenants_tables.js.js index aef995843a..4aa68c3ff4 100644 --- a/packages/auth/migrations/20240827131401_create_tenants_tables.js.js +++ b/packages/auth/migrations/20240827131401_create_tenants_tables.js.js @@ -5,7 +5,8 @@ exports.up = function (knex) { return knex.schema.createTable('tenants', function (table) { table.uuid('id').primary() - table.string('kratosUrl').notNullable() + table.string('idpConsentEndpoint').notNullable() + table.string('idpSecret').notNullable() table.timestamp('createdAt').defaultTo(knex.fn.now()) table.timestamp('updatedAt').defaultTo(knex.fn.now()) table.timestamp('deletedAt').nullable().defaultTo(null) diff --git a/packages/backend/migrations/20240827115808_create_tenants_tables.js.js b/packages/backend/migrations/20240827115808_create_tenants_tables.js.js index aef995843a..cfa2582e1d 100644 --- a/packages/backend/migrations/20240827115808_create_tenants_tables.js.js +++ b/packages/backend/migrations/20240827115808_create_tenants_tables.js.js @@ -5,7 +5,7 @@ exports.up = function (knex) { return knex.schema.createTable('tenants', function (table) { table.uuid('id').primary() - table.string('kratosUrl').notNullable() + table.string('kratosIdentityId').notNullable() table.timestamp('createdAt').defaultTo(knex.fn.now()) table.timestamp('updatedAt').defaultTo(knex.fn.now()) table.timestamp('deletedAt').nullable().defaultTo(null) From a9274a12c046f01788c9d8746c80285ba76b0e98 Mon Sep 17 00:00:00 2001 From: golobitch Date: Tue, 27 Aug 2024 17:08:49 +0300 Subject: [PATCH 06/24] feat(tenant): basic tenant admin api schema and service --- packages/backend/src/graphql/resolvers/tenant.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/backend/src/graphql/resolvers/tenant.ts b/packages/backend/src/graphql/resolvers/tenant.ts index c05353051b..5389def01f 100644 --- a/packages/backend/src/graphql/resolvers/tenant.ts +++ b/packages/backend/src/graphql/resolvers/tenant.ts @@ -1,3 +1,4 @@ +<<<<<<< HEAD import { GraphQLError } from 'graphql' import { ApolloContext } from '../../app' import { @@ -70,10 +71,17 @@ export const getTenant: QueryResolvers['tenant'] = async ( export const createTenant: MutationResolvers['createTenant'] = async ( +======= +import { ApolloContext } from "../../app"; +import { MutationResolvers, ResolversTypes } from "../generated/graphql"; + +export const createTenant: MutationResolvers['createTenant'] = async ( +>>>>>>> 51ad9b99 (feat(tenant): basic tenant admin api schema and service) _, args, ctx ): Promise => { +<<<<<<< HEAD const tenantService = await ctx.container.use('tenantService') const tenantOrError = await tenantService.create({ @@ -112,3 +120,7 @@ export function tenantToGraphql(tenant: Tenant): SchemaTenant { updatedAt: tenant.updatedAt.toISOString() } } +======= + return undefined; + } +>>>>>>> 51ad9b99 (feat(tenant): basic tenant admin api schema and service) From 76818a2b3162fe6566e8547212657e84556fcbea Mon Sep 17 00:00:00 2001 From: bsanduc Date: Tue, 27 Aug 2024 17:02:20 +0300 Subject: [PATCH 07/24] Fix file name for migrations --- ...20240827131401_create_tenants_tables.js.js | 22 ------ ...27131417_update_grants_with_tenantId.js.js | 25 ------- ...20240827115808_create_tenants_tables.js.js | 21 ------ ...15832_update_resources_with_tenantId.js.js | 75 ------------------- 4 files changed, 143 deletions(-) delete mode 100644 packages/auth/migrations/20240827131401_create_tenants_tables.js.js delete mode 100644 packages/auth/migrations/20240827131417_update_grants_with_tenantId.js.js delete mode 100644 packages/backend/migrations/20240827115808_create_tenants_tables.js.js delete mode 100644 packages/backend/migrations/20240827115832_update_resources_with_tenantId.js.js diff --git a/packages/auth/migrations/20240827131401_create_tenants_tables.js.js b/packages/auth/migrations/20240827131401_create_tenants_tables.js.js deleted file mode 100644 index 4aa68c3ff4..0000000000 --- a/packages/auth/migrations/20240827131401_create_tenants_tables.js.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @param { import("knex").Knex } knex - * @returns { Promise } - */ -exports.up = function (knex) { - return knex.schema.createTable('tenants', function (table) { - table.uuid('id').primary() - table.string('idpConsentEndpoint').notNullable() - table.string('idpSecret').notNullable() - table.timestamp('createdAt').defaultTo(knex.fn.now()) - table.timestamp('updatedAt').defaultTo(knex.fn.now()) - table.timestamp('deletedAt').nullable().defaultTo(null) - }) -} - -/** - * @param { import("knex").Knex } knex - * @returns { Promise } - */ -exports.down = function (knex) { - return knex.schema.dropTable('tenants') -} diff --git a/packages/auth/migrations/20240827131417_update_grants_with_tenantId.js.js b/packages/auth/migrations/20240827131417_update_grants_with_tenantId.js.js deleted file mode 100644 index 758d187419..0000000000 --- a/packages/auth/migrations/20240827131417_update_grants_with_tenantId.js.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @param { import("knex").Knex } knex - * @returns { Promise } - */ -exports.up = function (knex) { - return knex.schema.table('grants', function (table) { - table.uuid('tenantId').notNullable() - table - .foreign('tenantId') - .references('id') - .inTable('tenants') - .onDelete('CASCADE') - }) -} - -/** - * @param { import("knex").Knex } knex - * @returns { Promise } - */ -exports.down = function (knex) { - return knex.schema.table('grants', function (table) { - table.dropForeign(['tenantId']) - table.dropColumn('tenantId') - }) -} diff --git a/packages/backend/migrations/20240827115808_create_tenants_tables.js.js b/packages/backend/migrations/20240827115808_create_tenants_tables.js.js deleted file mode 100644 index cfa2582e1d..0000000000 --- a/packages/backend/migrations/20240827115808_create_tenants_tables.js.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @param { import("knex").Knex } knex - * @returns { Promise } - */ -exports.up = function (knex) { - return knex.schema.createTable('tenants', function (table) { - table.uuid('id').primary() - table.string('kratosIdentityId').notNullable() - table.timestamp('createdAt').defaultTo(knex.fn.now()) - table.timestamp('updatedAt').defaultTo(knex.fn.now()) - table.timestamp('deletedAt').nullable().defaultTo(null) - }) -} - -/** - * @param { import("knex").Knex } knex - * @returns { Promise } - */ -exports.down = function (knex) { - return knex.schema.dropTable('tenants') -} diff --git a/packages/backend/migrations/20240827115832_update_resources_with_tenantId.js.js b/packages/backend/migrations/20240827115832_update_resources_with_tenantId.js.js deleted file mode 100644 index aa1adde645..0000000000 --- a/packages/backend/migrations/20240827115832_update_resources_with_tenantId.js.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @param { import("knex").Knex } knex - * @returns { Promise } - */ -exports.up = function (knex) { - return knex.schema - .table('quotes', function (table) { - table.uuid('tenantId').notNullable() - table - .foreign('tenantId') - .references('id') - .inTable('tenants') - .onDelete('CASCADE') - }) - .table('incomingPayments', function (table) { - table.uuid('tenantId').notNullable() - table - .foreign('tenantId') - .references('id') - .inTable('tenants') - .onDelete('CASCADE') - }) - .table('outgoingPayments', function (table) { - table.uuid('tenantId').notNullable() - table - .foreign('tenantId') - .references('id') - .inTable('tenants') - .onDelete('CASCADE') - }) - .table('walletAddresses', function (table) { - table.uuid('tenantId').notNullable() - table - .foreign('tenantId') - .references('id') - .inTable('tenants') - .onDelete('CASCADE') - }) - .table('grants', function (table) { - table.uuid('tenantId').notNullable() - table - .foreign('tenantId') - .references('id') - .inTable('tenants') - .onDelete('CASCADE') - }) -} - -/** - * @param { import("knex").Knex } knex - * @returns { Promise } - */ -exports.down = function (knex) { - return knex.schema - .table('quotes', function (table) { - table.dropForeign(['tenantId']) - table.dropColumn('tenantId') - }) - .table('incomingPayments', function (table) { - table.dropForeign(['tenantId']) - table.dropColumn('tenantId') - }) - .table('outgoingPayments', function (table) { - table.dropForeign(['tenantId']) - table.dropColumn('tenantId') - }) - .table('walletAddresses', function (table) { - table.dropForeign(['tenantId']) - table.dropColumn('tenantId') - }) - .table('grants', function (table) { - table.dropForeign(['tenantId']) - table.dropColumn('tenantId') - }) -} From 3f6534879abbd7256db19624a2256d235aaaaa86 Mon Sep 17 00:00:00 2001 From: golobitch Date: Tue, 27 Aug 2024 18:02:23 +0300 Subject: [PATCH 08/24] feat(auth): create basic tenant service and model plus graphql schema --- packages/auth/src/index.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/auth/src/index.ts b/packages/auth/src/index.ts index 14ea6d2ed4..7c3a70b9be 100644 --- a/packages/auth/src/index.ts +++ b/packages/auth/src/index.ts @@ -93,6 +93,15 @@ export function initIocContainer( }) }) + container.singleton('tenantService', async (deps: IocContract) => { + const [logger, knex] = await Promise.all([ + deps.use('logger'), + deps.use('knex') + ]) + + return createTenantService({ logger, knex }) + }) + container.singleton( 'tenantService', async (deps: IocContract) => { From cdd197c478b43bf9f8086604ba655e47f8b11293 Mon Sep 17 00:00:00 2001 From: golobitch Date: Tue, 27 Aug 2024 18:02:41 +0300 Subject: [PATCH 09/24] feat(graphql): generated data --- packages/backend/src/graphql/resolvers/tenant.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/packages/backend/src/graphql/resolvers/tenant.ts b/packages/backend/src/graphql/resolvers/tenant.ts index 5389def01f..c05353051b 100644 --- a/packages/backend/src/graphql/resolvers/tenant.ts +++ b/packages/backend/src/graphql/resolvers/tenant.ts @@ -1,4 +1,3 @@ -<<<<<<< HEAD import { GraphQLError } from 'graphql' import { ApolloContext } from '../../app' import { @@ -71,17 +70,10 @@ export const getTenant: QueryResolvers['tenant'] = async ( export const createTenant: MutationResolvers['createTenant'] = async ( -======= -import { ApolloContext } from "../../app"; -import { MutationResolvers, ResolversTypes } from "../generated/graphql"; - -export const createTenant: MutationResolvers['createTenant'] = async ( ->>>>>>> 51ad9b99 (feat(tenant): basic tenant admin api schema and service) _, args, ctx ): Promise => { -<<<<<<< HEAD const tenantService = await ctx.container.use('tenantService') const tenantOrError = await tenantService.create({ @@ -120,7 +112,3 @@ export function tenantToGraphql(tenant: Tenant): SchemaTenant { updatedAt: tenant.updatedAt.toISOString() } } -======= - return undefined; - } ->>>>>>> 51ad9b99 (feat(tenant): basic tenant admin api schema and service) From ef68ed9657d6ee4141ea65a9371e9b2d84e0b5da Mon Sep 17 00:00:00 2001 From: golobitch Date: Wed, 28 Aug 2024 10:24:39 +0300 Subject: [PATCH 10/24] feat(auth): add basic tenant schema and appropriate resources like model and service --- packages/auth/src/index.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/auth/src/index.ts b/packages/auth/src/index.ts index 7c3a70b9be..f4c6c664f4 100644 --- a/packages/auth/src/index.ts +++ b/packages/auth/src/index.ts @@ -93,14 +93,17 @@ export function initIocContainer( }) }) - container.singleton('tenantService', async (deps: IocContract) => { - const [logger, knex] = await Promise.all([ - deps.use('logger'), - deps.use('knex') - ]) + container.singleton( + 'tenantService', + async (deps: IocContract) => { + const [logger, knex] = await Promise.all([ + deps.use('logger'), + deps.use('knex') + ]) - return createTenantService({ logger, knex }) - }) + return createTenantService({ logger, knex }) + } + ) container.singleton( 'tenantService', From 452755a854e69634548f91cb36fbf3b41e32bb57 Mon Sep 17 00:00:00 2001 From: golobitch Date: Wed, 28 Aug 2024 11:29:50 +0300 Subject: [PATCH 11/24] feat(backend): add apollo client do dependencies --- packages/backend/src/index.ts | 53 +++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index 57e295c04e..a5aee1105f 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -555,6 +555,59 @@ export function initIocContainer( }) }) + container.singleton('apolloClient', async (deps) => { + const [logger, config] = await Promise.all([ + deps.use('logger'), + deps.use('config') + ]) + + const httpLink = createHttpLink({ + uri: config.authAdminApiUrl + }) + + const errorLink = onError(({ graphQLErrors }) => { + if (graphQLErrors) { + logger.error(graphQLErrors) + graphQLErrors.map(({ extensions }) => { + if (extensions && extensions.code === 'UNAUTHENTICATED') { + logger.error('UNAUTHENTICATED') + } + + if (extensions && extensions.code === 'FORBIDDEN') { + logger.error('FORBIDDEN') + } + }) + } + }) + + const authLink = setContext((_, { headers }) => { + return { + headers: { + ...headers + } + } + }) + const link = ApolloLink.from([errorLink, authLink, httpLink]) + + const client = new ApolloClient({ + cache: new InMemoryCache({}), + link: link, + defaultOptions: { + query: { + fetchPolicy: 'no-cache' + }, + mutate: { + fetchPolicy: 'no-cache' + }, + watchQuery: { + fetchPolicy: 'no-cache' + } + } + }) + + return client + }) + container.singleton('paymentMethodHandlerService', async (deps) => { return createPaymentMethodHandlerService({ logger: await deps.use('logger'), From 28d07cc5ad2be7f5270f50a6b7185c40cb388c0f Mon Sep 17 00:00:00 2001 From: golobitch Date: Wed, 28 Aug 2024 11:41:58 +0300 Subject: [PATCH 12/24] feat(auth): delete tenant --- packages/auth/src/tenants/service.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/auth/src/tenants/service.ts b/packages/auth/src/tenants/service.ts index d23462e36e..c93497012c 100644 --- a/packages/auth/src/tenants/service.ts +++ b/packages/auth/src/tenants/service.ts @@ -36,7 +36,10 @@ async function deleteTenant( deps: ServiceDependencies, id: string ): Promise { - return Tenant.query(deps.knex).deleteById(id).returning('*').first() + return Tenant.query(deps.knex) + .deleteById(id) + .returning('*') + .first() } async function createTenant( From 30960562756ae213b1ec3ebe0a71cb85a0381af0 Mon Sep 17 00:00:00 2001 From: golobitch Date: Wed, 28 Aug 2024 16:50:08 +0300 Subject: [PATCH 13/24] chore(auth): format --- packages/auth/src/tenants/service.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/auth/src/tenants/service.ts b/packages/auth/src/tenants/service.ts index c93497012c..d23462e36e 100644 --- a/packages/auth/src/tenants/service.ts +++ b/packages/auth/src/tenants/service.ts @@ -36,10 +36,7 @@ async function deleteTenant( deps: ServiceDependencies, id: string ): Promise { - return Tenant.query(deps.knex) - .deleteById(id) - .returning('*') - .first() + return Tenant.query(deps.knex).deleteById(id).returning('*').first() } async function createTenant( From b998dd652145d8d36ce1a2fbd131b59d74d640c4 Mon Sep 17 00:00:00 2001 From: golobitch Date: Wed, 28 Aug 2024 16:50:27 +0300 Subject: [PATCH 14/24] feat(backend): create tenant service implementation --- packages/backend/src/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index a5aee1105f..4ea7b60791 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -564,7 +564,7 @@ export function initIocContainer( const httpLink = createHttpLink({ uri: config.authAdminApiUrl }) - + const errorLink = onError(({ graphQLErrors }) => { if (graphQLErrors) { logger.error(graphQLErrors) @@ -572,14 +572,14 @@ export function initIocContainer( if (extensions && extensions.code === 'UNAUTHENTICATED') { logger.error('UNAUTHENTICATED') } - + if (extensions && extensions.code === 'FORBIDDEN') { logger.error('FORBIDDEN') } }) } }) - + const authLink = setContext((_, { headers }) => { return { headers: { @@ -588,7 +588,7 @@ export function initIocContainer( } }) const link = ApolloLink.from([errorLink, authLink, httpLink]) - + const client = new ApolloClient({ cache: new InMemoryCache({}), link: link, From d1bb78c52fc00908538491c65a485aa0c3428689 Mon Sep 17 00:00:00 2001 From: golobitch Date: Wed, 28 Aug 2024 18:15:11 +0300 Subject: [PATCH 15/24] feat(packages): make multi tenant work wip --- packages/backend/src/graphql/resolvers/tenant.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/backend/src/graphql/resolvers/tenant.ts b/packages/backend/src/graphql/resolvers/tenant.ts index c05353051b..caf695eaca 100644 --- a/packages/backend/src/graphql/resolvers/tenant.ts +++ b/packages/backend/src/graphql/resolvers/tenant.ts @@ -88,6 +88,8 @@ export const createTenant: MutationResolvers['createTenant'] = email: args.input.email }) + console.log('TEANT: ', tenantOrError) + if (isTenantError(tenantOrError)) { throw new GraphQLError(errorToMessage[tenantOrError], { extensions: { From 8d5e9242a983479b313c0bab6024f025a4994eab Mon Sep 17 00:00:00 2001 From: golobitch Date: Thu, 29 Aug 2024 13:26:19 +0300 Subject: [PATCH 16/24] feat(backend): update resolvers with tenant id and finish the tenant creation --- .../backend/src/graphql/resolvers/tenant.ts | 2 - packages/backend/src/index.ts | 53 ------------------- 2 files changed, 55 deletions(-) diff --git a/packages/backend/src/graphql/resolvers/tenant.ts b/packages/backend/src/graphql/resolvers/tenant.ts index caf695eaca..c05353051b 100644 --- a/packages/backend/src/graphql/resolvers/tenant.ts +++ b/packages/backend/src/graphql/resolvers/tenant.ts @@ -88,8 +88,6 @@ export const createTenant: MutationResolvers['createTenant'] = email: args.input.email }) - console.log('TEANT: ', tenantOrError) - if (isTenantError(tenantOrError)) { throw new GraphQLError(errorToMessage[tenantOrError], { extensions: { diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index 4ea7b60791..57e295c04e 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -555,59 +555,6 @@ export function initIocContainer( }) }) - container.singleton('apolloClient', async (deps) => { - const [logger, config] = await Promise.all([ - deps.use('logger'), - deps.use('config') - ]) - - const httpLink = createHttpLink({ - uri: config.authAdminApiUrl - }) - - const errorLink = onError(({ graphQLErrors }) => { - if (graphQLErrors) { - logger.error(graphQLErrors) - graphQLErrors.map(({ extensions }) => { - if (extensions && extensions.code === 'UNAUTHENTICATED') { - logger.error('UNAUTHENTICATED') - } - - if (extensions && extensions.code === 'FORBIDDEN') { - logger.error('FORBIDDEN') - } - }) - } - }) - - const authLink = setContext((_, { headers }) => { - return { - headers: { - ...headers - } - } - }) - const link = ApolloLink.from([errorLink, authLink, httpLink]) - - const client = new ApolloClient({ - cache: new InMemoryCache({}), - link: link, - defaultOptions: { - query: { - fetchPolicy: 'no-cache' - }, - mutate: { - fetchPolicy: 'no-cache' - }, - watchQuery: { - fetchPolicy: 'no-cache' - } - } - }) - - return client - }) - container.singleton('paymentMethodHandlerService', async (deps) => { return createPaymentMethodHandlerService({ logger: await deps.use('logger'), From 03e24681bf5281375cee5f9a5abf4acec60d42fc Mon Sep 17 00:00:00 2001 From: golobitch Date: Thu, 29 Aug 2024 14:20:17 +0300 Subject: [PATCH 17/24] feat(backend): small changes to schema + mapping of tenant to graphql + bruno --- packages/backend/src/graphql/resolvers/tenant.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/backend/src/graphql/resolvers/tenant.ts b/packages/backend/src/graphql/resolvers/tenant.ts index c05353051b..a78b611e8c 100644 --- a/packages/backend/src/graphql/resolvers/tenant.ts +++ b/packages/backend/src/graphql/resolvers/tenant.ts @@ -64,6 +64,7 @@ export const getTenant: QueryResolvers['tenant'] = async ( } }) } + console.log('TENANT: ', tenant) return tenantToGraphql(tenant) } From 188f567601571ee5d757973148c5fbb84169d5a3 Mon Sep 17 00:00:00 2001 From: Nathan Lie Date: Fri, 30 Aug 2024 11:35:17 +0300 Subject: [PATCH 18/24] feat(backend,frontend): create kratos identity when tenants are created, permissioned admin UI pages --- packages/backend/src/graphql/resolvers/tenant.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/graphql/resolvers/tenant.ts b/packages/backend/src/graphql/resolvers/tenant.ts index a78b611e8c..8a2df3d4a8 100644 --- a/packages/backend/src/graphql/resolvers/tenant.ts +++ b/packages/backend/src/graphql/resolvers/tenant.ts @@ -107,7 +107,7 @@ export function tenantToGraphql(tenant: Tenant): SchemaTenant { id: tenant.id, email: tenant.email, kratosIdentityId: tenant.kratosIdentityId, - //we should probably paginate this, but for now, that we only have like two endpoints it should be ok + // TODO: we should probably paginate this, but for now, that we only have like two endpoints it should be ok endpoints: tenant.endpoints.map(tenantEndpointToGraphql), createdAt: tenant.createdAt.toISOString(), updatedAt: tenant.updatedAt.toISOString() From 711a96983d0e76e2b26dcb4b63c34ade30806640 Mon Sep 17 00:00:00 2001 From: Nathan Lie Date: Mon, 2 Sep 2024 09:40:22 -0700 Subject: [PATCH 19/24] feat(wip): use tenantId in OP flow --- packages/auth/src/app.ts | 2 +- packages/auth/src/grant/routes.ts | 6 ++++-- packages/auth/src/grant/service.ts | 8 +++++--- packages/backend/src/app.ts | 18 +++++++++--------- .../open_payments/payment/incoming/routes.ts | 2 ++ .../open_payments/payment/outgoing/routes.ts | 3 +++ .../backend/src/open_payments/quote/routes.ts | 2 ++ .../src/open_payments/wallet_address/routes.ts | 4 ++-- packages/frontend/app/lib/api/tenant.server.ts | 1 + .../frontend/app/routes/tenants._index.tsx | 1 + 10 files changed, 30 insertions(+), 17 deletions(-) diff --git a/packages/auth/src/app.ts b/packages/auth/src/app.ts index dc27684dbf..c79d035cfb 100644 --- a/packages/auth/src/app.ts +++ b/packages/auth/src/app.ts @@ -267,7 +267,7 @@ export class App { /* Back-channel GNAP Routes */ // Grant Initiation router.post( - '/', + '/:tenantId', createValidatorMiddleware(openApi.authServerSpec, { path: '/', method: HttpMethod.POST diff --git a/packages/auth/src/grant/routes.ts b/packages/auth/src/grant/routes.ts index 17e6f09128..aac537877d 100644 --- a/packages/auth/src/grant/routes.ts +++ b/packages/auth/src/grant/routes.ts @@ -135,7 +135,8 @@ async function createApprovedGrant( let grant: Grant let accessToken: AccessToken try { - grant = await grantService.create(body, trx) + const { tenantId } = ctx.params + grant = await grantService.create(body, tenantId, trx) accessToken = await deps.accessTokenService.create(grant.id, trx) await trx.commit() } catch (err) { @@ -170,6 +171,7 @@ async function createPendingGrant( ctx: CreateContext ): Promise { const { body } = ctx.request + const { tenantId } = ctx.params const { grantService, interactionService, config, logger } = deps if (!body.interact) { throw new GNAPServerRouteError( @@ -191,7 +193,7 @@ async function createPendingGrant( const trx = await Grant.startTransaction() try { - const grant = await grantService.create(body, trx) + const grant = await grantService.create(body, tenantId, trx) const interaction = await interactionService.create(grant.id, trx) await trx.commit() diff --git a/packages/auth/src/grant/service.ts b/packages/auth/src/grant/service.ts index 051b3d0984..3609f6abdb 100644 --- a/packages/auth/src/grant/service.ts +++ b/packages/auth/src/grant/service.ts @@ -24,7 +24,7 @@ interface GrantFilter { export interface GrantService { getByIdWithAccess(grantId: string): Promise - create(grantRequest: GrantRequest, trx?: Transaction): Promise + create(grantRequest: GrantRequest, tenantId: string, trx?: Transaction): Promise markPending(grantId: string, trx?: Transaction): Promise approve(grantId: string, trx?: Transaction): Promise finalize(grantId: string, reason: GrantFinalization): Promise @@ -115,8 +115,8 @@ export async function createGrantService({ } return { getByIdWithAccess: (grantId: string) => getByIdWithAccess(grantId), - create: (grantRequest: GrantRequest, trx?: Transaction) => - create(deps, grantRequest, trx), + create: (grantRequest: GrantRequest, tenantId: string, trx?: Transaction) => + create(deps, grantRequest, tenantId, trx), markPending: (grantId: string, trx?: Transaction) => markPending(deps, grantId, trx), approve: (grantId: string) => approve(grantId), @@ -211,6 +211,7 @@ async function revokeGrant( async function create( deps: ServiceDependencies, grantRequest: GrantRequest, + tenantId: string, trx?: Transaction ): Promise { const { accessService, knex } = deps @@ -224,6 +225,7 @@ async function create( const grantTrx = trx || (await Grant.startTransaction(knex)) try { const grantData = { + tenantId, state: canSkipInteraction(deps.config, grantRequest) ? GrantState.Approved : GrantState.Pending, diff --git a/packages/backend/src/app.ts b/packages/backend/src/app.ts index 3f95a20822..d8fdf626d4 100644 --- a/packages/backend/src/app.ts +++ b/packages/backend/src/app.ts @@ -491,7 +491,7 @@ export class App { // POST /incoming-payments // Create incoming payment router.post>( - '/incoming-payments', + '/:tenantId/incoming-payments', createValidatorMiddleware< ContextType> >( @@ -518,7 +518,7 @@ export class App { DefaultState, SignedCollectionContext >( - '/incoming-payments', + '/:tenantId/incoming-payments', createValidatorMiddleware< ContextType> >( @@ -542,7 +542,7 @@ export class App { // POST /outgoing-payment // Create outgoing payment router.post>( - '/outgoing-payments', + '/:tenantId/outgoing-payments', createValidatorMiddleware< ContextType> >( @@ -569,7 +569,7 @@ export class App { DefaultState, SignedCollectionContext >( - '/outgoing-payments', + '/:tenantId/outgoing-payments', createValidatorMiddleware< ContextType> >( @@ -593,7 +593,7 @@ export class App { // POST /quotes // Create quote router.post>( - '/quotes', + '/:tenantId/quotes', createValidatorMiddleware< ContextType> >( @@ -617,7 +617,7 @@ export class App { // GET /incoming-payments/{id} // Read incoming payment router.get( - '/incoming-payments/:id', + '/:tenantId/incoming-payments/:id', createValidatorMiddleware< ContextType >( @@ -642,7 +642,7 @@ export class App { // POST /incoming-payments/{id}/complete // Complete incoming payment router.post( - '/incoming-payments/:id/complete', + '/:tenantId/incoming-payments/:id/complete', createValidatorMiddleware>( resourceServerSpec, { @@ -664,7 +664,7 @@ export class App { // GET /outgoing-payments/{id} // Read outgoing payment router.get( - '/outgoing-payments/:id', + '/:tenantId/outgoing-payments/:id', createValidatorMiddleware>( resourceServerSpec, { @@ -686,7 +686,7 @@ export class App { // GET /quotes/{id} // Read quote router.get( - '/quotes/:id', + '/:tenantId/quotes/:id', createValidatorMiddleware>( resourceServerSpec, { diff --git a/packages/backend/src/open_payments/payment/incoming/routes.ts b/packages/backend/src/open_payments/payment/incoming/routes.ts index ac1a38ee3c..f659970225 100644 --- a/packages/backend/src/open_payments/payment/incoming/routes.ts +++ b/packages/backend/src/open_payments/payment/incoming/routes.ts @@ -127,6 +127,7 @@ async function createIncomingPayment( ctx: CreateContext ): Promise { const { body } = ctx.request + const { tenantId } = ctx.params let expiresAt: Date | undefined if (body.expiresAt !== undefined) { @@ -134,6 +135,7 @@ async function createIncomingPayment( } const incomingPaymentOrError = await deps.incomingPaymentService.create({ + tenantId, walletAddressId: ctx.walletAddress.id, tenantId: ctx.tenantId, client: ctx.client, diff --git a/packages/backend/src/open_payments/payment/outgoing/routes.ts b/packages/backend/src/open_payments/payment/outgoing/routes.ts index e39e0c3baf..fa50cdc52b 100644 --- a/packages/backend/src/open_payments/payment/outgoing/routes.ts +++ b/packages/backend/src/open_payments/payment/outgoing/routes.ts @@ -97,6 +97,7 @@ async function createOutgoingPayment( ctx: CreateContext ): Promise { const { body } = ctx.request + const { tenantId } = ctx.params const baseOptions: OutgoingPaymentCreateBaseOptions = { walletAddressId: ctx.walletAddress.id, metadata: body.metadata, @@ -108,6 +109,7 @@ async function createOutgoingPayment( if (isCreateFromIncomingPayment(body)) { options = { ...baseOptions, + tenantId, incomingPayment: body.incomingPayment, debitAmount: body.debitAmount } @@ -122,6 +124,7 @@ async function createOutgoingPayment( } options = { ...baseOptions, + tenantId, quoteId } } diff --git a/packages/backend/src/open_payments/quote/routes.ts b/packages/backend/src/open_payments/quote/routes.ts index bbe9c994d9..6435d1c11b 100644 --- a/packages/backend/src/open_payments/quote/routes.ts +++ b/packages/backend/src/open_payments/quote/routes.ts @@ -73,7 +73,9 @@ async function createQuote( ctx: CreateContext ): Promise { const { body } = ctx.request + const { tenantId } = ctx.params const options: CreateQuoteOptions = { + tenantId, walletAddressId: ctx.walletAddress.id, tenantId: ctx.tenantId, receiver: body.receiver, diff --git a/packages/backend/src/open_payments/wallet_address/routes.ts b/packages/backend/src/open_payments/wallet_address/routes.ts index 652394985e..be78be0539 100644 --- a/packages/backend/src/open_payments/wallet_address/routes.ts +++ b/packages/backend/src/open_payments/wallet_address/routes.ts @@ -60,8 +60,8 @@ export async function getWalletAddress( ) ctx.body = walletAddress.toOpenPaymentsType({ - authServer: deps.config.authServerGrantUrl, - resourceServer: deps.config.openPaymentsUrl + authServer: `${deps.config.authServerGrantUrl}/${walletAddress.tenantId}`, + resourceServer: `${deps.config.openPaymentsUrl}/${walletAddress.tenantId}` }) } diff --git a/packages/frontend/app/lib/api/tenant.server.ts b/packages/frontend/app/lib/api/tenant.server.ts index 67cf13f486..431cdba0ed 100644 --- a/packages/frontend/app/lib/api/tenant.server.ts +++ b/packages/frontend/app/lib/api/tenant.server.ts @@ -48,6 +48,7 @@ export const listTenants = async (args: QueryTenantsArgs, cookie?: string) => { node { id createdAt + email } } pageInfo { diff --git a/packages/frontend/app/routes/tenants._index.tsx b/packages/frontend/app/routes/tenants._index.tsx index ac9dbc9b8b..14da1de40c 100644 --- a/packages/frontend/app/routes/tenants._index.tsx +++ b/packages/frontend/app/routes/tenants._index.tsx @@ -70,6 +70,7 @@ export default function TenantsPage() { onClick={() => navigate(`/tenants/${tenant.node.id}`)} > {tenant.node.id} + {tenant.node.email} )) ) : ( From 5a1af30968ae1b6e74d961bdc7d677cf363c5537 Mon Sep 17 00:00:00 2001 From: Nathan Lie Date: Tue, 24 Sep 2024 09:35:46 -0700 Subject: [PATCH 20/24] feat: quote grant requests with tenantId --- .../src/open_payments/payment/incoming/model.ts | 2 +- .../src/open_payments/payment/incoming/routes.ts | 1 - .../payment/incoming_remote/service.ts | 16 ++++++++++++---- .../backend/src/open_payments/quote/routes.ts | 1 - .../backend/src/open_payments/quote/service.ts | 3 ++- .../src/open_payments/receiver/service.ts | 15 +++++++++------ 6 files changed, 24 insertions(+), 14 deletions(-) diff --git a/packages/backend/src/open_payments/payment/incoming/model.ts b/packages/backend/src/open_payments/payment/incoming/model.ts index 71913b1df4..4b6ff13e01 100644 --- a/packages/backend/src/open_payments/payment/incoming/model.ts +++ b/packages/backend/src/open_payments/payment/incoming/model.ts @@ -265,7 +265,7 @@ export class IncomingPayment } { return { receivedAmount: serializeAmount(this.receivedAmount), - authServer: authServerUrl + authServer: `${authServerUrl}/${this.tenantId}` } } } diff --git a/packages/backend/src/open_payments/payment/incoming/routes.ts b/packages/backend/src/open_payments/payment/incoming/routes.ts index f659970225..d5cdc50dc2 100644 --- a/packages/backend/src/open_payments/payment/incoming/routes.ts +++ b/packages/backend/src/open_payments/payment/incoming/routes.ts @@ -137,7 +137,6 @@ async function createIncomingPayment( const incomingPaymentOrError = await deps.incomingPaymentService.create({ tenantId, walletAddressId: ctx.walletAddress.id, - tenantId: ctx.tenantId, client: ctx.client, metadata: body.metadata, expiresAt, diff --git a/packages/backend/src/open_payments/payment/incoming_remote/service.ts b/packages/backend/src/open_payments/payment/incoming_remote/service.ts index 84920d13c3..0c6b77eec2 100644 --- a/packages/backend/src/open_payments/payment/incoming_remote/service.ts +++ b/packages/backend/src/open_payments/payment/incoming_remote/service.ts @@ -16,6 +16,7 @@ import { isGrantError } from '../../grant/errors' interface CreateRemoteIncomingPaymentArgs { walletAddressUrl: string + tenantId: string expiresAt?: Date incomingAmount?: Amount metadata?: Record @@ -23,7 +24,8 @@ interface CreateRemoteIncomingPaymentArgs { export interface RemoteIncomingPaymentService { get( - url: string + url: string, + tenantId: string ): Promise< OpenPaymentsIncomingPaymentWithPaymentMethods | RemoteIncomingPaymentError > @@ -52,7 +54,7 @@ export async function createRemoteIncomingPaymentService( } return { - get: (url) => get(deps, url), + get: (url, tenantId) => get(deps, url, tenantId), create: (args) => create(deps, args) } } @@ -103,6 +105,7 @@ async function createIncomingPayment( const grantOptions = { authServer: walletAddress.authServer, + tenantId: createArgs.tenantId, accessType: AccessType.IncomingPayment, accessActions: [AccessAction.Create, AccessAction.ReadAll] } @@ -176,7 +179,8 @@ async function createIncomingPayment( async function get( deps: ServiceDependencies, - url: string + url: string, + tenantId: string ): Promise< OpenPaymentsIncomingPaymentWithPaymentMethods | RemoteIncomingPaymentError > { @@ -199,6 +203,7 @@ async function get( return getIncomingPayment(deps, { url, + tenantId, authServerUrl: publicIncomingPayment.authServer }) } @@ -207,13 +212,15 @@ async function getIncomingPayment( deps: ServiceDependencies, { url, + tenantId, authServerUrl, retryOnTokenError = true - }: { url: string; authServerUrl: string; retryOnTokenError?: boolean } + }: { url: string; tenantId: string; authServerUrl: string; retryOnTokenError?: boolean } ): Promise< OpenPaymentsIncomingPaymentWithPaymentMethods | RemoteIncomingPaymentError > { const grantOptions = { + tenantId, authServer: authServerUrl, accessType: AccessType.IncomingPayment, accessActions: [AccessAction.ReadAll] @@ -267,6 +274,7 @@ async function getIncomingPayment( return getIncomingPayment(deps, { url, + tenantId, authServerUrl, retryOnTokenError: false }) diff --git a/packages/backend/src/open_payments/quote/routes.ts b/packages/backend/src/open_payments/quote/routes.ts index 6435d1c11b..a20073fc30 100644 --- a/packages/backend/src/open_payments/quote/routes.ts +++ b/packages/backend/src/open_payments/quote/routes.ts @@ -77,7 +77,6 @@ async function createQuote( const options: CreateQuoteOptions = { tenantId, walletAddressId: ctx.walletAddress.id, - tenantId: ctx.tenantId, receiver: body.receiver, client: ctx.client, method: body.method diff --git a/packages/backend/src/open_payments/quote/service.ts b/packages/backend/src/open_payments/quote/service.ts index 8fbe06d407..aedd716145 100644 --- a/packages/backend/src/open_payments/quote/service.ts +++ b/packages/backend/src/open_payments/quote/service.ts @@ -61,6 +61,7 @@ async function getQuote( interface QuoteOptionsBase { walletAddressId: string + tenantId: string receiver: string method: 'ilp' client?: string @@ -182,7 +183,7 @@ export async function resolveReceiver( deps: ServiceDependencies, options: CreateQuoteOptions ): Promise { - const receiver = await deps.receiverService.get(options.receiver) + const receiver = await deps.receiverService.get(options.receiver, options.tenantId) if (!receiver) { deps.logger.info( { receiver: options.receiver }, diff --git a/packages/backend/src/open_payments/receiver/service.ts b/packages/backend/src/open_payments/receiver/service.ts index cfd04f55f1..7c21dd0838 100644 --- a/packages/backend/src/open_payments/receiver/service.ts +++ b/packages/backend/src/open_payments/receiver/service.ts @@ -17,6 +17,7 @@ import { isRemoteIncomingPaymentError } from '../payment/incoming_remote/errors' interface CreateReceiverArgs { walletAddressUrl: string + tenantId: string expiresAt?: Date incomingAmount?: Amount metadata?: Record @@ -24,7 +25,7 @@ interface CreateReceiverArgs { // A receiver is resolved from an incoming payment export interface ReceiverService { - get(url: string): Promise + get(url: string, tenantId: string): Promise create(args: CreateReceiverArgs): Promise } @@ -50,7 +51,7 @@ export async function createReceiverService( } return { - get: (url) => getReceiver(deps, url), + get: (url, tenantId) => getReceiver(deps, url, tenantId), create: (url) => createReceiver(deps, url) } } @@ -135,7 +136,8 @@ async function createLocalIncomingPayment( async function getReceiver( deps: ServiceDependencies, - url: string + url: string, + tenantId: string ): Promise { try { const localIncomingPayment = await getLocalIncomingPayment(deps, url) @@ -143,7 +145,7 @@ async function getReceiver( return new Receiver(localIncomingPayment, true) } - const remoteIncomingPayment = await getRemoteIncomingPayment(deps, url) + const remoteIncomingPayment = await getRemoteIncomingPayment(deps, url, tenantId) if (remoteIncomingPayment) { return new Receiver(remoteIncomingPayment, false) } @@ -212,10 +214,11 @@ export async function getLocalIncomingPayment( async function getRemoteIncomingPayment( deps: ServiceDependencies, - url: string + url: string, + tenantId: string ): Promise { const incomingPaymentOrError = - await deps.remoteIncomingPaymentService.get(url) + await deps.remoteIncomingPaymentService.get(url, tenantId) if (isRemoteIncomingPaymentError(incomingPaymentOrError)) { return undefined From 293a52d69ec85f1ac5394e6b71f9d79ebc20c240 Mon Sep 17 00:00:00 2001 From: Nathan Lie Date: Tue, 24 Sep 2024 10:41:42 -0700 Subject: [PATCH 21/24] feat: outgoing payment with tenantId --- packages/backend/src/open_payments/payment/incoming/model.ts | 2 +- packages/backend/src/open_payments/payment/outgoing/service.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/open_payments/payment/incoming/model.ts b/packages/backend/src/open_payments/payment/incoming/model.ts index 4b6ff13e01..c11d3805d2 100644 --- a/packages/backend/src/open_payments/payment/incoming/model.ts +++ b/packages/backend/src/open_payments/payment/incoming/model.ts @@ -146,7 +146,7 @@ export class IncomingPayment public getUrl(walletAddress: WalletAddress): string { const url = new URL(walletAddress.url) - return `${url.origin}${IncomingPayment.urlPath}/${this.id}` + return `${url.origin}/${this.tenantId}${IncomingPayment.urlPath}/${this.id}` } public async onCredit({ diff --git a/packages/backend/src/open_payments/payment/outgoing/service.ts b/packages/backend/src/open_payments/payment/outgoing/service.ts index 507ef0d857..b64faf539e 100644 --- a/packages/backend/src/open_payments/payment/outgoing/service.ts +++ b/packages/backend/src/open_payments/payment/outgoing/service.ts @@ -288,7 +288,7 @@ async function createOutgoingPayment( throw OutgoingPaymentError.InsufficientGrant } } - const receiver = await deps.receiverService.get(payment.receiver) + const receiver = await deps.receiverService.get(payment.receiver, options.tenantId) if (!receiver) { throw OutgoingPaymentError.InvalidQuote } From d35a35243676b468bdd8e603e14a95af13acf0be Mon Sep 17 00:00:00 2001 From: Nathan Lie Date: Tue, 24 Sep 2024 11:00:52 -0700 Subject: [PATCH 22/24] chore: formatting --- packages/auth/src/grant/service.ts | 6 +++++- packages/backend/src/app.ts | 1 - .../open_payments/payment/incoming_remote/service.ts | 7 ++++++- .../src/open_payments/payment/outgoing/service.ts | 5 ++++- packages/backend/src/open_payments/quote/service.ts | 5 ++++- .../backend/src/open_payments/receiver/service.ts | 12 +++++++++--- 6 files changed, 28 insertions(+), 8 deletions(-) diff --git a/packages/auth/src/grant/service.ts b/packages/auth/src/grant/service.ts index 3609f6abdb..b96c0b61e7 100644 --- a/packages/auth/src/grant/service.ts +++ b/packages/auth/src/grant/service.ts @@ -24,7 +24,11 @@ interface GrantFilter { export interface GrantService { getByIdWithAccess(grantId: string): Promise - create(grantRequest: GrantRequest, tenantId: string, trx?: Transaction): Promise + create( + grantRequest: GrantRequest, + tenantId: string, + trx?: Transaction + ): Promise markPending(grantId: string, trx?: Transaction): Promise approve(grantId: string, trx?: Transaction): Promise finalize(grantId: string, reason: GrantFinalization): Promise diff --git a/packages/backend/src/app.ts b/packages/backend/src/app.ts index d8fdf626d4..f9d27d80f6 100644 --- a/packages/backend/src/app.ts +++ b/packages/backend/src/app.ts @@ -1,7 +1,6 @@ import { join } from 'path' import http, { Server } from 'http' import { ParsedUrlQuery } from 'querystring' -import axios from 'axios' import { Client as TigerbeetleClient } from 'tigerbeetle-node' import { IocContract } from '@adonisjs/fold' diff --git a/packages/backend/src/open_payments/payment/incoming_remote/service.ts b/packages/backend/src/open_payments/payment/incoming_remote/service.ts index 0c6b77eec2..9e8154ea01 100644 --- a/packages/backend/src/open_payments/payment/incoming_remote/service.ts +++ b/packages/backend/src/open_payments/payment/incoming_remote/service.ts @@ -215,7 +215,12 @@ async function getIncomingPayment( tenantId, authServerUrl, retryOnTokenError = true - }: { url: string; tenantId: string; authServerUrl: string; retryOnTokenError?: boolean } + }: { + url: string + tenantId: string + authServerUrl: string + retryOnTokenError?: boolean + } ): Promise< OpenPaymentsIncomingPaymentWithPaymentMethods | RemoteIncomingPaymentError > { diff --git a/packages/backend/src/open_payments/payment/outgoing/service.ts b/packages/backend/src/open_payments/payment/outgoing/service.ts index b64faf539e..afcbd80128 100644 --- a/packages/backend/src/open_payments/payment/outgoing/service.ts +++ b/packages/backend/src/open_payments/payment/outgoing/service.ts @@ -288,7 +288,10 @@ async function createOutgoingPayment( throw OutgoingPaymentError.InsufficientGrant } } - const receiver = await deps.receiverService.get(payment.receiver, options.tenantId) + const receiver = await deps.receiverService.get( + payment.receiver, + options.tenantId + ) if (!receiver) { throw OutgoingPaymentError.InvalidQuote } diff --git a/packages/backend/src/open_payments/quote/service.ts b/packages/backend/src/open_payments/quote/service.ts index aedd716145..0ce81fe63d 100644 --- a/packages/backend/src/open_payments/quote/service.ts +++ b/packages/backend/src/open_payments/quote/service.ts @@ -183,7 +183,10 @@ export async function resolveReceiver( deps: ServiceDependencies, options: CreateQuoteOptions ): Promise { - const receiver = await deps.receiverService.get(options.receiver, options.tenantId) + const receiver = await deps.receiverService.get( + options.receiver, + options.tenantId + ) if (!receiver) { deps.logger.info( { receiver: options.receiver }, diff --git a/packages/backend/src/open_payments/receiver/service.ts b/packages/backend/src/open_payments/receiver/service.ts index 7c21dd0838..10a12f1c57 100644 --- a/packages/backend/src/open_payments/receiver/service.ts +++ b/packages/backend/src/open_payments/receiver/service.ts @@ -145,7 +145,11 @@ async function getReceiver( return new Receiver(localIncomingPayment, true) } - const remoteIncomingPayment = await getRemoteIncomingPayment(deps, url, tenantId) + const remoteIncomingPayment = await getRemoteIncomingPayment( + deps, + url, + tenantId + ) if (remoteIncomingPayment) { return new Receiver(remoteIncomingPayment, false) } @@ -217,8 +221,10 @@ async function getRemoteIncomingPayment( url: string, tenantId: string ): Promise { - const incomingPaymentOrError = - await deps.remoteIncomingPaymentService.get(url, tenantId) + const incomingPaymentOrError = await deps.remoteIncomingPaymentService.get( + url, + tenantId + ) if (isRemoteIncomingPaymentError(incomingPaymentOrError)) { return undefined From d7f28830bf02d165f213211b5e1c0915613a9ff9 Mon Sep 17 00:00:00 2001 From: Nathan Lie Date: Tue, 24 Sep 2024 13:03:17 -0700 Subject: [PATCH 23/24] feat: bruno updates --- .../Create Incoming Payment.bru | 2 +- .../Create Outgoing Payment.bru | 4 ++-- .../Open Payments Without Quote/Get Outgoing Payment.bru | 2 +- .../Get receiver wallet address.bru | 2 ++ .../Get sender wallet address.bru | 4 +++- .../Grant Request Incoming Payment.bru | 2 +- .../Grant Request Outgoing Payment.bru | 2 +- .../Examples/Open Payments/Create Incoming Payment.bru | 5 +++-- .../Examples/Open Payments/Create Outgoing Payment.bru | 4 ++-- .../Rafiki/Examples/Open Payments/Create Quote.bru | 4 ++-- .../Examples/Open Payments/Get Outgoing Payment.bru | 2 +- .../Open Payments/Get receiver wallet address.bru | 8 +++++--- .../Examples/Open Payments/Get sender wallet address.bru | 5 ++++- .../Open Payments/Grant Request Incoming Payment.bru | 2 +- .../Open Payments/Grant Request Outgoing Payment.bru | 2 +- .../Rafiki/Examples/Open Payments/Grant Request Quote.bru | 6 +++++- .../Examples/Web Monetization/Create Incoming Payment.bru | 4 ++-- .../Web Monetization/Create Outgoing Payment 1.bru | 6 +++--- .../Web Monetization/Create Outgoing Payment 2.bru | 4 ++-- .../Web Monetization/Create Outgoing Payment 3.bru | 4 ++-- .../Examples/Web Monetization/Get Outgoing Payment.bru | 2 +- .../Web Monetization/Get receiver wallet address.bru | 4 +++- .../Web Monetization/Get sender wallet address.bru | 2 ++ .../Web Monetization/Grant Request Incoming Payment.bru | 2 +- .../Web Monetization/Grant Request Outgoing Payment.bru | 2 +- .../Incoming Payments/Complete Incoming Payment.bru | 2 +- .../Incoming Payments/Create Incoming Payment.bru | 4 ++-- .../Get Incoming Payment -Unauthenticated-.bru | 2 +- .../Incoming Payments/Get Incoming Payment.bru | 2 +- .../Incoming Payments/List Incoming Payments.bru | 4 ++-- .../Outgoing Payments/Create Outgoing Payment.bru | 4 ++-- .../Outgoing Payments/Get Outgoing Payment.bru | 2 +- .../Outgoing Payments/List Outgoing Payments.bru | 4 ++-- .../Rafiki/Open Payments APIs/Quotes/Create Quote.bru | 4 ++-- .../Rafiki/Open Payments APIs/Quotes/Get Quote.bru | 2 +- .../Open Payments Auth APIs/Grants/Grant Request.bru | 2 +- .../collections/Rafiki/environments/Local Playground.bru | 1 + 37 files changed, 69 insertions(+), 50 deletions(-) diff --git a/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Create Incoming Payment.bru b/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Create Incoming Payment.bru index 6fffd0742c..222f68ceb3 100644 --- a/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Create Incoming Payment.bru +++ b/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Create Incoming Payment.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{receiverOpenPaymentsHost}}/incoming-payments + url: {{receiverOpenPaymentsHost}}/{{receiverTenantId}}/incoming-payments body: json auth: none } diff --git a/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Create Outgoing Payment.bru b/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Create Outgoing Payment.bru index 4d9e3a2a63..6fb3d5c951 100644 --- a/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Create Outgoing Payment.bru +++ b/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Create Outgoing Payment.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{senderOpenPaymentsHost}}/outgoing-payments + url: {{senderOpenPaymentsHost}}/{{senderTenantId}}/outgoing-payments body: json auth: none } @@ -35,7 +35,7 @@ script:pre-request { script:post-response { const body = res.getBody(); - + if (body?.id) { bru.setEnvVar("outgoingPaymentId", body.id.split("/").pop()); } diff --git a/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Get Outgoing Payment.bru b/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Get Outgoing Payment.bru index 4946e1b040..a1a4c417bd 100644 --- a/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Get Outgoing Payment.bru +++ b/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Get Outgoing Payment.bru @@ -5,7 +5,7 @@ meta { } get { - url: {{senderOpenPaymentsHost}}/outgoing-payments/{{outgoingPaymentId}} + url: {{senderOpenPaymentsHost}}/{{senderTenantId}}/outgoing-payments/{{outgoingPaymentId}} body: none auth: none } diff --git a/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Get receiver wallet address.bru b/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Get receiver wallet address.bru index 5b9b0277a9..788684b60b 100644 --- a/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Get receiver wallet address.bru +++ b/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Get receiver wallet address.bru @@ -32,6 +32,8 @@ script:post-response { bru.setEnvVar("receiverAssetScale", body?.assetScale) const authUrl = url.parse(body?.authServer) + const receiverTenantId = authUrl.pathname.split('/')[1] + bru.setEnvVar('receiverTenantId', receiverTenantId) if ( authUrl.hostname.includes('cloud-nine-wallet') || authUrl.hostname.includes('happy-life-bank') diff --git a/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Get sender wallet address.bru b/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Get sender wallet address.bru index 384cfa6282..3338e21cdd 100644 --- a/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Get sender wallet address.bru +++ b/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Get sender wallet address.bru @@ -28,11 +28,13 @@ script:post-response { } const body = res.getBody() - + bru.setEnvVar("senderAssetCode", body?.assetCode) bru.setEnvVar("senderAssetScale", body?.assetScale) const authUrl = url.parse(body?.authServer) + const senderTenantId = authUrl.pathname.split('/')[1] + bru.setEnvVar('senderTenantId', senderTenantId) if ( authUrl.hostname.includes('cloud-nine-wallet') || authUrl.hostname.includes('happy-life-bank') diff --git a/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Grant Request Incoming Payment.bru b/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Grant Request Incoming Payment.bru index 6335a518af..70eb34c474 100644 --- a/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Grant Request Incoming Payment.bru +++ b/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Grant Request Incoming Payment.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{receiverOpenPaymentsAuthHost}}/ + url: {{receiverOpenPaymentsAuthHost}}/{{receiverTenantId}} body: json auth: none } diff --git a/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Grant Request Outgoing Payment.bru b/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Grant Request Outgoing Payment.bru index 5c8213f66a..fa033b3171 100644 --- a/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Grant Request Outgoing Payment.bru +++ b/bruno/collections/Rafiki/Examples/Open Payments Without Quote/Grant Request Outgoing Payment.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{senderOpenPaymentsAuthHost}}/ + url: {{senderOpenPaymentsAuthHost}}/{{senderTenantId}} body: json auth: none } diff --git a/bruno/collections/Rafiki/Examples/Open Payments/Create Incoming Payment.bru b/bruno/collections/Rafiki/Examples/Open Payments/Create Incoming Payment.bru index afc6464ee6..85683d2983 100644 --- a/bruno/collections/Rafiki/Examples/Open Payments/Create Incoming Payment.bru +++ b/bruno/collections/Rafiki/Examples/Open Payments/Create Incoming Payment.bru @@ -5,13 +5,14 @@ meta { } post { - url: {{receiverOpenPaymentsHost}}/incoming-payments + url: {{receiverOpenPaymentsHost}}/{{receiverTenantId}}/incoming-payments body: json auth: none } headers { Authorization: GNAP {{accessToken}} + x-operator-secret: {{operatorApiSecret}} } body:json { @@ -41,7 +42,7 @@ script:pre-request { script:post-response { const body = res.getBody(); - + if (body?.id) { bru.setEnvVar("incomingPaymentId", body.id.split("/").pop()); } diff --git a/bruno/collections/Rafiki/Examples/Open Payments/Create Outgoing Payment.bru b/bruno/collections/Rafiki/Examples/Open Payments/Create Outgoing Payment.bru index e14eaa6536..f4f30599d3 100644 --- a/bruno/collections/Rafiki/Examples/Open Payments/Create Outgoing Payment.bru +++ b/bruno/collections/Rafiki/Examples/Open Payments/Create Outgoing Payment.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{senderOpenPaymentsHost}}/outgoing-payments + url: {{senderOpenPaymentsHost}}/{{senderTenantId}}/outgoing-payments body: json auth: none } @@ -34,7 +34,7 @@ script:pre-request { script:post-response { const body = res.getBody(); - + if (body?.id) { bru.setEnvVar("outgoingPaymentId", body.id.split("/").pop()); } diff --git a/bruno/collections/Rafiki/Examples/Open Payments/Create Quote.bru b/bruno/collections/Rafiki/Examples/Open Payments/Create Quote.bru index a7708217f4..5f0e702830 100644 --- a/bruno/collections/Rafiki/Examples/Open Payments/Create Quote.bru +++ b/bruno/collections/Rafiki/Examples/Open Payments/Create Quote.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{senderOpenPaymentsHost}}/quotes + url: {{senderOpenPaymentsHost}}/{{senderTenantId}}/quotes body: json auth: none } @@ -17,7 +17,7 @@ headers { body:json { { "walletAddress": "{{senderWalletAddress}}", - "receiver": "{{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}}", + "receiver": "{{receiverOpenPaymentsHost}}/{{receiverTenantId}}/incoming-payments/{{incomingPaymentId}}", "method": "ilp" } } diff --git a/bruno/collections/Rafiki/Examples/Open Payments/Get Outgoing Payment.bru b/bruno/collections/Rafiki/Examples/Open Payments/Get Outgoing Payment.bru index 4946e1b040..a1a4c417bd 100644 --- a/bruno/collections/Rafiki/Examples/Open Payments/Get Outgoing Payment.bru +++ b/bruno/collections/Rafiki/Examples/Open Payments/Get Outgoing Payment.bru @@ -5,7 +5,7 @@ meta { } get { - url: {{senderOpenPaymentsHost}}/outgoing-payments/{{outgoingPaymentId}} + url: {{senderOpenPaymentsHost}}/{{senderTenantId}}/outgoing-payments/{{outgoingPaymentId}} body: none auth: none } diff --git a/bruno/collections/Rafiki/Examples/Open Payments/Get receiver wallet address.bru b/bruno/collections/Rafiki/Examples/Open Payments/Get receiver wallet address.bru index 9e5acc50c4..9c57818fde 100644 --- a/bruno/collections/Rafiki/Examples/Open Payments/Get receiver wallet address.bru +++ b/bruno/collections/Rafiki/Examples/Open Payments/Get receiver wallet address.bru @@ -22,22 +22,24 @@ script:pre-request { script:post-response { const url = require('url') - + if (res.getStatus() !== 200) { return } - + const body = res.getBody() bru.setEnvVar("receiverAssetCode", body?.assetCode) bru.setEnvVar("receiverAssetScale", body?.assetScale) const authUrl = url.parse(body?.authServer) + const receiverTenantId = authUrl.pathname.split('/')[1] + bru.setEnvVar("receiverTenantId", receiverTenantId) if ( authUrl.hostname.includes('cloud-nine-wallet') || authUrl.hostname.includes('happy-life-bank') ){ const port = authUrl.hostname.includes('cloud-nine-wallet')? authUrl.port: Number(authUrl.port) + 1000 - bru.setEnvVar("receiverOpenPaymentsAuthHost", authUrl.protocol + '//localhost:' + port ); + bru.setEnvVar("receiverOpenPaymentsAuthHost", authUrl.protocol + '//localhost:' + port); } else { bru.setEnvVar("receiverOpenPaymentsAuthHost", body?.authServer); } diff --git a/bruno/collections/Rafiki/Examples/Open Payments/Get sender wallet address.bru b/bruno/collections/Rafiki/Examples/Open Payments/Get sender wallet address.bru index 9665a40e32..e371cf5f8b 100644 --- a/bruno/collections/Rafiki/Examples/Open Payments/Get sender wallet address.bru +++ b/bruno/collections/Rafiki/Examples/Open Payments/Get sender wallet address.bru @@ -32,15 +32,18 @@ script:post-response { bru.setEnvVar("senderAssetScale", body?.assetScale) const authUrl = url.parse(body?.authServer) + const senderTenantId = authUrl.pathname.split('/')[1] + bru.setEnvVar("senderTenantId", senderTenantId) if ( authUrl.hostname.includes('cloud-nine-wallet') || authUrl.hostname.includes('happy-life-bank') ){ const port = authUrl.hostname.includes('cloud-nine-wallet')? authUrl.port: Number(authUrl.port) + 1000 - bru.setEnvVar("senderOpenPaymentsAuthHost", authUrl.protocol + '//localhost:' + port ); + bru.setEnvVar("senderOpenPaymentsAuthHost", authUrl.protocol + '//localhost:' + port); } else { bru.setEnvVar("senderOpenPaymentsAuthHost", body?.authServer); } + } tests { diff --git a/bruno/collections/Rafiki/Examples/Open Payments/Grant Request Incoming Payment.bru b/bruno/collections/Rafiki/Examples/Open Payments/Grant Request Incoming Payment.bru index 6335a518af..70eb34c474 100644 --- a/bruno/collections/Rafiki/Examples/Open Payments/Grant Request Incoming Payment.bru +++ b/bruno/collections/Rafiki/Examples/Open Payments/Grant Request Incoming Payment.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{receiverOpenPaymentsAuthHost}}/ + url: {{receiverOpenPaymentsAuthHost}}/{{receiverTenantId}} body: json auth: none } diff --git a/bruno/collections/Rafiki/Examples/Open Payments/Grant Request Outgoing Payment.bru b/bruno/collections/Rafiki/Examples/Open Payments/Grant Request Outgoing Payment.bru index 5be7a46476..5460d7a019 100644 --- a/bruno/collections/Rafiki/Examples/Open Payments/Grant Request Outgoing Payment.bru +++ b/bruno/collections/Rafiki/Examples/Open Payments/Grant Request Outgoing Payment.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{senderOpenPaymentsAuthHost}}/ + url: {{senderOpenPaymentsAuthHost}}/{{senderTenantId}} body: json auth: none } diff --git a/bruno/collections/Rafiki/Examples/Open Payments/Grant Request Quote.bru b/bruno/collections/Rafiki/Examples/Open Payments/Grant Request Quote.bru index 3c0736670d..a8df671fe5 100644 --- a/bruno/collections/Rafiki/Examples/Open Payments/Grant Request Quote.bru +++ b/bruno/collections/Rafiki/Examples/Open Payments/Grant Request Quote.bru @@ -5,11 +5,15 @@ meta { } post { - url: {{senderOpenPaymentsAuthHost}}/ + url: {{senderOpenPaymentsAuthHost}}/{{senderTenantId}} body: json auth: none } +headers { + x-operator-secret: {{operatorApiSecret}} +} + body:json { { "access_token": { diff --git a/bruno/collections/Rafiki/Examples/Web Monetization/Create Incoming Payment.bru b/bruno/collections/Rafiki/Examples/Web Monetization/Create Incoming Payment.bru index 071e7df0be..8bb0d8ad12 100644 --- a/bruno/collections/Rafiki/Examples/Web Monetization/Create Incoming Payment.bru +++ b/bruno/collections/Rafiki/Examples/Web Monetization/Create Incoming Payment.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{receiverOpenPaymentsHost}}/incoming-payments + url: {{receiverOpenPaymentsHost}}/{{receiverTenantId}}/incoming-payments body: json auth: none } @@ -36,7 +36,7 @@ script:pre-request { script:post-response { const body = res.getBody(); - + if (body?.id) { bru.setEnvVar("incomingPaymentId", body.id.split("/").pop()); bru.setEnvVar("quoteDebitAmount", JSON.stringify({ diff --git a/bruno/collections/Rafiki/Examples/Web Monetization/Create Outgoing Payment 1.bru b/bruno/collections/Rafiki/Examples/Web Monetization/Create Outgoing Payment 1.bru index 6bdb591816..5abaf4db52 100644 --- a/bruno/collections/Rafiki/Examples/Web Monetization/Create Outgoing Payment 1.bru +++ b/bruno/collections/Rafiki/Examples/Web Monetization/Create Outgoing Payment 1.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{senderOpenPaymentsHost}}/outgoing-payments + url: {{senderOpenPaymentsHost}}/{{senderTenantId}}/outgoing-payments body: json auth: none } @@ -17,7 +17,7 @@ headers { body:json { { "walletAddress": "{{senderWalletAddress}}", - "incomingPayment": "{{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}}", + "incomingPayment": "{{receiverOpenPaymentsHost}}/{{receiverTenantId}}/incoming-payments/{{incomingPaymentId}}", "debitAmount": { "value": "300", "assetCode": "USD", @@ -40,7 +40,7 @@ script:pre-request { script:post-response { const body = res.getBody(); - + if (body?.id) { bru.setEnvVar("outgoingPaymentId", body.id.split("/").pop()); } diff --git a/bruno/collections/Rafiki/Examples/Web Monetization/Create Outgoing Payment 2.bru b/bruno/collections/Rafiki/Examples/Web Monetization/Create Outgoing Payment 2.bru index 6dce96ac06..82f99a5669 100644 --- a/bruno/collections/Rafiki/Examples/Web Monetization/Create Outgoing Payment 2.bru +++ b/bruno/collections/Rafiki/Examples/Web Monetization/Create Outgoing Payment 2.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{senderOpenPaymentsHost}}/outgoing-payments + url: {{senderOpenPaymentsHost}}/{{senderTenantId}}/outgoing-payments body: json auth: none } @@ -17,7 +17,7 @@ headers { body:json { { "walletAddress": "{{senderWalletAddress}}", - "incomingPayment": "{{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}}", + "incomingPayment": "{{receiverOpenPaymentsHost}}/{{receiverTenantId}}/incoming-payments/{{incomingPaymentId}}", "debitAmount": { "value": "300", "assetCode": "USD", diff --git a/bruno/collections/Rafiki/Examples/Web Monetization/Create Outgoing Payment 3.bru b/bruno/collections/Rafiki/Examples/Web Monetization/Create Outgoing Payment 3.bru index 814d2171de..9b6300a5b8 100644 --- a/bruno/collections/Rafiki/Examples/Web Monetization/Create Outgoing Payment 3.bru +++ b/bruno/collections/Rafiki/Examples/Web Monetization/Create Outgoing Payment 3.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{senderOpenPaymentsHost}}/outgoing-payments + url: {{senderOpenPaymentsHost}}/{{senderTenantId}}/outgoing-payments body: json auth: none } @@ -17,7 +17,7 @@ headers { body:json { { "walletAddress": "{{senderWalletAddress}}", - "incomingPayment": "{{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}}", + "incomingPayment": "{{receiverOpenPaymentsHost}}/{{receiverTenantId}}/incoming-payments/{{incomingPaymentId}}", "debitAmount": { "value": "300", "assetCode": "USD", diff --git a/bruno/collections/Rafiki/Examples/Web Monetization/Get Outgoing Payment.bru b/bruno/collections/Rafiki/Examples/Web Monetization/Get Outgoing Payment.bru index 7c38f47444..3eb35e13c8 100644 --- a/bruno/collections/Rafiki/Examples/Web Monetization/Get Outgoing Payment.bru +++ b/bruno/collections/Rafiki/Examples/Web Monetization/Get Outgoing Payment.bru @@ -5,7 +5,7 @@ meta { } get { - url: {{senderOpenPaymentsHost}}/outgoing-payments/{{outgoingPaymentId}} + url: {{senderOpenPaymentsHost}}/{{senderTenantId}}/outgoing-payments/{{outgoingPaymentId}} body: none auth: none } diff --git a/bruno/collections/Rafiki/Examples/Web Monetization/Get receiver wallet address.bru b/bruno/collections/Rafiki/Examples/Web Monetization/Get receiver wallet address.bru index d59f39b24f..891c33a42a 100644 --- a/bruno/collections/Rafiki/Examples/Web Monetization/Get receiver wallet address.bru +++ b/bruno/collections/Rafiki/Examples/Web Monetization/Get receiver wallet address.bru @@ -28,11 +28,13 @@ script:post-response { } const body = res.getBody() - + bru.setEnvVar("receiverAssetCode", body?.assetCode) bru.setEnvVar("receiverAssetScale", body?.assetScale) const authUrl = url.parse(body?.authServer) + const receiverTenantId = authUrl.pathname.split('/')[1] + bru.setEnvVar('receiverTenantId', receiverTenantId) if ( authUrl.hostname.includes('cloud-nine-wallet') || authUrl.hostname.includes('happy-life-bank') diff --git a/bruno/collections/Rafiki/Examples/Web Monetization/Get sender wallet address.bru b/bruno/collections/Rafiki/Examples/Web Monetization/Get sender wallet address.bru index 9665a40e32..9b63145285 100644 --- a/bruno/collections/Rafiki/Examples/Web Monetization/Get sender wallet address.bru +++ b/bruno/collections/Rafiki/Examples/Web Monetization/Get sender wallet address.bru @@ -32,6 +32,8 @@ script:post-response { bru.setEnvVar("senderAssetScale", body?.assetScale) const authUrl = url.parse(body?.authServer) + const senderTenantId = authUrl.pathname.split('/')[1] + bru.setEnvVar('senderTenantId', senderTenantId) if ( authUrl.hostname.includes('cloud-nine-wallet') || authUrl.hostname.includes('happy-life-bank') diff --git a/bruno/collections/Rafiki/Examples/Web Monetization/Grant Request Incoming Payment.bru b/bruno/collections/Rafiki/Examples/Web Monetization/Grant Request Incoming Payment.bru index 6335a518af..70eb34c474 100644 --- a/bruno/collections/Rafiki/Examples/Web Monetization/Grant Request Incoming Payment.bru +++ b/bruno/collections/Rafiki/Examples/Web Monetization/Grant Request Incoming Payment.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{receiverOpenPaymentsAuthHost}}/ + url: {{receiverOpenPaymentsAuthHost}}/{{receiverTenantId}} body: json auth: none } diff --git a/bruno/collections/Rafiki/Examples/Web Monetization/Grant Request Outgoing Payment.bru b/bruno/collections/Rafiki/Examples/Web Monetization/Grant Request Outgoing Payment.bru index 5be7a46476..5460d7a019 100644 --- a/bruno/collections/Rafiki/Examples/Web Monetization/Grant Request Outgoing Payment.bru +++ b/bruno/collections/Rafiki/Examples/Web Monetization/Grant Request Outgoing Payment.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{senderOpenPaymentsAuthHost}}/ + url: {{senderOpenPaymentsAuthHost}}/{{senderTenantId}} body: json auth: none } diff --git a/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/Complete Incoming Payment.bru b/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/Complete Incoming Payment.bru index 0debce0d02..3e8177753d 100644 --- a/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/Complete Incoming Payment.bru +++ b/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/Complete Incoming Payment.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}}/complete + url: {{receiverOpenPaymentsHost}}/{{receiverTenantId}}/incoming-payments/{{incomingPaymentId}}/complete body: json auth: none } diff --git a/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/Create Incoming Payment.bru b/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/Create Incoming Payment.bru index c718828e1c..37b266901e 100644 --- a/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/Create Incoming Payment.bru +++ b/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/Create Incoming Payment.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{receiverOpenPaymentsHost}}/incoming-payments + url: {{receiverOpenPaymentsHost}}/{{receiverTenantId}}/incoming-payments body: json auth: none } @@ -42,7 +42,7 @@ script:pre-request { script:post-response { const body = res.getBody(); - + if (body?.id) { bru.setEnvVar("incomingPaymentId", body.id.split("/").pop()); } diff --git a/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/Get Incoming Payment -Unauthenticated-.bru b/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/Get Incoming Payment -Unauthenticated-.bru index d282f8123d..abba6b742a 100644 --- a/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/Get Incoming Payment -Unauthenticated-.bru +++ b/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/Get Incoming Payment -Unauthenticated-.bru @@ -5,7 +5,7 @@ meta { } get { - url: {{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}} + url: {{receiverOpenPaymentsHost}}/{{receiverTenantId}}/incoming-payments/{{incomingPaymentId}} body: none auth: none } diff --git a/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/Get Incoming Payment.bru b/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/Get Incoming Payment.bru index 797cf9ae66..cb3cefd4e7 100644 --- a/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/Get Incoming Payment.bru +++ b/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/Get Incoming Payment.bru @@ -5,7 +5,7 @@ meta { } get { - url: {{receiverOpenPaymentsHost}}/incoming-payments/{{incomingPaymentId}} + url: {{receiverOpenPaymentsHost}}/{{receiverTenantId}}/incoming-payments/{{incomingPaymentId}} body: none auth: none } diff --git a/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/List Incoming Payments.bru b/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/List Incoming Payments.bru index 9fd7a87872..a8a628b22d 100644 --- a/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/List Incoming Payments.bru +++ b/bruno/collections/Rafiki/Open Payments APIs/Incoming Payments/List Incoming Payments.bru @@ -5,12 +5,12 @@ meta { } get { - url: {{receiverOpenPaymentsHost}}/incoming-payments?first=10&wallet-address={{receiverWalletAddress}} + url: {{receiverOpenPaymentsHost}}/{{receiverTenantId}}/incoming-payments?first=10&wallet-address={{receiverWalletAddress}} body: none auth: none } -query { +params:query { first: 10 wallet-address: {{receiverWalletAddress}} ~cursor: ea3bf38f-2719-4473-a0f7-4ba967d1d81b diff --git a/bruno/collections/Rafiki/Open Payments APIs/Outgoing Payments/Create Outgoing Payment.bru b/bruno/collections/Rafiki/Open Payments APIs/Outgoing Payments/Create Outgoing Payment.bru index 62ec4793f7..d0158e7223 100644 --- a/bruno/collections/Rafiki/Open Payments APIs/Outgoing Payments/Create Outgoing Payment.bru +++ b/bruno/collections/Rafiki/Open Payments APIs/Outgoing Payments/Create Outgoing Payment.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{senderOpenPaymentsHost}}/outgoing-payments + url: {{senderOpenPaymentsHost}}/{{senderTenantId}}/outgoing-payments body: json auth: none } @@ -16,7 +16,7 @@ headers { body:json { { - "walletAddress": {{senderWalletAddress}}, + "walletAddress": "{{senderWalletAddress}}", "quoteId": "{{senderOpenPaymentsHost}}/quotes/{{quoteId}}", "metadata": { "description": "yolo", diff --git a/bruno/collections/Rafiki/Open Payments APIs/Outgoing Payments/Get Outgoing Payment.bru b/bruno/collections/Rafiki/Open Payments APIs/Outgoing Payments/Get Outgoing Payment.bru index a434aa6bfa..1af3991ab8 100644 --- a/bruno/collections/Rafiki/Open Payments APIs/Outgoing Payments/Get Outgoing Payment.bru +++ b/bruno/collections/Rafiki/Open Payments APIs/Outgoing Payments/Get Outgoing Payment.bru @@ -5,7 +5,7 @@ meta { } get { - url: {{senderOpenPaymentsHost}}/outgoing-payments/{{outgoingPaymentId}} + url: {{senderOpenPaymentsHost}}/{{senderTenantId}}/outgoing-payments/{{outgoingPaymentId}} body: none auth: none } diff --git a/bruno/collections/Rafiki/Open Payments APIs/Outgoing Payments/List Outgoing Payments.bru b/bruno/collections/Rafiki/Open Payments APIs/Outgoing Payments/List Outgoing Payments.bru index d85bd35fa5..17b1bce0aa 100644 --- a/bruno/collections/Rafiki/Open Payments APIs/Outgoing Payments/List Outgoing Payments.bru +++ b/bruno/collections/Rafiki/Open Payments APIs/Outgoing Payments/List Outgoing Payments.bru @@ -5,12 +5,12 @@ meta { } get { - url: {{senderOpenPaymentsHost}}/outgoing-payments?first=2&wallet-address={{senderWalletAddress}} + url: {{senderOpenPaymentsHost}}/{{senderTenantId}}/outgoing-payments?first=2&wallet-address={{senderWalletAddress}} body: none auth: none } -query { +params:query { first: 2 wallet-address: {{senderWalletAddress}} ~cursor: ea3bf38f-2719-4473-a0f7-4ba967d1d81b diff --git a/bruno/collections/Rafiki/Open Payments APIs/Quotes/Create Quote.bru b/bruno/collections/Rafiki/Open Payments APIs/Quotes/Create Quote.bru index 1e53624a2c..03bc78d913 100644 --- a/bruno/collections/Rafiki/Open Payments APIs/Quotes/Create Quote.bru +++ b/bruno/collections/Rafiki/Open Payments APIs/Quotes/Create Quote.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{senderOpenPaymentsHost}}/quotes + url: {{senderOpenPaymentsHost}}/{{senderTenantId}}/quotes body: json auth: none } @@ -37,7 +37,7 @@ script:pre-request { script:post-response { const body = res.getBody(); - + if (body?.id) { bru.setEnvVar("quoteId", body.id.split("/").pop()); bru.setEnvVar("quoteDebitAmount", JSON.stringify(body.debitAmount)) diff --git a/bruno/collections/Rafiki/Open Payments APIs/Quotes/Get Quote.bru b/bruno/collections/Rafiki/Open Payments APIs/Quotes/Get Quote.bru index 008c63222f..273b72b97d 100644 --- a/bruno/collections/Rafiki/Open Payments APIs/Quotes/Get Quote.bru +++ b/bruno/collections/Rafiki/Open Payments APIs/Quotes/Get Quote.bru @@ -5,7 +5,7 @@ meta { } get { - url: {{senderOpenPaymentsHost}}/quotes/{{quoteId}} + url: {{senderOpenPaymentsHost}}/{{senderTenantId}}/quotes/{{quoteId}} body: none auth: none } diff --git a/bruno/collections/Rafiki/Open Payments Auth APIs/Grants/Grant Request.bru b/bruno/collections/Rafiki/Open Payments Auth APIs/Grants/Grant Request.bru index 0f5d41e8d7..5d4488504e 100644 --- a/bruno/collections/Rafiki/Open Payments Auth APIs/Grants/Grant Request.bru +++ b/bruno/collections/Rafiki/Open Payments Auth APIs/Grants/Grant Request.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{receiverOpenPaymentsAuthHost}}/ + url: {{receiverOpenPaymentsAuthHost}}/{{receiverTenantId}} body: json auth: none } diff --git a/bruno/collections/Rafiki/environments/Local Playground.bru b/bruno/collections/Rafiki/environments/Local Playground.bru index 59244355df..45fb14ed6b 100644 --- a/bruno/collections/Rafiki/environments/Local Playground.bru +++ b/bruno/collections/Rafiki/environments/Local Playground.bru @@ -28,4 +28,5 @@ vars { authApiSignatureVersion: 1 authApiSignatureSecret: rPoZpe9tVyBNCigm05QDco7WLcYa0xMao7lO5KG1XG4= assetIdTigerBeetle: 1 + operatorApiSecret: tXhxCNRWuVOJs5W/CUgjsc+vBnKj0CVdqSb87EXN64E= } From 15ee2345a2db139dd2fd7366ca7c7fa513991e52 Mon Sep 17 00:00:00 2001 From: Nathan Lie Date: Tue, 24 Sep 2024 13:42:13 -0700 Subject: [PATCH 24/24] chore: remove some dangling merge stuff --- packages/backend/src/graphql/resolvers/tenant.ts | 1 - packages/backend/src/index.ts | 2 -- 2 files changed, 3 deletions(-) diff --git a/packages/backend/src/graphql/resolvers/tenant.ts b/packages/backend/src/graphql/resolvers/tenant.ts index 8a2df3d4a8..394c01d232 100644 --- a/packages/backend/src/graphql/resolvers/tenant.ts +++ b/packages/backend/src/graphql/resolvers/tenant.ts @@ -64,7 +64,6 @@ export const getTenant: QueryResolvers['tenant'] = async ( } }) } - console.log('TENANT: ', tenant) return tenantToGraphql(tenant) } diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index 57e295c04e..554a931ea4 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -758,8 +758,6 @@ export const start = async ( `Auto-peering server listening on ${config.autoPeeringServerPort}` ) } - - await app.createOperatorIdentity() } // If this script is run directly, start the server