diff --git a/.circleci/config.yml b/.circleci/config.yml index 6adc1ca25..32693ceec 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,12 +3,11 @@ jobs: build: working_directory: /temp docker: - - image: mono:latest + - image: microsoft/dotnet:latest + environment: + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 + DOTNET_CLI_TELEMETRY_OPTOUT: 1 steps: - checkout - - run: apt-get update - - run: apt-get --yes --force-yes install wget - - run: wget https://dist.nuget.org/win-x86-commandline/latest/nuget.exe - - run: mono nuget.exe restore CoiniumServ.sln - - run: msbuild CoiniumServ.sln /p:Configuration=Debug - - run: mono packages/xunit.runner.console.2.3.1/tools/net452/xunit.console.exe src/Tests/bin/Debug/CoiniumServ.Tests.dll + - run: dotnet build -c CI + - run: cd src/CoiniumServ.Tests/ && dotnet xunit \ No newline at end of file diff --git a/.gitignore b/.gitignore index 04bad9159..cc098451f 100644 --- a/.gitignore +++ b/.gitignore @@ -112,4 +112,4 @@ UpgradeLog*.XML # Misc Thumbs.db build/.vs/* -.vs/* \ No newline at end of file +.vs/* diff --git a/CoiniumServ.sln b/CoiniumServ.sln index b060c60e8..bac46b3dd 100644 --- a/CoiniumServ.sln +++ b/CoiniumServ.sln @@ -3,24 +3,37 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.27130.2010 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoiniumServ", "src\CoiniumServ\CoiniumServ.csproj", "{17A4E177-A910-40F8-899D-79A7F628699E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "src\Tests\Tests.csproj", "{6045414C-C243-45B1-907E-3CC9FC168169}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "src\Tests\Tests.csproj", "{ED50E979-2514-4C10-9E68-E35574B9A9AB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoiniumServ", "src\CoiniumServ\CoiniumServ.csproj", "{FDDC0C92-0F51-4B05-B5E2-5B9479AFF540}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nancy.CustomErrors.NetStandard1.6", "contrib\Nancy.CustomErrors\src\Nancy.CustomErrors.NetStandard1.6\Nancy.CustomErrors.NetStandard1.6.csproj", "{7EC1D299-070E-46BC-A02C-1FCDB86AA893}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + CI|Any CPU = CI|Any CPU Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {17A4E177-A910-40F8-899D-79A7F628699E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {17A4E177-A910-40F8-899D-79A7F628699E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {17A4E177-A910-40F8-899D-79A7F628699E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {17A4E177-A910-40F8-899D-79A7F628699E}.Release|Any CPU.Build.0 = Release|Any CPU - {ED50E979-2514-4C10-9E68-E35574B9A9AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {ED50E979-2514-4C10-9E68-E35574B9A9AB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ED50E979-2514-4C10-9E68-E35574B9A9AB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {ED50E979-2514-4C10-9E68-E35574B9A9AB}.Release|Any CPU.Build.0 = Release|Any CPU + {6045414C-C243-45B1-907E-3CC9FC168169}.CI|Any CPU.ActiveCfg = CI|Any CPU + {6045414C-C243-45B1-907E-3CC9FC168169}.CI|Any CPU.Build.0 = CI|Any CPU + {6045414C-C243-45B1-907E-3CC9FC168169}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6045414C-C243-45B1-907E-3CC9FC168169}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6045414C-C243-45B1-907E-3CC9FC168169}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6045414C-C243-45B1-907E-3CC9FC168169}.Release|Any CPU.Build.0 = Release|Any CPU + {FDDC0C92-0F51-4B05-B5E2-5B9479AFF540}.CI|Any CPU.ActiveCfg = CI|Any CPU + {FDDC0C92-0F51-4B05-B5E2-5B9479AFF540}.CI|Any CPU.Build.0 = CI|Any CPU + {FDDC0C92-0F51-4B05-B5E2-5B9479AFF540}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDDC0C92-0F51-4B05-B5E2-5B9479AFF540}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FDDC0C92-0F51-4B05-B5E2-5B9479AFF540}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FDDC0C92-0F51-4B05-B5E2-5B9479AFF540}.Release|Any CPU.Build.0 = Release|Any CPU + {7EC1D299-070E-46BC-A02C-1FCDB86AA893}.CI|Any CPU.ActiveCfg = CI|Any CPU + {7EC1D299-070E-46BC-A02C-1FCDB86AA893}.CI|Any CPU.Build.0 = CI|Any CPU + {7EC1D299-070E-46BC-A02C-1FCDB86AA893}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7EC1D299-070E-46BC-A02C-1FCDB86AA893}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7EC1D299-070E-46BC-A02C-1FCDB86AA893}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7EC1D299-070E-46BC-A02C-1FCDB86AA893}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Nuget.config b/Nuget.config new file mode 100644 index 000000000..e4e43b060 --- /dev/null +++ b/Nuget.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/assets/Coinium.ico b/assets/Coinium.ico new file mode 100644 index 000000000..fa82f09bf Binary files /dev/null and b/assets/Coinium.ico differ diff --git a/contrib/Nancy.CustomErrors/.gitattributes b/contrib/Nancy.CustomErrors/.gitattributes new file mode 100644 index 000000000..1ff0c4230 --- /dev/null +++ b/contrib/Nancy.CustomErrors/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/contrib/Nancy.CustomErrors/.gitignore b/contrib/Nancy.CustomErrors/.gitignore new file mode 100644 index 000000000..7a53e95ee --- /dev/null +++ b/contrib/Nancy.CustomErrors/.gitignore @@ -0,0 +1,267 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +#[Aa]rtifacts/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CAKE +**/tools/Addins/ +**/tools/Cake/ +**/tools/GitVersion.CommandLine +**/tools/nuget.exe +**/tools/NUnit.ConsoleRunner +**/tools/run-ps.cmd +**/tools/publish-nugetpackages.ps1 +**/tools/packages.config.md5sum + +# Xamarin +/source/Components +/tools/xunit.runner.console/tools diff --git a/contrib/Nancy.CustomErrors/.nuget/NuGet.Config b/contrib/Nancy.CustomErrors/.nuget/NuGet.Config new file mode 100644 index 000000000..67f8ea046 --- /dev/null +++ b/contrib/Nancy.CustomErrors/.nuget/NuGet.Config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/Nancy.CustomErrors.sln b/contrib/Nancy.CustomErrors/Nancy.CustomErrors.sln new file mode 100644 index 000000000..87163f58b --- /dev/null +++ b/contrib/Nancy.CustomErrors/Nancy.CustomErrors.sln @@ -0,0 +1,65 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.6 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nancy.CustomErrors", "src\Nancy.CustomErrors\Nancy.CustomErrors.csproj", "{CD7A7211-6563-499B-913D-8E5AF649BFE7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{56730B51-095D-4010-B942-DCB2696540C0}" + ProjectSection(SolutionItems) = preProject + build.ps1 = build.ps1 + default.ps1 = default.ps1 + Readme.md = Readme.md + version.json = version.json + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nancy.CustomErrors.Tests", "tests\Nancy.CustomErrors.Tests\Nancy.CustomErrors.Tests.csproj", "{F1930050-9A83-42BB-9E14-1D5D7C6F255B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nancy.CustomErrors.Example", "tests\Nancy.CustomErrors.Example\Nancy.CustomErrors.Example.csproj", "{5A8E7514-E653-4C00-8623-1E71D7DCE6C5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nancy.CustomErrors.NetStandard1.6", "src\Nancy.CustomErrors.NetStandard1.6\Nancy.CustomErrors.NetStandard1.6.csproj", "{BBFAEB4A-212F-4F00-AAE7-6723231C6969}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Nancy.CustomErrors.Shared", "src\Nancy.CustomErrors.Shared\Nancy.CustomErrors.Shared.shproj", "{0B0C2E66-9FD4-4475-AB31-81AB2F39F4DA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "source", "source", "{ED70835A-FD7E-43C7-803D-84CD326DA186}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{9CDF45E1-7B40-4BA2-A537-1407CA214AD0}" +EndProject +Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + src\Nancy.CustomErrors.Shared\Nancy.CustomErrors.Shared.projitems*{0b0c2e66-9fd4-4475-ab31-81ab2f39f4da}*SharedItemsImports = 13 + src\Nancy.CustomErrors.Shared\Nancy.CustomErrors.Shared.projitems*{cd7a7211-6563-499b-913d-8e5af649bfe7}*SharedItemsImports = 4 + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CD7A7211-6563-499B-913D-8E5AF649BFE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CD7A7211-6563-499B-913D-8E5AF649BFE7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CD7A7211-6563-499B-913D-8E5AF649BFE7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CD7A7211-6563-499B-913D-8E5AF649BFE7}.Release|Any CPU.Build.0 = Release|Any CPU + {F1930050-9A83-42BB-9E14-1D5D7C6F255B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F1930050-9A83-42BB-9E14-1D5D7C6F255B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1930050-9A83-42BB-9E14-1D5D7C6F255B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F1930050-9A83-42BB-9E14-1D5D7C6F255B}.Release|Any CPU.Build.0 = Release|Any CPU + {5A8E7514-E653-4C00-8623-1E71D7DCE6C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5A8E7514-E653-4C00-8623-1E71D7DCE6C5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5A8E7514-E653-4C00-8623-1E71D7DCE6C5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5A8E7514-E653-4C00-8623-1E71D7DCE6C5}.Release|Any CPU.Build.0 = Release|Any CPU + {BBFAEB4A-212F-4F00-AAE7-6723231C6969}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BBFAEB4A-212F-4F00-AAE7-6723231C6969}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BBFAEB4A-212F-4F00-AAE7-6723231C6969}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BBFAEB4A-212F-4F00-AAE7-6723231C6969}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {CD7A7211-6563-499B-913D-8E5AF649BFE7} = {ED70835A-FD7E-43C7-803D-84CD326DA186} + {F1930050-9A83-42BB-9E14-1D5D7C6F255B} = {9CDF45E1-7B40-4BA2-A537-1407CA214AD0} + {5A8E7514-E653-4C00-8623-1E71D7DCE6C5} = {9CDF45E1-7B40-4BA2-A537-1407CA214AD0} + {BBFAEB4A-212F-4F00-AAE7-6723231C6969} = {ED70835A-FD7E-43C7-803D-84CD326DA186} + {0B0C2E66-9FD4-4475-AB31-81AB2F39F4DA} = {ED70835A-FD7E-43C7-803D-84CD326DA186} + EndGlobalSection +EndGlobal diff --git a/contrib/Nancy.CustomErrors/Readme.md b/contrib/Nancy.CustomErrors/Readme.md new file mode 100644 index 000000000..77bde4a30 --- /dev/null +++ b/contrib/Nancy.CustomErrors/Readme.md @@ -0,0 +1,114 @@ +# Custom error handling for Nancyfx applications + +This work is *heavily* influenced by Paul Stovell's excellent [Consistent error handling with Nancy](http://paulstovell.com/blog/consistent-error-handling-with-nancy) article. + +## Features + +- Simple setup of custom views for error pages, 404 pages and authorization/authentication failure pages +- Supports any Nancy view engine +- Will send JSON serialized representation of errors if client has requested JSON +- Easily add support for custom error handling logic or for mapping application specific exception types to appropriate error responses + +## Installation + +Use Nuget! + +``` +Install-Package Nancy.CustomErrors +``` + +## Usage + +### Bootstrapping + +Custom error handling is set up in the ApplicationStartup method of your Nancy Bootstrapper. In its simplest form, your simply call Nancy.CustomErrors.Enable, passing an IPipelines instance. + +```csharp +protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines) +{ + base.ApplicationStartup(container, pipelines); + + // ... + CustomErrors.Enable(pipelines); +} +``` + +In this form, default configuration options will be assumed. The default configuration assumes the following + +- Any and all unhandled exceptions will generate a response with a 500 HTTP status code +- Any request with an Accept header containing a recognised json type will be served with a JSON representation of the error, rather than a rendered view + +*Note that if you are using the Nancy.Elmah package, ElmahLogging.Enable() should be called before CustomErrors.Enable()* + +### Configuration + +Setting up custom configuration is a simple case of implementing an configuration class that extends Nancy.CustomErrors.CustomErrorsConfiguration, and passing an instance of the class along in the call to CustomErrors.Enable() + +```csharp +public class MyErrorConfiguration : Nancy.CustomErrors.CustomErrorsConfiguration +{ + public MyErrorConfiguration() : base() + { + // Map error status codes to custom view names + ErrorViews[HttpStatusCode.NotFound] = "CustomNotFoundView"; + ErrorViews[HttpStatusCode.InternalServerError] = "CustomErrorView"; + ErrorViews[HttpStatusCode.Forbidden] = "Forbidden"; + } + + // Custom redirection handler for an unauthorised request + // Returning an empty string will result in the response being sent with HttpStatusCode.Forbidden + // Otherwise, return the url to redirect the client to. + public override string GetAuthorizationUrl(NancyContext context) { + if (context.CurrentUser == null) { + return "/accounts/login" + } + return String.Empty; + } + + // Custom mapping of a thrown exception to an ErrorResponse with status code + // The implementation in this example is the default implementation used in + // Nancy.CustomErrors.CustomErrorConfiguration. Override this if you need to + // Map custom exception types to different status codes, or error objects. + // An example might be to map a custom security exception to HttpForbidden status + // code, rather than the default InternalServerError status code + public override ErrorResponse HandleError(NancyContext context, Exception ex, ISerializer serializer) + { + var error = new Error + { + FullException = ex.ToString(), + Message = ex.Message + }; + + return new ErrorResponse(error, serializer).WithStatusCode(HttpStatusCode.InternalServerError) as ErrorResponse; + } +} +``` + +Once you've implemented a custom error handling configuration, just pass it along in the CustomErrors.Enable call in your bootstrapper + +```csharp +protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines) +{ + base.ApplicationStartup(container, pipelines); + + // ... + CustomErrors.Enable(pipelines, new MyErrorConfiguration()); +} +``` + +### Error views + +Your error views will be rendered with a simple object model, containing a Title, Summary and optional Details field. All fields are c# string type. + +We use whatever view engine is presently configured in your project. By default you will need to create a single view resolved by the name "Error" to handle all error types. If you would like to use different views for different status codes, just set up a custom configuration as shown above. + +Here is a simple example using the Razor view engine + +```html +@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase + +

Ouch!

+

@Model.Title

+

@Model.Summary

+

@Model.Details

