예제 #1
0
        public HttpResponseMessage <JsonQueryResult> Get(
            [FromUri(Name = "designmode")] bool isInDesignMode = false,
            string id    = null,
            string ns    = null,
            string alias = null
            )
        {
            using (Profiler.Measure("FormController.Get"))
            {
                // Get the entityRef
                EntityRef formRef = WebApiHelpers.MakeEntityRef(id, ns, alias);

                long formId;

                try
                {
                    formId = formRef.Id;
                } catch (ArgumentException)
                {
                    throw new FormNotFoundException();
                }

                EntityData formEntityData = _formControllerRequestHandler.GetFormAsEntityData(formId, isInDesignMode);

                var context = new EntityPackage();
                context.AddEntityData(formEntityData, "formEntity");
                return(new HttpResponseMessage <JsonQueryResult>(context.GetQueryResult()));
            }
        }
예제 #2
0
 protected EntityPackage SetLikeNew(EntityPackage package)
 {
     package.Entity.id = 0;
     package.Values.ForEach(x => x.id    = 0);
     package.Relations.ForEach(x => x.id = 0);
     return(package);
 }
예제 #3
0
 public bool CanUser(long userId, string action, EntityPackage package)
 {
     return(CanUser(new Requester()
     {
         userId = userId
     }, action, package));
 }
        //public static ILogger Logger = null;

        /// <summary>
        /// Write an entire entity wrapper as-is, setting all associated ids.
        /// </summary>
        /// <param name="provider"></param>
        /// <param name="entity"></param>
        /// <returns></returns>
        public static async Task WriteAsync(this IEntityProvider provider, EntityPackage entity)
        {
            var allWrite = new List <EntityBase>();

            allWrite.AddRange(entity.Values);
            allWrite.AddRange(entity.Relations);

            if (entity.Entity.id > 0)
            {
                //If this is an update entity, it's easy. Just save everything all
                //at once, making the whole dang thing atomic
                allWrite.Add(entity.Entity);
                await provider.WriteAsync(allWrite.ToArray());
            }
            else
            {
                //If this is a NEW entity, try to write it first then update the values and relations.
                //If something goes wrong with the values/relations, delete the entity we added.
                await provider.WriteAsync(entity.Entity);

                try
                {
                    entity.Values.ForEach(x => x.entityId     = entity.Entity.id);
                    entity.Relations.ForEach(x => x.entityId2 = entity.Entity.id); //Assume relations are all parents. a user has perms ON this entity, a category OWNS this entity, etc.
                    await provider.WriteAsync(allWrite.ToArray());
                }
                catch
                {
                    await provider.DeleteAsync(entity.Entity);

                    throw;
                }
            }
        }
예제 #5
0
        public static List <EntityBase> FlattenPackage(this EntityPackage package)
        {
            var result = new List <EntityBase>();

            FlattenPackage(package, result);
            return(result);
        }
예제 #6
0
        public void FullUpdate() //Lots of tests with updating
        {
            var package            = SimplePackage();
            var originaPackageCopy = new EntityPackage(package);

            service.InsertWithHistoryAsync(package, 1).Wait();

            var firstInsertedPackage = new EntityPackage(package);

            package.Relations.First().value = "Something NEW";
            package.Values.First().value    = "aha MORE";

            service.UpdateWithHistoryAsync(package, 1).Wait();

            //This shouldn't be "new", it should be the same as before
            Assert.Equal(firstInsertedPackage.Entity.id, package.Entity.id);

            var revisions = service.GetRevisionIdsAsync(package.Entity.id).Result;

            Assert.Single(revisions);
            Assert.NotEqual(package.Entity.id, revisions.First());

            //Ensure the CURRENT package we pulled out is EXACTLY the same (minus date kind)
            var currentPackage = provider.FindByIdAsync(package.Entity.id).Result;

            Assert.Equal(package, currentPackage);

            //Ensure the package from history is EXACTLY the same as the one before sans ids (set all to 0)
            var revisionPackage = provider.FindByIdAsync(revisions.First()).Result;
            var likeUpdate      = service.ConvertHistoryToUpdate(revisionPackage);

            Assert.Equal(firstInsertedPackage, likeUpdate);
        }
