diff --git a/src/SeqCli/Config/EnvironmentOverrides.cs b/src/SeqCli/Config/EnvironmentOverrides.cs index 42544c5..8d87880 100644 --- a/src/SeqCli/Config/EnvironmentOverrides.cs +++ b/src/SeqCli/Config/EnvironmentOverrides.cs @@ -1,5 +1,18 @@ +// Copyright © Datalust Pty Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + using System; -using System.Collections; using System.Collections.Generic; using System.Linq; @@ -30,7 +43,7 @@ internal static void Apply(string prefix, SeqCliConfig config, Dictionary p.CanRead && p.GetMethod!.IsPublic && !p.GetMethod.IsStatic && p.GetCustomAttribute() == null) + .Where(p => p.CanRead && p.GetMethod!.IsPublic && !p.GetMethod.IsStatic && p.GetCustomAttribute() == null) .SingleOrDefault(p => Camelize(GetUserFacingName(p)) == steps[i]); if (nextStep == null) @@ -38,10 +52,12 @@ public static void Set(SeqCliConfig config, string key, string? value) throw new InvalidOperationException("Intermediate configuration object is null."); } + // FUTURE: the use of `p.Name` and lack of `JsonIgnoreAttribute` checks here mean that sensitive values can + // intercept writes through hidden properties, triggering encoding where supported. A type-based solution + // would be more robust. var targetProperty = receiver.GetType().GetTypeInfo().DeclaredProperties - .Where(p => p is { CanRead: true, CanWrite: true } && p.GetMethod!.IsPublic && p.SetMethod!.IsPublic && - !p.GetMethod.IsStatic && p.GetCustomAttribute() == null) - .SingleOrDefault(p => Camelize(GetUserFacingName(p)) == steps[^1]); + .Where(p => p is { CanRead: true, CanWrite: true } && p.GetMethod!.IsPublic && p.SetMethod!.IsPublic && !p.GetMethod.IsStatic) + .SingleOrDefault(p => Camelize(p.Name) == steps[^1]); if (targetProperty == null) throw new ArgumentException("The key could not be found; run `seqcli config list` to view all keys."); @@ -56,7 +72,7 @@ public static void Set(SeqCliConfig config, string key, string? value) return value?.Split(',').Select(e => e.Trim()).ToArray() ?? []; if (propertyType == typeof(int[])) - return value?.Split(',').Select(e => int.Parse(e.Trim(), CultureInfo.InvariantCulture)).ToArray() ?? Array.Empty(); + return value?.Split(',').Select(e => int.Parse(e.Trim(), CultureInfo.InvariantCulture)).ToArray() ?? []; if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) { @@ -98,7 +114,7 @@ public static bool TryGetValue(object config, string key, out string? value, [No { foreach (var nextStep in receiver.GetType().GetTypeInfo().DeclaredProperties .Where(p => p.CanRead && p.GetMethod!.IsPublic && - !p.GetMethod.IsStatic && p.GetCustomAttribute() == null) + !p.GetMethod.IsStatic && p.GetCustomAttribute() == null && p.GetCustomAttribute() == null) .OrderBy(GetUserFacingName)) { var camel = Camelize(GetUserFacingName(nextStep)); @@ -131,6 +147,7 @@ public static bool TryGetValue(object config, string key, out string? value, [No else if (nextStep.CanRead && nextStep.GetMethod!.IsPublic && nextStep.CanWrite && nextStep.SetMethod!.IsPublic && !nextStep.SetMethod.IsStatic && + nextStep.GetCustomAttribute() == null && nextStep.GetCustomAttribute() == null) { var value = nextStep.GetValue(receiver); diff --git a/src/SeqCli/Config/RuntimeConfigurationLoader.cs b/src/SeqCli/Config/RuntimeConfigurationLoader.cs index 8733aa1..1550e7a 100644 --- a/src/SeqCli/Config/RuntimeConfigurationLoader.cs +++ b/src/SeqCli/Config/RuntimeConfigurationLoader.cs @@ -1,3 +1,17 @@ +// Copyright © Datalust Pty Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + using System; using System.IO; diff --git a/src/SeqCli/Config/SeqCliConfig.cs b/src/SeqCli/Config/SeqCliConfig.cs index c0d69b5..6efcbdd 100644 --- a/src/SeqCli/Config/SeqCliConfig.cs +++ b/src/SeqCli/Config/SeqCliConfig.cs @@ -54,7 +54,7 @@ public static void WriteToFile(SeqCliConfig data, string filename) { if (!data._exportable) throw new InvalidOperationException("The provided configuration is not exportable."); - + var content = JsonConvert.SerializeObject(data, Formatting.Indented, SerializerSettings); File.WriteAllText(filename, content); } diff --git a/src/SeqCli/Properties/launchSettings.json b/src/SeqCli/Properties/launchSettings.json index 6ff080f..fbea9f6 100644 --- a/src/SeqCli/Properties/launchSettings.json +++ b/src/SeqCli/Properties/launchSettings.json @@ -3,7 +3,7 @@ "profiles": { "SeqCli": { "commandName": "Project", - "commandLineArgs": "signal update --json-stdin" + "commandLineArgs": "config -k connection.apiKey -v test" } } }