Hi there!
Roles, duties and privileges security levels cover access to single elements, for example forms, and groups of elements needed to perform a duty. As developers we are responsible for defining more granular security levels by setting access on tables and controls in a form, and/or by associating classes that perform an action with permission (i.e. an action menu item)
In this article I would like to discuss, in detail, form permissions, code access permissions and how to create security policies using the extensible data security (XDS) method.
Form Permissions
Each form in the Application Object Tree (AOT) has a permissions node. It contains either four or five sub-nodes - Read, Update, Create, Delete and Correct. Now, correct is only displayed if a table in the form has Date Effective data.
Further, under the above nodes are four additional nodes - Controls, Tables, Server Methods and Associated Forms. When we add a table to a form data source, this table is automatically added to the Tables node for each of the Permissions sub-nodes. In addition, each of the nodes under the Tables node has an EffectiveAccess property which sets what access is allowed to the table and the EffectiveAccess property is automatically set based on properties on the data source.
So, this is where all makes sense, if the data source property AllowDelete is set to No, the EffectiveAccess property is set to Update. If the data source property AllowEdit is set to No, the EffectiveAccess property is set to Read.
NOTE: To set the security access for a form control, we need to set the Securable property on the control to Yes. Then, this control can then be added to the Controls node under each of the permissions nodes.
Code Permissions
These are a set of custom permissions that are created manually in the AOT under Security > Code Permissions.
For example, action menu items, can use these by setting the LinkedPermissionType property to CodePermission and the LinkedPermissionObject to the name of the code permission. Now, the great benefit about code permissions is that it can be extended to Service operations as well. This can be done by setting the Code Permission property under the Service operation > Operation method > Permissions > Associated Code Permissions node.
The following image depicts an access to post a Free-Text Invoice
Security policies - Developing an XDS Policy
The following walkthrough will show how to create a security policy that limits users from viewing other user’s prospects. This can be seen a lot in a sales environment, where one sales person does not want the other to see his/her prospects, well who wouldn’t?
So for this example, we are going to use the smmBusRelTable where leads can hopefully become the future buyers of our products.
So for this example, we are going to use the smmBusRelTable where leads can hopefully become the future buyers of our products.
A lead/prospect is stored in smmBusRelTable, and the employee who is responsible for the prospect is stored in the MainContactWorker field. In AX 2012, an employee is connected to the current user through the DirPerson and DirPersonUser tables.
There are two stages in creating the XDS policy:
1- Create the policy query.
2- Create the security policy.
Creating a Policy Query
The steps to create the policy query are as follows:
- In the AOT, create a new query, rename it to HcmWorkerUser.
- From a second AOT, locate the table Data Dictionary > Tables > HcmWorker. Drag the table HcmWorker to the Data Sources node of the query.
- In the property sheet of the Fields node of the HcmWorker_1 data source, set the Dynamic property to Yes.
- From the second AOT (Press CTRL + D to open a new AOT), locate the table Data Dictionary > Tables > DirPerson.
- Drag the table DirPerson to the Data Sources node of the HcmWorker_1 data source.
- In the property sheet for the DirPerson_1 data source, set the Relations property to Yes.
- In the property sheet for the Fields node of the DirPerson_1 data source, set the Dynamic property to Yes.
- From the second AOT, drag the table DirPersonUser to the Data Sources node of the DirPerson_1 data source.
- In the property sheet for the DirPersonUser_1 data source, set the Relations property to Yes.
- In the property sheet for the Fields node of the DirPersonUser_1 data source, set the Dynamic property to Yes.
- Right-click the Ranges node of the DirPersonUser_1 data source, and select New Range.
- In the property sheet for the new range, set the Field property to User, and the Value property to (currentUserId()) as it appears.
- Save your changes to the query.
Creating a Security Policy
Follow these steps to create the security policy:
- In the AOT, expand the Security node.
- Right-click the Policies node and select New Security Policy.
- In the property sheet for the security policy, set the Name property to SmmBusRelUser, set the Label property to Limit Prospects by User, set the Primary Table property to HcmWorker, set the Query property to HcmWorkerUser, set the ContextType property to RoleName, set the RoleName property to TradeSalesRepresentative, and set the Enabled property to Yes.
- Expand the SmmBusRelUser security policy.
- Right-click the Constrained Tables node and select New > Add table by relation.
- In the property sheet for the new constrained table, set the Table property to smmBusRelTable, set the TableRelation property to MainContactWorker. Save your changes to the policy.
Now, if you were to login with the name of a sales person, you could see that you will only have access (view) your prospects because when creating the policy query we set the currentUserId() to the value of the query range. Also, because a user is related in DirPerson and DirPersonUser tables, the policy is able to associate the user id with records in the smmBusRelTable.
That is all for now, and stay tune for the next series of security for developers as I will go in detail on consuming a secured class and setting authorization for display methods.
Until then!
Thanksfor this explanation of XDS.
ReplyDeleteFYI, AX2012 also allows a security setup on teams that will limit access to the Global Address Book. You can therefore get the same result for the prospects without code :)
Cheers,
Nicholas
Nicholas,
ReplyDeleteThanks for sharing this with me (and the community). I will look into it as it sounds like a good option.
Thanks for reading my blog!
This comment has been removed by the author.
ReplyDeleteHi John Johnson,
ReplyDeletethank you for making me understanding the security policies.
There is a table method named xds(), Can you please let us know about that.
Hi,
DeleteThe xds method overwrites the xds method class.
I hope this helps.
"So, this is where all makes sense, if the data source property AllowDelete is set to No, the EffectiveAccess property is set to Update. If the data source property AllowEdit is set to No, the EffectiveAccess property is set to Read."
ReplyDeleteWell, no, all doesn't make sense.
1. The logic explains only how EffectiveAccess values of Update and Read are determined: so how are EffectiveAccess values of Create or Delete determined?
2. Why isn’t the AllowCreate property of a form data source involved in the calculation?
3. Assuming setting AllowDelete = Yes would set EffectiveAccess to Delete, then why would setting AllowDelete = No downgrade EffectiveAccess all the way to Update, bypassing the intervening Create level?
Hi,
DeleteYes, it all makes sense.
Thanks!
Works like a charm, I didn't replicate this problem exactly but thanks to this I managed to build all the XDS I wanted and understand how Queries work so thanks!
ReplyDeleteHi!
ReplyDeleteI've been having this error after building a query similar to yours:
"The number of joins in the statement is 30. This exceeds the maximum of 26. Turn on exception for this warning to see the call stack."
Do you have any clue as of where this might come from?
Thanks in advance!
Hi Magnus,
DeleteBarndon George has a good explanation of this. Check his post.
http://dynamics-ax.blogspot.com/2012/02/ax-2012-server-configuration.html
I hope this helps!
Can we restrict a table from being created from AOT?
ReplyDeleteGreat question, which I do not know the answer. Let me ask around. Thanks!
Delete