Example #1
0
        internal override void CheckSecurity(OrganizationRequest orgRequest, EntityReference userRef)
        {
            var request  = MakeRequest <CreateRequest>(orgRequest);
            var settings = MockupExecutionContext.GetSettings(request);
            var entity   = request.Target;

            if (entity.LogicalName == null)
            {
                throw new MockupException("Entity needs a logical name");
            }

            var entityMetadata  = metadata.EntityMetadata.GetMetadata(entity.LogicalName);
            var clonedEntity    = entity.CloneEntity(entityMetadata, new ColumnSet(true));
            var validAttributes = clonedEntity.Attributes.Where(x => x.Value != null);

            clonedEntity.Attributes = new AttributeCollection();
            clonedEntity.Attributes.AddRange(validAttributes);

            if (userRef != null && userRef.Id != Guid.Empty)
            {
                if (!security.HasPermission(clonedEntity, AccessRights.CreateAccess, userRef))
                {
                    throw new FaultException($"Trying to create entity '{entity.LogicalName}'" +
                                             $", but the calling user with id '{userRef.Id}' does not have Create access for that entity (SecLib::AccessCheckEx2 failed)");
                }

                if (core.GetMockupSettings().AppendAndAppendToPrivilegeCheck.GetValueOrDefault(true))
                {
                    var references = clonedEntity.Attributes
                                     .Where(x => x.Value is EntityReference && x.Key != "ownerid")
                                     .ToArray();

                    if (references.Any())
                    {
                        if (!security.HasPermission(clonedEntity, AccessRights.AppendAccess, userRef))
                        {
                            throw new FaultException($"Trying to create entity '{entity.LogicalName}' with references" +
                                                     $", but the calling user with id '{userRef.Id}' does not have Append access for that entity (SecLib::AccessCheckEx2 failed)");
                        }
                    }

                    foreach (var attr in references)
                    {
                        var reference = attr.Value as EntityReference;
                        if (settings.ServiceRole == MockupServiceSettings.Role.UI &&
                            !security.HasPermission(reference, AccessRights.ReadAccess, userRef))
                        {
                            throw new FaultException($"Trying to create entity '{entity.LogicalName}'" +
                                                     $", but the calling user with id '{userRef.Id}' does not have read access for referenced entity '{reference.LogicalName}' on attribute '{attr.Key}' (SecLib::AccessCheckEx2 failed)");
                        }

                        if (!security.HasPermission(reference, AccessRights.AppendToAccess, userRef))
                        {
                            throw new FaultException($"Trying to create entity '{entity.LogicalName}'" +
                                                     $", but the calling user with id '{userRef.Id}' does not have AppendTo access for referenced entity '{reference.LogicalName}' on attribute '{attr.Key}'");
                        }
                    }
                }
            }
        }
Example #2
0
        private RetrieveResponse HandleRetrieve(OrganizationRequest orgRequest, EntityReference userRef)
        {
            var request  = MakeRequest <RetrieveRequest>(orgRequest);
            var resp     = new RetrieveResponse();
            var settings = MockupExecutionContext.GetSettings(request);

            resp.Results["Entity"] = dataMethods.Retrieve(request.Target, request.ColumnSet, request.RelatedEntitiesQuery, settings.SetUnsettableFields, userRef);
            return(resp);
        }
