![]() |
|
|
By: Ray Barley | Read Comments (7) | Print Ray is a Principal Architect at RDA Corporation and a MSSQLTips.com BI Expert. Related Tips: More |
|
Problem
I have a requirement to implement a custom security scheme where roles and the user's place in the organization hierarchy are used to determine which customers a user can access. In particular the requirements are that a sales person can only access their customers and any other role can access any customer in their level of the organization hierarchy and below. We have a simple hierarchy that is made up of regions and offices. Can you provide us with an example of how to do this?
Solution
Based on your requirements we can design a solution that leverages a parent-child hierarchy to determine what customers a user can access. Our goal is to create a table that we can query that will return the list of customers that a user can access based on his role and level in the organization hierarchy. In this tip we will walk through the following steps to achieve our goal:
Create the CustomerHierarchy Table
We will use the following table to define the organization hierarchy, user roles, and customers:
CREATE TABLE [dbo].[CustomerHierarchy] ( [HierarchyKey] [int] IDENTITY(1,1) NOT NULL, [HierarchyType] [varchar](50) NOT NULL, [Description] [varchar](50) NOT NULL, [UserLogin] [varchar](50) NULL, [RoleName] [varchar](50) NULL, [CustomerKey] [int] NULL, [ParentHierarchyKey] [int] NULL ) ALTER TABLE [dbo].[CustomerHierarchy] ADD CONSTRAINT [PK_CustomerHierarchy] PRIMARY KEY CLUSTERED ([HierarchyKey] ASC) ALTER TABLE [dbo].[CustomerHierarchy] ADD CONSTRAINT [FK_CustomerHierarchy] FOREIGN KEY ([ParentHierarchyKey]) REFERENCES [dbo].[CustomerHierarchy] ([HierarchyKey]) ALTER TABLE [dbo].[CustomerHierarchy] ADD CONSTRAINT [FK_CustomerHierarchy_Customer] FOREIGN KEY ([CustomerKey]) REFERENCES [dbo].[Customer] ([CustomerKey]) |
The following are the main points about the above script:
Populate the CustomerHierarchy Table
Let's manually populate the CustomerHierarchy table with some sample data so that we can execute some queries to show which customers a particular user can access. The following T-SQL command inserts a row as the top level of the hierarchy:
INSERT [dbo].[CustomerHierarchy] ( [HierarchyType] , [Description] ) VALUES ( 'ROOT' , 'CUSTOMER HIERARCHY' ) |
Add regions by specifying a ParentHierarchyKey value of 1 which is the HierarchyKey value of the top level of the hierarchy:
INSERT [dbo].[CustomerHierarchy] ( [HierarchyType] , [Description] , [ParentHierarchyKey] ) SELECT 'REGION', 'RED', 1 UNION ALL SELECT 'REGION', 'WHITE', 1 UNION ALL SELECT 'REGION', 'BLUE', 1 |
Add offices to each region by specifying a ParentHierarchyKey value which is the HierarchyKey value of its region:
INSERT [dbo].[CustomerHierarchy] ( [HierarchyType] , [Description] , [ParentHierarchyKey] ) SELECT 'OFFICE', 'Pittsburgh, PA', 2 UNION ALL SELECT 'OFFICE', 'New York, NY', 2 UNION ALL SELECT 'OFFICE', 'Chicago, IL', 3 UNION ALL SELECT 'OFFICE', 'St. Louis, MO', 3 UNION ALL SELECT 'OFFICE', 'Dallas, TX', 4 UNION ALL SELECT 'OFFICE', 'New Orleans, LA', 4 |
Add user roles to each region by specifying a ParentHierarchyKey value which is the HierarchyKey value of its region:
INSERT [dbo].[CustomerHierarchy] ( [HierarchyType] , [Description] , [UserLogin] , [RoleName] , [ParentHierarchyKey] ) SELECT 'ROLE', 'John Smith', 'DOMAIN\jsmith', 'MANAGER', 2 UNION ALL SELECT 'ROLE', 'Mark Jones', 'DOMAIN\mjones', 'MANAGER', 3 UNION ALL SELECT 'ROLE', 'Will Thomas', 'DOMAIN\wthomas', 'MANAGER', 4 |
Add user roles to an office by specifying a ParentHierarchyKey value which is the HierarchyKey value of its office:
INSERT [dbo].[CustomerHierarchy] ( [HierarchyType] , [Description] , [UserLogin] , [RoleName] , [ParentHierarchyKey] ) SELECT 'ROLE', 'Tim Willis', 'DOMAIN\twillis', 'ASSOCIATE', 6 UNION ALL SELECT 'ROLE', 'Ron Lewis', 'DOMAIN\rlewis', 'SALES', 6 UNION ALL SELECT 'ROLE', 'Bill Miller', 'DOMAIN\bmiller', 'SALES', 6 |
Connect customers to their sales person by specifying a ParentHierarchyKey value which is the HierarchyKey value of the sales person:
INSERT [dbo].[CustomerHierarchy] ( [HierarchyType] , [Description] , [CustomerKey] , [ParentHierarchyKey] ) SELECT 'CUSTOMER', 'A Bike Store', 1, 15 UNION ALL SELECT 'CUSTOMER', 'Progressive Sports', 2, 15 UNION ALL SELECT 'CUSTOMER', 'Advanced Bike Components', 3, 16 UNION ALL SELECT 'CUSTOMER', 'Modular Cycle Systems', 4, 16 |
After running the T-SQL commands above, the following is the result set of SELECT * FROM dbo.CustomerHierarchy:
The above result set represents a parent-child hierarchy where each row's ParentHierarchyKey specifies the HierarchyKey of its parent and:
Query the CustomerHierarchy Table
We need to create queries to satisfy the following business rules:
Here is our first query that returns the list of customers that are directly connected to a user in the SALES role:
SELECT c.CustomerKey FROM dbo.CustomerHierarchy p JOIN dbo.CustomerHierarchy c ON c.ParentHierarchyKey = p.HierarchyKey WHERE p.UserLogin = 'DOMAIN\rlewis' AND p.RoleName = 'SALES' |
The following is the result set from the above query:
The following are the main points about the above query:
Here is our second query that returns the list of customers that are either in the same level of the hierarchy or below based on the level of our user role:
; WITH customer_cte AS (
SELECT p.*
FROM dbo.CustomerHierarchy c
JOIN dbo.CustomerHierarchy p
ON p.HierarchyKey = c.ParentHierarchyKey
WHERE c.UserLogin = 'DOMAIN\jsmith'
AND c.RoleName NOT IN ('SALES')
UNION ALL
SELECT c.*
FROM customer_cte p
JOIN dbo.CustomerHierarchy c
ON c.ParentHierarchyKey = p.HierarchyKey
)
SELECT CustomerKey FROM customer_cte
WHERE HierarchyType = 'CUSTOMER'
|
The following is the result set from the above query:
The following are the main points about the above query:
Next Steps
| Share: | Share | Tweet |
|
![]() |
|
|
Free SQL Server Learning |
| Tuesday, February 16, 2010 - 7:53:44 PM - raybarley |
|
| Thanks for the tip. Now that you mention it I remember reading about that in your Trees and Hierarchies book so I will give it a try. | |
| Thursday, January 26, 2012 - 9:36:32 AM - Ray Barley |
|
|
No. I got a little bogged down with the MDX expressions that you need to make it work. I have a tip that is part of the solution: http://www.mssqltips.com/sqlservertip/1773/how-to-enable-user-defined-hierarchies-in-sql-server-analysis-services-ssas/ which lets you create user-defined hierarchies. This shows how to build user-defined hierarchies which could be leveraged to provide the data then you would need to set security such that only certain people can see certain hierarchies. |
|
| Friday, January 27, 2012 - 10:06:58 AM - Ray Barley |
|
|
I did do a related tip: http://www.mssqltips.com/sqlservertip/1844/sql-server-analysis-services-ssas-dimension-security-stored-procedures In that one I call out to .NET code from SSAS to security trim a dimension. Still not what I really want but works well in some instances. |
|
| Wednesday, February 01, 2012 - 7:27:36 AM - Tom |
|
| Thank you Ray. I will certainly read the tips you mention. | |
|
privacy | disclaimer | copyright | advertise | about authors | contribute | feedback | giveaways | user groups Some names and products listed are the registered trademarks of their respective owners. Edgewood Solutions LLC | MSSharePointTips.com | MSSQLTips.com |