예제 #7
0
        public async Task InsertWithHistoryAsync(EntityPackage newData, long user, Action <EntityPackage> modifyBeforeCreate = null)
        {
            if (newData.Entity.id > 0)
            {
                throw new InvalidOperationException("'New' package has non-zero id!");
            }

            var mainEntity = newData.Entity;
            await provider.WriteAsync(mainEntity);

            try
            {
                newData.Relink();
                modifyBeforeCreate?.Invoke(newData);

                var writes = new List <EntityBase>();

                //Must write everything else at the same time. We only wrote the first thing to get the ID
                writes.AddRange(newData.Values);
                writes.AddRange(newData.Relations);

                writes.Add(activityService.MakeActivity(newData.Entity, user, Keys.CreateAction));

                await provider.WriteAsync(writes.ToArray());
            }
            catch
            {
                logger.LogError("Failure during historic insert, trying to undo... Exception bubbling");
                await provider.DeleteAsync(mainEntity);

                throw;
            }
        }
예제 #8
0
 public bool CanUser(Requester requester, string action, EntityPackage package)
 {
     //Inefficient in compute but easier for me, the programmer, to use a single source of truth.
     return(PermissionWhere(package.Relations.Select(x => new EntityGroup()
     {
         permission = x
     }).AsQueryable(), requester, action).Any());
 }
예제 #9
0
 public void ApplyFromValueView(IValueView view, EntityPackage package, string type)
 {
     FromViewValues(view.values).ForEach(x =>
     {
         x.entityId = view.id;
         package.Add(x);
     });
 }
        /// <summary>
        /// Create a "new" copy of the given entity
        /// </summary>
        /// <param name="entity"></param>
        public static EntityPackage NewCopy(this EntityPackage entity)
        {
            var newEntity = new EntityPackage(entity);

            newEntity.Entity.id = 0;
            newEntity.Values.ForEach(x => x.id    = 0);
            newEntity.Relations.ForEach(x => x.id = 0);
            return(newEntity);
        }
예제 #11
0
        public override async Task <FileView> CleanViewUpdateAsync(FileView view, EntityPackage existing, Requester requester)
        {
            var result = await base.CleanViewGeneralAsync(view, requester);

            //Always restore the filetype, you can't change uploaded files anyway.
            result.fileType = existing.Entity.content;

            return(result);
        }
예제 #12
0
        public void ApplyToPermissionView(EntityPackage package, IPermissionView view)
        {
            if (package.HasRelation(Keys.ParentRelation))
            {
                view.parentId = package.GetRelation(Keys.ParentRelation).entityId1;
            }

            view.permissions = ToPerms(package.Relations);
        }
        public static Task DeleteAsync(this IEntityProvider provider, EntityPackage package)
        {
            var deletes = new List <EntityBase>();

            deletes.Add(package.Entity);
            deletes.AddRange(package.Values);
            deletes.AddRange(package.Relations);
            return(provider.DeleteAsync(deletes.ToArray()));
        }
예제 #14
0
        public HttpResponseMessage <JsonQueryResult> GetNavigationTree()
        {
            EntityPackage context;

            context = new EntityPackage();
            EntityData tree = ConsoleTreeRepository.GetTree();

            context.AddEntityData(tree, "navItems");
            return(new HttpResponseMessage <JsonQueryResult>(context.GetQueryResult()));
        }
예제 #15
0
        /// <summary>
        ///     Given a type, get the generated form for it.
        /// </summary>
        /// <param name="entityType">Type of the entity.</param>
        /// <param name="isInDesignMode">if set to <c>true</c> [is in design mode].</param>
        /// <returns>
        ///     A response containing entity data for the form
        /// </returns>
        public static HttpResponseMessage <JsonQueryResult> GetGeneratedFormForType(EntityRef entityType, bool isInDesignMode)
        {
            EntityData formEntityData = EditFormHelper.GenerateDefaultFormForResourceType(entityType, isInDesignMode);

            var entityBatch = new EntityPackage( );

            entityBatch.AddEntityData(formEntityData, "formEntity");

            return(new HttpResponseMessage <JsonQueryResult>(entityBatch.GetQueryResult( )));
        }