Example #3
0
        private UpdateResponse HandleUpdate(OrganizationRequest orgRequest, EntityReference userRef)
        {
            var request  = MakeRequest <UpdateRequest>(orgRequest);
            var resp     = new UpdateResponse();
            var settings = MockupExecutionContext.GetSettings(request);

            dataMethods.Update(request.Target, userRef, settings.ServiceRole);
            resp.Results["Target"] = request.Target;
            return(resp);
        }
        internal override OrganizationResponse Execute(OrganizationRequest orgRequest, EntityReference userRef)
        {
            var request  = MakeRequest <RetrieveRequest>(orgRequest);
            var settings = MockupExecutionContext.GetSettings(request);


            if (request.Target.LogicalName == null)
            {
                throw new FaultException("You must provide a LogicalName");
            }


#if !(XRM_MOCKUP_2011 || XRM_MOCKUP_2013 || XRM_MOCKUP_2015)
            if (request.ColumnSet == null && request.Target.KeyAttributes.Count == 0)
            {
                throw new FaultException("The columnset parameter must not be null when no KeyAttributes are provided");
            }
#else
            if (request.ColumnSet == null)
            {
                throw new FaultException("The columnset parameter must not be null");
            }
#endif
            var row = db.GetDbRow(request.Target);

            if (!security.HasPermission(row.ToEntity(), AccessRights.ReadAccess, userRef))
            {
                throw new FaultException($"Calling user with id '{userRef.Id}' does not have permission to read entity '{row.Table.TableName}'");
            }

#if !(XRM_MOCKUP_2011 || XRM_MOCKUP_2013)
            core.ExecuteCalculatedFields(row);
#endif
            row = db.GetDbRow(request.Target);
            var entity = core.GetStronglyTypedEntity(row.ToEntity(), row.Metadata, request.ColumnSet);

            Utility.SetFormmattedValues(db, entity, row.Metadata);

            if (!settings.SetUnsettableFields)
            {
                Utility.RemoveUnsettableAttributes("Retrieve", row.Metadata, entity);
            }

#if !(XRM_MOCKUP_2011 || XRM_MOCKUP_2013)
            Utility.HandlePrecision(metadata, db, entity);
#endif
            if (request.RelatedEntitiesQuery != null)
            {
                core.AddRelatedEntities(entity, request.RelatedEntitiesQuery, userRef);
            }

            var resp = new RetrieveResponse();
            resp.Results["Entity"] = entity;
            return(resp);
        }
        internal override void CheckSecurity(OrganizationRequest orgRequest, EntityReference userRef)
        {
            var request  = MakeRequest <UpdateRequest>(orgRequest);
            var settings = MockupExecutionContext.GetSettings(request);

            var entRef    = request.Target.ToEntityReferenceWithKeyAttributes();
            var entity    = request.Target;
            var row       = db.GetDbRow(entRef);
            var xrmEntity = row.ToEntity();

            if (!security.HasPermission(xrmEntity, AccessRights.WriteAccess, userRef))
            {
                throw new FaultException($"Trying to update entity '{row.Table.TableName}'" +
                                         $", but calling user with id '{userRef.Id}' does not have write access for that entity");
            }

            if (core.GetMockupSettings().AppendAndAppendToPrivilegeCheck.GetValueOrDefault(true))
            {
                var references = entity.Attributes
                                 .Where(x => x.Value is EntityReference && x.Key != "ownerid")
                                 .ToArray();

                if (references.Any())
                {
                    if (!security.HasPermission(xrmEntity, AccessRights.AppendAccess, userRef))
                    {
                        throw new FaultException($"Trying to update entity '{xrmEntity.LogicalName}' with references" +
                                                 $", but the calling user with id '{userRef.Id}' does not have Append access for that entity");
                    }
                }

                foreach (var attr in references)
                {
                    var existingRef = xrmEntity.GetAttributeValue <EntityReference>(attr.Key);
                    var newRef      = attr.Value as EntityReference;
                    if (existingRef?.Id == newRef.Id)
                    {
                        continue;
                    }

                    if (settings.ServiceRole == MockupServiceSettings.Role.UI && !security.HasPermission(newRef, AccessRights.ReadAccess, userRef))
                    {
                        throw new FaultException($"Trying to update entity '{xrmEntity.LogicalName}'" +
                                                 $", but the calling user with id '{userRef.Id}' does not have read access for referenced entity '{newRef.LogicalName}' on attribute '{attr.Key}'");
                    }
                    if (!security.HasPermission(newRef, AccessRights.AppendToAccess, userRef))
                    {
                        throw new FaultException($"Trying to update entity '{xrmEntity.LogicalName}'" +
                                                 $", but the calling user with id '{userRef.Id}' does not have AppendTo access for referenced entity '{newRef.LogicalName}' on attribute '{attr.Key}'");
                    }
                }
            }
        }
        internal override OrganizationResponse Execute(OrganizationRequest orgRequest, EntityReference userRef)
        {
            var request  = MakeRequest <AddUserToRecordTeamRequest>(orgRequest);
            var resp     = new AddUserToRecordTeamResponse();
            var settings = MockupExecutionContext.GetSettings(request);

            //check to see if the access team exists
            //where regarding object id = request.record.id
            //and teamtemplateid = request.teamtemplated

            var currentTeams = db.GetDBEntityRows("team");

            currentTeams = currentTeams.Where(x => x.GetColumn("regardingobjectid") != null);
            currentTeams = currentTeams.Where(x => (x.ToEntity().GetAttributeValue <EntityReference>("regardingobjectid").Id == request.Record.Id));
            currentTeams = currentTeams.Where(x => x.GetColumn("teamtemplateid") != null);
            currentTeams = currentTeams.Where(x => (x.ToEntity().GetAttributeValue <EntityReference>("teamtemplateid").Id == request.TeamTemplateId));

            Entity team;

            if (!currentTeams.Any())
            {
                team    = new Entity("team");
                team.Id = Guid.NewGuid();
                team["regardingobjectid"] = request.Record;
                team["teamtemplateid"]    = new EntityReference("teamtemplate", request.TeamTemplateId);
                team["teamtype"]          = new OptionSetValue(1); //access team
                db.Add(team);
                resp.Results["AccessTeamId"] = team.Id;
            }
            else
            {
                team = currentTeams.Single().ToEntity();
            }

            //and check to see if the user is a member of it
            var currentTeamMembers = db.GetDBEntityRows("teammembership");

            currentTeamMembers = currentTeamMembers.Where(x => x.GetColumn("teamid") != null);
            currentTeamMembers = currentTeamMembers.Where(x => (x.ToEntity().GetAttributeValue <Guid>("teamid") == team.Id));
            currentTeamMembers = currentTeamMembers.Where(x => x.GetColumn("systemuserid") != null);
            currentTeamMembers = currentTeamMembers.Where(x => (x.ToEntity().GetAttributeValue <Guid>("systemuserid") == request.SystemUserId));

            if (!currentTeamMembers.Any())
            {
                var teamMember = new Entity("teammembership");
                teamMember["teamid"]       = team.Id;
                teamMember["systemuserid"] = request.SystemUserId;
                db.Add(teamMember);
            }

            return(resp);
        }
