[英]Building access matrix based on parent=>child relationship of objects?
一些背景:
一个game
属于一个round
,
round
属于一个season
,
一个season
属于competition
competition
是无主的。
我们有八张桌子
名称=>列
`games` => `id`, `round_id`,
`rounds` => `id`, `season_id`,
`seasons` => `id`, `competition_id`,
`competitions` => `id`,
----
`user_game` => `user_id`, `game_id`,
`user_round` => `user_id`, `round_id`,
`user_season` => `user_id`, `season_id`,
`user_competition` => `user_id`, `competition_id`
因此,前四个表将不同部分链接在一起,
后四个表将用户链接到相应的部分。
一些虚拟数据,请注意,当第二个ID更改时,为了方便阅读,我将表格拆分了。
前四张桌子
/--GAMES--------------\ /--ROUNDS-------------\
| id | round_id | | id | season_id |
| 1 | 1 | | 1 | 1 |
| 2 | 1 | | 2 | 1 |
|----|----------------| | 3 | 1 |
| 3 | 2 | |----|----------------|
| 4 | 2 | | 4 | 2 |
|----|----------------| | 5 | 2 |
| 5 | 3 | | 6 | 2 |
| 6 | 3 | |----|----------------|
|----|----------------| | 7 | 3 |
| 7 | 4 | | 8 | 3 |
| 8 | 4 | | 9 | 3 |
|----|----------------| |----|----------------|
| 9 | 5 | | 10 | 4 |
| 10 | 5 | \---------------------/
|----|----------------|
| 11 | 6 | /--SEASONS------------\
| 12 | 6 | | id | competition_id |
|----|----------------| | 1 | 1 |
| 13 | 7 | | 2 | 1 |
| 14 | 7 | |----|----------------|
|----|----------------| | 3 | 2 |
| 15 | 8 | | 4 | 2 |
| 16 | 8 | \---------------------/
|----|----------------|
| 17 | 9 | /--COMPETITIONS-------\
| 18 | 9 | | id |
|----|----------------| | 1 |
| 19 | 10 | | 2 |
| 20 | 10 | \---------------------/
\---------------------/
接下来的四个表在下面的列表中得到了最好的解释
使用者:
user_game (user_id:1, game_id:1)
direct
进入游戏1 parent
访问权限 parent
访问权限 parent
对比赛1访问 user_round (user_id:2, round_id:1)
child
玩游戏1,2 direct
进入 parent
访问权限 parent
对比赛1访问 user_round (user_id:3, round_id:1)
direct
进入游戏2 user_game (user_id:3, game_id:13)
direct
进入游戏13 parent
访问权限 parent
访问权限 parent
对比赛2访问 因此,在获取上述三个用户的访问权限时,我想结束于这三个数组,请注意:
parent_access
:用户具有对子对象的访问权限(无论是哪个对象)
direct_access
:用户具有直接授予的完全访问权限
child access
:用户具有完全访问权限,而作为父对象(无论是哪个对象)的访问权限已被授予直接访问权限
用户1
$user1 = array(
'games' => array(
[1] => array(
'id' => 1,
'parent_access' => false,
'direct_access' => true,
'child_access' => false
)
),
'rounds' => array(
[1] => array(
'id' => 1,
'parent_access' => true,
'direct_access' => false,
'child_access' => false
)
),
'seasons' => array(
[1] => array(
'id' => 1,
'parent_access' => true,
'direct_access' => false,
'child_access' => false
),
),
'competitions' => array(
[1] => array(
'id' => 1,
'parent_access' => true,
'direct_access' => false,
'child_access' => false
),
)
);
用户2
$user2 = array(
'games' => array(
[1] => array(
'id' => 1,
'parent_access' => false,
'direct_access' => false,
'child_access' => true
),
[2] => array(
'id' => 2,
'parent_access' => false,
'direct_access' => false,
'child_access' => true
)
),
'rounds' => array(
[1] => array(
'id' => 1,
'parent_access' => false,
'direct_access' => true,
'child_access' => false
)
),
'seasons' => array(
[1] => array(
'id' => 1,
'parent_access' => true,
'direct_access' => false,
'child_access' => false
),
),
'competitions' => array(
[1] => array(
'id' => 1,
'parent_access' => true,
'direct_access' => false,
'child_access' => false
),
)
);
用户3
$user3 = array(
'games' => array(
[1] => array(
'id' => 1,
'parent_access' => false,
'direct_access' => false,
'child_access' => true
),
[2] => array(
'id' => 2,
'parent_access' => false,
'direct_access' => true,
'child_access' => true
),
[13] => array(
'id' => 13,
'parent_access' => false,
'direct_access' => true,
'child_access' => false
)
),
'rounds' => array(
[1] => array(
'id' => 1,
'parent_access' => false,
'direct_access' => true,
'child_access' => false
),
[7] => array(
'id' => 7,
'parent_access' => true,
'direct_access' => false,
'child_access' => false
)
),
'seasons' => array(
[1] => array(
'id' => 1,
'parent_access' => true,
'direct_access' => false,
'child_access' => false
),
[3] => array(
'id' => 3,
'parent_access' => true,
'direct_access' => false,
'child_access' => false
)
),
'competitions' => array(
[1] => array(
'id' => 1,
'parent_access' => true,
'direct_access' => false,
'child_access' => false
),
[2] => array(
'id' => 2,
'parent_access' => true,
'direct_access' => false,
'child_access' => false
)
)
);
结果略有不同,但这是发布在这里以显示我当前的工作,尽管我不满意,但它仍然可以作为答案。
所以,这是我当前的代码:像这样的行: $competitions = $this->competitions->disabled(true)->getAll();
在比赛表上运行查询并返回一个自定义对象,因此那里的内容有所不同,但是您应该能够通过代码确定它的作用。
您对此不满意的是,我们有18个foreach循环! 许多嵌套,所以这是18个重新运行的foreach循环! 谁能看到减少这种情况的方法?
public function access($user_id, $action = 'none')
{
$access = array(
'competitions' => array()
);
/* COMPETITIONS */
$competitions = $this->competitions->disabled(true)->getAll();
foreach ($competitions as $competition) {
$access['competitions'][$competition->data('id')] = array(
//'item' => $competition,
'type' => 'competition',
'id' => $competition->data('id'),
'child_access' => false,
'direct_access' => false,
'parent_access' => false,
'seasons' => array()
);
/* SEASONS */
$seasons = $competition->seasons(true);
foreach ($seasons as $season) {
$access['competitions'][$competition->data('id')]['seasons'][$season->data('id')] = array(
//'item' => $season,
'type' => 'season',
'id' => $season->data('id'),
'child_access' => false,
'direct_access' => false,
'parent_access' => false,
'rounds' => array()
);
/* ROUNDS */
$rounds = $season->rounds(true);
foreach ($rounds as $round) {
$access['competitions'][$competition->data('id')]['seasons'][$season->data('id')]['rounds'][$round->data('id')] = array(
//'item' => $round,
'type' => 'round',
'id' => $round->data('id'),
'child_access' => false,
'direct_access' => false,
'parent_access' => false,
'games' => array()
);
/* GAMES */
$games = $round->games(true);
foreach ($games as $game) {
//dump('$access["competitions"]['.$competition->data('id').']["seasons"]['.$season->data('id').']["rounds"]['.$round->data('id').']["games"]['.$game->data('id').']');
$access['competitions'][$competition->data('id')]['seasons'][$season->data('id')]['rounds'][$round->data('id')]['games'][$game->data('id')] = array(
//'item' => $game,
'type' => 'game',
'id' => $game->data('id'),
'child_access' => false,
'direct_access' => false,
'parent_access' => false
);
}
}
}
}
/* CHECK COMPETITIONS */
$competitions = $this->db->select('competition_id')->from('user_competition')->where('user_id', $user_id)->get();
foreach ($competitions->result() as $id) {
$id = $id->competition_id;
$access['competitions'][$id]['direct_access'] = true;
/* SEASONS */
foreach ($access['competitions'][$id]['seasons'] as &$season) {
$season['child_access'] = true;
/* ROUNDS */
foreach ($season['rounds'] as &$round) {
$round['child_access'] = true;
/* GAMES */
foreach ($round['games'] as &$game) {
$game['child_access'] = true;
unset($game);
}
unset($round);
}
unset($season);
}
}
/* CHECK SEASONS */
$seasons = $this->db->select('season_id')->from('user_season')->where('user_id', $user_id)->get();
foreach ($seasons->result() as $id) {
$id = $id->season_id;
$competition_id = $this->seasons->disabled(true)->get($id)->data('competition id');
$competition = $access['competitions'][$competition_id];
$competition['parent_access'] = true;
$season = $competition['seasons'][$id];
$season['direct_access'] = true;
/* ROUNDS */
foreach ($season['rounds'] as &$round) {
$round['child_access'] = true;
/* GAMES */
foreach ($round['games'] as &$game) {
$game['child_access'] = true;
unset($game);
}
unset($round);
}
}
/* CHECK ROUNDS */
$rounds = $this->db->select('round_id')->from('user_round')->where('user_id', $user_id)->get();
foreach ($rounds->result() as $id) {
$id = $id->round_id;
$round_obj = $this->rounds->disabled(true)->get($id);
$season_obj = $round_obj->season();
$competition_id = $season_obj->data('competition id');
$access['competitions'][$competition_id]['parent_access'] = true;
$access['competitions'][$competition_id]['seasons'][$season_obj->data('id')]['parent_access'] = true;
$access['competitions'][$competition_id]['seasons'][$season_obj->data('id')]['rounds'][$id]['direct_access'] = true;
/* GAMES */
foreach ($access['competitions'][$competition_id]['seasons'][$season_obj->data('id')]['rounds'][$id]['games'] as &$game) {
$game['child_access'] = true;
unset($game);
}
}
/* CHECK GAMES */
$games = $this->db->select('game_id')->from('user_game')->where('user_id', $user_id)->get();
foreach ($games->result() as $id) {
$id = $id->game_id;
$game_obj = $this->games->disabled(true)->get($id);
$round_obj = $game_obj->round();
$season_obj = $round_obj->season();
$competition_id = $season_obj->data('competition id');
$access['competitions'][$competition_id]['parent_access'] = true;
$access['competitions'][$competition_id]['seasons'][$season_obj->data('id')]['parent_access'] = true;
$access['competitions'][$competition_id]['seasons'][$season_obj->data('id')]['rounds'][$round_obj->data('id')]['parent_access'] = true;
$access['competitions'][$competition_id]['seasons'][$season_obj->data('id')]['rounds'][$round_obj->data('id')]['games'][$id]['direct_access'] = true;
}
if ($action == 'trim') {
foreach ($access['competitions'] as $k => &$competition) {
if ($competition['child_access'] === false &&
$competition['direct_access'] === false &&
$competition['parent_access'] === false
) {
unset($access['competitions'][$k]);
continue;
}
foreach ($competition['seasons'] as $k1 => &$season) {
if ($season['child_access'] === false &&
$season['direct_access'] === false &&
$season['parent_access'] === false
) {
unset($competition['seasons'][$k1]);
continue;
}
foreach ($season['rounds'] as $k2 => &$round) {
if ($round['child_access'] === false &&
$round['direct_access'] === false &&
$round['parent_access'] === false
) {
unset($season['rounds'][$k2]);
continue;
}
foreach ($round['games'] as $k3 => $game) {
if ($game['child_access'] === false &&
$game['direct_access'] === false &&
$game['parent_access'] === false
) {
unset($round['games'][$k3]);
continue;
}
}
}
}
}
}
dump($access);
}
您需要使用XACML之类的授权语言来表示谁可以访问哪些特定数据。 然后,您已将表变成“属性”的来源之一。
使用XACML,您可以表达以下规则:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.