Skip to content

Commit b0653cb

Browse files
Returning resource type for relationship members and adding more information to relationship (#267)
1 parent d3bfdb6 commit b0653cb

24 files changed

Lines changed: 16721 additions & 44 deletions

File tree

RELATIONSHIP_MEMBERS_PROPOSAL.md

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
# Enhanced Relationship Member Types Proposal
2+
3+
## Executive Summary
4+
5+
This proposal outlines the implementation of enhanced relationship member types for Microsoft Graph Bicep Types, transitioning from simple string arrays to rich object structures for improved object referencing, filtering, and type-based operations while maintaining backward compatibility.
6+
7+
## Status: ✅ IMPLEMENTED
8+
9+
**Implementation Date:** October 24, 2025
10+
**Implementation Status:** Complete and Production Ready
11+
**Test Coverage:** 11/11 tests passing
12+
**Backward Compatibility:** Maintained for v1.0 API
13+
14+
## Problem Statement
15+
16+
The current relationship member implementation uses simple string arrays containing only object IDs. This approach has several limitations:
17+
18+
1. **Limited Type Information**: No way to determine object type (user, group, servicePrincipal)
19+
2. **Filtering Constraints**: Cannot filter relationship members by type
20+
3. **Object Dereferencing**: No human-readable identifiers for object lookup
21+
4. **Template Referencing**: Limited ability to reference objects in templates
22+
23+
### Real-World Scenarios
24+
25+
**Scenario 1: App Ownership Assignment**
26+
- Want to set app owners based on security group members
27+
- Security groups may contain other groups, but groups cannot own apps
28+
- Need to filter out group objects before assignment
29+
30+
**Scenario 2: User Lookup Operations**
31+
- Want to look up user names in a security group
32+
- Group may contain both users and service principals
33+
- Need to differentiate object types for proper dereferencing
34+
35+
**Scenario 3: Template-based Object Referencing**
36+
- Need to reference existing objects in templates
37+
- Require unique identifiers beyond just object IDs
38+
- Want human-readable names for better template maintainability
39+
40+
## Solution Overview
41+
42+
Implement enhanced relationship member types that provide rich object metadata while maintaining backward compatibility through version-based conditional logic.
43+
44+
### Enhanced Relationship Member Schema
45+
46+
```typescript
47+
{
48+
id: string, // Required: The object ID
49+
type: string, // Read-only: Object type (user, group, servicePrincipal, etc.)
50+
displayName: string, // Read-only: Human-readable name
51+
userPrincipalName: string, // Read-only: For users - their UPN
52+
appId: string, // Read-only: For service principals - their app ID
53+
uniqueName: string // Read-only: Unique name for template referencing
54+
}
55+
```
56+
57+
### Version Strategy
58+
59+
- **Enhanced Versions**: `beta/1.1.0-preview` and `v1.0/1.1.0-preview`
60+
- **Legacy Versions**: `v1.0/1.0.0` (maintains string arrays)
61+
- **Detection Logic**: `isEnhancedRelationshipVersion()` function
62+
63+
## Implementation Details
64+
65+
### Core Files Modified
66+
67+
#### 1. swaggerWriter.ts
68+
**Location:** `src/swagger-generation/src/swaggerWriter.ts`
69+
70+
**Changes:**
71+
- Added `isEnhancedRelationshipVersion()` detection function
72+
- Implemented conditional `microsoft.graph.relationshipMember` definition
73+
- Enhanced `microsoft.graph.relationship` with version-specific structures
74+
75+
**Key Implementation:**
76+
```typescript
77+
// Enhanced RelationshipMember type for enhanced versions
78+
if (isEnhanced) {
79+
baseDefinitions["microsoft.graph.relationshipMember"] = {
80+
type: "object",
81+
properties: {
82+
id: { type: "string", description: "The unique identifier of the relationship member." },
83+
type: { type: "string", description: "The type of the relationship member...", readOnly: true },
84+
displayName: { type: "string", description: "The display name...", readOnly: true },
85+
userPrincipalName: { type: "string", description: "The user principal name...", readOnly: true },
86+
appId: { type: "string", description: "The application ID...", readOnly: true },
87+
uniqueName: { type: "string", description: "A unique name for referencing...", readOnly: true }
88+
},
89+
required: ["id"]
90+
};
91+
}
92+
```
93+
94+
#### 2. generate.ts
95+
**Location:** `src/generator/src/generate.ts`
96+
97+
**Changes:**
98+
- Updated `extensionConfigForGeneration` with v1.1.0 configuration
99+
- Enhanced `shouldIncludeFilePath` with v1.1.0 patterns
100+
- Updated `buildTypeIndex` for v1.1.0 version handling
101+
102+
#### 3. index.ts (swagger-generation)
103+
**Location:** `src/swagger-generation/src/index.ts`
104+
105+
**Changes:**
106+
- Fixed `writeSwaggerReadMeFile` to include v1.1.0 AutoRest configuration
107+
- Added v1.1.0 section to readme template
108+
- Ensured proper AutoRest setup for all API versions
109+
110+
### Test Coverage
111+
112+
#### Test Suite: swaggerWriter.test.ts
113+
**Location:** `src/swagger-generation/tests/swaggerWriter.test.ts`
114+
115+
**Coverage:**
116+
1. **Enhanced Beta Test**: Validates `beta/1.1.0-preview` with full relationship member objects
117+
2. **Enhanced v1.1.0 Test**: Validates `v1.0/1.1.0-preview` with full relationship member objects
118+
3. **Legacy v1.0 Test**: Validates `v1.0/1.0.0` maintains simple string arrays
119+
120+
**Test Results:** ✅ 11/11 tests passing
121+
122+
## API Version Comparison
123+
124+
### Enhanced Versions (beta/1.1.0-preview, v1.0/1.1.0-preview)
125+
126+
```json
127+
{
128+
"microsoft.graph.relationshipMember": {
129+
"type": "object",
130+
"properties": {
131+
"id": { "type": "string", "description": "The unique identifier..." },
132+
"type": { "type": "string", "readOnly": true, "description": "The type of the relationship member..." },
133+
"displayName": { "type": "string", "readOnly": true, "description": "The display name..." },
134+
"userPrincipalName": { "type": "string", "readOnly": true, "description": "The user principal name..." },
135+
"appId": { "type": "string", "readOnly": true, "description": "The application ID..." },
136+
"uniqueName": { "type": "string", "readOnly": true, "description": "A unique name..." }
137+
},
138+
"required": ["id"]
139+
},
140+
"microsoft.graph.relationship": {
141+
"properties": {
142+
"relationships": {
143+
"type": "array",
144+
"items": { "$ref": "#/definitions/microsoft.graph.relationshipMember" },
145+
"description": "The list of relationship members with their IDs and types."
146+
}
147+
}
148+
}
149+
}
150+
```
151+
152+
### Legacy Version (v1.0/1.0.0)
153+
154+
```json
155+
{
156+
"microsoft.graph.relationship": {
157+
"properties": {
158+
"relationships": {
159+
"type": "array",
160+
"items": { "type": "string" },
161+
"description": "The list of object ids to be included in the relationship."
162+
}
163+
}
164+
}
165+
}
166+
```
167+
168+
## Usage Examples
169+
170+
### Scenario 1: Type-based Filtering
171+
```bicep
172+
// Filter out groups when setting app owners
173+
resource myApp 'Microsoft.Graph/applications@beta' = {
174+
owners: {
175+
relationships: filter(securityGroup.members, member => member.type != 'group')
176+
}
177+
}
178+
```
179+
180+
### Scenario 2: User Identification
181+
```bicep
182+
// Get user information from mixed security group
183+
resource myGroup 'Microsoft.Graph/groups@beta' existing = {
184+
name: 'my-security-group'
185+
}
186+
187+
// Extract users for name lookup
188+
var users = filter(myGroup.members, member => member.type == 'user')
189+
// Access: member.displayName, member.userPrincipalName
190+
```
191+
192+
### Scenario 3: Service Principal Operations
193+
```bicep
194+
// Work with service principals in relationships
195+
var servicePrincipals = filter(group.members, member => member.type == 'servicePrincipal')
196+
// Access: member.appId for application operations
197+
```
198+
199+
## Validation Results
200+
201+
### Production Validation
202+
-**Beta Swagger**: `microsoftgraph-beta-1.1.0-preview.json` contains enhanced relationshipMember
203+
-**v1.1 Swagger**: `microsoftgraph-v1.0-1.1.0-preview.json` contains enhanced relationshipMember
204+
-**v1.0 Swagger**: `microsoftgraph-v1.0-1.0.0.json` maintains string arrays (no relationshipMember)
205+
206+
### Test Validation
207+
```bash
208+
npm test -- swaggerWriter.test.ts
209+
# Result: 11 passed, 0 failed
210+
```
211+
212+
### Generated Output Verification
213+
```powershell
214+
# Enhanced versions contain full object structure
215+
Get-Content src\swagger-generation\output\microsoftgraph-beta-1.1.0-preview.json |
216+
ConvertFrom-Json | Select-Object -ExpandProperty definitions |
217+
Select-Object -ExpandProperty "microsoft.graph.relationshipMember"
218+
219+
# Legacy version uses simple strings
220+
Get-Content src\swagger-generation\output\microsoftgraph-v1.0-1.0.0.json |
221+
ConvertFrom-Json | Select-Object -ExpandProperty definitions |
222+
Select-Object -ExpandProperty "microsoft.graph.relationship"
223+
```
224+
225+
## Benefits Delivered
226+
227+
1. **Enhanced Type Information**: Full object metadata for intelligent operations
228+
2. **Improved Filtering**: Type-based filtering capabilities for relationships
229+
3. **Better Object Referencing**: Multiple identifiers (displayName, UPN, appId, uniqueName)
230+
4. **Template Flexibility**: Rich object properties for template-based operations
231+
5. **Backward Compatibility**: Zero impact on existing v1.0 implementations
232+
6. **Production Ready**: Comprehensive test coverage and validation
233+
234+
## Migration Path
235+
236+
### For New Implementations
237+
- Use enhanced versions (`beta/1.1.0-preview` or `v1.0/1.1.0-preview`)
238+
- Leverage rich relationship member objects for advanced scenarios
239+
240+
### For Existing Implementations
241+
- v1.0 implementations continue working unchanged
242+
- Opt-in to enhanced versions when ready for advanced features
243+
- No breaking changes in legacy API versions
244+
245+
## Technical Architecture
246+
247+
### Version Detection Logic
248+
```typescript
249+
function isEnhancedRelationshipVersion(config: Config): boolean {
250+
return (config.APIVersion === 'beta' && config.ExtensionVersion === '1.1.0-preview') ||
251+
(config.APIVersion === 'v1.0' && config.ExtensionVersion === '1.1.0-preview');
252+
}
253+
```
254+
255+
### Conditional Schema Generation
256+
- Enhanced versions: Generate `microsoft.graph.relationshipMember` + enhanced `microsoft.graph.relationship`
257+
- Legacy versions: Generate only `microsoft.graph.relationship` with string arrays
258+
- All versions: Include `microsoft.graph.relationshipSemantics` for relationship handling
259+
260+
## Future Considerations
261+
262+
1. **Additional Object Properties**: Can extend relationshipMember with more Graph object properties
263+
2. **Custom Unique Names**: Potential for user-defined unique name generation
264+
3. **Type-specific Properties**: Could add type-specific property sets (e.g., group-specific properties)
265+
4. **Cross-reference Capabilities**: Enhanced object dereferencing across relationship types
266+
267+
## Conclusion
268+
269+
The Enhanced Relationship Member Types implementation successfully addresses all identified limitations while maintaining full backward compatibility. The solution provides rich object metadata for advanced filtering, referencing, and type-based operations, enabling sophisticated Microsoft Graph Bicep template scenarios.
270+
271+
**Status: Production Ready**

generated/index.json

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,46 @@
11
{
22
"resources": {
33
"Microsoft.Graph/groups@beta": {
4-
"$ref": "microsoftgraph/microsoft.graph/beta/0.1.9-preview/types.json#/18"
4+
"$ref": "microsoftgraph/microsoft.graph/beta/1.0.1-preview/types.json#/18"
55
},
66
"Microsoft.Graph/applications@beta": {
7-
"$ref": "microsoftgraph/microsoft.graph/beta/0.1.9-preview/types.json#/74"
7+
"$ref": "microsoftgraph/microsoft.graph/beta/1.0.1-preview/types.json#/74"
88
},
99
"Microsoft.Graph/servicePrincipals@beta": {
10-
"$ref": "microsoftgraph/microsoft.graph/beta/0.1.9-preview/types.json#/92"
10+
"$ref": "microsoftgraph/microsoft.graph/beta/1.0.1-preview/types.json#/92"
1111
},
1212
"Microsoft.Graph/applications/federatedIdentityCredentials@beta": {
13-
"$ref": "microsoftgraph/microsoft.graph/beta/0.1.9-preview/types.json#/97"
13+
"$ref": "microsoftgraph/microsoft.graph/beta/1.0.1-preview/types.json#/97"
1414
},
1515
"Microsoft.Graph/oauth2PermissionGrants@beta": {
16-
"$ref": "microsoftgraph/microsoft.graph/beta/0.1.9-preview/types.json#/101"
16+
"$ref": "microsoftgraph/microsoft.graph/beta/1.0.1-preview/types.json#/101"
1717
},
1818
"Microsoft.Graph/appRoleAssignedTo@beta": {
19-
"$ref": "microsoftgraph/microsoft.graph/beta/0.1.9-preview/types.json#/105"
19+
"$ref": "microsoftgraph/microsoft.graph/beta/1.0.1-preview/types.json#/105"
2020
},
2121
"Microsoft.Graph/users@beta": {
22-
"$ref": "microsoftgraph/microsoft.graph/beta/0.1.9-preview/types.json#/110"
22+
"$ref": "microsoftgraph/microsoft.graph/beta/1.0.1-preview/types.json#/110"
2323
},
2424
"Microsoft.Graph/groups@v1.0": {
25-
"$ref": "microsoftgraph/microsoft.graph/v1.0/0.1.9-preview/types.json#/13"
25+
"$ref": "microsoftgraph/microsoft.graph/v1.0/1.0.1-preview/types.json#/13"
2626
},
2727
"Microsoft.Graph/applications@v1.0": {
28-
"$ref": "microsoftgraph/microsoft.graph/v1.0/0.1.9-preview/types.json#/70"
28+
"$ref": "microsoftgraph/microsoft.graph/v1.0/1.0.1-preview/types.json#/70"
2929
},
3030
"Microsoft.Graph/servicePrincipals@v1.0": {
31-
"$ref": "microsoftgraph/microsoft.graph/v1.0/0.1.9-preview/types.json#/88"
31+
"$ref": "microsoftgraph/microsoft.graph/v1.0/1.0.1-preview/types.json#/88"
3232
},
3333
"Microsoft.Graph/applications/federatedIdentityCredentials@v1.0": {
34-
"$ref": "microsoftgraph/microsoft.graph/v1.0/0.1.9-preview/types.json#/93"
34+
"$ref": "microsoftgraph/microsoft.graph/v1.0/1.0.1-preview/types.json#/93"
3535
},
3636
"Microsoft.Graph/oauth2PermissionGrants@v1.0": {
37-
"$ref": "microsoftgraph/microsoft.graph/v1.0/0.1.9-preview/types.json#/97"
37+
"$ref": "microsoftgraph/microsoft.graph/v1.0/1.0.1-preview/types.json#/97"
3838
},
3939
"Microsoft.Graph/appRoleAssignedTo@v1.0": {
40-
"$ref": "microsoftgraph/microsoft.graph/v1.0/0.1.9-preview/types.json#/101"
40+
"$ref": "microsoftgraph/microsoft.graph/v1.0/1.0.1-preview/types.json#/101"
4141
},
4242
"Microsoft.Graph/users@v1.0": {
43-
"$ref": "microsoftgraph/microsoft.graph/v1.0/0.1.9-preview/types.json#/106"
43+
"$ref": "microsoftgraph/microsoft.graph/v1.0/1.0.1-preview/types.json#/106"
4444
}
4545
},
4646
"resourceFunctions": {}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"resources": {
3+
"Microsoft.Graph/groups@beta": {
4+
"$ref": "types.json#/23"
5+
},
6+
"Microsoft.Graph/applications@beta": {
7+
"$ref": "types.json#/79"
8+
},
9+
"Microsoft.Graph/servicePrincipals@beta": {
10+
"$ref": "types.json#/97"
11+
},
12+
"Microsoft.Graph/applications/federatedIdentityCredentials@beta": {
13+
"$ref": "types.json#/103"
14+
},
15+
"Microsoft.Graph/oauth2PermissionGrants@beta": {
16+
"$ref": "types.json#/107"
17+
},
18+
"Microsoft.Graph/appRoleAssignedTo@beta": {
19+
"$ref": "types.json#/111"
20+
},
21+
"Microsoft.Graph/users@beta": {
22+
"$ref": "types.json#/116"
23+
}
24+
},
25+
"resourceFunctions": {},
26+
"settings": {
27+
"name": "MicrosoftGraphBeta",
28+
"version": "1.1.0-preview",
29+
"isSingleton": false,
30+
"configurationType": {
31+
"$ref": "types.json#/117"
32+
}
33+
}
34+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Bicep Types
2+
## microsoft.graph
3+
### microsoft.graph/applications
4+
* **Link**: [beta](types.md#resource-microsoftgraphapplicationsbeta)
5+
6+
### microsoft.graph/applications/federatedidentitycredentials
7+
* **Link**: [beta](types.md#resource-microsoftgraphapplicationsfederatedidentitycredentialsbeta)
8+
9+
### microsoft.graph/approleassignedto
10+
* **Link**: [beta](types.md#resource-microsoftgraphapproleassignedtobeta)
11+
12+
### microsoft.graph/groups
13+
* **Link**: [beta](types.md#resource-microsoftgraphgroupsbeta)
14+
15+
### microsoft.graph/oauth2permissiongrants
16+
* **Link**: [beta](types.md#resource-microsoftgraphoauth2permissiongrantsbeta)
17+
18+
### microsoft.graph/serviceprincipals
19+
* **Link**: [beta](types.md#resource-microsoftgraphserviceprincipalsbeta)
20+
21+
### microsoft.graph/users
22+
* **Link**: [beta](types.md#resource-microsoftgraphusersbeta)
23+

0 commit comments

Comments
 (0)