Skip to content

Commit c0b83b6

Browse files
Merge pull request KelvinTegelaar#1598 from Zacgoose/contact_perms
Feat: Contact Permissions Management
2 parents 10cd5ae + 314d900 commit c0b83b6

File tree

4 files changed

+474
-0
lines changed

4 files changed

+474
-0
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
using namespace System.Net
2+
3+
function Invoke-ExecModifyContactPerms {
4+
<#
5+
.FUNCTIONALITY
6+
Entrypoint
7+
.ROLE
8+
Exchange.Mailbox.ReadWrite
9+
#>
10+
[CmdletBinding()]
11+
param($Request, $TriggerMetadata)
12+
13+
$APIName = $Request.Params.CIPPEndpoint
14+
$Headers = $Request.Headers
15+
Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug'
16+
17+
$Username = $Request.Body.userID
18+
$TenantFilter = $Request.Body.tenantFilter
19+
$Permissions = $Request.Body.permissions
20+
21+
Write-LogMessage -headers $Headers -API $APIName -message "Processing request for user: $Username, tenant: $TenantFilter" -Sev 'Debug'
22+
23+
if ($null -eq $Username) {
24+
Write-LogMessage -headers $Headers -API $APIName -message 'Username is null' -Sev 'Error'
25+
$body = [pscustomobject]@{'Results' = @('Username is required') }
26+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
27+
StatusCode = [HttpStatusCode]::BadRequest
28+
Body = $Body
29+
})
30+
return
31+
}
32+
33+
try {
34+
$UserId = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($Username)" -tenantid $TenantFilter).id
35+
Write-LogMessage -headers $Headers -API $APIName -message "Retrieved user ID: $UserId" -Sev 'Debug'
36+
} catch {
37+
Write-LogMessage -headers $Headers -API $APIName -message "Failed to get user ID: $($_.Exception.Message)" -Sev 'Error'
38+
$body = [pscustomobject]@{'Results' = @("Failed to get user ID: $($_.Exception.Message)") }
39+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
40+
StatusCode = [HttpStatusCode]::NotFound
41+
Body = $Body
42+
})
43+
return
44+
}
45+
46+
$Results = [System.Collections.Generic.List[string]]::new()
47+
$HasErrors = $false
48+
49+
# Convert permissions to array format if it's an object with numeric keys
50+
if ($Permissions -is [PSCustomObject]) {
51+
if ($Permissions.PSObject.Properties.Name -match '^\d+$') {
52+
$Permissions = $Permissions.PSObject.Properties.Value
53+
} else {
54+
$Permissions = @($Permissions)
55+
}
56+
}
57+
58+
Write-LogMessage -headers $Headers -API $APIName -message "Processing $($Permissions.Count) permission entries" -Sev 'Debug'
59+
60+
foreach ($Permission in $Permissions) {
61+
Write-LogMessage -headers $Headers -API $APIName -message "Processing permission: $($Permission | ConvertTo-Json)" -Sev 'Debug'
62+
63+
$PermissionLevel = $Permission.PermissionLevel.value ?? $Permission.PermissionLevel
64+
$Modification = $Permission.Modification
65+
$CanViewPrivateItems = $Permission.CanViewPrivateItems ?? $false
66+
$FolderName = $Permission.FolderName ?? 'Contact'
67+
$SendNotificationToUser = $Permission.SendNotificationToUser ?? $false
68+
69+
Write-LogMessage -headers $Headers -API $APIName -message "Permission Level: $PermissionLevel, Modification: $Modification, CanViewPrivateItems: $CanViewPrivateItems, FolderName: $FolderName" -Sev 'Debug'
70+
71+
# Handle UserID as array or single value
72+
$TargetUsers = @($Permission.UserID | ForEach-Object { $_.value ?? $_ })
73+
74+
Write-LogMessage -headers $Headers -API $APIName -message "Target Users: $($TargetUsers -join ', ')" -Sev 'Debug'
75+
76+
foreach ($TargetUser in $TargetUsers) {
77+
try {
78+
Write-LogMessage -headers $Headers -API $APIName -message "Processing target user: $TargetUser" -Sev 'Debug'
79+
$Params = @{
80+
APIName = $APIName
81+
Headers = $Headers
82+
RemoveAccess = if ($Modification -eq 'Remove') { $TargetUser } else { $null }
83+
TenantFilter = $TenantFilter
84+
UserID = $UserId
85+
folderName = $FolderName
86+
UserToGetPermissions = $TargetUser
87+
LoggingName = $TargetUser
88+
Permissions = $PermissionLevel
89+
SendNotificationToUser = $SendNotificationToUser
90+
}
91+
92+
# Write-Host "Request params: $($Params | ConvertTo-Json)"
93+
$Result = Set-CIPPContactPermission @Params
94+
95+
$null = $Results.Add($Result)
96+
} catch {
97+
$HasErrors = $true
98+
$null = $Results.Add("$($_.Exception.Message)")
99+
}
100+
}
101+
}
102+
103+
if ($Results.Count -eq 0) {
104+
Write-LogMessage -headers $Headers -API $APIName -message 'No results were generated from the operation' -Sev 'Warning'
105+
$null = $Results.Add('No results were generated from the operation. Please check the logs for more details.')
106+
$HasErrors = $true
107+
}
108+
109+
$Body = [pscustomobject]@{'Results' = @($Results) }
110+
111+
# Associate values to output bindings by calling 'Push-OutputBinding'.
112+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
113+
StatusCode = if ($HasErrors) { [HttpStatusCode]::InternalServerError } else { [HttpStatusCode]::OK }
114+
Body = $Body
115+
})
116+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using namespace System.Net
2+
3+
Function Invoke-ListContactPermissions {
4+
<#
5+
.FUNCTIONALITY
6+
Entrypoint
7+
.ROLE
8+
Exchange.Mailbox.Read
9+
#>
10+
[CmdletBinding()]
11+
param($Request, $TriggerMetadata)
12+
13+
$APIName = $Request.Params.CIPPEndpoint
14+
$Headers = $Request.Headers
15+
Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug'
16+
17+
$UserID = $Request.Query.UserID
18+
$TenantFilter = $Request.Query.tenantFilter
19+
20+
try {
21+
$GetContactParam = @{Identity = $UserID; FolderScope = 'Contacts' }
22+
$ContactFolder = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-MailboxFolderStatistics' -anchor $UserID -cmdParams $GetContactParam | Select-Object -First 1 -ExcludeProperty *data.type*
23+
$ContactParam = @{Identity = "$($UserID):\$($ContactFolder.name)" }
24+
$Mailbox = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-Mailbox' -cmdParams @{Identity = $UserID }
25+
$GraphRequest = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-MailboxFolderPermission' -anchor $UserID -cmdParams $ContactParam -UseSystemMailbox $true | Select-Object Identity, User, AccessRights, FolderName, @{ Name = 'MailboxInfo'; Expression = { $Mailbox } }
26+
27+
Write-LogMessage -API $APIName -tenant $TenantFilter -message "Contact permissions listed for $($TenantFilter)" -sev Debug
28+
$StatusCode = [HttpStatusCode]::OK
29+
} catch {
30+
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
31+
$StatusCode = [HttpStatusCode]::Forbidden
32+
$GraphRequest = $ErrorMessage
33+
}
34+
35+
# Associate values to output bindings by calling 'Push-OutputBinding'.
36+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
37+
StatusCode = $StatusCode
38+
Body = @($GraphRequest)
39+
})
40+
41+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
function Set-CIPPContactPermission {
2+
[CmdletBinding(SupportsShouldProcess = $true)]
3+
param(
4+
$APIName = 'Set Contact Permissions',
5+
$Headers,
6+
$RemoveAccess,
7+
$TenantFilter,
8+
$UserID,
9+
$FolderName,
10+
$UserToGetPermissions,
11+
$LoggingName,
12+
$Permissions,
13+
[bool]$SendNotificationToUser = $false
14+
)
15+
16+
try {
17+
# If a pretty logging name is not provided, use the ID instead
18+
if ([string]::IsNullOrWhiteSpace($LoggingName) -and $RemoveAccess) {
19+
$LoggingName = $RemoveAccess
20+
} elseif ([string]::IsNullOrWhiteSpace($LoggingName) -and $UserToGetPermissions) {
21+
$LoggingName = $UserToGetPermissions
22+
}
23+
24+
$ContactParam = [PSCustomObject]@{
25+
Identity = "$($UserID):\$FolderName"
26+
AccessRights = @($Permissions)
27+
User = $UserToGetPermissions
28+
SendNotificationToUser = $SendNotificationToUser
29+
}
30+
31+
if ($RemoveAccess) {
32+
if ($PSCmdlet.ShouldProcess("$UserID\$FolderName", "Remove permissions for $LoggingName")) {
33+
$null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Remove-MailboxFolderPermission' -cmdParams @{Identity = "$($UserID):\$FolderName"; User = $RemoveAccess }
34+
$Result = "Successfully removed access for $LoggingName from contact folder $($ContactParam.Identity)"
35+
Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -sev Info
36+
}
37+
} else {
38+
if ($PSCmdlet.ShouldProcess("$UserID\$FolderName", "Set permissions for $LoggingName to $Permissions")) {
39+
try {
40+
$null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Set-MailboxFolderPermission' -cmdParams $ContactParam -Anchor $UserID
41+
} catch {
42+
$null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Add-MailboxFolderPermission' -cmdParams $ContactParam -Anchor $UserID
43+
}
44+
45+
$Result = "Successfully set permissions on contact folder $($ContactParam.Identity). The user $LoggingName now has $Permissions permissions on this folder."
46+
47+
if ($SendNotificationToUser) {
48+
$Result += ' A notification has been sent to the user.'
49+
}
50+
51+
Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -sev Info
52+
}
53+
}
54+
} catch {
55+
$ErrorMessage = Get-CippException -Exception $_
56+
Write-Warning "Error changing contact permissions $($_.Exception.Message)"
57+
Write-Information $_.InvocationInfo.PositionMessage
58+
$Result = "Failed to set contact permissions for $LoggingName on $UserID : $($ErrorMessage.NormalizedError)"
59+
Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -sev Error -LogData $ErrorMessage
60+
throw $Result
61+
}
62+
63+
return $Result
64+
}

0 commit comments

Comments
 (0)