Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
854 changes: 730 additions & 124 deletions api-js/src/domain/mutations/__tests__/remove-domain.test.js

Large diffs are not rendered by default.

47 changes: 30 additions & 17 deletions api-js/src/domain/mutations/remove-domain.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { GraphQLNonNull, GraphQLID, GraphQLString } from 'graphql'
import { GraphQLNonNull, GraphQLID } from 'graphql'
import { mutationWithClientMutationId, fromGlobalId } from 'graphql-relay'
import { t } from '@lingui/macro'

import { removeDomainUnion } from '../unions'

export const removeDomain = new mutationWithClientMutationId({
name: 'RemoveDomain',
description: 'This mutation allows the removal of unused domains.',
Expand All @@ -16,13 +18,11 @@ export const removeDomain = new mutationWithClientMutationId({
},
}),
outputFields: () => ({
status: {
type: GraphQLNonNull(GraphQLString),
result: {
type: GraphQLNonNull(removeDomainUnion),
description:
'Status string to inform the user if the domain was successfully removed.',
resolve: async (payload) => {
return payload.status
},
'`RemoveDomainUnion` returning either a `DomainResultType`, or `DomainErrorType` object.',
resolve: (payload) => payload,
},
}),
mutateAndGetPayload: async (
Expand Down Expand Up @@ -55,7 +55,11 @@ export const removeDomain = new mutationWithClientMutationId({
console.warn(
`User: ${userKey} attempted to remove ${domainId} however no domain is associated with that id.`,
)
throw new Error(i18n._(t`Unable to remove unknown domain.`))
return {
_type: 'error',
code: 400,
description: i18n._(t`Unable to remove unknown domain.`),
}
}

// Get Org from db
Expand All @@ -66,9 +70,13 @@ export const removeDomain = new mutationWithClientMutationId({
console.warn(
`User: ${userKey} attempted to remove ${domain.slug} in org: ${orgId} however there is no organization associated with that id.`,
)
throw new Error(
i18n._(t`Unable to remove domain from unknown organization.`),
)
return {
_type: 'error',
code: 400,
description: i18n._(
t`Unable to remove domain from unknown organization.`,
),
}
}

// Get permission
Expand All @@ -79,22 +87,26 @@ export const removeDomain = new mutationWithClientMutationId({
console.warn(
`User: ${userKey} attempted to remove ${domain.slug} in ${org.slug} but does not have permission to remove a domain from a verified check org.`,
)
throw new Error(
i18n._(
return {
_type: 'error',
code: 403,
description: i18n._(
t`Permission Denied: Please contact super admin for help with removing domain.`,
),
)
}
}

if (permission !== 'super_admin' && permission !== 'admin') {
console.warn(
`User: ${userKey} attempted to remove ${domain.slug} in ${org.slug} however they do not have permission in that org.`,
)
throw new Error(
i18n._(
return {
_type: 'error',
code: 403,
description: i18n._(
t`Permission Denied: Please contact organization admin for help with removing domain.`,
),
)
}
}

// Check to see if more than one organization has a claim to this domain
Expand Down Expand Up @@ -241,6 +253,7 @@ export const removeDomain = new mutationWithClientMutationId({
`User: ${userKey} successfully removed domain: ${domain.slug} from org: ${org.slug}.`,
)
return {
_type: 'result',
status: i18n._(
t`Successfully removed domain: ${domain.slug} from ${org.slug}.`,
),
Expand Down
24 changes: 24 additions & 0 deletions api-js/src/domain/objects/__tests__/domain-result.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { GraphQLString } from 'graphql'

import { domainResultType } from '../domain-result'

describe('given the domainResultType object', () => {
describe('testing the field definitions', () => {
it('has an status field', () => {
const demoType = domainResultType.getFields()

expect(demoType).toHaveProperty('status')
expect(demoType.status.type).toMatchObject(GraphQLString)
})
})

describe('testing the field resolvers', () => {
describe('testing the status resolver', () => {
it('returns the resolved field', () => {
const demoType = domainResultType.getFields()

expect(demoType.status.resolve({ status: 'status' })).toEqual('status')
})
})
})
})
14 changes: 14 additions & 0 deletions api-js/src/domain/objects/domain-result.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { GraphQLObjectType, GraphQLString } from 'graphql'

export const domainResultType = new GraphQLObjectType({
name: 'DomainResult',
description:
'This object is used to inform the user that no errors were encountered while removing a domain.',
fields: () => ({
status: {
type: GraphQLString,
description: 'Informs the user if the domain removal was successful.',
resolve: ({ status }) => status,
},
}),
})
1 change: 1 addition & 0 deletions api-js/src/domain/objects/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './domain'
export * from './domain-connection'
export * from './domain-error'
export * from './domain-result'
export * from './domain-status'
45 changes: 45 additions & 0 deletions api-js/src/domain/unions/__tests__/remove-domain-union.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { domainErrorType, domainResultType } from '../../objects'
import { removeDomainUnion } from '../remove-domain-union'

describe('given the removeDomainUnion', () => {
describe('testing the field types', () => {
it('contains domainResultType', () => {
const demoType = removeDomainUnion.getTypes()

expect(demoType).toContain(domainResultType)
})
it('contains domainErrorType', () => {
const demoType = removeDomainUnion.getTypes()

expect(demoType).toContain(domainErrorType)
})
})
describe('testing the field selection', () => {
describe('testing the domainResultType', () => {
it('returns the correct type', () => {
const obj = {
_type: 'result',
status: 'status',
}

expect(removeDomainUnion.resolveType(obj)).toMatchObject(
domainResultType,
)
})
})
describe('testing the domainErrorType', () => {
it('returns the correct type', () => {
const obj = {
_type: 'error',
error: 'sign-in-error',
code: 401,
description: 'text',
}

expect(removeDomainUnion.resolveType(obj)).toMatchObject(
domainErrorType,
)
})
})
})
})
1 change: 1 addition & 0 deletions api-js/src/domain/unions/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './create-domain-union'
export * from './remove-domain-union'
export * from './update-domain-union'
17 changes: 17 additions & 0 deletions api-js/src/domain/unions/remove-domain-union.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { GraphQLUnionType } from 'graphql'
import { domainErrorType, domainResultType } from '../objects'

export const removeDomainUnion = new GraphQLUnionType({
name: 'RemoveDomainUnion',
description: `This union is used with the \`RemoveDomain\` mutation,
allowing for users to remove a domain belonging to their org,
and support any errors that may occur`,
types: [domainErrorType, domainResultType],
resolveType({ _type }) {
if (_type === 'result') {
return domainResultType
} else {
return domainErrorType
}
},
})
23 changes: 17 additions & 6 deletions frontend/schema.faker.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -1407,6 +1407,23 @@ type RegularSignInResult {
authResult: AuthResult
}

type RemoveDomainPayload {
# `RemoveDomainUnion` returning either a `DomainResultType`, or `DomainErrorType` object.
result: RemoveDomainUnion!
clientMutationId: String
}

# This union is used with the `RemoveDomain` mutation,
# allowing for users to remove a domain belonging to their org,
# and support any errors that may occur
union RemoveDomainUnion = DomainError | DomainResult

# This object is used to inform the user that no errors were encountered while removing a domain.
type DomainResult {
# Informs the user if the domain removal was successful.
status: String
}

input RemoveDomainInput {
# The global id of the domain you wish to remove.
domainId: ID!
Expand All @@ -1415,12 +1432,6 @@ input RemoveDomainInput {
clientMutationId: String
}

type RemoveDomainPayload {
# Status string to inform the user if the domain was successfully removed.
status: String!
clientMutationId: String
}

input RemoveOrganizationInput {
# The global id of the organization you wish you remove.
orgId: ID!
Expand Down
41 changes: 31 additions & 10 deletions frontend/src/AdminDomains.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,16 +150,37 @@ export function AdminDomains({ orgSlug, domainsPerPage, orgId }) {
position: 'top-left',
})
},
onCompleted() {
removeOnClose()
toast({
title: t`Domain removed`,
description: t`Domain removed from ${orgSlug}`,
status: 'info',
duration: 9000,
isClosable: true,
position: 'top-left',
})
onCompleted({ removeDomain }) {
if (removeDomain.result.__typename === 'DomainResult') {
removeOnClose()
toast({
title: t`Domain removed`,
description: t`Domain removed from ${orgSlug}`,
status: 'info',
duration: 9000,
isClosable: true,
position: 'top-left',
})
} else if (removeDomain.result.__typename === 'DomainError') {
toast({
title: t`Unable to remove domain.`,
description: removeDomain.result.description,
status: 'error',
duration: 9000,
isClosable: true,
position: 'top-left',
})
} else {
toast({
title: t`Incorrect send method received.`,
description: t`Incorrect removeDomain.result typename.`,
status: 'error',
duration: 9000,
isClosable: true,
position: 'top-left',
})
console.log('Incorrect removeDomain.result typename.')
}
},
},
)
Expand Down
10 changes: 9 additions & 1 deletion frontend/src/graphql/mutations.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,15 @@ export const CREATE_DOMAIN = gql`
export const REMOVE_DOMAIN = gql`
mutation RemoveDomain($domainId: ID!, $orgId: ID!) {
removeDomain(input: { domainId: $domainId, orgId: $orgId }) {
status
result {
... on DomainResult {
status
}
... on DomainError {
code
description
}
}
}
}
`
Expand Down