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}'"); } } } } }
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); }
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); }
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); }
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()); }
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); }
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); }
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); }