예제 #1
0
 /// <summary>
 /// Checks to see if the person is authorized to VIEW
 /// </summary>
 /// <param name="securedModel">The secured model.</param>
 /// <param name="person">The person.</param>
 /// <exception cref="System.Web.Http.HttpResponseException">
 /// </exception>
 protected virtual void CheckCanView(ISecured securedModel, Person person)
 {
     if (securedModel != null)
     {
         if (IsProxy(securedModel))
         {
             if (!securedModel.IsAuthorized(Rock.Security.Authorization.VIEW, person))
             {
                 throw new HttpResponseException(HttpStatusCode.Unauthorized);
             }
         }
         else
         {
             // Need to reload using service with a proxy enabled so that if model has custom
             // parent authorities, those properties can be lazy-loaded and checked for authorization
             SetProxyCreation(true);
             ISecured reloadedModel = (ISecured)Service.Get(securedModel.Id);
             if (reloadedModel != null && !reloadedModel.IsAuthorized(Rock.Security.Authorization.VIEW, person))
             {
                 throw new HttpResponseException(HttpStatusCode.Unauthorized);
             }
         }
     }
 }
예제 #2
0
        /// <summary>
        /// Raises the <see cref="E:System.Web.UI.Control.Init" /> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs" /> object that contains the event data.</param>
        protected override void OnInit(EventArgs e)
        {
            int?   entityTypeId   = PageParameter("EntityTypeId").AsIntegerOrNull();
            string entityTypeName = string.Empty;
            Type   type           = null;

            // Get Entity Type
            if (entityTypeId.HasValue)
            {
                var entityType = EntityTypeCache.Read(entityTypeId.Value);
                if (entityType != null)
                {
                    entityTypeName = entityType.FriendlyName;
                    type           = entityType.GetEntityType();
                }
            }

            // Get Entity Id
            int entityId = PageParameter("EntityId").AsIntegerOrNull() ?? 0;

            // Get object type
            if (type != null)
            {
                if (entityId == 0)
                {
                    iSecured = (ISecured)Activator.CreateInstance(type);
                }
                else
                {
                    // Get the context type since this may be for a non-rock core object
                    Type contextType = null;
                    var  contexts    = Rock.Reflection.SearchAssembly(type.Assembly, typeof(Rock.Data.DbContext));
                    if (contexts.Any())
                    {
                        contextType = contexts.First().Value;
                    }
                    else
                    {
                        contextType = typeof(RockContext);
                    }

                    Type   serviceType = typeof(Rock.Data.Service <>);
                    Type[] modelType   = { type };
                    Type   service     = serviceType.MakeGenericType(modelType);
                    var    getMethod   = service.GetMethod("Get", new Type[] { typeof(int) });

                    var context         = Activator.CreateInstance(contextType);
                    var serviceInstance = Activator.CreateInstance(service, new object[] { context });
                    iSecured = getMethod.Invoke(serviceInstance, new object[] { entityId }) as ISecured;
                }

                var block = iSecured as Rock.Model.Block;
                if (block != null)
                {
                    // If the entity is a block, get any actions that were updated or added by the block type using
                    // one or more SecurityActionAttributes.
                    var blockCache = BlockCache.Read(block.Id);
                    if (blockCache != null && blockCache.BlockType != null)
                    {
                        foreach (var action in BlockCache.Read(block.Id).BlockType.SecurityActions)
                        {
                            if (block.SupportedActions.ContainsKey(action.Key))
                            {
                                block.SupportedActions[action.Key] = action.Value;
                            }
                            else
                            {
                                block.SupportedActions.Add(action.Key, action.Value);
                            }
                        }
                    }

                    iSecured = block;
                }

                if (iSecured != null)
                {
                    if (iSecured.IsAuthorized(Authorization.ADMINISTRATE, CurrentPerson))
                    {
                        if (iSecured.SupportedActions.Any())
                        {
                            lActionDescription.Text = iSecured.SupportedActions.FirstOrDefault().Value;
                        }

                        rptActions.DataSource = iSecured.SupportedActions;
                        rptActions.DataBind();

                        rGrid.DataKeyNames        = new string[] { "Id" };
                        rGrid.GridReorder        += new GridReorderEventHandler(rGrid_GridReorder);
                        rGrid.GridRebind         += new GridRebindEventHandler(rGrid_GridRebind);
                        rGrid.RowDataBound       += new GridViewRowEventHandler(rGrid_RowDataBound);
                        rGrid.ShowHeaderWhenEmpty = false;
                        rGrid.EmptyDataText       = string.Empty;
                        rGrid.ShowActionRow       = false;

                        rGridParentRules.DataKeyNames        = new string[] { "Id" };
                        rGridParentRules.ShowHeaderWhenEmpty = false;
                        rGridParentRules.EmptyDataText       = string.Empty;
                        rGridParentRules.ShowActionRow       = false;

                        BindRoles();

                        string scriptFormat = @"
                    Sys.Application.add_load(function () {{
                        $('#modal-popup div.modal-header h3 small', window.parent.document).html('{0}');
                    }});
                ";
                        string script       = string.Format(scriptFormat, HttpUtility.JavaScriptStringEncode(iSecured.ToString()));

                        this.Page.ClientScript.RegisterStartupScript(this.GetType(), string.Format("set-html-{0}", this.ClientID), script, true);
                    }
                    else
                    {
                        nbMessage.Text = "Unfortunately, you are not able to edit security because you do not belong to a role that has been configured to allow administration of this item.";
                    }
                }
                else
                {
                    nbMessage.Text = "The item you are trying to secure does not exist or does not implement ISecured.";
                }
            }
            else
            {
                nbMessage.Text = string.Format("The requested entity type ('{0}') could not be loaded to determine security attributes.", entityTypeName);
            }

            base.OnInit(e);
        }
