我会解释我的情况:
我有以下数据库表:
+----+----------+---------+------------+---------+---------------+-----------+---------+------+
| id | owner_id | user_id | group_mode | item_id | capability_id | from_date | to_date | deny |
+----+----------+---------+------------+---------+---------------+-----------+---------+------+
id和owner_id字段与此问题无关。
group_mode可以有3种模式:0表示单个用户,1表示如果项目正在为一组用户共享,或者2表示以团队方式共享。
拒绝字段可以为0或1.如果为1,则用户将无法执行任何需要此权限的操作。如果它为0,则用户将能够这样做。 “默认”值表示没有为此用户和对象分配权限,如果在分配了该item_id的表中找不到该用户,则表示该权限。
我已经设法从这个查询中收到了我想要的东西,但它是一个非常大的查询并且重复了代码,因为每次比较都是针对每个“用户模式”。
我想进行查询以获得对象的最严格权限。如果用户对某个对象具有权限1(编辑),但是他所属的组被拒绝此权限(1),则应该拒绝该结果,反之亦然。如果某个组具有该权限但用户已将其拒绝,则该权限将被拒绝。
此外,如果用户是该项目的所有者,则授予所有权限,即使它们未在表格中列出(我解释这一点,以便您理解我将要编写的查询)。
所有这些必须是如果NOW() - 今天 - 在日期范围内。因此,如果我们离开此范围,则从X到Y的拒绝许可不再被拒绝:设置为默认(就像它不存在一样)。
当它变得复杂时,如果用户没有任何权限集但是他所属的组或团队拥有它,则应用该权限。我的意思是:用户可能没有授予任何权限,但是他所属的组是,所以他已获得此权限(此处)。
这很简单,但最后很长。我所做的就是检查:
如果用户在此日期范围内对此对象有此权限,则只有当他所属的任何团体未在此日期范围内拒绝此任何团队时才被拒绝任何团队 或者,如果此用户所属的任何群组已在此范围内为此对象设置了此权限,仅在用户自己没有被拒绝时才拒绝他所属的任何团队 或者团队也一样。
SELECT ITEM_SELECT_TABLE_FIELDS
FROM ITEM_ORIGINAL_TABLE
WHERE deleted IS NULL
AND (user_id = 'USER_ID'
OR unique_id IN
(SELECT sh.item_id
FROM SHARED_ITEMS_TABLE sh
WHERE (sh.user_id = 'USER_ID'
AND sh.deny = 0
AND sh.capability_id != 0
AND sh.from_date < NOW()
AND (sh.to_date > NOW()
OR sh.to_date IS NULL)
AND sh.user_id NOT IN
(SELECT gr.user_id
FROM GROUPS_TABLE gr
WHERE group_id IN
(SELECT sh2.user_id
FROM SHARED_ITEMS_TABLE sh2
WHERE sh2.group_mode = 1
AND sh2.deny = 1
AND sh2.from_date < NOW()
AND (sh2.to_date > NOW()
OR sh2.to_date IS NULL)
AND sh2.capability_id = sh.capability_id
)
)
AND sh.user_id NOT IN
(SELECT tm1.user_id
FROM TEAMS_TABLE tm1
WHERE tm1.team_id IN (
SELECT sh8.user_id
FROM SHARED_ITEMS_TABLE sh8
WHERE sh8.group_mode = 1
AND sh8.deny = 1
AND sh8.from_date < NOW()
AND (sh8.to_date > NOW()
OR sh8.to_date IS NULL)
AND sh8.capability_id = sh.capability_id
)
)
)
OR
(sh.user_id IN
(SELECT grus2.group_id
FROM GROUPS_TABLE grus2
WHERE grus2.user_id = 'USER_ID'
AND grus2.user_id NOT IN
(SELECT sh3.user_id
FROM SHARED_ITEMS_TABLE sh3
WHERE sh3.group_mode = 0
AND sh3.deny = 1
AND sh3.from_date < NOW()
AND (sh3.to_date > NOW()
OR sh3.to_date IS NULL)
AND sh3.capability_id = sh.capability_id
AND sh3.user_id NOT IN
(SELECT grus3.group_id
FROM GROUPS_TABLE grus3
WHERE grus3.user_id IN
(SELECT sh5.user_id
FROM SHARED_ITEMS_TABLE sh5
WHERE sh5.group_mode = 0
AND sh5.deny = 1
AND sh5.from_date < NOW()
AND (sh5.to_date > NOW()
OR sh5.to_date IS NULL)
AND sh5.capability_id = sh.capability_id
)
)
)
AND grus2.user_id NOT IN
(SELECT tm3.user_id
FROM TEAMS_TABLE tm3
WHERE tm3.team_id IN (
SELECT sh9.user_id
FROM SHARED_ITEMS_TABLE sh9
WHERE sh9.group_mode = 2
AND sh9.deny = 1
AND sh9.from_date < NOW()
AND (sh9.to_date > NOW()
OR sh9.to_date IS NULL)
AND sh9.capability_id = sh.capability_id
)
)
)
AND sh.deny = 0
AND group_mode = 1
AND sh.from_date < NOW()
AND (sh.to_date > NOW()
OR sh.to_date IS NULL)
)
OR
(sh.user_id IN
(SELECT tm4.team_id
FROM TEAMS_TABLE tm4
WHERE tm4.user_id = 'USER_ID'
AND sh.deny = 0
AND group_mode = 2
AND sh.from_date < NOW()
AND (sh.to_date > NOW()
OR sh.to_date IS NULL)
AND sh.user_id NOT IN
(SELECT gr2.user_id
FROM GROUPS_TABLE gr2
WHERE gr2.group_id IN
(SELECT sh10.user_id
FROM SHARED_ITEMS_TABLE sh10
WHERE sh10.group_mode = 1
AND sh10.deny = 1
AND sh10.from_date < NOW()
AND (sh10.to_date > NOW()
OR sh10.to_date IS NULL)
AND sh10.capability_id = sh.capability_id
)
)
AND sh.user_id NOT IN
(SELECT grus7.group_id
FROM GROUPS_TABLE grus7
WHERE grus7.user_id IN
(SELECT sh11.user_id
FROM SHARED_ITEMS_TABLE sh11
WHERE sh11.group_mode = 0
AND sh11.deny = 1
AND sh11.from_date < NOW()
AND (sh11.to_date > NOW()
OR sh11.to_date IS NULL)
AND sh11.capability_id = sh.capability_id
)
)
)
)
)
) ORDER BY created_timestamp DESC
这是一个非常大的查询,如果我添加另一个group_mode(例如,我可能想在权限中添加一组组),我必须重写每个WHERE条件以添加新的条件。这是一个问题。
我知道必须通过某种方式来简化所有这些,因为每个WHERE条件中的代码都是相同的:只需确保用户(组,团队或用户本身)的任何相关性都没有被拒绝。
我不需要你把查询写给我。如果你能解释我怎么做一些递归的东西(如果可能的话,不用程序)来检查我之前说过的东西会很棒。
很抱歉这个大问题和我糟糕的“MySQL语言”。
非常感谢你的时间和答案!
答案 0 :(得分:0)
我认为如果对每种请求进行一次查询并使用PHP单独验证,可能会更简单。
例如,您有一个拒绝项,例如$ item对象的属性($item->deny
)。
如果$item->deny=1
且用户想要对此项目执行某些操作,他会找到:
if($item->deny==1)
{
$message = "You are not allowed";
echo $message;
}
else
{
//do whatever
}
只是一个例子,但你可以用各种要求做到这一点。