internal override OrganizationResponse Execute(OrganizationRequest orgRequest, EntityReference userRef)
        {
            var request      = MakeRequest <MergeRequest>(orgRequest);
            var mainEntity   = db.GetEntity(request.Target);
            var casSelection = new CascadeSelection()
            {
                merge = true
            };
            var subordinateReference = new EntityReference {
                LogicalName = mainEntity.LogicalName, Id = request.SubordinateId
            };
            var subordinateEntity = core.GetDbEntityWithRelatedEntities(subordinateReference, EntityRole.Referencing, userRef, casSelection);

            foreach (var attr in request.UpdateContent.Attributes)
            {
                if (attr.Value != null)
                {
                    mainEntity[attr.Key] = attr.Value;
                }
            }

            foreach (var relatedEntities in subordinateEntity.RelatedEntities)
            {
                var relationshipMeta = metadata.EntityMetadata.GetMetadata(subordinateEntity.LogicalName).ManyToOneRelationships.First(r => r.SchemaName == relatedEntities.Key.SchemaName);
                if (relationshipMeta.CascadeConfiguration.Merge == CascadeType.Cascade)
                {
                    var entitiesToSwap = relatedEntities.Value.Entities.Select(e => e.ToEntityReference()).ToList();

                    var disassocHandler = core.RequestHandlers.Find(x => x is DisassociateRequestHandler);
                    disassocHandler.Execute(new DisassociateRequest {
                        RelatedEntities = new EntityReferenceCollection(entitiesToSwap),
                        Relationship    = relatedEntities.Key,
                        Target          = subordinateEntity.ToEntityReference()
                    }, userRef);

                    var assocHandler = core.RequestHandlers.Find(x => x is AssociateRequestHandler);
                    assocHandler.Execute(new AssociateRequest {
                        RelatedEntities = new EntityReferenceCollection(entitiesToSwap),
                        Relationship    = relatedEntities.Key,
                        Target          = mainEntity.ToEntityReference()
                    }, userRef);
                }
            }

            subordinateEntity["merged"] = true;
            db.Update(subordinateEntity);
            db.Update(mainEntity);
            var setStateHandler = core.RequestHandlers.Find(x => x is SetStateRequestHandler);
            var req             = new SetStateRequest()
            {
                EntityMoniker = subordinateReference,
                State         = new OptionSetValue(1),
                Status        = new OptionSetValue(2)
            };

            setStateHandler.Execute(req, userRef);

            return(new MergeResponse());
        }
        internal override OrganizationResponse Execute(OrganizationRequest orgRequest, EntityReference userRef)
        {
            var request      = MakeRequest <AssignRequest>(orgRequest);
            var casSelection = new CascadeSelection()
            {
                assign = true
            };
            var dbEntity = core.GetDbEntityWithRelatedEntities(request.Target, EntityRole.Referenced, userRef, casSelection);

            security.CheckAssignPermission(dbEntity, request.Assignee, userRef);

            // Cascade
            foreach (var relatedEntities in dbEntity.RelatedEntities)
            {
                var relationshipMeta = metadata.EntityMetadata.GetMetadata(dbEntity.LogicalName).OneToManyRelationships.First(r => r.SchemaName == relatedEntities.Key.SchemaName);
                var req = new AssignRequest();
                switch (relationshipMeta.CascadeConfiguration.Assign)
                {
                case CascadeType.Cascade:
                    foreach (var relatedEntity in relatedEntities.Value.Entities)
                    {
                        req.Target   = relatedEntity.ToEntityReference();
                        req.Assignee = request.Assignee;
                        core.Execute(req, userRef, null);
                    }
                    break;

                case CascadeType.Active:
                    foreach (var relatedEntity in relatedEntities.Value.Entities)
                    {
                        if (db.GetEntity(relatedEntity.ToEntityReference()).GetAttributeValue <OptionSetValue>("statecode")?.Value == 0)
                        {
                            req.Target   = relatedEntity.ToEntityReference();
                            req.Assignee = request.Assignee;
                            core.Execute(req, userRef, null);
                        }
                    }
                    break;

                case CascadeType.UserOwned:
                    foreach (var relatedEntity in relatedEntities.Value.Entities)
                    {
                        var currentOwner = dbEntity.Attributes["ownerid"] as EntityReference;
                        if (db.GetEntity(relatedEntity.ToEntityReference()).GetAttributeValue <EntityReference>("ownerid")?.Id == currentOwner.Id)
                        {
                            req.Target   = relatedEntity.ToEntityReference();
                            req.Assignee = request.Assignee;
                            core.Execute(req, userRef, null);
                        }
                    }
                    break;
                }
            }
            Utility.SetOwner(db, security, metadata, dbEntity, request.Assignee);
            Utility.Touch(dbEntity, metadata.EntityMetadata.GetMetadata(dbEntity.LogicalName), core.TimeOffset, userRef);
            db.Update(dbEntity);
            return(new AssignResponse());
        }
