├── .gitattributes ├── .gitignore ├── .semver ├── Fooidity.snk ├── build.bat ├── build.fsx ├── build_support ├── BuildUtils.rb ├── util.rb └── versioning.rb ├── install.bat ├── rakefile.rb ├── readme.md └── src ├── .nuget ├── NuGet.Config ├── NuGet.targets └── packages.config ├── Fooidity.AutofacIntegration ├── CodeSwitchContainerScope.cs ├── CodeSwitchEvaluationTrackingExtensions.cs ├── CodeSwitchRegistrationExtensions.cs ├── ContainerBuilderExtensions.cs ├── ContextProviderExtensions.cs ├── Fooidity.AutofacIntegration.csproj ├── Modules │ ├── ConfigurationCodeFeatureCacheModule.cs │ └── ConfigurationContextFeatureCacheModule.cs └── packages.config ├── Fooidity.AzureIntegration.Tests ├── App.config ├── Fooidity.AzureIntegration.Tests.csproj ├── TableStorage_Specs.cs └── packages.config ├── Fooidity.AzureIntegration ├── CloudCodeFeatureStateCacheProvider.cs ├── CloudContextFeatureStateCacheProvider.cs ├── CloudTableProvider.cs ├── ConfigurationCloudStorageAccountProvider.cs ├── Entities │ ├── CodeFeatureStateEntity.cs │ └── ContextFeatureStateEntity.cs ├── Fooidity.AzureIntegration.csproj ├── ICloudStorageAccountProvider.cs ├── ICloudTableProvider.cs ├── TableQueryExtensions.cs ├── TimestampExtensions.cs └── packages.config ├── Fooidity.Client.AutofacIntegration ├── AutofacClientConfigurator.cs ├── Fooidity.Client.AutofacIntegration.csproj ├── FooidityClientModule.cs ├── FooidityClientRegistrationExtensions.cs └── packages.config ├── Fooidity.Client.Tests ├── Configuration_Specs.cs ├── Fooidity.Client.Tests.csproj └── packages.config ├── Fooidity.Client ├── ApplicationHubCodeFeatureStateCacheProvider.cs ├── ApplicationHubCodeSwitchEventHandler.cs ├── ApplicationHubProxy.cs ├── Configuration │ ├── ClientSettings.cs │ ├── IClientConfigurator.cs │ └── IClientSettings.cs ├── Fooidity.Client.csproj ├── FooidityClient.cs ├── HubConnectionEventPublisher.cs ├── HubConnectionProvider.cs ├── IApplicationHubEventConnector.cs ├── IApplicationHubProxy.cs ├── IFooidityClient.cs ├── IHubConnectionProvider.cs ├── UpdateCacheApplicationHubEventConnector.cs └── packages.config ├── Fooidity.CloudService ├── Fooidity.CloudService.ccproj ├── Fooidity.Management.WebContent │ └── diagnostics.wadcfg ├── Profiles │ └── fooidityProduction.azurePubxml ├── ServiceConfiguration.Cloud.cscfg ├── ServiceConfiguration.Local.cscfg └── ServiceDefinition.csdef ├── Fooidity.ContainerTests ├── A_conditional_class_dependency.cs ├── ContainerSetup_Specs.cs ├── ContextContainer_Specs.cs ├── Contexts │ ├── UserContext.cs │ └── UserContextKeyProvider.cs ├── Defaults │ ├── FooIdContainer_Specs.cs │ └── RegisterGeneric_Specs.cs ├── ExceptionLogging_Specs.cs ├── Features │ ├── DbEnabled.cs │ ├── UseNewClass.cs │ ├── UseNewCodePath.cs │ └── UseNewMethod.cs ├── Fooidity.ContainerTests.csproj ├── Subjects │ └── ConditionalClass.cs ├── app.config └── packages.config ├── Fooidity.Management.AzureIntegration ├── CommandHandlers │ ├── CreateApplicationCommandHandler.cs │ ├── CreateApplicationKeyCommandHandler.cs │ ├── CreateOrganizationCommandHandler.cs │ ├── RegisterApplicationContextCommandHandler.cs │ ├── RegisterCodeFeatureCommandHandler.cs │ └── UpdateApplicationCodeFeatureStateCommandHandler.cs ├── DefaultAzureManagementSettings.cs ├── Entities │ ├── ApplicationCodeFeatureEntity.cs │ ├── ApplicationCodeFeatureStateEntity.cs │ ├── ApplicationContextCodeFeatureStateEntity.cs │ ├── ApplicationContextEntity.cs │ ├── ApplicationEntity.cs │ ├── KeyOrganizationApplicationIndexEntity.cs │ ├── OrganizationApplicationIndexEntity.cs │ ├── OrganizationApplicationKeyEntity.cs │ ├── OrganizationEntity.cs │ ├── OrganizationUserEntity.cs │ ├── UserApplicationIndexEntity.cs │ └── UserOrganizationIndexEntity.cs ├── Exceptions │ ├── ApplicationNotFoundException.cs │ ├── DuplicateEmailException.cs │ ├── DuplicateUsernameException.cs │ ├── FeatureNotFoundException.cs │ └── OrganizationNotFoundException.cs ├── Fooidity.Management.AzureIntegration.csproj ├── IAzureManagementSettings.cs ├── QueryCodeFeatureStateQueryHandler.cs ├── QueryHandlers │ ├── GetApplicationKeyQueryHandler.cs │ ├── GetApplicationQueryHandler.cs │ ├── GetCodeFeatureDetailQueryHandler.cs │ ├── GetOrganizationQueryHandler.cs │ ├── ListApplicationCodeFeaturesQueryHandler.cs │ ├── ListApplicationKeysQueryHandler.cs │ ├── ListApplicationsQueryHandler.cs │ └── ListOrganizationsQueryHandler.cs ├── UpdateCodeFeatureStateCommandHandler.cs ├── UserStore │ ├── Encoding │ │ ├── Base32BinaryEncodingFormatter.cs │ │ ├── Base32BinaryEncodingParser.cs │ │ ├── HashedHexBinaryEncodingFormatter.cs │ │ ├── HexBinaryEncodingFormatter.cs │ │ ├── HexBinaryEncodingParser.cs │ │ ├── IBinaryEncodingFormatter.cs │ │ ├── IBinaryEncodingParser.cs │ │ ├── ZBase32BinaryEncodingFormatter.cs │ │ └── ZBase32BinaryEncodingParser.cs │ ├── EncodingExtensions.cs │ ├── NonSerializedTableStoreAttribute.cs │ ├── TableUserStore.cs │ ├── UserClaimEntity.cs │ ├── UserEmailIndexEntity.cs │ ├── UserEntity.cs │ ├── UserLoginEntity.cs │ ├── UserLoginProviderKeyIndexEntity.cs │ ├── UserNameIndexEntity.cs │ └── UserRoleEntity.cs └── packages.config ├── Fooidity.Management.Web.Switching ├── Contexts │ ├── UserContext.cs │ └── UserContextKeyProvider.cs ├── Features │ └── Feature_NewScreen.cs └── Fooidity.Management.Web.Switching.csproj ├── Fooidity.Management.Web ├── App_Start │ ├── BundleConfig.cs │ ├── FilterConfig.cs │ ├── FooidityModule.cs │ ├── RouteConfig.cs │ ├── Startup.Auth.cs │ ├── WebApiConfig.cs │ └── WebAppContainer.cs ├── Content │ ├── Site.css │ ├── bootstrap-theme.css │ ├── bootstrap-theme.css.map │ ├── bootstrap-theme.min.css │ ├── bootstrap-theme.min.css.map │ ├── bootstrap.css │ ├── bootstrap.css.map │ ├── bootstrap.min.css │ └── bootstrap.min.css.map ├── Controllers │ ├── AccountController.cs │ ├── ApplicationController.cs │ ├── CodeFeatureApiController.cs │ ├── CodeFeatureController.cs │ ├── FeaturesController.cs │ ├── HomeController.cs │ └── OrganizationController.cs ├── Fooidity.Management.Web.csproj ├── Global.asax ├── Global.asax.cs ├── Hubs │ ├── ApplicationHub.cs │ ├── ApplicationHubEventHandler.cs │ └── ConnectionIdAppKeyDictionary.cs ├── Logging │ └── UnhandledExceptionLogger.cs ├── Models │ ├── AccountViewModels.cs │ ├── ApplicationUser.cs │ ├── ApplicationViewModel.cs │ ├── CodeFeatureDetailViewModel.cs │ ├── CodeFeatureModel.cs │ ├── CodeFeatureStateViewModel.cs │ ├── CreateApplicationKeyViewModel.cs │ ├── EnableCodeFeatureViewModel.cs │ ├── ExternalLoginListViewModel.cs │ ├── LoginViewModel.cs │ ├── ManageCodeFeatureViewModel.cs │ ├── ManageUserViewModel.cs │ ├── OrganizationViewModel.cs │ └── RegisterViewModel.cs ├── Providers │ └── ApplicationOAuthProvider.cs ├── Scripts │ ├── _references.js │ ├── bootstrap.js │ ├── bootstrap.min.js │ ├── jquery-1.10.2.intellisense.js │ ├── jquery-2.2.3.intellisense.js │ ├── jquery-2.2.3.js │ ├── jquery-2.2.3.min.js │ ├── jquery-2.2.3.min.map │ ├── jquery.signalR-2.2.0.js │ ├── jquery.signalR-2.2.0.min.js │ ├── modernizr-2.6.2.js │ ├── modernizr-2.8.3.js │ ├── respond.js │ ├── respond.matchmedia.addListener.js │ ├── respond.matchmedia.addListener.min.js │ └── respond.min.js ├── Startup.cs ├── Views │ ├── Account │ │ ├── ExternalLoginConfirmation.cshtml │ │ ├── ExternalLoginFailure.cshtml │ │ ├── Login.cshtml │ │ ├── Manage.cshtml │ │ ├── _ExternalLoginsListPartial.cshtml │ │ └── _RemoveAccountPartial.cshtml │ ├── Application │ │ ├── Create.cshtml │ │ ├── Details.cshtml │ │ └── Index.cshtml │ ├── CodeFeature │ │ └── Details.cshtml │ ├── Features │ │ ├── Details.cshtml │ │ └── Index.cshtml │ ├── Home │ │ └── Index.cshtml │ ├── Organization │ │ ├── Create.cshtml │ │ ├── Details.cshtml │ │ └── Index.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ ├── _Layout.cshtml │ │ └── _LoginPartial.cshtml │ ├── Web.config │ └── _ViewStart.cshtml ├── Web.Debug.config ├── Web.Release.config ├── Web.config ├── favicon.ico ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 └── packages.config ├── Fooidity.Management ├── Commands │ ├── CreateApplication.cs │ ├── CreateApplicationKey.cs │ ├── CreateOrganization.cs │ ├── ICreateApplication.cs │ ├── ICreateApplicationKey.cs │ ├── ICreateOrganization.cs │ ├── IRegisterApplicationContext.cs │ ├── IRegisterCodeFeature.cs │ ├── IUpdateApplicationCodeFeatureState.cs │ ├── RegisterApplicationContext.cs │ ├── RegisterCodeFeature.cs │ └── UpdateApplicationCodeFeatureState.cs ├── Contracts │ ├── ApplicationCodeFeatureStateUpdated.cs │ └── IApplicationCodeFeatureStateUpdated.cs ├── Fooidity.Management.csproj ├── ICommandHandler.cs ├── IEventHandler.cs ├── IQueryHandler.cs ├── Models │ ├── Application.cs │ ├── CodeFeatureDetail.cs │ ├── ICodeFeatureDetail.cs │ ├── IOrganization.cs │ ├── IOrganizationApplication.cs │ ├── IOrganizationApplicationKey.cs │ ├── IUser.cs │ └── IUserOrganizationApplication.cs ├── Queries │ ├── GetApplication.cs │ ├── GetApplicationByKey.cs │ ├── GetCodeFeatureDetail.cs │ ├── GetOrganization.cs │ ├── GetUser.cs │ ├── IGetApplication.cs │ ├── IGetApplicationByKey.cs │ ├── IGetCodeFeatureDetail.cs │ ├── IGetOrganization.cs │ ├── IListApplicationCodeFeatures.cs │ ├── IListApplicationKeys.cs │ ├── IListApplications.cs │ ├── IListOrganizations.cs │ ├── ListApplicationCodeFeatures.cs │ ├── ListApplicationKeys.cs │ ├── ListApplications.cs │ └── ListOrganizations.cs ├── QueryCodeFeatureState.cs └── UpdateCodeFeatureState.cs ├── Fooidity.MassTransitIntegration ├── ContextConsumerFactory.cs ├── ContextSagaRepository.cs ├── Fooidity.MassTransitIntegration.csproj ├── UpdateCodeFeatureCacheConsumer.cs ├── UpdateContextFeatureCacheConsumer.cs ├── app.config └── packages.config ├── Fooidity.Tests ├── A_disabled_DateRange.cs ├── App.config ├── CodeFeatureName_Specs.cs ├── ConfigurationFeatureState_Specs.cs ├── Dependent_Specs.cs ├── Fooidity.Tests.csproj ├── InlinePath_Specs.cs ├── ToggleSwitch_Specs.cs ├── Usage_Specs.cs └── packages.config ├── Fooidity.sln ├── Fooidity.sln.DotSettings ├── Fooidity ├── Caching │ ├── CachedCodeFeatureState.cs │ ├── CachedContextFeatureState.cs │ ├── CodeFeatureStateCache.cs │ ├── CodeFeatureStateCacheInstance.cs │ ├── ContextFeatureStateCache.cs │ ├── ContextFeatureStateCacheInstance.cs │ ├── ICachedCodeFeatureState.cs │ ├── ICachedContextFeatureState.cs │ ├── ICodeFeatureStateCacheInstance.cs │ ├── ICodeFeatureStateCacheProvider.cs │ ├── IContextFeatureStateCacheInstance.cs │ ├── IContextFeatureStateCacheProvider.cs │ ├── IReloadCache.cs │ ├── IUpdateCodeFeatureCache.cs │ ├── IUpdateContextFeatureCache.cs │ └── Internals │ │ ├── CacheItemAdded.cs │ │ ├── CacheItemRemoved.cs │ │ ├── CacheItemUpdated.cs │ │ ├── Connectable.cs │ │ ├── ConnectionHandle.cs │ │ ├── ICache.cs │ │ ├── ICacheIndex.cs │ │ ├── IReadOnlyCache.cs │ │ ├── InMemoryCache.cs │ │ └── InMemoryCacheIndex.cs ├── CodeFeatureId.cs ├── CodeSwitch.cs ├── CodeSwitchEvaluationObserver.cs ├── CodeSwitchFactory.cs ├── CodeSwitchOfT.cs ├── CodeSwitchOfT.tt ├── CodeSwitches │ ├── CodeFeatureStateCodeSwitch.cs │ ├── CodeSwitchEvaluatedObservable.cs │ ├── ContextFeatureStateCodeSwitch.cs │ ├── CurrentTimeProvider.cs │ ├── DateRangeCodeSwitch.cs │ ├── DisabledCodeSwitch.cs │ ├── EnabledCodeSwitch.cs │ ├── EnabledForAuthenticatedIdentityCodeSwitch.cs │ ├── EnabledForThreadPrincipalInRoleCodeSwitch.cs │ ├── IToggleSwitchState.cs │ ├── ToggleCodeSwitch.cs │ └── ToggleSwitchState.cs ├── Configuration │ ├── ConfigurationCodeFeatureStateCacheProvider.cs │ ├── ConfigurationContextFeatureStateCacheProvider.cs │ ├── ContextElement.cs │ ├── ContextElementCollection.cs │ ├── ContextInstanceElement.cs │ ├── ContextInstanceElementCollection.cs │ ├── DefaultCodeFeatureState.cs │ ├── FeatureStateElement.cs │ ├── FeatureStateElementCollection.cs │ └── FooidityConfigurationSection.cs ├── ContextId.cs ├── Contracts │ ├── CodeFeatureState.cs │ ├── CodeFeatureStateCacheLoaded.cs │ ├── CodeFeatureStateCacheUpdated.cs │ ├── CodeFeatureStateUpdated.cs │ ├── CodeSwitchEvaluated.cs │ ├── ContextCodeFeatureStateCacheLoaded.cs │ ├── ContextCodeFeatureStateCacheUpdated.cs │ ├── ContextCodeFeatureStateUpdated.cs │ ├── HeaderNames.cs │ ├── Host.cs │ ├── ICodeFeatureState.cs │ ├── ICodeFeatureStateCacheLoaded.cs │ ├── ICodeFeatureStateCacheUpdated.cs │ ├── ICodeFeatureStateUpdated.cs │ ├── ICodeSwitchEvaluated.cs │ ├── IContextCodeFeatureStateCacheLoaded.cs │ ├── IContextCodeFeatureStateCacheUpdated.cs │ ├── IContextCodeFeatureStateUpdated.cs │ ├── IHost.cs │ ├── IUpdateCodeFeature.cs │ ├── IUpdateContextCodeFeature.cs │ ├── UpdateCodeFeature.cs │ └── UpdateContextCodeFeature.cs ├── DateTimeSwitchExtensions.cs ├── DefaultContextProvider.cs ├── Dependents │ ├── DependentCodeSwitch.cs │ ├── DependentCodeSwitch.tt │ ├── DependentCodeSwitchFactory.cs │ ├── DependentCodeSwitchFactory.tt │ ├── IDependentCodeSwitchFactory.cs │ └── IDependentCodeSwitchFactory.tt ├── DistinctCodeSwitchEvaluationObserver.cs ├── Exceptions │ ├── CacheProviderSourceException.cs │ ├── ContextSwitchException.cs │ └── FooidityException.cs ├── Fooidity.csproj ├── Fooidity.csproj.DotSettings ├── ICodeFeature.cs ├── ICodeFeatureStateCache.cs ├── ICodeSwitch.cs ├── ICodeSwitchContainerScope.cs ├── ICodeSwitchEventHandler.cs ├── ICodeSwitchFactory.cs ├── ICodeSwitchesEvaluated.cs ├── IContextCodeSwitch.cs ├── IContextFeatureStateCache.cs ├── IContextKeyProvider.cs ├── IContextProvider.cs ├── IToggleCodeSwitch.cs ├── IfExtensions.cs ├── IfExtensions.tt ├── Metadata │ ├── CodeFeatureMetadata.cs │ ├── ContextMetadata.cs │ ├── HostMetadata.cs │ ├── ICodeFeatureMetadata.cs │ ├── IContextMetadata.cs │ └── IHostMetadata.cs ├── ObjectContextProvider.cs ├── SecurityCodeSwitchFactoryExtensions.cs ├── TypeUrn.cs ├── TypeUrnParser.cs └── ValueTypeContextProvider.cs └── packages └── repositories.config /.gitattributes: -------------------------------------------------------------------------------- 1 | *.doc diff=astextplain 2 | *.DOC diff=astextplain 3 | *.docx diff=astextplain 4 | *.DOCX diff=astextplain 5 | *.dot diff=astextplain 6 | *.DOT diff=astextplain 7 | *.pdf diff=astextplain 8 | *.PDF diff=astextplain 9 | *.rtf diff=astextplain 10 | *.RTF diff=astextplain 11 | 12 | *.jpg binary 13 | *.png binary 14 | *.gif binary 15 | 16 | core.eol crlf 17 | 18 | *.cs diff=csharp 19 | 20 | *.csproj merge=union 21 | *.vbproj merge=union 22 | *.fsproj merge=union 23 | *.dbproj merge=union 24 | *.sln merge=union -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build_artifacts/* 2 | build_output/* 3 | 4 | **/*.suo 5 | **/**/*.suo 6 | **/*.user 7 | **/**/*.user 8 | 9 | csx 10 | rcf 11 | 12 | bin 13 | obj 14 | _ReSharper* 15 | *.dotCover 16 | 17 | *.csproj.user 18 | *.resharper.user 19 | *.ReSharper.user 20 | *.cache 21 | *~ 22 | *.swp 23 | *.bak 24 | *.orig 25 | *.user 26 | 27 | *.nupkg 28 | src/.nuget/nuget.exe 29 | src/packages/**/* 30 | docs/build/**/* 31 | 32 | .DS_Store 33 | .fake 34 | .vs 35 | src/Backup 36 | 37 | TestResult.xml 38 | submit.xml 39 | src/tests/* 40 | tests/* 41 | SolutionVersion.cs 42 | -------------------------------------------------------------------------------- /.semver: -------------------------------------------------------------------------------- 1 | --- 2 | :major: 1 3 | :minor: 0 4 | :patch: 1 5 | :special: '' 6 | :metadata: '' 7 | -------------------------------------------------------------------------------- /Fooidity.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phatboyg/Fooidity/a55ea9391773903eab0e6b93a08951b75dd8a936/Fooidity.snk -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | cls 3 | If Not Exist src\.nuget\nuget.exe msbuild src\.nuget\NuGet.targets -Target:RestorePackages 4 | If Not Exist src\packages\FAKE\tools\fake.exe src\.nuget\nuget.exe Install FAKE -Source "https://www.nuget.org/api/v2/" -OutputDirectory "src\packages" -ExcludeVersion 5 | src\packages\FAKE\tools\fake.exe build.fsx %* 6 | -------------------------------------------------------------------------------- /build_support/util.rb: -------------------------------------------------------------------------------- 1 | def waitfor(&block) 2 | checks = 0 3 | 4 | until block.call || checks >10 5 | sleep 0.5 6 | checks += 1 7 | end 8 | 9 | raise 'Waitfor timeout expired. Make sure that you aren\'t running something from the build output folders, or that you have browsed to it through Explorer.' if checks > 10 10 | end 11 | 12 | def get_commit_hash_and_date 13 | begin 14 | commit = `git log -1 --pretty=format:%H` 15 | git_date = `git log -1 --date=iso --pretty=format:%ad` 16 | commit_date = DateTime.parse( git_date ).strftime("%Y-%m-%d %H%M%S") 17 | rescue 18 | commit = "git unavailable" 19 | end 20 | 21 | [commit, commit_date] 22 | end -------------------------------------------------------------------------------- /build_support/versioning.rb: -------------------------------------------------------------------------------- 1 | require 'semver' 2 | 3 | def commit_data 4 | begin 5 | commit = `git rev-parse --short HEAD`.chomp()[0,6] 6 | git_date = `git log -1 --date=iso --pretty=format:%ad` 7 | commit_date = DateTime.parse( git_date ).strftime("%Y-%m-%d %H%M%S") 8 | rescue Exception => e 9 | puts e.inspect 10 | commit = (ENV['BUILD_VCS_NUMBER'] || "000000")[0,6] 11 | commit_date = Time.new.strftime("%Y-%m-%d %H%M%S") 12 | end 13 | [commit, commit_date] 14 | end 15 | 16 | task :versioning do 17 | ver = SemVer.find 18 | revision = (ENV['BUILD_NUMBER'] || ver.patch).to_i 19 | var = SemVer.new(ver.major, ver.minor, revision, ver.special) 20 | 21 | # extensible number w/ git hash 22 | ENV['BUILD_VERSION'] = BUILD_VERSION = ver.format("%M.%m.%p%s") + ".#{commit_data()[0]}" 23 | 24 | # nuget (not full semver 2.0.0-rc.1 support) see http://nuget.codeplex.com/workitem/1796 25 | ENV['NUGET_VERSION'] = NUGET_VERSION = ver.format("%M.%m.%p%s") 26 | 27 | # purely M.m.p format 28 | ENV['FORMAL_VERSION'] = FORMAL_VERSION = "#{ SemVer.new(ver.major, ver.minor, revision).format "%M.%m.%p"}" 29 | puts "##teamcity[buildNumber '#{BUILD_VERSION}']" # tell teamcity our decision 30 | end -------------------------------------------------------------------------------- /install.bat: -------------------------------------------------------------------------------- 1 | "src\.nuget\NuGet.exe" "Install" "NUnit.Runners" "-OutputDirectory" "src\packages" "-ExcludeVersion" 2 | "src\.nuget\NuGet.exe" "Install" "FAKE" "-OutputDirectory" "src\packages" "-ExcludeVersion" 3 | "src\packages\FAKE\tools\Fake.exe" build.fsx 4 | -------------------------------------------------------------------------------- /src/.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/.nuget/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Fooidity.AutofacIntegration/CodeSwitchContainerScope.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | using Autofac; 4 | 5 | 6 | public class CodeSwitchContainerScope : 7 | ICodeSwitchContainerScope 8 | { 9 | readonly ILifetimeScope _scope; 10 | 11 | public CodeSwitchContainerScope(ILifetimeScope scope) 12 | { 13 | _scope = scope; 14 | } 15 | 16 | public void Dispose() 17 | { 18 | _scope.Dispose(); 19 | } 20 | 21 | public ICodeSwitchContainerScope CreateContainerScope() 22 | { 23 | return new CodeSwitchContainerScope(_scope.BeginLifetimeScope()); 24 | } 25 | 26 | public ICodeSwitchContainerScope CreateContainerScope(TContext context) 27 | where TContext : class 28 | { 29 | return new CodeSwitchContainerScope(_scope.BeginLifetimeScope(x => 30 | { 31 | x.RegisterInstance(context); 32 | })); 33 | } 34 | 35 | public bool TryResolve(out T instance) 36 | where T : class 37 | { 38 | return _scope.TryResolve(out instance); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/Fooidity.AutofacIntegration/CodeSwitchEvaluationTrackingExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using Autofac; 6 | using Contracts; 7 | 8 | 9 | public static class CodeSwitchEvaluationTrackingExtensions 10 | { 11 | public static void EnableCodeSwitchTracking(this ContainerBuilder builder) 12 | { 13 | builder.RegisterType() 14 | .As>() 15 | .As() 16 | .InstancePerLifetimeScope(); 17 | } 18 | 19 | public static IEnumerable GetEvaluatedCodeSwitches(this ILifetimeScope scope) 20 | { 21 | ICodeSwitchesEvaluated result; 22 | if (scope.TryResolve(out result)) 23 | return result; 24 | 25 | throw new FooidityException( 26 | "Code switch tracking is not enabled. Enable it while building the container using EnableCodeSwitchTracking"); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/Fooidity.AutofacIntegration/Modules/ConfigurationCodeFeatureCacheModule.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Modules 2 | { 3 | using Autofac; 4 | using Caching; 5 | using Configuration; 6 | 7 | 8 | /// 9 | /// Registers the types required to load the code feature cache via the App.Config 10 | /// 11 | public class ConfigurationCodeFeatureCacheModule : 12 | Module 13 | { 14 | protected override void Load(ContainerBuilder builder) 15 | { 16 | builder.RegisterType() 17 | .As() 18 | .As() 19 | .As() 20 | .SingleInstance(); 21 | 22 | builder.RegisterType() 23 | .As(); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/Fooidity.AutofacIntegration/Modules/ConfigurationContextFeatureCacheModule.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Modules 2 | { 3 | using Autofac; 4 | using Caching; 5 | using Configuration; 6 | 7 | 8 | /// 9 | /// Registers the types required to resolve the context cache for a given context type 10 | /// 11 | /// 12 | /// 13 | public class ConfigurationContextFeatureCacheModule : 14 | Module 15 | where TKeyProvider : class, IContextKeyProvider 16 | { 17 | protected override void Load(ContainerBuilder builder) 18 | { 19 | builder.RegisterType() 20 | .As>(); 21 | 22 | builder.RegisterType>() 23 | .As>() 24 | .As() 25 | .As() 26 | .SingleInstance(); 27 | 28 | builder.RegisterType>() 29 | .As>(); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/Fooidity.AutofacIntegration/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Fooidity.AzureIntegration.Tests/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Fooidity.AzureIntegration.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/Fooidity.AzureIntegration/CloudCodeFeatureStateCacheProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.AzureIntegration 2 | { 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | using Caching; 6 | using Entities; 7 | using Microsoft.WindowsAzure.Storage.Table; 8 | 9 | 10 | public class CloudCodeFeatureStateCacheProvider : 11 | ICodeFeatureStateCacheProvider 12 | { 13 | readonly ICloudTableProvider _tableProvider; 14 | 15 | public CloudCodeFeatureStateCacheProvider(ICloudTableProvider tableProvider) 16 | { 17 | _tableProvider = tableProvider; 18 | } 19 | 20 | public async Task GetDefaultState() 21 | { 22 | return false; 23 | } 24 | 25 | public async Task> Load() 26 | { 27 | CloudTable table = _tableProvider.GetTable("codeFeatureState"); 28 | 29 | TableQuery query = new TableQuery() 30 | .Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "Current")); 31 | 32 | return await table.ExecuteQueryAsync(query, 33 | entity => (ICachedCodeFeatureState)new CachedCodeFeatureState(new CodeFeatureId(entity.CodeFeatureId), entity.Enabled)); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/Fooidity.AzureIntegration/CloudContextFeatureStateCacheProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.AzureIntegration 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Threading.Tasks; 6 | using Caching; 7 | using Entities; 8 | using Microsoft.WindowsAzure.Storage.Table; 9 | 10 | 11 | public class CloudContextFeatureStateCacheProvider : 12 | IContextFeatureStateCacheProvider 13 | { 14 | readonly ICloudTableProvider _tableProvider; 15 | 16 | public CloudContextFeatureStateCacheProvider(ICloudTableProvider tableProvider) 17 | { 18 | _tableProvider = tableProvider; 19 | } 20 | 21 | public async Task>> Load() 22 | { 23 | CloudTable table = _tableProvider.GetTable("contextFeatureState"); 24 | 25 | TableQuery query = new TableQuery() 26 | .Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "Current")); 27 | 28 | return await table.ExecuteQueryAsync(query, 29 | entity => Tuple.Create(entity.ContextKey, 30 | (ICachedCodeFeatureState)new CachedCodeFeatureState(new CodeFeatureId(entity.CodeFeatureId), entity.Enabled))); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/Fooidity.AzureIntegration/ConfigurationCloudStorageAccountProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.AzureIntegration 2 | { 3 | using System; 4 | using Microsoft.Azure; 5 | using Microsoft.WindowsAzure.Storage; 6 | 7 | 8 | public class ConfigurationCloudStorageAccountProvider : 9 | ICloudStorageAccountProvider 10 | { 11 | readonly string _connectionName; 12 | readonly Lazy _value; 13 | 14 | public ConfigurationCloudStorageAccountProvider(string connectionName) 15 | { 16 | _connectionName = connectionName; 17 | _value = new Lazy(GetConfiguredStorageAccount); 18 | } 19 | 20 | public CloudStorageAccount GetStorageAccount() 21 | { 22 | return _value.Value; 23 | } 24 | 25 | CloudStorageAccount GetConfiguredStorageAccount() 26 | { 27 | string connectionString = CloudConfigurationManager.GetSetting(_connectionName); 28 | 29 | return CloudStorageAccount.Parse(connectionString); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/Fooidity.AzureIntegration/Entities/CodeFeatureStateEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.AzureIntegration.Entities 2 | { 3 | using System; 4 | using Microsoft.WindowsAzure.Storage.Table; 5 | 6 | 7 | public class CodeFeatureStateEntity : 8 | TableEntity 9 | { 10 | public CodeFeatureStateEntity() 11 | { 12 | } 13 | 14 | public CodeFeatureStateEntity(Uri codeFeatureId, DateTime timestamp, bool enabled, Guid? commandId = null) 15 | { 16 | if (codeFeatureId == null) 17 | throw new ArgumentNullException("codeFeatureId"); 18 | 19 | CodeFeatureId = codeFeatureId.ToString(); 20 | Enabled = enabled; 21 | 22 | CommandId = commandId; 23 | 24 | PartitionKey = CodeFeatureId; 25 | RowKey = timestamp.ToDescendingTimestamp(); 26 | Timestamp = timestamp; 27 | } 28 | 29 | /// 30 | /// The CodeFeatureId for this entity 31 | /// 32 | public string CodeFeatureId { get; set; } 33 | 34 | /// 35 | /// If the state is enabled or disabled 36 | /// 37 | public bool Enabled { get; set; } 38 | 39 | /// 40 | /// The command-id associated with this state change 41 | /// 42 | public Guid? CommandId { get; set; } 43 | } 44 | } -------------------------------------------------------------------------------- /src/Fooidity.AzureIntegration/ICloudStorageAccountProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.AzureIntegration 2 | { 3 | using Microsoft.WindowsAzure.Storage; 4 | 5 | 6 | public interface ICloudStorageAccountProvider 7 | { 8 | CloudStorageAccount GetStorageAccount(); 9 | } 10 | } -------------------------------------------------------------------------------- /src/Fooidity.AzureIntegration/ICloudTableProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.AzureIntegration 2 | { 3 | using Microsoft.WindowsAzure.Storage.Table; 4 | 5 | 6 | /// 7 | /// Returns a cloud table, given the table name, configured for the entity type 8 | /// 9 | public interface ICloudTableProvider 10 | { 11 | CloudTable GetTable(string tableName); 12 | } 13 | } -------------------------------------------------------------------------------- /src/Fooidity.AzureIntegration/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/Fooidity.Client.AutofacIntegration/FooidityClientRegistrationExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | using System; 4 | using Autofac; 5 | using Client.AutofacIntegration; 6 | using Client.Configuration; 7 | 8 | 9 | public static class FooidityClientRegistrationExtensions 10 | { 11 | public static void ConfigureFoodityClient(this ContainerBuilder builder, Action configureClient) 12 | { 13 | var configurator = new AutofacClientConfigurator(builder); 14 | 15 | configureClient(configurator); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/Fooidity.Client.AutofacIntegration/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Fooidity.Client.Tests/Configuration_Specs.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Client.Tests 2 | { 3 | using Autofac; 4 | using AutofacIntegration; 5 | using ClientSwitches; 6 | using NUnit.Framework; 7 | 8 | namespace ClientSwitches 9 | { 10 | public struct Feature_SupportSSL : 11 | ICodeFeature 12 | { 13 | } 14 | } 15 | 16 | 17 | [TestFixture, Explicit] 18 | public class Configuring_the_fooidity_client 19 | { 20 | [Test] 21 | public void Should_have_a_factory_syntax() 22 | { 23 | ICodeSwitch codeSwitch; 24 | Assert.IsTrue(_container.TryResolve(out codeSwitch)); 25 | 26 | Assert.IsFalse(codeSwitch.Enabled); 27 | } 28 | 29 | IContainer _container; 30 | 31 | [TestFixtureSetUp] 32 | public void Setup() 33 | { 34 | var builder = new ContainerBuilder(); 35 | 36 | builder.ConfigureFoodityClient(x => 37 | { 38 | x.Host("http://api.fooidity.com/"); 39 | x.ApplicationKey("[need application id]"); 40 | }); 41 | 42 | builder.RegisterCodeSwitch(); 43 | 44 | _container = builder.Build(); 45 | } 46 | 47 | [TestFixtureTearDown] 48 | public void Teardown() 49 | { 50 | if (_container != null) 51 | _container.Dispose(); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/Fooidity.Client.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/Fooidity.Client/ApplicationHubCodeFeatureStateCacheProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Client 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using Caching; 8 | using Contracts; 9 | 10 | 11 | public class ApplicationHubCodeFeatureStateCacheProvider : 12 | ICodeFeatureStateCacheProvider 13 | { 14 | readonly IApplicationHubProxy _proxy; 15 | 16 | public ApplicationHubCodeFeatureStateCacheProvider(IApplicationHubProxy proxy) 17 | { 18 | _proxy = proxy; 19 | } 20 | 21 | public async Task GetDefaultState() 22 | { 23 | return false; 24 | } 25 | 26 | public async Task> Load() 27 | { 28 | try 29 | { 30 | IEnumerable states = 31 | await _proxy.UseProxy(x => x.Invoke>("GetCodeFeatureStates")); 32 | 33 | return states.Select(x => new CachedCodeFeatureState(x.CodeFeatureId, x.Enabled)); 34 | } 35 | catch (Exception ex) 36 | { 37 | throw new CacheProviderSourceException("The code feature cache source was unavailable", ex); 38 | } 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/Fooidity.Client/ApplicationHubCodeSwitchEventHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Client 2 | { 3 | using System.Threading.Tasks; 4 | using Contracts; 5 | 6 | 7 | public class ApplicationHubCodeSwitchEventHandler : 8 | ICodeSwitchEventHandler 9 | { 10 | readonly IApplicationHubProxy _applicationHub; 11 | 12 | public ApplicationHubCodeSwitchEventHandler(IApplicationHubProxy applicationHub) 13 | { 14 | _applicationHub = applicationHub; 15 | } 16 | 17 | public async Task Handle(ICodeSwitchEvaluated message) 18 | { 19 | await _applicationHub.UseProxy(x => x.Invoke("OnCodeSwitchEvaluated", message)); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/Fooidity.Client/Configuration/ClientSettings.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Client.Configuration 2 | { 3 | public class ClientSettings : 4 | IClientSettings 5 | { 6 | public string HostAddress { get; set; } 7 | public string ApplicationKey { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /src/Fooidity.Client/Configuration/IClientConfigurator.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Client.Configuration 2 | { 3 | public interface IClientConfigurator 4 | { 5 | void Host(string hostAddress); 6 | void ApplicationKey(string applicationKey); 7 | } 8 | } -------------------------------------------------------------------------------- /src/Fooidity.Client/Configuration/IClientSettings.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Client.Configuration 2 | { 3 | public interface IClientSettings 4 | { 5 | string HostAddress { get; } 6 | string ApplicationKey { get; } 7 | } 8 | } -------------------------------------------------------------------------------- /src/Fooidity.Client/FooidityClient.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Client 2 | { 3 | public class FooidityClient : 4 | IFooidityClient 5 | { 6 | readonly IApplicationHubProxy _applicationHub; 7 | 8 | public FooidityClient(IApplicationHubProxy applicationHub) 9 | { 10 | _applicationHub = applicationHub; 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /src/Fooidity.Client/HubConnectionEventPublisher.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Client 2 | { 3 | using System; 4 | using Microsoft.AspNet.SignalR.Client; 5 | 6 | 7 | public class HubConnectionEventPublisher : 8 | IDisposable 9 | { 10 | readonly HubConnection _hubConnection; 11 | 12 | public HubConnectionEventPublisher(HubConnection hubConnection) 13 | { 14 | _hubConnection = hubConnection; 15 | 16 | hubConnection.Error += PublishError; 17 | hubConnection.ConnectionSlow += PublishSlow; 18 | hubConnection.StateChanged += PublishStateChange; 19 | hubConnection.Closed += PublishClosed; 20 | hubConnection.Reconnecting += PublishReconnecting; 21 | hubConnection.Reconnected += PublishReconnected; 22 | } 23 | 24 | public void Dispose() 25 | { 26 | } 27 | 28 | void PublishReconnected() 29 | { 30 | } 31 | 32 | void PublishReconnecting() 33 | { 34 | } 35 | 36 | void PublishClosed() 37 | { 38 | } 39 | 40 | void PublishStateChange(StateChange stateChange) 41 | { 42 | } 43 | 44 | void PublishSlow() 45 | { 46 | } 47 | 48 | void PublishError(Exception exception) 49 | { 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/Fooidity.Client/HubConnectionProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Client 2 | { 3 | using Configuration; 4 | using Contracts; 5 | using Microsoft.AspNet.SignalR.Client; 6 | 7 | 8 | /// 9 | /// Creates a hub connection using the client settings 10 | /// 11 | public class HubConnectionProvider : 12 | IHubConnectionProvider 13 | { 14 | readonly IClientSettings _settings; 15 | 16 | public HubConnectionProvider(IClientSettings settings) 17 | { 18 | _settings = settings; 19 | } 20 | 21 | public HubConnection GetConnection() 22 | { 23 | var hubConnection = new HubConnection(_settings.HostAddress); 24 | 25 | hubConnection.Headers.Add(Headers.FooidityAppKey, _settings.ApplicationKey); 26 | 27 | return hubConnection; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/Fooidity.Client/IApplicationHubEventConnector.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Client 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using Microsoft.AspNet.SignalR.Client; 6 | 7 | 8 | public interface IApplicationHubEventConnector 9 | { 10 | IEnumerable Connect(IHubProxy hubProxy); 11 | } 12 | } -------------------------------------------------------------------------------- /src/Fooidity.Client/IApplicationHubProxy.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Client 2 | { 3 | using System; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNet.SignalR.Client; 6 | 7 | 8 | public interface IApplicationHubProxy 9 | { 10 | Task UseProxy(Func> callback); 11 | Task UseProxy(Func callback); 12 | } 13 | } -------------------------------------------------------------------------------- /src/Fooidity.Client/IFooidityClient.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Client 2 | { 3 | public interface IFooidityClient 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /src/Fooidity.Client/IHubConnectionProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Client 2 | { 3 | using Microsoft.AspNet.SignalR.Client; 4 | 5 | 6 | public interface IHubConnectionProvider 7 | { 8 | HubConnection GetConnection(); 9 | } 10 | } -------------------------------------------------------------------------------- /src/Fooidity.Client/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/Fooidity.CloudService/ServiceConfiguration.Cloud.cscfg: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Fooidity.CloudService/ServiceConfiguration.Local.cscfg: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Fooidity.CloudService/ServiceDefinition.csdef: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/Fooidity.ContainerTests/Contexts/UserContext.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.ContainerTests.Contexts 2 | { 3 | public class UserContext 4 | { 5 | public string Name { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /src/Fooidity.ContainerTests/Contexts/UserContextKeyProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.ContainerTests.Contexts 2 | { 3 | public class UserContextKeyProvider : 4 | IContextKeyProvider 5 | { 6 | public string GetKey(UserContext context) 7 | { 8 | return context.Name; 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /src/Fooidity.ContainerTests/Features/DbEnabled.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.ContainerTests.Features 2 | { 3 | public struct DbEnabled : 4 | ICodeFeature 5 | { 6 | } 7 | } -------------------------------------------------------------------------------- /src/Fooidity.ContainerTests/Features/UseNewClass.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.ContainerTests.Features 2 | { 3 | public struct UseNewClass : 4 | ICodeFeature 5 | { 6 | } 7 | } -------------------------------------------------------------------------------- /src/Fooidity.ContainerTests/Features/UseNewCodePath.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.ContainerTests.Features 2 | { 3 | public struct UseNewCodePath : 4 | ICodeFeature 5 | { 6 | } 7 | } -------------------------------------------------------------------------------- /src/Fooidity.ContainerTests/Features/UseNewMethod.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.ContainerTests.Features 2 | { 3 | public struct UseNewMethod : 4 | ICodeFeature 5 | { 6 | } 7 | } -------------------------------------------------------------------------------- /src/Fooidity.ContainerTests/Subjects/ConditionalClass.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.ContainerTests.Subjects 2 | { 3 | using Features; 4 | 5 | 6 | public class ConditionalClass 7 | { 8 | readonly ICodeSwitch _useNewMethod; 9 | 10 | public ConditionalClass(ICodeSwitch useNewMethod) 11 | { 12 | _useNewMethod = useNewMethod; 13 | } 14 | 15 | public void MethodCall(int value, string text) 16 | { 17 | _useNewMethod.If(MethodCallV2, MethodCallOld, value, text); 18 | } 19 | 20 | void MethodCallOld(int value, string text) 21 | { 22 | } 23 | 24 | void MethodCallV2(int value, string text) 25 | { 26 | } 27 | 28 | public string FunctionCall(int value, string text) 29 | { 30 | return _useNewMethod.Iff(FunctionCallV2, FunctionCallOld, value, text); 31 | } 32 | 33 | string FunctionCallOld(int value, string text) 34 | { 35 | return string.Format("Old: {0}, {1}", value, text); 36 | } 37 | 38 | string FunctionCallV2(int value, string text) 39 | { 40 | return string.Format("V2: {0}, {1}", value, text); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/Fooidity.ContainerTests/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/Fooidity.ContainerTests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/Entities/ApplicationCodeFeatureEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.Entities 2 | { 3 | using Microsoft.WindowsAzure.Storage.Table; 4 | 5 | /// 6 | /// A code feature reported by an application, purely for inventory purposes. 7 | /// The timestamp is the last time it was reported by an application 8 | /// 9 | public class ApplicationCodeFeatureEntity : 10 | TableEntity 11 | { 12 | public ApplicationCodeFeatureEntity() 13 | { 14 | } 15 | 16 | public ApplicationCodeFeatureEntity(string applicationId, string codeFeatureId) 17 | { 18 | CodeFeatureId = codeFeatureId; 19 | ApplicationId = applicationId; 20 | 21 | PartitionKey = ApplicationId; 22 | RowKey = CodeFeatureId; 23 | } 24 | 25 | /// 26 | /// The CodeFeatureId for this entity 27 | /// 28 | public string CodeFeatureId { get; set; } 29 | 30 | public string ApplicationId { get; set; } 31 | } 32 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/Entities/ApplicationContextEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.Entities 2 | { 3 | using Microsoft.WindowsAzure.Storage.Table; 4 | 5 | 6 | /// 7 | /// A code feature reported by an application, purely for inventory purposes. 8 | /// The timestamp is the last time it was reported by an application 9 | /// 10 | public class ApplicationContextEntity : 11 | TableEntity 12 | { 13 | public ApplicationContextEntity() 14 | { 15 | } 16 | 17 | public ApplicationContextEntity(string applicationId, string contextId) 18 | { 19 | ContextId = contextId; 20 | ApplicationId = applicationId; 21 | 22 | PartitionKey = ApplicationId; 23 | RowKey = ContextId; 24 | } 25 | 26 | /// 27 | /// The CodeFeatureId for this entity 28 | /// 29 | public string ContextId { get; set; } 30 | 31 | public string ApplicationId { get; set; } 32 | } 33 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/Entities/ApplicationEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.Entities 2 | { 3 | using System; 4 | using Fooidity.AzureIntegration; 5 | using Microsoft.WindowsAzure.Storage.Table; 6 | using Models; 7 | using UserStore; 8 | 9 | 10 | public class ApplicationEntity : 11 | TableEntity, 12 | Application 13 | { 14 | public ApplicationEntity() 15 | { 16 | } 17 | 18 | public ApplicationEntity(string applicationName, DateTime timestamp) 19 | { 20 | Id = Guid.NewGuid().ToByteArray().ToBase32(); 21 | Name = applicationName; 22 | 23 | PartitionKey = Id; 24 | RowKey = timestamp.ToDescendingTimestamp(); 25 | Timestamp = timestamp; 26 | } 27 | 28 | public string Id { get; set; } 29 | public string Name { get; set; } 30 | } 31 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/Entities/KeyOrganizationApplicationIndexEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.Entities 2 | { 3 | using System; 4 | using Microsoft.WindowsAzure.Storage.Table; 5 | using Models; 6 | 7 | 8 | public class KeyOrganizationApplicationIndexEntity : 9 | TableEntity, 10 | IOrganizationApplicationKey 11 | { 12 | public KeyOrganizationApplicationIndexEntity() 13 | { 14 | } 15 | 16 | public KeyOrganizationApplicationIndexEntity(string key, string organizationId, string organizationName, string applicationId, 17 | string applicationName, DateTime timestamp) 18 | { 19 | Key = key; 20 | OrganizationId = organizationId; 21 | OrganizationName = organizationName; 22 | ApplicationId = applicationId; 23 | ApplicationName = applicationName; 24 | Timestamp = timestamp; 25 | 26 | PartitionKey = Key; 27 | RowKey = ApplicationId; 28 | } 29 | 30 | public string Key { get; set; } 31 | public string OrganizationId { get; set; } 32 | public string OrganizationName { get; set; } 33 | public string ApplicationId { get; set; } 34 | public string ApplicationName { get; set; } 35 | } 36 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/Entities/OrganizationApplicationIndexEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.Entities 2 | { 3 | using System; 4 | using Microsoft.WindowsAzure.Storage.Table; 5 | using Models; 6 | 7 | 8 | public class OrganizationApplicationIndexEntity : 9 | TableEntity, 10 | IOrganizationApplication 11 | { 12 | public OrganizationApplicationIndexEntity() 13 | { 14 | } 15 | 16 | public OrganizationApplicationIndexEntity(string organizationId, string organizationName, string applicationId, string applicationName, DateTime timestamp) 17 | { 18 | OrganizationId = organizationId; 19 | OrganizationName = organizationName; 20 | ApplicationId = applicationId; 21 | ApplicationName = applicationName; 22 | Timestamp = timestamp; 23 | 24 | PartitionKey = OrganizationId; 25 | RowKey = ApplicationId; 26 | } 27 | 28 | public string OrganizationId { get; set; } 29 | public string OrganizationName { get; set; } 30 | public string ApplicationId { get; set; } 31 | public string ApplicationName { get; set; } 32 | } 33 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/Entities/OrganizationApplicationKeyEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.Entities 2 | { 3 | using System; 4 | using Microsoft.WindowsAzure.Storage.Table; 5 | using Models; 6 | 7 | 8 | public class OrganizationApplicationKeyEntity : 9 | TableEntity, 10 | IOrganizationApplicationKey 11 | { 12 | public OrganizationApplicationKeyEntity() 13 | { 14 | } 15 | 16 | public OrganizationApplicationKeyEntity(string key, string organizationId, string organizationName, string applicationId, 17 | string applicationName, DateTime timestamp) 18 | { 19 | Key = key; 20 | OrganizationId = organizationId; 21 | OrganizationName = organizationName; 22 | ApplicationId = applicationId; 23 | ApplicationName = applicationName; 24 | Timestamp = timestamp; 25 | 26 | PartitionKey = ApplicationId; 27 | RowKey = Key; 28 | } 29 | 30 | public string Key { get; set; } 31 | public string OrganizationId { get; set; } 32 | public string OrganizationName { get; set; } 33 | public string ApplicationId { get; set; } 34 | public string ApplicationName { get; set; } 35 | } 36 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/Entities/OrganizationEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.Entities 2 | { 3 | using System; 4 | using Fooidity.AzureIntegration; 5 | using Microsoft.WindowsAzure.Storage.Table; 6 | using Models; 7 | using UserStore; 8 | 9 | 10 | public class OrganizationEntity : 11 | TableEntity, 12 | IOrganization 13 | { 14 | public OrganizationEntity() 15 | { 16 | } 17 | 18 | public OrganizationEntity(string createdByUserId, string organizationName, DateTime timestamp) 19 | { 20 | OrganizationId = Guid.NewGuid().ToByteArray().ToBase32(); 21 | CreatedByUserId = createdByUserId; 22 | OrganizationName = organizationName; 23 | 24 | PartitionKey = OrganizationId; 25 | RowKey = timestamp.ToDescendingTimestamp(); 26 | Timestamp = timestamp; 27 | } 28 | 29 | public string OrganizationId { get; set; } 30 | public string OrganizationName { get; set; } 31 | public string CreatedByUserId { get; set; } 32 | } 33 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/Entities/OrganizationUserEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.Entities 2 | { 3 | using System; 4 | using Fooidity.AzureIntegration; 5 | using Microsoft.WindowsAzure.Storage.Table; 6 | 7 | 8 | public class OrganizationUserEntity : 9 | TableEntity 10 | { 11 | const string SeparatorString = "'\u3000"; 12 | 13 | public OrganizationUserEntity() 14 | { 15 | } 16 | 17 | public OrganizationUserEntity(DateTime timestamp, string organizationId, string userId, bool active) 18 | { 19 | if (organizationId == null) 20 | throw new ArgumentNullException("organizationId"); 21 | if (userId == null) 22 | throw new ArgumentNullException("userId"); 23 | 24 | Active = active; 25 | OrganizationId = organizationId; 26 | UserId = userId; 27 | 28 | PartitionKey = FormatPartitionKey(organizationId, userId); 29 | RowKey = timestamp.ToDescendingTimestamp(); 30 | Timestamp = timestamp; 31 | } 32 | 33 | public string OrganizationId { get; set; } 34 | public string UserId { get; set; } 35 | public bool Active { get; set; } 36 | 37 | public static string FormatPartitionKey(string organizationId, string userId) 38 | { 39 | return string.Join(SeparatorString, organizationId, userId); 40 | ; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/Entities/UserApplicationIndexEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.Entities 2 | { 3 | using System; 4 | using Microsoft.WindowsAzure.Storage.Table; 5 | using Models; 6 | 7 | 8 | public class UserApplicationIndexEntity : 9 | TableEntity, 10 | IUserOrganizationApplication 11 | { 12 | public UserApplicationIndexEntity() 13 | { 14 | } 15 | 16 | public UserApplicationIndexEntity(string userId, string organizationId, string organizationName, string applicationId, 17 | string applicationName, DateTime timestamp) 18 | { 19 | UserId = userId; 20 | OrganizationId = organizationId; 21 | OrganizationName = organizationName; 22 | ApplicationId = applicationId; 23 | ApplicationName = applicationName; 24 | Timestamp = timestamp; 25 | 26 | PartitionKey = UserId; 27 | RowKey = ApplicationId; 28 | } 29 | 30 | public string UserId { get; set; } 31 | public string OrganizationId { get; set; } 32 | public string OrganizationName { get; set; } 33 | public string ApplicationId { get; set; } 34 | public string ApplicationName { get; set; } 35 | } 36 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/Entities/UserOrganizationIndexEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.Entities 2 | { 3 | using System; 4 | using Microsoft.WindowsAzure.Storage.Table; 5 | using Models; 6 | 7 | 8 | public class UserOrganizationIndexEntity : 9 | TableEntity, 10 | IOrganization 11 | { 12 | public UserOrganizationIndexEntity() 13 | { 14 | } 15 | 16 | public UserOrganizationIndexEntity(DateTime timestamp, string userId, string organizationId, string organizationName, 17 | string createdByUserId, bool active) 18 | { 19 | if (userId == null) 20 | throw new ArgumentNullException("userId"); 21 | if (organizationId == null) 22 | throw new ArgumentNullException("organizationId"); 23 | 24 | Active = active; 25 | OrganizationName = organizationName; 26 | CreatedByUserId = createdByUserId; 27 | OrganizationId = organizationId; 28 | UserId = userId; 29 | 30 | PartitionKey = userId; 31 | RowKey = organizationId; 32 | Timestamp = timestamp; 33 | } 34 | 35 | public string UserId { get; set; } 36 | public bool Active { get; set; } 37 | public string OrganizationId { get; set; } 38 | public string OrganizationName { get; set; } 39 | public string CreatedByUserId { get; set; } 40 | } 41 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/Exceptions/ApplicationNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.Exceptions 2 | { 3 | using System; 4 | using System.Runtime.Serialization; 5 | 6 | 7 | [Serializable] 8 | public class ApplicationNotFoundException : 9 | Exception 10 | { 11 | public ApplicationNotFoundException(string userId, string applicationId) 12 | : this(string.Format("The application {0} was not found for user {1}", applicationId, userId)) 13 | { 14 | } 15 | 16 | public ApplicationNotFoundException() 17 | { 18 | } 19 | 20 | public ApplicationNotFoundException(string message) 21 | : base(message) 22 | { 23 | } 24 | 25 | public ApplicationNotFoundException(string message, Exception innerException) 26 | : base(message, innerException) 27 | { 28 | } 29 | 30 | protected ApplicationNotFoundException(SerializationInfo info, StreamingContext context) 31 | : base(info, context) 32 | { 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/Exceptions/DuplicateEmailException.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.Exceptions 2 | { 3 | using System; 4 | using System.Runtime.Serialization; 5 | 6 | 7 | [Serializable] 8 | public class DuplicateEmailException : 9 | Exception 10 | { 11 | public DuplicateEmailException() 12 | { 13 | } 14 | 15 | public DuplicateEmailException(string message) 16 | : base(message) 17 | { 18 | } 19 | 20 | public DuplicateEmailException(string message, Exception innerException) 21 | : base(message, innerException) 22 | { 23 | } 24 | 25 | protected DuplicateEmailException(SerializationInfo info, StreamingContext context) 26 | : base(info, context) 27 | { 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/Exceptions/DuplicateUsernameException.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.Exceptions 2 | { 3 | using System; 4 | using System.Runtime.Serialization; 5 | 6 | 7 | [Serializable] 8 | public class DuplicateUsernameException : 9 | Exception 10 | { 11 | public DuplicateUsernameException() 12 | { 13 | } 14 | 15 | public DuplicateUsernameException(string message) 16 | : base(message) 17 | { 18 | } 19 | 20 | public DuplicateUsernameException(string message, Exception innerException) 21 | : base(message, innerException) 22 | { 23 | } 24 | 25 | protected DuplicateUsernameException(SerializationInfo info, StreamingContext context) 26 | : base(info, context) 27 | { 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/Exceptions/FeatureNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.Exceptions 2 | { 3 | using System; 4 | using System.Runtime.Serialization; 5 | 6 | 7 | [Serializable] 8 | public class FeatureNotFoundException : 9 | Exception 10 | { 11 | public FeatureNotFoundException(string userId, string applicationId, string codeFeatureId) 12 | : this(string.Format("The code feature {2} in application {0} was not found for user {1}", applicationId, userId, codeFeatureId) 13 | ) 14 | { 15 | } 16 | 17 | public FeatureNotFoundException() 18 | { 19 | } 20 | 21 | public FeatureNotFoundException(string message) 22 | : base(message) 23 | { 24 | } 25 | 26 | public FeatureNotFoundException(string message, Exception innerException) 27 | : base(message, innerException) 28 | { 29 | } 30 | 31 | protected FeatureNotFoundException(SerializationInfo info, StreamingContext context) 32 | : base(info, context) 33 | { 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/Exceptions/OrganizationNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.Exceptions 2 | { 3 | using System; 4 | using System.Runtime.Serialization; 5 | 6 | 7 | [Serializable] 8 | public class OrganizationNotFoundException : 9 | Exception 10 | { 11 | public OrganizationNotFoundException(string userId, string organizationId) 12 | : this(string.Format("The organization {0} was not found for user {1}", organizationId, userId)) 13 | { 14 | 15 | } 16 | public OrganizationNotFoundException() 17 | { 18 | } 19 | 20 | public OrganizationNotFoundException(string message) 21 | : base(message) 22 | { 23 | } 24 | 25 | public OrganizationNotFoundException(string message, Exception innerException) 26 | : base(message, innerException) 27 | { 28 | } 29 | 30 | protected OrganizationNotFoundException(SerializationInfo info, StreamingContext context) 31 | : base(info, context) 32 | { 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/IAzureManagementSettings.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration 2 | { 3 | public interface IAzureManagementSettings 4 | { 5 | string ApplicationTableName { get; } 6 | string OrganizationTableName { get; } 7 | string UserTableName { get; } 8 | string OrganizationUserTableName { get; } 9 | string UserOrganizationIndexTableName { get; } 10 | string OrganizationApplicationIndexTableName { get; } 11 | string UserApplicationIndexTableName { get; } 12 | string OrganizationApplicationKeyTableName { get; } 13 | string KeyOrganizationApplicationIndexTableName { get; } 14 | string ApplicationCodeFeatureTableName { get; } 15 | string ApplicationCodeFeatureStateTableName { get; } 16 | string ApplicationContextTableName { get; } 17 | } 18 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/UserStore/Encoding/HexBinaryEncodingFormatter.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.UserStore.Encoding 2 | { 3 | public class HexBinaryEncodingFormatter : 4 | IBinaryEncodingFormatter 5 | { 6 | readonly int _alpha; 7 | 8 | public HexBinaryEncodingFormatter(bool upperCase = false) 9 | { 10 | _alpha = upperCase ? 'A' : 'a'; 11 | } 12 | 13 | public string Format(byte[] bytes) 14 | { 15 | var result = new char[bytes.Length * 2]; 16 | 17 | int offset = 0; 18 | for (int i = 0; i < bytes.Length; i++) 19 | { 20 | byte value = bytes[i]; 21 | result[offset++] = HexToChar(value >> 4, _alpha); 22 | result[offset++] = HexToChar(value, _alpha); 23 | } 24 | 25 | return new string(result, 0, result.Length); 26 | } 27 | 28 | static char HexToChar(int value, int alpha) 29 | { 30 | value = value & 0xf; 31 | return (char)((value > 9) ? value - 10 + alpha : value + 0x30); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/UserStore/Encoding/HexBinaryEncodingParser.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.UserStore.Encoding 2 | { 3 | using System; 4 | 5 | 6 | internal class HexBinaryEncodingParser : 7 | IBinaryEncodingParser 8 | { 9 | public byte[] Parse(string input) 10 | { 11 | if (input.Length % 2 == 1) 12 | throw new Exception("The binary key cannot have an odd number of digits"); 13 | 14 | var result = new byte[input.Length >> 1]; 15 | 16 | for (int i = 0; i < input.Length >> 1; ++i) 17 | result[i] = (byte)((GetHexVal(input[i << 1]) << 4) + (GetHexVal(input[(i << 1) + 1]))); 18 | 19 | return result; 20 | } 21 | 22 | public static int GetHexVal(char hex) 23 | { 24 | int val = hex & ~0x20; 25 | return val - (val < 58 ? 48 : 55); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/UserStore/Encoding/IBinaryEncodingFormatter.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.UserStore.Encoding 2 | { 3 | public interface IBinaryEncodingFormatter 4 | { 5 | /// 6 | /// Format a byte array as an encoded string 7 | /// 8 | /// The byte array 9 | /// Returns the encoded string 10 | string Format(byte[] bytes); 11 | } 12 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/UserStore/Encoding/IBinaryEncodingParser.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.UserStore.Encoding 2 | { 3 | public interface IBinaryEncodingParser 4 | { 5 | /// 6 | /// Parse the input string into a byte array 7 | /// 8 | /// The input string 9 | /// The byte array (if the input string is null, null is returned) 10 | byte[] Parse(string input); 11 | } 12 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/UserStore/Encoding/ZBase32BinaryEncodingFormatter.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.UserStore.Encoding 2 | { 3 | public class ZBase32BinaryEncodingFormatter : 4 | Base32BinaryEncodingFormatter 5 | { 6 | // taken from analysis done at http://philzimmermann.com/docs/human-oriented-base-32-encoding.txt 7 | const string LowerCaseChars = "ybndrfg8ejkmcpqxot1uwisza345h769"; 8 | const string UpperCaseChars = "YBNDRFG8EJKMCPQXOT1UWISZA345H769"; 9 | 10 | public ZBase32BinaryEncodingFormatter(bool upperCase = false) 11 | : base(upperCase ? UpperCaseChars : LowerCaseChars) 12 | { 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/UserStore/Encoding/ZBase32BinaryEncodingParser.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.UserStore.Encoding 2 | { 3 | public class ZBase32BinaryEncodingParser : 4 | Base32BinaryEncodingParser 5 | { 6 | const string ConvertChars = "ybndrfg8ejkmcpqxot1uwisza345h769YBNDRFG8EJKMCPQXOT1UWISZA345H769"; 7 | const string TransposeChars = "ybndrfg8ejkmcpqx0tlvwis2a345h769YBNDRFG8EJKMCPQX0TLVWIS2A345H769"; 8 | 9 | public ZBase32BinaryEncodingParser(bool handleTransposedCharacters = false) 10 | : base(handleTransposedCharacters ? ConvertChars + TransposeChars : ConvertChars) 11 | { 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/UserStore/EncodingExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.UserStore 2 | { 3 | using System.Security.Cryptography; 4 | using Encoding; 5 | 6 | 7 | static class EncodingExtensions 8 | { 9 | public static string ToSha256(this string plainText) 10 | { 11 | byte[] bytes = System.Text.Encoding.UTF8.GetBytes(plainText); 12 | using (var hasher = new SHA256Managed()) 13 | { 14 | byte[] hash = hasher.ComputeHash(bytes, 0, bytes.Length); 15 | 16 | return hash.ToBase32(); 17 | } 18 | } 19 | 20 | public static string ToSha256(this byte[] data) 21 | { 22 | using (var hasher = new SHA256Managed()) 23 | { 24 | byte[] hash = hasher.ComputeHash(data, 0, data.Length); 25 | 26 | return hash.ToBase32(); 27 | } 28 | } 29 | 30 | /// 31 | /// Encode the byte array as a ZBase32 string 32 | /// 33 | /// 34 | /// 35 | public static string ToBase32(this byte[] data) 36 | { 37 | return Cached.Formatter.Format(data); 38 | } 39 | 40 | 41 | static class Cached 42 | { 43 | internal static readonly IBinaryEncodingFormatter Formatter = new ZBase32BinaryEncodingFormatter(); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/UserStore/NonSerializedTableStoreAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.UserStore 2 | { 3 | using System; 4 | 5 | 6 | [AttributeUsage(AttributeTargets.Property)] 7 | public class NonSerializedTableStoreAttribute : 8 | Attribute 9 | { 10 | } 11 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/UserStore/UserClaimEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.UserStore 2 | { 3 | using Microsoft.WindowsAzure.Storage.Table; 4 | 5 | 6 | public class UserClaimEntity : 7 | TableEntity 8 | { 9 | public UserClaimEntity() 10 | { 11 | } 12 | 13 | public UserClaimEntity(string userId, string claimType, string claimValue) 14 | { 15 | UserId = userId; 16 | ClaimType = claimType; 17 | ClaimValue = claimValue; 18 | 19 | PartitionKey = UserId; 20 | RowKey = ClaimType.ToSha256(); 21 | } 22 | 23 | public string UserId { get; set; } 24 | 25 | public string ClaimType { get; set; } 26 | 27 | public string ClaimValue { get; set; } 28 | } 29 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/UserStore/UserEmailIndexEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.UserStore 2 | { 3 | using Microsoft.WindowsAzure.Storage.Table; 4 | 5 | 6 | public class UserEmailIndexEntity : 7 | TableEntity 8 | { 9 | public UserEmailIndexEntity() 10 | { 11 | } 12 | 13 | public UserEmailIndexEntity(string hashedEmail, string userId) 14 | { 15 | PartitionKey = hashedEmail; 16 | RowKey = ""; 17 | 18 | UserId = userId; 19 | } 20 | 21 | public string UserId { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/UserStore/UserLoginEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.UserStore 2 | { 3 | using Microsoft.WindowsAzure.Storage.Table; 4 | 5 | 6 | public class UserLoginEntity : 7 | TableEntity 8 | { 9 | public UserLoginEntity() 10 | { 11 | } 12 | 13 | public UserLoginEntity(string userId, string loginProvider, string providerKey) 14 | { 15 | UserId = userId; 16 | LoginProvider = loginProvider; 17 | ProviderKey = providerKey; 18 | 19 | SetPartitionKeyRowKey(); 20 | } 21 | 22 | public string LoginProvider { get; set; } 23 | 24 | public string ProviderKey { get; set; } 25 | 26 | public string UserId { get; set; } 27 | 28 | public void SetPartitionKeyRowKey() 29 | { 30 | PartitionKey = UserId; 31 | RowKey = ""; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/UserStore/UserLoginProviderKeyIndexEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.UserStore 2 | { 3 | using Microsoft.WindowsAzure.Storage.Table; 4 | 5 | 6 | public class UserLoginProviderKeyIndexEntity : 7 | TableEntity 8 | { 9 | public UserLoginProviderKeyIndexEntity() 10 | { 11 | } 12 | 13 | public UserLoginProviderKeyIndexEntity(string userId, string providerKey, string loginProvider) 14 | { 15 | PartitionKey = string.Format("{0}_{1}", loginProvider.ToSha256(), providerKey.ToSha256()); 16 | RowKey = ""; 17 | 18 | UserId = userId; 19 | } 20 | 21 | public string UserId { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/UserStore/UserNameIndexEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.UserStore 2 | { 3 | using Microsoft.WindowsAzure.Storage.Table; 4 | 5 | 6 | public class UserNameIndexEntity : 7 | TableEntity 8 | { 9 | public UserNameIndexEntity() 10 | { 11 | } 12 | 13 | public UserNameIndexEntity(string hashedUserName, string userId) 14 | { 15 | PartitionKey = hashedUserName; 16 | RowKey = ""; 17 | 18 | UserId = userId; 19 | } 20 | 21 | public string UserId { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/UserStore/UserRoleEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.AzureIntegration.UserStore 2 | { 3 | using System; 4 | using Microsoft.AspNet.Identity; 5 | using Microsoft.WindowsAzure.Storage.Table; 6 | 7 | 8 | public class UserRoleEntity : 9 | TableEntity, 10 | IRole 11 | { 12 | public UserRoleEntity() 13 | { 14 | } 15 | 16 | public UserRoleEntity(string userId, string name) 17 | { 18 | Id = Guid.NewGuid().ToByteArray().ToBase32(); 19 | 20 | UserId = userId; 21 | Name = name; 22 | 23 | PartitionKey = UserId; 24 | RowKey = Name.ToSha256(); 25 | } 26 | 27 | public string UserId { get; set; } 28 | public string Id { get; set; } 29 | public string Name { get; set; } 30 | } 31 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.AzureIntegration/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Fooidity.Management.Web.Switching/Contexts/UserContext.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Switching.Contexts 2 | { 3 | public interface UserContext 4 | { 5 | string Username { get; } 6 | } 7 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web.Switching/Contexts/UserContextKeyProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Switching.Contexts 2 | { 3 | public class UserContextKeyProvider : 4 | IContextKeyProvider 5 | { 6 | public string GetKey(UserContext context) 7 | { 8 | return context.Username; 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web.Switching/Features/Feature_NewScreen.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Switching.Features 2 | { 3 | /// 4 | /// A new screen added to the application as part of a new feature 5 | /// 6 | public struct Feature_NewScreen : 7 | ICodeFeature 8 | { 9 | } 10 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/App_Start/BundleConfig.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web 2 | { 3 | using System.Web.Optimization; 4 | 5 | 6 | public class BundleConfig 7 | { 8 | // For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862 9 | public static void RegisterBundles(BundleCollection bundles) 10 | { 11 | bundles.Add(new ScriptBundle("~/bundles/jquery").Include( 12 | "~/Scripts/jquery-{version}.js")); 13 | 14 | // Use the development version of Modernizr to develop with and learn from. Then, when you're 15 | // ready for production, use the build tool at http://modernizr.com to pick only the tests you need. 16 | bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( 17 | "~/Scripts/modernizr-*")); 18 | 19 | bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( 20 | "~/Scripts/bootstrap.js", 21 | "~/Scripts/respond.js")); 22 | 23 | bundles.Add(new StyleBundle("~/Content/css").Include( 24 | "~/Content/bootstrap.css", 25 | "~/Content/site.css")); 26 | 27 | // Set EnableOptimizations to false for debugging. For more information, 28 | // visit http://go.microsoft.com/fwlink/?LinkId=301862 29 | BundleTable.EnableOptimizations = true; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web 2 | { 3 | using System.Web.Mvc; 4 | 5 | 6 | public class FilterConfig 7 | { 8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 9 | { 10 | filters.Add(new HandleErrorAttribute()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web 2 | { 3 | using System.Web.Mvc; 4 | using System.Web.Routing; 5 | 6 | 7 | public class RouteConfig 8 | { 9 | public static void RegisterRoutes(RouteCollection routes) 10 | { 11 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 12 | 13 | routes.MapMvcAttributeRoutes(); 14 | 15 | routes.MapRoute("Default", "{controller}/{action}/{id}", new 16 | { 17 | controller = "Home", 18 | action = "Index", 19 | id = UrlParameter.Optional 20 | }); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/App_Start/WebApiConfig.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web 2 | { 3 | using System.Web.Http; 4 | using System.Web.Http.ExceptionHandling; 5 | using Logging; 6 | using Microsoft.Owin.Security.OAuth; 7 | 8 | 9 | public static class WebApiConfig 10 | { 11 | public static void Register(HttpConfiguration config) 12 | { 13 | config.SuppressDefaultHostAuthentication(); 14 | config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); 15 | 16 | config.MapHttpAttributeRoutes(); 17 | 18 | config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new 19 | { 20 | id = RouteParameter.Optional 21 | }); 22 | 23 | config.Services.Add(typeof(IExceptionLogger), new UnhandledExceptionLogger()); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Content/Site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | /* Set padding to keep content from hitting the edges */ 7 | .body-content { 8 | padding-left: 15px; 9 | padding-right: 15px; 10 | } 11 | 12 | /* Set width on the form input elements since they're 100% wide by default */ 13 | input, 14 | select, 15 | textarea { 16 | max-width: 280px; 17 | } 18 | -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Controllers 2 | { 3 | using System.Web.Mvc; 4 | using Switching.Features; 5 | 6 | 7 | public class HomeController : 8 | Controller 9 | { 10 | readonly ICodeSwitch _newScreenSwitch; 11 | 12 | public HomeController(ICodeSwitch newScreenSwitch) 13 | { 14 | _newScreenSwitch = newScreenSwitch; 15 | } 16 | 17 | public ActionResult Index() 18 | { 19 | ViewBag.Title = "Home Page"; 20 | 21 | if (_newScreenSwitch.Enabled) 22 | ViewBag.Title += " - New Screen Enabled"; 23 | 24 | return View(); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="Fooidity.Management.Web.WebApiApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Global.asax.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web 2 | { 3 | using System.Web; 4 | using System.Web.Http; 5 | using System.Web.Mvc; 6 | using System.Web.Optimization; 7 | using System.Web.Routing; 8 | using Autofac.Integration.Mvc; 9 | using Autofac.Integration.WebApi; 10 | 11 | 12 | public class WebApiApplication : 13 | HttpApplication 14 | { 15 | protected void Application_Start() 16 | { 17 | AreaRegistration.RegisterAllAreas(); 18 | GlobalConfiguration.Configure(WebApiConfig.Register); 19 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 20 | RouteConfig.RegisterRoutes(RouteTable.Routes); 21 | BundleConfig.RegisterBundles(BundleTable.Bundles); 22 | 23 | GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(WebAppContainer.Container); 24 | 25 | DependencyResolver.SetResolver(new AutofacDependencyResolver(WebAppContainer.Container)); 26 | } 27 | 28 | protected void Application_End() 29 | { 30 | WebAppContainer.Container.Dispose(); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Hubs/ApplicationHubEventHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Hubs 2 | { 3 | using System.Threading.Tasks; 4 | using Contracts; 5 | using Fooidity.Contracts; 6 | using Microsoft.AspNet.SignalR; 7 | 8 | /// 9 | /// Handles events related to applications and publishes them to connections on the application hub 10 | /// 11 | public class ApplicationHubEventHandler : 12 | IEventHandler 13 | { 14 | public async Task Handle(Task eventTask) 15 | { 16 | IApplicationCodeFeatureStateUpdated updated = await eventTask; 17 | 18 | IHubContext context = GlobalHost.ConnectionManager.GetHubContext(); 19 | 20 | var clientEvent = new CodeFeatureStateUpdated(updated.CodeFeatureId, updated.Enabled, updated.EventId, updated.Timestamp, 21 | updated.CommandId); 22 | 23 | await context.Clients.Group(updated.ApplicationId).notifyCodeFeatureStateUpdated(clientEvent); 24 | // 25 | // await context.Clients.All.notifyCodeFeatureStateUpdated(clientEvent); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Hubs/ConnectionIdAppKeyDictionary.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Hubs 2 | { 3 | using System.Collections.Concurrent; 4 | using Management.Models; 5 | 6 | 7 | public class ConnectionIdAppKeyDictionary 8 | { 9 | readonly ConcurrentDictionary _ids; 10 | 11 | public ConnectionIdAppKeyDictionary() 12 | { 13 | _ids = new ConcurrentDictionary(); 14 | } 15 | 16 | public bool TryGetAppKey(string connectionId, out IOrganizationApplicationKey appKey) 17 | { 18 | if (_ids.TryGetValue(connectionId, out appKey)) 19 | return true; 20 | 21 | return false; 22 | } 23 | 24 | public bool TryAdd(string connectionId, IOrganizationApplicationKey appKey) 25 | { 26 | if (_ids.TryAdd(connectionId, appKey)) 27 | return true; 28 | 29 | return false; 30 | } 31 | 32 | public bool TryRemove(string connectionId, out IOrganizationApplicationKey application) 33 | { 34 | return _ids.TryRemove(connectionId, out application); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Logging/UnhandledExceptionLogger.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Logging 2 | { 3 | using System.Web.Http.ExceptionHandling; 4 | 5 | 6 | public class UnhandledExceptionLogger : 7 | ExceptionLogger 8 | { 9 | public override void Log(ExceptionLoggerContext context) 10 | { 11 | base.Log(context); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Models/AccountViewModels.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Models 2 | { 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | 6 | public class ExternalLoginConfirmationViewModel 7 | { 8 | [Required, EmailAddress, Display(Name = "Email")] 9 | public string Email { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Models/ApplicationUser.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Models 2 | { 3 | using System.Security.Claims; 4 | using System.Threading.Tasks; 5 | using AzureIntegration.UserStore; 6 | using Microsoft.AspNet.Identity; 7 | 8 | 9 | public class ApplicationUser : 10 | UserEntity 11 | { 12 | public ApplicationUser() 13 | { 14 | } 15 | 16 | 17 | public async Task GenerateUserIdentityAsync(UserManager manager) 18 | { 19 | // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType 20 | ClaimsIdentity userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); 21 | 22 | return userIdentity; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Models/ApplicationViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Models 2 | { 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.Linq; 6 | using System.Web.Mvc; 7 | 8 | 9 | public class ApplicationViewModel 10 | { 11 | [Display(Name = "Application Id")] 12 | public string Id { get; set; } 13 | 14 | public string Name { get; set; } 15 | 16 | public string OrganizationId { get; set; } 17 | 18 | [Display(Name = "Organization")] 19 | public string OrganizationName { get; set; } 20 | 21 | public List Keys { get; set; } 22 | 23 | public List Organizations { get; set; } 24 | 25 | public IEnumerable OrganizationItems 26 | { 27 | get { return Organizations.Select(x => new SelectListItem {Value = x.Id, Text = x.Name}); } 28 | } 29 | 30 | public IEnumerable Features { get; set; } 31 | } 32 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Models/CodeFeatureDetailViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Models 2 | { 3 | using System.Collections.Generic; 4 | 5 | 6 | public class CodeFeatureDetailViewModel 7 | { 8 | public string ApplicationId { get; set; } 9 | public string ApplicationName { get; set; } 10 | 11 | public CodeFeatureId CodeFeatureId { get; set; } 12 | 13 | public CodeFeatureStateViewModel CurrentState { get; set; } 14 | 15 | public IEnumerable StateHistory { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Models/CodeFeatureModel.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Models 2 | { 3 | using System; 4 | 5 | 6 | /// 7 | /// A code feature is defined in the system by identifier and identifies 8 | /// a feature that can be switched. 9 | /// 10 | public class CodeFeatureModel 11 | { 12 | /// 13 | /// Identifies the CodeFeature, generated from the code feature's Type 14 | /// 15 | public Uri CodeFeatureId { get; set; } 16 | 17 | /// 18 | /// True if the feature is enabled, otherwise false. 19 | /// 20 | public bool Enabled { get; set; } 21 | } 22 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Models/CodeFeatureStateViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Models 2 | { 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | 6 | 7 | public class CodeFeatureStateViewModel 8 | { 9 | [Display(Name = "Code Feature Id")] 10 | public CodeFeatureId CodeFeatureId { get; set; } 11 | 12 | public bool Enabled { get; set; } 13 | 14 | [Display(Name = "Updated")] 15 | public DateTime LastUpdated { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Models/CreateApplicationKeyViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Models 2 | { 3 | public class CreateApplicationKeyViewModel 4 | { 5 | public string ApplicationId { get; set; } 6 | public string OrganizationId { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Models/EnableCodeFeatureViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Models 2 | { 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | 6 | public class EnableCodeFeatureViewModel 7 | { 8 | [Required] 9 | public string ApplicationId { get; set; } 10 | 11 | [Required] 12 | public string CodeFeatureId { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Models/ExternalLoginListViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Models 2 | { 3 | public class ExternalLoginListViewModel 4 | { 5 | public string Action { get; set; } 6 | public string ReturnUrl { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Models/LoginViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Models 2 | { 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | 6 | public class LoginViewModel 7 | { 8 | [Required, EmailAddress, Display(Name = "Email")] 9 | public string Email { get; set; } 10 | 11 | [Required, DataType(DataType.Password), Display(Name = "Password")] 12 | public string Password { get; set; } 13 | 14 | [Display(Name = "Remember me?")] 15 | public bool RememberMe { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Models/ManageCodeFeatureViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Models 2 | { 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | 6 | 7 | public class ManageCodeFeatureViewModel 8 | { 9 | [Required] 10 | public string ApplicationId { get; set; } 11 | 12 | [Required] 13 | public Uri CodeFeatureId { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Models/ManageUserViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Models 2 | { 3 | public class ManageUserViewModel 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Models/OrganizationViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Models 2 | { 3 | public class OrganizationViewModel 4 | { 5 | public string Id { get; set; } 6 | 7 | public string Name { get; set; } 8 | 9 | public string CreatedByUserId { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Models/RegisterViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web.Models 2 | { 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | 6 | public class RegisterViewModel 7 | { 8 | [Required, EmailAddress, Display(Name = "Email")] 9 | public string Email { get; set; } 10 | 11 | [Required, StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6), 12 | DataType(DataType.Password), Display(Name = "Password")] 13 | public string Password { get; set; } 14 | 15 | [DataType(DataType.Password), Display(Name = "Confirm password"), 16 | Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] 17 | public string ConfirmPassword { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Scripts/_references.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phatboyg/Fooidity/a55ea9391773903eab0e6b93a08951b75dd8a936/src/Fooidity.Management.Web/Scripts/_references.js -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Startup.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Web 2 | { 3 | using Autofac; 4 | using Hubs; 5 | using Microsoft.AspNet.SignalR; 6 | using Owin; 7 | 8 | 9 | public partial class Startup 10 | { 11 | public void Configuration(IAppBuilder app) 12 | { 13 | ConfigureAuth(app); 14 | 15 | GlobalHost.DependencyResolver.Register(typeof(ApplicationHub), () => WebAppContainer.Container.Resolve()); 16 | 17 | app.MapSignalR(); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Views/Account/ExternalLoginFailure.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Login Failure"; 3 | } 4 | 5 |

@ViewBag.Title.

6 |

Unsuccessful login with service.

7 | -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Views/Account/Login.cshtml: -------------------------------------------------------------------------------- 1 | @using Fooidity.Management.Web.Models 2 | @model LoginViewModel 3 | 4 | @{ 5 | ViewBag.Title = "Log in"; 6 | } 7 | 8 |

@ViewBag.Title.

9 |
10 |
11 |
12 | Login the management portal using one of the supported authentication providers. 13 |
14 |
15 |
16 |
17 | @Html.Partial("_ExternalLoginsListPartial", new ExternalLoginListViewModel { Action = "ExternalLogin", ReturnUrl = ViewBag.ReturnUrl }) 18 |
19 |
20 |
21 | @section Scripts { 22 | @Scripts.Render("~/bundles/jqueryval") 23 | } -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Views/Account/Manage.cshtml: -------------------------------------------------------------------------------- 1 | @using Fooidity.Management.Web.Models; 2 | @using Microsoft.AspNet.Identity; 3 | @{ 4 | ViewBag.Title = "Manage Account"; 5 | } 6 | 7 |

@ViewBag.Title

8 | 9 |

@ViewBag.StatusMessage

10 |
11 |
12 |

You're logged in as @User.Identity.GetUserName().

13 |
14 |
15 |
16 | @Html.Action("RemoveAccountList") 17 | @Html.Partial("_ExternalLoginsListPartial", new ExternalLoginListViewModel { Action = "LinkLogin", ReturnUrl = ViewBag.ReturnUrl }) 18 |
19 |
20 |
21 | @section Scripts { 22 | @Scripts.Render("~/bundles/jqueryval") 23 | } 24 | -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Views/Account/_ExternalLoginsListPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.Owin.Security 2 | @model Fooidity.Management.Web.Models.ExternalLoginListViewModel 3 | 4 |

Authentication Providers

5 |
6 | @{ 7 | AuthenticationDescription[] providers = Context.GetOwinContext().Authentication.GetExternalAuthenticationTypes().ToArray(); 8 | if (providers.Any()) 9 | { 10 | using (Html.BeginForm(Model.Action, "Account", new {Model.ReturnUrl})) 11 | { 12 | @Html.AntiForgeryToken() 13 |
14 |

15 | @foreach (AuthenticationDescription provider in providers) 16 | { 17 | 18 | } 19 |

20 |
21 | } 22 | } 23 | else 24 | { 25 |
26 |

There are no external authentication providers configured.

27 |
28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Views/Account/_RemoveAccountPartial.cshtml: -------------------------------------------------------------------------------- 1 | @model ICollection 2 | 3 | @if (Model.Count > 0) 4 | { 5 |

Registered Logins

6 | 7 | 8 | @foreach (var account in Model) 9 | { 10 | 11 | 12 | 30 | 31 | } 32 | 33 |
@account.LoginProvider 13 | @if (ViewBag.ShowRemoveButton) 14 | { 15 | using (Html.BeginForm("Disassociate", "Account")) 16 | { 17 | @Html.AntiForgeryToken() 18 |
19 | @Html.Hidden("loginProvider", account.LoginProvider) 20 | @Html.Hidden("providerKey", account.ProviderKey) 21 | 22 |
23 | } 24 | } 25 | else 26 | { 27 | @:   28 | } 29 |
34 | } 35 | -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Views/Features/Details.cshtml: -------------------------------------------------------------------------------- 1 | @using Fooidity.Management.Web.Models 2 | @model Fooidity.Management.Web.Models.CodeFeatureStateViewModel 3 | 4 | @{ 5 | ViewBag.Title = "Details"; 6 | } 7 | 8 | I'm a code feature 9 | -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Views/Organization/Create.cshtml: -------------------------------------------------------------------------------- 1 | @model Fooidity.Management.Web.Models.OrganizationViewModel 2 | 3 | @{ 4 | ViewBag.Title = "Create Organization"; 5 | } 6 | 7 |

Create Organization

8 | 9 | 10 | @using (Html.BeginForm()) 11 | { 12 | @Html.AntiForgeryToken() 13 | 14 |
15 |

Create Organization

16 |
17 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 18 |
19 | @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" }) 20 |
21 | @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } }) 22 | @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" }) 23 |
24 |
25 | 26 |
27 |
28 | 29 |
30 |
31 |
32 | } 33 | 34 |
35 | @Html.ActionLink("Back to List", "Index") 36 |
37 | 38 | @section Scripts { 39 | @Scripts.Render("~/bundles/jqueryval") 40 | } 41 | -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Views/Organization/Details.cshtml: -------------------------------------------------------------------------------- 1 | @model Fooidity.Management.Web.Models.OrganizationViewModel 2 | 3 | @{ 4 | ViewBag.Title = "Organization Detail"; 5 | } 6 | 7 |

Organization Details

8 | 9 |
10 |

Organization

11 |
12 |
13 |
14 | @Html.DisplayNameFor(model => model.Id) 15 |
16 | 17 |
18 | @Html.DisplayFor(model => model.Id) 19 |
20 | 21 |
22 | @Html.DisplayNameFor(model => model.Name) 23 |
24 | 25 |
26 | @Html.DisplayFor(model => model.Name) 27 |
28 | 29 |
30 | @Html.DisplayNameFor(model => model.CreatedByUserId) 31 |
32 | 33 |
34 | @Html.DisplayFor(model => model.CreatedByUserId) 35 |
36 | 37 |
38 |
39 |

40 | @Html.ActionLink("Back to List", "Index") 41 |

42 | -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Views/Organization/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @{ 4 | ViewBag.Title = "Organizations"; 5 | } 6 | 7 |

Organizations

8 |

9 | Organizations contain applications and can be associated with multiple users. Associated users can create applications 10 | and manage the access keys for those applications. 11 |

12 |

13 | @Html.ActionLink("Create New", "Create", new { @class="btn btn-primary" }) 14 |

15 | 16 | 17 | 20 | 21 | 22 | 23 | @foreach (var item in Model) { 24 | 25 | 28 | 31 | 32 | } 33 | 34 |
18 | @Html.DisplayNameFor(model => model.Name) 19 |
26 | @Html.DisplayFor(modelItem => item.Name) 27 | 29 | @Html.ActionLink("Details", "Details", new { id=item.Id }) 30 |
35 | -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = null; 3 | } 4 | 5 | 6 | 7 | 8 | 9 | Error 10 | 11 | 12 |
13 |

