最初に保存する前にアイテムレベルの権限をプログラム的に変更する方法
質問
私はすでにカスタムフォームを書き込んだリストに対する厳密な権限要件がある状況を持っています。要件は、メタデータに基づいて作成時に、特定のユーザーだけがアイテムを読み書きするためのアクセス権を持っていることです。
これを最初の試みを試みた試みは、この項目が追加されたときに許可が更新されることを確認するために、リストのイベント受信者にこれを置くことでした。アイテムに追加されたイベントにアイテムを追加イベントに入れて、私は特権を上昇させ、アイテムの上昇したインスタンスを取得する方法がありません(私が知っている)。これにより、アイテムが作成された時間とコードが実際に走った時間の間には短い遅延が発生しました。
次のことを試したことは、アイテムのIDが作成された直後にアイテムの権限を設定することで、アイテムのIDを持つので、昇格されたコンテキストでそれを取得することができるようにする(アイテムをする必要があります。現在のユーザーのコンテキストで作成されました。このアプローチが実装されたとすぐに、アイテムを実行するワークフローでエラーが発生した時間の約50%が次のようになります。 ""ワークフローの起動に失敗しました。ワークフローが適用されている項目にアクセスできません。」 (これはNintex Workflowです) - 問題がある競合状態があると仮定すると、item.update()の途中で権限を設定すると、ワークフローは同時に起動しようとします。
理想的には、最初のアイテムアップデート(作成)またはItemAddingイベントの間にアクセス許可を更新することができますが、アイテムが作成されるようにプロセス全体を上げることなくこれを行う方法はわかりません。システムアカウントと実際にアイテムを作成したユーザーではありません。
私は私にどんなオプションを利用していますか?
解決
あなたが最初にItemAddedイベントを使ってそれを持っていた方法は正しいです。ただ行方不明の1ステップがあります - それを非同期的にはなく同期的に実行するように変更することによって、イベントをすぐに実行することができます。
同期モードの切り替え方法の詳細はこちら: http://blogs.technet.com/b/stefan_gossner/archive/2011/11/10/using-Synchronous-quot-after-quot-events-eg-itemupdated-in-sharepoint-2010.aspx
他のヒント
1つのアプローチを試すことができる、そのリストでコンテンツの承認を有効にしています。これは、新しいアイテムが作成されるたびに、それが承認されるまで保留中のの状態に残ることを意味します。項目が保留中の状態にあるとき、項目の発信者とリストとライブラリを管理する権限を持つ人々だけが表示されます。この文書ライブラリのドラフト項目が表示されます。 - >アイテムを承認できるユーザーだけが(およびアイテムの作成者)。 その後、ItemAddedイベントを使用してファイルの権限を変更したり、承認済み状態に入れることもできます。
私はあなたの特定のシナリオであなたを助けることを願っています。
アイテムを作成したユーザーを偽装したり、コードの変更を加えてください。
public override void ItemUpdating(SPItemEventProperties properties)
{
base.ItemUpdating(properties);
SPUserToken objSPUserToken = properties.OriginatingUserToken;
if (objSPUserToken != null)
{
using (SPSite objSPSite = new SPSite(properties.SiteId, objSPUserToken))
{
using (SPWeb objSPWeb = objSPSite.OpenWeb())
{
//You can perform user context specific changes here...
}
}
}
}
.
この問題を回避するために行ったことは、ワークフローの設定を介して自動的にワークフローを起動するのではなく、アクセス許可が更新された後のコードを介してワークフローを開始する「手動」です。
string workflowId = "{...}"; //dynamically retrieve workflow id
SPWorkflowManager workflowManager = item.Web.Site.WorkflowManager;
SPWorkflowAssociationCollection workflowCollection = item.ParentList.WorkflowAssociations;
foreach (SPWorkflowAssociation workflow in workflowCollection)
{
if (String.Compare(workflow.BaseId.ToString("B"), workflowId, true) == 0)
{
workflowManager.StartWorkflow(item, workflow, workflow.AssociationData, true);
break;
}
}
.