From 6dab5836c3f82a342c59bfb44f7cc3afcce7fbb3 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 25 Oct 2018 11:51:28 -0600 Subject: [PATCH] review: adapted graph responses for OIDC mutations --- .../server/graph/tenant/mutators/settings.ts | 12 +-- .../server/graph/tenant/resolvers/mutation.ts | 48 +++++++--- .../server/graph/tenant/schema/schema.graphql | 18 +++- src/core/server/models/tenant.ts | 89 +++++++++++++++++-- src/core/server/services/tenant/index.ts | 34 ++++--- 5 files changed, 151 insertions(+), 50 deletions(-) diff --git a/src/core/server/graph/tenant/mutators/settings.ts b/src/core/server/graph/tenant/mutators/settings.ts index 065e709d3..16c3ac6c0 100644 --- a/src/core/server/graph/tenant/mutators/settings.ts +++ b/src/core/server/graph/tenant/mutators/settings.ts @@ -21,9 +21,7 @@ export default ({ mongo, redis, tenantCache, tenant }: TenantContext) => ({ update(mongo, redis, tenantCache, tenant, omitBy(input, isNull)), regenerateSSOKey: (): Promise => regenerateSSOKey(mongo, redis, tenantCache, tenant), - createOIDCAuthIntegration: ( - input: GQLCreateOIDCAuthIntegrationInput - ): Promise => + createOIDCAuthIntegration: (input: GQLCreateOIDCAuthIntegrationInput) => createOIDCAuthIntegration( mongo, redis, @@ -31,9 +29,7 @@ export default ({ mongo, redis, tenantCache, tenant }: TenantContext) => ({ tenant, input.configuration ), - updateOIDCAuthIntegration: ( - input: GQLUpdateOIDCAuthIntegrationInput - ): Promise => + updateOIDCAuthIntegration: (input: GQLUpdateOIDCAuthIntegrationInput) => updateOIDCAuthIntegration( mongo, redis, @@ -42,8 +38,6 @@ export default ({ mongo, redis, tenantCache, tenant }: TenantContext) => ({ input.id, input.configuration ), - deleteOIDCAuthIntegration: ( - input: GQLDeleteOIDCAuthIntegrationInput - ): Promise => + deleteOIDCAuthIntegration: (input: GQLDeleteOIDCAuthIntegrationInput) => deleteOIDCAuthIntegration(mongo, redis, tenantCache, tenant, input.id), }); diff --git a/src/core/server/graph/tenant/resolvers/mutation.ts b/src/core/server/graph/tenant/resolvers/mutation.ts index cea0de73d..32425a67d 100644 --- a/src/core/server/graph/tenant/resolvers/mutation.ts +++ b/src/core/server/graph/tenant/resolvers/mutation.ts @@ -51,18 +51,42 @@ const Mutation: GQLMutationTypeResolver = { settings: await ctx.mutators.Settings.regenerateSSOKey(), clientMutationId: input.clientMutationId, }), - createOIDCAuthIntegration: async (source, { input }, ctx) => ({ - settings: await ctx.mutators.Settings.createOIDCAuthIntegration(input), - clientMutationId: input.clientMutationId, - }), - updateOIDCAuthIntegration: async (source, { input }, ctx) => ({ - settings: await ctx.mutators.Settings.updateOIDCAuthIntegration(input), - clientMutationId: input.clientMutationId, - }), - deleteOIDCAuthIntegration: async (source, { input }, ctx) => ({ - settings: await ctx.mutators.Settings.deleteOIDCAuthIntegration(input), - clientMutationId: input.clientMutationId, - }), + createOIDCAuthIntegration: async (source, { input }, ctx) => { + const result = await ctx.mutators.Settings.createOIDCAuthIntegration(input); + if (!result) { + return { clientMutationId: input.clientMutationId }; + } + + return { + integration: result.integration, + settings: result.tenant, + clientMutationId: input.clientMutationId, + }; + }, + updateOIDCAuthIntegration: async (source, { input }, ctx) => { + const result = await ctx.mutators.Settings.updateOIDCAuthIntegration(input); + if (!result) { + return { clientMutationId: input.clientMutationId }; + } + + return { + integration: result.integration, + settings: result.tenant, + clientMutationId: input.clientMutationId, + }; + }, + deleteOIDCAuthIntegration: async (source, { input }, ctx) => { + const result = await ctx.mutators.Settings.deleteOIDCAuthIntegration(input); + if (!result) { + return { clientMutationId: input.clientMutationId }; + } + + return { + integration: result.integration, + settings: result.tenant, + clientMutationId: input.clientMutationId, + }; + }, }; export default Mutation; diff --git a/src/core/server/graph/tenant/schema/schema.graphql b/src/core/server/graph/tenant/schema/schema.graphql index 2f88ed512..197530ce5 100644 --- a/src/core/server/graph/tenant/schema/schema.graphql +++ b/src/core/server/graph/tenant/schema/schema.graphql @@ -2046,6 +2046,11 @@ input CreateOIDCAuthIntegrationInput { } type CreateOIDCAuthIntegrationPayload { + """ + integration is the OIDCAuthIntegration we just created. + """ + integration: OIDCAuthIntegration + """ settings is the Settings that the OIDCAuthIntegration was created on. """ @@ -2143,6 +2148,11 @@ input UpdateOIDCAuthIntegrationInput { } type UpdateOIDCAuthIntegrationPayload { + """ + integration is the OIDCAuthIntegration we just updated. + """ + integration: OIDCAuthIntegration + """ settings is the Settings that the OIDCAuthIntegration was updated on. """ @@ -2172,7 +2182,13 @@ input DeleteOIDCAuthIntegrationInput { type DeleteOIDCAuthIntegrationPayload { """ - settings is the Settings that the OIDCAuthIntegration was deleted on. + integration is the OIDCAuthIntegration we just deleted. + """ + integration: OIDCAuthIntegration + + """ + settings is the Settings that the OIDCAuthIntegration was deleted on with the + OIDCAuthIntegration removed from it. """ settings: Settings diff --git a/src/core/server/models/tenant.ts b/src/core/server/models/tenant.ts index e6a12f8df..559cf7178 100644 --- a/src/core/server/models/tenant.ts +++ b/src/core/server/models/tenant.ts @@ -252,11 +252,17 @@ export type CreateTenantOIDCAuthIntegrationInput = Omit< "id" | "callbackURL" >; +export interface CreateTenantOIDCAuthIntegrationResultObject { + tenant?: Tenant; + integration?: Omit; + wasCreated: boolean; +} + export async function createTenantOIDCAuthIntegration( mongo: Db, id: string, input: CreateTenantOIDCAuthIntegrationInput -) { +): Promise { // Add the ID to the integration. const integration = { id: uuid.v4(), @@ -273,20 +279,40 @@ export async function createTenantOIDCAuthIntegration( // document. { returnOriginal: false } ); + if (!result.value) { + return { + wasCreated: false, + }; + } - return result.value || null; + const wasCreated = + result.value.auth.integrations.oidc.findIndex( + ({ id: integrationID }) => integrationID === integration.id + ) !== -1; + + return { + tenant: result.value, + integration, + wasCreated, + }; } export type UpdateTenantOIDCAuthIntegrationInput = Partial< Omit >; +export interface UpdateTenantOIDCAuthIntegrationResultObject { + tenant?: Tenant; + integration?: Omit; + wasUpdated: boolean; +} + export async function updateTenantOIDCAuthIntegration( mongo: Db, id: string, oidcID: string, input: UpdateTenantOIDCAuthIntegrationInput -) { +): Promise { const result = await collection(mongo).findOneAndUpdate( { id }, { @@ -307,8 +333,29 @@ export async function updateTenantOIDCAuthIntegration( returnOriginal: false, } ); + if (!result.value) { + return { + wasUpdated: false, + }; + } - return result.value || null; + const integration = result.value.auth.integrations.oidc.find( + ({ id: integrationID }) => integrationID === oidcID + ); + + const wasUpdated = Boolean(integration); + + return { + tenant: result.value, + integration, + wasUpdated, + }; +} + +export interface DeleteTenantOIDCAuthIntegrationResultObject { + tenant?: Tenant; + integration?: Omit; + wasDeleted: boolean; } /** @@ -323,18 +370,42 @@ export async function deleteTenantOIDCAuthIntegration( mongo: Db, id: string, oidcID: string -) { +): Promise { const result = await collection(mongo).findOneAndUpdate( { id }, { $pull: { "auth.integrations.oidc": { id: oidcID } }, }, { - // False to return the updated document instead of the original - // document. - returnOriginal: false, + // True to return the document before we modified it. This gives us the + // opportunity to return the original document and asertain if the + // integration was/could be removed. + returnOriginal: true, } ); + if (!result.value) { + return { wasDeleted: false }; + } - return result.value || null; + // Find the integration that we wanted to delete. + const integration = result.value.auth.integrations.oidc.find( + ({ id: integrationID }) => integrationID === oidcID + ); + if (!integration) { + // The integration was not in the original document, so we could not have + // possibly deleted it! + return { wasDeleted: false }; + } + + // The integration was found, we should pull that integration out of the + // resulting Tenant. + result.value.auth.integrations.oidc.filter( + ({ id: integrationID }) => integrationID !== integration.id + ); + + return { + tenant: result.value, + integration, + wasDeleted: true, + }; } diff --git a/src/core/server/services/tenant/index.ts b/src/core/server/services/tenant/index.ts index da73c651d..c484f3c83 100644 --- a/src/core/server/services/tenant/index.ts +++ b/src/core/server/services/tenant/index.ts @@ -134,22 +134,18 @@ export async function createOIDCAuthIntegration( input: CreateOIDCAuthIntegration ) { // Create the integration. By default, the integration is disabled. - const updatedTenant = await createTenantOIDCAuthIntegration( - mongo, - tenant.id, - { - enabled: false, - ...input, - } - ); - if (!updatedTenant) { + const result = await createTenantOIDCAuthIntegration(mongo, tenant.id, { + enabled: false, + ...input, + }); + if (!result.wasCreated || !result.tenant) { return null; } // Update the tenant cache. - await cache.update(redis, updatedTenant); + await cache.update(redis, result.tenant); - return updatedTenant; + return result; } export type UpdateOIDCAuthIntegration = GQLUpdateOIDCAuthIntegrationConfigurationInput; @@ -163,20 +159,20 @@ export async function updateOIDCAuthIntegration( input: UpdateOIDCAuthIntegration ) { // Update the integration. By default, the integration is disabled. - const updatedTenant = await updateTenantOIDCAuthIntegration( + const result = await updateTenantOIDCAuthIntegration( mongo, tenant.id, oidcID, input ); - if (!updatedTenant) { + if (!result.wasUpdated || !result.tenant) { return null; } // Update the tenant cache. - await cache.update(redis, updatedTenant); + await cache.update(redis, result.tenant); - return updatedTenant; + return result; } export async function deleteOIDCAuthIntegration( @@ -187,17 +183,17 @@ export async function deleteOIDCAuthIntegration( oidcID: string ) { // Delete the integration. By default, the integration is disabled. - const updatedTenant = await deleteTenantOIDCAuthIntegration( + const result = await deleteTenantOIDCAuthIntegration( mongo, tenant.id, oidcID ); - if (!updatedTenant) { + if (!result.wasDeleted || !result.tenant) { return null; } // Update the tenant cache. - await cache.update(redis, updatedTenant); + await cache.update(redis, result.tenant); - return updatedTenant; + return result; }