private string GetToTemporaryFile(ScheduledImportConfig config) { var secureId = config.SicPasswordSecureId; var password = secureId != null?Factory.SecuredData.Read((Guid)secureId) : string.Empty; try { return(Factory.RemoteFileFetcher.GetToTemporaryFile(config.SicUrl, config.SicUsername, password)); } catch (ConnectionException ex) { var message = $"Scheduled Import '{config.Name}' failed.\nDetails:\n File: {config.SicUrl} \n Message: {ex.Message}"; EventLog.Application.WriteInformation(message); SecurityBypassContext.Elevate(() => { CreateFailedImportRunEntity(config, message); }); return(null); } catch (Exception ex) { throw GenerateJobException(ex.Message, config); } }
/// <summary> /// A deferred action will not occur until after the current context completes or until we hit a handleDefered. /// </summary> /// <param name="action"></param> public void DeferAction(Action action, bool runBeforeSave = false) { Action wrappedAction = action; if (SecurityBypassContext.IsActive) { wrappedAction = () => SecurityBypassContext.Elevate(action); } if (this == _rootContext) { throw new ArgumentException("action"); } if (HandleDeferred || _parentContext == null) { var queue = runBeforeSave ? _deferredBeforeActions : _deferredAfterActions; queue.Enqueue(wrappedAction); } else { _parentContext.DeferAction(wrappedAction, runBeforeSave); } }
bool EvaluateForwardTriggers(IResourceTriggerFilterPolicyCache policyCache, IEntity entity, IEnumerable <long> changedFields, IEnumerable <long> changedRels, IEnumerable <long> changedRevRels, List <Action> postSaveActions) { using (Profiler.Measure("ResourceTriggerFilterEventTarget.EvaluateForwardTriggers")) { var typeId = entity.TypeIds.FirstOrDefault(); if (typeId != 0) { List <ResourceTriggerFilterDef> policies; if (policyCache.TypePolicyMap.TryGetValue(typeId, out policies)) { if (policies.Any()) { // we match on type var allChanges = changedFields.Union(changedRels).Union(changedRevRels); // // Check if our entity matches any of the fields and rels foreach (var policy in policies) { if (policy == null) { continue; // assert false } var watchedFields = policyCache.PolicyToFieldsMap[policy.Id]; if (!watchedFields.Any() || watchedFields.Intersect(allChanges).Any()) { var handler = policyCache.PolicyTypeHandlerMap[policy.TypeIds.First()]; if (handler != null) { var isNew = entity.IsTemporaryId; bool result = false; SecurityBypassContext.RunAsUser(() => { if (handler.OnBeforeSave(policy, entity, isNew, changedFields, changedRels, changedRevRels)) { result = true; } else { AddWrappedPostSaveAction(postSaveActions, () => handler.OnAfterSave(policy, entity, isNew, changedFields, changedRels, changedRevRels)); } }); if (result) { return(true); // We failed, so bug out } } } } } } } } return(false); }
/// <summary> /// Is there an access rule for the specified type(s) that includes the requested permission? E.g. create. /// </summary> /// <param name="entityType"> /// The <see cref="EntityType"/> to check. This cannot be null. /// </param> /// <param name="permission">The permission being sought.</param> /// <param name="user"> The user requesting access. This cannot be null. </param> /// <returns> /// True if the user can create entities of that type, false if not. /// </returns> private bool CheckTypeAccess(EntityType entityType, EntityRef permission, EntityRef user) { if (user == null) { throw new ArgumentNullException(nameof(user)); } if (entityType == null) { throw new ArgumentNullException(nameof(entityType)); } List <EntityType> entityTypesToCheck; bool result; using (new SecurityBypassContext()) using (Profiler.MeasureAndSuppress("SecuresFlagEntityAccessControlChecker.CheckTypeAccess")) { // Check if the type itself can be created using (MessageContext messageContext = new MessageContext(EntityAccessControlService.MessageName)) { messageContext.Append(() => "Checking access rules first:"); IDictionary <long, bool> resultAsDict = null; List <EntityType> entityTypeAsList = new List <EntityType> { entityType }; SecurityBypassContext.RunAsUser(() => resultAsDict = Checker.CheckTypeAccess(entityTypeAsList, permission, user)); result = resultAsDict [entityType.Id]; if (result) { return(result); } } // Walk graph to get list of types to check entityTypesToCheck = ReachableTypes(entityType.ToEnumerable( ), true, false) .Select(walkStep => walkStep.Node) .Where(et => et != entityType) // skip root type. .ToList( ); result = CheckTypeAccessRelatedTypesImpl(entityType, permission, user, entityTypesToCheck); if (!result) { return(false); } // Register cache invalidations using (CacheContext cacheContext = CacheContext.GetContext( )) { cacheContext.EntityTypes.Add(WellKnownAliases.CurrentTenant.Relationship); cacheContext.FieldTypes.Add(WellKnownAliases.CurrentTenant.SecuresFrom, WellKnownAliases.CurrentTenant.SecuresTo, WellKnownAliases.CurrentTenant.SecuresFromReadOnly, WellKnownAliases.CurrentTenant.SecuresToReadOnly); } } return(result); }
public void Test_Elevate() { bool elevated; elevated = false; SecurityBypassContext.Elevate(() => elevated = SecurityBypassContext.IsActive); Assert.That(elevated, Is.True, "Not elevated"); }
public void Test_RunAsUser() { bool elevated; elevated = false; SecurityBypassContext.RunAsUser(() => elevated = SecurityBypassContext.IsActive); Assert.That(elevated, Is.False, "Elevated"); }
/// <summary> /// Get the value of an access control field. /// </summary> /// <param name="entityId">The entityId</param> /// <param name="fieldId">The fieldId</param> /// <returns>A A typed value.</returns> internal static TypedValue TryGetAccessControlField(long entityId, IEntityRef fieldId) { var value = new TypedValue { Type = DatabaseType.BoolType }; if (entityId < 1) { throw new ArgumentNullException("entityId"); } if (fieldId == null || fieldId.Namespace != "core") { throw new ArgumentException("fieldId: invalid namespace"); } switch (fieldId.Alias) { case "canCreateType": { var entityType = Entity.Get <EntityType>(entityId); if (entityType == null) { throw new InvalidOperationException("Assert false: attempted to load an entity as an EntityType which is not a type."); } SecurityBypassContext.RunAsUser(() => { value.Value = AccessControlService.CanCreate(entityType); }); break; } case "canModify": { SecurityBypassContext.RunAsUser(() => { value.Value = AccessControlService.Check(entityId, new[] { Permissions.Modify }); }); break; } case "canDelete": { SecurityBypassContext.RunAsUser(() => { value.Value = AccessControlService.Check(entityId, new[] { Permissions.Delete }); }); break; } default: { // return null value break; } } return(value); }
/// <summary> /// Perform a create using the provided update action. To be used for testing. /// </summary> /// <param name="resType"></param> /// <param name="updateAction"></param> public static IEntity PerformCreate(EntityType resType, Action <IEntity> updateAction) { try { IEntity newEntity = null; SecurityBypassContext.RunAsUser(() => { newEntity = Entity.Create(resType); var provider = Factory.Current.Resolve <IEntityDefaultsDecoratorProvider>(); var decorator = provider.GetDefaultsDecorator(resType.Id); // Do per-entity work decorator.SetDefaultValues(newEntity.ToEnumerable()); }); updateAction(newEntity); SecurityBypassContext.RunAsUser(() => { newEntity.Save(); }); return(newEntity); } catch (ValidationException ex) { string message = ex.FieldName != null?string.Format("{0}: {1}", ex.FieldName, ex.Message) : ex.Message; throw new WorkflowRunException(message, ex); } catch (CardinalityViolationException ex) { throw new WorkflowRunException(ex.Message, ex); } catch (DuplicateKeyException ex) { throw new WorkflowRunException(ex.Message, ex); } catch (InvalidCastException ex) { throw new WorkflowRunException("Incorrect data type", ex); } catch (SqlException ex) { if (ex.Number == 547) { throw new CreateInvalidReferenceException(ex); } else { throw; } } }
public void Test_NoBypassContext() { bool elevated; elevated = false; SecurityBypassContext.Elevate(() => elevated = SecurityBypassContext.IsActive); Assert.That(elevated, Is.True, "Elevate is not elevated"); SecurityBypassContext.RunAsUser(() => elevated = SecurityBypassContext.IsActive); Assert.That(elevated, Is.False, "RunAsUser is elevated"); }
/// <summary> /// Update all the the provided expressions. /// </summary> private Dictionary <WfExpression, object> ResolveExpressions(IRunState context, ICollection <WfExpression> expressions) { Dictionary <WfExpression, object> result = null; // evaluate the expressions and update the targeted values SecurityBypassContext.RunAsUser(() => { result = expressions.ToDictionary(e => e, e => EvaluateExpression(context, e)); }); return(result); }
/// <summary> /// Send the notifications on a background thread. /// </summary> void SendMessagesInBackground(IRunState context, long notificationId, List <long> userIds, bool waitForReplies) { context.SetPostRunAction(() => { var runId = context.WorkflowRunId; WorkflowRunContext.Current.QueueAction(() => SecurityBypassContext.Elevate(() => { var workflowRunner = Factory.Current.Resolve <IWorkflowRunner>(); WorkflowRun run = Entity.Get <WorkflowRun>(runId);; try { var notification = Entity.Get <Notification>(notificationId); var users = Entity.Get(userIds); Factory.Current.Resolve <INotifier>().Send(notification, users, true); var sends = notification.SendRecords; var sentWithoutError = sends.Where(r => r.SrErrorMessage == null); // update the notification bool resume = true; if (waitForReplies) { notification = notification.AsWritable <Notification>(); notification.NPendingRun = run; notification.Save(); resume = notification.Complete(); // Just in case all the replies were completed while we were sending. } if (resume && run != null) { workflowRunner.ResumeWorkflow(run, new NotifyResumeEvent()); } } catch { if (run != null) { workflowRunner.ResumeWorkflow(run, new NotifyResumeFailedEvent()); } throw; } })); }); }
bool OnBeforeRelsThisEnd(IEnumerable <IEntity> entities, List <Action> postSaveActions) { using (Profiler.Measure("ResourceTriggerFilterEventTarget.OnBeforeDelete OnBeforeRelsThisEnd")) { var _policy = Factory.ResourceTriggerFilterPolicyCache; foreach (var entity in entities) { var typeId = entity.TypeIds.FirstOrDefault(); if (typeId != 0) { var policies = _policy.TypePolicyMap[typeId]; if (policies != null) { foreach (var policy in policies) { var handler = _policy.PolicyTypeHandlerMap[policy.TypeIds.First()]; if (handler != null) { var isNew = entity.IsTemporaryId; bool result = false; SecurityBypassContext.RunAsUser(() => { if (handler.OnBeforeDelete(policy, entity)) { result = true; } else { postSaveActions.Add(() => handler.OnAfterDelete(policy, entity)); } }); if (result) { return(true); // We failed, so bug out } } } } } } return(false); } }
public void Test_ChangePassword(Func <UserAccount> userAccountFactory, string oldPassword, string newPassword, HttpStatusCode expectedHttpStatusCode, string expectedMessage) { UserAccount userAccount; HttpWebResponse response; HttpError httpError; userAccount = null; try { using (new SecurityBypassContext()) { userAccount = userAccountFactory(); } using (PlatformHttpRequest loginRequest = new PlatformHttpRequest("data/v1/login/spchangepassword", PlatformHttpMethod.Post, doNotAuthenticate: true)) { loginRequest.PopulateBody(new JsonPasswordChangeRequest { Username = userAccount.Name, OldPassword = oldPassword, NewPassword = newPassword, Tenant = RequestContext.GetContext().Tenant.Name }); response = loginRequest.GetResponse(); Assert.That(response, Has.Property("StatusCode").EqualTo(expectedHttpStatusCode)); if (expectedMessage != null) { httpError = loginRequest.DeserialiseResponseBody <HttpError>(); Assert.That(httpError, Has.Property("Message").EqualTo(expectedMessage)); } } } finally { if (userAccount != null) { try { SecurityBypassContext.Elevate(() => Entity.Delete(userAccount)); } catch (Exception) { // Ignore errors } } } }
public void Test_InvalidLogin(Func <UserAccount> userAccountFactory, string password, HttpStatusCode expectedHttpStatusCode, string expectedMessage) { UserAccount userAccount; HttpWebResponse response; HttpError httpError; userAccount = null; try { using (new SecurityBypassContext()) { userAccount = userAccountFactory(); } using (PlatformHttpRequest loginRequest = new PlatformHttpRequest("data/v1/login/spsignin", PlatformHttpMethod.Post, doNotAuthenticate: true)) { loginRequest.PopulateBody(new JsonLoginCredential { Username = userAccount.Name, Password = password, Tenant = RequestContext.GetContext().Tenant.Name, Persistent = false }); response = loginRequest.GetResponse(); Assert.That(response, Has.Property("StatusCode").EqualTo(expectedHttpStatusCode)); if (expectedMessage != null) { httpError = loginRequest.DeserialiseResponseBody <HttpError>(); Assert.That(httpError, Has.Property("Message").EqualTo(expectedMessage)); } } } finally { if (userAccount != null) { try { SecurityBypassContext.Elevate(() => Entity.Delete(userAccount)); } catch (Exception) { // Do nothing on an error. This is just clean up code. } } } }
void IRunNowActivity.OnRunNow(IRunState context, ActivityInputs inputs) { var ResourceToUpdateKey = GetArgumentKey("setChoiceActivityResourceArgument"); var ValueKey = GetArgumentKey("setChoiceActivityValueArgument"); var FieldKey = GetArgumentKey("setChoiceActivityFieldArgument"); var replaceExistingKey = GetArgumentKey("setChoiceActivityReplaceExisting"); var choiceToUpdateRef = (IEntity)inputs[FieldKey]; var resId = (IEntity)inputs[ResourceToUpdateKey]; var valueId = (IEntity)inputs[ValueKey]; bool replaceExisting = false; object replaceExistingObj; if (inputs.TryGetValue(replaceExistingKey, out replaceExistingObj)) { replaceExisting = (bool?)replaceExistingObj ?? false; } var relationship = choiceToUpdateRef.As <Relationship>(); SecurityBypassContext.RunAsUser(() => { var resource = resId.AsWritable(); // Does not have to be a writeable copy because we are only manipulating relationships. var cardinality = relationship.Cardinality_Enum ?? CardinalityEnum_Enumeration.ManyToMany; replaceExisting = replaceExisting || cardinality == CardinalityEnum_Enumeration.OneToOne || cardinality == CardinalityEnum_Enumeration.ManyToOne; var relCollection = resource.GetRelationships(choiceToUpdateRef, Direction.Forward); // you can't have a reverse choice field. if (replaceExisting) { relCollection.Clear(); } relCollection.Add(valueId); resource.Save(); }); }
public void Test_OneBypassContext() { bool elevated; elevated = false; using (new SecurityBypassContext()) { Assert.That(SecurityBypassContext.IsActive, Is.True, "Not active"); SecurityBypassContext.Elevate(() => elevated = SecurityBypassContext.IsActive); Assert.That(elevated, Is.True, "Elevate is not elevated"); SecurityBypassContext.RunAsUser(() => elevated = SecurityBypassContext.IsActive); Assert.That(elevated, Is.False, "RunAsUser is elevated"); } }
void IRunNowActivity.OnRunNow(IRunState context, ActivityInputs inputs) { var typeRefKey = GetArgumentKey("getResourcesResourceType"); var reportRefKey = GetArgumentKey("getResourcesReport"); var listKey = GetArgumentKey("getResourcesList"); var firstKey = GetArgumentKey("getResourcesFirst"); var countKey = GetArgumentKey("getResourcesCount"); object o; EntityType resourceType = null; IEntity reportRef = null; if (inputs.TryGetValue(typeRefKey, out o)) { if (o != null) { resourceType = ((IEntity)o).As <EntityType>(); } } if (inputs.TryGetValue(reportRefKey, out o)) { if (o != null) { reportRef = (IEntity)o; } } if (resourceType == null && reportRef == null) { throw new WorkflowRunException("Get Resources must have one of either the Type or Report parameters specified."); } IEnumerable <IEntity> list = null; SecurityBypassContext.RunAsUser(() => { list = reportRef != null ? GetListFromReport(context, reportRef) : GetListFromType(resourceType); }); context.SetArgValue(ActivityInstance, listKey, list); context.SetArgValue(ActivityInstance, firstKey, list.FirstOrDefault()); context.SetArgValue(ActivityInstance, countKey, list.Count()); }
/// <summary> /// Process the request. /// </summary> /// <remarks> /// Assumes that user context has already been set. /// </remarks> /// <param name="request"></param> /// <param name="endpoint"></param> /// <returns></returns> public ConnectorResponse HandleRequest(ConnectorRequest request, ApiResourceEndpoint endpoint) { if (request == null) { throw new ArgumentNullException("request"); } if (endpoint == null) { throw new ArgumentNullException("endpoint"); } // Get resource mapping object ApiResourceMapping mapping = GetResourceMapping(endpoint); // Disable triggers if applicable bool disableTriggers; using (new SecurityBypassContext()) { disableTriggers = mapping.MappingSuppressWorkflows == true; } using (new WorkflowRunContext { DisableTriggers = disableTriggers }) { // Handle verbs if (request.Verb == ConnectorVerb.Post && SecurityBypassContext.Elevate(() => endpoint.EndpointCanCreate == true)) { return(HandlePost(request, mapping)); } if (request.Verb == ConnectorVerb.Put && SecurityBypassContext.Elevate(() => endpoint.EndpointCanUpdate == true)) { return(HandlePut(request, mapping)); } if (request.Verb == ConnectorVerb.Delete && SecurityBypassContext.Elevate(() => endpoint.EndpointCanDelete == true)) { return(HandleDelete(request, mapping)); } return(new ConnectorResponse(HttpStatusCode.MethodNotAllowed)); } }
/// <summary> /// Begin task to import spreadsheet data. /// </summary> /// <param name="importSettings">The settings of the import.</param> /// <returns>Returns the ID of the import run.</returns> public long StartImport(ImportSettings importSettings) { // Validate if (importSettings == null) { throw new ArgumentNullException(nameof(importSettings)); } if (string.IsNullOrEmpty(importSettings.FileToken)) { throw new ArgumentException("importSettings.FileToken"); } // Load the config ImportConfig importConfig = SecurityBypassContext.ElevateIf( importSettings.SuppressSecurityCheckOnImportConfig, () => _entityRepository.Get <ImportConfig>(importSettings.ImportConfigId)); if (importConfig == null) { throw new ArgumentException("importSettings.ImportConfigId"); } // Create a new import run ImportRun importRun = CreateImportRunEntity(importConfig, importSettings); SecurityBypassContext.Elevate(importRun.Save); long importRunId = importRun.Id; try { _asyncRunner.Start(() => _importRunWorker.StartImport(importRunId)); } catch { // Async operation failed to start // (This is not reached if the import itself fails) importRun.ImportRunStatus_Enum = WorkflowRunState_Enumeration.WorkflowRunFailed; importRun.ImportMessages = "Failed to start importer."; SecurityBypassContext.Elevate(importRun.Save); throw; } return(importRun.Id); }
void IRunNowActivity.OnRunNow(IRunState context, ActivityInputs inputs) { var resourceToDeleteKey = GetArgumentKey("deleteActivityResourceArgument"); var res = (IEntity)inputs[resourceToDeleteKey]; if (res == null) { throw new WorkflowRunException_Internal("No record provided.", null); } SecurityBypassContext.RunAsUser(() => { Entity.Delete(res.Id); }); context.RemoveReference(res.Id); }
private bool CheckTypeAccessRelatedTypesImpl(EntityType entityType, EntityRef permission, EntityRef user, List <EntityType> entityTypesToCheck) { bool result = false; using (MessageContext messageContext = new MessageContext(EntityAccessControlService.MessageName)) { IDictionary <long, bool> canAccessTypes; string message; // Allow access if the user has access to any of the related types if (entityTypesToCheck.Count == 0) { messageContext.Append(() => "No entity types found to check."); return(false); } // Check whether the user has access to the given types canAccessTypes = null; SecurityBypassContext.RunAsUser(() => canAccessTypes = Checker.CheckTypeAccess( entityTypesToCheck.ToList( ), permission, user)); message = string.Format( "Checking security relationship(s) to see whether user can create entities of type '{0}': ", entityType.Name ?? entityType.Id.ToString( )); if (canAccessTypes.Any(kvp => kvp.Value)) { messageContext.Append(() => string.Format( "{0} Allowed due to create access to entity type(s) '{1}'", message, canAccessTypes.Select(kvp => entityTypesToCheck.First(et => et.Id == kvp.Key).Name ?? kvp.Key.ToString( )))); result = true; } else { messageContext.Append(() => $"{message} Denied"); } } return(result); }
/// <summary> /// Given a text expression and runtimeArgs, evaluate the expression. /// Expressions must be compatible with DataColumn.Expression. the result is cast to T /// </summary> public object EvaluateExpression(WfExpression expression) { using (Profiler.Measure("RunStateBase.EvaluateExpression")) { ExprType targetType = null; SecurityBypassContext.Elevate(() => targetType = Metadata.GetExpressionType(expression)); var result = expression.EvaluateExpression(this); // force any lists to be resolved to prevent lazy evaluation in a different security context and get rid of the nulls if (targetType.IsList && result != null) { result = ((IEnumerable <IEntity>)result).Where(e => e != null).ToList <IEntity>(); } return(result); } }
/// <summary> /// Perform a update using the provided update action. To be used for testing. /// </summary> /// <param name="entityToUpdate"></param> /// <param name="updateAction"></param> public static void PerformUpdate(IEntity entityToUpdate, Action <IEntity> updateAction) { try { updateAction(entityToUpdate); SecurityBypassContext.RunAsUser(() => { entityToUpdate.Save(); }); } catch (EDC.ReadiNow.Model.ValidationException ex) { string message = ex.FieldName != null?string.Format("{0}: {1}", ex.FieldName, ex.Message) : ex.Message; throw new WorkflowRunException(message, ex); } catch (CardinalityViolationException ex) { throw new WorkflowRunException(ex.Message, ex); } catch (DuplicateKeyException ex) { throw new WorkflowRunException(ex.Message, ex); } catch (InvalidCastException ex) { throw new WorkflowRunException("Incorrect data type", ex); } catch (SqlException ex) { if (ex.Number == 547) { throw new UpdateInvalidReferenceException(ex); } else { throw; } } }
public override void Execute(EntityRef scheduledItemRef) { string logMessage = null; bool failed = true; var scheduledExportConfig = Entity.Get <ScheduledExportConfig>(scheduledItemRef, ScheduledExportConfig.Name_Field); if (scheduledExportConfig == null) { throw GenerateJobException("Unexpected error, ScheduleItemRef is not a ScheduledExportConfig.", null); } try { var report = scheduledExportConfig.SecReport; if (report == null) { throw new ExpectedErrorCondition("Failed to import, no report configuration provided."); } var url = scheduledExportConfig.SicUrl; if (String.IsNullOrEmpty(url)) { throw new ExpectedErrorCondition("Failed to export, no FTP address provided."); } var username = scheduledExportConfig.SicUsername; if (String.IsNullOrEmpty(username)) { throw new ExpectedErrorCondition("Failed to export, no username provided."); } var secureId = scheduledExportConfig.SicPasswordSecureId; var password = secureId != null?Factory.SecuredData.Read((Guid)secureId) : string.Empty; var format = scheduledExportConfig.SecFileType_Enum; if (format == null) { throw new ExpectedErrorCondition("Failed to export, no file format type provided."); } var fileformat = ConvertFileFormat(format); var exportInterface = Factory.Current.Resolve <IExportDataInterface>(); var exportInfo = exportInterface.ExportData(report.Id, new ExportSettings { Format = fileformat, TimeZone = null /* UTC */ }); var fileFetcher = Factory.Current.Resolve <IRemoteFileFetcher>(); fileFetcher.PutFromTemporaryFile(exportInfo.FileHash, url, username, password); logMessage = "Success"; failed = false; } catch (ExpectedErrorCondition ex) { logMessage = ex.Message; // expected exception swallowed, log message generated in finally } catch (ConnectionException ex) { logMessage = ex.Message; // expected exception swallowed, log message generated in finally } catch (PlatformSecurityException ex) { logMessage = ex.Message; // expected exception swallowed, log message generated in finally } catch (JobExecutionException ex) { EventLog.Application.WriteError("StartImportJob.Execute: Unexpected exception thrown: {0}", ex); logMessage = "Failed with an internal error."; throw; } catch (Exception ex) { EventLog.Application.WriteError("StartImportJob.Execute: Unexpected exception thrown: {0}", ex); logMessage = "Failed with an internal error."; throw GenerateJobException("Unexpected exception when performing scheduled import.", scheduledExportConfig); } finally { EventLog.Application.WriteTrace($"{scheduledExportConfig.Id} {(failed ? "Fail" : "Success")}: {logMessage}"); SecurityBypassContext.Elevate(() => { var logEntry = new TenantLogEntry { Name = $"Schedule Export: {scheduledExportConfig.Name ?? "[Unnamed]"}", Description = logMessage, LogEntrySeverity_Enum = failed ? LogSeverityEnum_Enumeration.ErrorSeverity : LogSeverityEnum_Enumeration.InformationSeverity, LogEventTime = DateTime.Now }; logEntry.GetRelationships("core:secRunLog", Direction.Reverse).Add(scheduledExportConfig); logEntry.Save(); }); } }
/// <summary> /// Executed before each test is run /// </summary> /// <param name="testDetails"> /// Provides details about the test that is going to be run. /// </param> public override void BeforeTest(TestDetails testDetails) { _securityBypassContext = new SecurityBypassContext(); }
/// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { _securityBypassContext.Dispose(); _securityBypassContext = null; }
/// <summary> /// Update a workflow using a update action. This will take care of handling paused instances by cloning. /// </summary> /// <param name="workflowId"></param> /// <param name="updateAction"></param> /// <returns>True if the workflow needed to be clones</returns> public static bool Update(long workflowId, Action updateAction) { using (new SecurityBypassContext(true)) { Workflow clone = null; var original = Entity.Get <Workflow>(workflowId); if (original == null) { throw new WebArgumentException("The provided Workflow Id is not a workflow"); } if (original.WfNewerVersion != null) { throw new WebArgumentException("This Workflow is not the latest version so cannot be updated"); } using (var databaseContext = DatabaseContext.GetContext(true)) { var havePausedInstances = original.RunningInstances.Any(r => r.WorkflowRunStatus_Enum == WorkflowRunState_Enumeration.WorkflowRunPaused); IDictionary <long, long> clonedIds = null; if (havePausedInstances) { // clone the workflow (Need to save because the clone occurs in the DB) clone = original.Clone <Workflow>(); clonedIds = clone.Save(); // There seems to be a bug in entity clone that means you can't remove solution till after it has been saved. clone = clone.AsWritable <Workflow>(); clone.InSolution = null; // Fix up the version linking - again we can't seem to do it as a single save. var originalWfOlderVersionId = original.WfOlderVersion != null ? original.WfOlderVersion.Id : -1; original = original.AsWritable <Workflow>(); original.WfOlderVersion = clone; original.Save(); if (originalWfOlderVersionId != -1) { clone.WfOlderVersion = Entity.Get <Workflow>(originalWfOlderVersionId); } clone.Save(); } SecurityBypassContext.RunAsUser(updateAction); original = original.AsWritable <Workflow>(); original.WorkflowUpdateHash = _randGen.Next().ToString(CultureInfo.InvariantCulture); // ideally this should be a hash of only the important aspects of the workflow original.WorkflowVersion = (original.WorkflowVersion ?? 1) + 1; if (havePausedInstances) { original.WfOlderVersion = clone; WorkflowRunHelper.MoveRuns(original, clone, clonedIds); } original.Save(); // This will also save the close databaseContext.CommitTransaction(); return(havePausedInstances); } } }
bool OnBeforeRelsOtherEnds(IEnumerable <IEntity> entities, List <Action> postSaveActions) { using (Profiler.Measure("ResourceTriggerFilterEventTarget.OnBeforeDelete OnBeforeRelsOtherEnds")) { var policyCache = Factory.ResourceTriggerFilterPolicyCache; foreach (var entity in entities) { // // Get the filtered list of relationships that could possibly apply to some of the related entities // var filteredRels = GetRelsWithPotentialPolicies(policyCache, entity).ToList(); if (!filteredRels.Any()) { continue; } // Prefill the cache var requestString = string.Join(",", filteredRels.Select(r => (r.Item2 == Direction.Reverse ? "-#" : "#") + r.Item1.Id + ".id")); BulkPreloader.Preload(new EntityRequest(entity.Id, requestString)); // // Check each entity on the other end of the filtered rels t see if any policies apply foreach (var relDir in filteredRels) { var rel = relDir.Item1; var direction = relDir.Item2; var relInstances = entity.GetRelationships(rel, direction); foreach (var otherEntity in relInstances) { var otherType = otherEntity.TypeIds.First(); var policies = policyCache.TypePolicyMap[otherType].Where(p => p.UpdatedRelationshipsToTriggerOn.Contains(rel, EntityIdEqualityComparer <Relationship> .Instance)); foreach (var policy in policies) { var handler = policyCache.PolicyTypeHandlerMap[policy.TypeIds.First()]; bool result = false; SecurityBypassContext.RunAsUser(() => { if (handler.OnBeforeReverseRemove(policy, rel.Id, direction.Reverse(), otherEntity, entity)) { result = true; } else { AddWrappedPostSaveAction(postSaveActions, () => handler.OnAfterReverseRemove(policy, rel.Id, direction.Reverse(), otherEntity, entity)); } }); if (result) { return(true); } } } } } return(false); } }
public void Test_RunAsUser_NullAction() { Assert.That(() => SecurityBypassContext.RunAsUser(null), Throws.TypeOf <ArgumentNullException>().And.Property("ParamName").EqualTo("action")); }
void IRunNowActivity.OnRunNow(IRunState context, ActivityInputs inputs) { var OriginKey = GetArgumentKey("setRelationshipActivityOriginArgument"); var DestinationKey = GetArgumentKey("setRelationshipActivityDestinationArgument"); var RelationshipKey = GetArgumentKey("setRelationshipActivityRelationshipArgument"); var replaceExistingKey = GetArgumentKey("setRelationshipActivityReplaceExisting"); var isReverseKey = GetArgumentKey("setRelationshipActivityIsReverse"); var originRef = (IEntity)inputs[OriginKey]; var relationshipRef = (IEntity)inputs[RelationshipKey]; IEntity destinationRef = null; object destinationRefObj; if (inputs.TryGetValue(DestinationKey, out destinationRefObj)) { destinationRef = (IEntity)destinationRefObj; } bool replaceExisting = false; object replaceExistingObj; if (inputs.TryGetValue(replaceExistingKey, out replaceExistingObj)) { replaceExisting = (bool?)replaceExistingObj ?? false; } var direction = Direction.Forward; object isReverseObj; if (inputs.TryGetValue(isReverseKey, out isReverseObj)) { direction = ((bool?)isReverseObj ?? false) ? Direction.Reverse : Direction.Forward; } var relationship = relationshipRef.As <Relationship>(); SecurityBypassContext.RunAsUser(() => { var origin = originRef.AsWritable <Entity>(); var cardinality = relationship.Cardinality_Enum ?? CardinalityEnum_Enumeration.ManyToMany; replaceExisting = replaceExisting || cardinality == CardinalityEnum_Enumeration.OneToOne || (direction == Direction.Forward && cardinality == CardinalityEnum_Enumeration.ManyToOne) || (direction == Direction.Reverse && cardinality == CardinalityEnum_Enumeration.OneToMany) ; var relCollection = origin.GetRelationships(relationshipRef, direction); if (replaceExisting) { relCollection.Clear(); } if (destinationRef != null) { relCollection.Add(destinationRef); } origin.Save(); }); }