3
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
4
*--------------------------------------------------------------------------------------------*/
5
5
6
- import { parseAzureResourceId } from '@microsoft/vscode-azext-azureutils' ;
7
- import { AzureWizardPromptStep , nonNullProp , type IAzureQuickPickItem , type IWizardOptions } from '@microsoft/vscode-azext-utils' ;
6
+ import { CommonRoleDefinitions , createAuthorizationManagementClient , createRoleId , parseAzureResourceId , RoleAssignmentExecuteStep , uiUtils , type Role } from '@microsoft/vscode-azext-azureutils' ;
7
+ import { ActivityChildItem , ActivityChildType , activitySuccessContext , activitySuccessIcon , AzureWizardPromptStep , createContextValue , nonNullProp , type AzureWizardExecuteStep , type IAzureQuickPickItem , type IWizardOptions } from '@microsoft/vscode-azext-utils' ;
8
8
import { localSettingsDescription } from '../../../../../constants-nls' ;
9
+ import { ext } from '../../../../../extensionVariables' ;
9
10
import { localize } from '../../../../../localize' ;
10
11
import { HttpDurableTaskSchedulerClient , type DurableTaskHubResource , type DurableTaskSchedulerClient } from '../../../../../tree/durableTaskScheduler/DurableTaskSchedulerClient' ;
12
+ import { FunctionAppUserAssignedIdentitiesListStep } from '../../../../identity/FunctionAppUserAssignedIdentitiesListStep' ;
11
13
import { type IDTSAzureConnectionWizardContext } from '../IDTSConnectionWizardContext' ;
12
14
import { DurableTaskHubCreateStep } from './DurableTaskHubCreateStep' ;
13
15
import { DurableTaskHubNameStep } from './DurableTaskHubNameStep' ;
@@ -22,7 +24,7 @@ export class DurableTaskHubListStep<T extends IDTSAzureConnectionWizardContext>
22
24
23
25
public async prompt ( context : T ) : Promise < void > {
24
26
context . dtsHub = ( await context . ui . showQuickPick ( await this . getPicks ( context ) , {
25
- placeHolder : localize ( 'selectTaskScheduler' , 'Select a Durable Task Scheduler ' ) ,
27
+ placeHolder : localize ( 'selectTaskScheduler' , 'Select a durable task hub ' ) ,
26
28
} ) ) . data ;
27
29
28
30
if ( context . dtsHub ) {
@@ -35,17 +37,6 @@ export class DurableTaskHubListStep<T extends IDTSAzureConnectionWizardContext>
35
37
return ! context . dtsHub ;
36
38
}
37
39
38
- public async getSubWizard ( context : T ) : Promise < IWizardOptions < T > | undefined > {
39
- if ( context . dtsHub ) {
40
- return undefined ;
41
- }
42
-
43
- return {
44
- promptSteps : [ new DurableTaskHubNameStep ( this . schedulerClient ) ] ,
45
- executeSteps : [ new DurableTaskHubCreateStep ( this . schedulerClient ) ] ,
46
- } ;
47
- }
48
-
49
40
private async getPicks ( context : T ) : Promise < IAzureQuickPickItem < DurableTaskHubResource | undefined > [ ] > {
50
41
const taskHubs : DurableTaskHubResource [ ] = context . dts ?
51
42
await this . schedulerClient . getSchedulerTaskHubs ( nonNullProp ( context , 'subscription' ) , parseAzureResourceId ( context . dts . id ) . resourceGroup , context . dts . name ) : [ ] ;
@@ -66,4 +57,80 @@ export class DurableTaskHubListStep<T extends IDTSAzureConnectionWizardContext>
66
57
} ) ,
67
58
] ;
68
59
}
60
+
61
+ public async getSubWizard ( context : T ) : Promise < IWizardOptions < T > | undefined > {
62
+ const promptSteps : AzureWizardPromptStep < T > [ ] = [ ] ;
63
+ const executeSteps : AzureWizardExecuteStep < T > [ ] = [ ] ;
64
+
65
+ if ( ! context . dtsHub ) {
66
+ promptSteps . push ( new DurableTaskHubNameStep ( this . schedulerClient ) ) ;
67
+ executeSteps . push ( new DurableTaskHubCreateStep ( this . schedulerClient ) ) ;
68
+ }
69
+
70
+ const dtsContributorRole : Role = {
71
+ scopeId : context . dtsHub ?. id ,
72
+ roleDefinitionId : createRoleId ( context . subscriptionId , CommonRoleDefinitions . durableTaskDataContributor ) ,
73
+ roleDefinitionName : CommonRoleDefinitions . durableTaskDataContributor . roleName ,
74
+ } ;
75
+
76
+ promptSteps . push ( new FunctionAppUserAssignedIdentitiesListStep ( dtsContributorRole /** targetRole */ , { identityAssignStepPriority : 180 } ) ) ;
77
+ executeSteps . push ( new RoleAssignmentExecuteStep ( this . getDTSRoleAssignmentCallback ( context , dtsContributorRole ) , { priority : 190 } ) ) ;
78
+
79
+ return { promptSteps, executeSteps } ;
80
+ }
81
+
82
+ private getDTSRoleAssignmentCallback ( context : T , role : Role ) : ( ) => Promise < Role [ ] > {
83
+ return async ( ) => {
84
+ const roleAssignment : Role = {
85
+ ...role ,
86
+ // This id may be missing when the role is initially passed in,
87
+ // but by the time we run the step, we should have the populated id ready.
88
+ scopeId : context . dtsHub ?. id ,
89
+ } ;
90
+
91
+ if ( ! roleAssignment . scopeId ) {
92
+ return [ ] ;
93
+ }
94
+
95
+ const amClient = await createAuthorizationManagementClient ( context ) ;
96
+
97
+ let hasRoleAssignment : boolean = false ;
98
+ if ( context . dtsHub ) {
99
+ const taskHubRoleAssignments = await uiUtils . listAllIterator ( amClient . roleAssignments . listForScope (
100
+ context . dtsHub . id ,
101
+ {
102
+ // $filter=principalId eq {id}
103
+ filter : `principalId eq '{${ context . managedIdentity ?. principalId } }'` ,
104
+ }
105
+ ) ) ;
106
+ hasRoleAssignment = taskHubRoleAssignments . some ( r => ! ! r . roleDefinitionId ?. endsWith ( role . roleDefinitionId ) ) ;
107
+ }
108
+
109
+ if ( ! hasRoleAssignment && context . dts ) {
110
+ const taskSchedulerRoleAssignments = await uiUtils . listAllIterator ( amClient . roleAssignments . listForScope (
111
+ context . dts . id ,
112
+ {
113
+ // $filter=principalId eq {id}
114
+ filter : `principalId eq '{${ context . managedIdentity ?. principalId } }'` ,
115
+ }
116
+ ) ) ;
117
+ hasRoleAssignment = taskSchedulerRoleAssignments . some ( r => ! ! r . roleDefinitionId ?. endsWith ( role . roleDefinitionId ) ) ;
118
+ }
119
+
120
+ if ( hasRoleAssignment ) {
121
+ context . activityChildren ?. push (
122
+ new ActivityChildItem ( {
123
+ label : localize ( 'verifyIdentityWithRoleLabel' , 'Verify identity "{0}" has role "{1}"' , context . managedIdentity ?. name , role . roleDefinitionName ) ,
124
+ description : '0s' ,
125
+ contextValue : createContextValue ( [ 'roleAssignmentExecuteStepItem' , activitySuccessContext ] ) ,
126
+ activityType : ActivityChildType . Success ,
127
+ iconPath : activitySuccessIcon ,
128
+ } ) ,
129
+ ) ;
130
+ ext . outputChannel . appendLog ( localize ( 'verifyIdentity' , 'Successfully verified identity "{0}" has role "{1}".' , context . managedIdentity ?. name , role . roleDefinitionName ) ) ;
131
+ }
132
+
133
+ return hasRoleAssignment ? [ ] : [ roleAssignment ] ;
134
+ } ;
135
+ }
69
136
}
0 commit comments