Skip to content

Commit

Permalink
Merge pull request #281 from BiggerNoise/feature/user-token-feature
Browse files Browse the repository at this point in the history
Add User Tokens to Roundhouse
  • Loading branch information
BiggerNoise authored Oct 14, 2017
2 parents 5ebabd7 + 541e4b8 commit ce7cf47
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 3 deletions.
5 changes: 5 additions & 0 deletions product/roundhouse.console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using roundhouse.folders;
using roundhouse.infrastructure;
using roundhouse.infrastructure.app;
using roundhouse.infrastructure.app.tokens;
using roundhouse.infrastructure.app.logging;
using roundhouse.infrastructure.commandline.options;
using roundhouse.infrastructure.containers;
Expand Down Expand Up @@ -323,6 +324,10 @@ private static void parse_arguments_and_set_up_configuration(ConfigurationProper
.Add("rcm=|recoverymode=",
"RecoveryMode - This instructs RH to set the database recovery mode to Simple|Full|NoChange. Defaults to NoChange.",
option => configuration.RecoveryMode = (RecoveryMode)Enum.Parse(typeof(RecoveryMode), option, true))
//user tokens
.Add("ut=|usertokens=",
"UserTokens - This is a list of key/value pairs used in scripts: the token '{{SomeToken}}' will be replace by 'value123' if 'ut=SomeToken=value123' is provided. Separate multiple tokens with ;",
option => configuration.UserTokens = UserTokenParser.Parse(option))
//debug
.Add("debug",
"Debug - This instructs RH to write out all messages. Defaults to false.",
Expand Down
5 changes: 4 additions & 1 deletion product/roundhouse.tasks/Roundhouse.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
namespace roundhouse.tasks

namespace roundhouse.tasks
{
using System;
using System.Collections.Generic;
using databases;
using folders;
using infrastructure.app;
Expand Down Expand Up @@ -190,6 +192,7 @@ public string RecoveryMode
public System.Text.Encoding FileEncoding { get; set; }

public bool DisableOutput { get; set; }
public Dictionary<string, string> UserTokens { get; set; }

public bool Initialize { get; set; }
public string ConfigurationFile { get; set; }
Expand Down
11 changes: 11 additions & 0 deletions product/roundhouse.tests/TestExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using NUnit.Framework;
using System.Collections;
using System.Collections.Generic;

namespace roundhouse.tests
{
Expand Down Expand Up @@ -29,6 +31,15 @@ public static void should_throw_an<T>(this Action a) where T: Exception
{
Assert.Throws<T>(() => a());
}

public static void should_only_contain<K,V>(this IDictionary<K,V> dictionary, params KeyValuePair<K,V>[] values)
{
Assert.That(dictionary, Has.Count.EqualTo(values.Length));
foreach(var value in values)
{
Assert.That(dictionary, Contains.Item(value));
}
}
}

}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System.Collections.Generic;

namespace roundhouse.tests.infrastructure.app.tokens
{
using consoles;
Expand All @@ -14,7 +16,15 @@ public abstract class concern_for_TokenReplacer : TinySpec

public override void Context()
{
configuration = new DefaultConfiguration { DatabaseName = database_name };
configuration = new DefaultConfiguration
{
DatabaseName = database_name,
UserTokens = new Dictionary<string,string>()
{
{ "UserId", "123" },
{ "UserName", "Some Name" }
}
};
}
}

Expand Down Expand Up @@ -71,6 +81,39 @@ public void if_given_a_value_that_does_not_exist_should_return_the_value_with_or
{
TokenReplacer.replace_tokens(configuration, "ALTER DATABASE {{DataBase}}").should_be_equal_to("ALTER DATABASE {{DataBase}}");
}
[Observation]
public void if_given_userid_and_username_should_replace_with_the_user_tokens_from_the_configuration()
{
TokenReplacer.replace_tokens(configuration, "SELECT * FROM Users WHERE UserId = {{UserId}} OR UserName = '{{UserName}}'")
.should_be_equal_to("SELECT * FROM Users WHERE UserId = "+configuration.UserTokens["UserId"]+" OR UserName = '"+configuration.UserTokens["UserName"]+"'");
}
}
[Concern(typeof(TokenReplacer))]
public class when_replacing_tokens_in_sql_files_using_user_tokens_from_configuration : TinySpec
{
protected static object result;
protected static ConfigurationPropertyHolder configuration;

public override void Context()
{
configuration = new DefaultConfiguration
{
UserTokens = new Dictionary<string,string>()
{
{ "UserId", "123" },
{ "UserName", "Some Name" }
}
};
}

public override void Because() {}

[Observation]
public void if_given_bracket_bracket_DatabaseName_bracket_bracket_should_replace_with_the_DatabaseName_from_the_configuration()
{
TokenReplacer.replace_tokens(configuration, "SELECT * FROM Users WHERE UserId = {{UserId}} OR UserName = '{{UserName}}'")
.should_be_equal_to("SELECT * FROM Users WHERE UserId = " + configuration.UserTokens["UserId"] + " OR UserName = '" + configuration.UserTokens["UserName"] + "'");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using roundhouse.infrastructure.app;

namespace roundhouse.tests.infrastructure.app.tokens
{
using roundhouse.infrastructure.app.tokens;
using System.IO;

public class UserTokenParserSpecs
{
[Concern(typeof(UserTokenParser))]
public class when_parsing_from_text : TinySpec
{
protected static object result;

public override void Context()
{
}

public override void Because()
{
}

[Observation]
public void if_given_keyvalues_should_parse_to_dictionary()
{
var dictionary = UserTokenParser.Parse("UserId=123;UserName=Some Name");
dictionary.should_be_an_instance_of<Dictionary<string, string>>();
dictionary.should_only_contain(
new KeyValuePair<string, string>("UserId", "123"),
new KeyValuePair<string, string>("UserName", "Some Name"));
}

[Observation]
public void if_given_filepath_with_keyvalues_should_parse_to_dictionary()
{
var filename = Path.GetTempFileName() + ".txt";
File.WriteAllText(filename, "UserId=123" + Environment.NewLine + "UserName=Some Name");
try
{
var dictionary = UserTokenParser.Parse(filename);
dictionary.should_be_an_instance_of<Dictionary<string, string>>();
dictionary.should_only_contain(
new KeyValuePair<string, string>("UserId", "123"),
new KeyValuePair<string, string>("UserName", "Some Name"));
}
finally
{
File.Delete(filename);
}
}
[Observation]
public void if_given_wrong_syntax_text_without_equals_sign_should_throw_format_exception()
{
Action action = () =>
{
var dictionary = UserTokenParser.Parse("UserId123User&NameSome Name");
};
action.should_throw_an<FormatException>();
}
[Observation]
public void if_given_empty_text_should_throw_argument_null_exception()
{
Action action = () =>
{
var dictionary = UserTokenParser.Parse("");
};
action.should_throw_an<ArgumentNullException>();
}
}

}
}
1 change: 1 addition & 0 deletions product/roundhouse.tests/roundhouse.tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
<Compile Include="EmptyTestContainer.cs" />
<Compile Include="cryptography\CryptographicServiceSpecs.cs" />
<Compile Include="infrastructure.app\tokens\TokenReplacerSpecs.cs" />
<Compile Include="infrastructure.app\tokens\UserTokenParserSpecs.cs" />
<Compile Include="infrastructure\containers\ContainerSpecs.cs" />
<Compile Include="infrastructure\containers\custom\StructureMapContainerSpecs.cs" />
<Compile Include="infrastructure\extensions\IterationSpecs.cs" />
Expand Down
3 changes: 3 additions & 0 deletions product/roundhouse/consoles/DefaultConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System.Collections.Generic;

namespace roundhouse.consoles
{
using System;
Expand Down Expand Up @@ -65,6 +67,7 @@ public sealed class DefaultConfiguration : ConfigurationPropertyHolder
public bool DisableTokenReplacement { get; set; }
public bool SearchAllSubdirectoriesInsteadOfTraverse { get; set; }
public bool DisableOutput { get; set; }
public Dictionary<string, string> UserTokens { get; set; }
public bool Initialize { get; set; }
public string ConfigurationFile { get; set; }
public System.Text.Encoding FileEncoding { get; set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Collections.Generic;
using roundhouse.infrastructure.logging;

namespace roundhouse.infrastructure.app
Expand Down Expand Up @@ -65,6 +66,7 @@ public interface ConfigurationPropertyHolder
bool DisableTokenReplacement { get; set; }
bool SearchAllSubdirectoriesInsteadOfTraverse { get; set; }
bool DisableOutput { get; set; }
Dictionary<string, string> UserTokens { get; set; }
System.Text.Encoding FileEncoding { get; set; }
string ConfigurationFile { get; set; }
}
Expand Down
30 changes: 30 additions & 0 deletions product/roundhouse/infrastructure.app/UserTokenParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
namespace roundhouse.infrastructure.app.tokens
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

public class UserTokenParser
{
public static Dictionary<string, string> Parse(string option)
{
if (String.IsNullOrEmpty(option))
throw new ArgumentNullException("option");

var textToParse = option;
var pairs = textToParse.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);

if (pairs.Length == 1 && File.Exists(textToParse))
{
textToParse = File.ReadAllText(textToParse);
pairs = textToParse.Split(new string[] { ";",Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
}

if (pairs.Any(p => !p.Contains("="))) throw new FormatException("Wrong format");

return pairs.ToDictionary(p => p.Split(new string[] { "=" }, StringSplitOptions.RemoveEmptyEntries)[0],
p => p.Split(new string[] { "=" }, StringSplitOptions.RemoveEmptyEntries)[1]);
}
}
}
14 changes: 13 additions & 1 deletion product/roundhouse/infrastructure.app/tokens/TokenReplacer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,19 @@ private static IDictionary<string, string> create_dictionary_from_configuration(
Dictionary<string, string> property_dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (var property in configuration.GetType().GetProperties())
{
property_dictionary.Add(property.Name, property.GetValue(configuration, null).to_string());
if (property.Name == "UserTokens")
{
var user_tokens = property.GetValue(configuration, null) as Dictionary<string, string>;
if (user_tokens == null)
continue;

foreach (var user_token in user_tokens)
{
property_dictionary[user_token.Key] = user_token.Value;
}
}
else property_dictionary.Add(property.Name, property.GetValue(configuration, null).to_string());

}

return property_dictionary;
Expand Down
1 change: 1 addition & 0 deletions product/roundhouse/roundhouse.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@
<Compile Include="infrastructure.app\builders\VersionResolverBuilder.cs" />
<Compile Include="infrastructure.app\DatabaseTypeSynonyms.cs" />
<Compile Include="infrastructure.app\persistence\NHibernateMigrationSessionFactory.cs" />
<Compile Include="infrastructure.app\UserTokenParser.cs" />
<Compile Include="infrastructure\extensions\ObjectExtensions.cs" />
<Compile Include="infrastructure\logging\custom\TraceLogger.cs" />
<Compile Include="infrastructure\logging\custom\ConsoleLogger.cs" />
Expand Down

0 comments on commit ce7cf47

Please sign in to comment.