按用户访问权限过滤记录

时间:2014-01-16 14:20:44

标签: sql-server

我有一个遗留系统,它可以同时与多个数据库配合使用。假设他们是MASTER和SLAVE。

有用户组(层次结构)。每个组都有一个父组,父组可以拥有自己的父组等。

table MASTER.dbo.GROUPS: 
GROUP_ID
PARENTGROUP_ID
NAME

可以将用户分配到不同的组。

table MASTER.dbo.LK_GROUPS:
GROUP_ID
USER_ID

有实体,每个实体都有所有者(一对多)。

table SLAVE.dbo.ENTITY_OWNERSHIP
ENTITY_ID
USER_ID (column has a bad name because it is GROUP_ID)

任务: 编写查询/函数/存储过程以仅选择用户有权访问的实体。应该可以使用解决方案作为sql查询的一部分,我无法修改。此外,应该可以使用2种模式:

  1. 假设实体的所有者是S1集并且用户组是S2集,如果S1-S2 = 0,则可以访问实体。
  2. 假设实体的所有者是S1集并且用户组是S2集,如果S1与S2相交,则可以访问实体。 0
  3. 所以我写了一个函数fn_checkUserRights:

    create function fn_checkUserRights (@userId bigint, @entityId bigint, @compareMode int)
    returns int
    as
    begin
        declare @result int;
        declare @count int;
    
        if @compareMode = 1
            begin
    
                with groups_with_ancestors
                as (
                    select GROUP_ID, PARENTGROUP_ID, NAME
                    from MASTER.dbo.GROUPS as GROUPS
                    where 
                        GROUP_ID in (
                            select 
                                GROUP_ID
                            from 
                                MASTER.dbo.LK_GROUPS
                            where 
                                USER_ID = @userId
                        )
    
                    union all
    
                    select 
                        b.GROUP_ID, b.PARENTGROUP_ID, b.NAME
                    from 
                        groups_with_ancestors a
                        inner join MASTER.dbo.GROUPS b on b.GROUP_ID = a.PARENTGROUP_ID
                ) 
                select @count = count(*) from (
                    select
                        ENTITY_OWNERSHIP.USER_ID as OWNER_ID 
                    from 
                        SLAVE.dbo.ENTITY_OWNERSHIP as ENTITY_OWNERSHIP
                    where 
                        ENTITY_OWNERSHIP.ENTITY_ID = @entityId
    
                    except
    
                    select distinct GROUP_ID from groups_with_ancestors
    
                ) a
    
                if @count > 0
                    set @result = 0
                else
                    set @result = 1
            end
    
        else if @compareMode = 2
            begin
    
                with groups_with_ancestors
                as (
                    select GROUP_ID, PARENTGROUP_ID, NAME
                    from MASTER.dbo.GROUPS as GROUPS
                    where GROUP_ID in (
                            select 
                                GROUP_ID
                            from 
                                MASTER.dbo.LK_GROUPS
                            where 
                                USER_ID = @userId
                        )
    
                    union all
    
                    select 
                        b.GROUP_ID, b.PARENTGROUP_ID, b.NAME
                    from 
                        groups_with_ancestors a
                        inner join MASTER.dbo.GROUPS b on b.GROUP_ID = a.PARENTGROUP_ID
                ) 
                select @count = count(*) from (
                    select
                        ENTITY_OWNERSHIP.USER_ID as OWNER_ID 
                    from 
                        SLAVE.dbo.ENTITY_OWNERSHIP as ENTITY_OWNERSHIP
                    where 
                        ENTITY_OWNERSHIP.ENTITY_ID = @entityId
    
                    intersect
    
                    select distinct GROUP_ID from groups_with_ancestors
    
                ) a
    
                if @count > 0
                    set @result = 1
                else
                    set @result = 0
    
            end
    
    
        return @result;
    
    end;
    

    使用示例:

    select * 
    from 
        SLAVE.dbo.ENTITY_OWNERSHIP as owners
    where 
        MASTER.dbo.fn_checkUserRights(10010, owners.ENTITY_ID, 1) = 1
    

    但是有一些问题:

    1. 函数使用2个DB中的表:MASTER和SLAVE。他们的名字事先不知道。我不能将名称作为参数传递,因为函数不允许动态查询执行。如何解决这个问题?
    2. @ compareMode = 1和@ compareMode = 2的代码块几乎相同,将公共代码提取到变量或函数会很棒。你能推荐什么?

0 个答案:

没有答案