Example #7
0
        internal OrganizationResponse Execute(OrganizationRequest request, EntityReference userRef, PluginContext parentPluginContext)
        {
            // Setup
            HandleInternalPreOperations(request, userRef);

            var primaryRef = Mappings.GetPrimaryEntityReferenceFromRequest(request);

            // Create the plugin context
            var pluginContext = new PluginContext()
            {
                UserId            = userRef.Id,
                InitiatingUserId  = userRef.Id,
                MessageName       = RequestNameToMessageName(request.RequestName),
                Depth             = 1,
                OrganizationName  = this.OrganizationName,
                OrganizationId    = this.OrganizationId,
                PrimaryEntityName = primaryRef?.LogicalName,
            };

            if (primaryRef != null)
            {
                var refEntity = db.GetEntityOrNull(primaryRef);
                pluginContext.PrimaryEntityId = refEntity == null ? Guid.Empty : refEntity.Id;
            }

            foreach (var prop in request.Parameters)
            {
                pluginContext.InputParameters[prop.Key] = prop.Value;
            }
            if (parentPluginContext != null)
            {
                pluginContext.ParentContext = parentPluginContext;
                pluginContext.Depth         = parentPluginContext.Depth + 1;
            }
            var buRef = GetBusinessUnit(userRef);

            pluginContext.BusinessUnitId = buRef.Id;

            Mappings.RequestToEventOperation.TryGetValue(request.GetType(), out EventOperation? eventOp);

            var entityInfo = GetEntityInfo(request);

            var settings = MockupExecutionContext.GetSettings(request);

            // Validation
            if (!settings.SetUnsettableFields && (request is UpdateRequest || request is CreateRequest))
            {
                var entity = request is UpdateRequest ? (request as UpdateRequest).Target : (request as CreateRequest).Target;
                Utility.RemoveUnsettableAttributes(request.RequestName, metadata.EntityMetadata.GetMetadata(entity.LogicalName), entity);
            }

            Entity preImage  = null;
            Entity postImage = null;

            if (settings.TriggerProcesses && entityInfo != null)
            {
                preImage = TryRetrieve(primaryRef);
                if (preImage != null)
                {
                    primaryRef.Id = preImage.Id;
                }
            }

            if (settings.TriggerProcesses && entityInfo != null && eventOp.HasValue)
            {
                // System Pre-validation
                pluginManager.TriggerSystem(eventOp.Value, ExecutionStage.PreValidation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                // Pre-validation
                pluginManager.Trigger(eventOp.Value, ExecutionStage.PreValidation, entityInfo.Item1, preImage, postImage, pluginContext, this);

                // Shared variables should be moved to parent context when transitioning from 10 to 20.
                pluginContext.ParentContext = pluginContext.Clone();
                pluginContext.SharedVariables.Clear();

                // Pre-operation
                pluginManager.Trigger(eventOp.Value, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                workflowManager.Trigger(eventOp.Value, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);

                // System Pre-operation
                pluginManager.TriggerSystem(eventOp.Value, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
            }

            // Core operation
            OrganizationResponse response = ExecuteRequest(request, userRef, parentPluginContext);

            // Post-operation
            if (settings.TriggerProcesses && entityInfo != null)
            {
                postImage = TryRetrieve(primaryRef);
                if (eventOp.HasValue)
                {
                    pluginManager.TriggerSystem(eventOp.Value, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                    pluginManager.Trigger(eventOp.Value, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                    workflowManager.Trigger(eventOp.Value, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                }
                workflowManager.ExecuteWaitingWorkflows(pluginContext, this);
            }

            return(response);
        }
Example #8
0
 private T SendRequest <T>(OrganizationRequest request) where T : OrganizationResponse
 {
     MockupExecutionContext.SetSettings(request, settings);
     return((T)core.Execute(request, userRef ?? core.AdminUserRef, pluginContext));
 }
        internal override OrganizationResponse Execute(OrganizationRequest orgRequest, EntityReference userRef)
        {
            var request  = MakeRequest <UpdateRequest>(orgRequest);
            var settings = MockupExecutionContext.GetSettings(request);

            var entRef = request.Target.ToEntityReferenceWithKeyAttributes();
            var row    = db.GetDbRow(entRef);

            if (settings.ServiceRole == MockupServiceSettings.Role.UI &&
                row.Table.TableName != LogicalNames.Opportunity &&
                row.Table.TableName != LogicalNames.SystemUser &&
                row.GetColumn <int?>("statecode") == 1)
            {
                throw new MockupException($"Trying to update inactive '{row.Table.TableName}', which is impossible in UI");
            }

            if (settings.ServiceRole == MockupServiceSettings.Role.UI &&
                row.Table.TableName == LogicalNames.Opportunity &&
                row.GetColumn <int?>("statecode") == 1)
            {
                throw new MockupException($"Trying to update closed opportunity '{row.Id}', which is impossible in UI");
            }


            if (settings.ServiceRole == MockupServiceSettings.Role.UI &&
                row.Table.TableName == LogicalNames.SystemUser &&
                row.GetColumn <bool?>("isdisabled") == true)
            {
                throw new MockupException($"Trying to update inactive systemuser '{row.Id}', which is impossible in UI");
            }

            // modify for all activites
            //if (entity.LogicalName == "activity" && dbEntity.GetAttributeValue<OptionSetValue>("statecode")?.Value == 1) return;
            var xrmEntity = row.ToEntity();

            if (!security.HasPermission(row.ToEntity(), AccessRights.WriteAccess, userRef))
            {
                throw new FaultException($"Trying to update entity '{row.Table.TableName}'" +
                                         $", but calling user with id '{userRef.Id}' does not have write access for that entity");
            }

            var ownerRef = request.Target.GetAttributeValue <EntityReference>("ownerid");

#if !(XRM_MOCKUP_2011 || XRM_MOCKUP_2013 || XRM_MOCKUP_2015)
            if (ownerRef != null)
            {
                security.CheckAssignPermission(xrmEntity, ownerRef, userRef);
            }
#endif

            var updEntity = request.Target.CloneEntity(row.Metadata, new ColumnSet(true));

            if (updEntity.Contains("statecode") || updEntity.Contains("statuscode"))
            {
                var defaultStateStatus = metadata.DefaultStateStatus[updEntity.LogicalName];
                var statusmeta         =
                    (metadata.EntityMetadata.GetMetadata(updEntity.LogicalName)
                     .Attributes.FirstOrDefault(a => a.LogicalName == "statuscode") as StatusAttributeMetadata)
                    ?.OptionSet.Options
                    .Cast <StatusOptionMetadata>()
                    .FirstOrDefault(o => o.Value == updEntity.GetAttributeValue <OptionSetValue>("statuscode")?.Value);

                if ((!updEntity.Contains("statecode") || updEntity.GetAttributeValue <OptionSetValue>("statecode") == null) &&
                    statusmeta != null)
                {
                    updEntity["statecode"] = new OptionSetValue(statusmeta.State.Value);
                }
                else if (!updEntity.Contains("statuscode") || updEntity.GetAttributeValue <OptionSetValue>("statuscode") == null)
                {
                    var state = updEntity.GetAttributeValue <OptionSetValue>("statecode").Value;
                    updEntity["statuscode"] = new OptionSetValue(defaultStateStatus[state]);
                }
            }


#if !(XRM_MOCKUP_2011 || XRM_MOCKUP_2013)
            Utility.CheckStatusTransitions(row.Metadata, updEntity, xrmEntity);
#endif


            if (Utility.HasCircularReference(metadata.EntityMetadata, updEntity))
            {
                throw new FaultException($"Trying to create entity '{xrmEntity.LogicalName}', but the attributes had a circular reference");
            }

            if (updEntity.LogicalName == LogicalNames.Contact || updEntity.LogicalName == LogicalNames.Lead || updEntity.LogicalName == LogicalNames.SystemUser)
            {
                Utility.SetFullName(metadata, updEntity);
            }

            updEntity.Attributes
            .Where(x => x.Value is string && string.IsNullOrEmpty((string)x.Value))
            .ToList()
            .ForEach(x => updEntity[x.Key] = null);

            xrmEntity.SetAttributes(updEntity.Attributes, metadata.EntityMetadata[updEntity.LogicalName]);

            var transactioncurrencyId = "transactioncurrencyid";
            if (updEntity.LogicalName != LogicalNames.TransactionCurrency &&
                (updEntity.Attributes.ContainsKey(transactioncurrencyId) ||
                 updEntity.Attributes.Any(a => row.Metadata.Attributes.Any(m => m.LogicalName == a.Key && m is MoneyAttributeMetadata))))
            {
                if (!xrmEntity.Attributes.ContainsKey(transactioncurrencyId))
                {
                    var user = db.GetEntity(userRef);
                    if (user.Attributes.ContainsKey(transactioncurrencyId))
                    {
                        xrmEntity[transactioncurrencyId] = user[transactioncurrencyId];
                    }
                    else
                    {
                        xrmEntity[transactioncurrencyId] = core.baseCurrency;
                    }
                }
                var currencyId = xrmEntity.GetAttributeValue <EntityReference>(transactioncurrencyId);
                var currency   = db.GetEntity(LogicalNames.TransactionCurrency, currencyId.Id);
                xrmEntity["exchangerate"] = currency.GetAttributeValue <decimal?>("exchangerate");
                Utility.HandleCurrencies(metadata, db, xrmEntity);
            }

#if !(XRM_MOCKUP_2011 || XRM_MOCKUP_2013 || XRM_MOCKUP_2015)
            if (updEntity.Attributes.ContainsKey("statecode") || updEntity.Attributes.ContainsKey("statuscode"))
            {
                Utility.HandleCurrencies(metadata, db, xrmEntity);
            }
#endif

            if (ownerRef != null)
            {
                Utility.SetOwner(db, security, metadata, xrmEntity, ownerRef);
#if !(XRM_MOCKUP_2011 || XRM_MOCKUP_2013 || XRM_MOCKUP_2015)
                security.CascadeOwnerUpdate(xrmEntity, userRef, ownerRef);
#endif
            }

            if (Utility.Activities.Contains(xrmEntity.LogicalName))
            {
                xrmEntity["activitytypecode"] = Utility.ActivityTypeCode[xrmEntity.LogicalName];

                var req = new UpdateRequest {
                    Target = xrmEntity.ToActivityPointer()
                };
                core.Execute(req, userRef);
            }

            Utility.Touch(xrmEntity, row.Metadata, core.TimeOffset, userRef);

            db.Update(xrmEntity);

            return(new UpdateResponse());
        }
Example #10
0
        internal OrganizationResponse Execute(OrganizationRequest request, EntityReference userRef, PluginContext parentPluginContext)
        {
            // Setup
            HandleInternalPreOperations(request, userRef);

            var primaryRef = Mappings.GetPrimaryEntityReferenceFromRequest(request);

            // Create the plugin context
            var pluginContext = new PluginContext()
            {
                UserId            = userRef.Id,
                InitiatingUserId  = userRef.Id,
                MessageName       = RequestNameToMessageName(request.RequestName),
                Depth             = 1,
                OrganizationName  = this.OrganizationName,
                OrganizationId    = this.OrganizationId,
                PrimaryEntityName = primaryRef?.LogicalName,
            };

            if (primaryRef != null)
            {
                var refEntity = db.GetEntityOrNull(primaryRef);
                pluginContext.PrimaryEntityId = refEntity == null ? Guid.Empty : refEntity.Id;
            }

            foreach (var prop in request.Parameters)
            {
                pluginContext.InputParameters[prop.Key] = prop.Value;
            }
            if (parentPluginContext != null)
            {
                pluginContext.ParentContext = parentPluginContext;
                pluginContext.Depth         = parentPluginContext.Depth + 1;
            }
            var buRef = GetBusinessUnit(userRef);

            pluginContext.BusinessUnitId = buRef.Id;

            Mappings.RequestToEventOperation.TryGetValue(request.GetType(), out string eventOp);
            if (string.IsNullOrEmpty(eventOp))
            {
                //then this may be a custom action request, so continue with the request name
                if (request.RequestName.Contains("_")) //if we have a prefix then assume it is a custom action
                {
                    eventOp = request.RequestName.ToLower();
                }
            }


            var entityInfo = GetEntityInfo(request);

            var settings = MockupExecutionContext.GetSettings(request);

            // Validation
            if (!settings.SetUnsettableFields && (request is UpdateRequest || request is CreateRequest))
            {
                var entity = request is UpdateRequest ? (request as UpdateRequest).Target : (request as CreateRequest).Target;
                Utility.RemoveUnsettableAttributes(request.RequestName, metadata.EntityMetadata.GetMetadata(entity.LogicalName), entity);
            }

            Entity preImage  = null;
            Entity postImage = null;

            if (settings.TriggerProcesses && entityInfo != null)
            {
                preImage = TryRetrieve(primaryRef);
                if (preImage != null)
                {
                    primaryRef.Id = preImage.Id;
                }
            }

            if (settings.TriggerProcesses && entityInfo != null && !string.IsNullOrEmpty(eventOp))
            {
                // System Pre-validation
                pluginManager.TriggerSystem(eventOp, ExecutionStage.PreValidation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                // Pre-validation
                pluginManager.Trigger(eventOp, ExecutionStage.PreValidation, entityInfo.Item1, preImage, postImage, pluginContext, this);

                // Shared variables should be moved to parent context when transitioning from 10 to 20.
                pluginContext.ParentContext = pluginContext.Clone();
                pluginContext.SharedVariables.Clear();

                // Pre-operation
                pluginManager.Trigger(eventOp, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                workflowManager.TriggerSync(eventOp, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);

                // System Pre-operation
                pluginManager.TriggerSystem(eventOp, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
            }

            // Core operation
            OrganizationResponse response = ExecuteRequest(request, userRef, parentPluginContext);

            // Post-operation
            if (settings.TriggerProcesses && entityInfo != null)
            {
                postImage = TryRetrieve(primaryRef);

                // In RetrieveMultipleRequests, the OutputParameters bag contains the entity collection
                if (request is RetrieveMultipleRequest)
                {
                    pluginContext.OutputParameters["BusinessEntityCollection"] = (response as RetrieveMultipleResponse)?.EntityCollection;
                }

                if (!string.IsNullOrEmpty(eventOp))
                {
                    //copy the createon etc system attributes onto the target so they are available for postoperation processing
                    CopySystemAttributes(postImage, entityInfo.Item1 as Entity);

                    pluginManager.TriggerSystem(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                    pluginManager.TriggerSync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                    pluginManager.StageAsync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);

                    workflowManager.TriggerSync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                    workflowManager.StageAsync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                }

                //When last Sync has been executed we trigger the Async jobs.
                if (parentPluginContext == null)
                {
                    pluginManager.TriggerAsyncWaitingJobs();
                    workflowManager.TriggerAsync(this);
                }
                workflowManager.ExecuteWaitingWorkflows(pluginContext, this);
            }
            return(response);
        }
        internal override OrganizationResponse Execute(OrganizationRequest orgRequest, EntityReference userRef)
        {
            var request  = MakeRequest <CreateRequest>(orgRequest);
            var resp     = new CreateResponse();
            var settings = MockupExecutionContext.GetSettings(request);
            var entity   = request.Target;

            if (entity.LogicalName == null)
            {
                throw new MockupException("Entity needs a logical name");
            }

            var entityMetadata  = metadata.EntityMetadata.GetMetadata(entity.LogicalName);
            var clonedEntity    = entity.CloneEntity(entityMetadata, new ColumnSet(true));
            var validAttributes = clonedEntity.Attributes.Where(x => x.Value != null);

            clonedEntity.Attributes = new AttributeCollection();
            clonedEntity.Attributes.AddRange(validAttributes);


            if (userRef != null && userRef.Id != Guid.Empty && !security.HasPermission(clonedEntity, AccessRights.CreateAccess, userRef))
            {
                throw new FaultException($"Trying to create entity '{entity.LogicalName}'" +
                                         $", but the calling user with id '{userRef.Id}' does not have create access for that entity");
            }

            if (Utility.HasCircularReference(metadata.EntityMetadata, clonedEntity))
            {
                throw new FaultException($"Trying to create entity '{clonedEntity.LogicalName}', but the attributes had a circular reference");
            }

            var transactioncurrencyId = "transactioncurrencyid";
            var exchangerate          = "exchangerate";

            if (!clonedEntity.Attributes.ContainsKey(transactioncurrencyId) &&
                Utility.IsSettableAttribute(transactioncurrencyId, entityMetadata) &&
                entityMetadata.Attributes.Any(m => m is MoneyAttributeMetadata) &&
                (settings.ServiceRole == MockupServiceSettings.Role.UI ||
                 (settings.ServiceRole == MockupServiceSettings.Role.SDK && clonedEntity.Attributes.Any(
                      attr => entityMetadata.Attributes.Where(a => a is MoneyAttributeMetadata).Any(m => m.LogicalName == attr.Key)))))
            {
                var user = db.GetEntityOrNull(userRef);
                if (user.Attributes.ContainsKey(transactioncurrencyId))
                {
                    clonedEntity.Attributes[transactioncurrencyId] = user[transactioncurrencyId];
                }
                else
                {
                    clonedEntity.Attributes[transactioncurrencyId] = Utility.GetBaseCurrency(metadata);
                }
            }

            if (!clonedEntity.Attributes.ContainsKey(exchangerate) &&
                Utility.IsSettableAttribute(exchangerate, entityMetadata) &&
                clonedEntity.Attributes.ContainsKey(transactioncurrencyId))
            {
                var currencyId = clonedEntity.GetAttributeValue <EntityReference>(transactioncurrencyId);
                var currency   = db.GetEntityOrNull(currencyId);
                clonedEntity.Attributes[exchangerate] = currency["exchangerate"];
                Utility.HandleCurrencies(metadata, db, clonedEntity);
            }

            if (Utility.IsSettableAttribute("statecode", entityMetadata) &&
                Utility.IsSettableAttribute("statuscode", entityMetadata))
            {
                var defaultState       = 0;
                var defaultStateStatus = metadata.DefaultStateStatus[clonedEntity.LogicalName];
                if (!clonedEntity.Attributes.ContainsKey("statecode") &&
                    !clonedEntity.Attributes.ContainsKey("statuscode"))
                {
                    clonedEntity["statecode"]  = new OptionSetValue(defaultState);
                    clonedEntity["statuscode"] = new OptionSetValue(defaultStateStatus[defaultState]);
                }
                else
                {
                    var statusmeta =
                        (entityMetadata.Attributes.FirstOrDefault(a => a.LogicalName == "statuscode") as StatusAttributeMetadata)
                        ?.OptionSet.Options
                        .Cast <StatusOptionMetadata>()
                        .FirstOrDefault(o => o.Value == clonedEntity.GetAttributeValue <OptionSetValue>("statuscode")?.Value);
                    if (clonedEntity.LogicalName != "opportunityclose" && // is allowed to be created inactive
                        ((clonedEntity.Attributes.ContainsKey("statecode") &&
                          clonedEntity.GetAttributeValue <OptionSetValue>("statecode")?.Value != defaultState) ||
                         (clonedEntity.Attributes.ContainsKey("statuscode") && statusmeta?.State != defaultState)))
                    {
                        clonedEntity["statecode"]  = new OptionSetValue(defaultState);
                        clonedEntity["statuscode"] = new OptionSetValue(defaultStateStatus[defaultState]);
                    }
                    else if (!clonedEntity.Contains("statecode") || clonedEntity.GetAttributeValue <OptionSetValue>("statecode") == null)
                    {
                        clonedEntity["statecode"] = new OptionSetValue(statusmeta.State.Value);
                    }
                    else if (!clonedEntity.Contains("statuscode") || clonedEntity.GetAttributeValue <OptionSetValue>("statuscode") == null)
                    {
                        clonedEntity["statuscode"] = new OptionSetValue(defaultStateStatus[defaultState]);
                    }
                }
            }

            if (Utility.IsSettableAttribute("createdon", entityMetadata))
            {
                clonedEntity["createdon"] = DateTime.UtcNow.Add(core.TimeOffset);
            }
            if (Utility.IsSettableAttribute("createdby", entityMetadata))
            {
                clonedEntity["createdby"] = userRef;
            }

            if (Utility.IsSettableAttribute("modifiedon", entityMetadata) &&
                Utility.IsSettableAttribute("modifiedby", entityMetadata))
            {
                clonedEntity["modifiedon"] = clonedEntity["createdon"];
                clonedEntity["modifiedby"] = clonedEntity["createdby"];
            }

            var owner = userRef;

            if (clonedEntity.Attributes.ContainsKey("ownerid"))
            {
                owner = clonedEntity.GetAttributeValue <EntityReference>("ownerid");
            }
            Utility.SetOwner(db, security, metadata, clonedEntity, owner);

            if (!clonedEntity.Attributes.ContainsKey("businessunitid") &&
                clonedEntity.LogicalName == LogicalNames.SystemUser || clonedEntity.LogicalName == LogicalNames.Team)
            {
                clonedEntity["businessunitid"] = metadata.RootBusinessUnit.ToEntityReference();
            }

            if (clonedEntity.LogicalName == LogicalNames.BusinessUnit && !clonedEntity.Attributes.ContainsKey("parentbusinessunitid"))
            {
                clonedEntity["parentbusinessunitid"] = metadata.RootBusinessUnit.ToEntityReference();
            }
            if (settings.ServiceRole == MockupServiceSettings.Role.UI)
            {
                foreach (var attr in entityMetadata.Attributes.Where(a => (a as BooleanAttributeMetadata)?.DefaultValue != null).ToList())
                {
                    if (!clonedEntity.Attributes.Any(a => a.Key == attr.LogicalName))
                    {
                        clonedEntity[attr.LogicalName] = (attr as BooleanAttributeMetadata).DefaultValue;
                    }
                }

                foreach (var attr in entityMetadata.Attributes.Where(a =>
                                                                     (a as PicklistAttributeMetadata)?.DefaultFormValue != null && (a as PicklistAttributeMetadata)?.DefaultFormValue.Value != -1).ToList())
                {
                    if (!clonedEntity.Attributes.Any(a => a.Key == attr.LogicalName))
                    {
                        clonedEntity[attr.LogicalName] = new OptionSetValue((attr as PicklistAttributeMetadata).DefaultFormValue.Value);
                    }
                }
            }

            if (clonedEntity.LogicalName == LogicalNames.Contact || clonedEntity.LogicalName == LogicalNames.Lead || clonedEntity.LogicalName == LogicalNames.SystemUser)
            {
                Utility.SetFullName(metadata, clonedEntity);
            }

            if (Utility.Activities.Contains(clonedEntity.LogicalName))
            {
                clonedEntity["activitytypecode"] = Utility.ActivityTypeCode[clonedEntity.LogicalName];

                var req = new CreateRequest {
                    Target = clonedEntity.ToActivityPointer()
                };
                core.Execute(req, userRef);
            }

            db.Add(clonedEntity);

            if (clonedEntity.LogicalName == LogicalNames.BusinessUnit)
            {
                security.AddRolesForBusinessUnit(db, clonedEntity.ToEntityReference());
            }

            if (entity.RelatedEntities.Count > 0)
            {
                foreach (var relatedEntities in entity.RelatedEntities)
                {
                    if (Utility.GetRelationshipMetadataDefaultNull(metadata.EntityMetadata, relatedEntities.Key.SchemaName, Guid.Empty, userRef) == null)
                    {
                        throw new FaultException($"Relationship with schemaname '{relatedEntities.Key.SchemaName}' does not exist in metadata");
                    }
                    foreach (var relatedEntity in relatedEntities.Value.Entities)
                    {
                        var req = new CreateRequest()
                        {
                            Target = relatedEntity
                        };
                        core.Execute(req, userRef);
                    }
                    var associateReq = new AssociateRequest {
                        Target          = entity.ToEntityReference(),
                        Relationship    = relatedEntities.Key,
                        RelatedEntities = new EntityReferenceCollection(relatedEntities.Value.Entities.Select(e => e.ToEntityReference()).ToList())
                    };
                    core.Execute(associateReq, userRef);
                }
            }
            resp.Results.Add("id", clonedEntity.Id);
            return(resp);
        }
Example #12
0
        internal OrganizationResponse Execute(OrganizationRequest request, EntityReference userRef,
                                              PluginContext parentPluginContext)
        {
            // Setup
            HandleInternalPreOperations(request, userRef);

            var primaryRef = Mappings.GetPrimaryEntityReferenceFromRequest(request);

            // Create the plugin context
            var pluginContext = new PluginContext()
            {
                UserId            = userRef.Id,
                InitiatingUserId  = userRef.Id,
                MessageName       = RequestNameToMessageName(request.RequestName),
                Depth             = 1,
                ExtensionDepth    = 1,
                OrganizationName  = this.OrganizationName,
                OrganizationId    = this.OrganizationId,
                PrimaryEntityName = primaryRef?.LogicalName,
            };

            if (primaryRef != null)
            {
                var refEntity = db.GetEntityOrNull(primaryRef);
                pluginContext.PrimaryEntityId = refEntity == null ? Guid.Empty : refEntity.Id;
            }

            foreach (var prop in request.Parameters)
            {
                pluginContext.InputParameters[prop.Key] = prop.Value;
            }

            if (parentPluginContext != null)
            {
                pluginContext.ParentContext        = parentPluginContext;
                pluginContext.Depth                = parentPluginContext.Depth + 1;
                pluginContext.ExtensionDepth       = parentPluginContext.ExtensionDepth + 1;
                parentPluginContext.ExtensionDepth = pluginContext.ExtensionDepth;
            }

            var buRef = GetBusinessUnit(userRef);

            pluginContext.BusinessUnitId = buRef.Id;

            Mappings.RequestToEventOperation.TryGetValue(request.GetType(), out string eventOp);

            var entityInfo = GetEntityInfo(request);

            var settings = MockupExecutionContext.GetSettings(request);

            // Validation
            if (!settings.SetUnsettableFields && (request is UpdateRequest || request is CreateRequest))
            {
                var entity = request is UpdateRequest
                    ? (request as UpdateRequest).Target
                    : (request as CreateRequest).Target;
                Utility.RemoveUnsettableAttributes(request.RequestName,
                                                   metadata.EntityMetadata.GetMetadata(entity.LogicalName), entity);
            }

            Entity preImage  = null;
            Entity postImage = null;

            if (settings.TriggerProcesses && entityInfo != null)
            {
                preImage = TryRetrieve(primaryRef);
                if (preImage != null)
                {
                    primaryRef.Id = preImage.Id;
                }
            }

            if (settings.TriggerProcesses && entityInfo != null)
            {
                // System Pre-validation
                pluginManager.TriggerSystem(eventOp, ExecutionStage.PreValidation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                // Pre-validation
                pluginManager.Trigger(eventOp, ExecutionStage.PreValidation, entityInfo.Item1, preImage, postImage, pluginContext, this);
            }

            //perform security checks for the request
            CheckRequestSecurity(request, userRef);

            if (settings.TriggerProcesses && entityInfo != null)
            {
                // Shared variables should be moved to parent context when transitioning from 10 to 20.
                pluginContext.ParentContext = pluginContext.Clone();
                pluginContext.SharedVariables.Clear();

                // Pre-operation
                pluginManager.Trigger(eventOp, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                workflowManager.TriggerSync(eventOp, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);

                // System Pre-operation
                pluginManager.TriggerSystem(eventOp, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
            }

            // Core operation
            OrganizationResponse response = ExecuteRequest(request, userRef, parentPluginContext);

            // Post-operation
            if (settings.TriggerProcesses && entityInfo != null)
            {
                postImage = TryRetrieve(primaryRef);

                // In RetrieveMultipleRequests, the OutputParameters bag contains the entity collection
                if (request is RetrieveMultipleRequest)
                {
                    pluginContext.OutputParameters["BusinessEntityCollection"] =
                        (response as RetrieveMultipleResponse)?.EntityCollection;
                }

                if (!string.IsNullOrEmpty(eventOp))
                {
                    //copy the createon etc system attributes onto the target so they are available for postoperation processing
                    CopySystemAttributes(postImage, entityInfo.Item1 as Entity);

                    pluginManager.TriggerSystem(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                    pluginManager.TriggerSync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                    pluginManager.StageAsync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);

                    workflowManager.TriggerSync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                    workflowManager.StageAsync(eventOp, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                }

                //When last Sync has been executed we trigger the Async jobs.
                if (parentPluginContext == null)
                {
                    pluginManager.TriggerAsyncWaitingJobs();
                    workflowManager.TriggerAsync(this);
                }

                workflowManager.ExecuteWaitingWorkflows(pluginContext, this);
            }

#if XRM_MOCKUP_365
            // Trigger Extension
            if (this.settings.MockUpExtensions.Any())
            {
                /*
                 * When moving business units, more than eight layers occur...
                 */
                if (pluginContext.ExtensionDepth > 8)
                {
                    throw new FaultException(
                              "This workflow job was canceled because the workflow that started it included an infinite loop." +
                              " Correct the workflow logic and try again.");
                }
            }

            switch (request.RequestName)
            {
            case "Create":
                var createResponse    = (CreateResponse)response;
                var entityLogicalName = ((Entity)request.Parameters["Target"]).LogicalName;

                var createdEntity =
                    GetDbRow(new EntityReference(entityLogicalName, createResponse.id))
                    .ToEntity();
                TriggerExtension(
                    new XrmExtension(this, userRef, pluginContext), request,
                    createdEntity, null, userRef);
                break;

            case "Update":
                var target        = (Entity)request.Parameters["Target"];
                var updatedEntity = GetDbRow(target.ToEntityReferenceWithKeyAttributes()).ToEntity();
                TriggerExtension(
                    new XrmExtension(this, userRef, pluginContext), request,
                    updatedEntity, preImage, userRef);
                break;

            case "Delete":
                TriggerExtension(
                    new XrmExtension(this, userRef, pluginContext), request,
                    null, preImage, userRef);
                break;
            }
#endif

            return(response);
        }
Example #13
0
        internal OrganizationResponse Execute(OrganizationRequest request, EntityReference userRef, PluginContext parentPluginContext)
        {
            // Setup
            dataMethods.HandleInternalPreOperations(request, userRef);

            var primaryRef = Mappings.GetPrimaryEntityReferenceFromRequest(request);

            // Create the plugin context
            var pluginContext = new PluginContext()
            {
                UserId            = userRef.Id,
                InitiatingUserId  = userRef.Id,
                MessageName       = RequestNameToMessageName(request.RequestName),
                Depth             = 1,
                OrganizationName  = dataMethods.OrganizationName,
                OrganizationId    = dataMethods.OrganizationId,
                PrimaryEntityName = primaryRef?.LogicalName,
            };

            if (primaryRef != null)
            {
                pluginContext.PrimaryEntityId = dataMethods.GetEntityId(primaryRef).GetValueOrDefault();
            }

            foreach (var prop in request.Parameters)
            {
                pluginContext.InputParameters[prop.Key] = prop.Value;
            }
            if (parentPluginContext != null)
            {
                pluginContext.ParentContext = parentPluginContext;
                pluginContext.Depth         = parentPluginContext.Depth + 1;
            }
            var buRef = GetBusinessUnit(userRef);

            Console.WriteLine($"User GUID: {userRef.Id}");
            Console.WriteLine($"BU GUID: {buRef.Id}");
            pluginContext.BusinessUnitId = buRef.Id;

            Mappings.RequestToEventOperation.TryGetValue(request.GetType(), out EventOperation? eventOp);

            var    entityInfo = GetEntityInfo(request);
            Entity preImage   = null;
            Entity postImage  = null;

            var settings = MockupExecutionContext.GetSettings(request);

            // Validation
            if (!settings.SetUnsettableFields && (request is UpdateRequest || request is CreateRequest))
            {
                var entity = request is UpdateRequest ? (request as UpdateRequest).Target : (request as CreateRequest).Target;
                dataMethods.RemoveUnsettableAttributes(request.RequestName, entity);
            }


            // Pre operation
            if (settings.TriggerProcesses && entityInfo != null)
            {
                preImage = TryRetrieve(primaryRef);
                if (preImage != null)
                {
                    primaryRef.Id = preImage.Id;
                }
                if (eventOp.HasValue)
                {
                    pluginManager.Trigger(eventOp.Value, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                    workflowManager.Trigger(eventOp.Value, ExecutionStage.PreOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                }
            }
            // Core operation
            OrganizationResponse response = ExecuteRequest(request, userRef, parentPluginContext);


            // Post operation
            if (settings.TriggerProcesses && entityInfo != null)
            {
                postImage = TryRetrieve(primaryRef);
                if (eventOp.HasValue)
                {
                    pluginManager.Trigger(eventOp.Value, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                    workflowManager.Trigger(eventOp.Value, ExecutionStage.PostOperation, entityInfo.Item1, preImage, postImage, pluginContext, this);
                }
                workflowManager.ExecuteWaitingWorkflows(pluginContext, this);
            }

            return(response);
        }