Error.

14 |

An error occurred while processing your request.

15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Views/Shared/_LoginPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNet.Identity 2 | @if (Request.IsAuthenticated) 3 | { 4 | using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" })) 5 | { 6 | @Html.AntiForgeryToken() 7 | 8 | 14 | } 15 | } 16 | else 17 | { 18 | 21 | } 22 | -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Web.Debug.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/Web.Release.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phatboyg/Fooidity/a55ea9391773903eab0e6b93a08951b75dd8a936/src/Fooidity.Management.Web/favicon.ico -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phatboyg/Fooidity/a55ea9391773903eab0e6b93a08951b75dd8a936/src/Fooidity.Management.Web/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phatboyg/Fooidity/a55ea9391773903eab0e6b93a08951b75dd8a936/src/Fooidity.Management.Web/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phatboyg/Fooidity/a55ea9391773903eab0e6b93a08951b75dd8a936/src/Fooidity.Management.Web/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/Fooidity.Management.Web/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phatboyg/Fooidity/a55ea9391773903eab0e6b93a08951b75dd8a936/src/Fooidity.Management.Web/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /src/Fooidity.Management/Commands/CreateApplication.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Commands 2 | { 3 | using System; 4 | 5 | 6 | public class CreateApplication : 7 | ICreateApplication 8 | { 9 | public CreateApplication(string userId, string organizationId, string applicationName, DateTime timestamp, Guid commandId) 10 | { 11 | UserId = userId; 12 | OrganizationId = organizationId; 13 | ApplicationName = applicationName; 14 | Timestamp = timestamp; 15 | CommandId = commandId; 16 | } 17 | 18 | public Guid CommandId { get; set; } 19 | public DateTime Timestamp { get; set; } 20 | public string UserId { get; set; } 21 | public string OrganizationId { get; set; } 22 | public string ApplicationName { get; set; } 23 | } 24 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Commands/CreateApplicationKey.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Commands 2 | { 3 | using System; 4 | 5 | 6 | public class CreateApplicationKey : 7 | ICreateApplicationKey 8 | { 9 | public CreateApplicationKey(string userId, string organizationId, string applicationId, DateTime timestamp, Guid commandId) 10 | { 11 | UserId = userId; 12 | OrganizationId = organizationId; 13 | ApplicationId = applicationId; 14 | Timestamp = timestamp; 15 | CommandId = commandId; 16 | } 17 | 18 | public Guid CommandId { get; set; } 19 | public DateTime Timestamp { get; set; } 20 | public string UserId { get; set; } 21 | public string OrganizationId { get; set; } 22 | public string ApplicationId { get; set; } 23 | } 24 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Commands/CreateOrganization.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Commands 2 | { 3 | using System; 4 | 5 | 6 | public class CreateOrganization : 7 | ICreateOrganization 8 | { 9 | public CreateOrganization(string userId, string organizationName) 10 | { 11 | CommandId = Guid.NewGuid(); 12 | Timestamp = DateTime.UtcNow; 13 | 14 | UserId = userId; 15 | OrganizationName = organizationName; 16 | } 17 | 18 | public Guid CommandId { get; set; } 19 | public DateTime Timestamp { get; set; } 20 | public string UserId { get; set; } 21 | public string OrganizationName { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Commands/ICreateApplication.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Commands 2 | { 3 | using System; 4 | 5 | 6 | public interface ICreateApplication 7 | { 8 | Guid CommandId { get; } 9 | 10 | DateTime Timestamp { get; } 11 | 12 | string UserId { get; } 13 | 14 | string OrganizationId { get; } 15 | 16 | string ApplicationName { get; } 17 | } 18 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Commands/ICreateApplicationKey.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Commands 2 | { 3 | using System; 4 | 5 | 6 | public interface ICreateApplicationKey 7 | { 8 | Guid CommandId { get; } 9 | 10 | DateTime Timestamp { get; } 11 | 12 | string UserId { get; } 13 | 14 | string OrganizationId { get; } 15 | 16 | string ApplicationId { get; } 17 | } 18 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Commands/ICreateOrganization.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Commands 2 | { 3 | using System; 4 | 5 | 6 | public interface ICreateOrganization 7 | { 8 | Guid CommandId { get; } 9 | 10 | DateTime Timestamp { get; } 11 | 12 | /// 13 | /// The user creating the application 14 | /// 15 | string UserId { get; } 16 | 17 | /// 18 | /// The organization in which the application is being created 19 | /// 20 | string OrganizationName { get; } 21 | } 22 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Commands/IRegisterApplicationContext.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Commands 2 | { 3 | public interface IRegisterApplicationContext 4 | { 5 | string ApplicationId { get; } 6 | 7 | string ContextId { get; } 8 | } 9 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Commands/IRegisterCodeFeature.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Commands 2 | { 3 | public interface IRegisterCodeFeature 4 | { 5 | string ApplicationId { get; } 6 | 7 | string CodeFeatureId { get; } 8 | } 9 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Commands/IUpdateApplicationCodeFeatureState.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Commands 2 | { 3 | using System; 4 | 5 | 6 | public interface IUpdateApplicationCodeFeatureState 7 | { 8 | Guid CommandId { get; } 9 | 10 | DateTime Timestamp { get; } 11 | 12 | string ApplicationId { get; } 13 | 14 | Uri CodeFeatureId { get; } 15 | 16 | bool Enabled { get; } 17 | } 18 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Commands/RegisterApplicationContext.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Commands 2 | { 3 | public class RegisterApplicationContext : 4 | IRegisterApplicationContext 5 | { 6 | public RegisterApplicationContext(string applicationId, string contextId) 7 | { 8 | ApplicationId = applicationId; 9 | ContextId = contextId; 10 | } 11 | 12 | public string ApplicationId { get; set; } 13 | public string ContextId { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Commands/RegisterCodeFeature.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Commands 2 | { 3 | using System; 4 | 5 | 6 | public class RegisterCodeFeature : 7 | IRegisterCodeFeature 8 | { 9 | public RegisterCodeFeature(string applicationId, Uri codeFeatureId) 10 | { 11 | ApplicationId = applicationId; 12 | CodeFeatureId = codeFeatureId.ToString(); 13 | } 14 | 15 | public string ApplicationId { get; set; } 16 | public string CodeFeatureId { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Commands/UpdateApplicationCodeFeatureState.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Commands 2 | { 3 | using System; 4 | 5 | 6 | public class UpdateApplicationCodeFeatureState : 7 | IUpdateApplicationCodeFeatureState 8 | { 9 | public UpdateApplicationCodeFeatureState(string applicationId, Uri codeFeatureId, bool enabled, DateTime timestamp, 10 | Guid? commandId = null) 11 | { 12 | CommandId = commandId.HasValue ? commandId.Value : Guid.NewGuid(); 13 | Timestamp = timestamp; 14 | 15 | ApplicationId = applicationId; 16 | CodeFeatureId = codeFeatureId; 17 | Enabled = enabled; 18 | } 19 | 20 | public Guid CommandId { get; set; } 21 | 22 | public DateTime Timestamp { get; set; } 23 | 24 | public string ApplicationId { get; set; } 25 | 26 | public Uri CodeFeatureId { get; set; } 27 | 28 | public bool Enabled { get; set; } 29 | } 30 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Contracts/ApplicationCodeFeatureStateUpdated.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Contracts 2 | { 3 | using System; 4 | 5 | 6 | public class ApplicationCodeFeatureStateUpdated : 7 | IApplicationCodeFeatureStateUpdated 8 | { 9 | public ApplicationCodeFeatureStateUpdated(string applicationId, Uri codeFeatureId, bool enabled, DateTime timestamp, 10 | Guid? commandId = null, 11 | Guid? eventId = null) 12 | { 13 | ApplicationId = applicationId; 14 | CodeFeatureId = codeFeatureId; 15 | Enabled = enabled; 16 | CommandId = commandId; 17 | EventId = eventId.HasValue ? eventId.Value : Guid.NewGuid(); 18 | Timestamp = timestamp; 19 | } 20 | 21 | public Guid EventId { get; set; } 22 | public DateTime Timestamp { get; set; } 23 | public Guid? CommandId { get; set; } 24 | public string ApplicationId { get; set; } 25 | public Uri CodeFeatureId { get; set; } 26 | public bool Enabled { get; set; } 27 | } 28 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Contracts/IApplicationCodeFeatureStateUpdated.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Contracts 2 | { 3 | using System; 4 | 5 | 6 | public interface IApplicationCodeFeatureStateUpdated 7 | { 8 | /// 9 | /// Generated EventId 10 | /// 11 | Guid EventId { get; } 12 | 13 | /// 14 | /// When the feature state was updated 15 | /// 16 | DateTime Timestamp { get; } 17 | 18 | /// 19 | /// The identifier of the command that enabled the context code feature 20 | /// 21 | Guid? CommandId { get; } 22 | 23 | /// 24 | /// The applicationId of the code feature state that was updated 25 | /// 26 | string ApplicationId { get; } 27 | 28 | /// 29 | /// The FeatureId that was updated 30 | /// 31 | Uri CodeFeatureId { get; } 32 | 33 | /// 34 | /// If the feature is enabled 35 | /// 36 | bool Enabled { get; } 37 | } 38 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/ICommandHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management 2 | { 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | 7 | public interface ICommandHandler 8 | { 9 | Task Execute(T command, CancellationToken cancellationToken = default(CancellationToken)); 10 | } 11 | 12 | 13 | public interface ICommandHandler 14 | { 15 | Task Execute(T command, CancellationToken cancellationToken = default(CancellationToken)); 16 | } 17 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/IEventHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management 2 | { 3 | using System.Threading.Tasks; 4 | 5 | /// 6 | /// Event handlers handle a specific input event type and are dependencies of classes 7 | /// that produce events 8 | /// 9 | /// The event type 10 | public interface IEventHandler 11 | { 12 | Task Handle(Task eventTask); 13 | } 14 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/IQueryHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management 2 | { 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | 7 | public interface IQueryHandler 8 | { 9 | Task Execute(T query, CancellationToken cancellationToken = default(CancellationToken)); 10 | } 11 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Models/Application.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Models 2 | { 3 | public interface Application 4 | { 5 | string Id { get; } 6 | 7 | string Name { get; } 8 | } 9 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Models/CodeFeatureDetail.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Models 2 | { 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using Fooidity.Contracts; 6 | 7 | 8 | public class CodeFeatureDetail : 9 | ICodeFeatureDetail 10 | { 11 | public CodeFeatureDetail(string applicationId, string applicationName, CodeFeatureId codeFeatureId, ICodeFeatureState currentState, 12 | IEnumerable stateHistory) 13 | { 14 | ApplicationId = applicationId; 15 | ApplicationName = applicationName; 16 | CodeFeatureId = codeFeatureId; 17 | CurrentState = currentState; 18 | StateHistory = stateHistory.ToArray(); 19 | } 20 | 21 | public string ApplicationId { get; set; } 22 | public string ApplicationName { get; set; } 23 | public CodeFeatureId CodeFeatureId { get; set; } 24 | public ICodeFeatureState CurrentState { get; set; } 25 | public IEnumerable StateHistory { get; set; } 26 | } 27 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Models/ICodeFeatureDetail.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Models 2 | { 3 | using System.Collections.Generic; 4 | using Fooidity.Contracts; 5 | 6 | 7 | public interface ICodeFeatureDetail 8 | { 9 | string ApplicationId { get; } 10 | string ApplicationName { get; } 11 | 12 | CodeFeatureId CodeFeatureId { get; } 13 | 14 | /// 15 | /// The current state of the code feature 16 | /// 17 | ICodeFeatureState CurrentState { get; } 18 | 19 | /// 20 | /// The entire code feature state history 21 | /// 22 | IEnumerable StateHistory { get; } 23 | } 24 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Models/IOrganization.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Models 2 | { 3 | /// 4 | /// An organization connects users to applications 5 | /// 6 | public interface IOrganization 7 | { 8 | /// 9 | /// The identifier for the organization 10 | /// 11 | string OrganizationId { get; } 12 | 13 | /// 14 | /// The organization name 15 | /// 16 | string OrganizationName { get; } 17 | 18 | /// 19 | /// The user which created the organization 20 | /// 21 | string CreatedByUserId { get; } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Models/IOrganizationApplication.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Models 2 | { 3 | /// 4 | /// An application created within an organization 5 | /// 6 | public interface IOrganizationApplication 7 | { 8 | string OrganizationId { get; } 9 | string OrganizationName { get; } 10 | string ApplicationId { get; } 11 | string ApplicationName { get; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Models/IOrganizationApplicationKey.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Models 2 | { 3 | public interface IOrganizationApplicationKey : 4 | IOrganizationApplication 5 | { 6 | string Key { get; } 7 | } 8 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Models/IUser.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Models 2 | { 3 | public interface IUser 4 | { 5 | string UserId { get; } 6 | } 7 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Models/IUserOrganizationApplication.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Models 2 | { 3 | /// 4 | /// An application created within an organization 5 | /// 6 | public interface IUserOrganizationApplication : 7 | IOrganizationApplication 8 | { 9 | string UserId { get; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Queries/GetApplication.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Queries 2 | { 3 | public class GetApplication : 4 | IGetApplication 5 | { 6 | public GetApplication(string userId, string applicationId) 7 | { 8 | ApplicationId = applicationId; 9 | UserId = userId; 10 | } 11 | 12 | public string UserId { get; set; } 13 | public string ApplicationId { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Queries/GetApplicationByKey.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Queries 2 | { 3 | public class GetApplicationByKey : 4 | IGetApplicationByKey 5 | { 6 | public GetApplicationByKey(string key) 7 | { 8 | Key = key; 9 | } 10 | 11 | public string Key { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Queries/GetCodeFeatureDetail.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Queries 2 | { 3 | using System; 4 | 5 | 6 | public class GetCodeFeatureDetail : 7 | IGetCodeFeatureDetail 8 | { 9 | public GetCodeFeatureDetail(string userId, string applicationId, Uri codeFeatureId) 10 | { 11 | UserId = userId; 12 | ApplicationId = applicationId; 13 | CodeFeatureId = codeFeatureId; 14 | } 15 | 16 | public string UserId { get; set; } 17 | public string ApplicationId { get; set; } 18 | public Uri CodeFeatureId { get; set; } 19 | } 20 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Queries/GetOrganization.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Queries 2 | { 3 | public class GetOrganization : 4 | IGetOrganization 5 | { 6 | public GetOrganization(string userId, string organizationId) 7 | { 8 | OrganizationId = organizationId; 9 | UserId = userId; 10 | } 11 | 12 | public string UserId { get; set; } 13 | public string OrganizationId { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Queries/GetUser.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Queries 2 | { 3 | public interface GetUser 4 | { 5 | string UserId { get; } 6 | } 7 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Queries/IGetApplication.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Queries 2 | { 3 | public interface IGetApplication 4 | { 5 | string UserId { get; } 6 | string ApplicationId { get; } 7 | } 8 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Queries/IGetApplicationByKey.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Queries 2 | { 3 | public interface IGetApplicationByKey 4 | { 5 | string Key { get; } 6 | } 7 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Queries/IGetCodeFeatureDetail.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Queries 2 | { 3 | using System; 4 | 5 | 6 | public interface IGetCodeFeatureDetail 7 | { 8 | string UserId { get; } 9 | 10 | string ApplicationId { get; } 11 | 12 | Uri CodeFeatureId { get; } 13 | } 14 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Queries/IGetOrganization.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Queries 2 | { 3 | public interface IGetOrganization 4 | { 5 | string UserId { get; } 6 | string OrganizationId { get; } 7 | } 8 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Queries/IListApplicationCodeFeatures.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Queries 2 | { 3 | public interface IListApplicationCodeFeatures 4 | { 5 | string UserId { get; } 6 | string ApplicationId { get; } 7 | } 8 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Queries/IListApplicationKeys.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Queries 2 | { 3 | public interface IListApplicationKeys 4 | { 5 | /// 6 | /// The userId making the request (only applications visible to the user can be displayed) 7 | /// 8 | string UserId { get; } 9 | 10 | /// 11 | /// The applicationId to get the keys for (must be visible to the userId) 12 | /// 13 | string ApplicationId { get; } 14 | } 15 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Queries/IListApplications.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Queries 2 | { 3 | public interface IListApplications 4 | { 5 | string UserId { get; } 6 | } 7 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Queries/IListOrganizations.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Queries 2 | { 3 | public interface IListOrganizations 4 | { 5 | string UserId { get; } 6 | } 7 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Queries/ListApplicationCodeFeatures.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Queries 2 | { 3 | public class ListApplicationCodeFeatures : 4 | IListApplicationCodeFeatures 5 | { 6 | public ListApplicationCodeFeatures(string userId, string applicationId) 7 | { 8 | UserId = userId; 9 | ApplicationId = applicationId; 10 | } 11 | 12 | public string UserId { get; set; } 13 | 14 | public string ApplicationId { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Queries/ListApplicationKeys.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Queries 2 | { 3 | public class ListApplicationKeys : 4 | IListApplicationKeys 5 | { 6 | public ListApplicationKeys(string userId, string applicationId) 7 | { 8 | ApplicationId = applicationId; 9 | UserId = userId; 10 | } 11 | 12 | public string UserId { get; set; } 13 | public string ApplicationId { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Queries/ListApplications.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Queries 2 | { 3 | public class ListApplications : 4 | IListApplications 5 | { 6 | public ListApplications(string userId) 7 | { 8 | UserId = userId; 9 | } 10 | 11 | public string UserId { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/Queries/ListOrganizations.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management.Queries 2 | { 3 | public class ListOrganizations : 4 | IListOrganizations 5 | { 6 | public ListOrganizations(string userId) 7 | { 8 | UserId = userId; 9 | } 10 | 11 | public string UserId { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/QueryCodeFeatureState.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management 2 | { 3 | public interface QueryCodeFeatureState 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /src/Fooidity.Management/UpdateCodeFeatureState.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Management 2 | { 3 | using System; 4 | 5 | 6 | public interface UpdateCodeFeatureState 7 | { 8 | Guid CommandId { get; } 9 | 10 | DateTime Timestamp { get; } 11 | 12 | CodeFeatureId CodeFeatureId { get; } 13 | 14 | bool Enabled { get; } 15 | } 16 | } -------------------------------------------------------------------------------- /src/Fooidity.MassTransitIntegration/UpdateCodeFeatureCacheConsumer.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.MassTransitIntegration 2 | { 3 | using System; 4 | using Caching; 5 | using Contracts; 6 | using MassTransit; 7 | using MassTransit.Logging; 8 | 9 | 10 | public class UpdateCodeFeatureCacheConsumer : 11 | Consumes.All 12 | { 13 | static readonly ILog _log = Logger.Get(); 14 | 15 | readonly IUpdateCodeFeatureCache _updateCache; 16 | 17 | public UpdateCodeFeatureCacheConsumer(IUpdateCodeFeatureCache updateCache) 18 | { 19 | _updateCache = updateCache; 20 | } 21 | 22 | public void Consume(ICodeFeatureStateUpdated message) 23 | { 24 | Uri id = message.CodeFeatureId; 25 | try 26 | { 27 | var codeFeatureId = new CodeFeatureId(id); 28 | 29 | var update = new UpdateCodeFeature(codeFeatureId, message.Enabled, message.Timestamp, message.CommandId ?? message.EventId); 30 | _updateCache.UpdateCache(update); 31 | } 32 | catch (FormatException ex) 33 | { 34 | _log.Error(string.Format("The CodeFeatureId was not valid: {0}", id), ex); 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/Fooidity.MassTransitIntegration/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/Fooidity.MassTransitIntegration/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Fooidity.Tests/A_disabled_DateRange.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Tests 2 | { 3 | using System; 4 | using NUnit.Framework; 5 | using Shouldly; 6 | 7 | 8 | public class A_disabled_DateRange 9 | { 10 | DateTime end = new DateTime(2014, 2, 1); 11 | DateTime start = new DateTime(2014, 1, 1); 12 | 13 | [Test] 14 | public void Enabled_and_correct_dates() 15 | { 16 | ICodeSwitch x = CodeSwitch.Factory.EnableBetween(start, end, 17 | () => new DateTime(2014, 1, 15)); 18 | 19 | x.Enabled.ShouldBe(true); 20 | } 21 | 22 | [Test] 23 | public void Disabled_even_if_date_is_right() 24 | { 25 | IToggleCodeSwitch x = CodeSwitch.Factory.EnableBetween(start, end, 26 | () => new DateTime(2014, 1, 15)); 27 | x.Disable(); 28 | 29 | x.Enabled.ShouldBe(false); 30 | } 31 | 32 | [Test] 33 | public void Disabled_if_date_is_incorrect() 34 | { 35 | ICodeSwitch x = CodeSwitch.Factory.EnableBetween(start, end, 36 | () => new DateTime(2014, 3, 15)); 37 | 38 | x.Enabled.ShouldBe(false); 39 | } 40 | 41 | 42 | struct SpecialDiscount : 43 | ICodeFeature 44 | { 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/Fooidity.Tests/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/Fooidity.Tests/Dependent_Specs.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Tests 2 | { 3 | using NUnit.Framework; 4 | 5 | 6 | [TestFixture] 7 | public class A_dependent_fooid 8 | { 9 | [Test] 10 | public void Should_be_disabled_by_default() 11 | { 12 | IToggleCodeSwitch level1 = CodeSwitch.Factory.Toggle(); 13 | 14 | ICodeSwitch level2 = CodeSwitch.Factory.Dependent(x => x.Upon(level1)); 15 | 16 | Assert.IsFalse(level2.Enabled); 17 | } 18 | 19 | [Test] 20 | public void Should_be_enabled_to_be_enabled() 21 | { 22 | IToggleCodeSwitch level1 = CodeSwitch.Factory.Toggle(); 23 | 24 | ICodeSwitch level2 = CodeSwitch.Factory.Dependent(x => x.Upon(level1)); 25 | 26 | level1.Enable(); 27 | Assert.IsTrue(level2.Enabled); 28 | } 29 | 30 | 31 | struct Level1 : 32 | ICodeFeature 33 | { 34 | } 35 | 36 | 37 | struct Level2 : 38 | ICodeFeature 39 | { 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/Fooidity.Tests/InlinePath_Specs.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Tests 2 | { 3 | using NUnit.Framework; 4 | 5 | 6 | [TestFixture] 7 | public class Using_a_code_switch_inline 8 | { 9 | [Test] 10 | public void Should_provide_a_clear_syntax_for_method_selection() 11 | { 12 | ICodeSwitch codeSwitch = CodeSwitch.Factory.Enabled(); 13 | 14 | bool called = false; 15 | codeSwitch.If(() => { called = true; }); 16 | Assert.IsTrue(called); 17 | 18 | codeSwitch.Unless(() => { Assert.Fail("Should not be called"); }); 19 | 20 | called = false; 21 | codeSwitch.If(() => { called = true; }, () => { Assert.Fail("Should not be called"); }); 22 | 23 | int result = codeSwitch.Iff(() => 27, () => 42); 24 | Assert.AreEqual(27, result); 25 | 26 | int value = codeSwitch.Iff((a, b) => a, (a, b) => b, 27, 42); 27 | Assert.AreEqual(27, value); 28 | } 29 | 30 | 31 | struct TestFeature : 32 | ICodeFeature 33 | { 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/Fooidity.Tests/ToggleSwitch_Specs.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Tests 2 | { 3 | namespace ToggleSwitch_Specs 4 | { 5 | using NUnit.Framework; 6 | 7 | 8 | struct A : 9 | ICodeFeature 10 | { 11 | } 12 | 13 | 14 | [TestFixture] 15 | public class Toggling_a_code_switch 16 | { 17 | [Test] 18 | public void Should_change_state() 19 | { 20 | IToggleCodeSwitch toggle = CodeSwitch.Factory.Toggle(); 21 | 22 | toggle.Enable(); 23 | 24 | Assert.IsTrue(toggle.Enabled); 25 | } 26 | 27 | [Test] 28 | public void Should_change_state_to_disabled() 29 | { 30 | IToggleCodeSwitch toggle = CodeSwitch.Factory.Toggle(true); 31 | 32 | 33 | toggle.Disable(); 34 | 35 | Assert.IsFalse(toggle.Enabled); 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/Fooidity.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/Fooidity/Caching/CachedCodeFeatureState.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Caching 2 | { 3 | using System; 4 | 5 | 6 | public class CachedCodeFeatureState : 7 | ICachedCodeFeatureState 8 | { 9 | readonly bool _enabled; 10 | readonly CodeFeatureId _id; 11 | 12 | public CachedCodeFeatureState(CodeFeatureId id, bool enabled) 13 | { 14 | _id = id; 15 | _enabled = enabled; 16 | } 17 | 18 | public CachedCodeFeatureState(Uri id, bool enabled) 19 | { 20 | _id = new CodeFeatureId(id); 21 | _enabled = enabled; 22 | } 23 | 24 | public CodeFeatureId Id 25 | { 26 | get { return _id; } 27 | } 28 | 29 | public bool Enabled 30 | { 31 | get { return _enabled; } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/Fooidity/Caching/CodeFeatureStateCacheInstance.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Caching 2 | { 3 | using Internals; 4 | 5 | 6 | class CodeFeatureStateCacheInstance : 7 | ICodeFeatureStateCacheInstance 8 | { 9 | readonly ICache _cache; 10 | readonly bool _defaultState; 11 | 12 | public CodeFeatureStateCacheInstance(ICache cache, bool defaultState) 13 | { 14 | _cache = cache; 15 | _defaultState = defaultState; 16 | } 17 | 18 | public bool DefaultState 19 | { 20 | get { return _defaultState; } 21 | } 22 | 23 | public int Count 24 | { 25 | get { return _cache.Values.Count; } 26 | } 27 | 28 | public bool TryGetState(CodeFeatureId id, out ICachedCodeFeatureState featureState) 29 | { 30 | return _cache.TryGet(id, out featureState); 31 | } 32 | 33 | public bool TryUpdate(CodeFeatureId id, ICachedCodeFeatureState featureState, ICachedCodeFeatureState previousFeatureState) 34 | { 35 | return _cache.TryUpdate(id, featureState, previousFeatureState); 36 | } 37 | 38 | public bool TryAdd(CodeFeatureId id, ICachedCodeFeatureState featureState) 39 | { 40 | return _cache.TryAdd(id, featureState); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/Fooidity/Caching/ContextFeatureStateCacheInstance.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Caching 2 | { 3 | using Internals; 4 | 5 | 6 | class ContextFeatureStateCacheInstance : 7 | IContextFeatureStateCacheInstance 8 | { 9 | readonly ICache _cache; 10 | 11 | public ContextFeatureStateCacheInstance(ICache cache) 12 | { 13 | _cache = cache; 14 | } 15 | 16 | public bool TryGetContextFeatureState(string key, out ICachedContextFeatureState featureState) 17 | { 18 | return _cache.TryGet(key, out featureState); 19 | } 20 | 21 | public bool TryAdd(string key, ICachedContextFeatureState contextFeatureState) 22 | { 23 | return _cache.TryAdd(key, contextFeatureState); 24 | } 25 | 26 | public int Count 27 | { 28 | get { return _cache.Values.Count; } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/Fooidity/Caching/ICachedCodeFeatureState.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Caching 2 | { 3 | /// 4 | /// The state of a code feature, typically loaded from a configuration source 5 | /// 6 | public interface ICachedCodeFeatureState 7 | { 8 | /// 9 | /// The switch Id, which is a URN formatted string based on the feature type 10 | /// 11 | CodeFeatureId Id { get; } 12 | 13 | /// 14 | /// The state of the switch 15 | /// 16 | bool Enabled { get; } 17 | } 18 | } -------------------------------------------------------------------------------- /src/Fooidity/Caching/ICachedContextFeatureState.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Caching 2 | { 3 | public interface ICachedContextFeatureState 4 | { 5 | string Key { get; } 6 | 7 | bool TryGetCodeFeatureState(CodeFeatureId codeFeatureId, out ICachedCodeFeatureState featureState); 8 | 9 | /// 10 | /// Attempt to update the code feature state to the new value 11 | /// 12 | /// 13 | /// 14 | /// 15 | /// 16 | bool TryUpdate(CodeFeatureId codeFeatureId, ICachedCodeFeatureState updated, ICachedCodeFeatureState existing); 17 | 18 | /// 19 | /// Try to add a new code feature state to the context 20 | /// 21 | /// 22 | /// 23 | /// 24 | bool TryAdd(CodeFeatureId codeFeatureId, ICachedCodeFeatureState featureState); 25 | } 26 | } -------------------------------------------------------------------------------- /src/Fooidity/Caching/ICodeFeatureStateCacheProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Caching 2 | { 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | 6 | 7 | public interface ICodeFeatureStateCacheProvider 8 | { 9 | /// 10 | /// Returns the default state for code features 11 | /// 12 | Task GetDefaultState(); 13 | 14 | /// 15 | /// Loads an enumeration of code feature states 16 | /// 17 | /// 18 | Task> Load(); 19 | } 20 | } -------------------------------------------------------------------------------- /src/Fooidity/Caching/IContextFeatureStateCacheInstance.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Caching 2 | { 3 | public interface IContextFeatureStateCacheInstance 4 | { 5 | /// 6 | /// The number of context entries in the cache 7 | /// 8 | int Count { get; } 9 | 10 | /// 11 | /// Return the context entry feature states if present 12 | /// 13 | /// 14 | /// 15 | /// 16 | bool TryGetContextFeatureState(string key, out ICachedContextFeatureState featureState); 17 | 18 | /// 19 | /// Try to add a context feature state to the cache 20 | /// 21 | /// 22 | /// 23 | /// 24 | bool TryAdd(string key, ICachedContextFeatureState contextFeatureState); 25 | } 26 | } -------------------------------------------------------------------------------- /src/Fooidity/Caching/IContextFeatureStateCacheProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Caching 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Threading.Tasks; 6 | 7 | 8 | public interface IContextFeatureStateCacheProvider 9 | { 10 | Task>> Load(); 11 | } 12 | } -------------------------------------------------------------------------------- /src/Fooidity/Caching/IReloadCache.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Caching 2 | { 3 | using System.Threading.Tasks; 4 | 5 | 6 | public interface IReloadCache 7 | { 8 | Task ReloadCache(); 9 | } 10 | } -------------------------------------------------------------------------------- /src/Fooidity/Caching/IUpdateCodeFeatureCache.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Caching 2 | { 3 | using Contracts; 4 | 5 | 6 | /// 7 | /// Update a cache using the supplied type argument 8 | /// 9 | public interface IUpdateCodeFeatureCache 10 | { 11 | void UpdateCache(IUpdateCodeFeature update); 12 | } 13 | } -------------------------------------------------------------------------------- /src/Fooidity/Caching/IUpdateContextFeatureCache.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Caching 2 | { 3 | using Contracts; 4 | 5 | 6 | /// 7 | /// Update a cache using the supplied type argument 8 | /// 9 | public interface IUpdateContextFeatureCache 10 | { 11 | void UpdateCache(IUpdateContextCodeFeature update); 12 | } 13 | } -------------------------------------------------------------------------------- /src/Fooidity/Caching/Internals/CacheItemAdded.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Caching.Internals 2 | { 3 | /// 4 | /// Signals an item was added to the cache 5 | /// 6 | /// 7 | interface CacheItemAdded 8 | { 9 | TValue Value { get; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/Fooidity/Caching/Internals/CacheItemRemoved.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Caching.Internals 2 | { 3 | /// 4 | /// Signals an item was removed from the cache 5 | /// 6 | /// 7 | interface CacheItemRemoved 8 | { 9 | TValue Value { get; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/Fooidity/Caching/Internals/CacheItemUpdated.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Caching.Internals 2 | { 3 | /// 4 | /// Signals an item in the cache was updated 5 | /// 6 | /// 7 | interface CacheItemUpdated 8 | { 9 | TValue Value { get; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/Fooidity/Caching/Internals/ConnectionHandle.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Caching.Internals 2 | { 3 | using System; 4 | 5 | 6 | interface ConnectionHandle : 7 | IDisposable 8 | { 9 | void Disconnect(); 10 | } 11 | } -------------------------------------------------------------------------------- /src/Fooidity/Caching/Internals/ICache.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Caching.Internals 2 | { 3 | /// 4 | /// A cache of objects with the primary index of type TKey 5 | /// 6 | /// The primary index type 7 | /// The value type 8 | interface ICache : 9 | IReadOnlyCache 10 | { 11 | bool TryAdd(TKey key, TValue value); 12 | 13 | bool TryRemove(TKey key); 14 | 15 | bool TryUpdate(TKey key, TValue value, TValue previousValue); 16 | } 17 | } -------------------------------------------------------------------------------- /src/Fooidity/Caching/Internals/ICacheIndex.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Caching.Internals 2 | { 3 | using System; 4 | 5 | 6 | /// 7 | /// An index to a cache for quick access to items 8 | /// 9 | /// 10 | /// 11 | interface ICacheIndex : 12 | IReadOnlyCache, 13 | IDisposable 14 | { 15 | } 16 | } -------------------------------------------------------------------------------- /src/Fooidity/Caching/Internals/IReadOnlyCache.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Caching.Internals 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | 7 | interface IReadOnlyCache : 8 | IObservable>, 9 | IObservable>, 10 | IObservable> 11 | { 12 | ICollection Values { get; } 13 | bool Contains(TKey key); 14 | bool ContainsValue(TValue value); 15 | 16 | bool Exists(Func predicate); 17 | 18 | bool Find(Func predicate, out TValue value); 19 | 20 | bool TryGet(TKey key, out TValue value); 21 | 22 | ICacheIndex GetIndex(Func keyProvider); 23 | } 24 | } -------------------------------------------------------------------------------- /src/Fooidity/CodeSwitch.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | /// 4 | /// A set of cached factory methods for various switch types 5 | /// 6 | public static class CodeSwitch 7 | { 8 | /// 9 | /// Factory instance used to create code switches, allowing extension methods 10 | /// to add new factory methods for a single point of creation 11 | /// 12 | public static ICodeSwitchFactory Factory 13 | { 14 | get { return Cached.CodeSwitchFactory; } 15 | } 16 | 17 | 18 | static class Cached 19 | { 20 | internal static readonly ICodeSwitchFactory CodeSwitchFactory = new CodeSwitchFactory(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Fooidity/CodeSwitchEvaluationObserver.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | using System; 4 | using System.Collections; 5 | using System.Collections.Concurrent; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using Contracts; 9 | 10 | 11 | /// 12 | /// Tracks the state of evaluated switches 13 | /// 14 | public class CodeSwitchEvaluationObserver : 15 | IObserver, 16 | ICodeSwitchesEvaluated 17 | { 18 | readonly ConcurrentBag _events; 19 | 20 | public CodeSwitchEvaluationObserver() 21 | { 22 | _events = new ConcurrentBag(); 23 | } 24 | 25 | public IEnumerator GetEnumerator() 26 | { 27 | return GetEvaluatedSwitches().GetEnumerator(); 28 | } 29 | 30 | IEnumerator IEnumerable.GetEnumerator() 31 | { 32 | return GetEnumerator(); 33 | } 34 | 35 | IEnumerable GetEvaluatedSwitches() 36 | { 37 | return _events.OrderBy(x => x.Timestamp).ToArray(); 38 | } 39 | 40 | public void OnNext(ICodeSwitchEvaluated value) 41 | { 42 | _events.Add(value); 43 | } 44 | 45 | public void OnError(Exception error) 46 | { 47 | } 48 | 49 | public void OnCompleted() 50 | { 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/Fooidity/CodeSwitchOfT.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ output extension="cs" #> 3 | <#@ assembly name="System.Core" #> 4 | <#@ import namespace="System.Linq" #> 5 | namespace Fooidity 6 | {<# for(int i=1; i<=16; i++){ 7 | var tActionArgs = String.Join(", ",Enumerable.Range(1,i).Select(it=>String.Format("T{0}",it))); 8 | #> 9 | 10 | public interface ICodeSwitch> : 11 | ICodeSwitch 12 | where T : struct, ICodeFeature 13 | <#= String.Join(Environment.NewLine + " ", Enumerable.Range(1, i).Select(x => String.Format("where T{0} : struct, ICodeFeature", x))) #> 14 | { 15 | <# for(int j = 1; j <= i; j++) { #> 16 | ICodeSwitch> Switch<#=j#> { get; } 17 | <# } #> 18 | } 19 | <# } #> 20 | } -------------------------------------------------------------------------------- /src/Fooidity/CodeSwitches/CodeSwitchEvaluatedObservable.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.CodeSwitches 2 | { 3 | using System; 4 | using Caching.Internals; 5 | using Contracts; 6 | using Metadata; 7 | 8 | 9 | class CodeSwitchEvaluatedObservable : 10 | Connectable> 11 | where TFeature : struct, ICodeFeature 12 | { 13 | public void Evaluated(bool enabled) 14 | { 15 | var evaluted = new CodeSwitchEvaluated(CodeFeatureMetadata.Id, enabled); 16 | ForEach(x => x.OnNext(evaluted)); 17 | } 18 | 19 | public void Evaluated(ContextId contextId, string contextKey, bool enabled) 20 | { 21 | var evaluted = new CodeSwitchEvaluated(CodeFeatureMetadata.Id, contextId, contextKey, enabled); 22 | ForEach(x => x.OnNext(evaluted)); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/Fooidity/CodeSwitches/CurrentTimeProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.CodeSwitches 2 | { 3 | using System; 4 | 5 | 6 | public delegate DateTime CurrentTimeProvider(); 7 | } -------------------------------------------------------------------------------- /src/Fooidity/CodeSwitches/DisabledCodeSwitch.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.CodeSwitches 2 | { 3 | using System; 4 | using Contracts; 5 | 6 | 7 | /// 8 | /// A disabled code switch is always disabled 9 | /// 10 | /// 11 | public class DisabledCodeSwitch : 12 | ICodeSwitch 13 | where TFeature : struct, ICodeFeature 14 | { 15 | readonly CodeSwitchEvaluatedObservable _evaluated; 16 | bool _evaluationComplete; 17 | 18 | public DisabledCodeSwitch() 19 | { 20 | _evaluated = new CodeSwitchEvaluatedObservable(); 21 | } 22 | 23 | bool ICodeSwitch.Enabled 24 | { 25 | get 26 | { 27 | if (!_evaluationComplete) 28 | { 29 | _evaluationComplete = true; 30 | 31 | _evaluated.Evaluated(false); 32 | } 33 | 34 | return false; 35 | } 36 | } 37 | 38 | public IDisposable Subscribe(IObserver observer) 39 | { 40 | return _evaluated.Connect(observer); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/Fooidity/CodeSwitches/EnabledCodeSwitch.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.CodeSwitches 2 | { 3 | using System; 4 | using Contracts; 5 | 6 | 7 | /// 8 | /// A code switch that is always on 9 | /// 10 | /// The code feature type 11 | public class EnabledCodeSwitch : 12 | ICodeSwitch 13 | where TFeature : struct, ICodeFeature 14 | { 15 | readonly CodeSwitchEvaluatedObservable _evaluated; 16 | bool _evaluationComplete; 17 | 18 | public EnabledCodeSwitch() 19 | { 20 | _evaluated = new CodeSwitchEvaluatedObservable(); 21 | } 22 | 23 | bool ICodeSwitch.Enabled 24 | { 25 | get 26 | { 27 | if (!_evaluationComplete) 28 | { 29 | _evaluationComplete = true; 30 | 31 | _evaluated.Evaluated(true); 32 | } 33 | 34 | return true; 35 | } 36 | } 37 | 38 | public IDisposable Subscribe(IObserver observer) 39 | { 40 | return _evaluated.Connect(observer); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/Fooidity/CodeSwitches/EnabledForAuthenticatedIdentityCodeSwitch.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.CodeSwitches 2 | { 3 | using System; 4 | using System.Security.Principal; 5 | using System.Threading; 6 | using Contracts; 7 | 8 | 9 | public class EnabledForAuthenticatedIdentityCodeSwitch : 10 | ICodeSwitch 11 | where TFeature : struct, ICodeFeature 12 | { 13 | readonly Lazy _enabled; 14 | readonly CodeSwitchEvaluatedObservable _evaluated; 15 | 16 | public EnabledForAuthenticatedIdentityCodeSwitch() 17 | { 18 | _evaluated = new CodeSwitchEvaluatedObservable(); 19 | _enabled = new Lazy(Evaluate); 20 | } 21 | 22 | public bool Enabled 23 | { 24 | get { return _enabled.Value; } 25 | } 26 | 27 | public IDisposable Subscribe(IObserver observer) 28 | { 29 | return _evaluated.Connect(observer); 30 | } 31 | 32 | static bool GetEnabled() 33 | { 34 | IPrincipal principal = Thread.CurrentPrincipal; 35 | if (principal == null) 36 | return false; 37 | 38 | return principal.Identity.IsAuthenticated; 39 | } 40 | 41 | bool Evaluate() 42 | { 43 | bool enabled = GetEnabled(); 44 | 45 | _evaluated.Evaluated(enabled); 46 | 47 | return enabled; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /src/Fooidity/CodeSwitches/IToggleSwitchState.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.CodeSwitches 2 | { 3 | /// 4 | /// Retains the state of the toggle switch outside of the switch itself. This is to ensure that 5 | /// each switch evaluation is able to be tracked and reported in the event of an exception 6 | /// 7 | /// 8 | public interface IToggleSwitchState 9 | where TFeature : struct, ICodeFeature 10 | { 11 | bool Enabled { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/Fooidity/CodeSwitches/ToggleSwitchState.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.CodeSwitches 2 | { 3 | public class ToggleSwitchState : 4 | IToggleSwitchState 5 | where TFeature : struct, ICodeFeature 6 | { 7 | public ToggleSwitchState() 8 | { 9 | } 10 | 11 | public ToggleSwitchState(bool initial) 12 | { 13 | Enabled = initial; 14 | } 15 | 16 | public bool Enabled { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /src/Fooidity/Configuration/ContextElement.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Configuration 2 | { 3 | using System.Configuration; 4 | 5 | 6 | public class ContextElement : 7 | ConfigurationElement 8 | { 9 | [ConfigurationProperty("id", DefaultValue = "", IsRequired = false)] 10 | public string Id 11 | { 12 | get { return (string)this["id"]; } 13 | set { this["id"] = value; } 14 | } 15 | 16 | [ConfigurationProperty("instances", IsDefaultCollection = true, IsRequired = false), 17 | ConfigurationCollection(typeof(ContextInstanceElementCollection))] 18 | public ContextInstanceElementCollection Instances 19 | { 20 | get { return (ContextInstanceElementCollection)this["instances"]; } 21 | set { this["instances"] = value; } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/Fooidity/Configuration/ContextInstanceElement.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Configuration 2 | { 3 | using System.Configuration; 4 | 5 | 6 | public class ContextInstanceElement : 7 | ConfigurationElement 8 | { 9 | [ConfigurationProperty("key", IsRequired = true)] 10 | public string Key 11 | { 12 | get { return (string)this["key"]; } 13 | set { this["key"] = value; } 14 | } 15 | 16 | [ConfigurationProperty("features", IsDefaultCollection = true, IsRequired = false), 17 | ConfigurationCollection(typeof(FeatureStateElementCollection))] 18 | public FeatureStateElementCollection Features 19 | { 20 | get { return (FeatureStateElementCollection)this["features"]; } 21 | set { this["features"] = value; } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/Fooidity/Configuration/DefaultCodeFeatureState.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Configuration 2 | { 3 | using Caching; 4 | using Metadata; 5 | 6 | 7 | public class DefaultCodeFeatureState : 8 | ICachedCodeFeatureState 9 | { 10 | readonly bool _enabled; 11 | 12 | public DefaultCodeFeatureState(bool enabled) 13 | { 14 | _enabled = enabled; 15 | } 16 | 17 | public CodeFeatureId Id 18 | { 19 | get { return CodeFeatureMetadata.Id; } 20 | } 21 | 22 | public bool Enabled 23 | { 24 | get { return _enabled; } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/Fooidity/Configuration/FeatureStateElement.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Configuration 2 | { 3 | using System.Configuration; 4 | 5 | 6 | public class FeatureStateElement : 7 | ConfigurationElement 8 | { 9 | [ConfigurationProperty("id", IsRequired = true)] 10 | public string Id 11 | { 12 | get { return (string)this["id"]; } 13 | set { this["id"] = value; } 14 | } 15 | 16 | [ConfigurationProperty("enabled", DefaultValue = false, IsRequired = false)] 17 | public bool Enabled 18 | { 19 | get { return (bool)this["enabled"]; } 20 | set { this["enabled"] = value; } 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Fooidity/Configuration/FooidityConfigurationSection.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Configuration 2 | { 3 | using System.Configuration; 4 | 5 | 6 | public class FooidityConfiguration : 7 | ConfigurationSection 8 | { 9 | [ConfigurationProperty("defaultState", DefaultValue = false, IsRequired = false)] 10 | public bool DefaultState 11 | { 12 | get { return (bool)this["defaultState"]; } 13 | set { this["defaultState"] = value; } 14 | } 15 | 16 | [ConfigurationProperty("features", IsDefaultCollection = false, IsRequired = false), 17 | ConfigurationCollection(typeof(FeatureStateElementCollection))] 18 | public FeatureStateElementCollection Features 19 | { 20 | get { return (FeatureStateElementCollection)this["features"]; } 21 | set { this["features"] = value; } 22 | } 23 | 24 | [ConfigurationProperty("contexts", IsDefaultCollection = false, IsRequired = false), 25 | ConfigurationCollection(typeof(ContextElementCollection))] 26 | public ContextElementCollection Contexts 27 | { 28 | get { return (ContextElementCollection)this["contexts"]; } 29 | set { this["contexts"] = value; } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/Fooidity/ContextId.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | using System; 4 | using System.Runtime.Serialization; 5 | using System.Text; 6 | 7 | 8 | /// 9 | /// A context id is generated based on the type and is used to identify a context 10 | /// in configuration sources 11 | /// 12 | [Serializable] 13 | public class ContextId : 14 | TypeUrn 15 | { 16 | public ContextId(Type type) 17 | : base(GetCodeFeatureId(type)) 18 | { 19 | } 20 | 21 | public ContextId(string uriString) 22 | : base(uriString) 23 | { 24 | if (!Scheme.Equals("urn", StringComparison.OrdinalIgnoreCase)) 25 | throw new FormatException("A ContextFeatureId must be a URN"); 26 | } 27 | 28 | protected ContextId(SerializationInfo serializationInfo, StreamingContext streamingContext) 29 | : base(serializationInfo, streamingContext) 30 | { 31 | } 32 | 33 | public ContextId(Uri uri) 34 | : base(uri.ToString()) 35 | { 36 | if (!Scheme.Equals("urn", StringComparison.OrdinalIgnoreCase)) 37 | throw new FormatException("A ContextFeatureId must be a URN"); 38 | } 39 | 40 | static string GetCodeFeatureId(Type type) 41 | { 42 | var sb = new StringBuilder("urn:context:"); 43 | 44 | return FormatId(sb, type, true); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/CodeFeatureState.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | 5 | 6 | public class CodeFeatureState : 7 | ICodeFeatureState, 8 | IEquatable 9 | { 10 | public CodeFeatureState(Uri codeFeatureId, DateTime lastUpdated, bool enabled) 11 | { 12 | CodeFeatureId = codeFeatureId; 13 | LastUpdated = lastUpdated; 14 | Enabled = enabled; 15 | } 16 | 17 | public Uri CodeFeatureId { get; set; } 18 | public DateTime LastUpdated { get; set; } 19 | public bool Enabled { get; set; } 20 | 21 | public bool Equals(CodeFeatureState other) 22 | { 23 | if (ReferenceEquals(null, other)) 24 | return false; 25 | if (ReferenceEquals(this, other)) 26 | return true; 27 | 28 | return CodeFeatureId.Equals(other.CodeFeatureId); 29 | } 30 | 31 | public override bool Equals(object obj) 32 | { 33 | if (ReferenceEquals(null, obj)) 34 | return false; 35 | if (ReferenceEquals(this, obj)) 36 | return true; 37 | if (obj.GetType() != GetType()) 38 | return false; 39 | 40 | return Equals((CodeFeatureState)obj); 41 | } 42 | 43 | public override int GetHashCode() 44 | { 45 | return CodeFeatureId.GetHashCode(); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/CodeFeatureStateCacheLoaded.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | using Metadata; 5 | 6 | 7 | public class CodeFeatureStateCacheLoaded : 8 | ICodeFeatureStateCacheLoaded 9 | { 10 | public CodeFeatureStateCacheLoaded() 11 | { 12 | } 13 | 14 | public CodeFeatureStateCacheLoaded(DateTime timestamp, TimeSpan duration, int codeFeatureCount) 15 | { 16 | EventId = Guid.NewGuid(); 17 | Timestamp = timestamp; 18 | Duration = duration; 19 | CodeFeatureCount = codeFeatureCount; 20 | Host = HostMetadata.Host; 21 | } 22 | 23 | public Host Host { get; set; } 24 | 25 | public Guid EventId { get; set; } 26 | 27 | public DateTime Timestamp { get; set; } 28 | 29 | public TimeSpan Duration { get; set; } 30 | 31 | public int CodeFeatureCount { get; set; } 32 | 33 | IHost ICodeFeatureStateCacheLoaded.Host 34 | { 35 | get { return Host; } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/CodeFeatureStateCacheUpdated.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | using Metadata; 5 | 6 | 7 | class CodeFeatureStateCacheUpdated : 8 | ICodeFeatureStateCacheUpdated 9 | { 10 | public CodeFeatureStateCacheUpdated() 11 | { 12 | } 13 | 14 | public CodeFeatureStateCacheUpdated(DateTime timestamp, TimeSpan duration, Uri codeFeatureId, bool enabled, 15 | Guid? commandId = null) 16 | { 17 | EventId = Guid.NewGuid(); 18 | Timestamp = timestamp; 19 | Duration = duration; 20 | CodeFeatureId = codeFeatureId; 21 | Enabled = enabled; 22 | CommandId = commandId; 23 | Host = HostMetadata.Host; 24 | } 25 | 26 | public Host Host { get; set; } 27 | 28 | public Guid EventId { get; set; } 29 | 30 | public DateTime Timestamp { get; set; } 31 | 32 | public Guid? CommandId { get; set; } 33 | 34 | public TimeSpan Duration { get; set; } 35 | 36 | public Uri CodeFeatureId { get; set; } 37 | 38 | public bool Enabled { get; set; } 39 | 40 | IHost ICodeFeatureStateCacheUpdated.Host 41 | { 42 | get { return Host; } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/CodeFeatureStateUpdated.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | 5 | 6 | public class CodeFeatureStateUpdated : 7 | ICodeFeatureStateUpdated 8 | { 9 | public CodeFeatureStateUpdated() 10 | { 11 | } 12 | 13 | public CodeFeatureStateUpdated(Uri codeFeatureId, bool enabled, Guid eventId, DateTime timestamp, Guid? commandId = null) 14 | { 15 | CodeFeatureId = codeFeatureId; 16 | Enabled = enabled; 17 | CommandId = commandId; 18 | EventId = eventId; 19 | Timestamp = timestamp; 20 | } 21 | 22 | public Guid EventId { get; set; } 23 | 24 | public DateTime Timestamp { get; set; } 25 | 26 | public Guid? CommandId { get; set; } 27 | 28 | public Uri CodeFeatureId { get; set; } 29 | 30 | public bool Enabled { get; set; } 31 | } 32 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/CodeSwitchEvaluated.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | using Metadata; 5 | 6 | 7 | public class CodeSwitchEvaluated : 8 | ICodeSwitchEvaluated 9 | { 10 | public CodeSwitchEvaluated() 11 | { 12 | } 13 | 14 | public CodeSwitchEvaluated(Uri codeFeatureId, bool enabled) 15 | { 16 | Timestamp = DateTime.UtcNow; 17 | CodeFeatureId = codeFeatureId; 18 | Enabled = enabled; 19 | Host = HostMetadata.Host; 20 | } 21 | 22 | public CodeSwitchEvaluated(Uri codeFeatureId, Uri contextId, string contextKey, bool enabled) 23 | : this(codeFeatureId, enabled) 24 | { 25 | ContextId = contextId; 26 | ContextKey = contextKey; 27 | } 28 | 29 | public Host Host { get; set; } 30 | 31 | public DateTime Timestamp { get; set; } 32 | 33 | public Uri CodeFeatureId { get; set; } 34 | 35 | public bool Enabled { get; set; } 36 | 37 | public Uri ContextId { get; set; } 38 | 39 | public string ContextKey { get; set; } 40 | 41 | IHost ICodeSwitchEvaluated.Host 42 | { 43 | get { return Host; } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/ContextCodeFeatureStateCacheLoaded.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | using Metadata; 5 | 6 | 7 | public class ContextCodeFeatureStateCacheLoaded : 8 | IContextCodeFeatureStateCacheLoaded 9 | { 10 | public ContextCodeFeatureStateCacheLoaded() 11 | { 12 | } 13 | 14 | public ContextCodeFeatureStateCacheLoaded(DateTime timestamp, TimeSpan duration, int contextCount) 15 | { 16 | EventId = Guid.NewGuid(); 17 | Timestamp = timestamp; 18 | Duration = duration; 19 | ContextCount = contextCount; 20 | Host = HostMetadata.Host; 21 | } 22 | 23 | public Host Host { get; private set; } 24 | 25 | public Guid EventId { get; private set; } 26 | 27 | public DateTime Timestamp { get; private set; } 28 | 29 | public TimeSpan Duration { get; private set; } 30 | 31 | public int ContextCount { get; private set; } 32 | 33 | IHost IContextCodeFeatureStateCacheLoaded.Host 34 | { 35 | get { return Host; } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/ContextCodeFeatureStateCacheUpdated.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | using Metadata; 5 | 6 | 7 | public class ContextCodeFeatureStateCacheUpdated : 8 | IContextCodeFeatureStateCacheUpdated 9 | { 10 | public ContextCodeFeatureStateCacheUpdated() 11 | { 12 | } 13 | 14 | public ContextCodeFeatureStateCacheUpdated(Uri contextId, string contextKey, Uri codeFeatureId, bool enabled, Guid? commandId = null) 15 | { 16 | EventId = Guid.NewGuid(); 17 | Timestamp = DateTime.UtcNow; 18 | 19 | CommandId = commandId; 20 | ContextId = contextId; 21 | ContextKey = contextKey; 22 | CodeFeatureId = codeFeatureId; 23 | Enabled = enabled; 24 | Host = HostMetadata.Host; 25 | } 26 | 27 | public Host Host { get; private set; } 28 | 29 | public bool Enabled { get; private set; } 30 | 31 | public Guid EventId { get; private set; } 32 | 33 | public DateTime Timestamp { get; private set; } 34 | 35 | public Guid? CommandId { get; private set; } 36 | 37 | public Uri ContextId { get; private set; } 38 | 39 | public string ContextKey { get; private set; } 40 | 41 | public Uri CodeFeatureId { get; private set; } 42 | 43 | IHost IContextCodeFeatureStateCacheUpdated.Host 44 | { 45 | get { return Host; } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/ContextCodeFeatureStateUpdated.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | 5 | 6 | public class ContextCodeFeatureStateUpdated : 7 | IContextCodeFeatureStateUpdated 8 | { 9 | public ContextCodeFeatureStateUpdated() 10 | { 11 | } 12 | 13 | public ContextCodeFeatureStateUpdated(Uri contextId, string contextKey, Uri codeFeatureId, bool enabled, Guid? commandId = null) 14 | { 15 | EventId = Guid.NewGuid(); 16 | Timestamp = DateTime.UtcNow; 17 | 18 | CodeFeatureId = codeFeatureId; 19 | Enabled = enabled; 20 | CommandId = commandId; 21 | ContextId = contextId; 22 | ContextKey = contextKey; 23 | } 24 | 25 | public bool Enabled { get; set; } 26 | 27 | public Guid EventId { get; set; } 28 | 29 | public DateTime Timestamp { get; set; } 30 | 31 | public Guid? CommandId { get; set; } 32 | 33 | public Uri CodeFeatureId { get; set; } 34 | 35 | public Uri ContextId { get; set; } 36 | 37 | public string ContextKey { get; set; } 38 | } 39 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/HeaderNames.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | public static class Headers 4 | { 5 | public const string FooidityAppKey = "X-Fooidity-AppKey"; 6 | } 7 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/Host.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | public class Host : 4 | IHost 5 | { 6 | public string FooidityVersion { get; set; } 7 | 8 | public string MachineName { get; set; } 9 | 10 | public string ProcessName { get; set; } 11 | 12 | public int ProcessId { get; set; } 13 | 14 | public string Assembly { get; set; } 15 | 16 | public string AssemblyVersion { get; set; } 17 | 18 | public string FrameworkVersion { get; set; } 19 | 20 | public string OsVersion { get; set; } 21 | } 22 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/ICodeFeatureState.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | 5 | 6 | public interface ICodeFeatureState 7 | { 8 | Uri CodeFeatureId { get; } 9 | 10 | DateTime LastUpdated { get; } 11 | 12 | bool Enabled { get; } 13 | } 14 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/ICodeFeatureStateCacheLoaded.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | 5 | 6 | /// 7 | /// Observable when the state cache is loaded 8 | /// 9 | public interface ICodeFeatureStateCacheLoaded 10 | { 11 | /// 12 | /// Identifies the event 13 | /// 14 | Guid EventId { get; } 15 | 16 | /// 17 | /// The time the cache load started 18 | /// 19 | DateTime Timestamp { get; } 20 | 21 | /// 22 | /// The time taken to load the cache 23 | /// 24 | TimeSpan Duration { get; } 25 | 26 | /// 27 | /// The number of code features loaded 28 | /// 29 | int CodeFeatureCount { get; } 30 | 31 | /// 32 | /// The host that loaded the cache 33 | /// 34 | IHost Host { get; } 35 | } 36 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/ICodeFeatureStateCacheUpdated.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | 5 | 6 | /// 7 | /// Observable when the state cache is loaded 8 | /// 9 | public interface ICodeFeatureStateCacheUpdated 10 | { 11 | Guid EventId { get; } 12 | 13 | /// 14 | /// The time the cache update started 15 | /// 16 | DateTime Timestamp { get; } 17 | 18 | /// 19 | /// The time taken to update the cache 20 | /// 21 | TimeSpan Duration { get; } 22 | 23 | /// 24 | /// The command identifier that triggered the update 25 | /// 26 | Guid? CommandId { get; } 27 | 28 | /// 29 | /// The FeatureId that was updated 30 | /// 31 | Uri CodeFeatureId { get; } 32 | 33 | /// 34 | /// The updated state of the feature 35 | /// 36 | bool Enabled { get; } 37 | 38 | /// 39 | /// The host that loaded the cache 40 | /// 41 | IHost Host { get; } 42 | } 43 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/ICodeFeatureStateUpdated.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | 5 | 6 | /// 7 | /// Sent to the cache when the state of code feature is updated, so that the cache can be updated 8 | /// 9 | public interface ICodeFeatureStateUpdated 10 | { 11 | Guid EventId { get; } 12 | 13 | /// 14 | /// When the feature state was updated 15 | /// 16 | DateTime Timestamp { get; } 17 | 18 | /// 19 | /// The identifier of the command that enabled the context code feature 20 | /// 21 | Guid? CommandId { get; } 22 | 23 | /// 24 | /// The FeatureId that was updated 25 | /// 26 | Uri CodeFeatureId { get; } 27 | 28 | /// 29 | /// The new state of the code feature 30 | /// 31 | bool Enabled { get; } 32 | } 33 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/ICodeSwitchEvaluated.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | 5 | 6 | /// 7 | /// Published when a code switch is evaluated, such that the state of the switch can be 8 | /// captured for use in later activations 9 | /// 10 | public interface ICodeSwitchEvaluated 11 | { 12 | /// 13 | /// The time at which the feature state was evaluated 14 | /// 15 | DateTime Timestamp { get; } 16 | 17 | /// 18 | /// The feature identifier connected to the code switch 19 | /// 20 | Uri CodeFeatureId { get; } 21 | 22 | /// 23 | /// Whether the feature was enabled or disabled after evaluation 24 | /// 25 | bool Enabled { get; } 26 | 27 | /// 28 | /// If context was used to evaluate the switch, the context id 29 | /// 30 | Uri ContextId { get; } 31 | 32 | /// 33 | /// The key used to select the context if a context is used 34 | /// 35 | string ContextKey { get; } 36 | 37 | /// 38 | /// The host on which the switch was evaluated 39 | /// 40 | IHost Host { get; } 41 | } 42 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/IContextCodeFeatureStateCacheLoaded.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | 5 | 6 | /// 7 | /// Observable when the state cache is loaded 8 | /// 9 | public interface IContextCodeFeatureStateCacheLoaded 10 | { 11 | /// 12 | /// Identifies the event 13 | /// 14 | Guid EventId { get; } 15 | 16 | /// 17 | /// The time the cache load started 18 | /// 19 | DateTime Timestamp { get; } 20 | 21 | /// 22 | /// The time taken to load the cache 23 | /// 24 | TimeSpan Duration { get; } 25 | 26 | /// 27 | /// The number of context instances 28 | /// 29 | int ContextCount { get; } 30 | 31 | /// 32 | /// The host that loaded the cache 33 | /// 34 | IHost Host { get; } 35 | } 36 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/IContextCodeFeatureStateCacheUpdated.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | 5 | 6 | /// 7 | /// Observable when the state cache is loaded 8 | /// 9 | public interface IContextCodeFeatureStateCacheUpdated 10 | { 11 | Guid EventId { get; } 12 | 13 | /// 14 | /// The time the cache update started 15 | /// 16 | DateTime Timestamp { get; } 17 | 18 | /// 19 | /// The command identifier that triggered the update 20 | /// 21 | Guid? CommandId { get; } 22 | 23 | /// 24 | /// The context that was updated 25 | /// 26 | Uri ContextId { get; } 27 | 28 | /// 29 | /// The key that was updated 30 | /// 31 | string ContextKey { get; } 32 | 33 | /// 34 | /// The FeatureId that was updated 35 | /// 36 | Uri CodeFeatureId { get; } 37 | 38 | /// 39 | /// The updated state of the feature 40 | /// 41 | bool Enabled { get; } 42 | 43 | /// 44 | /// The host that loaded the cache 45 | /// 46 | IHost Host { get; } 47 | } 48 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/IContextCodeFeatureStateUpdated.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | 5 | 6 | public interface IContextCodeFeatureStateUpdated 7 | { 8 | /// 9 | /// Identifies the event uniquely 10 | /// 11 | Guid EventId { get; } 12 | 13 | /// 14 | /// When the feature state was updated 15 | /// 16 | DateTime Timestamp { get; } 17 | 18 | /// 19 | /// The identifier of the command that enabled the context code feature 20 | /// 21 | Guid? CommandId { get; } 22 | 23 | /// 24 | /// The FeatureId that was updated 25 | /// 26 | Uri CodeFeatureId { get; } 27 | 28 | /// 29 | /// The context in which the code feature was updated 30 | /// 31 | Uri ContextId { get; } 32 | 33 | /// 34 | /// The context instance in which the code feature was updated 35 | /// 36 | string ContextKey { get; } 37 | 38 | /// 39 | /// if the code feature was enabled 40 | /// 41 | bool Enabled { get; } 42 | } 43 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/IUpdateCodeFeature.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | 5 | 6 | /// 7 | /// Sent to the cache when the state of code feature is updated, so that the cache can be updated 8 | /// 9 | public interface IUpdateCodeFeature 10 | { 11 | Guid CommandId { get; } 12 | 13 | /// 14 | /// When the feature state was updated 15 | /// 16 | DateTime Timestamp { get; } 17 | 18 | /// 19 | /// The FeatureId that was updated 20 | /// 21 | CodeFeatureId CodeFeatureId { get; } 22 | 23 | /// 24 | /// The updated state of the feature 25 | /// 26 | bool Enabled { get; } 27 | } 28 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/IUpdateContextCodeFeature.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | 5 | 6 | /// 7 | /// Sent to the cache when the state of code feature is updated, so that the cache can be updated 8 | /// 9 | public interface IUpdateContextCodeFeature 10 | { 11 | Guid CommandId { get; } 12 | 13 | /// 14 | /// When the feature state was updated 15 | /// 16 | DateTime Timestamp { get; } 17 | 18 | /// 19 | /// The FeatureId that was updated 20 | /// 21 | CodeFeatureId CodeFeatureId { get; } 22 | 23 | /// 24 | /// The context in which the code feature was updated 25 | /// 26 | Uri ContextId { get; } 27 | 28 | /// 29 | /// The context instance in which the code feature was updated 30 | /// 31 | string ContextKey { get; } 32 | 33 | /// 34 | /// The updated state of the feature 35 | /// 36 | bool Enabled { get; } 37 | } 38 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/UpdateCodeFeature.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | 5 | 6 | public class UpdateCodeFeature : 7 | IUpdateCodeFeature 8 | { 9 | public UpdateCodeFeature() 10 | { 11 | } 12 | 13 | public UpdateCodeFeature(CodeFeatureId codeFeatureId, bool enabled, DateTime timestamp, Guid commandId) 14 | { 15 | CodeFeatureId = codeFeatureId; 16 | CommandId = commandId; 17 | Enabled = enabled; 18 | Timestamp = timestamp; 19 | } 20 | 21 | public Guid CommandId { get; set; } 22 | 23 | public DateTime Timestamp { get; set; } 24 | 25 | public CodeFeatureId CodeFeatureId { get; set; } 26 | 27 | public bool Enabled { get; set; } 28 | } 29 | } -------------------------------------------------------------------------------- /src/Fooidity/Contracts/UpdateContextCodeFeature.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Contracts 2 | { 3 | using System; 4 | 5 | 6 | public class UpdateContextCodeFeature : 7 | IUpdateContextCodeFeature 8 | { 9 | public UpdateContextCodeFeature() 10 | { 11 | } 12 | 13 | public UpdateContextCodeFeature(Uri contextId, string contextKey, CodeFeatureId codeFeatureId, bool enabled, DateTime timestamp, 14 | Guid commandId) 15 | { 16 | CodeFeatureId = codeFeatureId; 17 | CommandId = commandId; 18 | ContextId = contextId; 19 | Enabled = enabled; 20 | ContextKey = contextKey; 21 | Timestamp = timestamp; 22 | } 23 | 24 | public Guid CommandId { get; set; } 25 | 26 | public DateTime Timestamp { get; set; } 27 | 28 | public CodeFeatureId CodeFeatureId { get; set; } 29 | 30 | public Uri ContextId { get; set; } 31 | 32 | public string ContextKey { get; set; } 33 | 34 | public bool Enabled { get; set; } 35 | } 36 | } -------------------------------------------------------------------------------- /src/Fooidity/DefaultContextProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | using System; 4 | 5 | 6 | /// 7 | /// Returns a default context for the given input type. Should be registered in the container 8 | /// as the default generic implementation. 9 | /// 10 | /// 11 | /// 12 | public class DefaultContextProvider : 13 | IContextProvider 14 | { 15 | Type IContextProvider.InputType 16 | { 17 | get { return typeof(TInput); } 18 | } 19 | 20 | bool IContextProvider.TryGetContext(T input, out TContext context) 21 | { 22 | context = default(TContext); 23 | return false; 24 | } 25 | 26 | bool IContextProvider.TryGetContext(TInput input, out TContext context) 27 | { 28 | context = default(TContext); 29 | return false; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/Fooidity/Dependents/DependentCodeSwitchFactory.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ output extension="cs" #> 3 | <#@ assembly name="System.Core" #> 4 | <#@ import namespace="System.Linq" #> 5 | namespace Fooidity.Dependents 6 | { 7 | public class DependentCodeSwitchFactory : 8 | IDependentCodeSwitchFactory 9 | where T : struct, ICodeFeature 10 | { 11 | <# for(int i=1; i<=16; i++){ 12 | var tActionArgs = String.Join(", ",Enumerable.Range(1,i).Select(it=>String.Format("T{0}",it))); 13 | var tPrevArgs = String.Join(", ",new[]{"T"}.Concat(Enumerable.Range(1,i-1).Select(it=>String.Format("T{0}",it)))); 14 | #> 15 | public ICodeSwitch> Upon<<#=tActionArgs#>>(<#= String.Join(", ", Enumerable.Range(1, i).Select(x => String.Format("ICodeSwitch codeSwitch{0}", x))) #>) 16 | <#= String.Join(Environment.NewLine + " ", Enumerable.Range(1, i).Select(x => String.Format("where T{0} : struct, ICodeFeature", x))) #> 17 | { 18 | return new DependentCodeSwitch>(<#= String.Join(", ", Enumerable.Range(1, i).Select(x => String.Format("codeSwitch{0}", x))) #>); 19 | } 20 | 21 | <# } #> 22 | } 23 | } -------------------------------------------------------------------------------- /src/Fooidity/Dependents/IDependentCodeSwitchFactory.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ output extension="cs" #> 3 | <#@ assembly name="System.Core" #> 4 | <#@ import namespace="System.Linq" #> 5 | namespace Fooidity.Dependents 6 | { 7 | public interface IDependentCodeSwitchFactory 8 | where T : struct, ICodeFeature 9 | {<# for(int i=1; i<=16; i++){ 10 | var tActionArgs = String.Join(", ",Enumerable.Range(1,i).Select(it=>String.Format("T{0}",it))); 11 | var tPrevArgs = String.Join(", ",new[]{"T"}.Concat(Enumerable.Range(1,i-1).Select(it=>String.Format("T{0}",it)))); 12 | #> 13 | 14 | ICodeSwitch> Upon<<#=tActionArgs#>>(<#= String.Join(", ", Enumerable.Range(1, i).Select(x => String.Format("ICodeSwitch fooId{0}", x))) #>) 15 | <#= String.Join(Environment.NewLine + " ", Enumerable.Range(1, i).Select(x => String.Format("where T{0} : struct, ICodeFeature", x))) #>; 16 | <# } #> 17 | } 18 | } -------------------------------------------------------------------------------- /src/Fooidity/Exceptions/CacheProviderSourceException.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | using System; 4 | using System.Runtime.Serialization; 5 | 6 | 7 | [Serializable] 8 | public class CacheProviderSourceException : 9 | FooidityException 10 | { 11 | public CacheProviderSourceException() 12 | { 13 | } 14 | 15 | public CacheProviderSourceException(string message) 16 | : base(message) 17 | { 18 | } 19 | 20 | public CacheProviderSourceException(string message, Exception innerException) 21 | : base(message, innerException) 22 | { 23 | } 24 | 25 | protected CacheProviderSourceException(SerializationInfo info, StreamingContext context) 26 | : base(info, context) 27 | { 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/Fooidity/Exceptions/ContextSwitchException.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | using System; 4 | using System.Runtime.Serialization; 5 | 6 | 7 | [Serializable] 8 | public class ContextSwitchException : 9 | FooidityException 10 | { 11 | public ContextSwitchException() 12 | { 13 | } 14 | 15 | public ContextSwitchException(string message) 16 | : base(message) 17 | { 18 | } 19 | 20 | public ContextSwitchException(string message, Exception innerException) 21 | : base(message, innerException) 22 | { 23 | } 24 | 25 | protected ContextSwitchException(SerializationInfo info, StreamingContext context) 26 | : base(info, context) 27 | { 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/Fooidity/Exceptions/FooidityException.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | using System; 4 | using System.Runtime.Serialization; 5 | 6 | 7 | [Serializable] 8 | public class FooidityException : 9 | Exception 10 | { 11 | public FooidityException() 12 | { 13 | } 14 | 15 | public FooidityException(string message) 16 | : base(message) 17 | { 18 | } 19 | 20 | public FooidityException(string message, Exception innerException) 21 | : base(message, innerException) 22 | { 23 | } 24 | 25 | protected FooidityException(SerializationInfo info, StreamingContext context) 26 | : base(info, context) 27 | { 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/Fooidity/Fooidity.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True -------------------------------------------------------------------------------- /src/Fooidity/ICodeFeature.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | /// 4 | /// A code feature identifies a switch which can be enabled or disabled. Code features must 5 | /// be implemented as structs, and should be public to support discoverability. 6 | /// 7 | /// public struct MyFeature : ICodeFeature {} 8 | /// 9 | public interface ICodeFeature 10 | { 11 | } 12 | } -------------------------------------------------------------------------------- /src/Fooidity/ICodeFeatureStateCache.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | using Caching; 4 | 5 | 6 | /// 7 | /// A cache of switches and their states 8 | /// 9 | public interface ICodeFeatureStateCache 10 | { 11 | /// 12 | /// Return the cached feature state, if available 13 | /// 14 | /// 15 | /// 16 | /// 17 | bool TryGetState(out ICachedCodeFeatureState featureState); 18 | } 19 | } -------------------------------------------------------------------------------- /src/Fooidity/ICodeSwitch.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | using System; 4 | using Contracts; 5 | 6 | 7 | /// 8 | /// A code switch determines and returns the state of the switch based on any environmental 9 | /// conditions that are present at the time of the switch being evaluated. 10 | /// 11 | /// The code feature that identifies the switch state 12 | public interface ICodeSwitch : 13 | IObservable 14 | where TFeature : struct, ICodeFeature 15 | { 16 | /// 17 | /// Returns true if the FooId is enabled 18 | /// 19 | bool Enabled { get; } 20 | } 21 | } -------------------------------------------------------------------------------- /src/Fooidity/ICodeSwitchContainerScope.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | using System; 4 | 5 | 6 | /// 7 | /// To switch by context, a container scope needs to be created and then used 8 | /// to resolve an instance of the consumer. 9 | /// 10 | public interface ICodeSwitchContainerScope : 11 | IDisposable 12 | { 13 | /// 14 | /// Create a nested container scope without a resolved context 15 | /// 16 | /// 17 | ICodeSwitchContainerScope CreateContainerScope(); 18 | 19 | /// 20 | /// Create a nested container scope 21 | /// 22 | /// The context type 23 | /// The context to add to the container 24 | /// 25 | ICodeSwitchContainerScope CreateContainerScope(TContext context) 26 | where TContext : class; 27 | 28 | /// 29 | /// Try to resolve an object of the specified type, returning that instance if available 30 | /// 31 | /// 32 | /// 33 | /// 34 | bool TryResolve(out T instance) 35 | where T : class; 36 | } 37 | } -------------------------------------------------------------------------------- /src/Fooidity/ICodeSwitchEventHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | using System.Threading.Tasks; 4 | using Contracts; 5 | 6 | 7 | public interface ICodeSwitchEventHandler 8 | { 9 | Task Handle(ICodeSwitchEvaluated message); 10 | } 11 | } -------------------------------------------------------------------------------- /src/Fooidity/ICodeSwitchesEvaluated.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | using System.Collections.Generic; 4 | using Contracts; 5 | 6 | 7 | /// 8 | /// Obtain a list of evaluated code switches during execution 9 | /// 10 | public interface ICodeSwitchesEvaluated : 11 | IEnumerable 12 | { 13 | } 14 | } -------------------------------------------------------------------------------- /src/Fooidity/IContextCodeSwitch.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | public interface IContextCodeSwitch : 4 | ICodeSwitch 5 | where TFeature : struct, ICodeFeature 6 | { 7 | } 8 | } -------------------------------------------------------------------------------- /src/Fooidity/IContextFeatureStateCache.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | using Caching; 4 | 5 | 6 | /// 7 | /// A cache of contextual feature states, which can be configured per-context 8 | /// 9 | /// 10 | public interface IContextFeatureStateCache 11 | { 12 | bool TryGetContextFeatureState(TContext context, out ICachedContextFeatureState featureState); 13 | } 14 | } -------------------------------------------------------------------------------- /src/Fooidity/IContextKeyProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | /// 4 | /// Used to convert context to a key, for storage purposes 5 | /// 6 | /// The context type 7 | public interface IContextKeyProvider 8 | { 9 | /// 10 | /// Return a key for the specified context, used to correlate the context to a 11 | /// saved feature state configuration for that context. 12 | /// 13 | /// The context to convert 14 | /// The resulting key type 15 | string GetKey(TContext context); 16 | } 17 | } -------------------------------------------------------------------------------- /src/Fooidity/IContextProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | using System; 4 | 5 | 6 | /// 7 | /// Supports returning a context (TContext) from an input (message, model, etc) 8 | /// 9 | /// 10 | public interface IContextProvider 11 | { 12 | Type InputType { get; } 13 | 14 | bool TryGetContext(T input, out TContext context); 15 | } 16 | 17 | 18 | /// 19 | /// Supports return a context for the given input type 20 | /// 21 | /// 22 | /// 23 | public interface IContextProvider : 24 | IContextProvider 25 | { 26 | bool TryGetContext(TInput input, out TContext context); 27 | } 28 | } -------------------------------------------------------------------------------- /src/Fooidity/IToggleCodeSwitch.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | /// 4 | /// Control a toggle fooId, allowing it to be enabled or disabled 5 | /// 6 | public interface IToggleCodeSwitch : 7 | ICodeSwitch 8 | where TFeature : struct, ICodeFeature 9 | { 10 | /// 11 | /// Enable the fooId 12 | /// 13 | void Enable(); 14 | 15 | /// 16 | /// Disable the fooId 17 | /// 18 | void Disable(); 19 | } 20 | } -------------------------------------------------------------------------------- /src/Fooidity/Metadata/CodeFeatureMetadata.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Metadata 2 | { 3 | using System; 4 | using System.Threading; 5 | 6 | 7 | /// 8 | /// Caches metadata about the code features to avoid duplication of information 9 | /// 10 | /// 11 | public class CodeFeatureMetadata : 12 | ICodeFeatureMetadata 13 | { 14 | readonly CodeFeatureId _id; 15 | 16 | CodeFeatureMetadata() 17 | { 18 | _id = new CodeFeatureId(typeof(TFeature)); 19 | } 20 | 21 | public static CodeFeatureId Id 22 | { 23 | get { return Cached.Instance.Value.Id; } 24 | } 25 | 26 | CodeFeatureId ICodeFeatureMetadata.Id 27 | { 28 | get { return _id; } 29 | } 30 | 31 | 32 | static class Cached 33 | { 34 | internal static readonly Lazy> Instance = new Lazy 35 | >( 36 | () => new CodeFeatureMetadata(), LazyThreadSafetyMode.PublicationOnly); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/Fooidity/Metadata/ContextMetadata.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Metadata 2 | { 3 | using System; 4 | using System.Threading; 5 | 6 | 7 | /// 8 | /// Caches metadata about the code features to avoid duplication of information 9 | /// 10 | /// 11 | public class ContextMetadata : 12 | IContextMetadata 13 | { 14 | readonly ContextId _id; 15 | 16 | ContextMetadata() 17 | { 18 | _id = new ContextId(typeof(TContext)); 19 | } 20 | 21 | public static ContextId Id 22 | { 23 | get { return Cached.Instance.Value.Id; } 24 | } 25 | 26 | ContextId IContextMetadata.Id 27 | { 28 | get { return _id; } 29 | } 30 | 31 | 32 | static class Cached 33 | { 34 | internal static readonly Lazy> Instance = new Lazy 35 | >(() => new ContextMetadata(), LazyThreadSafetyMode.PublicationOnly); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/Fooidity/Metadata/ICodeFeatureMetadata.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Metadata 2 | { 3 | public interface ICodeFeatureMetadata 4 | { 5 | CodeFeatureId Id { get; } 6 | } 7 | } -------------------------------------------------------------------------------- /src/Fooidity/Metadata/IContextMetadata.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Metadata 2 | { 3 | public interface IContextMetadata 4 | { 5 | ContextId Id { get; } 6 | } 7 | } -------------------------------------------------------------------------------- /src/Fooidity/Metadata/IHostMetadata.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity.Metadata 2 | { 3 | using Contracts; 4 | 5 | 6 | public interface IHostMetadata 7 | { 8 | Host Host { get; } 9 | } 10 | } -------------------------------------------------------------------------------- /src/Fooidity/SecurityCodeSwitchFactoryExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Fooidity 2 | { 3 | using CodeSwitches; 4 | 5 | 6 | public static class SecurityCodeSwitchFactoryExtensions 7 | { 8 | /// 9 | /// Enables the feature if the principal in is in the specified role 10 | /// 11 | /// 12 | /// 13 | /// The role required to enable the switch 14 | /// 15 | public static ICodeSwitch EnabledForPrincipalInRole(this ICodeSwitchFactory factory, 16 | string role) 17 | where TFeature : struct, ICodeFeature 18 | { 19 | return new EnabledForThreadPrincipalInRoleCodeSwitch(role); 20 | } 21 | 22 | /// 23 | /// Enabled if the current principal identity is authenticated 24 | /// 25 | /// The code feature 26 | /// 27 | public static ICodeSwitch EnabledForAuthenticatedIdentity(this ICodeSwitchFactory factory) 28 | where TFeature : struct, ICodeFeature 29 | { 30 | return new EnabledForAuthenticatedIdentityCodeSwitch(); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/packages/repositories.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | --------------------------------------------------------------------------------