11using System ;
22using System . Collections ;
3+ using System . Collections . Generic ;
34using System . Linq ;
5+ using System . Reflection ;
6+ using System . Text ;
47using Microsoft . Extensions . Configuration ;
58using Serilog . Events ;
69
710namespace SqlStreamStore . Server
811{
912 internal class SqlStreamStoreServerConfiguration
1013 {
11- private readonly IConfigurationRoot _configuration ;
14+ private static readonly string [ ] s_sensitiveKeys = typeof ( ConfigurationData ) . GetProperties ( )
15+ . Where ( property => property . GetCustomAttributes < SensitiveAttribute > ( ) . Any ( ) )
16+ . Select ( property => property . Name )
17+ . ToArray ( ) ;
1218
13- public bool UseCanonicalUris => _configuration . GetValue < bool > ( "use-canonical-uris" ) ;
14- public LogEventLevel LogLevel => _configuration . GetValue ( "log-level" , LogEventLevel . Information ) ;
15- public string ConnectionString => _configuration . GetValue < string > ( "connection-string" ) ;
16- public string Schema => _configuration . GetValue < string > ( "schema" ) ;
17- public string Provider => _configuration . GetValue < string > ( "provider" ) ;
19+ private static readonly string [ ] s_allKeys = typeof ( ConfigurationData ) . GetProperties ( )
20+ . Select ( property => property . Name )
21+ . ToArray ( ) ;
1822
19- public SqlStreamStoreServerConfiguration ( IDictionary environment , string [ ] args )
23+ private readonly ConfigurationData _configuration ;
24+ private readonly IDictionary < string , ( string source , string value ) > _values ;
25+
26+ public bool UseCanonicalUris => _configuration . UseCanonicalUris ;
27+ public LogEventLevel LogLevel => _configuration . LogLevel ;
28+ public string ConnectionString => _configuration . ConnectionString ;
29+ public string Schema => _configuration . Schema ;
30+ public string Provider => _configuration . Provider ;
31+
32+ public SqlStreamStoreServerConfiguration (
33+ IDictionary environment ,
34+ string [ ] args )
2035 {
21- if ( environment == null )
36+ if ( environment == null )
2237 throw new ArgumentNullException ( nameof ( environment ) ) ;
23- if ( args == null )
38+ if ( args == null )
2439 throw new ArgumentNullException ( nameof ( args ) ) ;
25- _configuration = new ConfigurationBuilder ( )
26- . AddCommandLine ( args )
27- . Add ( new UpperCasedEnvironmentVariablesConfigurationSource ( environment ) )
28- . Build ( ) ;
40+
41+ _values = new Dictionary < string , ( string source , string value ) > ( ) ;
42+
43+ void Log ( string logName , IDictionary < string , string > data )
44+ {
45+ foreach ( var ( key , value ) in data )
46+ {
47+ _values [ key ] = ( logName , value ) ;
48+ }
49+ }
50+
51+ _configuration = new ConfigurationData (
52+ new ConfigurationBuilder ( )
53+ . Add ( new Default ( Log ) )
54+ . Add ( new CommandLine ( args , Log ) )
55+ . Add ( new EnvironmentVariables ( environment , Log ) )
56+ . Build ( ) ) ;
57+ }
58+
59+ public override string ToString ( )
60+ {
61+ const string delimiter = " │ " ;
62+
63+ var column0Width = _values . Keys . Count > 0 ? _values . Keys . Max ( x => x ? . Length ?? 0 ) : 0 ;
64+ var column1Width = _values . Values . Count > 0 ? _values . Values . Max ( _ => _ . value ? . Length ?? 0 ) : 0 ;
65+ var column2Width = _values . Values . Count > 0 ? _values . Values . Max ( _ => _ . source ? . Length ?? 0 ) : 0 ;
66+
67+ return new [ ]
68+ {
69+ new [ ]
70+ {
71+ delimiter ,
72+ "Argument" ,
73+ "Value" ,
74+ "Source"
75+ } ,
76+ new [ ]
77+ {
78+ "─┼─" ,
79+ new string ( '─' , column0Width ) ,
80+ new string ( '─' , column1Width ) ,
81+ new string ( '─' , column2Width )
82+ }
83+ }
84+ . Concat (
85+ s_allKeys
86+ . Select ( key => new [ ] { delimiter , key , _values [ key ] . value , _values [ key ] . source } ) )
87+ . Aggregate (
88+ new StringBuilder ( ) . AppendLine ( "SQL Stream Store Configuration:" ) ,
89+ ( builder , values ) => builder
90+ . Append ( ( values [ 1 ] ?? string . Empty ) . PadRight ( column0Width , ' ' ) )
91+ . Append ( values [ 0 ] )
92+ . Append ( ( s_sensitiveKeys . Contains ( values [ 1 ] )
93+ ? new string ( '*' , Math . Min ( column1Width , 8 ) )
94+ : values [ 2 ] ?? string . Empty ) . PadRight ( column1Width , ' ' ) )
95+ . Append ( values [ 0 ] )
96+ . AppendLine ( values [ 3 ] ) ) . ToString ( ) ;
97+ }
98+
99+ private static string Computerize ( string value ) =>
100+ string . Join (
101+ string . Empty ,
102+ ( value ? . Replace ( "-" , "_" ) . ToLowerInvariant ( )
103+ ?? string . Empty ) . Split ( '_' )
104+ . Select ( x => new string ( x . Select ( ( c , i ) => i == 0 ? char . ToUpper ( c ) : c ) . ToArray ( ) ) ) ) ;
105+
106+ private class ConfigurationData
107+ {
108+ private readonly IConfigurationRoot _configuration ;
109+
110+ public bool UseCanonicalUris => _configuration . GetValue < bool > ( nameof ( UseCanonicalUris ) ) ;
111+ public LogEventLevel LogLevel => _configuration . GetValue ( nameof ( LogLevel ) , LogEventLevel . Information ) ;
112+ [ Sensitive ] public string ConnectionString => _configuration . GetValue < string > ( nameof ( ConnectionString ) ) ;
113+ public string Schema => _configuration . GetValue < string > ( nameof ( Schema ) ) ;
114+ public string Provider => _configuration . GetValue < string > ( nameof ( Provider ) ) ;
115+
116+ public ConfigurationData ( IConfigurationRoot configuration )
117+ {
118+ if ( configuration == null ) throw new ArgumentNullException ( nameof ( configuration ) ) ;
119+ _configuration = configuration ;
120+ }
121+ }
122+
123+ private class Default : IConfigurationSource
124+ {
125+ private readonly Action < string , IDictionary < string , string > > _log ;
126+
127+ public Default ( Action < string , IDictionary < string , string > > log )
128+ {
129+ if ( log == null )
130+ {
131+ throw new ArgumentNullException ( nameof ( log ) ) ;
132+ }
133+
134+ _log = log ;
135+ }
136+
137+ public IConfigurationProvider Build ( IConfigurationBuilder builder ) =>
138+ new DefaultConfigurtationProvider ( _log ) ;
139+ }
140+
141+ private class DefaultConfigurtationProvider : ConfigurationProvider
142+ {
143+ private readonly Action < string , IDictionary < string , string > > _log ;
144+
145+ public DefaultConfigurtationProvider ( Action < string , IDictionary < string , string > > log )
146+ {
147+ if ( log == null ) throw new ArgumentNullException ( nameof ( log ) ) ;
148+ _log = log ;
149+ }
150+
151+ public override void Load ( )
152+ {
153+ Data = new Dictionary < string , string >
154+ {
155+ [ nameof ( ConnectionString ) ] = default ,
156+ [ nameof ( Provider ) ] = "inmemory" ,
157+ [ nameof ( LogLevel ) ] = nameof ( LogEventLevel . Information ) ,
158+ [ nameof ( Schema ) ] = default ,
159+ [ nameof ( UseCanonicalUris ) ] = default
160+ } ;
161+
162+ _log ( nameof ( Default ) , Data ) ;
163+ }
164+ }
165+
166+ private class CommandLine : IConfigurationSource
167+ {
168+ private readonly IEnumerable < string > _args ;
169+ private readonly Action < string , IDictionary < string , string > > _log ;
170+
171+ public CommandLine (
172+ IEnumerable < string > args ,
173+ Action < string , IDictionary < string , string > > log )
174+ {
175+ if ( args == null )
176+ {
177+ throw new ArgumentNullException ( nameof ( args ) ) ;
178+ }
179+
180+ if ( log == null )
181+ {
182+ throw new ArgumentNullException ( nameof ( log ) ) ;
183+ }
184+
185+ _args = args ;
186+ _log = log ;
187+ }
188+
189+ public IConfigurationProvider Build ( IConfigurationBuilder builder )
190+ => new CommandLineConfigurationProvider ( _args , _log ) ;
191+ }
192+
193+ private class CommandLineConfigurationProvider
194+ : Microsoft . Extensions . Configuration . CommandLine . CommandLineConfigurationProvider
195+ {
196+ private readonly Action < string , IDictionary < string , string > > _log ;
197+
198+ public CommandLineConfigurationProvider ( IEnumerable < string > args ,
199+ Action < string , IDictionary < string , string > > log ,
200+ IDictionary < string , string > switchMappings = null ) : base ( args , switchMappings )
201+ {
202+ if ( log == null )
203+ {
204+ throw new ArgumentNullException ( nameof ( log ) ) ;
205+ }
206+
207+ _log = log ;
208+ }
209+
210+ public override void Load ( )
211+ {
212+ base . Load ( ) ;
213+
214+ Data = Data . Keys . ToDictionary ( Computerize , x => Data [ x ] ) ;
215+
216+ _log ( nameof ( CommandLine ) , Data ) ;
217+ }
29218 }
30219
31- private class UpperCasedEnvironmentVariablesConfigurationSource : IConfigurationSource
220+ private class EnvironmentVariables : IConfigurationSource
32221 {
33222 private readonly IDictionary _environment ;
223+ private readonly Action < string , IDictionary < string , string > > _log ;
34224 public string Prefix { get ; set ; } = "SQLSTREAMSTORE" ;
35225
36- public UpperCasedEnvironmentVariablesConfigurationSource ( IDictionary environment )
226+ public EnvironmentVariables (
227+ IDictionary environment ,
228+ Action < string , IDictionary < string , string > > log )
37229 {
230+ if ( log == null )
231+ {
232+ throw new ArgumentNullException ( nameof ( log ) ) ;
233+ }
234+
235+ if ( environment == null )
236+ {
237+ throw new ArgumentNullException ( nameof ( environment ) ) ;
238+ }
239+
38240 _environment = environment ;
241+ _log = log ;
39242 }
40243
41244 public IConfigurationProvider Build ( IConfigurationBuilder builder )
42- => new UpperCasedEnvironmentVariablesConfigurationProvider ( Prefix , _environment ) ;
245+ => new EnvironmentVariablesConfigurationProvider ( Prefix , _environment , _log ) ;
43246 }
44247
45- private class UpperCasedEnvironmentVariablesConfigurationProvider : ConfigurationProvider
248+ private class EnvironmentVariablesConfigurationProvider : ConfigurationProvider
46249 {
47250 private readonly IDictionary _environment ;
251+ private readonly Action < string , IDictionary < string , string > > _log ;
48252 private readonly string _prefix ;
49253
50- public UpperCasedEnvironmentVariablesConfigurationProvider ( string prefix , IDictionary environment )
254+ public EnvironmentVariablesConfigurationProvider (
255+ string prefix ,
256+ IDictionary environment ,
257+ Action < string , IDictionary < string , string > > log )
51258 {
52- _environment = environment ;
259+ if ( log == null )
260+ {
261+ throw new ArgumentNullException ( nameof ( log ) ) ;
262+ }
263+
264+ if ( environment == null )
265+ {
266+ throw new ArgumentNullException ( nameof ( environment ) ) ;
267+ }
268+
53269 _prefix = $ "{ prefix } _";
270+ _environment = environment ;
271+ _log = log ;
54272 }
55273
56274 public override void Load ( )
57275 {
58276 Data = ( from entry in _environment . OfType < DictionaryEntry > ( )
59277 let key = ( string ) entry . Key
60278 where key . StartsWith ( _prefix )
61- select new { key = key . Remove ( 0 , _prefix . Length ) . Replace ( '_' , '-' ) . ToLowerInvariant ( ) , value = ( string ) entry . Value } )
279+ select new
280+ {
281+ key = Computerize ( key . Remove ( 0 , _prefix . Length ) ) ,
282+ value = ( string ) entry . Value
283+ } )
62284 . ToDictionary ( x => x . key , x => x . value ) ;
285+
286+ _log ( nameof ( EnvironmentVariables ) , Data ) ;
63287 }
64288 }
289+
290+ private class SensitiveAttribute : Attribute
291+ {
292+ }
65293 }
66- }
294+ }
0 commit comments