private static ActionAndStrategy GetClaimSetSpecificActionAndStrategy(ActionAndStrategy pair, string claimSetName) { if (pair == null) { return(null); } if (!pair.ExplicitActionAndStrategyByClaimSetName.ContainsKey(claimSetName)) { return(null); } return(pair.ExplicitActionAndStrategyByClaimSetName[claimSetName]); }
//private static void ClearOutputFolder() //{ // if (Directory.Exists(BaseOutputFolder)) // { // Directory // .GetFiles(BaseOutputFolder) // .ToList() // .ForEach(File.Delete); // } //} private static AdjacencyGraph <Resource, Edge <Resource> > LoadAuthorizationMetadataGraph( string connectionString, out List <string> claimSetNames) { var resourceGraph = new AdjacencyGraph <Resource, Edge <Resource> >(); const string providerName = "System.Data.SqlClient"; string metadataSql = @" select rc.ResourceClaimId, rc.ResourceName, prc.ResourceName as ParentResourceName, a.ActionName, as_.AuthorizationStrategyName from dbo.ResourceClaims rc left join dbo.ResourceClaims prc ON rc.ParentResourceClaimId = prc.ResourceClaimId left join dbo.ResourceClaimAuthorizationMetadatas rcas ON rc.ResourceClaimId = rcas.ResourceClaim_ResourceClaimId left join dbo.AuthorizationStrategies as_ ON rcas.AuthorizationStrategy_AuthorizationStrategyId = as_.AuthorizationStrategyId left join dbo.Actions a ON rcas.Action_ActionId = a.ActionId order by rc.ResourceName, a.ActionId, as_.AuthorizationStrategyName"; string claimSetSql = @" select ClaimSetId, ClaimSetName, ResourceName, ActionName, null As StrategyName from dbo.ClaimSets cs left join dbo.ClaimSetResourceClaims csrc ON cs.ClaimSetId = csrc.ClaimSet_ClaimSetId left join dbo.Actions a ON csrc.Action_ActionId = a.ActionId left join dbo.ResourceClaims rc ON csrc.ResourceClaim_ResourceClaimId = rc.ResourceClaimId order by ClaimSetName, ResourceName, Action_ActionId "; var metadataEdges = GetResourceClaimMetadata(connectionString, providerName, metadataSql); var claimsetResourceActions = GetClaimSetMetadata(connectionString, providerName, claimSetSql); var distinctMetadataEdges = (from e in metadataEdges select new { e.ResourceName, e.ParentResourceName } ).Distinct(); // First process the segments into the graph foreach (var metadataEdge in distinctMetadataEdges) { if (string.IsNullOrEmpty(metadataEdge.ParentResourceName)) { resourceGraph.AddVertex(new Resource(metadataEdge.ResourceName)); } else { resourceGraph.AddVerticesAndEdge( new Edge <Resource>(new Resource(metadataEdge.ParentResourceName), new Resource(metadataEdge.ResourceName))); } } // Now augment the vertices with authorization strategies and actions var edgesGroupedByResoureName = from e in metadataEdges where e.ActionName != null group e by e.ResourceName into g select new { ResourceName = g.Key, Actions = g.Select( x => new { x.ActionName, StrategyName = x.AuthorizationStrategyName }) }; // Augment each vertex with the actions/strategies foreach (var edge in edgesGroupedByResoureName) { var vertex = resourceGraph.Vertices.Single(x => x.Name == edge.ResourceName); vertex.ActionAndStrategyPairs.AddRange( from e in edge.Actions select new ActionAndStrategy { ActionName = e.ActionName, AuthorizationStrategy = e.StrategyName }); } // Process claim set data var claimsetMetadata = (from c in claimsetResourceActions group c by c.ClaimSetName into mainGroup select new { ClaimSetName = mainGroup.Key, Resources = (from mg in mainGroup group mg by mg.ResourceName into subGroup select new { ResourceName = subGroup.Key, ActionStrategy = (from sg in subGroup where !string.IsNullOrEmpty(sg.ActionName) select new { sg.ActionName, sg.StrategyName }) .ToList() }).ToList() }).ToList(); claimSetNames = claimsetMetadata.Select(x => x.ClaimSetName).ToList(); foreach (var claimsetItem in claimsetMetadata) { string claimSetName = claimsetItem.ClaimSetName; foreach (var resourceItem in claimsetItem.Resources) { var resourceVertex = resourceGraph.Vertices.Single(x => x.Name == resourceItem.ResourceName); foreach (var actionStrategyItem in resourceItem.ActionStrategy) { var actionVertex = resourceVertex.ActionAndStrategyPairs.SingleOrDefault(x => x.ActionName == actionStrategyItem.ActionName); // If action vertex doesn't yet exist in the graph, create it implicitly now if (actionVertex == null) { var newAction = new ActionAndStrategy { ActionName = actionStrategyItem.ActionName }; resourceVertex.ActionAndStrategyPairs.Add(newAction); actionVertex = newAction; } // Make note that we've got metadata explicitly assigning this action actionVertex.ExplicitActionAndStrategyByClaimSetName[claimSetName] = new ActionAndStrategy { ActionName = actionStrategyItem.ActionName, AuthorizationStrategy = actionStrategyItem.StrategyName }; } } // Now process each of the root nodes from top to bottom to determine effective permissions at each vertex foreach (var rootVertex in GetRootNodes(resourceGraph)) { SetParentReferences(null, rootVertex, resourceGraph); } } return(resourceGraph); }
private static AdjacencyGraph <Resource, Edge <Resource> > LoadAuthorizationMetadataGraph( string connectionString, out List <string> claimSetNames) { var resourceGraph = new AdjacencyGraph <Resource, Edge <Resource> >(); var calimsSql = @" SELECT rc.ClaimName, rc.DisplayName, prc.ClaimName AS ParentClaimName, prc.DisplayName AS ParentDisplayName, a.ActionName, as_.AuthorizationStrategyName FROM dbo.ResourceClaims rc LEFT JOIN dbo.ResourceClaims prc ON rc.ParentResourceClaimId = prc.ResourceClaimId LEFT JOIN dbo.ResourceClaimActions rca ON rc.ResourceClaimId = rca.ResourceClaimId LEFT JOIN dbo.ResourceClaimActionAuthorizationStrategies rcaas ON rca.ResourceClaimActionId = rcaas.ResourceClaimActionId LEFT JOIN dbo.AuthorizationStrategies as_ ON rcaas.AuthorizationStrategyId = as_.AuthorizationStrategyId LEFT JOIN dbo.Actions a ON rca.ActionId = a.ActionId ORDER BY rc.DisplayName, a.ActionId, as_.AuthorizationStrategyName "; var claimSetsSql = @" SELECT ClaimSetName, ClaimName, ActionName, AuthorizationStrategyName AS StrategyName FROM dbo.ClaimSets cs LEFT JOIN dbo.ClaimSetResourceClaimActions csrca ON cs.ClaimSetId = csrca.ClaimSetId LEFT JOIN dbo.ClaimSetResourceClaimActionAuthorizationStrategyOverrides csrcaaso ON csrca.ClaimSetResourceClaimActionId = csrcaaso.ClaimSetResourceClaimActionId LEFT JOIN dbo.AuthorizationStrategies as_ ON csrcaaso.AuthorizationStrategyId = as_.AuthorizationStrategyId LEFT JOIN dbo.Actions a ON csrca.ActionId = a.ActionId LEFT JOIN dbo.ResourceClaims rc ON csrca.ResourceClaimId = rc.ResourceClaimId ORDER BY ClaimSetName, rc.DisplayName, a.ActionId "; using var conn = new SqlConnection(connectionString); var claims = conn.Query <ResourceSegmentData>(calimsSql); var claimSets = conn.Query <ClaimsetResourceActionData>(claimSetsSql); // Ignore ClaimSets that don't have ClaimSetResourceClaimActions ('Ownership Based Test', for example) claimSets = claimSets .Where(x => x.ClaimName != null) .ToList(); var uniqueEdges = claims .GroupBy(e => (e.ClaimName, e.ParentClaimName)) .Select(grp => grp.First()); claimNamesToDisplayNames = uniqueEdges.ToDictionary(e => e.ClaimName, e => e.DisplayName); // First add empty vertices and edges to the graph, each claim is a vertex foreach (var edge in uniqueEdges) { var vertex = GetOrAddVertex(resourceGraph, edge.ClaimName); if (!string.IsNullOrEmpty(edge.ParentClaimName)) { var parentVertex = GetOrAddVertex(resourceGraph, edge.ParentClaimName); resourceGraph.AddEdge(new Edge <Resource>(parentVertex, vertex)); } } var edgesGroupedByClaim = claims .Where(resource => resource.ActionName != null) .GroupBy(resource => resource.ClaimName) .Select(resourcesByClaim => new { ClaimName = resourcesByClaim.Key, Actions = resourcesByClaim .GroupBy(resource => resource.ActionName) .Select(resourcesByAction => new { Name = resourcesByAction.Key, Strategies = resourcesByAction.Select(resource => resource.AuthorizationStrategyName).ToHashSet() }) }); // Now augment the vertices with authorization strategies and actions foreach (var edge in edgesGroupedByClaim) { var vertex = resourceGraph.Vertices.Single(x => x.ClaimName == edge.ClaimName); vertex.ActionAndStrategyPairs.AddRange( edge.Actions.Select(action => new ActionAndStrategy { ActionName = action.Name, AuthorizationStrategy = action.Strategies }) ); } var claimSetsGroupedByName = claimSets .GroupBy(csra => csra.ClaimSetName) .Select(csrasByClaimSet => new { ClaimSetName = csrasByClaimSet.Key, Resources = csrasByClaimSet .GroupBy(csra => csra.ClaimName) .Select(csrasByClaim => new { ClaimName = csrasByClaim.Key, ActionStrategy = csrasByClaim .Where(csra => !string.IsNullOrEmpty(csra.ActionName)) .Select(csra => new { csra.ActionName, csra.StrategyName }) .ToList() }) .ToList() }) .ToList(); claimSetNames = claimSetsGroupedByName.Select(x => x.ClaimSetName).ToList(); // Now augment the vertices with claimSet overrides foreach (var claimSet in claimSetsGroupedByName) { var claimSetName = claimSet.ClaimSetName; foreach (var resource in claimSet.Resources) { var vertex = resourceGraph.Vertices.Single(x => x.ClaimName == resource.ClaimName); foreach (var actionStrategy in resource.ActionStrategy) { var actionAndStrategyPair = vertex.ActionAndStrategyPairs.SingleOrDefault(x => x.ActionName == actionStrategy.ActionName); if (actionAndStrategyPair == null) { // There are no ActionAndStrategyPairs because the resource doesn't have explicit metadata, // but it has an override so add the ActionAndStrategyPair now var newActionAndStrategyPair = new ActionAndStrategy { ActionName = actionStrategy.ActionName // AuthorizationStrategy stays null since it only stores metadata, // overrides go to StrategyOverridesByClaimSetName }; vertex.ActionAndStrategyPairs.Add(newActionAndStrategyPair); actionAndStrategyPair = newActionAndStrategyPair; } // Make note that we've got an override explicitly assigned if (!actionAndStrategyPair.StrategyOverridesByClaimSetName.ContainsKey(claimSetName)) { actionAndStrategyPair.StrategyOverridesByClaimSetName.Add(claimSetName, new HashSet <string>()); } if (actionStrategy.StrategyName != null) { actionAndStrategyPair.StrategyOverridesByClaimSetName[claimSetName].Add(actionStrategy.StrategyName); } } } // Now process each of the root nodes from top to bottom to determine effective permissions at each vertex foreach (var rootVertex in GetRootNodes(resourceGraph)) { SetParentReferences(null, rootVertex, resourceGraph); } } return(resourceGraph); }