Skip to content

Commit 9b9a50b

Browse files
Merge pull request KelvinTegelaar#1705 from kris6673/group-soa
Feat: Add functions to manage SOA
2 parents 6122630 + 696d9c9 commit 9b9a50b

File tree

4 files changed

+129
-32
lines changed

4 files changed

+129
-32
lines changed

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Contacts/Invoke-ListContacts.ps1

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using namespace System.Collections.Generic
22
using namespace System.Text.RegularExpressions
33

4-
Function Invoke-ListContacts {
4+
function Invoke-ListContacts {
55
<#
66
.FUNCTIONALITY
77
Entrypoint
@@ -18,10 +18,9 @@ Function Invoke-ListContacts {
1818
# Early validation and exit
1919
if (-not $TenantFilter) {
2020
return ([HttpResponseContext]@{
21-
StatusCode = [HttpStatusCode]::BadRequest
22-
Body = 'tenantFilter is required'
23-
})
24-
return
21+
StatusCode = [HttpStatusCode]::BadRequest
22+
Body = 'tenantFilter is required'
23+
})
2524
}
2625

2726
# Pre-compiled regex for MailTip cleaning
@@ -52,35 +51,35 @@ Function Invoke-ListContacts {
5251
$phones = if ($phoneCapacity -gt 0) {
5352
$phoneList = [List[hashtable]]::new($phoneCapacity)
5453
if ($Contact.Phone) {
55-
$phoneList.Add(@{ type = "business"; number = $Contact.Phone })
54+
$phoneList.Add(@{ type = 'business'; number = $Contact.Phone })
5655
}
5756
if ($Contact.MobilePhone) {
58-
$phoneList.Add(@{ type = "mobile"; number = $Contact.MobilePhone })
57+
$phoneList.Add(@{ type = 'mobile'; number = $Contact.MobilePhone })
5958
}
6059
$phoneList.ToArray()
6160
} else { @() }
6261

6362
return @{
64-
id = $Contact.Id
65-
displayName = $Contact.DisplayName
66-
givenName = $Contact.FirstName
67-
surname = $Contact.LastName
68-
mail = $mailAddress
69-
companyName = $Contact.Company
70-
jobTitle = $Contact.Title
71-
website = $Contact.WebPage
72-
notes = $Contact.Notes
73-
hidefromGAL = $MailContact.HiddenFromAddressListsEnabled
74-
mailTip = $cleanMailTip
63+
id = $Contact.Id
64+
displayName = $Contact.DisplayName
65+
givenName = $Contact.FirstName
66+
surname = $Contact.LastName
67+
mail = $mailAddress
68+
companyName = $Contact.Company
69+
jobTitle = $Contact.Title
70+
website = $Contact.WebPage
71+
notes = $Contact.Notes
72+
hidefromGAL = $MailContact.HiddenFromAddressListsEnabled
73+
mailTip = $cleanMailTip
7574
onPremisesSyncEnabled = $Contact.IsDirSynced
76-
addresses = @(@{
77-
street = $Contact.StreetAddress
78-
city = $Contact.City
79-
state = $Contact.StateOrProvince
80-
countryOrRegion = $Contact.CountryOrRegion
81-
postalCode = $Contact.PostalCode
82-
})
83-
phones = $phones
75+
addresses = @(@{
76+
street = $Contact.StreetAddress
77+
city = $Contact.City
78+
state = $Contact.StateOrProvince
79+
countryOrRegion = $Contact.CountryOrRegion
80+
postalCode = $Contact.PostalCode
81+
})
82+
phones = $phones
8483
}
8584
}
8685

@@ -98,20 +97,29 @@ Function Invoke-ListContacts {
9897
}
9998

10099
if (!$Contact -or !$MailContact) {
101-
throw "Contact not found or insufficient permissions"
100+
throw 'Contact not found or insufficient permissions'
102101
}
103102

104103
$ContactResponse = ConvertTo-ContactObject -Contact $Contact -MailContact $MailContact
105104

106105
} else {
107106
# Get all contacts - simplified approach
108-
Write-Host "Getting all contacts"
107+
Write-Host 'Getting all contacts'
109108

110109
$ContactResponse = New-EXORequest -tenantid $TenantFilter -cmdlet 'Get-Contact' -cmdParams @{
111-
Filter = "RecipientTypeDetails -eq 'MailContact'"
110+
Filter = "RecipientTypeDetails -eq 'MailContact'"
112111
ResultSize = 'Unlimited'
113112
} | Select-Object -Property City, Company, Department, DisplayName, FirstName, LastName, IsDirSynced, Guid, WindowsEmailAddress
114113

114+
# Add Graph ID to each contact based on email match
115+
$GraphContacts = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/contacts' -tenantid $TenantFilter
116+
foreach ($contact in $ContactResponse) {
117+
$GraphMatch = $GraphContacts | Where-Object { $_.mail -eq $contact.WindowsEmailAddress }
118+
if ($GraphMatch) {
119+
$contact | Add-Member -MemberType NoteProperty -Name 'graphId' -Value $GraphMatch.id -Force
120+
}
121+
}
122+
115123
# Return empty array if no contacts found
116124
if (!$ContactResponse) {
117125
$ContactResponse = @()
@@ -128,7 +136,7 @@ Function Invoke-ListContacts {
128136
}
129137

130138
return ([HttpResponseContext]@{
131-
StatusCode = $StatusCode
132-
Body = $ContactResponse
133-
})
139+
StatusCode = $StatusCode
140+
Body = $ContactResponse
141+
})
134142
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
function Invoke-ExecSetCloudManaged {
2+
<#
3+
.FUNCTIONALITY
4+
Entrypoint
5+
.ROLE
6+
Identity.DirSync.ReadWrite
7+
.DESCRIPTION
8+
Sets the cloud-managed status of a user, group, or contact.
9+
#>
10+
[CmdletBinding()]
11+
param($Request, $TriggerMetadata)
12+
13+
$APIName = $Request.Params.CIPPEndpoint
14+
$Headers = $Request.Headers
15+
16+
# Interact with query parameters or the body of the request.
17+
$TenantFilter = $Request.Body.tenantFilter
18+
$GroupID = $Request.Body.ID
19+
$DisplayName = $Request.Body.displayName
20+
$Type = $Request.Body.type
21+
$IsCloudManaged = [System.Convert]::ToBoolean($Request.Body.isCloudManaged)
22+
23+
try {
24+
$Params = @{
25+
Id = $GroupID
26+
TenantFilter = $TenantFilter
27+
DisplayName = $DisplayName
28+
Type = $Type
29+
IsCloudManaged = $IsCloudManaged
30+
APIName = $APIName
31+
Headers = $Headers
32+
}
33+
$Result = Set-CIPPCloudManaged @Params
34+
$StatusCode = [HttpStatusCode]::OK
35+
} catch {
36+
$Result = "$($_.Exception.Message)"
37+
$StatusCode = [HttpStatusCode]::InternalServerError
38+
}
39+
return ([HttpResponseContext]@{
40+
StatusCode = $StatusCode
41+
Body = @{'Results' = $Result }
42+
})
43+
}