예제 #16
0
        // Edit vview applications

        public void ApplyToEditView(EntityPackage package, IEditView view)
        {
            ApplyToBaseView(package.Entity, view);

            //History has a creator and an editor. The create date comes from base
            var creatorRelation = package.GetRelation(Keys.CreatorRelation);

            view.editDate     = (DateTime)creatorRelation.createDateProper();
            view.createUserId = creatorRelation.entityId1;
            view.editUserId   = long.Parse(creatorRelation.value);
        }
예제 #17
0
        private static List <string> PopulateEntityList(EntityPackage package)
        {
            var items = new List <string>();

            for (var i = 0; i < package.loadedObjects_.Count; i++)
            {
                items.Add(package.loadedObjectNames_[i]);
            }

            return(items);
        }
        /// <summary>
        /// Get a value from an entity package
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static EntityValue GetValue(this EntityPackage entity, string key)
        {
            var values = FindValues(entity, key);

            if (values.Count() != 1)
            {
                throw new InvalidOperationException($"Not a single value for key: {key}");
            }

            return(values.First());
        }
        /// <summary>
        /// Get a relation from an entity package
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static EntityRelation GetRelation(this EntityPackage entity, string type)
        {
            var relations = FindRelations(entity, type);

            if (relations.Count() != 1)
            {
                throw new InvalidOperationException($"Not a single relation for type: {type}");
            }

            return(relations.First());
        }
예제 #20
0
        /// <summary>
        /// Allow "fake" deletion of ANY historic entity (of any type)
        /// </summary>
        /// <param name="entityId"></param>
        /// <returns></returns>
        public async Task DeleteWithHistoryAsync(EntityPackage package, long user)
        {
            var historicPart = package.Entity;

            MakeHistoric(historicPart);

            //Notice it is a WRITe and not a delete. The activity extra will include the title.
            await provider.WriteAsync <EntityBase>(
                historicPart,
                activityService.MakeActivity(historicPart, user, Keys.DeleteAction, package.Entity.name));
        }
        public EntityPackage NewPackage()
        {
            var package = new EntityPackage()
            {
                Entity = NewEntity()
            };
            var value    = NewValue();
            var relation = NewRelation();

            package.Add(value);
            package.Add(relation);
            return(package);
        }
예제 #22
0
        /// <summary>
        /// Clean the view specifically for updates, run AFTER general
        /// </summary>
        /// <param name="view"></param>
        /// <param name="existing"></param>
        /// <returns></returns>
        public virtual Task <V> CleanViewUpdateAsync(V view, EntityPackage existing, Requester requester)
        {
            //FORCE these to be what they were before.
            view.createDate   = (DateTime)existing.Entity.createDateProper();
            view.createUserId = existing.GetRelation(Keys.CreatorRelation).entityId1;

            //Don't allow posting over some other entity! THIS IS SUUUUPER IMPORTANT!!!
            if (!existing.Entity.type.StartsWith(EntityType))
            {
                throw new BadRequestException($"No entity of proper type with id {view.id}");
            }

            return(Task.FromResult(view));
        }
        /// <summary>
        ///     Packages the form data response.
        /// </summary>
        /// <param name="entityData">The entity data.</param>
        /// <param name="initiallyHiddenControls">The initially hidden controls.</param>
        /// <returns></returns>
        private FormDataResponse PackageFormDataResponse(EntityData entityData, ISet <long> initiallyHiddenControls)
        {
            var context = new EntityPackage();

            context.AddEntityData(entityData, "entity");

            var response = new FormDataResponse
            {
                FormDataEntity          = context.GetQueryResult(),
                InitiallyHiddenControls = initiallyHiddenControls
            };

            return(response);
        }
예제 #24
0
        public override async Task <FileView> CleanViewUpdateAsync(FileView view, EntityPackage existing, Requester requester)
        {
            var result = await base.CleanViewUpdateAsync(view, existing, requester);

            var existingView = converter.ToView(existing);

            //Always restore the filetype, you can't change uploaded files anyway.
            if (!requester.system)
            {
                result.fileType     = existingView.fileType;     //.Entity.content;
                result.quantization = existingView.quantization; //.GetValue();
            }

            return(result);
        }
        public override CategoryView ToView(EntityPackage package)
        {
            var view = new CategoryView();

            this.ApplyToStandard(package, view);

            view.name        = package.Entity.name;
            view.description = package.Entity.content;

            foreach (var v in package.Relations.Where(x => x.type == Keys.SuperRelation))
            {
                view.localSupers.Add(v.entityId1);
            }

            return(view);
        }