예제 #3
0
        /// <summary>
        /// Renders the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="result">The result.</param>
        /// <exception cref="System.Exception">Your Lava command must contain at least one valid filter. If you configured a filter it's possible that the property or attribute you provided does not exist.</exception>
        public override void Render(Context context, TextWriter result)
        {
            // first ensure that entity commands are allowed in the context
            if (!this.IsAuthorized(context))
            {
                result.Write(string.Format(RockLavaBlockBase.NotAuthorizedMessage, this.Name));
                base.Render(context, result);
                return;
            }

            bool hasFilter = false;

            var modelName = string.Empty;

            // get a service for the entity based off it's friendly name
            if (_entityName == "business")
            {
                modelName = "Rock.Model.Person";
            }
            else
            {
                modelName = "Rock.Model." + _entityName;
            }

            // Check first to see if this is a core model. use the createIfNotFound = false option
            var entityTypeCache = EntityTypeCache.Get(modelName, false);

            if (entityTypeCache == null)
            {
                var entityTypes = EntityTypeCache.All();

                // If not, look for first plug-in model that has same friendly name
                entityTypeCache = entityTypes
                                  .Where(e =>
                                         e.IsEntity &&
                                         !e.Name.StartsWith("Rock.Model") &&
                                         e.FriendlyName != null &&
                                         e.FriendlyName.RemoveSpaces().ToLower() == _entityName)
                                  .OrderBy(e => e.Id)
                                  .FirstOrDefault();

                // If still null check to see if this was a duplicate class and full class name was used as entity name
                if (entityTypeCache == null)
                {
                    modelName       = _entityName.Replace('_', '.');
                    entityTypeCache = entityTypes.Where(e => String.Equals(e.Name, modelName, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
                }
            }

            if (entityTypeCache != null)
            {
                Type entityType = entityTypeCache.GetEntityType();
                if (entityType != null)
                {
                    // Get the appropriate database context for this entity type.
                    // Note that this may be different from the standard RockContext if the entity is sourced from a plug-in.
                    var dbContext = Reflection.GetDbContextForEntityType(entityType);

                    // Check if there is a RockContext in the Lava context. If so then use the RockContext passed in.
                    if (dbContext is RockContext)
                    {
                        var lavaContext = context.Registers["RockContext"];

                        if (lavaContext.IsNotNull())
                        {
                            dbContext = (DbContext)lavaContext;
                        }
                    }

                    // Disable change-tracking for this data context to improve performance - objects supplied to a Lava context are read-only.
                    dbContext.Configuration.AutoDetectChangesEnabled = false;

                    // Create an instance of the entity's service
                    IService serviceInstance = Reflection.GetServiceForEntityType(entityType, dbContext);

                    ParameterExpression paramExpression = Expression.Parameter(entityType, "x");
                    Expression          queryExpression = null; // the base expression we'll use to build our query from

                    // Parse markup
                    var parms = ParseMarkup(_markup, context);

                    if (parms.Any(p => p.Key == "id"))
                    {
                        string propertyName = "Id";

                        List <string> selectionParms = new List <string>();
                        selectionParms.Add(PropertyComparisonConversion("==").ToString());
                        selectionParms.Add(parms["id"].ToString());
                        selectionParms.Add(propertyName);

                        var entityProperty = entityType.GetProperty(propertyName);
                        queryExpression = ExpressionHelper.PropertyFilterExpression(selectionParms, paramExpression, propertyName, entityProperty.PropertyType);

                        hasFilter = true;
                    }
                    else
                    {
                        // where clause expression
                        if (parms.Any(p => p.Key == "where"))
                        {
                            queryExpression = ParseWhere(parms["where"], entityType, serviceInstance, paramExpression, entityType, entityTypeCache);

                            if (queryExpression != null)
                            {
                                hasFilter = true;
                            }
                        }

                        // DataView expression
                        if (parms.Any(p => p.Key == "dataview"))
                        {
                            var dataViewId = parms["dataview"].AsIntegerOrNull();

                            if (dataViewId.HasValue)
                            {
                                var dataViewExpression = GetDataViewExpression(dataViewId.Value, serviceInstance, paramExpression, entityTypeCache);

                                if (queryExpression == null)
                                {
                                    queryExpression = dataViewExpression;
                                    hasFilter       = true;
                                }
                                else
                                {
                                    queryExpression = Expression.AndAlso(queryExpression, dataViewExpression);
                                }
                            }
                        }

                        // process dynamic filter expressions (from the query string)
                        if (parms.Any(p => p.Key == "dynamicparameters"))
                        {
                            var dynamicFilters = parms["dynamicparameters"].Split(',')
                                                 .Select(x => x.Trim())
                                                 .Where(x => !string.IsNullOrWhiteSpace(x))
                                                 .ToList();

                            foreach (var dynamicFilter in dynamicFilters)
                            {
                                var dynamicFilterValue      = HttpContext.Current.Request[dynamicFilter];
                                var dynamicFilterExpression = GetDynamicFilterExpression(dynamicFilter, dynamicFilterValue, entityType, serviceInstance, paramExpression);
                                if (dynamicFilterExpression != null)
                                {
                                    if (queryExpression == null)
                                    {
                                        queryExpression = dynamicFilterExpression;
                                        hasFilter       = true;
                                    }
                                    else
                                    {
                                        queryExpression = Expression.AndAlso(queryExpression, dynamicFilterExpression);
                                    }
                                }
                            }
                        }
                    }

                    // Make the query from the expression.

                    /* [2020-10-08] DL
                     * "Get" is intentionally used here rather than "GetNoTracking" to allow lazy-loading of navigation properties from the Lava context.
                     * (Refer https://github.com/SparkDevNetwork/Rock/issues/4293)
                     */
                    MethodInfo getMethod = serviceInstance.GetType().GetMethod("Get", new Type[] { typeof(ParameterExpression), typeof(Expression), typeof(Rock.Web.UI.Controls.SortProperty), typeof(int?) });

                    if (getMethod != null)
                    {
                        // get a listing of ids and build it into the query expression
                        if (parms.Any(p => p.Key == "ids"))
                        {
                            List <int>         value = parms["ids"].ToString().Split(',').Select(int.Parse).ToList();
                            MemberExpression   propertyExpression = Expression.Property(paramExpression, "Id");
                            ConstantExpression constantExpression = Expression.Constant(value, typeof(List <int>));
                            Expression         containsExpression = Expression.Call(constantExpression, typeof(List <int>).GetMethod("Contains", new Type[] { typeof(int) }), propertyExpression);
                            if (queryExpression != null)
                            {
                                queryExpression = Expression.AndAlso(queryExpression, containsExpression);
                            }
                            else
                            {
                                queryExpression = containsExpression;
                            }

                            hasFilter = true;
                        }

                        var getResult   = getMethod.Invoke(serviceInstance, new object[] { paramExpression, queryExpression, null, null });
                        var queryResult = getResult as IQueryable <IEntity>;

                        // process entity specific filters
                        switch (_entityName)
                        {
                        case "person":
                        {
                            queryResult = PersonFilters((IQueryable <Person>)queryResult, parms);
                            break;
                        }

                        case "business":
                        {
                            queryResult = BusinessFilters((IQueryable <Person>)queryResult, parms);
                            break;
                        }
                        }

                        // if there was a dynamic expression add it now
                        if (parms.Any(p => p.Key == "expression"))
                        {
                            queryResult = queryResult.Where(parms["expression"]);
                            hasFilter   = true;
                        }

                        var queryResultExpression = queryResult.Expression;

                        // add sort expressions
                        if (parms.Any(p => p.Key == "sort"))
                        {
                            string orderByMethod = "OrderBy";

                            foreach (var column in parms["sort"].Split(',').Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList())
                            {
                                string propertyName;
                                var    direction = SortDirection.Ascending;

                                if (column.EndsWith(" desc", StringComparison.OrdinalIgnoreCase))
                                {
                                    direction    = SortDirection.Descending;
                                    propertyName = column.Left(column.Length - 5);
                                }
                                else
                                {
                                    propertyName = column;
                                }

                                string methodName = direction == SortDirection.Descending ? orderByMethod + "Descending" : orderByMethod;

                                if (entityType.GetProperty(propertyName) != null)
                                {
                                    // sorting a entity property
                                    var memberExpression          = Expression.Property(paramExpression, propertyName);
                                    LambdaExpression sortSelector = Expression.Lambda(memberExpression, paramExpression);
                                    queryResultExpression = Expression.Call(typeof(Queryable), methodName, new Type[] { queryResult.ElementType, sortSelector.ReturnType }, queryResultExpression, sortSelector);
                                }
                                else
                                {
                                    // sorting on an attribute

                                    // get attribute id
                                    int?attributeId = null;
                                    foreach (var attribute in AttributeCache.GetByEntityType(entityTypeCache.Id))
                                    {
                                        if (attribute.Key == propertyName)
                                        {
                                            attributeId = attribute.Id;
                                            break;
                                        }
                                    }

                                    if (attributeId.HasValue)
                                    {
                                        // get AttributeValue queryable and parameter
                                        if (dbContext is RockContext)
                                        {
                                            var attributeValues = new AttributeValueService(dbContext as RockContext).Queryable();
                                            ParameterExpression attributeValueParameter = Expression.Parameter(typeof(AttributeValue), "v");
                                            MemberExpression    idExpression            = Expression.Property(paramExpression, "Id");
                                            var attributeExpression = Attribute.Helper.GetAttributeValueExpression(attributeValues, attributeValueParameter, idExpression, attributeId.Value);

                                            LambdaExpression sortSelector = Expression.Lambda(attributeExpression, paramExpression);
                                            queryResultExpression = Expression.Call(typeof(Queryable), methodName, new Type[] { queryResult.ElementType, sortSelector.ReturnType }, queryResultExpression, sortSelector);
                                        }
                                        else
                                        {
                                            throw new Exception(string.Format("The database context for type {0} does not support RockContext attribute value queries.", entityTypeCache.FriendlyName));
                                        }
                                    }
                                }

                                orderByMethod = "ThenBy";
                            }
                        }

                        // check to ensure we had some form of filter (otherwise we'll return all results in the table)
                        if (!hasFilter)
                        {
                            throw new Exception("Your Lava command must contain at least one valid filter. If you configured a filter it's possible that the property or attribute you provided does not exist.");
                        }

                        // reassemble the queryable with the sort expressions
                        queryResult = queryResult.Provider.CreateQuery(queryResultExpression) as IQueryable <IEntity>;

                        if (parms.GetValueOrNull("count").AsBoolean())
                        {
                            int countResult = queryResult.Count();
                            context.Scopes.Last()["count"] = countResult;
                        }
                        else
                        {
                            // Run security check on each result if enabled and entity is not a person (we do not check security on people)
                            if (parms["securityenabled"].AsBoolean() && _entityName != "person")
                            {
                                var items        = queryResult.ToList();
                                var itemsSecured = new List <IEntity>();

                                Person person = GetCurrentPerson(context);

                                foreach (IEntity item in items)
                                {
                                    ISecured itemSecured = item as ISecured;
                                    if (itemSecured == null || itemSecured.IsAuthorized(Authorization.VIEW, person))
                                    {
                                        itemsSecured.Add(item);

                                        /*
                                         *      8/13/2020 - JME
                                         *      It might seem logical to break out of the loop if there is limit parameter provided once the
                                         *  limit is reached. This though has two issues.
                                         *
                                         *  FIRST
                                         *  Depending how it was implemented it can have the effect of breaking when an offset is
                                         *  provided.
                                         *          {% contentchannelitem where:'ContentChannelId == 1' limit:'3' %}
                                         *          {% for item in contentchannelitemItems %}
                                         *              {{ item.Id }} - {{ item.Title }}<br>
                                         *          {% endfor %}
                                         *      {% endcontentchannelitem %}
                                         *  Returns 3 items (correct)
                                         *
                                         *      {% contentchannelitem where:'ContentChannelId == 1' limit:'3' offset:'1' %}
                                         *          {% for item in contentchannelitemItems %}
                                         *              {{ item.Id }} - {{ item.Title }}<br>
                                         *          {% endfor %}
                                         *      {% endcontentchannelitem %}
                                         *  Returns only 2 items (incorrect) - because of the offset
                                         *
                                         *  SECOND
                                         *  If the limit is moved before the security check it's possible that the security checks
                                         *  will remove items and will therefore not give you the amount of items that you asked for.
                                         *
                                         *  Unfortunately this has to be an inefficent process to ensure pagination works. I will also
                                         *  add a detailed note to the documentation to encourage people to disable security checks,
                                         *  especially when used with pagination, in the Lava docs.
                                         */
                                    }
                                }

                                queryResult = itemsSecured.AsQueryable();
                            }

                            // offset
                            if (parms.Any(p => p.Key == "offset"))
                            {
                                queryResult = queryResult.Skip(parms["offset"].AsInteger());
                            }

                            // limit, default to 1000
                            if (parms.Any(p => p.Key == "limit"))
                            {
                                queryResult = queryResult.Take(parms["limit"].AsInteger());
                            }
                            else
                            {
                                queryResult = queryResult.Take(1000);
                            }

                            var resultList = queryResult.ToList();

                            // if there is only one item to return set an alternative non-array based variable
                            if (resultList.Count == 1)
                            {
                                context.Scopes.Last()[_entityName] = resultList.FirstOrDefault();
                            }

                            context.Scopes.Last()[parms["iterator"]] = resultList;
                        }
                    }
                }
            }
            else
            {
                result.Write(string.Format("Could not find a model for {0}.", _entityName));
                base.Render(context, result);
            }

            base.Render(context, result);
        }
예제 #4
0
        protected override void OnInit(EventArgs e)
        {
            string entityParam = PageParameter("EntityTypeId");
            Type   type        = null;

            // Get Entity Type
            int entityTypeId = 0;

            if (Int32.TryParse(entityParam, out entityTypeId))
            {
                var entityType = EntityTypeCache.Read(entityTypeId);
                if (entityType != null)
                {
                    entityParam = entityType.FriendlyName;
                    type        = entityType.GetEntityType();
                }
            }

            // Get Entity Id
            int entityId = 0;

            if (!Int32.TryParse(PageParameter("EntityId"), out entityId))
            {
                entityId = 0;
            }

            // Get object type
            if (type != null)
            {
                if (entityId == 0)
                {
                    iSecured = (ISecured)Activator.CreateInstance(type);
                }
                else
                {
                    // Get the context type since this may be for a non-rock core object
                    Type contextType = null;
                    var  contexts    = Rock.Reflection.SearchAssembly(type.Assembly, typeof(System.Data.Entity.DbContext));
                    if (contexts.Any())
                    {
                        contextType = contexts.First().Value;
                    }

                    Type   serviceType = typeof(Rock.Data.Service <>);
                    Type[] modelType   = { type };
                    Type   service     = serviceType.MakeGenericType(modelType);
                    var    getMethod   = service.GetMethod("Get", new Type[] { typeof(int) });

                    if (contextType != null)
                    {
                        var context         = Activator.CreateInstance(contextType);
                        var serviceInstance = Activator.CreateInstance(service, new object[] { context });
                        iSecured = getMethod.Invoke(serviceInstance, new object[] { entityId }) as ISecured;
                    }
                    else
                    {
                        var serviceInstance = Activator.CreateInstance(service);
                        iSecured = getMethod.Invoke(serviceInstance, new object[] { entityId }) as ISecured;
                    }
                }

                var block = iSecured as Rock.Model.Block;
                if (block != null)
                {
                    // If the entity is a block, get the cachedblock's supported action, as the RockPage may have
                    // added additional actions when the cache was created.
                    foreach (var action in BlockCache.Read(block.Id).SupportedActions)
                    {
                        if (!block.SupportedActions.Contains(action))
                        {
                            block.SupportedActions.Add(action);
                        }
                    }

                    iSecured = block;
                }

                if (iSecured != null && iSecured.IsAuthorized("Administrate", CurrentPerson))
                {
                    rptActions.DataSource = iSecured.SupportedActions;
                    rptActions.DataBind();

                    rGrid.DataKeyNames        = new string[] { "id" };
                    rGrid.GridReorder        += new GridReorderEventHandler(rGrid_GridReorder);
                    rGrid.GridRebind         += new GridRebindEventHandler(rGrid_GridRebind);
                    rGrid.RowDataBound       += new GridViewRowEventHandler(rGrid_RowDataBound);
                    rGrid.ShowHeaderWhenEmpty = false;
                    rGrid.EmptyDataText       = string.Empty;
                    rGrid.ShowActionRow       = false;

                    rGridParentRules.DataKeyNames        = new string[] { "id" };
                    rGridParentRules.ShowHeaderWhenEmpty = false;
                    rGridParentRules.EmptyDataText       = string.Empty;
                    rGridParentRules.ShowActionRow       = false;

                    BindRoles();

                    string script = string.Format(@"
                    Sys.Application.add_load(function () {{
                        $('#modal-popup div.modal-header h3 small', window.parent.document).html('{0}');
                    }});
                ", HttpUtility.JavaScriptStringEncode(iSecured.ToString()));
                    this.Page.ClientScript.RegisterStartupScript(this.GetType(), string.Format("set-html-{0}", this.ClientID), script, true);
                }
                else
                {
                    rGrid.Visible            = false;
                    rGridParentRules.Visible = false;
                    nbMessage.Text           = "Unfortunately, you are not able to edit security because you do not belong to a role that has been configured to allow administration of this item.";
                    nbMessage.Visible        = true;
                }
            }
            else
            {
                rGrid.Visible            = false;
                rGridParentRules.Visible = false;
                nbMessage.Text           = string.Format("The requested entity type ('{0}') could not be loaded to determine security attributes.", entityParam);
                nbMessage.Visible        = true;
            }
            base.OnInit(e);
        }
예제 #5
0
        /// <summary>
        /// Renders the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="result">The result.</param>
        /// <exception cref="System.Exception">Your Lava command must contain at least one valid filter. If you configured a filter it's possible that the property or attribute you provided does not exist.</exception>
        public override void Render(Context context, TextWriter result)
        {
            // first ensure that entity commands are allowed in the context
            if (!this.IsAuthorized(context))
            {
                result.Write(string.Format(RockLavaBlockBase.NotAuthorizedMessage, this.Name));
                base.Render(context, result);
                return;
            }

            bool hasFilter = false;

            // get a service for the entity based off it's friendly name
            var entityTypes = EntityTypeCache.All();

            var model = string.Empty;

            if (_entityName == "business")
            {
                model = "Rock.Model.Person";
            }
            else
            {
                model = "Rock.Model." + _entityName;
            }

            // Check first to see if this is a core model
            var entityTypeCache = entityTypes.Where(e => String.Equals(e.Name, model, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

            // If not, look for first plugin model that has same friendly name
            if (entityTypeCache == null)
            {
                entityTypeCache = entityTypes
                                  .Where(e =>
                                         e.IsEntity &&
                                         !e.Name.StartsWith("Rock.Model") &&
                                         e.FriendlyName != null &&
                                         e.FriendlyName.RemoveSpaces().ToLower() == _entityName)
                                  .OrderBy(e => e.Id)
                                  .FirstOrDefault();
            }

            // If still null check to see if this was a duplicate class and full class name was used as entity name
            if (entityTypeCache == null)
            {
                model           = _entityName.Replace('_', '.');
                entityTypeCache = entityTypes.Where(e => String.Equals(e.Name, model, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
            }

            if (entityTypeCache != null)
            {
                Type entityType = entityTypeCache.GetEntityType();
                if (entityType != null)
                {
                    // Get the database context
                    Type contextType = null;
                    Rock.Data.DbContext dbContext = null;
                    var contexts = Rock.Reflection.SearchAssembly(entityType.Assembly, typeof(Rock.Data.DbContext));
                    if (contexts.Any())
                    {
                        contextType = contexts.First().Value;
                        dbContext   = Activator.CreateInstance(contextType) as Rock.Data.DbContext;
                    }
                    if (dbContext == null)
                    {
                        dbContext = _rockContext;
                    }

                    // create an instance of the entity's service
                    Type[]             modelType          = { entityType };
                    Type               genericServiceType = typeof(Rock.Data.Service <>);
                    Type               modelServiceType   = genericServiceType.MakeGenericType(modelType);
                    Rock.Data.IService serviceInstance    = Activator.CreateInstance(modelServiceType, new object[] { dbContext }) as IService;

                    ParameterExpression paramExpression = Expression.Parameter(entityType, "x");
                    Expression          queryExpression = null; // the base expression we'll use to build our query from

                    // parse markup
                    var parms = ParseMarkup(_markup, context);

                    if (parms.Any(p => p.Key == "id"))
                    {
                        string propertyName = "Id";

                        List <string> selectionParms = new List <string>();
                        selectionParms.Add(PropertyComparisonConverstion("==").ToString());
                        selectionParms.Add(parms["id"].ToString());
                        selectionParms.Add(propertyName);

                        var entityProperty = entityType.GetProperty(propertyName);
                        queryExpression = ExpressionHelper.PropertyFilterExpression(selectionParms, paramExpression, propertyName, entityProperty.PropertyType);

                        hasFilter = true;
                    }
                    else
                    {
                        // where clause expression
                        if (parms.Any(p => p.Key == "where"))
                        {
                            queryExpression = ParseWhere(parms["where"], entityType, serviceInstance, paramExpression, entityType, entityTypeCache);

                            if (queryExpression != null)
                            {
                                hasFilter = true;
                            }
                        }

                        // dataview expression
                        if (parms.Any(p => p.Key == "dataview"))
                        {
                            var dataViewId = parms["dataview"].AsIntegerOrNull();

                            if (dataViewId.HasValue)
                            {
                                var dataViewExpression = GetDataViewExpression(dataViewId.Value, serviceInstance, paramExpression, entityTypeCache);

                                if (queryExpression == null)
                                {
                                    queryExpression = dataViewExpression;
                                    hasFilter       = true;
                                }
                                else
                                {
                                    queryExpression = Expression.AndAlso(queryExpression, dataViewExpression);
                                }
                            }
                        }

                        // process dynamic filter expressions (from the query string)
                        if (parms.Any(p => p.Key == "dynamicparameters"))
                        {
                            var dynamicFilters = parms["dynamicparameters"].Split(',')
                                                 .Select(x => x.Trim())
                                                 .Where(x => !string.IsNullOrWhiteSpace(x))
                                                 .ToList();

                            foreach (var dynamicFilter in dynamicFilters)
                            {
                                var dynamicFilterValue      = HttpContext.Current.Request[dynamicFilter];
                                var dynamicFilterExpression = GetDynamicFilterExpression(dynamicFilter, dynamicFilterValue, entityType, serviceInstance, paramExpression);
                                if (dynamicFilterExpression != null)
                                {
                                    if (queryExpression == null)
                                    {
                                        queryExpression = dynamicFilterExpression;
                                        hasFilter       = true;
                                    }
                                    else
                                    {
                                        queryExpression = Expression.AndAlso(queryExpression, dynamicFilterExpression);
                                    }
                                }
                            }
                        }
                    }

                    // make the query from the expression
                    MethodInfo getMethod = serviceInstance.GetType().GetMethod("Get", new Type[] { typeof(ParameterExpression), typeof(Expression), typeof(Rock.Web.UI.Controls.SortProperty), typeof(int?) });
                    if (getMethod != null)
                    {
                        var queryResult = getMethod.Invoke(serviceInstance, new object[] { paramExpression, queryExpression, null, null }) as IQueryable <IEntity>;

                        // process entity specific filters
                        switch (_entityName)
                        {
                        case "person":
                        {
                            queryResult = PersonFilters((IQueryable <Person>)queryResult, parms);
                            break;
                        }

                        case "business":
                        {
                            queryResult = BusinessFilters((IQueryable <Person>)queryResult, parms);
                            break;
                        }
                        }

                        // if there was a dynamic expression add it now
                        if (parms.Any(p => p.Key == "expression"))
                        {
                            queryResult = queryResult.Where(parms["expression"]);
                            hasFilter   = true;
                        }

                        // get a listing of ids
                        if (parms.Any(p => p.Key == "ids"))
                        {
                            var value = parms["ids"].ToString().Split(',').Select(int.Parse).ToList();
                            queryResult = queryResult.Where(x => value.Contains(x.Id));
                            hasFilter   = true;
                        }

                        var queryResultExpression = queryResult.Expression;

                        // add sort expressions
                        if (parms.Any(p => p.Key == "sort"))
                        {
                            string orderByMethod = "OrderBy";


                            foreach (var column in parms["sort"].Split(',').Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList())
                            {
                                string propertyName;
                                var    direction = SortDirection.Ascending;

                                if (column.EndsWith(" desc", StringComparison.OrdinalIgnoreCase))
                                {
                                    direction    = SortDirection.Descending;
                                    propertyName = column.Left(column.Length - 5);
                                }
                                else
                                {
                                    propertyName = column;
                                }

                                string methodName = direction == SortDirection.Descending ? orderByMethod + "Descending" : orderByMethod;

                                if (entityType.GetProperty(propertyName) != null)
                                {
                                    // sorting a entity property
                                    var memberExpression          = Expression.Property(paramExpression, propertyName);
                                    LambdaExpression sortSelector = Expression.Lambda(memberExpression, paramExpression);
                                    queryResultExpression = Expression.Call(typeof(Queryable), methodName, new Type[] { queryResult.ElementType, sortSelector.ReturnType }, queryResultExpression, sortSelector);
                                }
                                else
                                {
                                    // sorting on an attribute

                                    // get attribute id
                                    int?attributeId = null;
                                    foreach (var id in AttributeCache.GetByEntity(entityTypeCache.Id).SelectMany(a => a.AttributeIds))
                                    {
                                        var attribute = AttributeCache.Get(id);
                                        if (attribute.Key == propertyName)
                                        {
                                            attributeId = id;
                                        }
                                    }

                                    if (attributeId.HasValue)
                                    {
                                        // get AttributeValue queryable and parameter
                                        var attributeValues = _rockContext.Set <AttributeValue>();
                                        ParameterExpression attributeValueParameter = Expression.Parameter(typeof(AttributeValue), "v");
                                        MemberExpression    idExpression            = Expression.Property(paramExpression, "Id");
                                        var attributeExpression = Attribute.Helper.GetAttributeValueExpression(attributeValues, attributeValueParameter, idExpression, attributeId.Value);

                                        LambdaExpression sortSelector = Expression.Lambda(attributeExpression, paramExpression);
                                        queryResultExpression = Expression.Call(typeof(Queryable), methodName, new Type[] { queryResult.ElementType, sortSelector.ReturnType }, queryResultExpression, sortSelector);
                                    }
                                }

                                orderByMethod = "ThenBy";
                            }
                        }

                        // reassemble the queryable with the sort expressions
                        queryResult = queryResult.Provider.CreateQuery(queryResultExpression) as IQueryable <IEntity>;

                        if (parms.GetValueOrNull("count").AsBoolean())
                        {
                            int countResult = queryResult.Count();
                            context.Scopes.Last()["count"] = countResult;
                        }
                        else
                        {
                            // run security check on each result
                            var items        = queryResult.ToList();
                            var itemsSecured = new List <IEntity>();

                            Person person = GetCurrentPerson(context);

                            foreach (IEntity item in items)
                            {
                                ISecured itemSecured = item as ISecured;
                                if (itemSecured == null || itemSecured.IsAuthorized(Authorization.VIEW, person))
                                {
                                    itemsSecured.Add(item);
                                }
                            }

                            queryResult = itemsSecured.AsQueryable();

                            // offset
                            if (parms.Any(p => p.Key == "offset"))
                            {
                                queryResult = queryResult.Skip(parms["offset"].AsInteger());
                            }

                            // limit, default to 1000
                            if (parms.Any(p => p.Key == "limit"))
                            {
                                queryResult = queryResult.Take(parms["limit"].AsInteger());
                            }
                            else
                            {
                                queryResult = queryResult.Take(1000);
                            }

                            // check to ensure we had some form of filter (otherwise we'll return all results in the table)
                            if (!hasFilter)
                            {
                                throw new Exception("Your Lava command must contain at least one valid filter. If you configured a filter it's possible that the property or attribute you provided does not exist.");
                            }

                            var resultList = queryResult.ToList();

                            // if there is only one item to return set an alternative non-array based variable
                            if (resultList.Count == 1)
                            {
                                context.Scopes.Last()[_entityName] = resultList.FirstOrDefault();
                            }

                            context.Scopes.Last()[parms["iterator"]] = resultList;
                        }
                    }
                }
            }
            else
            {
                result.Write(string.Format("Could not find a model for {0}.", _entityName));
                base.Render(context, result);
            }

            base.Render(context, result);
        }
예제 #6
0
        protected override void OnInit(EventArgs e)
        {
            // Read parameter values
            string entityName = Authorization.DecodeEntityTypeName(PageParameter("EntityType"));

            int entityId = 0;

            if (!Int32.TryParse(PageParameter("EntityId"), out entityId))
            {
                entityId = 0;
            }

            // Get object type
            Type type = Type.GetType(entityName);

            if (type != null)
            {
                if (entityId == 0)
                {
                    iSecured = (ISecured)Activator.CreateInstance(type);
                }
                else
                {
                    iSecured = type.InvokeMember("Read", System.Reflection.BindingFlags.InvokeMethod, null, type, new object[] { entityId }) as ISecured;
                }

                if (iSecured.IsAuthorized("Administrate", CurrentPerson))
                {
                    rptActions.DataSource = iSecured.SupportedActions;
                    rptActions.DataBind();

                    rGrid.DataKeyNames        = new string[] { "id" };
                    rGrid.GridReorder        += new GridReorderEventHandler(rGrid_GridReorder);
                    rGrid.GridRebind         += new GridRebindEventHandler(rGrid_GridRebind);
                    rGrid.RowDataBound       += new GridViewRowEventHandler(rGrid_RowDataBound);
                    rGrid.ShowHeaderWhenEmpty = false;
                    rGrid.EmptyDataText       = string.Empty;
                    rGrid.ShowActionRow       = false;

                    rGridParentRules.DataKeyNames        = new string[] { "id" };
                    rGridParentRules.ShowHeaderWhenEmpty = false;
                    rGridParentRules.EmptyDataText       = string.Empty;
                    rGridParentRules.ShowActionRow       = false;

                    BindRoles();

                    string script = string.Format(@"
                    Sys.Application.add_load(function () {{
                        $('#modal-popup div.modal-header h3 small', window.parent.document).html('{0}');
                    }});
                ", iSecured.ToString());

                    this.Page.ClientScript.RegisterStartupScript(this.GetType(), string.Format("set-html-{0}", this.ClientID), script, true);
                }
            }
            else
            {
                rGrid.Visible            = false;
                rGridParentRules.Visible = false;
                nbMessage.Text           = string.Format("Could not load the requested entity type ('{0}') to determine security attributes", entityName);
                nbMessage.Visible        = true;
            }
            base.OnInit(e);
        }