Skip to content

Commit bfcb6b0

Browse files
Merge pull request #1950 from johnduprey/dev
Tenant Onboarding
2 parents a0bc505 + d7b8d17 commit bfcb6b0

File tree

3 files changed

+120
-70
lines changed

3 files changed

+120
-70
lines changed

src/components/buttons/TableModalButton.jsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,16 @@ import { CButton } from '@coreui/react'
33
import { ModalService } from '../utilities'
44
import { cellGenericFormatter } from '../tables/CellGenericFormat'
55
import PropTypes from 'prop-types'
6+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
67

7-
export default function TableModalButton({ data, title, className, countOnly = false, ...input }) {
8+
export default function TableModalButton({
9+
data,
10+
title,
11+
className,
12+
countOnly = false,
13+
icon = '',
14+
...input
15+
}) {
816
const handleTable = (data) => {
917
const QueryColumns = []
1018
const columns = Object.keys(data[0]).map((key) => {
@@ -31,6 +39,7 @@ export default function TableModalButton({ data, title, className, countOnly = f
3139

3240
return (
3341
<CButton {...input} className={buttonClass} onClick={() => handleTable(data)}>
42+
{icon != '' && <FontAwesomeIcon icon={icon} className="me-2" />}
3443
<>{countOnly === true ? data.length : `${title} (${data.length})`}</>
3544
</CButton>
3645
)

src/views/tenant/administration/GDAPInviteWizard.jsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ const GDAPInviteWizard = () => {
8787
<div className="mb-2">
8888
<TitleButton href="/tenant/administration/gdap-role-wizard" title="Map GDAP Roles" />
8989
</div>
90+
9091
<Field name="gdapRoles" validate={requiredArray}>
9192
{(props) => (
9293
<WizardTableField
@@ -198,6 +199,14 @@ const GDAPInviteWizard = () => {
198199
wrapLongLines={true}
199200
language="text"
200201
/>
202+
203+
<TitleButton
204+
href={
205+
'/tenant/administration/tenant-onboarding-wizard?tableFilter=Complex: id eq ' +
206+
results.Invite.RowKey
207+
}
208+
title="Start Onboarding"
209+
/>
201210
</CCallout>
202211
)
203212
})}

src/views/tenant/administration/TenantOnboardingWizard.jsx

Lines changed: 101 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@ import {
77
CButton,
88
CCallout,
99
CCol,
10-
CFormLabel,
11-
CListGroup,
12-
CListGroupItem,
1310
CRow,
1411
CSpinner,
1512
} from '@coreui/react'
@@ -29,6 +26,7 @@ import {
2926
cellNullTextFormatter,
3027
} from 'src/components/tables'
3128
import ReactTimeAgo from 'react-time-ago'
29+
import { TableModalButton, TitleButton } from 'src/components/buttons'
3230

3331
const Error = ({ name }) => (
3432
<Field
@@ -37,7 +35,7 @@ const Error = ({ name }) => (
3735
render={({ meta: { touched, error } }) =>
3836
touched && error ? (
3937
<CCallout color="danger">
40-
<FontAwesomeIcon icon={faExclamationTriangle} color="danger" />
38+
<FontAwesomeIcon icon={faExclamationTriangle} color="danger" className="me-2" />
4139
{error}
4240
</CCallout>
4341
) : null
@@ -70,7 +68,7 @@ function useInterval(callback, delay, state) {
7068
}, [delay, state])
7169
}
7270

73-
const RelationshipOnboarding = ({ relationship, gdapRoles }) => {
71+
const RelationshipOnboarding = ({ relationship, gdapRoles, autoMapRoles, addMissingGroups }) => {
7472
const [relationshipReady, setRelationshipReady] = useState(false)
7573
const [refreshGuid, setRefreshGuid] = useState(false)
7674
const [getOnboardingStatus, onboardingStatus] = useLazyGenericPostRequestQuery()
@@ -155,22 +153,31 @@ const RelationshipOnboarding = ({ relationship, gdapRoles }) => {
155153
{onboardingStatus.isUninitialized &&
156154
getOnboardingStatus({
157155
path: '/api/ExecOnboardTenant',
158-
values: { id: relationship.id, gdapRoles },
156+
values: { id: relationship.id, gdapRoles, autoMapRoles, addMissingGroups },
159157
})}
160158
{onboardingStatus.isSuccess && (
161159
<>
162-
{onboardingStatus.data?.Status == 'failed' && (
163-
<CButton
164-
onClick={() =>
165-
getOnboardingStatus({
166-
path: '/api/ExecOnboardTenant?Retry=True',
167-
values: { id: relationship.id, gdapRoles },
168-
})
169-
}
160+
{onboardingStatus.data?.Status != 'running' &&
161+
onboardingStatus.data?.Status != 'queued' && (
162+
<CButton
163+
onClick={() =>
164+
getOnboardingStatus({
165+
path: '/api/ExecOnboardTenant?Retry=True',
166+
values: { id: relationship.id, gdapRoles, autoMapRoles, addMissingGroups },
167+
})
168+
}
169+
className="mb-3 me-2"
170+
>
171+
<FontAwesomeIcon icon="sync" /> Retry
172+
</CButton>
173+
)}
174+
{onboardingStatus.data?.Logs && (
175+
<TableModalButton
176+
title="Logs"
177+
icon="book"
178+
data={onboardingStatus.data?.Logs}
170179
className="mb-3"
171-
>
172-
Retry
173-
</CButton>
180+
/>
174181
)}
175182
<hr className="mb-3" />
176183
{onboardingStatus.data?.OnboardingSteps?.map((step, idx) => (
@@ -211,6 +218,7 @@ const TenantOnboardingWizard = () => {
211218
const tenantDomain = useSelector((state) => state.app.currentTenant.defaultDomainName)
212219
const currentSettings = useSelector((state) => state.app)
213220
const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery()
221+
const requiredArray = (value) => (value && value.length !== 0 ? undefined : 'Required')
214222

215223
const handleSubmit = async (values) => {}
216224
const columns = [
@@ -289,32 +297,41 @@ const TenantOnboardingWizard = () => {
289297
<h5 className="card-title mb-4">Choose a relationship</h5>
290298
</center>
291299
<hr className="my-4" />
292-
<Field name="selectedRelationships">
300+
<div className="mb-2">
301+
<TitleButton href="/tenant/administration/gdap-invite" title="Create GDAP Invite" />
302+
</div>
303+
<Field name="selectedRelationships" validate={requiredArray}>
293304
{(props) => (
294-
<WizardTableField
295-
reportName="Add-GDAP-Relationship"
296-
keyField="id"
297-
path="/api/ListGraphRequest"
298-
params={{ Endpoint: 'tenantRelationships/delegatedAdminRelationships' }}
299-
columns={columns}
300-
filterlist={[
301-
{ filterName: 'Active Relationships', filter: 'Complex: status eq active' },
302-
{ filterName: 'Terminated Relationships', filter: 'Complex: status eq terminated' },
303-
{
304-
filterName: 'Pending Relationships',
305-
filter: 'Complex: status eq approvalPending',
306-
},
307-
{
308-
filterName: 'Active with Auto Extend',
309-
filter: 'Complex: status eq active; autoExtendDuration ne PT0S',
310-
},
311-
{
312-
filterName: 'Active without Auto Extend',
313-
filter: 'Complex: status eq active; autoExtendDuration eq PT0S',
314-
},
315-
]}
316-
fieldProps={props}
317-
/>
305+
<>
306+
<WizardTableField
307+
reportName="Add-GDAP-Relationship"
308+
keyField="id"
309+
path="/api/ListGraphRequest"
310+
params={{ Endpoint: 'tenantRelationships/delegatedAdminRelationships' }}
311+
columns={columns}
312+
filterlist={[
313+
{ filterName: 'Active Relationships', filter: 'Complex: status eq active' },
314+
{
315+
filterName: 'Terminated Relationships',
316+
filter: 'Complex: status eq terminated',
317+
},
318+
{
319+
filterName: 'Pending Relationships',
320+
filter: 'Complex: status eq approvalPending',
321+
},
322+
{
323+
filterName: 'Active with Auto Extend',
324+
filter: 'Complex: status eq active; autoExtendDuration ne PT0S',
325+
},
326+
{
327+
filterName: 'Active without Auto Extend',
328+
filter: 'Complex: status eq active; autoExtendDuration eq PT0S',
329+
},
330+
]}
331+
fieldProps={props}
332+
/>
333+
<Error name="selectedRelationships" />
334+
</>
318335
)}
319336
</Field>
320337
<hr className="my-4" />
@@ -328,33 +345,46 @@ const TenantOnboardingWizard = () => {
328345
<h5 className="card-title mb-4">Tenant Onboarding Options</h5>
329346
</center>
330347
<hr className="my-4" />
331-
<CFormLabel>
332-
(Optional) Automatically map groups for relationships not created in CIPP. This will not
333-
map groups that do not have a corresponding role in the relationship.
334-
</CFormLabel>
335-
<Field name="gdapRoles">
336-
{(props) => (
337-
<WizardTableField
338-
reportName="gdaproles"
339-
keyField="defaultDomainName"
340-
path="/api/ListGDAPRoles"
341-
columns={[
342-
{
343-
name: 'Name',
344-
selector: (row) => row['RoleName'],
345-
sortable: true,
346-
exportselector: 'Name',
347-
},
348-
{
349-
name: 'Group',
350-
selector: (row) => row['GroupName'],
351-
sortable: true,
352-
},
353-
]}
354-
fieldProps={props}
355-
/>
356-
)}
357-
</Field>
348+
<RFFCFormSwitch name="autoMapRoles" label="Map missing groups to GDAP Roles" />
349+
<RFFCFormSwitch name="addMissingGroups" label="Add CIPP SAM user to missing groups" />
350+
<FormSpy>
351+
{/* eslint-disable react/prop-types */}
352+
{(props) => {
353+
return (
354+
<>
355+
{(props.values.autoMapRoles || props.values.addMissingGroups) && (
356+
<Field name="gdapRoles" validate={requiredArray}>
357+
{(props) => (
358+
<>
359+
<WizardTableField
360+
reportName="gdaproles"
361+
keyField="defaultDomainName"
362+
path="/api/ListGDAPRoles"
363+
isModal={true}
364+
columns={[
365+
{
366+
name: 'Name',
367+
selector: (row) => row['RoleName'],
368+
sortable: true,
369+
exportselector: 'Name',
370+
},
371+
{
372+
name: 'Group',
373+
selector: (row) => row['GroupName'],
374+
sortable: true,
375+
},
376+
]}
377+
fieldProps={props}
378+
/>
379+
<Error name="gdapRoles" />
380+
</>
381+
)}
382+
</Field>
383+
)}
384+
</>
385+
)
386+
}}
387+
</FormSpy>
358388
<hr className="my-4" />
359389
</CippWizard.Page>
360390
<CippWizard.Page
@@ -382,6 +412,8 @@ const TenantOnboardingWizard = () => {
382412
<RelationshipOnboarding
383413
relationship={relationship}
384414
gdapRoles={props.values.gdapRoles}
415+
autoMapRoles={props.values.autoMapRoles}
416+
addMissingGroups={props.values.addMissingGroups}
385417
key={idx}
386418
/>
387419
))}

0 commit comments

Comments
 (0)