Update: New Plugin Framework
Plugin Framework re-written. Initial commit.
This commit is contained in:
+232
-231
@@ -1,232 +1,233 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{095E6F94-3C34-47AE-BB83-46203535E0F6}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Disco</RootNamespace>
|
||||
<AssemblyName>Disco.BI</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="BitMiracle.LibTiff.NET">
|
||||
<HintPath>..\Resources\Libraries\LibTiff.NET\BitMiracle.LibTiff.NET.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="EntityFramework">
|
||||
<HintPath>..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="itextsharp">
|
||||
<HintPath>..\Resources\Libraries\iTextSharp\itextsharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Quartz">
|
||||
<HintPath>..\Resources\Libraries\Quartz\Quartz.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SignalR, Version=0.5.1.10822, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\SignalR.Server.0.5.3\lib\net40\SignalR.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SignalR.Hosting.AspNet, Version=0.5.1.10822, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\SignalR.Hosting.AspNet.0.5.3\lib\net45\SignalR.Hosting.AspNet.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SignalR.Hosting.Common">
|
||||
<HintPath>..\packages\SignalR.Hosting.Common.0.5.3\lib\net40\SignalR.Hosting.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Spring.Core">
|
||||
<HintPath>..\Resources\Libraries\Spring.NET\Spring.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.Entity" />
|
||||
<Reference Include="System.DirectoryServices" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Management" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<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.Xml" />
|
||||
<Reference Include="Tamir.SharpSSH">
|
||||
<HintPath>..\Resources\Libraries\SharpSSH\Tamir.SharpSSH.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="zxing">
|
||||
<HintPath>..\Resources\Libraries\ZXing\zxing.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BI\DataStore.cs" />
|
||||
<Compile Include="BI\AttachmentBI\Utilities.cs" />
|
||||
<Compile Include="BI\DeviceBI\BatchUtilities.cs" />
|
||||
<Compile Include="BI\DeviceBI\Searching.cs" />
|
||||
<Compile Include="BI\DisposableImageCollection.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\DocumentTemplateQRCodeLocationCache.cs" />
|
||||
<Compile Include="BI\Expressions\EvaluateExpressionParseException.cs" />
|
||||
<Compile Include="BI\Expressions\ExpressionCachePreloadTask.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\DataExt.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\DeviceExt.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\ImageExt.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\ImageResultImplementations\BaseImageExpressionResult.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\ImageResultImplementations\FileMontageImageExpressionResult.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\ImageResultImplementations\FileImageExpressionResult.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\ImageResultImplementations\BitmapImageExpressionResult.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\UserExt.cs" />
|
||||
<Compile Include="BI\Extensions\AttachmentActionExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\AttachmentExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\ClientServicesExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceActionExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceBatchExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceCertificateExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceModelExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceProfileExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\JobActionExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\JobExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\JobFlagExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\JobTableExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\UserExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\WirelessCertificateExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceExtensions.cs" />
|
||||
<Compile Include="BI\DeviceBI\EnrolSafeException.cs" />
|
||||
<Compile Include="BI\DeviceBI\Enrol.cs" />
|
||||
<Compile Include="BI\DeviceBI\EnrolmentLog.cs" />
|
||||
<Compile Include="BI\Extensions\DocumentTemplateExtensions.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\Utilities.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\DocumentUniqueIdentifier.cs" />
|
||||
<Compile Include="BI\Expressions\EvaluateExpressionPart.cs" />
|
||||
<Compile Include="BI\Expressions\Expression.cs" />
|
||||
<Compile Include="BI\Expressions\ExpressionTypeDescriptor.cs" />
|
||||
<Compile Include="BI\Expressions\ExpressionTypeMemberDescriptor.cs" />
|
||||
<Compile Include="BI\Expressions\IExpressionPart.cs" />
|
||||
<Compile Include="BI\Expressions\TextExpressionPart.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentDropBoxMonitor.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterJob.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterCleanCacheJob.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterLog.cs" />
|
||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectory.cs" />
|
||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryCachedGroups.cs" />
|
||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryHelpers.cs" />
|
||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryMachineAccountExtensions.cs" />
|
||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryOrganisationalUnit.cs" />
|
||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryUpdateLastNetworkLogonDateJob.cs" />
|
||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryUserAccountExtensions.cs" />
|
||||
<Compile Include="BI\Expressions\ExpressionCache.cs" />
|
||||
<Compile Include="BI\Interop\Community\UpdateCheck.cs" />
|
||||
<Compile Include="BI\Interop\Community\UpdateCheckTask.cs" />
|
||||
<Compile Include="BI\Interop\MimeTypes.cs" />
|
||||
<Compile Include="BI\Interop\Pdf\PdfGenerator.cs" />
|
||||
<Compile Include="BI\Interop\Pdf\PdfImporter.cs" />
|
||||
<Compile Include="BI\Interop\PluginServices\IDiscoScheduledTask.cs" />
|
||||
<Compile Include="BI\Interop\PluginServices\Utilities.cs" />
|
||||
<Compile Include="BI\Interop\SignalRHandlers\UserHeldDevices.cs" />
|
||||
<Compile Include="BI\JobBI\Searching.cs" />
|
||||
<Compile Include="BI\JobBI\Statistics\DailyOpenedClosed.cs" />
|
||||
<Compile Include="BI\JobBI\Utilities.cs" />
|
||||
<Compile Include="BI\UserBI\Searching.cs" />
|
||||
<Compile Include="BI\UserBI\UserCache.cs" />
|
||||
<Compile Include="BI\UserBI\Utilities.cs" />
|
||||
<Compile Include="BI\Extensions\UtilityExtensions.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Disco.Data\Disco.Data.csproj">
|
||||
<Project>{85A6BD19-2C64-4746-8F2C-A68A86E8C2D7}</Project>
|
||||
<Name>Disco.Data</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Disco.Models\Disco.Models.csproj">
|
||||
<Project>{FBC05512-FCCA-4B16-9E76-8C413C5DE6C9}</Project>
|
||||
<Name>Disco.Models</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Disco.Services\Disco.Services.csproj">
|
||||
<Project>{B80A737F-BD6A-4986-9182-DD7B932BD950}</Project>
|
||||
<Name>Disco.Services</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-img16.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-pdf16.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\EmptyLogo.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-doc48.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-pdf48.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-unknown48.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="BI\CertificateBI\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties BuildVersion_UseGlobalSettings="True" BuildVersion_DetectChanges="False" BuildVersion_BuildAction="ReBuild" BuildVersion_StartDate="2001/1/1" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.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>
|
||||
-->
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{095E6F94-3C34-47AE-BB83-46203535E0F6}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Disco</RootNamespace>
|
||||
<AssemblyName>Disco.BI</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="BitMiracle.LibTiff.NET">
|
||||
<HintPath>..\Resources\Libraries\LibTiff.NET\BitMiracle.LibTiff.NET.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="EntityFramework">
|
||||
<HintPath>..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="itextsharp">
|
||||
<HintPath>..\Resources\Libraries\iTextSharp\itextsharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Quartz">
|
||||
<HintPath>..\Resources\Libraries\Quartz\Quartz.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SignalR, Version=0.5.1.10822, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\SignalR.Server.0.5.3\lib\net40\SignalR.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SignalR.Hosting.AspNet, Version=0.5.1.10822, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\SignalR.Hosting.AspNet.0.5.3\lib\net45\SignalR.Hosting.AspNet.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SignalR.Hosting.Common">
|
||||
<HintPath>..\packages\SignalR.Hosting.Common.0.5.3\lib\net40\SignalR.Hosting.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Spring.Core">
|
||||
<HintPath>..\Resources\Libraries\Spring.NET\Spring.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.Entity" />
|
||||
<Reference Include="System.DirectoryServices" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Management" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<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.Xml" />
|
||||
<Reference Include="Tamir.SharpSSH">
|
||||
<HintPath>..\Resources\Libraries\SharpSSH\Tamir.SharpSSH.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="zxing">
|
||||
<HintPath>..\Resources\Libraries\ZXing\zxing.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BI\DataStore.cs" />
|
||||
<Compile Include="BI\AttachmentBI\Utilities.cs" />
|
||||
<Compile Include="BI\DeviceBI\BatchUtilities.cs" />
|
||||
<Compile Include="BI\DeviceBI\DeviceModelBI.cs" />
|
||||
<Compile Include="BI\DeviceBI\Searching.cs" />
|
||||
<Compile Include="BI\DisposableImageCollection.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\DocumentTemplateQRCodeLocationCache.cs" />
|
||||
<Compile Include="BI\Expressions\EvaluateExpressionParseException.cs" />
|
||||
<Compile Include="BI\Expressions\ExpressionCachePreloadTask.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\DataExt.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\DeviceExt.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\ImageExt.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\ImageResultImplementations\BaseImageExpressionResult.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\ImageResultImplementations\FileMontageImageExpressionResult.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\ImageResultImplementations\FileImageExpressionResult.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\ImageResultImplementations\BitmapImageExpressionResult.cs" />
|
||||
<Compile Include="BI\Expressions\Extensions\UserExt.cs" />
|
||||
<Compile Include="BI\Extensions\AttachmentActionExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\AttachmentExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\ClientServicesExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceActionExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceBatchExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceCertificateExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceModelExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceProfileExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\JobActionExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\JobExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\JobFlagExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\JobTableExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\UserExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\WirelessCertificateExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceExtensions.cs" />
|
||||
<Compile Include="BI\DeviceBI\EnrolSafeException.cs" />
|
||||
<Compile Include="BI\DeviceBI\Enrol.cs" />
|
||||
<Compile Include="BI\DeviceBI\EnrolmentLog.cs" />
|
||||
<Compile Include="BI\Extensions\DocumentTemplateExtensions.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\Utilities.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\DocumentUniqueIdentifier.cs" />
|
||||
<Compile Include="BI\Expressions\EvaluateExpressionPart.cs" />
|
||||
<Compile Include="BI\Expressions\Expression.cs" />
|
||||
<Compile Include="BI\Expressions\ExpressionTypeDescriptor.cs" />
|
||||
<Compile Include="BI\Expressions\ExpressionTypeMemberDescriptor.cs" />
|
||||
<Compile Include="BI\Expressions\IExpressionPart.cs" />
|
||||
<Compile Include="BI\Expressions\TextExpressionPart.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentDropBoxMonitor.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterJob.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterCleanCacheJob.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterLog.cs" />
|
||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectory.cs" />
|
||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryCachedGroups.cs" />
|
||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryHelpers.cs" />
|
||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryMachineAccountExtensions.cs" />
|
||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryOrganisationalUnit.cs" />
|
||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryUpdateLastNetworkLogonDateJob.cs" />
|
||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryUserAccountExtensions.cs" />
|
||||
<Compile Include="BI\Expressions\ExpressionCache.cs" />
|
||||
<Compile Include="BI\Interop\Community\UpdateCheck.cs" />
|
||||
<Compile Include="BI\Interop\Community\UpdateCheckTask.cs" />
|
||||
<Compile Include="BI\Interop\MimeTypes.cs" />
|
||||
<Compile Include="BI\Interop\Pdf\PdfGenerator.cs" />
|
||||
<Compile Include="BI\Interop\Pdf\PdfImporter.cs" />
|
||||
<Compile Include="BI\Interop\PluginServices\IDiscoScheduledTask.cs" />
|
||||
<Compile Include="BI\Interop\PluginServices\Utilities.cs" />
|
||||
<Compile Include="BI\Interop\SignalRHandlers\UserHeldDevices.cs" />
|
||||
<Compile Include="BI\JobBI\Searching.cs" />
|
||||
<Compile Include="BI\JobBI\Statistics\DailyOpenedClosed.cs" />
|
||||
<Compile Include="BI\JobBI\Utilities.cs" />
|
||||
<Compile Include="BI\UserBI\Searching.cs" />
|
||||
<Compile Include="BI\UserBI\UserCache.cs" />
|
||||
<Compile Include="BI\UserBI\Utilities.cs" />
|
||||
<Compile Include="BI\Extensions\UtilityExtensions.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Disco.Data\Disco.Data.csproj">
|
||||
<Project>{85A6BD19-2C64-4746-8F2C-A68A86E8C2D7}</Project>
|
||||
<Name>Disco.Data</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Disco.Models\Disco.Models.csproj">
|
||||
<Project>{FBC05512-FCCA-4B16-9E76-8C413C5DE6C9}</Project>
|
||||
<Name>Disco.Models</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Disco.Services\Disco.Services.csproj">
|
||||
<Project>{B80A737F-BD6A-4986-9182-DD7B932BD950}</Project>
|
||||
<Name>Disco.Services</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-img16.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-pdf16.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\EmptyLogo.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-doc48.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-pdf48.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-unknown48.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="BI\CertificateBI\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties BuildVersion_StartDate="2001/1/1" BuildVersion_BuildAction="ReBuild" BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="True" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.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>
|
||||
@@ -1,36 +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("Disco - Business Intelligence")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[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("01887659-9fd6-4464-8493-cf0506ee2569")]
|
||||
|
||||
// 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.2.0131.2002")]
|
||||
[assembly: AssemblyFileVersion("1.2.0131.2002")]
|
||||
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("Disco - Business Intelligence")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[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("01887659-9fd6-4464-8493-cf0506ee2569")]
|
||||
|
||||
// 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.2.0207.1727")]
|
||||
[assembly: AssemblyFileVersion("1.2.0207.1727")]
|
||||
|
||||
Binary file not shown.
@@ -1,36 +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("Disco - Client")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[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("aa39bf57-b0e8-43ba-a29a-f38b3e5b189c")]
|
||||
|
||||
// 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.2.0131.2002")]
|
||||
[assembly: AssemblyFileVersion("1.2.0131.2002")]
|
||||
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("Disco - Client")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[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("aa39bf57-b0e8-43ba-a29a-f38b3e5b189c")]
|
||||
|
||||
// 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.2.0207.1727")]
|
||||
[assembly: AssemblyFileVersion("1.2.0207.1727")]
|
||||
|
||||
@@ -1,36 +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("Disco - Client Bootstrapper")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[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("5d11beb8-8b5f-4842-8604-9f2d8284f04d")]
|
||||
|
||||
// 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.2.0131.2002")]
|
||||
[assembly: AssemblyFileVersion("1.2.0131.2002")]
|
||||
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("Disco - Client Bootstrapper")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[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("5d11beb8-8b5f-4842-8604-9f2d8284f04d")]
|
||||
|
||||
// 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.2.0207.1727")]
|
||||
[assembly: AssemblyFileVersion("1.2.0207.1727")]
|
||||
|
||||
@@ -1,472 +1,479 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using Disco.Models.BI.Interop.Community;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Disco.Data.Configuration
|
||||
{
|
||||
public class ConfigurationContext
|
||||
{
|
||||
private DiscoDataContext _dbContext;
|
||||
private DiscoDataContext dbContext
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dbContext != null)
|
||||
return _dbContext;
|
||||
else
|
||||
throw new InvalidOperationException("Cache-miss where Configuration Item requested from Cache-Only Configuration Context");
|
||||
}
|
||||
}
|
||||
|
||||
public bool CacheOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
return _dbContext == null;
|
||||
}
|
||||
}
|
||||
|
||||
public ConfigurationContext(DiscoDataContext dbContext)
|
||||
{
|
||||
this._dbContext = dbContext;
|
||||
|
||||
// Init Modules
|
||||
this.moduleBootstrapperConfiguration = new Lazy<Modules.BootstrapperConfiguration>(() => new Modules.BootstrapperConfiguration(this));
|
||||
this.moduleDeviceProfilesConfiguration = new Lazy<Modules.DeviceProfilesConfiguration>(() => new Modules.DeviceProfilesConfiguration(this));
|
||||
this.moduleOrganisationAddressesConfiguration = new Lazy<Modules.OrganisationAddressesConfiguration>(() => new Modules.OrganisationAddressesConfiguration(this));
|
||||
this.moduleWirelessConfiguration = new Lazy<Modules.WirelessConfiguration>(() => new Modules.WirelessConfiguration(this));
|
||||
}
|
||||
|
||||
#region Item Cache
|
||||
|
||||
private static Dictionary<String, Dictionary<String, ConfigurationItem>> configDictionary = new Dictionary<string, Dictionary<string, ConfigurationItem>>();
|
||||
private static List<ConfigurationItem> configurationItems = new List<ConfigurationItem>();
|
||||
private static object configurationItemsLock = new object();
|
||||
|
||||
private void loadConfigurationItems(string Scope, bool Reload)
|
||||
{
|
||||
if (Reload || !configDictionary.ContainsKey(Scope))
|
||||
{
|
||||
lock (configurationItemsLock)
|
||||
{
|
||||
if (Reload || !configDictionary.ContainsKey(Scope))
|
||||
{
|
||||
var newItems = this.dbContext.ConfigurationItems.Where(ci => ci.Scope == Scope).ToArray();
|
||||
|
||||
if (configDictionary.ContainsKey(Scope))
|
||||
{
|
||||
var existingItems = configDictionary[Scope];
|
||||
foreach (var existingItem in existingItems.Values)
|
||||
{
|
||||
configurationItems.Remove(existingItem);
|
||||
}
|
||||
}
|
||||
configurationItems.AddRange(newItems);
|
||||
configDictionary[Scope] = newItems.ToDictionary(ci => ci.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public Dictionary<string, Dictionary<string, ConfigurationItem>> ConfigurationDictionary(string IncludingScope)
|
||||
{
|
||||
this.loadConfigurationItems(IncludingScope, false);
|
||||
return configDictionary;
|
||||
}
|
||||
public ConfigurationItem ConfigurationItem(string Scope, string Key)
|
||||
{
|
||||
Dictionary<string, ConfigurationItem> scopeDict = default(Dictionary<string, ConfigurationItem>);
|
||||
if (this.ConfigurationDictionary(Scope).TryGetValue(Scope, out scopeDict))
|
||||
{
|
||||
ConfigurationItem item = default(ConfigurationItem);
|
||||
if (scopeDict.TryGetValue(Key, out item))
|
||||
return item;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private List<ConfigurationItem> ConfigurationItems(string IncludingScope)
|
||||
{
|
||||
this.loadConfigurationItems(IncludingScope, false);
|
||||
return configurationItems;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
public ValueType GetConfigurationValue<ValueType>(string Scope, string Key, ValueType Default)
|
||||
{
|
||||
var ci = this.ConfigurationItem(Scope, Key);
|
||||
if (ci == null)
|
||||
return Default;
|
||||
else
|
||||
return (ValueType)Convert.ChangeType(ci.Value, typeof(ValueType));
|
||||
}
|
||||
public void SetConfigurationValue<ValueType>(string Scope, string Key, ValueType Value)
|
||||
{
|
||||
if (CacheOnly)
|
||||
throw new InvalidOperationException("Cannot save changes with a CacheOnly Context");
|
||||
|
||||
var ci = this.ConfigurationItem(Scope, Key);
|
||||
if (ci == null && Value != null)
|
||||
{
|
||||
lock (configurationItemsLock)
|
||||
{
|
||||
ci = this.ConfigurationItem(Scope, Key);
|
||||
if (ci == null)
|
||||
{
|
||||
// Create Configuration Item
|
||||
ci = new ConfigurationItem() { Scope = Scope, Key = Key, Value = Value.ToString() };
|
||||
// Add Item to DB & Internal Collections
|
||||
this.dbContext.ConfigurationItems.Add(ci);
|
||||
this.ConfigurationItems(Scope).Add(ci);
|
||||
this.ConfigurationDictionary(Scope)[Scope].Add(Key, ci);
|
||||
ci = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ci != null)
|
||||
{
|
||||
lock (configurationItemsLock)
|
||||
{
|
||||
var entityInfo = dbContext.Entry(ci);
|
||||
if (entityInfo.State == System.Data.EntityState.Detached)
|
||||
{
|
||||
// Reload Scope from DB
|
||||
this.loadConfigurationItems(Scope, true);
|
||||
ci = this.ConfigurationItem(Scope, Key);
|
||||
}
|
||||
|
||||
if (Value == null)
|
||||
{
|
||||
dbContext.ConfigurationItems.Remove(ci);
|
||||
configurationItems.Remove(ci);
|
||||
configDictionary[Scope].Remove(Key);
|
||||
}
|
||||
else
|
||||
{
|
||||
ci.Value = Value.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string ObsfucateValue(string Value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Value))
|
||||
return Value;
|
||||
else
|
||||
return Convert.ToBase64String(Encoding.Unicode.GetBytes(Value));
|
||||
}
|
||||
public static string DeobsfucateValue(string ObsfucatedValue)
|
||||
{
|
||||
if (string.IsNullOrEmpty(ObsfucatedValue))
|
||||
return ObsfucatedValue;
|
||||
else
|
||||
return Encoding.Unicode.GetString(Convert.FromBase64String(ObsfucatedValue));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Configuration Modules
|
||||
|
||||
private Lazy<Modules.BootstrapperConfiguration> moduleBootstrapperConfiguration;
|
||||
private Lazy<Modules.DeviceProfilesConfiguration> moduleDeviceProfilesConfiguration;
|
||||
private Lazy<Modules.OrganisationAddressesConfiguration> moduleOrganisationAddressesConfiguration;
|
||||
private Lazy<Modules.WirelessConfiguration> moduleWirelessConfiguration;
|
||||
|
||||
public Modules.BootstrapperConfiguration Bootstrapper
|
||||
{
|
||||
get
|
||||
{
|
||||
return moduleBootstrapperConfiguration.Value;
|
||||
}
|
||||
}
|
||||
public Modules.DeviceProfilesConfiguration DeviceProfiles
|
||||
{
|
||||
get
|
||||
{
|
||||
return moduleDeviceProfilesConfiguration.Value;
|
||||
}
|
||||
}
|
||||
public Modules.OrganisationAddressesConfiguration OrganisationAddresses
|
||||
{
|
||||
get
|
||||
{
|
||||
return moduleOrganisationAddressesConfiguration.Value;
|
||||
}
|
||||
}
|
||||
public Modules.WirelessConfiguration Wireless
|
||||
{
|
||||
get
|
||||
{
|
||||
return moduleWirelessConfiguration.Value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region System Configuration Items
|
||||
|
||||
public string Scope { get { return "System"; } }
|
||||
|
||||
public string DataStoreLocation
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = this.GetConfigurationValue<string>(this.Scope, "DataStoreLocation", null);
|
||||
if (result == null)
|
||||
{
|
||||
var appDataPath = System.Web.HttpContext.Current.Server.MapPath("~/App_Data");
|
||||
if (appDataPath.EndsWith("\\"))
|
||||
return appDataPath;
|
||||
else
|
||||
return string.Concat(appDataPath, '\\');
|
||||
}
|
||||
else
|
||||
return result;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
if (!System.IO.Directory.Exists(value))
|
||||
throw new System.IO.DirectoryNotFoundException(string.Format("DataStoreLocation: '{0}' could not be found", value));
|
||||
string storePath;
|
||||
if (value.EndsWith("\\"))
|
||||
storePath = value;
|
||||
else
|
||||
storePath = string.Concat(value, '\\');
|
||||
this.SetConfigurationValue(this.Scope, "DataStoreLocation", storePath);
|
||||
}
|
||||
}
|
||||
public string PluginsLocation
|
||||
{
|
||||
get
|
||||
{
|
||||
return System.IO.Path.Combine(this.DataStoreLocation, @"Plugins\");
|
||||
}
|
||||
}
|
||||
public string PluginStorageLocation
|
||||
{
|
||||
get
|
||||
{
|
||||
return System.IO.Path.Combine(this.DataStoreLocation, @"PluginStorage\");
|
||||
}
|
||||
}
|
||||
#region Organisation Logo
|
||||
private string OrganisationLogoPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return System.IO.Path.Combine(DataStoreLocation, "OrganisationLogo.png");
|
||||
}
|
||||
}
|
||||
//private static string _OrganisationLogoHash;
|
||||
//private static byte[] _OrganisationLogo;
|
||||
//private static object _OrganisationLogoLock = new object();
|
||||
//private static void LoadOrganisationLogo(ConfigurationContext context, bool reload = false)
|
||||
//{
|
||||
// if (_OrganisationLogoHash == null || reload)
|
||||
// {
|
||||
// lock (_OrganisationLogoLock)
|
||||
// {
|
||||
// if (_OrganisationLogoHash == null || reload)
|
||||
// {
|
||||
// _OrganisationLogo = null;
|
||||
// _OrganisationLogoHash = null;
|
||||
|
||||
// string organisationLogoPath = context.OrganisationLogoPath;
|
||||
// if (System.IO.File.Exists(organisationLogoPath))
|
||||
// _OrganisationLogo = System.IO.File.ReadAllBytes(organisationLogoPath);
|
||||
// }
|
||||
// if (_OrganisationLogo == null || _OrganisationLogo.Length == 0)
|
||||
// {
|
||||
// _OrganisationLogo = Disco.Data.Properties.Resources.EmptyLogo;
|
||||
// }
|
||||
// if (_OrganisationLogoHash == null)
|
||||
// {
|
||||
// using (SHA256 h = SHA256.Create())
|
||||
// {
|
||||
// _OrganisationLogoHash = Convert.ToBase64String(h.ComputeHash(_OrganisationLogo));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
public string OrganisationLogoHash
|
||||
{
|
||||
get
|
||||
{
|
||||
var path = this.OrganisationLogoPath;
|
||||
if (File.Exists(path))
|
||||
return File.GetLastWriteTimeUtc(path).ToBinary().ToString();
|
||||
else
|
||||
return "-1";
|
||||
}
|
||||
}
|
||||
public Stream OrganisationLogo
|
||||
{
|
||||
get
|
||||
{
|
||||
//LoadOrganisationLogo(this);
|
||||
//if (_OrganisationLogo == null || _OrganisationLogo.Length != 0)
|
||||
// return new MemoryStream(_OrganisationLogo);
|
||||
//else
|
||||
// return null;
|
||||
var path = this.OrganisationLogoPath;
|
||||
if (File.Exists(path))
|
||||
return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
else
|
||||
return new MemoryStream(Disco.Data.Properties.Resources.EmptyLogo);
|
||||
}
|
||||
set
|
||||
{
|
||||
string organisationLogoPath = this.OrganisationLogoPath;
|
||||
if (value == null)
|
||||
{
|
||||
if (System.IO.File.Exists(organisationLogoPath))
|
||||
System.IO.File.Delete(organisationLogoPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (FileStream fs = new FileStream(organisationLogoPath, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
value.CopyTo(fs);
|
||||
}
|
||||
}
|
||||
//LoadOrganisationLogo(this, true);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
public string OrganisationName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetConfigurationValue<string>(this.Scope, "OrganisationName", null);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetConfigurationValue(this.Scope, "OrganisationName", value);
|
||||
}
|
||||
}
|
||||
public bool MultiSiteMode
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetConfigurationValue<bool>(this.Scope, "MultiSiteMode", false);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetConfigurationValue(this.Scope, "MultiSiteMode", value);
|
||||
}
|
||||
}
|
||||
|
||||
#region Proxy Configuration
|
||||
public string ProxyAddress
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetConfigurationValue<string>(this.Scope, "ProxyAddress", null);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetConfigurationValue(this.Scope, "ProxyAddress", value);
|
||||
}
|
||||
}
|
||||
public int ProxyPort
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetConfigurationValue(this.Scope, "ProxyPort", 8080);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetConfigurationValue(this.Scope, "ProxyPort", value);
|
||||
}
|
||||
}
|
||||
public string ProxyUsername
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetConfigurationValue<string>(this.Scope, "ProxyUsername", null);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetConfigurationValue(this.Scope, "ProxyUsername", value);
|
||||
}
|
||||
}
|
||||
public string ProxyPassword
|
||||
{
|
||||
get
|
||||
{
|
||||
return DeobsfucateValue(this.GetConfigurationValue<string>(this.Scope, "ProxyPassword", null));
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetConfigurationValue(this.Scope, "ProxyPassword", ObsfucateValue(value));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UpdateCheck
|
||||
public string DeploymentId
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetConfigurationValue<string>(this.Scope, "DeploymentId", null);
|
||||
}
|
||||
}
|
||||
public UpdateResponse UpdateLastCheck
|
||||
{
|
||||
get
|
||||
{
|
||||
var json = this.GetConfigurationValue<string>(this.Scope, "UpdateLastCheck", null);
|
||||
if (json != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return JsonConvert.DeserializeObject<UpdateResponse>(json);
|
||||
}
|
||||
catch (Exception)
|
||||
{ }// Ignore Serialization Issues
|
||||
}
|
||||
return null;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
this.SetConfigurationValue<string>(this.Scope, "UpdateLastCheck", null);
|
||||
|
||||
var json = JsonConvert.SerializeObject(value);
|
||||
this.SetConfigurationValue<string>(this.Scope, "UpdateLastCheck", json);
|
||||
}
|
||||
}
|
||||
public bool UpdateBetaDeployment
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetConfigurationValue<bool>(this.Scope, "UpdateBetaDeployment", false);
|
||||
}
|
||||
}
|
||||
public string InstalledDatabaseVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetConfigurationValue<string>(this.Scope, "InstalledDatabaseVersion", null);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetConfigurationValue<string>(this.Scope, "InstalledDatabaseVersion", value);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using Disco.Models.BI.Interop.Community;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Disco.Data.Configuration
|
||||
{
|
||||
public class ConfigurationContext
|
||||
{
|
||||
private DiscoDataContext _dbContext;
|
||||
private DiscoDataContext dbContext
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dbContext != null)
|
||||
return _dbContext;
|
||||
else
|
||||
throw new InvalidOperationException("Cache-miss where Configuration Item requested from Cache-Only Configuration Context");
|
||||
}
|
||||
}
|
||||
|
||||
public bool CacheOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
return _dbContext == null;
|
||||
}
|
||||
}
|
||||
|
||||
public ConfigurationContext(DiscoDataContext dbContext)
|
||||
{
|
||||
this._dbContext = dbContext;
|
||||
|
||||
// Init Modules
|
||||
this.moduleBootstrapperConfiguration = new Lazy<Modules.BootstrapperConfiguration>(() => new Modules.BootstrapperConfiguration(this));
|
||||
this.moduleDeviceProfilesConfiguration = new Lazy<Modules.DeviceProfilesConfiguration>(() => new Modules.DeviceProfilesConfiguration(this));
|
||||
this.moduleOrganisationAddressesConfiguration = new Lazy<Modules.OrganisationAddressesConfiguration>(() => new Modules.OrganisationAddressesConfiguration(this));
|
||||
this.moduleWirelessConfiguration = new Lazy<Modules.WirelessConfiguration>(() => new Modules.WirelessConfiguration(this));
|
||||
}
|
||||
|
||||
#region Item Cache
|
||||
|
||||
private static Dictionary<String, Dictionary<String, ConfigurationItem>> configDictionary = new Dictionary<string, Dictionary<string, ConfigurationItem>>();
|
||||
private static List<ConfigurationItem> configurationItems = new List<ConfigurationItem>();
|
||||
private static object configurationItemsLock = new object();
|
||||
|
||||
private void loadConfigurationItems(string Scope, bool Reload)
|
||||
{
|
||||
if (Reload || !configDictionary.ContainsKey(Scope))
|
||||
{
|
||||
lock (configurationItemsLock)
|
||||
{
|
||||
if (Reload || !configDictionary.ContainsKey(Scope))
|
||||
{
|
||||
var newItems = this.dbContext.ConfigurationItems.Where(ci => ci.Scope == Scope).ToArray();
|
||||
|
||||
if (configDictionary.ContainsKey(Scope))
|
||||
{
|
||||
var existingItems = configDictionary[Scope];
|
||||
foreach (var existingItem in existingItems.Values)
|
||||
{
|
||||
configurationItems.Remove(existingItem);
|
||||
}
|
||||
}
|
||||
configurationItems.AddRange(newItems);
|
||||
configDictionary[Scope] = newItems.ToDictionary(ci => ci.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public Dictionary<string, Dictionary<string, ConfigurationItem>> ConfigurationDictionary(string IncludingScope)
|
||||
{
|
||||
this.loadConfigurationItems(IncludingScope, false);
|
||||
return configDictionary;
|
||||
}
|
||||
public ConfigurationItem ConfigurationItem(string Scope, string Key)
|
||||
{
|
||||
Dictionary<string, ConfigurationItem> scopeDict = default(Dictionary<string, ConfigurationItem>);
|
||||
if (this.ConfigurationDictionary(Scope).TryGetValue(Scope, out scopeDict))
|
||||
{
|
||||
ConfigurationItem item = default(ConfigurationItem);
|
||||
if (scopeDict.TryGetValue(Key, out item))
|
||||
return item;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private List<ConfigurationItem> ConfigurationItems(string IncludingScope)
|
||||
{
|
||||
this.loadConfigurationItems(IncludingScope, false);
|
||||
return configurationItems;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
public ValueType GetConfigurationValue<ValueType>(string Scope, string Key, ValueType Default)
|
||||
{
|
||||
var ci = this.ConfigurationItem(Scope, Key);
|
||||
if (ci == null)
|
||||
return Default;
|
||||
else
|
||||
return (ValueType)Convert.ChangeType(ci.Value, typeof(ValueType));
|
||||
}
|
||||
public void SetConfigurationValue<ValueType>(string Scope, string Key, ValueType Value)
|
||||
{
|
||||
if (CacheOnly)
|
||||
throw new InvalidOperationException("Cannot save changes with a CacheOnly Context");
|
||||
|
||||
var ci = this.ConfigurationItem(Scope, Key);
|
||||
if (ci == null && Value != null)
|
||||
{
|
||||
lock (configurationItemsLock)
|
||||
{
|
||||
ci = this.ConfigurationItem(Scope, Key);
|
||||
if (ci == null)
|
||||
{
|
||||
// Create Configuration Item
|
||||
ci = new ConfigurationItem() { Scope = Scope, Key = Key, Value = Value.ToString() };
|
||||
// Add Item to DB & Internal Collections
|
||||
this.dbContext.ConfigurationItems.Add(ci);
|
||||
this.ConfigurationItems(Scope).Add(ci);
|
||||
this.ConfigurationDictionary(Scope)[Scope].Add(Key, ci);
|
||||
ci = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ci != null)
|
||||
{
|
||||
lock (configurationItemsLock)
|
||||
{
|
||||
var entityInfo = dbContext.Entry(ci);
|
||||
if (entityInfo.State == System.Data.EntityState.Detached)
|
||||
{
|
||||
// Reload Scope from DB
|
||||
this.loadConfigurationItems(Scope, true);
|
||||
ci = this.ConfigurationItem(Scope, Key);
|
||||
}
|
||||
|
||||
if (Value == null)
|
||||
{
|
||||
dbContext.ConfigurationItems.Remove(ci);
|
||||
configurationItems.Remove(ci);
|
||||
configDictionary[Scope].Remove(Key);
|
||||
}
|
||||
else
|
||||
{
|
||||
ci.Value = Value.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string ObsfucateValue(string Value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Value))
|
||||
return Value;
|
||||
else
|
||||
return Convert.ToBase64String(Encoding.Unicode.GetBytes(Value));
|
||||
}
|
||||
public static string DeobsfucateValue(string ObsfucatedValue)
|
||||
{
|
||||
if (string.IsNullOrEmpty(ObsfucatedValue))
|
||||
return ObsfucatedValue;
|
||||
else
|
||||
return Encoding.Unicode.GetString(Convert.FromBase64String(ObsfucatedValue));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Configuration Modules
|
||||
|
||||
private Lazy<Modules.BootstrapperConfiguration> moduleBootstrapperConfiguration;
|
||||
private Lazy<Modules.DeviceProfilesConfiguration> moduleDeviceProfilesConfiguration;
|
||||
private Lazy<Modules.OrganisationAddressesConfiguration> moduleOrganisationAddressesConfiguration;
|
||||
private Lazy<Modules.WirelessConfiguration> moduleWirelessConfiguration;
|
||||
|
||||
public Modules.BootstrapperConfiguration Bootstrapper
|
||||
{
|
||||
get
|
||||
{
|
||||
return moduleBootstrapperConfiguration.Value;
|
||||
}
|
||||
}
|
||||
public Modules.DeviceProfilesConfiguration DeviceProfiles
|
||||
{
|
||||
get
|
||||
{
|
||||
return moduleDeviceProfilesConfiguration.Value;
|
||||
}
|
||||
}
|
||||
public Modules.OrganisationAddressesConfiguration OrganisationAddresses
|
||||
{
|
||||
get
|
||||
{
|
||||
return moduleOrganisationAddressesConfiguration.Value;
|
||||
}
|
||||
}
|
||||
public Modules.WirelessConfiguration Wireless
|
||||
{
|
||||
get
|
||||
{
|
||||
return moduleWirelessConfiguration.Value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region System Configuration Items
|
||||
|
||||
public string Scope { get { return "System"; } }
|
||||
|
||||
public string DataStoreLocation
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = this.GetConfigurationValue<string>(this.Scope, "DataStoreLocation", null);
|
||||
if (result == null)
|
||||
{
|
||||
var appDataPath = System.Web.HttpContext.Current.Server.MapPath("~/App_Data");
|
||||
if (appDataPath.EndsWith("\\"))
|
||||
return appDataPath;
|
||||
else
|
||||
return string.Concat(appDataPath, '\\');
|
||||
}
|
||||
else
|
||||
return result;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
if (!System.IO.Directory.Exists(value))
|
||||
throw new System.IO.DirectoryNotFoundException(string.Format("DataStoreLocation: '{0}' could not be found", value));
|
||||
string storePath;
|
||||
if (value.EndsWith("\\"))
|
||||
storePath = value;
|
||||
else
|
||||
storePath = string.Concat(value, '\\');
|
||||
this.SetConfigurationValue(this.Scope, "DataStoreLocation", storePath);
|
||||
}
|
||||
}
|
||||
public string PluginsLocation
|
||||
{
|
||||
get
|
||||
{
|
||||
return System.IO.Path.Combine(this.DataStoreLocation, @"Plugins\");
|
||||
}
|
||||
}
|
||||
public string PluginStorageLocation
|
||||
{
|
||||
get
|
||||
{
|
||||
return System.IO.Path.Combine(this.DataStoreLocation, @"PluginStorage\");
|
||||
}
|
||||
}
|
||||
public string PluginPackagesLocation
|
||||
{
|
||||
get
|
||||
{
|
||||
return System.IO.Path.Combine(this.DataStoreLocation, @"PluginPackages\");
|
||||
}
|
||||
}
|
||||
#region Organisation Logo
|
||||
private string OrganisationLogoPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return System.IO.Path.Combine(DataStoreLocation, "OrganisationLogo.png");
|
||||
}
|
||||
}
|
||||
//private static string _OrganisationLogoHash;
|
||||
//private static byte[] _OrganisationLogo;
|
||||
//private static object _OrganisationLogoLock = new object();
|
||||
//private static void LoadOrganisationLogo(ConfigurationContext context, bool reload = false)
|
||||
//{
|
||||
// if (_OrganisationLogoHash == null || reload)
|
||||
// {
|
||||
// lock (_OrganisationLogoLock)
|
||||
// {
|
||||
// if (_OrganisationLogoHash == null || reload)
|
||||
// {
|
||||
// _OrganisationLogo = null;
|
||||
// _OrganisationLogoHash = null;
|
||||
|
||||
// string organisationLogoPath = context.OrganisationLogoPath;
|
||||
// if (System.IO.File.Exists(organisationLogoPath))
|
||||
// _OrganisationLogo = System.IO.File.ReadAllBytes(organisationLogoPath);
|
||||
// }
|
||||
// if (_OrganisationLogo == null || _OrganisationLogo.Length == 0)
|
||||
// {
|
||||
// _OrganisationLogo = Disco.Data.Properties.Resources.EmptyLogo;
|
||||
// }
|
||||
// if (_OrganisationLogoHash == null)
|
||||
// {
|
||||
// using (SHA256 h = SHA256.Create())
|
||||
// {
|
||||
// _OrganisationLogoHash = Convert.ToBase64String(h.ComputeHash(_OrganisationLogo));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
public string OrganisationLogoHash
|
||||
{
|
||||
get
|
||||
{
|
||||
var path = this.OrganisationLogoPath;
|
||||
if (File.Exists(path))
|
||||
return File.GetLastWriteTimeUtc(path).ToBinary().ToString();
|
||||
else
|
||||
return "-1";
|
||||
}
|
||||
}
|
||||
public Stream OrganisationLogo
|
||||
{
|
||||
get
|
||||
{
|
||||
//LoadOrganisationLogo(this);
|
||||
//if (_OrganisationLogo == null || _OrganisationLogo.Length != 0)
|
||||
// return new MemoryStream(_OrganisationLogo);
|
||||
//else
|
||||
// return null;
|
||||
var path = this.OrganisationLogoPath;
|
||||
if (File.Exists(path))
|
||||
return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
else
|
||||
return new MemoryStream(Disco.Data.Properties.Resources.EmptyLogo);
|
||||
}
|
||||
set
|
||||
{
|
||||
string organisationLogoPath = this.OrganisationLogoPath;
|
||||
if (value == null)
|
||||
{
|
||||
if (System.IO.File.Exists(organisationLogoPath))
|
||||
System.IO.File.Delete(organisationLogoPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (FileStream fs = new FileStream(organisationLogoPath, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
value.CopyTo(fs);
|
||||
}
|
||||
}
|
||||
//LoadOrganisationLogo(this, true);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
public string OrganisationName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetConfigurationValue<string>(this.Scope, "OrganisationName", null);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetConfigurationValue(this.Scope, "OrganisationName", value);
|
||||
}
|
||||
}
|
||||
public bool MultiSiteMode
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetConfigurationValue<bool>(this.Scope, "MultiSiteMode", false);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetConfigurationValue(this.Scope, "MultiSiteMode", value);
|
||||
}
|
||||
}
|
||||
|
||||
#region Proxy Configuration
|
||||
public string ProxyAddress
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetConfigurationValue<string>(this.Scope, "ProxyAddress", null);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetConfigurationValue(this.Scope, "ProxyAddress", value);
|
||||
}
|
||||
}
|
||||
public int ProxyPort
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetConfigurationValue(this.Scope, "ProxyPort", 8080);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetConfigurationValue(this.Scope, "ProxyPort", value);
|
||||
}
|
||||
}
|
||||
public string ProxyUsername
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetConfigurationValue<string>(this.Scope, "ProxyUsername", null);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetConfigurationValue(this.Scope, "ProxyUsername", value);
|
||||
}
|
||||
}
|
||||
public string ProxyPassword
|
||||
{
|
||||
get
|
||||
{
|
||||
return DeobsfucateValue(this.GetConfigurationValue<string>(this.Scope, "ProxyPassword", null));
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetConfigurationValue(this.Scope, "ProxyPassword", ObsfucateValue(value));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UpdateCheck
|
||||
public string DeploymentId
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetConfigurationValue<string>(this.Scope, "DeploymentId", null);
|
||||
}
|
||||
}
|
||||
public UpdateResponse UpdateLastCheck
|
||||
{
|
||||
get
|
||||
{
|
||||
var json = this.GetConfigurationValue<string>(this.Scope, "UpdateLastCheck", null);
|
||||
if (json != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return JsonConvert.DeserializeObject<UpdateResponse>(json);
|
||||
}
|
||||
catch (Exception)
|
||||
{ }// Ignore Serialization Issues
|
||||
}
|
||||
return null;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
this.SetConfigurationValue<string>(this.Scope, "UpdateLastCheck", null);
|
||||
|
||||
var json = JsonConvert.SerializeObject(value);
|
||||
this.SetConfigurationValue<string>(this.Scope, "UpdateLastCheck", json);
|
||||
}
|
||||
}
|
||||
public bool UpdateBetaDeployment
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetConfigurationValue<bool>(this.Scope, "UpdateBetaDeployment", false);
|
||||
}
|
||||
}
|
||||
public string InstalledDatabaseVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetConfigurationValue<string>(this.Scope, "InstalledDatabaseVersion", null);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SetConfigurationValue<string>(this.Scope, "InstalledDatabaseVersion", value);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +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("Disco - Data")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[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("77cc3aa4-5055-44aa-97b1-c42e5f5e1acd")]
|
||||
|
||||
// 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.2.0131.2002")]
|
||||
[assembly: AssemblyFileVersion("1.2.0131.2002")]
|
||||
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("Disco - Data")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[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("77cc3aa4-5055-44aa-97b1-c42e5f5e1acd")]
|
||||
|
||||
// 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.2.0207.1727")]
|
||||
[assembly: AssemblyFileVersion("1.2.0207.1727")]
|
||||
|
||||
@@ -1,36 +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("Disco - Data Models")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[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("44f11caf-e8d3-4c5a-9406-d84779e6d427")]
|
||||
|
||||
// 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.2.0131.2002")]
|
||||
[assembly: AssemblyFileVersion("1.2.0131.2002")]
|
||||
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("Disco - Data Models")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[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("44f11caf-e8d3-4c5a-9406-d84779e6d427")]
|
||||
|
||||
// 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.2.0207.1727")]
|
||||
[assembly: AssemblyFileVersion("1.2.0207.1727")]
|
||||
|
||||
@@ -1,188 +1,189 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{B80A737F-BD6A-4986-9182-DD7B932BD950}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Disco.Services</RootNamespace>
|
||||
<AssemblyName>Disco.Services</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="EntityFramework">
|
||||
<HintPath>..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Quartz">
|
||||
<HintPath>..\Resources\Libraries\Quartz\Quartz.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RazorGenerator.Mvc, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\RazorGenerator.Mvc.1.5.0.0\lib\net40\RazorGenerator.Mvc.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SignalR, Version=0.5.1.10822, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\SignalR.Server.0.5.3\lib\net40\SignalR.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SignalR.Hosting.AspNet, Version=0.5.1.10822, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\SignalR.Hosting.AspNet.0.5.3\lib\net45\SignalR.Hosting.AspNet.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SignalR.Hosting.Common">
|
||||
<HintPath>..\packages\SignalR.Hosting.Common.0.5.3\lib\net40\SignalR.Hosting.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.Entity" />
|
||||
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.SqlServer.Compact.4.0.8876.1\lib\net40\System.Data.SqlServerCe.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Extensions" />
|
||||
<Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WebActivator, Version=1.5.3.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\WebActivator.1.5.3\lib\net40\WebActivator.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="App_Start\RazorGeneratorMvcStart.cs" />
|
||||
<Compile Include="Logging\LogBase.cs" />
|
||||
<Compile Include="Logging\LogContext.cs" />
|
||||
<Compile Include="Logging\LogReInitalizeJob.cs" />
|
||||
<Compile Include="Logging\Models\LogEvent.cs" />
|
||||
<Compile Include="Logging\Models\LogEventType.cs" />
|
||||
<Compile Include="Logging\Models\LogLiveEvent.cs" />
|
||||
<Compile Include="Logging\Models\LogModule.cs" />
|
||||
<Compile Include="Logging\ReadLogContext.cs" />
|
||||
<Compile Include="Logging\SystemLog.cs" />
|
||||
<Compile Include="Logging\Targets\LogLiveContext.cs" />
|
||||
<Compile Include="Logging\Targets\LogPersistContext.cs" />
|
||||
<Compile Include="Logging\Utilities.cs" />
|
||||
<None Include="_Plugins\Categories\CertificateProvider\CertificateProviderPlugin.cs" />
|
||||
<None Include="_Plugins\Categories\CertificateProvider\CertificateProviderLog.cs" />
|
||||
<None Include="_Plugins\Categories\InteroperabilityProvider\InteroperabilityProviderPlugin.cs" />
|
||||
<None Include="_Plugins\Categories\WarrantyProvider\WarrantyProviderPlugin.cs" />
|
||||
<None Include="_Plugins\Categories\WarrantyProvider\WarrantyProviderSubmitJobException.cs" />
|
||||
<None Include="_Plugins\PluginCategoryAttribute.cs" />
|
||||
<None Include="_Plugins\PluginDefinition.cs" />
|
||||
<None Include="_Plugins\Plugins.cs" />
|
||||
<None Include="_Plugins\Plugin.cs" />
|
||||
<None Include="_Plugins\IPluginConfiguration.cs" />
|
||||
<None Include="_Plugins\IPluginWebController.cs" />
|
||||
<None Include="_Plugins\InvalidCategoryTypeException.cs" />
|
||||
<None Include="_Plugins\PluginExtensions.cs" />
|
||||
<None Include="_Plugins\PluginsLog.cs" />
|
||||
<None Include="_Plugins\PluginWebControllerException.cs" />
|
||||
<None Include="_Plugins\PluginWebControllerExtensions.cs" />
|
||||
<None Include="_Plugins\UnknownPluginException.cs" />
|
||||
<Compile Include="Plugins\PluginAttribute.cs" />
|
||||
<Compile Include="Plugins\PluginExtensions.cs" />
|
||||
<Compile Include="Plugins\PluginFeatureAttribute.cs" />
|
||||
<Compile Include="Plugins\Features\CertificateProvider\CertificateProviderFeature.cs" />
|
||||
<Compile Include="Plugins\Features\CertificateProvider\CertificateProviderLog.cs" />
|
||||
<Compile Include="Plugins\Features\InteroperabilityProvider\InteroperabilityProviderFeature.cs" />
|
||||
<Compile Include="Plugins\Features\Other\OtherFeature.cs" />
|
||||
<Compile Include="Plugins\Features\WarrantyProvider\WarrantyProviderFeature.cs" />
|
||||
<Compile Include="Plugins\Features\WarrantyProvider\WarrantyProviderSubmitJobException.cs" />
|
||||
<Compile Include="Plugins\InvalidFeatureCategoryTypeException.cs" />
|
||||
<Compile Include="Plugins\Plugin.cs" />
|
||||
<Compile Include="Plugins\PluginConfigurationHandler.cs" />
|
||||
<Compile Include="Plugins\PluginFeature.cs" />
|
||||
<Compile Include="Plugins\PluginFeatureCategoryAttribute.cs" />
|
||||
<Compile Include="Plugins\PluginFeatureManifest.cs" />
|
||||
<Compile Include="Plugins\PluginManifest.cs" />
|
||||
<Compile Include="Plugins\Plugins.cs" />
|
||||
<Compile Include="Plugins\PluginsLog.cs" />
|
||||
<Compile Include="Plugins\PluginWebHandler.cs" />
|
||||
<Compile Include="Plugins\PluginWebHandlerController.cs" />
|
||||
<Compile Include="Plugins\UnknownPluginException.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Tasks\ScheduledTask.cs" />
|
||||
<Compile Include="Tasks\ScheduledTaskCleanup.cs" />
|
||||
<Compile Include="Tasks\ScheduledTasks.cs" />
|
||||
<Compile Include="Tasks\ScheduledTasksLog.cs" />
|
||||
<Compile Include="Tasks\ScheduledTaskStatus.cs" />
|
||||
<Compile Include="Tasks\ScheduledTasksLiveStatusService.cs" />
|
||||
<Compile Include="Tasks\ScheduledTaskStatusLive.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Disco.Data\Disco.Data.csproj">
|
||||
<Project>{85A6BD19-2C64-4746-8F2C-A68A86E8C2D7}</Project>
|
||||
<Name>Disco.Data</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Disco.Models\Disco.Models.csproj">
|
||||
<Project>{FBC05512-FCCA-4B16-9E76-8C413C5DE6C9}</Project>
|
||||
<Name>Disco.Models</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties BuildVersion_UseGlobalSettings="True" BuildVersion_DetectChanges="False" BuildVersion_BuildAction="ReBuild" BuildVersion_StartDate="2001/1/1" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
if not exist "$(TargetDir)x86" md "$(TargetDir)x86"
|
||||
xcopy /s /y "$(SolutionDir)packages\Microsoft.SqlServer.Compact.4.0.8876.1\NativeBinaries\x86\*.*" "$(TargetDir)x86"
|
||||
if not exist "$(TargetDir)amd64" md "$(TargetDir)amd64"
|
||||
xcopy /s /y "$(SolutionDir)packages\Microsoft.SqlServer.Compact.4.0.8876.1\NativeBinaries\amd64\*.*" "$(TargetDir)amd64"</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.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>
|
||||
-->
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{B80A737F-BD6A-4986-9182-DD7B932BD950}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Disco.Services</RootNamespace>
|
||||
<AssemblyName>Disco.Services</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="EntityFramework">
|
||||
<HintPath>..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Quartz">
|
||||
<HintPath>..\Resources\Libraries\Quartz\Quartz.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RazorGenerator.Mvc, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\RazorGenerator.Mvc.1.5.0.0\lib\net40\RazorGenerator.Mvc.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SignalR, Version=0.5.1.10822, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\SignalR.Server.0.5.3\lib\net40\SignalR.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SignalR.Hosting.AspNet, Version=0.5.1.10822, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\SignalR.Hosting.AspNet.0.5.3\lib\net45\SignalR.Hosting.AspNet.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SignalR.Hosting.Common">
|
||||
<HintPath>..\packages\SignalR.Hosting.Common.0.5.3\lib\net40\SignalR.Hosting.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.Entity" />
|
||||
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.SqlServer.Compact.4.0.8876.1\lib\net40\System.Data.SqlServerCe.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Extensions" />
|
||||
<Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WebActivator, Version=1.5.3.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\WebActivator.1.5.3\lib\net40\WebActivator.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Logging\LogBase.cs" />
|
||||
<Compile Include="Logging\LogContext.cs" />
|
||||
<Compile Include="Logging\LogReInitalizeJob.cs" />
|
||||
<Compile Include="Logging\Models\LogEvent.cs" />
|
||||
<Compile Include="Logging\Models\LogEventType.cs" />
|
||||
<Compile Include="Logging\Models\LogLiveEvent.cs" />
|
||||
<Compile Include="Logging\Models\LogModule.cs" />
|
||||
<Compile Include="Logging\ReadLogContext.cs" />
|
||||
<Compile Include="Logging\SystemLog.cs" />
|
||||
<Compile Include="Logging\Targets\LogLiveContext.cs" />
|
||||
<Compile Include="Logging\Targets\LogPersistContext.cs" />
|
||||
<Compile Include="Logging\Utilities.cs" />
|
||||
<None Include="_Plugins\Categories\CertificateProvider\CertificateProviderPlugin.cs" />
|
||||
<None Include="_Plugins\Categories\CertificateProvider\CertificateProviderLog.cs" />
|
||||
<None Include="_Plugins\Categories\InteroperabilityProvider\InteroperabilityProviderPlugin.cs" />
|
||||
<None Include="_Plugins\Categories\WarrantyProvider\WarrantyProviderPlugin.cs" />
|
||||
<None Include="_Plugins\Categories\WarrantyProvider\WarrantyProviderSubmitJobException.cs" />
|
||||
<None Include="_Plugins\PluginCategoryAttribute.cs" />
|
||||
<None Include="_Plugins\PluginDefinition.cs" />
|
||||
<None Include="_Plugins\Plugins.cs" />
|
||||
<None Include="_Plugins\Plugin.cs" />
|
||||
<None Include="_Plugins\IPluginConfiguration.cs" />
|
||||
<None Include="_Plugins\IPluginWebController.cs" />
|
||||
<None Include="_Plugins\InvalidCategoryTypeException.cs" />
|
||||
<None Include="_Plugins\PluginExtensions.cs" />
|
||||
<None Include="_Plugins\PluginsLog.cs" />
|
||||
<None Include="_Plugins\PluginWebControllerException.cs" />
|
||||
<None Include="_Plugins\PluginWebControllerExtensions.cs" />
|
||||
<None Include="_Plugins\UnknownPluginException.cs" />
|
||||
<Compile Include="Plugins\InstallPluginTask.cs" />
|
||||
<Compile Include="Plugins\PluginAttribute.cs" />
|
||||
<Compile Include="Plugins\PluginExtensions.cs" />
|
||||
<Compile Include="Plugins\PluginFeatureAttribute.cs" />
|
||||
<Compile Include="Plugins\Features\CertificateProvider\CertificateProviderFeature.cs" />
|
||||
<Compile Include="Plugins\Features\CertificateProvider\CertificateProviderLog.cs" />
|
||||
<Compile Include="Plugins\Features\InteroperabilityProvider\InteroperabilityProviderFeature.cs" />
|
||||
<Compile Include="Plugins\Features\Other\OtherFeature.cs" />
|
||||
<Compile Include="Plugins\Features\WarrantyProvider\WarrantyProviderFeature.cs" />
|
||||
<Compile Include="Plugins\Features\WarrantyProvider\WarrantyProviderSubmitJobException.cs" />
|
||||
<Compile Include="Plugins\InvalidFeatureCategoryTypeException.cs" />
|
||||
<Compile Include="Plugins\Plugin.cs" />
|
||||
<Compile Include="Plugins\PluginConfigurationHandler.cs" />
|
||||
<Compile Include="Plugins\PluginFeature.cs" />
|
||||
<Compile Include="Plugins\PluginFeatureCategoryAttribute.cs" />
|
||||
<Compile Include="Plugins\PluginFeatureManifest.cs" />
|
||||
<Compile Include="Plugins\PluginManifest.cs" />
|
||||
<Compile Include="Plugins\Plugins.cs" />
|
||||
<Compile Include="Plugins\PluginsLog.cs" />
|
||||
<Compile Include="Plugins\PluginWebHandler.cs" />
|
||||
<Compile Include="Plugins\PluginWebHandlerController.cs" />
|
||||
<Compile Include="Plugins\UninstallPluginTask.cs" />
|
||||
<Compile Include="Plugins\UnknownPluginException.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Tasks\ScheduledTask.cs" />
|
||||
<Compile Include="Tasks\ScheduledTaskCleanup.cs" />
|
||||
<Compile Include="Tasks\ScheduledTasks.cs" />
|
||||
<Compile Include="Tasks\ScheduledTasksLog.cs" />
|
||||
<Compile Include="Tasks\ScheduledTaskStatus.cs" />
|
||||
<Compile Include="Tasks\ScheduledTasksLiveStatusService.cs" />
|
||||
<Compile Include="Tasks\ScheduledTaskStatusLive.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Disco.Data\Disco.Data.csproj">
|
||||
<Project>{85A6BD19-2C64-4746-8F2C-A68A86E8C2D7}</Project>
|
||||
<Name>Disco.Data</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Disco.Models\Disco.Models.csproj">
|
||||
<Project>{FBC05512-FCCA-4B16-9E76-8C413C5DE6C9}</Project>
|
||||
<Name>Disco.Models</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties BuildVersion_UseGlobalSettings="True" BuildVersion_DetectChanges="False" BuildVersion_BuildAction="ReBuild" BuildVersion_StartDate="2001/1/1" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
if not exist "$(TargetDir)x86" md "$(TargetDir)x86"
|
||||
xcopy /s /y "$(SolutionDir)packages\Microsoft.SqlServer.Compact.4.0.8876.1\NativeBinaries\x86\*.*" "$(TargetDir)x86"
|
||||
if not exist "$(TargetDir)amd64" md "$(TargetDir)amd64"
|
||||
xcopy /s /y "$(SolutionDir)packages\Microsoft.SqlServer.Compact.4.0.8876.1\NativeBinaries\amd64\*.*" "$(TargetDir)amd64"</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.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,132 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Services.Tasks;
|
||||
using Quartz;
|
||||
|
||||
namespace Disco.Services.Plugins
|
||||
{
|
||||
public class InstallPluginTask : ScheduledTask
|
||||
{
|
||||
public override string TaskName { get { return "Installing Plugin"; } }
|
||||
|
||||
protected override void ExecuteTask()
|
||||
{
|
||||
string packageFilePath = (string)this.ExecutionContext.JobDetail.JobDataMap["PackageFilePath"];
|
||||
bool DeletePackageAfterInstall = (bool)this.ExecutionContext.JobDetail.JobDataMap["DeletePackageAfterInstall"];
|
||||
|
||||
if (!Plugins.PluginsLoaded)
|
||||
throw new InvalidOperationException("Plugins have not been initialized");
|
||||
|
||||
this.Status.UpdateStatus(10, "Opening Plugin Package", Path.GetFileName(packageFilePath));
|
||||
|
||||
using (var packageStream = File.OpenRead(packageFilePath))
|
||||
{
|
||||
using (ZipArchive packageArchive = new ZipArchive(packageStream, ZipArchiveMode.Read, false))
|
||||
{
|
||||
|
||||
ZipArchiveEntry packageManifestEntry = packageArchive.GetEntry("manifest.json");
|
||||
if (packageManifestEntry == null)
|
||||
throw new InvalidDataException("The plugin package does not contain the 'manifest.json' entry");
|
||||
|
||||
PluginManifest packageManifest;
|
||||
|
||||
using (Stream packageManifestStream = packageManifestEntry.Open())
|
||||
{
|
||||
packageManifest = PluginManifest.FromPluginManifestFile(packageManifestStream);
|
||||
}
|
||||
|
||||
this.Status.UpdateStatus(20, string.Format("{0} [{1} v{2}] by {3}", packageManifest.Name, packageManifest.Id, packageManifest.Version.ToString(4), packageManifest.Author), "Initializing Install Environment");
|
||||
|
||||
PluginsLog.LogInstalling(packageManifest);
|
||||
|
||||
lock (Plugins._PluginLock)
|
||||
{
|
||||
if (!Plugins.PluginsLoaded)
|
||||
throw new InvalidOperationException("Plugins have not been initialized");
|
||||
|
||||
// Ensure not already installed
|
||||
if (Plugins.GetPlugins().FirstOrDefault(p => p.Id == packageManifest.Id) != null)
|
||||
throw new InvalidOperationException(string.Format("The '{0} [{1}]' Plugin is already installed, please uninstall any existing versions before trying again", packageManifest.Name, packageManifest.Id));
|
||||
|
||||
using (DiscoDataContext dbContext = new DiscoDataContext())
|
||||
{
|
||||
string packagePath = Path.Combine(dbContext.DiscoConfiguration.PluginsLocation, packageManifest.Id);
|
||||
|
||||
// Force Delete of Existing Folder
|
||||
if (Directory.Exists(packagePath))
|
||||
{
|
||||
this.Status.UpdateStatus(25, "Removing Existing Files");
|
||||
Directory.Delete(packagePath, true);
|
||||
}
|
||||
Directory.CreateDirectory(packagePath);
|
||||
|
||||
|
||||
this.Status.UpdateStatus(30, "Extracting Files");
|
||||
|
||||
double extractFileInterval = (double)50 / packageArchive.Entries.Count;
|
||||
int countExtractedFiles = 0;
|
||||
|
||||
// Extract Package Contents
|
||||
foreach (var packageEntry in packageArchive.Entries)
|
||||
{
|
||||
this.Status.UpdateStatus(30 + (countExtractedFiles++ * extractFileInterval), string.Format("Extracting File: {0}", packageEntry.FullName));
|
||||
|
||||
// Determine Extraction Path
|
||||
var packageEntryTarget = Path.Combine(packagePath, packageEntry.FullName);
|
||||
|
||||
// Create Sub Directories
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(packageEntryTarget));
|
||||
|
||||
using (var packageEntryStream = packageEntry.Open())
|
||||
{
|
||||
using (var packageTargetStream = File.Open(packageEntryTarget, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
packageEntryStream.CopyTo(packageTargetStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reload Manifest
|
||||
packageManifest = PluginManifest.FromPluginManifestFile(Path.Combine(packagePath, "manifest.json"));
|
||||
|
||||
// Install Plugin
|
||||
this.Status.UpdateStatus(80, "Initial Package Configuration");
|
||||
packageManifest.InstallPlugin(dbContext, this.Status);
|
||||
|
||||
// Initialize Plugin
|
||||
this.Status.UpdateStatus(98, "Initializing Plugin for Use");
|
||||
packageManifest.InitializePlugin(dbContext);
|
||||
|
||||
// Add Plugin Manifest to Host Environment
|
||||
Plugins.AddPlugin(packageManifest);
|
||||
|
||||
PluginsLog.LogInstalled(packageManifest);
|
||||
this.Status.Finished("Plugin Installation Completed", string.Format("/Config/Plugins/{0}", System.Web.HttpUtility.UrlEncode(packageManifest.Id)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DeletePackageAfterInstall)
|
||||
File.Delete(packageFilePath);
|
||||
}
|
||||
|
||||
public static ScheduledTaskStatus InstallPlugin(string PackageFilePath, bool DeletePackageAfterInstall)
|
||||
{
|
||||
if (ScheduledTasks.GetTaskStatuses(typeof(InstallPluginTask)).Where(s => s.IsRunning).Count() > 0)
|
||||
throw new InvalidOperationException("A plugin is already being Installed");
|
||||
|
||||
JobDataMap taskData = new JobDataMap() { { "PackageFilePath", PackageFilePath }, { "DeletePackageAfterInstall", DeletePackageAfterInstall } };
|
||||
|
||||
var instance = new InstallPluginTask();
|
||||
|
||||
return instance.ScheduleTask(taskData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Disco.Data.Repository;
|
||||
|
||||
namespace Disco.Services.Plugins
|
||||
{
|
||||
public abstract class Plugin : IDisposable
|
||||
{
|
||||
public PluginManifest Manifest {get; internal set;}
|
||||
|
||||
#region Lifecycle
|
||||
public abstract bool Install(DiscoDataContext dbContext);
|
||||
public abstract bool Initalize(DiscoDataContext dbContext);
|
||||
public abstract bool Uninstall(DiscoDataContext dbContext);
|
||||
public abstract bool BeforeUpdate(DiscoDataContext dbContext, PluginManifest updateManifest);
|
||||
#endregion
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
// Nothing in Base Class
|
||||
}
|
||||
|
||||
public override sealed string ToString()
|
||||
{
|
||||
return string.Format("{0} ({1}) - v{2}", this.Manifest.Name, this.Manifest.Id, this.Manifest.Version.ToString(4));
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Services.Tasks;
|
||||
|
||||
namespace Disco.Services.Plugins
|
||||
{
|
||||
public abstract class Plugin : IDisposable
|
||||
{
|
||||
public PluginManifest Manifest {get; internal set;}
|
||||
|
||||
#region Lifecycle
|
||||
// Events/Triggers for Custom Plugin Initialization (Optional)
|
||||
public virtual void Install(DiscoDataContext dbContext, ScheduledTaskStatus Status) { return; }
|
||||
public virtual void Initialize(DiscoDataContext dbContext) { return; }
|
||||
public virtual void Uninstall(DiscoDataContext dbContext, bool UninstallData, ScheduledTaskStatus Status) { return; }
|
||||
public virtual void BeforeUpdate(DiscoDataContext dbContext, PluginManifest UpdateManifest, ScheduledTaskStatus Status) { return; }
|
||||
public virtual void AfterUpdate(DiscoDataContext dbContext, PluginManifest PreviousManifest) { return; }
|
||||
#endregion
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
// Nothing in Base Class
|
||||
}
|
||||
|
||||
public override sealed string ToString()
|
||||
{
|
||||
return string.Format("{0} ({1}) - v{2}", this.Manifest.Name, this.Manifest.Id, this.Manifest.Version.ToString(4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Disco.Data.Repository;
|
||||
|
||||
namespace Disco.Services.Plugins
|
||||
{
|
||||
public abstract class PluginFeature : IDisposable
|
||||
{
|
||||
public PluginFeatureManifest Manifest {get; internal set;}
|
||||
|
||||
public abstract bool Initalize(DiscoDataContext dbContext);
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
// Nothing in Base Class
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Disco.Data.Repository;
|
||||
|
||||
namespace Disco.Services.Plugins
|
||||
{
|
||||
public abstract class PluginFeature : IDisposable
|
||||
{
|
||||
public PluginFeatureManifest Manifest {get; internal set;}
|
||||
|
||||
// Allow Custom Initialization (Optional)
|
||||
public virtual void Initialize(DiscoDataContext dbContext) { return; }
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
// Nothing in Base Class
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,107 +1,107 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Disco.Data.Repository;
|
||||
using Newtonsoft.Json;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Disco.Services.Plugins
|
||||
{
|
||||
public class PluginFeatureManifest
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string TypeName { get; set; }
|
||||
|
||||
[JsonProperty]
|
||||
private string CategoryTypeName { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public PluginManifest PluginManifest { get; private set; }
|
||||
[JsonIgnore]
|
||||
internal Type Type { get; private set; }
|
||||
[JsonIgnore]
|
||||
public Type CategoryType { get; private set; }
|
||||
|
||||
internal bool Initialize(DiscoDataContext dbContext, PluginManifest pluginManifest)
|
||||
{
|
||||
this.PluginManifest = pluginManifest;
|
||||
|
||||
if (this.Type == null)
|
||||
this.Type = this.PluginManifest.PluginAssembly.GetType(this.TypeName, true, true);
|
||||
|
||||
if (this.CategoryType == null)
|
||||
this.CategoryType = Type.GetType(this.CategoryTypeName, true, true);
|
||||
|
||||
using (var instance = this.CreateInstance())
|
||||
{
|
||||
instance.Initalize(dbContext);
|
||||
}
|
||||
|
||||
PluginsLog.LogInitializedPluginFeature(this.PluginManifest, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public PluginFeature CreateInstance()
|
||||
{
|
||||
var i = (PluginFeature)Activator.CreateInstance(Type);
|
||||
i.Manifest = this;
|
||||
return i;
|
||||
}
|
||||
public CategoryType CreateInstance<CategoryType>() where CategoryType : PluginFeature
|
||||
{
|
||||
if (typeof(CategoryType).IsAssignableFrom(this.Type))
|
||||
{
|
||||
var i = (CategoryType)Activator.CreateInstance(Type);
|
||||
i.Manifest = this;
|
||||
return i;
|
||||
}
|
||||
else
|
||||
throw new InvalidOperationException(string.Format("The feature [{0}] cannot be cast into type [{1}]", this.Type.Name, typeof(CategoryType).Name));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses reflection to build a Plugin Manifest
|
||||
/// </summary>
|
||||
/// <param name="pluginAssembly">Assembly containing a plugin</param>
|
||||
/// <returns>A plugin manifest for the first encountered plugin within the assembly</returns>
|
||||
public static PluginFeatureManifest FromPluginFeatureType(Type featureType, PluginManifest pluginManifest)
|
||||
{
|
||||
var featureAttribute = (PluginFeatureAttribute)featureType.GetCustomAttributes(typeof(PluginFeatureAttribute), false).FirstOrDefault();
|
||||
|
||||
if (featureAttribute == null)
|
||||
throw new ArgumentException(string.Format("Plugin Feature found [{0}], but no PluginFeatureAttribute found", featureType.Name), "featureType");
|
||||
|
||||
var featureId = featureAttribute.Id;
|
||||
var featureName = featureAttribute.Name;
|
||||
|
||||
// Determine Feature Category
|
||||
var featureCategoryType = featureType.BaseType;
|
||||
|
||||
if (featureCategoryType == null)
|
||||
throw new ArgumentException(string.Format("Plugin Feature found [{0}], but has no Base Type to determine its Category", featureType.Name), "featureType");
|
||||
|
||||
if (featureCategoryType == typeof(PluginFeature) || !typeof(PluginFeature).IsAssignableFrom(featureCategoryType))
|
||||
throw new ArgumentException(string.Format("Plugin Feature found [{0}], but its Base Type is not a valid Feature Category Type (Base Feature or not assignable)", featureType.Name), "featureType");
|
||||
|
||||
var featureCategoryAttribute = (PluginFeatureCategoryAttribute)featureCategoryType.GetCustomAttributes(typeof(PluginFeatureCategoryAttribute), false).FirstOrDefault();
|
||||
|
||||
if (featureCategoryAttribute == null)
|
||||
throw new ArgumentException(string.Format("Plugin Feature found [{0}], but its Base Type is not a valid Feature Category Type (no attribute)", featureType.Name), "featureType");
|
||||
|
||||
return new PluginFeatureManifest()
|
||||
{
|
||||
PluginManifest = pluginManifest,
|
||||
Id = featureId,
|
||||
Name = featureName,
|
||||
Type = featureType,
|
||||
TypeName = featureType.FullName,
|
||||
CategoryType = featureCategoryType,
|
||||
CategoryTypeName = featureCategoryType.FullName
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Disco.Data.Repository;
|
||||
using Newtonsoft.Json;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Disco.Services.Plugins
|
||||
{
|
||||
public class PluginFeatureManifest
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string TypeName { get; set; }
|
||||
|
||||
[JsonProperty]
|
||||
private string CategoryTypeName { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public PluginManifest PluginManifest { get; private set; }
|
||||
[JsonIgnore]
|
||||
internal Type Type { get; private set; }
|
||||
[JsonIgnore]
|
||||
public Type CategoryType { get; private set; }
|
||||
|
||||
internal bool Initialize(DiscoDataContext dbContext, PluginManifest pluginManifest)
|
||||
{
|
||||
this.PluginManifest = pluginManifest;
|
||||
|
||||
if (this.Type == null)
|
||||
this.Type = this.PluginManifest.PluginAssembly.GetType(this.TypeName, true, true);
|
||||
|
||||
if (this.CategoryType == null)
|
||||
this.CategoryType = Type.GetType(this.CategoryTypeName, true, true);
|
||||
|
||||
using (var instance = this.CreateInstance())
|
||||
{
|
||||
instance.Initialize(dbContext);
|
||||
}
|
||||
|
||||
PluginsLog.LogInitializedPluginFeature(this.PluginManifest, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public PluginFeature CreateInstance()
|
||||
{
|
||||
var i = (PluginFeature)Activator.CreateInstance(Type);
|
||||
i.Manifest = this;
|
||||
return i;
|
||||
}
|
||||
public CategoryType CreateInstance<CategoryType>() where CategoryType : PluginFeature
|
||||
{
|
||||
if (typeof(CategoryType).IsAssignableFrom(this.Type))
|
||||
{
|
||||
var i = (CategoryType)Activator.CreateInstance(Type);
|
||||
i.Manifest = this;
|
||||
return i;
|
||||
}
|
||||
else
|
||||
throw new InvalidOperationException(string.Format("The feature [{0}] cannot be cast into type [{1}]", this.Type.Name, typeof(CategoryType).Name));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses reflection to build a Plugin Manifest
|
||||
/// </summary>
|
||||
/// <param name="pluginAssembly">Assembly containing a plugin</param>
|
||||
/// <returns>A plugin manifest for the first encountered plugin within the assembly</returns>
|
||||
public static PluginFeatureManifest FromPluginFeatureType(Type featureType, PluginManifest pluginManifest)
|
||||
{
|
||||
var featureAttribute = (PluginFeatureAttribute)featureType.GetCustomAttributes(typeof(PluginFeatureAttribute), false).FirstOrDefault();
|
||||
|
||||
if (featureAttribute == null)
|
||||
throw new ArgumentException(string.Format("Plugin Feature found [{0}], but no PluginFeatureAttribute found", featureType.Name), "featureType");
|
||||
|
||||
var featureId = featureAttribute.Id;
|
||||
var featureName = featureAttribute.Name;
|
||||
|
||||
// Determine Feature Category
|
||||
var featureCategoryType = featureType.BaseType;
|
||||
|
||||
if (featureCategoryType == null)
|
||||
throw new ArgumentException(string.Format("Plugin Feature found [{0}], but has no Base Type to determine its Category", featureType.Name), "featureType");
|
||||
|
||||
if (featureCategoryType == typeof(PluginFeature) || !typeof(PluginFeature).IsAssignableFrom(featureCategoryType))
|
||||
throw new ArgumentException(string.Format("Plugin Feature found [{0}], but its Base Type is not a valid Feature Category Type (Base Feature or not assignable)", featureType.Name), "featureType");
|
||||
|
||||
var featureCategoryAttribute = (PluginFeatureCategoryAttribute)featureCategoryType.GetCustomAttributes(typeof(PluginFeatureCategoryAttribute), false).FirstOrDefault();
|
||||
|
||||
if (featureCategoryAttribute == null)
|
||||
throw new ArgumentException(string.Format("Plugin Feature found [{0}], but its Base Type is not a valid Feature Category Type (no attribute)", featureType.Name), "featureType");
|
||||
|
||||
return new PluginFeatureManifest()
|
||||
{
|
||||
PluginManifest = pluginManifest,
|
||||
Id = featureId,
|
||||
Name = featureName,
|
||||
Type = featureType,
|
||||
TypeName = featureType.FullName,
|
||||
CategoryType = featureCategoryType,
|
||||
CategoryTypeName = featureCategoryType.FullName
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,321 +1,386 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using Disco.Data.Repository;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Disco.Services.Plugins
|
||||
{
|
||||
public class PluginManifest
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Author { get; set; }
|
||||
public Version Version { get; set; }
|
||||
[JsonProperty]
|
||||
internal string AssemblyPath { get; set; }
|
||||
[JsonProperty]
|
||||
private string TypeName { get; set; }
|
||||
[JsonProperty]
|
||||
private string ConfigurationHandlerTypeName { get; set; }
|
||||
[JsonProperty]
|
||||
private string WebHandlerTypeName { get; set; }
|
||||
|
||||
[JsonProperty]
|
||||
internal Dictionary<string, string> AssemblyReferences { get; set; }
|
||||
|
||||
[JsonProperty]
|
||||
public List<PluginFeatureManifest> Features { get; private set; }
|
||||
|
||||
[JsonIgnore]
|
||||
internal Assembly PluginAssembly { get; private set; }
|
||||
[JsonIgnore]
|
||||
internal Type Type { get; private set; }
|
||||
[JsonIgnore]
|
||||
private Type ConfigurationHandlerType { get; set; }
|
||||
[JsonIgnore]
|
||||
private Type WebHandlerType { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string PluginLocation { get; private set; }
|
||||
[JsonIgnore]
|
||||
public string StorageLocation { get; private set; }
|
||||
|
||||
private static Dictionary<string, Tuple<string, DateTime>> WebResourceHashes = new Dictionary<string, Tuple<string, DateTime>>();
|
||||
|
||||
public List<PluginFeatureManifest> GetFeatures(Type FeatureCategoryType)
|
||||
{
|
||||
return this.Features.Where(fm => fm.CategoryType.IsAssignableFrom(FeatureCategoryType)).ToList();
|
||||
}
|
||||
public PluginFeatureManifest GetFeature(string PluginFeatureId)
|
||||
{
|
||||
return this.Features.Where(fm => fm.Id == PluginFeatureId).FirstOrDefault();
|
||||
}
|
||||
|
||||
public Plugin CreateInstance()
|
||||
{
|
||||
var i = (Plugin)Activator.CreateInstance(Type);
|
||||
i.Manifest = this;
|
||||
return i;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes a Json Manifest
|
||||
/// </summary>
|
||||
/// <param name="FilePath">Path to the Json Manifest file</param>
|
||||
/// <returns></returns>
|
||||
public static PluginManifest FromPluginManifestFile(string FilePath)
|
||||
{
|
||||
using (Stream manifestStream = File.OpenRead(FilePath))
|
||||
{
|
||||
PluginManifest manifest = FromPluginManifestFile(manifestStream, Path.GetDirectoryName(FilePath));
|
||||
return manifest;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes a Json Manifest
|
||||
/// </summary>
|
||||
/// <param name="FileStream">Stream containing the encoded Json Manifest File</param>
|
||||
/// <param name="PluginLocation">PluginLocation to be set in the manifest</param>
|
||||
/// <returns></returns>
|
||||
public static PluginManifest FromPluginManifestFile(Stream FileStream, string PluginLocation = null)
|
||||
{
|
||||
string manifestString;
|
||||
using (StreamReader manifestStreamReader = new StreamReader(FileStream))
|
||||
{
|
||||
manifestString = manifestStreamReader.ReadToEnd();
|
||||
}
|
||||
|
||||
var manifest = JsonConvert.DeserializeObject<PluginManifest>(manifestString);
|
||||
|
||||
manifest.PluginLocation = PluginLocation;
|
||||
|
||||
return manifest;
|
||||
}
|
||||
/// <summary>
|
||||
/// Uses reflection to build a Plugin Manifest
|
||||
/// </summary>
|
||||
/// <param name="pluginAssembly">Assembly containing a plugin</param>
|
||||
/// <returns>A plugin manifest for the first encountered plugin within the assembly</returns>
|
||||
public static PluginManifest FromPluginAssembly(Assembly assembly)
|
||||
{
|
||||
// Determine Plugin Properties
|
||||
var pluginType = (from type in assembly.GetTypes()
|
||||
where typeof(Plugin).IsAssignableFrom(type) && !type.IsAbstract
|
||||
select type).FirstOrDefault();
|
||||
|
||||
if (pluginType == null)
|
||||
throw new ArgumentException("No Plugin was found in this Assembly", "pluginAssembly");
|
||||
|
||||
var assemblyName = assembly.GetName();
|
||||
|
||||
var pluginAttributes = pluginType.GetCustomAttribute<PluginAttribute>(false);
|
||||
|
||||
if (pluginAttributes == null)
|
||||
throw new ArgumentException(string.Format("Plugin found [{0}], but no PluginAttribute found", pluginType.Name), "pluginAssembly");
|
||||
|
||||
var pluginId = pluginAttributes.Id;
|
||||
var pluginName = pluginAttributes.Name;
|
||||
var pluginAuthor = pluginAttributes.Author;
|
||||
|
||||
var pluginVersion = assemblyName.Version;
|
||||
var pluginAssemblyPath = Path.GetFileName(assembly.Location);
|
||||
var pluginTypeName = pluginType.FullName;
|
||||
var pluginLocation = Path.GetDirectoryName(assembly.Location);
|
||||
|
||||
// Find Configuration Handler
|
||||
var pluginConfigurationHandlerType = (from type in assembly.GetTypes()
|
||||
where typeof(PluginConfigurationHandler).IsAssignableFrom(type) && !type.IsAbstract
|
||||
select type).FirstOrDefault();
|
||||
if (pluginConfigurationHandlerType == null)
|
||||
throw new ArgumentException("A Plugin was found, but no Configuration Handler was found in this Assembly - this is required", "pluginAssembly");
|
||||
|
||||
// Find Web Handler
|
||||
var pluginWebHandlerType = (from type in assembly.GetTypes()
|
||||
where typeof(PluginWebHandler).IsAssignableFrom(type) && !type.IsAbstract
|
||||
select type).FirstOrDefault();
|
||||
|
||||
Dictionary<string, string> pluginAssemblyReferences = new Dictionary<string, string>();
|
||||
foreach (string referenceFilename in Directory.EnumerateFiles(pluginLocation, "*.dll", SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
if (!referenceFilename.Equals(assembly.Location, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
try
|
||||
{
|
||||
Assembly pluginRefAssembly = Assembly.ReflectionOnlyLoadFrom(referenceFilename);
|
||||
pluginAssemblyReferences[pluginRefAssembly.FullName] = referenceFilename.Substring(pluginLocation.Length + 1);
|
||||
}
|
||||
catch (Exception) { } // Ignore Load Exceptions
|
||||
}
|
||||
}
|
||||
|
||||
PluginManifest pluginManifest = new PluginManifest()
|
||||
{
|
||||
Id = pluginId,
|
||||
Name = pluginName,
|
||||
Author = pluginAuthor,
|
||||
Version = pluginVersion,
|
||||
AssemblyPath = pluginAssemblyPath,
|
||||
TypeName = pluginTypeName,
|
||||
AssemblyReferences = pluginAssemblyReferences,
|
||||
PluginAssembly = assembly,
|
||||
Type = pluginType,
|
||||
PluginLocation = pluginLocation,
|
||||
ConfigurationHandlerType = pluginConfigurationHandlerType,
|
||||
ConfigurationHandlerTypeName = pluginConfigurationHandlerType.FullName,
|
||||
WebHandlerType = pluginWebHandlerType,
|
||||
WebHandlerTypeName = (pluginWebHandlerType == null ? null : pluginWebHandlerType.FullName)
|
||||
};
|
||||
|
||||
pluginManifest.Features = (from type in assembly.GetTypes()
|
||||
where typeof(PluginFeature).IsAssignableFrom(type) && !type.IsAbstract
|
||||
select PluginFeatureManifest.FromPluginFeatureType(type, pluginManifest)).ToList();
|
||||
|
||||
return pluginManifest;
|
||||
}
|
||||
|
||||
public string ToManifestFile()
|
||||
{
|
||||
return JsonConvert.SerializeObject(this, Formatting.Indented);
|
||||
}
|
||||
public bool InitializePlugin(DiscoDataContext dbContext)
|
||||
{
|
||||
var assemblyFullPath = Path.Combine(this.PluginLocation, this.AssemblyPath);
|
||||
|
||||
if (!File.Exists(assemblyFullPath))
|
||||
throw new FileNotFoundException(string.Format("Plugin Assembly [{0}] not found at: {1}", this.Id, assemblyFullPath), assemblyFullPath);
|
||||
|
||||
if (this.PluginAssembly == null)
|
||||
this.PluginAssembly = Assembly.LoadFile(assemblyFullPath);
|
||||
|
||||
if (this.PluginAssembly == null)
|
||||
throw new InvalidOperationException(string.Format("Unable to load Plugin Assembly [{0}] at: {1}", this.Id, assemblyFullPath));
|
||||
|
||||
PluginsLog.LogInitializingPluginAssembly(this.PluginAssembly);
|
||||
|
||||
// Check Manifest/Assembly Versions Match
|
||||
if (this.Version != this.PluginAssembly.GetName().Version)
|
||||
throw new InvalidOperationException(string.Format("The plugin [{0}] manifest version [{1}] doesn't match the plugin assembly [{2} : {3}]", this.Id, this.Version, assemblyFullPath, this.PluginAssembly.GetName().Version));
|
||||
|
||||
if (this.Type == null)
|
||||
this.Type = this.PluginAssembly.GetType(this.TypeName, true, true);
|
||||
|
||||
if (this.ConfigurationHandlerType == null)
|
||||
this.ConfigurationHandlerType = this.PluginAssembly.GetType(this.ConfigurationHandlerTypeName, true, true);
|
||||
|
||||
if (!string.IsNullOrEmpty(this.WebHandlerTypeName) && this.WebHandlerType == null)
|
||||
this.WebHandlerType = this.PluginAssembly.GetType(this.WebHandlerTypeName, true, true);
|
||||
|
||||
// Update non-static values
|
||||
this.StorageLocation = Path.Combine(dbContext.DiscoConfiguration.PluginStorageLocation, this.Id);
|
||||
|
||||
// Initialize Plugin
|
||||
using (var pluginInstance = this.CreateInstance())
|
||||
{
|
||||
pluginInstance.Initalize(dbContext);
|
||||
}
|
||||
PluginsLog.LogInitializedPlugin(this);
|
||||
|
||||
// Initialize Plugin Features
|
||||
if (Features != null)
|
||||
{
|
||||
foreach (var feature in Features)
|
||||
{
|
||||
feature.Initialize(dbContext, this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Features = new List<PluginFeatureManifest>();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public PluginConfigurationHandler CreateConfigurationHandler()
|
||||
{
|
||||
// Configuration Handler is Required
|
||||
if (this.ConfigurationHandlerType == null)
|
||||
throw new ArgumentNullException("ConfigurationType");
|
||||
if (!typeof(PluginConfigurationHandler).IsAssignableFrom(this.ConfigurationHandlerType))
|
||||
throw new ArgumentException("The Plugin ConfigurationHandlerType must inherit Disco.Services.Plugins.PluginConfigurationHandler", "ConfigurationHandlerType");
|
||||
|
||||
var handler = (PluginConfigurationHandler)Activator.CreateInstance(this.ConfigurationHandlerType);
|
||||
|
||||
handler.Manifest = this;
|
||||
|
||||
return handler;
|
||||
}
|
||||
[JsonIgnore]
|
||||
public bool HasWebHandler
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.WebHandlerType != null;
|
||||
}
|
||||
}
|
||||
public PluginWebHandler CreateWebHandler(Controller HostController)
|
||||
{
|
||||
// Web Handler is Not Required
|
||||
if (this.WebHandlerType == null)
|
||||
return null;
|
||||
|
||||
if (!typeof(PluginWebHandler).IsAssignableFrom(this.WebHandlerType))
|
||||
throw new ArgumentException("The Plugin WebHandlerType must inherit Disco.Services.Plugins.PluginWebHandler", "WebHandlerType");
|
||||
|
||||
var handler = (PluginWebHandler)Activator.CreateInstance(this.WebHandlerType);
|
||||
|
||||
handler.Manifest = this;
|
||||
handler.HostController = HostController;
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
public Tuple<string, string> WebResourcePath(string Resource)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Resource))
|
||||
throw new ArgumentNullException("Resource");
|
||||
|
||||
if (Resource.Contains(".."))
|
||||
throw new ArgumentException("Resource Paths cannot navigate to the parent", "Resource");
|
||||
|
||||
var resourcePath = Path.Combine(this.PluginLocation, "WebResources", Resource.Replace(@"/", @"\"));
|
||||
|
||||
Tuple<string, DateTime> resourceHash;
|
||||
string resourceKey = string.Format("{0}://{1}", this.Name, Resource);
|
||||
if (WebResourceHashes.TryGetValue(resourceKey, out resourceHash))
|
||||
{
|
||||
#if DEBUG
|
||||
var fileDateCheck = System.IO.File.GetLastWriteTime(resourcePath);
|
||||
if (fileDateCheck == resourceHash.Item2)
|
||||
#endif
|
||||
return new Tuple<string, string>(resourcePath, resourceHash.Item1);
|
||||
}
|
||||
|
||||
if (!File.Exists(resourcePath))
|
||||
throw new FileNotFoundException(string.Format("Resource [{0}] not found", Resource), resourcePath);
|
||||
|
||||
var fileDate = System.IO.File.GetLastWriteTime(resourcePath);
|
||||
var fileBytes = System.IO.File.ReadAllBytes(resourcePath);
|
||||
if (fileBytes.Length > 0)
|
||||
{
|
||||
using (SHA256 sha = SHA256.Create())
|
||||
{
|
||||
byte[] hash = sha.ComputeHash(fileBytes);
|
||||
resourceHash = new Tuple<string, DateTime>(HttpServerUtility.UrlTokenEncode(hash), fileDate);
|
||||
}
|
||||
}
|
||||
WebResourceHashes[resourceKey] = resourceHash;
|
||||
|
||||
return new Tuple<string, string>(resourcePath, resourceHash.Item1);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Services.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Disco.Services.Plugins
|
||||
{
|
||||
public class PluginManifest
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Author { get; set; }
|
||||
public Version Version { get; set; }
|
||||
[JsonProperty]
|
||||
internal string AssemblyPath { get; set; }
|
||||
[JsonProperty]
|
||||
private string TypeName { get; set; }
|
||||
[JsonProperty]
|
||||
private string ConfigurationHandlerTypeName { get; set; }
|
||||
[JsonProperty]
|
||||
private string WebHandlerTypeName { get; set; }
|
||||
|
||||
[JsonProperty]
|
||||
internal Dictionary<string, string> AssemblyReferences { get; set; }
|
||||
|
||||
[JsonProperty]
|
||||
public List<PluginFeatureManifest> Features { get; private set; }
|
||||
|
||||
[JsonIgnore]
|
||||
internal Assembly PluginAssembly { get; private set; }
|
||||
[JsonIgnore]
|
||||
internal Type Type { get; private set; }
|
||||
[JsonIgnore]
|
||||
private Type ConfigurationHandlerType { get; set; }
|
||||
[JsonIgnore]
|
||||
private Type WebHandlerType { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string PluginLocation { get; private set; }
|
||||
[JsonIgnore]
|
||||
public string StorageLocation { get; private set; }
|
||||
|
||||
[JsonIgnore]
|
||||
private bool environmentInitalized { get; set; }
|
||||
|
||||
private static Dictionary<string, Tuple<string, DateTime>> WebResourceHashes = new Dictionary<string, Tuple<string, DateTime>>();
|
||||
|
||||
public List<PluginFeatureManifest> GetFeatures(Type FeatureCategoryType)
|
||||
{
|
||||
return this.Features.Where(fm => fm.CategoryType.IsAssignableFrom(FeatureCategoryType)).ToList();
|
||||
}
|
||||
public PluginFeatureManifest GetFeature(string PluginFeatureId)
|
||||
{
|
||||
return this.Features.Where(fm => fm.Id == PluginFeatureId).FirstOrDefault();
|
||||
}
|
||||
|
||||
public Plugin CreateInstance()
|
||||
{
|
||||
var i = (Plugin)Activator.CreateInstance(Type);
|
||||
i.Manifest = this;
|
||||
return i;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes a Json Manifest
|
||||
/// </summary>
|
||||
/// <param name="FilePath">Path to the Json Manifest file</param>
|
||||
/// <returns></returns>
|
||||
public static PluginManifest FromPluginManifestFile(string FilePath)
|
||||
{
|
||||
using (Stream manifestStream = File.OpenRead(FilePath))
|
||||
{
|
||||
PluginManifest manifest = FromPluginManifestFile(manifestStream, Path.GetDirectoryName(FilePath));
|
||||
return manifest;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes a Json Manifest
|
||||
/// </summary>
|
||||
/// <param name="FileStream">Stream containing the encoded Json Manifest File</param>
|
||||
/// <param name="PluginLocation">PluginLocation to be set in the manifest</param>
|
||||
/// <returns></returns>
|
||||
public static PluginManifest FromPluginManifestFile(Stream FileStream, string PluginLocation = null)
|
||||
{
|
||||
string manifestString;
|
||||
using (StreamReader manifestStreamReader = new StreamReader(FileStream))
|
||||
{
|
||||
manifestString = manifestStreamReader.ReadToEnd();
|
||||
}
|
||||
|
||||
var manifest = JsonConvert.DeserializeObject<PluginManifest>(manifestString);
|
||||
|
||||
manifest.PluginLocation = PluginLocation;
|
||||
|
||||
return manifest;
|
||||
}
|
||||
/// <summary>
|
||||
/// Uses reflection to build a Plugin Manifest
|
||||
/// </summary>
|
||||
/// <param name="pluginAssembly">Assembly containing a plugin</param>
|
||||
/// <returns>A plugin manifest for the first encountered plugin within the assembly</returns>
|
||||
public static PluginManifest FromPluginAssembly(Assembly assembly)
|
||||
{
|
||||
// Determine Plugin Properties
|
||||
var pluginType = (from type in assembly.GetTypes()
|
||||
where typeof(Plugin).IsAssignableFrom(type) && !type.IsAbstract
|
||||
select type).FirstOrDefault();
|
||||
|
||||
if (pluginType == null)
|
||||
throw new ArgumentException("No Plugin was found in this Assembly", "pluginAssembly");
|
||||
|
||||
var assemblyName = assembly.GetName();
|
||||
|
||||
var pluginAttributes = pluginType.GetCustomAttribute<PluginAttribute>(false);
|
||||
|
||||
if (pluginAttributes == null)
|
||||
throw new ArgumentException(string.Format("Plugin found [{0}], but no PluginAttribute found", pluginType.Name), "pluginAssembly");
|
||||
|
||||
var pluginId = pluginAttributes.Id;
|
||||
var pluginName = pluginAttributes.Name;
|
||||
var pluginAuthor = pluginAttributes.Author;
|
||||
|
||||
var pluginVersion = assemblyName.Version;
|
||||
var pluginAssemblyPath = Path.GetFileName(assembly.Location);
|
||||
var pluginTypeName = pluginType.FullName;
|
||||
var pluginLocation = Path.GetDirectoryName(assembly.Location);
|
||||
|
||||
// Find Configuration Handler
|
||||
var pluginConfigurationHandlerType = (from type in assembly.GetTypes()
|
||||
where typeof(PluginConfigurationHandler).IsAssignableFrom(type) && !type.IsAbstract
|
||||
select type).FirstOrDefault();
|
||||
if (pluginConfigurationHandlerType == null)
|
||||
throw new ArgumentException("A Plugin was found, but no Configuration Handler was found in this Assembly - this is required", "pluginAssembly");
|
||||
|
||||
// Find Web Handler
|
||||
var pluginWebHandlerType = (from type in assembly.GetTypes()
|
||||
where typeof(PluginWebHandler).IsAssignableFrom(type) && !type.IsAbstract
|
||||
select type).FirstOrDefault();
|
||||
|
||||
Dictionary<string, string> pluginAssemblyReferences = new Dictionary<string, string>();
|
||||
foreach (string referenceFilename in Directory.EnumerateFiles(pluginLocation, "*.dll", SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
if (!referenceFilename.Equals(assembly.Location, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
try
|
||||
{
|
||||
Assembly pluginRefAssembly = Assembly.ReflectionOnlyLoadFrom(referenceFilename);
|
||||
pluginAssemblyReferences[pluginRefAssembly.FullName] = referenceFilename.Substring(pluginLocation.Length + 1);
|
||||
}
|
||||
catch (Exception) { } // Ignore Load Exceptions
|
||||
}
|
||||
}
|
||||
|
||||
PluginManifest pluginManifest = new PluginManifest()
|
||||
{
|
||||
Id = pluginId,
|
||||
Name = pluginName,
|
||||
Author = pluginAuthor,
|
||||
Version = pluginVersion,
|
||||
AssemblyPath = pluginAssemblyPath,
|
||||
TypeName = pluginTypeName,
|
||||
AssemblyReferences = pluginAssemblyReferences,
|
||||
PluginAssembly = assembly,
|
||||
Type = pluginType,
|
||||
PluginLocation = pluginLocation,
|
||||
ConfigurationHandlerType = pluginConfigurationHandlerType,
|
||||
ConfigurationHandlerTypeName = pluginConfigurationHandlerType.FullName,
|
||||
WebHandlerType = pluginWebHandlerType,
|
||||
WebHandlerTypeName = (pluginWebHandlerType == null ? null : pluginWebHandlerType.FullName)
|
||||
};
|
||||
|
||||
pluginManifest.Features = (from type in assembly.GetTypes()
|
||||
where typeof(PluginFeature).IsAssignableFrom(type) && !type.IsAbstract
|
||||
select PluginFeatureManifest.FromPluginFeatureType(type, pluginManifest)).ToList();
|
||||
|
||||
return pluginManifest;
|
||||
}
|
||||
|
||||
public string ToManifestFile()
|
||||
{
|
||||
return JsonConvert.SerializeObject(this, Formatting.Indented);
|
||||
}
|
||||
private bool InitializePluginEnvironment(DiscoDataContext dbContext)
|
||||
{
|
||||
if (!environmentInitalized)
|
||||
{
|
||||
|
||||
var assemblyFullPath = Path.Combine(this.PluginLocation, this.AssemblyPath);
|
||||
|
||||
if (!File.Exists(assemblyFullPath))
|
||||
throw new FileNotFoundException(string.Format("Plugin Assembly [{0}] not found at: {1}", this.Id, assemblyFullPath), assemblyFullPath);
|
||||
|
||||
if (this.PluginAssembly == null)
|
||||
this.PluginAssembly = Assembly.LoadFile(assemblyFullPath);
|
||||
|
||||
if (this.PluginAssembly == null)
|
||||
throw new InvalidOperationException(string.Format("Unable to load Plugin Assembly [{0}] at: {1}", this.Id, assemblyFullPath));
|
||||
|
||||
PluginsLog.LogInitializingPluginAssembly(this.PluginAssembly);
|
||||
|
||||
// Check Manifest/Assembly Versions Match
|
||||
if (this.Version != this.PluginAssembly.GetName().Version)
|
||||
throw new InvalidOperationException(string.Format("The plugin [{0}] manifest version [{1}] doesn't match the plugin assembly [{2} : {3}]", this.Id, this.Version, assemblyFullPath, this.PluginAssembly.GetName().Version));
|
||||
|
||||
if (this.Type == null)
|
||||
this.Type = this.PluginAssembly.GetType(this.TypeName, true, true);
|
||||
|
||||
if (this.ConfigurationHandlerType == null)
|
||||
this.ConfigurationHandlerType = this.PluginAssembly.GetType(this.ConfigurationHandlerTypeName, true, true);
|
||||
|
||||
if (!string.IsNullOrEmpty(this.WebHandlerTypeName) && this.WebHandlerType == null)
|
||||
this.WebHandlerType = this.PluginAssembly.GetType(this.WebHandlerTypeName, true, true);
|
||||
|
||||
// Update non-static values
|
||||
this.StorageLocation = Path.Combine(dbContext.DiscoConfiguration.PluginStorageLocation, this.Id);
|
||||
|
||||
environmentInitalized = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
internal bool BeforePluginUpdate(DiscoDataContext dbContext, PluginManifest UpdateManifest, ScheduledTaskStatus Status)
|
||||
{
|
||||
// Initialize Plugin
|
||||
InitializePluginEnvironment(dbContext);
|
||||
|
||||
using (var pluginInstance = this.CreateInstance())
|
||||
{
|
||||
pluginInstance.BeforeUpdate(dbContext, UpdateManifest, Status);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
internal bool AfterPluginUpdate(DiscoDataContext dbContext, PluginManifest PreviousManifest)
|
||||
{
|
||||
// Initialize Plugin
|
||||
InitializePluginEnvironment(dbContext);
|
||||
|
||||
using (var pluginInstance = this.CreateInstance())
|
||||
{
|
||||
pluginInstance.AfterUpdate(dbContext, PreviousManifest);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
internal bool UninstallPlugin(DiscoDataContext dbContext, bool UninstallData, ScheduledTaskStatus Status)
|
||||
{
|
||||
// Initialize Plugin
|
||||
InitializePluginEnvironment(dbContext);
|
||||
|
||||
using (var pluginInstance = this.CreateInstance())
|
||||
{
|
||||
pluginInstance.Uninstall(dbContext, UninstallData, Status);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
internal bool InstallPlugin(DiscoDataContext dbContext, ScheduledTaskStatus Status)
|
||||
{
|
||||
// Initialize Plugin
|
||||
InitializePluginEnvironment(dbContext);
|
||||
|
||||
using (var pluginInstance = this.CreateInstance())
|
||||
{
|
||||
pluginInstance.Install(dbContext, Status);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
internal bool InitializePlugin(DiscoDataContext dbContext)
|
||||
{
|
||||
// Initialize Plugin
|
||||
InitializePluginEnvironment(dbContext);
|
||||
|
||||
// Initialize Plugin
|
||||
using (var pluginInstance = this.CreateInstance())
|
||||
{
|
||||
pluginInstance.Initialize(dbContext);
|
||||
}
|
||||
PluginsLog.LogInitializedPlugin(this);
|
||||
|
||||
// Initialize Plugin Features
|
||||
if (Features != null)
|
||||
{
|
||||
foreach (var feature in Features)
|
||||
{
|
||||
feature.Initialize(dbContext, this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Features = new List<PluginFeatureManifest>();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public PluginConfigurationHandler CreateConfigurationHandler()
|
||||
{
|
||||
// Configuration Handler is Required
|
||||
if (this.ConfigurationHandlerType == null)
|
||||
throw new ArgumentNullException("ConfigurationType");
|
||||
if (!typeof(PluginConfigurationHandler).IsAssignableFrom(this.ConfigurationHandlerType))
|
||||
throw new ArgumentException("The Plugin ConfigurationHandlerType must inherit Disco.Services.Plugins.PluginConfigurationHandler", "ConfigurationHandlerType");
|
||||
|
||||
var handler = (PluginConfigurationHandler)Activator.CreateInstance(this.ConfigurationHandlerType);
|
||||
|
||||
handler.Manifest = this;
|
||||
|
||||
return handler;
|
||||
}
|
||||
[JsonIgnore]
|
||||
public bool HasWebHandler
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.WebHandlerType != null;
|
||||
}
|
||||
}
|
||||
public PluginWebHandler CreateWebHandler(Controller HostController)
|
||||
{
|
||||
// Web Handler is Not Required
|
||||
if (this.WebHandlerType == null)
|
||||
return null;
|
||||
|
||||
if (!typeof(PluginWebHandler).IsAssignableFrom(this.WebHandlerType))
|
||||
throw new ArgumentException("The Plugin WebHandlerType must inherit Disco.Services.Plugins.PluginWebHandler", "WebHandlerType");
|
||||
|
||||
var handler = (PluginWebHandler)Activator.CreateInstance(this.WebHandlerType);
|
||||
|
||||
handler.Manifest = this;
|
||||
handler.HostController = HostController;
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
public Tuple<string, string> WebResourcePath(string Resource)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Resource))
|
||||
throw new ArgumentNullException("Resource");
|
||||
|
||||
if (Resource.Contains(".."))
|
||||
throw new ArgumentException("Resource Paths cannot navigate to the parent", "Resource");
|
||||
|
||||
var resourcePath = Path.Combine(this.PluginLocation, "WebResources", Resource.Replace(@"/", @"\"));
|
||||
|
||||
Tuple<string, DateTime> resourceHash;
|
||||
string resourceKey = string.Format("{0}://{1}", this.Name, Resource);
|
||||
if (WebResourceHashes.TryGetValue(resourceKey, out resourceHash))
|
||||
{
|
||||
#if DEBUG
|
||||
var fileDateCheck = System.IO.File.GetLastWriteTime(resourcePath);
|
||||
if (fileDateCheck == resourceHash.Item2)
|
||||
#endif
|
||||
return new Tuple<string, string>(resourcePath, resourceHash.Item1);
|
||||
}
|
||||
|
||||
if (!File.Exists(resourcePath))
|
||||
throw new FileNotFoundException(string.Format("Resource [{0}] not found", Resource), resourcePath);
|
||||
|
||||
var fileDate = System.IO.File.GetLastWriteTime(resourcePath);
|
||||
var fileBytes = System.IO.File.ReadAllBytes(resourcePath);
|
||||
if (fileBytes.Length > 0)
|
||||
{
|
||||
using (SHA256 sha = SHA256.Create())
|
||||
{
|
||||
byte[] hash = sha.ComputeHash(fileBytes);
|
||||
resourceHash = new Tuple<string, DateTime>(HttpServerUtility.UrlTokenEncode(hash), fileDate);
|
||||
}
|
||||
}
|
||||
WebResourceHashes[resourceKey] = resourceHash;
|
||||
|
||||
return new Tuple<string, string>(resourcePath, resourceHash.Item1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+427
-363
@@ -1,363 +1,427 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Disco.Data.Repository;
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace Disco.Services.Plugins
|
||||
{
|
||||
public static class Plugins
|
||||
{
|
||||
private static Dictionary<Assembly, PluginManifest> _PluginAssemblyManifests;
|
||||
private static Dictionary<string, PluginManifest> _PluginManifests;
|
||||
internal static Dictionary<Type, string> FeatureCategoryDisplayNames;
|
||||
|
||||
private static object _PluginLock = new object();
|
||||
public static string PluginPath { get; private set; }
|
||||
|
||||
public static PluginManifest GetPlugin(string PluginId, Type ContainsCategoryType)
|
||||
{
|
||||
if (_PluginManifests == null)
|
||||
throw new InvalidOperationException("Plugins have not been initialized");
|
||||
|
||||
PluginManifest manifest;
|
||||
if (_PluginManifests.TryGetValue(PluginId, out manifest))
|
||||
{
|
||||
if (ContainsCategoryType == null)
|
||||
return manifest;
|
||||
else
|
||||
{
|
||||
foreach (var featureManifest in manifest.Features)
|
||||
{
|
||||
if (ContainsCategoryType.IsAssignableFrom(featureManifest.CategoryType))
|
||||
return manifest;
|
||||
}
|
||||
|
||||
throw new InvalidFeatureCategoryTypeException(ContainsCategoryType, PluginId);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new UnknownPluginException(PluginId);
|
||||
}
|
||||
}
|
||||
public static PluginManifest GetPlugin(string PluginId)
|
||||
{
|
||||
return GetPlugin(PluginId, null);
|
||||
}
|
||||
public static PluginManifest GetPlugin(Assembly PluginAssembly)
|
||||
{
|
||||
if (_PluginAssemblyManifests == null)
|
||||
throw new InvalidOperationException("Plugins have not been initialized");
|
||||
|
||||
PluginManifest manifest;
|
||||
if (_PluginAssemblyManifests.TryGetValue(PluginAssembly, out manifest))
|
||||
{
|
||||
return manifest;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new UnknownPluginException(PluginAssembly.FullName);
|
||||
}
|
||||
}
|
||||
public static List<PluginManifest> GetPlugins()
|
||||
{
|
||||
if (_PluginManifests == null)
|
||||
throw new InvalidOperationException("Plugins have not been initialized");
|
||||
|
||||
return _PluginManifests.Values.ToList();
|
||||
}
|
||||
|
||||
public static PluginFeatureManifest GetPluginFeature(string PluginFeatureId, Type CategoryType)
|
||||
{
|
||||
if (_PluginManifests == null)
|
||||
throw new InvalidOperationException("Plugins have not been initialized");
|
||||
|
||||
var featureManifest = _PluginManifests.Values.SelectMany(pm => pm.Features).Where(fm => fm.Id == PluginFeatureId).FirstOrDefault();
|
||||
|
||||
if (featureManifest == null)
|
||||
throw new UnknownPluginException(PluginFeatureId, "Unknown Feature");
|
||||
|
||||
if (CategoryType == null)
|
||||
return featureManifest;
|
||||
else
|
||||
if (CategoryType.IsAssignableFrom(featureManifest.CategoryType))
|
||||
return featureManifest;
|
||||
else
|
||||
throw new InvalidFeatureCategoryTypeException(CategoryType, PluginFeatureId);
|
||||
}
|
||||
public static PluginFeatureManifest GetPluginFeature(string PluginFeatureId)
|
||||
{
|
||||
return GetPluginFeature(PluginFeatureId, null);
|
||||
}
|
||||
public static List<PluginFeatureManifest> GetPluginFeatures(Type FeatureCategoryType)
|
||||
{
|
||||
if (_PluginManifests == null)
|
||||
throw new InvalidOperationException("Plugins have not been initialized");
|
||||
|
||||
return _PluginManifests.Values.SelectMany(pm => pm.Features).Where(fm => fm.CategoryType.IsAssignableFrom(FeatureCategoryType)).OrderBy(fm => fm.PluginManifest.Name).ToList();
|
||||
}
|
||||
public static List<PluginFeatureManifest> GetPluginFeatures()
|
||||
{
|
||||
if (_PluginManifests == null)
|
||||
throw new InvalidOperationException("Plugins have not been initialized");
|
||||
|
||||
return _PluginManifests.Values.SelectMany(pm => pm.Features).ToList();
|
||||
}
|
||||
|
||||
|
||||
public static string PluginFeatureCategoryDisplayName(Type FeatureCategoryType)
|
||||
{
|
||||
if (FeatureCategoryType == null)
|
||||
throw new ArgumentNullException("FeatureType");
|
||||
|
||||
string displayName;
|
||||
if (FeatureCategoryDisplayNames.TryGetValue(FeatureCategoryType, out displayName))
|
||||
return displayName;
|
||||
else
|
||||
throw new InvalidOperationException(string.Format("Unknown Plugin Feature Category Type: [{0}]", FeatureCategoryType.Name));
|
||||
}
|
||||
|
||||
public static void InitalizePlugins(DiscoDataContext dbContext)
|
||||
{
|
||||
if (_PluginManifests == null)
|
||||
{
|
||||
lock (_PluginLock)
|
||||
{
|
||||
if (_PluginManifests == null)
|
||||
{
|
||||
Dictionary<string, PluginManifest> loadedPlugins = new Dictionary<string, PluginManifest>();
|
||||
|
||||
PluginPath = dbContext.DiscoConfiguration.PluginsLocation;
|
||||
|
||||
AppDomain appDomain = AppDomain.CurrentDomain;
|
||||
|
||||
// Subscribe to Assembly Resolving
|
||||
appDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
|
||||
|
||||
DirectoryInfo pluginDirectoryRoot = new DirectoryInfo(PluginPath);
|
||||
if (pluginDirectoryRoot.Exists)
|
||||
{
|
||||
foreach (DirectoryInfo pluginDirectory in pluginDirectoryRoot.EnumerateDirectories())
|
||||
{
|
||||
string pluginManifestFilename = Path.Combine(pluginDirectory.FullName, "manifest.json");
|
||||
if (File.Exists(pluginManifestFilename))
|
||||
{
|
||||
PluginManifest pluginManifest = null;
|
||||
try
|
||||
{
|
||||
pluginManifest = PluginManifest.FromPluginManifestFile(pluginManifestFilename);
|
||||
|
||||
if (pluginManifest != null)
|
||||
{
|
||||
if (loadedPlugins.ContainsKey(pluginManifest.Id))
|
||||
throw new InvalidOperationException(string.Format("The plugin [{0}] is already initialized", pluginManifest.Id));
|
||||
|
||||
pluginManifest.InitializePlugin(dbContext);
|
||||
|
||||
loadedPlugins[pluginManifest.Id] = pluginManifest;
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { PluginsLog.LogInitializeException(pluginManifestFilename, ex); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_PluginManifests = loadedPlugins;
|
||||
|
||||
ReinitializePluginEnvironment();
|
||||
|
||||
// Install Plugins - TEMPORARY? Workaround until UI in place? Or Useful for 'built-in' plugins?
|
||||
if (pluginDirectoryRoot.Exists)
|
||||
{
|
||||
foreach (FileInfo pluginPackageFile in pluginDirectoryRoot.EnumerateFiles("*.discoPlugin", SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
// Install Plugin
|
||||
InstallPlugin(dbContext, pluginPackageFile.FullName);
|
||||
// Delete Package File
|
||||
pluginPackageFile.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReinitializePluginEnvironment()
|
||||
{
|
||||
FeatureCategoryDisplayNames = InitializeFeatureCategoryDetails(_PluginManifests.Values);
|
||||
_PluginAssemblyManifests = _PluginManifests.Values.ToDictionary(p => p.PluginAssembly, p => p);
|
||||
}
|
||||
|
||||
public static void InstallPlugin(DiscoDataContext dbContext, String PackageFilePath)
|
||||
{
|
||||
using (var packageStream = File.OpenRead(PackageFilePath))
|
||||
{
|
||||
InstallPlugin(dbContext, packageStream);
|
||||
}
|
||||
}
|
||||
|
||||
public static void InstallPlugin(DiscoDataContext dbContext, Stream PluginPackage)
|
||||
{
|
||||
if (_PluginManifests == null)
|
||||
throw new InvalidOperationException("Plugins have not been initialized");
|
||||
|
||||
using (MemoryStream packageStream = new MemoryStream())
|
||||
{
|
||||
PluginPackage.CopyTo(packageStream);
|
||||
packageStream.Position = 0;
|
||||
|
||||
using (ZipArchive packageArchive = new ZipArchive(packageStream, ZipArchiveMode.Read, false))
|
||||
{
|
||||
|
||||
ZipArchiveEntry packageManifestEntry = packageArchive.GetEntry("manifest.json");
|
||||
if (packageManifestEntry == null)
|
||||
throw new InvalidDataException("The plugin package does not contain the 'manifest.json' entry");
|
||||
|
||||
PluginManifest packageManifest;
|
||||
|
||||
using (Stream packageManifestStream = packageManifestEntry.Open())
|
||||
{
|
||||
packageManifest = PluginManifest.FromPluginManifestFile(packageManifestStream);
|
||||
}
|
||||
|
||||
lock (_PluginLock)
|
||||
{
|
||||
if (_PluginManifests == null)
|
||||
throw new InvalidOperationException("Plugins have not been initialized");
|
||||
|
||||
// Ensure not already installed
|
||||
if (_PluginManifests.ContainsKey(packageManifest.Id))
|
||||
throw new InvalidOperationException(string.Format("The '{0} [{1}]' Plugin is already installed, please uninstall any existing versions before trying again", packageManifest.Name, packageManifest.Id));
|
||||
|
||||
string packagePath = Path.Combine(dbContext.DiscoConfiguration.PluginsLocation, packageManifest.Id);
|
||||
|
||||
// Force Delete of Existing Folder
|
||||
if (Directory.Exists(packagePath))
|
||||
Directory.Delete(packagePath, true);
|
||||
|
||||
Directory.CreateDirectory(packagePath);
|
||||
|
||||
// Extract Package Contents
|
||||
foreach (var packageEntry in packageArchive.Entries)
|
||||
{
|
||||
// Determine Extraction Path
|
||||
var packageEntryTarget = Path.Combine(packagePath, packageEntry.FullName);
|
||||
|
||||
// Create Sub Directories
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(packageEntryTarget));
|
||||
|
||||
using (var packageEntryStream = packageEntry.Open())
|
||||
{
|
||||
using (var packageTargetStream = File.Open(packageEntryTarget, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
packageEntryStream.CopyTo(packageTargetStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reload Manifest
|
||||
packageManifest = PluginManifest.FromPluginManifestFile(Path.Combine(packagePath, "manifest.json"));
|
||||
|
||||
// Initialize Plugin
|
||||
packageManifest.InitializePlugin(dbContext);
|
||||
|
||||
// Add Plugin Manifest to Environment
|
||||
_PluginManifests[packageManifest.Id] = packageManifest;
|
||||
|
||||
// Reinitialize Plugin Environment
|
||||
ReinitializePluginEnvironment();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<Type, string> InitializeFeatureCategoryDetails(IEnumerable<PluginManifest> pluginManifests)
|
||||
{
|
||||
Dictionary<Type, string> categoryDisplayNames = new Dictionary<Type, string>();
|
||||
|
||||
// Always add 'Other'
|
||||
var otherFeatureType = typeof(Features.Other.OtherFeature);
|
||||
categoryDisplayNames.Add(otherFeatureType, ((PluginFeatureCategoryAttribute)otherFeatureType.GetCustomAttributes(typeof(PluginFeatureCategoryAttribute), false).FirstOrDefault()).DisplayName);
|
||||
|
||||
foreach (var pluginManifest in pluginManifests)
|
||||
{
|
||||
foreach (var featureManifest in pluginManifest.Features)
|
||||
{
|
||||
if (!categoryDisplayNames.ContainsKey(featureManifest.CategoryType))
|
||||
{
|
||||
string displayName = null;
|
||||
|
||||
var displayAttributes = featureManifest.CategoryType.GetCustomAttributes(typeof(PluginFeatureCategoryAttribute), true);
|
||||
if (displayAttributes != null && displayAttributes.Length > 0)
|
||||
displayName = ((PluginFeatureCategoryAttribute)(displayAttributes[0])).DisplayName;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(displayName))
|
||||
displayName = featureManifest.CategoryType.Name;
|
||||
|
||||
categoryDisplayNames[featureManifest.CategoryType] = displayName;
|
||||
}
|
||||
}
|
||||
}
|
||||
return categoryDisplayNames;
|
||||
}
|
||||
|
||||
#region Plugin Referenced Assemblies Resolving
|
||||
|
||||
public static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
||||
{
|
||||
if (args.RequestingAssembly.Location.StartsWith(PluginPath, StringComparison.InvariantCultureIgnoreCase) && _PluginManifests != null)
|
||||
{
|
||||
// Try best guess first
|
||||
PluginManifest requestingPlugin = _PluginManifests.Values.Where(p => p.Type.Assembly == args.RequestingAssembly).FirstOrDefault();
|
||||
if (requestingPlugin != null)
|
||||
{
|
||||
Assembly loadedAssembly = CurrentDomain_AssemblyResolve_ByPlugin(requestingPlugin, args);
|
||||
if (loadedAssembly != null)
|
||||
return loadedAssembly;
|
||||
}
|
||||
|
||||
// Try all Plugin References
|
||||
foreach (var pluginDef in _PluginManifests.Values)
|
||||
{
|
||||
Assembly loadedAssembly = CurrentDomain_AssemblyResolve_ByPlugin(pluginDef, args);
|
||||
if (loadedAssembly != null)
|
||||
return loadedAssembly;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private static Assembly CurrentDomain_AssemblyResolve_ByPlugin(PluginManifest pluginManifest, ResolveEventArgs args)
|
||||
{
|
||||
if (pluginManifest.AssemblyReferences != null)
|
||||
{
|
||||
string assemblyPath;
|
||||
if (pluginManifest.AssemblyReferences.TryGetValue(args.Name, out assemblyPath))
|
||||
{
|
||||
var resolvedAssemblyPath = Path.Combine(pluginManifest.PluginLocation, assemblyPath);
|
||||
|
||||
try
|
||||
{
|
||||
Assembly loadedAssembly = Assembly.LoadFile(resolvedAssemblyPath);
|
||||
|
||||
PluginsLog.LogPluginReferenceAssemblyLoaded(args.Name, resolvedAssemblyPath, args.RequestingAssembly.FullName);
|
||||
|
||||
return loadedAssembly;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginsLog.LogPluginException(string.Format("Resolving Plugin Reference Assembly: '{0}' [{1}]; Requested by: '{2}' [{3}]; Disco.Plugins.DiscoPlugins.CurrentDomain_AssemblyResolve()", args.Name, resolvedAssemblyPath, args.RequestingAssembly.FullName, args.RequestingAssembly.Location), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Disco.Data.Repository;
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace Disco.Services.Plugins
|
||||
{
|
||||
public static class Plugins
|
||||
{
|
||||
private static Dictionary<Assembly, PluginManifest> _PluginAssemblyManifests;
|
||||
private static Dictionary<string, PluginManifest> _PluginManifests;
|
||||
internal static Dictionary<Type, string> FeatureCategoryDisplayNames;
|
||||
|
||||
internal static object _PluginLock = new object();
|
||||
public static string PluginPath { get; private set; }
|
||||
|
||||
public static bool PluginsLoaded
|
||||
{
|
||||
get
|
||||
{
|
||||
return (_PluginManifests != null);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void AddPlugin(PluginManifest Manifest)
|
||||
{
|
||||
lock (_PluginLock)
|
||||
{
|
||||
if (_PluginManifests.ContainsKey(Manifest.Id))
|
||||
throw new InvalidOperationException(string.Format("The '{0} [{1}]' Plugin is already installed, please uninstall any existing versions before trying again", Manifest.Name, Manifest.Id));
|
||||
|
||||
// Add Plugin Manifest to Environment
|
||||
_PluginManifests[Manifest.Id] = Manifest;
|
||||
|
||||
// Reinitialize Plugin Host Environment
|
||||
Plugins.ReinitializePluginHostEnvironment();
|
||||
}
|
||||
}
|
||||
|
||||
public static PluginManifest GetPlugin(string PluginId, Type ContainsCategoryType)
|
||||
{
|
||||
if (_PluginManifests == null)
|
||||
throw new InvalidOperationException("Plugins have not been initialized");
|
||||
|
||||
PluginManifest manifest;
|
||||
if (_PluginManifests.TryGetValue(PluginId, out manifest))
|
||||
{
|
||||
if (ContainsCategoryType == null)
|
||||
return manifest;
|
||||
else
|
||||
{
|
||||
foreach (var featureManifest in manifest.Features)
|
||||
{
|
||||
if (ContainsCategoryType.IsAssignableFrom(featureManifest.CategoryType))
|
||||
return manifest;
|
||||
}
|
||||
|
||||
throw new InvalidFeatureCategoryTypeException(ContainsCategoryType, PluginId);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new UnknownPluginException(PluginId);
|
||||
}
|
||||
}
|
||||
public static PluginManifest GetPlugin(string PluginId)
|
||||
{
|
||||
return GetPlugin(PluginId, null);
|
||||
}
|
||||
public static PluginManifest GetPlugin(Assembly PluginAssembly)
|
||||
{
|
||||
if (_PluginAssemblyManifests == null)
|
||||
throw new InvalidOperationException("Plugins have not been initialized");
|
||||
|
||||
PluginManifest manifest;
|
||||
if (_PluginAssemblyManifests.TryGetValue(PluginAssembly, out manifest))
|
||||
{
|
||||
return manifest;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new UnknownPluginException(PluginAssembly.FullName);
|
||||
}
|
||||
}
|
||||
public static List<PluginManifest> GetPlugins()
|
||||
{
|
||||
if (_PluginManifests == null)
|
||||
throw new InvalidOperationException("Plugins have not been initialized");
|
||||
|
||||
return _PluginManifests.Values.ToList();
|
||||
}
|
||||
|
||||
public static PluginFeatureManifest GetPluginFeature(string PluginFeatureId, Type CategoryType)
|
||||
{
|
||||
if (_PluginManifests == null)
|
||||
throw new InvalidOperationException("Plugins have not been initialized");
|
||||
|
||||
var featureManifest = _PluginManifests.Values.SelectMany(pm => pm.Features).Where(fm => fm.Id == PluginFeatureId).FirstOrDefault();
|
||||
|
||||
if (featureManifest == null)
|
||||
throw new UnknownPluginException(PluginFeatureId, "Unknown Feature");
|
||||
|
||||
if (CategoryType == null)
|
||||
return featureManifest;
|
||||
else
|
||||
if (CategoryType.IsAssignableFrom(featureManifest.CategoryType))
|
||||
return featureManifest;
|
||||
else
|
||||
throw new InvalidFeatureCategoryTypeException(CategoryType, PluginFeatureId);
|
||||
}
|
||||
public static PluginFeatureManifest GetPluginFeature(string PluginFeatureId)
|
||||
{
|
||||
return GetPluginFeature(PluginFeatureId, null);
|
||||
}
|
||||
public static List<PluginFeatureManifest> GetPluginFeatures(Type FeatureCategoryType)
|
||||
{
|
||||
if (_PluginManifests == null)
|
||||
throw new InvalidOperationException("Plugins have not been initialized");
|
||||
|
||||
return _PluginManifests.Values.SelectMany(pm => pm.Features).Where(fm => fm.CategoryType.IsAssignableFrom(FeatureCategoryType)).OrderBy(fm => fm.PluginManifest.Name).ToList();
|
||||
}
|
||||
public static List<PluginFeatureManifest> GetPluginFeatures()
|
||||
{
|
||||
if (_PluginManifests == null)
|
||||
throw new InvalidOperationException("Plugins have not been initialized");
|
||||
|
||||
return _PluginManifests.Values.SelectMany(pm => pm.Features).ToList();
|
||||
}
|
||||
|
||||
|
||||
public static string PluginFeatureCategoryDisplayName(Type FeatureCategoryType)
|
||||
{
|
||||
if (FeatureCategoryType == null)
|
||||
throw new ArgumentNullException("FeatureType");
|
||||
|
||||
string displayName;
|
||||
if (FeatureCategoryDisplayNames.TryGetValue(FeatureCategoryType, out displayName))
|
||||
return displayName;
|
||||
else
|
||||
throw new InvalidOperationException(string.Format("Unknown Plugin Feature Category Type: [{0}]", FeatureCategoryType.Name));
|
||||
}
|
||||
|
||||
public static void InitalizePlugins(DiscoDataContext dbContext)
|
||||
{
|
||||
if (_PluginManifests == null)
|
||||
{
|
||||
lock (_PluginLock)
|
||||
{
|
||||
if (_PluginManifests == null)
|
||||
{
|
||||
Dictionary<string, PluginManifest> loadedPlugins = new Dictionary<string, PluginManifest>();
|
||||
|
||||
PluginPath = dbContext.DiscoConfiguration.PluginsLocation;
|
||||
|
||||
AppDomain appDomain = AppDomain.CurrentDomain;
|
||||
|
||||
// Subscribe to Assembly Resolving
|
||||
appDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
|
||||
|
||||
DirectoryInfo pluginDirectoryRoot = new DirectoryInfo(PluginPath);
|
||||
if (pluginDirectoryRoot.Exists)
|
||||
{
|
||||
foreach (DirectoryInfo pluginDirectory in pluginDirectoryRoot.EnumerateDirectories())
|
||||
{
|
||||
string pluginManifestFilename = Path.Combine(pluginDirectory.FullName, "manifest.json");
|
||||
if (File.Exists(pluginManifestFilename))
|
||||
{
|
||||
PluginManifest pluginManifest = null;
|
||||
try
|
||||
{
|
||||
pluginManifest = PluginManifest.FromPluginManifestFile(pluginManifestFilename);
|
||||
|
||||
if (pluginManifest != null)
|
||||
{
|
||||
if (loadedPlugins.ContainsKey(pluginManifest.Id))
|
||||
throw new InvalidOperationException(string.Format("The plugin [{0}] is already initialized", pluginManifest.Id));
|
||||
|
||||
// Check for Update
|
||||
string updatePackagePath = Path.Combine(pluginDirectoryRoot.FullName, string.Format("{0}.discoPlugin", pluginManifest.Id));
|
||||
if (File.Exists(updatePackagePath))
|
||||
{
|
||||
// Update Plugin
|
||||
pluginManifest = UpdatePlugin(dbContext, pluginManifest, updatePackagePath);
|
||||
}
|
||||
|
||||
if (pluginManifest != null)
|
||||
{
|
||||
pluginManifest.InitializePlugin(dbContext);
|
||||
loadedPlugins[pluginManifest.Id] = pluginManifest;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { PluginsLog.LogInitializeException(pluginManifestFilename, ex); }
|
||||
}
|
||||
else
|
||||
{
|
||||
string pluginManifestUninstallFilename = Path.Combine(pluginDirectory.FullName, "manifest.uninstall.json");
|
||||
if (File.Exists(pluginManifestUninstallFilename))
|
||||
{
|
||||
PluginManifest uninstallManifest = PluginManifest.FromPluginManifestFile(pluginManifestUninstallFilename);
|
||||
|
||||
// Remove All Files
|
||||
DateTime removeRetryTime = DateTime.Now.AddSeconds(60);
|
||||
while (true)
|
||||
{
|
||||
UnauthorizedAccessException lastAccessException;
|
||||
try
|
||||
{
|
||||
pluginDirectory.Delete(true);
|
||||
break;
|
||||
}
|
||||
catch (UnauthorizedAccessException ex) { lastAccessException = ex; }
|
||||
if (removeRetryTime < DateTime.Now)
|
||||
throw lastAccessException;
|
||||
System.Threading.Thread.Sleep(2000);
|
||||
}
|
||||
|
||||
// Check for Data Removal
|
||||
bool DataUninstalled = false;
|
||||
string pluginStorageLocation = Path.Combine(dbContext.DiscoConfiguration.PluginStorageLocation, uninstallManifest.Id);
|
||||
|
||||
string pluginManifestUninstallDataFilename = Path.Combine(pluginStorageLocation, "manifest.uninstall.json");
|
||||
if (File.Exists(pluginManifestUninstallDataFilename))
|
||||
{
|
||||
DataUninstalled = true;
|
||||
Directory.Delete(pluginStorageLocation, true);
|
||||
}
|
||||
|
||||
PluginsLog.LogUninstalled(uninstallManifest, DataUninstalled);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_PluginManifests = loadedPlugins;
|
||||
|
||||
ReinitializePluginHostEnvironment();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReinitializePluginHostEnvironment()
|
||||
{
|
||||
FeatureCategoryDisplayNames = InitializeFeatureCategoryDetails(_PluginManifests.Values);
|
||||
_PluginAssemblyManifests = _PluginManifests.Values.ToDictionary(p => p.PluginAssembly, p => p);
|
||||
}
|
||||
|
||||
public static PluginManifest UpdatePlugin(DiscoDataContext dbContext, PluginManifest ExistingManifest, String UpdatePluginPackageFilePath)
|
||||
{
|
||||
PluginManifest updatedManifest;
|
||||
|
||||
using (var packageStream = File.OpenRead(UpdatePluginPackageFilePath))
|
||||
{
|
||||
updatedManifest = UpdatePlugin(dbContext, ExistingManifest, packageStream);
|
||||
}
|
||||
|
||||
// Remove Update after processing
|
||||
File.Delete(UpdatePluginPackageFilePath);
|
||||
|
||||
return updatedManifest;
|
||||
}
|
||||
|
||||
public static PluginManifest UpdatePlugin(DiscoDataContext dbContext, PluginManifest ExistingManifest, Stream UpdatePluginPackage)
|
||||
{
|
||||
using (MemoryStream packageStream = new MemoryStream())
|
||||
{
|
||||
if (UpdatePluginPackage.Position != 0)
|
||||
UpdatePluginPackage.Position = 0;
|
||||
|
||||
UpdatePluginPackage.CopyTo(packageStream);
|
||||
packageStream.Position = 0;
|
||||
|
||||
using (ZipArchive packageArchive = new ZipArchive(packageStream, ZipArchiveMode.Read, false))
|
||||
{
|
||||
|
||||
ZipArchiveEntry packageManifestEntry = packageArchive.GetEntry("manifest.json");
|
||||
if (packageManifestEntry == null)
|
||||
throw new InvalidDataException("The plugin package does not contain the 'manifest.json' entry");
|
||||
|
||||
PluginManifest packageManifest;
|
||||
|
||||
using (Stream packageManifestStream = packageManifestEntry.Open())
|
||||
{
|
||||
packageManifest = PluginManifest.FromPluginManifestFile(packageManifestStream);
|
||||
}
|
||||
|
||||
if (ExistingManifest.Version == packageManifest.Version)
|
||||
{
|
||||
// Skip Update if already installed
|
||||
PluginsLog.LogInitializeWarning(string.Format("This plugin [{0}] version [{1}] is already installed, skipping Update", ExistingManifest.Id, ExistingManifest.Version));
|
||||
return ExistingManifest;
|
||||
}
|
||||
if (ExistingManifest.Version > packageManifest.Version)
|
||||
{
|
||||
throw new InvalidDataException("A newer version of this plugin is already installed");
|
||||
}
|
||||
|
||||
string packagePath = Path.Combine(dbContext.DiscoConfiguration.PluginsLocation, packageManifest.Id);
|
||||
|
||||
// Force Delete of Existing Folder
|
||||
if (Directory.Exists(packagePath))
|
||||
Directory.Delete(packagePath, true);
|
||||
|
||||
Directory.CreateDirectory(packagePath);
|
||||
|
||||
// Extract Package Contents
|
||||
foreach (var packageEntry in packageArchive.Entries)
|
||||
{
|
||||
// Determine Extraction Path
|
||||
var packageEntryTarget = Path.Combine(packagePath, packageEntry.FullName);
|
||||
|
||||
// Create Sub Directories
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(packageEntryTarget));
|
||||
|
||||
using (var packageEntryStream = packageEntry.Open())
|
||||
{
|
||||
using (var packageTargetStream = File.Open(packageEntryTarget, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
packageEntryStream.CopyTo(packageTargetStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reload Manifest
|
||||
packageManifest = PluginManifest.FromPluginManifestFile(Path.Combine(packagePath, "manifest.json"));
|
||||
|
||||
// Trigger AfterPluginUpdate
|
||||
packageManifest.AfterPluginUpdate(dbContext, ExistingManifest);
|
||||
|
||||
PluginsLog.LogAfterUpdate(ExistingManifest, packageManifest);
|
||||
|
||||
// Return Updated Manifest
|
||||
return packageManifest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<Type, string> InitializeFeatureCategoryDetails(IEnumerable<PluginManifest> pluginManifests)
|
||||
{
|
||||
Dictionary<Type, string> categoryDisplayNames = new Dictionary<Type, string>();
|
||||
|
||||
// Always add 'Other'
|
||||
var otherFeatureType = typeof(Features.Other.OtherFeature);
|
||||
categoryDisplayNames.Add(otherFeatureType, ((PluginFeatureCategoryAttribute)otherFeatureType.GetCustomAttributes(typeof(PluginFeatureCategoryAttribute), false).FirstOrDefault()).DisplayName);
|
||||
|
||||
foreach (var pluginManifest in pluginManifests)
|
||||
{
|
||||
foreach (var featureManifest in pluginManifest.Features)
|
||||
{
|
||||
if (!categoryDisplayNames.ContainsKey(featureManifest.CategoryType))
|
||||
{
|
||||
string displayName = null;
|
||||
|
||||
var displayAttributes = featureManifest.CategoryType.GetCustomAttributes(typeof(PluginFeatureCategoryAttribute), true);
|
||||
if (displayAttributes != null && displayAttributes.Length > 0)
|
||||
displayName = ((PluginFeatureCategoryAttribute)(displayAttributes[0])).DisplayName;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(displayName))
|
||||
displayName = featureManifest.CategoryType.Name;
|
||||
|
||||
categoryDisplayNames[featureManifest.CategoryType] = displayName;
|
||||
}
|
||||
}
|
||||
}
|
||||
return categoryDisplayNames;
|
||||
}
|
||||
|
||||
#region Plugin Referenced Assemblies Resolving
|
||||
|
||||
public static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
||||
{
|
||||
if (args.RequestingAssembly.Location.StartsWith(PluginPath, StringComparison.InvariantCultureIgnoreCase) && _PluginManifests != null)
|
||||
{
|
||||
// Try best guess first
|
||||
PluginManifest requestingPlugin = _PluginManifests.Values.Where(p => p.Type.Assembly == args.RequestingAssembly).FirstOrDefault();
|
||||
if (requestingPlugin != null)
|
||||
{
|
||||
Assembly loadedAssembly = CurrentDomain_AssemblyResolve_ByPlugin(requestingPlugin, args);
|
||||
if (loadedAssembly != null)
|
||||
return loadedAssembly;
|
||||
}
|
||||
|
||||
// Try all Plugin References
|
||||
foreach (var pluginDef in _PluginManifests.Values)
|
||||
{
|
||||
Assembly loadedAssembly = CurrentDomain_AssemblyResolve_ByPlugin(pluginDef, args);
|
||||
if (loadedAssembly != null)
|
||||
return loadedAssembly;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private static Assembly CurrentDomain_AssemblyResolve_ByPlugin(PluginManifest pluginManifest, ResolveEventArgs args)
|
||||
{
|
||||
if (pluginManifest.AssemblyReferences != null)
|
||||
{
|
||||
string assemblyPath;
|
||||
if (pluginManifest.AssemblyReferences.TryGetValue(args.Name, out assemblyPath))
|
||||
{
|
||||
var resolvedAssemblyPath = Path.Combine(pluginManifest.PluginLocation, assemblyPath);
|
||||
|
||||
try
|
||||
{
|
||||
Assembly loadedAssembly = Assembly.LoadFile(resolvedAssemblyPath);
|
||||
|
||||
PluginsLog.LogPluginReferenceAssemblyLoaded(args.Name, resolvedAssemblyPath, args.RequestingAssembly.FullName);
|
||||
|
||||
return loadedAssembly;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginsLog.LogPluginException(string.Format("Resolving Plugin Reference Assembly: '{0}' [{1}]; Requested by: '{2}' [{3}]; Disco.Plugins.DiscoPlugins.CurrentDomain_AssemblyResolve()", args.Name, resolvedAssemblyPath, args.RequestingAssembly.FullName, args.RequestingAssembly.Location), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,275 +1,373 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Services.Logging;
|
||||
using Disco.Services.Logging.Models;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Disco.Services.Plugins
|
||||
{
|
||||
public class PluginsLog : LogBase
|
||||
{
|
||||
private const int _ModuleId = 10;
|
||||
|
||||
public override string ModuleDescription { get { return "Plugins"; } }
|
||||
public override int ModuleId { get { return _ModuleId; } }
|
||||
public override string ModuleName { get { return "Plugins"; } }
|
||||
|
||||
public enum EventTypeIds
|
||||
{
|
||||
InitializingPlugins = 10,
|
||||
InitializingPluginAssembly,
|
||||
InitializedPlugin,
|
||||
InitializedPluginFeature,
|
||||
InitializeWarning = 15,
|
||||
InitializeError,
|
||||
InitializeException,
|
||||
InitializeExceptionWithInner,
|
||||
PluginException = 20,
|
||||
PluginExceptionWithInner,
|
||||
PluginReferenceAssemblyLoaded = 50,
|
||||
PluginConfigurationLoaded = 100,
|
||||
PluginConfigurationSaved = 104,
|
||||
PluginWebControllerAccessed = 200
|
||||
}
|
||||
|
||||
public static PluginsLog Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return (PluginsLog)LogContext.LogModules[_ModuleId];
|
||||
}
|
||||
}
|
||||
private static void Log(EventTypeIds EventTypeId, params object[] Args)
|
||||
{
|
||||
Current.Log((int)EventTypeId, Args);
|
||||
}
|
||||
|
||||
public static void LogInitializingPlugins(string PluginDirectory)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.InitializingPlugins, PluginDirectory);
|
||||
}
|
||||
public static void LogInitializingPluginAssembly(Assembly PluginAssembly)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.InitializingPluginAssembly, PluginAssembly.FullName, PluginAssembly.Location);
|
||||
}
|
||||
public static void LogInitializedPlugin(PluginManifest Menifest)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.InitializedPlugin, Menifest.Id, Menifest.Version.ToString(3), Menifest.Type.Name, Menifest.Type.Assembly.Location);
|
||||
}
|
||||
public static void LogInitializedPluginFeature(PluginManifest PluginMenifest, PluginFeatureManifest FeatureManifest)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.InitializedPluginFeature, PluginMenifest.Id, FeatureManifest.Type.Name);
|
||||
}
|
||||
public static void LogInitializeWarning(string Warning)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.InitializeWarning, Warning);
|
||||
}
|
||||
public static void LogInitializeError(string Error)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.InitializeError, Error);
|
||||
}
|
||||
public static void LogPluginReferenceAssemblyLoaded(string AssemblyFullName, string AssemblyPath, string RequestedBy)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.PluginReferenceAssemblyLoaded, AssemblyFullName, AssemblyPath, RequestedBy);
|
||||
}
|
||||
public static void LogPluginConfigurationLoaded(string PluginId, string UserId)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.PluginConfigurationLoaded, PluginId, UserId);
|
||||
}
|
||||
public static void LogPluginConfigurationSaved(string PluginId, string UserId)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.PluginConfigurationSaved, PluginId, UserId);
|
||||
}
|
||||
public static void LogPluginWebControllerAccessed(string PluginId, string PluginAction, string UserId)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.PluginWebControllerAccessed, PluginId, PluginAction, UserId);
|
||||
}
|
||||
|
||||
public static void LogInitializeException(string PluginFilename, Exception ex)
|
||||
{
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
Log(EventTypeIds.InitializeExceptionWithInner, PluginFilename, ex.GetType().Name, ex.Message, ex.StackTrace, ex.InnerException.GetType().Name, ex.InnerException.Message, ex.InnerException.StackTrace);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(EventTypeIds.InitializeException, PluginFilename, ex.GetType().Name, ex.Message, ex.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LogPluginException(string Component, Exception ex)
|
||||
{
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
Log(EventTypeIds.PluginExceptionWithInner, Component, ex.GetType().Name, ex.Message, ex.StackTrace, ex.InnerException.GetType().Name, ex.InnerException.Message, ex.InnerException.StackTrace);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(EventTypeIds.PluginException, Component, ex.GetType().Name, ex.Message, ex.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
protected override List<Logging.Models.LogEventType> LoadEventTypes()
|
||||
{
|
||||
return new System.Collections.Generic.List<LogEventType>
|
||||
{
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.InitializingPlugins,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Initializing Plugins",
|
||||
Format = "Starting plugin discovery and initialization from: {0}",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = false,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.InitializingPluginAssembly,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Initializing Plugin Assembly",
|
||||
Format = "Initializing Plugin Assembly: [{0}] From '{1}'",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = false,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.InitializedPlugin,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Initialized Plugin",
|
||||
Format = "Initialized Plugin: '{0} (v{1})' [{2}] From '{3}'",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = false,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.InitializedPluginFeature,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Initialized Plugin Feature",
|
||||
Format = "Initialized Plugin Feature: '{1}' From '{0}'",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = false,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.InitializeWarning,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Initialize Warning",
|
||||
Format = "Initialize Warning: {0}",
|
||||
Severity = (int)LogEventType.Severities.Warning,
|
||||
UseLive = false,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.InitializeError,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Initialize Error",
|
||||
Format = "Initialize Error: {0}",
|
||||
Severity = (int)LogEventType.Severities.Error,
|
||||
UseLive = false,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.InitializeException,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Initialize Exception",
|
||||
Format = "Exception: {0}; {1}: {2}; {3}",
|
||||
Severity = (int)LogEventType.Severities.Error,
|
||||
UseLive = false,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.InitializeExceptionWithInner,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Initialize Exception with Inner Exception",
|
||||
Format = "Exception: {0}; {1}: {2}; {3}; Inner: {4}: {5}; {6}",
|
||||
Severity = (int)LogEventType.Severities.Error,
|
||||
UseLive = false,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.PluginException,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Plugin Exception",
|
||||
Format = "Exception: {0}; {1}: {2}; {3}",
|
||||
Severity = (int)LogEventType.Severities.Error,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.PluginExceptionWithInner,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Plugin Exception with Inner Exception",
|
||||
Format = "Exception: {0}; {1}: {2}; {3}; Inner: {4}: {5}; {6}",
|
||||
Severity = (int)LogEventType.Severities.Error,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.PluginReferenceAssemblyLoaded,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Plugin Reference Assembly Loaded",
|
||||
Format = "Loaded Plugin Reference Assembly: [{0}] From: '{1}'; Requested by: [{2}]",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.PluginConfigurationLoaded,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Plugin Configuration Loaded",
|
||||
Format = "Plugin Configuration Loaded: [{0}] by [{1}]",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.PluginConfigurationSaved,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Plugin Configuration Saved",
|
||||
Format = "Plugin Configuration Saved: [{0}] by [{1}]",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.PluginWebControllerAccessed,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Plugin Web Controller Accessed",
|
||||
Format = "Plugin Web Controller Accessed: Plugin [{0}], Action [{1}], By [{2}]",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Services.Logging;
|
||||
using Disco.Services.Logging.Models;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Disco.Services.Plugins
|
||||
{
|
||||
public class PluginsLog : LogBase
|
||||
{
|
||||
private const int _ModuleId = 10;
|
||||
|
||||
public override string ModuleDescription { get { return "Plugins"; } }
|
||||
public override int ModuleId { get { return _ModuleId; } }
|
||||
public override string ModuleName { get { return "Plugins"; } }
|
||||
|
||||
public enum EventTypeIds
|
||||
{
|
||||
InitializingPlugins = 10,
|
||||
InitializingPluginAssembly,
|
||||
InitializedPlugin,
|
||||
InitializedPluginFeature,
|
||||
InitializeWarning = 15,
|
||||
InitializeError,
|
||||
InitializeException,
|
||||
InitializeExceptionWithInner,
|
||||
PluginException = 20,
|
||||
PluginExceptionWithInner,
|
||||
PluginReferenceAssemblyLoaded = 50,
|
||||
PluginConfigurationLoaded = 100,
|
||||
PluginConfigurationSaved = 104,
|
||||
PluginWebControllerAccessed = 200,
|
||||
|
||||
Installing = 500,
|
||||
Installed = 550,
|
||||
BeforeUpdate = 600,
|
||||
AfterUpdate = 700,
|
||||
Uninstalling = 800,
|
||||
Uninstalled = 850
|
||||
}
|
||||
|
||||
public static PluginsLog Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return (PluginsLog)LogContext.LogModules[_ModuleId];
|
||||
}
|
||||
}
|
||||
private static void Log(EventTypeIds EventTypeId, params object[] Args)
|
||||
{
|
||||
Current.Log((int)EventTypeId, Args);
|
||||
}
|
||||
|
||||
public static void LogInitializingPlugins(string PluginDirectory)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.InitializingPlugins, PluginDirectory);
|
||||
}
|
||||
public static void LogInitializingPluginAssembly(Assembly PluginAssembly)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.InitializingPluginAssembly, PluginAssembly.FullName, PluginAssembly.Location);
|
||||
}
|
||||
public static void LogInitializedPlugin(PluginManifest Menifest)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.InitializedPlugin, Menifest.Id, Menifest.Version.ToString(3), Menifest.Type.Name, Menifest.Type.Assembly.Location);
|
||||
}
|
||||
public static void LogInitializedPluginFeature(PluginManifest PluginMenifest, PluginFeatureManifest FeatureManifest)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.InitializedPluginFeature, PluginMenifest.Id, FeatureManifest.Type.Name);
|
||||
}
|
||||
public static void LogInitializeWarning(string Warning)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.InitializeWarning, Warning);
|
||||
}
|
||||
public static void LogInitializeError(string Error)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.InitializeError, Error);
|
||||
}
|
||||
public static void LogPluginReferenceAssemblyLoaded(string AssemblyFullName, string AssemblyPath, string RequestedBy)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.PluginReferenceAssemblyLoaded, AssemblyFullName, AssemblyPath, RequestedBy);
|
||||
}
|
||||
public static void LogPluginConfigurationLoaded(string PluginId, string UserId)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.PluginConfigurationLoaded, PluginId, UserId);
|
||||
}
|
||||
public static void LogPluginConfigurationSaved(string PluginId, string UserId)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.PluginConfigurationSaved, PluginId, UserId);
|
||||
}
|
||||
public static void LogPluginWebControllerAccessed(string PluginId, string PluginAction, string UserId)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.PluginWebControllerAccessed, PluginId, PluginAction, UserId);
|
||||
}
|
||||
|
||||
public static void LogInstalling(PluginManifest Manifest)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.Installing, Manifest.Id, Manifest.Version.ToString(4), Manifest.Name);
|
||||
}
|
||||
public static void LogInstalled(PluginManifest Manifest)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.Installing, Manifest.Id, Manifest.Version.ToString(4), Manifest.Name, Manifest.PluginLocation);
|
||||
}
|
||||
public static void LogBeforeUpdate(PluginManifest ExistingManifest, PluginManifest UpdateManifest)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.BeforeUpdate, ExistingManifest.Id, ExistingManifest.Name, ExistingManifest.PluginLocation, ExistingManifest.Version.ToString(4), UpdateManifest.Version.ToString(4));
|
||||
}
|
||||
public static void LogAfterUpdate(PluginManifest ExistingManifest, PluginManifest UpdateManifest)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.AfterUpdate, UpdateManifest.Id, UpdateManifest.Name, UpdateManifest.PluginLocation, ExistingManifest.Version.ToString(4), UpdateManifest.Version.ToString(4));
|
||||
}
|
||||
public static void LogUninstalling(PluginManifest Manifest, bool UninstallData)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.Uninstalling, Manifest.Id, Manifest.Name, Manifest.PluginLocation, Manifest.Version.ToString(4), UninstallData);
|
||||
}
|
||||
public static void LogUninstalled(PluginManifest Manifest, bool UninstalledData)
|
||||
{
|
||||
Current.Log((int)EventTypeIds.Uninstalled, Manifest.Id, Manifest.Name, Manifest.PluginLocation, Manifest.Version.ToString(4), UninstalledData);
|
||||
}
|
||||
|
||||
public static void LogInitializeException(string PluginFilename, Exception ex)
|
||||
{
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
Log(EventTypeIds.InitializeExceptionWithInner, PluginFilename, ex.GetType().Name, ex.Message, ex.StackTrace, ex.InnerException.GetType().Name, ex.InnerException.Message, ex.InnerException.StackTrace);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(EventTypeIds.InitializeException, PluginFilename, ex.GetType().Name, ex.Message, ex.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LogPluginException(string Component, Exception ex)
|
||||
{
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
Log(EventTypeIds.PluginExceptionWithInner, Component, ex.GetType().Name, ex.Message, ex.StackTrace, ex.InnerException.GetType().Name, ex.InnerException.Message, ex.InnerException.StackTrace);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(EventTypeIds.PluginException, Component, ex.GetType().Name, ex.Message, ex.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
protected override List<Logging.Models.LogEventType> LoadEventTypes()
|
||||
{
|
||||
return new System.Collections.Generic.List<LogEventType>
|
||||
{
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.InitializingPlugins,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Initializing Plugins",
|
||||
Format = "Starting plugin discovery and initialization from: {0}",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = false,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.InitializingPluginAssembly,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Initializing Plugin Assembly",
|
||||
Format = "Initializing Plugin Assembly: [{0}] From '{1}'",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = false,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.InitializedPlugin,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Initialized Plugin",
|
||||
Format = "Initialized Plugin: '{0} (v{1})' [{2}] From '{3}'",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = false,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.InitializedPluginFeature,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Initialized Plugin Feature",
|
||||
Format = "Initialized Plugin Feature: '{1}' From '{0}'",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = false,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.InitializeWarning,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Initialize Warning",
|
||||
Format = "Initialize Warning: {0}",
|
||||
Severity = (int)LogEventType.Severities.Warning,
|
||||
UseLive = false,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.InitializeError,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Initialize Error",
|
||||
Format = "Initialize Error: {0}",
|
||||
Severity = (int)LogEventType.Severities.Error,
|
||||
UseLive = false,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.InitializeException,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Initialize Exception",
|
||||
Format = "Exception: {0}; {1}: {2}; {3}",
|
||||
Severity = (int)LogEventType.Severities.Error,
|
||||
UseLive = false,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.InitializeExceptionWithInner,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Initialize Exception with Inner Exception",
|
||||
Format = "Exception: {0}; {1}: {2}; {3}; Inner: {4}: {5}; {6}",
|
||||
Severity = (int)LogEventType.Severities.Error,
|
||||
UseLive = false,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.PluginException,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Plugin Exception",
|
||||
Format = "Exception: {0}; {1}: {2}; {3}",
|
||||
Severity = (int)LogEventType.Severities.Error,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.PluginExceptionWithInner,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Plugin Exception with Inner Exception",
|
||||
Format = "Exception: {0}; {1}: {2}; {3}; Inner: {4}: {5}; {6}",
|
||||
Severity = (int)LogEventType.Severities.Error,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.PluginReferenceAssemblyLoaded,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Plugin Reference Assembly Loaded",
|
||||
Format = "Loaded Plugin Reference Assembly: [{0}] From: '{1}'; Requested by: [{2}]",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.PluginConfigurationLoaded,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Plugin Configuration Loaded",
|
||||
Format = "Plugin Configuration Loaded: [{0}] by [{1}]",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.PluginConfigurationSaved,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Plugin Configuration Saved",
|
||||
Format = "Plugin Configuration Saved: [{0}] by [{1}]",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.PluginWebControllerAccessed,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Plugin Web Controller Accessed",
|
||||
Format = "Plugin Web Controller Accessed: Plugin [{0}], Action [{1}], By [{2}]",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.Installing,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Installing Plugin",
|
||||
Format = "Installing Plugin: {2} [{0} v{1}]",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.Installed,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Plugin Installed",
|
||||
Format = "Plugin Installed: {2} [{0} v{1}], Location: {3}",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.BeforeUpdate,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Updating Plugin",
|
||||
Format = "Updating Plugin: {1} [{0}], v{3} -> v{4}, Location: {2}",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.AfterUpdate,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Plugin Updated",
|
||||
Format = "Plugin Updated: {1} [{0}], v{3} -> v{4}, Location: {2}",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = false,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.Uninstalling,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Uninstalling Plugin",
|
||||
Format = "Uninstalling Plugin: {1} [{0} v{3}], Location: {2}, UninstallData: {4}",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.Uninstalled,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Plugin Uninstalled",
|
||||
Format = "Plugin Uninstalled: {1} [{0} v{3}], Location: {2}, UninstallData: {4}",
|
||||
Severity = (int)LogEventType.Severities.Information,
|
||||
UseLive = false,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using Disco.Services.Tasks;
|
||||
using Quartz;
|
||||
|
||||
namespace Disco.Services.Plugins
|
||||
{
|
||||
public class UninstallPluginTask : ScheduledTask
|
||||
{
|
||||
public override string TaskName { get { return "Uninstalling Plugin"; } }
|
||||
|
||||
protected override void ExecuteTask()
|
||||
{
|
||||
PluginManifest manifest = (PluginManifest)this.ExecutionContext.JobDetail.JobDataMap["PluginManifest"];
|
||||
bool UninstallData = (bool)this.ExecutionContext.JobDetail.JobDataMap["UninstallData"];
|
||||
|
||||
this.Status.UpdateStatus(25, string.Format("Uninstalling Plugin: {0} [{1}]", manifest.Name, manifest.Id), "Queuing plugin for uninstall");
|
||||
|
||||
PluginsLog.LogUninstalling(manifest, UninstallData);
|
||||
|
||||
string manifestFileLocation = Path.Combine(manifest.PluginLocation, "manifest.json");
|
||||
if (!File.Exists(manifestFileLocation))
|
||||
throw new FileNotFoundException("Plugin Manifest File Not Found", manifestFileLocation);
|
||||
|
||||
string manifestUninstallFileLocation = Path.Combine(manifest.PluginLocation, "manifest.uninstall.json");
|
||||
|
||||
if (File.Exists(manifestUninstallFileLocation))
|
||||
File.Delete(manifestUninstallFileLocation);
|
||||
|
||||
File.Move(manifestFileLocation, manifestUninstallFileLocation);
|
||||
|
||||
if (UninstallData && Directory.Exists(manifest.StorageLocation))
|
||||
{
|
||||
var manifestDataUninstallFileLocation = Path.Combine(manifest.StorageLocation, "manifest.uninstall.json");
|
||||
if (File.Exists(manifestDataUninstallFileLocation))
|
||||
File.Delete(manifestDataUninstallFileLocation);
|
||||
|
||||
File.Copy(manifestUninstallFileLocation, manifestDataUninstallFileLocation);
|
||||
}
|
||||
|
||||
this.Status.Finished("Restarting Disco, please wait...", "/Config/Plugins");
|
||||
RestartApp(1500);
|
||||
}
|
||||
|
||||
public static ScheduledTaskStatus UninstallPlugin(PluginManifest Manifest, bool UninstallData)
|
||||
{
|
||||
if (ScheduledTasks.GetTaskStatuses(typeof(InstallPluginTask)).Where(s => s.IsRunning).Count() > 0)
|
||||
throw new InvalidOperationException("A plugin is already being Uninstalled");
|
||||
|
||||
JobDataMap taskData = new JobDataMap() { { "PluginManifest", Manifest }, { "UninstallData", UninstallData } };
|
||||
|
||||
var instance = new UninstallPluginTask();
|
||||
|
||||
return instance.ScheduleTask(taskData);
|
||||
}
|
||||
|
||||
#region Restart App
|
||||
private static object _restartTimerLock = new object();
|
||||
private static Timer _restartTimer;
|
||||
private void RestartApp(int DelayMilliseconds)
|
||||
{
|
||||
lock (_restartTimerLock)
|
||||
{
|
||||
if (_restartTimer != null)
|
||||
{
|
||||
_restartTimer.Dispose();
|
||||
}
|
||||
|
||||
_restartTimer = new Timer((state) =>
|
||||
{
|
||||
HttpRuntime.UnloadAppDomain();
|
||||
//AppDomain.Unload(AppDomain.CurrentDomain);
|
||||
}, null, DelayMilliseconds, Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,36 +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("Disco.Services")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco.Services")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[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("3f4b432d-2abd-4bc2-86cd-f90650b73930")]
|
||||
|
||||
// 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.2.0131.2002")]
|
||||
[assembly: AssemblyFileVersion("1.2.0131.2002")]
|
||||
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("Disco.Services")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco.Services")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[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("3f4b432d-2abd-4bc2-86cd-f90650b73930")]
|
||||
|
||||
// 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.2.0207.1727")]
|
||||
[assembly: AssemblyFileVersion("1.2.0207.1727")]
|
||||
|
||||
@@ -1,108 +1,108 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Quartz;
|
||||
using Disco.Data.Repository;
|
||||
|
||||
namespace Disco.Services.Tasks
|
||||
{
|
||||
public abstract class ScheduledTask : IJob
|
||||
{
|
||||
public abstract void InitalizeScheduledTask(DiscoDataContext dbContext);
|
||||
|
||||
internal protected ScheduledTaskStatus Status { get; private set; }
|
||||
internal protected IJobExecutionContext ExecutionContext { get; private set; }
|
||||
|
||||
public abstract bool CancelInitiallySupported { get; }
|
||||
public abstract bool SingleInstanceTask { get; }
|
||||
public virtual bool IsSilent { get { return false; } }
|
||||
public virtual bool LogExceptionsOnly { get { return false; } }
|
||||
public abstract string TaskName { get; }
|
||||
protected abstract void ExecuteTask();
|
||||
|
||||
#region Protected Triggers
|
||||
/// <summary>
|
||||
/// Schedules the Task to Begin Immediately
|
||||
/// </summary>
|
||||
protected ScheduledTaskStatus ScheduleTask()
|
||||
{
|
||||
return ScheduleTask(null, null);
|
||||
}
|
||||
/// <summary>
|
||||
/// Schedules the Task to Begin Immediately
|
||||
/// </summary>
|
||||
/// <param name="DataMap">DataMap passed into the executing Task</param>
|
||||
/// <returns></returns>
|
||||
protected ScheduledTaskStatus ScheduleTask(JobDataMap DataMap)
|
||||
{
|
||||
return ScheduleTask(null, DataMap);
|
||||
}
|
||||
/// <summary>
|
||||
/// Schedules the Task to Begin based on the Trigger
|
||||
/// </summary>
|
||||
/// <param name="Trigger">Trigger for the Task</param>
|
||||
protected ScheduledTaskStatus ScheduleTask(TriggerBuilder Trigger)
|
||||
{
|
||||
return ScheduleTask(Trigger, null);
|
||||
}
|
||||
/// <summary>
|
||||
/// Schedules the Task to Begin based on the Trigger including the DataMap
|
||||
/// </summary>
|
||||
/// <param name="Trigger">Trigger for the Task</param>
|
||||
/// <param name="DataMap">DataMap passed into the executing Task</param>
|
||||
/// <returns></returns>
|
||||
protected ScheduledTaskStatus ScheduleTask(TriggerBuilder Trigger, JobDataMap DataMap)
|
||||
{
|
||||
if (Trigger == null)
|
||||
Trigger = TriggerBuilder.Create(); // Defaults to Start Immediately
|
||||
|
||||
if (DataMap != null)
|
||||
Trigger = Trigger.UsingJobData(DataMap);
|
||||
|
||||
return ScheduledTasks.RegisterTask(this, Trigger);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void Execute(IJobExecutionContext context)
|
||||
{
|
||||
// Task Status
|
||||
this.ExecutionContext = context;
|
||||
this.Status = context.GetDiscoScheduledTaskStatus();
|
||||
if (this.Status == null)
|
||||
this.Status = ScheduledTasks.RegisterTask(this);
|
||||
|
||||
try
|
||||
{
|
||||
if (!this.LogExceptionsOnly)
|
||||
ScheduledTasksLog.LogScheduledTaskExecuted(this.Status.TaskName, this.Status.SessionId);
|
||||
|
||||
this.Status.Started();
|
||||
this.ExecuteTask();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ScheduledTasksLog.LogScheduledTaskException(this.Status.TaskName, this.Status.SessionId, this.GetType(), ex);
|
||||
this.Status.SetTaskException(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!this.Status.FinishedTimestamp.HasValue) // Scheduled Task Didn't Trigger 'Finished'
|
||||
this.Status.Finished();
|
||||
|
||||
var nextTriggerTime = context.NextFireTimeUtc;
|
||||
if (nextTriggerTime.HasValue)
|
||||
{ // Continuous Task
|
||||
this.Status.Reset(nextTriggerTime.Value.LocalDateTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.UnregisterTask();
|
||||
}
|
||||
|
||||
if (!this.LogExceptionsOnly)
|
||||
ScheduledTasksLog.LogScheduledTaskFinished(this.Status.TaskName, this.Status.SessionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Quartz;
|
||||
using Disco.Data.Repository;
|
||||
|
||||
namespace Disco.Services.Tasks
|
||||
{
|
||||
public abstract class ScheduledTask : IJob
|
||||
{
|
||||
public virtual void InitalizeScheduledTask(DiscoDataContext dbContext) { return; }
|
||||
|
||||
internal protected ScheduledTaskStatus Status { get; private set; }
|
||||
internal protected IJobExecutionContext ExecutionContext { get; private set; }
|
||||
|
||||
public virtual bool CancelInitiallySupported { get { return true; } }
|
||||
public virtual bool SingleInstanceTask { get { return true; } }
|
||||
public virtual bool IsSilent { get { return false; } }
|
||||
public virtual bool LogExceptionsOnly { get { return false; } }
|
||||
public abstract string TaskName { get; }
|
||||
protected abstract void ExecuteTask();
|
||||
|
||||
#region Protected Triggers
|
||||
/// <summary>
|
||||
/// Schedules the Task to Begin Immediately
|
||||
/// </summary>
|
||||
protected ScheduledTaskStatus ScheduleTask()
|
||||
{
|
||||
return ScheduleTask(null, null);
|
||||
}
|
||||
/// <summary>
|
||||
/// Schedules the Task to Begin Immediately
|
||||
/// </summary>
|
||||
/// <param name="DataMap">DataMap passed into the executing Task</param>
|
||||
/// <returns></returns>
|
||||
protected ScheduledTaskStatus ScheduleTask(JobDataMap DataMap)
|
||||
{
|
||||
return ScheduleTask(null, DataMap);
|
||||
}
|
||||
/// <summary>
|
||||
/// Schedules the Task to Begin based on the Trigger
|
||||
/// </summary>
|
||||
/// <param name="Trigger">Trigger for the Task</param>
|
||||
protected ScheduledTaskStatus ScheduleTask(TriggerBuilder Trigger)
|
||||
{
|
||||
return ScheduleTask(Trigger, null);
|
||||
}
|
||||
/// <summary>
|
||||
/// Schedules the Task to Begin based on the Trigger including the DataMap
|
||||
/// </summary>
|
||||
/// <param name="Trigger">Trigger for the Task</param>
|
||||
/// <param name="DataMap">DataMap passed into the executing Task</param>
|
||||
/// <returns></returns>
|
||||
protected ScheduledTaskStatus ScheduleTask(TriggerBuilder Trigger, JobDataMap DataMap)
|
||||
{
|
||||
if (Trigger == null)
|
||||
Trigger = TriggerBuilder.Create(); // Defaults to Start Immediately
|
||||
|
||||
if (DataMap != null)
|
||||
Trigger = Trigger.UsingJobData(DataMap);
|
||||
|
||||
return ScheduledTasks.RegisterTask(this, Trigger);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void Execute(IJobExecutionContext context)
|
||||
{
|
||||
// Task Status
|
||||
this.ExecutionContext = context;
|
||||
this.Status = context.GetDiscoScheduledTaskStatus();
|
||||
if (this.Status == null)
|
||||
this.Status = ScheduledTasks.RegisterTask(this);
|
||||
|
||||
try
|
||||
{
|
||||
if (!this.LogExceptionsOnly)
|
||||
ScheduledTasksLog.LogScheduledTaskExecuted(this.Status.TaskName, this.Status.SessionId);
|
||||
|
||||
this.Status.Started();
|
||||
this.ExecuteTask();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ScheduledTasksLog.LogScheduledTaskException(this.Status.TaskName, this.Status.SessionId, this.GetType(), ex);
|
||||
this.Status.SetTaskException(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!this.Status.FinishedTimestamp.HasValue) // Scheduled Task Didn't Trigger 'Finished'
|
||||
this.Status.Finished();
|
||||
|
||||
var nextTriggerTime = context.NextFireTimeUtc;
|
||||
if (nextTriggerTime.HasValue)
|
||||
{ // Continuous Task
|
||||
this.Status.Reset(nextTriggerTime.Value.LocalDateTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.UnregisterTask();
|
||||
}
|
||||
|
||||
if (!this.LogExceptionsOnly)
|
||||
ScheduledTasksLog.LogScheduledTaskFinished(this.Status.TaskName, this.Status.SessionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+60
-36
@@ -1,36 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web.Mvc;
|
||||
using Disco.Services.Plugins;
|
||||
|
||||
namespace Disco.Web.Extensions
|
||||
{
|
||||
public static class DiscoPluginDefinitionExtensions
|
||||
{
|
||||
public static List<SelectListItem> ToSelectListItems(this IEnumerable<PluginFeatureManifest> PluginFeatureDefinitions, PluginFeatureManifest SelectedItem)
|
||||
{
|
||||
string selectedId = default(string);
|
||||
|
||||
if (SelectedItem != null)
|
||||
selectedId = SelectedItem.Id;
|
||||
|
||||
return PluginFeatureDefinitions.ToSelectListItems(selectedId);
|
||||
}
|
||||
|
||||
public static List<SelectListItem> ToSelectListItems(this IEnumerable<PluginFeatureManifest> PluginDefinitions, string SelectedId = null, bool IncludeInstructionFirst = false, string InstructionMessage = "Select a Plugin")
|
||||
{
|
||||
var selectItems = default(List<SelectListItem>);
|
||||
if (SelectedId == null)
|
||||
selectItems = PluginDefinitions.Select(wpd => new SelectListItem { Value = wpd.Id, Text = wpd.Name }).ToList();
|
||||
else
|
||||
selectItems = PluginDefinitions.Select(wpd => new SelectListItem { Value = wpd.Id, Text = wpd.Name, Selected = (SelectedId.Equals(wpd.Id)) }).ToList();
|
||||
|
||||
if (IncludeInstructionFirst)
|
||||
selectItems.Insert(0, new SelectListItem() { Value = String.Empty, Text = String.Format("<{0}>", InstructionMessage), Selected = String.IsNullOrEmpty(SelectedId) });
|
||||
|
||||
return selectItems;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web.Mvc;
|
||||
using Disco.Services.Plugins;
|
||||
|
||||
namespace Disco.Web.Extensions
|
||||
{
|
||||
public static class DiscoPluginDefinitionExtensions
|
||||
{
|
||||
public static List<SelectListItem> ToSelectListItems(this IEnumerable<PluginFeatureManifest> PluginFeatureDefinitions, PluginFeatureManifest SelectedItem)
|
||||
{
|
||||
string selectedId = default(string);
|
||||
|
||||
if (SelectedItem != null)
|
||||
selectedId = SelectedItem.Id;
|
||||
|
||||
return PluginFeatureDefinitions.ToSelectListItems(selectedId);
|
||||
}
|
||||
|
||||
public static List<SelectListItem> ToSelectListItems(this IEnumerable<PluginFeatureManifest> PluginDefinitions, string SelectedId = null, bool IncludeInstructionFirst = false, string InstructionMessage = "Select a Plugin")
|
||||
{
|
||||
var selectItems = default(List<SelectListItem>);
|
||||
if (SelectedId == null)
|
||||
selectItems = PluginDefinitions.Select(wpd => new SelectListItem { Value = wpd.Id, Text = wpd.Name }).ToList();
|
||||
else
|
||||
selectItems = PluginDefinitions.Select(wpd => new SelectListItem { Value = wpd.Id, Text = wpd.Name, Selected = (SelectedId.Equals(wpd.Id)) }).ToList();
|
||||
|
||||
if (IncludeInstructionFirst)
|
||||
selectItems.Insert(0, new SelectListItem() { Value = String.Empty, Text = String.Format("<{0}>", InstructionMessage), Selected = String.IsNullOrEmpty(SelectedId) });
|
||||
|
||||
return selectItems;
|
||||
}
|
||||
|
||||
public static List<SelectListItem> ToSelectListItems(this IEnumerable<PluginManifest> PluginFeatureDefinitions, PluginManifest SelectedItem)
|
||||
{
|
||||
string selectedId = default(string);
|
||||
|
||||
if (SelectedItem != null)
|
||||
selectedId = SelectedItem.Id;
|
||||
|
||||
return PluginFeatureDefinitions.ToSelectListItems(selectedId);
|
||||
}
|
||||
|
||||
public static List<SelectListItem> ToSelectListItems(this IEnumerable<PluginManifest> PluginDefinitions, string SelectedId = null, bool IncludeInstructionFirst = false, string InstructionMessage = "Select a Plugin")
|
||||
{
|
||||
var selectItems = default(List<SelectListItem>);
|
||||
if (SelectedId == null)
|
||||
selectItems = PluginDefinitions.Select(wpd => new SelectListItem { Value = wpd.Id, Text = wpd.Name }).ToList();
|
||||
else
|
||||
selectItems = PluginDefinitions.Select(wpd => new SelectListItem { Value = wpd.Id, Text = wpd.Name, Selected = (SelectedId.Equals(wpd.Id)) }).ToList();
|
||||
|
||||
if (IncludeInstructionFirst)
|
||||
selectItems.Insert(0, new SelectListItem() { Value = String.Empty, Text = String.Format("<{0}>", InstructionMessage), Selected = String.IsNullOrEmpty(SelectedId) });
|
||||
|
||||
return selectItems;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,150 +1,150 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{C433EFBA-8608-4451-874B-AF32C8536792}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Disco.Web.Extensions</RootNamespace>
|
||||
<AssemblyName>Disco.Web.Extensions</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="dotless.Core">
|
||||
<HintPath>..\packages\dotless.1.3.0.5\lib\dotless.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="EntityFramework">
|
||||
<HintPath>..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.4.5.9\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.Entity" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Helpers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.Helpers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.AspNet.Mvc.4.0.20710.0\lib\net40\System.Web.Mvc.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.AspNet.Razor.2.0.20710.0\lib\net40\System.Web.Razor.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.WebPages, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Deployment.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Razor.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WebActivator">
|
||||
<HintPath>..\packages\WebActivator.1.5.2\lib\net40\WebActivator.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BIModelExtensions\OrganisationAddressExtensions.cs" />
|
||||
<Compile Include="BIModelExtensions\UtilityExtensions.cs" />
|
||||
<Compile Include="BIModelExtensions\DiscoPluginDefinitionExtensions.cs" />
|
||||
<Compile Include="DataModelExtension\DeviceBatchExtensions.cs" />
|
||||
<Compile Include="DataModelExtension\DeviceModelExtensions.cs" />
|
||||
<Compile Include="DataModelExtension\DeviceProfileExtensions.cs" />
|
||||
<Compile Include="DataModelExtension\DocumentTemplateExtensions.cs" />
|
||||
<Compile Include="DataModelExtension\JobSubTypeExtensions.cs" />
|
||||
<Compile Include="DataModelExtension\JobTypeExtensions.cs" />
|
||||
<Compile Include="MvcExtensions\Bundles\Bundle.cs" />
|
||||
<Compile Include="MvcExtensions\Bundles\BundleExtensions.cs" />
|
||||
<Compile Include="MvcExtensions\Bundles\BundleHandler.cs" />
|
||||
<Compile Include="MvcExtensions\Bundles\BundleModule.cs" />
|
||||
<Compile Include="MvcExtensions\Bundles\BundleTable.cs" />
|
||||
<Compile Include="MvcExtensions\dbAdminController.cs" />
|
||||
<Compile Include="MvcExtensions\dbController.cs" />
|
||||
<Compile Include="MvcExtensions\JsonNet\JsonNetResult.cs" />
|
||||
<Compile Include="MvcExtensions\PartialCompiled\PartialCompiledHtmlExtensions.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="MvcExtensions\XmlResult.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Disco.BI\Disco.BI.csproj">
|
||||
<Project>{095E6F94-3C34-47AE-BB83-46203535E0F6}</Project>
|
||||
<Name>Disco.BI</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Disco.Data\Disco.Data.csproj">
|
||||
<Project>{85A6BD19-2C64-4746-8F2C-A68A86E8C2D7}</Project>
|
||||
<Name>Disco.Data</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Disco.Models\Disco.Models.csproj">
|
||||
<Project>{FBC05512-FCCA-4B16-9E76-8C413C5DE6C9}</Project>
|
||||
<Name>Disco.Models</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Disco.Services\Disco.Services.csproj">
|
||||
<Project>{B80A737F-BD6A-4986-9182-DD7B932BD950}</Project>
|
||||
<Name>Disco.Services</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties BuildVersion_BuildAction="ReBuild" BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="True" BuildVersion_StartDate="2001/1/1" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.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>
|
||||
-->
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{C433EFBA-8608-4451-874B-AF32C8536792}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Disco.Web.Extensions</RootNamespace>
|
||||
<AssemblyName>Disco.Web.Extensions</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="dotless.Core">
|
||||
<HintPath>..\packages\dotless.1.3.0.5\lib\dotless.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="EntityFramework">
|
||||
<HintPath>..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.4.5.9\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.Entity" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Helpers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.Helpers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.AspNet.Mvc.4.0.20710.0\lib\net40\System.Web.Mvc.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.AspNet.Razor.2.0.20710.0\lib\net40\System.Web.Razor.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.WebPages, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Deployment.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Razor.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WebActivator">
|
||||
<HintPath>..\packages\WebActivator.1.5.2\lib\net40\WebActivator.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BIModelExtensions\OrganisationAddressExtensions.cs" />
|
||||
<Compile Include="BIModelExtensions\UtilityExtensions.cs" />
|
||||
<Compile Include="BIModelExtensions\PluginExtensions.cs" />
|
||||
<Compile Include="DataModelExtension\DeviceBatchExtensions.cs" />
|
||||
<Compile Include="DataModelExtension\DeviceModelExtensions.cs" />
|
||||
<Compile Include="DataModelExtension\DeviceProfileExtensions.cs" />
|
||||
<Compile Include="DataModelExtension\DocumentTemplateExtensions.cs" />
|
||||
<Compile Include="DataModelExtension\JobSubTypeExtensions.cs" />
|
||||
<Compile Include="DataModelExtension\JobTypeExtensions.cs" />
|
||||
<Compile Include="MvcExtensions\Bundles\Bundle.cs" />
|
||||
<Compile Include="MvcExtensions\Bundles\BundleExtensions.cs" />
|
||||
<Compile Include="MvcExtensions\Bundles\BundleHandler.cs" />
|
||||
<Compile Include="MvcExtensions\Bundles\BundleModule.cs" />
|
||||
<Compile Include="MvcExtensions\Bundles\BundleTable.cs" />
|
||||
<Compile Include="MvcExtensions\dbAdminController.cs" />
|
||||
<Compile Include="MvcExtensions\dbController.cs" />
|
||||
<Compile Include="MvcExtensions\JsonNet\JsonNetResult.cs" />
|
||||
<Compile Include="MvcExtensions\PartialCompiled\PartialCompiledHtmlExtensions.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="MvcExtensions\XmlResult.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Disco.BI\Disco.BI.csproj">
|
||||
<Project>{095E6F94-3C34-47AE-BB83-46203535E0F6}</Project>
|
||||
<Name>Disco.BI</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Disco.Data\Disco.Data.csproj">
|
||||
<Project>{85A6BD19-2C64-4746-8F2C-A68A86E8C2D7}</Project>
|
||||
<Name>Disco.Data</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Disco.Models\Disco.Models.csproj">
|
||||
<Project>{FBC05512-FCCA-4B16-9E76-8C413C5DE6C9}</Project>
|
||||
<Name>Disco.Models</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Disco.Services\Disco.Services.csproj">
|
||||
<Project>{B80A737F-BD6A-4986-9182-DD7B932BD950}</Project>
|
||||
<Name>Disco.Services</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties BuildVersion_StartDate="2001/1/1" BuildVersion_UseGlobalSettings="True" BuildVersion_DetectChanges="False" BuildVersion_BuildAction="ReBuild" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.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>
|
||||
@@ -1,36 +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("Disco.Web.Extensions")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco.Web.Extensions")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2012")]
|
||||
[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("a673b3dc-88d3-4df6-827f-cef274c5470c")]
|
||||
|
||||
// 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.2.0131.2002")]
|
||||
[assembly: AssemblyFileVersion("1.2.0131.2002")]
|
||||
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("Disco.Web.Extensions")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco.Web.Extensions")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2012")]
|
||||
[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("a673b3dc-88d3-4df6-827f-cef274c5470c")]
|
||||
|
||||
// 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.2.0207.1727")]
|
||||
[assembly: AssemblyFileVersion("1.2.0207.1727")]
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using Disco.Services.Plugins;
|
||||
|
||||
namespace Disco.Web.Areas.API.Controllers
|
||||
{
|
||||
public partial class PluginController : dbAdminController
|
||||
{
|
||||
|
||||
public virtual ActionResult Uninstall(string id, bool UninstallData)
|
||||
{
|
||||
if (string.IsNullOrEmpty(id))
|
||||
throw new ArgumentNullException("id");
|
||||
|
||||
PluginManifest manifest = Plugins.GetPlugin(id);
|
||||
|
||||
var status = UninstallPluginTask.UninstallPlugin(manifest, UninstallData);
|
||||
|
||||
return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId));
|
||||
}
|
||||
|
||||
public virtual ActionResult Install(HttpPostedFileBase Plugin)
|
||||
{
|
||||
if (Plugin == null || Plugin.ContentLength <= 0 || string.IsNullOrWhiteSpace(Plugin.FileName))
|
||||
throw new ArgumentException("A discoPlugin file must be uploaded", "Plugin");
|
||||
|
||||
var tempPluginLocation = Path.Combine(dbContext.DiscoConfiguration.PluginPackagesLocation, Path.GetFileName(Plugin.FileName));
|
||||
|
||||
if (!Directory.Exists(dbContext.DiscoConfiguration.PluginPackagesLocation))
|
||||
Directory.CreateDirectory(dbContext.DiscoConfiguration.PluginPackagesLocation);
|
||||
|
||||
if (System.IO.File.Exists(tempPluginLocation))
|
||||
System.IO.File.Delete(tempPluginLocation);
|
||||
|
||||
|
||||
Plugin.SaveAs(tempPluginLocation);
|
||||
|
||||
var status = InstallPluginTask.InstallPlugin(tempPluginLocation, true);
|
||||
|
||||
return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,99 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using Disco.Services.Plugins;
|
||||
using Disco.Web.Areas.Config.Models.Plugins;
|
||||
|
||||
namespace Disco.Web.Areas.Config.Controllers
|
||||
{
|
||||
public partial class PluginsController : dbAdminController
|
||||
{
|
||||
[HttpGet]
|
||||
public virtual ActionResult Index()
|
||||
{
|
||||
Models.Plugins.IndexViewModel vm = new Models.Plugins.IndexViewModel()
|
||||
{
|
||||
PluginManifests = Plugins.GetPlugins()
|
||||
};
|
||||
return View(vm);
|
||||
}
|
||||
|
||||
#region Plugin Configuration
|
||||
[HttpPost]
|
||||
public virtual ActionResult Configure(string PluginId, FormCollection form)
|
||||
{
|
||||
if (string.IsNullOrEmpty(PluginId))
|
||||
return RedirectToAction(MVC.Config.Plugins.Index());
|
||||
|
||||
PluginManifest manifest = Plugins.GetPlugin(PluginId);
|
||||
|
||||
using (PluginConfigurationHandler configHandler = manifest.CreateConfigurationHandler())
|
||||
{
|
||||
if (configHandler.Post(dbContext, form, this))
|
||||
{
|
||||
dbContext.SaveChanges();
|
||||
|
||||
PluginsLog.LogPluginConfigurationSaved(manifest.Id, DiscoApplication.CurrentUser.Id);
|
||||
|
||||
return RedirectToAction(MVC.Config.Plugins.Index());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Config Errors
|
||||
PluginConfigurationViewModel vm = new PluginConfigurationViewModel(configHandler.Get(dbContext, this));
|
||||
return View(Views.Configure, vm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public virtual ActionResult Configure(string PluginId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(PluginId))
|
||||
return RedirectToAction(MVC.Config.Plugins.Index());
|
||||
|
||||
PluginManifest manifest = Plugins.GetPlugin(PluginId);
|
||||
|
||||
using (PluginConfigurationHandler configHandler = manifest.CreateConfigurationHandler())
|
||||
{
|
||||
PluginConfigurationViewModel vm = new PluginConfigurationViewModel(configHandler.Get(dbContext, this));
|
||||
PluginsLog.LogPluginConfigurationLoaded(manifest.Id, DiscoApplication.CurrentUser.Id);
|
||||
return View(Views.Configure, vm);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
//public virtual ActionResult PluginAction(string PluginId, string PluginAction)
|
||||
//{
|
||||
// if (string.IsNullOrEmpty(PluginId))
|
||||
// return HttpNotFound("PluginId is Required");
|
||||
// if (string.IsNullOrEmpty(PluginAction))
|
||||
// return HttpNotFound("PluginAction is Required");
|
||||
|
||||
// PluginManifest def = Plugins.GetPlugin(PluginId);
|
||||
|
||||
// using (Plugin instance = def.CreateInstance())
|
||||
// {
|
||||
// IPluginWebController instanceController = instance as IPluginWebController;
|
||||
|
||||
// if (instanceController == null)
|
||||
// return HttpNotFound("Plugin is not a Web Controller");
|
||||
|
||||
// PluginsLog.LogPluginWebControllerAccessed(instance.Id, PluginAction, DiscoApplication.CurrentUser.Id);
|
||||
|
||||
// try
|
||||
// {
|
||||
// return instanceController.ExecuteAction(PluginAction, this);
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// PluginsLog.LogPluginException("Disco Plugin Web Controller Action", new PluginWebControllerException(instance.Id, PluginAction, ex));
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using Disco.Services.Plugins;
|
||||
using Disco.Web.Areas.Config.Models.Plugins;
|
||||
|
||||
namespace Disco.Web.Areas.Config.Controllers
|
||||
{
|
||||
public partial class PluginsController : dbAdminController
|
||||
{
|
||||
[HttpGet]
|
||||
public virtual ActionResult Index()
|
||||
{
|
||||
Models.Plugins.IndexViewModel vm = new Models.Plugins.IndexViewModel()
|
||||
{
|
||||
PluginManifests = Plugins.GetPlugins()
|
||||
};
|
||||
return View(vm);
|
||||
}
|
||||
|
||||
#region Plugin Configuration
|
||||
[HttpPost]
|
||||
public virtual ActionResult Configure(string PluginId, FormCollection form)
|
||||
{
|
||||
if (string.IsNullOrEmpty(PluginId))
|
||||
return RedirectToAction(MVC.Config.Plugins.Index());
|
||||
|
||||
PluginManifest manifest = Plugins.GetPlugin(PluginId);
|
||||
|
||||
using (PluginConfigurationHandler configHandler = manifest.CreateConfigurationHandler())
|
||||
{
|
||||
if (configHandler.Post(dbContext, form, this))
|
||||
{
|
||||
dbContext.SaveChanges();
|
||||
|
||||
PluginsLog.LogPluginConfigurationSaved(manifest.Id, DiscoApplication.CurrentUser.Id);
|
||||
|
||||
return RedirectToAction(MVC.Config.Plugins.Index());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Config Errors
|
||||
PluginConfigurationViewModel vm = new PluginConfigurationViewModel(configHandler.Get(dbContext, this));
|
||||
return View(Views.Configure, vm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public virtual ActionResult Configure(string PluginId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(PluginId))
|
||||
return RedirectToAction(MVC.Config.Plugins.Index());
|
||||
|
||||
PluginManifest manifest = Plugins.GetPlugin(PluginId);
|
||||
|
||||
using (PluginConfigurationHandler configHandler = manifest.CreateConfigurationHandler())
|
||||
{
|
||||
PluginConfigurationViewModel vm = new PluginConfigurationViewModel(configHandler.Get(dbContext, this));
|
||||
PluginsLog.LogPluginConfigurationLoaded(manifest.Id, DiscoApplication.CurrentUser.Id);
|
||||
return View(Views.Configure, vm);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,76 +1,201 @@
|
||||
@model Disco.Web.Areas.Config.Models.Plugins.IndexViewModel
|
||||
@using Disco.Services.Plugins;
|
||||
@{
|
||||
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Plugins");
|
||||
}
|
||||
@{
|
||||
if (Model.PluginManifests.Count == 0)
|
||||
{
|
||||
<div class="form" style="width: 450px">
|
||||
<span class="smallMessage">No Plugins Installed</span>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
var pluginGroups = Model.PluginManifestsByType;
|
||||
|
||||
|
||||
int itemsPerColumn = pluginGroups.Count / 3;
|
||||
var itemNextId = 0;
|
||||
|
||||
<table id="pageMenu">
|
||||
<tr>
|
||||
@for (int i = 0; i < 3; i++)
|
||||
{
|
||||
<td>
|
||||
@{
|
||||
int itemsForThisColumn = itemsPerColumn + (pluginGroups.Count % 3 > i ? 1 : 0);
|
||||
for (int i2 = 0; i2 < itemsForThisColumn && itemNextId < pluginGroups.Count; i2++)
|
||||
{
|
||||
var pluginGroup = pluginGroups[itemNextId];
|
||||
itemNextId++;
|
||||
<div class="pageMenuArea">
|
||||
<h2>@Plugins.PluginFeatureCategoryDisplayName(pluginGroup.Item1)</h2>
|
||||
@foreach (var pluginDefinition in pluginGroup.Item2)
|
||||
{
|
||||
@Html.ActionLink(pluginDefinition.Name, MVC.Config.Plugins.Configure(pluginDefinition.Id))
|
||||
<div class="pageMenuBlurb">
|
||||
@pluginDefinition.Id | v@(pluginDefinition.Version.ToString(3))
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@*
|
||||
foreach (var pluginGroup in pluginGroups)
|
||||
{
|
||||
<div class="form" style="width: 450px">
|
||||
<h2>@DiscoPlugins.PluginCategoryDisplayName(pluginGroup.Key)</h2>
|
||||
<table>
|
||||
@foreach (var pluginDefinition in pluginGroup)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
@if (pluginDefinition.HasConfiguration)
|
||||
{
|
||||
@Html.ActionLink(pluginDefinition.Name, MVC.Config.Plugins.Configure(pluginDefinition.Id))<br />
|
||||
<span class="smallMessage">@pluginDefinition.Id | v@(pluginDefinition.Version.ToString(3))</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
@pluginDefinition.Name <br />
|
||||
<span class="smallMessage">@pluginDefinition.Id | v@(pluginDefinition.Version.ToString(2))
|
||||
| Not Configurable</span>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
</div> *@
|
||||
}
|
||||
}
|
||||
@model Disco.Web.Areas.Config.Models.Plugins.IndexViewModel
|
||||
@using Disco.Services.Plugins;
|
||||
@{
|
||||
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Plugins");
|
||||
}
|
||||
@{
|
||||
if (Model.PluginManifests.Count == 0)
|
||||
{
|
||||
<div class="form" style="width: 450px; padding: 100px 0;">
|
||||
<h2>No Plugins are Installed</h2>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
var pluginGroups = Model.PluginManifestsByType;
|
||||
|
||||
|
||||
int itemsPerColumn = pluginGroups.Count / 3;
|
||||
var itemNextId = 0;
|
||||
|
||||
<table id="pageMenu">
|
||||
<tr>
|
||||
@for (int i = 0; i < 3; i++)
|
||||
{
|
||||
<td>
|
||||
@{
|
||||
int itemsForThisColumn = itemsPerColumn + (pluginGroups.Count % 3 > i ? 1 : 0);
|
||||
for (int i2 = 0; i2 < itemsForThisColumn && itemNextId < pluginGroups.Count; i2++)
|
||||
{
|
||||
var pluginGroup = pluginGroups[itemNextId];
|
||||
itemNextId++;
|
||||
<div class="pageMenuArea">
|
||||
<h2>@Plugins.PluginFeatureCategoryDisplayName(pluginGroup.Item1)</h2>
|
||||
@foreach (var pluginDefinition in pluginGroup.Item2)
|
||||
{
|
||||
@Html.ActionLink(pluginDefinition.Name, MVC.Config.Plugins.Configure(pluginDefinition.Id))
|
||||
<div class="pageMenuBlurb">
|
||||
@pluginDefinition.Id | v@(pluginDefinition.Version.ToString(3))
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
</table>
|
||||
<div id="dialogUninstallPlugins" title="Uninstall Plugin">
|
||||
<div>
|
||||
@Html.DropDownList("uninstallPlugin", Model.PluginManifests.ToSelectListItems(null, true, "Select a Plugin to Uninstall"))
|
||||
</div>
|
||||
<div>
|
||||
<input id="uninstallPluginData" type="checkbox" /><label for="uninstallPluginData"> Uninstall Plugin Data</label>
|
||||
<div id="uninstallPluginDataAlert" style="display: none; padding: 0.7em 0.7em; margin-top: 8px;" class="ui-state-error ui-corner-all">
|
||||
<span style="margin-right: 0.3em; float: left;" class="ui-icon ui-icon-alert"></span>NOTE: Data will be permanently deleted
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="dialogUninstallPluginConfirm" title="Confirm Plugin Uninstall">
|
||||
<div style="padding: 0.7em 0.7em; margin-top: 8px;" class="ui-state-highlight ui-corner-all">
|
||||
<span style="margin-right: 0.3em; float: left;" class="ui-icon ui-icon-help"></span>Are you sure you want to uninstall this plugin?
|
||||
<h4 id="uninstallPluginConfirm"></h4>
|
||||
</div>
|
||||
<div id="uninstallPluginDataConfirm" style="display: none; padding: 0.7em 0.7em; margin-top: 8px;" class="ui-state-error ui-corner-all">
|
||||
<span style="margin-right: 0.3em; float: left;" class="ui-icon ui-icon-alert"></span>NOTE: Data will be permanently deleted
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
// Uninstall
|
||||
var uninstallUrl = '@(Url.Action(MVC.API.Plugin.Uninstall()))/';
|
||||
var uninstallPlugin, uninstallPluginData, $dialogConfirm, uninstallPluginConfirm, uninstallPluginDataConfirm;
|
||||
|
||||
var pluginId, pluginName, pluginUninstallData;
|
||||
|
||||
var $dialog = $('#dialogUninstallPlugins').dialog({
|
||||
resizable: false,
|
||||
modal: true,
|
||||
width: 350,
|
||||
autoOpen: false,
|
||||
buttons: {
|
||||
"Uninstall": function () {
|
||||
pluginId = uninstallPlugin.val();
|
||||
pluginName = uninstallPlugin.find('option:selected').text();
|
||||
pluginUninstallData = uninstallPluginData.is(':checked');
|
||||
|
||||
if (!pluginId) {
|
||||
alert('Select a plugin to uninstall');
|
||||
} else {
|
||||
uninstallPluginConfirm.text(pluginName + ' [' + pluginId + ']');
|
||||
if (pluginUninstallData)
|
||||
uninstallPluginDataConfirm.show();
|
||||
else
|
||||
uninstallPluginDataConfirm.hide();
|
||||
|
||||
$dialogConfirm.dialog('open');
|
||||
$(this).dialog("close");
|
||||
}
|
||||
},
|
||||
Cancel: function () {
|
||||
uninstallPluginData.removeAttr('checked');
|
||||
$('#uninstallPluginDataAlert').hide();
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$dialogConfirm = $('#dialogUninstallPluginConfirm').dialog({
|
||||
resizable: false,
|
||||
modal: true,
|
||||
width: 350,
|
||||
autoOpen: false,
|
||||
buttons: {
|
||||
"Confirm Uninstall": function () {
|
||||
var url = uninstallUrl + pluginId;
|
||||
if (pluginUninstallData)
|
||||
url += '?UninstallData=true'
|
||||
else
|
||||
url += '?UninstallData=false'
|
||||
|
||||
window.location.href = url;
|
||||
$(this).dialog("disable");
|
||||
},
|
||||
Cancel: function () {
|
||||
uninstallPluginData.removeAttr('checked');
|
||||
$('#uninstallPluginDataAlert').hide();
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
uninstallPlugin = $('#uninstallPlugin');
|
||||
uninstallPluginData = $('#uninstallPluginData');
|
||||
uninstallPluginConfirm = $('#uninstallPluginConfirm');
|
||||
uninstallPluginDataConfirm = $('#uninstallPluginDataConfirm');
|
||||
|
||||
$('#buttonUninstall').click(function () {
|
||||
$dialog.dialog('open');
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#uninstallPluginData').change(function () {
|
||||
if ($(this).is(':checked')) {
|
||||
$('#uninstallPluginDataAlert').slideDown();
|
||||
} else {
|
||||
$('#uninstallPluginDataAlert').slideUp();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
}
|
||||
}
|
||||
<div id="dialogInstallPlugin" title="Install Plugin">
|
||||
<div style="padding-bottom: 10px;">
|
||||
@using (Html.BeginForm(MVC.API.Plugin.Install(), FormMethod.Post, new { enctype = "multipart/form-data" }))
|
||||
{
|
||||
<label for="pluginFile">Plugin Package: </label>
|
||||
<input id="pluginFile" name="Plugin" type="file" />
|
||||
}
|
||||
</div>
|
||||
<div style="padding: 0.7em 0.7em; margin-top: 8px;" class="ui-state-error ui-corner-all">
|
||||
<span style="margin-right: 0.3em; margin-bottom: 2em; float: left;" class="ui-icon ui-icon-alert"></span>Warning: All plugins run with the same level of network privileges as the Disco Web App.<br />
|
||||
<strong>Only install plugins from a trusted source.</strong>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
// Install
|
||||
var $dialogInstall = $('#dialogInstallPlugin').dialog({
|
||||
resizable: false,
|
||||
modal: true,
|
||||
width: 350,
|
||||
autoOpen: false,
|
||||
buttons: {
|
||||
"Upload & Install": function () {
|
||||
var pluginFile = $('#pluginFile');
|
||||
if (pluginFile.val()) {
|
||||
pluginFile.closest('form').submit();
|
||||
$(this).dialog('disable');
|
||||
} else {
|
||||
alert('Choose a Plugin Package to Install');
|
||||
}
|
||||
},
|
||||
Cancel: function () {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
});
|
||||
$('#buttonInstall').click(function () {
|
||||
$dialogInstall.dialog('open');
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<div class="actionBar">
|
||||
@if (Model.PluginManifests.Count > 0)
|
||||
{
|
||||
@Html.ActionLinkButton("Uninstall Plugins", MVC.Config.Plugins.Index(), "buttonUninstall")
|
||||
}
|
||||
@Html.ActionLinkButton("Install Plugins", MVC.Config.Plugins.Index(), "buttonInstall")
|
||||
</div>
|
||||
|
||||
@@ -1,251 +1,512 @@
|
||||
#pragma warning disable 1591
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.17929
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Disco.Web.Areas.Config.Views.Plugins
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Web.Helpers;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Mvc.Ajax;
|
||||
using System.Web.Mvc.Html;
|
||||
using System.Web.Routing;
|
||||
using System.Web.Security;
|
||||
using System.Web.UI;
|
||||
using System.Web.WebPages;
|
||||
using Disco.BI.Extensions;
|
||||
using Disco.Models.Repository;
|
||||
|
||||
#line 2 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
using Disco.Services.Plugins;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
using Disco.Web;
|
||||
using Disco.Web.Extensions;
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "1.5.0.0")]
|
||||
[System.Web.WebPages.PageVirtualPathAttribute("~/Areas/Config/Views/Plugins/Index.cshtml")]
|
||||
public class Index : System.Web.Mvc.WebViewPage<Disco.Web.Areas.Config.Models.Plugins.IndexViewModel>
|
||||
{
|
||||
public Index()
|
||||
{
|
||||
}
|
||||
public override void Execute()
|
||||
{
|
||||
|
||||
#line 3 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Plugins");
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\r\n");
|
||||
|
||||
|
||||
#line 6 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
if (Model.PluginManifests.Count == 0)
|
||||
{
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <div");
|
||||
|
||||
WriteLiteral(" class=\"form\"");
|
||||
|
||||
WriteLiteral(" style=\"width: 450px\"");
|
||||
|
||||
WriteLiteral(">\r\n <span");
|
||||
|
||||
WriteLiteral(" class=\"smallMessage\"");
|
||||
|
||||
WriteLiteral(">No Plugins Installed</span>\r\n </div> \r\n");
|
||||
|
||||
|
||||
#line 12 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
}
|
||||
else
|
||||
{
|
||||
var pluginGroups = Model.PluginManifestsByType;
|
||||
|
||||
|
||||
int itemsPerColumn = pluginGroups.Count / 3;
|
||||
var itemNextId = 0;
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <table");
|
||||
|
||||
WriteLiteral(" id=\"pageMenu\"");
|
||||
|
||||
WriteLiteral(">\r\n <tr>\r\n");
|
||||
|
||||
|
||||
#line 23 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 23 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <td>\r\n");
|
||||
|
||||
|
||||
#line 26 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 26 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
int itemsForThisColumn = itemsPerColumn + (pluginGroups.Count % 3 > i ? 1 : 0);
|
||||
for (int i2 = 0; i2 < itemsForThisColumn && itemNextId < pluginGroups.Count; i2++)
|
||||
{
|
||||
var pluginGroup = pluginGroups[itemNextId];
|
||||
itemNextId++;
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <div");
|
||||
|
||||
WriteLiteral(" class=\"pageMenuArea\"");
|
||||
|
||||
WriteLiteral(">\r\n <h2>");
|
||||
|
||||
|
||||
#line 33 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
Write(Plugins.PluginFeatureCategoryDisplayName(pluginGroup.Item1));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("</h2>\r\n");
|
||||
|
||||
|
||||
#line 34 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 34 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
foreach (var pluginDefinition in pluginGroup.Item2)
|
||||
{
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 36 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
Write(Html.ActionLink(pluginDefinition.Name, MVC.Config.Plugins.Configure(pluginDefinition.Id)));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 36 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <div");
|
||||
|
||||
WriteLiteral(" class=\"pageMenuBlurb\"");
|
||||
|
||||
WriteLiteral(">\r\n");
|
||||
|
||||
WriteLiteral(" ");
|
||||
|
||||
|
||||
#line 38 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
Write(pluginDefinition.Id);
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" | v");
|
||||
|
||||
|
||||
#line 38 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
Write(pluginDefinition.Version.ToString(3));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\r\n </div>\r\n");
|
||||
|
||||
|
||||
#line 40 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" </div>\r\n");
|
||||
|
||||
|
||||
#line 42 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\r\n </td>\r\n");
|
||||
|
||||
|
||||
#line 45 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" </tr>\r\n </table>\r\n");
|
||||
|
||||
|
||||
#line 48 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 74 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\r\n");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
||||
#pragma warning disable 1591
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.17929
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Disco.Web.Areas.Config.Views.Plugins
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Web.Helpers;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Mvc.Ajax;
|
||||
using System.Web.Mvc.Html;
|
||||
using System.Web.Routing;
|
||||
using System.Web.Security;
|
||||
using System.Web.UI;
|
||||
using System.Web.WebPages;
|
||||
using Disco.BI.Extensions;
|
||||
using Disco.Models.Repository;
|
||||
|
||||
#line 2 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
using Disco.Services.Plugins;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
using Disco.Web;
|
||||
using Disco.Web.Extensions;
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "1.5.0.0")]
|
||||
[System.Web.WebPages.PageVirtualPathAttribute("~/Areas/Config/Views/Plugins/Index.cshtml")]
|
||||
public class Index : System.Web.Mvc.WebViewPage<Disco.Web.Areas.Config.Models.Plugins.IndexViewModel>
|
||||
{
|
||||
public Index()
|
||||
{
|
||||
}
|
||||
public override void Execute()
|
||||
{
|
||||
|
||||
#line 3 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Plugins");
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\r\n");
|
||||
|
||||
|
||||
#line 6 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
if (Model.PluginManifests.Count == 0)
|
||||
{
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <div");
|
||||
|
||||
WriteLiteral(" class=\"form\"");
|
||||
|
||||
WriteLiteral(" style=\"width: 450px; padding: 100px 0;\"");
|
||||
|
||||
WriteLiteral(">\r\n <h2>No Plugins are Installed</h2>\r\n </div> \r\n");
|
||||
|
||||
|
||||
#line 12 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
}
|
||||
else
|
||||
{
|
||||
var pluginGroups = Model.PluginManifestsByType;
|
||||
|
||||
|
||||
int itemsPerColumn = pluginGroups.Count / 3;
|
||||
var itemNextId = 0;
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <table");
|
||||
|
||||
WriteLiteral(" id=\"pageMenu\"");
|
||||
|
||||
WriteLiteral(">\r\n <tr>\r\n");
|
||||
|
||||
|
||||
#line 23 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 23 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <td>\r\n");
|
||||
|
||||
|
||||
#line 26 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 26 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
int itemsForThisColumn = itemsPerColumn + (pluginGroups.Count % 3 > i ? 1 : 0);
|
||||
for (int i2 = 0; i2 < itemsForThisColumn && itemNextId < pluginGroups.Count; i2++)
|
||||
{
|
||||
var pluginGroup = pluginGroups[itemNextId];
|
||||
itemNextId++;
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <div");
|
||||
|
||||
WriteLiteral(" class=\"pageMenuArea\"");
|
||||
|
||||
WriteLiteral(">\r\n <h2>");
|
||||
|
||||
|
||||
#line 33 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
Write(Plugins.PluginFeatureCategoryDisplayName(pluginGroup.Item1));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("</h2>\r\n");
|
||||
|
||||
|
||||
#line 34 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 34 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
foreach (var pluginDefinition in pluginGroup.Item2)
|
||||
{
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 36 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
Write(Html.ActionLink(pluginDefinition.Name, MVC.Config.Plugins.Configure(pluginDefinition.Id)));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 36 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <div");
|
||||
|
||||
WriteLiteral(" class=\"pageMenuBlurb\"");
|
||||
|
||||
WriteLiteral(">\r\n");
|
||||
|
||||
WriteLiteral(" ");
|
||||
|
||||
|
||||
#line 38 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
Write(pluginDefinition.Id);
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" | v");
|
||||
|
||||
|
||||
#line 38 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
Write(pluginDefinition.Version.ToString(3));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\r\n </div>\r\n");
|
||||
|
||||
|
||||
#line 40 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" </div>\r\n");
|
||||
|
||||
|
||||
#line 42 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\r\n </td>\r\n");
|
||||
|
||||
|
||||
#line 45 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" </tr>\r\n </table>\r\n");
|
||||
|
||||
WriteLiteral(" <div");
|
||||
|
||||
WriteLiteral(" id=\"dialogUninstallPlugins\"");
|
||||
|
||||
WriteLiteral(" title=\"Uninstall Plugin\"");
|
||||
|
||||
WriteLiteral(">\r\n <div>\r\n");
|
||||
|
||||
WriteLiteral(" ");
|
||||
|
||||
|
||||
#line 50 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
Write(Html.DropDownList("uninstallPlugin", Model.PluginManifests.ToSelectListItems(null, true, "Select a Plugin to Uninstall")));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\r\n </div>\r\n <div>\r\n <input");
|
||||
|
||||
WriteLiteral(" id=\"uninstallPluginData\"");
|
||||
|
||||
WriteLiteral(" type=\"checkbox\"");
|
||||
|
||||
WriteLiteral(" /><label");
|
||||
|
||||
WriteLiteral(" for=\"uninstallPluginData\"");
|
||||
|
||||
WriteLiteral("> Uninstall Plugin Data</label>\r\n <div");
|
||||
|
||||
WriteLiteral(" id=\"uninstallPluginDataAlert\"");
|
||||
|
||||
WriteLiteral(" style=\"display: none; padding: 0.7em 0.7em; margin-top: 8px;\"");
|
||||
|
||||
WriteLiteral(" class=\"ui-state-error ui-corner-all\"");
|
||||
|
||||
WriteLiteral(">\r\n <span");
|
||||
|
||||
WriteLiteral(" style=\"margin-right: 0.3em; float: left;\"");
|
||||
|
||||
WriteLiteral(" class=\"ui-icon ui-icon-alert\"");
|
||||
|
||||
WriteLiteral("></span>NOTE: Data will be permanently deleted\r\n </div>\r\n </div" +
|
||||
">\r\n </div>\r\n");
|
||||
|
||||
WriteLiteral(" <div");
|
||||
|
||||
WriteLiteral(" id=\"dialogUninstallPluginConfirm\"");
|
||||
|
||||
WriteLiteral(" title=\"Confirm Plugin Uninstall\"");
|
||||
|
||||
WriteLiteral(">\r\n <div");
|
||||
|
||||
WriteLiteral(" style=\"padding: 0.7em 0.7em; margin-top: 8px;\"");
|
||||
|
||||
WriteLiteral(" class=\"ui-state-highlight ui-corner-all\"");
|
||||
|
||||
WriteLiteral(">\r\n <span");
|
||||
|
||||
WriteLiteral(" style=\"margin-right: 0.3em; float: left;\"");
|
||||
|
||||
WriteLiteral(" class=\"ui-icon ui-icon-help\"");
|
||||
|
||||
WriteLiteral("></span>Are you sure you want to uninstall this plugin?\r\n <h4");
|
||||
|
||||
WriteLiteral(" id=\"uninstallPluginConfirm\"");
|
||||
|
||||
WriteLiteral("></h4>\r\n </div>\r\n <div");
|
||||
|
||||
WriteLiteral(" id=\"uninstallPluginDataConfirm\"");
|
||||
|
||||
WriteLiteral(" style=\"display: none; padding: 0.7em 0.7em; margin-top: 8px;\"");
|
||||
|
||||
WriteLiteral(" class=\"ui-state-error ui-corner-all\"");
|
||||
|
||||
WriteLiteral(">\r\n <span");
|
||||
|
||||
WriteLiteral(" style=\"margin-right: 0.3em; float: left;\"");
|
||||
|
||||
WriteLiteral(" class=\"ui-icon ui-icon-alert\"");
|
||||
|
||||
WriteLiteral("></span>NOTE: Data will be permanently deleted\r\n </div>\r\n </div>\r\n");
|
||||
|
||||
WriteLiteral(" <script>\r\n $(function () {\r\n // Uninstall\r\n var " +
|
||||
"uninstallUrl = \'");
|
||||
|
||||
|
||||
#line 71 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
Write(Url.Action(MVC.API.Plugin.Uninstall()));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("/\';\r\n var uninstallPlugin, uninstallPluginData, $dialogConfirm, uninst" +
|
||||
"allPluginConfirm, uninstallPluginDataConfirm;\r\n\r\n var pluginId, plugi" +
|
||||
"nName, pluginUninstallData;\r\n\r\n var $dialog = $(\'#dialogUninstallPlug" +
|
||||
"ins\').dialog({\r\n resizable: false,\r\n modal: true,\r" +
|
||||
"\n width: 350,\r\n autoOpen: false,\r\n " +
|
||||
"buttons: {\r\n \"Uninstall\": function () {\r\n " +
|
||||
" pluginId = uninstallPlugin.val();\r\n pluginName = unin" +
|
||||
"stallPlugin.find(\'option:selected\').text();\r\n pluginUnins" +
|
||||
"tallData = uninstallPluginData.is(\':checked\');\r\n\r\n if (!p" +
|
||||
"luginId) {\r\n alert(\'Select a plugin to uninstall\');\r\n" +
|
||||
" } else {\r\n uninstallPluginCon" +
|
||||
"firm.text(pluginName + \' [\' + pluginId + \']\');\r\n if (" +
|
||||
"pluginUninstallData)\r\n uninstallPluginDataConfirm" +
|
||||
".show();\r\n else\r\n unin" +
|
||||
"stallPluginDataConfirm.hide();\r\n\r\n $dialogConfirm.dia" +
|
||||
"log(\'open\');\r\n $(this).dialog(\"close\");\r\n " +
|
||||
" }\r\n },\r\n Cancel: function () {" +
|
||||
"\r\n uninstallPluginData.removeAttr(\'checked\');\r\n " +
|
||||
" $(\'#uninstallPluginDataAlert\').hide();\r\n $(" +
|
||||
"this).dialog(\"close\");\r\n }\r\n }\r\n })" +
|
||||
";\r\n\r\n $dialogConfirm = $(\'#dialogUninstallPluginConfirm\').dialog({\r\n " +
|
||||
" resizable: false,\r\n modal: true,\r\n " +
|
||||
"width: 350,\r\n autoOpen: false,\r\n buttons: {\r\n " +
|
||||
" \"Confirm Uninstall\": function () {\r\n var u" +
|
||||
"rl = uninstallUrl + pluginId;\r\n if (pluginUninstallData)\r" +
|
||||
"\n url += \'?UninstallData=true\'\r\n " +
|
||||
" else\r\n url += \'?UninstallData=false\'\r\n\r\n " +
|
||||
" window.location.href = url;\r\n $(this).dialo" +
|
||||
"g(\"disable\");\r\n },\r\n Cancel: function () {" +
|
||||
"\r\n uninstallPluginData.removeAttr(\'checked\');\r\n " +
|
||||
" $(\'#uninstallPluginDataAlert\').hide();\r\n $(" +
|
||||
"this).dialog(\"close\");\r\n }\r\n }\r\n })" +
|
||||
";\r\n\r\n uninstallPlugin = $(\'#uninstallPlugin\');\r\n uninstall" +
|
||||
"PluginData = $(\'#uninstallPluginData\');\r\n uninstallPluginConfirm = $(" +
|
||||
"\'#uninstallPluginConfirm\');\r\n uninstallPluginDataConfirm = $(\'#uninst" +
|
||||
"allPluginDataConfirm\');\r\n\r\n $(\'#buttonUninstall\').click(function () {" +
|
||||
"\r\n $dialog.dialog(\'open\');\r\n return false;\r\n " +
|
||||
" });\r\n\r\n $(\'#uninstallPluginData\').change(function () {\r\n " +
|
||||
" if ($(this).is(\':checked\')) {\r\n $(\'#uninstallPluginD" +
|
||||
"ataAlert\').slideDown();\r\n } else {\r\n $(\'#unins" +
|
||||
"tallPluginDataAlert\').slideUp();\r\n }\r\n });\r\n })" +
|
||||
";\r\n </script>\r\n");
|
||||
|
||||
|
||||
#line 151 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\r\n<div");
|
||||
|
||||
WriteLiteral(" id=\"dialogInstallPlugin\"");
|
||||
|
||||
WriteLiteral(" title=\"Install Plugin\"");
|
||||
|
||||
WriteLiteral(">\r\n <div");
|
||||
|
||||
WriteLiteral(" style=\"padding-bottom: 10px;\"");
|
||||
|
||||
WriteLiteral(">\r\n");
|
||||
|
||||
|
||||
#line 155 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 155 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
using (Html.BeginForm(MVC.API.Plugin.Install(), FormMethod.Post, new { enctype = "multipart/form-data" }))
|
||||
{
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <label");
|
||||
|
||||
WriteLiteral(" for=\"pluginFile\"");
|
||||
|
||||
WriteLiteral(">Plugin Package: </label>\r\n");
|
||||
|
||||
WriteLiteral(" <input");
|
||||
|
||||
WriteLiteral(" id=\"pluginFile\"");
|
||||
|
||||
WriteLiteral(" name=\"Plugin\"");
|
||||
|
||||
WriteLiteral(" type=\"file\"");
|
||||
|
||||
WriteLiteral(" />\r\n");
|
||||
|
||||
|
||||
#line 159 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" </div>\r\n <div");
|
||||
|
||||
WriteLiteral(" style=\"padding: 0.7em 0.7em; margin-top: 8px;\"");
|
||||
|
||||
WriteLiteral(" class=\"ui-state-error ui-corner-all\"");
|
||||
|
||||
WriteLiteral(">\r\n <span");
|
||||
|
||||
WriteLiteral(" style=\"margin-right: 0.3em; margin-bottom: 2em; float: left;\"");
|
||||
|
||||
WriteLiteral(" class=\"ui-icon ui-icon-alert\"");
|
||||
|
||||
WriteLiteral(@"></span>Warning: All plugins run with the same level of network privileges as the Disco Web App.<br />
|
||||
<strong>Only install plugins from a trusted source.</strong>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
// Install
|
||||
var $dialogInstall = $('#dialogInstallPlugin').dialog({
|
||||
resizable: false,
|
||||
modal: true,
|
||||
width: 350,
|
||||
autoOpen: false,
|
||||
buttons: {
|
||||
""Upload & Install"": function () {
|
||||
var pluginFile = $('#pluginFile');
|
||||
if (pluginFile.val()) {
|
||||
pluginFile.closest('form').submit();
|
||||
$(this).dialog('disable');
|
||||
} else {
|
||||
alert('Choose a Plugin Package to Install');
|
||||
}
|
||||
},
|
||||
Cancel: function () {
|
||||
$(this).dialog(""close"");
|
||||
}
|
||||
}
|
||||
});
|
||||
$('#buttonInstall').click(function () {
|
||||
$dialogInstall.dialog('open');
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<div");
|
||||
|
||||
WriteLiteral(" class=\"actionBar\"");
|
||||
|
||||
WriteLiteral(">\r\n");
|
||||
|
||||
|
||||
#line 196 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 196 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
if (Model.PluginManifests.Count > 0)
|
||||
{
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 198 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
Write(Html.ActionLinkButton("Uninstall Plugins", MVC.Config.Plugins.Index(), "buttonUninstall"));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 198 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" ");
|
||||
|
||||
|
||||
#line 200 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
|
||||
Write(Html.ActionLinkButton("Install Plugins", MVC.Config.Plugins.Index(), "buttonInstall"));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\r\n</div>\r\n");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
||||
|
||||
@@ -1,306 +1,308 @@
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
using System.Threading;
|
||||
using System.Web.Mvc;
|
||||
using Disco.Web.Models.InitialConfig;
|
||||
using Disco.Data.Repository;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.IO.Compression;
|
||||
using System.Management;
|
||||
|
||||
namespace Disco.Web.Controllers
|
||||
{
|
||||
[OutputCache(Duration = 0, Location = System.Web.UI.OutputCacheLocation.None)]
|
||||
public partial class InitialConfigController : Controller
|
||||
{
|
||||
|
||||
#region Determine Server Is Core SKU
|
||||
// Added 2012-11-01 G#
|
||||
// http://www.discoict.com.au/forum/support/2012/10/install-on-server-core.aspx
|
||||
private static Lazy<bool> ServerIsCoreSKU = new Lazy<bool>(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
uint osSKU = 0;
|
||||
using (var mSearcher = new ManagementObjectSearcher("SELECT OperatingSystemSKU FROM Win32_OperatingSystem"))
|
||||
{
|
||||
using (var mResults = mSearcher.Get())
|
||||
{
|
||||
foreach (ManagementObject mResult in mResults)
|
||||
{
|
||||
osSKU = (uint)mResult.Properties["OperatingSystemSKU"].Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (osSKU)
|
||||
{
|
||||
case 12: // Datacenter Server Core Edition
|
||||
case 13: // Standard Server Core Edition
|
||||
case 14: // Enterprise Server Core Edition
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Ignore Exceptions
|
||||
}
|
||||
|
||||
// Default to "Not Core"
|
||||
return false;
|
||||
});
|
||||
// End Added 2012-11-01 G#
|
||||
#endregion
|
||||
|
||||
protected override void OnActionExecuting(ActionExecutingContext filterContext)
|
||||
{
|
||||
// Updated 2012-11-01 G# - Consider ServerIsCoreSKU
|
||||
if (!Request.IsLocal && !ServerIsCoreSKU.Value)
|
||||
{
|
||||
filterContext.Result = new HttpStatusCodeResult(System.Net.HttpStatusCode.ServiceUnavailable, "Initial Configuration of Disco is only allowed via a local connection");
|
||||
}
|
||||
base.OnActionExecuting(filterContext);
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Install/
|
||||
|
||||
public virtual ActionResult Index()
|
||||
{
|
||||
return RedirectToAction(MVC.InitialConfig.Welcome());
|
||||
}
|
||||
|
||||
#region Welcome
|
||||
public virtual ActionResult Welcome()
|
||||
{
|
||||
var m = new WelcomeModel();
|
||||
|
||||
m.AutodetectOrganisation();
|
||||
|
||||
return View(m);
|
||||
}
|
||||
[HttpPost]
|
||||
public virtual ActionResult Welcome(WelcomeModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
DiscoApplication.OrganisationName = model.OrganisationName;
|
||||
|
||||
return RedirectToAction(MVC.InitialConfig.Database());
|
||||
}
|
||||
|
||||
return View(model);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Database
|
||||
public virtual ActionResult Database()
|
||||
{
|
||||
var cs = Disco.Data.Repository.DiscoDatabaseConnectionFactory.DiscoDataContextConnectionString;
|
||||
|
||||
DatabaseModel m;
|
||||
|
||||
if (cs == null)
|
||||
m = new DatabaseModel(); // Just use Defaults
|
||||
else
|
||||
m = DatabaseModel.FromConnectionString(cs); // Import from existing Connection String
|
||||
|
||||
return View(m);
|
||||
}
|
||||
[HttpPost]
|
||||
public virtual ActionResult Database(DatabaseModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
// Continue with Configuration
|
||||
var connectionString = model.ToConnectionString();
|
||||
|
||||
// Try Creating/Migrating
|
||||
connectionString.ConnectTimeout = 5;
|
||||
Disco.Data.Repository.DiscoDatabaseConnectionFactory.SetDiscoDataContextConnectionString(connectionString.ToString(), false);
|
||||
|
||||
try
|
||||
{
|
||||
Disco.Data.Migrations.DiscoDataMigrator.MigrateLatest(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Find inner exception
|
||||
SqlException sqlException = null;
|
||||
Exception innermostException = ex;
|
||||
do
|
||||
{
|
||||
if (sqlException == null)
|
||||
sqlException = innermostException as SqlException;
|
||||
if (innermostException.InnerException != null)
|
||||
innermostException = innermostException.InnerException;
|
||||
else
|
||||
break;
|
||||
} while (true);
|
||||
|
||||
if (sqlException != null)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, string.Format("Unable to create or migrate the database to the latest version: [{0}] {1}", sqlException.GetType().Name, sqlException.Message));
|
||||
}
|
||||
else
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, string.Format("Unable to create or migrate the database to the latest version: [{0}] {1}", innermostException.GetType().Name, innermostException.Message));
|
||||
}
|
||||
}
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
// Save Connection String
|
||||
//Disco.Data.Repository.DiscoDatabaseConnectionFactory.SetDiscoDataContextConnectionString(model.ToConnectionString().ToString(), true);
|
||||
// Write Organisation Name into DB
|
||||
using (DiscoDataContext db = new DiscoDataContext())
|
||||
{
|
||||
db.DiscoConfiguration.OrganisationName = DiscoApplication.OrganisationName;
|
||||
db.SaveChanges();
|
||||
}
|
||||
|
||||
return RedirectToAction(MVC.InitialConfig.FileStore());
|
||||
}
|
||||
}
|
||||
|
||||
return View(model);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FileStore
|
||||
public virtual ActionResult FileStore()
|
||||
{
|
||||
// Try and retrieve FileStore path from DB
|
||||
string FileStoreLocation = null;
|
||||
try
|
||||
{
|
||||
using (DiscoDataContext db = new DiscoDataContext())
|
||||
FileStoreLocation = db.ConfigurationItems.Where(ci => ci.Scope == "System" && ci.Key == "DataStoreLocation").Select(ci => ci.Value).FirstOrDefault();
|
||||
}
|
||||
catch (Exception) { } // Ignore All Errors
|
||||
|
||||
FileStoreModel m = new FileStoreModel();
|
||||
|
||||
// Test for valid Format
|
||||
if (!string.IsNullOrEmpty(FileStoreLocation))
|
||||
if (!Regex.IsMatch(FileStoreLocation, @"^[A-z]:(\\[^\\/:*?""<>|0x0-0x1F]+)+(\\)?$", RegexOptions.Singleline))
|
||||
FileStoreLocation = null;
|
||||
m.FileStoreLocation = FileStoreLocation;
|
||||
if (m.FileStoreLocation != null && m.FileStoreLocation.EndsWith(@"\"))
|
||||
m.FileStoreLocation = m.FileStoreLocation.TrimEnd('\\');
|
||||
|
||||
m.ExpandDirectoryModel();
|
||||
|
||||
return View(m);
|
||||
}
|
||||
[HttpPost]
|
||||
public virtual ActionResult FileStore(FileStoreModel m)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
// Ensure Path Exists
|
||||
using (DiscoDataContext db = new DiscoDataContext())
|
||||
{
|
||||
var configItem = db.ConfigurationItems.Where(ci => ci.Scope == "System" && ci.Key == "DataStoreLocation").FirstOrDefault();
|
||||
if (configItem == null)
|
||||
{ // Create Config
|
||||
db.ConfigurationItems.Add(new Disco.Models.Repository.ConfigurationItem()
|
||||
{
|
||||
Scope = "System",
|
||||
Key = "DataStoreLocation",
|
||||
Value = m.FileStoreLocation
|
||||
});
|
||||
}
|
||||
else
|
||||
{ // Update Config
|
||||
configItem.Value = m.FileStoreLocation;
|
||||
}
|
||||
db.SaveChanges();
|
||||
}
|
||||
|
||||
// Extract DataStore Template into FileStore
|
||||
var templatePath = Server.MapPath("~/ClientBin/DataStoreTemplate.zip");
|
||||
if (System.IO.File.Exists(templatePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (ZipArchive templateArchive = ZipFile.Open(templatePath, ZipArchiveMode.Read))
|
||||
{
|
||||
foreach (var entry in templateArchive.Entries)
|
||||
{
|
||||
var entryDestinationPath = Path.Combine(m.FileStoreLocation, entry.FullName);
|
||||
if (System.IO.File.Exists(entryDestinationPath))
|
||||
System.IO.File.Delete(entryDestinationPath);
|
||||
}
|
||||
templateArchive.ExtractToDirectory(m.FileStoreLocation);
|
||||
}
|
||||
return RedirectToAction(MVC.InitialConfig.Complete());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, string.Format("Unable to extract File Store template: [{0}] {1}", ex.GetType().Name, ex.Message));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return RedirectToAction(MVC.InitialConfig.Complete());
|
||||
}
|
||||
}
|
||||
|
||||
m.ExpandDirectoryModel();
|
||||
|
||||
return View(m);
|
||||
}
|
||||
public virtual ActionResult FileStoreBranch(string Path)
|
||||
{
|
||||
return Json(FileStoreModel.FileStoreDirectoryModel.FromPath(Path, true), JsonRequestBehavior.AllowGet);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Complete
|
||||
public virtual ActionResult Complete()
|
||||
{
|
||||
var m = new CompleteModel();
|
||||
|
||||
m.PerformTests();
|
||||
|
||||
return View(m);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Restart WebApp
|
||||
|
||||
public virtual ActionResult RestartWebApp()
|
||||
{
|
||||
RestartWebApp(1500);
|
||||
return View();
|
||||
}
|
||||
|
||||
|
||||
private static object _restartTimerLock = new object();
|
||||
private static Timer _restartTimer;
|
||||
private void RestartWebApp(int DelayMilliseconds)
|
||||
{
|
||||
lock (_restartTimerLock)
|
||||
{
|
||||
if (_restartTimer != null)
|
||||
{
|
||||
_restartTimer.Dispose();
|
||||
}
|
||||
|
||||
_restartTimer = new Timer((state) =>
|
||||
{
|
||||
AppDomain.Unload(AppDomain.CurrentDomain);
|
||||
}, null, DelayMilliseconds, Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
using System.Threading;
|
||||
using System.Web.Mvc;
|
||||
using Disco.Web.Models.InitialConfig;
|
||||
using Disco.Data.Repository;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.IO.Compression;
|
||||
using System.Management;
|
||||
using System.Web;
|
||||
|
||||
namespace Disco.Web.Controllers
|
||||
{
|
||||
[OutputCache(Duration = 0, Location = System.Web.UI.OutputCacheLocation.None)]
|
||||
public partial class InitialConfigController : Controller
|
||||
{
|
||||
|
||||
#region Determine Server Is Core SKU
|
||||
// Added 2012-11-01 G#
|
||||
// http://www.discoict.com.au/forum/support/2012/10/install-on-server-core.aspx
|
||||
private static Lazy<bool> ServerIsCoreSKU = new Lazy<bool>(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
uint osSKU = 0;
|
||||
using (var mSearcher = new ManagementObjectSearcher("SELECT OperatingSystemSKU FROM Win32_OperatingSystem"))
|
||||
{
|
||||
using (var mResults = mSearcher.Get())
|
||||
{
|
||||
foreach (ManagementObject mResult in mResults)
|
||||
{
|
||||
osSKU = (uint)mResult.Properties["OperatingSystemSKU"].Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (osSKU)
|
||||
{
|
||||
case 12: // Datacenter Server Core Edition
|
||||
case 13: // Standard Server Core Edition
|
||||
case 14: // Enterprise Server Core Edition
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Ignore Exceptions
|
||||
}
|
||||
|
||||
// Default to "Not Core"
|
||||
return false;
|
||||
});
|
||||
// End Added 2012-11-01 G#
|
||||
#endregion
|
||||
|
||||
protected override void OnActionExecuting(ActionExecutingContext filterContext)
|
||||
{
|
||||
// Updated 2012-11-01 G# - Consider ServerIsCoreSKU
|
||||
if (!Request.IsLocal && !ServerIsCoreSKU.Value)
|
||||
{
|
||||
filterContext.Result = new HttpStatusCodeResult(System.Net.HttpStatusCode.ServiceUnavailable, "Initial Configuration of Disco is only allowed via a local connection");
|
||||
}
|
||||
base.OnActionExecuting(filterContext);
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Install/
|
||||
|
||||
public virtual ActionResult Index()
|
||||
{
|
||||
return RedirectToAction(MVC.InitialConfig.Welcome());
|
||||
}
|
||||
|
||||
#region Welcome
|
||||
public virtual ActionResult Welcome()
|
||||
{
|
||||
var m = new WelcomeModel();
|
||||
|
||||
m.AutodetectOrganisation();
|
||||
|
||||
return View(m);
|
||||
}
|
||||
[HttpPost]
|
||||
public virtual ActionResult Welcome(WelcomeModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
DiscoApplication.OrganisationName = model.OrganisationName;
|
||||
|
||||
return RedirectToAction(MVC.InitialConfig.Database());
|
||||
}
|
||||
|
||||
return View(model);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Database
|
||||
public virtual ActionResult Database()
|
||||
{
|
||||
var cs = Disco.Data.Repository.DiscoDatabaseConnectionFactory.DiscoDataContextConnectionString;
|
||||
|
||||
DatabaseModel m;
|
||||
|
||||
if (cs == null)
|
||||
m = new DatabaseModel(); // Just use Defaults
|
||||
else
|
||||
m = DatabaseModel.FromConnectionString(cs); // Import from existing Connection String
|
||||
|
||||
return View(m);
|
||||
}
|
||||
[HttpPost]
|
||||
public virtual ActionResult Database(DatabaseModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
// Continue with Configuration
|
||||
var connectionString = model.ToConnectionString();
|
||||
|
||||
// Try Creating/Migrating
|
||||
connectionString.ConnectTimeout = 5;
|
||||
Disco.Data.Repository.DiscoDatabaseConnectionFactory.SetDiscoDataContextConnectionString(connectionString.ToString(), false);
|
||||
|
||||
try
|
||||
{
|
||||
Disco.Data.Migrations.DiscoDataMigrator.MigrateLatest(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Find inner exception
|
||||
SqlException sqlException = null;
|
||||
Exception innermostException = ex;
|
||||
do
|
||||
{
|
||||
if (sqlException == null)
|
||||
sqlException = innermostException as SqlException;
|
||||
if (innermostException.InnerException != null)
|
||||
innermostException = innermostException.InnerException;
|
||||
else
|
||||
break;
|
||||
} while (true);
|
||||
|
||||
if (sqlException != null)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, string.Format("Unable to create or migrate the database to the latest version: [{0}] {1}", sqlException.GetType().Name, sqlException.Message));
|
||||
}
|
||||
else
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, string.Format("Unable to create or migrate the database to the latest version: [{0}] {1}", innermostException.GetType().Name, innermostException.Message));
|
||||
}
|
||||
}
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
// Save Connection String
|
||||
//Disco.Data.Repository.DiscoDatabaseConnectionFactory.SetDiscoDataContextConnectionString(model.ToConnectionString().ToString(), true);
|
||||
// Write Organisation Name into DB
|
||||
using (DiscoDataContext db = new DiscoDataContext())
|
||||
{
|
||||
db.DiscoConfiguration.OrganisationName = DiscoApplication.OrganisationName;
|
||||
db.SaveChanges();
|
||||
}
|
||||
|
||||
return RedirectToAction(MVC.InitialConfig.FileStore());
|
||||
}
|
||||
}
|
||||
|
||||
return View(model);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FileStore
|
||||
public virtual ActionResult FileStore()
|
||||
{
|
||||
// Try and retrieve FileStore path from DB
|
||||
string FileStoreLocation = null;
|
||||
try
|
||||
{
|
||||
using (DiscoDataContext db = new DiscoDataContext())
|
||||
FileStoreLocation = db.ConfigurationItems.Where(ci => ci.Scope == "System" && ci.Key == "DataStoreLocation").Select(ci => ci.Value).FirstOrDefault();
|
||||
}
|
||||
catch (Exception) { } // Ignore All Errors
|
||||
|
||||
FileStoreModel m = new FileStoreModel();
|
||||
|
||||
// Test for valid Format
|
||||
if (!string.IsNullOrEmpty(FileStoreLocation))
|
||||
if (!Regex.IsMatch(FileStoreLocation, @"^[A-z]:(\\[^\\/:*?""<>|0x0-0x1F]+)+(\\)?$", RegexOptions.Singleline))
|
||||
FileStoreLocation = null;
|
||||
m.FileStoreLocation = FileStoreLocation;
|
||||
if (m.FileStoreLocation != null && m.FileStoreLocation.EndsWith(@"\"))
|
||||
m.FileStoreLocation = m.FileStoreLocation.TrimEnd('\\');
|
||||
|
||||
m.ExpandDirectoryModel();
|
||||
|
||||
return View(m);
|
||||
}
|
||||
[HttpPost]
|
||||
public virtual ActionResult FileStore(FileStoreModel m)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
// Ensure Path Exists
|
||||
using (DiscoDataContext db = new DiscoDataContext())
|
||||
{
|
||||
var configItem = db.ConfigurationItems.Where(ci => ci.Scope == "System" && ci.Key == "DataStoreLocation").FirstOrDefault();
|
||||
if (configItem == null)
|
||||
{ // Create Config
|
||||
db.ConfigurationItems.Add(new Disco.Models.Repository.ConfigurationItem()
|
||||
{
|
||||
Scope = "System",
|
||||
Key = "DataStoreLocation",
|
||||
Value = m.FileStoreLocation
|
||||
});
|
||||
}
|
||||
else
|
||||
{ // Update Config
|
||||
configItem.Value = m.FileStoreLocation;
|
||||
}
|
||||
db.SaveChanges();
|
||||
}
|
||||
|
||||
// Extract DataStore Template into FileStore
|
||||
var templatePath = Server.MapPath("~/ClientBin/DataStoreTemplate.zip");
|
||||
if (System.IO.File.Exists(templatePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (ZipArchive templateArchive = ZipFile.Open(templatePath, ZipArchiveMode.Read))
|
||||
{
|
||||
foreach (var entry in templateArchive.Entries)
|
||||
{
|
||||
var entryDestinationPath = Path.Combine(m.FileStoreLocation, entry.FullName);
|
||||
if (System.IO.File.Exists(entryDestinationPath))
|
||||
System.IO.File.Delete(entryDestinationPath);
|
||||
}
|
||||
templateArchive.ExtractToDirectory(m.FileStoreLocation);
|
||||
}
|
||||
return RedirectToAction(MVC.InitialConfig.Complete());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, string.Format("Unable to extract File Store template: [{0}] {1}", ex.GetType().Name, ex.Message));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return RedirectToAction(MVC.InitialConfig.Complete());
|
||||
}
|
||||
}
|
||||
|
||||
m.ExpandDirectoryModel();
|
||||
|
||||
return View(m);
|
||||
}
|
||||
public virtual ActionResult FileStoreBranch(string Path)
|
||||
{
|
||||
return Json(FileStoreModel.FileStoreDirectoryModel.FromPath(Path, true), JsonRequestBehavior.AllowGet);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Complete
|
||||
public virtual ActionResult Complete()
|
||||
{
|
||||
var m = new CompleteModel();
|
||||
|
||||
m.PerformTests();
|
||||
|
||||
return View(m);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Restart WebApp
|
||||
|
||||
public virtual ActionResult RestartWebApp()
|
||||
{
|
||||
RestartWebApp(1500);
|
||||
return View();
|
||||
}
|
||||
|
||||
|
||||
private static object _restartTimerLock = new object();
|
||||
private static Timer _restartTimer;
|
||||
private void RestartWebApp(int DelayMilliseconds)
|
||||
{
|
||||
lock (_restartTimerLock)
|
||||
{
|
||||
if (_restartTimer != null)
|
||||
{
|
||||
_restartTimer.Dispose();
|
||||
}
|
||||
|
||||
_restartTimer = new Timer((state) =>
|
||||
{
|
||||
HttpRuntime.UnloadAppDomain();
|
||||
//AppDomain.Unload(AppDomain.CurrentDomain);
|
||||
}, null, DelayMilliseconds, Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+1824
-1823
File diff suppressed because it is too large
Load Diff
@@ -1,35 +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("Disco ICT Management Website")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco ICT Management")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[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("2e74ba84-f784-4006-b99c-1967612fe48f")]
|
||||
|
||||
// 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.2.0131.2002")]
|
||||
[assembly: AssemblyFileVersion("1.2.0131.2002")]
|
||||
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("Disco ICT Management Website")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Disco ICT Management")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[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("2e74ba84-f784-4006-b99c-1967612fe48f")]
|
||||
|
||||
// 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.2.0207.1727")]
|
||||
[assembly: AssemblyFileVersion("1.2.0207.1727")]
|
||||
|
||||
+8989
-8895
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user