Modules/CIPPCore/Public/SAMManifest.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,18 @@
538538
{
539539
"id": "0a42382f-155c-4eb1-9bdc-21548ccaa387",
540540
"type": "Role"
541+
},
542+
{
543+
"id": "2d9bd318-b883-40be-9df7-63ec4fcdc424",
544+
"type": "Role"
545+
},
546+
{
547+
"id": "c8948c23-e66b-42db-83fd-770b71ab78d2",
548+
"type": "Role"
549+
},
550+
{
551+
"id": "a94a502d-0281-4d15-8cd2-682ac9362c4c",
552+
"type": "Role"
541553
}
542554
]
543555
},
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
function Set-CIPPCloudManaged(
2+
[string]$TenantFilter,
3+
[string]$Id,
4+
[string]$DisplayName,
5+
[ValidateSet('User', 'Group', 'Contact')]
6+
[string]$Type,
7+
[bool]$IsCloudManaged,
8+
[string]$APIName = 'Set Cloud Managed',
9+
$Headers
10+
) {
11+
try {
12+
$statusText = if ($IsCloudManaged -eq $true) { 'cloud-managed' } else { 'on-premises managed' }
13+
14+
$URI = switch ($Type) {
15+
'User' { "https://graph.microsoft.com/beta/users/$Id/onPremisesSyncBehavior" }
16+
'Group' { "https://graph.microsoft.com/beta/groups/$Id/onPremisesSyncBehavior" }
17+
'Contact' { "https://graph.microsoft.com/beta/contacts/$Id/onPremisesSyncBehavior" }
18+
}
19+
20+
$Body = @{
21+
isCloudManaged = $IsCloudManaged
22+
} | ConvertTo-Json -Depth 10
23+
24+
$null = New-GraphPOSTRequest -uri $URI -type PATCH -tenantid $TenantFilter -body $Body -AsApp $true
25+
$Message = "Successfully set $Type $DisplayName ($Id) source of authority to $statusText"
26+
Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Message -Sev 'Info'
27+
return $Message
28+
} catch {
29+
$ErrorMessage = Get-CippException -Exception $_
30+
$Message = "Failed to set $Type $DisplayName ($Id) source of authority to ${statusText}: $($ErrorMessage.NormalizedError)"
31+
Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Message -Sev 'Error' -LogData $ErrorMessage
32+
throw $Message
33+
}
34+
}

0 commit comments

Comments
 (0)