modules/Azure/Discovery/Public/Save-CIEMAzureEffectiveRoleAssignment.ps1

function Save-CIEMAzureEffectiveRoleAssignment {
    [CmdletBinding(DefaultParameterSetName = 'ByProperties')]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Upsert operation for bulk data')]
    param(
        [Parameter(Mandatory, ParameterSetName = 'ByProperties')]
        [string]$PrincipalId,

        [Parameter(Mandatory, ParameterSetName = 'ByProperties')]
        [string]$PrincipalType,

        [Parameter(ParameterSetName = 'ByProperties')]
        [string]$PrincipalDisplayName,

        [Parameter(Mandatory, ParameterSetName = 'ByProperties')]
        [string]$OriginalPrincipalId,

        [Parameter(Mandatory, ParameterSetName = 'ByProperties')]
        [string]$OriginalPrincipalType,

        [Parameter(Mandatory, ParameterSetName = 'ByProperties')]
        [string]$RoleDefinitionId,

        [Parameter(ParameterSetName = 'ByProperties')]
        [string]$RoleName,

        [Parameter(Mandatory, ParameterSetName = 'ByProperties')]
        [string]$Scope,

        [Parameter(ParameterSetName = 'ByProperties')]
        [string]$PermissionsJson,

        [Parameter(Mandatory, ParameterSetName = 'ByProperties')]
        [string]$ComputedAt,

        [Parameter()]
        $Connection,

        [Parameter(Mandatory, ParameterSetName = 'InputObject', ValueFromPipeline)]
        [PSObject[]]$InputObject
    )

    begin {
        $items = [System.Collections.Generic.List[object]]::new()
    }

    process {
        if ($PSCmdlet.ParameterSetName -eq 'InputObject') {
            foreach ($item in $InputObject) {
                $items.Add([pscustomobject]@{
                    PrincipalId = $item.PrincipalId
                    PrincipalType = $item.PrincipalType
                    PrincipalDisplayName = $item.PrincipalDisplayName
                    OriginalPrincipalId = $item.OriginalPrincipalId
                    OriginalPrincipalType = $item.OriginalPrincipalType
                    RoleDefinitionId = $item.RoleDefinitionId
                    RoleName = $item.RoleName
                    Scope = $item.Scope
                    PermissionsJson = $item.PermissionsJson
                    ComputedAt = $item.ComputedAt
                })
            }
            return
        }

        $items.Add([pscustomobject]@{
            PrincipalId = $PrincipalId
            PrincipalType = $PrincipalType
            PrincipalDisplayName = $PrincipalDisplayName
            OriginalPrincipalId = $OriginalPrincipalId
            OriginalPrincipalType = $OriginalPrincipalType
            RoleDefinitionId = $RoleDefinitionId
            RoleName = $RoleName
            Scope = $Scope
            PermissionsJson = $PermissionsJson
            ComputedAt = $ComputedAt
        })
    }

    end {
        if ($items.Count -eq 0) {
            return
        }

        $columns = @(
            'principal_id', 'principal_type', 'principal_display_name', 'original_principal_id', 'original_principal_type',
            'role_definition_id', 'role_name', 'scope', 'permissions_json', 'computed_at'
        )

        for ($offset = 0; $offset -lt $items.Count; $offset += $script:CIEMSqlBatchSize) {
            $remaining = $items.Count - $offset
            $chunkSize = [Math]::Min($script:CIEMSqlBatchSize, $remaining)
            $rows = @()
            $parameters = @{}

            for ($rowIndex = 0; $rowIndex -lt $chunkSize; $rowIndex++) {
                $item = $items[$offset + $rowIndex]
                $suffix = $rowIndex + 1
                $rows += "(@principal_id_$suffix, @principal_type_$suffix, @principal_display_name_$suffix, @original_principal_id_$suffix, @original_principal_type_$suffix, @role_definition_id_$suffix, @role_name_$suffix, @scope_$suffix, @permissions_json_$suffix, @computed_at_$suffix)"

                $parameters["principal_id_$suffix"] = $item.PrincipalId
                $parameters["principal_type_$suffix"] = $item.PrincipalType
                $parameters["principal_display_name_$suffix"] = $item.PrincipalDisplayName
                $parameters["original_principal_id_$suffix"] = $item.OriginalPrincipalId
                $parameters["original_principal_type_$suffix"] = $item.OriginalPrincipalType
                $parameters["role_definition_id_$suffix"] = $item.RoleDefinitionId
                $parameters["role_name_$suffix"] = $item.RoleName
                $parameters["scope_$suffix"] = $item.Scope
                $parameters["permissions_json_$suffix"] = $item.PermissionsJson
                $parameters["computed_at_$suffix"] = $item.ComputedAt
            }

            $sql = "INSERT OR REPLACE INTO azure_effective_role_assignments ($($columns -join ', ')) VALUES $($rows -join ', ')"
            if ($Connection) {
                Invoke-PSUSQLiteQuery -Connection $Connection -Query $sql -Parameters $parameters -AsNonQuery | Out-Null
            }
            else {
                Invoke-CIEMQuery -Query $sql -Parameters $parameters -AsNonQuery | Out-Null
            }
        }
    }
}