Exemplo n.º 3
0
        internal override OrganizationResponse Execute(OrganizationRequest orgRequest, EntityReference userRef)
        {
            var request      = MakeRequest <DeleteRequest>(orgRequest);
            var casSelection = new CascadeSelection()
            {
                delete = true
            };
            var entity = core.GetDbEntityWithRelatedEntities(request.Target, EntityRole.Referenced, userRef, casSelection);

            if (entity == null)
            {
                throw new FaultException($"{request.Target.LogicalName} with Id '{request.Target.Id}' does not exist");
            }

            if (entity != null)
            {
                foreach (var relatedEntities in entity.RelatedEntities)
                {
                    var relationshipMeta = metadata.EntityMetadata.GetMetadata(entity.LogicalName).OneToManyRelationships.FirstOrDefault(r => r.SchemaName == relatedEntities.Key.SchemaName);

                    if (relationshipMeta == null)
                    {
                        continue;
                    }
                    switch (relationshipMeta.CascadeConfiguration.Delete)
                    {
                    case CascadeType.Cascade:
                        foreach (var relatedEntity in relatedEntities.Value.Entities)
                        {
                            var req = new DeleteRequest {
                                Target = new EntityReference(relatedEntity.LogicalName, relatedEntity.Id)
                            };
                            core.Execute(req, userRef, null);
                        }
                        break;

                    case CascadeType.RemoveLink:
                        var disassocHandler = core.RequestHandlers.Find(x => x is DisassociateRequestHandler);
                        disassocHandler.Execute(new DisassociateRequest {
                            RelatedEntities = new EntityReferenceCollection(relatedEntities.Value.Entities.Select(e => e.ToEntityReference()).ToList()),
                            Relationship    = relatedEntities.Key,
                            Target          = entity.ToEntityReference()
                        }, userRef);
                        break;

                    case CascadeType.Restrict:
                        var trace = core.ServiceFactory.GetService(typeof(ITracingService)) as ITracingService;
                        trace.Trace($"Delete restricted for {relatedEntities.Key.SchemaName} when trying to delete {entity.LogicalName} with id {entity.Id}");
                        return(new DeleteResponse());
                    }
                }

                db.Delete(entity);
            }

            return(new DeleteResponse());
        }
Exemplo n.º 4
0
        private bool CascadeCompare(CascadeConfiguration cascadeConfiguration, CascadeSelection selection)
        {
            if (selection == null)
            {
                return(true);
            }

            if (selection.assign && HasCascadeBehaviour(cascadeConfiguration.Assign))
            {
                return(true);
            }

            if (selection.delete && HasCascadeBehaviour(cascadeConfiguration.Delete))
            {
                return(true);
            }

            if (selection.merge && HasCascadeBehaviour(cascadeConfiguration.Merge))
            {
                return(true);
            }

            if (selection.reparent && HasCascadeBehaviour(cascadeConfiguration.Reparent))
            {
                return(true);
            }

            if (selection.share && HasCascadeBehaviour(cascadeConfiguration.Share))
            {
                return(true);
            }

            if (selection.unshare && HasCascadeBehaviour(cascadeConfiguration.Unshare))
            {
                return(true);
            }

#if !(XRM_MOCKUP_2011 || XRM_MOCKUP_2013 || XRM_MOCKUP_2015 || XRM_MOCKUP_2016)
            if (selection.rollup && HasCascadeBehaviour(cascadeConfiguration.RollupView))
            {
                return(true);
            }
#endif
            return(false);
        }
