/*
Find deployed runtime attributes with security classifications that should
exercise LMXProxy WriteSecured / WriteSecured2 paths.

Connection:
  sqlcmd -S localhost -d ZB -E -i analysis/sql/select_secured_write_candidates.sql
*/
SET NOCOUNT ON;

;WITH deployed_package_chain AS (
    SELECT
        g.gobject_id,
        p.package_id,
        p.derived_from_package_id,
        0 AS depth
    FROM gobject g
    INNER JOIN package p
        ON p.package_id = g.deployed_package_id
    WHERE g.is_template = 0
        AND g.deployed_package_id <> 0
    UNION ALL
    SELECT
        dpc.gobject_id,
        p.package_id,
        p.derived_from_package_id,
        dpc.depth + 1
    FROM deployed_package_chain dpc
    INNER JOIN package p
        ON p.package_id = dpc.derived_from_package_id
    WHERE dpc.derived_from_package_id <> 0
        AND dpc.depth < 10
),
ranked_dynamic AS (
    SELECT
        dpc.gobject_id,
        g.tag_name,
        CAST('' AS nvarchar(255)) AS primitive_name,
        da.attribute_name,
        g.tag_name + '.' + da.attribute_name
            + CASE WHEN da.is_array = 1 THEN '[]' ELSE '' END AS full_tag_reference,
        da.mx_data_type,
        dt.description AS data_type_name,
        da.is_array,
        CASE WHEN da.is_array = 1
             THEN CONVERT(int, CONVERT(varbinary(2),
                  SUBSTRING(da.mx_value, 15, 2) + SUBSTRING(da.mx_value, 13, 2), 2))
             ELSE NULL
        END AS array_dimension,
        da.mx_attribute_category,
        da.security_classification,
        CAST('dynamic' AS varchar(16)) AS attribute_source,
        ROW_NUMBER() OVER (
            PARTITION BY dpc.gobject_id, da.attribute_name
            ORDER BY dpc.depth
        ) AS rn
    FROM deployed_package_chain dpc
    INNER JOIN dynamic_attribute da
        ON da.package_id = dpc.package_id
    INNER JOIN gobject g
        ON g.gobject_id = dpc.gobject_id
    INNER JOIN template_definition td
        ON td.template_definition_id = g.template_definition_id
    LEFT JOIN data_type dt
        ON dt.mx_data_type = da.mx_data_type
    WHERE td.category_id IN (1, 3, 4, 10, 11, 13, 17, 24, 26)
        AND da.attribute_name NOT LIKE '[_]%'
        AND da.attribute_name NOT LIKE '%.Description'
        AND da.mx_attribute_category IN (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 24)
),
all_attributes AS (
    SELECT
        g.gobject_id,
        g.tag_name,
        pi.primitive_name,
        ad.attribute_name,
        CASE WHEN pi.primitive_name = ''
             THEN g.tag_name + '.' + ad.attribute_name
             ELSE g.tag_name + '.' + pi.primitive_name + '.' + ad.attribute_name
        END + CASE WHEN ad.is_array = 1 THEN '[]' ELSE '' END AS full_tag_reference,
        ad.mx_data_type,
        dt.description AS data_type_name,
        ad.is_array,
        CASE WHEN ad.is_array = 1
             THEN CONVERT(int, CONVERT(varbinary(2),
                  SUBSTRING(ad.mx_value, 15, 2) + SUBSTRING(ad.mx_value, 13, 2), 2))
             ELSE NULL
        END AS array_dimension,
        ad.mx_attribute_category,
        ad.security_classification,
        CAST('primitive' AS varchar(16)) AS attribute_source
    FROM gobject g
    INNER JOIN instance i
        ON i.gobject_id = g.gobject_id
    INNER JOIN template_definition td
        ON td.template_definition_id = g.template_definition_id
        AND td.runtime_clsid <> '{00000000-0000-0000-0000-000000000000}'
    INNER JOIN package p
        ON p.package_id = g.deployed_package_id
    INNER JOIN primitive_instance pi
        ON pi.package_id = p.package_id
        AND pi.property_bitmask & 0x10 <> 0x10
    INNER JOIN attribute_definition ad
        ON ad.primitive_definition_id = pi.primitive_definition_id
        AND ad.attribute_name NOT LIKE '[_]%'
        AND ad.mx_attribute_category IN (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 24)
    LEFT JOIN data_type dt
        ON dt.mx_data_type = ad.mx_data_type
    WHERE td.category_id IN (1, 3, 4, 10, 11, 13, 17, 24, 26)
        AND g.is_template = 0
        AND g.deployed_package_id <> 0

    UNION ALL

    SELECT
        gobject_id,
        tag_name,
        primitive_name,
        attribute_name,
        full_tag_reference,
        mx_data_type,
        data_type_name,
        is_array,
        array_dimension,
        mx_attribute_category,
        security_classification,
        attribute_source
    FROM ranked_dynamic
    WHERE rn = 1
)
SELECT TOP (100)
    full_tag_reference,
    data_type_name,
    mx_data_type,
    is_array,
    array_dimension,
    security_classification,
    CASE security_classification
        WHEN 2 THEN 'SecuredWrite'
        WHEN 3 THEN 'VerifiedWrite'
        ELSE 'Other'
    END AS security_name,
    mx_attribute_category,
    attribute_source
FROM all_attributes
WHERE security_classification IN (2, 3)
    AND mx_data_type IN (1, 2, 3, 4, 5, 6, 7)
ORDER BY
    CASE WHEN tag_name LIKE 'Test%' OR tag_name LIKE '%Test%' THEN 0 ELSE 1 END,
    security_classification,
    is_array,
    full_tag_reference
OPTION (MAXRECURSION 20);
