diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..4964ad7 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,133 @@ +root = true + +# All files +[*] +indent_style = tab +indent_size = 4 +csharp_indent_labels = one_less_than_current +csharp_using_directive_placement = outside_namespace:silent +csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_braces = true:silent +csharp_style_namespace_declarations = block_scoped:silent +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +csharp_space_around_binary_operators = before_and_after +csharp_style_throw_expression = true:suggestion +csharp_style_prefer_null_check_over_type_check = true:suggestion +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_prefer_local_over_anonymous_function = true:suggestion +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_range_operator = true:suggestion +csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion +csharp_style_prefer_tuple_swap = true:suggestion +csharp_style_prefer_utf8_string_literals = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_unused_value_assignment_preference = discard_variable:none +csharp_style_unused_value_expression_statement_preference = discard_variable:none +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent +csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent +csharp_style_prefer_readonly_struct = true:suggestion +csharp_prefer_static_local_function = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent +csharp_style_prefer_switch_expression = true:suggestion +csharp_style_prefer_pattern_matching = true:silent +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion +csharp_style_var_for_built_in_types = false:suggestion +csharp_style_var_when_type_is_apparent = false:suggestion +csharp_style_var_elsewhere = false:suggestion + + +[*.{cs,vb}] +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case +dotnet_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 4 +end_of_line = crlf +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +insert_final_newline = true +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_namespace_match_folder = true:suggestion +dotnet_style_readonly_field = true:suggestion +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent +dotnet_style_allow_multiple_blank_lines_experimental = true:silent +dotnet_code_quality_unused_parameters = all:suggestion +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_property = false:silent +dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_event = false:silent diff --git a/Aleph1.ClientFile.Models/Aleph1.ClientFile.Models.csproj b/Aleph1.ClientFile.Models/Aleph1.ClientFile.Models.csproj index 7c6e836..6ab4f34 100644 --- a/Aleph1.ClientFile.Models/Aleph1.ClientFile.Models.csproj +++ b/Aleph1.ClientFile.Models/Aleph1.ClientFile.Models.csproj @@ -1,25 +1,27 @@  - - net20;netstandard1.0 - 1.0.3 - Avraham Essoudry - Aleph1 ClientFile - Aleph1.png - MIT - https://github.com/avrahamcool/Aleph1 - Aleph1 - false - git - Copyright Aleph1 © 2019 - https://github.com/avrahamcool/Aleph1.git - ClientFile Model for easy file uploading via JSON POST directly from the client - Full - bin\$(Configuration)\$(TargetFramework)\Aleph1.ClientFile.Models.xml - fixed compiler warnings + embedded PackageIcon - + + net48 + 4.8.0 + 4.8.0.0 + 4.8.0.0 + Avraham Essoudry + Aleph1 ClientFile + Aleph1.png + MIT + https://github.com/avrahamcool/Aleph1 + Aleph1 + false + git + Copyright Aleph1 © 2019 + https://github.com/avrahamcool/Aleph1.git + ClientFile Model for easy file uploading via JSON POST directly from the client + Full + bin\$(Configuration)\$(TargetFramework)\Aleph1.ClientFile.Models.xml + fixed compiler warnings + embedded PackageIcon + - - - + + + diff --git a/Aleph1.ClientFile.Models/ClientFile.cs b/Aleph1.ClientFile.Models/ClientFile.cs index 46e8a92..e666ea2 100644 --- a/Aleph1.ClientFile.Models/ClientFile.cs +++ b/Aleph1.ClientFile.Models/ClientFile.cs @@ -1,24 +1,22 @@ namespace Aleph1.ClientFile.Models { - /// a file uploaded from an HTTP client using JSON - /// https://developer.mozilla.org/en-US/docs/Web/API/File - public class ClientFile - { - /// the name of the file - public string Name { get; set; } + /// a file uploaded from an HTTP client using JSON + /// https://developer.mozilla.org/en-US/docs/Web/API/File + public class ClientFile + { + /// the name of the file + public string Name { get; set; } - /// the last modified time of the file, in millisecond since the UNIX epoch (January 1st, 1970 at Midnight). - public long LastModified { get; set; } + /// the last modified time of the file, in millisecond since the UNIX epoch (January 1st, 1970 at Midnight). + public long LastModified { get; set; } - /// the size of the file in bytes. - public long Size { get; set; } + /// the size of the file in bytes. + public long Size { get; set; } - /// the MIME type of the file. - public string Type { get; set; } + /// the MIME type of the file. + public string Type { get; set; } - - /// the file itself. - [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "DTO")] - public byte[] Content { get; set; } - } + /// the file itself. + public byte[] Content { get; set; } + } } diff --git a/Aleph1.DI.Contracts/Aleph1.DI.Contracts.csproj b/Aleph1.DI.Contracts/Aleph1.DI.Contracts.csproj index bf0e87a..efe1aeb 100644 --- a/Aleph1.DI.Contracts/Aleph1.DI.Contracts.csproj +++ b/Aleph1.DI.Contracts/Aleph1.DI.Contracts.csproj @@ -1,29 +1,38 @@  - - net40;net45;net471 - 4.1.1 - Avraham Essoudry - Aleph1 DI - MIT - https://github.com/avrahamcool/Aleph1 - Aleph1 - false - git - Copyright Aleph1 © 2018 - https://github.com/avrahamcool/Aleph1.git - Provides the necessary code to register components into the DI container - Full - bin\$(Configuration)\$(TargetFramework)\Aleph1.DI.Contracts.xml - better fix for dynamic loading - Aleph1.png - + + net48 + 4.8.0 + 4.8.0.0 + 4.8.0.0 + Avraham Essoudry + Aleph1 DI + MIT + https://github.com/avrahamcool/Aleph1 + Aleph1 + false + git + Copyright Aleph1 © 2018 + https://github.com/avrahamcool/Aleph1.git + Provides the necessary code to register components into the DI container + Full + bin\$(Configuration)\$(TargetFramework)\Aleph1.DI.Contracts.xml + better fix for dynamic loading + Aleph1.png + true + - - - + + + - - - + + + + + + + <_Parameter1>true + + diff --git a/Aleph1.DI.Contracts/IModule.cs b/Aleph1.DI.Contracts/IModule.cs index 89a53d7..5d3734a 100644 --- a/Aleph1.DI.Contracts/IModule.cs +++ b/Aleph1.DI.Contracts/IModule.cs @@ -1,10 +1,10 @@ namespace Aleph1.DI.Contracts { - /// To register all the internal type with the DI container. - public interface IModule - { - /// register all the internal types that are known to this DLL into the DI container - /// the DI container registrar - void Initialize(IModuleRegistrar registrar); - } + /// To register all the internal type with the DI container. + public interface IModule + { + /// register all the internal types that are known to this DLL into the DI container + /// the DI container registrar + void Initialize(IModuleRegistrar registrar); + } } diff --git a/Aleph1.DI.Contracts/IModuleRegistrar.cs b/Aleph1.DI.Contracts/IModuleRegistrar.cs index 4fd09b6..bca3fe2 100644 --- a/Aleph1.DI.Contracts/IModuleRegistrar.cs +++ b/Aleph1.DI.Contracts/IModuleRegistrar.cs @@ -1,25 +1,25 @@ namespace Aleph1.DI.Contracts { - /// Allows objects implementing IModule to register types to the DI container. - public interface IModuleRegistrar - { - /// register a transient type mapping between a concrete type to an Interface - /// Interface - /// concrete type implementation - /// name to use for Named Registration, use null for default - void RegisterType(string name = null) where TTo : TFrom; + /// Allows objects implementing IModule to register types to the DI container. + public interface IModuleRegistrar + { + /// register a transient type mapping between a concrete type to an Interface + /// Interface + /// concrete type implementation + /// name to use for Named Registration, use null for default + void RegisterType(string name = null) where TTo : TFrom; - /// register a singleton type mapping between a concrete type to a Interface - /// Interface - /// concrete type implementation - /// name to use for Named Registration, use null for default - void RegisterTypeAsSingelton(string name = null) where TTo : TFrom; + /// register a singleton type mapping between a concrete type to a Interface + /// Interface + /// concrete type implementation + /// name to use for Named Registration, use null for default + void RegisterTypeAsSingelton(string name = null) where TTo : TFrom; - /// register a singleton type mapping between a concrete instance to a Interface - /// Interface - /// concrete instance implementation - /// concrete instance implementation - /// name to use for Named Registration, use null for default - void RegisterTypeAsSingelton(TTo instance, string name = null) where TTo : TFrom; - } + /// register a singleton type mapping between a concrete instance to a Interface + /// Interface + /// concrete instance implementation + /// concrete instance implementation + /// name to use for Named Registration, use null for default + void RegisterTypeAsSingelton(TTo instance, string name = null) where TTo : TFrom; + } } diff --git a/Aleph1.DI.Contracts/ModuleLoader.cs b/Aleph1.DI.Contracts/ModuleLoader.cs index 95e131b..b7728d6 100644 --- a/Aleph1.DI.Contracts/ModuleLoader.cs +++ b/Aleph1.DI.Contracts/ModuleLoader.cs @@ -7,53 +7,53 @@ namespace Aleph1.DI.Contracts { - /// Handles loading from DLL's into the - public static class ModuleLoader - { - /// uses MEF to load all the IModule implementations to the Registrar - /// IModuleRegistrar - /// path to the root directory of the project - /// relative path to the modules directory - /// names the DLLs to load - public static void LoadModulesFromAssemblies(IModuleRegistrar registrar, string rootPath, string modulesDir, string[] assemblies) - { - Uri baseUri = new Uri(rootPath); + /// Handles loading from DLL's into the + public static class ModuleLoader + { + /// uses MEF to load all the IModule implementations to the Registrar + /// IModuleRegistrar + /// path to the root directory of the project + /// relative path to the modules directory + /// names the DLLs to load + public static void LoadModulesFromAssemblies(IModuleRegistrar registrar, string rootPath, string modulesDir, string[] assemblies) + { + Uri baseUri = new Uri(rootPath); - AppDomain.CurrentDomain.AssemblyResolve += (object sender, ResolveEventArgs args) => - { - string assemblyPartialName = args.Name.Substring(0, args.Name.IndexOf(',')) + ".dll"; - string assemblyPartialPath = Path.Combine(modulesDir, assemblyPartialName); - string assemblyFullPath = new Uri(baseUri, assemblyPartialPath).LocalPath; + AppDomain.CurrentDomain.AssemblyResolve += (object sender, ResolveEventArgs args) => + { + string assemblyPartialName = args.Name.Substring(0, args.Name.IndexOf(',')) + ".dll"; + string assemblyPartialPath = Path.Combine(modulesDir, assemblyPartialName); + string assemblyFullPath = new Uri(baseUri, assemblyPartialPath).LocalPath; - return File.Exists(assemblyFullPath) ? Assembly.LoadFile(assemblyFullPath) : null; - }; + return File.Exists(assemblyFullPath) ? Assembly.LoadFile(assemblyFullPath) : null; + }; - List assembliesPath = assemblies - .Select(assName => Path.Combine(modulesDir, assName)) - .Select(assPath => new Uri(baseUri, assPath).LocalPath).ToList(); - string badPath = assembliesPath.FirstOrDefault(ap => !File.Exists(ap)); - if (badPath != null) - { - throw new Exception($"Could not load {badPath}. Current EXE Dir: {rootPath}. Current BaseUri {baseUri}"); - } + List assembliesPath = assemblies + .Select(assName => Path.Combine(modulesDir, assName)) + .Select(assPath => new Uri(baseUri, assPath).LocalPath).ToList(); + string badPath = assembliesPath.FirstOrDefault(ap => !File.Exists(ap)); + if (badPath != null) + { + throw new Exception($"Could not load {badPath}. Current EXE Dir: {rootPath}. Current BaseUri {baseUri}"); + } - try - { - //Creating a single catalog from all the DLL's - using (AggregateCatalog catalog = new AggregateCatalog(assembliesPath.Select(ap => new AssemblyCatalog(ap)))) - using (CompositionContainer compositionContainer = new CompositionContainer(catalog)) - { - //Get all the modules and register them - foreach (IModule module in compositionContainer.GetExports().Select(e => e.Value)) - { - module.Initialize(registrar); - } - } - } - catch (ReflectionTypeLoadException rtle) - { - throw new Exception(string.Join(Environment.NewLine, rtle.LoaderExceptions.Select(e => e.ToString()))); - } - } - } + try + { + //Creating a single catalog from all the DLL's + using (AggregateCatalog catalog = new AggregateCatalog(assembliesPath.Select(ap => new AssemblyCatalog(ap)))) + using (CompositionContainer compositionContainer = new CompositionContainer(catalog)) + { + //Get all the modules and register them + foreach (IModule module in compositionContainer.GetExports().Select(e => e.Value)) + { + module.Initialize(registrar); + } + } + } + catch (ReflectionTypeLoadException rtle) + { + throw new Exception(string.Join(Environment.NewLine, rtle.LoaderExceptions.Select(e => e.ToString()))); + } + } + } } diff --git a/Aleph1.DI.CustomConfigurationSection/Aleph1.DI.CustomConfigurationSection.csproj b/Aleph1.DI.CustomConfigurationSection/Aleph1.DI.CustomConfigurationSection.csproj index 27058d9..fb844d7 100644 --- a/Aleph1.DI.CustomConfigurationSection/Aleph1.DI.CustomConfigurationSection.csproj +++ b/Aleph1.DI.CustomConfigurationSection/Aleph1.DI.CustomConfigurationSection.csproj @@ -1,30 +1,38 @@  - - net45;net471 - 4.0.0 - Avraham Essoudry - Aleph1 DI - Aleph1.png - MIT - https://github.com/avrahamcool/Aleph1 - Aleph1 - false - git - Copyright Aleph1 © 2018 - https://github.com/avrahamcool/Aleph1.git - Custom Configuration Section to facilitate Aleph1.DI config - Full - bin\$(Configuration)\$(TargetFramework)\Aleph1.DI.CustomConfigurationSection.xml - embedded PackageIcon - + + net48 + 4.8.0 + 4.8.0.0 + 4.8.00 + Avraham Essoudry + Aleph1 DI + Aleph1.png + MIT + https://github.com/avrahamcool/Aleph1 + Aleph1 + false + git + Copyright Aleph1 © 2018 + https://github.com/avrahamcool/Aleph1.git + Custom Configuration Section to facilitate Aleph1.DI config + Full + bin\$(Configuration)\$(TargetFramework)\Aleph1.DI.CustomConfigurationSection.xml + embedded PackageIcon + true + - - - + + + - - - - + + + + + + + <_Parameter1>true + + diff --git a/Aleph1.DI.CustomConfigurationSection/ModulesSection.cs b/Aleph1.DI.CustomConfigurationSection/ModulesSection.cs index af56953..f1d02a8 100644 --- a/Aleph1.DI.CustomConfigurationSection/ModulesSection.cs +++ b/Aleph1.DI.CustomConfigurationSection/ModulesSection.cs @@ -3,86 +3,86 @@ namespace Aleph1.DI.CustomConfigurationSection { - /// Custom Config Section for loading modules by the DI - /// - public class ModulesSection : ConfigurationSection - { - /// path to the modules directory - [ConfigurationProperty("base")] - public BaseElement Base - { - get => (BaseElement)(base["base"]); - set => base["base"] = value; - } + /// Custom Configuration Section for loading modules by the DI + /// + public class ModulesSection : ConfigurationSection + { + /// path to the modules directory + [ConfigurationProperty("base")] + public BaseElement Base + { + get => (BaseElement)base["base"]; + set => base["base"] = value; + } - /// collection of modules elements - [ConfigurationProperty("modules")] - public ModuleElementCollection Modules - { - get => (ModuleElementCollection)(base["modules"]); - set => base["modules"] = value; - } - } + /// collection of modules elements + [ConfigurationProperty("modules")] + public ModuleElementCollection Modules + { + get => (ModuleElementCollection)base["modules"]; + set => base["modules"] = value; + } + } - /// collection of modules elements - /// - [ConfigurationCollection(typeof(ModuleElement))] - public class ModuleElementCollection : ConfigurationElementCollection - { - /// Gets the type of the . - public override ConfigurationElementCollectionType CollectionType => ConfigurationElementCollectionType.BasicMapAlternate; + /// collection of modules elements + /// + [ConfigurationCollection(typeof(ModuleElement))] + public class ModuleElementCollection : ConfigurationElementCollection + { + /// Gets the type of the . + public override ConfigurationElementCollectionType CollectionType => ConfigurationElementCollectionType.BasicMapAlternate; - /// Gets the name used to identify this collection of elements in the configuration file when overridden in a derived class. - protected override string ElementName => "module"; + /// Gets the name used to identify this collection of elements in the configuration file when overridden in a derived class. + protected override string ElementName => "module"; - /// Indicates whether the specified exists in the . - /// The name of the element to verify. - protected override bool IsElementName(string elementName) - { - return elementName.Equals("module", StringComparison.InvariantCultureIgnoreCase); - } + /// Indicates whether the specified exists in the . + /// The name of the element to verify. + protected override bool IsElementName(string elementName) + { + return elementName.Equals("module", StringComparison.InvariantCultureIgnoreCase); + } - /// Indicates whether the object is read only. - public override bool IsReadOnly() - { - return false; - } + /// Indicates whether the object is read only. + public override bool IsReadOnly() + { + return false; + } - /// When overridden in a derived class, creates a new . - protected override ConfigurationElement CreateNewElement() - { - return new ModuleElement(); - } + /// When overridden in a derived class, creates a new . + protected override ConfigurationElement CreateNewElement() + { + return new ModuleElement(); + } - /// Gets the element key for a specified configuration element when overridden in a derived class. - /// The to return the key for. - /// An that acts as the key for the specified . - protected override object GetElementKey(ConfigurationElement element) - { - return ((ModuleElement)element).Path; - } + /// Gets the element key for a specified configuration element when overridden in a derived class. + /// The to return the key for. + /// An that acts as the key for the specified . + protected override object GetElementKey(ConfigurationElement element) + { + return ((ModuleElement)element).Path; + } - /// Gets the with the specified index. - /// The . - /// The index. - public ModuleElement this[int idx] => (ModuleElement)BaseGet(idx); - } + /// Gets the with the specified index. + /// The . + /// The index. + public ModuleElement this[int idx] => (ModuleElement)BaseGet(idx); + } - /// a single Module to load - /// - public class ModuleElement : ConfigurationElement - { - /// Gets the path to the module - [ConfigurationProperty("path", IsRequired = true, IsKey = true)] - public string Path => (string)base["path"]; - } + /// a single Module to load + /// + public class ModuleElement : ConfigurationElement + { + /// Gets the path to the module + [ConfigurationProperty("path", IsRequired = true, IsKey = true)] + public string Path => (string)base["path"]; + } - /// path to the modules directory - /// - public class BaseElement : ConfigurationElement - { - /// path to the modules directory - [ConfigurationProperty("path", IsRequired = true, IsKey = true)] - public string Path => (string)base["path"]; - } + /// path to the modules directory + /// + public class BaseElement : ConfigurationElement + { + /// path to the modules directory + [ConfigurationProperty("path", IsRequired = true, IsKey = true)] + public string Path => (string)base["path"]; + } } diff --git a/Aleph1.DI.UnityImplementation/Aleph1.DI.UnityImplementation.csproj b/Aleph1.DI.UnityImplementation/Aleph1.DI.UnityImplementation.csproj index e562c81..27b9bf9 100644 --- a/Aleph1.DI.UnityImplementation/Aleph1.DI.UnityImplementation.csproj +++ b/Aleph1.DI.UnityImplementation/Aleph1.DI.UnityImplementation.csproj @@ -1,34 +1,42 @@  - - net45;net471 - 3.4.0 - Avraham Essoudry - Aleph1 DI - Aleph1.png - MIT - https://github.com/avrahamcool/Aleph1 - Aleph1 - false - git - Copyright Aleph1 © 2018 - https://github.com/avrahamcool/Aleph1.git - Concrete Implementation of Aleph1.DI using Unity - Full - bin\$(Configuration)\$(TargetFramework)\Aleph1.DI.UnityImplementation.xml - added instance registration - + + net48 + 4.8.0 + 4.8.0.0 + 4.8.0.0 + Avraham Essoudry + Aleph1 DI + Aleph1.png + MIT + https://github.com/avrahamcool/Aleph1 + Aleph1 + false + git + Copyright Aleph1 © 2018 + https://github.com/avrahamcool/Aleph1.git + Concrete Implementation of Aleph1.DI using Unity + Full + bin\$(Configuration)\$(TargetFramework)\Aleph1.DI.UnityImplementation.xml + added instance registration + true + - - - + + + - - - + + + - - - - + + + + + + + <_Parameter1>true + + diff --git a/Aleph1.DI.UnityImplementation/UnityModuleRegistrar.cs b/Aleph1.DI.UnityImplementation/UnityModuleRegistrar.cs index cbf3a04..1cb0f8c 100644 --- a/Aleph1.DI.UnityImplementation/UnityModuleRegistrar.cs +++ b/Aleph1.DI.UnityImplementation/UnityModuleRegistrar.cs @@ -5,65 +5,65 @@ namespace Aleph1.DI.UnityImplementation { - /// concrete implementation of the using Unity - /// - public class UnityModuleRegistrar : IModuleRegistrar - { - private readonly IUnityContainer _container; - /// Initializes a new instance of the class. - /// The Unity container. - public UnityModuleRegistrar(IUnityContainer container) - { - _container = container; - } + /// concrete implementation of the using Unity + /// + public class UnityModuleRegistrar : IModuleRegistrar + { + private readonly IUnityContainer _container; + /// Initializes a new instance of the class. + /// The Unity container. + public UnityModuleRegistrar(IUnityContainer container) + { + _container = container; + } - /// register a transient type mapping between a concrete type to an Interface - /// Interface - /// concrete type implementation - /// name to use for Named Registration, use null for default - public void RegisterType(string name = null) where TTo : TFrom - { - if(name == null) - { - _container.RegisterType(); - } - else - { - _container.RegisterType(name); - } - } + /// register a transient type mapping between a concrete type to an Interface + /// Interface + /// concrete type implementation + /// name to use for Named Registration, use null for default + public void RegisterType(string name = null) where TTo : TFrom + { + if (name == null) + { + _container.RegisterType(); + } + else + { + _container.RegisterType(name); + } + } - /// register a singleton type mapping between a concrete type to a Interface - /// Interface - /// concrete type implementation - /// name to use for Named Registration, use null for default - public void RegisterTypeAsSingelton(string name = null) where TTo : TFrom - { - if (name == null) - { - _container.RegisterType(new ContainerControlledLifetimeManager()); - } - else - { - _container.RegisterType(name, new ContainerControlledLifetimeManager()); - } - } + /// register a singleton type mapping between a concrete type to a Interface + /// Interface + /// concrete type implementation + /// name to use for Named Registration, use null for default + public void RegisterTypeAsSingelton(string name = null) where TTo : TFrom + { + if (name == null) + { + _container.RegisterType(new ContainerControlledLifetimeManager()); + } + else + { + _container.RegisterType(name, new ContainerControlledLifetimeManager()); + } + } - /// register a singleton type mapping between a concrete instance to a Interface - /// Interface - /// concrete instance implementation - /// concrete instance implementation - /// name to use for Named Registration, use null for default - public void RegisterTypeAsSingelton(TTo instance, string name = null) where TTo : TFrom - { - if (name == null) - { - _container.RegisterInstance(instance, new ContainerControlledLifetimeManager()); - } - else - { - _container.RegisterInstance(name, instance, new ContainerControlledLifetimeManager()); - } - } - } + /// register a singleton type mapping between a concrete instance to a Interface + /// Interface + /// concrete instance implementation + /// concrete instance implementation + /// name to use for Named Registration, use null for default + public void RegisterTypeAsSingelton(TTo instance, string name = null) where TTo : TFrom + { + if (name == null) + { + _container.RegisterInstance(instance, new ContainerControlledLifetimeManager()); + } + else + { + _container.RegisterInstance(name, instance, new ContainerControlledLifetimeManager()); + } + } + } } diff --git a/Aleph1.Logging/Aleph1.Logging.csproj b/Aleph1.Logging/Aleph1.Logging.csproj index 133822e..dbf6b9b 100644 --- a/Aleph1.Logging/Aleph1.Logging.csproj +++ b/Aleph1.Logging/Aleph1.Logging.csproj @@ -1,42 +1,48 @@  - - net40;net45;net471 - 6.0.1 - Avraham Essoudry - Aleph1 Logging NLog PostSharp - Aleph1.png - MIT - https://github.com/avrahamcool/Aleph1 - Aleph1 - false - git - Copyright Aleph1 © 2018 - https://github.com/avrahamcool/Aleph1.git - Logging aspect using PostSharp - Full - bin\$(Configuration)\$(TargetFramework)\Aleph1.Logging.xml - moved to Json.Net, embedded icon - 6.0.1.0 - 6.0.1.0 - + + net48 + 6.8.0 + 6.8.0.0 + 6.8.0.0 + Avraham Essoudry + Aleph1 Logging NLog PostSharp + Aleph1.png + MIT + https://github.com/avrahamcool/Aleph1 + Aleph1 + false + git + Copyright Aleph1 © 2018 + https://github.com/avrahamcool/Aleph1.git + Logging aspect using PostSharp + Full + bin\$(Configuration)\$(TargetFramework)\Aleph1.Logging.xml + moved to Json.Net, embedded icon + true + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + + + + <_Parameter1>false + + diff --git a/Aleph1.Logging/LoggedAttribute.cs b/Aleph1.Logging/LoggedAttribute.cs index 3d84fee..46d0347 100644 --- a/Aleph1.Logging/LoggedAttribute.cs +++ b/Aleph1.Logging/LoggedAttribute.cs @@ -1,89 +1,96 @@ -using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +using Newtonsoft.Json; using NLog; using PostSharp.Aspects; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - namespace Aleph1.Logging { - /// Aspect to handle logging - [Serializable, AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true), LinesOfCodeAvoided(20)] - public sealed class LoggedAttribute : OnMethodBoundaryAspect - { - /// Default = true, set to False when you don't want the parameters of the function to be logged - public bool LogParameters { get; set; } = true; - - /// Default = false, set to true when you want the return value of the function to be logged - public bool LogReturnValue { get; set; } = false; - - [NonSerialized] - private ILogger logger; - - private string[] ParameterNames { get; set; } - private string ClassName { get; set; } - private string MethodName { get; set; } - - /// Initializing the fixed fields at compile time to improve performance - public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo) - { - ClassName = method.ReflectedType.Name; - MethodName = method.Name; - ParameterNames = method.GetParameters().Select(pi => pi.Name).ToArray(); - } - - /// Initializing the run time fields - public override void RuntimeInitialize(MethodBase method) - { - logger = LogManager.GetLogger(ClassName); - } - - /// Handle the logging of entering a function. depends on LogParameters - /// - public override sealed void OnEntry(MethodExecutionArgs args) - { - args.MethodExecutionTag = Guid.NewGuid(); - string message = LogParameters ? $"Entering with parameters: {GetArguments(args)}" : "Entering"; - logger.LogAleph1(LogLevel.Trace, message, null, args.MethodExecutionTag, ClassName, MethodName); - } - - /// Handle the logging of exiting a function. depends on LogReturnValue - /// - public override sealed void OnExit(MethodExecutionArgs args) - { - string message = LogReturnValue ? $"Leaving with result: {GetReturnValue(args)}" : "Leaving"; - logger.LogAleph1(LogLevel.Trace, message, null, args.MethodExecutionTag, ClassName, MethodName); - } - - /// Handle the logging of an error in a function - /// - public override sealed void OnException(MethodExecutionArgs args) - { - logger.LogAleph1(LogLevel.Error, args.Exception.StackTrace, args.Exception, args.MethodExecutionTag, ClassName, MethodName); - } - - private string GetArguments(MethodExecutionArgs args) - { - if (ParameterNames.Length == 0) - return "null"; - - Dictionary o = new Dictionary(); - for (int i = 0; i < ParameterNames.Length; i++) - o.Add(ParameterNames[i], args.Arguments[i]); - try { return JsonConvert.SerializeObject(o); } - catch (JsonSerializationException e) { return $"[Error in Serializing the arguments: {e.Message}]"; } - } - private string GetReturnValue(MethodExecutionArgs args) - { - if (args.ReturnValue == null) - return "null"; - - try { return JsonConvert.SerializeObject(args.ReturnValue); } - catch (JsonSerializationException e) { return $"[Error in Serializing the return value: {e.Message} ---ReturnValue.ToString: {args.ReturnValue.ToString()}]"; } - } - } + /// Aspect to handle logging + [Serializable, AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true), LinesOfCodeAvoided(20)] + public sealed class LoggedAttribute : OnMethodBoundaryAspect + { + /// Default = true, set to False when you don't want the parameters of the function to be logged + public bool LogParameters { get; set; } = true; + + /// Default = false, set to true when you want the return value of the function to be logged + public bool LogReturnValue { get; set; } = false; + + [NonSerialized] + private ILogger logger; + + private string[] ParameterNames { get; set; } + private string ClassName { get; set; } + private string MethodName { get; set; } + + /// Initializing the fixed fields at compile time to improve performance + public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo) + { + ClassName = method.ReflectedType.Name; + MethodName = method.Name; + ParameterNames = method.GetParameters().Select(pi => pi.Name).ToArray(); + } + + /// Initializing the run time fields + public override void RuntimeInitialize(MethodBase method) + { + logger = LogManager.GetLogger(ClassName); + } + + /// Handle the logging of entering a function. depends on LogParameters + /// + public sealed override void OnEntry(MethodExecutionArgs args) + { + args.MethodExecutionTag = Guid.NewGuid(); + string message = LogParameters ? $"Entering with parameters: {GetArguments(args)}" : "Entering"; + logger.LogAleph1(LogLevel.Trace, message, null, args.MethodExecutionTag, ClassName, MethodName); + } + + /// Handle the logging of exiting a function. depends on LogReturnValue + /// + public sealed override void OnExit(MethodExecutionArgs args) + { + string message = LogReturnValue ? $"Leaving with result: {GetReturnValue(args)}" : "Leaving"; + logger.LogAleph1(LogLevel.Trace, message, null, args.MethodExecutionTag, ClassName, MethodName); + } + + /// Handle the logging of an error in a function + /// + public sealed override void OnException(MethodExecutionArgs args) + { + logger.LogAleph1(LogLevel.Error, $"parameters: {GetArguments(args)}", args.Exception, args.MethodExecutionTag, ClassName, MethodName); + } + + private string GetArguments(MethodExecutionArgs args) + { + if (ParameterNames.Length == 0) + { + return "null"; + } + + Dictionary o = new Dictionary(); + for (int i = 0; i < ParameterNames.Length; i++) + { + o.Add(ParameterNames[i], args.Arguments[i]); + } + + try { return JsonConvert.SerializeObject(o); } + catch (JsonSerializationException e) { return $"[Error in Serializing the arguments: {e.Message}]"; } + } + private static string GetReturnValue(MethodExecutionArgs args) + { + if (args.ReturnValue == null) + { + return "null"; + } + + try { return JsonConvert.SerializeObject(args.ReturnValue); } + catch (JsonSerializationException e) { return $"[Error in Serializing the return value: {e.Message} ---ReturnValue.ToString: {args.ReturnValue}]"; } + } + } } diff --git a/Aleph1.Logging/LoggerHelper.cs b/Aleph1.Logging/LoggerHelper.cs index 29b1d8a..498f445 100644 --- a/Aleph1.Logging/LoggerHelper.cs +++ b/Aleph1.Logging/LoggerHelper.cs @@ -1,36 +1,36 @@ -using Aleph1.Utitilies; -using NLog; -using System; +using System; using System.Diagnostics; using System.Runtime.CompilerServices; +using Aleph1.Utilities; + +using NLog; + namespace Aleph1.Logging { - /// Helper for NLog Logger - public static class LoggerHelper - { - /// Log a message in the Aleph1 format - /// the logger to log to - /// log level - /// message - /// optional - exception - /// optional - can be used to identify multiple messages as part of an action - /// optional - caller class name - calculated at runtime - /// optional - caller method name - calculated at build time - public static void LogAleph1(this ILogger logger, LogLevel logLevel, string message, Exception exception = null, object correlationID = null, string className = null, [CallerMemberName] string methodName = "") - { - LogEventInfo lei = new LogEventInfo(logLevel, logger.Name, message); - - className = className ?? new StackFrame(1, false).GetMethod().DeclaringType.Name; - - lei.Properties.Add("A1_UserName", UserExtentions.CurrentUserName); - lei.Properties.Add("A1_ClassName", className); - lei.Properties.Add("A1_MethodName", methodName); - lei.Properties.Add("A1_CorrelationID", correlationID); + /// Helper for NLog Logger + public static class LoggerHelper + { + /// Log a message in the Aleph1 format + /// the logger to log to + /// log level + /// message + /// optional - exception + /// optional - can be used to identify multiple messages as part of an action + /// optional - caller class name - calculated at runtime + /// optional - caller method name - calculated at build time + public static void LogAleph1(this ILogger logger, LogLevel logLevel, string message, Exception exception = null, object correlationID = null, string className = null, [CallerMemberName] string methodName = "") + { + LogEventInfo lei = new LogEventInfo(logLevel, logger.Name, message); + + lei.Properties.Add("A1_UserName", UserExtentions.CurrentUserName); + lei.Properties.Add("A1_ClassName", className ?? new StackFrame(1, false).GetMethod().DeclaringType.Name); + lei.Properties.Add("A1_MethodName", methodName); + lei.Properties.Add("A1_CorrelationID", correlationID); - lei.Exception = exception; + lei.Exception = exception; - logger.Log(lei); - } - } + logger.Log(lei); + } + } } diff --git a/Aleph1.Logging/net40fix.cs b/Aleph1.Logging/net40fix.cs deleted file mode 100644 index 12c7265..0000000 --- a/Aleph1.Logging/net40fix.cs +++ /dev/null @@ -1,22 +0,0 @@ -#if NET40 -namespace System.Runtime.CompilerServices -{ - /// - [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] - public sealed class CallerMemberNameAttribute : Attribute - { - } - - /// - [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] - public sealed class CallerFilePathAttribute : Attribute - { - } - - /// - [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] - public sealed class CallerLineNumberAttribute : Attribute - { - } -} -#endif \ No newline at end of file diff --git a/Aleph1.Security.Contracts/Aleph1.Security.Contracts.csproj b/Aleph1.Security.Contracts/Aleph1.Security.Contracts.csproj index e229a18..56c84f7 100644 --- a/Aleph1.Security.Contracts/Aleph1.Security.Contracts.csproj +++ b/Aleph1.Security.Contracts/Aleph1.Security.Contracts.csproj @@ -1,26 +1,28 @@  - - net20;net45;net471 - 3.3.1 - Avraham Essoudry - Aleph1 Security Contracts - Aleph1.png - MIT - https://github.com/avrahamcool/Aleph1 - Aleph1 - false - git - Copyright Aleph1 © 2018 - https://github.com/avrahamcool/Aleph1.git - Contracts for Aleph1.Security - Full - bin\$(Configuration)\$(TargetFramework)\Aleph1.Security.Contracts.xml - embedded PackageIcon - + + net48 + 4.8.0 + 4.8.0.0 + 4.8.0.0 + Avraham Essoudry + Aleph1 Security Contracts + Aleph1.png + MIT + https://github.com/avrahamcool/Aleph1 + Aleph1 + false + git + Copyright Aleph1 © 2018 + https://github.com/avrahamcool/Aleph1.git + Contracts for Aleph1.Security + Full + bin\$(Configuration)\$(TargetFramework)\Aleph1.Security.Contracts.xml + embedded PackageIcon + + + + + - - - - \ No newline at end of file diff --git a/Aleph1.Security.Contracts/ICipher.cs b/Aleph1.Security.Contracts/ICipher.cs index 9883ca5..01f6c31 100644 --- a/Aleph1.Security.Contracts/ICipher.cs +++ b/Aleph1.Security.Contracts/ICipher.cs @@ -2,25 +2,25 @@ namespace Aleph1.Security.Contracts { - /// A common interface for Encryption / Decryption of data - public interface ICipher - { - /// Encrypts the specified data for a specific user in a specific application. - /// Any - /// The application prefix. - /// The user unique identifier. - /// The data to encrypt - /// the duration of the ticket generated - /// the encrypted data - string Encrypt(string appPrefix, string userUniqueID, T data, TimeSpan? timeSpan = null); + /// A common interface for Encryption / Decryption of data + public interface ICipher + { + /// Encrypts the specified data for a specific user in a specific application. + /// Any + /// The application prefix. + /// The user unique identifier. + /// The data to encrypt + /// the duration of the ticket generated + /// the encrypted data + string Encrypt(string appPrefix, string userUniqueID, T data, TimeSpan? timeSpan = null); - /// Decrypts the specified data for a specific user in a specific application. - /// Any - /// The application prefix. - /// The user unique identifier. - /// The encrypted data. - /// the decrypted data - T Decrypt(string appPrefix, string userUniqueID, string encryptedData); - } + /// Decrypts the specified data for a specific user in a specific application. + /// Any + /// The application prefix. + /// The user unique identifier. + /// The encrypted data. + /// the decrypted data + T Decrypt(string appPrefix, string userUniqueID, string encryptedData); + } } diff --git a/Aleph1.Security.Implementation.3DES/Aleph1.Security.Implementation.3DES.csproj b/Aleph1.Security.Implementation.3DES/Aleph1.Security.Implementation.3DES.csproj deleted file mode 100644 index 17dc31d..0000000 --- a/Aleph1.Security.Implementation.3DES/Aleph1.Security.Implementation.3DES.csproj +++ /dev/null @@ -1,34 +0,0 @@ - - - - net20;net45;net471 - 4.0.2 - Avraham Essoudry - Aleph1 Security TripleDES 3DES - Aleph1.png - MIT - https://github.com/avrahamcool/Aleph1 - Aleph1 - false - git - Copyright Aleph1 © 2018 - https://github.com/avrahamcool/Aleph1.git - Aleph1 Security implementation using the TripleDES algorithm - Full - bin\$(Configuration)\$(TargetFramework)\Aleph1.Security.Implementation.3DES.xml - updated json + embedded PackageIcon - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Aleph1.Security.Implementation.3DES/TripleDES.cs b/Aleph1.Security.Implementation.3DES/TripleDES.cs deleted file mode 100644 index a631891..0000000 --- a/Aleph1.Security.Implementation.3DES/TripleDES.cs +++ /dev/null @@ -1,108 +0,0 @@ -using Aleph1.Security.Contracts; -using Newtonsoft.Json; -using System; -using System.Security.Cryptography; -using System.Text; - -namespace Aleph1.Security.Implementation._3DES -{ - /// Implementation of the ICyper interface using the TripleDES algorithm - /// - public class TripleDES : ICipher - { - private const int KEY_SIZE = 24; - - private static byte[] GetKey(string appPrefix, string userUniqueID) - { - string key = appPrefix + userUniqueID; - string monoSizeKey = Encoding.UTF8.GetByteCount(key) < KEY_SIZE - ? key.PadRight(KEY_SIZE, ' ') - : key.Substring(0, KEY_SIZE); - return Encoding.UTF8.GetBytes(monoSizeKey); - } - - private class Storage - { - public Storage() { } - public Storage(T data, string appPrefix, string userUniqueID, TimeSpan? timeSpan) - { - Data = data; - AppPrefix = appPrefix; - UserUniqueID = userUniqueID; - if (timeSpan.HasValue) - ExpirationDate = DateTime.UtcNow + timeSpan.Value; - } - - public T Data { get; set; } - - /// if the date is null - the ticket is unlimited - public DateTime? ExpirationDate { get; set; } - - /// Encrypted into the ticket for further check - public string AppPrefix { get; set; } - - /// Encrypted into the ticket for further check - public string UserUniqueID { get; set; } - } - - /// Decrypts the specified data for a specific user in a specific application. - /// Any - /// The application prefix. - /// The user unique identifier. - /// The encrypted data. - /// the decrypted data - /// - public T Decrypt(string appPrefix, string userUniqueID, string encryptedData) - { - using (TripleDESCryptoServiceProvider cryptoService = new TripleDESCryptoServiceProvider()) - { - cryptoService.Mode = CipherMode.ECB; - cryptoService.Padding = PaddingMode.PKCS7; - cryptoService.Key = GetKey(appPrefix, userUniqueID); - using (ICryptoTransform decryptor = cryptoService.CreateDecryptor()) - { - byte[] buffer = Convert.FromBase64String(encryptedData.Replace(' ', '+')); - - //Throws error when invalid - string serizlizedTicket = Encoding.UTF8.GetString(decryptor.TransformFinalBlock(buffer, 0, buffer.Length)); - - Storage store = JsonConvert.DeserializeObject>(serizlizedTicket); - - //Ticket Decrypted successfully - but not for the right user - if (store.AppPrefix != appPrefix || store.UserUniqueID != userUniqueID) - throw new CryptographicException($"Ticket Violation"); - - //Ticket Decrypted successfully - but expired - if (store.ExpirationDate.HasValue && store.ExpirationDate.Value < DateTime.UtcNow) - throw new CryptographicException($"Data Expired {DateTime.UtcNow - store.ExpirationDate.Value} ago"); - - return store.Data; - } - } - } - - /// Encrypts the specified data for a specific user in a specific application. - /// Any - /// The application prefix. - /// The user unique identifier. - /// The data to encrypt - /// the duration of the ticket generated - /// the encrypted data - public string Encrypt(string appPrefix, string userUniqueID, T data, TimeSpan? timeSpan = null) - { - using (TripleDESCryptoServiceProvider cryptoService = new TripleDESCryptoServiceProvider()) - { - cryptoService.Mode = CipherMode.ECB; - cryptoService.Padding = PaddingMode.PKCS7; - cryptoService.Key = GetKey(appPrefix, userUniqueID); - - using (ICryptoTransform encryptor = cryptoService.CreateEncryptor()) - { - Storage store = new Storage(data, appPrefix, userUniqueID, timeSpan); - byte[] buffer = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(store)); - return Convert.ToBase64String(encryptor.TransformFinalBlock(buffer, 0, buffer.Length)); - } - } - } - } -} diff --git a/Aleph1.Security.Implementation.RijndaelManaged/Aleph1.Security.Implementation.RijndaelManaged.csproj b/Aleph1.Security.Implementation.RijndaelManaged/Aleph1.Security.Implementation.RijndaelManaged.csproj index 1382e12..9aa5e8a 100644 --- a/Aleph1.Security.Implementation.RijndaelManaged/Aleph1.Security.Implementation.RijndaelManaged.csproj +++ b/Aleph1.Security.Implementation.RijndaelManaged/Aleph1.Security.Implementation.RijndaelManaged.csproj @@ -1,34 +1,37 @@ - - net45;net471 - 1.0.1 - Avraham Essoudry - Aleph1 Security RijndaelManaged - Aleph1.png - MIT - https://github.com/avrahamcool/Aleph1 - Aleph1 - false - git - Copyright Aleph1 © 2018 - https://github.com/avrahamcool/Aleph1.git - Aleph1 Security implementation using the RijndaelManaged algorithm - Full - bin\$(Configuration)\$(TargetFramework)\Aleph1.Security.Implementation.RijndaelManaged.xml - Throws exceptions when decrypting empty strings or null. - + + net48 + 4.8.0 + 4.8.0.0 + 4.8.0.0 + Avraham Essoudry + Aleph1 Security RijndaelManaged + Aleph1.png + MIT + https://github.com/avrahamcool/Aleph1 + Aleph1 + false + git + Copyright Aleph1 © 2018 + https://github.com/avrahamcool/Aleph1.git + Aleph1 Security implementation using the RijndaelManaged algorithm + Full + bin\$(Configuration)\$(TargetFramework)\Aleph1.Security.Implementation.RijndaelManaged.xml + Throws exceptions when decrypting empty strings or null. + - - - - - - + + + - - - + + + + + + + \ No newline at end of file diff --git a/Aleph1.Security.Implementation.RijndaelManaged/RijndaelManaged.cs b/Aleph1.Security.Implementation.RijndaelManaged/RijndaelManaged.cs index 8371f5d..21176ec 100644 --- a/Aleph1.Security.Implementation.RijndaelManaged/RijndaelManaged.cs +++ b/Aleph1.Security.Implementation.RijndaelManaged/RijndaelManaged.cs @@ -1,189 +1,189 @@ -using Aleph1.Security.Contracts; - -using Newtonsoft.Json; - -using System; +using System; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; +using Aleph1.Security.Contracts; + +using Newtonsoft.Json; + namespace Aleph1.Security.Implementation.RijndaelManagedCipher { - /// Implementation of the ICyper interface using the RijndaelManaged algorithm - /// - public class RijndaelManagedCipher : ICipher - { - // This constant is used to determine the key size of the encryption algorithm in bits. - // We divide this by 8 within the code below to get the equivalent number of bytes. - private const int KEY_SIZE = 256; - private const int KEY_SIZE_BYTES = KEY_SIZE / 8; - - // This constant determines the number of iterations for the password bytes generation function. - private const int DERIVATION_ITERATIONS = 1000; - - private class Storage - { - public Storage() { } - public Storage(T data, string appPrefix, string userUniqueID, TimeSpan? timeSpan) - { - Data = data; - AppPrefix = appPrefix; - UserUniqueID = userUniqueID; - if (timeSpan.HasValue) - { - ExpirationDate = DateTime.UtcNow + timeSpan.Value; - } - } - - public T Data { get; set; } - - /// if the date is null - the ticket is unlimited - public DateTime? ExpirationDate { get; set; } - - /// Encrypted into the ticket for further check - public string AppPrefix { get; set; } - - /// Encrypted into the ticket for further check - public string UserUniqueID { get; set; } - } - - private static byte[] GenerateBitsOfRandomEntropy() - { - byte[] randomBytes = new byte[KEY_SIZE_BYTES]; - - // Fill the array with cryptographically secure random bytes. - using (RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider()) - { - rngCsp.GetBytes(randomBytes); - } - - return randomBytes; - } - - /// Decrypts the specified data for a specific user in a specific application. - /// Any - /// The application prefix. - /// The user unique identifier. - /// The encrypted data. - /// the decrypted data - public T Decrypt(string appPrefix, string userUniqueID, string encryptedData) - { - if (string.IsNullOrWhiteSpace(appPrefix) || string.IsNullOrWhiteSpace(userUniqueID) || string.IsNullOrWhiteSpace(encryptedData)) - { - throw new CryptographicException("empty appPrefix or userUniqueID or encryptedData"); - } - - string passPhrase = appPrefix + userUniqueID; - - // Get the complete stream of bytes that represent: - // [32 bytes of Salt] + [32 bytes of IV] + [n bytes of CipherText] - byte[] cipherTextBytesWithSaltAndIv = Convert.FromBase64String(encryptedData); - - // Get the salt bytes by extracting the first KEY_SIZE_BYTES bytes from the supplied cipherText bytes. - byte[] saltStringBytes = cipherTextBytesWithSaltAndIv.Take(KEY_SIZE_BYTES).ToArray(); - - // Get the IV bytes by extracting the next KEY_SIZE_BYTES bytes from the supplied cipherText bytes. - byte[] ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(KEY_SIZE_BYTES).Take(KEY_SIZE_BYTES).ToArray(); - - // Get the actual cipher text bytes by removing the first 2 * KEY_SIZE_BYTES bytes from the cipherText string. - byte[] cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip(KEY_SIZE_BYTES * 2).Take(cipherTextBytesWithSaltAndIv.Length - (KEY_SIZE_BYTES * 2)).ToArray(); - - using (Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DERIVATION_ITERATIONS)) - { - byte[] keyBytes = password.GetBytes(KEY_SIZE_BYTES); - using (RijndaelManaged symmetricKey = new RijndaelManaged()) - { - symmetricKey.BlockSize = KEY_SIZE; - symmetricKey.Mode = CipherMode.CBC; - symmetricKey.Padding = PaddingMode.PKCS7; - using (ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes)) - { - using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes)) - { - using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) - { - byte[] plainTextBytes = new byte[cipherTextBytes.Length]; - int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length); - memoryStream.Close(); - cryptoStream.Close(); - - //Throws error when invalid - string serizlizedTicket = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount); - - Storage store = JsonConvert.DeserializeObject>(serizlizedTicket); - - //Ticket Decrypted successfully - but not for the right user - if (store.AppPrefix != appPrefix || store.UserUniqueID != userUniqueID) - { - throw new CryptographicException($"Ticket Violation"); - } - - //Ticket Decrypted successfully - but expired - if (store.ExpirationDate.HasValue && store.ExpirationDate.Value < DateTime.UtcNow) - { - throw new CryptographicException($"Data Expired {DateTime.UtcNow - store.ExpirationDate.Value} ago"); - } - - return store.Data; - } - } - } - } - } - } - - /// Encrypts the specified data for a specific user in a specific application. - /// Any - /// The application prefix. - /// The user unique identifier. - /// The data to encrypt - /// the duration of the ticket generated - /// the encrypted data - public string Encrypt(string appPrefix, string userUniqueID, T data, TimeSpan? timeSpan = null) - { - if (string.IsNullOrWhiteSpace(appPrefix) || string.IsNullOrWhiteSpace(userUniqueID)) - { - throw new CryptographicException("empty appPrefix or userUniqueID"); - } - - Storage store = new Storage(data, appPrefix, userUniqueID, timeSpan); - string plainText = JsonConvert.SerializeObject(store); - string passPhrase = appPrefix + userUniqueID; - - // Salt and IV is randomly generated each time, but is prepended to encrypted cipher text - // so that the same Salt and IV values can be used when decrypting. - byte[] saltStringBytes = GenerateBitsOfRandomEntropy(); - byte[] ivStringBytes = GenerateBitsOfRandomEntropy(); - byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); - using (Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DERIVATION_ITERATIONS)) - { - byte[] keyBytes = password.GetBytes(KEY_SIZE_BYTES); - using (RijndaelManaged symmetricKey = new RijndaelManaged()) - { - symmetricKey.BlockSize = KEY_SIZE; - symmetricKey.Mode = CipherMode.CBC; - symmetricKey.Padding = PaddingMode.PKCS7; - using (ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes)) - { - using (MemoryStream memoryStream = new MemoryStream()) - { - using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) - { - cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length); - cryptoStream.FlushFinalBlock(); - // Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes. - byte[] cipherTextBytes = saltStringBytes; - cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray(); - cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray(); - memoryStream.Close(); - cryptoStream.Close(); - return Convert.ToBase64String(cipherTextBytes); - } - } - } - } - } - } - } + /// Implementation of the ICyper interface using the RijndaelManaged algorithm + /// + public class RijndaelManagedCipher : ICipher + { + // This constant is used to determine the key size of the encryption algorithm in bits. + // We divide this by 8 within the code below to get the equivalent number of bytes. + private const int KEY_SIZE = 256; + private const int KEY_SIZE_BYTES = KEY_SIZE / 8; + + // This constant determines the number of iterations for the password bytes generation function. + private const int DERIVATION_ITERATIONS = 1000; + + private class Storage + { + public Storage() { } + public Storage(T data, string appPrefix, string userUniqueID, TimeSpan? timeSpan) + { + Data = data; + AppPrefix = appPrefix; + UserUniqueID = userUniqueID; + if (timeSpan.HasValue) + { + ExpirationDate = DateTime.UtcNow + timeSpan.Value; + } + } + + public T Data { get; set; } + + /// if the date is null - the ticket is unlimited + public DateTime? ExpirationDate { get; set; } + + /// Encrypted into the ticket for further check + public string AppPrefix { get; set; } + + /// Encrypted into the ticket for further check + public string UserUniqueID { get; set; } + } + + private static byte[] GenerateBitsOfRandomEntropy() + { + byte[] randomBytes = new byte[KEY_SIZE_BYTES]; + + // Fill the array with cryptographically secure random bytes. + using (RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider()) + { + rngCsp.GetBytes(randomBytes); + } + + return randomBytes; + } + + /// Decrypts the specified data for a specific user in a specific application. + /// Any + /// The application prefix. + /// The user unique identifier. + /// The encrypted data. + /// the decrypted data + public T Decrypt(string appPrefix, string userUniqueID, string encryptedData) + { + if (string.IsNullOrWhiteSpace(appPrefix) || string.IsNullOrWhiteSpace(userUniqueID) || string.IsNullOrWhiteSpace(encryptedData)) + { + throw new CryptographicException("empty appPrefix or userUniqueID or encryptedData"); + } + + string passPhrase = appPrefix + userUniqueID; + + // Get the complete stream of bytes that represent: + // [32 bytes of Salt] + [32 bytes of IV] + [n bytes of CipherText] + byte[] cipherTextBytesWithSaltAndIv = Convert.FromBase64String(encryptedData); + + // Get the salt bytes by extracting the first KEY_SIZE_BYTES bytes from the supplied cipherText bytes. + byte[] saltStringBytes = cipherTextBytesWithSaltAndIv.Take(KEY_SIZE_BYTES).ToArray(); + + // Get the IV bytes by extracting the next KEY_SIZE_BYTES bytes from the supplied cipherText bytes. + byte[] ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(KEY_SIZE_BYTES).Take(KEY_SIZE_BYTES).ToArray(); + + // Get the actual cipher text bytes by removing the first 2 * KEY_SIZE_BYTES bytes from the cipherText string. + byte[] cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip(KEY_SIZE_BYTES * 2).Take(cipherTextBytesWithSaltAndIv.Length - (KEY_SIZE_BYTES * 2)).ToArray(); + + using (Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DERIVATION_ITERATIONS)) + { + byte[] keyBytes = password.GetBytes(KEY_SIZE_BYTES); + using (RijndaelManaged symmetricKey = new RijndaelManaged()) + { + symmetricKey.BlockSize = KEY_SIZE; + symmetricKey.Mode = CipherMode.CBC; + symmetricKey.Padding = PaddingMode.PKCS7; + using (ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes)) + { + using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes)) + { + using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) + { + byte[] plainTextBytes = new byte[cipherTextBytes.Length]; + int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length); + memoryStream.Close(); + cryptoStream.Close(); + + //Throws error when invalid + string serizlizedTicket = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount); + + Storage store = JsonConvert.DeserializeObject>(serizlizedTicket); + + //Ticket Decrypted successfully - but not for the right user + if (store.AppPrefix != appPrefix || store.UserUniqueID != userUniqueID) + { + throw new CryptographicException($"Ticket Violation"); + } + + //Ticket Decrypted successfully - but expired + if (store.ExpirationDate.HasValue && store.ExpirationDate.Value < DateTime.UtcNow) + { + throw new CryptographicException($"Data Expired {DateTime.UtcNow - store.ExpirationDate.Value} ago"); + } + + return store.Data; + } + } + } + } + } + } + + /// Encrypts the specified data for a specific user in a specific application. + /// Any + /// The application prefix. + /// The user unique identifier. + /// The data to encrypt + /// the duration of the ticket generated + /// the encrypted data + public string Encrypt(string appPrefix, string userUniqueID, T data, TimeSpan? timeSpan = null) + { + if (string.IsNullOrWhiteSpace(appPrefix) || string.IsNullOrWhiteSpace(userUniqueID)) + { + throw new CryptographicException("empty appPrefix or userUniqueID"); + } + + Storage store = new Storage(data, appPrefix, userUniqueID, timeSpan); + string plainText = JsonConvert.SerializeObject(store); + string passPhrase = appPrefix + userUniqueID; + + // Salt and IV are randomly generated each time, and added to encrypted cipher text + // so that the same Salt and IV values can be used when decrypting. + byte[] saltStringBytes = GenerateBitsOfRandomEntropy(); + byte[] ivStringBytes = GenerateBitsOfRandomEntropy(); + byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); + using (Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DERIVATION_ITERATIONS)) + { + byte[] keyBytes = password.GetBytes(KEY_SIZE_BYTES); + using (RijndaelManaged symmetricKey = new RijndaelManaged()) + { + symmetricKey.BlockSize = KEY_SIZE; + symmetricKey.Mode = CipherMode.CBC; + symmetricKey.Padding = PaddingMode.PKCS7; + using (ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes)) + { + using (MemoryStream memoryStream = new MemoryStream()) + { + using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) + { + cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length); + cryptoStream.FlushFinalBlock(); + // Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes. + byte[] cipherTextBytes = saltStringBytes; + cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray(); + cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray(); + memoryStream.Close(); + cryptoStream.Close(); + return Convert.ToBase64String(cipherTextBytes); + } + } + } + } + } + } + } } diff --git a/Aleph1.Security.Tests/Aleph1.Security.Tests.csproj b/Aleph1.Security.Tests/Aleph1.Security.Tests.csproj index 7285763..70425e1 100644 --- a/Aleph1.Security.Tests/Aleph1.Security.Tests.csproj +++ b/Aleph1.Security.Tests/Aleph1.Security.Tests.csproj @@ -1,6 +1,6 @@  - + Debug @@ -10,7 +10,7 @@ Properties Aleph1.Security.Tests Aleph1.Security.Tests - v4.7.1 + v4.8 512 {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 15.0 @@ -20,6 +20,7 @@ UnitTest + true @@ -39,14 +40,14 @@ 4 - - ..\packages\Fastenshtein.1.0.0.5\lib\net40-client\Fastenshtein.dll + + ..\packages\Fastenshtein.1.0.0.8\lib\net452\Fastenshtein.dll - ..\packages\MSTest.TestFramework.2.1.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll + ..\packages\MSTest.TestFramework.3.0.2\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.dll - ..\packages\MSTest.TestFramework.2.1.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll + ..\packages\MSTest.TestFramework.3.0.2\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll @@ -66,10 +67,6 @@ {3b055dbe-7e97-46c2-968c-382694377882} Aleph1.Security.Contracts - - {c1e516ca-a48d-4446-b535-ca60cf22b6f9} - Aleph1.Security.Implementation.3DES - {b4b99fde-c818-4692-9e5c-edb28b0882c4} Aleph1.Security.Implementation.RijndaelManaged @@ -84,8 +81,8 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - + + - + \ No newline at end of file diff --git a/Aleph1.Security.Tests/CipherTests.cs b/Aleph1.Security.Tests/CipherTests.cs index 6041357..9cc9b04 100644 --- a/Aleph1.Security.Tests/CipherTests.cs +++ b/Aleph1.Security.Tests/CipherTests.cs @@ -1,114 +1,114 @@ -using Aleph1.Security.Contracts; +using System; +using System.Security.Cryptography; +using System.Threading; + +using Aleph1.Security.Contracts; using Fastenshtein; using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Security.Cryptography; -using System.Threading; - namespace Aleph1.Security.Tests { - [TestClass] - public class CipherTests - { - private readonly ICipher cipher = new Implementation.RijndaelManagedCipher.RijndaelManagedCipher(); - private readonly string secret = "My special secret - hello world"; - private readonly string appPrefix = "{3EE06365-D5E3-4D2E-A8D0-1F6E10138D29}"; - private readonly string userUniqueID = "127.0.0.0"; - private readonly string wrongAppPrefix = "{4EE06365-D5E3-4D2E-A8D0-1F6E10138D29}"; - private readonly string wrongUserUniqueID = "127.1.0.0"; - - [TestMethod] - public void Decrypd_RightApp_RightClient_RightTime_Should_Work() - { - string ticket = cipher.Encrypt(appPrefix, userUniqueID, secret, TimeSpan.FromMinutes(1)); - - Assert.AreEqual(secret, cipher.Decrypt(appPrefix, userUniqueID, ticket)); - } - - [TestMethod] - public void Decrypd_RightApp_RightClient_UnlimitedTime_Should_Work() - { - string ticket = cipher.Encrypt(appPrefix, userUniqueID, secret); - - Assert.AreEqual(secret, cipher.Decrypt(appPrefix, userUniqueID, ticket)); - } - - [TestMethod] - public void Decrypd_RightApp_RightClient_WrongTime_Should_Fail() - { - string ticket = cipher.Encrypt(appPrefix, userUniqueID, secret, TimeSpan.FromMilliseconds(15)); - Thread.Sleep(30); - - Assert.ThrowsException(() => cipher.Decrypt(appPrefix, userUniqueID, ticket)); - } - - [TestMethod] - public void Decrypd_RightApp_WrongClient_Should_Fail() - { - string ticket = cipher.Encrypt(appPrefix, userUniqueID, secret); - - Assert.ThrowsException(() => cipher.Decrypt(appPrefix, wrongUserUniqueID, ticket)); - } - - [TestMethod] - public void Decrypd_WrongtApp_Should_Fail() - { - string ticket = cipher.Encrypt(appPrefix, userUniqueID, secret); - - Assert.ThrowsException(() => cipher.Decrypt(wrongAppPrefix, userUniqueID, ticket)); - } - - [TestMethod] - public void Decrypd_NullsAndEmptyStrings() - { - string ticket = cipher.Encrypt(appPrefix, userUniqueID, secret); - - Assert.ThrowsException(() => cipher.Decrypt("", "", ticket)); - Assert.ThrowsException(() => cipher.Decrypt(null, "", ticket)); - Assert.ThrowsException(() => cipher.Decrypt("", null, ticket)); - Assert.ThrowsException(() => cipher.Decrypt(null, null, ticket)); - Assert.ThrowsException(() => cipher.Decrypt(appPrefix, userUniqueID, "")); - Assert.ThrowsException(() => cipher.Decrypt(appPrefix, userUniqueID, null)); - } - - [TestMethod] - public void Decrypd_ChangingOneLetter_Should_Fail() - { - string ticket = cipher.Encrypt(appPrefix, userUniqueID, secret); - - string someChar = ticket[ticket.Length / 2] == 'a' ? "b" : "a"; - string wrongTicket = ticket.Remove(20, 1).Insert(1, someChar); - - Assert.ThrowsException(() => cipher.Decrypt(appPrefix, userUniqueID, wrongTicket)); - } - - - [TestMethod] - public void Encrypt_NullsAndEmptyStrings() - { - Assert.ThrowsException(() => cipher.Encrypt("", "", secret)); - Assert.ThrowsException(() => cipher.Encrypt(null, "", secret)); - Assert.ThrowsException(() => cipher.Encrypt("", null, secret)); - Assert.ThrowsException(() => cipher.Encrypt(null, null, secret)); - - string emptyStringCipher = cipher.Encrypt(appPrefix, userUniqueID, ""); - Assert.AreEqual("", cipher.Decrypt(appPrefix, userUniqueID, emptyStringCipher)); - - string nullCipher = cipher.Encrypt(appPrefix, userUniqueID, null); - Assert.IsNull(cipher.Decrypt(appPrefix, userUniqueID, nullCipher)); - } - - [TestMethod] - public void Encrypt_DifferentTimes_ShouldResultInBigVariant() - { - string ticket1 = cipher.Encrypt(appPrefix, userUniqueID, secret, TimeSpan.FromMinutes(1)); - string ticket2 = cipher.Encrypt(appPrefix, userUniqueID, secret, TimeSpan.FromMinutes(15)); - int distance = Levenshtein.Distance(ticket1, ticket2); - - Assert.IsTrue(distance > 0.7 * ticket1.Length, "encrypted text don't vary enough"); - } - } + [TestClass] + public class CipherTests + { + private readonly ICipher cipher = new Implementation.RijndaelManagedCipher.RijndaelManagedCipher(); + private readonly string secret = "My special secret - hello world"; + private readonly string appPrefix = "{3EE06365-D5E3-4D2E-A8D0-1F6E10138D29}"; + private readonly string userUniqueID = "127.0.0.0"; + private readonly string wrongAppPrefix = "{4EE06365-D5E3-4D2E-A8D0-1F6E10138D29}"; + private readonly string wrongUserUniqueID = "127.1.0.0"; + + [TestMethod] + public void Decrypd_RightApp_RightClient_RightTime_Should_Work() + { + string ticket = cipher.Encrypt(appPrefix, userUniqueID, secret, TimeSpan.FromMinutes(1)); + + Assert.AreEqual(secret, cipher.Decrypt(appPrefix, userUniqueID, ticket)); + } + + [TestMethod] + public void Decrypd_RightApp_RightClient_UnlimitedTime_Should_Work() + { + string ticket = cipher.Encrypt(appPrefix, userUniqueID, secret); + + Assert.AreEqual(secret, cipher.Decrypt(appPrefix, userUniqueID, ticket)); + } + + [TestMethod] + public void Decrypd_RightApp_RightClient_WrongTime_Should_Fail() + { + string ticket = cipher.Encrypt(appPrefix, userUniqueID, secret, TimeSpan.FromMilliseconds(15)); + Thread.Sleep(30); + + Assert.ThrowsException(() => cipher.Decrypt(appPrefix, userUniqueID, ticket)); + } + + [TestMethod] + public void Decrypd_RightApp_WrongClient_Should_Fail() + { + string ticket = cipher.Encrypt(appPrefix, userUniqueID, secret); + + Assert.ThrowsException(() => cipher.Decrypt(appPrefix, wrongUserUniqueID, ticket)); + } + + [TestMethod] + public void Decrypd_WrongtApp_Should_Fail() + { + string ticket = cipher.Encrypt(appPrefix, userUniqueID, secret); + + Assert.ThrowsException(() => cipher.Decrypt(wrongAppPrefix, userUniqueID, ticket)); + } + + [TestMethod] + public void Decrypd_NullsAndEmptyStrings() + { + string ticket = cipher.Encrypt(appPrefix, userUniqueID, secret); + + Assert.ThrowsException(() => cipher.Decrypt("", "", ticket)); + Assert.ThrowsException(() => cipher.Decrypt(null, "", ticket)); + Assert.ThrowsException(() => cipher.Decrypt("", null, ticket)); + Assert.ThrowsException(() => cipher.Decrypt(null, null, ticket)); + Assert.ThrowsException(() => cipher.Decrypt(appPrefix, userUniqueID, "")); + Assert.ThrowsException(() => cipher.Decrypt(appPrefix, userUniqueID, null)); + } + + [TestMethod] + public void Decrypd_ChangingOneLetter_Should_Fail() + { + string ticket = cipher.Encrypt(appPrefix, userUniqueID, secret); + + string someChar = ticket[ticket.Length / 2] == 'a' ? "b" : "a"; + string wrongTicket = ticket.Remove(20, 1).Insert(1, someChar); + + Assert.ThrowsException(() => cipher.Decrypt(appPrefix, userUniqueID, wrongTicket)); + } + + + [TestMethod] + public void Encrypt_NullsAndEmptyStrings() + { + Assert.ThrowsException(() => cipher.Encrypt("", "", secret)); + Assert.ThrowsException(() => cipher.Encrypt(null, "", secret)); + Assert.ThrowsException(() => cipher.Encrypt("", null, secret)); + Assert.ThrowsException(() => cipher.Encrypt(null, null, secret)); + + string emptyStringCipher = cipher.Encrypt(appPrefix, userUniqueID, ""); + Assert.AreEqual("", cipher.Decrypt(appPrefix, userUniqueID, emptyStringCipher)); + + string nullCipher = cipher.Encrypt(appPrefix, userUniqueID, null); + Assert.IsNull(cipher.Decrypt(appPrefix, userUniqueID, nullCipher)); + } + + [TestMethod] + public void Encrypt_DifferentTimes_ShouldResultInBigVariant() + { + string ticket1 = cipher.Encrypt(appPrefix, userUniqueID, secret, TimeSpan.FromMinutes(1)); + string ticket2 = cipher.Encrypt(appPrefix, userUniqueID, secret, TimeSpan.FromMinutes(15)); + int distance = Levenshtein.Distance(ticket1, ticket2); + + Assert.IsTrue(distance > 0.7 * ticket1.Length, "encrypted text don't vary enough"); + } + } } diff --git a/Aleph1.Security.Tests/packages.config b/Aleph1.Security.Tests/packages.config index 752875a..259bf40 100644 --- a/Aleph1.Security.Tests/packages.config +++ b/Aleph1.Security.Tests/packages.config @@ -1,7 +1,7 @@  - - - + + + \ No newline at end of file diff --git a/Aleph1.Utilities/Aleph1.Utilities.csproj b/Aleph1.Utilities/Aleph1.Utilities.csproj index 91ce908..ae7af42 100644 --- a/Aleph1.Utilities/Aleph1.Utilities.csproj +++ b/Aleph1.Utilities/Aleph1.Utilities.csproj @@ -1,30 +1,38 @@  - - net40;net45;net471 - 3.3.1 - Avraham Essoudry - Aleph1 DI - Aleph1.png - MIT - https://github.com/avrahamcool/Aleph1 - Aleph1 - false - git - Copyright Aleph1 © 2018 - https://github.com/avrahamcool/Aleph1.git - Common Utilities for Aleph1 projects - Full - bin\$(Configuration)\$(TargetFramework)\Aleph1.Utilities.xml - embedded PackageIcon - + + net48 + 4.8.0 + 4.8.0.0 + 4.8.0.0 + Avraham Essoudry + Aleph1 DI + Aleph1.png + MIT + https://github.com/avrahamcool/Aleph1 + Aleph1 + false + git + Copyright Aleph1 © 2018 + https://github.com/avrahamcool/Aleph1.git + Common Utilities for Aleph1 projects + Full + bin\$(Configuration)\$(TargetFramework)\Aleph1.Utilities.xml + embedded PackageIcon + true + - - - + + + - - - - + + + + + + + <_Parameter1>true + + diff --git a/Aleph1.Utilities/UserExtentions.cs b/Aleph1.Utilities/UserExtentions.cs index 0d85d6f..7c53433 100644 --- a/Aleph1.Utilities/UserExtentions.cs +++ b/Aleph1.Utilities/UserExtentions.cs @@ -1,27 +1,28 @@ -using System; -using System.Security.Principal; +using System.Security.Principal; using System.Web; -namespace Aleph1.Utitilies +namespace Aleph1.Utilities { - /// Handles common User related tasks (such as, getting the current user login name) - public static class UserExtentions - { - /// Get the current user login name - /// 1) Identity from HttpContext: Name => IP => Empty string, 2) Identity from Windows Context - public static string CurrentUserName - { - get - { - // Accessing HttpContext.Current.Request Throws Exception when no handler configured - if (HttpContext.Current != null && HttpContext.Current.Handler != null) - return String.IsNullOrWhiteSpace(HttpContext.Current.User?.Identity?.Name) ? - HttpContext.Current.Request.UserHostAddress : - HttpContext.Current.User.Identity.Name - ?? String.Empty; + /// Handles common User related tasks (such as, getting the current user login name) + public static class UserExtentions + { + /// Get the current user login name + /// 1) Identity from HttpContext: Name => IP => Empty string, 2) Identity from Windows Context + public static string CurrentUserName + { + get + { + // Accessing HttpContext.Current.Request Throws Exception when no handler configured + if (HttpContext.Current != null && HttpContext.Current.Handler != null) + { + string identifierFromHttp = string.IsNullOrWhiteSpace(HttpContext.Current.User?.Identity?.Name) ? + HttpContext.Current.Request.UserHostAddress : + HttpContext.Current.User.Identity.Name; + return identifierFromHttp ?? string.Empty; + } - return WindowsIdentity.GetCurrent()?.Name ?? String.Empty; - } - } - } + return WindowsIdentity.GetCurrent()?.Name ?? string.Empty; + } + } + } } diff --git a/Aleph1.WebAPI.ExceptionHandler/Aleph1.WebAPI.ExceptionHandler.csproj b/Aleph1.WebAPI.ExceptionHandler/Aleph1.WebAPI.ExceptionHandler.csproj deleted file mode 100644 index b7186f1..0000000 --- a/Aleph1.WebAPI.ExceptionHandler/Aleph1.WebAPI.ExceptionHandler.csproj +++ /dev/null @@ -1,34 +0,0 @@ - - - - net45;net471 - 3.1.2 - Avraham Essoudry - Aleph1 WebAPI ExceptionHandler - Aleph1.png - MIT - https://github.com/avrahamcool/Aleph1 - Aleph1 - false - git - Copyright Aleph1 © 2018 - https://github.com/avrahamcool/Aleph1.git - Handling custom Errors from WebAPI controllers with a single attribute - Full - fixed compiler warnings - embedded PackageIcon - bin\$(Configuration)\$(TargetFramework)\Aleph1.WebAPI.ExceptionHandler.xml - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Aleph1.WebAPI.ExceptionHandler/FriendlyMessageAttribute.cs b/Aleph1.WebAPI.ExceptionHandler/FriendlyMessageAttribute.cs deleted file mode 100644 index d03adfc..0000000 --- a/Aleph1.WebAPI.ExceptionHandler/FriendlyMessageAttribute.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Web.Http.Filters; - -namespace Aleph1.WebAPI.ExceptionHandler -{ - /// Let the Actions use a friendly message - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)] - public sealed class FriendlyMessageAttribute : ExceptionFilterAttribute - { - /// The message to show for the client - public string FriendlyMessage { get; set; } - - /// You have to specify a Friendly message - /// The message to show for the client - public FriendlyMessageAttribute(string friendlyMessage) - { - this.FriendlyMessage = friendlyMessage; - } - - /// replace the current Exception with a new one - /// - public override void OnException(HttpActionExecutedContext actionExecutedContext) - { - actionExecutedContext.Exception = new Exception(FriendlyMessage, actionExecutedContext.Exception); - } - } -} diff --git a/Aleph1.sln b/Aleph1.sln index bf26682..ad14b1d 100644 --- a/Aleph1.sln +++ b/Aleph1.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 -VisualStudioVersion = 16.0.29020.237 +VisualStudioVersion = 16.0.33027.164 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{E736B54E-3F6A-4B4F-AE7F-CEC89B50759A}" ProjectSection(SolutionItems) = preProject @@ -14,6 +14,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "1. Aleph1.Utilities", "1. A EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".solution", ".solution", "{1408A32E-D513-4E65-88F2-A8A5BC5C203B}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig .gitattributes = .gitattributes .gitignore = .gitignore README.md = README.md @@ -21,11 +22,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".solution", ".solution", "{ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "0. Aleph1.DI", "0. Aleph1.DI", "{B6A902AE-3492-4363-AFC3-539DF6713B2B}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3. Aleph1.WebAPI.ExceptionHandler", "3. Aleph1.WebAPI.ExceptionHandler", "{12B7D42B-619B-46C7-AD97-64C244698F03}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2. Aleph1.Logging", "2. Aleph1.Logging", "{DAEF5E87-1B4E-4DC4-A552-2B94F1313E0C}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "4. Aleph1.Security", "4. Aleph1.Security", "{84434352-B4A2-432B-A96E-F8652306342B}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3. Aleph1.Security", "3. Aleph1.Security", "{84434352-B4A2-432B-A96E-F8652306342B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aleph1.DI.Contracts", "Aleph1.DI.Contracts\Aleph1.DI.Contracts.csproj", "{F9DCAC9C-4063-4836-9975-7AAC60CEAE69}" EndProject @@ -35,21 +34,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aleph1.DI.UnityImplementati EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aleph1.Utilities", "Aleph1.Utilities\Aleph1.Utilities.csproj", "{F9E30980-269F-4021-8880-871C856C8349}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aleph1.WebAPI.ExceptionHandler", "Aleph1.WebAPI.ExceptionHandler\Aleph1.WebAPI.ExceptionHandler.csproj", "{A8F5C501-7CFA-4A43-9DB8-432E444DDC48}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aleph1.Security.Contracts", "Aleph1.Security.Contracts\Aleph1.Security.Contracts.csproj", "{3B055DBE-7E97-46C2-968C-382694377882}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aleph1.Security.Implementation.3DES", "Aleph1.Security.Implementation.3DES\Aleph1.Security.Implementation.3DES.csproj", "{C1E516CA-A48D-4446-B535-CA60CF22B6F9}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aleph1.Logging", "Aleph1.Logging\Aleph1.Logging.csproj", "{51EA994D-1D45-420C-81D4-2C7B8F2BFC54}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aleph1.Security.Tests", "Aleph1.Security.Tests\Aleph1.Security.Tests.csproj", "{E38043E5-9CDA-450D-947D-02CB431CD015}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "5. Aleph1.ClientFile", "5. Aleph1.ClientFile", "{21589C2D-A85E-4066-B0C1-BE6503423BC9}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "4. Aleph1.ClientFile", "4. Aleph1.ClientFile", "{21589C2D-A85E-4066-B0C1-BE6503423BC9}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aleph1.ClientFile.Models", "Aleph1.ClientFile.Models\Aleph1.ClientFile.Models.csproj", "{B4AB612C-FE17-474D-B442-B9ADFFE724A8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aleph1.Security.Implementation.RijndaelManaged", "Aleph1.Security.Implementation.RijndaelManaged\Aleph1.Security.Implementation.RijndaelManaged.csproj", "{B4B99FDE-C818-4692-9E5C-EDB28B0882C4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aleph1.Security.Implementation.RijndaelManaged", "Aleph1.Security.Implementation.RijndaelManaged\Aleph1.Security.Implementation.RijndaelManaged.csproj", "{B4B99FDE-C818-4692-9E5C-EDB28B0882C4}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -73,18 +68,10 @@ Global {F9E30980-269F-4021-8880-871C856C8349}.Debug|Any CPU.Build.0 = Debug|Any CPU {F9E30980-269F-4021-8880-871C856C8349}.Release|Any CPU.ActiveCfg = Release|Any CPU {F9E30980-269F-4021-8880-871C856C8349}.Release|Any CPU.Build.0 = Release|Any CPU - {A8F5C501-7CFA-4A43-9DB8-432E444DDC48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A8F5C501-7CFA-4A43-9DB8-432E444DDC48}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A8F5C501-7CFA-4A43-9DB8-432E444DDC48}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A8F5C501-7CFA-4A43-9DB8-432E444DDC48}.Release|Any CPU.Build.0 = Release|Any CPU {3B055DBE-7E97-46C2-968C-382694377882}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3B055DBE-7E97-46C2-968C-382694377882}.Debug|Any CPU.Build.0 = Debug|Any CPU {3B055DBE-7E97-46C2-968C-382694377882}.Release|Any CPU.ActiveCfg = Release|Any CPU {3B055DBE-7E97-46C2-968C-382694377882}.Release|Any CPU.Build.0 = Release|Any CPU - {C1E516CA-A48D-4446-B535-CA60CF22B6F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C1E516CA-A48D-4446-B535-CA60CF22B6F9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C1E516CA-A48D-4446-B535-CA60CF22B6F9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C1E516CA-A48D-4446-B535-CA60CF22B6F9}.Release|Any CPU.Build.0 = Release|Any CPU {51EA994D-1D45-420C-81D4-2C7B8F2BFC54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {51EA994D-1D45-420C-81D4-2C7B8F2BFC54}.Debug|Any CPU.Build.0 = Debug|Any CPU {51EA994D-1D45-420C-81D4-2C7B8F2BFC54}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -110,9 +97,7 @@ Global {4A79B0A7-55B0-4F84-8355-C2D5BA7EE7BF} = {B6A902AE-3492-4363-AFC3-539DF6713B2B} {714E1B8F-9991-43B7-8903-9F6321B89D6F} = {B6A902AE-3492-4363-AFC3-539DF6713B2B} {F9E30980-269F-4021-8880-871C856C8349} = {ACD6CF11-DFDB-4AAB-93D5-6645C38917B2} - {A8F5C501-7CFA-4A43-9DB8-432E444DDC48} = {12B7D42B-619B-46C7-AD97-64C244698F03} {3B055DBE-7E97-46C2-968C-382694377882} = {84434352-B4A2-432B-A96E-F8652306342B} - {C1E516CA-A48D-4446-B535-CA60CF22B6F9} = {84434352-B4A2-432B-A96E-F8652306342B} {51EA994D-1D45-420C-81D4-2C7B8F2BFC54} = {DAEF5E87-1B4E-4DC4-A552-2B94F1313E0C} {E38043E5-9CDA-450D-947D-02CB431CD015} = {84434352-B4A2-432B-A96E-F8652306342B} {B4AB612C-FE17-474D-B442-B9ADFFE724A8} = {21589C2D-A85E-4066-B0C1-BE6503423BC9} diff --git a/README.md b/README.md index 835c066..b7ec667 100644 --- a/README.md +++ b/README.md @@ -35,18 +35,14 @@ ILogger logger = LogManager.GetCurrentClassLogger(); logger.LogAleph1(LogLevel.Info, "message"); ``` -### 3. Aleph1.WebAPI.ExceptionHandler -* #### Aleph1.WebAPI.ExceptionHandler -adding a [FriendlyMessage] aspect for handling WebApi exception in a granular way. - -### 4. Aleph1.Security +### 3. Aleph1.Security * #### Aleph1.Security.Contracts a common interface for the custom Security handler used by Aleph1 projects * #### Aleph1.Security.Implementation.3DES a concrete implementation of the Security interface using 3DES -### 5. Aleph1.ClientFile +### 4. Aleph1.ClientFile * #### Aleph1.ClientFile.Models ClientFile Model for easy file uploading via JSON POST directly from the client. Should be use with [aleph1-client-file](https://github.com/avrahamcool/aleph1-client-file) \ No newline at end of file