Salesforce删除数据时出现Insufficient privileges的可能原因

遇到一个诡异的情况,用户通过界面删除一条自定义Object的数据的时候出现了Insufficient privileges。
按理说,如果用户的Profile没有此Object的删除权限的话,应该连删除按钮都看不到才对。

事情有蹊跷。首先检查了Profile,增删改查都有,但是没有Motify All和View All。
那么排除了Profile的嫌疑。
接下来查看Role。发现此用户的Role在role hierarchy中已经是比较高的位置了。
然后检查Sharing Rule。发现此Object的基本Sharing设定已经改成了Private,并且启用了role hierarchy。
那么问题就应该出在这里了。
去查看用户无法删除的那条数据,果然Owner不是用户本人,且Owner的Role与此用户同级。

在Salesforce中,如果Object的全局Sharing Rule为Private,那么除非用户的Profile是System Admin或者拥有Motify All权限,否则当用户想删除的数据的Owner为别人且Role为同级或者更高级的话,就会出现权限不足的问题。

告知用户,想删除此数据的话,请先把Owner改成自己,然后再删除。问题解决。

参考来自官网的信息

Task中的字段TaskSubType在ApexClass中不可见问题

在Task上有一个标准字段叫做TaskSubType,是一个Picklist。在属性页面无法看到与选择任何属性。也无法更改Picklist里的值,虽然里面有内置三个值。

某一天,我试图在Task的trigger里判断字段TaskSubType的值,在保存代码时报错,错误内容为“Error: Compile Error: Invalid field TaskSubtype for SObject Task”。

我用查询工具查询该字段,正常。
我用匿名块访问该字段,正常。

奇了个怪了。

使用查询工具查看该字段,有create-able,filter-able,nillable,restricted picklist,sort-able,没有update-able。不过应该不影响这里。也查看了FLS,也没有问题。

好,耐心查看Task的文档,发现此字段原名ActivitySubType,是在Winter’16加入Salesforce的。再回头一看ApexClass,原来用的是API 30。

果断改成API 36。保存正常。

这个就类似于Java的JDK,在JDK1.8加入的新特性,在JDK1.4是肯定无法使用的。
较早前创建的Apex Class或者Visualforce Page一定要注意API版本问题。

Salesforce的Trust终于改版了

trust site是由Salesforce提供,用来监控所有服务与实例状态的网站。

经典应用场景是,发现实例变得很慢,然后打开trust,哦。。。发生了性能降低。

新版trust也提供了新版API,可以获得相关实例的JSON串,自己定时获取,自己解析,可以实现自动提醒,自动警报。

API地址 https://api.status.salesforce.com/v1/instances/{你的实例名}/status

所有接口的说明 https://api.status.salesforce.com/v1/docs/

phpfreechat中一个啼笑皆非的Bug

因为觉得所有在线聊天工具要经过人家的服务器不够把握,所以在自己的服务器上架设了phpfreechat。
这款在线聊天室,有着不在服务器储存任何聊天记录的优点。

然后有一天,我试图在上面发送一个数字 0
没有任何反应。
习惯性的按了下F12,发现phpfreechat提供了控制台输出。

readyState: 4, responseText: "{ "error": "Wrong message format (must be a JSON string)" }", status: 400, statusText: "error"}

哦?必须是个Json?
又去下了一份源代码,查找报错内容 “Wrong message format (must be a JSON string)”。
顺利定位到唯一一本代码,channels.php中的如下代码片段。

  // check that request content contains a message
  $data = json_decode($req->getBody());
  if (!$data or !is_string($data)) {
    $res->status(400); // Wrong message format
    $res['Content-Type'] = 'application/json; charset=utf-8';
    $res->body('{ "error": "Wrong message format (must be a JSON string)" }');
    return;
  }

如果我在第二行传入了一个0,$data仍然等于0。
在第三行,死在了!$data上。!$data是个很诡异的判断。
在PHP中,非0即true,0即false,”0″是false,’0’也是false。
就因为我写了一个0,便中了招,进入了报错代码块。

我们再来看一下第三行代码的意图: 如果非(false/0/null/未初始化/””/…) 或者 不是字符串的话,报错。
可是我单独打一个0,并不应该被算作非法输入。
那么改成什么好呢?

Salesfroce更新了Summer 16′ 版本的ForceIDE v37.0

官网地址:https://developer.salesforce.com/page/Force.com_IDE_Installation
更新日志:https://developer.salesforce.com/page/Force.com_IDE_Release_Notes

