Skip to content

Commit f881287

Browse files
authored
Merge pull request #135 from KelvinTegelaar/dev
[pull] dev from KelvinTegelaar:dev
2 parents 3e223fb + 5099c20 commit f881287

File tree

3 files changed

+464
-56
lines changed

3 files changed

+464
-56
lines changed

Config/schemaDefinitions.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[
2+
{
3+
"id": "cippUser",
4+
"description": "CIPP User Schema",
5+
"targetTypes": ["User"],
6+
"properties": [
7+
{ "name": "jitAdminEnabled", "type": "Boolean" },
8+
{ "name": "jitAdminExpiration", "type": "DateTime" },
9+
{ "name": "mailboxType", "type": "String" },
10+
{ "name": "archiveEnabled", "type": "Boolean" },
11+
{ "name": "autoExpandingArchiveEnabled", "type": "Boolean" },
12+
{ "name": "perUserMfaState", "type": "String" }
13+
],
14+
"status": "Available"
15+
}
16+
]
Lines changed: 353 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,353 @@
1+
function Invoke-ExecCustomData {
2+
<#
3+
.FUNCTIONALITY
4+
Entrypoint,AnyTenant
5+
.ROLE
6+
CIPP.AppSettings.ReadWrite
7+
#>
8+
[CmdletBinding()]
9+
param($Request, $TriggerMetadata)
10+
11+
$Action = $Request.Query.Action ?? $Request.Body.Action
12+
$CustomDataTable = Get-CippTable -TableName 'CustomData'
13+
14+
Write-Information "Executing action '$Action'"
15+
16+
switch ($Action) {
17+
'ListSchemaExtensions' {
18+
try {
19+
$SchemaExtensions = Get-CIPPAzDataTableEntity @CustomDataTable -Filter "PartitionKey eq 'SchemaExtension'" | Select-Object -ExpandProperty JSON | ConvertFrom-Json
20+
if (!$SchemaExtensions) {
21+
$SchemaExtensions = Get-CIPPSchemaExtensions | Sort-Object id
22+
}
23+
$Body = @{
24+
Results = @($SchemaExtensions)
25+
}
26+
} catch {
27+
$Body = @{
28+
Results = @(
29+
@{
30+
state = 'error'
31+
resultText = "Failed to retrieve schema extensions: $($_.Exception.Message)"
32+
}
33+
)
34+
}
35+
}
36+
}
37+
'AddSchemaExtension' {
38+
try {
39+
$SchemaExtension = $Request.Body.schemaExtension
40+
if (!$SchemaExtension) {
41+
throw 'SchemaExtension data is missing in the request body.'
42+
}
43+
44+
$Entity = @{
45+
PartitionKey = 'SchemaExtension'
46+
RowKey = $SchemaExtension.id
47+
JSON = [string]($SchemaExtension | ConvertTo-Json -Depth 5 -Compress)
48+
}
49+
50+
Add-CIPPAzDataTableEntity @CustomDataTable -Entity $Entity -Force
51+
$SchemaExtensions = Get-CIPPSchemaExtensions | Where-Object { $_.id -eq $SchemaExtension.id }
52+
53+
$Body = @{
54+
Results = @{
55+
state = 'success'
56+
resultText = "Schema extension '$($SchemaExtension.id)' added successfully."
57+
}
58+
}
59+
} catch {
60+
$Body = @{
61+
Results = @(
62+
@{
63+
state = 'error'
64+
resultText = "Failed to add schema extension: $($_.Exception.Message)"
65+
}
66+
)
67+
}
68+
}
69+
}
70+
'DeleteSchema' {
71+
try {
72+
$SchemaId = $Request.Body.id
73+
if (!$SchemaId) {
74+
throw 'Schema ID is missing in the request body.'
75+
}
76+
77+
# Retrieve the schema extension entity
78+
$SchemaEntity = Get-CIPPAzDataTableEntity @CustomDataTable -Filter "PartitionKey eq 'SchemaExtension'" | Where-Object { $SchemaId -match $_.RowKey }
79+
if (!$SchemaEntity) {
80+
throw "Schema extension with ID '$SchemaId' not found."
81+
}
82+
83+
# Ensure the schema is in 'InDevelopment' state before deletion
84+
$SchemaDefinition = $SchemaEntity.JSON | ConvertFrom-Json
85+
if ($SchemaDefinition.status -ne 'InDevelopment') {
86+
throw "Schema extension '$SchemaId' cannot be deleted because it is not in 'InDevelopment' state."
87+
}
88+
89+
try {
90+
$null = New-GraphPOSTRequest -Type DELETE -Uri "https://graph.microsoft.com/v1.0/schemaExtensions/$SchemaId" -AsApp $true -NoAuthCheck $true -tenantid $env:TenantID -Verbose
91+
} catch {
92+
Write-Warning "Schema extension '$SchemaId' not found in Microsoft Graph."
93+
}
94+
95+
96+
# Delete the schema extension entity
97+
Remove-AzDataTableEntity @CustomDataTable -Entity $SchemaEntity
98+
99+
$Body = @{
100+
Results = @{
101+
state = 'success'
102+
resultText = "Schema extension '$SchemaId' deleted successfully."
103+
}
104+
}
105+
} catch {
106+
$Body = @{
107+
Results = @(
108+
@{
109+
state = 'error'
110+
resultText = "Failed to delete schema extension: $($_.Exception.Message)"
111+
}
112+
)
113+
}
114+
}
115+
}
116+
'AddSchemaProperty' {
117+
try {
118+
$SchemaId = $Request.Body.id
119+
$Name = $Request.Body.name
120+
$Type = $Request.Body.type
121+
$NewProperty = @{
122+
name = $Name
123+
type = $Type
124+
}
125+
if (!$SchemaId) {
126+
throw 'Schema ID is missing in the request body.'
127+
}
128+
if (!$Name -or !$Type) {
129+
throw 'Property data is missing or incomplete in the request body.'
130+
}
131+
132+
# Retrieve the schema extension entity
133+
$SchemaEntity = Get-CIPPAzDataTableEntity @CustomDataTable -Filter "PartitionKey eq 'SchemaExtension'" | Where-Object { $SchemaId -match $_.RowKey }
134+
if (!$SchemaEntity) {
135+
throw "Schema extension with ID '$SchemaId' not found."
136+
}
137+
138+
# Parse the schema definition
139+
$SchemaDefinition = $SchemaEntity.JSON | ConvertFrom-Json
140+
141+
if ($SchemaDefinition.status -eq 'Deprecated') {
142+
throw "Properties cannot be added to schema extension '$SchemaId' because it is in the 'Deprecated' state."
143+
}
144+
145+
# Check if the property already exists
146+
if ($SchemaDefinition.properties | Where-Object { $_.name -eq $NewProperty.name }) {
147+
throw "Property with name '$($NewProperty.name)' already exists in schema extension '$SchemaId'."
148+
}
149+
150+
# Add the new property
151+
$Properties = [System.Collections.Generic.List[object]]::new()
152+
foreach ($Property in $SchemaDefinition.properties) {
153+
$Properties.Add($Property)
154+
}
155+
$Properties.Add($NewProperty)
156+
$SchemaDefinition.properties = $Properties
157+
158+
# Update the schema extension entity
159+
$SchemaEntity.JSON = [string]($SchemaDefinition | ConvertTo-Json -Depth 5 -Compress)
160+
Add-CIPPAzDataTableEntity @CustomDataTable -Entity $SchemaEntity -Force
161+
try { $null = Get-CIPPSchemaExtensions } catch {}
162+
163+
$Body = @{
164+
Results = @{
165+
state = 'success'
166+
resultText = "Property '$($NewProperty.name)' added to schema extension '$SchemaId' successfully."
167+
}
168+
}
169+
} catch {
170+
$Body = @{
171+
Results = @(
172+
@{
173+
state = 'error'
174+
resultText = "Failed to add property to schema extension: $($_.Exception.Message)"
175+
}
176+
)
177+
}
178+
}
179+
}
180+
'ChangeSchemaState' {
181+
try {
182+
$SchemaId = $Request.Body.id
183+
$NewStatus = $Request.Body.status
184+
if (!$SchemaId) {
185+
throw 'Schema ID is missing in the request body.'
186+
}
187+
if (!$NewStatus) {
188+
throw 'New status is missing in the request body.'
189+
}
190+
191+
# Retrieve the schema extension entity
192+
$SchemaEntity = Get-CIPPAzDataTableEntity @CustomDataTable -Filter "PartitionKey eq 'SchemaExtension'" | Where-Object { $SchemaId -match $_.RowKey }
193+
if (!$SchemaEntity) {
194+
throw "Schema extension with ID '$SchemaId' not found."
195+
}
196+
197+
# Parse the schema definition
198+
$SchemaDefinition = $SchemaEntity.JSON | ConvertFrom-Json
199+
200+
# Check if the status is already the same
201+
if ($SchemaDefinition.status -eq $NewStatus) {
202+
throw "Schema extension '$SchemaId' is already in the '$NewStatus' state."
203+
}
204+
205+
# Update the status
206+
$SchemaDefinition.status = $NewStatus
207+
208+
# Update the schema extension entity
209+
$SchemaEntity.JSON = [string]($SchemaDefinition | ConvertTo-Json -Depth 5 -Compress)
210+
Add-CIPPAzDataTableEntity @CustomDataTable -Entity $SchemaEntity -Force
211+
$null = Get-CIPPSchemaExtensions
212+
213+
$Body = @{
214+
Results = @{
215+
state = 'success'
216+
resultText = "Schema extension '$SchemaId' status changed to '$NewStatus' successfully."
217+
}
218+
}
219+
} catch {
220+
$Body = @{
221+
Results = @(
222+
@{
223+
state = 'error'
224+
resultText = "Failed to change schema extension status: $($_.Exception.Message)"
225+
}
226+
)
227+
}
228+
}
229+
}
230+
'ListDirectoryExtensions' {
231+
try {
232+
$Uri = "https://graph.microsoft.com/beta/applications(appId='$($env:ApplicationId)')/extensionProperties"
233+
$DirectoryExtensions = New-GraphGetRequest -uri $Uri -AsApp $true -NoAuthCheck $true -tenantid $env:TenantID
234+
235+
$Body = @{
236+
Results = @($DirectoryExtensions)
237+
}
238+
} catch {
239+
$Body = @{
240+
Results = @(
241+
@{
242+
state = 'error'
243+
resultText = "Failed to retrieve directory extensions: $($_.Exception.Message)"
244+
}
245+
)
246+
}
247+
}
248+
}
249+
'AddDirectoryExtension' {
250+
try {
251+
$ExtensionName = $Request.Body.name
252+
$DataType = $Request.Body.dataType
253+
$TargetObjects = $Request.Body.targetObjects
254+
$IsMultiValued = $Request.Body.isMultiValued -eq $true
255+
256+
if (!$ExtensionName -or !$DataType -or !$TargetObjects) {
257+
throw 'Extension name, data type, and target objects are required.'
258+
}
259+
260+
$AppId = $env:ApplicationId # Replace with your application ID
261+
$Uri = "https://graph.microsoft.com/beta/applications(appId='$AppId')/extensionProperties"
262+
263+
$BodyContent = @{
264+
name = $ExtensionName
265+
dataType = $DataType
266+
targetObjects = $TargetObjects
267+
isMultiValued = $IsMultiValued
268+
} | ConvertTo-Json -Depth 5 -Compress
269+
270+
$Response = New-GraphPOSTRequest -Uri $Uri -Body $BodyContent -AsApp $true -NoAuthCheck $true -tenantid $env:TenantID
271+
272+
$Body = @{
273+
Results = @{
274+
state = 'success'
275+
resultText = "Directory extension '$ExtensionName' added successfully."
276+
extension = $Response
277+
}
278+
}
279+
280+
# store the extension in the custom data table
281+
$Entity = @{
282+
PartitionKey = 'DirectoryExtension'
283+
RowKey = $Response.name
284+
JSON = [string](ConvertFrom-Json $Response -Compress -Depth 5)
285+
}
286+
} catch {
287+
$Body = @{
288+
Results = @(
289+
@{
290+
state = 'error'
291+
resultText = "Failed to add directory extension: $($_.Exception.Message)"
292+
}
293+
)
294+
}
295+
}
296+
}
297+
'DeleteDirectoryExtension' {
298+
try {
299+
$ExtensionName = $Request.Body.name
300+
$ExtensionId = $Request.Body.id
301+
if (!$ExtensionName) {
302+
throw 'Extension name is missing in the request body.'
303+
}
304+
$AppId = $env:ApplicationId # Replace with your application ID
305+
$Uri = "https://graph.microsoft.com/beta/applications(appId='$AppId')/extensionProperties/$ExtensionId"
306+
307+
# Delete the directory extension from Microsoft Graph
308+
$null = New-GraphPOSTRequest -Type DELETE -Uri $Uri -AsApp $true -NoAuthCheck $true -tenantid $env:TenantID
309+
try {
310+
$CustomDataTable = Get-CippTable -TableName 'CustomData'
311+
$ExtensionEntity = Get-CIPPAzDataTableEntity @CustomDataTable -Filter "PartitionKey eq 'DirectoryExtension' and RowKey eq '$ExtensionName'"
312+
# Remove the extension from the custom data table
313+
if ($ExtensionEntity) {
314+
Remove-AzDataTableEntity @CustomDataTable -Entity $ExtensionEntity
315+
}
316+
} catch {
317+
Write-Warning "Failed to delete directory extension from custom data table: $($_.Exception.Message)"
318+
}
319+
320+
$Body = @{
321+
Results = @{
322+
state = 'success'
323+
resultText = "Directory extension '$ExtensionName' deleted successfully."
324+
}
325+
}
326+
} catch {
327+
$Body = @{
328+
Results = @(
329+
@{
330+
state = 'error'
331+
resultText = "Failed to delete directory extension: $($_.Exception.Message)"
332+
}
333+
)
334+
}
335+
}
336+
}
337+
default {
338+
$Body = @{
339+
Results = @(
340+
@{
341+
state = 'error'
342+
resultText = 'Invalid action specified.'
343+
}
344+
)
345+
}
346+
}
347+
}
348+
349+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
350+
StatusCode = [HttpStatusCode]::OK
351+
Body = $Body
352+
})
353+
}

0 commit comments

Comments
 (0)