Commit e2c1e66
Changed files (31)
trunk
build
product
Gorilla.Commons.Infrastructure
Cloning
Gorilla.Commons.Infrastructure.ThirdParty
Experiments
Gorilla.Commons.Utility
MoMoney.Service
Infrastructure
Security
MyMoney
boot
container
registration
proxy_configuration
trunk/build/build_utilities.rb
@@ -0,0 +1,187 @@
+include FileTest
+
+class SqlRunner
+ def initialize(settings = Hash.new("Not found"))
+ @sql_tool = settings.fetch(:sql_tool,File.join(ENV['SystemDrive'],'program files','microsoft sql server','100','tools','binn','osql.exe'))
+ @command_line_args = settings.fetch(:command_line_args, '-b -i')
+ @connection_string = settings.fetch(:connection_string,"-E")
+ end
+
+ def process_sql_files(files)
+ files.each do|file|
+ begin
+ sh "#{@sql_tool} #{@connection_string} #{@command_line_args} #{file}"
+ rescue
+ puts("Error processing sql file:#{file}")
+ raise
+ end
+ end
+ end
+end
+
+class LocalSettings
+ attr_reader :settings
+
+ def [](setting)
+ @settings[setting]
+ end
+
+ def each_pair
+ @settings.each_key do|key,value|
+ yield key,@settings[key]
+ end
+ end
+end
+
+class TemplateFile
+ attr_reader :template_file_name
+ attr_reader :output_file_name
+
+ def initialize(template_file_name)
+ @template_file_name = template_file_name
+ @output_file_name = template_file_name.gsub('.template','')
+ end
+
+ def generate(settings_dictionary)
+ generate_to(@output_file_name,settings_dictionary)
+ end
+
+ def generate_to_directory(output_directory,settings_dictionary)
+ generate_to(File.join(output_directory,File.basename(@output_file_name)),settings_dictionary)
+ end
+
+ def generate_to_directories(output_directories,settings_dictionary)
+ output_directories.each do |directory|
+ generate_to_directory(directory,settings_dictionary)
+ end
+ end
+
+ def generate_to(output_file,settings_dictionary)
+ File.delete?(output_file)
+
+ File.open_for_write(output_file) do|generated_file|
+ File.open_for_read(@template_file_name) do|template_line|
+ settings_dictionary.each_key do|key|
+ template_line = template_line.gsub("@#{key}@","#{settings_dictionary[key]}")
+ end
+ generated_file.puts(template_line)
+ end
+ end
+ end
+
+ def to_s()
+ "Template File- Template:#{@template_file_name} : Output:#{@output_file_name}"
+ end
+
+end
+
+class TemplateFileList
+ @template_files
+ def initialize(files_pattern)
+ @template_files = []
+ FileList.new(files_pattern).each do|file|
+ @template_files.push(TemplateFile.new(file))
+ end
+ end
+
+ def each()
+ @template_files.each do |file|
+ yield file
+ end
+ end
+
+ def generate_all_output_files(settings)
+ @template_files.each do |file|
+ file.generate(settings)
+ end
+ end
+end
+
+class MbUnitRunner
+ def initialize(items)
+ @source_dir = items.fetch(:source_dir, 'product')
+ @mbunit_dir = items.fetch(:mbunit_dir, 'tools/gallio')
+ @test_results_dir = items.fetch(:test_results_dir, 'artifacts')
+ @compile_target = items.fetch(:compile_target, 'debug')
+ @category_to_exclude = items.fetch(:category_to_exclude, 'missing')
+ @show_report = items.fetch(:show_report, false)
+ @report_type = items.fetch(:report_type,'text')
+ end
+
+ def execute_tests(assemblies)
+ Dir.mkdir @test_results_dir unless exists?(@test_results_dir)
+
+ assemblies.each do |assem|
+ sh build_command_line_for(assem)
+ end
+ end
+
+ def build_command_line_for(assembly)
+ file = File.expand_path("#{@source_dir}/#{assembly}/bin/#{@compile_target}/#{assembly}.dll")
+ "#{@mbunit_dir}/gallio.echo.exe #{file} /sr /rt:#{@report_type} /rd:#{@test_results_dir} /rnf:#{assembly}.dll-results "
+ end
+end
+
+class MSBuildRunner
+ def self.compile(attributes)
+ version = attributes.fetch(:clrversion, 'v3.5')
+ compile_target = attributes.fetch(:compile_target, 'debug')
+ solution_file = attributes[:solution_file]
+
+ framework_dir = File.join(ENV['windir'].dup, 'Microsoft.NET', 'Framework', 'v3.5')
+ msbuild_file = File.join(framework_dir, 'msbuild.exe')
+
+ sh "#{msbuild_file} #{solution_file} /property:Configuration=#{compile_target} /t:Rebuild"
+ end
+end
+
+class File
+ def self.open_for_read(file)
+ File.open(file,'r').each do|line|
+ yield line
+ end
+ end
+
+ def self.read_all_text(file)
+ contents = ''
+ File.open_for_read(file) do |line|
+ contents += line
+ end
+ end
+
+ def self.delete?(file)
+ File.delete(file) if File.exists?(file)
+ end
+
+ def self.open_for_write(file)
+ File.open(file,'w') do|new_file|
+ yield new_file
+ end
+ end
+
+ def self.base_name_without_extensions(file)
+ File.basename(file,'.*')
+ end
+
+ end
+
+class BDDDocRunner
+ def initialize(settings = Hash.new('missing'))
+ @output_folder = settings.fetch(:output_folder,'artifacts')
+ @observation_attribute = settings.fetch(:observation_attribute,'ObservationAttribute')
+ @bdddoc_folder = settings.fetch(:bdddoc_folder,'thirdparty\developwithpassion.bdddoc')
+ @mbunit_test_output_folder = settings.fetch(:mbunit_test_output_folder,'artifacts')
+ @developwithpassion_bdddoc_exe = settings.fetch(:bdddoc_exe,'developwithpassion.bdddoc.exe')
+ @logo_jpg = settings.fetch(:logo_jpg,File.join(@bdddoc_folder,'developwithpassion.bdddoc-logo.jpg'))
+ @css = settings.fetch(:css,File.join(@bdddoc_folder,'developwithpassion.bdddoc.css'))
+ end
+
+ def run(test_library)
+ test_file = File.basename(test_library)
+ output_file = "#{File.join(@output_folder,test_file)}.developwithpassion.bdddoc.html"
+ mbunit_test_output_file = "#{File.join(@mbunit_test_output_folder,test_file)}-results.xml"
+ sh "#{File.join(@bdddoc_folder,@developwithpassion_bdddoc_exe)} #{test_library} #{@observation_attribute} #{output_file} #{mbunit_test_output_file}"
+ FileUtils.cp @logo_jpg,@output_folder
+ FileUtils.cp @css,@output_folder
+ end
+end
trunk/build/Empty.cs
@@ -0,0 +1,7 @@
+namespace MyMoney.Build
+{
+ public class Empty
+ {
+
+ }
+}
\ No newline at end of file
trunk/build/local_properties.rb
@@ -0,0 +1,33 @@
+require "project_name.rb"
+
+class LocalSettings
+ attr_reader :settings
+ def initialize
+ @settings = {
+ :app_config_template => 'app.config.xp.template' ,
+ #:app_config_template => 'app.config.vista.template' ,
+ :path_to_runtime_log4net_config => 'artifacts\log4net.config.xml',
+ :initial_catalog => "#{Project.name}",
+ :database_provider => 'System.Data.SqlClient' ,
+ :database_path => 'C:\databases' ,
+ :asp_net_worker_process => 'aspnet_wp.exe',
+ :log_file_name => "#{Project.name}Log.txt",
+ :log_level => 'DEBUG',
+ :xunit_report_file_dir => 'artifacts' ,
+ :xunit_report_file_name => 'test_report',
+ :xunit_report_type => 'text',
+ :xunit_show_test_report => true,
+ :debug => true,
+ }
+@settings[:xunit_report_file_name_with_extension] = "#{@settings[:xunit_report_file_name]}.#{@settings[:xunit_report_type]}"
+@settings[:asp_net_account] = "#{ENV["computername"]}\\ASPNet";
+#@settings[:db_account_sql]= "#{@settings[:asp_net_account]} WITH PASSWORD=N'#{@settings[:asp_net_account]}', DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[us_english], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF")
+@settings[:db_account_sql] = "#{@settings[:asp_net_account]}', N'#{@settings[:asp_net_account]}'"
+
+#these settings may need to be changed to be specific to your local machine
+@settings[:osql_connectionstring] = '-E'
+@settings[:sql_tools_path] = File.join(ENV['SystemDrive'],'program files/microsoft sql server/100/tools/binn')
+@settings[:osql_exe] = File.join("#{@settings[:sql_tools_path]}",'osql.exe')
+@settings[:config_connectionstring] = "data source=(local);Integrated Security=SSPI;Initial Catalog=#{@settings[:initial_catalog]}"
+ end
+end
trunk/build/MyMoney.Build.csproj
@@ -67,6 +67,9 @@
<ItemGroup>
<Content Include="local.properties.xml" />
</ItemGroup>
+ <ItemGroup>
+ <Compile Include="Empty.cs" />
+ </ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
trunk/build/project_name.rb
@@ -0,0 +1,8 @@
+class Project
+ attr_reader :name
+
+ def self.name
+ @name = "momoney"
+ end
+
+end
trunk/build/rakefile.rb
@@ -0,0 +1,50 @@
+require 'build_utilities.rb'
+require 'local_properties.rb'
+require 'project_name.rb'
+require 'rake/clean'
+require 'fileutils'
+
+#load settings that differ by machine
+local_settings = LocalSettings.new
+
+COMPILE_TARGET = 'debug'
+
+CLEAN.include('artifacts','**/bin','**/obj')
+
+#target folders that can be run from VS
+project_test_dir = File.join('product',"#{Project.name}.tests",'bin','debug')
+
+output_folders = [project_test_dir]
+
+task :default => [:full_test]
+
+task :init => :clean do
+ mkdir 'artifacts'
+ mkdir 'artifacts/coverage'
+ mkdir 'artifacts/deploy'
+end
+
+desc 'compiles the project'
+task :compile => :init do
+ MSBuildRunner.compile :compile_target => COMPILE_TARGET, :solution_file => '../solution.sln'
+end
+
+task :deploy => :compile do
+ Dir.glob(File.join('product','**','mo.money*.dll')).each do|file|
+ FileUtils.cp file,File.join('artifacts','deploy')
+ end
+end
+
+desc 'run the tests for the project'
+task :test, :category_to_exclude, :needs => [:compile] do |t,args|
+ args.with_defaults(:category_to_exclude => 'SLOW')
+ runner = MbUnitRunner.new :compile_target => COMPILE_TARGET, :category_to_exclude => args.category_to_exclude
+ runner.execute_tests ["Gorilla.Commons.Infrastructure"]
+end
+
+desc 'run the bdddoc test report for the project'
+task :run_test_report => [:test] do
+ runner = BDDDocRunner.new
+ runner.run(File.join('product','developwithpassion.bdd.tests','bin','debug','developwithpassion.bdd.tests.dll'))
+end
+
trunk/build/run.bat
@@ -0,0 +1,3 @@
+@echo off
+cls
+rake rakefile.rb %*
trunk/product/Gorilla.Commons.Infrastructure/Cloning/Serializer.cs
@@ -14,17 +14,13 @@ namespace Gorilla.Commons.Infrastructure.Cloning
public void serialize(T to_serialize)
{
using (var stream = new FileStream(file_path, FileMode.Create, FileAccess.Write))
- {
formatter.Serialize(stream, to_serialize);
- }
}
public T deserialize()
{
using (var stream = new FileStream(file_path, FileMode.Open, FileAccess.Read))
- {
return (T) formatter.Deserialize(stream);
- }
}
public void Dispose()
trunk/product/Gorilla.Commons.Infrastructure.ThirdParty/Experiments/Autofac/AutofacContainerBuilder.cs
@@ -1,75 +0,0 @@
-using System;
-using System.Linq.Expressions;
-using Autofac;
-using Autofac.Builder;
-using Autofac.Modules;
-using Autofac.Registrars;
-using AutofacContrib.DynamicProxy2;
-using Gorilla.Commons.Infrastructure.Castle.DynamicProxy;
-using Gorilla.Commons.Infrastructure.Container;
-using Gorilla.Commons.Infrastructure.Experiments;
-using Gorilla.Commons.Utility.Core;
-using Gorilla.Commons.Utility.Extensions;
-
-namespace Gorilla.Commons.Infrastructure.New.Autofac
-{
- public class AutofacContainerBuilder : IContainerBuilder
- {
- readonly ContainerBuilder builder;
- readonly Func<IContainer> container;
-
- public AutofacContainerBuilder() : this(new ContainerBuilder())
- {
- }
-
- public AutofacContainerBuilder(ContainerBuilder builder)
- {
- this.builder = builder;
- builder.RegisterModule(new ImplicitCollectionSupportModule());
- builder.RegisterModule(new StandardInterceptionModule());
- builder.SetDefaultScope(InstanceScope.Factory);
- container = () => builder.Build();
- container = container.memorize();
- }
-
- public IDependencyRegistry build()
- {
- throw new NotImplementedException();
- }
-
- public IExtendedRegistration<T> register<T>(Expression<Func<T>> func) where T : class
- {
- return new AutofacExtendedRegistration<T>(builder, func);
- }
- }
-
- public class AutofacExtendedRegistration<T> : IExtendedRegistration<T> where T : class
- {
- IConcreteRegistrar registrar;
-
- public AutofacExtendedRegistration(ContainerBuilder builder, Expression<Func<T>> expression)
- {
- pretty_print = expression.ToString();
- registrar = builder.Register(x => expression.Compile()).As<T>();
- registrar.FactoryScoped();
- }
-
- public string pretty_print { get; set; }
-
- public IExtendedRegistration<T> as_singleton()
- {
- registrar.SingletonScoped();
- return this;
- }
-
- public IExtendedRegistration<T> with_expiry(string date_time)
- {
- throw new NotImplementedException();
- }
-
- public IExtendedRegistration<T> with_proxy(IConfiguration<IProxyBuilder<T>> configuration)
- {
- throw new NotImplementedException();
- }
- }
-}
\ No newline at end of file
trunk/product/Gorilla.Commons.Infrastructure.ThirdParty/Experiments/ExtendedRegistration.cs
@@ -1,57 +0,0 @@
-using System;
-using System.Globalization;
-using System.Linq.Expressions;
-using Gorilla.Commons.Infrastructure.Castle.DynamicProxy;
-using Gorilla.Commons.Utility;
-using Gorilla.Commons.Utility.Core;
-using Gorilla.Commons.Utility.Extensions;
-
-namespace Gorilla.Commons.Infrastructure.Experiments
-{
- public class ExtendedRegistration<T> : IResolver<T>, IExtendedRegistration<T> where T : class
- {
- public Func<T> build { get; private set; }
- const string time_format = "dd/MM/yyyy HH:mm:ss";
-
- public ExtendedRegistration(Expression<Func<T>> expression)
- {
- pretty_print = expression.ToString();
- build = expression.Compile();
- }
-
- public string pretty_print { get; set; }
-
- public IExtendedRegistration<T> as_singleton()
- {
- build = build.memorize();
- return this;
- }
-
- public IExtendedRegistration<T> with_expiry(string date_time)
- {
- var the_date_time = DateTime.ParseExact(date_time, time_format, CultureInfo.InvariantCulture);
- var original_func = build;
-
- build = () =>
- {
- if (Clock.now() > the_date_time)
- throw new ObjectUsageHasExpiredException(original_func().GetType(), date_time);
-
- return original_func();
- };
- return this;
- }
-
- public IExtendedRegistration<T> with_proxy(IConfiguration<IProxyBuilder<T>> configuration)
- {
- var original_func = build;
- build = () =>
- {
- var builder = new ProxyBuilder<T>();
- configuration.configure(builder);
- return builder.create_proxy_for(original_func);
- };
- return this;
- }
- }
-}
\ No newline at end of file
trunk/product/Gorilla.Commons.Infrastructure.ThirdParty/Experiments/IContainerBuilder.cs
@@ -1,12 +0,0 @@
-using System;
-using System.Linq.Expressions;
-using Gorilla.Commons.Infrastructure.Container;
-using Gorilla.Commons.Utility.Core;
-
-namespace Gorilla.Commons.Infrastructure.Experiments
-{
- public interface IContainerBuilder : IBuilder<IDependencyRegistry>
- {
- IExtendedRegistration<T> register<T>(Expression<Func<T>> func) where T : class;
- }
-}
\ No newline at end of file
trunk/product/Gorilla.Commons.Infrastructure.ThirdParty/Experiments/IExtendedRegistration.cs
@@ -1,17 +0,0 @@
-using Gorilla.Commons.Infrastructure.Castle.DynamicProxy;
-using Gorilla.Commons.Utility.Core;
-
-namespace Gorilla.Commons.Infrastructure.Experiments
-{
- public interface IExtendedRegistration
- {
- string pretty_print { get; }
- }
-
- public interface IExtendedRegistration<T> : IExtendedRegistration where T : class
- {
- IExtendedRegistration<T> as_singleton();
- IExtendedRegistration<T> with_expiry(string date_time);
- IExtendedRegistration<T> with_proxy(IConfiguration<IProxyBuilder<T>> configuration);
- }
-}
\ No newline at end of file
trunk/product/Gorilla.Commons.Infrastructure.ThirdParty/Experiments/IResolver.cs
@@ -1,9 +0,0 @@
-using System;
-
-namespace Gorilla.Commons.Infrastructure.Experiments
-{
- public interface IResolver<T>
- {
- Func<T> build { get; }
- }
-}
\ No newline at end of file
trunk/product/Gorilla.Commons.Infrastructure.ThirdParty/Experiments/ObjectUsageHasExpiredException.cs
@@ -1,16 +0,0 @@
-using System;
-
-namespace Gorilla.Commons.Infrastructure.Experiments
-{
- internal class ObjectUsageHasExpiredException : Exception
- {
- public ObjectUsageHasExpiredException(Type type, string date_time) : base(build_message(type, date_time))
- {
- }
-
- static string build_message(Type type, string date_time)
- {
- return string.Format("Cannot use {0} after {1}.", type.Name, date_time);
- }
- }
-}
\ No newline at end of file
trunk/product/Gorilla.Commons.Infrastructure.ThirdParty/Experiments/SimpleContainerBuilder.cs
@@ -1,31 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq.Expressions;
-using Gorilla.Commons.Infrastructure.Container;
-
-namespace Gorilla.Commons.Infrastructure.Experiments
-{
- public class SimpleContainerBuilder : IContainerBuilder
- {
- readonly IDictionary<Type, IExtendedRegistration> registries = new Dictionary<Type, IExtendedRegistration>();
-
- public IDependencyRegistry build()
- {
- return new SimpleRegistry(registries);
- }
-
- public IExtendedRegistration<T> register<T>(Expression<Func<T>> func) where T : class
- {
- try
- {
- var registration = new ExtendedRegistration<T>(func);
- registries.Add(typeof (T), registration);
- return registration;
- }
- catch (ArgumentException e)
- {
- throw new TypeAlreadyRegisteredInContainerException(typeof (T), registries[typeof (T)].pretty_print);
- }
- }
- }
-}
\ No newline at end of file
trunk/product/Gorilla.Commons.Infrastructure.ThirdParty/Experiments/SimpleRegistry.cs
@@ -1,34 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Gorilla.Commons.Infrastructure.Container;
-using Gorilla.Commons.Utility.Extensions;
-
-namespace Gorilla.Commons.Infrastructure.Experiments
-{
- public class SimpleRegistry : IDependencyRegistry
- {
- readonly IDictionary<Type, IList<IExtendedRegistration>> registrations;
-
- public SimpleRegistry(IDictionary<Type, IList<IExtendedRegistration>> registrations)
- {
- this.registrations = registrations;
- }
-
- public Interface get_a<Interface>()
- {
- return registrations[typeof (Interface)].First().downcast_to<IResolver<Interface>>().build();
- }
-
- public IEnumerable<Interface> all_the<Interface>()
- {
- foreach (var registration in registrations[typeof(Interface)])
- {
- yield return registration.downcast_to<IResolver<Interface>>().build()
-
-
- }
- yield return registrations[typeof(Interface)].each(x => x.downcast_to<IResolver<Interface>>().build());
- }
- }
-}
\ No newline at end of file
trunk/product/Gorilla.Commons.Infrastructure.ThirdParty/Experiments/TypeAlreadyRegisteredInContainerException.cs
@@ -1,18 +0,0 @@
-using System;
-
-namespace Gorilla.Commons.Infrastructure.Experiments
-{
- public class TypeAlreadyRegisteredInContainerException : Exception
- {
- public TypeAlreadyRegisteredInContainerException(Type typeNotFound, string registration)
- : base(build_message(typeNotFound, registration))
- {
- }
-
- static string build_message(Type typeNotFound, string registration)
- {
- return string.Format("The type {0} has already been registered with {1} in the container",
- typeNotFound.FullName, registration);
- }
- }
-}
\ No newline at end of file
trunk/product/Gorilla.Commons.Infrastructure.ThirdParty/Gorilla.Commons.Infrastructure.ThirdParty.csproj
@@ -131,15 +131,6 @@
<Compile Include="Castle\Windsor\WindsorContainerFactory.cs" />
<Compile Include="Castle\Windsor\WindsorDependencyRegistry.cs" />
<Compile Include="Castle\Windsor\WindsorDependencyRegistrySpecs.cs" />
- <Compile Include="Experiments\Autofac\AutofacContainerBuilder.cs" />
- <Compile Include="Experiments\ExtendedRegistration.cs" />
- <Compile Include="Experiments\IContainerBuilder.cs" />
- <Compile Include="Experiments\IExtendedRegistration.cs" />
- <Compile Include="Experiments\IResolver.cs" />
- <Compile Include="Experiments\ObjectUsageHasExpiredException.cs" />
- <Compile Include="Experiments\SimpleContainerBuilder.cs" />
- <Compile Include="Experiments\SimpleRegistry.cs" />
- <Compile Include="Experiments\TypeAlreadyRegisteredInContainerException.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Gorilla.Commons.Infrastructure\Gorilla.Commons.Infrastructure.csproj">
trunk/product/Gorilla.Commons.Utility/Core/NotSpecification.cs
@@ -0,0 +1,17 @@
+namespace Gorilla.Commons.Utility.Core
+{
+ public class NotSpecification<T> : ISpecification<T>
+ {
+ readonly ISpecification<T> item_to_match;
+
+ public NotSpecification(ISpecification<T> item_to_match)
+ {
+ this.item_to_match = item_to_match;
+ }
+
+ public bool is_satisfied_by(T item)
+ {
+ return !item_to_match.is_satisfied_by(item);
+ }
+ }
+}
\ No newline at end of file
trunk/product/Gorilla.Commons.Utility/Core/NotSpecificationSpecs.cs
@@ -0,0 +1,43 @@
+using developwithpassion.bdd.contexts;
+using Gorilla.Commons.Testing;
+
+namespace Gorilla.Commons.Utility.Core
+{
+ public class NotSpecificationSpecs
+ {
+ }
+
+ public class when_checking_if_a_condition_is_not_met : concerns_for<ISpecification<int>, NotSpecification<int>>
+ {
+ static protected ISpecification<int> criteria;
+
+ context c = () => { criteria = the_dependency<ISpecification<int>>(); };
+
+ public override ISpecification<int> create_sut()
+ {
+ return new NotSpecification<int>(criteria);
+ }
+ }
+
+ public class when_a_condition_is_not_met : when_checking_if_a_condition_is_not_met
+ {
+ context c = () => when_the(criteria).is_told_to(x => x.is_satisfied_by(1)).it_will_return(false);
+
+ because b = () => { result = sut.is_satisfied_by(1); };
+
+ it should_return_true = () => result.should_be_true();
+
+ static bool result;
+ }
+
+ public class when_a_condition_is_met : when_checking_if_a_condition_is_not_met
+ {
+ context c = () => when_the(criteria).is_told_to(x => x.is_satisfied_by(1)).it_will_return(true);
+
+ because b = () => { result = sut.is_satisfied_by(1); };
+
+ it should_return_false = () => result.should_be_false();
+
+ static bool result;
+ }
+}
\ No newline at end of file
trunk/product/Gorilla.Commons.Utility/Extensions/EnumerableExtensions.cs
@@ -4,43 +4,36 @@ using System.Linq;
namespace Gorilla.Commons.Utility.Extensions
{
- public static class EnumerableExtensions
+ static public class EnumerableExtensions
{
- public static IEnumerable<T> where<T>(this IEnumerable<T> items, Func<T, bool> condition_is_met)
+ static public IEnumerable<T> where<T>(this IEnumerable<T> items, Func<T, bool> condition_is_met)
{
- return null == items ? new List<T>() : items.Where(condition_is_met);
+ return null == items ? Enumerable.Empty<T>() : items.Where(condition_is_met);
}
- public static IList<T> databind<T>(this IEnumerable<T> items_to_bind_to)
+ static public IList<T> databind<T>(this IEnumerable<T> items_to_bind_to)
{
- return items_to_bind_to.ToList();
+ return null == items_to_bind_to ? new List<T>() : items_to_bind_to.ToList();
}
- public static IEnumerable<T> that_satisfy<T>(this IEnumerable<T> items_to_peek_in_to,
- Predicate<T> criteria_to_satisfy)
- {
- foreach (var item in items_to_peek_in_to ?? new List<T>())
- if (item.satisfies(criteria_to_satisfy)) yield return item;
- }
-
- public static IEnumerable<T> sorted_using<T>(this IEnumerable<T> items_to_sort, IComparer<T> sorting_algorithm)
+ static public IEnumerable<T> sorted_using<T>(this IEnumerable<T> items_to_sort, IComparer<T> sorting_algorithm)
{
var sorted_items = new List<T>(items_to_sort);
sorted_items.Sort(sorting_algorithm);
return sorted_items;
}
- public static IEnumerable<T> all<T>(this IEnumerable<T> items)
+ static public IEnumerable<T> all<T>(this IEnumerable<T> items)
{
- foreach (var item in items ?? new List<T>()) yield return item;
+ foreach (var item in items ?? Enumerable.Empty<T>()) yield return item;
}
- public static void each<T>(this IEnumerable<T> items, Action<T> action)
+ static public void each<T>(this IEnumerable<T> items, Action<T> action)
{
- foreach (var item in items ?? new List<T>()) action(item);
+ foreach (var item in items ?? Enumerable.Empty<T>()) action(item);
}
- public static IEnumerable<T> join_with<T>(this IEnumerable<T> left, IEnumerable<T> right)
+ static public IEnumerable<T> join_with<T>(this IEnumerable<T> left, IEnumerable<T> right)
{
if (null == right) return left;
trunk/product/Gorilla.Commons.Utility/Extensions/SpecificationExtensions.cs
@@ -1,10 +1,18 @@
using System;
+using System.Collections.Generic;
using Gorilla.Commons.Utility.Core;
namespace Gorilla.Commons.Utility.Extensions
{
static public class SpecificationExtensions
{
+ static public IEnumerable<T> that_satisfy<T>(this IEnumerable<T> items_to_peek_in_to,
+ Predicate<T> criteria_to_satisfy)
+ {
+ foreach (var item in items_to_peek_in_to ?? new List<T>())
+ if (item.satisfies(criteria_to_satisfy)) yield return item;
+ }
+
static public bool satisfies<T>(this T item_to_interrogate, Predicate<T> criteria_to_satisfy)
{
return criteria_to_satisfy(item_to_interrogate);
@@ -24,5 +32,10 @@ namespace Gorilla.Commons.Utility.Extensions
{
return new OrSpecification<T>(left, right);
}
+
+ static public ISpecification<T> not<T>(this ISpecification<T> original)
+ {
+ return new NotSpecification<T>(original);
+ }
}
}
\ No newline at end of file
trunk/product/Gorilla.Commons.Utility/Gorilla.Commons.Utility.csproj
@@ -89,6 +89,8 @@
<Compile Include="Core\IVisitable.cs" />
<Compile Include="Core\IVisitor.cs" />
<Compile Include="Core\Mapper.cs" />
+ <Compile Include="Core\NotSpecification.cs" />
+ <Compile Include="Core\NotSpecificationSpecs.cs" />
<Compile Include="Core\OrSpecification.cs" />
<Compile Include="Core\OrSpecificationSpecs.cs" />
<Compile Include="Core\PredicateSpecification.cs" />
trunk/product/MoMoney.Service/Infrastructure/Security/IsInRole.cs
@@ -0,0 +1,20 @@
+using System.Security.Principal;
+using Gorilla.Commons.Utility.Core;
+
+namespace MoMoney.Service.Infrastructure.Security
+{
+ public class IsInRole : ISpecification<IPrincipal>
+ {
+ readonly Role role;
+
+ public IsInRole(Role role)
+ {
+ this.role = role;
+ }
+
+ public bool is_satisfied_by(IPrincipal item)
+ {
+ return item.IsInRole(role);
+ }
+ }
+}
\ No newline at end of file
trunk/product/MoMoney.Service/Infrastructure/Security/IsInRoleSpecs.cs
@@ -0,0 +1,56 @@
+using System.Security.Principal;
+using developwithpassion.bdd.contexts;
+using Gorilla.Commons.Testing;
+using Gorilla.Commons.Utility.Core;
+using MoMoney.Service.Infrastructure.Security;
+
+public class IsInRoleSpecs
+{
+}
+
+public class when_checking_if_a_principal_belongs_to_a_role :
+ concerns_for<ISpecification<IPrincipal>, IsInRole>
+{
+ static protected readonly Role administrator_role = new Role("administrators");
+
+ public override ISpecification<IPrincipal> create_sut()
+ {
+ return new IsInRole(administrator_role);
+ }
+}
+
+public class when_not_in_one_of_the_roles : when_checking_if_a_principal_belongs_to_a_role
+{
+ context c = () =>
+ {
+ principal = the_dependency<IPrincipal>();
+ when_the(principal)
+ .is_told_to(x => x.IsInRole(administrator_role))
+ .it_will_return(false);
+ };
+
+ because b = () => { result = sut.is_satisfied_by(principal); };
+
+ it should_return_false = () => result.should_be_false();
+
+ static bool result;
+ static IPrincipal principal;
+}
+
+public class when_in_one_of_the_roles : when_checking_if_a_principal_belongs_to_a_role
+{
+ context c = () =>
+ {
+ principal = the_dependency<IPrincipal>();
+ when_the(principal)
+ .is_told_to(x => x.IsInRole(administrator_role))
+ .it_will_return(true);
+ };
+
+ because b = () => { result = sut.is_satisfied_by(principal); };
+
+ it should_return_true = () => result.should_be_true();
+
+ static bool result;
+ static IPrincipal principal;
+}
\ No newline at end of file
trunk/product/MoMoney.Service/Infrastructure/Security/Role.cs
@@ -0,0 +1,42 @@
+namespace MoMoney.Service.Infrastructure.Security
+{
+ public class Role
+ {
+ readonly string name;
+
+ public Role(string name)
+ {
+ this.name = name;
+ }
+
+ static public implicit operator string(Role role)
+ {
+ return role.name;
+ }
+
+ static public implicit operator Role(string role)
+ {
+ return new Role(role);
+ }
+
+ public bool Equals(Role other)
+ {
+ if (ReferenceEquals(null, other)) return false;
+ if (ReferenceEquals(this, other)) return true;
+ return Equals(other.name, name);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != typeof (Role)) return false;
+ return Equals((Role) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return (name != null ? name.GetHashCode() : 0);
+ }
+ }
+}
\ No newline at end of file
trunk/product/MoMoney.Service/MoMoney.Service.csproj
@@ -83,6 +83,9 @@
<Compile Include="Application\SaveNewBillCommand.cs" />
<Compile Include="Infrastructure\Logging\LogFileTasks.cs" />
<Compile Include="Infrastructure\ProjectTasks.cs" />
+ <Compile Include="Infrastructure\Security\IsInRole.cs" />
+ <Compile Include="Infrastructure\Security\IsInRoleSpecs.cs" />
+ <Compile Include="Infrastructure\Security\Role.cs" />
<Compile Include="Infrastructure\Updating\CancelUpdate.cs" />
<Compile Include="Infrastructure\Updating\CancelUpdateSpecs.cs" />
<Compile Include="Infrastructure\Updating\CurrentDeployment.cs" />
trunk/product/MyMoney/boot/container/registration/proxy_configuration/InterceptingFilter.cs
@@ -0,0 +1,24 @@
+using System.Security.Principal;
+using System.Threading;
+using Castle.Core.Interceptor;
+using Gorilla.Commons.Infrastructure.Logging;
+using Gorilla.Commons.Utility.Core;
+
+namespace MoMoney.boot.container.registration.proxy_configuration
+{
+ public class InterceptingFilter : IInterceptor
+ {
+ readonly ISpecification<IPrincipal> filter;
+
+ public InterceptingFilter(ISpecification<IPrincipal> filter)
+ {
+ this.filter = filter;
+ }
+
+ public void Intercept(IInvocation invocation)
+ {
+ if (filter.is_satisfied_by(Thread.CurrentPrincipal)) invocation.Proceed();
+ else this.log().debug("call to {0} was blocked");
+ }
+ }
+}
\ No newline at end of file
trunk/product/MyMoney/boot/container/registration/proxy_configuration/InterceptingFilterSpecs.cs
@@ -0,0 +1,57 @@
+using System.Security.Principal;
+using System.Threading;
+using Castle.Core.Interceptor;
+using developwithpassion.bdd.contexts;
+using Gorilla.Commons.Testing;
+using Gorilla.Commons.Utility.Core;
+
+namespace MoMoney.boot.container.registration.proxy_configuration
+{
+ public class InterceptingFilterSpecs
+ {
+ }
+
+ public class when_attempting_to_perform_an_action_that_requires_authentication :
+ concerns_for< InterceptingFilter>
+ {
+ context c = () => { filter = the_dependency<ISpecification<IPrincipal>>(); };
+
+ static protected ISpecification<IPrincipal> filter;
+ }
+
+ public class when_logged_in_as_a_user_that_belongs_to_the_proper_role :
+ when_attempting_to_perform_an_action_that_requires_authentication
+ {
+ context c = () =>
+ {
+ invocation = an<IInvocation>();
+ when_the(filter)
+ .is_told_to(x => x.is_satisfied_by(Thread.CurrentPrincipal))
+ .it_will_return(true);
+ };
+
+ because b = () => sut.Intercept(invocation);
+
+ it should_proceed_with_request = () => invocation.was_told_to(x => x.Proceed());
+
+ static IInvocation invocation;
+ }
+
+ public class when_not_logged_in_as_a_user_that_belongs_to_the_proper_role :
+ when_attempting_to_perform_an_action_that_requires_authentication
+ {
+ context c = () =>
+ {
+ invocation = an<IInvocation>();
+ when_the(filter)
+ .is_told_to(x => x.is_satisfied_by(Thread.CurrentPrincipal))
+ .it_will_return(false);
+ };
+
+ because b = () => sut.Intercept(invocation);
+
+ it should_not_proceed_with_request = () => invocation.was_not_told_to(x => x.Proceed());
+
+ static IInvocation invocation;
+ }
+}
\ No newline at end of file
trunk/product/MyMoney/boot/container/registration/proxy_configuration/ServiceLayerConfiguration.cs
@@ -2,6 +2,8 @@ using Gorilla.Commons.Infrastructure;
using Gorilla.Commons.Infrastructure.Castle.DynamicProxy;
using Gorilla.Commons.Infrastructure.Castle.DynamicProxy.Interceptors;
using Gorilla.Commons.Utility.Core;
+using Gorilla.Commons.Utility.Extensions;
+using MoMoney.Service.Infrastructure.Security;
namespace MoMoney.boot.container.registration.proxy_configuration
{
@@ -10,6 +12,10 @@ namespace MoMoney.boot.container.registration.proxy_configuration
public void configure(IProxyBuilder<T> item)
{
item.add_interceptor(Lazy.load<IUnitOfWorkInterceptor>()).intercept_all();
+ item.add_interceptor(
+ new InterceptingFilter(new IsInRole("Users")
+ .and(new IsInRole("Administrators"))))
+ .intercept_all();
}
}
}
\ No newline at end of file
trunk/product/MyMoney/MyMoney.csproj
@@ -188,6 +188,8 @@
<Compile Include="boot\container\registration\mapping\PropertyResolver.cs" />
<Compile Include="boot\container\registration\mapping\TargetActionFactory.cs" />
<Compile Include="boot\container\registration\proxy_configuration\NoConfiguration.cs" />
+ <Compile Include="boot\container\registration\proxy_configuration\InterceptingFilter.cs" />
+ <Compile Include="boot\container\registration\proxy_configuration\InterceptingFilterSpecs.cs" />
<Compile Include="boot\container\registration\proxy_configuration\ServiceLayerConfiguration.cs" />
<Compile Include="boot\container\registration\proxy_configuration\SynchronizedConfiguration.cs" />
<Compile Include="boot\container\registration\wire_up_the_infrastructure_in_to_the.cs" />