我在Eclipse Neon上已经成功更新。
本次更新的最大变更是。。。。更改了插件安装地址。没错。
还有提供了Lightning单独的开发组件。

另外,值得一提的是,启用了Java早就有的Open Type功能。

重点来了,打断点! Debug调式!没错!像个堂堂正正的Java程序员那样!
不过我还没试验这个新功能,之后会更新。

Owncloud8以后版本如何直接从后台放文件

在Owncloud还年轻的时候,直接从后台上传文件到Owncloud的文件目录,会自动的归纳到文件系统里,并显示到网页上。
但自从Owncloud升级到高版本之后,这个特性就消失了。就是你可以放,但是人家就是不收录。

这个急坏了我了,因为有些文件通过正规上传功能就是死活上传不上去。这样我只能通过FTP先传到服务器上。
经过千辛万苦的尝试,有办法了。

第一种是执行Owncloud的CLI命令。具体位置是在Owncloud根目录,有个文件叫OCC,实际调用的是console.php,是个PHP脚本。通过命令 PHP OCC fils:scan –all即可重新扫描文件目录下的所有文件了。代价是所有文件的ID会重置,导致同步的桌面客户端会认为都是新文件,继而全部重新下载。不过,我不用同步客户端。。。。
在使用这种方法的时候我遇到了问题,因为Owncloud的Base.php使用了PHP5.4特性,虽然我在godday的管理页面选择了5.4,但在SSH中使用PHP命令的时候,仍然提示为PHP 5.3(Fxxk Godday)。

既然此路不通,我研究了下代码,发现了一个更简单的方式——–
[truncate oc_filecache;]命令
由于我使用的是MySql作为Owncloud的后台,就给了我操纵表的机会。。。执行之后,重新登录,文件都出来了。

// Update 1
答记者问,truncate命令要进入MySQL后台执行,truncate掉OwnCloud的oc_filecache这张表。之后重新登录OwnCloud,Owncloud系统会自动重新填充数据。

瑕疵

世界上没有完美的东西
世界上没有毫无瑕疵的东西

如果基因遗传体系是完美的,将不会有进化。
生物不会如此多样。

如果力学是完美的,原子核不会结合。
宇宙仍是一团雾气。

而我们在软件工程或者生产线生产中却在极致的追求无瑕疵。

贴心的PHP:内置常量

用各语言做网站的同学,经常遇到的一个问题就是在不同操作系统下路径格式不同。有的必须用“\”,有的必须用“\\”,用的得用“/”之类的。如果我们的开发机和生产环境不是同一种操作系统,总是会遇到麻烦。

但PHP居然贴心的准备了两个内置常量,DIRECTORY_SEPARATOR与PATH_SEPARATOR。

用法很简单。

<?php
$path = join(DIRECTORY_SEPARATOR, array('root', 'lib', 'file.php');
?>

或者

<?php
require 'webroot' . DIRECTORY_SEPARATOR . 'index.php';
?>

之后PHP会自动的根据运行的系统将DIRECTORY_SEPARATOR替换成适当的符号。

但是有的同学说了,如果每次都要敲出这么长的一个常量好烦啊。那么我们可以这么做。Best Practice from CAKEPHP。

<?php
/**
 * Use the DS to separate the directories in other defines
 */
if (!defined('DS')) {
    define('DS', DIRECTORY_SEPARATOR);
}
?>

然后在地方就可以这样写了。

<?php
require 'webroot' . DS . 'index.php';
?>

Salesforce的Auto Number

在Salesforce中新建Object的时候,可以对Name选择Auto Number,即自动编号。如果没有仔细阅读说明的话,会有一个很容易让人迷惑的地方。

在选择时候,Salesforce提供的示例为 示例:  A-{0000}。

那么问题来了,假设我如示例一样设定了4个0,那么当我的数据编号已经到达了A-9999会怎么样呢?

真实情况是,什么都不会发生,A-10000会被正常创建,A-10001也会被正常创建。

原因是这样的,A-{0000}的意思,是至少要有4位数字,不足则补零。例如,第99条数据的Name为A-0099。就是说,这个格式只是用来标注补零的位数的。。。不是用来限制编号最大位的。。。

然后,在设定是还可以输入开始数字,假设我设定从99999开始呢? 还是没关系。但如果设定的开始数字为1,000,000,000以上,则会告诉你,不能大于这个数。

OK,那我设为999,999,999。接下来创建数据会怎样呢?

没错,A-1000000000会被正常创建,在建一条,A-1000000001也出来了。。。。。。

所以不用担心编号用光的事情了。200多位。。。我觉得有生之前都不一定用得没了。。