コード例 #1
0
        public static void AuditAutoCrudMetadataFilter(AutoCrudMetadata meta)
        {
            foreach (var applyAttr in meta.AutoApplyAttrs)
            {
                switch (applyAttr.Name)
                {
                case Behavior.AuditQuery:
                    meta.Add(new AutoFilterAttribute(
                                 QueryTerm.Ensure, nameof(AuditBase.DeletedDate), SqlTemplate.IsNull));
                    break;

                case Behavior.AuditCreate:
                case Behavior.AuditModify:
                    if (applyAttr.Name == Behavior.AuditCreate)
                    {
                        meta.Add(new AutoPopulateAttribute(nameof(AuditBase.CreatedDate))
                        {
                            Eval = "utcNow"
                        });
                        meta.Add(new AutoPopulateAttribute(nameof(AuditBase.CreatedBy))
                        {
                            Eval = "userAuthName"
                        });
                    }
                    meta.Add(new AutoPopulateAttribute(nameof(AuditBase.ModifiedDate))
                    {
                        Eval = "utcNow"
                    });
                    meta.Add(new AutoPopulateAttribute(nameof(AuditBase.ModifiedBy))
                    {
                        Eval = "userAuthName"
                    });
                    break;

                case Behavior.AuditDelete:
                case Behavior.AuditSoftDelete:
                    if (applyAttr.Name == Behavior.AuditSoftDelete)
                    {
                        meta.SoftDelete = true;
                    }

                    meta.Add(new AutoPopulateAttribute(nameof(AuditBase.DeletedDate))
                    {
                        Eval = "utcNow"
                    });
                    meta.Add(new AutoPopulateAttribute(nameof(AuditBase.DeletedBy))
                    {
                        Eval = "userAuthName"
                    });
                    break;
                }
            }
        }
