public async Task <IActionResult> InspectUploadedStructure([FromRoute] string environmentCategory, [FromRoute] string environmentName, [FromBody] DtoStructure structure) { if (string.IsNullOrWhiteSpace(environmentCategory)) { return(BadRequest("no environment-category given")); } if (string.IsNullOrWhiteSpace(environmentName)) { return(BadRequest("no environment-name given")); } if (structure is null) { return(BadRequest("no structure was uploaded")); } switch (structure.Structure.ValueKind) { case JsonValueKind.Object: if (!structure.Structure.EnumerateObject().Any()) { return(BadRequest("empty structure-body given")); } break; case JsonValueKind.Array: if (!structure.Structure.EnumerateArray().Any()) { return(BadRequest("empty structure-body given")); } break; default: return(BadRequest("invalid structure-body given (invalid type or null)")); } IDictionary <string, string> structKeys; try { structKeys = _translator.ToDictionary(structure.Structure); } catch (Exception e) { Logger.LogWarning(e, "could not translate given json.Structure to dictionary"); return(BadRequest("structure could not be mapped to a dictionary ($.Structure)")); } var envId = new EnvironmentIdentifier(environmentCategory, environmentName); var envKeysResult = await _store.Environments.GetKeys(new EnvironmentKeyQueryParameters { Environment = envId, Range = QueryRange.All }); if (envKeysResult.IsError) { return(ProviderError(envKeysResult)); } var envKeys = envKeysResult.Data; CompilationResult compilationResult; try { compilationResult = _compiler.Compile( new EnvironmentCompilationInfo { Keys = envKeys, Name = envId.ToString() }, new StructureCompilationInfo { Name = structure.Name ?? "Inspected Structure", Keys = structKeys, Variables = (structure.Variables ?? new Dictionary <string, object>()).ToDictionary(kvp => kvp.Key, kvp => kvp.Value?.ToString()) }, _parser); } catch (Exception e) { Logger.LogWarning(e, $"structure could not be inspected in context of '{envId}'; compilation failed"); return(Ok(new StructureInspectionResult { CompilationSuccessful = false })); } var result = AnalyzeCompilation(compilationResult); return(Ok(result)); }
public async Task <IActionResult> InspectStructure([FromRoute] string environmentCategory, [FromRoute] string environmentName, [FromRoute] string structureName, [FromRoute] int structureVersion) { if (string.IsNullOrWhiteSpace(environmentCategory)) { return(BadRequest("no environment-category given")); } if (string.IsNullOrWhiteSpace(environmentName)) { return(BadRequest("no environment-name given")); } if (string.IsNullOrWhiteSpace(structureName)) { return(BadRequest("no structure-name was given")); } if (structureVersion <= 0) { return(BadRequest("structure-version invalid")); } var envId = new EnvironmentIdentifier(environmentCategory, environmentName); var structId = new StructureIdentifier(structureName, structureVersion); var envKeysResult = await _store.Environments.GetKeys(new EnvironmentKeyQueryParameters { Environment = envId, Range = QueryRange.All }); if (envKeysResult.IsError) { return(ProviderError(envKeysResult)); } var envKeys = envKeysResult.Data; IDictionary <string, string> structKeys; IDictionary <string, string> structVars; try { var keyResult = await _store.Structures.GetKeys(structId, QueryRange.All); if (keyResult.IsError) { return(ProviderError(keyResult)); } var varResult = await _store.Structures.GetVariables(structId, QueryRange.All); if (varResult.IsError) { return(ProviderError(varResult)); } structKeys = keyResult.Data; structVars = varResult.Data; } catch (Exception e) { Logger.LogWarning(e, "could not retrieve structure-data or -variables"); return(BadRequest("could not retrieve structure-data or -variables")); } CompilationResult compilationResult; try { compilationResult = _compiler.Compile( new EnvironmentCompilationInfo { Keys = envKeys, Name = envId.ToString() }, new StructureCompilationInfo { Name = structureName, Keys = structKeys, Variables = structVars }, _parser); } catch (Exception e) { Logger.LogWarning(e, $"structure could not be inspected in context of '{envId}'; compilation failed"); return(Ok(new StructureInspectionResult { CompilationSuccessful = false })); } var result = AnalyzeCompilation(compilationResult); return(Ok(result)); }
/// <inheritdoc /> public async Task <IResult> Delete(EnvironmentIdentifier identifier) { _logger.LogDebug($"attempting to delete environment '{identifier}'"); var envResult = await _domainObjectStore.ReplayObject(new ConfigEnvironment(identifier), identifier.ToString()); if (envResult.IsError) { return(envResult); } var environment = envResult.Data; _logger.LogDebug("deleting environment"); var createResult = environment.Delete(); if (createResult.IsError) { return(createResult); } _logger.LogDebug("validating resulting events"); var errors = environment.Validate(_validators); if (errors.Any()) { return(Result.Error("failed to validate generated DomainEvents", ErrorCode.ValidationFailed, errors.Values .SelectMany(_ => _) .ToList())); } return(await environment.WriteRecordedEvents(_eventStore)); }
/// <inheritdoc /> public async Task <IResult> UpdateKeys(EnvironmentIdentifier identifier, ICollection <DtoConfigKey> keys) { _logger.LogDebug($"attempting to update {keys.Count} keys in '{identifier}'"); var envResult = await _domainObjectStore.ReplayObject(new ConfigEnvironment(identifier), identifier.ToString()); if (envResult.IsError) { return(envResult); } var environment = envResult.Data; if (!environment.Created) { return(Result.Error("environment does not exist", ErrorCode.NotFound)); } _logger.LogDebug($"transforming DTOs to '{nameof(ConfigEnvironmentKey)}'"); var updates = keys.Select(dto => new ConfigEnvironmentKey(dto.Key, dto.Value, dto.Type, dto.Description, 0)) .ToList(); _logger.LogDebug("updating environment keys"); var result = environment.UpdateKeys(updates); if (result.IsError) { return(result); } _logger.LogDebug("validating generated events"); var errors = environment.Validate(_validators); if (errors.Any()) { return(Result.Error("failed to validate generated DomainEvents", ErrorCode.ValidationFailed, errors.Values .SelectMany(_ => _) .ToList())); } return(await environment.WriteRecordedEvents(_eventStore)); }
/// <inheritdoc /> public async Task <IResult <IList <DtoConfigKeyCompletion> > > GetKeyAutoComplete(EnvironmentIdentifier identifier, string key, QueryRange range, long version) { try { _logger.LogDebug($"attempting to retrieve next paths in '{identifier}' for path '{key}', range={range}"); _logger.LogDebug($"removing escape-sequences from key"); key = Uri.UnescapeDataString(key ?? string.Empty); _logger.LogDebug($"using new key='{key}'"); var envResult = await(version <= 0 ? _domainObjectStore.ReplayObject(new ConfigEnvironment(identifier), identifier.ToString()) : _domainObjectStore.ReplayObject(new ConfigEnvironment(identifier), identifier.ToString(), version)); if (envResult.IsError) { return(Result.Error <IList <DtoConfigKeyCompletion> >( "no environment found with (" + $"{nameof(identifier.Category)}: {identifier.Category}; " + $"{nameof(identifier.Name)}: {identifier.Name})", ErrorCode.NotFound)); } var environment = envResult.Data; var paths = environment.KeyPaths; // send auto-completion data for all roots if (string.IsNullOrWhiteSpace(key)) { _logger.LogDebug("early-exit, sending root-paths because key was empty"); return(Result.Success <IList <DtoConfigKeyCompletion> >( paths.Select(p => new DtoConfigKeyCompletion { HasChildren = p.Children.Any(), FullPath = p.FullPath, Completion = p.Path }) .OrderBy(p => p.Completion) .ToList())); } var parts = new Queue <string>(key.Contains('/') ? key.Split('/') : new[] { key }); var rootPart = parts.Dequeue(); _logger.LogDebug($"starting with path '{rootPart}'"); // if the user is searching within the roots if (!parts.Any()) { _logger.LogDebug($"no further parts found, returning direct children"); var possibleRoots = paths.Where(p => p.Path.Contains(rootPart)) .ToList(); // if there is only one possible root, and that one matches what were searching for // we're returning all paths directly below that one List <ConfigEnvironmentKeyPath> selectedRoots; if (possibleRoots.Count == 1 && possibleRoots.First() .Path .Equals(rootPart, StringComparison.OrdinalIgnoreCase)) { _logger.LogDebug("selecting children of only root for further processing"); selectedRoots = paths.First().Children; } else { _logger.LogDebug("selecting original matches for further processing"); selectedRoots = paths; } return(Result.Success <IList <DtoConfigKeyCompletion> >( selectedRoots.Select(p => new DtoConfigKeyCompletion { HasChildren = p.Children.Any(), FullPath = p.Children.Any() ? p.FullPath + '/' : p.FullPath, Completion = p.Path }) .OrderBy(p => p.Completion) .ToList())); } var root = paths.FirstOrDefault(p => p.Path == rootPart); if (root is null) { _logger.LogDebug($"no path found that matches '{rootPart}'"); return(Result.Error <IList <DtoConfigKeyCompletion> >( $"key '{key}' is ambiguous, root does not match anything", ErrorCode.NotFound)); } var result = GetKeyAutoCompleteInternal(root, parts.ToList(), range); return(result); } catch (Exception e) { _logger.LogError(e, $"failed to get autocomplete data for '{key}' in " + $"({nameof(identifier.Category)}: {identifier.Category}; {nameof(identifier.Name)}: {identifier.Name})"); return(Result.Error <IList <DtoConfigKeyCompletion> >($"failed to get autocomplete data for '{key}' in " + $"({nameof(identifier.Category)}: {identifier.Category}; {nameof(identifier.Name)}: {identifier.Name}): {e}", ErrorCode.DbQueryError)); } }
/// <inheritdoc /> public async Task <IResult> Import(ConfigExport export) { if (export is null) { return(Result.Error($"{nameof(export)} must not be null", ErrorCode.InvalidData)); } foreach (var envExport in export.Environments) { var identifier = new EnvironmentIdentifier(envExport.Category, envExport.Name); var envResult = await _domainObjectStore.ReplayObject(new ConfigEnvironment(identifier), identifier.ToString()); if (envResult.IsError) { return(envResult); } var environment = envResult.Data; environment.ImportKeys(envExport.Keys .Select(k => new ConfigEnvironmentKey(k.Key, k.Value, k.Type, k.Description, 0)) .ToList()); var errors = environment.Validate(_validators); if (errors.Any()) { var errorMessages = string.Join("\r\n", errors.Values .SelectMany(_ => _) .Select(r => r.Message)); return(Result.Error($"data-validation failed; {errorMessages}", ErrorCode.ValidationFailed)); } var result = await environment.WriteRecordedEvents(_eventStore); if (result.IsError) { return(result); } } return(Result.Success()); }