Skip to content

Commit 6291ef2

Browse files
committed
feat: full tenant group management
1 parent 0a6cdc1 commit 6291ef2

File tree

5 files changed

+171
-78
lines changed

5 files changed

+171
-78
lines changed

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecTenantGroup.ps1

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
function Invoke-ExecTenantGroup {
22
<#
3+
.SYNOPSIS
4+
Entrypoint for tenant group management
5+
.DESCRIPTION
6+
This function is used to manage tenant groups in CIPP
37
.FUNCTIONALITY
4-
Entrypoint
8+
Entrypoint,AnyTenant
59
.ROLE
610
Tenant.Config.ReadWrite
711
#>
@@ -14,56 +18,86 @@ function Invoke-ExecTenantGroup {
1418
$groupId = $Request.Body.groupId ?? [guid]::NewGuid().ToString()
1519
$groupName = $Request.Body.groupName
1620
$groupDescription = $Request.Body.groupDescription
17-
$membersToAdd = $Request.Body.membersToAdd
18-
$membersToRemove = $Request.Body.membersToRemove
21+
$members = $Request.Body.members
1922

2023
switch ($Action) {
2124
'AddEdit' {
25+
$Results = [System.Collections.Generic.List[object]]::new()
2226
# Update group details
2327
$GroupEntity = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq 'TenantGroup' and RowKey eq '$groupId'"
2428
if ($GroupEntity) {
2529
if ($groupName) {
26-
$GroupEntity.groupName = $groupName
30+
$GroupEntity.Name = $groupName
2731
}
2832
if ($groupDescription) {
29-
$GroupEntity.groupDescription = $groupDescription
33+
$GroupEntity.Description = $groupDescription
3034
}
3135
Add-CIPPAzDataTableEntity @Table -Entity $GroupEntity -Force
3236
} else {
3337
$GroupEntity = @{
3438
PartitionKey = 'TenantGroup'
3539
RowKey = $groupId
36-
groupName = $groupName
37-
groupDescription = $groupDescription
40+
Name = $groupName
41+
Description = $groupDescription
3842
}
3943
Add-CIPPAzDataTableEntity @Table -Entity $GroupEntity -Force
4044
}
4145

46+
$CurrentMembers = Get-CIPPAzDataTableEntity @MembersTable -Filter "GroupId eq '$groupId'"
47+
48+
$Adds = [System.Collections.Generic.List[string]]::new()
49+
$Removes = [System.Collections.Generic.List[string]]::new()
4250
# Add members
43-
foreach ($member in $membersToAdd) {
51+
foreach ($member in $members) {
52+
if ($CurrentMembers) {
53+
$CurrentMember = $CurrentMembers | Where-Object { $_.customerId -eq $member.value }
54+
if ($CurrentMember) {
55+
continue
56+
}
57+
}
4458
$MemberEntity = @{
45-
PartitionKey = $groupId
46-
RowKey = $member
59+
PartitionKey = 'Member'
60+
RowKey = '{0}-{1}' -f $groupId, $member.value
61+
GroupId = $groupId
62+
customerId = $member.value
4763
}
4864
Add-CIPPAzDataTableEntity @MembersTable -Entity $MemberEntity -Force
65+
$Adds.Add('Added member {0}' -f $member.label)
4966
}
5067

51-
# Remove members
52-
foreach ($member in $membersToRemove) {
53-
$MemberEntity = Get-CIPPAzDataTableEntity @MembersTable -Filter "PartitionKey eq '$groupId' and RowKey eq '$member'"
54-
if ($MemberEntity) {
55-
Remove-AzDataTableEntity @MembersTable -Entity $MemberEntity -Force
68+
if ($CurrentMembers) {
69+
foreach ($CurrentMember in $CurrentMembers) {
70+
if ($members.value -notcontains $CurrentMember.customerId) {
71+
Remove-AzDataTableEntity @MembersTable -Entity $CurrentMember -Force
72+
$Removes.Add('Removed member {0}' -f $CurrentMember.customerId)
73+
}
5674
}
5775
}
76+
$Results.Add(@{
77+
resultText = "Group '$groupName' saved successfully"
78+
state = 'success'
79+
})
80+
foreach ($Add in $Adds) {
81+
$Results.Add(@{
82+
resultText = $Add
83+
state = 'success'
84+
})
85+
}
86+
foreach ($Remove in $Removes) {
87+
$Results.Add(@{
88+
resultText = $Remove
89+
state = 'success'
90+
})
91+
}
5892

59-
$Body = @{ Results = "Group '$groupName' saved successfully" }
93+
$Body = @{ Results = $Results }
6094
}
6195
'Delete' {
6296
# Delete group
6397
$GroupEntity = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq 'TenantGroup' and RowKey eq '$groupId'"
6498
if ($GroupEntity) {
6599
Remove-AzDataTableEntity @Table -Entity $GroupEntity -Force
66-
$Body = @{ Results = "Group '$groupId' deleted successfully" }
100+
$Body = @{ Results = "Group '$($GroupEntity.Name)' deleted successfully" }
67101
} else {
68102
$Body = @{ Results = "Group '$groupId' not found" }
69103
}

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ListTenantGroups.ps1

Lines changed: 5 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,18 @@
11
function Invoke-ListTenantGroups {
22
<#
3+
.SYNOPSIS
4+
Entrypoint for listing tenant groups
35
.FUNCTIONALITY
4-
Entrypoint
6+
Entrypoint,AnyTenant
57
.ROLE
68
CIPP.Core.Read
79
#>
810
[CmdletBinding()]
911
param($Request, $TriggerMetadata)
1012

11-
$Table = Get-CippTable -tablename 'TenantGroups'
12-
$MembersTable = Get-CippTable -tablename 'TenantGroupMembers'
13-
$Action = $Request.Query.Action ?? $Request.Body.Action
1413
$groupFilter = $Request.Query.groupId ?? $Request.Body.groupId
15-
16-
switch ($Action) {
17-
'ListMembers' {
18-
if (!$groupFilter) {
19-
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
20-
StatusCode = [HttpStatusCode]::BadRequest
21-
Body = 'groupFilter is required for ListMembers action'
22-
})
23-
return
24-
}
25-
26-
$Tenants = Get-Tenants -IncludeErrors
27-
$Members = Get-CIPPAzDataTableEntity @MembersTable -Filter "PartitionKey eq '$groupFilter'"
28-
if (!$Members) {
29-
$Members = @()
30-
}
31-
32-
$Results = $Members | ForEach-Object {
33-
$Tenant = $Tenants | Where-Object { $_.customerId -eq $_.RowKey }
34-
if ($Tenant) {
35-
@{
36-
customerId = $Tenant.customerId
37-
displayName = $Tenant.displayName
38-
defaultDomainName = $Tenant.defaultDomainName
39-
}
40-
}
41-
}
42-
43-
$Body = @{ Results = $Results }
44-
}
45-
default {
46-
$Groups = Get-CIPPAzDataTableEntity @Table
47-
if (!$Groups) {
48-
$Results = @()
49-
} else {
50-
$Results = $Groups | ForEach-Object {
51-
@{
52-
groupId = $_.RowKey
53-
groupName = $_.groupName
54-
groupDescription = $_.groupDescription
55-
groupMembersCount = (Get-CIPPAzDataTableEntity @MembersTable -Filter "PartitionKey eq '$($_.RowKey)'" -Property PartitionKey, RowKey).Count
56-
}
57-
}
58-
}
59-
$Body = @{ Results = @($Results) }
60-
}
61-
}
14+
$TenantGroups = (Get-TenantGroups -GroupId $groupFilter) ?? @()
15+
$Body = @{ Results = @($TenantGroups) }
6216

6317
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
6418
StatusCode = [HttpStatusCode]::OK

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-EditTenant.ps1

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ using namespace System.Net
33
Function Invoke-EditTenant {
44
<#
55
.FUNCTIONALITY
6-
Entrypoint
6+
Entrypoint,AnyTenant
77
.ROLE
88
Tenant.Config.ReadWrite
99
#>
@@ -16,12 +16,13 @@ Function Invoke-EditTenant {
1616

1717
$customerId = $Request.Body.customerId
1818
$tenantAlias = $Request.Body.Alias
19-
$tenantGroups = $Request.Body.Groups
19+
$tenantGroups = $Request.Body.tenantGroups
2020

2121
$PropertiesTable = Get-CippTable -TableName 'TenantProperties'
2222
$Existing = Get-CIPPAzDataTableEntity @PropertiesTable -Filter "PartitionKey eq '$customerId'"
2323
$Tenant = Get-Tenants -TenantFilter $customerId
2424
$TenantTable = Get-CippTable -TableName 'Tenants'
25+
$GroupMembersTable = Get-CippTable -TableName 'TenantGroupMembers'
2526

2627
try {
2728
$AliasEntity = $Existing | Where-Object { $_.RowKey -eq 'Alias' }
@@ -43,14 +44,27 @@ Function Invoke-EditTenant {
4344
$null = Add-CIPPAzDataTableEntity @TenantTable -Entity $Tenant -Force
4445
}
4546

46-
<## Update tenant groups
47-
$groupsEntity = @{
48-
PartitionKey = $customerId
49-
RowKey = 'tenantGroups'
50-
Value = ($tenantGroups | ConvertTo-Json)
47+
# Update tenant groups
48+
$CurrentMembers = Get-CIPPAzDataTableEntity @GroupMembersTable -Filter "customerId eq '$customerId'"
49+
foreach ($Group in $tenantGroups) {
50+
$GroupEntity = $CurrentMembers | Where-Object { $_.GroupId -eq $Group.groupId }
51+
if (!$GroupEntity) {
52+
$GroupEntity = @{
53+
PartitionKey = 'Member'
54+
RowKey = '{0}-{1}' -f $Group.groupId, $customerId
55+
GroupId = $Group.groupId
56+
customerId = $customerId
57+
}
58+
Add-CIPPAzDataTableEntity @GroupMembersTable -Entity $GroupEntity -Force
59+
}
60+
}
61+
62+
# Remove any groups that are no longer selected
63+
foreach ($Group in $CurrentMembers) {
64+
if ($tenantGroups -notcontains $Group.GroupId) {
65+
Remove-AzDataTableEntity @GroupMembersTable -Entity $Group
66+
}
5167
}
52-
Set-CIPPAzDataTableEntity -Context $context -Entity $groupsEntity
53-
#>
5468

5569
$response = @{
5670
state = 'success'

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-ListTenantDetails.ps1

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,12 @@ Function Invoke-ListTenantDetails {
2323
tenantType, createdDateTime, onPremisesLastPasswordSyncDateTime, onPremisesLastSyncDateTime, onPremisesSyncEnabled, assignedPlans
2424

2525
$customProperties = Get-TenantProperties -customerId $tenantfilter
26-
2726
$org | Add-Member -MemberType NoteProperty -Name 'customProperties' -Value $customProperties
2827

28+
$Groups = (Get-TenantGroups -TenantFilter $tenantfilter) ?? @()
29+
$org | Add-Member -MemberType NoteProperty -Name 'Groups' -Value @($Groups)
30+
31+
2932
# Respond with the successful output
3033
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
3134
StatusCode = [HttpStatusCode]::OK
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
function Get-TenantGroups {
2+
<#
3+
.SYNOPSIS
4+
Get tenant groups
5+
.DESCRIPTION
6+
Get tenant groups from Azure Table Storage
7+
.PARAMETER GroupId
8+
The group id to filter on
9+
.PARAMETER TenantFilter
10+
The tenant filter to apply to get the groups for a specific tenant
11+
#>
12+
[CmdletBinding()]
13+
param(
14+
$GroupId,
15+
$TenantFilter
16+
)
17+
18+
$GroupTable = Get-CippTable -tablename 'TenantGroups'
19+
$MembersTable = Get-CippTable -tablename 'TenantGroupMembers'
20+
21+
if ($TenantFilter) {
22+
$TenantParams = @{
23+
TenantFilter = $TenantFilter
24+
IncludeErrors = $true
25+
}
26+
} else {
27+
$TenantParams = @{
28+
IncludeErrors = $true
29+
}
30+
}
31+
$Tenants = Get-Tenants @TenantParams
32+
33+
if ($GroupFilter) {
34+
$Groups = Get-CIPPAzDataTableEntity @GroupTable -Filter "RowKey eq '$GroupFilter'"
35+
$AllMembers = Get-CIPPAzDataTableEntity @MembersTable -Filter "GroupId eq '$GroupFilter'"
36+
} else {
37+
$Groups = Get-CIPPAzDataTableEntity @GroupTable
38+
$AllMembers = Get-CIPPAzDataTableEntity @MembersTable
39+
}
40+
41+
if (!$Groups) {
42+
return @()
43+
}
44+
45+
if ($TenantFilter) {
46+
$Memberships = $AllMembers | Where-Object { $_.customerId -eq $Tenants.customerId }
47+
foreach ($Group in $Memberships) {
48+
$Group = $Groups | Where-Object { $_.RowKey -eq $Group.GroupId }
49+
if ($Group) {
50+
[PSCustomObject]@{
51+
Id = $Group.RowKey
52+
Name = $Group.Name
53+
Description = $Group.Description
54+
}
55+
}
56+
}
57+
} else {
58+
$Groups | ForEach-Object {
59+
$Group = $_
60+
$Members = $AllMembers | Where-Object { $_.GroupId -eq $Group.RowKey }
61+
if (!$Members) {
62+
$Members = @()
63+
}
64+
65+
$Members = $Members | ForEach-Object {
66+
$Member = $_
67+
$Tenant = $Tenants | Where-Object { $Member.customerId -eq $_.customerId }
68+
if ($Tenant) {
69+
@{
70+
customerId = $Tenant.customerId
71+
displayName = $Tenant.displayName
72+
defaultDomainName = $Tenant.defaultDomainName
73+
}
74+
}
75+
}
76+
if (!$Members) {
77+
$Members = @()
78+
}
79+
80+
[PSCustomObject]@{
81+
Id = $Group.RowKey
82+
Name = $Group.Name
83+
Description = $Group.Description
84+
Members = @($Members)
85+
}
86+
}
87+
}
88+
}

0 commit comments

Comments
 (0)