コード例 #2
0
        /// <summary>
        /// Deletes entry into Table
        /// </summary>
        public virtual async Task <object> Delete <Table>(IDeleteDb <Table> dto)
        {
            using var db = AutoQuery.GetDb <Table>(Request);
            using (Profiler.Current.Step("AutoQuery.Delete"))
            {
                var response = await ExecAndReturnResponseAsync <Table>(dto, db,
                                                                        async ctx => {
                    var dtoValues = ResolveDtoValues(dto, skipDefaults: true);

                    //Should have at least 1 non-default filter
                    if (dtoValues.Count == 0)
                    {
                        throw new NotSupportedException($"'{dto.GetType().Name}' did not contain any filters");
                    }

                    var meta       = AutoCrudMetadata.Create(dto.GetType());
                    var pkFieldDef = meta.ModelDef.PrimaryKey;
                    var idValue    = pkFieldDef != null && dtoValues.TryGetValue(pkFieldDef.Name, out var oId)
                            ? oId
                            : null;

                    // Should only update a Single Row
                    if (GetAutoFilterExpressions(db, dto, dtoValues, Request, out var expr, out var exprParams))
                    {
                        //If there were Auto Filters, construct filter expression manually by adding any remaining DTO values
                        foreach (var entry in dtoValues)
                        {
                            var fieldDef = meta.ModelDef.GetFieldDefinition(entry.Key);
                            if (fieldDef == null)
                            {
                                throw new NotSupportedException($"Unknown '{entry.Key}' Field in '{dto.GetType().Name}' IDeleteDb<{typeof(Table).Name}> Request");
                            }

                            if (expr.Length > 0)
                            {
                                expr += " AND ";
                            }

                            var quotedColumn = db.GetDialectProvider().GetQuotedColumnName(meta.ModelDef, fieldDef);

                            expr += quotedColumn + " = {" + exprParams.Count + "}";
                            exprParams.Add(entry.Value);
                        }

                        var q = db.From <Table>();
                        q.Where(expr, exprParams.ToArray());
                        return(new ExecValue(idValue, await db.DeleteAsync(q)));
                    }
コード例 #3
0
        public static void AuditAutoCrudMetadataFilter(AutoCrudMetadata meta)
        {
            var applyAttrs = meta.AutoApplyAttrs;

            if (applyAttrs.IsEmpty())
            {
                return;
            }

            var hasAuditQuery      = applyAttrs.Any(x => x.Name == Behavior.AuditQuery);
            var hasAuditCreate     = applyAttrs.Any(x => x.Name == Behavior.AuditCreate);
            var hasAuditModify     = applyAttrs.Any(x => x.Name == Behavior.AuditModify);
            var hasAuditSoftDelete = applyAttrs.Any(x => x.Name == Behavior.AuditSoftDelete);

            if (hasAuditQuery)
            {
                meta.AddFilterAttribute(new AutoFilterAttribute(
                                            QueryTerm.Ensure, nameof(AuditBase.DeletedDate), SqlTemplate.IsNull));
            }

            if (!hasAuditCreate && !hasAuditModify && !hasAuditSoftDelete)
            {
                return;
            }

            meta.PopulateAttrs ??= new List <AutoPopulateAttribute>();
            if (hasAuditCreate)
            {
                meta.PopulateAttrs.Add(new AutoPopulateAttribute(nameof(AuditBase.CreatedDate))
                {
                    Eval = "utcNow"
                });
                meta.PopulateAttrs.Add(new AutoPopulateAttribute(nameof(AuditBase.CreatedBy))
                {
                    Eval = "userAuthName"
                });
            }
            if (hasAuditCreate || hasAuditModify)
            {
                meta.PopulateAttrs.Add(new AutoPopulateAttribute(nameof(AuditBase.ModifiedDate))
                {
                    Eval = "utcNow"
                });
                meta.PopulateAttrs.Add(new AutoPopulateAttribute(nameof(AuditBase.ModifiedBy))
                {
                    Eval = "userAuthName"
                });
            }
            if (hasAuditSoftDelete)
            {
                meta.PopulateAttrs.Add(new AutoPopulateAttribute(nameof(AuditBase.DeletedDate))
                {
                    Eval = "utcNow"
                });
                meta.PopulateAttrs.Add(new AutoPopulateAttribute(nameof(AuditBase.DeletedBy))
                {
                    Eval = "userAuthName"
                });
                meta.SoftDelete = true;
            }
        }
コード例 #4
0
        private Dictionary <string, object> ResolveDtoValues(object dto, bool skipDefaults = false)
        {
            var dtoValues = dto.ToObjectDictionary();

            var meta = AutoCrudMetadata.Create(dto.GetType());

            if (meta.MapAttrs != null)
            {
                foreach (var entry in meta.MapAttrs)
                {
                    if (dtoValues.TryRemove(entry.Key, out var value))
                    {
                        dtoValues[entry.Value.To] = value;
                    }
                }
            }

            var appHost = HostContext.AppHost;

            if (skipDefaults || meta.UpdateAttrs != null || meta.DefaultAttrs != null)
            {
                List <string> removeKeys = null;
                Dictionary <string, object> replaceValues = null;

                foreach (var entry in dtoValues)
                {
                    var isNullable     = meta.NullableProps?.Contains(entry.Key) == true;
                    var isDefaultValue = entry.Value == null || (!isNullable && AutoMappingUtils.IsDefaultValue(entry.Value));
                    if (isDefaultValue)
                    {
                        var handled = false;
                        if (meta.DefaultAttrs != null && meta.DefaultAttrs.TryGetValue(entry.Key, out var defaultAttr))
                        {
                            handled = true;
                            replaceValues ??= new Dictionary <string, object>();
                            replaceValues[entry.Key] = appHost.EvalScriptValue(defaultAttr, Request);
                        }
                        if (!handled)
                        {
                            if (skipDefaults ||
                                (meta.UpdateAttrs != null && meta.UpdateAttrs.TryGetValue(entry.Key, out var attr) &&
                                 attr.Style == AutoUpdateStyle.NonDefaults))
                            {
                                removeKeys ??= new List <string>();
                                removeKeys.Add(entry.Key);
                            }
                        }
                    }
                }

                if (removeKeys != null)
                {
                    foreach (var key in removeKeys)
                    {
                        dtoValues.RemoveKey(key);
                    }
                }

                if (replaceValues != null)
                {
                    foreach (var entry in replaceValues)
                    {
                        dtoValues[entry.Key] = entry.Value;
                    }
                }
            }

            if (meta.PopulateAttrs != null)
            {
                foreach (var populateAttr in meta.PopulateAttrs)
                {
                    dtoValues[populateAttr.Field] = appHost.EvalScriptValue(populateAttr, Request);
                }
            }

            var populatorFn = AutoMappingUtils.GetPopulator(
                typeof(Dictionary <string, object>), meta.DtoType);

            populatorFn?.Invoke(dtoValues, dto);

            // Ensure RowVersion is always populated if defined on Request DTO
            if (meta.RowVersionGetter != null && !dtoValues.ContainsKey(Keywords.RowVersion))
            {
                dtoValues[Keywords.RowVersion] = default(uint);
            }

            return(dtoValues);
        }
コード例 #5
0
            internal static AutoCrudMetadata Create(Type dtoType)
            {
                if (cache.TryGetValue(dtoType, out var to))
                {
                    return(to);
                }

                to = new AutoCrudMetadata {
                    DtoType   = dtoType,
                    ModelType = GetModelType(dtoType),
                    DtoProps  = TypeProperties.Get(dtoType),
                };
                if (to.ModelType != null)
                {
                    to.ModelDef = to.ModelType.GetModelMetadata();
                }

                to.RowVersionGetter = to.DtoProps.GetPublicGetter(Keywords.RowVersion);

                var dtoAttrs = dtoType.AllAttributes();

                foreach (var dtoAttr in dtoAttrs)
                {
                    if (dtoAttr is AutoPopulateAttribute populateAttr)
                    {
                        to.PopulateAttrs ??= new List <AutoPopulateAttribute>();
                        to.PopulateAttrs.Add(populateAttr);
                    }
                    else if (dtoAttr is AutoFilterAttribute filterAttr)
                    {
                        to.AutoFilters ??= new List <AutoFilterAttribute>();
                        to.AutoFiltersDbFields ??= new List <QueryDbFieldAttribute>();

                        to.AutoFilters.Add(filterAttr);
                        to.AutoFiltersDbFields.Add(ExprResult.ToDbFieldAttribute(filterAttr));
                    }
                }

                foreach (var pi in to.DtoProps.PublicPropertyInfos)
                {
                    var allAttrs = pi.AllAttributes();
                    var propName = pi.Name;

                    if (allAttrs.FirstOrDefault(x => x is AutoMapAttribute) is AutoMapAttribute mapAttr)
                    {
                        to.MapAttrs ??= new Dictionary <string, AutoMapAttribute>();
                        to.MapAttrs[propName] = mapAttr;
                        propName = mapAttr.To;
                    }

                    if (allAttrs.FirstOrDefault(x => x is AutoUpdateAttribute) is AutoUpdateAttribute updateAttr)
                    {
                        to.UpdateAttrs ??= new Dictionary <string, AutoUpdateAttribute>();
                        to.UpdateAttrs[propName] = updateAttr;
                    }

                    if (allAttrs.FirstOrDefault(x => x is AutoDefaultAttribute) is AutoDefaultAttribute defaultAttr)
                    {
                        to.DefaultAttrs ??= new Dictionary <string, AutoDefaultAttribute>();
                        to.DefaultAttrs[propName] = defaultAttr;
                    }

                    if (pi.PropertyType.IsNullableType())
                    {
                        to.NullableProps ??= new HashSet <string>();
                        to.NullableProps.Add(propName);
                    }
                }

                return(cache[dtoType] = to);
            }
コード例 #6
0
        internal bool GetAutoFilterExpressions(IDbConnection db, object dto, Dictionary <string, object> dtoValues, IRequest req, out string expr, out List <object> exprParams)
        {
            var meta = AutoCrudMetadata.Create(dto.GetType());

            if (meta.AutoFilters != null)
            {
                var dialectProvider = db.GetDialectProvider();
                var sb             = StringBuilderCache.Allocate();
                var exprParamsList = new List <object>();

                //Update's require PK's, Delete's don't need to
                if (dtoValues.TryRemove(meta.ModelDef.PrimaryKey.Name, out var idValue))
                {
                    var idColumn = dialectProvider.GetQuotedColumnName(meta.ModelDef, meta.ModelDef.PrimaryKey);
                    sb.Append(idColumn + " = {0}");
                    exprParamsList.Add(idValue);
                }

                var appHost = HostContext.AppHost;
                for (var i = 0; i < meta.AutoFilters.Count; i++)
                {
                    var filter = meta.AutoFilters[i];
                    var dbAttr = meta.AutoFiltersDbFields[i];

                    var fieldDef = meta.ModelDef.GetFieldDefinition(filter.Field);
                    if (fieldDef == null)
                    {
                        throw new NotSupportedException($"{dto.GetType().Name} '{filter.Field}' AutoFilter was not found on '{meta.ModelType.Name}'");
                    }

                    var quotedColumn = dialectProvider.GetQuotedColumnName(meta.ModelDef, fieldDef);

                    var value = appHost.EvalScriptValue(filter, req);

                    var ret = ExprResult.CreateExpression("AND", quotedColumn, value, dbAttr);


                    if (ret != null)
                    {
                        if (sb.Length > 0)
                        {
                            sb.Append(" AND ");
                        }

                        var exprResult = ret.Value;
                        if (exprResult.Format.IndexOf("{1}", StringComparison.Ordinal) >= 0)
                        {
                            throw new NotSupportedException($"SQL Template '{exprResult.Format}' with multiple arguments is not supported");
                        }

                        if (exprResult.Values != null)
                        {
                            for (var index = 0; index < exprResult.Values.Length; index++)
                            {
                                sb.Append(exprResult.Format.Replace("{" + index + "}", "{" + exprParamsList.Count + "}"));
                                exprParamsList.Add(exprResult.Values[index]);
                            }
                        }
                    }

                    expr       = StringBuilderCache.ReturnAndFree(sb);
                    exprParams = exprParamsList;
                    return(true);
                }
            }

            expr       = null;
            exprParams = null;
            return(false);
        }