The error occurs when a custom File Attachment class has a PersistentAlias property with the CurrentUserId function in its expression, and this property is used in Object Permissions.
C#[FileAttachment("File")]
public class UserFileAttachment : BaseObject {
//...
[PersistentAlias("Owner.Oid = CurrentUserId()")]
public bool IsCurrentUser {
get {
return (bool)EvaluateAlias(nameof(IsCurrentUser));
}
}
}
public class Updater : ModuleUpdater {
public override void UpdateDatabaseAfterUpdateSchema() {
//...
defaultRole.AddObjectPermissionFromLambda<UserFileAttachment>(SecurityOperations.Read, f => !f.IsCurrentUser, SecurityPermissionState.Deny);
//...
}
}
Steps to reproduce
- Run the attached project.
- Log in as 'User'.
- Go to My Details.
- Add a file to the Files collection.
- Download this file.
Current behavior
The file is not downloaded. The application throws the following exception:
System.InvalidOperationException: 'ValueManagerContext.Storage is null.'
Call StackDevExpress.ExpressApp.AspNetCore.v22.2.dll!DevExpress.ExpressApp.Blazor.AmbientContext.AspNetCoreValueManager<DevExpress.ExpressApp.Security.ISecurityStrategyBase>.CheckPossibleDeploymentIssues() Line 60 C# DevExpress.ExpressApp.AspNetCore.v22.2.dll!DevExpress.ExpressApp.Blazor.AmbientContext.AspNetCoreValueManager<DevExpress.ExpressApp.Security.ISecurityStrategyBase>.EnsureStorage() Line 55 C# DevExpress.ExpressApp.AspNetCore.v22.2.dll!DevExpress.ExpressApp.Blazor.AmbientContext.AspNetCoreValueManager<DevExpress.ExpressApp.Security.ISecurityStrategyBase>.Value.get() Line 52 C# DevExpress.ExpressApp.v22.2.dll!DevExpress.ExpressApp.SecuritySystem.Instance.get() Line 172 C# DevExpress.ExpressApp.v22.2.dll!DevExpress.ExpressApp.SecuritySystem.CurrentUserId.get() Line 177 C# DevExpress.ExpressApp.v22.2.dll!DevExpress.ExpressApp.SystemModule.CurrentUserIdOperator.Evaluate(object[] operands) Line 54 C# DevExpress.Data.v22.2.dll!DevExpress.Data.Filtering.Helpers.ExpressionEvaluator.EvaluateCustomFunction(string functionName, object[] operands) Line 1404 C# DevExpress.Data.v22.2.dll!DevExpress.Data.Filtering.Helpers.ExpressionEvaluatorCoreBase.FnCustom(DevExpress.Data.Filtering.FunctionOperator theOperator) Line 763 C# DevExpress.Data.v22.2.dll!DevExpress.Data.Filtering.Helpers.ExpressionEvaluatorCoreBase.Visit(DevExpress.Data.Filtering.FunctionOperator theOperator) Line 666 C# DevExpress.Data.v22.2.dll!DevExpress.Data.Filtering.FunctionOperator.Accept<object>(DevExpress.Data.Filtering.ICriteriaVisitor<object> visitor) Line 2800 C# DevExpress.Data.v22.2.dll!DevExpress.Data.Filtering.Helpers.ExpressionEvaluatorCoreBase.Process(DevExpress.Data.Filtering.CriteriaOperator operand) Line 527 C# DevExpress.Data.v22.2.dll!DevExpress.Data.Filtering.Helpers.ExpressionEvaluatorCoreBase.Evaluate(DevExpress.Data.Filtering.Helpers.EvaluatorContext evaluationContext, DevExpress.Data.Filtering.CriteriaOperator evaluatorCriteria, System.Collections.IComparer customComparer) Line 1144 C# DevExpress.Data.v22.2.dll!DevExpress.Data.Filtering.Helpers.ExpressionEvaluator.Evaluate(object theObject, System.Collections.IComparer customComparer) Line 1321 C# DevExpress.Data.v22.2.dll!DevExpress.Data.Filtering.Helpers.ExpressionEvaluator.Evaluate(object theObject) Line 1318 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.UnknownCriteriaEleminatorBase.Evaluate(DevExpress.Data.Filtering.CriteriaOperator theOperator) Line 588 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.UnknownCriteriaEleminatorBase.Visit(DevExpress.Data.Filtering.FunctionOperator theOperator) Line 344 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.PersistentCriterionExpander.Visit(DevExpress.Data.Filtering.FunctionOperator theOperator) Line 1212 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.StronglyTypedCriteriaVisitorBase<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder>.DevExpress.Data.Filtering.ICriteriaVisitor<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder>.Visit(DevExpress.Data.Filtering.FunctionOperator theOperator) Line 120 C# DevExpress.Data.v22.2.dll!DevExpress.Data.Filtering.FunctionOperator.Accept<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder>(DevExpress.Data.Filtering.ICriteriaVisitor<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder> visitor) Line 2800 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.UnknownCriteriaEleminatorBase.Process(DevExpress.Data.Filtering.CriteriaOperator operand) Line 583 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.UnknownCriteriaEleminatorBase.Visit(DevExpress.Data.Filtering.BinaryOperator theOperator) Line 527 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.PersistentCriterionExpander.Visit(DevExpress.Data.Filtering.BinaryOperator theOperator) Line 706 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.StronglyTypedCriteriaVisitorBase<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder>.DevExpress.Data.Filtering.ICriteriaVisitor<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder>.Visit(DevExpress.Data.Filtering.BinaryOperator theOperator) Line 135 C# DevExpress.Data.v22.2.dll!DevExpress.Data.Filtering.BinaryOperator.Accept<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder>(DevExpress.Data.Filtering.ICriteriaVisitor<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder> visitor) Line 2535 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.UnknownCriteriaEleminatorBase.Process(DevExpress.Data.Filtering.CriteriaOperator operand) Line 583 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.PersistentCriterionExpander.Expand(DevExpress.Xpo.Metadata.XPClassInfo[] upLevels, DevExpress.Xpo.Helpers.IPersistentValueExtractor persistentValuesSource, DevExpress.Data.Filtering.CriteriaOperator op, int aliasDepthWatchDog, bool doDetectPostProcessing) Line 1153 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.PersistentCriterionExpander.ProcessInContext(DevExpress.Xpo.Metadata.XPClassInfo[] upLevels, DevExpress.Data.Filtering.CriteriaOperator operand) Line 1150 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.PersistentCriterionExpander.Visit(DevExpress.Data.Filtering.OperandProperty theOriginalOperand) Line 928 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.StronglyTypedCriteriaVisitorBase<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder>.DevExpress.Data.Filtering.IClientCriteriaVisitor<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder>.Visit(DevExpress.Data.Filtering.OperandProperty theOperand) Line 111 C# DevExpress.Data.v22.2.dll!DevExpress.Data.Filtering.OperandProperty.Accept<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder>(DevExpress.Data.Filtering.ICriteriaVisitor<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder> visitor) Line 1871 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.UnknownCriteriaEleminatorBase.Process(DevExpress.Data.Filtering.CriteriaOperator operand) Line 583 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.UnknownCriteriaEleminatorBase.Visit(DevExpress.Data.Filtering.UnaryOperator theOperator) Line 492 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.StronglyTypedCriteriaVisitorBase<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder>.DevExpress.Data.Filtering.ICriteriaVisitor<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder>.Visit(DevExpress.Data.Filtering.UnaryOperator theOperator) Line 132 C# DevExpress.Data.v22.2.dll!DevExpress.Data.Filtering.UnaryOperator.Accept<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder>(DevExpress.Data.Filtering.ICriteriaVisitor<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder> visitor) Line 2681 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.UnknownCriteriaEleminatorBase.Process(DevExpress.Data.Filtering.CriteriaOperator operand) Line 583 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.UnknownCriteriaEleminatorBase.Visit(DevExpress.Data.Filtering.UnaryOperator theOperator) Line 492 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.StronglyTypedCriteriaVisitorBase<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder>.DevExpress.Data.Filtering.ICriteriaVisitor<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder>.Visit(DevExpress.Data.Filtering.UnaryOperator theOperator) Line 132 C# DevExpress.Data.v22.2.dll!DevExpress.Data.Filtering.UnaryOperator.Accept<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder>(DevExpress.Data.Filtering.ICriteriaVisitor<DevExpress.Xpo.Helpers.ExpandedCriteriaHolder> visitor) Line 2681 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.UnknownCriteriaEleminatorBase.Process(DevExpress.Data.Filtering.CriteriaOperator operand) Line 583 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.PersistentCriterionExpander.Expand(DevExpress.Xpo.Metadata.XPClassInfo[] upLevels, DevExpress.Xpo.Helpers.IPersistentValueExtractor persistentValuesSource, DevExpress.Data.Filtering.CriteriaOperator op, int aliasDepthWatchDog, bool doDetectPostProcessing) Line 1153 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.PersistentCriterionExpander.Expand(DevExpress.Xpo.Metadata.XPClassInfo[] upLevels, DevExpress.Xpo.Helpers.IPersistentValueExtractor persistentValuesSource, DevExpress.Data.Filtering.CriteriaOperator op, bool doDetectPostProcessing) Line 1156 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.PersistentCriterionExpander.Expand(DevExpress.Xpo.Metadata.XPClassInfo ci, DevExpress.Xpo.Helpers.IPersistentValueExtractor persistentValuesSource, DevExpress.Data.Filtering.CriteriaOperator op, bool doDetectPostProcessing) Line 1197 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.PersistentCriterionExpander.Expand(DevExpress.Xpo.Helpers.IPersistentValueExtractor persistentValuesSource, DevExpress.Xpo.Metadata.XPClassInfo ci, DevExpress.Data.Filtering.CriteriaOperator op, bool doDetectPostProcessing) Line 1203 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.SecurityContext.Expand(DevExpress.Xpo.Metadata.XPClassInfo classInfo, DevExpress.Data.Filtering.CriteriaOperator op) Line 159 C# DevExpress.ExpressApp.Security.Xpo.v22.2.dll!DevExpress.ExpressApp.Security.ClientServer.SecurityRule2.GetSelectMemberExpression(DevExpress.Xpo.SecurityContext context, DevExpress.Xpo.Metadata.XPClassInfo classInfo, DevExpress.Xpo.Metadata.XPMemberInfo memberInfo, out DevExpress.Data.Filtering.CriteriaOperator expression) Line 354 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.SecurityContext.GetSelectMemberExpression(DevExpress.Xpo.ISecurityRule2 rule, DevExpress.Xpo.Metadata.XPClassInfo ci, DevExpress.Xpo.Metadata.XPMemberInfo mi, out DevExpress.Data.Filtering.CriteriaOperator memberExpression) Line 200 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.SecurityContext.GetSelectMemberExpression(DevExpress.Xpo.Metadata.XPClassInfo ci, DevExpress.Xpo.Metadata.XPMemberInfo mi, out DevExpress.Data.Filtering.CriteriaOperator memberExpression) Line 220 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.NestedLoader.GetProcessedGroup(DevExpress.Xpo.Metadata.XPClassInfo classInfo, System.Collections.Generic.IDictionary<DevExpress.Xpo.Metadata.XPClassInfo, DevExpress.Xpo.Helpers.NestedLoader.ObjectGroup> processed) Line 249 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.NestedLoader.BeginCloneObjects(DevExpress.Xpo.Helpers.ObjectDictionary<object> processedPairs, System.Collections.Generic.List<object> toFireLoaded, System.Collections.Generic.IDictionary<DevExpress.Xpo.Metadata.XPClassInfo, DevExpress.Xpo.Helpers.NestedLoader.ObjectGroup> processed) Line 236 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.NestedLoader.BeginProcessParentObjectsForGetNestedObjectsCore(System.Collections.ICollection[] parentObjects, bool[] force, DevExpress.Xpo.Helpers.ObjectDictionary<object> processedPairs, System.Collections.Generic.List<object> toFireLoaded, System.Collections.Generic.IDictionary<DevExpress.Xpo.Metadata.XPClassInfo, DevExpress.Xpo.Helpers.NestedLoader.ObjectGroup> processed) Line 579 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.NestedLoader.BeginProcessParentObjectsForGetNestedObjects(System.Collections.ICollection[] parentObjects, bool[] force, DevExpress.Xpo.Helpers.ObjectDictionary<object> processedPairs, System.Collections.Generic.List<object> toFireLoaded, System.Collections.Generic.IDictionary<DevExpress.Xpo.Metadata.XPClassInfo, DevExpress.Xpo.Helpers.NestedLoader.ObjectGroup> processed) Line 547 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.NestedLoader.ProcessParentObjectsForGetNestedObjects(System.Collections.ICollection[] parentObjects, bool[] force, System.Collections.Generic.List<object> outObjectsToFireLoaded) Line 510 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.NestedLoader.GetNestedObjectsCore(System.Collections.ICollection[] parentObjects, bool[] force, System.Collections.Generic.List<object> outObjectsToFireLoaded) Line 497 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Helpers.NestedLoader.GetNestedObjects(System.Collections.ICollection[] parentObjects, bool[] force) Line 473 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.SessionObjectLayer.GetObjectsByKey(DevExpress.Xpo.Session session, DevExpress.Xpo.ObjectsByKeyQuery[] queries) Line 956 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Session.GetObjectByKey.AnonymousMethod__0() Line 3015 C# DevExpress.Data.v22.2.dll!DevExpress.Xpo.Logger.LogManager.Log<object>(string category, DevExpress.Xpo.Logger.LogManager.LogHandler<object> handler, DevExpress.Xpo.Logger.LogManager.MessageHandler<DevExpress.Xpo.Logger.LogMessage> createMessageHandler) Line 199 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Session.GetObjectByKey(DevExpress.Xpo.Metadata.XPClassInfo classInfo, object id, bool alwaysGetFromDataStore) Line 3006 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Session.GetObjectByKey(DevExpress.Xpo.Metadata.XPClassInfo classInfo, object id) Line 2787 C# DevExpress.Xpo.v22.2.dll!DevExpress.Xpo.Session.GetObjectByKey(System.Type classType, object id) Line 2784 C# DevExpress.ExpressApp.Xpo.v22.2.dll!DevExpress.ExpressApp.Xpo.XPObjectSpace.GetObjectByKey(System.Type objectType, object key) Line 686 C# DevExpress.ExpressApp.AspNetCore.v22.2.dll!DevExpress.ExpressApp.AspNetCore.Streaming.StreamService.GetFileStream(DevExpress.ExpressApp.DC.ITypeInfo typeInfo, string objectKey, string propertyName) Line 77 C# DevExpress.ExpressApp.Blazor.v22.2.dll!DevExpress.ExpressApp.AspNetCore.Streaming.FileService.GetFileStream(string objectType, string objectKey, string propertyName) Line 66 C# DevExpress.ExpressApp.Blazor.v22.2.dll!DevExpress.ExpressApp.AspNetCore.Streaming.FileService.GetFile(string objectType, string objectKey, string propertyName) Line 60 C# DevExpress.ExpressApp.Blazor.v22.2.dll!DevExpress.ExpressApp.Blazor.Services.FileDataResourcesMiddleware.Invoke(Microsoft.AspNetCore.Http.HttpContext context, DevExpress.ExpressApp.AspNetCore.Streaming.IFileService fileService) Line 94 C#
Workaround
Replace PersistentAlias properties with their expressions in Object and Member permissions:
C#//defaultRole.AddObjectPermissionFromLambda<UserFileAttachment>(SecurityOperations.Read, f => !f.IsCurrentUser, SecurityPermissionState.Deny);
defaultRole.AddObjectPermissionFromLambda<UserFileAttachment>(SecurityOperations.Read, f => f.Owner.Oid != (Guid)CurrentUserIdOperator.CurrentUserId(), SecurityPermissionState.Deny);
Hello,
An additional workaround without changing a criterion is applicable to the FileService service. You can use the solution with a custom IObjectSpaceFactoryWrapper instance described here: T1120269 - Urgent: ValueManagerContext.Storage is null in 22.1.5.
I created a separate ticket for further investigation and discussion: T1147982 - Security.Blazor - "ValueManagerContext.Storage is null" error occurs when a custom function criteria operator is not processed by the SecurityFunctionPatcher logic. We will publish all further updates there.