/// <summary> /// Process the <see cref="ConfigurationSetReadyRequest"/> /// </summary> /// <param name="request"> /// The request /// </param> /// <returns> /// The <see cref="Task"/>. /// </returns> private async Task OnConfigurationCheck(ConfigurationCheckRequest request) { try { using (var ds = this.GetContext()) { Context.GetLogger().Info("{Type}: checking configuration {ConfigurationId}", this.GetType().Name, request.Id); var configuration = ds.Configurations.FirstOrDefault(r => r.Id == request.Id); if (configuration == null) { this.Sender.Tell(CrudActionResponse <Configuration> .Error(new EntityNotFoundException(), null)); Context.GetLogger().Info( "{Type}: checking configuration {ConfigurationId} - not found", this.GetType().Name, request.Id); return; } if (configuration.State != EnConfigurationState.Draft) { this.Sender.Tell( CrudActionResponse <Configuration> .Error( new Exception("Only draft configurations can be checked"), null)); Context.GetLogger().Info( "{Type}: checking configuration {ConfigurationId} - not draft", this.GetType().Name, request.Id); return; } var supportedFrameworks = Context.System.Settings.Config.GetStringList("KlusterKite.NodeManager.SupportedFrameworks"); Context.GetLogger().Info( "{Type}: checking configuration {ConfigurationId} against frameworks {Frameworks}", this.GetType().Name, request.Id, string.Join(", ", supportedFrameworks)); var errors = await configuration.CheckAll(ds, this.nugetRepository, supportedFrameworks.ToList()); if (errors.Count > 0) { this.Sender.Tell( CrudActionResponse <Configuration> .Error(new MutationException(errors.ToArray()), null)); Context.GetLogger().Info( "{Type}: checking configuration {ConfigurationId} completed", this.GetType().Name, request.Id); return; } this.Sender.Tell(CrudActionResponse <Configuration> .Success(configuration, null)); } } catch (Exception exception) { this.Sender.Tell(CrudActionResponse <Configuration> .Error(exception, null)); } }
/// <summary> /// Creates mutation response from actor response /// </summary> /// <param name="response">The actor response</param> /// <returns>The mutation response</returns> protected static MutationResult <TObject> CreateResponse(CrudActionResponse <TObject> response) { if (response.Data != null) { return(new MutationResult <TObject> { Result = response.Data }); } var errors = response.Exception.Match <List <ErrorDescription> >() .With <EntityNotFoundException>( e => new List <ErrorDescription> { new ErrorDescription("id", "not found") }) .With <MutationException>(e => e.Errors) .ResultOrDefault( e => { var exception = e as Exception; var errorDescription = new ErrorDescription( "null", exception != null ? $"{exception.Message}\n{exception.StackTrace}" : "unknown error"); return(new List <ErrorDescription> { errorDescription }); }); return(new MutationResult <TObject> { Errors = errors }); }
protected virtual async Task OnRequest <TObject, TId>(CrudActionMessage <TObject, TId> request) where TObject : class { CrudActionResponse <TObject> response; try { response = await this.ProcessRequest(request); } catch (Exception exception) { Context.GetLogger().Error( exception, "{Type}: Error while processing {ActionType} for {EntityType}", this.GetType().Name, request.ActionType, typeof(TObject).Name); response = new CrudActionResponse <TObject> { Exception = exception, ExtraData = request.ExtraData }; } if (typeof(ILargeObject).GetTypeInfo().IsAssignableFrom(typeof(TObject))) { Context.GetParcelManager().Tell(new Parcel { Payload = response, Recipient = this.Sender }, this.Self); } else { this.Sender.Tell(response); } }
/// <summary> /// Process the <see cref="ConfigurationSetReadyRequest"/> /// </summary> /// <param name="request"> /// The request /// </param> /// <returns> /// The <see cref="Task"/>. /// </returns> private async Task OnConfigurationSetReady(ConfigurationSetReadyRequest request) { try { using (var ds = this.GetContext()) { var configuration = ds.Configurations.FirstOrDefault(r => r.Id == request.Id); if (configuration == null) { this.Sender.Tell(CrudActionResponse <Configuration> .Error(new EntityNotFoundException(), null)); return; } if (configuration.State != EnConfigurationState.Draft) { this.Sender.Tell( CrudActionResponse <Configuration> .Error( new Exception("Only draft configurations can be made ready"), null)); return; } if (ds.Configurations.Any(r => r.State == EnConfigurationState.Ready)) { this.Sender.Tell( CrudActionResponse <Configuration> .Error( new Exception( "There is an already defined ready configuration. Please remove the previous one."), null)); return; } var supportedFrameworks = Context.System.Settings.Config.GetStringList("KlusterKite.NodeManager.SupportedFrameworks"); var errors = await configuration.CheckAll(ds, this.nugetRepository, supportedFrameworks.ToList()); if (errors.Count > 0) { this.Sender.Tell(CrudActionResponse <Configuration> .Error(new MutationException(errors.ToArray()), null)); return; } configuration.State = EnConfigurationState.Ready; ds.SaveChanges(); this.Sender.Tell(CrudActionResponse <Configuration> .Success(configuration, null)); SecurityLog.CreateRecord( EnSecurityLogType.OperationGranted, EnSeverity.Crucial, request.Context, "Configuration {ConfigurationId} marked as Ready", configuration.Id); } } catch (Exception exception) { this.Sender.Tell(CrudActionResponse <Configuration> .Error(exception, null)); } }
/// <summary> /// Process the <see cref="ConfigurationSetStableRequest"/> /// </summary> /// <param name="request">The request</param> private void OnConfigurationSetStable(ConfigurationSetStableRequest request) { try { using (var ds = this.GetContext()) { var configuration = ds.Configurations.FirstOrDefault(r => r.Id == request.Id); if (configuration == null) { this.Sender.Tell(CrudActionResponse <Configuration> .Error(new EntityNotFoundException(), null)); return; } if (configuration.State != EnConfigurationState.Active) { this.Sender.Tell( CrudActionResponse <Configuration> .Error( new Exception("Only active configurations can be marked as stable"), null)); return; } if (configuration.IsStable != request.IsStable) { var error = new ErrorDescription("isStable", "The value is not changed"); var mutationException = new MutationException(error); this.Sender.Tell(CrudActionResponse <Configuration> .Error(mutationException, null)); return; } configuration.IsStable = request.IsStable; ds.SaveChanges(); this.Sender.Tell(CrudActionResponse <Configuration> .Success(configuration, null)); } } catch (Exception exception) { this.Sender.Tell(CrudActionResponse <Configuration> .Error(exception, null)); } }
/// <summary> /// Process the <see cref="ConfigurationSetObsoleteRequest"/> /// </summary> /// <param name="request">The request</param> private void OnConfigurationSetObsolete(ConfigurationSetObsoleteRequest request) { try { using (var ds = this.GetContext()) { var configuration = ds.Configurations.FirstOrDefault(r => r.Id == request.Id); if (configuration == null) { this.Sender.Tell(CrudActionResponse <Configuration> .Error(new EntityNotFoundException(), null)); return; } if (configuration.State != EnConfigurationState.Ready) { this.Sender.Tell( CrudActionResponse <Configuration> .Error( new Exception("Only ready configurations can be made obsolete manually"), null)); return; } configuration.State = EnConfigurationState.Obsolete; ds.SaveChanges(); this.Sender.Tell(CrudActionResponse <Configuration> .Success(configuration, null)); SecurityLog.CreateRecord( EnSecurityLogType.OperationGranted, EnSeverity.Crucial, request.Context, "Configuration {ConfigurationId} marked as obsolete", configuration.Id); } } catch (Exception exception) { this.Sender.Tell(CrudActionResponse <Configuration> .Error(exception, null)); } }
protected virtual async Task <CrudActionResponse <TObject> > ProcessRequest <TObject, TId>( CrudActionMessage <TObject, TId> request) where TObject : class { using (var ds = this.GetContext()) { var factory = DataFactory <TContext, TObject, TId> .CreateFactory(this.ComponentContext, ds); switch (request.ActionType) { case EnActionType.Get: try { var result = await factory.Get(request.Id); if (result.HasValue) { result = this.OnSelect(result.Value); } // security read log should be set on client endpoint return(result.HasValue ? CrudActionResponse <TObject> .Success(result, request.ExtraData) : CrudActionResponse <TObject> .Error( new EntityNotFoundException(), request.ExtraData)); } catch (Exception exception) { return(CrudActionResponse <TObject> .Error( new DatasourceInnerException("Exception on Get operation", exception), request.ExtraData)); } case EnActionType.Create: { var entity = request.Data; if (entity == null) { return(CrudActionResponse <TObject> .Error( new RequestEmptyException(), request.ExtraData)); } entity = this.BeforeCreate(entity); var oldObject = await factory.Get(factory.GetId(entity)); if (oldObject != null) { var crudActionResponse = CrudActionResponse <TObject> .Error( new InsertDuplicateIdException(), request.ExtraData); crudActionResponse.Data = oldObject; return(crudActionResponse); } if (entity == null) { return(CrudActionResponse <TObject> .Error( new BeforeActionException(), request.ExtraData)); } try { await factory.Insert(entity); // security update logs are set here to be sure that they are made independently of client notification success SecurityLog.CreateRecord( EnSecurityLogType.DataCreateGranted, entity is ICrucialObject ? EnSeverity.Crucial : EnSeverity.Trivial, request.RequestContext, "{ObjectType} with {ObjectId} id was created", typeof(TObject).FullName, factory.GetId(entity)); this.AfterCreate(entity); return(CrudActionResponse <TObject> .Success(entity, request.ExtraData)); } catch (Exception exception) { return(CrudActionResponse <TObject> .Error( new DatasourceInnerException("Exception on Insert operation", exception), request.ExtraData)); } } case EnActionType.Update: { var entity = request.Data; if (entity == null) { return(CrudActionResponse <TObject> .Error( new RequestEmptyException(), request.ExtraData)); } var oldObject = await factory.Get(request.Id); if (oldObject == null) { return(CrudActionResponse <TObject> .Error( new EntityNotFoundException(), request.ExtraData)); } if (request.ApiRequest != null) { var updatedObject = await factory.Get(request.Id); if (updatedObject == null) { return(CrudActionResponse <TObject> .Error( new EntityNotFoundException(), request.ExtraData)); } DataUpdater <TObject> .Update(updatedObject, entity, request.ApiRequest); entity = updatedObject; } entity = this.BeforeUpdate <TObject>(entity, oldObject); if (entity == null) { return(CrudActionResponse <TObject> .Error( new BeforeActionException(), request.ExtraData)); } try { await factory.Update(entity, oldObject); // security update logs are set here to be sure that they are made independently of client notification success if (!factory.GetId(entity).Equals(factory.GetId(oldObject))) { SecurityLog.CreateRecord( EnSecurityLogType.DataUpdateGranted, entity is ICrucialObject ? EnSeverity.Crucial : EnSeverity.Trivial, request.RequestContext, "{ObjectType} with id {ObjectId} was updated. New id is {NewObjectId}", typeof(TObject).FullName, factory.GetId(oldObject), factory.GetId(entity)); } else { SecurityLog.CreateRecord( EnSecurityLogType.DataUpdateGranted, entity is ICrucialObject ? EnSeverity.Crucial : EnSeverity.Trivial, request.RequestContext, "{ObjectType} with id {ObjectId} was updated.", typeof(TObject).FullName, factory.GetId(entity)); } this.AfterUpdate <TObject>(entity, oldObject); return(CrudActionResponse <TObject> .Success(entity, request.ExtraData)); } catch (Exception exception) { return(CrudActionResponse <TObject> .Error( new DatasourceInnerException("Exception on Update operation", exception), request.ExtraData)); } } case EnActionType.Delete: { var oldObject = await factory.Get(request.Id); if (oldObject == null) { return(CrudActionResponse <TObject> .Error( new EntityNotFoundException(), request.ExtraData)); } oldObject = this.BeforeDelete(oldObject.Value); if (oldObject == null) { return(CrudActionResponse <TObject> .Error( new BeforeActionException(), request.ExtraData)); } try { oldObject = await factory.Delete(factory.GetId(oldObject)); } catch (Exception exception) { return(CrudActionResponse <TObject> .Error( new DatasourceInnerException("Exception on Delete operation", exception), request.ExtraData)); } if (oldObject == null) { return(CrudActionResponse <TObject> .Error( new EntityNotFoundException("After \"Before\" action modification"), request.ExtraData)); } // security update logs are set here to be sure that they are made independently of client notification success SecurityLog.CreateRecord( EnSecurityLogType.DataDeleteGranted, oldObject.Value is ICrucialObject ? EnSeverity.Crucial : EnSeverity.Trivial, request.RequestContext, "{ObjectType} with id {ObjectId} was deleted.", typeof(TObject).FullName, factory.GetId(oldObject)); this.AfterDelete <TObject>(oldObject); return(CrudActionResponse <TObject> .Success(oldObject, request.ExtraData)); } default: return(CrudActionResponse <TObject> .Error( new ArgumentOutOfRangeException(nameof(request.ActionType)), request.ExtraData)); } } }