Skip to content

Commit 1447bcb

Browse files
authored
Introduce Remove Domain Union (canada-ca#1964)
* create domain result object * create remove domain union * update mutation to use union * update faker * update mutation string * update AdminDomains component
1 parent 322beb8 commit 1447bcb

11 files changed

Lines changed: 919 additions & 158 deletions

File tree

api-js/src/domain/mutations/__tests__/remove-domain.test.js

Lines changed: 730 additions & 124 deletions
Large diffs are not rendered by default.

api-js/src/domain/mutations/remove-domain.js

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import { GraphQLNonNull, GraphQLID, GraphQLString } from 'graphql'
1+
import { GraphQLNonNull, GraphQLID } from 'graphql'
22
import { mutationWithClientMutationId, fromGlobalId } from 'graphql-relay'
33
import { t } from '@lingui/macro'
44

5+
import { removeDomainUnion } from '../unions'
6+
57
export const removeDomain = new mutationWithClientMutationId({
68
name: 'RemoveDomain',
79
description: 'This mutation allows the removal of unused domains.',
@@ -16,13 +18,11 @@ export const removeDomain = new mutationWithClientMutationId({
1618
},
1719
}),
1820
outputFields: () => ({
19-
status: {
20-
type: GraphQLNonNull(GraphQLString),
21+
result: {
22+
type: GraphQLNonNull(removeDomainUnion),
2123
description:
22-
'Status string to inform the user if the domain was successfully removed.',
23-
resolve: async (payload) => {
24-
return payload.status
25-
},
24+
'`RemoveDomainUnion` returning either a `DomainResultType`, or `DomainErrorType` object.',
25+
resolve: (payload) => payload,
2626
},
2727
}),
2828
mutateAndGetPayload: async (
@@ -55,7 +55,11 @@ export const removeDomain = new mutationWithClientMutationId({
5555
console.warn(
5656
`User: ${userKey} attempted to remove ${domainId} however no domain is associated with that id.`,
5757
)
58-
throw new Error(i18n._(t`Unable to remove unknown domain.`))
58+
return {
59+
_type: 'error',
60+
code: 400,
61+
description: i18n._(t`Unable to remove unknown domain.`),
62+
}
5963
}
6064

6165
// Get Org from db
@@ -66,9 +70,13 @@ export const removeDomain = new mutationWithClientMutationId({
6670
console.warn(
6771
`User: ${userKey} attempted to remove ${domain.slug} in org: ${orgId} however there is no organization associated with that id.`,
6872
)
69-
throw new Error(
70-
i18n._(t`Unable to remove domain from unknown organization.`),
71-
)
73+
return {
74+
_type: 'error',
75+
code: 400,
76+
description: i18n._(
77+
t`Unable to remove domain from unknown organization.`,
78+
),
79+
}
7280
}
7381

7482
// Get permission
@@ -79,22 +87,26 @@ export const removeDomain = new mutationWithClientMutationId({
7987
console.warn(
8088
`User: ${userKey} attempted to remove ${domain.slug} in ${org.slug} but does not have permission to remove a domain from a verified check org.`,
8189
)
82-
throw new Error(
83-
i18n._(
90+
return {
91+
_type: 'error',
92+
code: 403,
93+
description: i18n._(
8494
t`Permission Denied: Please contact super admin for help with removing domain.`,
8595
),
86-
)
96+
}
8797
}
8898

8999
if (permission !== 'super_admin' && permission !== 'admin') {
90100
console.warn(
91101
`User: ${userKey} attempted to remove ${domain.slug} in ${org.slug} however they do not have permission in that org.`,
92102
)
93-
throw new Error(
94-
i18n._(
103+
return {
104+
_type: 'error',
105+
code: 403,
106+
description: i18n._(
95107
t`Permission Denied: Please contact organization admin for help with removing domain.`,
96108
),
97-
)
109+
}
98110
}
99111

100112
// Check to see if more than one organization has a claim to this domain
@@ -241,6 +253,7 @@ export const removeDomain = new mutationWithClientMutationId({
241253
`User: ${userKey} successfully removed domain: ${domain.slug} from org: ${org.slug}.`,
242254
)
243255
return {
256+
_type: 'result',
244257
status: i18n._(
245258
t`Successfully removed domain: ${domain.slug} from ${org.slug}.`,
246259
),
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { GraphQLString } from 'graphql'
2+
3+
import { domainResultType } from '../domain-result'
4+
5+
describe('given the domainResultType object', () => {
6+
describe('testing the field definitions', () => {
7+
it('has an status field', () => {
8+
const demoType = domainResultType.getFields()
9+
10+
expect(demoType).toHaveProperty('status')
11+
expect(demoType.status.type).toMatchObject(GraphQLString)
12+
})
13+
})
14+
15+
describe('testing the field resolvers', () => {
16+
describe('testing the status resolver', () => {
17+
it('returns the resolved field', () => {
18+
const demoType = domainResultType.getFields()
19+
20+
expect(demoType.status.resolve({ status: 'status' })).toEqual('status')
21+
})
22+
})
23+
})
24+
})
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { GraphQLObjectType, GraphQLString } from 'graphql'
2+
3+
export const domainResultType = new GraphQLObjectType({
4+
name: 'DomainResult',
5+
description:
6+
'This object is used to inform the user that no errors were encountered while removing a domain.',
7+
fields: () => ({
8+
status: {
9+
type: GraphQLString,
10+
description: 'Informs the user if the domain removal was successful.',
11+
resolve: ({ status }) => status,
12+
},
13+
}),
14+
})

api-js/src/domain/objects/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from './domain'
22
export * from './domain-connection'
33
export * from './domain-error'
4+
export * from './domain-result'
45
export * from './domain-status'
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { domainErrorType, domainResultType } from '../../objects'
2+
import { removeDomainUnion } from '../remove-domain-union'
3+
4+
describe('given the removeDomainUnion', () => {
5+
describe('testing the field types', () => {
6+
it('contains domainResultType', () => {
7+
const demoType = removeDomainUnion.getTypes()
8+
9+
expect(demoType).toContain(domainResultType)
10+
})
11+
it('contains domainErrorType', () => {
12+
const demoType = removeDomainUnion.getTypes()
13+
14+
expect(demoType).toContain(domainErrorType)
15+
})
16+
})
17+
describe('testing the field selection', () => {
18+
describe('testing the domainResultType', () => {
19+
it('returns the correct type', () => {
20+
const obj = {
21+
_type: 'result',
22+
status: 'status',
23+
}
24+
25+
expect(removeDomainUnion.resolveType(obj)).toMatchObject(
26+
domainResultType,
27+
)
28+
})
29+
})
30+
describe('testing the domainErrorType', () => {
31+
it('returns the correct type', () => {
32+
const obj = {
33+
_type: 'error',
34+
error: 'sign-in-error',
35+
code: 401,
36+
description: 'text',
37+
}
38+
39+
expect(removeDomainUnion.resolveType(obj)).toMatchObject(
40+
domainErrorType,
41+
)
42+
})
43+
})
44+
})
45+
})

api-js/src/domain/unions/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from './create-domain-union'
2+
export * from './remove-domain-union'
23
export * from './update-domain-union'
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { GraphQLUnionType } from 'graphql'
2+
import { domainErrorType, domainResultType } from '../objects'
3+
4+
export const removeDomainUnion = new GraphQLUnionType({
5+
name: 'RemoveDomainUnion',
6+
description: `This union is used with the \`RemoveDomain\` mutation,
7+
allowing for users to remove a domain belonging to their org,
8+
and support any errors that may occur`,
9+
types: [domainErrorType, domainResultType],
10+
resolveType({ _type }) {
11+
if (_type === 'result') {
12+
return domainResultType
13+
} else {
14+
return domainErrorType
15+
}
16+
},
17+
})

frontend/schema.faker.graphql

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,6 +1407,23 @@ type RegularSignInResult {
14071407
authResult: AuthResult
14081408
}
14091409

1410+
type RemoveDomainPayload {
1411+
# `RemoveDomainUnion` returning either a `DomainResultType`, or `DomainErrorType` object.
1412+
result: RemoveDomainUnion!
1413+
clientMutationId: String
1414+
}
1415+
1416+
# This union is used with the `RemoveDomain` mutation,
1417+
# allowing for users to remove a domain belonging to their org,
1418+
# and support any errors that may occur
1419+
union RemoveDomainUnion = DomainError | DomainResult
1420+
1421+
# This object is used to inform the user that no errors were encountered while removing a domain.
1422+
type DomainResult {
1423+
# Informs the user if the domain removal was successful.
1424+
status: String
1425+
}
1426+
14101427
input RemoveDomainInput {
14111428
# The global id of the domain you wish to remove.
14121429
domainId: ID!
@@ -1415,12 +1432,6 @@ input RemoveDomainInput {
14151432
clientMutationId: String
14161433
}
14171434

1418-
type RemoveDomainPayload {
1419-
# Status string to inform the user if the domain was successfully removed.
1420-
status: String!
1421-
clientMutationId: String
1422-
}
1423-
14241435
input RemoveOrganizationInput {
14251436
# The global id of the organization you wish you remove.
14261437
orgId: ID!

frontend/src/AdminDomains.js

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -150,16 +150,37 @@ export function AdminDomains({ orgSlug, domainsPerPage, orgId }) {
150150
position: 'top-left',
151151
})
152152
},
153-
onCompleted() {
154-
removeOnClose()
155-
toast({
156-
title: t`Domain removed`,
157-
description: t`Domain removed from ${orgSlug}`,
158-
status: 'info',
159-
duration: 9000,
160-
isClosable: true,
161-
position: 'top-left',
162-
})
153+
onCompleted({ removeDomain }) {
154+
if (removeDomain.result.__typename === 'DomainResult') {
155+
removeOnClose()
156+
toast({
157+
title: t`Domain removed`,
158+
description: t`Domain removed from ${orgSlug}`,
159+
status: 'info',
160+
duration: 9000,
161+
isClosable: true,
162+
position: 'top-left',
163+
})
164+
} else if (removeDomain.result.__typename === 'DomainError') {
165+
toast({
166+
title: t`Unable to remove domain.`,
167+
description: removeDomain.result.description,
168+
status: 'error',
169+
duration: 9000,
170+
isClosable: true,
171+
position: 'top-left',
172+
})
173+
} else {
174+
toast({
175+
title: t`Incorrect send method received.`,
176+
description: t`Incorrect removeDomain.result typename.`,
177+
status: 'error',
178+
duration: 9000,
179+
isClosable: true,
180+
position: 'top-left',
181+
})
182+
console.log('Incorrect removeDomain.result typename.')
183+
}
163184
},
164185
},
165186
)

0 commit comments

Comments
 (0)