/// <summary>
        /// In case of a delete command we always filter based on the tenantId
        /// </summary>
        private static void InterceptDeleteCommand(DbCommandTreeInterceptionContext interceptionContext, string userId)
        {
            var deleteCommand = interceptionContext.Result as DbDeleteCommandTree;

            if (deleteCommand != null)
            {
                var column = TenantAwareAttribute.GetTenantColumnName(deleteCommand.Target.VariableType.EdmType);
                if (!string.IsNullOrEmpty(column))
                {
                    // Create the variable reference in order to create the property
                    var variableReference = DbExpressionBuilder.Variable(deleteCommand.Target.VariableType,
                                                                         deleteCommand.Target.VariableName);
                    // Create the property to which will assign the correct value
                    var tenantProperty         = DbExpressionBuilder.Property(variableReference, column);
                    var tenantIdWherePredicate = DbExpressionBuilder.Equal(tenantProperty, DbExpression.FromString(userId));

                    // The initial predicate is the sql where statement
                    var initialPredicate = deleteCommand.Predicate;
                    // Add to the initial statement the tenantId statement which translates in sql AND TenantId = 'value'
                    var finalPredicate = initialPredicate.And(tenantIdWherePredicate);

                    var newDeleteCommand = new DbDeleteCommandTree(
                        deleteCommand.MetadataWorkspace,
                        deleteCommand.DataSpace,
                        deleteCommand.Target,
                        finalPredicate);

                    interceptionContext.Result = newDeleteCommand;
                }
            }
        }
Example #2
0
        /// <summary>
        /// This method called before the one below it when a filtering is already exists in the query (e.g. fetch an entity by id)
        /// so we apply the dynamic filtering at this level
        /// </summary>
        public override DbExpression Visit(DbFilterExpression expression)
        {
            var column = TenantAwareAttribute.GetTenantColumnName(expression.Input.Variable.ResultType.EdmType);

            if (!_injectedDynamicFilter && !string.IsNullOrEmpty(column))
            {
                var newFilterExpression = BuildFilterExpression(expression.Input, expression.Predicate, column);
                if (newFilterExpression != null)
                {
                    //  If not null, a new DbFilterExpression has been created with our dynamic filters.
                    return(base.Visit(newFilterExpression));
                }
            }
            return(base.Visit(expression));
        }
        /// <summary>
        /// In case of an update command we always filter based on the tenantId
        /// </summary>
        private static bool InterceptUpdate(DbCommandTreeInterceptionContext interceptionContext, string userId)
        {
            var updateCommand = interceptionContext.Result as DbUpdateCommandTree;

            if (updateCommand != null)
            {
                var column = TenantAwareAttribute.GetTenantColumnName(updateCommand.Target.VariableType.EdmType);
                if (!string.IsNullOrEmpty(column))
                {
                    // Create the variable reference in order to create the property
                    var variableReference = DbExpressionBuilder.Variable(updateCommand.Target.VariableType,
                                                                         updateCommand.Target.VariableName);
                    // Create the property to which will assign the correct value
                    var tenantProperty = DbExpressionBuilder.Property(variableReference, column);
                    // Create the tenantId where predicate, object representation of sql where tenantId = value statement
                    var tenantIdWherePredicate = DbExpressionBuilder.Equal(tenantProperty, DbExpression.FromString(userId));

                    // Remove potential assignment of tenantId for extra safety
                    var filteredSetClauses =
                        updateCommand.SetClauses.Cast <DbSetClause>()
                        .Where(sc => ((DbPropertyExpression)sc.Property).Property.Name != column);

                    // Construct the final clauses, object representation of sql insert command values
                    var finalSetClauses =
                        new ReadOnlyCollection <DbModificationClause>(new List <DbModificationClause>(filteredSetClauses));

                    // The initial predicate is the sql where statement
                    var initialPredicate = updateCommand.Predicate;
                    // Add to the initial statement the tenantId statement which translates in sql AND TenantId = 'value'
                    var finalPredicate = initialPredicate.And(tenantIdWherePredicate);

                    var newUpdateCommand = new DbUpdateCommandTree(
                        updateCommand.MetadataWorkspace,
                        updateCommand.DataSpace,
                        updateCommand.Target,
                        finalPredicate,
                        finalSetClauses,
                        updateCommand.Returning);

                    interceptionContext.Result = newUpdateCommand;
                    // True means an interception successfully happened so there is no need to continue
                    return(true);
                }
            }
            return(false);
        }
Example #4
0
        public override DbExpression Visit(DbScanExpression expression)
        {
            var column = TenantAwareAttribute.GetTenantColumnName(expression.Target.ElementType);

            if (!_injectedDynamicFilter && !string.IsNullOrEmpty(column))
            {
                // Get the current expression
                var dbExpression = base.Visit(expression);
                // Get the current expression binding
                var currentExpressionBinding = DbExpressionBuilder.Bind(dbExpression);
                var newFilterExpression      = BuildFilterExpression(currentExpressionBinding, null, column);
                if (newFilterExpression != null)
                {
                    //  If not null, a new DbFilterExpression has been created with our dynamic filters.
                    return(base.Visit(newFilterExpression));
                }
            }

            return(base.Visit(expression));
        }