在 Salesforce 中,设置对象的访问控制为“Controlled by Parent”时,该对象的可见性通常由其主对象(Parent)的共享规则或权限决定。如果主对象可见,子对象也会自动继承可见性。然而,有时候我们希望实现一些特例,即:主对象可见,但子对象在某些情况下不可见。
这是一个挑战,因为“Controlled by Parent”默认不支持这样的场景。但可以通过以下方法实现:
方法 1: 使用 Restriction Rules 限制访问
-
场景描述:即使用户对 Parent 对象有权限,某些情况下希望限制子对象的可见性或访问。
-
实现步骤:
- 在对象管理器中找到对象,点击对象的Restriction Rule,新建一个,设置筛选条件筛选出该用户可见的对象。
- Restriction Rule生效后优先级是最高的,即使其它方式(例如共享规则)可见,如果不符合Restriction Rule也会变得不可见。
-
效果:用户即使对 Parent 有权限,也无法访问受限制的子对象。
方法 2: 使用 Record Types 和页面布局分配
-
场景描述:希望控制子对象的某些记录是否可见,同时限制特定用户组的访问。
-
实现步骤:
- 创建 Record Types:为子对象创建两个或多个 Record Type(如
VisibleRecordType
和HiddenRecordType
)。 - 自定义页面布局:为不同的 Record Type 创建不同的页面布局,将“隐藏”记录的布局设置为空(或限制显示字段)。
- 分配权限:
- 在 Profiles 或 Permission Sets 中,限制某些用户访问特定的 Record Type。
- 在业务逻辑中(如触发器或流程生成器),自动将子对象的 Record Type 设置为相应的类型。
- 创建 Record Types:为子对象创建两个或多个 Record Type(如
-
效果:通过 Record Type 和页面布局限制,用户可以访问 Parent,但无法查看特定子对象记录。
方法 3: 使用 Apex Sharing Rules 自定义共享
- 场景描述:在“Controlled by Parent”的设置下,使用自定义共享规则进一步调整子对象的可见性。
- 实现步骤:
- 在子对象上启用 Defer Sharing Calculation。
- 使用 Apex Sharing Rules 编写逻辑,动态调整子对象记录的可见性。
- 示例代码:
List<CustomObject__Share> shares = new List<CustomObject__Share>(); for (CustomObject__c record : recordsToRestrict) { CustomObject__Share share = new CustomObject__Share(); share.ParentId = record.Id; share.UserOrGroupId = restrictedUserId; share.AccessLevel = 'None'; shares.add(share); } insert shares;
- 效果:尽管 Parent 对象可见,子对象的访问权限将根据共享规则动态调整。
方法 4: 使用 Flow 或 Process Builder 自动化限制
-
场景描述:基于特定条件动态调整子对象记录的可见性。
-
实现步骤:
- 创建一个 Flow 或 Process,在子对象的记录创建或更新时触发。
- 根据条件,将子对象记录的
OwnerId
字段设置为一个虚拟用户(如系统管理员)或其他不常用用户,从而间接限制普通用户的访问权限。 - 配置条件:
- 如果 Parent 满足可见条件,但子对象不满足,则更改
OwnerId
。
- 如果 Parent 满足可见条件,但子对象不满足,则更改
-
效果:用户对 Parent 有权限,但子对象在某些条件下被系统自动“转移”以限制访问。
方法 5: 拆分对象并调整共享模型
如果业务逻辑复杂,可以考虑将子对象的访问控制从“Controlled by Parent”改为“Private”,并通过手动共享规则或 Apex 共享实现。
- 调整共享设置:在子对象的共享设置中,将其改为“Private”或“Public Read Only”。
- 手动共享规则:根据需要为不同用户组配置访问权限。
注意事项:
- 性能问题:自定义共享和复杂权限逻辑可能对系统性能造成影响,需要合理优化。
- 测试和验证:实现上述功能后,需要全面测试用户的访问权限是否满足预期。
- 合规性检查:确保权限设置符合公司的安全和隐私要求。
以上方法可以根据实际业务需求选择实现方式。如果你需要更具体的示例代码或设置步骤,请告诉我!