+``` diff --git a/contrib/Nancy.CustomErrors/build.cake b/contrib/Nancy.CustomErrors/build.cake new file mode 100644 index 000000000..adf0adb92 --- /dev/null +++ b/contrib/Nancy.CustomErrors/build.cake @@ -0,0 +1,360 @@ +/////////////////////////////////////////////////////////////////////////////// +// Directives +/////////////////////////////////////////////////////////////////////////////// + +#l "tools/versionUtils.cake" +#l "tools/settingsUtils.cake" +#tool "nuget:?package=NUnit.ConsoleRunner" +#tool "nuget:?package=xunit.runner.console" + +/////////////////////////////////////////////////////////////////////////////// +// ARGUMENTS +/////////////////////////////////////////////////////////////////////////////// + +var settings = SettingsUtils.LoadSettings(Context); +var versionInfo = VersionUtils.LoadVersion(Context, settings); + +/////////////////////////////////////////////////////////////////////////////// +// GLOBAL VARIABLES +/////////////////////////////////////////////////////////////////////////////// + +var solutions = GetFiles(settings.Build.SolutionFilePath); +var solutionPaths = solutions.Select(solution => solution.GetDirectory()); + +/////////////////////////////////////////////////////////////////////////////// +// SETUP / TEARDOWN +/////////////////////////////////////////////////////////////////////////////// + +Setup((c) => +{ + // Executed BEFORE the first task. + settings.Display(c); + versionInfo.Display(c); +}); + +Teardown((c) => +{ + // Executed AFTER the last task. + Information("Finished running tasks."); +}); + +/////////////////////////////////////////////////////////////////////////////// +// TASK DEFINITIONS +/////////////////////////////////////////////////////////////////////////////// + +Task("CleanAll") + .Description("Cleans all directories that are used during the build process.") + .Does(() => +{ + // Clean solution directories. + foreach(var path in solutionPaths) + { + Information("Cleaning {0}", path); + CleanDirectories(path + "/**/bin"); + CleanDirectories(path + "/**/obj"); + CleanDirectories(path + "/packages/**/*"); + CleanDirectories(path + "/artifacts/**/*"); + CleanDirectories(path + "/packages"); + CleanDirectories(path + "/artifacts"); + } + + var pathTest = MakeAbsolute(Directory(settings.Test.SourcePath)).FullPath; + Information("Cleaning {0}", pathTest); + try { CleanDirectories(pathTest + "/**/bin"); } catch {} + try { CleanDirectories(pathTest + "/**/obj"); } catch {} +}); + +Task("Clean") + .Description("Cleans all directories that are used during the build process.") + .WithCriteria(settings.ExecuteBuild) + .Does(() => +{ + // Clean solution directories. + foreach(var path in solutionPaths) + { + Information("Cleaning {0}", path); + try { CleanDirectories(path + "/**/bin/" + settings.Configuration); } catch {} + try { CleanDirectories(path + "/**/obj/" + settings.Configuration); } catch {} + } + + var pathTest = MakeAbsolute(Directory(settings.Test.SourcePath)).FullPath; + Information("Cleaning {0}", pathTest); + try { CleanDirectories(pathTest + "/**/bin/" + settings.Configuration); } catch {} + try { CleanDirectories(pathTest + "/**/obj/" + settings.Configuration); } catch {} + +}); + +Task("CleanPackages") + .Description("Cleans all packages that are used during the build process.") + .Does(() => +{ + // Clean solution directories. + foreach(var path in solutionPaths) + { + Information("Cleaning {0}", path); + CleanDirectories(path + "/packages/**/*"); + CleanDirectories(path + "/packages"); + } +}); + +Task("Restore") + .Description("Restores all the NuGet packages that are used by the specified solution.") + .WithCriteria(settings.ExecuteBuild) + .Does(() => +{ + // Restore all NuGet packages. + foreach(var solution in solutions) + { + Information("Restoring {0}...", solution); + NuGetRestore(solution, new NuGetRestoreSettings { ConfigFile = settings.NuGet.NuGetConfig }); + } +}); + +Task("Build") + .Description("Builds all the different parts of the project.") + .WithCriteria(settings.ExecuteBuild) + .IsDependentOn("Clean") + .IsDependentOn("Restore") + .IsDependentOn("UpdateVersion") + .Does(() => +{ + if (settings.Version.AutoIncrementVersion) + { + RunTarget("IncrementVersion"); + } + + // Build all solutions. + foreach(var solution in solutions) + { + Information("Building {0}", solution); + try { + MSBuild(solution, s => + s.SetPlatformTarget(PlatformTarget.MSIL) + .SetMaxCpuCount(settings.Build.MaxCpuCount) + .WithProperty("TreatWarningsAsErrors",settings.Build.TreatWarningsAsErrors.ToString()) + .WithTarget("Build") + .SetConfiguration(settings.Configuration)); + } + catch (Exception ex) + { + Error("Files to build project: " + solution + ". Error: " + ex.Message); + } + } +}); + +Task("UnitTest") + .Description("Run unit tests for the solution.") + .WithCriteria(settings.ExecuteUnitTest) + .IsDependentOn("Build") + .Does(() => +{ + // Run all unit tests we can find. + + var assemplyFilePath = string.Format("{0}/**/bin/{1}/{2}", settings.Test.SourcePath, settings.Configuration, settings.Test.AssemblyFileSpec); + + Information("Unit Test Files: {0}", assemplyFilePath); + + var unitTestAssemblies = GetFiles(assemplyFilePath); + + foreach(var uta in unitTestAssemblies) + { + Information("Executing Tests for {0}", uta); + + switch (settings.Test.Framework) + { + case TestFrameworkTypes.NUnit2: + NUnit(uta.ToString(), new NUnitSettings { }); + break; + case TestFrameworkTypes.NUnit3: + NUnit3(uta.ToString(), new NUnit3Settings { Configuration=settings.Configuration }); + break; + case TestFrameworkTypes.XUnit: + XUnit(uta.ToString(), new XUnitSettings { OutputDirectory = settings.Test.ResultsPath }); + break; + case TestFrameworkTypes.XUnit2: + XUnit2(uta.ToString(), new XUnit2Settings { OutputDirectory = settings.Test.ResultsPath, XmlReportV1 = true }); + break; + } + } +}); + +Task("Package") + .Description("Packages all nuspec files into nupkg packages.") + .WithCriteria(settings.ExecutePackage) + .IsDependentOn("UnitTest") + .Does(() => +{ + var artifactsPath = Directory(settings.NuGet.ArtifactsPath); + var nugetProps = new Dictionary() { {"Configuration", settings.Configuration} }; + + CreateDirectory(artifactsPath); + + var nuspecFiles = GetFiles(settings.NuGet.NuSpecFileSpec); + foreach(var nsf in nuspecFiles) + { + Information("Packaging {0}", nsf); + + if (settings.NuGet.UpdateVersion) { + VersionUtils.UpdateNuSpecVersion(Context, settings, versionInfo, nsf.ToString()); + } + + if (settings.NuGet.UpdateLibraryDependencies) { + VersionUtils.UpdateNuSpecVersionDependency(Context, settings, versionInfo, nsf.ToString()); + } + + NuGetPack(nsf, new NuGetPackSettings { + Version = versionInfo.ToString(), + ReleaseNotes = versionInfo.ReleaseNotes, + Symbols = true, + Properties = nugetProps, + OutputDirectory = artifactsPath + }); + } +}); + +Task("Publish") + .Description("Publishes all of the nupkg packages to the nuget server. ") + .IsDependentOn("Package") + .Does(() => +{ + var authError = false; + + if (settings.NuGet.FeedApiKey.ToLower() == "local") + { + settings.NuGet.FeedUrl = Directory(settings.NuGet.FeedUrl).Path.FullPath; + //Information("Using Local repository: {0}", settings.NuGet.FeedUrl); + } + + Information("Publishing Packages from {0} to {1} for version {2}", settings.NuGet.ArtifactsPath, settings.NuGet.FeedUrl, versionInfo.ToString()); + + // Lets get the list of packages (we can skip anything that is not part of the current version being built) + var nupkgFiles = GetFiles(settings.NuGet.NuGetPackagesSpec).Where(x => x.ToString().Contains(versionInfo.ToString())).ToList(); + + Information("\t{0}", string.Join("\n\t", nupkgFiles.Select(x => x.GetFilename().ToString()).ToList())); + + foreach (var n in nupkgFiles) + { + try + { + NuGetPush(n, new NuGetPushSettings { + Source = settings.NuGet.FeedUrl, + ApiKey = settings.NuGet.FeedApiKey, + ConfigFile = settings.NuGet.NuGetConfig, + Verbosity = NuGetVerbosity.Normal + }); + } + catch (Exception ex) + { + Information("\tFailed to published: ", ex.Message); + + if (ex.Message.Contains("403")) { authError = true; } + } + } + + if (authError && settings.NuGet.FeedApiKey == "VSTS") + { + Warning("\tYou may need to Configuration Your Credentials.\r\n\t\tCredentialProvider.VSS.exe -Uri {0}", settings.NuGet.FeedUrl); + } +}); + +Task("UnPublish") + .Description("UnPublishes all of the current nupkg packages from the nuget server. Issue: versionToDelete must use : instead of . due to bug in cake") + .Does(() => +{ + var v = Argument("versionToDelete", versionInfo.ToString()).Replace(":","."); + + var nuspecFiles = GetFiles(settings.NuGet.NuSpecFileSpec); + foreach(var f in nuspecFiles) + { + Information("UnPublishing {0}", f.GetFilenameWithoutExtension()); + + var args = string.Format("delete {0} {1} -Source {2} -NonInteractive", + f.GetFilenameWithoutExtension(), + v, + settings.NuGet.FeedUrl + ); + + //if (settings.NuGet.FeedApiKey != "VSTS" ) { + args = args + string.Format(" -ApiKey {0}", settings.NuGet.FeedApiKey); + //} + + if (!string.IsNullOrEmpty(settings.NuGet.NuGetConfig)) { + args = args + string.Format(" -Config {0}", settings.NuGet.NuGetConfig); + } + + Information("NuGet Command Line: {0}", args); + using (var process = StartAndReturnProcess("tools\\nuget.exe", new ProcessSettings { + Arguments = args + })) + { + process.WaitForExit(); + Information("nuget delete exit code: {0}", process.GetExitCode()); + } + } +}); + +Task("UpdateVersion") + .Description("Updates the version number in the necessary files") + .Does(() => +{ + Information("Updating Version to {0}", versionInfo.ToString()); + + VersionUtils.UpdateVersion(Context, settings, versionInfo); +}); + +Task("IncrementVersion") + .Description("Increments the version number and then updates it in the necessary files") + .Does(() => +{ + var oldVer = versionInfo.ToString(); + if (versionInfo.IsPreRelease) versionInfo.PreRelease++; else versionInfo.Build++; + + Information("Incrementing Version {0} to {1}", oldVer, versionInfo.ToString()); + + RunTarget("UpdateVersion"); +}); + +Task("BuildNewVersion") + .Description("Increments and Builds a new version") + .IsDependentOn("IncrementVersion") + .IsDependentOn("Build") + .Does(() => +{ +}); + +Task("PublishNewVersion") + .Description("Increments, Builds, and publishes a new version") + .IsDependentOn("BuildNewVersion") + .IsDependentOn("Publish") + .Does(() => +{ +}); + +Task("DisplaySettings") + .Description("Displays All Settings.") + .Does(() => +{ + // Settings will be displayed as they are part of the Setup task +}); + +Task("DisplayHelp") + .Description("Displays All Settings.") + .Does(() => +{ + // Settings will be displayed as they are part of the Setup task + SettingsUtils.DisplayHelp(Context); +}); + +/////////////////////////////////////////////////////////////////////////////// +// TARGETS +/////////////////////////////////////////////////////////////////////////////// + +Task("Default") + .Description("This is the default task which will be ran if no specific target is passed in.") + .IsDependentOn("Build"); + +/////////////////////////////////////////////////////////////////////////////// +// EXECUTION +/////////////////////////////////////////////////////////////////////////////// + +RunTarget(settings.Target); \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/build.osx.sh b/contrib/Nancy.CustomErrors/build.osx.sh new file mode 100644 index 000000000..6e8f207c8 --- /dev/null +++ b/contrib/Nancy.CustomErrors/build.osx.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env bash + +########################################################################## +# This is the Cake bootstrapper script for Linux and OS X. +# This file was downloaded from https://github.com/cake-build/resources +# Feel free to change this file to fit your needs. +########################################################################## + +# Define directories. +SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +TOOLS_DIR=$SCRIPT_DIR/tools +NUGET_EXE=$TOOLS_DIR/nuget.exe +CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe +PACKAGES_CONFIG=$TOOLS_DIR/packages.config +PACKAGES_CONFIG_MD5=$TOOLS_DIR/packages.config.md5sum + +# Define md5sum or md5 depending on Linux/OSX +MD5_EXE= +if [[ "$(uname -s)" == "Darwin" ]]; then + MD5_EXE="md5 -r" +else + MD5_EXE="md5sum" +fi + +# Define default arguments. +SCRIPT="build.cake" +TARGET="Default" +CONFIGURATION="Release" +VERBOSITY="verbose" +DRYRUN= +SHOW_VERSION=false +SCRIPT_ARGUMENTS=() + +# Parse arguments. +for i in "$@"; do + case $1 in + -s|--script) SCRIPT="$2"; shift ;; + -t|--target) TARGET="$2"; shift ;; + -c|--configuration) CONFIGURATION="$2"; shift ;; + -v|--verbosity) VERBOSITY="$2"; shift ;; + -d|--dryrun) DRYRUN="-dryrun" ;; + --version) SHOW_VERSION=true ;; + --) shift; SCRIPT_ARGUMENTS+=("$@"); break ;; + *) SCRIPT_ARGUMENTS+=("$1") ;; + esac + shift +done + +# Make sure the tools folder exist. +if [ ! -d "$TOOLS_DIR" ]; then + mkdir "$TOOLS_DIR" +fi + +# Make sure that packages.config exist. +if [ ! -f "$TOOLS_DIR/packages.config" ]; then + echo "Downloading packages.config..." + curl -Lsfo "$TOOLS_DIR/packages.config" http://cakebuild.net/download/bootstrapper/packages + if [ $? -ne 0 ]; then + echo "An error occured while downloading packages.config." + exit 1 + fi +fi + +# Download NuGet if it does not exist. +if [ ! -f "$NUGET_EXE" ]; then + echo "Downloading NuGet..." + curl -Lsfo "$NUGET_EXE" https://dist.nuget.org/win-x86-commandline/latest/nuget.exe + if [ $? -ne 0 ]; then + echo "An error occured while downloading nuget.exe." + exit 1 + fi +fi + +# Restore tools from NuGet. +pushd "$TOOLS_DIR" >/dev/null +if [ ! -f $PACKAGES_CONFIG_MD5 ] || [ "$( cat $PACKAGES_CONFIG_MD5 | sed 's/\r$//' )" != "$( $MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' )" ]; then + find . -type d ! -name . | xargs rm -rf +fi + +mono "$NUGET_EXE" install -ExcludeVersion +if [ $? -ne 0 ]; then + echo "Could not restore NuGet packages." + exit 1 +fi + +$MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' >| $PACKAGES_CONFIG_MD5 + +popd >/dev/null + +# Make sure that Cake has been installed. +if [ ! -f "$CAKE_EXE" ]; then + echo "Could not find Cake.exe at '$CAKE_EXE'." + exit 1 +fi + +# Start Cake +if $SHOW_VERSION; then + exec mono "$CAKE_EXE" -version +else + exec mono "$CAKE_EXE" $SCRIPT -verbosity=$VERBOSITY -configuration=$CONFIGURATION -target=$TARGET $DRYRUN "${SCRIPT_ARGUMENTS[@]}" +fi \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/build.ps1 b/contrib/Nancy.CustomErrors/build.ps1 new file mode 100644 index 000000000..dd0c32c8d --- /dev/null +++ b/contrib/Nancy.CustomErrors/build.ps1 @@ -0,0 +1,189 @@ +########################################################################## +# This is the Cake bootstrapper script for PowerShell. +# This file was downloaded from https://github.com/cake-build/resources +# Feel free to change this file to fit your needs. +########################################################################## + +<# + +.SYNOPSIS +This is a Powershell script to bootstrap a Cake build. + +.DESCRIPTION +This Powershell script will download NuGet if missing, restore NuGet tools (including Cake) +and execute your Cake build script with the parameters you provide. + +.PARAMETER Script +The build script to execute. +.PARAMETER Target +The build script target to run. +.PARAMETER Configuration +The build configuration to use. +.PARAMETER Verbosity +Specifies the amount of information to be displayed. +.PARAMETER Experimental +Tells Cake to use the latest Roslyn release. +.PARAMETER WhatIf +Performs a dry run of the build script. +No tasks will be executed. +.PARAMETER Mono +Tells Cake to use the Mono scripting engine. +.PARAMETER SkipToolPackageRestore +Skips restoring of packages. +.PARAMETER ScriptArgs +Remaining arguments are added here. + +.LINK +http://cakebuild.net + +#> + +[CmdletBinding()] +Param( + [string]$Script = "build.cake", + [string]$Target = "Default", + [ValidateSet("Release", "Debug")] + [string]$Configuration = "Release", + [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")] + [string]$Verbosity = "Verbose", + [switch]$Experimental, + [Alias("DryRun","Noop")] + [switch]$WhatIf, + [switch]$Mono, + [switch]$SkipToolPackageRestore, + [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] + [string[]]$ScriptArgs +) + +[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null +function MD5HashFile([string] $filePath) +{ + if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf)) + { + return $null + } + + [System.IO.Stream] $file = $null; + [System.Security.Cryptography.MD5] $md5 = $null; + try + { + $md5 = [System.Security.Cryptography.MD5]::Create() + $file = [System.IO.File]::OpenRead($filePath) + return [System.BitConverter]::ToString($md5.ComputeHash($file)) + } + finally + { + if ($file -ne $null) + { + $file.Dispose() + } + } +} + +Write-Host "Preparing to run build script..." + +if(!$PSScriptRoot){ + $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent +} + +$TOOLS_DIR = Join-Path $PSScriptRoot "tools" +$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe" +$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe" +$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" +$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config" +$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum" + +# Should we use mono? +$UseMono = ""; +if($Mono.IsPresent) { + Write-Verbose -Message "Using the Mono based scripting engine." + $UseMono = "-mono" +} + +# Should we use the new Roslyn? +$UseExperimental = ""; +if($Experimental.IsPresent -and !($Mono.IsPresent)) { + Write-Verbose -Message "Using experimental version of Roslyn." + $UseExperimental = "-experimental" +} + +# Is this a dry run? +$UseDryRun = ""; +if($WhatIf.IsPresent) { + $UseDryRun = "-dryrun" +} + +# Make sure tools folder exists +if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) { + Write-Verbose -Message "Creating tools directory..." + New-Item -Path $TOOLS_DIR -Type directory | out-null +} + +# Make sure that packages.config exist. +if (!(Test-Path $PACKAGES_CONFIG)) { + Write-Verbose -Message "Downloading packages.config..." + try { (New-Object System.Net.WebClient).DownloadFile("http://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch { + Throw "Could not download packages.config." + } +} + +# Try find NuGet.exe in path if not exists +if (!(Test-Path $NUGET_EXE)) { + Write-Verbose -Message "Trying to find nuget.exe in PATH..." + $existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_ -PathType Container) } + $NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1 + if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) { + Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)." + $NUGET_EXE = $NUGET_EXE_IN_PATH.FullName + } +} + +# Try download NuGet.exe if not exists +if (!(Test-Path $NUGET_EXE)) { + Write-Verbose -Message "Downloading NuGet.exe..." + try { + (New-Object System.Net.WebClient).DownloadFile($NUGET_URL, $NUGET_EXE) + } catch { + Throw "Could not download NuGet.exe." + } +} + +# Save nuget.exe path to environment to be available to child processed +$ENV:NUGET_EXE = $NUGET_EXE + +# Restore tools from NuGet? +if(-Not $SkipToolPackageRestore.IsPresent) { + Push-Location + Set-Location $TOOLS_DIR + + # Check for changes in packages.config and remove installed tools if true. + [string] $md5Hash = MD5HashFile($PACKAGES_CONFIG) + if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or + ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) { + Write-Verbose -Message "Missing or changed package.config hash..." + Remove-Item * -Recurse -Exclude packages.config,nuget.exe,settingsUtils.cake,versionUtils.cake + } + + Write-Verbose -Message "Restoring tools from NuGet..." + $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`"" + + if ($LASTEXITCODE -ne 0) { + Throw "An error occured while restoring NuGet tools." + } + else + { + $md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII" + } + Write-Verbose -Message ($NuGetOutput | out-string) + Pop-Location +} + +# Make sure that Cake has been installed. +if (!(Test-Path $CAKE_EXE)) { + Throw "Could not find Cake.exe at $CAKE_EXE" +} + +# Start Cake +Write-Host "Running build script..." +Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -target=`"$Target`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseMono $UseDryRun $UseExperimental $ScriptArgs" +exit $LASTEXITCODE \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/nuspec/Nancy.CustomErrors.nuspec b/contrib/Nancy.CustomErrors/nuspec/Nancy.CustomErrors.nuspec new file mode 100644 index 000000000..467e82d2b --- /dev/null +++ b/contrib/Nancy.CustomErrors/nuspec/Nancy.CustomErrors.nuspec @@ -0,0 +1,33 @@ + + + + Nancy.CustomErrors + 2.0.0-pre01 + Nancy Custom Errors + Brendan ravensorb + Brendan McMahon + https://github.com/bernos/Nancy.CustomErrors + Adds exception handling for cases when custom error views cannot be found + false + Simple custom error handling for Nancyfx projects + Copyright 2017 + Nancyfx + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/settings.json b/contrib/Nancy.CustomErrors/settings.json new file mode 100644 index 000000000..3d57486f5 --- /dev/null +++ b/contrib/Nancy.CustomErrors/settings.json @@ -0,0 +1,37 @@ +{ + "version": { + "VersionFile": "./version.json", + "AssemblyInfoFile": "./Nancy.CustomErrors/Properties/AssemblyInfo.cs", + "LoadFrom": "versionfile", + "AutoIncrementVersion": false + }, + "build": { + "SourcePath": "./src", + "SolutionFileSpec": "./*.sln", + "TreatWarningsAsErrors": false + }, + "xamarin":{ + "EnableXamarinIOS": false, + "MacAgentIPAddress": "", + "MacAgentUserName": "", + "MacAgentUserPassword": "" + }, + "test": { + "SourcePath": "./tests", + "ResultsPath": "./artifacts", + "AssemblyFileSpec": "*.Tests.dll", + "Framework": "XUnit2" + }, + "nuget": { + "NuGetConfig": "./.nuget/NuGet.config", + "FeedUrl": "", + "FeedAPIKey": "", + "ArtifactsPath": "./artifacts/packages", + "NuspecPath": "./nuspec", + "UpdateVersion": true, + "UpdateLibraryDependencies": false, + "VersionDependencyForLibrary": "greaterthanorequal", + "LibraryNamespaceBase": "", + "LibraryMinVersionDependency": "" + } +} \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/src/AssemblyInfo.Shared.cs b/contrib/Nancy.CustomErrors/src/AssemblyInfo.Shared.cs new file mode 100644 index 000000000..b7c94c46d --- /dev/null +++ b/contrib/Nancy.CustomErrors/src/AssemblyInfo.Shared.cs @@ -0,0 +1,36 @@ +// *********************************************************************** +// +// Copyright (c) . All rights reserved. +// +// +// +// *********************************************************************** +// + +using System.Reflection; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyCompany("Brendan McMahon")] +[assembly: AssemblyProduct("Nancy.CustomErrors")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyConfiguration("")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("2.0.0")] +//[assembly: AssemblyFileVersion("2.0.0")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +//[assembly: ComVisible(false)] diff --git a/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.NetStandard1.6/Nancy.CustomErrors.NetStandard1.6.csproj b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.NetStandard1.6/Nancy.CustomErrors.NetStandard1.6.csproj new file mode 100644 index 000000000..143acac2d --- /dev/null +++ b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.NetStandard1.6/Nancy.CustomErrors.NetStandard1.6.csproj @@ -0,0 +1,16 @@ + + + + netstandard1.6 + Nancy.CustomErrors + Nancy.CustomErrors + Debug;Release;CI + + + + + + + + + \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/CustomErrors.cs b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/CustomErrors.cs new file mode 100644 index 000000000..61253f73e --- /dev/null +++ b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/CustomErrors.cs @@ -0,0 +1,37 @@ +using System; +using Nancy.Bootstrapper; +using Nancy.Responses; + +namespace Nancy.CustomErrors +{ + public class CustomErrors + { + private static CustomErrorsConfiguration _configuration; + public static CustomErrorsConfiguration Configuration + { + get { return _configuration ?? (_configuration = new CustomErrorsConfiguration()); } + } + + public static void Enable(IPipelines pipelines, CustomErrorsConfiguration configuration, ISerializer serializer) + { + if (pipelines == null) + { + throw new ArgumentNullException("pipelines"); + } + + if (configuration == null) + { + throw new ArgumentNullException("configuration"); + } + + _configuration = configuration; + + pipelines.OnError.AddItemToEndOfPipeline(GetErrorHandler(configuration, serializer)); + } + + private static Func GetErrorHandler(CustomErrorsConfiguration configuration, ISerializer serializer) + { + return (context, ex) => configuration.HandleError(context, ex, serializer); + } + } +} \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/CustomErrorsConfiguration.cs b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/CustomErrorsConfiguration.cs new file mode 100644 index 000000000..683527697 --- /dev/null +++ b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/CustomErrorsConfiguration.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; + +namespace Nancy.CustomErrors +{ + public class CustomErrorsConfiguration + { + public string NotFoundTitle = "404 Not Found"; + public string NotFoundSummary = "The requested resource could not be found."; + public string ForbiddenTitle = "Forbidden"; + public string ForbiddenSummary = "You do not have permission to do that."; + public string UnauthorizedTitle = "Unauthorized"; + public string UnauthorizedSummary = "You do not have permission to do that."; + public string ErrorTitle = "Error"; + public string ErrorSummary = "An unexpected error occurred."; + + public bool AlwaysReturnJson = false; + + /// + /// If set to true, then we will emit full stack traces in our ErrorResponse + /// + public bool Debug = false; + + /// + /// Converts a thrown exception to the appropriate ErrorResponse. Override this method if you need + /// to handle custom exception types, or implement your own error handling logic. The default + /// implementation converts all thrown exceptions to a regular ErrorResponse with an HttpStatusCode + /// of 500 + /// + /// + /// + /// + /// + public virtual ErrorResponse HandleError(NancyContext context, Exception ex, ISerializer serializer) + { + var error = new Error + { + FullException = ex.ToString(), + Message = ex.Message + }; + + return new ErrorResponse(error, serializer, context.Environment).WithStatusCode(HttpStatusCode.InternalServerError) as ErrorResponse; + } + + /// + /// Maps different HttpStatusCodes to the appropriate views. + /// + public IDictionary ErrorViews = new Dictionary + { + { HttpStatusCode.NotFound, "Error" }, + { HttpStatusCode.InternalServerError, "Error" }, + { HttpStatusCode.Forbidden, "Error" } + }; + } +} diff --git a/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/Error.cs b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/Error.cs new file mode 100644 index 000000000..2948a1222 --- /dev/null +++ b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/Error.cs @@ -0,0 +1,9 @@ + +namespace Nancy.CustomErrors +{ + public class Error + { + public string Message { get; set; } + public string FullException { get; set; } + } +} \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/ErrorResponse.cs b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/ErrorResponse.cs new file mode 100644 index 000000000..25f2a04e9 --- /dev/null +++ b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/ErrorResponse.cs @@ -0,0 +1,24 @@ +using Nancy.Configuration; +using Nancy.Responses; + +namespace Nancy.CustomErrors +{ + public class ErrorResponse : JsonResponse + { + private readonly Error _error; + + public string ErrorMessage { get { return _error.Message; } } + + public string FullException { get { return _error.FullException; } } + + public ErrorResponse(Error error, ISerializer serializer, INancyEnvironment environment) : base(error, serializer, environment) + { + if (!CustomErrors.Configuration.Debug) + { + error.FullException = null; + } + + _error = error; + } + } +} diff --git a/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/ErrorStatusCodeHandler.cs b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/ErrorStatusCodeHandler.cs new file mode 100644 index 000000000..0c14aa2fd --- /dev/null +++ b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/ErrorStatusCodeHandler.cs @@ -0,0 +1,155 @@ +using System; +using System.IO; +using System.Linq; +using Nancy.ErrorHandling; +using Nancy.Responses; +using Nancy.Responses.Negotiation; +using Nancy.ViewEngines; + +namespace Nancy.CustomErrors +{ + public class ErrorStatusCodeHandler : DefaultViewRenderer, IStatusCodeHandler + { + private readonly ISerializer _serializer; + + public ErrorStatusCodeHandler(IViewFactory viewFactory) : base(viewFactory) + { + } + + //Made this private as some DI containers like Autofac and Ninject have issues when multiple registered instances of an interface exist and + // convention based DI is used for constructors + private ErrorStatusCodeHandler(IViewFactory viewFactory, ISerializer serializer) + : base(viewFactory) + { + _serializer = serializer; + } + + public bool HandlesStatusCode(HttpStatusCode statusCode, NancyContext context) + { + return statusCode == HttpStatusCode.NotFound + || statusCode == HttpStatusCode.InternalServerError + || statusCode == HttpStatusCode.Forbidden + || statusCode == HttpStatusCode.Unauthorized; + } + + public void Handle(HttpStatusCode statusCode, NancyContext context) + { + var headers = context.Response.Headers.Select(h => Tuple.Create(h.Key, h.Value)).ToArray(); + + if (!ShouldRenderFriendlyErrorPage(context)) + { + // Assume a valid error response was built earlier in the request lifecycle + // Nothing more for us to do here, so just bail out. + if (context.Response is ErrorResponse) + { + return; + } + + var err = new Error + { + Message = CustomErrors.Configuration.ErrorSummary + }; + + if (context.Response is NotFoundResponse) + { + // Normally we return 404's ourselves so we have an ErrorResponse. + // But if no route is matched, Nancy will set a NotFound response itself. + // When this happens we still want to return our nice JSON response. + err.Message = CustomErrors.Configuration.NotFoundSummary; + } + else + { + switch (statusCode) + { + case HttpStatusCode.Forbidden : + case HttpStatusCode.Unauthorized : + err.Message = CustomErrors.Configuration.UnauthorizedSummary; + break; + case HttpStatusCode.NotFound : + err.Message = CustomErrors.Configuration.NotFoundSummary; + context.Response = new ErrorResponse(new Error + { + Message = CustomErrors.Configuration.NotFoundSummary + }, _serializer, context.Environment); + break; + } + } + + context.Response = new ErrorResponse(err, _serializer, context.Environment).WithHeaders(headers).WithStatusCode(statusCode); + + return; + } + + var error = context.Response as ErrorResponse; + + var model = new ErrorViewModel + { + Details = error == null ? "" : error.FullException + }; + + switch (statusCode) + { + case HttpStatusCode.Forbidden: + model.Title = CustomErrors.Configuration.ForbiddenTitle; + model.Summary = CustomErrors.Configuration.ForbiddenSummary; + + break; + + case HttpStatusCode.Unauthorized: + model.Title = CustomErrors.Configuration.UnauthorizedTitle; + model.Summary = error == null ? CustomErrors.Configuration.UnauthorizedSummary : error.ErrorMessage; + + break; + + case HttpStatusCode.NotFound: + model.Title = CustomErrors.Configuration.NotFoundTitle; + model.Summary = CustomErrors.Configuration.NotFoundSummary; + + break; + case HttpStatusCode.InternalServerError: + model.Title = CustomErrors.Configuration.ErrorTitle; + model.Summary = error == null ? CustomErrors.Configuration.ErrorSummary : error.ErrorMessage; + + break; + } + + try + { + context.Response = + RenderView(context, CustomErrors.Configuration.ErrorViews[statusCode], model) + .WithStatusCode(statusCode) + .WithHeaders(headers); + } + catch(Exception e) + { + context.Response = new Response + { + StatusCode = HttpStatusCode.InternalServerError, + ContentType = "text/plain", + Contents = stream => + { + var writer = new StreamWriter(stream); + writer.AutoFlush = true; + writer.Write(string.Format("Could not locate your error view! Details: {0}", e.Message)); + } + }; + } + } + + private static bool ShouldRenderFriendlyErrorPage(NancyContext context) + { + if (CustomErrors.Configuration.AlwaysReturnJson) + { + return false; + } + + if (context.Request.Headers.Accept.OrderByDescending(o => o.Item2) + .Any(o => o.Item1 == "application/json" || o.Item1 == "text/json")) + { + return false; + } + + return true; + } + } +} \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/ErrorViewModel.cs b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/ErrorViewModel.cs new file mode 100644 index 000000000..3895ced33 --- /dev/null +++ b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/ErrorViewModel.cs @@ -0,0 +1,9 @@ +namespace Nancy.CustomErrors +{ + public class ErrorViewModel + { + public string Title { get; set; } + public string Summary { get; set; } + public string Details { get; set; } + } +} diff --git a/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/Nancy.CustomErrors.Shared.projitems b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/Nancy.CustomErrors.Shared.projitems new file mode 100644 index 000000000..01be28a0e --- /dev/null +++ b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/Nancy.CustomErrors.Shared.projitems @@ -0,0 +1,20 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + 0b0c2e66-9fd4-4475-ab31-81ab2f39f4da + + + Nancy.CustomErrors.Shared + + + + + + + + + + + \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/Nancy.CustomErrors.Shared.shproj b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/Nancy.CustomErrors.Shared.shproj new file mode 100644 index 000000000..8cbcca314 --- /dev/null +++ b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/Nancy.CustomErrors.Shared.shproj @@ -0,0 +1,13 @@ + + + + 0b0c2e66-9fd4-4475-ab31-81ab2f39f4da + 14.0 + + + + + + + + diff --git a/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/ResponseFormatterExtensions.cs b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/ResponseFormatterExtensions.cs new file mode 100644 index 000000000..69740feab --- /dev/null +++ b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors.Shared/ResponseFormatterExtensions.cs @@ -0,0 +1,16 @@ +using System.Linq; +using Nancy.Responses.Negotiation; + +namespace Nancy.CustomErrors +{ + public static class ResponseFormatterExtensions + { + public static Response AsError(this IResponseFormatter formatter, string message, + HttpStatusCode statusCode = HttpStatusCode.InternalServerError) + { + var serializer = formatter.SerializerFactory.GetSerializer(new MediaRange("application/json")); + + return new ErrorResponse(new Error {Message = message}, serializer, formatter.Environment).WithStatusCode(statusCode); + } + } +} \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors/Nancy.CustomErrors.csproj b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors/Nancy.CustomErrors.csproj new file mode 100644 index 000000000..ba25d4ef9 --- /dev/null +++ b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors/Nancy.CustomErrors.csproj @@ -0,0 +1,71 @@ + + + + + Release + AnyCPU + {CD7A7211-6563-499B-913D-8E5AF649BFE7} + Library + Properties + Nancy.CustomErrors + Nancy.CustomErrors + v4.6.1 + 512 + + ..\..\ + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + + ..\..\packages\Nancy.2.0.0-clinteastwood\lib\net452\Nancy.dll + + + + + + + + + + + + + Properties\AssemblyInfo.Shared.cs + + + + + Designer + + + + + + + + \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors/Properties/AssemblyInfo.cs b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..662817a2c --- /dev/null +++ b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors/Properties/AssemblyInfo.cs @@ -0,0 +1,31 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Nancy.CustomErrors")] +[assembly: AssemblyDescription("Simple custom error handling for Nancyfx projects")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("12a22ed0-6a81-4b42-89e5-9a8b1ccb2018")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("2.0.0")] +//[assembly: AssemblyVersion("2.0.0")] +//[assembly: AssemblyFileVersion("2.0.0")] diff --git a/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors/packages.config b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors/packages.config new file mode 100644 index 000000000..c174f646b --- /dev/null +++ b/contrib/Nancy.CustomErrors/src/Nancy.CustomErrors/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Example/App.config b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Example/App.config new file mode 100644 index 000000000..bae5d6d81 --- /dev/null +++ b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Example/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Example/Nancy.CustomErrors.Example.csproj b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Example/Nancy.CustomErrors.Example.csproj new file mode 100644 index 000000000..7476b1dd5 --- /dev/null +++ b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Example/Nancy.CustomErrors.Example.csproj @@ -0,0 +1,78 @@ + + + + + Debug + AnyCPU + {5A8E7514-E653-4C00-8623-1E71D7DCE6C5} + Exe + Properties + Nancy.CustomErrors.Example + Nancy.CustomErrors.Example + v4.6.1 + 512 + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\packages\Nancy.2.0.0-clinteastwood\lib\net452\Nancy.dll + + + ..\..\packages\Nancy.Hosting.Self.2.0.0-clinteastwood\lib\net452\Nancy.Hosting.Self.dll + + + + + + + + + + + + + + + + + PreserveNewest + + + + + + {cd7a7211-6563-499b-913d-8e5af649bfe7} + Nancy.CustomErrors + + + + + + + + \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Example/Program.cs b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Example/Program.cs new file mode 100644 index 000000000..bb21f9f4d --- /dev/null +++ b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Example/Program.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Nancy.Hosting.Self; +using Nancy.Responses; + +namespace Nancy.CustomErrors.Example +{ + class Program + { + static void Main(string[] args) + { + using (var host = new NancyHost(new Uri("http://localhost:1234"))) + { + host.Start(); + Console.ReadKey(); + } + } + } + + public class TestBootstrapper : DefaultNancyBootstrapper + { + protected override void ApplicationStartup(Nancy.TinyIoc.TinyIoCContainer container, Nancy.Bootstrapper.IPipelines pipelines) + { + base.ApplicationStartup(container, pipelines); + + CustomErrors.Enable(pipelines, new ErrorConfiguration(), new DefaultJsonSerializer(this.GetEnvironment())); + } + } + + public class TestModule : NancyModule + { + public TestModule() + : base("/") + { + Get("/test", _ => + { + var response = Response.AsText("test", "application/json"); + response.StatusCode = HttpStatusCode.InternalServerError; + return response; + }); + + Get("/err", _ => + { + throw new Exception("asdadsfdaf"); + }); + } + } + + public class ErrorConfiguration : CustomErrorsConfiguration + { + public ErrorConfiguration() + { + // Map error status codes to custom view names + ErrorViews[HttpStatusCode.NotFound] = "error"; + ErrorViews[HttpStatusCode.InternalServerError] = "error"; + ErrorViews[HttpStatusCode.Forbidden] = "error"; + } + public override ErrorResponse HandleError(NancyContext context, Exception ex, ISerializer serializer) + { + var error = new Error + { + FullException = ex.ToString(), + Message = ex.Message + }; + + return new ErrorResponse(error, serializer, context.Environment).WithStatusCode(HttpStatusCode.InternalServerError) as ErrorResponse; + } + } +} diff --git a/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Example/Properties/AssemblyInfo.cs b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Example/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..f1d716e0a --- /dev/null +++ b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Example/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Nancy.CustomErrors.Example")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Nancy.CustomErrors.Example")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("089565ef-a41d-463b-aa9c-9d5df6978aeb")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("2.0.0")] +[assembly: AssemblyVersion("2.0.0")] +[assembly: AssemblyFileVersion("2.0.0")] diff --git a/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Example/Views/error.html b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Example/Views/error.html new file mode 100644 index 000000000..b4fe785d2 --- /dev/null +++ b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Example/Views/error.html @@ -0,0 +1 @@ +ERROR! \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Example/packages.config b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Example/packages.config new file mode 100644 index 000000000..fa5b759ab --- /dev/null +++ b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Example/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/CustomErrorsFixture.cs b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/CustomErrorsFixture.cs new file mode 100644 index 000000000..3840b2301 --- /dev/null +++ b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/CustomErrorsFixture.cs @@ -0,0 +1,37 @@ +using System; +using System.Net; +using Nancy.Bootstrapper; +using Nancy.Configuration; +using Nancy.Responses; +using Nancy.Testing; +using NSubstitute; +using Xunit; + +namespace Nancy.CustomErrors.Tests +{ + public class CustomErrorsFixture + { + [Fact] + public void Should_throw_with_null_pipelines_passed_to_enable() + { + Assert.Throws(() => CustomErrors.Enable(null, new CustomErrorsConfiguration(), new DefaultJsonSerializer(new DefaultNancyEnvironment()))); + } + + [Fact] + public void Should_throw_with_null_configuration_passed_to_enable() + { + Assert.Throws(() => CustomErrors.Enable(Substitute.For(), null, new DefaultJsonSerializer(new DefaultNancyEnvironment()))); + } + + [Fact] + public void Should_add_error_hook_when_enabled() + { + var pipelines = Substitute.For(); + pipelines.OnError.Returns(Substitute.For()); + + CustomErrors.Enable(pipelines, Substitute.For(), new DefaultJsonSerializer(new DefaultNancyEnvironment())); + + pipelines.OnError.Received(1).AddItemToEndOfPipeline(Arg.Any>()); + } + } +} diff --git a/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/ErrorStatusCodeHandlerFixture.cs b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/ErrorStatusCodeHandlerFixture.cs new file mode 100644 index 000000000..fc763b60a --- /dev/null +++ b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/ErrorStatusCodeHandlerFixture.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Nancy.Configuration; +using Nancy.Responses; +using Nancy.Testing; +using Xunit; + +namespace Nancy.CustomErrors.Tests +{ + public class ErrorStatusCodeHandlerFixture + { + private readonly CustomErrorsConfiguration configuration; + private readonly Browser browser; + + public ErrorStatusCodeHandlerFixture() + { + configuration = new CustomErrorsConfiguration(); + + browser = new Browser(new ConfigurableBootstrapper(with => + { + with.ApplicationStartup((container, pipelines) => CustomErrors.Enable(pipelines, configuration, new DefaultJsonSerializer(new DefaultNancyEnvironment()))); + with.Module(); + with.StatusCodeHandler(); + })); + } + + + [Fact] + public void Should_return_custom_error_response_for_route_not_found() + { + var response = browser.Get("/nuffin", with => with.Header("Accept", "application/json")).Result; + + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); + Assert.Equal("The requested resource could not be found.", response.Body.DeserializeJson().Message); + } + + [Fact] + public void Should_return_json_for_application_json_accept_header() + { + var response = browser.Get("/error", with => with.Header("Accept", "application/json")).Result; + + Assert.NotNull(response.Body.DeserializeJson()); + } + + [Fact] + public void Should_return_json_for_text_json_accept_header() + { + var response = browser.Get("/error", with => with.Header("Accept", "text/json")).Result; + + Assert.NotNull(response.Body.DeserializeJson()); + } + + [Fact] + public void Should_return_html_for_text_html_accept_header() + { + var response = browser.Get("/error", with => with.Header("Accept", "text/html")).Result; + + response.Body["title"].ShouldExistOnce().And.ShouldContain(configuration.ErrorTitle); + } + + [Fact] + public void Should_return_html_no_accept_header() + { + var response = browser.Get("/error").Result; + + response.Body["title"].ShouldExistOnce().And.ShouldContain(configuration.ErrorTitle); + } + + [Fact] + public void Should_return_custom_error_response_for_uncaught_exception() + { + var response = browser.Get("/error", with => with.Header("Accept", "application/json")).Result; + + Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + Assert.Equal("ERROR MESSAGE HERE", response.Body.DeserializeJson().Message); + } + + [Fact] + public void Should_return_custom_error_response_for_forbidden() + { + var response = browser.Get("forbidden", with => with.Header("Accept", "application/json")).Result; + + Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); + Assert.NotNull(response.Body.DeserializeJson()); + } + + [Fact] + public void Should_return_custom_error_response_for_unauthorised() + { + var response = browser.Get("unauthorised", with => with.Header("Accept", "application/json")).Result; + + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + Assert.NotNull(response.Body.DeserializeJson()); + } + + [Fact] + public void Should_render_custom_html_for_uncaught_exception() + { + var response = browser.Get("error").Result; + + response.Body["title"].ShouldExistOnce().And.ShouldContain(configuration.ErrorTitle); + response.Body["h1"].ShouldExistOnce().And.ShouldContain("ERROR MESSAGE HERE"); + } + + [Fact] + public void Should_suppress_full_stack_trace_by_default() + { + var response = browser.Get("/err", with => with.Header("Accept", "application/json")).Result; + + Assert.Null(response.Body.DeserializeJson().FullException); + } + + [Fact] + public void Should_expose_full_stack_trace_in_debug_mode() + { + CustomErrors.Configuration.Debug = true; + + var response = browser.Get("/error", with => with.Header("Accept", "application/json")).Result; + + Assert.NotNull(response.Body.DeserializeJson().FullException); + + CustomErrors.Configuration.Debug = false; + } + + [Fact] + public void Should_retain_headers_already_set() + { + var response = browser.Get("/headers", with => with.Header("Accept", "application/json")).Result; + + Assert.NotNull(response.Headers.Where(h => h.Key == "CustomHeader")); + } + } + + + public class TestModule : NancyModule + { + public TestModule() + { + Get("error", _ => + { + throw new Exception("ERROR MESSAGE HERE"); + }); + + Get("forbidden", _ => HttpStatusCode.Forbidden); + Get("unauthorised", _ => HttpStatusCode.Unauthorized); + Get("headers", + _ => + new Response().WithStatusCode(HttpStatusCode.InternalServerError) + .WithHeader("CustomHeader", "CustomHeaderValue")); + } + } +} diff --git a/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/Nancy.CustomErrors.Tests.csproj b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/Nancy.CustomErrors.Tests.csproj new file mode 100644 index 000000000..65aca8c2c --- /dev/null +++ b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/Nancy.CustomErrors.Tests.csproj @@ -0,0 +1,113 @@ + + + + + + Debug + AnyCPU + {F1930050-9A83-42BB-9E14-1D5D7C6F255B} + Library + Properties + Nancy.CustomErrors.Tests + Nancy.CustomErrors.Tests + v4.6.1 + 512 + + b4ddc62d + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + + ..\..\packages\AngleSharp.0.9.9\lib\net45\AngleSharp.dll + + + ..\..\packages\CsQuery.1.3.5-beta5\lib\net40\CsQuery.dll + + + ..\..\packages\Nancy.2.0.0-clinteastwood\lib\net452\Nancy.dll + + + ..\..\packages\Nancy.Authentication.Forms.2.0.0-clinteastwood\lib\net452\Nancy.Authentication.Forms.dll + + + ..\..\packages\Nancy.Testing.2.0.0-clinteastwood\lib\net452\Nancy.Testing.dll + + + ..\..\packages\NSubstitute.2.0.3\lib\net45\NSubstitute.dll + + + + + + + + + + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + + + ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + + + ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + + + + + + + + + + + + + + {cd7a7211-6563-499b-913d-8e5af649bfe7} + Nancy.CustomErrors + + + + + PreserveNewest + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/Properties/AssemblyInfo.cs b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..6a8b63019 --- /dev/null +++ b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Nancy.CustomErrors.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Nancy.CustomErrors.Tests")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("07c53d9c-05da-40f3-adb5-60407c1a745f")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("2.0.0")] +[assembly: AssemblyVersion("2.0.0")] +[assembly: AssemblyFileVersion("2.0.0")] diff --git a/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/Views/Error.html b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/Views/Error.html new file mode 100644 index 000000000..481a8ba5f --- /dev/null +++ b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/Views/Error.html @@ -0,0 +1,11 @@ + + + + + + @Model.Title + + +

@Model.Summary

+ + \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/app.config b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/app.config new file mode 100644 index 000000000..0e3042431 --- /dev/null +++ b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/packages.config b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/packages.config new file mode 100644 index 000000000..d11892aa8 --- /dev/null +++ b/contrib/Nancy.CustomErrors/tests/Nancy.CustomErrors.Tests/packages.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/tools/packages.config b/contrib/Nancy.CustomErrors/tools/packages.config new file mode 100644 index 000000000..a4d70bcd8 --- /dev/null +++ b/contrib/Nancy.CustomErrors/tools/packages.config @@ -0,0 +1,4 @@ + + + + diff --git a/contrib/Nancy.CustomErrors/tools/settingsUtils.cake b/contrib/Nancy.CustomErrors/tools/settingsUtils.cake new file mode 100644 index 000000000..01a423e96 --- /dev/null +++ b/contrib/Nancy.CustomErrors/tools/settingsUtils.cake @@ -0,0 +1,332 @@ +#addin "Cake.Json" + +public class SettingsUtils +{ + public static Settings LoadSettings(ICakeContext context) + { + var settingsFile = context.Argument("settingsFile", ".\\settings.json"); + + context.Information("Loading Settings: {0}", settingsFile); + + if (!context.FileExists(settingsFile)) + { + context.Error("Settings File Does Not Exist"); + return null; + } + + var obj = context.DeserializeJsonFromFile(settingsFile); + + obj.SettingsFile = settingsFile; + + // Allow for any overrides + obj.Target = context.Argument("target", obj.Target); + obj.Configuration = context.Argument("configuration", obj.Configuration); + obj.VersionFile = context.Argument("versionFile", obj.VersionFile); + + obj.ExecuteBuild = GetBoolArgument(context, "build", obj.ExecuteBuild); + obj.ExecuteBuild = !GetBoolArgument(context, "skipBuild", !obj.ExecuteBuild); + + obj.ExecutePackage = GetBoolArgument(context, "package", obj.ExecutePackage); + obj.ExecutePackage = !GetBoolArgument(context, "skipPackage", !obj.ExecutePackage); + + obj.ExecuteUnitTest = GetBoolArgument(context, "unitTest", obj.ExecuteUnitTest); + obj.ExecuteUnitTest = !GetBoolArgument(context, "skipUnitTest", !obj.ExecuteUnitTest); + + obj.ExecuteClean = GetBoolArgument(context, "clean", obj.ExecuteClean); + obj.ExecuteClean = !GetBoolArgument(context, "skipClean", !obj.ExecuteClean); + + if (obj.Xamarin == null) obj.Xamarin = new XamarinSettings(); + + obj.Xamarin.EnableXamarinIOS = GetBoolArgument(context, "enableXamarinIOS", obj.Xamarin.EnableXamarinIOS); + obj.Xamarin.MacAgentIPAddress = context.Argument("macAgentIP", obj.Xamarin.MacAgentIPAddress); + obj.Xamarin.MacAgentUserName = context.Argument("macUserName", obj.Xamarin.MacAgentUserName); + obj.Xamarin.MacAgentUserPassword = context.Argument("macPassword", obj.Xamarin.MacAgentUserPassword); + + if (obj.NuGet == null) obj.NuGet = new NuGetSettings(); + + obj.NuGet.FeedUrl = context.Argument("nugetFeed", obj.NuGet.FeedUrl); + obj.NuGet.FeedUrl = context.Argument("nugetFeedUrl", obj.NuGet.FeedUrl); + + obj.NuGet.FeedApiKey = context.Argument("nugetApiKey", obj.NuGet.FeedApiKey); + + obj.NuGet.LibraryMinVersionDependency = (context.Argument("dependencyVersion", obj.NuGet.LibraryMinVersionDependency)).Replace(":","."); + obj.NuGet.VersionDependencyTypeForLibrary = context.Argument("dependencyType", obj.NuGet.VersionDependencyTypeForLibrary); + + return obj; + } + + private static bool GetBoolArgument(ICakeContext context, string argumentName, bool defaultValue) + { + var result = context.Argument(argumentName, defaultValue.ToString()).ToLower() == "true" || + context.Argument(argumentName, argumentName.ToString()) == "1"; + + return result; + } + + public static void DisplayHelp(ICakeContext context) + { + var defaultValues = new Settings(); + + context.Information("Command Line Help/Syntax:"); + context.Information("\t.\\build.ps1 \t\t\t\t(Default: {0})", defaultValues.Target); + context.Information("\t\t-Configuration=\t\t(Default: {0})", defaultValues.Configuration); + context.Information("\t\t-settingsFile=\t\t(Default: {0})", defaultValues.SettingsFile); + context.Information("\t\t-versionFile=\t\t(Default: {0})", defaultValues.VersionFile); + context.Information("\t\t-build=<0|1>\t\t\t\t(Default: {0})", defaultValues.ExecuteBuild); + context.Information("\t\t-package=<0|1>\t\t\t\t(Default: {0})", defaultValues.ExecutePackage); + context.Information("\t\t-unitTest=<0|1>\t\t\t\t(Default: {0})", defaultValues.ExecuteUnitTest); + context.Information("\t\t-clean=<0|1>\t\t\t\t(Default: {0})", defaultValues.ExecuteClean); + context.Information("\t\t-nugetFeed=\t\t(Default: {0})", defaultValues.NuGet.FeedUrl); + context.Information("\t\t-nugetApiKey=\t(Default: {0})", defaultValues.NuGet.FeedApiKey); + context.Information("\t\t-dependencyVersion=\t(Default: {0})", defaultValues.NuGet.LibraryMinVersionDependency); + context.Information("\t\t-dependencyType=\t\t(Default: {0})", defaultValues.NuGet.VersionDependencyTypeForLibrary); + context.Information("\t\t-enableXamarinIOS=<0|1>\t\t\t(Default: {0})", defaultValues.Xamarin.EnableXamarinIOS); + context.Information("\t\t-macAgentIP=\t\t(Default: {0})", defaultValues.Xamarin.MacAgentIPAddress); + context.Information("\t\t-macUserName=\t\t(Default: {0})", defaultValues.Xamarin.MacAgentUserName); + context.Information("\t\t-macPassword=\t\t(Default: {0})", defaultValues.Xamarin.MacAgentUserPassword); + context.Information(""); + context.Information("Examples:"); + context.Information("\t.\\build Build -Configuration=Release"); + context.Information("\t.\\build UnitTest -build=0"); + } +} + +public class Settings +{ + public Settings() + { + ExecuteBuild = true; + ExecutePackage = true; + ExecuteUnitTest = true; + ExecuteClean = true; + + Target = "DisplayHelp"; + Configuration = "Release"; + SettingsFile = ".\\settings.json"; + VersionFile = ".\\version.json"; + + Version = new VersionSettings(); + Build = new BuildSettings(); + Xamarin = new XamarinSettings(); + Test = new TestSettings(); + NuGet = new NuGetSettings(); + } + + public string Target {get;set;} + public string Configuration {get;set;} + public string SettingsFile {get;set;} + public string VersionFile {get;set;} + + public bool ExecuteBuild {get;set;} + public bool ExecutePackage {get;set;} + public bool ExecuteUnitTest {get;set;} + public bool ExecuteClean {get;set;} + + public VersionSettings Version {get;set;} + public BuildSettings Build {get;set;} + public TestSettings Test {get;set;} + public NuGetSettings NuGet {get;set;} + public XamarinSettings Xamarin {get;set;} + + public void Display(ICakeContext context) + { + context.Information("Settings:"); + + context.Information("\tTarget: {0}", Target); + context.Information("\tConfiguration: {0}", Configuration); + context.Information("\tSettings File: {0}", SettingsFile); + context.Information("\tVersion File: {0}", VersionFile); + + context.Information("\tExecute Build: {0}", ExecuteBuild); + context.Information("\tExecute Package: {0}", ExecutePackage); + context.Information("\tExecute UnitTests: {0}", ExecuteUnitTest); + context.Information("\tExecute Clean: {0}", ExecuteClean); + + Version.Display(context); + Build.Display(context); + Xamarin.Display(context); + Test.Display(context); + NuGet.Display(context); + } +} + +public class VersionSettings +{ + public VersionSettings() + { + LoadFrom = VersionSourceTypes.versionfile; + } + + public string VersionFile {get;set;} + public string AssemblyInfoFile {get;set;} + public VersionSourceTypes LoadFrom {get;set;} + public bool AutoIncrementVersion {get;set;} + + public void Display(ICakeContext context) + { + context.Information("Version Settings:"); + context.Information("\tVersion File: {0}", VersionFile); + context.Information("\tAssemblyInfo File: {0}", AssemblyInfoFile); + context.Information("\tLoad From: {0}", LoadFrom); + context.Information("\tAutoIncrement Version: {0}", AutoIncrementVersion); + } +} + +public class BuildSettings +{ + public BuildSettings() + { + SourcePath = "./source"; + SolutionFileSpec = "*.sln"; + TreatWarningsAsErrors = false; + MaxCpuCount = 0; + } + + public string SourcePath {get;set;} + public string SolutionFileSpec {get;set;} + public bool TreatWarningsAsErrors {get;set;} + public int MaxCpuCount {get;set;} + + public string SolutionFilePath { + get { + if (SolutionFileSpec.Contains("/")) return SolutionFileSpec; + + return string.Format("{0}{1}{2}", SourcePath, SolutionFileSpec.Contains("*") ? "/**/" : "", SolutionFileSpec); + } + } + + public void Display(ICakeContext context) + { + context.Information("Build Settings:"); + context.Information("\tSource Path: {0}", SourcePath); + context.Information("\tSolution File Spec: {0}", SolutionFileSpec); + context.Information("\tSolution File Path: {0}", SolutionFilePath); + context.Information("\tTreat Warnings As Errors: {0}", TreatWarningsAsErrors); + context.Information("\tMax Cpu Count: {0}", MaxCpuCount); + } +} + +public class XamarinSettings +{ + public XamarinSettings() + { + EnableXamarinIOS = false; + } + + public bool EnableXamarinIOS {get;set;} + public string MacAgentIPAddress {get;set;} + public string MacAgentUserName {get;set;} + public string MacAgentUserPassword {get;set;} + + public void Display(ICakeContext context) + { + context.Information("Xamarin Settings:"); + context.Information("\tEnable Xamarin IOS: {0}", EnableXamarinIOS); + context.Information("\tMac Agent IP Address: {0}", MacAgentIPAddress); + context.Information("\tMac Agent User Name: {0}", MacAgentUserName); + //context.Information("\tMac Agent User Password: {0}", MacAgentUserPassword); + } +} + +public class TestSettings +{ + public TestSettings() + { + SourcePath = "./tests"; + ResultsPath = "./tests"; + AssemblyFileSpec = "*.UnitTests.dll"; + Framework = TestFrameworkTypes.NUnit3; + } + + public string SourcePath {get;set;} + public string ResultsPath {get;set;} + public string AssemblyFileSpec {get;set;} + public TestFrameworkTypes Framework {get;set;} + + public void Display(ICakeContext context) + { + context.Information("Test Settings:"); + context.Information("\tSource Path: {0}", SourcePath); + context.Information("\tResults Path: {0}", ResultsPath); + context.Information("\tTest Assemploes File Spec: {0}", AssemblyFileSpec); + } +} + +public class NuGetSettings +{ + public NuGetSettings() + { + NuSpecPath = "./nuspec"; + NuGetConfig = "./.nuget/NuGet.Config"; + ArtifactsPath = "artifacts/packages"; + UpdateVersion = false; + VersionDependencyTypeForLibrary = VersionDependencyTypes.none; + UpdateLibraryDependencies = false; + LibraryNamespaceBase = null; + LibraryMinVersionDependency = null; + } + + public string NuGetConfig {get;set;} + public string FeedUrl {get;set;} + public string FeedApiKey {get;set;} + public string NuSpecPath {get;set;} + public string ArtifactsPath {get;set;} + public bool UpdateVersion {get;set;} + public VersionDependencyTypes VersionDependencyTypeForLibrary {get;set;} + public bool UpdateLibraryDependencies {get;set;} + public string LibraryNamespaceBase {get;set;} + public string LibraryMinVersionDependency {get;set;} + + public string NuSpecFileSpec { + get { + return string.Format("{0}/**/*.nuspec", NuSpecPath); + } + } + + public string NuGetPackagesSpec { + get { + return string.Format("{0}/*.nupkg", ArtifactsPath); + } + } + + public void Display(ICakeContext context) + { + context.Information("NuGet Settings:"); + context.Information("\tNuGet Config: {0}", NuGetConfig); + context.Information("\tFeed Url: {0}", FeedUrl); + //context.Information("\tFeed API Key: {0}", FeedApiKey); + context.Information("\tNuSpec Path: {0}", NuSpecPath); + context.Information("\tNuSpec File Spec: {0}", NuSpecFileSpec); + context.Information("\tArtifacts Path: {0}", ArtifactsPath); + context.Information("\tNuGet Packages Spec: {0}", NuGetPackagesSpec); + context.Information("\tUpdate Version: {0}", UpdateVersion); + context.Information("\tUpdate Library Dependencies: {0}", UpdateLibraryDependencies); + context.Information("\tForce Version Match: {0}", VersionDependencyTypeForLibrary); + context.Information("\tLibrary Namespace Base: {0}", LibraryNamespaceBase); + context.Information("\tLibrary Min Version Dependency: {0}", LibraryMinVersionDependency); + } +} + +public enum VersionDependencyTypes { + none, + exact, + greaterthan, + greaterthanorequal, + lessthan +} + +public enum VersionSourceTypes { + none, + versionfile, + assemblyinfo, + git, + tfs +} + +public enum TestFrameworkTypes { + none, + NUnit2, + NUnit3, + XUnit, + XUnit2 +} \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/tools/versionUtils.cake b/contrib/Nancy.CustomErrors/tools/versionUtils.cake new file mode 100644 index 000000000..7d9908d3b --- /dev/null +++ b/contrib/Nancy.CustomErrors/tools/versionUtils.cake @@ -0,0 +1,236 @@ +#addin "Cake.Json" +#addin "Cake.FileHelpers" + +#tool nuget:?package=GitVersion.CommandLine + +public class VersionUtils +{ + public static VersionInfo LoadVersion(ICakeContext context, Settings settings) + { + if (context == null) + { + throw new ArgumentNullException("context"); + } + + VersionInfo verInfo = null; + + switch (settings.Version.LoadFrom) + { + case VersionSourceTypes.none: + break; + case VersionSourceTypes.versionfile: + verInfo = LoadVersionFromJson(context, settings.Version.VersionFile); + break; + case VersionSourceTypes.assemblyinfo: + verInfo = LoadVersionFromAssemblyInfo(context, settings.Version.AssemblyInfoFile); + break; + case VersionSourceTypes.git: + verInfo = LoadVersionFromGit(context); + break; + case VersionSourceTypes.tfs: + //verInfo = LoadVersionFromTfs(context); + break; + } + + if (verInfo != null) + { + verInfo.CakeVersion = typeof(ICakeContext).Assembly.GetName().Version.ToString(); + } + + return verInfo; + } + + private static VersionInfo LoadVersionFromJson(ICakeContext context, string versionFile) + { + context.Information("Loading Version Info From File: {0}", versionFile); + if (string.IsNullOrEmpty(versionFile) || !context.FileExists(versionFile)) + { + context.Error("Version File Does Not Exist"); + return null; + } + + var obj = context.DeserializeJsonFromFile(versionFile); + + return obj; + } + + private static VersionInfo LoadVersionFromAssemblyInfo(ICakeContext context, string assemblyInfoFile) + { + context.Information("Fetching Version Info from AssemblyInfo File: {0}", assemblyInfoFile); + + if (!string.IsNullOrEmpty(assemblyInfoFile) || !context.FileExists(assemblyInfoFile)) + { + context.Error("AssemblyInfo file does not exist"); + return null; + } + + try { + var assemblyInfo = context.ParseAssemblyInfo(assemblyInfoFile); + var v = Version.Parse(assemblyInfo.AssemblyVersion); + + var verInfo = new VersionInfo { + Major = v.Major, + Minor = v.Minor, + Build = v.Build, + Semantic = assemblyInfo.AssemblyInformationalVersion, + Milestone = string.Concat("v", v.ToString()) + }; + + return verInfo; + } + catch {} + + return null; + } + + private static VersionInfo LoadVersionFromGit(ICakeContext context) + { + context.Information("Fetching Verson Infop from Git"); + + try { + GitVersion assertedVersions = context.GitVersion(new GitVersionSettings + { + OutputType = GitVersionOutput.Json, + }); + + var verInfo = new VersionInfo { + Major = assertedVersions.Major, + Minor = assertedVersions.Minor, + Build = assertedVersions.Patch, + Semantic = assertedVersions.LegacySemVerPadded, + Milestone = string.Concat("v", assertedVersions.MajorMinorPatch) + }; + + context.Information("Calculated Semantic Version: {0}", verInfo.Semantic); + + return verInfo; + } catch {} + + return null; + } + + public static void UpdateVersion(ICakeContext context, Settings settings, VersionInfo verInfo) + { + if (context == null) + { + throw new ArgumentNullException("context"); + } + + if (!string.IsNullOrEmpty(settings.Version.VersionFile) && context.FileExists(settings.Version.VersionFile)) + { + context.Information("Updating Version File {0}", settings.Version.VersionFile); + + context.SerializeJsonToFile(settings.Version.VersionFile, verInfo); + } + + if (!string.IsNullOrEmpty(settings.Version.AssemblyInfoFile) && context.FileExists(settings.Version.AssemblyInfoFile)) + { + context.Information("Updating Assembly Info File {0}", settings.Version.AssemblyInfoFile); + + context.ReplaceRegexInFiles(settings.Version.AssemblyInfoFile, "AssemblyVersion\\(.*\\)", string.Format("AssemblyVersion(\"{0}\")", verInfo.ToString(false))); + context.ReplaceRegexInFiles(settings.Version.AssemblyInfoFile, "AssemblyFileVersion\\(.*\\)", string.Format("AssemblyFileVersion(\"{0}\")", verInfo.ToString(false))); + } + } + + public static void UpdateNuSpecVersion(ICakeContext context, Settings settings, VersionInfo verInfo, FilePath nuspecFile) + { + if (context == null) + { + throw new ArgumentNullException("context"); + } + + var xpq = string.Format("/n:package/n:metadata/n:version"); + + context.Information("\tUpdating Version in Nuspec File {0} to {1}", nuspecFile, verInfo.ToString()); + + try { + context.XmlPoke(nuspecFile, xpq, verInfo.ToString(), new XmlPokeSettings { + PreserveWhitespace = true + , Namespaces = new Dictionary { + { /* Prefix */ "n", /* URI */ "http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd"} + } + }); + } catch {} // Its ok to throw these away as it most likely means the file didn't exist or the XPath didn't find any nodes + } + + public static void UpdateNuSpecVersionDependency(ICakeContext context, Settings settings, VersionInfo verInfo, FilePath nuspecFile) + { + if (context == null) + { + throw new ArgumentNullException("context"); + } + + if (string.IsNullOrEmpty(settings.NuGet.LibraryNamespaceBase)) return; + + var xpq = string.Format("/n:package/n:metadata/n:dependencies//n:dependency[starts-with(@id, '{0}')]/@version", settings.NuGet.LibraryNamespaceBase); + + var replacementStr = !string.IsNullOrEmpty(settings.NuGet.LibraryMinVersionDependency) ? settings.NuGet.LibraryMinVersionDependency : verInfo.ToString(); + + switch (settings.NuGet.VersionDependencyTypeForLibrary) + { + case VersionDependencyTypes.none: break; + case VersionDependencyTypes.exact: replacementStr = string.Format("[{0}]", replacementStr); break; + case VersionDependencyTypes.greaterthan: replacementStr = string.Format("(,{0})", replacementStr); break; + case VersionDependencyTypes.greaterthanorequal: replacementStr = string.Format("(,{0}]", replacementStr); break; + case VersionDependencyTypes.lessthan: replacementStr = string.Format("({0},)", replacementStr); break; + } + + context.Information("\tUpdating Version for {0} Namespace Assemblies in Nuspec File {1} to {2}", settings.NuGet.LibraryNamespaceBase, nuspecFile, replacementStr); + + try { + context.XmlPoke(nuspecFile, xpq, replacementStr, new XmlPokeSettings { + PreserveWhitespace = true + , Namespaces = new Dictionary { + { /* Prefix */ "n", /* URI */ "http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd"} + } + }); + } catch {} // Its ok to throw these away as it most likely means the file didn't exist or the XPath didn't find any nodes + } +} + +public class VersionInfo +{ + [Newtonsoft.Json.JsonProperty("major")] + public int Major {get;set;} + [Newtonsoft.Json.JsonProperty("minor")] + public int Minor {get;set;} + [Newtonsoft.Json.JsonProperty("build")] + public int Build {get;set;} + [Newtonsoft.Json.JsonProperty("preRelease")] + public int? PreRelease {get;set;} + [Newtonsoft.Json.JsonProperty("releaseNotes")] + public string[] ReleaseNotes {get;set;} + + [Newtonsoft.Json.JsonIgnore] + public string Semantic {get;set;} + [Newtonsoft.Json.JsonIgnore] + public string Milestone {get;set;} + [Newtonsoft.Json.JsonIgnore] + public string CakeVersion {get;set;} + + [Newtonsoft.Json.JsonIgnore] + public bool IsPreRelease { get { return PreRelease != null && PreRelease != 0; } } + + public new string ToString(bool includePreRelease = true) + { + var str = string.Format("{0:#0}.{1:#0}.{2:#0}", Major, Minor, Build); + if (IsPreRelease && includePreRelease) str += string.Format("-pre{0:00}", PreRelease); + + return str; + } + + public void Display(ICakeContext context) + { + context.Information("Version:"); + context.Information("\tMajor: {0}", Major); + context.Information("\tMinor: {0}", Minor); + context.Information("\tBuild: {0}", Build); + context.Information("\tIs PreRelease: {0}", IsPreRelease); + context.Information("\tPreRelease: {0}", PreRelease); + context.Information("\tSemantic: {0}", Semantic); + context.Information("\tMilestone: {0}", Milestone); + context.Information("\tCake Version: {0}", CakeVersion); + + if (ReleaseNotes != null) context.Information("\tRelease Notes: {0}", ReleaseNotes); + } +} \ No newline at end of file diff --git a/contrib/Nancy.CustomErrors/version.json b/contrib/Nancy.CustomErrors/version.json new file mode 100644 index 000000000..697e456cb --- /dev/null +++ b/contrib/Nancy.CustomErrors/version.json @@ -0,0 +1 @@ +{"major":2,"minor":0,"build":0,"preRelease":1,"releaseNotes":null} \ No newline at end of file diff --git a/src/CoiniumServ/App.config b/src/CoiniumServ/App.config deleted file mode 100644 index 325c75a39..000000000 --- a/src/CoiniumServ/App.config +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/CoiniumServ/Coinium.ico b/src/CoiniumServ/Coinium.ico new file mode 100644 index 000000000..fa82f09bf Binary files /dev/null and b/src/CoiniumServ/Coinium.ico differ diff --git a/src/CoiniumServ/CoiniumServ.csproj b/src/CoiniumServ/CoiniumServ.csproj index cbfa739a7..9da29e1e3 100644 --- a/src/CoiniumServ/CoiniumServ.csproj +++ b/src/CoiniumServ/CoiniumServ.csproj @@ -1,30 +1,33 @@ - - - + + - Debug - AnyCPU - {17A4E177-A910-40F8-899D-79A7F628699E} Exe - CoiniumServ - CoiniumServ - v4.7 - 512 - true - - - + netcoreapp2.0 + Next-gen crypto currency mining pool software + Int6ware + 0.2.7.0 + 0.2.7.0 + CoiniumServ.Program + Coinium.ico + 0.2.7.0 + Debug;Release;CI - - AnyCPU - true - full - false + + + latest + ..\..\build\bin\Release\ + + + + latest + ..\..\build\bin\Debug\ + + + + latest ..\..\build\bin\Debug\ - DEBUG;TRACE - prompt - 4 + AnyCPU none @@ -34,472 +37,48 @@ prompt 4 + - - ..\..\packages\AustinHarris.JsonRpc.1.1.70\lib\net40\AustinHarris.JsonRpc.dll - - - ..\..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll - - - ..\..\packages\CryptSharpOfficial.2.1.0.0\lib\CryptSharp.dll - - - ..\..\packages\Dapper.1.50.4\lib\net451\Dapper.dll - - - ..\..\packages\FluentMigrator.1.6.2\lib\40\FluentMigrator.dll - - - ..\..\packages\FluentMigrator.Runner.1.6.2\lib\40\FluentMigrator.Runner.dll - - - ..\..\packages\Gibbed.IO.1.0.0\lib\Gibbed.IO.dll - - - ..\..\packages\HashLib.2.0.1\lib\net40\HashLib.dll - - - ..\..\packages\JsonConfig.1.0.0\lib\JsonConfig.dll - - - ..\..\packages\JsonFx.2.0.1209.2802\lib\net40\JsonFx.dll - - - ..\..\packages\MySql.Data.6.8.8\lib\net45\MySql.Data.dll - - - ..\..\packages\Nancy.1.4.4\lib\net40\Nancy.dll - - - ..\..\packages\Nancy.CustomErrors.1.2.0.0\lib\net40\Nancy.CustomErrors.dll - - - ..\..\packages\Nancy.Hosting.Self.1.4.1\lib\net40\Nancy.Hosting.Self.dll - - - ..\..\packages\Nancy.Viewengines.Razor.1.4.3\lib\net40\Nancy.ViewEngines.Razor.dll - - - ..\..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll - - - ..\..\packages\Serilog.2.6.0\lib\net46\Serilog.dll - - - ..\..\packages\Serilog.Sinks.ColoredConsole.3.0.1\lib\net45\Serilog.Sinks.ColoredConsole.dll - - - ..\..\packages\Serilog.Sinks.Console.3.1.1\lib\net45\Serilog.Sinks.Console.dll - - - ..\..\packages\Serilog.Sinks.File.4.0.0\lib\net45\Serilog.Sinks.File.dll - - - ..\..\packages\Serilog.Sinks.RollingFile.3.3.0\lib\net45\Serilog.Sinks.RollingFile.dll - - - ..\..\packages\StackExchange.Redis.1.2.4\lib\net46\StackExchange.Redis.dll - - - - - - ..\..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - Always - Designer - - + - - - + + + - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + \ No newline at end of file diff --git a/src/CoiniumServ/Configuration/ConfigManager.cs b/src/CoiniumServ/Configuration/ConfigManager.cs index de5321d20..eb0dc08a4 100644 --- a/src/CoiniumServ/Configuration/ConfigManager.cs +++ b/src/CoiniumServ/Configuration/ConfigManager.cs @@ -40,7 +40,6 @@ using CoiniumServ.Server.Web.Config; using CoiniumServ.Statistics; using CoiniumServ.Utils.Helpers; -using CoiniumServ.Utils.Platform; using Serilog; namespace CoiniumServ.Configuration @@ -103,7 +102,6 @@ private void LoadGlobalConfig() // print a version banner. _logger.Information("CoiniumServ {0:l} {1:l} warming-up..", VersionInfo.CodeName, Assembly.GetAssembly(typeof(Program)).GetName().Version); - PlatformManager.PrintPlatformBanner(); // load rest of the configs. StackConfig = new StackConfig(data.stack); diff --git a/src/CoiniumServ/Persistance/Layers/Hybrid/HybridStorage.Shares.cs b/src/CoiniumServ/Persistance/Layers/Hybrid/HybridStorage.Shares.cs index bab8560af..0373254b3 100644 --- a/src/CoiniumServ/Persistance/Layers/Hybrid/HybridStorage.Shares.cs +++ b/src/CoiniumServ/Persistance/Layers/Hybrid/HybridStorage.Shares.cs @@ -34,7 +34,6 @@ using CoiniumServ.Persistance.Blocks; using CoiniumServ.Shares; using CoiniumServ.Utils.Helpers; -using CoiniumServ.Server.Mining.Stratum; namespace CoiniumServ.Persistance.Layers.Hybrid { diff --git a/src/CoiniumServ/Properties/AssemblyInfo.cs b/src/CoiniumServ/Properties/AssemblyInfo.cs deleted file mode 100644 index 4e9592561..000000000 --- a/src/CoiniumServ/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,60 +0,0 @@ -#region License -// -// MIT License -// -// CoiniumServ - Crypto Currency Mining Pool Server Software -// Copyright (C) 2013 - 2017, CoiniumServ Project -// Hüseyin Uslu, shalafiraistlin at gmail dot com -// https://github.com/bonesoul/CoiniumServ -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -#endregion - -using System.Reflection; -using System.Runtime.InteropServices; -using CoiniumServ; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("CoiniumServ")] -[assembly: AssemblyDescription("Next-gen crypto currency mining pool software")] -[assembly: AssemblyCompany("CoiniumServ")] -[assembly: AssemblyProduct("CoiniumServ - " + VersionInfo.CodeName)] -[assembly: AssemblyCopyright("Copyright (C) 2013 - 2018, CoiniumServ project")] -[assembly: AssemblyTrademark("CoiniumServ")] -[assembly: AssemblyCulture("")] - -#if DEBUG - [assembly: AssemblyConfiguration("Debug")] -#else - [assembly: AssemblyConfiguration("Release")] -#endif - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("a1d6e088-c67d-4a4e-9e5c-3884c021d843")] - -// Set the assembly version from VersionInfo.cs file. -[assembly: AssemblyVersion(VersionInfo.Assembly.Version)] diff --git a/src/CoiniumServ/Server/Commands/Stats.cs b/src/CoiniumServ/Server/Commands/Stats.cs index 0520fc8b9..663d18b90 100644 --- a/src/CoiniumServ/Server/Commands/Stats.cs +++ b/src/CoiniumServ/Server/Commands/Stats.cs @@ -28,7 +28,6 @@ #endregion using System; -using System.Diagnostics; using System.Text; using CoiniumServ.Utils.Commands; @@ -44,38 +43,38 @@ public string Detailed(string[] @params) output.AppendFormat("GC Allocated Memory: {0}KB ", GC.GetTotalMemory(true) / 1024); - if (PerformanceCounterCategory.Exists("Processor") && PerformanceCounterCategory.CounterExists("% Processor Time", "Processor")) - { - var processorTimeCounter = new PerformanceCounter { CategoryName = "Processor", CounterName = "% Processor Time", InstanceName = "_Total" }; - output.AppendFormat("Processor Time: {0}%", processorTimeCounter.NextValue()); - } + //if (PerformanceCounterCategory.Exists("Processor") && PerformanceCounterCategory.CounterExists("% Processor Time", "Processor")) + //{ + // var processorTimeCounter = new PerformanceCounter { CategoryName = "Processor", CounterName = "% Processor Time", InstanceName = "_Total" }; + // output.AppendFormat("Processor Time: {0}%", processorTimeCounter.NextValue()); + //} - if (PerformanceCounterCategory.Exists(".NET CLR LocksAndThreads")) - { - if (PerformanceCounterCategory.CounterExists("# of current physical Threads", ".NET CLR LocksAndThreads")) - { - var physicalThreadsCounter = new PerformanceCounter { CategoryName = ".NET CLR LocksAndThreads", CounterName = "# of current physical Threads", InstanceName = Process.GetCurrentProcess().ProcessName }; - output.AppendFormat("\nPhysical Threads: {0} ", physicalThreadsCounter.NextValue()); - } + //if (PerformanceCounterCategory.Exists(".NET CLR LocksAndThreads")) + //{ + // if (PerformanceCounterCategory.CounterExists("# of current physical Threads", ".NET CLR LocksAndThreads")) + // { + // var physicalThreadsCounter = new PerformanceCounter { CategoryName = ".NET CLR LocksAndThreads", CounterName = "# of current physical Threads", InstanceName = Process.GetCurrentProcess().ProcessName }; + // output.AppendFormat("\nPhysical Threads: {0} ", physicalThreadsCounter.NextValue()); + // } - if (PerformanceCounterCategory.CounterExists("# of current logical Threads", ".NET CLR LocksAndThreads")) - { - var logicalThreadsCounter = new PerformanceCounter { CategoryName = ".NET CLR LocksAndThreads", CounterName = "# of current logical Threads", InstanceName = Process.GetCurrentProcess().ProcessName }; - output.AppendFormat("Logical Threads: {0} ", logicalThreadsCounter.NextValue()); - } + // if (PerformanceCounterCategory.CounterExists("# of current logical Threads", ".NET CLR LocksAndThreads")) + // { + // var logicalThreadsCounter = new PerformanceCounter { CategoryName = ".NET CLR LocksAndThreads", CounterName = "# of current logical Threads", InstanceName = Process.GetCurrentProcess().ProcessName }; + // output.AppendFormat("Logical Threads: {0} ", logicalThreadsCounter.NextValue()); + // } - if (PerformanceCounterCategory.CounterExists("Contention Rate / sec", ".NET CLR LocksAndThreads")) - { - var contentionRateCounter = new PerformanceCounter { CategoryName = ".NET CLR LocksAndThreads", CounterName = "Contention Rate / sec", InstanceName = Process.GetCurrentProcess().ProcessName }; - output.AppendFormat("Contention Rate: {0}/sec", contentionRateCounter.NextValue()); - } - } + // if (PerformanceCounterCategory.CounterExists("Contention Rate / sec", ".NET CLR LocksAndThreads")) + // { + // var contentionRateCounter = new PerformanceCounter { CategoryName = ".NET CLR LocksAndThreads", CounterName = "Contention Rate / sec", InstanceName = Process.GetCurrentProcess().ProcessName }; + // output.AppendFormat("Contention Rate: {0}/sec", contentionRateCounter.NextValue()); + // } + //} - if (PerformanceCounterCategory.Exists(".NET CLR Exceptions") && PerformanceCounterCategory.CounterExists("# of Exceps Thrown", ".NET CLR Exceptions")) - { - var exceptionsThrownCounter = new PerformanceCounter { CategoryName = ".NET CLR Exceptions", CounterName = "# of Exceps Thrown", InstanceName = Process.GetCurrentProcess().ProcessName }; - output.AppendFormat("\nExceptions Thrown: {0}", exceptionsThrownCounter.NextValue()); - } + //if (PerformanceCounterCategory.Exists(".NET CLR Exceptions") && PerformanceCounterCategory.CounterExists("# of Exceps Thrown", ".NET CLR Exceptions")) + //{ + // var exceptionsThrownCounter = new PerformanceCounter { CategoryName = ".NET CLR Exceptions", CounterName = "# of Exceps Thrown", InstanceName = Process.GetCurrentProcess().ProcessName }; + // output.AppendFormat("\nExceptions Thrown: {0}", exceptionsThrownCounter.NextValue()); + //} return output.ToString(); } diff --git a/src/CoiniumServ/Server/Web/Modules/AlgorithmModule.cs b/src/CoiniumServ/Server/Web/Modules/AlgorithmModule.cs index 1fdb1deba..319f17279 100644 --- a/src/CoiniumServ/Server/Web/Modules/AlgorithmModule.cs +++ b/src/CoiniumServ/Server/Web/Modules/AlgorithmModule.cs @@ -40,16 +40,16 @@ public class AlgorithmModule:NancyModule public AlgorithmModule(IAlgorithmManager algorithmManager) :base("/algorithm") { - Get["/{slug}"] = _ => + Get("/{slug}", args => { - var algorithm = algorithmManager.Get(HttpUtility.HtmlEncode(_.slug)); // find the requested algorithm. + var algorithm = algorithmManager.Get(HttpUtility.HtmlEncode(args.slug)); // find the requested algorithm. if (algorithm == null) { return View["error", new ErrorViewModel { - Details = string.Format("The requested algorithm does not exist: {0}", _.slug) - }]; + Details = string.Format("The requested algorithm does not exist: {0}", args.slug) + }]; } ViewBag.Header = algorithm.Name; @@ -58,7 +58,7 @@ public AlgorithmModule(IAlgorithmManager algorithmManager) { Algorithm = algorithm }]; - }; + }); } } } diff --git a/src/CoiniumServ/Server/Web/Modules/AlgorithmsModule.cs b/src/CoiniumServ/Server/Web/Modules/AlgorithmsModule.cs index 5e6fcb98c..f30be0f43 100644 --- a/src/CoiniumServ/Server/Web/Modules/AlgorithmsModule.cs +++ b/src/CoiniumServ/Server/Web/Modules/AlgorithmsModule.cs @@ -38,14 +38,14 @@ public class AlgorithmsModule : NancyModule public AlgorithmsModule(IAlgorithmManager algorithmManager) : base("/algorithms") { - Get["/"] = _ => + Get("/" , args => { // return our view return View["algorithms", new AlgorithmsModel { Algorithms = algorithmManager.GetAllAsReadOnly() }]; - }; + }); } } } diff --git a/src/CoiniumServ/Server/Web/Modules/ApiModule.cs b/src/CoiniumServ/Server/Web/Modules/ApiModule.cs index 60a02fca1..5cbf52d72 100644 --- a/src/CoiniumServ/Server/Web/Modules/ApiModule.cs +++ b/src/CoiniumServ/Server/Web/Modules/ApiModule.cs @@ -46,7 +46,7 @@ public class ApiModule: NancyModule public ApiModule(IStatisticsManager statisticsManager, IPoolManager poolManager, IAlgorithmManager algorithmManager) :base("/api") { - Get["/"] = _ => + Get("/", args => { // include common data required by layout. ViewBag.Header = "Public API"; @@ -57,47 +57,47 @@ public ApiModule(IStatisticsManager statisticsManager, IPoolManager poolManager, BaseUrl = Request.Url.SiteBase, Coin = poolManager.First().Config.Coin }]; - }; + }); - Get["/pools"] = _ => + Get("/pools", args => { var response = (Response) poolManager.ServiceResponse; response.ContentType = "application/json"; return response; - }; + }); - Get["/pool/{slug}"] = _ => + Get("/pool/{slug}", args => { - var pool = poolManager.Get(HttpUtility.HtmlEncode(_.slug)); // query the requested pool. + var pool = poolManager.Get(HttpUtility.HtmlEncode(args.slug)); // query the requested pool. - var response = pool != null ? (Response)pool.ServiceResponse : PoolNotFound; + var response = pool != null ? (Response) pool.ServiceResponse : PoolNotFound; response.ContentType = "application/json"; return response; - }; + }); - Get["/algorithms"] = _ => + Get("/algorithms", args => { var response = (Response)algorithmManager.ServiceResponse; response.ContentType = "application/json"; return response; - }; + }); - Get["/algorithm/{slug}"] = _ => + Get("/algorithm/{slug}", args => { - var algorithm = algorithmManager.Get(HttpUtility.HtmlEncode(_.slug)); // query the requested pool. + var algorithm = algorithmManager.Get(HttpUtility.HtmlEncode(args.slug)); // query the requested pool. - var response = algorithm != null ? (Response)algorithm.ServiceResponse : AlgorithmNotFound; + var response = algorithm != null ? (Response) algorithm.ServiceResponse : AlgorithmNotFound; response.ContentType = "application/json"; return response; - }; + }); - Get["/global"] = _ => + Get("/global", args => { var response = (Response) statisticsManager.ServiceResponse; response.ContentType = "application/json"; return response; - }; + }); } } } diff --git a/src/CoiniumServ/Server/Web/Modules/ContactModule.cs b/src/CoiniumServ/Server/Web/Modules/ContactModule.cs index e8eed9bab..9635a9e88 100644 --- a/src/CoiniumServ/Server/Web/Modules/ContactModule.cs +++ b/src/CoiniumServ/Server/Web/Modules/ContactModule.cs @@ -36,14 +36,14 @@ public class ContactModule : NancyModule public ContactModule() : base("/contact") { - Get["/"] = _ => + Get("/", args => { // include common data required by layout. ViewBag.Header = "Contact Us"; // return our view return View["contact"]; - }; + }); } } } diff --git a/src/CoiniumServ/Server/Web/Modules/DonateModule.cs b/src/CoiniumServ/Server/Web/Modules/DonateModule.cs index 657770915..8380f507d 100644 --- a/src/CoiniumServ/Server/Web/Modules/DonateModule.cs +++ b/src/CoiniumServ/Server/Web/Modules/DonateModule.cs @@ -36,14 +36,14 @@ public class DonateModule : NancyModule public DonateModule() :base("/donate") { - Get["/"] = _ => + Get("/", args => { // include common data required by layout. ViewBag.Header = "Donation"; // return our view return View["donate"]; - }; + }); } } } diff --git a/src/CoiniumServ/Server/Web/Modules/HelpModule.cs b/src/CoiniumServ/Server/Web/Modules/HelpModule.cs index 1d614fd3b..1823a3c52 100644 --- a/src/CoiniumServ/Server/Web/Modules/HelpModule.cs +++ b/src/CoiniumServ/Server/Web/Modules/HelpModule.cs @@ -42,14 +42,14 @@ public class HelpModule:NancyModule public HelpModule(IPoolManager poolManager, IConfigManager configManager, ISoftwareRepository softwareRepository) :base("/help") { - Get["/faq"] = _ => + Get("/faq", args => { ViewBag.Header = "Frequently Asked Questions"; return View["faq"]; - }; + }); - Get["/gettingstarted/"] = _ => + Get("/gettingstarted/", args => { var model = new GettingStartedModel { @@ -58,17 +58,17 @@ public HelpModule(IPoolManager poolManager, IConfigManager configManager, ISoftw }; return View["gettingstarted/index", model]; - }; + }); - Get["/gettingstarted/pool/{slug}"] = _ => + Get("/gettingstarted/pool/{slug}", args => { - var pool = poolManager.Get(HttpUtility.HtmlEncode(_.slug)); // find the requested pool. + var pool = poolManager.Get(HttpUtility.HtmlEncode(args.slug)); // find the requested pool. if (pool == null) { return View["error", new ErrorViewModel { - Details = string.Format("The requested pool does not exist: {0}", _.slug) + Details = string.Format("The requested pool does not exist: {0}", args.slug) }]; } @@ -79,12 +79,12 @@ public HelpModule(IPoolManager poolManager, IConfigManager configManager, ISoftw }; return View["gettingstarted/pool", model]; - }; + }); - Get["/miningsoftware/"] = _ => + Get("/miningsoftware/", args => { return View["miningsoftware", softwareRepository]; - }; + }); } } } diff --git a/src/CoiniumServ/Server/Web/Modules/IndexModule.cs b/src/CoiniumServ/Server/Web/Modules/IndexModule.cs index 822d89c77..ec1b22c48 100644 --- a/src/CoiniumServ/Server/Web/Modules/IndexModule.cs +++ b/src/CoiniumServ/Server/Web/Modules/IndexModule.cs @@ -46,14 +46,14 @@ public IndexModule(IStatisticsManager statisticsManager, IPoolManager poolManage Statistics = statisticsManager }; - Get["/"] = _ => + Get("/", args => { // include common data required by layout. ViewBag.Header = "Welcome"; // return our view return View["index", model]; - }; + }); } } } diff --git a/src/CoiniumServ/Server/Web/Modules/PoolModule.cs b/src/CoiniumServ/Server/Web/Modules/PoolModule.cs index eedfd35cc..703202909 100644 --- a/src/CoiniumServ/Server/Web/Modules/PoolModule.cs +++ b/src/CoiniumServ/Server/Web/Modules/PoolModule.cs @@ -44,15 +44,15 @@ public class PoolModule : NancyModule public PoolModule(IPoolManager poolManager) : base("/pool") { - Get["/{slug}"] = _ => + Get("/{slug}", args => { - var pool = poolManager.Get(HttpUtility.HtmlEncode(_.slug)); // find the requested pool. + var pool = poolManager.Get(HttpUtility.HtmlEncode(args.slug)); // find the requested pool. if (pool == null) { return View["error", new ErrorViewModel { - Details = string.Format("The requested pool does not exist: {0}", _.slug) + Details = string.Format("The requested pool does not exist: {0}", args.slug) }]; } @@ -64,17 +64,17 @@ public PoolModule(IPoolManager poolManager) { Pool = pool }]; - }; + }); - Get["/{slug}/workers"] = _ => + Get("/{slug}/workers", args => { - var pool = poolManager.Get(HttpUtility.HtmlEncode(_.slug)); // find the requested pool. + var pool = poolManager.Get(HttpUtility.HtmlEncode(args.slug)); // find the requested pool. if (pool == null) // make sure queried pool exists. { return View["error", new ErrorViewModel { - Details = string.Format("The requested pool does not exist: {0}", _.slug) + Details = string.Format("The requested pool does not exist: {0}", args.slug) }]; } @@ -85,17 +85,17 @@ public PoolModule(IPoolManager poolManager) { Workers = pool.MinerManager.Miners }]; - }; + }); - Get["/{slug}/round"] = _ => + Get("/{slug}/round", args => { - var pool = poolManager.Get(HttpUtility.HtmlEncode(_.slug)); // find the requested pool. + var pool = poolManager.Get(HttpUtility.HtmlEncode(args.slug)); // find the requested pool. if (pool == null) // make sure queried pool exists. { return View["error", new ErrorViewModel { - Details = string.Format("The requested pool does not exist: {0}", _.slug) + Details = string.Format("The requested pool does not exist: {0}", args.slug) }]; } @@ -107,22 +107,22 @@ public PoolModule(IPoolManager poolManager) Round = pool.NetworkInfo.Round, Shares = pool.RoundShares }]; - }; + }); - Get["/{slug}/blocks/{page?1}"] = _ => + Get("/{slug}/blocks/{page?1}", args => { - var pool = (IPool)poolManager.Get(HttpUtility.HtmlEncode(_.slug)); // find the requested pool. + var pool = (IPool)poolManager.Get(HttpUtility.HtmlEncode(args.slug)); // find the requested pool. if (pool == null) // make sure queried pool exists. { return View["error", new ErrorViewModel { - Details = string.Format("The requested pool does not exist: {0}", _.slug) + Details = string.Format("The requested pool does not exist: {0}", args.slug) }]; } int page; - if (!Int32.TryParse(_.page, out page)) + if (!Int32.TryParse(args.page, out page)) page = 1; var paginationQuery = new PaginationQuery(page); @@ -146,22 +146,22 @@ public PoolModule(IPoolManager poolManager) }; return View["blocks", model]; - }; + }); - Get["/{slug}/blocks/paid/{page?1}"] = _ => + Get("/{slug}/blocks/paid/{page?1}", args => { - var pool = (IPool)poolManager.Get(HttpUtility.HtmlEncode(_.slug)); // find the requested pool. + var pool = (IPool)poolManager.Get(HttpUtility.HtmlEncode(args.slug)); // find the requested pool. if (pool == null) // make sure queried pool exists. { return View["error", new ErrorViewModel { - Details = string.Format("The requested pool does not exist: {0}", _.slug) + Details = string.Format("The requested pool does not exist: {0}", args.slug) }]; } int page; - if (!Int32.TryParse(_.page, out page)) + if (!Int32.TryParse(args.page, out page)) page = 1; var paginationQuery = new PaginationQuery(page); @@ -185,27 +185,27 @@ public PoolModule(IPoolManager poolManager) }; return View["blocks", model]; - }; + }); - Get["/{slug}/block/{height:int}"] = _ => + Get("/{slug}/block/{height:int}", args => { - var pool = (IPool)poolManager.Get(HttpUtility.HtmlEncode(_.slug)); // find the requested pool. + var pool = (IPool)poolManager.Get(HttpUtility.HtmlEncode(args.slug)); // find the requested pool. if (pool == null) // make sure queried pool exists. { return View["error", new ErrorViewModel { - Details = string.Format("The requested pool does not exist: {0}", _.slug) + Details = string.Format("The requested pool does not exist: {0}", args.slug) }]; } - var block = pool.BlockRepository.Get((uint)_.height); + var block = pool.BlockRepository.Get((uint)args.height); if (block == null) { return View["error", new ErrorViewModel { - Details = string.Format("The requested block does not exist: {0}", _.height) + Details = string.Format("The requested block does not exist: {0}", args.height) }]; } @@ -213,28 +213,28 @@ public PoolModule(IPoolManager poolManager) { Block = block, Coin = pool.Config.Coin, - Payments = pool.PaymentRepository.GetPaymentDetailsForBlock((uint)_.height) + Payments = pool.PaymentRepository.GetPaymentDetailsForBlock((uint)args.height) }; ViewBag.Header = string.Format("Block {0}", block.Height); ViewBag.SubHeader = string.Format("{0} block", pool.Config.Coin.Name); return View["block", model]; - }; + }); - Get["/{slug}/tx/{id:int}"] = _ => + Get("/{slug}/tx/{id:int}", args => { - var pool = (IPool)poolManager.Get(HttpUtility.HtmlEncode(_.slug)); // find the requested pool. + var pool = (IPool)poolManager.Get(HttpUtility.HtmlEncode(args.slug)); // find the requested pool. if (pool == null) // make sure queried pool exists. { return View["error", new ErrorViewModel { - Details = string.Format("The requested pool does not exist: {0}", _.slug) + Details = string.Format("The requested pool does not exist: {0}", args.slug) }]; } - var details = pool.PaymentRepository.GetPaymentDetailsByTransactionId((uint)_.id); + var details = pool.PaymentRepository.GetPaymentDetailsByTransactionId((uint)args.id); if (details == null) { @@ -259,21 +259,21 @@ public PoolModule(IPoolManager poolManager) }; return View["paymentdetails", model]; - }; + }); - Get["/{slug}/payment/{id:int}"] = _ => + Get("/{slug}/payment/{id:int}", args => { - var pool = (IPool)poolManager.Get(HttpUtility.HtmlEncode(_.slug)); // find the requested pool. + var pool = (IPool)poolManager.Get(HttpUtility.HtmlEncode(args.slug)); // find the requested pool. if (pool == null) // make sure queried pool exists. { return View["error", new ErrorViewModel { - Details = string.Format("The requested pool does not exist: {0}", _.slug) + Details = string.Format("The requested pool does not exist: {0}", args.slug) }]; } - var details = pool.PaymentRepository.GeyPaymentDetailsByPaymentId((uint)_.id); + var details = pool.PaymentRepository.GeyPaymentDetailsByPaymentId((uint)args.id); if (details == null) { @@ -298,32 +298,32 @@ public PoolModule(IPoolManager poolManager) }; return View["paymentdetails", model]; - }; + }); - Get["/{slug}/account/address/{address:length(26,34)}/{page?1}"] = _ => + Get("/{slug}/account/address/{address:length(26,34)}/{page?1}", args => { - var pool = (IPool)poolManager.Get(HttpUtility.HtmlEncode(_.slug)); // find the requested pool. + var pool = (IPool)poolManager.Get(HttpUtility.HtmlEncode(args.slug)); // find the requested pool. if (pool == null) { return View["error", new ErrorViewModel { - Details = string.Format("The requested pool does not exist: {0}", HttpUtility.HtmlEncode(_.slug)) + Details = string.Format("The requested pool does not exist: {0}", HttpUtility.HtmlEncode(args.slug)) }]; } - var account = (IAccount)pool.AccountManager.GetAccountByAddress(_.address); + var account = (IAccount)pool.AccountManager.GetAccountByAddress(args.address); if (account == null) { return View["error", new ErrorViewModel { - Details = string.Format("The requested account does not exist: {0}", _.address) + Details = string.Format("The requested account does not exist: {0}", args.address) }]; } int page; - if (!Int32.TryParse(_.page, out page)) + if (!Int32.TryParse(args.page, out page)) page = 1; var paginationQuery = new PaginationQuery(page); @@ -342,7 +342,7 @@ public PoolModule(IPoolManager poolManager) Payments = payments, PaginationQuery = paginationQuery }]; - }; + }); } } } diff --git a/src/CoiniumServ/Server/Web/Modules/PoolsModule.cs b/src/CoiniumServ/Server/Web/Modules/PoolsModule.cs index 9b25d9a94..e2ac1f67b 100644 --- a/src/CoiniumServ/Server/Web/Modules/PoolsModule.cs +++ b/src/CoiniumServ/Server/Web/Modules/PoolsModule.cs @@ -38,10 +38,13 @@ public class PoolsModule : NancyModule public PoolsModule(IPoolManager poolManager) : base("/pools") { - Get["/"] = _ => View["pools", new PoolsModel + Get("/", args => { - Pools = poolManager.GetAllAsReadOnly() - }]; + return View["pools", new PoolsModel + { + Pools = poolManager.GetAllAsReadOnly() + }]; + }); } } } diff --git a/src/CoiniumServ/Server/Web/Modules/TosModule.cs b/src/CoiniumServ/Server/Web/Modules/TosModule.cs index 7898ee4f3..0beb3ff44 100644 --- a/src/CoiniumServ/Server/Web/Modules/TosModule.cs +++ b/src/CoiniumServ/Server/Web/Modules/TosModule.cs @@ -36,14 +36,14 @@ public class TosModule : NancyModule public TosModule() : base("/tos") { - Get["/"] = _ => + Get("/", args => { // include common data required by layout. ViewBag.Header = "Terms of Service"; // return our view return View["tos"]; - }; + }); } } } diff --git a/src/CoiniumServ/Server/Web/NancyBootstrapper.cs b/src/CoiniumServ/Server/Web/NancyBootstrapper.cs index 50a22098f..65fb2fa23 100644 --- a/src/CoiniumServ/Server/Web/NancyBootstrapper.cs +++ b/src/CoiniumServ/Server/Web/NancyBootstrapper.cs @@ -27,6 +27,7 @@ // #endregion +using System.Collections.Generic; using CoiniumServ.Configuration; using CoiniumServ.Container.Context; using CoiniumServ.Pools; @@ -37,6 +38,8 @@ using Nancy.CustomErrors; using Nancy.TinyIoc; using Nancy.Diagnostics; +using Nancy.Responses; +using Nancy.ViewEngines.Razor; namespace CoiniumServ.Server.Web { @@ -78,7 +81,7 @@ protected override void ApplicationStartup(TinyIoCContainer container, IPipeline ctx.ViewBag.LastUpdate = _statisticsManager.LastUpdate.ToString("HH:mm:ss tt zz"); // last statistics update. }; - CustomErrors.Enable(pipelines, new ErrorConfiguration()); + CustomErrors.Enable(pipelines, new ErrorConfiguration(), new DefaultJsonSerializer(GetEnvironment())); // todo: fix this. } protected override void ConfigureConventions(NancyConventions nancyConventions) @@ -99,16 +102,46 @@ protected override TinyIoCContainer GetApplicationContainer() return _applicationContext.Container; } - #if DEBUG // on debug mode, enable http://website/_Nancy/ - protected override DiagnosticsConfiguration DiagnosticsConfiguration + public override void Configure(Nancy.Configuration.INancyEnvironment environment) { - get { return new DiagnosticsConfiguration { Password = @"debug" }; } + #if DEBUG + environment.Views(true, true); // on debug mode enable runtime view discovery + environment.Tracing(true, true); // enable tracing + environment.Diagnostics(password: "debug"); // on debug mode, enable http://website/_Nancy/ + #else + environment.Views(false, false); + environment.Tracing(false, false); // enable tracing + #endif } - #endif protected override void ConfigureApplicationContainer(TinyIoCContainer container) { // prevents nancy from autoregistering it's own set of resolvers. } + + protected override void RegisterInstances( + TinyIoCContainer container, IEnumerable instanceRegistrations) + { + base.RegisterInstances(container, instanceRegistrations); + container.Register(new CustomRazorConfiguration()); + } + } + + public class CustomRazorConfiguration : IRazorConfiguration + { + public bool AutoIncludeModelNamespace + { + get { return true; } + } + + public IEnumerable GetAssemblyNames() + { + yield return "CoiniumServ.Server.Web.Models"; + } + + public IEnumerable GetDefaultNamespaces() + { + yield return "CoiniumServ.Server.Web.Models"; + } } } diff --git a/src/CoiniumServ/Server/Web/RootPathProvider.cs b/src/CoiniumServ/Server/Web/RootPathProvider.cs index d51ee4cb3..6635d118b 100644 --- a/src/CoiniumServ/Server/Web/RootPathProvider.cs +++ b/src/CoiniumServ/Server/Web/RootPathProvider.cs @@ -42,7 +42,7 @@ public RootPathProvider(string template) // determine the root path #if DEBUG // on debug mode use static files form source directory, so live edits can be possible // note: we need to convert relative path to absolute path as nancy can only server static files with absolute path. - _rootPath = Path.GetFullPath(FileHelpers.GetAbsolutePath($"../../../src/web/{template}")); // if not yet do so. + _rootPath = Path.GetFullPath(FileHelpers.GetAbsolutePath($"../../../../src/web/{template}")); // if not yet do so. #else // on release mode use static files from bin/Release. _rootPath = FileHelpers.GetAbsolutePath($"web/{template}"); #endif diff --git a/src/CoiniumServ/Server/Web/WebServer.cs b/src/CoiniumServ/Server/Web/WebServer.cs index 746af09d6..02684d3f1 100644 --- a/src/CoiniumServ/Server/Web/WebServer.cs +++ b/src/CoiniumServ/Server/Web/WebServer.cs @@ -32,7 +32,6 @@ using System.Net; using System.Net.Sockets; using CoiniumServ.Configuration; -using Nancy; using Nancy.Bootstrapper; using Nancy.Hosting.Self; using Serilog; @@ -87,16 +86,6 @@ public bool Start() try { - #if DEBUG // on debug mode enable runtime view discovery & request tracing - StaticConfiguration.Caching.EnableRuntimeViewDiscovery = true; - StaticConfiguration.Caching.EnableRuntimeViewUpdates = true; - StaticConfiguration.EnableRequestTracing = true; - #else - StaticConfiguration.Caching.EnableRuntimeViewDiscovery = false; - StaticConfiguration.Caching.EnableRuntimeViewUpdates = false; - StaticConfiguration.EnableRequestTracing = false; - #endif - var host = new NancyHost(_webBootstrapper, hostConfiguration, uri); // create nancy host. host.Start(); @@ -131,7 +120,7 @@ public bool Start() if (baseException is DirectoryNotFoundException) _logger.Error("Invalid template path for web-server given; {0:l}", baseException.Message); else - _logger.Error("An error occured while starting web-server: {0:l}", e); + _logger.Error("An error occurred while starting web-server: {0:l}", e); IsListening = false; return false; diff --git a/src/CoiniumServ/Utils/Helpers/FileHelpers.cs b/src/CoiniumServ/Utils/Helpers/FileHelpers.cs index 375c4745e..a7cd755bf 100644 --- a/src/CoiniumServ/Utils/Helpers/FileHelpers.cs +++ b/src/CoiniumServ/Utils/Helpers/FileHelpers.cs @@ -31,7 +31,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using CoiniumServ.Utils.Platform; using Serilog; namespace CoiniumServ.Utils.Helpers @@ -46,10 +45,6 @@ public static string AssemblyRoot public static string GetAbsolutePath(string file) { var path = Path.Combine(AssemblyRoot, file); // first get the path as *unix paths. - - if (PlatformManager.Framework == Frameworks.DotNet) // if we are running on windows, - path = path.Replace('/', '\\'); // replace to windows-native paths. - return path; } diff --git a/src/CoiniumServ/Utils/Platform/Frameworks.cs b/src/CoiniumServ/Utils/Platform/Frameworks.cs deleted file mode 100644 index b2ce582e2..000000000 --- a/src/CoiniumServ/Utils/Platform/Frameworks.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region License -// -// MIT License -// -// CoiniumServ - Crypto Currency Mining Pool Server Software -// Copyright (C) 2013 - 2017, CoiniumServ Project -// Hüseyin Uslu, shalafiraistlin at gmail dot com -// https://github.com/bonesoul/CoiniumServ -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -#endregion - -namespace CoiniumServ.Utils.Platform -{ - /// - /// .Net frameworks. - /// - public enum Frameworks - { - DotNet, - Mono - } - - public enum DotNetVersion - { - DotNet4, - DotNet45 - } -} diff --git a/src/CoiniumServ/Utils/Platform/PlatformManager.cs b/src/CoiniumServ/Utils/Platform/PlatformManager.cs deleted file mode 100644 index 3a4aeb01b..000000000 --- a/src/CoiniumServ/Utils/Platform/PlatformManager.cs +++ /dev/null @@ -1,104 +0,0 @@ -#region License -// -// MIT License -// -// CoiniumServ - Crypto Currency Mining Pool Server Software -// Copyright (C) 2013 - 2017, CoiniumServ Project -// Hüseyin Uslu, shalafiraistlin at gmail dot com -// https://github.com/bonesoul/CoiniumServ -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -#endregion - -using System; -using System.Reflection; -using Serilog; - -namespace CoiniumServ.Utils.Platform -{ - /// - /// Platform Manager that identifies platforms & manages them. - /// - public class PlatformManager - { - /// - /// Current framework we are running on. - /// - public static Frameworks Framework { get; private set; } - - /// - /// Is the framework .Net 4.5? - /// - public static bool IsDotNet45 { get; private set; } - - /// - /// Current framework's version. - /// - public static Version FrameworkVersion { get; private set; } - - /// - /// Gets the mono version. - /// - /// The mono version. - public static string MonoVersion { get; private set; } - - static PlatformManager() - { - IdentifyPlatform(); - } - - public static void PrintPlatformBanner() - { - Log.ForContext().Information("Running over {0:l}, framework: {1:l} (v{2:l}).", - Framework == Frameworks.DotNet ? ".Net" : string.Format("Mono {0}", MonoVersion), - IsDotNet45 ? "4.5" : "4", FrameworkVersion); - } - - /// - /// Identifies the current platform and used frameworks. - /// - private static void IdentifyPlatform() - { - Framework = Type.GetType("Mono.Runtime") != null ? Frameworks.Mono : Frameworks.DotNet; - IsDotNet45 = Type.GetType("System.Reflection.ReflectionContext", false) != null; /* ReflectionContext exists from .NET 4.5 onwards. */ - FrameworkVersion = Environment.Version; - - if (Framework == Frameworks.Mono) - MonoVersion = GetMonoVersion(); - } - - private static string GetMonoVersion() - { - // we can use reflection to get mono version using Mono.Runtime.GetDisplayName(). - - var type = Type.GetType("Mono.Runtime"); - - if (type == null) - return string.Empty; - - var displayName = type.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static); - - if (displayName == null) - return string.Empty; - - return displayName.Invoke(null, null).ToString(); - } - } -} diff --git a/src/CoiniumServ/packages.config b/src/CoiniumServ/packages.config deleted file mode 100644 index 769b4938f..000000000 --- a/src/CoiniumServ/packages.config +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Tests/Banning/BanConfigTests.cs b/src/Tests/Banning/BanConfigTests.cs index 3ddc95203..c0235fa7a 100644 --- a/src/Tests/Banning/BanConfigTests.cs +++ b/src/Tests/Banning/BanConfigTests.cs @@ -30,8 +30,8 @@ using CoiniumServ.Banning; using CoiniumServ.Configuration; using CoiniumServ.Container; +using FluentAssertions; using Nancy.TinyIoc; -using Should.Fluent; using Xunit; namespace CoiniumServ.Tests.Banning @@ -97,7 +97,7 @@ public void InvalidJson_ShouldBeInvalid() var config = new BanConfig(data); // as we have just supplied an invalid json, config should be just marked as invalid. - config.Valid.Should().Equal(false); + config.Valid.Should().Be(false); } } } diff --git a/src/Tests/Blocks/BlockProcessorTests.cs b/src/Tests/Blocks/BlockProcessorTests.cs index 52b64c5ce..59c87b63b 100644 --- a/src/Tests/Blocks/BlockProcessorTests.cs +++ b/src/Tests/Blocks/BlockProcessorTests.cs @@ -38,8 +38,8 @@ using CoiniumServ.Persistance.Layers; using CoiniumServ.Pools; using ExposedObject; +using FluentAssertions; using NSubstitute; -using Should.Fluent; using Xunit; namespace CoiniumServ.Tests.Blocks @@ -80,7 +80,7 @@ private void QueryBlockTest_WithInvalidBlockHash_ShouldBeOrphaned() exposed.QueryBlock(block); // block should be marked as orphaned. - block.Status.Should().Equal(BlockStatus.Orphaned); + block.Status.Should().Be(BlockStatus.Orphaned); } [Fact] @@ -95,7 +95,7 @@ private void QueryBlockTest_WithNegativeConfirmations_ShouldBeOrphaned() exposed.QueryBlock(block); // block should be marked as orphaned. - block.Status.Should().Equal(BlockStatus.Orphaned); + block.Status.Should().Be(BlockStatus.Orphaned); } [Fact] @@ -110,7 +110,7 @@ private void QueryBlockTest_WithInvalidTransactionHash_ShouldBeOrphaned() exposed.QueryBlock(block); // block should be marked as orphaned. - block.Status.Should().Equal(BlockStatus.Orphaned); + block.Status.Should().Be(BlockStatus.Orphaned); } [Fact] @@ -136,7 +136,7 @@ private void QueryBlockTest_WithNonExistingGenerationTransaction_ShouldBeOrphane exposed.QueryBlock(block); // block should be marked as orphaned. - block.Status.Should().Equal(BlockStatus.Orphaned); + block.Status.Should().Be(BlockStatus.Orphaned); } [Fact] @@ -152,7 +152,7 @@ private void QueryBlockTest_WithNonExistingPoolOutput_ShouldBeOrphaned() exposed.QueryBlock(block); // block should be marked as orphaned. - block.Status.Should().Equal(BlockStatus.Orphaned); + block.Status.Should().Be(BlockStatus.Orphaned); } [Fact] @@ -173,7 +173,7 @@ private void QueryBlockTest_WithIncorrectPoolOutputAddress_ShouldBeOrphaned() exposed.QueryBlock(block); // block should be marked as orphaned. - block.Status.Should().Equal(BlockStatus.Orphaned); + block.Status.Should().Be(BlockStatus.Orphaned); } [Fact] @@ -194,7 +194,7 @@ private void QueryBlockTest_WithIncorrectPoolOutputAccount_ShouldBeOrphaned() exposed.QueryBlock(block); // block should be marked as orphaned. - block.Status.Should().Equal(BlockStatus.Orphaned); + block.Status.Should().Be(BlockStatus.Orphaned); } [Fact] @@ -215,7 +215,7 @@ private void QueryBlockTest_ShouldSetReward() exposed.QueryBlock(block); // block reward should be set to 999 - block.Reward.Should().Equal((decimal)999); + block.Reward.Should().Be((decimal)999); } [Fact] @@ -236,7 +236,7 @@ private void QueryBlockTest_WithImmaturePoolOutputCategory_ShouldStayPending() exposed.QueryBlock(block); // block should still stay as pending - block.Status.Should().Equal(BlockStatus.Pending); + block.Status.Should().Be(BlockStatus.Pending); } [Fact] @@ -257,7 +257,7 @@ private void QueryBlockTest_WithGeneratePoolOutputCategory_ShouldGetConfirmed() exposed.QueryBlock(block); // block should still stay as pending - block.Status.Should().Equal(BlockStatus.Confirmed); + block.Status.Should().Be(BlockStatus.Confirmed); } [Fact] @@ -278,7 +278,7 @@ private void QueryBlockTest_WithOprhanedPoolOutputCategory_ShouldGetOrphaned() exposed.QueryBlock(block); // block should still stay as pending - block.Status.Should().Equal(BlockStatus.Orphaned); + block.Status.Should().Be(BlockStatus.Orphaned); } } } diff --git a/src/Tests/Coin/AmountTests.cs b/src/Tests/Coin/AmountTests.cs index e8f13f31f..d7d829f80 100644 --- a/src/Tests/Coin/AmountTests.cs +++ b/src/Tests/Coin/AmountTests.cs @@ -28,7 +28,7 @@ #endregion using CoiniumServ.Utils.Helpers; -using Should.Fluent; +using FluentAssertions; using Xunit; namespace CoiniumServ.Tests.Coin @@ -54,20 +54,20 @@ public void ConversionTests() // test all instances against each other. - amount1.Coins.Should().Equal(amount2.Coins); - amount1.MilliBits.Should().Equal(amount2.MilliBits); - amount1.MicroBits.Should().Equal(amount2.MicroBits); - amount1.Satoshis.Should().Equal(amount2.Satoshis); + amount1.Coins.Should().Be(amount2.Coins); + amount1.MilliBits.Should().Be(amount2.MilliBits); + amount1.MicroBits.Should().Be(amount2.MicroBits); + amount1.Satoshis.Should().Be(amount2.Satoshis); - amount2.Coins.Should().Equal(amount3.Coins); - amount2.MilliBits.Should().Equal(amount3.MilliBits); - amount2.MicroBits.Should().Equal(amount3.MicroBits); - amount2.Satoshis.Should().Equal(amount3.Satoshis); + amount2.Coins.Should().Be(amount3.Coins); + amount2.MilliBits.Should().Be(amount3.MilliBits); + amount2.MicroBits.Should().Be(amount3.MicroBits); + amount2.Satoshis.Should().Be(amount3.Satoshis); - amount3.Coins.Should().Equal(amount4.Coins); - amount3.MilliBits.Should().Equal(amount4.MilliBits); - amount3.MicroBits.Should().Equal(amount4.MicroBits); - amount3.Satoshis.Should().Equal(amount4.Satoshis); + amount3.Coins.Should().Be(amount4.Coins); + amount3.MilliBits.Should().Be(amount4.MilliBits); + amount3.MicroBits.Should().Be(amount4.MicroBits); + amount3.Satoshis.Should().Be(amount4.Satoshis); } } } diff --git a/src/Tests/Coin/Base58Test.cs b/src/Tests/Coin/Base58Test.cs index acd25c9d8..b64325a45 100644 --- a/src/Tests/Coin/Base58Test.cs +++ b/src/Tests/Coin/Base58Test.cs @@ -31,7 +31,7 @@ using CoiniumServ.Coin.Address; using CoiniumServ.Coin.Address.Exceptions; using Org.BouncyCastle.Math; -using Should.Fluent; +using FluentAssertions; using Xunit; namespace CoiniumServ.Tests.Coin @@ -42,10 +42,10 @@ public class Base58Test public void TestEncode() { var testbytes = Encoding.UTF8.GetBytes("Hello World"); - Base58.Encode(testbytes).Should().Equal("JxF12TrwUP45BMd"); + Base58.Encode(testbytes).Should().Be("JxF12TrwUP45BMd"); var bi = BigInteger.ValueOf(3471844090); - Base58.Encode(bi.ToByteArray()).Should().Equal("16Ho7Hs"); + Base58.Encode(bi.ToByteArray()).Should().Be("16Ho7Hs"); } [Fact] diff --git a/src/Tests/Coin/Coinbase/SerializersTests.cs b/src/Tests/Coin/Coinbase/SerializersTests.cs index 2979b14dc..aa3719995 100644 --- a/src/Tests/Coin/Coinbase/SerializersTests.cs +++ b/src/Tests/Coin/Coinbase/SerializersTests.cs @@ -43,7 +43,7 @@ using CoiniumServ.Utils.Extensions; using Newtonsoft.Json; using NSubstitute; -using Should.Fluent; +using FluentAssertions; using Xunit; /* @@ -200,7 +200,7 @@ public void SerializeCoinbaseTest() const UInt32 extraNonce2 = 0x07000000; var coinbase = Serializers.SerializeCoinbase(_job, extraNonce1, extraNonce2); - coinbase.ToHexString().Should().Equal("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff270310cf04062f503253482f0430a3aa530858000000070000000d2f6e6f64655374726174756d2f000000000280010b27010000001976a914329035234168b8da5af106ceb20560401236849888ac80f0fa02000000001976a9147d576fbfca48b899dc750167dd2a2a6572fff49588ac00000000"); + coinbase.ToHexString().Should().Be("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff270310cf04062f503253482f0430a3aa530858000000070000000d2f6e6f64655374726174756d2f000000000280010b27010000001976a914329035234168b8da5af106ceb20560401236849888ac80f0fa02000000001976a9147d576fbfca48b899dc750167dd2a2a6572fff49588ac00000000"); } [Fact] @@ -222,7 +222,7 @@ public void SerializeHeaderTest() var header = Serializers.SerializeHeader(_job, merkleRoot, nTime, nonce); // test the header. - header.ToHexString().Should().Equal("0100000062804ac7aa2748b16841fc12ac15721dc5be748c64c6b596b74c56478eb84e1c1732a2242d83c6b1a935eecec4c48e56a10b0977f723456331f6b2ff5efb757831a3aa53f7d4481d00507244"); + header.ToHexString().Should().Be("0100000062804ac7aa2748b16841fc12ac15721dc5be748c64c6b596b74c56478eb84e1c1732a2242d83c6b1a935eecec4c48e56a10b0977f723456331f6b2ff5efb757831a3aa53f7d4481d00507244"); } [Fact] @@ -247,7 +247,7 @@ public void SerializeBlockTest() var blockHex = Serializers.SerializeBlock(_job, header, coinbase); // test the block hex - blockHex.ToHexString().Should().Equal("0100000062804ac7aa2748b16841fc12ac15721dc5be748c64c6b596b74c56478eb84e1c1732a2242d83c6b1a935eecec4c48e56a10b0977f723456331f6b2ff5efb757831a3aa53f7d4481d005072440201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff270310cf04062f503253482f0430a3aa530858000000070000000d2f6e6f64655374726174756d2f000000000280010b27010000001976a914329035234168b8da5af106ceb20560401236849888ac80f0fa02000000001976a9147d576fbfca48b899dc750167dd2a2a6572fff49588ac00000000010000000332a82e92f522deee69b09e27858ba9b87585f2a4913ef71018df40909032fdc3000000006a473044022019ca05cb880a04f0d842268b7e75ac6d2695fc544df033e3daeb29239251a8970220031f6336767f2ea617347484e1290ec0bdcc71056ea2d3084e75384905250ec50121030dd394118fb66ca288bff71d8ea762678783b005770f7f9ba4128233191e0847ffffffff086747cbd339b21b950774186091653a7b8f5751b00a906ff6f5561b3a6fcee6010000006b4830450221009ae1ba9a216d313cc592fc2c1ef08f1e0e555a32b6c1b305f685ac882d38356b0220243106bbb5bb76dde142e574cba8f30c1e2f7059e8e9161770396fbd2b50420f0121030dd394118fb66ca288bff71d8ea762678783b005770f7f9ba4128233191e0847ffffffffe2f15804b1e41c36c925c6f64f219b2bdb3c9fbff4c97a4f0e8c7f31d7e6f2af000000006b48304502200be8894fdd7f5c19be248a979c08bbf2395f606e038c3e02c0266474c03699ab022100ff5de87086e487410f5d7b68012655ca6d814f0caeb9ca42d9c425a90f68b3030121030dd394118fb66ca288bff71d8ea762678783b005770f7f9ba4128233191e0847ffffffff02a0f01900000000001976a9141c50209a1dfdf53313d237b75e9aeb553ca1dfda88ac00e1f505000000001976a914cbb9a3e7a7c1651b1006f876f08b40be85b274f588ac00000000"); + blockHex.ToHexString().Should().Be("0100000062804ac7aa2748b16841fc12ac15721dc5be748c64c6b596b74c56478eb84e1c1732a2242d83c6b1a935eecec4c48e56a10b0977f723456331f6b2ff5efb757831a3aa53f7d4481d005072440201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff270310cf04062f503253482f0430a3aa530858000000070000000d2f6e6f64655374726174756d2f000000000280010b27010000001976a914329035234168b8da5af106ceb20560401236849888ac80f0fa02000000001976a9147d576fbfca48b899dc750167dd2a2a6572fff49588ac00000000010000000332a82e92f522deee69b09e27858ba9b87585f2a4913ef71018df40909032fdc3000000006a473044022019ca05cb880a04f0d842268b7e75ac6d2695fc544df033e3daeb29239251a8970220031f6336767f2ea617347484e1290ec0bdcc71056ea2d3084e75384905250ec50121030dd394118fb66ca288bff71d8ea762678783b005770f7f9ba4128233191e0847ffffffff086747cbd339b21b950774186091653a7b8f5751b00a906ff6f5561b3a6fcee6010000006b4830450221009ae1ba9a216d313cc592fc2c1ef08f1e0e555a32b6c1b305f685ac882d38356b0220243106bbb5bb76dde142e574cba8f30c1e2f7059e8e9161770396fbd2b50420f0121030dd394118fb66ca288bff71d8ea762678783b005770f7f9ba4128233191e0847ffffffffe2f15804b1e41c36c925c6f64f219b2bdb3c9fbff4c97a4f0e8c7f31d7e6f2af000000006b48304502200be8894fdd7f5c19be248a979c08bbf2395f606e038c3e02c0266474c03699ab022100ff5de87086e487410f5d7b68012655ca6d814f0caeb9ca42d9c425a90f68b3030121030dd394118fb66ca288bff71d8ea762678783b005770f7f9ba4128233191e0847ffffffff02a0f01900000000001976a9141c50209a1dfdf53313d237b75e9aeb553ca1dfda88ac00e1f505000000001976a914cbb9a3e7a7c1651b1006f876f08b40be85b274f588ac00000000"); } /// @@ -298,11 +298,11 @@ public void SerializeStringTest() { // < 253 test var serialized = Serializers.SerializeString("https://github.com/CoiniumServ/CoiniumServ"); - serialized.ToHexString().Should().Equal("2a68747470733a2f2f6769746875622e636f6d2f436f696e69756d536572762f436f696e69756d53657276"); + serialized.ToHexString().Should().Be("2a68747470733a2f2f6769746875622e636f6d2f436f696e69756d536572762f436f696e69756d53657276"); // >= 253 & <65536 (0x10000) test serialized = Serializers.SerializeString(@"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."); - serialized.ToHexString().Should().Equal("fd3e024c6f72656d20497073756d2069732073696d706c792064756d6d792074657874206f6620746865207072696e74696e6720616e64207479706573657474696e6720696e6475737472792e204c6f72656d20497073756d20686173206265656e2074686520696e6475737472792773207374616e646172642064756d6d79207465787420657665722073696e6365207468652031353030732c207768656e20616e20756e6b6e6f776e207072696e74657220746f6f6b20612067616c6c6579206f66207479706520616e6420736372616d626c656420697420746f206d616b65206120747970652073706563696d656e20626f6f6b2e20497420686173207375727669766564206e6f74206f6e6c7920666976652063656e7475726965732c2062757420616c736f20746865206c65617020696e746f20656c656374726f6e6963207479706573657474696e672c2072656d61696e696e6720657373656e7469616c6c7920756e6368616e6765642e2049742077617320706f70756c61726973656420696e207468652031393630732077697468207468652072656c65617365206f66204c657472617365742073686565747320636f6e7461696e696e67204c6f72656d20497073756d2070617373616765732c20616e64206d6f726520726563656e746c792077697468206465736b746f70207075626c697368696e6720736f667477617265206c696b6520416c64757320506167654d616b657220696e636c7564696e672076657273696f6e73206f66204c6f72656d20497073756d2e"); + serialized.ToHexString().Should().Be("fd3e024c6f72656d20497073756d2069732073696d706c792064756d6d792074657874206f6620746865207072696e74696e6720616e64207479706573657474696e6720696e6475737472792e204c6f72656d20497073756d20686173206265656e2074686520696e6475737472792773207374616e646172642064756d6d79207465787420657665722073696e6365207468652031353030732c207768656e20616e20756e6b6e6f776e207072696e74657220746f6f6b20612067616c6c6579206f66207479706520616e6420736372616d626c656420697420746f206d616b65206120747970652073706563696d656e20626f6f6b2e20497420686173207375727669766564206e6f74206f6e6c7920666976652063656e7475726965732c2062757420616c736f20746865206c65617020696e746f20656c656374726f6e6963207479706573657474696e672c2072656d61696e696e6720657373656e7469616c6c7920756e6368616e6765642e2049742077617320706f70756c61726973656420696e207468652031393630732077697468207468652072656c65617365206f66204c657472617365742073686565747320636f6e7461696e696e67204c6f72656d20497073756d2070617373616765732c20616e64206d6f726520726563656e746c792077697468206465736b746f70207075626c697368696e6720736f667477617265206c696b6520416c64757320506167654d616b657220696e636c7564696e672076657273696f6e73206f66204c6f72656d20497073756d2e"); } } } diff --git a/src/Tests/Coin/Coinbase/UtilsTests.cs b/src/Tests/Coin/Coinbase/UtilsTests.cs index 733182037..eecd83629 100644 --- a/src/Tests/Coin/Coinbase/UtilsTests.cs +++ b/src/Tests/Coin/Coinbase/UtilsTests.cs @@ -28,7 +28,7 @@ #endregion using CoiniumServ.Utils.Extensions; -using Should.Fluent; +using FluentAssertions; using Xunit; namespace CoiniumServ.Tests.Coin.Coinbase @@ -45,7 +45,7 @@ public void WalletAddressToScriotTest_WithValidInput_ShouldSuccess() const string expected = "76a914238fdcf8c710c698a1f2c32d378da10fcab1082888ac"; var result = CoiniumServ.Coin.Coinbase.Utils.CoinAddressToScript(input); - result.ToHexString().Should().Equal(expected); + result.ToHexString().Should().Be(expected); } /// @@ -72,7 +72,7 @@ public void PubKeyToScriptToScriptTest_WithValidInput_ShouldSuccess() const string expected = "2103679839c140a5d48b19f8d3b7c799d7534c5716d7131c5d36ec26422ba52bd378ac"; var result = CoiniumServ.Coin.Coinbase.Utils.PubKeyToScript(input); - result.ToHexString().Should().Equal(expected); + result.ToHexString().Should().Be(expected); } /// diff --git a/src/Tests/Cryptology/Merkle/MerkleTreeTests.cs b/src/Tests/Cryptology/Merkle/MerkleTreeTests.cs index f6d1ad0d1..74313093d 100644 --- a/src/Tests/Cryptology/Merkle/MerkleTreeTests.cs +++ b/src/Tests/Cryptology/Merkle/MerkleTreeTests.cs @@ -34,7 +34,7 @@ using CoiniumServ.Transactions.Utils; using CoiniumServ.Utils.Extensions; using Newtonsoft.Json; -using Should.Fluent; +using FluentAssertions; using Xunit; namespace CoiniumServ.Tests.Cryptology.Merkle @@ -64,16 +64,16 @@ public void TestWithZeroTransaction() var tree = new MerkleTree(hashList); // steps counts should be zero - tree.Steps.Count.Should().Equal(0); - tree.Branches.Count.Should().Equal(0); + tree.Steps.Count.Should().Be(0); + tree.Branches.Count.Should().Be(0); // calculate the result var result = tree.WithFirst("a3291f854e60860ec74caf232ed34f98d0ff447dd7d38dbd7d451462b4b6f263".HexToByteArray()); var root = result.ReverseBuffer(); // check the result and root - result.ToHexString().Should().Equal("a3291f854e60860ec74caf232ed34f98d0ff447dd7d38dbd7d451462b4b6f263"); - root.ToHexString().Should().Equal("63f2b6b46214457dbd8dd3d77d44ffd0984fd32e23af4cc70e86604e851f29a3"); + result.ToHexString().Should().Be("a3291f854e60860ec74caf232ed34f98d0ff447dd7d38dbd7d451462b4b6f263"); + root.ToHexString().Should().Be("63f2b6b46214457dbd8dd3d77d44ffd0984fd32e23af4cc70e86604e851f29a3"); } [Fact] @@ -99,13 +99,13 @@ public void TestWithSingleTransaction() var tree = new MerkleTree(hashList); // tests steps - tree.Steps.Count.Should().Equal(1); - tree.Branches.Count.Should().Equal(1); - tree.Steps.First().ToHexString().Should().Equal("35f25037aed5a2342dccb9fb5d5659cfe16c02d5c4e269562c24514e1a5db6a0"); + tree.Steps.Count.Should().Be(1); + tree.Branches.Count.Should().Be(1); + tree.Steps.First().ToHexString().Should().Be("35f25037aed5a2342dccb9fb5d5659cfe16c02d5c4e269562c24514e1a5db6a0"); // check root var root = tree.WithFirst("357deb5f66416ac7bd10d21557f50d358d85581c4c2e725dc1113cd277869a1a".HexToByteArray()).ReverseBuffer(); - root.ToHexString().Should().Equal("29b144ae2dfb6619502d541bbfd80ac9d800d8b44cf76e04459c7be4eb7c30da"); + root.ToHexString().Should().Be("29b144ae2dfb6619502d541bbfd80ac9d800d8b44cf76e04459c7be4eb7c30da"); } } } diff --git a/src/Tests/Daemon/BlockTemplateTests.cs b/src/Tests/Daemon/BlockTemplateTests.cs index 741b3495c..eacca0b3c 100644 --- a/src/Tests/Daemon/BlockTemplateTests.cs +++ b/src/Tests/Daemon/BlockTemplateTests.cs @@ -31,7 +31,7 @@ using CoiniumServ.Daemon; using CoiniumServ.Daemon.Responses; using Newtonsoft.Json; -using Should.Fluent; +using FluentAssertions; using Xunit; /* sample data - https://github.com/CoiniumServ/CoiniumServ/wiki/Litecoin-Testnet-Stream @@ -144,29 +144,29 @@ public void TestBlockTemplate() var blockTemplate = @object.Result; // test the values. - blockTemplate.Version.Should().Equal(_expected.Version); - blockTemplate.PreviousBlockHash.Should().Equal(_expected.PreviousBlockHash); + blockTemplate.Version.Should().Be(_expected.Version); + blockTemplate.PreviousBlockHash.Should().Be(_expected.PreviousBlockHash); for(int i=0;i - - - - - + + - Debug - AnyCPU - {ED50E979-2514-4C10-9E68-E35574B9A9AB} + netcoreapp2.0 + 2.0.5 + false Library - Properties - CoiniumServ.Tests - CoiniumServ.Tests - v4.7 - 512 - - - + Debug;Release;CI - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 + + + latest - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 + + + latest + + + latest + + - - ..\..\packages\AustinHarris.JsonRpc.1.1.70\lib\net40\AustinHarris.JsonRpc.dll - - - ..\..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll - - - ..\..\packages\ExposedObject.1.3.0\lib\net461\ExposedObject.dll - - - ..\..\packages\Nancy.1.4.4\lib\net40\Nancy.dll - - - ..\..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll - - - ..\..\packages\NSubstitute.1.7.2.0\lib\NET45\NSubstitute.dll - - - ..\..\packages\ShouldFluent.1.1.19\lib\Should.Fluent.dll - - - - - - - - - - - ..\..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll - - - ..\..\packages\xunit.assert.2.3.1\lib\netstandard1.1\xunit.assert.dll - - - ..\..\packages\xunit.extensibility.core.2.3.1\lib\netstandard1.1\xunit.core.dll - - - ..\..\packages\xunit.extensibility.execution.2.3.1\lib\net452\xunit.execution.desktop.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - {17a4e177-a910-40f8-899d-79a7f628699e} - CoiniumServ - + - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - \ No newline at end of file + + diff --git a/src/Tests/Transactions/GenerationTransactionTests.cs b/src/Tests/Transactions/GenerationTransactionTests.cs index 836529d9a..61414a59c 100644 --- a/src/Tests/Transactions/GenerationTransactionTests.cs +++ b/src/Tests/Transactions/GenerationTransactionTests.cs @@ -39,9 +39,9 @@ using CoiniumServ.Transactions; using CoiniumServ.Transactions.Script; using CoiniumServ.Utils.Extensions; +using FluentAssertions; using Newtonsoft.Json; using NSubstitute; -using Should.Fluent; using Xunit; /* sample data @@ -164,48 +164,48 @@ public void CreateGenerationTransactionTest() generationTransaction.Create(); // test version. - generationTransaction.Version.Should().Equal((UInt32)2); - generationTransaction.Initial.Take(4).ToHexString().Should().Equal("02000000"); + generationTransaction.Version.Should().Be((UInt32)2); + generationTransaction.Initial.Take(4).ToHexString().Should().Be("02000000"); // test inputs count. - generationTransaction.InputsCount.Should().Equal((UInt32)1); + generationTransaction.InputsCount.Should().Be((UInt32)1); generationTransaction.Initial.Skip(4).Take(1).Should().Equal(new byte[] { 0x01 }); // test the input previous-output hash - generationTransaction.Initial.Skip(5).Take(32).ToHexString().Should().Equal("0000000000000000000000000000000000000000000000000000000000000000"); + generationTransaction.Initial.Skip(5).Take(32).ToHexString().Should().Be("0000000000000000000000000000000000000000000000000000000000000000"); // test the input previous-output index - generationTransaction.Inputs.First().PreviousOutput.Index.Should().Equal(0xffffffff); - generationTransaction.Initial.Skip(37).Take(4).ToHexString().Should().Equal("ffffffff"); + generationTransaction.Inputs.First().PreviousOutput.Index.Should().Be(0xffffffff); + generationTransaction.Initial.Skip(37).Take(4).ToHexString().Should().Be("ffffffff"); // test the lenghts byte - generationTransaction.Inputs.First().SignatureScript.Initial.Length.Should().Equal(17); - _extraNonce.ExtraNoncePlaceholder.Length.Should().Equal(8); - generationTransaction.Inputs.First().SignatureScript.Final.Length.Should().Equal(14); - generationTransaction.Initial.Skip(41).Take(1).ToHexString().Should().Equal("27"); + generationTransaction.Inputs.First().SignatureScript.Initial.Length.Should().Be(17); + _extraNonce.ExtraNoncePlaceholder.Length.Should().Be(8); + generationTransaction.Inputs.First().SignatureScript.Final.Length.Should().Be(14); + generationTransaction.Initial.Skip(41).Take(1).ToHexString().Should().Be("27"); // test the signature script initial - generationTransaction.Initial.Skip(42).Take(17).ToHexString().Should().Equal("03be9d04062f503253482f04c3e89a5308"); + generationTransaction.Initial.Skip(42).Take(17).ToHexString().Should().Be("03be9d04062f503253482f04c3e89a5308"); // test the signature script final - generationTransaction.Final.Take(14).ToHexString().Should().Equal("0d2f6e6f64655374726174756d2f"); + generationTransaction.Final.Take(14).ToHexString().Should().Be("0d2f6e6f64655374726174756d2f"); // test the inputs sequence - generationTransaction.Inputs.First().Sequence.Should().Equal((UInt32)0x00); - generationTransaction.Final.Skip(14).Take(4).ToHexString().Should().Equal("00000000"); + generationTransaction.Inputs.First().Sequence.Should().Be((UInt32)0x00); + generationTransaction.Final.Skip(14).Take(4).ToHexString().Should().Be("00000000"); // test the outputs buffer - generationTransaction.Final.Skip(18).Take(69).ToHexString().Should().Equal("0280010b27010000001976a914329035234168b8da5af106ceb20560401236849888ac80f0fa02000000001976a9147d576fbfca48b899dc750167dd2a2a6572fff49588ac"); + generationTransaction.Final.Skip(18).Take(69).ToHexString().Should().Be("0280010b27010000001976a914329035234168b8da5af106ceb20560401236849888ac80f0fa02000000001976a9147d576fbfca48b899dc750167dd2a2a6572fff49588ac"); // test the lock time - generationTransaction.LockTime.Should().Equal((UInt32)0x00); - generationTransaction.Final.Skip(87).Take(4).ToHexString().Should().Equal("00000000"); + generationTransaction.LockTime.Should().Be((UInt32)0x00); + generationTransaction.Final.Skip(87).Take(4).ToHexString().Should().Be("00000000"); // test the generation transaction initial part. - generationTransaction.Initial.ToHexString().Should().Equal("02000000010000000000000000000000000000000000000000000000000000000000000000ffffffff2703be9d04062f503253482f04c3e89a5308"); + generationTransaction.Initial.ToHexString().Should().Be("02000000010000000000000000000000000000000000000000000000000000000000000000ffffffff2703be9d04062f503253482f04c3e89a5308"); // test the generation transaction final part. - generationTransaction.Final.ToHexString().Should().Equal("0d2f6e6f64655374726174756d2f000000000280010b27010000001976a914329035234168b8da5af106ceb20560401236849888ac80f0fa02000000001976a9147d576fbfca48b899dc750167dd2a2a6572fff49588ac00000000"); + generationTransaction.Final.ToHexString().Should().Be("0d2f6e6f64655374726174756d2f000000000280010b27010000001976a914329035234168b8da5af106ceb20560401236849888ac80f0fa02000000001976a9147d576fbfca48b899dc750167dd2a2a6572fff49588ac00000000"); } } } diff --git a/src/Tests/Transactions/OutputsTests.cs b/src/Tests/Transactions/OutputsTests.cs index 2776090e1..5a9884565 100644 --- a/src/Tests/Transactions/OutputsTests.cs +++ b/src/Tests/Transactions/OutputsTests.cs @@ -34,8 +34,8 @@ using CoiniumServ.Daemon.Responses; using CoiniumServ.Transactions; using CoiniumServ.Utils.Extensions; +using FluentAssertions; using NSubstitute; -using Should.Fluent; using Xunit; /* @@ -87,17 +87,17 @@ public void TestOutputs() outputs.AddPoolWallet(poolWallet, blockReward); // test the recipient rewards - outputs.List.Last().Value.Should().Equal((UInt64)0x0000000002faf080); // packInt64LE: 80f0fa0200000000 + outputs.List.Last().Value.Should().Be((UInt64)0x0000000002faf080); // packInt64LE: 80f0fa0200000000 outputs.List.Last().PublicKeyScriptLenght.Should().Equal(new byte[] { 0x19 }); - outputs.List.Last().PublicKeyScript.ToHexString().Should().Equal("76a9147d576fbfca48b899dc750167dd2a2a6572fff49588ac"); + outputs.List.Last().PublicKeyScript.ToHexString().Should().Be("76a9147d576fbfca48b899dc750167dd2a2a6572fff49588ac"); // test the pool wallet - outputs.List.First().Value.Should().Equal((UInt64)0x00000001270b0180); // packInt64LE: 80010b2701000000 + outputs.List.First().Value.Should().Be((UInt64)0x00000001270b0180); // packInt64LE: 80010b2701000000 outputs.List.First().PublicKeyScriptLenght.Should().Equal(new byte[] { 0x19 }); - outputs.List.First().PublicKeyScript.ToHexString().Should().Equal("76a914329035234168b8da5af106ceb20560401236849888ac"); + outputs.List.First().PublicKeyScript.ToHexString().Should().Be("76a914329035234168b8da5af106ceb20560401236849888ac"); // test the outputs buffer. - outputs.GetBuffer().ToHexString().Should().Equal("0280010b27010000001976a914329035234168b8da5af106ceb20560401236849888ac80f0fa02000000001976a9147d576fbfca48b899dc750167dd2a2a6572fff49588ac"); + outputs.GetBuffer().ToHexString().Should().Be("0280010b27010000001976a914329035234168b8da5af106ceb20560401236849888ac80f0fa02000000001976a9147d576fbfca48b899dc750167dd2a2a6572fff49588ac"); } } } diff --git a/src/Tests/Transactions/Script/SignatureScriptTests.cs b/src/Tests/Transactions/Script/SignatureScriptTests.cs index b624f8414..27f0c849e 100644 --- a/src/Tests/Transactions/Script/SignatureScriptTests.cs +++ b/src/Tests/Transactions/Script/SignatureScriptTests.cs @@ -32,8 +32,8 @@ using CoiniumServ.Jobs; using CoiniumServ.Transactions.Script; using CoiniumServ.Utils.Extensions; +using FluentAssertions; using Newtonsoft.Json; -using Should.Fluent; using Xunit; /* sample data @@ -77,8 +77,8 @@ public void SignatureScriptTest() "/nodeStratum/"); // test the objects. - signatureScript.Initial.ToHexString().Should().Equal("03547f04062f503253482f04afe0945308"); - signatureScript.Final.ToHexString().Should().Equal("0d2f6e6f64655374726174756d2f"); + signatureScript.Initial.ToHexString().Should().Be("03547f04062f503253482f04afe0945308"); + signatureScript.Final.ToHexString().Should().Be("0d2f6e6f64655374726174756d2f"); } } } diff --git a/src/Tests/Transactions/Utils/TransactionUtilsTests.cs b/src/Tests/Transactions/Utils/TransactionUtilsTests.cs index fc1dfb67c..ce8c80547 100644 --- a/src/Tests/Transactions/Utils/TransactionUtilsTests.cs +++ b/src/Tests/Transactions/Utils/TransactionUtilsTests.cs @@ -30,7 +30,7 @@ using System; using CoiniumServ.Transactions.Utils; using CoiniumServ.Utils.Extensions; -using Should.Fluent; +using FluentAssertions; using Xunit; namespace CoiniumServ.Tests.Transactions.Utils @@ -46,10 +46,10 @@ public class TransactionUtilsTests [Fact] public void SerializedUnixDateTimeTest() { - FinalUnixDateTime.Should().Equal((Int64)1402265775); + FinalUnixDateTime.Should().Be((Int64)1402265775); var serializedUnixTime = TransactionUtils.GetSerializedUnixDateTime(UnixDateTime); - serializedUnixTime.ToHexString().Should().Equal("04afe09453"); + serializedUnixTime.ToHexString().Should().Be("04afe09453"); } } } diff --git a/src/Tests/Utils/Extensions/ArrayExtensionsTests.cs b/src/Tests/Utils/Extensions/ArrayExtensionsTests.cs index 53d54b535..fb740611a 100644 --- a/src/Tests/Utils/Extensions/ArrayExtensionsTests.cs +++ b/src/Tests/Utils/Extensions/ArrayExtensionsTests.cs @@ -29,7 +29,7 @@ using System.Linq; using CoiniumServ.Utils.Extensions; -using Should.Fluent; +using FluentAssertions; using Xunit; namespace CoiniumServ.Tests.Utils.Extensions @@ -46,7 +46,7 @@ public void ToHexStringTest() }; var output = input.ToHexString(); - output.Should().Equal("71f6391e10600e54d83bd8c0265303cccaafe375bcc3b0117296ebd144e3f95a"); + output.Should().Be("71f6391e10600e54d83bd8c0265303cccaafe375bcc3b0117296ebd144e3f95a"); } [Fact] @@ -59,7 +59,7 @@ public void ToHexStringFromEnumareableTest() }.Take(32); var output = input.ToHexString(); - output.Should().Equal("71f6391e10600e54d83bd8c0265303cccaafe375bcc3b0117296ebd144e3f95a"); + output.Should().Be("71f6391e10600e54d83bd8c0265303cccaafe375bcc3b0117296ebd144e3f95a"); } [Fact] @@ -74,7 +74,7 @@ public void ReverseByteOrderTest() var input = "2fb6f87a2eaa2f5ca970ef355d66d394ab907fb1ebe3b7688e5979e7a4d2120a".HexToByteArray(); var output = input.ReverseByteOrder().ToHexString(); - output.Should().Equal("a4d2120a8e5979e7ebe3b768ab907fb15d66d394a970ef352eaa2f5c2fb6f87a"); + output.Should().Be("a4d2120a8e5979e7ebe3b768ab907fb15d66d394a970ef352eaa2f5c2fb6f87a"); } [Fact] @@ -88,7 +88,7 @@ public void ReverseBufferTest() var input = "5af9e344d1eb967211b0c3bc75e3afcacc035326c0d83bd8540e60101e39f671".HexToByteArray(); var output = input.ReverseBuffer().ToHexString(); - output.Should().Equal("71f6391e10600e54d83bd8c0265303cccaafe375bcc3b0117296ebd144e3f95a"); + output.Should().Be("71f6391e10600e54d83bd8c0265303cccaafe375bcc3b0117296ebd144e3f95a"); } } } diff --git a/src/Tests/Utils/Extensions/StringExtensionsTests.cs b/src/Tests/Utils/Extensions/StringExtensionsTests.cs index 036697fa3..1e599dcc2 100644 --- a/src/Tests/Utils/Extensions/StringExtensionsTests.cs +++ b/src/Tests/Utils/Extensions/StringExtensionsTests.cs @@ -28,7 +28,7 @@ #endregion using CoiniumServ.Utils.Extensions; -using Should.Fluent; +using FluentAssertions; using Xunit; namespace CoiniumServ.Tests.Utils.Extensions diff --git a/src/Tests/app.config b/src/Tests/app.config deleted file mode 100644 index dd8f9da36..000000000 --- a/src/Tests/app.config +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Tests/packages.config b/src/Tests/packages.config deleted file mode 100644 index babb6efae..000000000 --- a/src/Tests/packages.config +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file