Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(backend): backend tenant graphql resolvers #3234

Open
wants to merge 9 commits into
base: 2893/multi-tenancy-v1
Choose a base branch
from

Conversation

njlie
Copy link
Contributor

@njlie njlie commented Jan 21, 2025

Changes proposed in this pull request

  • Adds the following resolvers to the backend Admin GraphQL API:
    • whoami
    • tenant
    • tenants
    • createTenant
    • updateTenant
    • deleteTenant

Context

Fixes #3124.

Checklist

  • Related issues linked using fixes #number
  • Tests added/updated
  • Make sure that all checks pass
  • Bruno collection updated (if necessary)
  • Documentation issue created with user-docs label (if necessary)
  • OpenAPI specs updated (if necessary)

@github-actions github-actions bot added type: tests Testing related pkg: backend Changes in the backend package. pkg: frontend Changes in the frontend package. type: source Changes business logic pkg: mock-ase pkg: mock-account-service-lib labels Jan 21, 2025
@njlie njlie force-pushed the nl/3124/backend-tenant-resolvers branch from 23e34b2 to 99d6982 Compare January 21, 2025 22:16
@njlie njlie marked this pull request as ready for review January 21, 2025 22:20
koekiebox

This comment was marked as outdated.

Copy link
Collaborator

@koekiebox koekiebox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code in the PR looks good.
Just the Bruno collection to be added.

@mkurapov mkurapov linked an issue Jan 23, 2025 that may be closed by this pull request
6 tasks
Comment on lines 155 to 156
"Fetch a paginated list of tenants on the instance."
tenants(
Copy link
Contributor

@BlairCurrey BlairCurrey Jan 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably mention this is for operators only. I also wondered about using a new isOperator directive instead of throwing in the resolver. Not sure it matters much but I wonder if the generated docs would pick it up. Maybe not much point unless we have more resolvers that use it though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the createTenant is operator only as well. So should probably note it there in the same way.

beforeAll(async (): Promise<void> => {
deps = await initIocContainer({
...Config,
databaseUrl: process.env.TENANT_TEST_DATABASE_URL as string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this separate db instead of just using TEST_DATABASE_URL?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added another test database to handle pagination tests correctly for tenants. Pagination tests need to truncate the tables between tests in order to work properly - if we do this on the same database as the other tests, that will break the ones that require the existence of an operator tenant to work, as it will have been deleted.

I realize that the pagination tests will be testing a scenario that shouldn't happen, but I feel like it makes sense to do it this way to make sure that pagination works correctly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can get away with this by using e.g. dbSchema config instead. This is how I ended up solving this (comment).

@njlie njlie requested a review from koekiebox January 24, 2025 21:26
@@ -1493,6 +1527,75 @@ type CancelIncomingPaymentResponse {
payment: IncomingPayment
}

type Tenant implements Model {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the create tenants migration, email, idpConsentUrl and idpSecret (in the model and the create input) should be optional

test('Cannot get page as non-operator', async (): Promise<void> => {
const tenant = await createTenant(deps)
const apolloClient = createTenantedApolloClient(appContainer, tenant.id)
try {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
try {
try {
expect.assertions(2)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same for a few tests below)

beforeAll(async (): Promise<void> => {
deps = await initIocContainer({
...Config,
databaseUrl: process.env.TENANT_TEST_DATABASE_URL as string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can get away with this by using e.g. dbSchema config instead. This is how I ended up solving this (comment).

Copy link
Collaborator

@koekiebox koekiebox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Copy link
Collaborator

@koekiebox koekiebox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/interledger/rafiki/actions/runs/12996726301/job/36246174979?pr=3234

Just need to look at the unit and integration tests failing.

@@ -3,6 +3,8 @@ set -e

psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
DROP DATABASE IF EXISTS TESTING;
DROP DATABASE IF EXISTS TENANT_TESTING;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can be removed as well

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(still applies)

@@ -148,6 +148,26 @@ type Query {
"Unique identifier of the receiver (incoming payment URL)."
id: String!
): Receiver

"Retrieve a tenant of the instance."
tenant("Unique identifier of the tenant." id: String!): Tenant
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
tenant("Unique identifier of the tenant." id: String!): Tenant
tenant("Unique identifier of the tenant." id: String!): Tenant!

Since resolver throws if the tenant isn't found

${true} | ${'operator'}
${false} | ${'tenant'}
`(
'Can delete a tenant as $description',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean a tenant can delete itself?
If so, do you think should it be reserved only for operators?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making deleteTenant operator-only as per call today.

@github-actions github-actions bot added the pkg: auth Changes in the GNAP auth package. label Jan 28, 2025
Copy link
Collaborator

@koekiebox koekiebox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Copy link
Contributor

@mkurapov mkurapov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few final things

@@ -1,4 +1,4 @@
process.env.LOG_LEVEL = 'silent'
process.env.LOG_LEVEL = 'info'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we leave it as silent to keep the test output tidy

@@ -3,6 +3,8 @@ set -e

psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
DROP DATABASE IF EXISTS TESTING;
DROP DATABASE IF EXISTS TENANT_TESTING;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(still applies)

${false} | ${'tenant'}
`('whoami query as $description', async ({ isOperator }): Promise<void> => {
const tenant = await createTenant(deps)
console.log('created tenant')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
console.log('created tenant')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg: auth Changes in the GNAP auth package. pkg: backend Changes in the backend package. pkg: frontend Changes in the frontend package. pkg: mock-account-service-lib pkg: mock-ase type: source Changes business logic type: tests Testing related
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Multi-Tenant] backend Admin Tenant API
4 participants