In the previous script I provide a way to browse and export Microsoft Teams Information using Graph but this time I have taken that to next level. The script below will allow you to create a Team, Channel, Members, Owners, Tabs and Message, all using Microsoft Graph. The script is created for someone who do not have great knowledge of Graph and may act as starting point. It is not a complete solution but can be use to provision team with basic to medium complexities. Creating Team from Graph and PowerShell may look a bit complex but once you read the graph documentation, It become very easy. The script uses both v1.0 and beta endpoints based on their availability.
The CSV format is as following
ID,TeamName,MailNickName,TeamType,Classification,DeleteExistingTeam,Description,Channels,Owners,Members,Tabs,
1,TeamMXC,TeamMXC,Private,Internal,Yes,Demo Team will provide support,Channel1#Channel2#Channel3,GarthF@tenant.onmicrosoft.com#jerryyasir@tenant.onmicrosoft.com,GarretV@tenant.onmicrosoft.com#abrown@tenant.onmicrosoft.com,C:\temp\CreateTeam-Members.csv,Channel1;Tab1;Tab2#Channel2;Tab3;Tab4
Script
#$scopes = @(“Group.Read.All”,”Group.ReadWrite.All”,”User.ReadWrite.All”, “Directory.Read.All”,”Reports.Read.All”)
$scopes = $null
$ApplicationID = “”
$Password = ”
$appaaddomain = ‘tenant.onmicrosoft.com’
$CurrentUser = “jerryyasir@tenant.onmicrosoft.com”
$GraphURL = “https://graph.microsoft.com/beta”
$graphV1Endpoint = “https://graph.microsoft.com/v1.0″
#Establish connection
If($scopes.Length -gt 0){
Connect-PnPOnline -Scopes $scopes
} elseif($ApplicationID.Length -gt 0) {
#Connect-PnPOnline -AppId $ApplicationID -AppSecret $Password -AADDomain $appaaddomain
Connect-PnPMicrosoftGraph -AppId $ApplicationID -AppSecret $Password -AADDomain $appaaddomain
} else {
write-host ‘Connection issue’ -ForegroundColor Red
exit
}
$token = Get-PnPAccessToken
$CSVPath = “C:\temp\CreateTeam-Basic-Graph.csv”
$Data = Import-Csv -Path $CSVPath
foreach($team in $Data)
{
Write-Host “Team Creation Started…” $team.TeamsName -ForegroundColor Yellow
$TeamName = $team.TeamName
$displayname = $team.TeamName
$MailNickName = $team.MailNickName
$AccessType = $team.TeamType
$Description = $team.Description
$Classification = $team.Classification
$TeamChannels = $team.Channels
$TeamMembers = $team.Members
$TeamOwners = $team.Owners
$DeleteExistingTeam = $team.DeleteExistingTeam
#$url = “$GraphURL/groups?`$filter=displayName eq ‘TeamABC'”
$getTeamFromGraphUrl = “$GraphURL/groups?`$filter=displayName eq ‘” + $TeamName + “‘”
$teamAlreadyExistResponse = Invoke-RestMethod -Uri $getTeamFromGraphUrl -Headers @{Authorization = “Bearer $token”}
if($teamAlreadyExistResponse.value.Count -gt 0){
foreach($r in $teamAlreadyExistResponse.value){
if($r.resourceProvisioningOptions -eq ‘Team’){
$GroupCreatedDateTime = $r.createdDateTime
$TeamID = $r.id
$TeamsOwnerUrl = “$GraphURL/groups/$TeamID/owners”
$teamsOwnersResponse = Invoke-RestMethod -Uri $TeamsOwnerUrl -Headers @{Authorization = “Bearer $token”}
$OwnerName = “”
if($teamsOwnersResponse)
{
Write-Host ” Team Owners:”
foreach($owner in $teamsOwnersResponse.value)
{
$OwnerName += $owner.displayName + “;”
}
$teamsOwnersResponse = $null
}
write-host “The Team $($r.displayname) Created On $GroupCreatedDateTime Owned by $OwnerName already exist on the tenant.” -ForegroundColor Yellow
if($DeleteExistingTeam)
{
}
}
else {
write-host $r.displayname “is an O365 Group.” -ForegroundColor Green
}
}
}
else
{
$arrayMembers = New-Object System.Collections.ArrayList
try
{
$arrTeamMembers = $TeamMembers -split “#”
if($arrTeamMembers)
{
for($i =0; $i -le ($arrTeamMembers.count – 1) ; $i++)
{
$MemberUrl = “$graphV1Endpoint/users”
$UserUserPrincipalName = $arrTeamMembers[$i]
if($UserUserPrincipalName -ne $CurrentUser)
{
#$arrayMembers.Add(“$MemberUrl/$UserUserPrincipalName”)
$arrayMembers.Add($UserUserPrincipalName)
}
}
}
}
Catch
{
Write-Host “There is issue with Channel settings in CSV, Check and Fix:. $teamchannels”
}
$arrayOwners = New-Object System.Collections.ArrayList
try
{
$arrTeamOwners = $TeamOwners -split “#”
if($arrTeamOwners)
{
for($i =0; $i -le ($arrTeamOwners.count – 1) ; $i++)
{
$OwnerUserPrincipalName = $arrTeamOwners[$i]
$OwnerUrl = “$graphV1Endpoint/users”
$arrayOwners.Add($OwnerUserPrincipalName)
}
}
}
Catch
{
Write-Host “There is issue with Channel settings in CSV, Check and Fix:. $teamchannels”
}
$arryGroupType = @(“Unified”)
$arrayOwnersInREST = New-Object System.Collections.ArrayList
$arrayMembersInREST = New-Object System.Collections.ArrayList
foreach($Member in $arrayMembers)
{
$FindMemberUrl = “https://graph.microsoft.com/v1.0/users/” + $Member + “?`$Select=Id”
$Response = Invoke-RestMethod -Uri $FindMemberUrl -Headers @{Authorization = “Bearer $token”} -Method Get -ContentType “application/json” -Verbose
if($Response)
{
$Response.id
$MembersUrl = “https://graph.microsoft.com/v1.0/Users/$($Response.id)”
$arrayMembersInREST.Add($MembersUrl)
}
}
foreach($owner in $arrayOwners)
{
$FindOwnerUrl = “https://graph.microsoft.com/v1.0/users/” + $owner + “?`$Select=Id”
$Response = Invoke-RestMethod -Uri $FindOwnerUrl -Headers @{Authorization = “Bearer $token”} -Method Get -ContentType “application/json” -Verbose
if($Response)
{$Response.id
$OwnerUrl = “https://graph.microsoft.com/v1.0/Users/$($Response.id)”
$arrayOwnersInREST.Add($OwnerUrl)
}
}
$FindOwnerUrl = “https://graph.microsoft.com/v1.0/users/” + $CurrentUser + “?`$Select=Id”
$Response = Invoke-RestMethod -Uri $FindOwnerUrl -Headers @{Authorization = “Bearer $token”} -Method Get -ContentType “application/json” -Verbose
if($Response)
{
$Response.id
$CurrentUserAsMemberUrl = “https://graph.microsoft.com/v1.0/directoryobjects/$($Response.id)”
$CurrentUserAsMember = “$graphV1Endpoint/groups/$TeamID/members/`$ref”
$body = [ordered]@{
“@odata.id” = $CurrentUserAsMemberUrl
}
$bodyJSON = $body | ConvertTo-Json
Invoke-RestMethod -Uri $CurrentUserAsMember -Headers @{Authorization = “Bearer $token”} -Body $bodyJSON -Method Post -ContentType “application/json” -Verbose
$PlannerUri = “$GraphURL/planner/plans”
$body = [ordered]@{
owner = $TeamID;
title = $TeamName;
}
$bodyJSON = $body | ConvertTo-Json
Invoke-RestMethod -Uri $PlannerUri -Headers @{Authorization = “Bearer $token”} -Body $bodyJSON -Method Post -ContentType “application/json” -Verbose
Write-Host ” A planner plan $TeamName is now added to the Team.” -ForegroundColor Green
}
$GroupUrl = “$graphV1Endpoint/groups”
$body = [ordered]@{
displayName = $TeamName;
description = $Description;
groupTypes = $arryGroupType;
mailEnabled= $true;
mailnickname = $MailNickName;
securityEnabled=$false;
“members@odata.bind” = $arrayMembersInREST;
“owners@odata.bind” = $arrayOwnersInREST;
}
$bodyJSON = $body | ConvertTo-Json
$Response = Invoke-RestMethod -Uri $GroupUrl -Headers @{Authorization = “Bearer $token”} -Body $bodyJSON -Method Post -ContentType “application/json” -Verbose
$GroupCreationResponse = $null
$Stoploop = $false
$GroupId = $null
do {
$GroupQueryUrl=$GroupUrl + “/?`$filter=displayName eq ‘” + $TeamName + “‘”
$GroupCreationResponse = Invoke-RestMethod -Uri $GroupQueryUrl -Headers @{Authorization = “Bearer $token”} -Method Get -Verbose
if($GroupCreationResponse.value.Count -gt 0){
$Stoploop = $true
foreach($val in $GroupCreationResponse.value)
{
$GroupId = $val.Id
}
}
}
While ($Stoploop -eq $false)
$memberSettings = @{}
$memberSettings.Add(“allowCreateUpdateChannels”,$true)
$messagingSettings = @{}
$messagingSettings.Add(“allowUserEditMessages”,$true)
$messagingSettings.Add(“allowUserDeleteMessages”,$true)
$funSettings = @{}
$funSettings.Add(“allowGiphy”,$true)
$funSettings.Add(“giphyContentRating”,$true)
$TeamCreationUrl = “$GraphURL/groups/$GroupId/team”
$body = [ordered]@{
}
$bodyJSON = $body | ConvertTo-Json
$TeamCreationResponse = $null
$TeamCreationResponse=Invoke-RestMethod -Uri $TeamCreationUrl -Headers @{Authorization = “Bearer $token”} -Body $bodyJSON -Method Put -ContentType “application/json” -Verbose
if($TeamCreationResponse -eq $null)
{
$Stoploop = $false
do {
$TeamCreationResponse = Invoke-RestMethod -Uri $getTeamFromGraphUrl -Headers @{Authorization = “Bearer $token”} -Method Get -Verbose
if($TeamCreationResponse){
$Stoploop = $true
}
}
While ($Stoploop -eq $false)
}
if($TeamCreationResponse){
foreach($t in $TeamCreationResponse){
$newTeamDisplayName = $t.displayName
$TeamId = $t.Id
Write-Host “Team $newTeamDisplayName has been created successfully…” -ForegroundColor Green
}
Write-Host “Adding Channels to $newTeamDisplayName Team…” -ForegroundColor Yellow
$TeamsChannelsUrl = “$GraphURL/teams/$TeamId/channels”
try
{
$arrteamchannels = $TeamChannels -split “#”
if($arrteamchannels)
{
for($i =0; $i -le ($arrteamchannels.count – 1) ; $i++)
{
$ChannelName = $arrteamchannels[$i]
$ChannelDescription = “Channel 1 Description”
$body = [ordered]@{
displayName = $ChannelName;
description = $ChannelDescription;
}
$bodyJSON = $body | ConvertTo-Json
Invoke-RestMethod -Uri $TeamsChannelsUrl -Headers @{Authorization = “Bearer $token”} -Body $bodyJSON -Method Post -ContentType “application/json” -Verbose
Write-Host ” Channel $ChannelName is now added to the Team.” -ForegroundColor Green
}
}
}
Catch
{
Write-Host “There is issue with Channel settings in CSV, Check and Fix:. $teamchannels”
}
$GeneralChannelsUrl = “$TeamsChannelsUrl” + “?`$filter=displayName eq ‘General’&`$select=Id”
$GeneralChannelResponse = Invoke-RestMethod -Uri $GeneralChannelsUrl -Headers @{Authorization = “Bearer $token”} -Method Get -Verbose
$ChannelID = $GeneralChannelResponse.value[0].id;
$GeneralChannelMessageUrl = “$TeamsChannelsUrl/$ChannelID/messages”
$Message = “<H1>Welcome to Microsoft Teams From DXC Technology</H1>”
$RootMessage = @{}
$MessageBody = @{}
$MessageBody.Add(“ContentType”,1)
$MessageBody.Add(“content”,$Message)
$RootMessage.Add(“body”,$MessageBody)
$body = [ordered]@{
rootMessage = $RootMessage;
}
$bodyJSON = $body | ConvertTo-Json
Invoke-RestMethod -Uri $GeneralChannelMessageUrl -Headers @{Authorization = “Bearer $token”} -Body $bodyJSON -Method Post -ContentType “application/json” -Verbose
Write-Host ” Message has been posted on the Channel.” -ForegroundColor Green
#Adding Tab in General
$TeamsUrl = “$GraphURL/teams/$TeamID”
$TeamsAppsUrl = “$TeamsUrl/installedApps”
$TabConfiguration = @{}
$TabConfiguration.Add(“entityId”,$null)
$TabConfiguration.Add(“contentUrl”,”https://www.bing.com/maps/embed?h=768&w=800&cp=39.90073511625853~-75.16744692848968&lvl=18&typ=d&sty=h&src=SHELL&FORM=MBEDV8″)
$TabConfiguration.Add(“websiteUrl”,”https://binged.it/2BqOkiG”)
$TabConfiguration.Add(“removeUrl”,$null)
$TabPath = $GraphURL + “/appCatalogs/teamsApps/com.microsoft.teamspace.tab.web”
$body = [ordered]@{
“name”=”Places to Go”
“teamsApp@odata.bind”=$TabPath
Configuration = $TabConfiguration;
}
$bodyJSON = $body | ConvertTo-Json
$GeneralChannelTabs = “$TeamsChannelsUrl/$ChannelID/tabs”
Invoke-RestMethod -Uri $GeneralChannelTabs -Headers @{Authorization = “Bearer $token”} -Body $bodyJSON -Method Post -ContentType “application/json” -Verbose
Write-Host ” Message has been posted on the Channel.” -ForegroundColor Green
}
}
}