Exemplo n.º 5
0
        internal override void CheckSecurity(OrganizationRequest orgRequest, EntityReference userRef)
        {
            var request      = MakeRequest <DeleteRequest>(orgRequest);
            var casSelection = new CascadeSelection()
            {
                delete = true
            };
            var entity = core.GetDbEntityWithRelatedEntities(request.Target, EntityRole.Referenced, userRef, casSelection);

            if (entity == null)
            {
                throw new FaultException($"{request.Target.LogicalName} with Id '{request.Target.Id}' does not exist");
            }
            if (!security.HasPermission(entity, AccessRights.DeleteAccess, userRef))
            {
                throw new FaultException($"You do not have permission to access entity '{request.Target.LogicalName}' for delete");
            }
        }
Exemplo n.º 6
0
        //TODO: update to also take in cascading filtering on Assign, Delete, Merge, reparent, rollup
        internal Entity GetDbEntityWithRelatedEntities(EntityReference reference, EntityRole primaryEntityRole, EntityReference userRef, CascadeSelection cascadeSelection = null, params Relationship[] relations)
        {
            var entity = db.GetEntityOrNull(reference);

            if (entity == null)
            {
                return(null);
            }

            var metadata = this.metadata.EntityMetadata.GetMetadata(entity.LogicalName);

            if (entity.RelatedEntities.Count() > 0)
            {
                var clone = entity.CloneEntity(metadata, new ColumnSet(true));
                db.Update(clone);
                entity = clone;
            }
            var relationQuery     = new RelationshipQueryCollection();
            var relationsMetadata =
                primaryEntityRole == EntityRole.Referenced
                ? metadata.OneToManyRelationships
                : metadata.ManyToOneRelationships;

            if (cascadeSelection != null)
            {
                relationsMetadata.Where(x => CascadeCompare(x.CascadeConfiguration, cascadeSelection));
            }

            if (relations.Any())
            {
                relationsMetadata = relationsMetadata.Join(relations, x => x.SchemaName, y => y.SchemaName, (r1, r2) => r1).ToArray();
            }
            relationQuery.AddRange(
                relationsMetadata
                .Select(relationshipMeta =>
            {
                var rel = new Relationship()
                {
                    SchemaName        = relationshipMeta.SchemaName,
                    PrimaryEntityRole = primaryEntityRole
                };
                var query = new QueryExpression()
                {
                    EntityName =
                        primaryEntityRole == EntityRole.Referenced
                            ? relationshipMeta.ReferencingEntity
                            : relationshipMeta.ReferencedEntity,
                    ColumnSet = new ColumnSet(true)
                };
                return(new KeyValuePair <Relationship, QueryBase>(rel, query));
            }));


            foreach (var relationshipMeta in relationsMetadata)
            {
            }

            if (cascadeSelection == null)
            {
                var relationShipManyMetadata = metadata.ManyToManyRelationships;
                if (relations.Any())
                {
                    relationShipManyMetadata = relationShipManyMetadata.Join(relations, x => x.SchemaName, y => y.SchemaName, (r1, r2) => r1).ToArray();
                }
                relationQuery.AddRange(relationShipManyMetadata
                                       .Select(relationshipMeta =>
                {
                    var rel = new Relationship()
                    {
                        SchemaName = relationshipMeta.SchemaName
                    };
                    var query = new QueryExpression(relationshipMeta.IntersectEntityName)
                    {
                        ColumnSet = new ColumnSet(true)
                    };
                    return(new KeyValuePair <Relationship, QueryBase>(rel, query));
                }));
            }

            AddRelatedEntities(entity, relationQuery, userRef);
            return(entity);
        }