継承されたアクセスをクリーンアップする方法
この記事では、Microsoft Dataverse でテーブルのカスケード構成が変更されたときに、レコードの継承されたアクセス権を削除する方法について説明します。
現象
Reparent または Share アクションのテーブル リレーションシップのケース化動作が No Cascade に変更された後も、削除する必要がある関連レコードに引き続きアクセスできます。
関連レコードへのアクセスを確認する方法
ユーザーは、レコードに予期しないアクセス権があることを報告する場合があります。 関連レコードへのアクセスを確認するには、 Check Access 機能と RetrieveAccessOrigin
メッセージの 2 つの方法があります。
アクセスの確認機能を使用する
モデル駆動型アプリの Check Access 機能を使用して、レコードにアクセスできるユーザーを確認します。 管理者は、この機能を使用して、個々のユーザーまたはレコードにアクセスできるすべてのユーザーを確認できます。
アクセス チェッカーを使用すると、ユーザーがアクセス権を持つ理由の一覧が表示されます。 これらの理由の一部は、関連レコードへのアクセスが原因で共有が許可されたことを示しています。 例えば次が挙げられます。
- 関連レコードにアクセスできるため、レコードが共有されました。
- レコードは、チームが関連レコードにアクセスできるため、自分がメンバーになっているチームと共有されました。
RetrieveAccessOrigin メッセージを使用する
開発者は、 RetrieveAccessOrigin
メッセージを使用して、レコードにアクセスできるユーザーを検出できます。 このメッセージは、ユーザーがアクセス権を持つ理由を説明する文を返します。 次のいずれかの結果は、関連レコードの共有が原因でアクセスが許可されたことを示しています。
PrincipalId is owner of a parent entity of object (<record ID>)
PrincipalId is member of team (<team ID>) who is owner of a parent entity of object (<record ID>)
PrincipalId is member of organization (<organization ID>) who is owner of a parent entity of object (<record ID>)
PrincipalId has access to (<parent record ID>) through hierarchy security. (<parent record ID>) is owner of a parent entity of object (<record ID>)
詳細については、「 ユーザーがコードを使用してアクセス権を持つ理由を確認するを参照してください。
原因
テーブル リレーションシップの連鎖動作が変更されると、Dataverse は非同期ジョブを開始して、ユーザーが以前に付与したアクセス権を削除します。 ただし、このジョブが失敗し、ユーザーがアクセスを保持する可能性があります。
解決方法
この問題を解決する最初の手順は、システム ジョブを再作成してアクセス権を削除することです。 ジョブが失敗した場合、開発者は ResetInheritedAccess
メッセージを使用して、指定したレコードセットに変更を適用できます。
システム ジョブを再作成してアクセス権を削除する
開発者は、 CreateAsyncJobToRevokeInheritedAccess
メッセージを使用して、非同期ジョブをもう一度作成できます。
Microsoft.Xrm.Sdk.Messages.CreateAsyncJobToRevokeInheritedAccessRequest クラスを使用します。
/// <summary>
/// Creates and executes an asynchronous cleanup job to revoke inherited access granted through cascading inheritance.
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance to use.</param>
/// <param name="relationshipSchemaName">The schema name of the entity relationship.</param>
public static void CreateAsyncJobToRevokeInheritedAccessExample(IOrganizationService service, string relationshipSchemaName)
{
var request = new Microsoft.Xrm.Sdk.Messages.CreateAsyncJobToRevokeInheritedAccessRequest()
{
RelationshipSchema = relationshipSchemaName
};
service.Execute(request);
}
CreateAsyncJobToRevokeInheritedAccess
アクションは、RevokeInheritedAccess
という名前の新しい非同期ジョブを作成します。 このジョブの成功を監視できます。 詳細については、「システム ジョブの監視コードを使用したシステム ジョブの管理を参照してください。
継承されたアクセスをリセットする
システム ジョブを してアクセスを削除 失敗した場合、システム管理者またはシステム カスタマイザー権限を持つ開発者は、 ResetInheritedAccess
メッセージを使用して、一致するレコードのサブセットをターゲットにすることができます。 すべてのレコードへのアクセスを削除するには、このメッセージを複数回使用する必要がある場合があります。
/// <summary>
/// Resets the inherited access for the matching records.
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance to use.</param>
/// <param name="fetchXml">The fetchxml query.</param>
public static void OutputResetInheritedAccess(IOrganizationService service, string fetchXml)
{
var parameters = new ParameterCollection()
{
{ "FetchXml", fetchXml}
};
var request = new OrganizationRequest()
{
RequestName = "ResetInheritedAccess",
Parameters = parameters
};
var response = service.Execute(request);
Console.WriteLine(response.Results["ResetInheritedAccessResponse"]);
}
ResetInheritedAccess
メッセージは、一致するレコードが多くない場合に同期的に実行しようとします。 その後、 ResetInheritedAccessResponse
の値は ExecutionMode : Sync
で終わります。 一致するレコードが多数存在する場合、操作にかかる時間が長くなり、値は ExecutionMode : Async
で終了します。 Denormalization_PrincipalObjectAccess_principalobjectaccess:<caller ID>
という名前のシステム ジョブが作成され、そのジョブの成功を監視できます。 詳細については、「システム ジョブの監視コードを使用したシステム ジョブの管理を参照してください。
ResetInheritedAccess
メッセージでは、レコードを識別するために FetchXml クエリが必要です。 このクエリは、次の要件を満たしている必要があります。
principalobjectaccess
(POA) テーブルを使用します。principalobjectaccessid
列のみを返します。link-entity
要素を含めてはなりません。 別のテーブルに結合を追加することはできません。principalobjectaccess
テーブルの列のみをフィルター処理します。
このテーブルは、 principalobjectaccess エンティティ型として Web API で使用できます。 POA テーブルは直接データ変更操作をサポートしていないためDataverse テーブル/エンティティ参照には含まれません。 FetchXml クエリを作成するには、このテーブルの列を知っている必要があります。
POA テーブルの列
これらの列のみを使用して FetchXml クエリを作成する必要があります。
論理名 | タイプ | Description |
---|---|---|
accessrightsmask |
整数 | プリンシパルが直接持つアクセス権の組み合わせ AccessRights 列挙型 メンバー値を格納します。 |
changedon |
DateTime | プリンシパルのレコードへのアクセスが変更された最後の日付。 |
inheritedaccessrightsmask |
Integer | 継承のために適用されるアクセス権の結合された AccessRights 列挙型 メンバー値を格納します。 |
objectid |
一意識別子 | プリンシパルがアクセスできるレコードの ID。 |
objecttypecode |
Integer | テーブルに対応する EntityMetadata.ObjectTypeCode 値。 この値は、異なる環境で必ずしも同じであるとは限りません。 カスタム テーブルの場合、テーブルが作成された順序に基づいて割り当てられます。 この値を取得するには、テーブルのメタデータを表示することが必要な場合があります。 これを見つけるためのコミュニティ ツールがいくつかあります。 Microsoft のソリューションを次に示します。 環境内のテーブル定義を参照してください。 |
principalid |
一意識別子 | アクセス権を持つユーザーまたはチームの ID。 |
principalobjectaccessid |
一意識別子 | POA テーブルの主キー。 |
principaltypecode |
Integer | プリンシパルの型コード。 SystemUser = 8、 Team = 9。 |
次の AccessRights 列挙型 メンバー値は、 accessrightsmask
列と inheritedaccessrightsmask
列に適用されます。
アクセスの種類 | 値 | 説明 |
---|---|---|
None |
0 | アクセスはありません。 |
Read |
1 | レコードを読み取る権限。 |
Write |
2 | レコードを更新する権限。 |
Append |
4 | 指定したレコードを別のレコードに追加する権限。 |
AppendTo |
16 | 指定したレコードに別のレコードを追加する権限。 |
Create |
32 | レコードを作成する権限。 |
Delete |
65,536 | レコードを削除する権限。 |
Share |
262,144 | レコードを共有する権限。 |
Assign |
524,288 | 指定したレコードを別のユーザーまたはチームに割り当てる権限。 |
inheritedaccessrightsmask
値は一般的に 135,069,719 であることがわかります。 この値には、 Create
を除くすべてのアクセスの種類が含まれます。これらの権限は既に作成されているレコードにのみ適用されるため、必要ありません。
FetchXml の例
このセクションでは、 ResetInheritedAccess
メッセージで使用できる FetchXml クエリの例をいくつか示します。 詳細については、FetchXML の使用によるクエリの作成 を参照してください。
特定のアカウントの特定のユーザーに付与された継承されたアクセス権をリセットする
<fetch>
<entity name="principalobjectaccess">
<attribute name="principalobjectaccessid"/>
<filter type="and">
<condition attribute="principalid" operator="eq" value="9b5f621b-584e-423f-99fd-4620bb00bf1f" />
<condition attribute="objectid" operator="eq" value="B52B7A48-EAFB-ED11-884B-00224809B6C7" />
</filter>
</entity>
</fetch>
指定されたオブジェクト タイプのすべての子行に与えられた継承されたアクセスをリセットします
<fetch>
<entity name="principalobjectaccess">
<attribute name="principalobjectaccessid"/>
<filter type="and">
<condition attribute="objecttypecode" operator="eq" value="10042" />
</filter>
</entity>
</fetch>
すべてのオブジェクト タイプについて、指定したユーザーに与えられている継承されたアクセス権をリセットする
<fetch>
<entity name="principalobjectaccess">
<attribute name="principalobjectaccessid"/>
<filter type="and">
<condition attribute="principalid" operator="eq" value="9b5f621b-584e-423f-99fd-4620bb00bf1f" />
</filter>
</entity>
</fetch>