我刚刚完成了这个功能的构建。虽然没有开箱即用的方法,但有许多可能的方法可以解决这个问题,包括:
- item:saving 事件处理程序(注意“保存”而不是“保存”,这是事后发生的),或者
- 为 saveUI 管道创建一个处理器,在 UI 中执行“保存”按钮时执行,或者我们采用的方式
- 为 getContentEditorWarnings 管道创建一个处理器
最后一种方法允许您禁用 Sitecore 用户界面并向用户显示一条消息,但不会阻止代码或 API 更改项目,这对我们来说是理想的。我们的处理器接受路径列表(在配置中)作为子元素,允许我们将功能限制在站点的某些区域(我们控制对营销控制面板的访问)。
这是我们注入片段的<getContentEditorWarnings> 管道的摘录。
....
<processor type="Sitecore.Pipelines.GetContentEditorWarnings.CanWrite, Sitecore.Kernel"/>
<processor type="PingWorks.Pipelines.GetContentEditorWarnings.EditorIsFromAuthorGroup, PingWorks.Pipelines.GetContentEditorWarnings" patch:source="PingWorks.Pipelines.GetContentEditorWarnings.config">
<ignoredRoles hint="list:AddIgnoredRole">
<role>sitecore\_UserBase</role>
</ignoredRoles>
<paths hint="list:AddPath">
<path>/sitecore/system/Marketing Control Panel/Taxonomies/</path>
<path>/sitecore/system/Marketing Control Panel/Campaigns/</path>
<path>/sitecore/system/Marketing Control Panel/Engagement Plans/</path>
<path>/sitecore/system/Marketing Control Panel/Experience Analytics/</path>
<path>/sitecore/system/Marketing Control Panel/FXM/</path>
<path>/sitecore/system/Marketing Control Panel/Outcomes/</path>
<path>/sitecore/system/Marketing Control Panel/Path Analyzer/</path>
<path>/sitecore/system/Marketing Control Panel/Personalization/</path>
<path>/sitecore/system/Marketing Control Panel/Test Lab/</path>
<path>/sitecore/system/Marketing Control Panel/Experience Explorer/</path>
<path>/sitecore/system/Marketing Control Panel/Analytics Filters/</path>
</paths>
</processor>
<processor type="Sitecore.Pipelines.GetContentEditorWarnings.CanWriteWorkflow, Sitecore.Kernel"/>
...
请注意如何使用 Sitecore 配置工厂来填充管道执行器将使用子元素创建的实例的属性,以及在这种情况下我们如何通过 @ 向 List<string> 属性添加字符串987654324@ 和 ::AddPath() 方法。
在我们的特殊情况下,我们希望只允许编辑与原作者属于同一角色组的成员进行编辑,尽管您的逻辑将比我们的逻辑更直接。在我们的案例中,我们还为管理员用户添加了一个覆盖,并添加了一个自定义缓存来存储角色搜索结果以加快处理速度,因为在我们的案例中角色成员身份不会经常更改。
我会省去你处理的大部分工作,但关键在于::Process() 方法(我必须反映这段代码,因为我目前无法访问源代码):
public void Process(GetContentEditorWarningsArgs args)
{
string displayName;
this._item = args.Item;
if (!this._isValidForProcessing())
return;
User user = null;
List<string> creatorRoles = this._getRolesForUser(this._item.Statistics.CreatedBy, out user);
List<string> editorRoles = this._getRolesForUser(Context.User);
// compare creator's roles with current editor to find a match
if ( creatorRoles.Any() && editorRoles.Any() && editorRoles.Any( r => creatorRoles.Contains(r) ) )
return;
// if we haven't already aborted, add a warning to display and block editing
GetContentEditorWarningsArgs.ContentEditorWarning cew = args.Add();
cew.IsExclusive = true;
cew.Key = "EditorIsFromAuthorGroup";
cew.Title = "Editing restricted";
cew.Text = $"Editing for this item is restricted. Editors must share a role with the original author, in this case <{user?.DisplayName ?? "Unknown Author"}>.";
}
private bool _isValidForProcessing()
{
if (this._item == null)
return false;
if (Context.IsAdministrator)
return false;
if (!this._paths.Any<string>((string p) => this._item.Paths.FullPath.ToLower().StartsWith(p)))
return false;
return true;
}
这可能足以让您在需要的地方有一个良好的开端。