예제 #26
0
 public static void SetGenericValue(this EntityPackage package, string key, string value)
 {
     if (package.HasValue(key))
     {
         package.GetValue(key).value = value;
     }
     else
     {
         package.Add(new EntityValue()
         {
             key        = key,
             value      = value,
             createDate = null
         });
     }
 }
예제 #27
0
        public override ContentView ToView(EntityPackage package)
        {
            var view = new ContentView();

            this.ApplyToStandard(package, view);

            view.name    = package.Entity.name;
            view.content = package.Entity.content;
            view.type    = package.Entity.type.Substring(Keys.ContentType.Length);

            foreach (var keyword in package.Values.Where(x => x.key == Keys.KeywordKey))
            {
                view.keywords.Add(keyword.value);
            }

            return(view);
        }
예제 #28
0
        public void ApplyFromEditView(IEditView view, EntityPackage package, string type)
        {
            ApplyFromBaseView(view, package.Entity);

            package.Entity.type = type;

            var relation = new EntityRelation()
            {
                entityId1  = view.createUserId,
                entityId2  = view.id,
                type       = Keys.CreatorRelation,
                value      = view.editUserId.ToString(),
                createDate = view.editDate
            };

            package.Add(relation);
        }
예제 #29
0
        /// <summary>
        ///     Given a type, get the default form for it.
        /// </summary>
        /// <param name="entityType">Type of the entity.</param>
        /// <param name="isInDesignMode">if set to <c>true</c> [is in design mode].</param>
        /// <param name="forceGenerate">Force a generated form to be used</param>
        /// <returns>
        ///     A response containing entity data for the form
        /// </returns>
        public static HttpResponseMessage <JsonQueryResult> GetDefaultFormForType(EntityType entityType, bool isInDesignMode, bool forceGenerate)
        {
            CustomEditForm formRef = entityType.DefaultEditForm;

            if (formRef != null && !forceGenerate)
            {
                var entityBatch = new EntityPackage( );

                EntityData formEntityData = EditFormHelper.GetFormAsEntityData(formRef);

                entityBatch.AddEntityData(formEntityData, "formEntity");

                return(new HttpResponseMessage <JsonQueryResult>(entityBatch.GetQueryResult( )));
            }
            //TODO: return something to indicate that there is no form
            return(GetGeneratedFormForType(entityType, isInDesignMode));
        }
예제 #30
0
        /// <summary>
        /// Update the given existing entity with the new entity, preserving the history for the original.
        /// </summary>
        /// <param name="updateData"></param>
        /// <param name="originalData"></param>
        /// <returns></returns>
        public async Task UpdateWithHistoryAsync(EntityPackage updateData, long user, EntityPackage originalData = null)
        {
            logger.LogTrace($"WriteHistoric called for entity {updateData.Entity.id}");

            //The original isn't necessary; we can find it using the id from our apparently updated data
            if (originalData == null)
            {
                originalData = await provider.FindByIdAsync(updateData.Entity.id);
            }

            var history = await CreateHistoricCopyAsync(originalData.Entity);

            try
            {
                //Bring all the existing over to this historic entity
                history.Relink(originalData.Values, originalData.Relations);

                //WE have to link the new stuff to US because we want to write everything all at once
                originalData.Entity.Relink(updateData.Values, updateData.Relations);

                //Add the historic link back to the history copy from the
                originalData.Relations.Add(NewHistoryLink(updateData.Entity, history));

                //A special thing: the values and relations need to be NEW for the update data
                updateData.Relations.ForEach(x => x.id = 0);
                updateData.Values.ForEach(x => x.id    = 0);

                //We're writing the entirety of the "update" data.
                var writes = updateData.FlattenPackage();

                //Also writing the relinked original stuff.
                writes.AddRange(originalData.Values);
                writes.AddRange(originalData.Relations);

                writes.Add(activityService.MakeActivity(updateData.Entity, user, Keys.UpdateAction, history.id.ToString()));

                await provider.WriteAsync(writes.ToArray());
            }
            catch
            {
                logger.LogError("Failure during historic update, trying to undo... Exception bubbling...");
                await provider.DeleteAsync(history);

                throw;
            }
        }