EBS mo_glob_org_access_tmp表的分析
mo_glob_org_access_tmp介绍
在多OU的实现中,VPD都是通过判断基表的org_id是否在mo_glob_org_access_tmp表中存在,如果存在则为安全数据。该表是一张session临时表,其中的值只能通过使用mo_globlal和mo_utils包的方法进行操作。该表中的值是在mo_global.populate_orgs中进行插值,mo_global.delete_orgs进行删除操作的,在populate_orgs过程中,有这样一条bug修改记录:
Bug fix 4511279:Need to populate temp table even when access mode is “S”.
该注释表明,该表不仅在多OU模式下需要插值,并且在单OU模式下也需要进行插值操作,当然单OU下该表有且仅有一条记录。
mo_global.populate_orgs方法包含四个参数:
PROCEDURE populate_orgs (
p_org_id_char VARCHAR2,
p_sp_id_char VARCHAR2,
p_current_org_id OUT NOCOPY VARCHAR2,
p_view_all_org OUT NOCOPY VARCHAR2);
- 1
- 2
- 3
- 4
- 5
参数 | 说明 |
---|---|
p_org_id_char | 当前的OU “MO: Operating Unit” |
p_sp_id_char | 当前的安全性配置文件“MO: Security Profile” |
p_current_org_id | 当前的org_id |
p_view_all_org | 是否查看所有的OU标示 |
p_org_id_char和p_sp_id_char的值分别对应“MO: Operating Unit”和“MO: Security Profile”预制文件的值,在调用populate_orgs过程前,有一个逻辑判断
IF l_security_profile_id IS NOT NULL THEN
l_org_id := null;
END IF;
- 1
- 2
- 3
该逻辑的含义即为,如果设置了“MO: Security Profile”预制文件,那么“MO: Operating Unit”的值会自动被覆盖,也即是参数p_org_id_char和p_sp_id_char中一定是有一个为空的。当p_org_id_char不为空时,肯定是单OU模式。
table记录的生成逻辑:
在多OU的设置开始我们会定义一个安全性配置文件和设置当前的安全性配置文件,该配置文件中定义了一系列组织访问的权限控制,我们可以使用下面语句查询出当前使用的安全性控制文件
SELECT security_profile_name
, business_group_id
,view_all_organizations_flag
FROM per_security_profiles
WHERE security_profile_id =
to_number(fnd_profile.VALUE('XLA_MO_SECURITY_PROFILE_LEVEL'));
- 1
- 2
- 3
- 4
- 5
- 6
可以通过以下语句获取当前安全性配置文件和当前用户在当前职责下可访问的OU
SELECT per.organization_id organization_id
, hr.NAME name
FROM per_organization_list per
, hr_operating_units hr
WHERE per.security_profile_id = to_number(fnd_profile.VALUE('XLA_MO_SECURITY_PROFILE_LEVEL'))
AND hr.organization_id = per.organization_id
AND hr.usable_flag is null;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
当一切条件设置完成后,下面进入mo_global.populate_orgs进行插值操作,伪代码如下:
1.IF 安全性配置文件预制文件不为空 THEN
获取安全性预制文件的信息,文件名,业务组,查看所有标示
SELECT security_profile_name
, business_group_id,
view_all_organizations_flag
INTO l_sp_name
,l_bg_id
,p_view_all_org
FROM per_security_profiles
WHERE security_profile_id = to_number(p_sp_id_char);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
1.1 IF 安全性配置文件没有设置组织控制 THEN
1.1.1 IF 安全性预制文件指定了业务组 THEN
获取该业务组下对应的所有org_id
SELECT hr.organization_id organization_id
,hr.name NAME
INTO t_org_id
,t_ou_name;
FROM hr_operating_units hr
WHERE hr.business_group_id = l_bg_id
AND hr.usable_flag is null;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
1.1.2 ELSE 安全性预制文件没有定业务组 THEN
获取系统所有的org_id
SELECT hr.organization_id organization_id
,hr.NAME NAME
INTO t_org_id
,t_ou_name;
FROM hr_operating_units hr
WHERE hr.usable_flag IS NULL;
- 1
- 2
- 3
- 4
- 5
- 6
END IF;
1.2 ELSE 安全性设置文件中指定了OU范围 THEN
获取安全性配置文件对应的所有Org_id
SELECT per.organization_id organization_id
,hr.NAME NAME
INTO t_org_id
,t_ou_name;
FROM per_organization_list per, hr_operating_units hr
WHERE per.security_profile_id = to_number(p_sp_id_char)
AND hr.organization_id = per.organization_id
AND hr.usable_flag IS NULL;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
END IF;
2.ELSE 没有设置安全性配置文件 THEN
2.1 IF 当前OU配置文件有值 THEN
获取当前的org_id
SELECT hr.organization_id organization_id
, hr.name NAME
INTO t_org_id
,t_ou_name;
FROM hr_operating_units hr
WHERE hr.organization_id = to_number(p_org_id_char)
AND hr.usable_flag is null;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
END IF;
END IF;
3.IF 如果t_org_id的长度大于1,即为当前用户有多OU访问权限 THEN
获取用户首选项的org_id的值
SELECT organization_id
FROM fnd_mo_sp_preferences
INTO t_pref_org_id
WHERE user_id = fnd_global.user_id
AND resp_id = fnd_global.resp_id;
- 1
- 2
- 3
- 4
- 5
3.1 IF 用户首选项的t_pref_org_id表长度不为空 then
3.1.1 IF (g_sync <> ‘N’) THEN
sync_ind := ‘Y’;
END IF;
判断用户首选项的值和当前所有的OU值是否相同,如果相同
则将值放入放入t_common_org信息表中;
将fnd_mo_sp_preferences用户首选项表中没有访问权限的OU信息删除
END IF;
3.2 IF 要求同步 (sync_ind = ‘Y’) AND 首选项中有值 THEN
FOR i IN t_common_org_id.FIRST .. t_common_org_id.LAST LOOP
INSERT
INTO mo_glob_org_access_tmp
(organization_id
, organization_name)
VALUES (t_common_org_id(i)
, t_common_ou_name(i));
END LOOP;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
3.3 ELSIF 如果没有要求同步,则mo_glob_org_access_tmp表中
的值为当前能选择的所有值 then
FOR i IN t_org_id.FIRST .. t_org_id.LAST LOOP
INSERT
INTO mo_glob_org_access_tmp
(organization_id
, organization_name)
VALUES (t_org_id(i)
, t_ou_name(i));
END LOOP;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
END IF;
g_ou_count := t_org_id.COUNT;
END IF;
4.IF p_sp_id_char IS NOT NULL AND l_bg_id IS NOT NULL AND 访问所有OU标示 = ‘Y’ THEN
设置访问所有OU的标志
访问所有OU标示 := ‘N’;
END IF;
设置全局访问模式
5.IF 访问所有OU标示 = ‘Y’ THEN
访问模式:=’A’; –ALL
6.ELSIF g_ou_count = 1 THEN
访问模式:=’S’; –Single
7.ELSIF g_ou_count > 1 THEN
访问模式:=’M’; –Mutil
END IF;
8.IF ou表的长度=1 THEN
设置默认org_id为当前唯一的org_id
END IF;
view_all_organizations_flag字段
在上段的分析过程中,有一个概念是 访问所有OU标示(p_view_all_org)它是对应的安全性配置文件表的view_all_organizations_flag字段,当界面上的安全性类型为查看所有组织(无安全性)时,此值对应的结果为“Y”,否则为“N”。
fnd_mo_sp_preferences值逻辑
在上面的分析过程中涉及到一个fnd_mo_sp_preferences表,在多OU操作的情况下,向mo_glob_org_access_tmp表插值时需要检查设置fnd_mo_sp_preferences的值,只有是该表和查询出的结果值都满足才插入到mo_glob_org_access_tmp,他的设置是在EBS MOAC 多OU使用配置 中的添加功能下有介绍的。
按照EBS MOAC 多OU使用配置 中的添加功能的界面查询值是只有一个默认值的结果的,但当我们将四个组织都设置为首选时如图
该查询才会有值
SELECT msp.user_id
,msp.resp_id
,msp.security_profile_id
,msp.organization_id
FROM fnd_mo_sp_preferences msp;
- 1
- 2
- 3
- 4
- 5
结果如下:
但security_profile_id=0的记录是怎么产生的呢? 通过查询
SELECT security_profile_name
,business_group_id
,view_all_organizations_flag
FROM per_security_profiles
WHERE security_profile_id = 0
- 1
- 2
- 3
- 4
- 5
可以得知该值时安全性配置文件Setup Business Group产生的,该文件时系统默认的安全性配置文件。其内部机制有待研究……
总结
在该节中对mo_glob_org_access_tmp的值生成分析是对应的多OU模式下的验证值,但在进行验证的过程中有段代码是:
EXISTS (SELECT 1
FROM mo_glob_org_access_tmp oa
WHERE oa.organization_id = org_id)
- 1
- 2
- 3
但对应单OU模式下的验证语句
org_id = sys_context(”multi_org2”,”current_org_id”)
sys_context(”multi_org2”,”current_org_id”)的值是怎么获取的呢?详见:EBS MO_GLOBAL包的分析