mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
Compare commits
113 Commits
feature/te
...
1.0.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71e57df1d1 | ||
|
|
c498a5ab4c | ||
|
|
feee784469 | ||
|
|
aad8f0ee15 | ||
|
|
3d815d8a13 | ||
|
|
a3bbf4ef49 | ||
|
|
9187d5f4ae | ||
|
|
64692415f2 | ||
|
|
61e704c297 | ||
|
|
a791145693 | ||
|
|
8c6219f460 | ||
|
|
40ec14dd2a | ||
|
|
46cc5609a3 | ||
|
|
00e977a74c | ||
|
|
3bb87f54e1 | ||
|
|
1a9c51795e | ||
|
|
ce74a0e223 | ||
|
|
28c5214273 | ||
|
|
b7c3fc796f | ||
|
|
4fb9768edf | ||
|
|
0fd0956f02 | ||
|
|
4626b85129 | ||
|
|
2992e41d09 | ||
|
|
fb9f45f6cc | ||
|
|
4e351c4d0b | ||
|
|
c852a88084 | ||
|
|
7e071beba4 | ||
|
|
25f1047922 | ||
|
|
34155919a6 | ||
|
|
ca94b09e91 | ||
|
|
ceed3c27d8 | ||
|
|
65e23d5859 | ||
|
|
e245dd5ce1 | ||
|
|
14b13c026a | ||
|
|
0169fa68ee | ||
|
|
cf9c6040d3 | ||
|
|
88e39407ef | ||
|
|
3ef5499d94 | ||
|
|
81503f4363 | ||
|
|
f194614296 | ||
|
|
76af70e21d | ||
|
|
a70b51eee0 | ||
|
|
d3249afaca | ||
|
|
ee2e8c7a6d | ||
|
|
f9cf0b7fef | ||
|
|
21cf463c3b | ||
|
|
838fb79411 | ||
|
|
997a9cda0c | ||
|
|
94d87ff0eb | ||
|
|
be01a7dac4 | ||
|
|
0c758b5492 | ||
|
|
c5dcf58022 | ||
|
|
5facde1aee | ||
|
|
7e07f2771f | ||
|
|
8bab0d66ef | ||
|
|
5d28589afe | ||
|
|
5e4518119f | ||
|
|
3c13172dea | ||
|
|
efb70627fb | ||
|
|
b88fc651f8 | ||
|
|
7b7b640e8d | ||
|
|
9f5db40605 | ||
|
|
8baf0ca550 | ||
|
|
016cdc4489 | ||
|
|
e4e0f657f6 | ||
|
|
b301e04fe5 | ||
|
|
a3294affd2 | ||
|
|
0832e344d7 | ||
|
|
50db6acf45 | ||
|
|
3df91b51de | ||
|
|
d5ac015c12 | ||
|
|
07b11ecaab | ||
|
|
9154ecdf67 | ||
|
|
d621232812 | ||
|
|
e7209d308b | ||
|
|
e510b179f5 | ||
|
|
134b5e83a0 | ||
|
|
7f6672861b | ||
|
|
f0aa1aebc8 | ||
|
|
849a41df6c | ||
|
|
4462746c43 | ||
|
|
1ebc5a6f78 | ||
|
|
5221c01ae3 | ||
|
|
88e7378165 | ||
|
|
80744b1633 | ||
|
|
56315b92d1 | ||
|
|
bf9651e332 | ||
|
|
d721a0189b | ||
|
|
75e5a5ee1c | ||
|
|
bc27d3d673 | ||
|
|
94c1e6b7b9 | ||
|
|
0d23e58f03 | ||
|
|
a5196b4940 | ||
|
|
e209571315 | ||
|
|
8a180b8b8f | ||
|
|
3cc5c3b4c3 | ||
|
|
acbf738327 | ||
|
|
50e4e5635f | ||
|
|
c648e5b2ae | ||
|
|
35f941cf4e | ||
|
|
d63703903c | ||
|
|
ea68f07d81 | ||
|
|
042d87c309 | ||
|
|
55790a606f | ||
|
|
e942437481 | ||
|
|
7d95f1184d | ||
|
|
32cd707bd0 | ||
|
|
abdb83a9c3 | ||
|
|
82daedee80 | ||
|
|
add2e1c3b9 | ||
|
|
6ee3b0d2eb | ||
|
|
b1fb3900d9 | ||
|
|
cef0022df3 |
17
.gitignore
vendored
17
.gitignore
vendored
@@ -96,7 +96,6 @@ publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.Publish.xml
|
||||
*.pubxml
|
||||
|
||||
# NuGet Packages Directory
|
||||
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
|
||||
@@ -165,7 +164,7 @@ build/
|
||||
/buildtasks
|
||||
/artifacts
|
||||
*.sln.cache
|
||||
src/Orchard.Web/Media/*
|
||||
#src/Orchard.Web/Media/*
|
||||
log.xml
|
||||
profiling/
|
||||
*.orig
|
||||
@@ -183,10 +182,14 @@ src/Orchard.Web/Orchard.Web.Publish.xml
|
||||
src/TestResults/*
|
||||
src/Orchard.Web/Properties/PublishProfiles
|
||||
src/Orchard.Azure/Orchard.Azure.CloudService/Staging/
|
||||
src/Orchard.Web/Modules/Orchard.Azure.MediaServices/node_modules
|
||||
src/Orchard.Web/Modules/Orchard.Layouts/node_modules
|
||||
src/Orchard.Web/Modules/Orchard.DynamicForms/node_modules
|
||||
node_modules/
|
||||
|
||||
#enable all /lib artifacts
|
||||
# Enable all /lib artifacts
|
||||
!lib/*/*.*
|
||||
*/.vs/*
|
||||
|
||||
# Enable version control of some IDeliverable specifics.
|
||||
src/Orchard.Web/Media/Default/RecipeJournal/*
|
||||
src/Orchard.Web/Media/Default/_Profiles/*
|
||||
|
||||
# Enable "IDeliverable/Packaging/" folder.
|
||||
!src/IDeliverable/Packaging/*/*.*
|
||||
@@ -1,8 +1,4 @@
|
||||
FOR %%b in (
|
||||
"%VS140COMNTOOLS%..\..\VC\vcvarsall.bat"
|
||||
"%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"
|
||||
"%ProgramFiles%\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"
|
||||
|
||||
FOR %%b in (
|
||||
"%VS120COMNTOOLS%..\..\VC\vcvarsall.bat"
|
||||
"%ProgramFiles(x86)%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"
|
||||
"%ProgramFiles%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
# Orchard
|
||||
|
||||
Orchard is a free, open source, community-focused Content Management System built on the ASP.NET MVC platform.
|
||||
|
||||
[](https://gitter.im/OrchardCMS/Orchard?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
## About The Orchard Project
|
||||
|
||||
#### Please visit our website at http://orchardproject.net for the most current information about this project.
|
||||
@@ -19,8 +16,8 @@ Our mission is to empower our users and foster a dedicated and diverse community
|
||||
There are many ways you can [contribute to Orchard](http://orchardproject.net/contribution): you can [fix bugs](https://github.com/OrchardCMS/Orchard/issues), contribute modules and themes to [our gallery](http://gallery.orchardproject.net/), [write documentation](https://github.com/OrchardCMS/OrchardDoc), [translate Orchard](http://orchardproject.net/localize), or answer questions [on our forums](http://orchard.codeplex.com/discussions) and [on Stack Overflow](http://stackoverflow.com/questions/tagged/orchardcms).
|
||||
|
||||
## Project Status
|
||||
Orchard is currently in version 1.9. We invite participation by the developer community in shaping the project’s direction, so that we can publicly validate our designs and development approach.
|
||||
Our 1.9 release is available from [our Downloads page](https://github.com/OrchardCMS/Orchard/releases), and is easy to [Install Orchard using the Web Platform Installer](http://www.orchardproject.net/docs/Installing-Orchard.ashx). We encourage interested developers to check out the source code on the Orchard Github site and get involved with the project.
|
||||
Orchard is currently in version 1.8.1. We invite participation by the developer community in shaping the project’s direction, so that we can publicly validate our designs and development approach.
|
||||
Our 1.8.1 release is available from our Downloads page, and is easy to [Install Orchard using the Web Platform Installer](http://www.orchardproject.net/docs/Installing-Orchard.ashx). We encourage interested developers to check out the source code on the Orchard Github site and get involved with the project.
|
||||
|
||||
* [Download the latest release](https://github.com/OrchardCMS/Orchard/releases)
|
||||
* [Feature roadmap](http://www.orchardproject.net/docs/feature-roadmap.ashx)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,7 +0,0 @@
|
||||
Copyright (c) 2002-2013, The Npgsql Development Team
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement is hereby granted, provided that the above copyright notice and this paragraph and the following two paragraphs appear in all copies.
|
||||
|
||||
IN NO EVENT SHALL THE NPGSQL DEVELOPMENT TEAM BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE NPGSQL DEVELOPMENT TEAM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
THE NPGSQL DEVELOPMENT TEAM SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@@ -1,52 +0,0 @@
|
||||
Npgsql - .NET Data Provider for PostgreSQL
|
||||
=============
|
||||
|
||||
###What Is Npgsql?
|
||||
|
||||
Npgsql is a .Net Data Provider for PostgreSQL. It allows you to connect and interact with PostgreSQL server using .NET.
|
||||
|
||||
|
||||
###Project Information
|
||||
|
||||
+ [Offical Site][1]
|
||||
+ [Npgsql source code @ GitHub][2]
|
||||
+ [Available on NuGet Gallery][3]
|
||||
+ [Wiki - Usage and other information][4]
|
||||
|
||||
|
||||
###Developers
|
||||
|
||||
Developers who contributes to Npgsql currently or in past, in no particular order:
|
||||
|
||||
+ Brar Piening
|
||||
+ Francisco Figueiredo Jr.
|
||||
+ Ben Clewett
|
||||
+ Daniel Morgan
|
||||
+ Dave Page
|
||||
+ Ulrich Sprick
|
||||
+ Glen Parker
|
||||
+ Josh Cooley
|
||||
+ Jon Asher
|
||||
+ Chris Morgan
|
||||
+ Thilo Utke
|
||||
+ Hiroshi Saito
|
||||
+ Shay Rojansky
|
||||
|
||||
###License
|
||||
|
||||
Refer LICENSE.txt for more information on license terms.
|
||||
|
||||
###Code history
|
||||
|
||||
On December 2nd, [we committed a change][5] to restructure Npgsql code. This change modified file locations and unfortunately made the complete modification history of those files to not be available anymore through GitHub interface directly. [This stackoverflow post][6] documents a way to access the history before the rename: You just need to access the object tree **before** the rename and then you can see the rest of the file history.
|
||||
In the case of this rename, this is the tree: https://github.com/npgsql/Npgsql/tree/2f8928e4dee59275767de0df2ec41a654744a3bc
|
||||
|
||||
This will help future searches for the history of the files. Note that you stil can access the complete history of the file through command line: `git log --follow ./newflodername/file`
|
||||
|
||||
|
||||
[1]: http://www.npgsql.org/ "Official site"
|
||||
[2]: https://github.com/npgsql/Npgsql/ "Npgsql source code @ GitHub"
|
||||
[3]: http://www.nuget.org/packages/Npgsql/ "Npgsql @ Nuget Gallery"
|
||||
[4]: https://github.com/npgsql/Npgsql/wiki/ "Wiki"
|
||||
[5]: https://github.com/npgsql/Npgsql/commit/d7beea23f3407b38747cde05568a59ac87cdd121#diff-3b02da674650ba0f31603c365249f34f
|
||||
[6]: http://stackoverflow.com/questions/17213046/see-history-in-github-after-folder-rename
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,90 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{F1467A6B-2397-447B-BE90-766D192EC3D9}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>IDeliverable.Licensing.Orchard</RootNamespace>
|
||||
<AssemblyName>IDeliverable.Licensing.Orchard</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Autofac, Version=3.5.0.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\autofac\Autofac.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\..\..\lib\newtonsoft.json\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Abstractions" />
|
||||
<Reference Include="System.Web.Http, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\aspnetwebapi\System.Web.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Mvc, Version=5.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\aspnetmvc\System.Web.Mvc.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ILicensedProductManifest.cs" />
|
||||
<Compile Include="LicenseValidationControllerBase.cs" />
|
||||
<Compile Include="LicenseValidationErrorBannerBase.cs" />
|
||||
<Compile Include="LicenseValidationHelper.cs" />
|
||||
<Compile Include="LicenseVerificationTokenStore.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="LicenseSettingsPartHandlerBase.cs" />
|
||||
<Compile Include="LicenseSettingsPartBase.cs" />
|
||||
<Compile Include="LicenseSettingsPartDriverBase.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\IDeliverable.Licensing\IDeliverable.Licensing.csproj">
|
||||
<Project>{7e439cb7-1ace-435f-a8f3-5bb929423e34}</Project>
|
||||
<Name>IDeliverable.Licensing</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Orchard\Orchard.Framework.csproj">
|
||||
<Project>{2d1d92bb-4555-4cbe-8d0e-63563d6ce4c6}</Project>
|
||||
<Name>Orchard.Framework</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,15 @@
|
||||
using Orchard;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace IDeliverable.Licensing.Orchard
|
||||
{
|
||||
public interface ILicensedProductManifest : IDependency
|
||||
{
|
||||
string ProductId { get; }
|
||||
string ProductName { get; }
|
||||
string ExtensionId { get; }
|
||||
bool SkipValidationForLocalRequests { get; }
|
||||
string LicenseKey { get; }
|
||||
ILogger Logger { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Utilities;
|
||||
|
||||
namespace IDeliverable.Licensing.Orchard
|
||||
{
|
||||
public abstract class LicenseSettingsPartBase : ContentPart
|
||||
{
|
||||
public readonly LazyField<string> mProductVersionField = new LazyField<string>();
|
||||
public abstract string ProductId { get; }
|
||||
|
||||
public string LicenseKey
|
||||
{
|
||||
get { return this.Retrieve(x => x.LicenseKey); }
|
||||
set { this.Store(x => x.LicenseKey, value); }
|
||||
}
|
||||
|
||||
public string ProductVersion => mProductVersionField.Value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.Environment.Extensions;
|
||||
|
||||
namespace IDeliverable.Licensing.Orchard
|
||||
{
|
||||
public abstract class LicenseSettingsPartDriverBase<TPart> : ContentPartDriver<TPart> where TPart : LicenseSettingsPartBase, new()
|
||||
{
|
||||
protected abstract string EditorShapeName { get; }
|
||||
protected abstract string EditorShapeTemplateName { get; }
|
||||
|
||||
protected override DriverResult Editor(TPart part, dynamic shapeHelper)
|
||||
{
|
||||
return Editor(part, null, shapeHelper);
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(TPart part, IUpdateModel updater, dynamic shapeHelper)
|
||||
{
|
||||
return ContentShape(EditorShapeName, () =>
|
||||
{
|
||||
updater?.TryUpdateModel(part, Prefix, null, null);
|
||||
return shapeHelper.EditorTemplate(TemplateName: EditorShapeTemplateName, Prefix: Prefix, Model: part);
|
||||
}).OnGroup("Licenses");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace IDeliverable.Licensing.Orchard
|
||||
{
|
||||
public abstract class LicenseSettingsPartHandlerBase<TPart> : ContentHandler where TPart : LicenseSettingsPartBase, new()
|
||||
{
|
||||
protected LicenseSettingsPartHandlerBase(IEnumerable<ILicensedProductManifest> products, IExtensionManager extensionManager)
|
||||
{
|
||||
Filters.Add(new ActivatingFilter<TPart>("Site"));
|
||||
OnGetContentItemMetadata<TPart>((context, part) => context.Metadata.EditorGroupInfo.Add(new GroupInfo(T("Licenses"))));
|
||||
OnActivated<TPart>(SetupLazyFields);
|
||||
|
||||
mProducts = products;
|
||||
mExtensionManager = extensionManager;
|
||||
}
|
||||
|
||||
private readonly IEnumerable<ILicensedProductManifest> mProducts;
|
||||
private readonly IExtensionManager mExtensionManager;
|
||||
public Localizer T { get; set; } = NullLocalizer.Instance;
|
||||
|
||||
private void SetupLazyFields(ActivatedContentContext context, TPart part)
|
||||
{
|
||||
part.mProductVersionField.Loader(value =>
|
||||
{
|
||||
var productManifest = mProducts.Single(x => x.ProductId == part.ProductId);
|
||||
var extension = mExtensionManager.GetExtension(productManifest.ExtensionId);
|
||||
|
||||
return extension.Version;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System.Web.Mvc;
|
||||
using Orchard.Localization;
|
||||
using Orchard.UI.Notify;
|
||||
using Orchard.Utility.Extensions;
|
||||
|
||||
namespace IDeliverable.Licensing.Orchard
|
||||
{
|
||||
public abstract class LicenseValidationControllerBase : Controller
|
||||
{
|
||||
protected LicenseValidationControllerBase(INotifier notifier)
|
||||
{
|
||||
Notifier = notifier;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
protected INotifier Notifier { get; }
|
||||
protected abstract string ProductId { get; }
|
||||
|
||||
public ActionResult VerifyLicenseKey()
|
||||
{
|
||||
LicenseValidationHelper.Instance.ClearLicenseValidationResult(ProductId);
|
||||
|
||||
if (LicenseValidationHelper.GetLicenseIsValid(ProductId))
|
||||
Notifier.Information(T("License key succesfully validated."));
|
||||
|
||||
var urlReferrer = Request.UrlReferrer?.ToString();
|
||||
return Redirect(Request.IsLocalUrl(urlReferrer) ? urlReferrer : "~/");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using IDeliverable.Licensing.Validation;
|
||||
using Orchard;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Logging;
|
||||
using Orchard.UI.Admin.Notification;
|
||||
using Orchard.UI.Notify;
|
||||
|
||||
namespace IDeliverable.Licensing.Orchard
|
||||
{
|
||||
public abstract class LicenseValidationErrorBannerBase : Component, INotificationProvider
|
||||
{
|
||||
protected LicenseValidationErrorBannerBase(IEnumerable<ILicensedProductManifest> products, UrlHelper urlHelper, string productId)
|
||||
{
|
||||
mProducts = products;
|
||||
mUrlHelper = urlHelper;
|
||||
mProductId = productId;
|
||||
}
|
||||
|
||||
private readonly IEnumerable<ILicensedProductManifest> mProducts;
|
||||
private readonly UrlHelper mUrlHelper;
|
||||
private readonly string mProductId;
|
||||
|
||||
public IEnumerable<NotifyEntry> GetNotifications()
|
||||
{
|
||||
var productManifest = mProducts.Single(x => x.ProductId == mProductId);
|
||||
var licenseSettingsUrl = mUrlHelper.Action("Index", "Admin", new { area = "Settings", groupInfoId = "Licenses" });
|
||||
var retryResultUrl = mUrlHelper.Action("VerifyLicenseKey", "LicenseValidation", new { area = productManifest.ProductName });
|
||||
var retryResultLink = T("<a href=\"{0}\">Try again</a>", retryResultUrl);
|
||||
LocalizedString message = null;
|
||||
|
||||
try
|
||||
{
|
||||
LicenseValidationHelper.EnsureLicenseIsValid(productManifest.ProductId);
|
||||
}
|
||||
catch (LicenseValidationException ex)
|
||||
{
|
||||
switch (ex.Error)
|
||||
{
|
||||
case LicenseValidationError.UnknownLicenseKey:
|
||||
message = T("The <a href=\"{0}\">configured license key</a> for the {1} module is invalid. {2}", licenseSettingsUrl, productManifest.ProductName, retryResultLink);
|
||||
break;
|
||||
case LicenseValidationError.HostnameMismatch:
|
||||
message = T("The <a href=\"{0}\">configured license key</a> for the {1} module is invalid for the current host name. {2}", licenseSettingsUrl, productManifest.ProductName, retryResultLink);
|
||||
break;
|
||||
case LicenseValidationError.NoActiveSubscription:
|
||||
message = T("The <a href=\"{0}\">configured license key</a> for the {1} module has no active subscription. {2}", licenseSettingsUrl, productManifest.ProductName, retryResultLink);
|
||||
break;
|
||||
case LicenseValidationError.LicenseRevoked:
|
||||
message = T("The <a href=\"{0}\">configured license key</a> for the {1} module has been revoked. {2}", licenseSettingsUrl, productManifest.ProductName, retryResultLink);
|
||||
break;
|
||||
case LicenseValidationError.TokenAgeValidationFailed:
|
||||
case LicenseValidationError.TokenSignatureValidationFailed:
|
||||
case LicenseValidationError.LicensingServiceError:
|
||||
case LicenseValidationError.LicensingServiceUnreachable:
|
||||
case LicenseValidationError.UnexpectedError:
|
||||
default:
|
||||
message = T("There was an error validating the <a href=\"{0}\">configured license key</a> for the {1} module. {2}", licenseSettingsUrl, productManifest.ProductName, retryResultLink);
|
||||
break;
|
||||
}
|
||||
|
||||
Logger.Warning(ex, "An error occurred while validating the configured license key for the {0} module. {1}", productManifest.ProductName, retryResultLink);
|
||||
}
|
||||
|
||||
if (message != null)
|
||||
yield return new NotifyEntry { Message = message, Type = NotifyType.Warning };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using IDeliverable.Licensing.Validation;
|
||||
using IDeliverable.Licensing.VerificationTokens;
|
||||
using Orchard;
|
||||
using Orchard.Logging;
|
||||
using Orchard.FileSystems.AppData;
|
||||
|
||||
namespace IDeliverable.Licensing.Orchard
|
||||
{
|
||||
public class LicenseValidationHelper
|
||||
{
|
||||
public static bool GetLicenseIsValid(string productId)
|
||||
{
|
||||
try
|
||||
{
|
||||
EnsureLicenseIsValid(productId);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void EnsureLicenseIsValid(string productId)
|
||||
{
|
||||
Instance.ValidateLicense(productId);
|
||||
}
|
||||
|
||||
public static LicenseValidationHelper Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
var workContext = HttpContext.Current.Request.RequestContext.GetWorkContext();
|
||||
var products = workContext.Resolve<IEnumerable<ILicensedProductManifest>>();
|
||||
var appDataFolder = workContext.Resolve<IAppDataFolder>();
|
||||
var instance = new LicenseValidationHelper(products, appDataFolder);
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly TimeSpan _validationResultCachedFor = TimeSpan.FromMinutes(5);
|
||||
|
||||
public LicenseValidationHelper(IEnumerable<ILicensedProductManifest> products, IAppDataFolder appDataFolder)
|
||||
{
|
||||
var tokenStore = new LicenseVerificationTokenStore(appDataFolder);
|
||||
var tokenAccessor = new LicenseVerificationTokenAccessor(tokenStore);
|
||||
|
||||
mProducts = products;
|
||||
mLicenseValidator = new LicenseValidator(tokenAccessor);
|
||||
mCacheService = new CacheService();
|
||||
}
|
||||
|
||||
private readonly IEnumerable<ILicensedProductManifest> mProducts;
|
||||
private readonly LicenseValidator mLicenseValidator;
|
||||
private readonly CacheService mCacheService;
|
||||
|
||||
public void ValidateLicense(string productId)
|
||||
{
|
||||
var productManifest = GetLicensedProductManifest(productId);
|
||||
productManifest.Logger.Debug("Validating license for product '{0}'...", productId);
|
||||
|
||||
try
|
||||
{
|
||||
var cacheKey = ComputeCacheKey(productManifest);
|
||||
mCacheService.GetValue(cacheKey, context =>
|
||||
{
|
||||
context.ValidFor = _validationResultCachedFor;
|
||||
|
||||
var options = LicenseValidationOptions.Default;
|
||||
if (productManifest.SkipValidationForLocalRequests)
|
||||
options = options | LicenseValidationOptions.SkipForLocalRequests;
|
||||
|
||||
productManifest.Logger.Debug("Validation result not in cache. Invoking the license validator for product '{0}'...", productId);
|
||||
mLicenseValidator.ValidateLicense(productManifest.ProductId, productManifest.LicenseKey, options);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
productManifest.Logger.Debug("License successfully validated for product '{0}'.", productId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
productManifest.Logger.Error(ex, "An error occurred while validating the license for product '{0}'.", productId);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearLicenseValidationResult(string productId)
|
||||
{
|
||||
var productManifest = GetLicensedProductManifest(productId);
|
||||
productManifest.Logger.Debug("Clearing license validation result for product '{0}'...", productId);
|
||||
|
||||
var cacheKey = ComputeCacheKey(productManifest);
|
||||
mCacheService.RemoveValue(cacheKey);
|
||||
}
|
||||
|
||||
private ILicensedProductManifest GetLicensedProductManifest(string productId)
|
||||
{
|
||||
return mProducts.Single(x => x.ProductId == productId);
|
||||
}
|
||||
|
||||
private string ComputeCacheKey(ILicensedProductManifest productManifest)
|
||||
{
|
||||
return $"ValidateLicenseResult-{productManifest.ProductId}-{productManifest.LicenseKey}-{productManifest.SkipValidationForLocalRequests}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using IDeliverable.Licensing.VerificationTokens;
|
||||
using Orchard.FileSystems.AppData;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace IDeliverable.Licensing.Orchard
|
||||
{
|
||||
internal class LicenseVerificationTokenStore : ILicenseVerificationTokenStore
|
||||
{
|
||||
public LicenseVerificationTokenStore(IAppDataFolder appDataFolder)
|
||||
{
|
||||
mAppDataFolder = appDataFolder;
|
||||
}
|
||||
|
||||
private readonly IAppDataFolder mAppDataFolder;
|
||||
|
||||
public LicenseVerificationToken Load(string productId)
|
||||
{
|
||||
var path = GetRelativeTokenFilePath(productId);
|
||||
if (!mAppDataFolder.FileExists(path))
|
||||
return null;
|
||||
|
||||
LicenseVerificationToken token = null;
|
||||
var tokenBase64 = mAppDataFolder.ReadFile(path);
|
||||
|
||||
try
|
||||
{
|
||||
token = LicenseVerificationToken.FromBase64(tokenBase64);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// An exception while parsing the token indicates somebody probably
|
||||
// tampered with it or it got corrupted. In this case, let's clear out
|
||||
// the store and return nothing.
|
||||
Clear(productId);
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
public void Save(string productId, LicenseVerificationToken token)
|
||||
{
|
||||
Clear(productId);
|
||||
|
||||
var path = GetRelativeTokenFilePath(productId);
|
||||
|
||||
var tokenBase64 = token.ToBase64();
|
||||
mAppDataFolder.CreateFile(path, tokenBase64);
|
||||
}
|
||||
|
||||
public void Clear(string productId)
|
||||
{
|
||||
var path = GetRelativeTokenFilePath(productId);
|
||||
if (mAppDataFolder.FileExists(path))
|
||||
mAppDataFolder.DeleteFile(path);
|
||||
}
|
||||
|
||||
private string GetRelativeTokenFilePath(string productId)
|
||||
{
|
||||
return $"IDeliverable.Licensing/{productId}.lic";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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("IDeliverable.Licensing.Orchard.Orchard")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("IDeliverable.Licensing.Orchard.Orchard")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[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("f1467a6b-2397-447b-be90-766d192ec3d9")]
|
||||
|
||||
// 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("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
using System.Web.Http.Filters;
|
||||
|
||||
namespace IDeliverable.Licensing.Service
|
||||
{
|
||||
internal class ApiKeyAuthorizationAttribute : AuthorizationFilterAttribute
|
||||
{
|
||||
public override void OnAuthorization(HttpActionContext actionContext)
|
||||
{
|
||||
var values = new List<string>();
|
||||
|
||||
var paramsQuery =
|
||||
from param in actionContext.Request.GetQueryNameValuePairs()
|
||||
where String.Equals(param.Key, "ApiKey", StringComparison.OrdinalIgnoreCase)
|
||||
select param.Value;
|
||||
values.AddRange(paramsQuery.ToArray());
|
||||
|
||||
IEnumerable<string> headers;
|
||||
actionContext.Request.Headers.TryGetValues("ApiKey", out headers);
|
||||
if (headers != null)
|
||||
values.AddRange(headers);
|
||||
|
||||
string apiKey = values != null ? values.FirstOrDefault() : null;
|
||||
|
||||
if (String.IsNullOrWhiteSpace(apiKey))
|
||||
actionContext.Response = actionContext.ControllerContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
|
||||
|
||||
var expectedApiKey = ConfigurationManager.AppSettings["ApiKey"];
|
||||
|
||||
if (apiKey != expectedApiKey)
|
||||
actionContext.Response = actionContext.ControllerContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Web.Http;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace IDeliverable.Licensing.Service
|
||||
{
|
||||
internal static class WebApiConfig
|
||||
{
|
||||
public static void Register(HttpConfiguration config)
|
||||
{
|
||||
ConfigSerializationSettings(config);
|
||||
|
||||
config.MapHttpAttributeRoutes();
|
||||
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
|
||||
}
|
||||
|
||||
private static void ConfigSerializationSettings(HttpConfiguration config)
|
||||
{
|
||||
var jsonSetting = new JsonSerializerSettings();
|
||||
jsonSetting.Converters.Add(new StringEnumConverter());
|
||||
config.Formatters.JsonFormatter.SerializerSettings = jsonSetting;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ApplicationInsights xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings">
|
||||
<!--
|
||||
Learn more about Application Insights configuration with ApplicationInsights.config here:
|
||||
http://go.microsoft.com/fwlink/?LinkID=513840
|
||||
-->
|
||||
<TelemetryModules>
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Implementation.Tracing.DiagnosticsTelemetryModule, Microsoft.ApplicationInsights" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCollector.PerformanceCollectorModule, Microsoft.ApplicationInsights.Extensibility.PerfCollector">
|
||||
<!--
|
||||
Use the following syntax here to collect additional performance counters:
|
||||
|
||||
<Counters>
|
||||
<Add PerformanceCounter="\Process(??APP_WIN32_PROC??)\Handle Count" ReportAs="Process handle count" />
|
||||
...
|
||||
</Counters>
|
||||
|
||||
PerformanceCounter must be either \CategoryName(InstanceName)\CounterName or \CategoryName\CounterName
|
||||
|
||||
Counter names may only contain letters, round brackets, forward slashes, hyphens, underscores, spaces and dots.
|
||||
You may provide an optional ReportAs attribute which will be used as the metric name when reporting counter data.
|
||||
For the purposes of reporting, metric names will be sanitized by removing all invalid characters from the resulting metric name.
|
||||
|
||||
The following placeholders are supported as InstanceName:
|
||||
??APP_WIN32_PROC?? - instance name of the application process for Win32 counters.
|
||||
??APP_W3SVC_PROC?? - instance name of the application IIS worker process for IIS/ASP.NET counters.
|
||||
??APP_CLR_PROC?? - instance name of the application CLR process for .NET counters.
|
||||
-->
|
||||
</Add>
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.RuntimeTelemetry.RemoteDependencyModule, Microsoft.ApplicationInsights.Extensibility.RuntimeTelemetry" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryModules.WebApplicationLifecycleModule, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryModules.WebRequestTrackingTelemetryModule, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryModules.WebExceptionTrackingTelemetryModule, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryModules.WebSessionTrackingTelemetryModule, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryModules.WebUserTrackingTelemetryModule, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
</TelemetryModules>
|
||||
<TelemetryChannel Type="Microsoft.ApplicationInsights.Channel.PersistenceChannel, Microsoft.ApplicationInsights.PersistenceChannel" />
|
||||
<ContextInitializers>
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.BuildInfoConfigComponentVersionContextInitializer, Microsoft.ApplicationInsights" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.DeviceContextInitializer, Microsoft.ApplicationInsights" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.ContextInitializers.AzureRoleEnvironmentContextInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.ContextInitializers.DomainNameRoleInstanceContextInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
</ContextInitializers>
|
||||
<TelemetryInitializers>
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryInitializers.WebSyntheticTelemetryInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryInitializers.WebClientIpHeaderTelemetryInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryInitializers.WebUserAgentTelemetryInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryInitializers.WebOperationNameTelemetryInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryInitializers.WebOperationIdTelemetryInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryInitializers.WebUserTelemetryInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryInitializers.WebSessionTelemetryInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
</TelemetryInitializers>
|
||||
</ApplicationInsights>
|
||||
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using IDeliverable.Licensing.Exceptions;
|
||||
using IDeliverable.Licensing.Service.Services;
|
||||
using IDeliverable.Licensing.VerificationTokens;
|
||||
|
||||
namespace IDeliverable.Licensing.Service.Controllers
|
||||
{
|
||||
[RoutePrefix("api/v1")]
|
||||
public class LicenseController : ApiController
|
||||
{
|
||||
[HttpGet]
|
||||
[Route("license/{licenseKey}/verify")]
|
||||
[ApiKeyAuthorization]
|
||||
public LicenseVerificationToken Verify(string licenseKey, string productId, string hostname)
|
||||
{
|
||||
var service = GetLicenseService();
|
||||
|
||||
try
|
||||
{
|
||||
return service.VerifyLicense(licenseKey, productId, hostname, throwOnError: false);
|
||||
}
|
||||
catch (LicenseVerificationException ex)
|
||||
{
|
||||
switch (ex.Error)
|
||||
{
|
||||
case LicenseVerificationError.UnknownLicenseKey:
|
||||
ThrowHttpResponseException(ex, HttpStatusCode.NotFound);
|
||||
break;
|
||||
|
||||
case LicenseVerificationError.HostnameMismatch:
|
||||
ThrowHttpResponseException(ex, HttpStatusCode.Forbidden);
|
||||
break;
|
||||
|
||||
case LicenseVerificationError.NoActiveSubscription:
|
||||
case LicenseVerificationError.LicenseRevoked:
|
||||
ThrowHttpResponseException(ex, HttpStatusCode.Gone);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("test")]
|
||||
[ApiKeyAuthorization]
|
||||
public HttpResponseMessage Test()
|
||||
{
|
||||
var testKey = ConfigurationManager.AppSettings["TestKey"];
|
||||
var testProductId = ConfigurationManager.AppSettings["TestProductId"];
|
||||
var testHostname = ConfigurationManager.AppSettings["TestHostname"];
|
||||
var service = GetLicenseService();
|
||||
|
||||
try
|
||||
{
|
||||
service.VerifyLicense(testKey, testProductId, testHostname, throwOnError: true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new HttpResponseMessage(HttpStatusCode.InternalServerError) { ReasonPhrase = $"Verification for a supposedly valid license failed: {ex.Message}." };
|
||||
}
|
||||
|
||||
return new HttpResponseMessage(HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
private static LicenseService GetLicenseService()
|
||||
{
|
||||
var sendOwlApiEndpoint = ConfigurationManager.AppSettings["SendOwlApiEndpoint"];
|
||||
var sendOwlApiKey = ConfigurationManager.AppSettings["SendOwlApiKey"];
|
||||
var sendOwlApiSecret = ConfigurationManager.AppSettings["SendOwlApiSecret"];
|
||||
var tokenSigningCertificateThumbprint = ConfigurationManager.AppSettings["TokenSigningCertificateThumbprint"];
|
||||
|
||||
return new LicenseService(sendOwlApiEndpoint, sendOwlApiKey, sendOwlApiSecret, tokenSigningCertificateThumbprint);
|
||||
}
|
||||
|
||||
private static void ThrowHttpResponseException(LicenseVerificationException ex, HttpStatusCode httpStatusCode)
|
||||
{
|
||||
var response = new HttpResponseMessage(httpStatusCode) { ReasonPhrase = ex.Message };
|
||||
response.Headers.Add("LicensingErrorCode", ex.Error.ToString());
|
||||
throw new HttpResponseException(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<%@ Application Codebehind="Global.asax.cs" Inherits="IDeliverable.Licensing.Service.WebApiApplication" Language="C#" %>
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Web.Http;
|
||||
using Microsoft.ApplicationInsights.Extensibility;
|
||||
|
||||
namespace IDeliverable.Licensing.Service
|
||||
{
|
||||
public class WebApiApplication : System.Web.HttpApplication
|
||||
{
|
||||
protected void Application_Start()
|
||||
{
|
||||
GlobalConfiguration.Configure(WebApiConfig.Register);
|
||||
|
||||
// Configure ApplicationInsights instrumentation key.
|
||||
var instrumentationKey = ConfigurationManager.AppSettings["ApplicationInsights.InstrumentationKey"];
|
||||
if (!String.IsNullOrWhiteSpace(instrumentationKey))
|
||||
TelemetryConfiguration.Active.InstrumentationKey = instrumentationKey;
|
||||
else
|
||||
TelemetryConfiguration.Active.DisableTelemetry = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>
|
||||
</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{6014E7AC-C979-4D50-B8D9-5FD9DC8CA641}</ProjectGuid>
|
||||
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>IDeliverable.Licensing.Service</RootNamespace>
|
||||
<AssemblyName>IDeliverable.Licensing.Service</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<MvcBuildViews>false</MvcBuildViews>
|
||||
<UseIISExpress>true</UseIISExpress>
|
||||
<IISExpressSSLPort />
|
||||
<IISExpressAnonymousAuthentication />
|
||||
<IISExpressWindowsAuthentication />
|
||||
<IISExpressUseClassicPipelineMode />
|
||||
<UseGlobalApplicationHostFile>true</UseGlobalApplicationHostFile>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
<ApplicationInsightsResourceId>/subscriptions/1788357e-d506-4118-9f88-092c1dcddc16/resourcegroups/Internal/providers/microsoft.insights/components/ideliverable-licensing</ApplicationInsightsResourceId>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="log4net, Version=1.2.13.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\log4net.2.0.3\lib\net40-full\log4net.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="LogentriesCore, Version=2.6.7.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\logentries.core.2.7.0\lib\net40\LogentriesCore.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="LogentriesLog4net, Version=2.6.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\logentries.log4net.2.7.0\lib\net40\LogentriesLog4net.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ApplicationInsights, Version=0.14.3.177, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.ApplicationInsights.0.14.3-build00177\lib\net40\Microsoft.ApplicationInsights.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ApplicationInsights.Extensibility.PerfCollector, Version=0.14.3.185, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.ApplicationInsights.PerformanceCollector.0.14.3-build00177\lib\net40\Microsoft.ApplicationInsights.Extensibility.PerfCollector.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ApplicationInsights.Extensibility.RuntimeTelemetry, Version=0.14.3.177, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.ApplicationInsights.RuntimeTelemetry.0.14.3-build00177\lib\net45\Microsoft.ApplicationInsights.Extensibility.RuntimeTelemetry.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ApplicationInsights.Extensibility.Web, Version=0.14.3.177, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.ApplicationInsights.Web.0.14.3-build00177\lib\net45\Microsoft.ApplicationInsights.Extensibility.Web.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ApplicationInsights.PersistenceChannel, Version=0.14.3.186, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.ApplicationInsights.PersistenceChannel.0.14.3-build00177\lib\net40\Microsoft.ApplicationInsights.PersistenceChannel.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="Microsoft.Diagnostics.Instrumentation.Extensions.Intercept, Version=0.14.0.8007, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.ApplicationInsights.Agent.Intercept.0.14.0-build08008\lib\net40\Microsoft.Diagnostics.Instrumentation.Extensions.Intercept.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Diagnostics.Tracing.EventSource, Version=1.1.16.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Diagnostics.Tracing.EventSource.Redist.1.1.16-beta\lib\net45\Microsoft.Diagnostics.Tracing.EventSource.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Threading.Tasks.Extensions, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop, Version=1.0.168.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Web.Infrastructure">
|
||||
<HintPath>..\..\..\lib\aspnetmvc\Microsoft.Web.Infrastructure.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.WindowsAzure.Configuration, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.WindowsAzure.ConfigurationManager.3.1.0\lib\net40\Microsoft.WindowsAzure.Configuration.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\..\..\lib\newtonsoft.json\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net" />
|
||||
<Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Entity" />
|
||||
<Reference Include="System.Web.ApplicationServices" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Web.Helpers">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Mvc, Version=4.0.0.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Razor">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.WebPages">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.WebPages.Deployment">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.WebPages.Razor">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Abstractions" />
|
||||
<Reference Include="System.Web.Routing" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.Net.Http">
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.WebRequest">
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<Compile Include="App_Start\WebApiConfig.cs" />
|
||||
<Compile Include="ApiKeyAuthorizationAttribute.cs" />
|
||||
<Compile Include="Controllers\LicenseController.cs" />
|
||||
<Compile Include="Global.asax.cs">
|
||||
<DependentUpon>Global.asax</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Services\LicenseInfo.cs" />
|
||||
<Compile Include="Services\LicenseService.cs" />
|
||||
<Compile Include="Services\Logger.cs" />
|
||||
<Compile Include="Services\OrderInfo.cs" />
|
||||
<Compile Include="Services\OrderStatus.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Global.asax" />
|
||||
<Content Include="packages.config" />
|
||||
<Content Include="ApplicationInsights.config" />
|
||||
<Content Include="Log4net.config" />
|
||||
<None Include="Properties\PublishProfiles\ideliverable-licensing.pubxml" />
|
||||
<Content Include="Web.config">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
<Content Include="Web.Debug.config">
|
||||
<DependentUpon>Web.config</DependentUpon>
|
||||
</Content>
|
||||
<Content Include="Web.Release.config">
|
||||
<DependentUpon>Web.config</DependentUpon>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\IDeliverable.Licensing\IDeliverable.Licensing.csproj">
|
||||
<Project>{7e439cb7-1ace-435f-a8f3-5bb929423e34}</Project>
|
||||
<Name>IDeliverable.Licensing</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
|
||||
<Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
|
||||
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
|
||||
</Target>
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>56979</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:56979/</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
</CustomServerUrl>
|
||||
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
|
||||
</WebProjectProperties>
|
||||
</FlavorProperties>
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<Import Project="..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
|
||||
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="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=317567." HelpKeyword="BCLBUILD2001" />
|
||||
<Error Condition="Exists('..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
|
||||
</Target>
|
||||
<Import Project="..\..\packages\Microsoft.Diagnostics.Tracing.EventSource.Redist.1.1.16-beta\build\portable-net45+win8+wpa81\Microsoft.Diagnostics.Tracing.EventSource.Redist.targets" Condition="Exists('..\..\packages\Microsoft.Diagnostics.Tracing.EventSource.Redist.1.1.16-beta\build\portable-net45+win8+wpa81\Microsoft.Diagnostics.Tracing.EventSource.Redist.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>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}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.Diagnostics.Tracing.EventSource.Redist.1.1.16-beta\build\portable-net45+win8+wpa81\Microsoft.Diagnostics.Tracing.EventSource.Redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Diagnostics.Tracing.EventSource.Redist.1.1.16-beta\build\portable-net45+win8+wpa81\Microsoft.Diagnostics.Tracing.EventSource.Redist.targets'))" />
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.ApplicationInsights.Agent.Intercept.0.14.0-build08008\build\Microsoft.ApplicationInsights.Agent.Intercept.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.ApplicationInsights.Agent.Intercept.0.14.0-build08008\build\Microsoft.ApplicationInsights.Agent.Intercept.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\..\packages\Microsoft.ApplicationInsights.0.14.3-build00177\tools\net40\Microsoft.ApplicationInsights.targets" Condition="Exists('..\..\packages\Microsoft.ApplicationInsights.0.14.3-build00177\tools\net40\Microsoft.ApplicationInsights.targets')" />
|
||||
<Target Name="EnsureApplicationInsightsImported" BeforeTargets="BeforeBuild" Condition="'$(ApplicationInsightsImported)' == ''">
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.ApplicationInsights.0.14.3-build00177\tools\net40\Microsoft.ApplicationInsights.targets')" Text="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=317567." />
|
||||
<Error Condition="Exists('..\..\packages\Microsoft.ApplicationInsights.0.14.3-build00177\tools\net40\Microsoft.ApplicationInsights.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." />
|
||||
</Target>
|
||||
<Import Project="..\..\packages\Microsoft.ApplicationInsights.Agent.Intercept.0.14.0-build08008\build\Microsoft.ApplicationInsights.Agent.Intercept.targets" Condition="Exists('..\..\packages\Microsoft.ApplicationInsights.Agent.Intercept.0.14.0-build08008\build\Microsoft.ApplicationInsights.Agent.Intercept.targets')" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target> -->
|
||||
</Project>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<log4net>
|
||||
|
||||
<root>
|
||||
<!-- Value of level may be ALL, DEBUG, INFO, WARN, ERROR, FATAL, OFF -->
|
||||
<level value="DEBUG" />
|
||||
<appender-ref ref="DebuggerAppender" />
|
||||
<appender-ref ref="LeAppender" />
|
||||
</root>
|
||||
|
||||
<appender name="LeAppender" type="log4net.Appender.LogentriesAppender, LogentriesLog4net">
|
||||
<!-- Credentials are read from appSettings. -->
|
||||
<immediateFlush value="true" />
|
||||
<debug value="true" />
|
||||
<useHttpPut value="false" />
|
||||
<useSsl value="false" />
|
||||
<layout type="log4net.Layout.PatternLayout">
|
||||
<!-- The below pattern has been carefully formatted and optimized to work well with the Logentries.com entry parser. For reference see https://logentries.com/doc/search/. -->
|
||||
<param name="ConversionPattern" value="%d %logger %level% %m%n%exceptionSessionId='%aspnet-request{ASP.NET_SessionId}'; Username='%aspnet-request{AUTH_USER}'; ClientIpAddress='%aspnet-request{REMOTE_ADDR}'; ClientUserAgent='%aspnet-request{HTTP_USER_AGENT}'; ServerName='%aspnet-request{SERVER_NAME}'; RequestMethod='%aspnet-request{REQUEST_METHOD}'; RequestUrl='%aspnet-request{URL}'; RequestQueryString='%aspnet-request{QUERY_STRING}'; RequestCookies='%aspnet-request{HTTP_COOKIE}'; MachineName='%property{log4net:HostName}';%n" />
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<appender name="DebuggerAppender" type="log4net.Appender.DebugAppender">
|
||||
<immediateFlush value="true" />
|
||||
<layout type="log4net.Layout.SimpleLayout" />
|
||||
</appender>
|
||||
|
||||
</log4net>
|
||||
@@ -0,0 +1,35 @@
|
||||
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("IDeliverable.Licensing.Service")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("IDeliverable.Licensing.Service")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[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("c2a67b6c-4615-4ecf-bfc6-39bf0f975c1f")]
|
||||
|
||||
// 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 Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
|
||||
by editing this MSBuild file. In order to learn more about this please visit http://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<WebPublishMethod>MSDeploy</WebPublishMethod>
|
||||
<ADUsesOwinOrOpenIdConnect>False</ADUsesOwinOrOpenIdConnect>
|
||||
<LastUsedBuildConfiguration>Debug</LastUsedBuildConfiguration>
|
||||
<LastUsedPlatform>Any CPU</LastUsedPlatform>
|
||||
<SiteUrlToLaunchAfterPublish>http://ideliverable-licensing.azurewebsites.net</SiteUrlToLaunchAfterPublish>
|
||||
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
|
||||
<ExcludeApp_Data>False</ExcludeApp_Data>
|
||||
<MSDeployServiceURL>ideliverable-licensing.scm.azurewebsites.net:443</MSDeployServiceURL>
|
||||
<DeployIisAppPath>ideliverable-licensing</DeployIisAppPath>
|
||||
<RemoteSitePhysicalPath />
|
||||
<SkipExtraFilesOnServer>True</SkipExtraFilesOnServer>
|
||||
<MSDeployPublishMethod>WMSVC</MSDeployPublishMethod>
|
||||
<EnableMSDeployBackup>True</EnableMSDeployBackup>
|
||||
<UserName>$ideliverable-licensing</UserName>
|
||||
<_SavePWD>True</_SavePWD>
|
||||
<_DestinationType>AzureWebSite</_DestinationType>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace IDeliverable.Licensing.Service.Services
|
||||
{
|
||||
internal class LicenseInfo
|
||||
{
|
||||
public LicenseInfo(string key, int orderId)
|
||||
{
|
||||
Key = key;
|
||||
OrderId = orderId;
|
||||
}
|
||||
|
||||
public string Key { get; }
|
||||
public int OrderId { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using IDeliverable.Licensing.Exceptions;
|
||||
using IDeliverable.Licensing.VerificationTokens;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace IDeliverable.Licensing.Service.Services
|
||||
{
|
||||
internal class LicenseService
|
||||
{
|
||||
public LicenseService(string sendOwlApiEndpoint, string sendOwlApiKey, string sendOwlApiSecret, string tokenSigningCertificateThumbprint)
|
||||
{
|
||||
mSendOwlApiEndpoint = sendOwlApiEndpoint;
|
||||
mSendOwlApiKey = sendOwlApiKey;
|
||||
mSendOwlApiSecret = sendOwlApiSecret;
|
||||
mTokenSigningCertificateThumbprint = tokenSigningCertificateThumbprint;
|
||||
mLogger = new Logger(nameof(LicenseService));
|
||||
}
|
||||
|
||||
private readonly string mSendOwlApiEndpoint;
|
||||
private readonly string mSendOwlApiKey;
|
||||
private readonly string mSendOwlApiSecret;
|
||||
private readonly string mTokenSigningCertificateThumbprint;
|
||||
private readonly Logger mLogger;
|
||||
|
||||
public LicenseVerificationToken VerifyLicense(string licenseKey, string productId, string hostname, bool throwOnError)
|
||||
{
|
||||
mLogger.Info($"Starting license verification... LicenseKey={licenseKey}; ProductId={productId}; Hostname={hostname};");
|
||||
|
||||
try
|
||||
{
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
client.BaseAddress = new Uri(mSendOwlApiEndpoint);
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", CreateBasicAuthenticationToken(mSendOwlApiKey, mSendOwlApiSecret));
|
||||
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
|
||||
var licenses = ParseLicenseInfo(client.GetAsync($"products/{productId}/licenses/check_valid?key={licenseKey}").Result.Content.ReadAsStringAsync().Result).ToList();
|
||||
|
||||
if (!licenses.Any())
|
||||
throw new LicenseVerificationException($"No license with key '{licenseKey}' was found.", LicenseVerificationError.UnknownLicenseKey);
|
||||
|
||||
var orderId = licenses.First(x => x.Key == licenseKey).OrderId;
|
||||
var order = ParseOrderInfo(client.GetAsync($"orders/{orderId}").Result.Content.ReadAsStringAsync().Result);
|
||||
|
||||
if (!order.IsProductAccessAllowed)
|
||||
{
|
||||
if(order.SubscriptionId != null)
|
||||
throw new LicenseVerificationException($"The license with key '{licenseKey}' is not associated with an active subscription.", LicenseVerificationError.NoActiveSubscription);
|
||||
|
||||
throw new LicenseVerificationException($"The license with key '{licenseKey}' has been revoked.", LicenseVerificationError.LicenseRevoked);
|
||||
}
|
||||
|
||||
if (!order.Hostnames.Contains(hostname, StringComparer.OrdinalIgnoreCase))
|
||||
throw new LicenseVerificationException($"The license with key '{licenseKey}' is not valid for the provided '{hostname}'. Valid hostnames are '{String.Join(",", order.Hostnames)}", LicenseVerificationError.HostnameMismatch);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!(ex is LicenseVerificationException))
|
||||
{
|
||||
mLogger.Error($"An error occurred while verifying license with SendOwl. LicenseKey={licenseKey}; ProductId={productId}; Hostname={hostname};", ex);
|
||||
|
||||
if (throwOnError)
|
||||
throw;
|
||||
|
||||
mLogger.Info("Ignoring error and issuing verification token anyway. LicenseKey={licenseKey}; ProductId={productId}; Hostname={hostname};");
|
||||
}
|
||||
|
||||
mLogger.Info($"License verification finished. LicenseKey={licenseKey}; ProductId={productId}; Hostname={hostname};");
|
||||
|
||||
return CreateVerificationToken(productId, hostname, licenseKey);
|
||||
}
|
||||
|
||||
private LicenseVerificationToken CreateVerificationToken(string productId, string hostname, string key)
|
||||
{
|
||||
X509Certificate2 signingCert = null;
|
||||
|
||||
// Try to find the certificate in either the CurrentUser or LocalMachine stores
|
||||
// to maximize code portability.
|
||||
signingCert = GetSigningCertificateFrom(StoreLocation.CurrentUser) ?? GetSigningCertificateFrom(StoreLocation.LocalMachine);
|
||||
if (signingCert == null)
|
||||
throw new Exception($"No certificate with thumbprint '{mTokenSigningCertificateThumbprint}' was found in the certificate store.");
|
||||
|
||||
var info = new LicenseVerificationInfo(productId, hostname, key, DateTime.UtcNow.Ticks);
|
||||
var token = LicenseVerificationToken.Create(info, signingCert);
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
private X509Certificate2 GetSigningCertificateFrom(StoreLocation location)
|
||||
{
|
||||
var store = new X509Store(StoreName.My, location);
|
||||
store.Open(OpenFlags.ReadOnly);
|
||||
|
||||
try
|
||||
{
|
||||
var certificates = store.Certificates.Find(X509FindType.FindByThumbprint, mTokenSigningCertificateThumbprint, validOnly: false);
|
||||
return certificates.Count > 0 ? certificates[0] : null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
store.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private string CreateBasicAuthenticationToken(string userName, string password)
|
||||
{
|
||||
return Convert.ToBase64String(Encoding.UTF8.GetBytes($"{userName}:{password}"), Base64FormattingOptions.None);
|
||||
}
|
||||
|
||||
private IEnumerable<LicenseInfo> ParseLicenseInfo(string json)
|
||||
{
|
||||
var licensesQuery =
|
||||
from node in JArray.Parse(json)
|
||||
select new LicenseInfo((string)node["license"]["key"], (int)node["license"]["order_id"]);
|
||||
|
||||
return licensesQuery.ToArray();
|
||||
}
|
||||
|
||||
private OrderInfo ParseOrderInfo(string json)
|
||||
{
|
||||
var order = JObject.Parse(json)["order"];
|
||||
var status = ReadOrderStatus(order);
|
||||
var isAccessAllowed = (bool) order["access_allowed"];
|
||||
var subscriptionId = (int?) order["subscription_id"];
|
||||
var customFields = (JArray)order["order_custom_checkout_fields"];
|
||||
var hostnames = new List<string>();
|
||||
|
||||
if (customFields.Count > 0)
|
||||
{
|
||||
var hostnameString = (string)customFields[0]["order_custom_checkout_field"]["value"];
|
||||
if (!String.IsNullOrWhiteSpace(hostnameString))
|
||||
hostnames.Add(ParseHostname(hostnameString));
|
||||
}
|
||||
|
||||
if (customFields.Count > 1)
|
||||
{
|
||||
var hostnameString = (string)customFields[1]["order_custom_checkout_field"]["value"];
|
||||
if (!String.IsNullOrWhiteSpace(hostnameString))
|
||||
hostnames.Add(ParseHostname(hostnameString));
|
||||
}
|
||||
|
||||
return new OrderInfo((int)order["id"], status, isAccessAllowed, subscriptionId, hostnames);
|
||||
}
|
||||
|
||||
private string ParseHostname(string hostnameString)
|
||||
{
|
||||
Uri uri = null;
|
||||
|
||||
if (Uri.TryCreate(hostnameString, UriKind.Absolute, out uri))
|
||||
return uri.Host;
|
||||
|
||||
return hostnameString;
|
||||
}
|
||||
|
||||
private static OrderStatus ReadOrderStatus(JToken order)
|
||||
{
|
||||
var dictionary = new Dictionary<string, OrderStatus>
|
||||
{
|
||||
{"initial", OrderStatus.Initial },
|
||||
{"payment_started", OrderStatus.PaymentStarted },
|
||||
{"payment_pending", OrderStatus.PaymentPending },
|
||||
{"failed", OrderStatus.Failed },
|
||||
{"complete", OrderStatus.Complete },
|
||||
{"chargeback", OrderStatus.Chargeback },
|
||||
{"refunded", OrderStatus.Refunded },
|
||||
{"in_dispute", OrderStatus.InDispute },
|
||||
{"free", OrderStatus.Free },
|
||||
{"imported", OrderStatus.Imported },
|
||||
{"fraud_review", OrderStatus.FraudReview },
|
||||
{"subscription_setup", OrderStatus.SubscriptionSetup },
|
||||
{"subscription_active", OrderStatus.SubscriptionActive },
|
||||
{"subscription_complete", OrderStatus.SubscriptionComplete },
|
||||
{"subscription_cancelled", OrderStatus.SubscriptionCancelled }
|
||||
};
|
||||
var status = (string) order["state"];
|
||||
|
||||
return dictionary.ContainsKey(status) ? dictionary[status] : OrderStatus.Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using log4net;
|
||||
using log4net.Config;
|
||||
|
||||
namespace IDeliverable.Licensing.Service.Services
|
||||
{
|
||||
public class Logger
|
||||
{
|
||||
private const string ConfigFileName = "Log4net.config";
|
||||
|
||||
static Logger()
|
||||
{
|
||||
var basePath = AppDomain.CurrentDomain.BaseDirectory;
|
||||
var configFilePath = Path.Combine(basePath, ConfigFileName);
|
||||
if (File.Exists(configFilePath))
|
||||
XmlConfigurator.Configure(new FileInfo(configFilePath));
|
||||
else
|
||||
throw new Exception($"The log4net configuration file could not be found at path '{configFilePath}'.");
|
||||
}
|
||||
|
||||
public Logger(Type loggerType)
|
||||
:this(loggerType.FullName)
|
||||
{
|
||||
}
|
||||
|
||||
public Logger(string loggerName)
|
||||
{
|
||||
mLog = LogManager.GetLogger(loggerName);
|
||||
}
|
||||
|
||||
private ILog mLog;
|
||||
|
||||
public void Fatal(string message, Exception ex = null)
|
||||
{
|
||||
if (mLog.IsFatalEnabled)
|
||||
mLog.Fatal(message, ex);
|
||||
}
|
||||
|
||||
public void Error(string message, Exception ex = null)
|
||||
{
|
||||
if (mLog.IsErrorEnabled)
|
||||
mLog.Error(message, ex);
|
||||
}
|
||||
|
||||
public void Warn(string message, Exception ex = null)
|
||||
{
|
||||
if (mLog.IsWarnEnabled)
|
||||
mLog.Warn(message, ex);
|
||||
}
|
||||
|
||||
public void Info(string message, Exception ex = null)
|
||||
{
|
||||
if (mLog.IsInfoEnabled)
|
||||
mLog.Info(message, ex);
|
||||
}
|
||||
|
||||
public void Debug(string message, Exception ex = null)
|
||||
{
|
||||
if (mLog.IsDebugEnabled)
|
||||
mLog.Debug(message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IDeliverable.Licensing.Service.Services
|
||||
{
|
||||
internal class OrderInfo
|
||||
{
|
||||
public OrderInfo(int orderId, OrderStatus status, bool isProductAccessAllowed, int? subscriptionId, IEnumerable<string> hostnames)
|
||||
{
|
||||
OrderId = orderId;
|
||||
Hostnames = hostnames;
|
||||
Status = status;
|
||||
IsProductAccessAllowed = isProductAccessAllowed;
|
||||
SubscriptionId = subscriptionId;
|
||||
}
|
||||
|
||||
public int OrderId { get; }
|
||||
public IEnumerable<string> Hostnames { get; }
|
||||
public OrderStatus Status { get; }
|
||||
public bool IsProductAccessAllowed { get; }
|
||||
public int? SubscriptionId { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace IDeliverable.Licensing.Service.Services {
|
||||
internal enum OrderStatus
|
||||
{
|
||||
Unknown,
|
||||
Initial,
|
||||
PaymentStarted,
|
||||
PaymentPending,
|
||||
Failed,
|
||||
Complete,
|
||||
Chargeback,
|
||||
Refunded,
|
||||
InDispute,
|
||||
Free,
|
||||
Imported,
|
||||
FraudReview,
|
||||
SubscriptionSetup,
|
||||
SubscriptionActive,
|
||||
SubscriptionComplete,
|
||||
SubscriptionCancelled,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!-- For more information on using Web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=301874 -->
|
||||
|
||||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
|
||||
<!--
|
||||
In the example below, the "SetAttributes" transform will change the value of
|
||||
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator
|
||||
finds an attribute "name" that has a value of "MyDB".
|
||||
|
||||
<connectionStrings>
|
||||
<add name="MyDB"
|
||||
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
|
||||
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
|
||||
</connectionStrings>
|
||||
-->
|
||||
<system.web>
|
||||
<!--
|
||||
In the example below, the "Replace" transform will replace the entire
|
||||
<customErrors> section of your Web.config file.
|
||||
Note that because there is only one customErrors section under the
|
||||
<system.web> node, there is no need to use the "xdt:Locator" attribute.
|
||||
|
||||
<customErrors defaultRedirect="GenericError.htm"
|
||||
mode="RemoteOnly" xdt:Transform="Replace">
|
||||
<error statusCode="500" redirect="InternalError.htm"/>
|
||||
</customErrors>
|
||||
-->
|
||||
</system.web>
|
||||
</configuration>
|
||||
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!-- For more information on using Web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=301874 -->
|
||||
|
||||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
|
||||
<!--
|
||||
In the example below, the "SetAttributes" transform will change the value of
|
||||
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator
|
||||
finds an attribute "name" that has a value of "MyDB".
|
||||
|
||||
<connectionStrings>
|
||||
<add name="MyDB"
|
||||
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
|
||||
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
|
||||
</connectionStrings>
|
||||
-->
|
||||
<system.web>
|
||||
<compilation xdt:Transform="RemoveAttributes(debug)" />
|
||||
<!--
|
||||
In the example below, the "Replace" transform will replace the entire
|
||||
<customErrors> section of your Web.config file.
|
||||
Note that because there is only one customErrors section under the
|
||||
<system.web> node, there is no need to use the "xdt:Locator" attribute.
|
||||
|
||||
<customErrors defaultRedirect="GenericError.htm"
|
||||
mode="RemoteOnly" xdt:Transform="Replace">
|
||||
<error statusCode="500" redirect="InternalError.htm"/>
|
||||
</customErrors>
|
||||
-->
|
||||
</system.web>
|
||||
</configuration>
|
||||
52
src/IDeliverable/IDeliverable.Licensing.Service/Web.config
Normal file
52
src/IDeliverable/IDeliverable.Licensing.Service/Web.config
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
|
||||
<appSettings>
|
||||
<add key="ApiKey" value="MJb17j7YAzSjyEYkhsoI" />
|
||||
<add key="TestProductId" value="233554" />
|
||||
<add key="TestHostname" value="ideliverable.com" />
|
||||
<add key="TestKey" value="ADB5-2D53-0A62-4C2F" />
|
||||
<add key="SendOwlApiEndpoint" value="https://www.sendowl.com/api/v1/" />
|
||||
<add key="SendOwlApiKey" value="14be9ee5e05222e" />
|
||||
<add key="SendOwlApiSecret" value="1a10fe7987724e0a56a1" />
|
||||
<add key="TokenSigningCertificateThumbprint" value="fa4746a778716109e7e80e1b8dc2ed2a2ba3b852" />
|
||||
<add key="Logentries.Token" value="5c73ab7f-39a3-4171-b730-03da5c3d4b24"/> <!-- Local -->
|
||||
<add key="ApplicationInsights.InstrumentationKey" value="" /> <!-- Disabled -->
|
||||
</appSettings>
|
||||
|
||||
<system.web>
|
||||
<compilation debug="true" targetFramework="4.5.2" />
|
||||
<httpRuntime targetFramework="4.5.2" />
|
||||
<httpModules>
|
||||
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Extensibility.Web.RequestTracking.WebRequestTrackingModule, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
</httpModules>
|
||||
</system.web>
|
||||
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
|
||||
<remove name="OPTIONSVerbHandler" />
|
||||
<remove name="TRACEVerbHandler" />
|
||||
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
|
||||
</handlers>
|
||||
<validation validateIntegratedModeConfiguration="false" />
|
||||
<modules>
|
||||
<remove name="ApplicationInsightsWebTracking" />
|
||||
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Extensibility.Web.RequestTracking.WebRequestTrackingModule, Microsoft.ApplicationInsights.Extensibility.Web" preCondition="managedHandler" />
|
||||
</modules>
|
||||
</system.webServer>
|
||||
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
|
||||
<bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
</configuration>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="log4net" version="2.0.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="logentries.core" version="2.7.0" targetFramework="net452" userInstalled="true" />
|
||||
<package id="logentries.log4net" version="2.7.0" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.ApplicationInsights" version="0.14.3-build00177" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.ApplicationInsights.Agent.Intercept" version="0.14.0-build08008" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.ApplicationInsights.JavaScript" version="0.11.0-build09387" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.ApplicationInsights.PerformanceCollector" version="0.14.3-build00177" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.ApplicationInsights.PersistenceChannel" version="0.14.3-build00177" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.ApplicationInsights.RuntimeTelemetry" version="0.14.3-build00177" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.ApplicationInsights.Web" version="0.14.3-build00177" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.Razor" version="3.2.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.WebApi.HelpPage" version="5.2.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.Bcl" version="1.1.8" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.Diagnostics.Tracing.EventSource.Redist" version="1.1.16-beta" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.WindowsAzure.ConfigurationManager" version="3.1.0" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net452" userInstalled="true" />
|
||||
</packages>
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Web.Caching;
|
||||
|
||||
namespace IDeliverable.Licensing
|
||||
{
|
||||
public class CacheInvalidationContext
|
||||
{
|
||||
public CacheDependency CacheDependency { get; set; }
|
||||
public TimeSpan? ValidFor { get; set; }
|
||||
}
|
||||
}
|
||||
52
src/IDeliverable/IDeliverable.Licensing/CacheService.cs
Normal file
52
src/IDeliverable/IDeliverable.Licensing/CacheService.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Web.Caching;
|
||||
|
||||
namespace IDeliverable.Licensing
|
||||
{
|
||||
public class CacheService
|
||||
{
|
||||
private readonly HttpContextAccessor mHttpContextAccessor = new HttpContextAccessor();
|
||||
|
||||
private Cache Cache => mHttpContextAccessor.Current().Cache;
|
||||
|
||||
public void SetValue<T>(string key, T value, CacheDependency dependency = null, TimeSpan? validFor = null)
|
||||
{
|
||||
var absoluteExpiration = validFor != null ? DateTime.UtcNow.Add(validFor.Value) : Cache.NoAbsoluteExpiration;
|
||||
Cache.Insert(key, value, dependency, absoluteExpiration, Cache.NoSlidingExpiration);
|
||||
}
|
||||
|
||||
public T GetValue<T>(string key, Func<CacheInvalidationContext, T> valueFactory = null)
|
||||
{
|
||||
var value = Cache.Get(key);
|
||||
var exception = value as Exception;
|
||||
|
||||
if (exception != null)
|
||||
throw (Exception)value;
|
||||
|
||||
if (value != null)
|
||||
return (T)value;
|
||||
|
||||
if (valueFactory == null)
|
||||
return default(T);
|
||||
|
||||
var context = new CacheInvalidationContext();
|
||||
|
||||
try
|
||||
{
|
||||
value = valueFactory(context);
|
||||
SetValue(key, value, context.CacheDependency, context.ValidFor);
|
||||
return (T) value;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SetValue(key, ex, context.CacheDependency, context.ValidFor);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public object RemoveValue(string key)
|
||||
{
|
||||
return Cache.Remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace IDeliverable.Licensing.Exceptions
|
||||
{
|
||||
public enum LicenseVerificationError
|
||||
{
|
||||
UnknownLicenseKey,
|
||||
NoActiveSubscription,
|
||||
LicenseRevoked,
|
||||
HostnameMismatch,
|
||||
UnhandledException
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
|
||||
namespace IDeliverable.Licensing.Exceptions
|
||||
{
|
||||
public class LicenseVerificationException : Exception
|
||||
{
|
||||
public LicenseVerificationException(LicenseVerificationError error)
|
||||
:this("An error occurred while verifying the license.", error)
|
||||
{
|
||||
}
|
||||
|
||||
public LicenseVerificationException(string message, LicenseVerificationError error) : base(message)
|
||||
{
|
||||
Error = error;
|
||||
}
|
||||
|
||||
public LicenseVerificationException(LicenseVerificationError error, Exception innerException)
|
||||
: this("An error occurred while verifying the license.", error, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
public LicenseVerificationException(string message, LicenseVerificationError error, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
Error = error;
|
||||
}
|
||||
|
||||
public LicenseVerificationError Error { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System.Web;
|
||||
|
||||
namespace IDeliverable.Licensing
|
||||
{
|
||||
public class HttpContextAccessor
|
||||
{
|
||||
public HttpContextBase Current()
|
||||
{
|
||||
return new HttpContextWrapper(HttpContext.Current);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Web;
|
||||
|
||||
namespace IDeliverable.Licensing
|
||||
{
|
||||
internal static class HttpRequestExtensions
|
||||
{
|
||||
public static string GetHttpHost(this HttpRequestBase request)
|
||||
{
|
||||
var host = request.ServerVariables["HTTP_HOST"];
|
||||
|
||||
if (host?.Contains(":") == true)
|
||||
host = host.Substring(0, host.IndexOf(':'));
|
||||
|
||||
return host;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{7E439CB7-1ACE-435F-A8F3-5BB929423E34}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>IDeliverable.Licensing</RootNamespace>
|
||||
<AssemblyName>IDeliverable.Licensing</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\..\..\lib\newtonsoft.json\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CacheInvalidationContext.cs" />
|
||||
<Compile Include="CacheService.cs" />
|
||||
<Compile Include="Exceptions\LicenseVerificationError.cs" />
|
||||
<Compile Include="Exceptions\LicenseVerificationException.cs" />
|
||||
<Compile Include="HttpContextAccessor.cs" />
|
||||
<Compile Include="HttpRequestExtensions.cs" />
|
||||
<Compile Include="Validation\LicenseValidationError.cs" />
|
||||
<Compile Include="Validation\LicenseValidationException.cs" />
|
||||
<Compile Include="Validation\LicenseValidator.cs" />
|
||||
<Compile Include="VerificationTokens\LicenseVerificationTokenError.cs" />
|
||||
<Compile Include="VerificationTokens\LicenseVerificationTokenException.cs" />
|
||||
<Compile Include="VerificationTokens\LicenseVerificationInfo.cs" />
|
||||
<Compile Include="VerificationTokens\LicenseVerificationToken.cs" />
|
||||
<Compile Include="VerificationTokens\LicenseVerificationTokenAccessor.cs" />
|
||||
<Compile Include="VerificationTokens\LicensingServiceClient.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Validation\LicenseValidationOptions.cs" />
|
||||
<Compile Include="VerificationTokens\ILicenseVerificationTokenStore.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -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("IDeliverable.LicensingFramework")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("IDeliverable.LicensingFramework")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[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("7e439cb7-1ace-435f-a8f3-5bb929423e34")]
|
||||
|
||||
// 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("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace IDeliverable.Licensing.Validation
|
||||
{
|
||||
public enum LicenseValidationError
|
||||
{
|
||||
UnknownLicenseKey,
|
||||
HostnameMismatch,
|
||||
NoActiveSubscription,
|
||||
LicenseRevoked,
|
||||
LicensingServiceError,
|
||||
LicensingServiceUnreachable,
|
||||
TokenAgeValidationFailed,
|
||||
TokenSignatureValidationFailed,
|
||||
UnexpectedError,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
|
||||
namespace IDeliverable.Licensing.Validation
|
||||
{
|
||||
public class LicenseValidationException : Exception
|
||||
{
|
||||
public LicenseValidationException(LicenseValidationError error)
|
||||
:this("An error occurred while validating the license.", error)
|
||||
{
|
||||
}
|
||||
|
||||
public LicenseValidationException(string message, LicenseValidationError error) : base(message)
|
||||
{
|
||||
Error = error;
|
||||
}
|
||||
|
||||
public LicenseValidationException(LicenseValidationError error, Exception innerException)
|
||||
: this("An error occurred while validating the license.", error, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
public LicenseValidationException(string message, LicenseValidationError error, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
Error = error;
|
||||
}
|
||||
|
||||
public LicenseValidationError Error { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace IDeliverable.Licensing.Validation
|
||||
{
|
||||
[Flags]
|
||||
public enum LicenseValidationOptions
|
||||
{
|
||||
Default = 0,
|
||||
SkipForLocalRequests = 1,
|
||||
ForceRenewToken = 2,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
using System;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using IDeliverable.Licensing.VerificationTokens;
|
||||
|
||||
namespace IDeliverable.Licensing.Validation
|
||||
{
|
||||
public class LicenseValidator
|
||||
{
|
||||
private static readonly TimeSpan sVerificationTokenValidFor = TimeSpan.FromDays(21);
|
||||
private static readonly TimeSpan sAllowableClockSkew = TimeSpan.FromMinutes(10);
|
||||
|
||||
public LicenseValidator(LicenseVerificationTokenAccessor verificationTokenAccessor)
|
||||
{
|
||||
mHttpContextAccessor = new HttpContextAccessor();
|
||||
mVerificationTokenAccessor = verificationTokenAccessor;
|
||||
}
|
||||
|
||||
private readonly HttpContextAccessor mHttpContextAccessor;
|
||||
private readonly LicenseVerificationTokenAccessor mVerificationTokenAccessor;
|
||||
|
||||
public void ValidateLicense(string productId, string licenseKey, LicenseValidationOptions options = LicenseValidationOptions.Default)
|
||||
{
|
||||
var request = mHttpContextAccessor.Current().Request;
|
||||
|
||||
var isLocal = request.IsLocal;
|
||||
var isDebugMode = mHttpContextAccessor.Current().IsDebuggingEnabled;
|
||||
|
||||
var skipForLocalRequests = (options & LicenseValidationOptions.SkipForLocalRequests) == LicenseValidationOptions.SkipForLocalRequests;
|
||||
if (skipForLocalRequests && isLocal && isDebugMode)
|
||||
return;
|
||||
|
||||
LicenseVerificationToken token;
|
||||
|
||||
try
|
||||
{
|
||||
var forceRenewToken = (options & LicenseValidationOptions.ForceRenewToken) == LicenseValidationOptions.ForceRenewToken;
|
||||
token = mVerificationTokenAccessor.GetLicenseVerificationToken(productId, licenseKey, request.GetHttpHost(), forceRenewToken);
|
||||
|
||||
// If the token we got back is too old to be considered valid anymore, try to get the token
|
||||
// again, this time forcing token renewal.
|
||||
if (token.Age > sVerificationTokenValidFor)
|
||||
token = mVerificationTokenAccessor.GetLicenseVerificationToken(productId, licenseKey, request.GetHttpHost(), forceRenew: true);
|
||||
}
|
||||
catch (LicenseVerificationTokenException ex)
|
||||
{
|
||||
var error = LicenseValidationError.UnexpectedError;
|
||||
|
||||
switch (ex.Error)
|
||||
{
|
||||
case LicenseVerificationTokenError.UnknownLicenseKey:
|
||||
error = LicenseValidationError.UnknownLicenseKey;
|
||||
break;
|
||||
|
||||
case LicenseVerificationTokenError.HostnameMismatch:
|
||||
error = LicenseValidationError.HostnameMismatch;
|
||||
break;
|
||||
|
||||
case LicenseVerificationTokenError.NoActiveSubscription:
|
||||
error = LicenseValidationError.NoActiveSubscription;
|
||||
break;
|
||||
|
||||
case LicenseVerificationTokenError.LicenseRevoked:
|
||||
error = LicenseValidationError.LicenseRevoked;
|
||||
break;
|
||||
|
||||
case LicenseVerificationTokenError.LicenseServiceError:
|
||||
error = LicenseValidationError.LicensingServiceError;
|
||||
break;
|
||||
|
||||
case LicenseVerificationTokenError.LicenseServiceUnreachable:
|
||||
error = LicenseValidationError.LicensingServiceUnreachable;
|
||||
break;
|
||||
}
|
||||
|
||||
throw new LicenseValidationException(ex.Message, error);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new LicenseValidationException("An unexpected error occurred while validating the license.", LicenseValidationError.UnexpectedError, ex);
|
||||
}
|
||||
|
||||
// It should never happen that at this point we don't have a token or it's too old.
|
||||
if (token == null || token.Age > sVerificationTokenValidFor)
|
||||
throw new LicenseValidationException(LicenseValidationError.UnexpectedError);
|
||||
|
||||
// If the token age is negative by more than 10 minutes (allowable clock skew between licensing
|
||||
// service and local machine) then this is a strong indication of an attempt to bypass license
|
||||
// validation by changing the system clock.
|
||||
if (token.Age < -sAllowableClockSkew)
|
||||
throw new LicenseValidationException("The license verification token age is negative by more than the allowable clock skew. This might indicate that system clock of either the client or the licensing service is offset.", LicenseValidationError.TokenAgeValidationFailed);
|
||||
|
||||
var signingCertificate = GetSigningCertificate();
|
||||
if (!token.GetSignatureIsValid(signingCertificate))
|
||||
throw new LicenseValidationException("License verification token signature validation failed.", LicenseValidationError.TokenSignatureValidationFailed);
|
||||
}
|
||||
|
||||
private static X509Certificate2 GetSigningCertificate()
|
||||
{
|
||||
const string certBase64 =
|
||||
@"MIIG0TCCBLmgAwIBAgIQ7qnUeLGos7hDPcw3o9G74jANBgkqhkiG9w0BAQ0FADCB
|
||||
ozELMAkGA1UEBhMCQ1kxETAPBgNVBAgTCExpbWFzc29sMREwDwYDVQQHEwhMaW1h
|
||||
c3NvbDEZMBcGA1UEChMQSURlbGl2ZXJhYmxlIEx0ZDETMBEGA1UECxMKT3BlcmF0
|
||||
aW9uczEYMBYGA1UEAxMPSURlbGl2ZXJhYmxlIENBMSQwIgYJKoZIhvcNAQkBFhVp
|
||||
bmZvQGlkZWxpdmVyYWJsZS5jb20wHhcNMTQxMjMxMjEwMDAwWhcNMjQxMjMxMjEw
|
||||
MDAwWjCBrjELMAkGA1UEBhMCQ1kxETAPBgNVBAgTCExpbWFzc29sMREwDwYDVQQH
|
||||
EwhMaW1hc3NvbDEZMBcGA1UEChMQSURlbGl2ZXJhYmxlIEx0ZDETMBEGA1UECxMK
|
||||
T3BlcmF0aW9uczEjMCEGA1UEAxMabGljZW5zaW5nLmlkZWxpdmVyYWJsZS5jb20x
|
||||
JDAiBgkqhkiG9w0BCQEWFWluZm9AaWRlbGl2ZXJhYmxlLmNvbTCCAiIwDQYJKoZI
|
||||
hvcNAQEBBQADggIPADCCAgoCggIBAJ0LddkeiE9f0p60exUCR1PxrKBHoVwF5von
|
||||
Lq+4GxA4I7Frtt8MV/dEYnYT44d/S6lEkAPLfF70CnyyWfpPO7MkIJYlFNZ2eJSz
|
||||
9wu0VZ12CZO9RilxrEzK1xLS+f6g7P+rPP3m1CqSt84wpd3YloLdBuB3HwPWNh5H
|
||||
a0Ew7W6IKyhzIX4MNzXXNc2evDIoaur3jQiPewtSastXzSQEEUx+S4St4qFbJ8lK
|
||||
v6pwC1BmqX37uoNURqqS1CWg3iKiAfzqtTIwt9vBu8C1ev4ZnlKmAF4C1fTuH3Wo
|
||||
X1lT+wpkycqWIUxoV7zoXYpxkleeNCw/GavDYmqhfU0qSjI4bdD/uy0s66dubtWB
|
||||
rCZ3VRC7mjHhmEWj1Y9GYvvg6Fjt/BchVMNEhIBd873MdXDqIx0cV6SILiQgudtr
|
||||
uvAUm5rT6KEYNSsHq9gQWN+LAgy8mDSOGLjYXdBtAOJMxS/w8XNA+bXWzvNYOl9q
|
||||
QO8w7Py3U/8mnLkxgHaVGktWazwQ1QkwaLyQz7lbTBedXkxOzP3LvLAe+POd4Zre
|
||||
wYcNUs/W51WfLup9o/IMEvDk/z0FCJ1fGFiHny3QFWrhJB3dAia1dwYtUpy42ZuY
|
||||
w4UQEuZVr3BzDCXudx6638WOURpvaMe/Enfdr2bcqvCYvzbT06RPD/VTtuKtZ8O7
|
||||
Q/hr0NvTAgMBAAGjgfMwgfAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwgdgGA1UdAQSB
|
||||
0DCBzYAQFBF2JL0Y1AduVxGNb4H7DqGBpjCBozELMAkGA1UEBhMCQ1kxETAPBgNV
|
||||
BAgTCExpbWFzc29sMREwDwYDVQQHEwhMaW1hc3NvbDEZMBcGA1UEChMQSURlbGl2
|
||||
ZXJhYmxlIEx0ZDETMBEGA1UECxMKT3BlcmF0aW9uczEYMBYGA1UEAxMPSURlbGl2
|
||||
ZXJhYmxlIENBMSQwIgYJKoZIhvcNAQkBFhVpbmZvQGlkZWxpdmVyYWJsZS5jb22C
|
||||
EMgq1WuLQwSJTj+ogMza3/YwDQYJKoZIhvcNAQENBQADggIBAEU9gdrydWT3ZwtA
|
||||
LP/HEct2DJRQdK9WuL02x2xbdmszyb8xoayTIcJdvs2WHPBqxM417XAhNTZuG3Aw
|
||||
Yx6OPSzbfmS1X7aVctSeBwZCfzxOk2MhTsKoZ+wjmFn6LVYz3P6K2deJVz6t+HRc
|
||||
mMwFrsctzgGZsxIvMXa0eqyDE6hhxj0XKYLFmYNGBdUd5sW68Ko26Njv1FPLkoqo
|
||||
Me2y+Gi6SltgjD/bmza36IRvaQVQtOjOxq+TncOBqLJ2+ikQOr93pkCgx3nso3CM
|
||||
YH1ryRpXbSAb5aA9sF0jb6LLLUgHv5q2ExpEFcoRja5gww5R2VKwEJ2PXjK+2O/A
|
||||
DgHOLKuiODxBF61+Ou/d29XiSX2HxCoH+onppi2h6ceJPcFwPrgzKVszsGkavtKL
|
||||
7myxufgdBUgTFxYMaTEtrU0yaRiJItxreH1wj/vl1zKyl25MXZLM1LyFvszAX49h
|
||||
9hgWApwE9hL1i6ygIfrpq2B+djPS8ZwX5S/t/QO5SmBjNLmw1GD1gHN5xqY0vMzS
|
||||
VxDXrH6Kllhwipu8GLeMWn/VmWWLy1vr//GoBjujhplIZHJPYBrYjqwfxH1ZLa4B
|
||||
O+N7bHDp63M0UVX5FdX1sN0laL29L1jXX/oe7x8PHNt3W4aOwVaIilh+/adXNDxr
|
||||
1yumH4G7QEeMQisiMhlPxnZJHajX";
|
||||
|
||||
var certBytes = Convert.FromBase64String(certBase64);
|
||||
var cert = new X509Certificate2(certBytes);
|
||||
|
||||
return cert;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace IDeliverable.Licensing.VerificationTokens
|
||||
{
|
||||
public interface ILicenseVerificationTokenStore
|
||||
{
|
||||
LicenseVerificationToken Load(string productId);
|
||||
void Save(string productId, LicenseVerificationToken token);
|
||||
void Clear(string productId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace IDeliverable.Licensing.VerificationTokens
|
||||
{
|
||||
public class LicenseVerificationInfo
|
||||
{
|
||||
public LicenseVerificationInfo(string productId, string hostname, string licenseKey, long verifiedUtcTicks)
|
||||
{
|
||||
ProductId = productId;
|
||||
Hostname = hostname;
|
||||
LicenseKey = licenseKey;
|
||||
VerifiedUtcTicks = verifiedUtcTicks;
|
||||
}
|
||||
|
||||
public string ProductId { get; }
|
||||
public string Hostname { get; }
|
||||
public string LicenseKey { get; }
|
||||
public long VerifiedUtcTicks { get; }
|
||||
|
||||
public DateTime VerifiedUtc => new DateTime(VerifiedUtcTicks, DateTimeKind.Utc);
|
||||
public TimeSpan Age => DateTime.UtcNow - VerifiedUtc;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return JsonConvert.SerializeObject(
|
||||
new
|
||||
{
|
||||
ProductId,
|
||||
Hostname,
|
||||
LicenseKey,
|
||||
VerifiedUtcTicks
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace IDeliverable.Licensing.VerificationTokens
|
||||
{
|
||||
public class LicenseVerificationToken
|
||||
{
|
||||
public static LicenseVerificationToken Create(LicenseVerificationInfo info, X509Certificate2 signingCert)
|
||||
{
|
||||
var infoString = info.ToString();
|
||||
var infoBytes = Encoding.UTF8.GetBytes(infoString);
|
||||
var privateKey = (RSACryptoServiceProvider)signingCert.PrivateKey;
|
||||
var signatureBytes = privateKey.SignData(infoBytes, "md5");
|
||||
var signature = Convert.ToBase64String(signatureBytes);
|
||||
|
||||
return new LicenseVerificationToken(info, signature);
|
||||
}
|
||||
|
||||
public static LicenseVerificationToken FromBase64(string value)
|
||||
{
|
||||
var tokenBytes = Convert.FromBase64String(value);
|
||||
var tokenJson = Encoding.UTF8.GetString(tokenBytes);
|
||||
return Parse(tokenJson);
|
||||
}
|
||||
|
||||
public static LicenseVerificationToken Parse(string value)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<LicenseVerificationToken>(value, new StringEnumConverter());
|
||||
}
|
||||
|
||||
public LicenseVerificationToken(LicenseVerificationInfo info, string signature)
|
||||
{
|
||||
if (info == null)
|
||||
throw new ArgumentNullException(nameof(info), $"The parameter {nameof(info)} cannot be null.");
|
||||
|
||||
Info = info;
|
||||
Signature = signature;
|
||||
}
|
||||
|
||||
public LicenseVerificationInfo Info { get; }
|
||||
public string Signature { get; }
|
||||
|
||||
public DateTime VerifiedUtc => Info.VerifiedUtc; // Delegated to Info because it needs to be included in signature.
|
||||
public TimeSpan Age => Info.Age; // Delegated to Info because it needs to be included in signature.
|
||||
|
||||
public string ToBase64()
|
||||
{
|
||||
var tokenJson = ToString();
|
||||
var tokenBytes = Encoding.UTF8.GetBytes(tokenJson);
|
||||
return Convert.ToBase64String(tokenBytes);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return JsonConvert.SerializeObject(this);
|
||||
}
|
||||
|
||||
public bool GetSignatureIsValid(X509Certificate2 signingCert)
|
||||
{
|
||||
var publicKey = (RSACryptoServiceProvider)signingCert.PublicKey.Key;
|
||||
var infoBytes = Encoding.UTF8.GetBytes(Info.ToString());
|
||||
var signatureBytes = Convert.FromBase64String(Signature);
|
||||
var isValid = publicKey.VerifyData(infoBytes, "md5", signatureBytes);
|
||||
|
||||
return isValid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
|
||||
namespace IDeliverable.Licensing.VerificationTokens
|
||||
{
|
||||
public class LicenseVerificationTokenAccessor
|
||||
{
|
||||
private static readonly TimeSpan sTokenRenewalInterval = TimeSpan.FromHours(48);
|
||||
|
||||
public LicenseVerificationTokenAccessor(ILicenseVerificationTokenStore store)
|
||||
{
|
||||
mStore = store;
|
||||
mLicensingServiceClient = new LicensingServiceClient();
|
||||
}
|
||||
|
||||
private readonly ILicenseVerificationTokenStore mStore;
|
||||
private readonly LicensingServiceClient mLicensingServiceClient;
|
||||
|
||||
public LicenseVerificationToken GetLicenseVerificationToken(string productId, string licenseKey, string hostname, bool forceRenew = false)
|
||||
{
|
||||
var token = mStore.Load(productId);
|
||||
|
||||
// Delete the existing verification token from store if:
|
||||
// * It was issued for a different license key OR
|
||||
// * We are instructed by caller to force renewal
|
||||
if (token != null && (token.Info.LicenseKey != licenseKey || forceRenew))
|
||||
{
|
||||
mStore.Clear(productId);
|
||||
token = null;
|
||||
}
|
||||
|
||||
// Try to renew verification token from licensing service if:
|
||||
// * We don't have a token in store OR
|
||||
// * The one we have has passed the token renewal interval
|
||||
if (token == null || token.Age > sTokenRenewalInterval)
|
||||
{
|
||||
try
|
||||
{
|
||||
token = mLicensingServiceClient.VerifyLicense(productId, licenseKey, hostname);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// If the license key is reported by licensing service to be either invalid or for
|
||||
// a different hostname, we delete any existing token from store and throw unconditionally.
|
||||
if (ex is LicenseVerificationTokenException)
|
||||
{
|
||||
var lvtex = (LicenseVerificationTokenException)ex;
|
||||
if (lvtex.Error == LicenseVerificationTokenError.UnknownLicenseKey ||
|
||||
lvtex.Error == LicenseVerificationTokenError.HostnameMismatch ||
|
||||
lvtex.Error == LicenseVerificationTokenError.NoActiveSubscription ||
|
||||
lvtex.Error == LicenseVerificationTokenError.LicenseRevoked)
|
||||
{
|
||||
mStore.Clear(productId);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have an existing token from before, return it rather than throwing.
|
||||
if (token != null)
|
||||
return token;
|
||||
|
||||
if (ex is LicenseVerificationTokenException)
|
||||
throw;
|
||||
|
||||
throw new LicenseVerificationTokenException(LicenseVerificationTokenError.UnexpectedError, ex);
|
||||
}
|
||||
|
||||
mStore.Save(productId, token);
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace IDeliverable.Licensing.VerificationTokens
|
||||
{
|
||||
public enum LicenseVerificationTokenError
|
||||
{
|
||||
UnknownLicenseKey,
|
||||
HostnameMismatch,
|
||||
NoActiveSubscription,
|
||||
LicenseRevoked,
|
||||
LicenseServiceError,
|
||||
LicenseServiceUnreachable,
|
||||
UnexpectedError
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
|
||||
namespace IDeliverable.Licensing.VerificationTokens
|
||||
{
|
||||
public class LicenseVerificationTokenException : Exception
|
||||
{
|
||||
public LicenseVerificationTokenException(LicenseVerificationTokenError error)
|
||||
:this("An error occurred while getting a license verification token.", error)
|
||||
{
|
||||
}
|
||||
|
||||
public LicenseVerificationTokenException(string message, LicenseVerificationTokenError error) : base(message)
|
||||
{
|
||||
Error = error;
|
||||
}
|
||||
|
||||
public LicenseVerificationTokenException(LicenseVerificationTokenError error, Exception innerException)
|
||||
: this("An error occurred while getting a license verification token.", error, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
public LicenseVerificationTokenException(string message, LicenseVerificationTokenError error, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
Error = error;
|
||||
}
|
||||
|
||||
public LicenseVerificationTokenError Error { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Security;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using IDeliverable.Licensing.Exceptions;
|
||||
|
||||
namespace IDeliverable.Licensing.VerificationTokens
|
||||
{
|
||||
public class LicensingServiceClient
|
||||
{
|
||||
// These are consciously hard coded (need to be obfuscated).
|
||||
private static readonly string sLicensingServiceUrl = "https://licensing.ideliverable.com/api/v1/";
|
||||
private static readonly string sLicensingServiceApiKey = "MJb17j7YAzSjyEYkhsoI";
|
||||
private static readonly string sExpectedServerCertificateThumbprint = "fa4746a778716109e7e80e1b8dc2ed2a2ba3b852";
|
||||
|
||||
public LicenseVerificationToken VerifyLicense(string productId, string licenseKey, string hostname)
|
||||
{
|
||||
RemoteCertificateValidationCallback certValidationHandler = (sender, certificate, chain, errors) =>
|
||||
{
|
||||
// Accept the server certificate as long as it matches the expected thumbprint. This makes sure
|
||||
// that the API call works even if the client host doesn't trust IDeliverable CA certificate, but
|
||||
// fails if somebody is trying to spoof the service.
|
||||
var serverCertThumbprint = ((X509Certificate2)certificate).Thumbprint;
|
||||
return String.Equals(serverCertThumbprint, sExpectedServerCertificateThumbprint, StringComparison.OrdinalIgnoreCase);
|
||||
};
|
||||
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
client.BaseAddress = new Uri(sLicensingServiceUrl);
|
||||
client.DefaultRequestHeaders.Add("ApiKey", sLicensingServiceApiKey);
|
||||
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
|
||||
ServicePointManager.ServerCertificateValidationCallback += certValidationHandler;
|
||||
|
||||
try
|
||||
{
|
||||
HttpResponseMessage response;
|
||||
|
||||
try
|
||||
{
|
||||
response = client.GetAsync($"license/{licenseKey}/verify?productId={productId}&hostname={hostname}").Result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new LicenseVerificationTokenException("An error occurred while calling the licensing service.", LicenseVerificationTokenError.LicenseServiceUnreachable, ex);
|
||||
}
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
var licenseVerificationError = ReadLicenseVerificationError(response);
|
||||
|
||||
switch (licenseVerificationError)
|
||||
{
|
||||
case LicenseVerificationError.UnknownLicenseKey:
|
||||
throw new LicenseVerificationTokenException(response.ReasonPhrase, LicenseVerificationTokenError.UnknownLicenseKey);
|
||||
|
||||
case LicenseVerificationError.HostnameMismatch:
|
||||
throw new LicenseVerificationTokenException(response.ReasonPhrase, LicenseVerificationTokenError.HostnameMismatch);
|
||||
|
||||
case LicenseVerificationError.NoActiveSubscription:
|
||||
throw new LicenseVerificationTokenException(response.ReasonPhrase, LicenseVerificationTokenError.NoActiveSubscription);
|
||||
|
||||
case LicenseVerificationError.LicenseRevoked:
|
||||
throw new LicenseVerificationTokenException(response.ReasonPhrase, LicenseVerificationTokenError.LicenseRevoked);
|
||||
|
||||
default:
|
||||
throw new LicenseVerificationTokenException(response.ReasonPhrase, LicenseVerificationTokenError.LicenseServiceError);
|
||||
}
|
||||
}
|
||||
|
||||
var responseText = response.Content.ReadAsStringAsync().Result;
|
||||
var token = LicenseVerificationToken.Parse(responseText);
|
||||
|
||||
return token;
|
||||
}
|
||||
finally
|
||||
{
|
||||
ServicePointManager.ServerCertificateValidationCallback -= certValidationHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static LicenseVerificationError? ReadLicenseVerificationError(HttpResponseMessage response)
|
||||
{
|
||||
IEnumerable<string> values;
|
||||
if (!response.Headers.TryGetValues("LicensingErrorCode", out values))
|
||||
return null;
|
||||
|
||||
var value = values.First();
|
||||
return (LicenseVerificationError)Enum.Parse(typeof(LicenseVerificationError), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
src/IDeliverable/Packaging/Confuser/Confuser.CLI.exe
Normal file
BIN
src/IDeliverable/Packaging/Confuser/Confuser.CLI.exe
Normal file
Binary file not shown.
BIN
src/IDeliverable/Packaging/Confuser/Confuser.Core.dll
Normal file
BIN
src/IDeliverable/Packaging/Confuser/Confuser.Core.dll
Normal file
Binary file not shown.
3234
src/IDeliverable/Packaging/Confuser/Confuser.Core.xml
Normal file
3234
src/IDeliverable/Packaging/Confuser/Confuser.Core.xml
Normal file
File diff suppressed because it is too large
Load Diff
BIN
src/IDeliverable/Packaging/Confuser/Confuser.DynCipher.dll
Normal file
BIN
src/IDeliverable/Packaging/Confuser/Confuser.DynCipher.dll
Normal file
Binary file not shown.
BIN
src/IDeliverable/Packaging/Confuser/Confuser.Protections.dll
Normal file
BIN
src/IDeliverable/Packaging/Confuser/Confuser.Protections.dll
Normal file
Binary file not shown.
BIN
src/IDeliverable/Packaging/Confuser/Confuser.Renamer.dll
Normal file
BIN
src/IDeliverable/Packaging/Confuser/Confuser.Renamer.dll
Normal file
Binary file not shown.
BIN
src/IDeliverable/Packaging/Confuser/Confuser.Runtime.dll
Normal file
BIN
src/IDeliverable/Packaging/Confuser/Confuser.Runtime.dll
Normal file
Binary file not shown.
BIN
src/IDeliverable/Packaging/Confuser/ConfuserEx.exe
Normal file
BIN
src/IDeliverable/Packaging/Confuser/ConfuserEx.exe
Normal file
Binary file not shown.
14
src/IDeliverable/Packaging/Confuser/ConfuserEx.exe.config
Normal file
14
src/IDeliverable/Packaging/Confuser/ConfuserEx.exe.config
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Practices.ServiceLocation" publicKeyToken="31BF3856AD364E35"
|
||||
culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.2.0.0" newVersion="1.2.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
<loadFromRemoteSources enabled="true" />
|
||||
</runtime>
|
||||
</configuration>
|
||||
Binary file not shown.
BIN
src/IDeliverable/Packaging/Confuser/GalaSoft.MvvmLight.WPF4.dll
Normal file
BIN
src/IDeliverable/Packaging/Confuser/GalaSoft.MvvmLight.WPF4.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/IDeliverable/Packaging/Confuser/Ookii.Dialogs.Wpf.dll
Normal file
BIN
src/IDeliverable/Packaging/Confuser/Ookii.Dialogs.Wpf.dll
Normal file
Binary file not shown.
BIN
src/IDeliverable/Packaging/Confuser/System.Threading.dll
Normal file
BIN
src/IDeliverable/Packaging/Confuser/System.Threading.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/IDeliverable/Packaging/Confuser/dnlib.dll
Normal file
BIN
src/IDeliverable/Packaging/Confuser/dnlib.dll
Normal file
Binary file not shown.
BIN
src/IDeliverable/Packaging/ILMerge/ILMerge.doc
Normal file
BIN
src/IDeliverable/Packaging/ILMerge/ILMerge.doc
Normal file
Binary file not shown.
BIN
src/IDeliverable/Packaging/ILMerge/ILMerge.exe
Normal file
BIN
src/IDeliverable/Packaging/ILMerge/ILMerge.exe
Normal file
Binary file not shown.
@@ -101,7 +101,6 @@
|
||||
<ProjectReference Include="..\Orchard\Orchard.Framework.csproj">
|
||||
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
|
||||
<Name>Orchard.Framework</Name>
|
||||
<Private>false</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -127,11 +126,11 @@
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -18,7 +18,7 @@
|
||||
</appSettings>
|
||||
|
||||
<system.web.webPages.razor>
|
||||
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
|
||||
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
|
||||
<pages pageBaseType="Orchard.Mvc.ViewEngines.Razor.WebViewPage">
|
||||
<namespaces>
|
||||
<add namespace="System.Collections.Generic"/>
|
||||
@@ -60,7 +60,7 @@
|
||||
<add extension=".csproj" type="Orchard.Environment.Extensions.Compilers.CSharpExtensionBuildProviderShim"/>
|
||||
</buildProviders>
|
||||
<assemblies>
|
||||
<add assembly="System.Web.Mvc, Version=5.2.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/>
|
||||
<add assembly="System.Web.Mvc, Version=5..0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/>
|
||||
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/>
|
||||
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/>
|
||||
<add assembly="System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
|
||||
@@ -147,7 +147,7 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.0.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.0.0" newVersion="5.2.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35"/>
|
||||
@@ -171,11 +171,11 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.0.0" newVersion="5.2.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.0.0" newVersion="5.2.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="NHibernate" publicKeyToken="aa95f207798dfdb4" culture="neutral"/>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Autofac;
|
||||
using JetBrains.Annotations;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Caching;
|
||||
@@ -82,6 +83,7 @@ namespace Orchard.Core.Tests.Body {
|
||||
}
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
public class ThingHandler : ContentHandler {
|
||||
public ThingHandler() {
|
||||
Filters.Add(new ActivatingFilter<Thing>(ThingDriver.ContentTypeName));
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Routing;
|
||||
using Autofac;
|
||||
using JetBrains.Annotations;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Caching;
|
||||
@@ -133,12 +134,12 @@ namespace Orchard.Core.Tests.Common.Providers {
|
||||
}
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
class TestHandler : ContentHandler {
|
||||
public TestHandler() {
|
||||
Filters.Add(new ActivatingFilter<CommonPart>("test-item"));
|
||||
Filters.Add(new ActivatingFilter<ContentPart<CommonPartVersionRecord>>("test-item"));
|
||||
Filters.Add(new ActivatingFilter<TestUser>("User"));
|
||||
Filters.Add(new ActivatingFilter<AlternateTestUser>("AlternateUser"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,11 +148,6 @@ namespace Orchard.Core.Tests.Common.Providers {
|
||||
public string UserName { get { return "x"; } }
|
||||
public string Email { get { return "y"; } }
|
||||
}
|
||||
class AlternateTestUser : ContentPart, IUser {
|
||||
public new int Id { get { return 6655322; } }
|
||||
public string UserName { get { return "y"; } }
|
||||
public string Email { get { return "x"; } }
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OwnerShouldBeNullAndZeroByDefault() {
|
||||
@@ -365,22 +361,14 @@ namespace Orchard.Core.Tests.Common.Providers {
|
||||
public void EditingShouldSetModifiedUtc() {
|
||||
var contentManager = _container.Resolve<IContentManager>();
|
||||
|
||||
var user = contentManager.New<IUser>("User");
|
||||
_authn.Setup(x => x.GetAuthenticatedUser()).Returns(user);
|
||||
|
||||
var createUtc = _clock.UtcNow;
|
||||
var item = contentManager.Create<ICommonPart>("test-item", VersionOptions.Draft, init => { });
|
||||
contentManager.Publish(item.ContentItem);
|
||||
|
||||
Assert.That(item.CreatedUtc, Is.EqualTo(createUtc));
|
||||
Assert.That(item.ModifiedUtc, Is.EqualTo(createUtc));
|
||||
Assert.That(item.VersionModifiedBy, Is.EqualTo(user.UserName));
|
||||
Assert.That(item.PublishedUtc, Is.EqualTo(createUtc));
|
||||
|
||||
// Switch user
|
||||
var secondUser = contentManager.New<IUser>("AlternateUser");
|
||||
_authn.Setup(x => x.GetAuthenticatedUser()).Returns(secondUser);
|
||||
|
||||
_clock.Advance(TimeSpan.FromMinutes(1));
|
||||
var editUtc = _clock.UtcNow;
|
||||
|
||||
@@ -391,7 +379,6 @@ namespace Orchard.Core.Tests.Common.Providers {
|
||||
Assert.That(item.ModifiedUtc, Is.EqualTo(editUtc));
|
||||
Assert.That(item.PublishedUtc, Is.EqualTo(createUtc));
|
||||
Assert.That(updater.ModelErrors.Count, Is.EqualTo(0));
|
||||
Assert.That(item.VersionModifiedBy, Is.EqualTo(secondUser.UserName));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -127,12 +127,10 @@
|
||||
<ProjectReference Include="..\Orchard.Web\Core\Orchard.Core.csproj">
|
||||
<Project>{9916839C-39FC-4CEB-A5AF-89CA7E87119F}</Project>
|
||||
<Name>Orchard.Core</Name>
|
||||
<Private>True</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard\Orchard.Framework.csproj">
|
||||
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
|
||||
<Name>Orchard.Framework</Name>
|
||||
<Private>True</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -156,10 +154,10 @@
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
-->
|
||||
<Target Name="CopySqlCeBinaries">
|
||||
<ItemGroup>
|
||||
|
||||
@@ -30,5 +30,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("1.9.1")]
|
||||
[assembly: AssemblyFileVersion("1.9.1")]
|
||||
[assembly: AssemblyVersion("1.9.0")]
|
||||
[assembly: AssemblyFileVersion("1.9.0")]
|
||||
|
||||
@@ -30,5 +30,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("1.9.1")]
|
||||
[assembly: AssemblyFileVersion("1.9.1")]
|
||||
[assembly: AssemblyVersion("1.9.0")]
|
||||
[assembly: AssemblyFileVersion("1.9.0")]
|
||||
|
||||
@@ -1 +1 @@
|
||||
setup /SiteName:Profiling /AdminUsername:admin /AdminPassword:profiling-secret /DatabaseProvider:SQLServer /DatabaseConnectionString:"Data Source=.;Initial Catalog=Orchard;Integrated Security=True" /EnabledFeatures:Profiling,Orchard.Framework,Common,Containers,Contents,Dashboard,Feeds,Navigation,Scheduling,Settings,Shapes,Title,PackagingServices,Gallery,Orchard.PublishLater,Orchard.Blogs,Orchard.Comments,Orchard.ContentTypes,Orchard.jQuery,Orchard.Lists,Orchard.MediaLibrary,Orchard.ContentPicker,Orchard.MediaPicker,Orchard.Modules,Orchard.Packaging,Orchard.Pages,Orchard.Recipes,Orchard.Roles,Orchard.Tags,Orchard.Themes,Orchard.Users,Orchard.Scripting,Orchard.Scripting.Lightweight,Orchard.Widgets,TinyMce,TheThemeMachine,Orchard.Tokens,Orchard.Alias,Orchard.Autoroute
|
||||
setup /SiteName:Profiling /AdminUsername:admin /AdminPassword:profiling-secret /DatabaseProvider:SQLServer /DatabaseConnectionString:"Data Source=.;Initial Catalog=Orchard;Integrated Security=True" /EnabledFeatures:Profiling,Orchard.Framework,Common,Containers,Contents,Dashboard,Feeds,Navigation,Reports,Scheduling,Settings,Shapes,Title,PackagingServices,Gallery,Orchard.PublishLater,Orchard.Blogs,Orchard.Comments,Orchard.ContentTypes,Orchard.jQuery,Orchard.Lists,Orchard.MediaLibrary,Orchard.ContentPicker,Orchard.MediaPicker,Orchard.Modules,Orchard.Packaging,Orchard.Pages,Orchard.Recipes,Orchard.Roles,Orchard.Tags,Orchard.Themes,Orchard.Users,Orchard.Scripting,Orchard.Scripting.Lightweight,Orchard.Widgets,TinyMce,TheThemeMachine,Orchard.Tokens,Orchard.Alias,Orchard.Autoroute
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Orchard.Specs.Bindings {
|
||||
virtualDirectory,
|
||||
TableData(
|
||||
new { extension = "Module", names = "Lucene, Markdown, Orchard.Alias, Orchard.AntiSpam, Orchard.ArchiveLater, Orchard.Autoroute, Orchard.Azure, Orchard.Blogs, Orchard.Caching, Orchard.CodeGeneration, Orchard.Comments, Orchard.ContentPermissions, Orchard.ContentPicker, Orchard.ContentTypes, Orchard.CustomForms, Orchard.DesignerTools, Orchard.Email, Orchard.Fields, Orchard.Forms, Orchard.ImageEditor, Orchard.ImportExport, Orchard.Indexing, Orchard.JobsQueue, Orchard.jQuery, Orchard.Layouts, Orchard.Lists, Orchard.Localization, Orchard.Media, Orchard.MediaLibrary, Orchard.MediaPicker, Orchard.MediaProcessing, Orchard.Migrations, Orchard.Modules, Orchard.MultiTenancy, Orchard.OutputCache, Orchard.Packaging, Orchard.Pages, Orchard.Projections, Orchard.PublishLater, Orchard.Recipes, Orchard.Roles, Orchard.Rules, Orchard.Scripting, Orchard.Scripting.CSharp, Orchard.Scripting.Dlr, Orchard.Search, Orchard.SecureSocketsLayer, Orchard.Setup, Orchard.Tags, Orchard.TaskLease, Orchard.Taxonomies, Orchard.Templates, Orchard.Themes, Orchard.Tokens, Orchard.Users, Orchard.Warmup, Orchard.Widgets, Orchard.Workflows, SysCache, TinyMce, Upgrade" },
|
||||
new { extension = "Core", names = "Common, Containers, Contents, Dashboard, Feeds, Navigation, Scheduling, Settings, Shapes, Title, XmlRpc" },
|
||||
new { extension = "Core", names = "Common, Containers, Contents, Dashboard, Feeds, Navigation, Reports, Scheduling, Settings, Shapes, Title, XmlRpc" },
|
||||
new { extension = "Theme", names = "SafeMode, TheAdmin, TheThemeMachine" }));
|
||||
|
||||
webApp.WhenIGoTo("Setup");
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<system.web>
|
||||
<compilation targetFramework="4.5">
|
||||
<assemblies>
|
||||
<add assembly="System.Web.Mvc, Version=5.2.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/>
|
||||
<add assembly="System.Web.Mvc, Version=5.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/>
|
||||
</assemblies>
|
||||
</compilation>
|
||||
<pages>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user