Salesforce提供对象的访问权限可以通过 安全性控制 → 共享设置,可以查看每个对象在系统内部默认的访问权限
- 共用读写:对象的记录任何用户都可以进行读写操作
- 公用只读:对象的记录任何用户都可以查看,但是只有记录所有人以及具有权限的用户可以编辑
- 专用:对应的记录只有具有权限的用户才可以进行读写操作
- 从父级控制:对象记录访问权限跟随父级
以Movie__c对象为例,此时对象权限为公用读写,看到的记录详情页面是这样的
而在编辑页面布局上看到“共享按钮”是被拉出来的状态
当我们将Movie__c的组织权限修改为专用,则记录页面显示如下
通过共享按钮可以将记录共享给其他公用小组/用户/角色/角色及下属,访问级别提供了只读/读写两种级别。用户可以通过共享按钮来将记录的权限共享给其他用户用于查看或修改。
但是很多时候,我们更希望做到的是类似于记录能自动共享给一部分人的情况,比如记录上有一个查找用户字段,当记录被创建时,权限自动共享给该用户,该用户被修改后也能把之前的权限给到新用户并将权限从之前的用户身上收回。
我们在Movie__c对象上新建一个查找(用户)的字段,约会人Engagement__c
需求:当Movie__c记录被创建时,将记录读写权限共享给约会人
实现如下:
1 trigger MovieTrigger on Movie__c (after insert,after update) { 2 //触发器的实现类 3 MovieTriggerHandler handler = new MovieTriggerHandler(); 4 5 //当记录新建的时候触发 6 if(trigger.isAfter && trigger.isInsert){ 7 Set<Id> Set_movieId = new Set<Id>(); 8 for(Movie__c movie:trigger.new){ 9 //记录约会人!=null 且 记录约会人!=记录所有人 10 if(movie.Engagement__c != null && movie.Engagement__c != movie.OwnerId){ 11 Set_movieId.add(movie.id); 12 } 13 } 14 //判断是否有符合条件的记录 15 if(Set_movieId.size() > 0) handler.shareWithPerson(Set_movieId); 16 } 17 }
然后是写触发器的实现类
1 public class MovieTriggerHandler{ 2 3 public void shareWithPerson(Set<Id> Set_movieId){ 4 //查询电影列表的记录 5 List<Movie__c> list_movie = new List<Movie__c>([select id,OwnerId,Engagement__c from Movie__c where id=:Set_movieId]); 6 7 //存储共享记录列表 8 List<Movie__Share> list_share = new List<Movie__Share>(); 9 10 for(Movie__c ml:list_movie){ 11 Movie__Share share = new Movie__Share(); 12 share.UserOrGroupId = ml.Engagement__c;//需要共享给的用户 or 小组 13 share.ParentId = ml.id;//记录id 14 share.AccessLevel = 'edit'; //edit:读写/read:只读 15 list_share.add(share); 16 } 17 //判断是否为空 18 if(list_share.size() > 0) insert list_share; 19 } 20 }
写完代码后,不要忘记启用触发器让它生效
此时创建一条数据,如果约会人存在且不等于所有人,则再次查看我们的共享列表就能看到类似如下的内容
这也就是通过代码实现的自动共享操作。
需要注意的有几个点:
- 1.约会人不能为空
- 2.约会人不能等于记录所有人
- 3.约会人不能等于系统管理员
- 4.约会人必须是被启用的用户
- 5.当记录所有人被修改,共享过来的用户都会被清空掉,需要重新共享权限
重点看下第五条,通过共享按钮共享到的用户会随着记录所有人的变更,从共享列表中被清除,所以我们在触发器中需要根据这一点做好相关判断与处理
1 //当记录修改的时候触发 2 if(trigger.isAfter && trigger.isUpdate){ 3 Set<Id> Set_movieId = new Set<Id>(); 4 for(Movie__c movie:trigger.new){ 5 Movie__c oldMovie = trigger.oldMap.get(movie.id); 6 //所有人发生变更且新记录约会人不等于空 7 if(movie.OwnerId != oldMovie.OwnerId && movie.Engagement__c != null){ 8 Set_movieId.add(movie.id); 9 } 10 } 11 //判断是否又符合条件的记录 12 if(Set_movieId.size() > 0) handler.shareWithPerson(Set_movieId); 13 }
我们可以同样使用新建时候的逻辑,传递一个满足条件的Set集合到MovieTriggerHandler中的shareWithPerson方法中去,复用该方法。
这个问题在共享规则中是不存在的,用共享规则共享出去的权限不受记录所有人变更的影响。
那么在最后还有一点值得一提的是,如果字段约会人本身发生修改,在触发器中除了要共享给新的约会人以权限,也需要删除原约会人的记录
1 List<Movie__Share> plist = new List<Movie__Share>([select UserOrGroupId,ParentId,AccessLevel 2 from Movie__Share where UserOrGroupId ='movieId' and RowCause =: 'Manual']); //类型:手动共享
查询原约会人推荐加上对原因类型的判断,Manual即指代手动共享的类型,来自我们用共享按钮或Apex类的共享,从而有效避免查询的用户会有因其他原因具备查看该记录的权限结果被我们删除的情况。
Salesforce提供了相对简单的权限设置方法,层级的模式下,在共享的时候要尽可能减少能看到记录的用户数量,进而保证数据的安全性,最后,如有遗漏欢迎指正,有问题可以在评论区留言。