Access the Currently Logged User for Data Filtering, Business Logic, and Security Permissions
- 5 minutes to read
An application’s functionality may depend on the user who is logged on. You may need to obtain the user name, user ID, or entire user object. This topic describes how to do that in popular scenarios.
In .NET Applications
The following help topics describe how to use Dependency Injection to access an object that stores information about the current user:
- Access Object Space, Security System, Caption Helper, and XAF Modules in the ASP.NET Core Environment
- Access Object Space, Security System, and Caption Helper in Custom Endpoint Methods
In .NET Framework Applications
In .NET Framework Applications, you can use the following static properties exposed by the SecuritySystem class to access information about the current user:
- SecuritySystem.CurrentUserName
- SecuritySystem.CurrentUserId
- SecuritySystem.UserType
- SecuritySystem.CurrentUser
Note
ASP.NET classes (MVC controllers, Razor components) and Web API controllers cannot use these static properties.
Access Current User in Criteria
Use the CurrentUserId
function criteria operator to access the current user in a filter criterion.
Initialize the Object Owner (CreatedBy, UpdatedBy Properties)
To assign the current user reference to the CreatedBy
and UpdatedBy
properties of your business class, inherit your business class from BaseObject
and override the OnSaving
method. To set the property values, call the BaseObject.SetPropertyValueWithSecurityBypass method. This method allows you to modify the value of a business object’s property even if write access to this property is denied for the current user by the XAF Security System.
Important
CreatedBy
, UpdatedBy
, UpdatedOn
, CreatedOn
, and similar properties are supposed to be read-only in the UI for security and audit reasons (they can only be modified by developers in the program code). To make these properties read-only, set the AllowEdit
setting to false
for these properties through data annotation attributes (ModelDefault
, Browsable
, VisibleInXXX
). Depending on your security and UI customization requirements, you may want to add additional constraints. You can make sure that end users cannot display these properties or their sub-fields in the UI. To accomplish this, do the following:
- Turn off Customization Forms in ListView and DetailView completely.
- Hide unwanted properties in Customization Forms.
- Hide UI elements that add/remove fields in Customization Forms (allow access to predefined fields only).
The following code snippet demonstrates how to initialize a business object’s CreatedBy
and UpdatedBy
properties:
File: MySolution.Module/BusinessObjects/TestClass.cs
using DevExpress.ExpressApp.Model;
using DevExpress.ExpressApp.Security;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl.EF;
using Microsoft.Extensions.DependencyInjection;
// ...
public class TestClass : BaseObject {
// ...
[ModelDefault(nameof(IModelCommonMemberViewItem.AllowEdit), "False")]
public virtual ApplicationUser CreatedBy { get; set; }
[ModelDefault(nameof(IModelCommonMemberViewItem.AllowEdit), "False")]
public virtual ApplicationUser UpdatedBy { get; set; }
ApplicationUser GetCurrentUser() {
return ObjectSpace.GetObjectByKey<ApplicationUser>(
ObjectSpace.ServiceProvider.GetRequiredService<ISecurityStrategyBase>().UserId);
}
public override void OnSaving() {
base.OnSaving();
if (ObjectSpace.IsNewObject(this)) {
SetPropertyValueWithSecurityBypass(nameof(CreatedBy), GetCurrentUser());
}
else {
SetPropertyValueWithSecurityBypass(nameof(UpdatedBy), GetCurrentUser());
}
}
}
Initialize the Object Owner - Middle-Tier Security Specifics
In applications with middle-tier security, you need to take the following additional considerations into account:
- A business object’s
OnCreated
andAfterConstruction
methods are called on the client side, so property values initialized by these methods are available to the client application. Because of this, it is not secure to use these methods to initialize properties that store sensitive data (CreatedBy
,UpdatedBy
, and so on). - In cases when you need to initialize properties that store sensitive data, we strongly recommend that you always use the OnSaving method. This method is secure because it is called on the middle-tier server side only.
- In applications with middle tier security, the BaseObject.SetPropertyValueWithSecurityBypass method can only be called from the
OnSaving
method. Otherwise, an exception is thrown.
Configure Permissions Based on the Object Owner
To grant access to objects that are owned by the current user and prohibit access to other objects, implement the CreatedBy
property as demonstrated above, and configure the security permissions as follows:
- Add a Type Permission for the object type you wish to filter and set its
ReadState
property toDeny
or leave it empty if the role’s Permission Policy isDenyAllByDefault
. - Add an Object Permission that allows reading objects whose owner user’s ID matches
CurrentUserId()
.
File: MySolution.Module/DatabaseUpdate/Updater.cs
using DevExpress.ExpressApp.Security;
using DevExpress.ExpressApp.SystemModule;
// ...
defaultRole.AddTypePermission<TestClass>(SecurityOperations.Read, SecurityPermissionState.Deny);
defaultRole.AddObjectPermissionFromLambda<TestClass>(
SecurityOperations.Read,
e => e.CreatedBy.ID == (Guid)CurrentUserIdOperator.CurrentUserId(),
SecurityPermissionState.Allow
);
// or
// userRole.AddObjectPermission<Note>(SecurityOperations.Read,
// "CreatedBy.ID = CurrentUserId()", SecurityPermissionState.Allow);
For more information, refer to Create Predefined Users, Roles and Permissions in the Database.
To try the described technique in your application and add several users, run the application and create an object of your business class under different user accounts - only the currently logged-in user’s objects are displayed in the List View:
The following example implements a more complex use case scenario with cascading owner objects:
Check Security Permissions in Code
The following help topic describes how to check if a user has a specific role or permission to perform a certain operation: Determine if the Current User Has Specific Permissions.