Private/Collect/Get-TcTeamsCollector.ps1

function Get-TcTeamsCollector {
    <#
    .SYNOPSIS
    Lists the Teams collectors, in the order they run.
    #>

    [CmdletBinding()]
    [OutputType([hashtable])]
    param()

    @(
        @{
            Id       = 'TMS-01'
            Workload = 'Teams'
            Title    = 'Teams'
            Service  = 'Teams'
            Collect  = {
                Add-TcTable 'teams' @(foreach ($t in @(Get-Team -ErrorAction Stop)) {
                        [ordered]@{
                            'Id'          = (Get-TcProperty $t 'GroupId')
                            'Name'        = (Get-TcProperty $t 'DisplayName')
                            'Visibility'  = [string](Get-TcProperty $t 'Visibility')
                            'Archived'    = [bool](Get-TcProperty $t 'Archived')
                            'Alias'       = (Get-TcProperty $t 'MailNickName')
                            'Description' = (Limit-TcText ([string](Get-TcProperty $t 'Description')) 300)
                        }
                    })
                Invoke-TcCollectorPart 'Team activity (Microsoft 365 report)' {
                    Connect-TcTenant -Role $script:TcCurrentTenant['role']
                    Add-TcTable 'teamActivity' @(foreach ($r in Get-TcUsageReport 'getTeamsTeamActivityDetail' | Where-Object { (Get-TcProperty $_ 'Is Deleted') -ne 'True' }) {
                            [ordered]@{
                                'Team'             = (Get-TcProperty $r 'Team Name')
                                'Type'             = (Get-TcProperty $r 'Team Type')
                                'Last activity'    = (Get-TcProperty $r 'Last Activity Date')
                                'Active users'     = [int]('0' + (Get-TcProperty $r 'Active Users'))
                                'Guests'           = [int]('0' + (Get-TcProperty $r 'Guests'))
                                'Channel messages' = [int]('0' + (Get-TcProperty $r 'Channel Messages'))
                                'Meetings'         = [int]('0' + (Get-TcProperty $r 'Meetings Organized'))
                            }
                        })
                }
            }
        }

        @{
            Id       = 'TMS-02'
            Workload = 'Teams'
            Title    = 'Channels (standard, private, shared) and members per team'
            Service  = 'Teams'
            Depth    = 'Complete'
            Requires = @('teams')
            Collect  = {
                $teamRows = @(Limit-TcCollectorRow 'teams' @(Get-TcTable 'teams') ([int](Get-TcCollectionSetting 'maxTeamDetails')))
                $n = 0; $channels = [System.Collections.Generic.List[object]]::new()
                Add-TcTable 'teamComposition' @(foreach ($t in $teamRows) {
                        $n++
                        if ($n % 25 -eq 0) { Write-TcMessage -Message ('Teams detailed: {0}/{1}' -f $n, $teamRows.Count) }
                        try {
                            $teamChannels = @(Get-TeamChannel -GroupId (Get-TcProperty $t 'Id') -ErrorAction Stop)
                            foreach ($c in $teamChannels) {
                                $channels.Add([ordered]@{
                                        'Team'    = (Get-TcProperty $t 'Name')
                                        'Channel' = (Get-TcProperty $c 'DisplayName')
                                        'Type'    = [string](Get-TcProperty $c 'MembershipType')
                                    })
                            }
                            $m = @(Get-TeamUser -GroupId (Get-TcProperty $t 'Id') -ErrorAction Stop)
                            [ordered]@{
                                'Team'              = (Get-TcProperty $t 'Name')
                                'Owners'            = @($m | Where-Object Role -EQ 'owner').Count
                                'Members'           = @($m | Where-Object Role -EQ 'member').Count
                                'Guests'            = @($m | Where-Object Role -EQ 'guest').Count
                                'Standard channels' = @($teamChannels | Where-Object { [string](Get-TcProperty $_ 'MembershipType') -eq 'Standard' }).Count
                                'Private channels'  = @($teamChannels | Where-Object { [string](Get-TcProperty $_ 'MembershipType') -eq 'Private' }).Count
                                'Shared channels'   = @($teamChannels | Where-Object { [string](Get-TcProperty $_ 'MembershipType') -eq 'Shared' }).Count
                            }
                        }
                        catch { Add-TcCollectorWarning "Team $(Get-TcProperty $t 'Name')" $_ }
                    })
                Add-TcTable 'channels' $channels
            }
        }

        @{
            Id       = 'TMS-03'
            Workload = 'Teams'
            Title    = 'Organization settings and Teams policies'
            Service  = 'Teams'
            Collect  = {
                $settingKinds = [ordered]@{
                    'CsTenantFederationConfiguration'          = 'External access'
                    'CsTeamsClientConfiguration'               = 'Teams client'
                    'CsTeamsGuestMeetingConfiguration'         = 'Guests - meetings'
                    'CsTeamsGuestMessagingConfiguration'       = 'Guests - messaging'
                    'CsTeamsGuestCallingConfiguration'         = 'Guests - calling'
                    'CsTeamsMeetingConfiguration'              = 'Meetings'
                    'CsOnlineDialInConferencingTenantSettings' = 'Audio conferencing'
                    'CsTeamsAcsFederationConfiguration'        = 'ACS federation'
                }
                foreach ($k in $settingKinds.Keys) {
                    if (-not (Get-Command "Get-$k" -ErrorAction SilentlyContinue)) { continue }
                    Invoke-TcCollectorPart $settingKinds[$k] { Add-TcTable 'teamsSettings' -Append @(ConvertTo-TcSettingRow (& "Get-$k" -ErrorAction Stop) $settingKinds[$k]) }
                }
                $types = 'TeamsMeetingPolicy', 'TeamsMessagingPolicy', 'TeamsAppSetupPolicy', 'TeamsAppPermissionPolicy', 'TeamsChannelsPolicy', 'TeamsUpdateManagementPolicy', 'TeamsEventsPolicy',
                'TeamsFeedbackPolicy', 'TeamsFilesPolicy', 'TeamsMobilityPolicy', 'TeamsMeetingTemplatePermissionPolicy', 'TeamsEnhancedEncryptionPolicy', 'ExternalAccessPolicy',
                'TeamsCallingPolicy', 'TeamsCallParkPolicy', 'TeamsEmergencyCallingPolicy', 'TeamsEmergencyCallRoutingPolicy', 'TeamsIPPhonePolicy', 'TeamsVoiceApplicationsPolicy',
                'TeamsComplianceRecordingPolicy', 'TeamsSharedCallingRoutingPolicy', 'TeamsShiftsPolicy', 'TeamsVdiPolicy', 'OnlineVoicemailPolicy', 'CallingLineIdentity'
                $preset = '^(Global|Tag:(Default|AllOn|AllOff|RestrictedAnonymousAccess|RestrictedAnonymousNoRecording|RestrictedAnonymousNoRecordingIgnoringSearch|Kiosk|Firstline.*|FirstLine.*|Education_.*|PrivateMeetingAllowed|AllowCalling.*|DisallowCalling|PreventForwardingtoPhone|PreventTollBypass|Restricted.*|OrgWideDefault|.*_Default))$'
                foreach ($t in $types) {
                    if (-not (Get-Command "Get-Cs$t" -ErrorAction SilentlyContinue)) { continue }
                    Invoke-TcCollectorPart "$t policies" {
                        foreach ($p in @(& "Get-Cs$t" -ErrorAction Stop)) {
                            $id = [string](Get-TcProperty $p 'Identity')
                            Add-TcTable 'teamsPolicies' -Append @([ordered]@{
                                    'Type'        = $t
                                    'Identity'    = $id
                                    'Custom'      = ($id -notmatch $preset)
                                    'Description' = (Limit-TcText ([string](Get-TcSafeProperty $p 'Description')) 200)
                                })
                            if ($id -eq 'Global') { Add-TcTable 'teamsSettings' -Append @(ConvertTo-TcSettingRow $p "Global policy $t") }
                        }
                    }
                }
                Invoke-TcCollectorPart 'Organization Teams apps (Graph)' {
                    Connect-TcTenant -Role $script:TcCurrentTenant['role']
                    Add-TcTable 'teamsApps' @(foreach ($a in Get-TcGraphList "v1.0/appCatalogs/teamsApps?`$filter=distributionMethod eq 'organization'&`$expand=appDefinitions") {
                            $d = @((Get-TcProperty $a 'appDefinitions')) | Select-Object -Last 1
                            [ordered]@{
                                'Name'         = (Get-TcProperty $a 'displayName')
                                'Version'      = (Get-TcProperty $d 'version')
                                'Publishing'   = (Get-TcProperty $d 'publishingState')
                                'Distribution' = (Get-TcProperty $a 'distributionMethod')
                            }
                        })
                }
                Invoke-TcCollectorPart 'Teams devices (phones, rooms)' {
                    Connect-TcTenant -Role $script:TcCurrentTenant['role']
                    Add-TcTable 'teamsDevices' @(foreach ($d in Get-TcGraphList 'beta/teamwork/devices') {
                            [ordered]@{
                                'Type'     = (Get-TcProperty $d 'deviceType')
                                'Model'    = ('{0} {1}' -f (Get-TcProperty (Get-TcProperty $d 'hardwareDetail') 'manufacturer'), (Get-TcProperty (Get-TcProperty $d 'hardwareDetail') 'model')).Trim()
                                'User'     = (Get-TcProperty (Get-TcProperty $d 'currentUser') 'displayName')
                                'State'    = (Get-TcProperty $d 'healthStatus')
                                'Activity' = (Get-TcProperty $d 'activityState')
                            }
                        })
                }
            }
        }

        @{
            Id       = 'TMS-04'
            Workload = 'Teams'
            Title    = 'Teams users, voice and assigned policies'
            Service  = 'Teams'
            Collect  = {
                $p = @{ ErrorAction = 'Stop' }
                if ((Get-TcProperty (Get-Command Get-CsOnlineUser) 'Parameters').ContainsKey('ResultSize')) { $p['ResultSize'] = 100000 }
                $properties = 'TeamsMeetingPolicy', 'TeamsMessagingPolicy', 'TeamsAppSetupPolicy', 'TeamsAppPermissionPolicy', 'TeamsChannelsPolicy', 'TeamsUpdateManagementPolicy', 'TeamsEventsPolicy',
                'ExternalAccessPolicy', 'TeamsCallingPolicy', 'TeamsCallParkPolicy', 'TeamsEmergencyCallingPolicy', 'TeamsEmergencyCallRoutingPolicy', 'TeamsIPPhonePolicy',
                'TeamsVoiceApplicationsPolicy', 'TeamsComplianceRecordingPolicy', 'OnlineVoicemailPolicy', 'CallingLineIdentity', 'OnlineVoiceRoutingPolicy', 'TenantDialPlan', 'TeamsMobilityPolicy'
                Add-TcTable 'teamsUsers' @(foreach ($u in @(Get-CsOnlineUser @p)) {
                        $policies = @(foreach ($k in $properties) { $v = [string](Get-TcSafeProperty $u $k); if ($v) { '{0}={1}' -f $k, $v } })
                        [ordered]@{
                            'UPN'              = (Get-TcProperty $u 'UserPrincipalName')
                            'Name'             = (Get-TcProperty $u 'DisplayName')
                            'Enabled'          = [bool](Get-TcSafeProperty $u 'AccountEnabled' $true)
                            'Enterprise Voice' = [bool](Get-TcSafeProperty $u 'EnterpriseVoiceEnabled' $false)
                            'Number'           = (([string](Get-TcSafeProperty $u 'LineUri')) -replace '^tel:', '')
                            'Features'         = (Format-TcValue (Get-TcSafeProperty $u 'FeatureTypes'))
                            'Teams mode'       = [string](Get-TcSafeProperty $u 'TeamsUpgradeEffectiveMode')
                            'Policies'         = ($policies -join '; ')
                            'ObjectId'         = [string](Get-TcSafeProperty $u 'Identity')
                        }
                    })
            }
        }

    )
}