44 Commits

Author SHA1 Message Date
Gary Sharp 76318d8d00 Release v2.0.0918.1700 2014-09-18 19:11:21 +10:00
Gary Sharp f2ac35a7fa Bug Fix #75: Display errors creating device batch
Thanks Patrick Connell
2014-09-15 13:24:28 +10:00
Gary Sharp b1575fa321 Unified SignalR disconnected/error dialogs
Dialogs (with a refresh option) appear whenever the SignalR client
disconnects or encounters an error. Nonsensical error messages replaced.
Page refresh technique changed to allow for urls containing fragment
hashes.
2014-09-11 17:21:39 +10:00
Gary Sharp 4283b62803 Bug Fix: Job searching with username
When searching jobs, the default domain is now assumed if none is
provided when checking for job users.
2014-09-11 16:48:45 +10:00
Gary Sharp 7551b39b8e Generated Job Log to Markdown
Generated job logs are formatted with Markdown. Includes other minor css
changes.
2014-09-09 13:54:14 +10:00
Gary Sharp 3ae99f45bb Update device model type on Enrolment 2014-09-08 14:53:10 +10:00
Gary Sharp c846fa053a Dialog height reduced & remove js minify maps
Provide better support for lower resolution devices (buttons became
hidden in tall dialogs). Remove references to JavaScript minification
source maps which aren't deployed and caused confusion.
2014-09-08 14:51:51 +10:00
Gary Sharp 57c2e062fc Update: Plugin provided assemblies
Update assemblies which are available to all plugins.
2014-09-02 14:45:44 +10:00
Gary Sharp e940c24522 Bug Fix: Document template bulk examples 2014-09-02 14:45:02 +10:00
Gary Sharp 73d6160db6 Fix typo: AvilableDomainControllers
AvilableDomainControllers -> AvailableDomainControllers
Thanks Boris Pekez
2014-08-29 14:46:29 +10:00
Gary Sharp 13c5efe5d6 Added new UI Icons in FontAwesome 4.2.0 2014-08-28 15:32:57 +10:00
Gary Sharp bbe4cccc91 Update #74: Friendly disconnected messages
When the live connection to the server is interrupted some ui elements
are disabled. If the connection fails (due to errors or failed
reconnection) a dialog instructs the user to check their connection and
refresh the browser. Relates to Device, Job and User pages (logs and
attachments).
2014-08-28 14:59:39 +10:00
Gary Sharp 41e061df54 Update: Font Awesome 4.2.0 2014-08-28 13:53:35 +10:00
Gary Sharp 35a07344cc Bug Fix #71: Update managed groups on device enrol 2014-08-28 12:50:53 +10:00
Gary Sharp 4b6604df5b Feature #69 #72: Noticeboard themes and filtering 2014-08-26 16:27:37 +10:00
Gary Sharp 0de162fce3 Update: Update Job Identifiers 2014-08-19 10:53:59 +10:00
Gary Sharp f26474fa4d Device decommissioning 'returned' reason 2014-08-07 13:43:59 +10:00
Gary Sharp 8e2a17cfc5 Beta Release: v2.0.0731 2014-07-31 16:23:56 +10:00
Gary Sharp 3b0286fe11 Feature: Disco Device Registration
A method of 'Enrolling' devices which only updates the Disco database
(makes no changes to clients or AD). Can be easily called from a script
and used to add servers or any custom device.
2014-07-31 15:52:42 +10:00
Gary Sharp 12fc071786 Bug Fix: Reimage Job Enrol wouldn't join AD domain 2014-07-31 11:53:42 +10:00
Gary Sharp 1d931463a8 Update: Cannot close job until charge added
If a Non-Warranty job has 'Accounting Charge Required' it cannot be
normally closed until 'Accounting Charge Added' (even if 'Account Charge
Paid'). The job can still be forcibly closed (by those with permission
to forcibly close jobs).
The 'Awaiting Finance' and 'Accounting Charge' lists have been updated
to reflect this requirement.
2014-07-30 21:53:25 +10:00
Gary Sharp f01bc940f6 Bug Fix: Task progress incorrectly calculated 2014-07-29 14:17:58 +10:00
Gary Sharp ea80876286 Feature #40: Exceptionless error reporting 2014-07-28 20:55:53 +10:00
Gary Sharp 7062a40dfb Bug Fix #68: Undetected Pages dialog scale
Automatically scales the undetected page preview based on the browser
size.
2014-07-28 17:33:49 +10:00
Gary Sharp 2d8dcb6900 Bug Fix: Device/User search filtering and sorting 2014-07-28 16:51:17 +10:00
Gary Sharp 3358d9e320 Update: Disco ICT Online Services - Plugin Library
Migrate plugin library to https://services.discoict.com.au
2014-07-28 15:02:33 +10:00
Gary Sharp 1cc7e94646 Feature #67: Advanced document template events
OnGenerated and OnImportAttachment allow advanced users to enter
expressions which will be evaluated whenever these document
template/importing events are triggered. This enables greater
automation.
2014-07-26 20:02:59 +10:00
Gary Sharp c528a2be26 Bug Fix #66: Add offline device ui glitch
Only updates the text-box with the user id (instead of the full name),
to avoid users not correctly selecting a item from the auto-complete
list and then trying to submit the form.
2014-07-26 16:06:56 +10:00
Gary Sharp a43db01b96 Update: 3rd-party libraries updated, refactoring
Updated: SignalR 2.1.1, Moment.js 2.7, Reactive Extensions 2.2.5,
TinyMCE 4.1.2.
Customized TinyMCE skin and implemented FontAwesome icons.
T4MVC refactored.
2014-07-26 15:54:01 +10:00
Gary Sharp b78ce003a7 Bug Fix: Error when assigning devices
The noticeboard listens for updates to user assignments (including who
was previously assigned the device), but was requesting data which no
longer existed (as updates are delayed and buffered for up to 500ms).
2014-07-26 12:25:20 +10:00
Gary Sharp 81d024618a Bug Fix #65: Mac enrolment not updating model 2014-07-26 11:32:18 +10:00
Gary Sharp 4d8fec2ced Update: Job Publishing - Repair Jobs
Repair jobs can also submit attachments to repairers via Disco ICT
Online Services.
2014-07-24 21:27:24 +10:00
Gary Sharp 7cbed23a74 Feature: Disco ICT Online Services - Job Publishing
When warranty jobs are submitted (via plugins) users can choose to
include attachments. These attachments are submitted to Disco ICT Online
Services. A secure link is then provided to the plugin so the
attachments can be retrieved.
2014-07-24 20:58:48 +10:00
Gary Sharp 6700d092b3 Update: Disco Online Services Update Checking
Migrates Disco Update checking to new services at
https://services.discoict.com.au.
2014-07-23 19:14:08 +10:00
Gary Sharp 4b3905b4fc Bug Fix #62: DeviceDomainId may be null 2014-07-15 14:57:58 +10:00
Gary Sharp 09b1c93bf0 Export devices without a batch assigned #60 2014-07-14 13:30:25 +10:00
Gary Sharp 5c5e5a23a2 Bug Fix #61: Fix Decommission/Recommission Device
Checks to ensure a device domain id is valid before interacting with AD.
2014-07-14 13:04:42 +10:00
Gary Sharp 9bfa95e263 Bug Fix #58: Fail to assign MacSecureEnrol devices
Various code-paths *assumed* valid domain account ids as long as an id
existed (simple null-check). Correct checks for valid domain account ids
has been implemented.
2014-07-10 18:33:05 +10:00
Gary Sharp 2274e2201d Bug Fix #56: Noticeboard device profile filtering 2014-07-10 17:49:36 +10:00
Gary Sharp f4394fe2a0 Feature #2: Implement Repair Provider
Logging Repair for Non-Warranty jobs has been brought into line with
Logging Warranty. RepairProviderFeature implemented which allows plugins
to be used in submitting jobs to third-parties for repair.
2014-07-10 17:45:13 +10:00
Gary Sharp 5ba9fde10f Feature #2: Improve Warranty Logging
Warranty job UI changes to make consistent with plans for Repair Logging
2014-07-08 16:47:13 +10:00
Gary Sharp 67a624d5b5 Bug Fix #53: Plugin install fails when dll loaded 2014-07-07 15:19:46 +10:00
Gary Sharp 0b79140290 Bug Fix #54: Save proxy settings with ajax 2014-07-07 13:49:38 +10:00
Gary Sharp 5013fa27bd Bug Fix #55: Updating device batch when unassigned 2014-07-07 10:19:52 +10:00
398 changed files with 47201 additions and 29227 deletions
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<solution>
<add key="disableSourceControlIntegration" value="true" />
</solution>
</configuration>
BIN
View File
Binary file not shown.
-153
View File
@@ -1,153 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>
<!-- Enable the restore command to run before builds -->
<RestorePackages Condition=" '$(RestorePackages)' == '' ">false</RestorePackages>
<!-- Property that enables building a package from a project -->
<BuildPackage Condition=" '$(BuildPackage)' == '' ">false</BuildPackage>
<!-- Determines if package restore consent is required to restore packages -->
<RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">true</RequireRestoreConsent>
<!-- Download NuGet.exe if it does not already exist -->
<DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">false</DownloadNuGetExe>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageSources)' == '' ">
<!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
<!-- The official NuGet package source (https://nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
<!--
<PackageSource Include="https://nuget.org/api/v2/" />
<PackageSource Include="https://my-nuget-source/nuget/" />
-->
</ItemGroup>
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
<!-- Windows specific commands -->
<NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
<PackagesConfig>$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>
<PackagesDir>$([System.IO.Path]::Combine($(SolutionDir), "packages"))</PackagesDir>
</PropertyGroup>
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT'">
<!-- We need to launch nuget.exe with the mono command if we're not on windows -->
<NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>
<PackagesConfig>packages.config</PackagesConfig>
<PackagesDir>$(SolutionDir)packages</PackagesDir>
</PropertyGroup>
<PropertyGroup>
<!-- NuGet command -->
<NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\nuget.exe</NuGetExePath>
<PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>
<NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
<NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 $(NuGetExePath)</NuGetCommand>
<PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>
<RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch>
<!-- Commands -->
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(RequireConsentSwitch) -o "$(PackagesDir)"</RestoreCommand>
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols</BuildCommand>
<!-- We need to ensure packages are restored prior to assembly resolve -->
<ResolveReferencesDependsOn Condition="$(RestorePackages) == 'true'">
RestorePackages;
$(ResolveReferencesDependsOn);
</ResolveReferencesDependsOn>
<!-- Make the build depend on restore packages -->
<BuildDependsOn Condition="$(BuildPackage) == 'true'">
$(BuildDependsOn);
BuildPackage;
</BuildDependsOn>
</PropertyGroup>
<Target Name="CheckPrerequisites">
<!-- Raise an error if we're unable to locate nuget.exe -->
<Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
<SetEnvironmentVariable EnvKey="VisualStudioVersion" EnvValue="$(VisualStudioVersion)" Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' " />
<!--
Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
This effectively acts as a lock that makes sure that the download operation will only happen once and all
parallel builds will have to wait for it to complete.
-->
<MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT" />
</Target>
<Target Name="_DownloadNuGet">
<DownloadNuGet OutputFilename="$(NuGetExePath)" Condition=" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" />
</Target>
<Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
<Exec Command="$(RestoreCommand)"
Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />
<Exec Command="$(RestoreCommand)"
LogStandardErrorAsError="true"
Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
</Target>
<Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
<Exec Command="$(BuildCommand)"
Condition=" '$(OS)' != 'Windows_NT' " />
<Exec Command="$(BuildCommand)"
LogStandardErrorAsError="true"
Condition=" '$(OS)' == 'Windows_NT' " />
</Target>
<UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<OutputFilename ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Core" />
<Using Namespace="System" />
<Using Namespace="System.IO" />
<Using Namespace="System.Net" />
<Using Namespace="Microsoft.Build.Framework" />
<Using Namespace="Microsoft.Build.Utilities" />
<Code Type="Fragment" Language="cs">
<![CDATA[
try {
OutputFilename = Path.GetFullPath(OutputFilename);
Log.LogMessage("Downloading latest version of NuGet.exe...");
WebClient webClient = new WebClient();
webClient.DownloadFile("https://nuget.org/nuget.exe", OutputFilename);
return true;
}
catch (Exception ex) {
Log.LogErrorFromException(ex);
return false;
}
]]>
</Code>
</Task>
</UsingTask>
<UsingTask TaskName="SetEnvironmentVariable" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<EnvKey ParameterType="System.String" Required="true" />
<EnvValue ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Using Namespace="System" />
<Code Type="Fragment" Language="cs">
<![CDATA[
try {
Environment.SetEnvironmentVariable(EnvKey, EnvValue, System.EnvironmentVariableTarget.Process);
}
catch {
}
]]>
</Code>
</Task>
</UsingTask>
</Project>
-4
View File
@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.SignalR.Utils" version="2.1.0" />
</packages>
+11 -5
View File
@@ -1,9 +1,10 @@
using System;
using Disco.BI.Extensions;
using Exceptionless;
using iTextSharp.text.pdf;
using System;
using System.Drawing;
using System.IO;
using System.Linq;
using Disco.BI.Extensions;
using iTextSharp.text.pdf;
namespace Disco.BI.AttachmentBI
{
@@ -33,10 +34,11 @@ namespace Disco.BI.AttachmentBI
}
}
}
catch (Exception)
catch (Exception ex)
{
ex.ToExceptionless().Submit();
// Ignore Thumbnail Generation exceptions for images
//throw;
}
}
@@ -63,6 +65,10 @@ namespace Disco.BI.AttachmentBI
}
}
}
catch (Exception ex)
{
ex.ToExceptionless().Submit();
}
finally
{
if (pdfReader != null)
+6 -1
View File
@@ -28,7 +28,7 @@ namespace Disco.BI
{
// Check again now that lock is enforced
deviceModel = DeviceModelsSet.FirstOrDefault(dm => dm.Manufacturer == Manufacturer && dm.Model == Model);
if (deviceModel == null)
{
// Create the Device Model in a different DataContext so we don't have to commit unrelated changes
@@ -52,6 +52,11 @@ namespace Disco.BI
}
}
}
else
{
if (deviceModel.ModelType != ModelType)
deviceModel.ModelType = ModelType;
}
return new Tuple<DeviceModel,bool>(deviceModel, false);
}
+229 -47
View File
@@ -5,9 +5,9 @@ using Disco.Models.Repository;
using Disco.Services.Authorization;
using Disco.Services.Interop.ActiveDirectory;
using Disco.Services.Users;
using Exceptionless;
using System;
using System.Collections.Generic;
using System.DirectoryServices.ActiveDirectory;
using System.Linq;
using System.Text.RegularExpressions;
using Tamir.SharpSsh;
@@ -20,7 +20,8 @@ namespace Disco.BI.DeviceBI
{
Normal,
Mac = 5,
MacSecure
MacSecure,
Register = 30
}
private static Regex SshPromptRegEx = new Regex("[\\$,\\#]", RegexOptions.Multiline);
@@ -118,6 +119,7 @@ namespace Disco.BI.DeviceBI
}
catch (System.Exception ex)
{
ex.ToExceptionless().Submit();
EnrolmentLog.LogSessionError(sessionId, ex);
throw ex;
}
@@ -265,21 +267,16 @@ namespace Disco.BI.DeviceBI
{
EnrolmentLog.LogSessionProgress(sessionId, 50, "Existing Device, Updating Disco Instance");
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
if (!RepoDevice.DeviceModelId.HasValue || RepoDevice.DeviceModelId.Value == 1)
{
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
DeviceModel deviceModel = deviceModelResult.Item1;
if (deviceModelResult.Item2)
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
else
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id);
RepoDevice.DeviceModel = deviceModel;
}
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
DeviceModel deviceModel = deviceModelResult.Item1;
if (deviceModelResult.Item2)
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
else
{
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, RepoDevice.DeviceModelId);
}
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id);
RepoDevice.DeviceModel = deviceModel;
RepoDevice.DeviceDomainId = Request.DeviceComputerName;
if (!RepoDevice.EnrolledDate.HasValue)
{
@@ -311,6 +308,7 @@ namespace Disco.BI.DeviceBI
}
catch (System.Exception ex2)
{
ex2.ToExceptionless().Submit();
EnrolmentLog.LogSessionError(sessionId, ex2);
throw ex2;
}
@@ -365,7 +363,7 @@ namespace Disco.BI.DeviceBI
if (domain == null)
domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName);
if (!authenticatedToken.User.UserId.Equals(string.Format(@"{0}\{1}$", domain.NetBiosName, Request.DeviceComputerName), System.StringComparison.OrdinalIgnoreCase))
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.UserId));
}
@@ -470,49 +468,46 @@ namespace Disco.BI.DeviceBI
if (adMachineAccount == null)
{
if (isAuthenticated || RepoDevice.AllowUnauthenticatedEnrol)
if (RepoDevice.DeviceProfile.ProvisionADAccount)
{
if (RepoDevice.DeviceProfile.ProvisionADAccount)
{
EnrolmentLog.LogSessionProgress(sessionId, 50, "Provisioning an Active Directory Computer Account");
EnrolmentLog.LogSessionProgress(sessionId, 50, "Provisioning an Active Directory Computer Account");
if (string.IsNullOrWhiteSpace(RepoDevice.DeviceProfile.OrganisationalUnit))
throw new InvalidOperationException("No Organisational Unit has been set in the device profile");
if (domain == null)
domain = ActiveDirectory.Context.GetDomainFromDistinguishedName(RepoDevice.DeviceProfile.OrganisationalUnit);
if (string.IsNullOrWhiteSpace(RepoDevice.DeviceProfile.OrganisationalUnit))
throw new InvalidOperationException("No Organisational Unit has been set in the device profile");
if (domain == null)
domain = ActiveDirectory.Context.GetDomainFromDistinguishedName(RepoDevice.DeviceProfile.OrganisationalUnit);
if (string.IsNullOrEmpty(RepoDevice.DeviceDomainId) || RepoDevice.DeviceProfile.EnforceComputerNameConvention)
RepoDevice.DeviceDomainId = RepoDevice.ComputerNameRender(Database, domain);
if (string.IsNullOrEmpty(RepoDevice.DeviceDomainId) || RepoDevice.DeviceProfile.EnforceComputerNameConvention)
RepoDevice.DeviceDomainId = RepoDevice.ComputerNameRender(Database, domain);
string offlineProvisionDiagnosicInfo;
EnrolmentLog.LogSessionTaskProvisioningADAccount(sessionId, RepoDevice.SerialNumber, RepoDevice.DeviceDomainId);
adMachineAccount = domainController.Value.RetrieveADMachineAccount(RepoDevice.DeviceDomainId);
string offlineProvisionDiagnosicInfo;
EnrolmentLog.LogSessionTaskProvisioningADAccount(sessionId, RepoDevice.SerialNumber, RepoDevice.DeviceDomainId);
adMachineAccount = domainController.Value.RetrieveADMachineAccount(RepoDevice.DeviceDomainId);
response.OfflineDomainJoin = domainController.Value.OfflineDomainJoinProvision(RepoDevice.DeviceDomainId, RepoDevice.DeviceProfile.OrganisationalUnit, ref adMachineAccount, out offlineProvisionDiagnosicInfo);
response.OfflineDomainJoin = domainController.Value.OfflineDomainJoinProvision(RepoDevice.DeviceDomainId, RepoDevice.DeviceProfile.OrganisationalUnit, ref adMachineAccount, out offlineProvisionDiagnosicInfo);
EnrolmentLog.LogSessionDiagnosticInformation(sessionId, offlineProvisionDiagnosicInfo);
EnrolmentLog.LogSessionDiagnosticInformation(sessionId, offlineProvisionDiagnosicInfo);
response.RequireReboot = true;
}
if (adMachineAccount != null)
{
response.DeviceComputerName = adMachineAccount.Name;
response.DeviceDomainName = adMachineAccount.Domain.NetBiosName;
}
else
{
string accountUsername;
ADDomain accountDomain;
ActiveDirectory.ParseDomainAccountId(RepoDevice.DeviceDomainId, out accountUsername, out accountDomain);
response.RequireReboot = true;
}
if (adMachineAccount != null)
{
response.DeviceComputerName = adMachineAccount.Name;
response.DeviceDomainName = adMachineAccount.Domain.NetBiosName;
}
else if (ActiveDirectory.IsValidDomainAccountId(RepoDevice.DeviceDomainId))
{
string accountUsername;
ADDomain accountDomain;
ActiveDirectory.ParseDomainAccountId(RepoDevice.DeviceDomainId, out accountUsername, out accountDomain);
response.DeviceDomainName = accountDomain == null ? null : accountDomain.NetBiosName;
response.DeviceComputerName = accountUsername;
}
response.DeviceDomainName = accountDomain == null ? null : accountDomain.NetBiosName;
response.DeviceComputerName = accountUsername;
}
else
{
response.DeviceComputerName = Request.DeviceComputerName;
response.DeviceDomainName = Request.DeviceDNSDomainName;
response.DeviceComputerName = Request.DeviceComputerName;
}
}
else
@@ -655,6 +650,193 @@ namespace Disco.BI.DeviceBI
}
catch (System.Exception ex2)
{
ex2.ToExceptionless().Submit();
EnrolmentLog.LogSessionError(sessionId, ex2);
throw ex2;
}
finally
{
EnrolmentLog.LogSessionFinished(sessionId);
}
return response;
}
public static RegisterResponse Register(DiscoDataContext Database, string Username, Register Request)
{
RegisterResponse response = new RegisterResponse();
ADMachineAccount adMachineAccount = null;
AuthorizationToken authenticatedToken = null;
ADDomain domain = null;
Lazy<ADDomainController> domainController = new Lazy<ADDomainController>(() =>
{
if (domain == null)
throw new InvalidOperationException("The [domain] variable must be initialized first");
return domain.GetAvailableDomainController(RequireWritable: true);
});
string sessionId = System.Guid.NewGuid().ToString("B");
response.SessionId = sessionId;
EnrolmentLog.LogSessionStarting(sessionId, Request.DeviceSerialNumber, EnrolmentTypes.Register);
EnrolmentLog.LogSessionDeviceInfo(sessionId, Request);
try
{
EnrolmentLog.LogSessionProgress(sessionId, 10, "Loading User Data");
if (!string.IsNullOrWhiteSpace(Username))
{
authenticatedToken = UserService.GetAuthorization(Username, Database);
}
EnrolmentLog.LogSessionProgress(sessionId, 13, "Loading Device Data");
Device RepoDevice = Database.Devices.Include("AssignedUser").Include("DeviceModel").Include("DeviceProfile").Where(d => d.SerialNumber == Request.DeviceSerialNumber).FirstOrDefault();
EnrolmentLog.LogSessionProgress(sessionId, 15, "Discovering User/Device Disco Permissions");
if (authenticatedToken != null)
{
if (!authenticatedToken.Has(Claims.Device.Actions.EnrolDevices))
{
if (!authenticatedToken.Has(Claims.ComputerAccount))
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.UserId));
if (domain == null)
domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName);
if (!authenticatedToken.User.UserId.Equals(string.Format(@"{0}\{1}$", domain.NetBiosName, Request.DeviceComputerName), System.StringComparison.OrdinalIgnoreCase))
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.UserId));
}
}
else
{
if (RepoDevice == null)
{
throw new EnrolSafeException(string.Format("Unknown Device Serial Number (SN: '{0}')", Request.DeviceSerialNumber));
}
if (!RepoDevice.AllowUnauthenticatedEnrol)
{
if (RepoDevice.DeviceProfile.AllowUntrustedReimageJobEnrolment)
{
if (Database.Jobs.Count(j => j.DeviceSerialNumber == RepoDevice.SerialNumber && j.JobTypeId == JobType.JobTypeIds.SImg && !j.ClosedDate.HasValue) == 0)
{
throw new EnrolSafeException(string.Format("Device has no open 'Software - Reimage' job (SN: '{0}')", Request.DeviceSerialNumber));
}
}
else
{
throw new EnrolSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.DeviceSerialNumber));
}
}
}
if (Request.DeviceIsPartOfDomain && !string.IsNullOrWhiteSpace(Request.DeviceComputerName))
{
EnrolmentLog.LogSessionProgress(sessionId, 20, "Loading Active Directory Computer Account");
System.Guid? uuidGuid = null;
if (!string.IsNullOrEmpty(Request.DeviceUUID))
uuidGuid = ADMachineAccount.NetbootGUIDFromUUID(Request.DeviceUUID);
if (domain == null)
domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName);
var requestDeviceId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.DeviceComputerName);
adMachineAccount = domainController.Value.RetrieveADMachineAccount(requestDeviceId, uuidGuid);
}
if (RepoDevice == null)
{
EnrolmentLog.LogSessionProgress(sessionId, 30, "New Device, Creating Disco Instance");
EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.DeviceSerialNumber);
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
DeviceModel deviceModel = deviceModelResult.Item1;
if (deviceModelResult.Item2)
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
else
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id);
if (domain == null)
domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName);
RepoDevice = new Device
{
SerialNumber = Request.DeviceSerialNumber,
DeviceDomainId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.DeviceComputerName),
DeviceProfile = deviceProfile,
DeviceModel = deviceModel,
AllowUnauthenticatedEnrol = false,
CreatedDate = DateTime.Now,
EnrolledDate = DateTime.Now,
LastEnrolDate = DateTime.Now,
DeviceDetails = new List<DeviceDetail>()
};
Database.Devices.Add(RepoDevice);
}
else
{
EnrolmentLog.LogSessionProgress(sessionId, 30, "Existing Device, Updating Disco Instance");
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
DeviceModel deviceModel = deviceModelResult.Item1;
if (deviceModelResult.Item2)
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
else
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id);
RepoDevice.DeviceModel = deviceModel;
if (!RepoDevice.EnrolledDate.HasValue)
RepoDevice.EnrolledDate = DateTime.Now;
RepoDevice.LastEnrolDate = DateTime.Now;
}
if (adMachineAccount == null)
{
if (adMachineAccount != null)
{
response.DeviceComputerName = adMachineAccount.Name;
response.DeviceDomainName = adMachineAccount.Domain.NetBiosName;
}
else if (ActiveDirectory.IsValidDomainAccountId(RepoDevice.DeviceDomainId))
{
string accountUsername;
ADDomain accountDomain;
ActiveDirectory.ParseDomainAccountId(RepoDevice.DeviceDomainId, out accountUsername, out accountDomain);
response.DeviceDomainName = accountDomain == null ? null : accountDomain.NetBiosName;
response.DeviceComputerName = accountUsername;
}
else
{
response.DeviceDomainName = Request.DeviceDNSDomainName;
response.DeviceComputerName = Request.DeviceComputerName;
}
}
else
{
RepoDevice.DeviceDomainId = adMachineAccount.Id.Trim('$');
response.DeviceComputerName = adMachineAccount.Name;
response.DeviceDomainName = adMachineAccount.Domain.NetBiosName;
}
// Reset 'AllowUnauthenticatedEnrol'
if (RepoDevice.AllowUnauthenticatedEnrol)
RepoDevice.AllowUnauthenticatedEnrol = false;
EnrolmentLog.LogSessionProgress(sessionId, 100, "Completed Successfully");
}
catch (EnrolSafeException ex)
{
EnrolmentLog.LogSessionError(sessionId, ex);
return new RegisterResponse
{
SessionId = sessionId,
ErrorMessage = ex.Message
};
}
catch (System.Exception ex2)
{
ex2.ToExceptionless().Submit();
EnrolmentLog.LogSessionError(sessionId, ex2);
throw ex2;
}
+4
View File
@@ -108,6 +108,10 @@ namespace Disco.BI.DeviceBI
{
EnrolmentLog.LogSessionDeviceInfo(SessionId, Request.DeviceSerialNumber, Request.DeviceUUID, Request.DeviceComputerName, Request.DeviceLanMacAddress, Request.DeviceWlanMacAddress, Request.DeviceManufacturer, Request.DeviceModel, Request.DeviceModelType);
}
public static void LogSessionDeviceInfo(string SessionId, Models.ClientServices.Register Request)
{
EnrolmentLog.LogSessionDeviceInfo(SessionId, Request.DeviceSerialNumber, Request.DeviceUUID, Request.DeviceComputerName, null, null, Request.DeviceManufacturer, Request.DeviceModel, Request.DeviceModelType);
}
public static void LogSessionProgress(string SessionId, int Progress, string Status)
{
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionProgress, new object[]
@@ -0,0 +1,478 @@
using Disco.Models.Repository;
using Disco.Services.Logging;
using Disco.Services.Logging.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace Disco.BI.DocumentTemplateBI
{
public class DocumentsLog : LogBase
{
public enum EventTypeIds
{
ImportStarting = 10,
ImportProgress,
ImportFinished,
ImportWarning = 15,
ImportError,
ImportAttachmentExpressionEvaluated = 50,
ImportPageStarting = 100,
ImportPageImageUpdate = 104,
ImportPageProgress,
ImportPageDetected = 110,
ImportPageUndetected = 115,
ImportPageError = 120,
ImportPageUndetectedStored = 150,
DocumentGenerated = 500,
DocumentGeneratedWithExpression
}
private const int _ModuleId = 40;
public static DocumentsLog Current
{
get
{
return (DocumentsLog)LogContext.LogModules[_ModuleId];
}
}
public override string ModuleDescription
{
get
{
return "Documents";
}
}
public override int ModuleId
{
get
{
return _ModuleId;
}
}
public override string ModuleName
{
get
{
return "Documents";
}
}
private static void Log(DocumentsLog.EventTypeIds EventTypeId, params object[] Args)
{
DocumentsLog.Current.Log((int)EventTypeId, Args);
}
public static void LogImportStarting(string SessionId, string DocumentName)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportStarting, new object[]
{
SessionId,
DocumentName
});
}
public static void LogImportProgress(string SessionId, int? Progress, string Status)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportProgress, new object[]
{
SessionId,
Progress,
Status
});
}
public static void LogImportFinished(string SessionId)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportFinished, new object[]
{
SessionId
});
}
public static void LogImportWarning(string SessionId, string Message)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportWarning, new object[]
{
SessionId,
Message
});
}
public static void LogImportError(string SessionId, string Message)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportError, new object[]
{
SessionId,
Message
});
}
public static void LogImportAttachmentExpressionEvaluated(DocumentTemplate template, Device device, DeviceAttachment attachment, string Result)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportAttachmentExpressionEvaluated, new object[]
{
template.Id,
device.SerialNumber,
attachment.Id,
Result
});
}
public static void LogImportAttachmentExpressionEvaluated(DocumentTemplate template, Job job, JobAttachment attachment, string Result)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportAttachmentExpressionEvaluated, new object[]
{
template.Id,
job.Id,
attachment.Id,
Result
});
}
public static void LogImportAttachmentExpressionEvaluated(DocumentTemplate template, User user, UserAttachment attachment, string Result)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportAttachmentExpressionEvaluated, new object[]
{
template.Id,
user.UserId,
attachment.Id,
Result
});
}
public static void LogImportAttachmentExpressionEvaluated(DocumentTemplate Template, object Data, object Attachment, string Result)
{
if (Data is Job)
LogImportAttachmentExpressionEvaluated(Template, (Job)Data, (JobAttachment)Attachment, Result);
else if (Data is User)
LogImportAttachmentExpressionEvaluated(Template, (User)Data, (UserAttachment)Attachment, Result);
else if (Data is Device)
LogImportAttachmentExpressionEvaluated(Template, (Device)Data, (DeviceAttachment)Attachment, Result);
else
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportAttachmentExpressionEvaluated, new object[]
{
Template.Id,
Data.ToString(),
Attachment.ToString(),
Result
});
}
public static void LogImportPageStarting(string SessionId, int PageNumber)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportPageStarting, new object[]
{
SessionId,
PageNumber
});
}
public static void LogImportPageImageUpdate(string SessionId, int PageNumber)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportPageImageUpdate, new object[]
{
SessionId,
PageNumber
});
}
public static void LogImportPageProgress(string SessionId, int PageNumber, int? Progress, string Status)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportPageProgress, new object[]
{
SessionId,
PageNumber,
Progress,
Status
});
}
public static void LogImportPageDetected(string SessionId, int PageNumber, string DocumentTypeId, string DocumentTypeName, string TargetType, string AssignedId, string AssignedName)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportPageDetected, new object[]
{
SessionId,
PageNumber,
DocumentTypeId,
DocumentTypeName,
TargetType,
AssignedId,
AssignedName
});
}
public static void LogImportPageUndetected(string SessionId, int PageNumber)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportPageUndetected, new object[]
{
SessionId,
PageNumber
});
}
public static void LogImportPageError(string SessionId, int PageNumber, string Message)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportPageError, new object[]
{
SessionId,
PageNumber,
Message
});
}
public static void LogImportPageUndetectedStored(string SessionId, int PageNumber)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportPageUndetectedStored, new object[]
{
SessionId,
PageNumber
});
}
public static void LogDocumentGenerated(DocumentTemplate Template, Device Device, User Author, string ExpressionResult)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.DocumentGeneratedWithExpression, new object[]
{
Template.Id,
Device.SerialNumber,
Author.UserId,
ExpressionResult
});
}
public static void LogDocumentGenerated(DocumentTemplate Template, Job Job, User Author, string ExpressionResult)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.DocumentGeneratedWithExpression, new object[]
{
Template.Id,
Job.Id,
Author.UserId,
ExpressionResult
});
}
public static void LogDocumentGenerated(DocumentTemplate Template, User User, User Author, string ExpressionResult)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.DocumentGeneratedWithExpression, new object[]
{
Template.Id,
User.UserId,
Author.UserId,
ExpressionResult
});
}
public static void LogDocumentGenerated(DocumentTemplate Template, object Data, User Author, string ExpressionResult)
{
if (Data is Job)
LogDocumentGenerated(Template, (Job)Data, Author, ExpressionResult);
else if (Data is User)
LogDocumentGenerated(Template, (User)Data, Author, ExpressionResult);
else if (Data is Device)
LogDocumentGenerated(Template, (Device)Data, Author, ExpressionResult);
else
DocumentsLog.Log(DocumentsLog.EventTypeIds.DocumentGeneratedWithExpression, new object[]
{
Template.Id,
"UNKNOWN",
Author.UserId,
ExpressionResult
});
}
public static void LogDocumentGenerated(DocumentTemplate Template, Device Device, User Author)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.DocumentGenerated, new object[]
{
Template.Id,
Device.SerialNumber,
Author.UserId
});
}
public static void LogDocumentGenerated(DocumentTemplate Template, Job Job, User Author)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.DocumentGenerated, new object[]
{
Template.Id,
Job.Id,
Author.UserId
});
}
public static void LogDocumentGenerated(DocumentTemplate Template, User User, User Author)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.DocumentGenerated, new object[]
{
Template.Id,
User.UserId,
Author.UserId
});
}
public static void LogDocumentGenerated(DocumentTemplate Template, object Data, User Author)
{
if (Data is Job)
LogDocumentGenerated(Template, (Job)Data, Author);
else if (Data is User)
LogDocumentGenerated(Template, (User)Data, Author);
else if (Data is Device)
LogDocumentGenerated(Template, (Device)Data, Author);
else
DocumentsLog.Log(DocumentsLog.EventTypeIds.DocumentGenerated, new object[]
{
Template.Id,
"UNKNOWN",
Author.UserId
});
}
protected override System.Collections.Generic.List<LogEventType> LoadEventTypes()
{
return new System.Collections.Generic.List<LogEventType>
{
new LogEventType
{
Id = (int)EventTypeIds.ImportStarting,
ModuleId = _ModuleId,
Name = "Import Starting",
Format = "Starting import of document: {1} (SessionId: {0})",
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.ImportProgress,
ModuleId = _ModuleId,
Name = "Import Progress",
Format = "Processing: {1}% Complete; Status: {2}",
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = false,
UseDisplay = false
},
new LogEventType
{
Id = (int)EventTypeIds.ImportFinished,
ModuleId = _ModuleId,
Name = "Import Finished",
Format = "Import of document complete (SessionId: {0})",
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.ImportWarning,
ModuleId = _ModuleId,
Name = "Import Warning",
Format = "Import Warning: {1} (SessionId: {0})",
Severity = (int)LogEventType.Severities.Warning,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.ImportError,
ModuleId = _ModuleId,
Name = "Import Error",
Format = "Import Error: {1} (SessionId: {0})",
Severity = (int)LogEventType.Severities.Error,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.ImportAttachmentExpressionEvaluated,
ModuleId = _ModuleId,
Name = "Import Attachment Expression Evaluated",
Format = "The import attachment expression for '{0}' was evaluated for '{1}' (attachment id: {2}) with the result: {3}",
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.ImportPageStarting,
ModuleId = _ModuleId,
Name = "Import Page Starting",
Format = "Starting import of page: {1} (SessionId: {0})",
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.ImportPageImageUpdate,
ModuleId = _ModuleId,
Name = "Import Page Image Update",
Format = null,
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = false,
UseDisplay = false
},
new LogEventType
{
Id = (int)EventTypeIds.ImportPageProgress,
ModuleId = _ModuleId,
Name = "Import Page Progress",
Format = "Processing: Page {1}; {2}% Complete; Status: {3}",
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = false,
UseDisplay = false
},
new LogEventType
{
Id = (int)EventTypeIds.ImportPageDetected,
ModuleId = _ModuleId,
Name = "Import Page Assigned",
Format = "Page {1} of type '{3}' assigned to {4}: '{6}'",
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.ImportPageUndetected,
ModuleId = _ModuleId,
Name = "Import Page Undetected",
Format = "Page {1} not detected",
Severity = (int)LogEventType.Severities.Warning,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.ImportPageError,
ModuleId = _ModuleId,
Name = "Import Page Error",
Format = "Page {1}, Import Error: {2}",
Severity = (int)LogEventType.Severities.Error,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.ImportPageUndetectedStored,
ModuleId = _ModuleId,
Name = "Import Page Undetected Stored",
Format = null,
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = false,
UseDisplay = false
},
new LogEventType
{
Id = (int)EventTypeIds.DocumentGenerated,
ModuleId = _ModuleId,
Name = "Document Generated",
Format = "A '{0}' document was generated for '{1}' by '{2}'",
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.DocumentGeneratedWithExpression,
ModuleId = _ModuleId,
Name = "Document Generated with Expression",
Format = "A '{0}' document was generated for '{1}' by '{2}'. The expression returned: {3}",
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = true,
UseDisplay = true
}
};
}
}
}
@@ -1,9 +1,10 @@
using Disco.Data.Repository;
using Exceptionless;
using Quartz;
using Quartz.Impl.Triggers;
using System;
using System.IO;
using System.Web.Caching;
using Disco.Data.Repository;
using Quartz;
using Quartz.Impl.Triggers;
namespace Disco.BI.DocumentTemplateBI.Importer
{
@@ -28,12 +29,12 @@ namespace Disco.BI.DocumentTemplateBI.Importer
if (!string.IsNullOrEmpty(friendlyFilename))
friendlyFilename = System.IO.Path.GetFileName(friendlyFilename);
DocumentImporterLog.LogImportStarting(sessionId, friendlyFilename);
DocumentsLog.LogImportStarting(sessionId, friendlyFilename);
if (!File.Exists(filename))
{
DocumentImporterLog.LogImportWarning(sessionId, string.Format("File not found: {0}", filename));
DocumentImporterLog.LogImportFinished(sessionId);
DocumentsLog.LogImportWarning(sessionId, string.Format("File not found: {0}", filename));
DocumentsLog.LogImportFinished(sessionId);
context.Scheduler.DeleteJob(context.JobDetail.Key);
return;
}
@@ -69,8 +70,9 @@ namespace Disco.BI.DocumentTemplateBI.Importer
}
File.Move(filename, filenameError);
}
catch
catch (Exception ex)
{
ex.ToExceptionless().Submit();
// Ignore Errors
}
}
@@ -79,7 +81,7 @@ namespace Disco.BI.DocumentTemplateBI.Importer
else
{
// To Many Errors
DocumentImporterLog.LogImportError(sessionId, string.Format("To many errors occurred trying to import '{1}' (SessionId: {0})", sessionId, friendlyFilename));
DocumentsLog.LogImportError(sessionId, string.Format("To many errors occurred trying to import '{1}' (SessionId: {0})", sessionId, friendlyFilename));
// Move to Errors Folder
if (File.Exists(filename))
{
@@ -101,14 +103,15 @@ namespace Disco.BI.DocumentTemplateBI.Importer
}
}
}
DocumentImporterLog.LogImportFinished(sessionId);
DocumentsLog.LogImportFinished(sessionId);
// All Done
context.Scheduler.DeleteJob(context.JobDetail.Key);
}
catch (Exception ex)
{
DocumentImporterLog.LogImportWarning(sessionId, string.Format("{0}; Will try again in 10 Seconds", ex.Message));
ex.ToExceptionless().Submit();
DocumentsLog.LogImportWarning(sessionId, string.Format("{0}; Will try again in 10 Seconds", ex.Message));
// Reschedule Job for 10 seconds
SimpleTriggerImpl trig = new SimpleTriggerImpl(Guid.NewGuid().ToString(), new DateTimeOffset(DateTime.Now.AddSeconds(10)));
context.Scheduler.RescheduleJob(context.Trigger.Key, trig);
@@ -1,304 +0,0 @@
using Disco.Services.Logging;
using Disco.Services.Logging.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace Disco.BI.DocumentTemplateBI.Importer
{
public class DocumentImporterLog : LogBase
{
public enum EventTypeIds
{
ImportStarting = 10,
ImportProgress,
ImportFinished,
ImportWarning = 15,
ImportError,
ImportPageStarting = 100,
ImportPageImageUpdate = 104,
ImportPageProgress,
ImportPageDetected = 110,
ImportPageUndetected = 115,
ImportPageError = 120,
ImportPageUndetectedStored = 150
}
private const int _ModuleId = 40;
public static DocumentImporterLog Current
{
get
{
return (DocumentImporterLog)LogContext.LogModules[_ModuleId];
}
}
public override string ModuleDescription
{
get
{
return "Document Importer";
}
}
public override int ModuleId
{
get
{
return _ModuleId;
}
}
public override string ModuleName
{
get
{
return "DocumentImporter";
}
}
private static void Log(DocumentImporterLog.EventTypeIds EventTypeId, params object[] Args)
{
DocumentImporterLog.Current.Log((int)EventTypeId, Args);
}
public static void LogImportStarting(string SessionId, string DocumentName)
{
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportStarting, new object[]
{
SessionId,
DocumentName
});
}
public static void LogImportProgress(string SessionId, int? Progress, string Status)
{
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportProgress, new object[]
{
SessionId,
Progress,
Status
});
}
public static void LogImportFinished(string SessionId)
{
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportFinished, new object[]
{
SessionId
});
}
public static void LogImportWarning(string SessionId, string Message)
{
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportWarning, new object[]
{
SessionId,
Message
});
}
public static void LogImportError(string SessionId, string Message)
{
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportError, new object[]
{
SessionId,
Message
});
}
public static void LogImportPageStarting(string SessionId, int PageNumber)
{
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportPageStarting, new object[]
{
SessionId,
PageNumber
});
}
public static void LogImportPageImageUpdate(string SessionId, int PageNumber)
{
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportPageImageUpdate, new object[]
{
SessionId,
PageNumber
});
}
public static void LogImportPageProgress(string SessionId, int PageNumber, int? Progress, string Status)
{
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportPageProgress, new object[]
{
SessionId,
PageNumber,
Progress,
Status
});
}
public static void LogImportPageDetected(string SessionId, int PageNumber, string DocumentTypeId, string DocumentTypeName, string TargetType, string AssignedId, string AssignedName)
{
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportPageDetected, new object[]
{
SessionId,
PageNumber,
DocumentTypeId,
DocumentTypeName,
TargetType,
AssignedId,
AssignedName
});
}
public static void LogImportPageUndetected(string SessionId, int PageNumber)
{
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportPageUndetected, new object[]
{
SessionId,
PageNumber
});
}
public static void LogImportPageError(string SessionId, int PageNumber, string Message)
{
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportPageError, new object[]
{
SessionId,
PageNumber,
Message
});
}
public static void LogImportPageUndetectedStored(string SessionId, int PageNumber)
{
DocumentImporterLog.Log(DocumentImporterLog.EventTypeIds.ImportPageUndetectedStored, new object[]
{
SessionId,
PageNumber
});
}
protected override System.Collections.Generic.List<LogEventType> LoadEventTypes()
{
return new System.Collections.Generic.List<LogEventType>
{
new LogEventType
{
Id = 10,
ModuleId = 40,
Name = "Import Starting",
Format = "Starting import of document: {1} (SessionId: {0})",
Severity = 0,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = 11,
ModuleId = 40,
Name = "Import Progress",
Format = "Processing: {1}% Complete; Status: {2}",
Severity = 0,
UseLive = true,
UsePersist = false,
UseDisplay = false
},
new LogEventType
{
Id = 12,
ModuleId = 40,
Name = "Import Finished",
Format = "Import of document complete (SessionId: {0})",
Severity = 0,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = 15,
ModuleId = 40,
Name = "Import Warning",
Format = "Import Warning: {1} (SessionId: {0})",
Severity = 1,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = 16,
ModuleId = 40,
Name = "Import Error",
Format = "Import Error: {1} (SessionId: {0})",
Severity = 2,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = 100,
ModuleId = 40,
Name = "Import Page Starting",
Format = "Starting import of page: {1} (SessionId: {0})",
Severity = 0,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = 104,
ModuleId = 40,
Name = "Import Page Image Update",
Format = null,
Severity = 0,
UseLive = true,
UsePersist = false,
UseDisplay = false
},
new LogEventType
{
Id = 105,
ModuleId = 40,
Name = "Import Page Progress",
Format = "Processing: Page {1}; {2}% Complete; Status: {3}",
Severity = 0,
UseLive = true,
UsePersist = false,
UseDisplay = false
},
new LogEventType
{
Id = 110,
ModuleId = 40,
Name = "Import Page Assigned",
Format = "Page {1} of type '{3}' assigned to {4}: '{6}'",
Severity = 0,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = 115,
ModuleId = 40,
Name = "Import Page Undetected",
Format = "Page {1} not detected",
Severity = 1,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = 120,
ModuleId = 40,
Name = "Import Page Error",
Format = "Page {1}, Import Error: {2}",
Severity = 2,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = 150,
ModuleId = 40,
Name = "Import Page Undetected Stored",
Format = null,
Severity = 0,
UseLive = true,
UsePersist = false,
UseDisplay = false
}
};
}
}
}
+26 -14
View File
@@ -1,12 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Disco.Models.Repository;
using Disco.BI.DocumentTemplateBI;
using Disco.Data.Repository;
using System.IO;
using Disco.BI.DocumentTemplateBI;
using Disco.Models.Repository;
using Disco.Services.Logging;
using Disco.Services.Users;
using Exceptionless;
using System;
using System.IO;
namespace Disco.BI.Extensions
{
@@ -15,11 +14,11 @@ namespace Disco.BI.Extensions
public static bool ImportPdfAttachment(this DocumentUniqueIdentifier UniqueIdentifier, DiscoDataContext Database, System.IO.Stream PdfContent, byte[] PdfThumbnail)
{
UniqueIdentifier.LoadComponents(Database);
DocumentTemplate documentTemplate = UniqueIdentifier.DocumentTemplate;
string filename;
string comments;
object attachment;
if (documentTemplate == null)
{
@@ -42,20 +41,33 @@ namespace Disco.BI.Extensions
{
case DocumentTemplate.DocumentTemplateScopes.Device:
Device d = (Device)UniqueIdentifier.Data;
d.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
return true;
attachment = d.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
break;
case DocumentTemplate.DocumentTemplateScopes.Job:
Job j = (Job)UniqueIdentifier.Data;
j.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
return true;
attachment = j.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
break;
case DocumentTemplate.DocumentTemplateScopes.User:
User u = (User)UniqueIdentifier.Data;
u.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
return true;
attachment = u.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
break;
default:
return false;
}
if (documentTemplate != null && !string.IsNullOrWhiteSpace(documentTemplate.OnImportAttachmentExpression))
{
try
{
var expressionResult = documentTemplate.EvaluateOnAttachmentImportExpression(attachment, Database, creatorUser, UniqueIdentifier.TimeStamp);
DocumentsLog.LogImportAttachmentExpressionEvaluated(documentTemplate, UniqueIdentifier.Data, attachment, expressionResult);
}
catch (Exception ex)
{
SystemLog.LogException("Document Importer - OnImportAttachmentExpression", ex);
}
}
return true;
}
public static string RepositoryFilename(this DeviceAttachment da, DiscoDataContext Database)
@@ -1,13 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Disco.Data.Repository;
using Disco.Models.ClientServices;
using System.Web;
using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Services.Users;
using Disco.Services.Authorization;
using Disco.Services.Users;
using System;
using System.Web;
namespace Disco.BI.Extensions
{
@@ -69,5 +65,22 @@ namespace Disco.BI.Extensions
}
}
public static RegisterResponse BuildResponse(this Register request)
{
if (HttpContext.Current == null)
throw new PlatformNotSupportedException("This function can only be accessed from within ASP.NET");
string username = null;
if (HttpContext.Current.Request.IsAuthenticated)
username = HttpContext.Current.User.Identity.Name;
using (DiscoDataContext database = new DiscoDataContext())
{
RegisterResponse response = DeviceBI.DeviceEnrol.Register(database, username, request);
database.SaveChanges();
return response;
}
}
}
}
@@ -88,7 +88,7 @@ namespace Disco.BI.Extensions
d.DecommissionReason = Reason;
// Disable AD Account
if (d.DeviceDomainId != null)
if (ActiveDirectory.IsValidDomainAccountId(d.DeviceDomainId))
{
var adAccount = d.ActiveDirectoryAccount();
if (adAccount != null && !adAccount.IsCriticalSystemObject)
@@ -115,7 +115,7 @@ namespace Disco.BI.Extensions
d.DecommissionReason = null;
// Enable AD Account
if (d.DeviceDomainId != null)
if (ActiveDirectory.IsValidDomainAccountId(d.DeviceDomainId))
{
var adAccount = d.ActiveDirectoryAccount();
if (adAccount != null && !adAccount.IsCriticalSystemObject)
@@ -157,8 +157,8 @@ namespace Disco.BI.Extensions
JobId = j.Id,
TechUserId = UserService.CurrentUser.UserId,
Timestamp = DateTime.Now,
Comments = string.Format("Device Deleted{0}{0}Serial Number: {1}{0}Computer Name: {2}{0}Model: {3}{0}Profile: {4}",
Environment.NewLine, d.SerialNumber, d.DeviceDomainId, d.DeviceModel, d.DeviceProfile)
Comments = string.Format("# Device Deleted\r\n\r\nSerial Number: **{0}**\r\nComputer Name: **{1}**\r\nModel: **{2}**\r\nProfile: **{3}**",
d.SerialNumber, d.DeviceDomainId, d.DeviceModel, d.DeviceProfile)
};
Database.JobLogs.Add(jobLog);
}
+6 -4
View File
@@ -9,6 +9,7 @@ using System.IO;
using Disco.Services.Users;
using Disco.Services.Authorization;
using Disco.Services.Interop.ActiveDirectory;
using Exceptionless;
namespace Disco.BI.Extensions
{
@@ -36,6 +37,7 @@ namespace Disco.BI.Extensions
}
catch (Exception ex)
{
ex.ToExceptionless().AddObject(deviceProfile.ComputerNameTemplate, "ComputerNameTemplate").Submit();
throw new InvalidOperationException(string.Format("An error occurred rendering the computer name: [{0}] {1}", ex.GetType().Name, ex.Message), ex.InnerException);
}
if (rendered == null || rendered.Length > 24)
@@ -177,13 +179,11 @@ namespace Disco.BI.Extensions
}
// Update AD Account
if (!string.IsNullOrEmpty(d.DeviceDomainId))
if (ActiveDirectory.IsValidDomainAccountId(d.DeviceDomainId))
{
var adMachineAccount = ActiveDirectory.RetrieveADMachineAccount(d.DeviceDomainId);
if (adMachineAccount != null)
{
adMachineAccount.SetDescription(d);
}
}
return newDua;
@@ -191,7 +191,7 @@ namespace Disco.BI.Extensions
public static ADMachineAccount ActiveDirectoryAccount(this Device Device, params string[] AdditionalProperties)
{
if (!string.IsNullOrEmpty(Device.DeviceDomainId))
if (ActiveDirectory.IsValidDomainAccountId(Device.DeviceDomainId))
return ActiveDirectory.RetrieveADMachineAccount(Device.DeviceDomainId, AdditionalProperties: AdditionalProperties);
else
return null;
@@ -213,6 +213,8 @@ namespace Disco.BI.Extensions
return "Damaged";
case DecommissionReasons.Donated:
return "Donated";
case DecommissionReasons.Returned:
return "Returned";
default:
return "Unknown";
}
@@ -75,16 +75,29 @@ namespace Disco.BI.Extensions
}
public static System.IO.Stream GeneratePdf(this DocumentTemplate dt, DiscoDataContext Database, object Data, User CreatorUser, System.DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
{
return Interop.Pdf.PdfGenerator.GenerateFromTemplate(dt, Database, Data, CreatorUser, TimeStamp, State, FlattenFields);
bool generateExpression = !string.IsNullOrEmpty(dt.OnGenerateExpression);
string generateExpressionResult = null;
if (generateExpression)
generateExpressionResult = dt.EvaluateOnGenerateExpression(Data, Database, CreatorUser, TimeStamp, State);
var pdfStream = Interop.Pdf.PdfGenerator.GenerateFromTemplate(dt, Database, Data, CreatorUser, TimeStamp, State, FlattenFields);
if (generateExpression)
DocumentsLog.LogDocumentGenerated(dt, Data, CreatorUser, generateExpressionResult);
else
DocumentsLog.LogDocumentGenerated(dt, Data, CreatorUser);
return pdfStream;
}
public static Expression FilterExpressionFromCache(this DocumentTemplate dt)
{
return ExpressionCache.GetValue("DocumentTemplateFilterExpression", dt.Id, () => { return Expression.TokenizeSingleDynamic(null, dt.FilterExpression, 0); });
return ExpressionCache.GetValue("DocumentTemplate_FilterExpression", dt.Id, () => { return Expression.TokenizeSingleDynamic(null, dt.FilterExpression, 0); });
}
public static void FilterExpressionInvalidateCache(this DocumentTemplate dt)
{
ExpressionCache.InvalidateKey("DocumentTemplateFilterExpression", dt.Id);
ExpressionCache.InvalidateKey("DocumentTemplate_FilterExpression", dt.Id);
}
public static bool FilterExpressionMatches(this DocumentTemplate dt, object Data, DiscoDataContext Database, User User, System.DateTime TimeStamp, DocumentState State)
{
@@ -112,6 +125,64 @@ namespace Disco.BI.Extensions
}
return true;
}
public static Expression OnImportAttachmentExpressionFromCache(this DocumentTemplate dt)
{
return ExpressionCache.GetValue("DocumentTemplate_OnImportExpression", dt.Id, () => { return Expression.TokenizeSingleDynamic(null, dt.OnImportAttachmentExpression, 0); });
}
public static void OnImportAttachmentExpressionInvalidateCache(this DocumentTemplate dt)
{
ExpressionCache.InvalidateKey("DocumentTemplate_OnImportExpression", dt.Id);
}
public static string EvaluateOnAttachmentImportExpression(this DocumentTemplate dt, object Data, DiscoDataContext Database, User User, System.DateTime TimeStamp)
{
if (!string.IsNullOrEmpty(dt.OnImportAttachmentExpression))
{
Expression compiledExpression = dt.OnImportAttachmentExpressionFromCache();
System.Collections.IDictionary evaluatorVariables = Expression.StandardVariables(dt, Database, User, TimeStamp, null);
try
{
object result = compiledExpression.EvaluateFirst<object>(Data, evaluatorVariables);
if (result == null)
return null;
else
return result.ToString();
}
catch
{
throw;
}
}
return null;
}
public static Expression OnGenerateExpressionFromCache(this DocumentTemplate dt)
{
return ExpressionCache.GetValue("DocumentTemplate_OnGenerateExpression", dt.Id, () => { return Expression.TokenizeSingleDynamic(null, dt.OnGenerateExpression, 0); });
}
public static void OnGenerateExpressionInvalidateCache(this DocumentTemplate dt)
{
ExpressionCache.InvalidateKey("DocumentTemplate_OnGenerateExpression", dt.Id);
}
public static string EvaluateOnGenerateExpression(this DocumentTemplate dt, object Data, DiscoDataContext Database, User User, System.DateTime TimeStamp, DocumentState State)
{
if (!string.IsNullOrEmpty(dt.OnGenerateExpression))
{
Expression compiledExpression = dt.OnGenerateExpressionFromCache();
System.Collections.IDictionary evaluatorVariables = Expression.StandardVariables(dt, Database, User, TimeStamp, State);
try
{
object result = compiledExpression.EvaluateFirst<object>(Data, evaluatorVariables);
return result.ToString();
}
catch
{
throw;
}
}
return null;
}
public static string GetDataId(this DocumentTemplate dt, object Data)
{
if (Data is string)
+194 -32
View File
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Exceptionless;
using Disco.Data.Repository;
using Disco.Models.BI.Config;
using Disco.Models.Repository;
@@ -8,6 +9,10 @@ using Disco.Services.Plugins;
using Disco.Services.Plugins.Features.WarrantyProvider;
using Disco.Services.Users;
using Disco.Services.Authorization;
using Disco.Services.Plugins.Features.RepairProvider;
using PublishJobResult = Disco.Models.Services.Interop.DiscoServices.PublishJobResult;
using DiscoServicesJobs = Disco.Services.Interop.DiscoServices.Jobs;
namespace Disco.BI.Extensions
{
@@ -108,7 +113,7 @@ namespace Disco.BI.Extensions
JobId = j.Id,
TechUserId = Technician.UserId,
Timestamp = DateTime.Now,
Comments = string.Format("Waiting on User Action{0}Reason: {1}", Environment.NewLine, Reason)
Comments = string.Format("# Waiting on User Action\r\n{0}", string.IsNullOrWhiteSpace(Reason) ? "<no reason provided>" : Reason)
};
Database.JobLogs.Add(jobLog);
}
@@ -135,7 +140,7 @@ namespace Disco.BI.Extensions
JobId = j.Id,
TechUserId = Technician.UserId,
Timestamp = DateTime.Now,
Comments = string.Format("User Action Resolved{0}Resolution: {1}", Environment.NewLine, Resolution)
Comments = string.Format("# User Action Resolved\r\n{0}", string.IsNullOrWhiteSpace(Resolution) ? "<no comment provided>" : Resolution)
};
Database.JobLogs.Add(jobLog);
}
@@ -146,30 +151,55 @@ namespace Disco.BI.Extensions
{
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.LogWarranty))
return false;
return !j.ClosedDate.HasValue &&
(j.DeviceSerialNumber != null) &&
j.JobTypeId == JobType.JobTypeIds.HWar &&
!j.JobMetaWarranty.ExternalLoggedDate.HasValue;
}
public static void OnLogWarranty(this Job j, DiscoDataContext Database, string FaultDescription, PluginFeatureManifest WarrantyProviderDefinition, OrganisationAddress Address, User TechUser, Dictionary<string, string> WarrantyProviderProperties)
public static void OnLogWarranty(this Job j, DiscoDataContext Database, string FaultDescription, List<JobAttachment> SendAttachments, PluginFeatureManifest WarrantyProviderDefinition, OrganisationAddress Address, User TechUser, Dictionary<string, string> WarrantyProviderProperties)
{
if (!j.CanLogWarranty())
throw new InvalidOperationException("Log Warranty was Denied");
if (string.IsNullOrWhiteSpace(FaultDescription))
FaultDescription = j.GenerateFaultDescriptionFooter(Database, WarrantyProviderDefinition);
else
FaultDescription = string.Concat(FaultDescription, Environment.NewLine, Environment.NewLine, j.GenerateFaultDescriptionFooter(Database, WarrantyProviderDefinition));
PublishJobResult publishJobResult = null;
using (WarrantyProviderFeature WarrantyProvider = WarrantyProviderDefinition.CreateInstance<WarrantyProviderFeature>())
{
string providerRef = WarrantyProvider.SubmitJob(Database, j, Address, TechUser, FaultDescription, WarrantyProviderProperties);
if (SendAttachments != null && SendAttachments.Count > 0)
{
publishJobResult = DiscoServicesJobs.Publish(
Database,
j,
TechUser,
WarrantyProvider.WarrantyProviderId,
null,
FaultDescription,
SendAttachments,
Disco.BI.Extensions.AttachmentExtensions.RepositoryFilename);
if (!publishJobResult.Success)
throw new Exception(string.Format("Disco ICT Online Services failed with the following message: ", publishJobResult.ErrorMessage));
if (string.IsNullOrWhiteSpace(FaultDescription))
FaultDescription = publishJobResult.PublishMessage;
else
FaultDescription = string.Concat(FaultDescription, Environment.NewLine, "___", Environment.NewLine, publishJobResult.PublishMessage);
}
string submitDescription;
if (string.IsNullOrWhiteSpace(FaultDescription))
submitDescription = j.GenerateFaultDescriptionFooter(Database, WarrantyProviderDefinition);
else
submitDescription = string.Concat(FaultDescription, Environment.NewLine, Environment.NewLine, j.GenerateFaultDescriptionFooter(Database, WarrantyProviderDefinition));
string providerRef = WarrantyProvider.SubmitJob(Database, j, Address, TechUser, submitDescription, WarrantyProviderProperties);
j.JobMetaWarranty.ExternalLoggedDate = DateTime.Now;
j.JobMetaWarranty.ExternalName = WarrantyProvider.WarrantyProviderId;
if (providerRef.Length > 100)
if (providerRef != null && providerRef.Length > 100)
j.JobMetaWarranty.ExternalReference = providerRef.Substring(0, 100);
else
j.JobMetaWarranty.ExternalReference = providerRef;
@@ -180,11 +210,43 @@ namespace Disco.BI.Extensions
JobId = j.Id,
TechUserId = TechUser.UserId,
Timestamp = DateTime.Now,
Comments = string.Format("Warranty Claim Submitted{0}{0}Provider: {1}{0}Repair Address: {2}{0}Provider Reference: {3}{0}{0}{4}", Environment.NewLine, WarrantyProvider.Manifest.Name, Address.Name, providerRef, FaultDescription)
Comments = string.Format("# Warranty Claim Submitted\r\nProvider: **{0}**\r\nAddress: **{1}**\r\nReference: **{2}**\r\n___\r\n```{3}```", WarrantyProvider.Manifest.Name, Address.Name, providerRef, FaultDescription)
};
Database.JobLogs.Add(jobLog);
if (publishJobResult != null)
{
try
{
DiscoServicesJobs.UpdateRecipientReference(Database, j, publishJobResult.Id, publishJobResult.Secret, j.JobMetaWarranty.ExternalReference);
}
catch (Exception ex) { ex.ToExceptionless().Submit(); } // Ignore Errors as this is not completely necessary
}
}
}
public static void OnLogWarranty(this Job j, DiscoDataContext Database, string FaultDescription, string ManualProviderName, string ManualProviderReference, OrganisationAddress Address, User TechUser)
{
if (!j.CanLogWarranty())
throw new InvalidOperationException("Log Warranty was Denied");
j.JobMetaWarranty.ExternalLoggedDate = DateTime.Now;
j.JobMetaWarranty.ExternalName = ManualProviderName;
if (ManualProviderReference != null && ManualProviderReference.Length > 100)
j.JobMetaWarranty.ExternalReference = ManualProviderReference.Substring(0, 100);
else
j.JobMetaWarranty.ExternalReference = ManualProviderReference;
// Write Log
JobLog jobLog = new JobLog()
{
JobId = j.Id,
TechUserId = TechUser.UserId,
Timestamp = DateTime.Now,
Comments = string.Format("# Manual Warranty Claim Submitted\r\nProvider: **{0}**\r\nAddress: **{1}**\r\nReference: **{2}**\r\n___\r\n```{3}```", ManualProviderName, Address.Name, ManualProviderReference ?? "<none>", FaultDescription)
};
Database.JobLogs.Add(jobLog);
}
#endregion
#region Convert HWar to HNWar
@@ -260,7 +322,7 @@ namespace Disco.BI.Extensions
JobId = j.Id,
TechUserId = techUser.UserId,
Timestamp = DateTime.Now,
Comments = string.Format("Job Type Converted{0}From: {1}{0}To: {2}", Environment.NewLine, Database.JobTypes.Find(JobType.JobTypeIds.HWar), Database.JobTypes.Find(JobType.JobTypeIds.HNWar))
Comments = string.Format("# Job Type Converted\r\nFrom: **{0}**\r\nTo: **{1}**", Database.JobTypes.Find(JobType.JobTypeIds.HWar), Database.JobTypes.Find(JobType.JobTypeIds.HNWar))
};
Database.JobLogs.Add(jobLog);
@@ -317,16 +379,95 @@ namespace Disco.BI.Extensions
!j.JobMetaNonWarranty.RepairerLoggedDate.HasValue &&
!j.JobMetaNonWarranty.RepairerCompletedDate.HasValue;
}
public static void OnLogRepair(this Job j, string RepairerName, string RepairerReference)
public static void OnLogRepair(this Job j, DiscoDataContext Database, string RepairDescription, List<JobAttachment> SendAttachments, PluginFeatureManifest RepairProviderDefinition, OrganisationAddress Address, User TechUser, Dictionary<string, string> RepairProviderProperties)
{
if (!j.CanLogRepair())
throw new InvalidOperationException("Log Repair was Denied");
PublishJobResult publishJobResult = null;
using (RepairProviderFeature RepairProvider = RepairProviderDefinition.CreateInstance<RepairProviderFeature>())
{
if (SendAttachments != null && SendAttachments.Count > 0)
{
publishJobResult = DiscoServicesJobs.Publish(
Database,
j,
TechUser,
RepairProvider.ProviderId,
null,
RepairDescription,
SendAttachments,
Disco.BI.Extensions.AttachmentExtensions.RepositoryFilename);
if (!publishJobResult.Success)
throw new Exception(string.Format("Disco ICT Online Services failed with the following message: ", publishJobResult.ErrorMessage));
if (string.IsNullOrWhiteSpace(RepairDescription))
RepairDescription = publishJobResult.PublishMessage;
else
RepairDescription = string.Concat(RepairDescription, Environment.NewLine, "___", Environment.NewLine, publishJobResult.PublishMessage);
}
string submitDescription;
if (string.IsNullOrWhiteSpace(RepairDescription))
submitDescription = j.GenerateFaultDescriptionFooter(Database, RepairProviderDefinition);
else
submitDescription = string.Concat(RepairDescription, Environment.NewLine, Environment.NewLine, j.GenerateFaultDescriptionFooter(Database, RepairProviderDefinition));
string providerRef = RepairProvider.SubmitJob(Database, j, Address, TechUser, submitDescription, RepairProviderProperties);
j.JobMetaNonWarranty.RepairerLoggedDate = DateTime.Now;
j.JobMetaNonWarranty.RepairerName = RepairProvider.ProviderId;
if (providerRef != null && providerRef.Length > 100)
j.JobMetaNonWarranty.RepairerReference = providerRef.Substring(0, 100);
else
j.JobMetaNonWarranty.RepairerReference = providerRef;
// Write Log
JobLog jobLog = new JobLog()
{
JobId = j.Id,
TechUserId = TechUser.UserId,
Timestamp = DateTime.Now,
Comments = string.Format("# Repair Request Submitted\r\nProvider: **{0}**\r\nAddress: **{1}**\r\nReference: **{2}**\r\n___\r\n```{3}```", RepairProvider.Manifest.Name, Address.Name, providerRef, RepairDescription)
};
Database.JobLogs.Add(jobLog);
if (publishJobResult != null)
{
try
{
DiscoServicesJobs.UpdateRecipientReference(Database, j, publishJobResult.Id, publishJobResult.Secret, j.JobMetaNonWarranty.RepairerReference);
}
catch (Exception ex) { ex.ToExceptionless().Submit(); } // Ignore Errors as this is not completely necessary
}
}
}
public static void OnLogRepair(this Job j, DiscoDataContext Database, string FaultDescription, string ManualProviderName, string ManualProviderReference, OrganisationAddress Address, User TechUser)
{
if (!j.CanLogRepair())
throw new InvalidOperationException("Log Repair was Denied");
if (j.JobMetaNonWarranty.RepairerName != RepairerName)
j.JobMetaNonWarranty.RepairerName = RepairerName;
if (j.JobMetaNonWarranty.RepairerReference != RepairerReference)
j.JobMetaNonWarranty.RepairerReference = RepairerReference;
j.JobMetaNonWarranty.RepairerLoggedDate = DateTime.Now;
j.JobMetaNonWarranty.RepairerName = ManualProviderName;
if (ManualProviderReference != null && ManualProviderReference.Length > 100)
j.JobMetaNonWarranty.RepairerReference = ManualProviderReference.Substring(0, 100);
else
j.JobMetaNonWarranty.RepairerReference = ManualProviderReference;
// Write Log
JobLog jobLog = new JobLog()
{
JobId = j.Id,
TechUserId = TechUser.UserId,
Timestamp = DateTime.Now,
Comments = string.Format("# Manual Repair Request Submitted\r\nProvider: **{0}**\r\nAddress: **{1}**\r\nReference: **{2}**\r\n___\r\n```{3}```", ManualProviderName, Address.Name, ManualProviderReference ?? "<none>", FaultDescription)
};
Database.JobLogs.Add(jobLog);
}
#endregion
@@ -389,7 +530,7 @@ namespace Disco.BI.Extensions
return false;
}
public static bool CanCloseNormally(this Job j)
{
if (j.CanCloseNever())
@@ -403,20 +544,25 @@ namespace Disco.BI.Extensions
switch (j.JobTypeId)
{
case JobType.JobTypeIds.HWar:
if (!string.IsNullOrEmpty(j.JobMetaWarranty.ExternalReference) && !j.JobMetaWarranty.ExternalCompletedDate.HasValue)
return false; // Job Logged (Warranty) but not completed
break;
case JobType.JobTypeIds.HNWar:
if (j.JobMetaNonWarranty.RepairerLoggedDate.HasValue && !j.JobMetaNonWarranty.RepairerCompletedDate.HasValue)
return false; // Job Logged (Repair) but not completed
if (j.JobMetaNonWarranty.AccountingChargeRequiredDate.HasValue && (!j.JobMetaNonWarranty.AccountingChargePaidDate.HasValue || !j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue))
return false; // Accounting Charge Required, but not added or paid
if (j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue && !j.JobMetaNonWarranty.AccountingChargePaidDate.HasValue)
return false; // Accounting Charge Added, but not paid
if (j.JobMetaNonWarranty.AccountingChargeRequiredDate.HasValue && !j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue)
return false; // Accounting Charge Required, but not added
if ((j.JobMetaNonWarranty.AccountingChargeRequiredDate.HasValue || j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue) && !j.JobMetaNonWarranty.AccountingChargePaidDate.HasValue)
return false; // Accounting Charge Required or Added, but not paid
if (j.JobMetaNonWarranty.IsInsuranceClaim && !j.JobMetaInsurance.ClaimFormSentDate.HasValue)
return false; // Is Insurance Claim, but claim form not sent
break;
}
@@ -435,6 +581,14 @@ namespace Disco.BI.Extensions
#region Force Close
public static bool CanCloseForced(this Job j)
{
List<string> reasons;
return CanCloseForced(j, out reasons);
}
public static bool CanCloseForced(this Job j, out List<string> Reasons)
{
Reasons = null;
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.ForceClose))
return false;
@@ -444,27 +598,35 @@ namespace Disco.BI.Extensions
if (j.CanCloseNormally())
return false;
Reasons = new List<string>();
switch (j.JobTypeId)
{
case JobType.JobTypeIds.HWar:
if (!string.IsNullOrEmpty(j.JobMetaWarranty.ExternalReference) && !j.JobMetaWarranty.ExternalCompletedDate.HasValue)
return true; // Job Logged (Warranty) but not completed
Reasons.Add("Warranty Job Not Completed"); // Job Logged (Warranty) but not completed
break;
case JobType.JobTypeIds.HNWar:
if (j.JobMetaNonWarranty.RepairerLoggedDate.HasValue && !j.JobMetaNonWarranty.RepairerCompletedDate.HasValue)
return true; // Job Logged (Repair) but not completed
if (j.JobMetaNonWarranty.AccountingChargeRequiredDate.HasValue && (!j.JobMetaNonWarranty.AccountingChargePaidDate.HasValue || !j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue))
return true; // Accounting Charge Required, but not added or paid
if (j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue && !j.JobMetaNonWarranty.AccountingChargePaidDate.HasValue)
return true; // Accounting Charge Added, but not paid
if (j.JobMetaNonWarranty.RepairerLoggedDate.HasValue && !j.JobMetaNonWarranty.RepairerCompletedDate.HasValue)
Reasons.Add("Repair Job Not Completed"); // Job Logged (Repair) but not completed
if (j.JobMetaNonWarranty.AccountingChargeRequiredDate.HasValue && (!j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue && !j.JobMetaNonWarranty.AccountingChargePaidDate.HasValue))
Reasons.Add("Accounting Charge Required But Not Added Or Paid"); // Accounting Charge Required, but not added or paid
else if (j.JobMetaNonWarranty.AccountingChargeRequiredDate.HasValue && !j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue)
Reasons.Add("Accounting Charge Required But Not Added"); // Accounting Charge Required, but not added
else if (j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue && !j.JobMetaNonWarranty.AccountingChargePaidDate.HasValue)
Reasons.Add("Accounting Charge Added But Not Paid"); // Accounting Charge Added, but not paid
else if (j.JobMetaNonWarranty.AccountingChargeRequiredDate.HasValue && !j.JobMetaNonWarranty.AccountingChargePaidDate.HasValue)
Reasons.Add("Accounting Charge Required But Not Paid"); // Accounting Charge Required, but not paid
if (j.JobMetaNonWarranty.IsInsuranceClaim && !j.JobMetaInsurance.ClaimFormSentDate.HasValue)
return true; // Is Insurance Claim, but claim form not sent
Reasons.Add("Insurance Claim Form Not Sent"); // Is Insurance Claim, but claim form not sent
break;
}
return false;
return (Reasons.Count > 0);
}
public static void OnCloseForced(this Job j, DiscoDataContext Database, User Technician, string Reason)
{
@@ -477,7 +639,7 @@ namespace Disco.BI.Extensions
JobId = j.Id,
TechUserId = Technician.UserId,
Timestamp = DateTime.Now,
Comments = string.Format("Job Forcibly Closed{0}Reason: {1}", Environment.NewLine, Reason)
Comments = string.Format("# Job Forcibly Closed\r\n{0}", string.IsNullOrWhiteSpace(Reason) ? "<no reason provided>" : Reason)
};
Database.JobLogs.Add(jobLog);
+5 -5
View File
@@ -132,18 +132,18 @@ namespace Disco.BI.Extensions
if (addedSubTypes.Count > 0 || removedSubTypes.Count > 0)
{
StringBuilder logBuilder = new StringBuilder();
logBuilder.AppendLine("Updated Job Sub Types");
logBuilder.AppendLine("# Updated Job Sub Types");
if (removedSubTypes.Count > 0)
{
logBuilder.AppendLine("Removed:");
logBuilder.AppendLine().AppendLine("Removed:");
foreach (var t in removedSubTypes)
logBuilder.Append("- ").AppendLine(t.ToString());
logBuilder.Append("- **").Append(t.ToString()).AppendLine("**");
}
if (addedSubTypes.Count > 0)
{
logBuilder.AppendLine("Added:");
logBuilder.AppendLine().AppendLine("Added:");
foreach (var t in addedSubTypes)
logBuilder.Append("- ").AppendLine(t.ToString());
logBuilder.Append("- **").Append(t.ToString()).AppendLine("**");
}
Database.JobLogs.Add(new JobLog()
{
@@ -1,188 +0,0 @@
using Disco.Data.Repository;
using Disco.Models.BI.Interop.Community;
using Disco.Models.Repository;
using Disco.Services.Tasks;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Xml.Linq;
using System.Xml.Serialization;
namespace Disco.BI.Interop.Community
{
public static class UpdateCheck
{
private static string UpdateUrl()
{
return string.Concat(Disco.Data.Configuration.CommunityHelpers.CommunityUrl(), "DiscoUpdate/V1");
}
public static Version CurrentDiscoVersion()
{
return typeof(UpdateCheck).Assembly.GetName().Version;
}
public static string CurrentDiscoVersionFormatted()
{
var v = CurrentDiscoVersion();
return string.Format("{0}.{1}.{2:0000}.{3:0000}", v.Major, v.Minor, v.Build, v.Revision);
}
public static UpdateResponse Check(DiscoDataContext Database, bool UseProxy, IScheduledTaskStatus status)
{
status.UpdateStatus(10, "Building Update Request");
var request = BuildRequest(Database);
status.UpdateStatus(40, "Sending Request");
var DiscoBIVersion = CurrentDiscoVersionFormatted();
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(UpdateUrl());
// Added: 2013-02-08 G#
// Fix for Proxy Servers which dont support KeepAlive
webRequest.KeepAlive = false;
// End Added: 2013-02-08 G#
if (!UseProxy)
webRequest.Proxy = new WebProxy();
webRequest.ContentType = "application/json";
webRequest.Method = WebRequestMethods.Http.Post;
webRequest.UserAgent = string.Format("Disco/{0} (Update)", DiscoBIVersion);
using (var wrStream = webRequest.GetRequestStream())
{
XmlSerializer xml = new XmlSerializer(typeof(UpdateRequestV1));
xml.Serialize(wrStream, request);
}
status.UpdateStatus(50, "Waiting for Response");
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{
if (webResponse.StatusCode == HttpStatusCode.OK)
{
status.UpdateStatus(90, "Reading Response");
UpdateResponse result;
using (var wResStream = webResponse.GetResponseStream())
{
XmlSerializer xml = new XmlSerializer(typeof(UpdateResponse));
result = (UpdateResponse)xml.Deserialize(wResStream);
}
Database.DiscoConfiguration.UpdateLastCheck = result;
Database.SaveChanges();
status.SetFinishedMessage(string.Format("The update server reported Version {0} is the latest.", result.Version));
return result;
}
else
{
status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
return null;
}
}
}
private static UpdateRequestV1 BuildRequest(DiscoDataContext Database)
{
var m = new UpdateRequestV1();
m.DeploymentId = Database.DiscoConfiguration.DeploymentId;
m.CurrentDiscoVersion = CurrentDiscoVersionFormatted();
m.OrganisationName = Database.DiscoConfiguration.OrganisationName;
m.BroadbandDoeWanId = GetBroadbandDoeWanId();
m.BetaDeployment = Database.DiscoConfiguration.UpdateBetaDeployment;
m.Stat_JobCounts = Database.Jobs.GroupBy(j => j.JobTypeId).Select(g => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = g.Key, Count = g.Count() }).ToList();
m.Stat_OpenJobCounts = Database.Jobs.Where(j => j.ClosedDate == null).GroupBy(j => j.JobTypeId).Select(g => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = g.Key, Count = g.Count() }).ToList();
m.Stat_DeviceModelCounts = Database.DeviceModels.Select(dm => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = dm.Manufacturer + ";" + dm.Model, Count = dm.Devices.Count(d => d.DecommissionedDate == null) }).ToList();
var activeThreshold = DateTime.Now.AddDays(-60);
m.Stat_ActiveDeviceModelCounts = Database.DeviceModels.Select(dm => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = dm.Manufacturer + ";" + dm.Model, Count = dm.Devices.Count(d => d.DecommissionedDate == null && (d.LastNetworkLogonDate == null || d.LastNetworkLogonDate > activeThreshold)) }).ToList();
m.Stat_UserCounts = new List<UpdateRequestV1.Stat>() {
new UpdateRequestV1.Stat(){
Key = "All Users",
Count = Database.Users.Count()
}
};
m.Stat_JobWarrantyVendorCounts = Database.Jobs.Where(j => j.JobTypeId == JobType.JobTypeIds.HWar && j.JobMetaWarranty.ExternalLoggedDate.HasValue && j.JobMetaWarranty.ExternalName != null).GroupBy(j => j.JobMetaWarranty.ExternalName).Select(g => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = g.Key ?? "<Unknown>", Count = g.Count() }).ToList();
m.InstalledPlugins = Disco.Services.Plugins.Plugins.GetPlugins().Select(manifest => new Disco.Models.BI.Interop.Community.UpdateRequestV1.PluginRef { Id = manifest.Id, Version = manifest.VersionFormatted }).ToList();
return m;
}
#region DoE Query
public static string GetBroadbandDoeWanId()
{
// DnsQuery for broadband.doe.wan
IPHostEntry doeWanDnsEntry;
try
{
doeWanDnsEntry = Dns.GetHostEntry("broadband.doe.wan");
}
catch (Exception)
{ return null; } // Fail on error
// Try using IPSearch feature
XDocument doeWanIPSearchResult = TryDownloadDoeIPSearch(false);
if (doeWanIPSearchResult == null)
doeWanIPSearchResult = TryDownloadDoeIPSearch(true);
if (doeWanIPSearchResult == null)
return null;
try
{
return doeWanIPSearchResult.Element("resultset").Element("site").Element("number").Value.ToLower();
}
catch (Exception)
{ return null; } // Fail on error
}
private static XDocument TryDownloadDoeIPSearch(bool useProxy)
{
try
{
var DiscoBIVersion = CurrentDiscoVersionFormatted();
HttpWebRequest wReq = (HttpWebRequest)HttpWebRequest.Create("http://broadband.doe.wan/ipsearch/showresult.php");
// Added: 2013-02-08 G#
// Fix for Proxy Servers which dont support KeepAlive
wReq.KeepAlive = false;
// End Added: 2013-02-08 G#
if (!useProxy)
wReq.Proxy = new WebProxy(); // Empty Proxy Config
wReq.Method = WebRequestMethods.Http.Post;
wReq.ContentType = "application/x-www-form-urlencoded";
wReq.UserAgent = string.Format("Disco/{0}", DiscoBIVersion);
using (var wrStream = wReq.GetRequestStream())
{
using (var wrStreamWriter = new StreamWriter(wrStream))
{
wrStreamWriter.Write("mode=whoami");
}
}
using (HttpWebResponse wRes = (HttpWebResponse)wReq.GetResponse())
{
if (wRes.StatusCode == HttpStatusCode.OK)
{
using (var wResStream = wRes.GetResponseStream())
{
return XDocument.Load(wResStream);
}
}
else
return null;
}
}
catch (Exception)
{ return null; } // Fail on error
}
#endregion
}
}
+1 -1
View File
@@ -242,7 +242,7 @@ namespace Disco.BI.Interop.Pdf
TechUserId = CreatorUser.UserId,
Timestamp = DateTime.Now
};
jl.Comments = string.Format("Document Generated{0}{1} [{2}]", Environment.NewLine, dt.Description, dt.Id);
jl.Comments = string.Format("# Document Generated\r\n**{0}** [{1}]", dt.Description, dt.Id);
Database.JobLogs.Add(jl);
}
+21 -15
View File
@@ -307,7 +307,7 @@ namespace Disco.BI.Interop.Pdf
{
DetectPageResult result = new DetectPageResult() { PageNumber = PageNumber };
DocumentImporterLog.LogImportPageProgress(SessionId, PageNumber, 10, "Loading Page Images");
DocumentsLog.LogImportPageProgress(SessionId, PageNumber, 10, "Loading Page Images");
using (DisposableImageCollection pageImages = pdfReader.PdfPageImages(PageNumber))
{
@@ -317,13 +317,13 @@ namespace Disco.BI.Interop.Pdf
var pageThumbnailFilename = Path.Combine(DataStoreSessionCacheLocation, string.Format("{0}-{1}", SessionId, PageNumber));
result.ThumbnailImage.Montage.SavePng(pageThumbnailFilename);
DocumentImporterLog.LogImportPageImageUpdate(SessionId, PageNumber);
DocumentsLog.LogImportPageImageUpdate(SessionId, PageNumber);
double pageProgressInterval = 90 / pageImages.Count;
foreach (var pageImageOriginal in pageImages)
{
DocumentImporterLog.LogImportPageProgress(SessionId, PageNumber, (int)(10 + (pageProgressInterval * pageImages.IndexOf(pageImageOriginal))), String.Format("Processing Page Image {0} of {1}", pageImages.IndexOf(pageImageOriginal) + 1, pageImages.Count));
DocumentsLog.LogImportPageProgress(SessionId, PageNumber, (int)(10 + (pageProgressInterval * pageImages.IndexOf(pageImageOriginal))), String.Format("Processing Page Image {0} of {1}", pageImages.IndexOf(pageImageOriginal) + 1, pageImages.Count));
using (var zxingResult = DetectImage(Database, pageImageOriginal, SessionId, detectDocumentTemplates, StateHints))
{
@@ -343,7 +343,7 @@ namespace Disco.BI.Interop.Pdf
}
result.ThumbnailImage.Montage.SavePng(pageThumbnailFilename);
DocumentImporterLog.LogImportPageImageUpdate(SessionId, PageNumber);
DocumentsLog.LogImportPageImageUpdate(SessionId, PageNumber);
result.AttachmentThumbnailImage = new MemoryStream();
using (var attachmentThumbImage = pageImages.BuildImageMontage(48, 48, true))
@@ -381,7 +381,7 @@ namespace Disco.BI.Interop.Pdf
{
var dataStoreUnassignedLocation = DataStore.CreateLocation(Database, "DocumentDropBox_Unassigned");
DocumentImporterLog.LogImportProgress(SessionId, 0, "Reading File");
DocumentsLog.LogImportProgress(SessionId, 0, "Reading File");
using (FileStream fs = new FileStream(Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
@@ -398,8 +398,8 @@ namespace Disco.BI.Interop.Pdf
for (int PageNumber = 1; PageNumber <= pdfReader.NumberOfPages; PageNumber++)
{
DocumentImporterLog.LogImportProgress(SessionId, (int)(PageNumber * progressInterval), string.Format("Processing Page {0} of {1}", PageNumber, pdfReader.NumberOfPages));
DocumentImporterLog.LogImportPageStarting(SessionId, PageNumber);
DocumentsLog.LogImportProgress(SessionId, (int)(PageNumber * progressInterval), string.Format("Processing Page {0} of {1}", PageNumber, pdfReader.NumberOfPages));
DocumentsLog.LogImportPageStarting(SessionId, PageNumber);
using (var pageResult = DetectPage(Database, pdfReader, PageNumber, SessionId, dataStoreSessionPagesCacheLocation, detectDocumentTemplates, detectStateHints))
{
@@ -409,19 +409,25 @@ namespace Disco.BI.Interop.Pdf
pdfPagesAssigned.Add(PageNumber, new Tuple<DocumentUniqueIdentifier, byte[]>(docId, pageResult.AttachmentThumbnailImage.ToArray()));
docId.LoadComponents(Database);
DocumentImporterLog.LogImportPageDetected(SessionId, PageNumber, docId.TemplateTypeId, docId.DocumentTemplate.Description, docId.DocumentTemplate.Scope, docId.DataId, docId.DataDescription);
DocumentsLog.LogImportPageDetected(SessionId, PageNumber, docId.TemplateTypeId, docId.DocumentTemplate.Description, docId.DocumentTemplate.Scope, docId.DataId, docId.DataDescription);
}
else
{
// Undetected Page - Write Preview-Images while still in Memory
DocumentImporterLog.LogImportPageUndetected(SessionId, PageNumber);
DocumentsLog.LogImportPageUndetected(SessionId, PageNumber);
// Thumbnail:
string unassignedImageThumbnailFilename = Path.Combine(dataStoreUnassignedLocation, string.Format("{0}_{1}_thumbnail.png", SessionId, PageNumber));
pageResult.ThumbnailImage.Montage.SavePng(unassignedImageThumbnailFilename);
if (pageResult.ThumbnailImage != null)
pageResult.ThumbnailImage.Montage.SavePng(unassignedImageThumbnailFilename);
else
Disco.Properties.Resources.MimeType_pdf48.SavePng(unassignedImageThumbnailFilename);
// Large Preview
string unassignedImageFilename = Path.Combine(dataStoreUnassignedLocation, string.Format("{0}_{1}.jpg", SessionId, PageNumber));
pageResult.UndetectedPageImage.Montage.SaveJpg(90, unassignedImageFilename);
if (pageResult.UndetectedPageImage != null)
pageResult.UndetectedPageImage.Montage.SaveJpg(90, unassignedImageFilename);
else
Disco.Properties.Resources.MimeType_pdf48.SaveJpg(90, unassignedImageFilename);
}
}
@@ -435,7 +441,7 @@ namespace Disco.BI.Interop.Pdf
foreach (var documentPortion in assignedDocuments)
{
DocumentImporterLog.LogImportProgress(SessionId, (int)(70 + (assignedDocuments.IndexOf(documentPortion) * progressInterval)), string.Format("Importing Documents {0} of {1}", assignedDocuments.IndexOf(documentPortion) + 1, assignedDocuments.Count));
DocumentsLog.LogImportProgress(SessionId, (int)(70 + (assignedDocuments.IndexOf(documentPortion) * progressInterval)), string.Format("Importing Documents {0} of {1}", assignedDocuments.IndexOf(documentPortion) + 1, assignedDocuments.Count));
var documentPortionInfo = documentPortion.First().Value;
var documentPortionIdentifier = documentPortionInfo.Item1;
@@ -506,7 +512,7 @@ namespace Disco.BI.Interop.Pdf
//dataStoreUnassignedLocation
foreach (var PageNumber in pdfPagesUnassigned)
{
DocumentImporterLog.LogImportProgress(SessionId, (int)(90 + (pdfPagesUnassigned.IndexOf(PageNumber) * progressInterval)), string.Format("Processing Undetected Documents {0} of {1}", pdfPagesUnassigned.IndexOf(PageNumber) + 1, pdfPagesUnassigned.Count));
DocumentsLog.LogImportProgress(SessionId, (int)(90 + (pdfPagesUnassigned.IndexOf(PageNumber) * progressInterval)), string.Format("Processing Undetected Documents {0} of {1}", pdfPagesUnassigned.IndexOf(PageNumber) + 1, pdfPagesUnassigned.Count));
using (MemoryStream msBuilder = new MemoryStream())
{
@@ -527,14 +533,14 @@ namespace Disco.BI.Interop.Pdf
File.WriteAllBytes(Path.Combine(dataStoreUnassignedLocation, string.Format("{0}_{1}.pdf", SessionId, PageNumber)), msBuilder.ToArray());
DocumentImporterLog.LogImportPageUndetectedStored(SessionId, PageNumber);
DocumentsLog.LogImportPageUndetectedStored(SessionId, PageNumber);
}
}
}
}
DocumentImporterLog.LogImportProgress(SessionId, 100, "Finished Importing Document");
DocumentsLog.LogImportProgress(SessionId, 100, "Finished Importing Document");
return true;
}
+34 -15
View File
@@ -43,6 +43,14 @@
<Reference Include="EntityFramework">
<HintPath>..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll</HintPath>
</Reference>
<Reference Include="Exceptionless, Version=1.5.2092.0, Culture=neutral, PublicKeyToken=fc181f0a46f65747, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Exceptionless.1.5.2092\lib\net45\Exceptionless.dll</HintPath>
</Reference>
<Reference Include="Exceptionless.Models, Version=1.5.2092.0, Culture=neutral, PublicKeyToken=fc181f0a46f65747, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Exceptionless.1.5.2092\lib\net45\Exceptionless.Models.dll</HintPath>
</Reference>
<Reference Include="itextsharp">
<HintPath>..\Resources\Libraries\iTextSharp\itextsharp.dll</HintPath>
</Reference>
@@ -59,21 +67,29 @@
<Reference Include="System.DirectoryServices" />
<Reference Include="System.Drawing" />
<Reference Include="System.Management" />
<Reference Include="System.Reactive.Core, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-Core.2.2.4\lib\net45\System.Reactive.Core.dll</HintPath>
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.Extensions">
<HintPath>..\packages\Microsoft.Net.Http.2.2.22\lib\net45\System.Net.Http.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Interfaces, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-Interfaces.2.2.4\lib\net45\System.Reactive.Interfaces.dll</HintPath>
<Reference Include="System.Net.Http.Primitives">
<HintPath>..\packages\Microsoft.Net.Http.2.2.22\lib\net45\System.Net.Http.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Linq, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Reactive.Core, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-Linq.2.2.4\lib\net45\System.Reactive.Linq.dll</HintPath>
<HintPath>..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.PlatformServices, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Reference Include="System.Reactive.Interfaces, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-PlatformServices.2.2.4\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
<HintPath>..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Linq, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.PlatformServices, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
@@ -144,10 +160,8 @@
<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\DocumentTemplateBI\DocumentsLog.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" />
@@ -183,6 +197,7 @@
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
@@ -207,10 +222,14 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
<UserProperties BuildVersion_StartDate="2014/6/1" BuildVersion_BuildAction="Both" BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" />
<UserProperties BuildVersion_UpdateFileVersion="True" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_UseGlobalSettings="False" BuildVersion_DetectChanges="False" BuildVersion_BuildAction="Both" BuildVersion_StartDate="2014/6/1" />
</VisualStudio>
</ProjectExtensions>
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
</Target>
<!-- 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">
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.0.0626.0000")]
[assembly: AssemblyFileVersion("2.0.0626.0000")]
[assembly: AssemblyVersion("2.0.0918.1700")]
[assembly: AssemblyFileVersion("2.0.0918.1700")]
+12
View File
@@ -40,6 +40,18 @@
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
+9 -5
View File
@@ -1,9 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EntityFramework" version="5.0.0" targetFramework="net45" />
<package id="Rx-Core" version="2.2.4" targetFramework="net45" />
<package id="Rx-Interfaces" version="2.2.4" targetFramework="net45" />
<package id="Rx-Linq" version="2.2.4" targetFramework="net45" />
<package id="Rx-Main" version="2.2.4" targetFramework="net45" />
<package id="Rx-PlatformServices" version="2.2.4" targetFramework="net45" />
<package id="Exceptionless" version="1.5.2092" targetFramework="net45" />
<package id="Microsoft.Bcl" version="1.1.9" targetFramework="net45" />
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net45" />
<package id="Microsoft.Net.Http" version="2.2.22" targetFramework="net45" />
<package id="Rx-Core" version="2.2.5" targetFramework="net45" />
<package id="Rx-Interfaces" version="2.2.5" targetFramework="net45" />
<package id="Rx-Linq" version="2.2.5" targetFramework="net45" />
<package id="Rx-Main" version="2.2.5" targetFramework="net45" />
<package id="Rx-PlatformServices" version="2.2.5" targetFramework="net45" />
</packages>
-1
View File
@@ -129,7 +129,6 @@
"$(ProjectDir)Package Creation\7z.exe" a -tzip "$(ProjectDir)Package Creation\PreparationClient.zip" "$(TargetDir)*.*" -x!*.tmp -x!*.vshost.* -x!Newtonsoft.Json.xml -x!*.pdb
COPY "$(ProjectDir)Package Creation\PreparationClient.zip" "$(ProjectDir)..\Disco.Web\ClientBin"</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">
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.0.0626.0000")]
[assembly: AssemblyFileVersion("2.0.0626.0000")]
[assembly: AssemblyVersion("2.0.0918.1700")]
[assembly: AssemblyFileVersion("2.0.0918.1700")]
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.0.0626.0000")]
[assembly: AssemblyFileVersion("2.0.0626.0000")]
[assembly: AssemblyVersion("2.0.0918.1700")]
[assembly: AssemblyFileVersion("2.0.0918.1700")]
@@ -1,29 +0,0 @@
using System;
using System.Linq;
using System.Net;
namespace Disco.Data.Configuration
{
public static class CommunityHelpers
{
public static string CommunityUrl()
{
// Special case for DiscoCommunity Hosting Network
try
{
var ip = (from addr in Dns.GetHostEntry(Dns.GetHostName()).AddressList
where addr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork
&& addr.ToString().StartsWith("10.131.200.")
select addr).FirstOrDefault();
if (ip != null)
{
return "http://hades3:9393/base/";
}
}
catch (Exception)
{ } // Ignore Errors
return "https://discoict.com.au/base/";
}
}
}
@@ -41,6 +41,22 @@ namespace Disco.Data.Configuration.Modules
}
}
/// <summary>
/// Theme used in noticeboards by default.
/// <see cref="Disco.Services.Extensions.UIHelpers.NoticeboardThemes"/>
/// </summary>
public string DefaultNoticeboardTheme
{
get { return Get("default"); }
set
{
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentNullException("DefaultNoticeboardTheme");
Set(value);
}
}
public LocationModes LocationMode
{
get { return Get<LocationModes>(LocationModes.Unrestricted); }
@@ -1,5 +1,5 @@
using Disco.Data.Repository;
using Disco.Models.BI.Interop.Community;
using Disco.Models.Services.Interop.DiscoServices;
using System;
using System.IO;
@@ -269,11 +269,18 @@ namespace Disco.Data.Configuration
return this.Get<string>(null);
}
}
public UpdateResponse UpdateLastCheck
public string DeploymentSecret
{
get
{
return this.Get<UpdateResponse>(null);
return this.Get<string>(null);
}
}
public UpdateResponseV2 UpdateLastCheckResponse
{
get
{
return this.Get<UpdateResponseV2>(null);
}
set
{
+22 -10
View File
@@ -49,21 +49,21 @@
<Reference Include="System.Data.Entity" />
<Reference Include="System.DirectoryServices" />
<Reference Include="System.Drawing" />
<Reference Include="System.Reactive.Core, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Reference Include="System.Reactive.Core, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-Core.2.2.4\lib\net45\System.Reactive.Core.dll</HintPath>
<HintPath>..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Interfaces, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Reference Include="System.Reactive.Interfaces, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-Interfaces.2.2.4\lib\net45\System.Reactive.Interfaces.dll</HintPath>
<HintPath>..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Linq, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Reference Include="System.Reactive.Linq, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-Linq.2.2.4\lib\net45\System.Reactive.Linq.dll</HintPath>
<HintPath>..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.PlatformServices, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Reference Include="System.Reactive.PlatformServices, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-PlatformServices.2.2.4\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
<HintPath>..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Xml.Linq" />
@@ -73,7 +73,6 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Configuration\CommunityHelpers.cs" />
<Compile Include="Configuration\ConfigurationBase.cs" />
<Compile Include="Configuration\ConfigurationCache.cs" />
<Compile Include="Configuration\Modules\ActiveDirectoryConfiguration.cs" />
@@ -143,6 +142,14 @@
<Compile Include="Migrations\201406160912525_DBv14.Designer.cs">
<DependentUpon>201406160912525_DBv14.cs</DependentUpon>
</Compile>
<Compile Include="Migrations\201407100413342_DBv15.cs" />
<Compile Include="Migrations\201407100413342_DBv15.Designer.cs">
<DependentUpon>201407100413342_DBv15.cs</DependentUpon>
</Compile>
<Compile Include="Migrations\201407260624238_DBv16.cs" />
<Compile Include="Migrations\201407260624238_DBv16.Designer.cs">
<DependentUpon>201407260624238_DBv16.cs</DependentUpon>
</Compile>
<Compile Include="Migrations\Configuration.cs" />
<Compile Include="Migrations\DiscoDataMigrator.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@@ -200,6 +207,12 @@
<EmbeddedResource Include="Migrations\201406160912525_DBv14.resx">
<DependentUpon>201406160912525_DBv14.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Migrations\201407100413342_DBv15.resx">
<DependentUpon>201407100413342_DBv15.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Migrations\201407260624238_DBv16.resx">
<DependentUpon>201407260624238_DBv16.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
@@ -216,7 +229,6 @@
<UserProperties BuildVersion_UpdateFileVersion="True" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_StartDate="2014/6/1" BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildAction="Both" />
</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">
+27
View File
@@ -0,0 +1,27 @@
// <auto-generated />
namespace Disco.Data.Migrations
{
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
public sealed partial class DBv15 : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(DBv15));
string IMigrationMetadata.Id
{
get { return "201407100413342_DBv15"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
}
}
}
@@ -0,0 +1,21 @@
namespace Disco.Data.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class DBv15 : DbMigration
{
public override void Up()
{
AddColumn("dbo.DeviceModels", "DefaultRepairProvider", c => c.String(maxLength: 40));
// Clear UpdateLastCheck due to Update Protocol v2
Sql("DELETE [Configuration] WHERE [Scope]='System' AND [Key]='UpdateLastCheck'");
}
public override void Down()
{
DropColumn("dbo.DeviceModels", "DefaultRepairProvider");
}
}
}
File diff suppressed because one or more lines are too long
+27
View File
@@ -0,0 +1,27 @@
// <auto-generated />
namespace Disco.Data.Migrations
{
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
public sealed partial class DBv16 : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(DBv16));
string IMigrationMetadata.Id
{
get { return "201407260624238_DBv16"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
}
}
}
@@ -0,0 +1,22 @@
namespace Disco.Data.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class DBv16 : DbMigration
{
public override void Up()
{
AddColumn("dbo.DocumentTemplates", "OnGenerateExpression", c => c.String());
AddColumn("dbo.DocumentTemplates", "OnImportAttachmentExpression", c => c.String());
AlterColumn("dbo.DocumentTemplates", "FilterExpression", c => c.String());
}
public override void Down()
{
AlterColumn("dbo.DocumentTemplates", "FilterExpression", c => c.String(maxLength: 250));
DropColumn("dbo.DocumentTemplates", "OnImportAttachmentExpression");
DropColumn("dbo.DocumentTemplates", "OnGenerateExpression");
}
}
}
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.0.0626.0000")]
[assembly: AssemblyFileVersion("2.0.0626.0000")]
[assembly: AssemblyVersion("2.0.0918.1700")]
[assembly: AssemblyFileVersion("2.0.0918.1700")]
+5
View File
@@ -34,6 +34,11 @@ namespace Disco.Data.Repository
var deploymentId = Guid.NewGuid().ToString("D");
Database.ConfigurationItems.Add(new ConfigurationItem { Scope = "System", Key = "DeploymentId", Value = deploymentId });
}
if (Database.ConfigurationItems.Count(ci => ci.Scope == "System" && ci.Key == "DeploymentSecret") == 0)
{
var deploymentId = Guid.NewGuid().ToString("N");
Database.ConfigurationItems.Add(new ConfigurationItem { Scope = "System", Key = "DeploymentSecret", Value = deploymentId });
}
}
public static void SeedJobTypes(this DiscoDataContext Database)
{
+5 -5
View File
@@ -2,9 +2,9 @@
<packages>
<package id="EntityFramework" version="5.0.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="6.0.3" targetFramework="net45" />
<package id="Rx-Core" version="2.2.4" targetFramework="net45" />
<package id="Rx-Interfaces" version="2.2.4" targetFramework="net45" />
<package id="Rx-Linq" version="2.2.4" targetFramework="net45" />
<package id="Rx-Main" version="2.2.4" targetFramework="net45" />
<package id="Rx-PlatformServices" version="2.2.4" targetFramework="net45" />
<package id="Rx-Core" version="2.2.5" targetFramework="net45" />
<package id="Rx-Interfaces" version="2.2.5" targetFramework="net45" />
<package id="Rx-Linq" version="2.2.5" targetFramework="net45" />
<package id="Rx-Main" version="2.2.5" targetFramework="net45" />
<package id="Rx-PlatformServices" version="2.2.5" targetFramework="net45" />
</packages>
@@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Models.BI.Interop.Community
{
public class PluginLibraryCompatibilityItem
{
public string Id { get; set; }
public string Version { get; set; }
public bool Compatible { get; set; }
public string Reason { get; set; }
}
}
@@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Models.BI.Interop.Community
{
public class PluginLibraryCompatibilityRequest
{
public string HostVersion { get; set; }
public string DeploymentId { get; set; }
}
}
@@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Models.BI.Interop.Community
{
public class PluginLibraryCompatibilityResponse
{
public string HostVersion { get; set; }
public DateTime ResponseTimestamp { get; set; }
public List<PluginLibraryCompatibilityItem> Plugins { get; set; }
}
}
@@ -1,23 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Models.BI.Interop.Community
{
public class PluginLibraryItem
{
public string Id { get; set; }
public string Name { get; set; }
public string Author { get; set; }
public string Url { get; set; }
public string Blurb { get; set; }
public string LatestVersion { get; set; }
public string LatestChangeLog { get; set; }
public string LatestHostVersionMin { get; set; }
public string LatestHostVersionMax { get; set; }
public string LatestDownloadUrl { get; set; }
}
}
@@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Models.BI.Interop.Community
{
public class PluginLibraryUpdateRequest
{
public string HostVersion { get; set; }
public string DeploymentId { get; set; }
}
}
@@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Models.BI.Interop.Community
{
public class PluginLibraryUpdateResponse
{
public DateTime ResponseTimestamp { get; set; }
public List<PluginLibraryItem> Plugins { get; set; }
}
}
@@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Disco.Models.BI.Interop.Community
{
public class UpdateRequestBase
{
public virtual int RequestVersion { get; set; }
}
}
@@ -1,42 +0,0 @@
using System;
using System.Collections.Generic;
namespace Disco.Models.BI.Interop.Community
{
public class UpdateRequestV1 : UpdateRequestBase
{
public UpdateRequestV1()
{
this.RequestVersion = 1;
}
public string DeploymentId { get; set; }
public string CurrentDiscoVersion { get; set; }
public bool BetaDeployment { get; set; }
public string OrganisationName { get; set; }
public string BroadbandDoeWanId { get; set; }
public List<Stat> Stat_JobCounts { get; set; }
public List<Stat> Stat_OpenJobCounts { get; set; }
public List<Stat> Stat_ActiveDeviceModelCounts { get; set; }
public List<Stat> Stat_DeviceModelCounts { get; set; }
public List<Stat> Stat_UserCounts { get; set; }
public List<PluginRef> InstalledPlugins { get; set; }
public List<Stat> Stat_JobWarrantyVendorCounts { get; set; }
public class Stat
{
public string Key { get; set; }
public int Count { get; set; }
}
public class PluginRef
{
public string Id { get; set; }
public string Version { get; set; }
}
}
}
@@ -1,24 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Models.BI.Interop.Community
{
public class UpdateResponse
{
public string Version { get; set; }
public DateTime VersionReleasedTimestamp { get; set; }
public string Blurb { get; set; }
public string UrlLink { get; set; }
public DateTime ResponseTimestamp { get; set; }
public bool BetaRelease { get; set; }
public bool IsUpdatable(Version TestVersion)
{
var updateVersion = System.Version.Parse(this.Version);
return (updateVersion > TestVersion);
}
}
}
+26
View File
@@ -0,0 +1,26 @@
using System.ComponentModel.DataAnnotations;
namespace Disco.Models.ClientServices
{
public class Register
{
[Required]
public string DeviceUUID { get; set; }
[Required]
public string DeviceSerialNumber { get; set; }
[Required]
public string DeviceDNSDomainName { get; set; }
[Required]
public string DeviceComputerName { get; set; }
[Required]
public bool DeviceIsPartOfDomain { get; set; }
[Required]
public string DeviceManufacturer { get; set; }
[Required]
public string DeviceModel { get; set; }
[Required]
public string DeviceModelType { get; set; }
}
}
@@ -0,0 +1,13 @@

namespace Disco.Models.ClientServices
{
public class RegisterResponse
{
public string SessionId { get; set; }
public string DeviceDomainName { get; set; }
public string DeviceComputerName { get; set; }
public string ErrorMessage { get; set; }
}
}
+12 -9
View File
@@ -34,6 +34,9 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.6.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Core" />
@@ -46,6 +49,8 @@
</ItemGroup>
<ItemGroup>
<Compile Include="BI\Job\LocationModes.cs" />
<Compile Include="ClientServices\Register.cs" />
<Compile Include="ClientServices\RegisterResponse.cs" />
<Compile Include="Repository\Device\DeviceDecommissionReasons.cs" />
<Compile Include="Repository\User\Flag\UserFlag.cs" />
<Compile Include="Repository\User\Flag\UserFlagAssignment.cs" />
@@ -57,15 +62,6 @@
<Compile Include="BI\Device\ImportDeviceSession.cs" />
<Compile Include="BI\DocumentTemplate\DocumentState.cs" />
<Compile Include="BI\Expressions\IImageExpressionResult.cs" />
<Compile Include="BI\Interop\Community\PluginLibraryCompatibilityItem.cs" />
<Compile Include="BI\Interop\Community\PluginLibraryCompatibilityResponse.cs" />
<Compile Include="BI\Interop\Community\PluginLibraryCompatibilityRequest.cs" />
<Compile Include="BI\Interop\Community\PluginLibraryItem.cs" />
<Compile Include="BI\Interop\Community\PluginLibraryUpdateRequest.cs" />
<Compile Include="BI\Interop\Community\PluginLibraryUpdateResponse.cs" />
<Compile Include="BI\Interop\Community\UpdateRequestBase.cs" />
<Compile Include="BI\Interop\Community\UpdateRequestV1.cs" />
<Compile Include="BI\Interop\Community\UpdateResponse.cs" />
<Compile Include="BI\Job\Statistics\DailyOpenedClosedItem.cs" />
<Compile Include="ClientServices\EnrolResponse.cs" />
<Compile Include="ClientServices\MacEnrol.cs" />
@@ -112,6 +108,12 @@
<Compile Include="Services\Devices\Importing\IDeviceImportContext.cs" />
<Compile Include="Services\Devices\Importing\IDeviceImportField.cs" />
<Compile Include="Services\Interop\ActiveDirectory\ADManagedGroupConfiguration.cs" />
<Compile Include="Services\Interop\DiscoServices\PluginIncompatibility.cs" />
<Compile Include="Services\Interop\DiscoServices\PluginLibraryIncompatibility.cs" />
<Compile Include="Services\Interop\DiscoServices\PluginLibraryManifestV2.cs" />
<Compile Include="Services\Interop\DiscoServices\PublishJobResult.cs" />
<Compile Include="Services\Interop\DiscoServices\UpdateRequestV2.cs" />
<Compile Include="Services\Interop\DiscoServices\UpdateResponseV2.cs" />
<Compile Include="Services\Jobs\JobLists\JobLocationReference.cs" />
<Compile Include="Services\Jobs\JobLists\JobTableItemModel.cs" />
<Compile Include="Services\Jobs\JobLists\JobTableModel.cs" />
@@ -177,6 +179,7 @@
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.0.0626.0000")]
[assembly: AssemblyFileVersion("2.0.0626.0000")]
[assembly: AssemblyVersion("2.0.0918.1700")]
[assembly: AssemblyFileVersion("2.0.0918.1700")]
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Disco.Models.Repository
{
public enum DecommissionReasons
@@ -13,6 +8,7 @@ namespace Disco.Models.Repository
Stolen = 20,
Lost = 30,
Damaged = 40,
Donated = 50
Donated = 50,
Returned = 60
}
}
@@ -33,6 +33,9 @@ namespace Disco.Models.Repository
[StringLength(40)]
public string DefaultWarrantyProvider { get; set; }
[StringLength(40)]
public string DefaultRepairProvider { get; set; }
public virtual IList<DeviceComponent> DeviceComponents { get; set; }
public virtual IList<Device> Devices { get; set; }
@@ -20,14 +20,14 @@ namespace Disco.Models.Repository
[Required, StringLength(10)]
public string ShortName { get; set; }
[StringLength(500)]
[StringLength(500), DataType(DataType.MultilineText)]
public string Description { get; set; }
public int? DefaultOrganisationAddress { get; set; }
// Migration from DeviceProfile Configuration
// 2012-06-14 G#
[Required]
[Required, DataType(DataType.MultilineText)]
public string ComputerNameTemplate { get; set; }
[Required]
@@ -18,8 +18,12 @@ namespace Disco.Models.Repository
public string Description { get; set; }
[Required, StringLength(6)]
public string Scope { get; set; }
[StringLength(250), DataType(DataType.MultilineText)]
[DataType(DataType.MultilineText)]
public string FilterExpression { get; set; }
[DataType(DataType.MultilineText)]
public string OnGenerateExpression { get; set; }
[DataType(DataType.MultilineText)]
public string OnImportAttachmentExpression { get; set; }
// Feature Request 2012-05-10 by G#: https://disco.uservoice.com/forums/159707-feedback/suggestions/2811092-document-template-option-flatten-form-on-generate
public bool FlattenForm { get; set; }
@@ -0,0 +1,12 @@
using System;
namespace Disco.Models.Services.Interop.DiscoServices
{
public class PluginIncompatibility
{
public string PluginId { get; set; }
public Version Version { get; set; }
public string Reason { get; set; }
}
}
@@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace Disco.Models.Services.Interop.DiscoServices
{
public class PluginLibraryIncompatibility
{
public List<PluginIncompatibility> IncompatiblePlugins { get; set; }
}
}
@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
namespace Disco.Models.Services.Interop.DiscoServices
{
public class PluginLibraryManifestV2
{
public DateTime ManifestDate { get; set; }
public List<PluginLibraryItemV2> Plugins { get; set; }
}
public class PluginLibraryItemV2
{
public string Id { get; set; }
public string Name { get; set; }
public string Author { get; set; }
public string InformationUrl { get; set; }
public string PrimaryFeatureCategory { get; set; }
public string Description { get; set; }
public List<PluginLibraryItemReleaseV2> Releases { get; set; }
}
public class PluginLibraryItemReleaseV2
{
public string PluginId { get; set; }
public string Version { get; set; }
public string HostMinVersion { get; set; }
public string HostMaxVersion { get; set; }
public bool Blocked { get; set; }
public string Description { get; set; }
public string DownloadUrl { get; set; }
}
}
@@ -0,0 +1,15 @@

namespace Disco.Models.Services.Interop.DiscoServices
{
public class PublishJobResult
{
public bool Success { get; set; }
public int Id { get; set; }
public string Secret { get; set; }
public string DeepLink { get; set; }
public string PublishMessage { get; set; }
public string ErrorMessage { get; set; }
}
}
@@ -0,0 +1,127 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace Disco.Models.Services.Interop.DiscoServices
{
public class UpdateRequestV2
{
public Guid DeploymentId { get; set; }
public DateTime RequestDate { get; set; }
public string VersionCurrent { get; set; }
public bool IsBetaDeployment { get; set; }
public string OrganisationName { get; set; }
public string VicEduDeptWanId { get; set; }
public List<StatisticInt> Stat_JobCounts { get; set; }
public List<StatisticInt> Stat_OpenJobCounts { get; set; }
public List<StatisticInt> Stat_ActiveDeviceModelCounts { get; set; }
public List<StatisticInt> Stat_DeviceModelCounts { get; set; }
public List<StatisticInt> Stat_UserCounts { get; set; }
public List<StatisticString> InstalledPlugins { get; set; }
public List<StatisticIntPair> Stat_JobIdentifiers { get; set; }
public List<StatisticJob> Stat_Jobs { get; set; }
public class StatisticIntPair
{
[JsonProperty("B")]
public int Begin;
[JsonProperty("E")]
public int End;
}
public class StatisticInt
{
[JsonProperty("K")]
public string Key;
[JsonProperty("V")]
public int Value;
}
public class StatisticString
{
[JsonProperty("K")]
public string Key;
[JsonProperty("V")]
public string Value;
}
public class StatisticJob
{
/// <summary>
/// Job Identifier
/// </summary>
[JsonProperty("I")]
public int Identifier { get; set; }
/// <summary>
/// Opened Date
/// </summary>
[JsonProperty("OD")]
public DateTime OpenedDate { get; set; }
/// <summary>
/// Closed Date
/// </summary>
[JsonProperty("CD", NullValueHandling = NullValueHandling.Ignore)]
public DateTime? ClosedDate { get; set; }
/// <summary>
/// Job Type
/// </summary>
[JsonProperty("T")]
public string Type { get; set; }
/// <summary>
/// Job Sub Types (Semicolon Separated)
/// </summary>
[JsonProperty("ST")]
public string SubTypes { get; set; }
/// <summary>
/// Deployment-Unique Device Serial Identifier (Device Serial Number anonymized via hashing salted with Deployment Secret)
/// </summary>
[JsonProperty("D", NullValueHandling = NullValueHandling.Ignore)]
public string DeviceIdentifier { get; set; }
/// <summary>
/// Deployment-Unique Job User Identifier (Job User Id anonymized via hashing salted with Deployment Secret)
/// </summary>
[JsonProperty("U", NullValueHandling = NullValueHandling.Ignore)]
public string UserIdentifier { get; set; }
/// <summary>
/// Deployment-Unique Job Technician Identifier (Job Technician Id anonymized via hashing salted with Deployment Secret)
/// </summary>
[JsonProperty("TI")]
public string TechnicianIdentifier { get; set; }
/// <summary>
/// Device Model
/// </summary>
[JsonProperty("DM", NullValueHandling = NullValueHandling.Ignore)]
public string DeviceModel { get; set; }
/// <summary>
/// External Repairer
/// </summary>
[JsonProperty("R", NullValueHandling = NullValueHandling.Ignore)]
public string Repairer { get; set; }
/// <summary>
/// External Repairer Logged
/// </summary>
[JsonProperty("RL", NullValueHandling = NullValueHandling.Ignore)]
public DateTime? RepairerLogged { get; set; }
/// <summary>
/// External Repairer Completed
/// </summary>
[JsonProperty("RC", NullValueHandling = NullValueHandling.Ignore)]
public DateTime? RepairerCompleted { get; set; }
}
}
}
@@ -0,0 +1,16 @@
using System;
namespace Disco.Models.Services.Interop.DiscoServices
{
public class UpdateResponseV2
{
public string LatestVersion { get; set; }
public DateTime ReleasedDate { get; set; }
public string Description { get; set; }
public bool IsBetaRelease { get; set; }
public string UrlLink { get; set; }
public DateTime UpdateResponseDate { get; set; }
}
}
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="6.0.3" targetFramework="net45" />
</packages>
+8
View File
@@ -36,6 +36,14 @@
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
+16 -8
View File
@@ -45,8 +45,8 @@ namespace Disco.Services.Authorization
{ "Config.DeviceProfile.Delete", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceProfile.Delete, (c, v) => c.Config.DeviceProfile.Delete = v, "Delete Device Profiles", "Can delete device profiles", false) },
{ "Config.DeviceProfile.Show", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceProfile.Show, (c, v) => c.Config.DeviceProfile.Show = v, "Show Device Profiles", "Can show device profiles", false) },
{ "Config.DocumentTemplate.BulkGenerate", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DocumentTemplate.BulkGenerate, (c, v) => c.Config.DocumentTemplate.BulkGenerate = v, "Bulk Generate Document Templates", "Can bulk generate document templates", false) },
{ "Config.DocumentTemplate.ConfigureFilterExpression", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DocumentTemplate.ConfigureFilterExpression, (c, v) => c.Config.DocumentTemplate.ConfigureFilterExpression = v, "Configure Advanced Expression", "Can configure filter, generate and import expressions for document templates", false) },
{ "Config.DocumentTemplate.Configure", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DocumentTemplate.Configure, (c, v) => c.Config.DocumentTemplate.Configure = v, "Configure Document Templates", "Can configure document templates", false) },
{ "Config.DocumentTemplate.ConfigureFilterExpression", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DocumentTemplate.ConfigureFilterExpression, (c, v) => c.Config.DocumentTemplate.ConfigureFilterExpression = v, "Configure Filter Expression", "Can configure filter expressions for document templates", false) },
{ "Config.DocumentTemplate.Create", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DocumentTemplate.Create, (c, v) => c.Config.DocumentTemplate.Create = v, "Create Document Templates", "Can create document templates", false) },
{ "Config.DocumentTemplate.Delete", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DocumentTemplate.Delete, (c, v) => c.Config.DocumentTemplate.Delete = v, "Delete Document Templates", "Can delete document templates", false) },
{ "Config.DocumentTemplate.UndetectedPages", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DocumentTemplate.UndetectedPages, (c, v) => c.Config.DocumentTemplate.UndetectedPages = v, "Process Undetected Pages", "Can show and assign imported documents which were not undetected", false) },
@@ -133,6 +133,7 @@ namespace Disco.Services.Authorization
{ "Job.Properties.NonWarrantyProperties.PurchaseOrderRaised", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.PurchaseOrderRaised, (c, v) => c.Job.Properties.NonWarrantyProperties.PurchaseOrderRaised = v, "Purchase Order Raised Property", "Can update property", false) },
{ "Job.Properties.NonWarrantyProperties.PurchaseOrderReference", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.PurchaseOrderReference, (c, v) => c.Job.Properties.NonWarrantyProperties.PurchaseOrderReference = v, "Purchase Order Reference Property", "Can update property", false) },
{ "Job.Properties.NonWarrantyProperties.PurchaseOrderSent", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.PurchaseOrderSent, (c, v) => c.Job.Properties.NonWarrantyProperties.PurchaseOrderSent = v, "Purchase Order Sent Property", "Can update property", false) },
{ "Job.Properties.NonWarrantyProperties.RepairProviderDetails", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.RepairProviderDetails, (c, v) => c.Job.Properties.NonWarrantyProperties.RepairProviderDetails = v, "Repair Provider Details", "Can access repair provider details", false) },
{ "Job.Properties.NonWarrantyProperties.RepairerCompletedDate", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.RepairerCompletedDate, (c, v) => c.Job.Properties.NonWarrantyProperties.RepairerCompletedDate = v, "Repairer Completed Date Property", "Can update property", false) },
{ "Job.Properties.NonWarrantyProperties.RepairerLoggedDate", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.RepairerLoggedDate, (c, v) => c.Job.Properties.NonWarrantyProperties.RepairerLoggedDate = v, "Repairer Logged Date Property", "Can update property", false) },
{ "Job.Properties.NonWarrantyProperties.RepairerName", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.RepairerName, (c, v) => c.Job.Properties.NonWarrantyProperties.RepairerName = v, "Repairer Name Property", "Can update property", false) },
@@ -252,8 +253,8 @@ namespace Disco.Services.Authorization
}),
new ClaimNavigatorItem("Config.DocumentTemplate", "Document Templates", "Permissions related to Document Templates", false, new List<IClaimNavigatorItem>() {
new ClaimNavigatorItem("Config.DocumentTemplate.BulkGenerate", false),
new ClaimNavigatorItem("Config.DocumentTemplate.Configure", false),
new ClaimNavigatorItem("Config.DocumentTemplate.ConfigureFilterExpression", false),
new ClaimNavigatorItem("Config.DocumentTemplate.Configure", false),
new ClaimNavigatorItem("Config.DocumentTemplate.Create", false),
new ClaimNavigatorItem("Config.DocumentTemplate.Delete", false),
new ClaimNavigatorItem("Config.DocumentTemplate.UndetectedPages", false),
@@ -352,6 +353,7 @@ namespace Disco.Services.Authorization
new ClaimNavigatorItem("Job.Properties.NonWarrantyProperties.PurchaseOrderRaised", false),
new ClaimNavigatorItem("Job.Properties.NonWarrantyProperties.PurchaseOrderReference", false),
new ClaimNavigatorItem("Job.Properties.NonWarrantyProperties.PurchaseOrderSent", false),
new ClaimNavigatorItem("Job.Properties.NonWarrantyProperties.RepairProviderDetails", false),
new ClaimNavigatorItem("Job.Properties.NonWarrantyProperties.RepairerCompletedDate", false),
new ClaimNavigatorItem("Job.Properties.NonWarrantyProperties.RepairerLoggedDate", false),
new ClaimNavigatorItem("Job.Properties.NonWarrantyProperties.RepairerName", false),
@@ -557,8 +559,8 @@ namespace Disco.Services.Authorization
c.Config.DeviceProfile.Delete = true;
c.Config.DeviceProfile.Show = true;
c.Config.DocumentTemplate.BulkGenerate = true;
c.Config.DocumentTemplate.Configure = true;
c.Config.DocumentTemplate.ConfigureFilterExpression = true;
c.Config.DocumentTemplate.Configure = true;
c.Config.DocumentTemplate.Create = true;
c.Config.DocumentTemplate.Delete = true;
c.Config.DocumentTemplate.UndetectedPages = true;
@@ -645,6 +647,7 @@ namespace Disco.Services.Authorization
c.Job.Properties.NonWarrantyProperties.PurchaseOrderRaised = true;
c.Job.Properties.NonWarrantyProperties.PurchaseOrderReference = true;
c.Job.Properties.NonWarrantyProperties.PurchaseOrderSent = true;
c.Job.Properties.NonWarrantyProperties.RepairProviderDetails = true;
c.Job.Properties.NonWarrantyProperties.RepairerCompletedDate = true;
c.Job.Properties.NonWarrantyProperties.RepairerLoggedDate = true;
c.Job.Properties.NonWarrantyProperties.RepairerName = true;
@@ -894,16 +897,16 @@ namespace Disco.Services.Authorization
/// </summary>
public const string BulkGenerate = "Config.DocumentTemplate.BulkGenerate";
/// <summary>Configure Advanced Expression
/// <para>Can configure filter, generate and import expressions for document templates</para>
/// </summary>
public const string ConfigureFilterExpression = "Config.DocumentTemplate.ConfigureFilterExpression";
/// <summary>Configure Document Templates
/// <para>Can configure document templates</para>
/// </summary>
public const string Configure = "Config.DocumentTemplate.Configure";
/// <summary>Configure Filter Expression
/// <para>Can configure filter expressions for document templates</para>
/// </summary>
public const string ConfigureFilterExpression = "Config.DocumentTemplate.ConfigureFilterExpression";
/// <summary>Create Document Templates
/// <para>Can create document templates</para>
/// </summary>
@@ -1424,6 +1427,11 @@ namespace Disco.Services.Authorization
/// </summary>
public const string PurchaseOrderSent = "Job.Properties.NonWarrantyProperties.PurchaseOrderSent";
/// <summary>Repair Provider Details
/// <para>Can access repair provider details</para>
/// </summary>
public const string RepairProviderDetails = "Job.Properties.NonWarrantyProperties.RepairProviderDetails";
/// <summary>Repairer Completed Date Property
/// <para>Can update property</para>
/// </summary>
@@ -12,7 +12,7 @@ namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.DocumentT
[ClaimDetails("Configure Document Templates", "Can configure document templates")]
public bool Configure { get; set; }
[ClaimDetails("Configure Filter Expression", "Can configure filter expressions for document templates")]
[ClaimDetails("Configure Advanced Expression", "Can configure filter, generate and import expressions for document templates")]
public bool ConfigureFilterExpression { get; set; }
[ClaimDetails("Upload Document Templates", "Can upload document templates")]
@@ -44,6 +44,9 @@ namespace Disco.Services.Authorization.Roles.ClaimGroups.Job
[ClaimDetails("Repairer Reference Property", "Can update property")]
public bool RepairerReference { get; set; }
[ClaimDetails("Repair Provider Details", "Can access repair provider details")]
public bool RepairProviderDetails { get; set; }
[ClaimDetails("Insurance Detail Properties", "Can update insurance detail properties")]
public bool InsuranceDetails { get; set; }
}
@@ -157,12 +157,15 @@ namespace Disco.Services.Authorization.Roles
/// </summary>
private static void MigrateAuthorizationRoles(DiscoDataContext Database)
{
// Use 'MyJobs' (A new claim) to detect if the Role hasn't been migrated yet
var affectedRoles = Database.AuthorizationRoles.Where(r => !r.ClaimsJson.Contains("MyJobs")).ToList();
// Determine roles which need migration from DBv11 -> DBv14
var affectedRoles_DBv14 = Database.AuthorizationRoles.Where(r => !r.ClaimsJson.Contains("MyJobs")).ToList();
// Determine roles which need migration from DBv14 -> DBv15
var affectedRoles_DBv15 = Database.AuthorizationRoles.Where(r => !r.ClaimsJson.Contains("RepairProviderDetails")).ToList();
if (affectedRoles.Count > 0)
if (affectedRoles_DBv14.Count > 0)
{
foreach (var role in affectedRoles)
foreach (var role in affectedRoles_DBv14)
{
var claims = JsonConvert.DeserializeObject<RoleClaims>(role.ClaimsJson);
@@ -204,6 +207,24 @@ namespace Disco.Services.Authorization.Roles
Database.SaveChanges();
}
if (affectedRoles_DBv15.Count > 0)
{
foreach (var role in affectedRoles_DBv15)
{
var claims = JsonConvert.DeserializeObject<RoleClaims>(role.ClaimsJson);
// If the user previously had the ability to view warranty provider details, they probably should be able to view repair provider details (new feature).
if (claims.Job.Properties.WarrantyProperties.ProviderDetails)
{
claims.Job.Properties.NonWarrantyProperties.RepairProviderDetails = true;
}
role.ClaimsJson = Newtonsoft.Json.JsonConvert.SerializeObject(claims);
}
Database.SaveChanges();
}
}
}
}
@@ -120,7 +120,10 @@ namespace Disco.Services.Devices.Exporting
case DeviceExportTypes.All:
return GenerateExport(Database, Database.Devices, Options, TaskStatus);
case DeviceExportTypes.Batch:
return GenerateExport(Database, Database.Devices.Where(d => d.DeviceBatchId == Options.ExportTypeTargetId), Options, TaskStatus);
if (Options.ExportTypeTargetId.HasValue && Options.ExportTypeTargetId.Value > 0)
return GenerateExport(Database, Database.Devices.Where(d => d.DeviceBatchId == Options.ExportTypeTargetId), Options, TaskStatus);
else
return GenerateExport(Database, Database.Devices.Where(d => d.DeviceBatchId == null), Options, TaskStatus);
case DeviceExportTypes.Model:
return GenerateExport(Database, Database.Devices.Where(d => d.DeviceModelId == Options.ExportTypeTargetId), Options, TaskStatus);
case DeviceExportTypes.Profile:
@@ -36,7 +36,7 @@ namespace Disco.Services.Devices.ManagedGroups
(e.EventType == RepositoryMonitorEventType.Added &&
ActiveDirectory.IsValidDomainAccountId(((Device)e.Entity).DeviceDomainId)) ||
(e.EventType == RepositoryMonitorEventType.Modified &&
(e.ModifiedProperties.Contains("DeviceBatchId") || e.ModifiedProperties.Contains("DeviceDomainId"))) ||
(e.ModifiedProperties.Contains("DeviceBatchId") || e.ModifiedProperties.Contains("DeviceDomainId") || e.ModifiedProperties.Contains("LastEnrolDate"))) ||
(e.EventType == RepositoryMonitorEventType.Deleted)
)
));
@@ -37,7 +37,7 @@ namespace Disco.Services.Devices.ManagedGroups
(e.EventType == RepositoryMonitorEventType.Added &&
ActiveDirectory.IsValidDomainAccountId(((Device)e.Entity).DeviceDomainId)) ||
(e.EventType == RepositoryMonitorEventType.Modified &&
(e.ModifiedProperties.Contains("DeviceProfileId") || e.ModifiedProperties.Contains("DeviceDomainId"))) ||
(e.ModifiedProperties.Contains("DeviceProfileId") || e.ModifiedProperties.Contains("DeviceDomainId") || e.ModifiedProperties.Contains("LastEnrolDate"))) ||
(e.EventType == RepositoryMonitorEventType.Deleted)
)
));
+46 -18
View File
@@ -39,18 +39,26 @@
<Reference Include="EntityFramework">
<HintPath>..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll</HintPath>
</Reference>
<Reference Include="Exceptionless">
<HintPath>..\packages\Exceptionless.1.5.2092\lib\net45\Exceptionless.dll</HintPath>
</Reference>
<Reference Include="Exceptionless.Models">
<HintPath>..\packages\Exceptionless.1.5.2092\lib\net45\Exceptionless.Models.dll</HintPath>
</Reference>
<Reference Include="LumenWorks.Framework.IO">
<HintPath>..\packages\LumenWorks.Framework.IO.3.8.0\lib\net20\LumenWorks.Framework.IO.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AspNet.SignalR.Core, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Reference Include="Microsoft.AspNet.SignalR.Core, Version=2.1.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.SignalR.Core.2.1.0\lib\net45\Microsoft.AspNet.SignalR.Core.dll</HintPath>
<HintPath>..\packages\Microsoft.AspNet.SignalR.Core.2.1.1\lib\net45\Microsoft.AspNet.SignalR.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin">
<HintPath>..\packages\Microsoft.Owin.2.0.1\lib\net45\Microsoft.Owin.dll</HintPath>
<Reference Include="Microsoft.Owin, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.2.1.0\lib\net45\Microsoft.Owin.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.Security">
<HintPath>..\packages\Microsoft.Owin.Security.2.0.1\lib\net45\Microsoft.Owin.Security.dll</HintPath>
<Reference Include="Microsoft.Owin.Security, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Security.2.1.0\lib\net45\Microsoft.Owin.Security.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
@@ -79,21 +87,29 @@
</Reference>
<Reference Include="System.DirectoryServices" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Reactive.Core, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-Core.2.2.4\lib\net45\System.Reactive.Core.dll</HintPath>
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.Extensions">
<HintPath>..\packages\Microsoft.Net.Http.2.2.22\lib\net45\System.Net.Http.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Interfaces, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-Interfaces.2.2.4\lib\net45\System.Reactive.Interfaces.dll</HintPath>
<Reference Include="System.Net.Http.Primitives">
<HintPath>..\packages\Microsoft.Net.Http.2.2.22\lib\net45\System.Net.Http.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Linq, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Reactive.Core, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-Linq.2.2.4\lib\net45\System.Reactive.Linq.dll</HintPath>
<HintPath>..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.PlatformServices, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Reference Include="System.Reactive.Interfaces, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-PlatformServices.2.2.4\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
<HintPath>..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Linq, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.PlatformServices, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions" />
@@ -236,6 +252,13 @@
<Compile Include="Interop\ActiveDirectory\ADUserAccount.cs" />
<Compile Include="Interop\ActiveDirectory\Description.cs" />
<Compile Include="Interop\ActiveDirectory\IADObject.cs" />
<Compile Include="Interop\DiscoServices\DiscoServiceHelpers.cs" />
<Compile Include="Interop\DiscoServices\Jobs.cs" />
<Compile Include="Interop\DiscoServices\PluginLibrary.cs" />
<Compile Include="Interop\DiscoServices\PluginLibraryUpdateTask.cs" />
<Compile Include="Interop\VicEduDept\VicSmart.cs" />
<Compile Include="Interop\DiscoServices\UpdateQuery.cs" />
<Compile Include="Interop\DiscoServices\UpdateQueryTask.cs" />
<Compile Include="Jobs\JobExtensions.cs" />
<Compile Include="Jobs\JobLists\JobTableExtensions.cs" />
<Compile Include="Jobs\JobQueues\Cache.cs" />
@@ -260,7 +283,8 @@
<Compile Include="Logging\Persistance\LogPersistContext.cs" />
<Compile Include="Logging\Persistance\LogPersistContextInitializer.cs" />
<Compile Include="Logging\Utilities.cs" />
<Compile Include="Plugins\CommunityInterop\PluginLibraryUpdateTask.cs" />
<Compile Include="Plugins\Features\RepairProvider\RepairProviderFeature.cs" />
<Compile Include="Plugins\Features\RepairProvider\RepairProviderSubmitJobException.cs" />
<Compile Include="Plugins\Features\UIExtension\Results\LiteralResult.cs" />
<Compile Include="Plugins\Features\UIExtension\Results\MultipleResult.cs" />
<Compile Include="Plugins\Features\UIExtension\Results\PluginResourceCssResult.cs" />
@@ -372,7 +396,11 @@
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" />
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
</Target>
<!-- 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">
+38 -2
View File
@@ -17,6 +17,10 @@ namespace Disco.Services.Extensions
/// User-selectable Colour Themes
/// </summary>
public static ReadOnlyCollection<KeyValuePair<string, string>> ThemeColours { get; private set; }
/// <summary>
/// Noticeboard Colour Themes
/// </summary>
public static ReadOnlyCollection<KeyValuePair<string, string>> NoticeboardThemes { get; private set; }
/// <summary>
/// Returns a randomly selected Icon using <see cref="System.Random"/>.
@@ -73,6 +77,7 @@ namespace Disco.Services.Extensions
new KeyValuePair<string, string>("android" , "Android"),
new KeyValuePair<string, string>("apple" , "Apple"),
new KeyValuePair<string, string>("archive" , "Archive"),
new KeyValuePair<string, string>("area-chart" , "Area Chart"),
new KeyValuePair<string, string>("arrow-circle-down" , "Arrow Circle Down"),
new KeyValuePair<string, string>("arrow-circle-left" , "Arrow Circle Left"),
new KeyValuePair<string, string>("arrow-circle-right" , "Arrow Circle Right"),
@@ -81,16 +86,20 @@ namespace Disco.Services.Extensions
new KeyValuePair<string, string>("ban" , "Ban"),
new KeyValuePair<string, string>("beer" , "Beer"),
new KeyValuePair<string, string>("bell" , "Bell"),
new KeyValuePair<string, string>("binoculars" , "Binoculars"),
new KeyValuePair<string, string>("bolt" , "Bolt"),
new KeyValuePair<string, string>("bomb" , "Bomb"),
new KeyValuePair<string, string>("book" , "Book"),
new KeyValuePair<string, string>("bookmark" , "Bookmark"),
new KeyValuePair<string, string>("briefcase" , "Briefcase"),
new KeyValuePair<string, string>("bug" , "Bug"),
new KeyValuePair<string, string>("bicycle" , "Bicycle"),
new KeyValuePair<string, string>("building-o" , "Building"),
new KeyValuePair<string, string>("bullhorn" , "Bullhorn"),
new KeyValuePair<string, string>("bullseye" , "Bullseye"),
new KeyValuePair<string, string>("bus" , "Bus"),
new KeyValuePair<string, string>("cab" , "Cab"),
new KeyValuePair<string, string>("calculator" , "Calculator"),
new KeyValuePair<string, string>("calendar" , "Calendar"),
new KeyValuePair<string, string>("calendar-o" , "Calendar"),
new KeyValuePair<string, string>("car" , "Car"),
@@ -111,6 +120,7 @@ namespace Disco.Services.Extensions
new KeyValuePair<string, string>("envelope" , "Envelope"),
new KeyValuePair<string, string>("exclamation" , "Exclamation"),
new KeyValuePair<string, string>("eye" , "Eye"),
new KeyValuePair<string, string>("eyedropper" , "Eyedropper"),
new KeyValuePair<string, string>("fax" , "Fax"),
new KeyValuePair<string, string>("female" , "Female"),
new KeyValuePair<string, string>("fighter-jet" , "Fighter Jet"),
@@ -142,6 +152,7 @@ namespace Disco.Services.Extensions
new KeyValuePair<string, string>("legal" , "Legal"),
new KeyValuePair<string, string>("life-ring" , "Life Ring"),
new KeyValuePair<string, string>("lightbulb-o" , "Lightbulb"),
new KeyValuePair<string, string>("line-chart" , "Line Chart"),
new KeyValuePair<string, string>("linux" , "Linux"),
new KeyValuePair<string, string>("location-arrow" , "Location Arrow"),
new KeyValuePair<string, string>("magnet" , "Magnet"),
@@ -156,13 +167,17 @@ namespace Disco.Services.Extensions
new KeyValuePair<string, string>("money" , "Money"),
new KeyValuePair<string, string>("moon-o" , "Moon"),
new KeyValuePair<string, string>("music" , "Music"),
new KeyValuePair<string, string>("newspaper-o" , "Newspaper"),
new KeyValuePair<string, string>("paint-brush" , "Paint Brush"),
new KeyValuePair<string, string>("paper-plane" , "Paper Plane"),
new KeyValuePair<string, string>("paperclip" , "Paperclip"),
new KeyValuePair<string, string>("paw" , "Paw"),
new KeyValuePair<string, string>("pencil" , "Pencil"),
new KeyValuePair<string, string>("phone" , "Phone"),
new KeyValuePair<string, string>("pie-chart" , "Pie Chart"),
new KeyValuePair<string, string>("picture-o" , "Picture"),
new KeyValuePair<string, string>("plane" , "Plane"),
new KeyValuePair<string, string>("plug" , "Plug"),
new KeyValuePair<string, string>("power-off" , "Power Off"),
new KeyValuePair<string, string>("print" , "Print"),
new KeyValuePair<string, string>("puzzle-piece" , "Puzzle Piece"),
@@ -188,14 +203,15 @@ namespace Disco.Services.Extensions
new KeyValuePair<string, string>("thumbs-o-up" , "Thumbs Up"),
new KeyValuePair<string, string>("thumbs-up" , "Thumbs Up"),
new KeyValuePair<string, string>("thumb-tack" , "Thumb Tack"),
new KeyValuePair<string, string>("trash-o" , "Trash"),
new KeyValuePair<string, string>("trash" , "Trash"),
new KeyValuePair<string, string>("trophy" , "Trophy"),
new KeyValuePair<string, string>("truck" , "Truck"),
new KeyValuePair<string, string>("umbrella" , "Umbrella"),
new KeyValuePair<string, string>("university" , "University"),
new KeyValuePair<string, string>("wheelchair" , "Wheelchair"),
new KeyValuePair<string, string>("windows" , "Windows"),
new KeyValuePair<string, string>("wrench" , "Wrench")
new KeyValuePair<string, string>("wrench" , "Wrench"),
new KeyValuePair<string, string>("wifi" , "WiFi")
}.AsReadOnly();
// Icon Colours
@@ -221,6 +237,26 @@ namespace Disco.Services.Extensions
new KeyValuePair<string, string>("mauve" , "Mauve"),
new KeyValuePair<string, string>("sienna" , "Sienna")
}.AsReadOnly();
// Noticeboard Themes
NoticeboardThemes = new List<KeyValuePair<string, string>>(){
new KeyValuePair<string, string>("default" , "Default Blue"),
new KeyValuePair<string, string>("default-soft" , "Default Blue Soft"),
new KeyValuePair<string, string>("green" , "Green"),
new KeyValuePair<string, string>("green-soft" , "Green Soft"),
new KeyValuePair<string, string>("violet" , "Violet"),
new KeyValuePair<string, string>("violet-soft" , "Violet Soft"),
new KeyValuePair<string, string>("magenta" , "Magenta"),
new KeyValuePair<string, string>("magenta-soft" , "Magenta Soft"),
new KeyValuePair<string, string>("crimson" , "Crimson"),
new KeyValuePair<string, string>("crimson-soft" , "Crimson Soft"),
new KeyValuePair<string, string>("amber" , "Amber"),
new KeyValuePair<string, string>("amber-soft" , "Amber Soft"),
new KeyValuePair<string, string>("brown" , "Brown"),
new KeyValuePair<string, string>("brown-soft" , "Brown Soft"),
new KeyValuePair<string, string>("steel" , "Steel"),
new KeyValuePair<string, string>("steel-soft" , "Steel Soft")
}.AsReadOnly();
}
}
}
@@ -107,18 +107,18 @@ namespace Disco.Services.Interop.ActiveDirectory
IEnumerable<ADDomainController> availableServers;
// Try Site Servers first
availableServers = AvilableDomainControllers(RequireSiteServer: true, RequireWritable: RequireWritable);
availableServers = AvailableDomainControllers(RequireSiteServer: true, RequireWritable: RequireWritable);
if (!availableServers.Any())
{
// No Site Servers available - try all
availableServers = AvilableDomainControllers(RequireSiteServer: false, RequireWritable: RequireWritable);
availableServers = AvailableDomainControllers(RequireSiteServer: false, RequireWritable: RequireWritable);
if (!availableServers.Any())
{
lock (domainMaintainLock)
{
availableServers = AvilableDomainControllers(RequireSiteServer: false, RequireWritable: RequireWritable);
availableServers = AvailableDomainControllers(RequireSiteServer: false, RequireWritable: RequireWritable);
if (!availableServers.Any())
return DiscoverAvailableDomainController(RequireWritable);
@@ -142,7 +142,7 @@ namespace Disco.Services.Interop.ActiveDirectory
return availableServers.ElementAt(dcrrValue);
}
}
private IEnumerable<ADDomainController> AvilableDomainControllers(bool RequireSiteServer, bool RequireWritable)
private IEnumerable<ADDomainController> AvailableDomainControllers(bool RequireSiteServer, bool RequireWritable)
{
IEnumerable<ADDomainController> query = this.DomainControllers.Where(dc => dc.IsAvailable);
if (RequireSiteServer)
@@ -0,0 +1,21 @@
using System;
namespace Disco.Services.Interop.DiscoServices
{
public static class DiscoServiceHelpers
{
[Obsolete]
public static string CommunityUrl()
{
return "https://discoict.com.au/base/";
}
public static string ServicesUrl
{
get
{
return "https://services.discoict.com.au/";
}
}
}
}
@@ -0,0 +1,103 @@
using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Models.Services.Interop.DiscoServices;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
namespace Disco.Services.Interop.DiscoServices
{
public static class Jobs
{
private static string ServiceUrl(string Action)
{
return string.Concat(DiscoServiceHelpers.ServicesUrl, "API/Jobs/", Action);
}
public static PublishJobResult Publish(DiscoDataContext Database, Job Job, User TechUser, string Recipient, string RecipientReference, string Comments, List<JobAttachment> Attachments, Func<JobAttachment, DiscoDataContext, string> AttachmentFilenameRetriever)
{
var url = ServiceUrl("Publish");
using (var httpClient = new HttpClient())
{
using (var formData = new MultipartFormDataContent())
{
formData.Add(new StringContent(Database.DiscoConfiguration.DeploymentId), "DeploymentId");
formData.Add(new StringContent(Job.Id.ToString()), "JobId");
formData.Add(new StringContent(TechUser.UserId), "TechnicianId");
formData.Add(new StringContent(TechUser.DisplayName ?? TechUser.UserId), "TechnicianName");
if (!string.IsNullOrWhiteSpace(TechUser.PhoneNumber))
formData.Add(new StringContent(TechUser.PhoneNumber), "TechnicianPhone");
if (!string.IsNullOrWhiteSpace(TechUser.EmailAddress))
formData.Add(new StringContent(TechUser.EmailAddress), "TechnicianEmail");
formData.Add(new StringContent(Recipient), "Recipient");
if (!string.IsNullOrWhiteSpace(RecipientReference))
formData.Add(new StringContent(RecipientReference), "RecipientReference");
if (!string.IsNullOrWhiteSpace(Comments))
formData.Add(new StringContent(Comments), "PublishedComments");
if (Attachments != null && Attachments.Count > 0)
{
Attachments
.Select(a => new { Attachment = a, Filename = AttachmentFilenameRetriever(a, Database) })
.Where(a => System.IO.File.Exists(a.Filename))
.Select((a, i) => new { Attachment = a.Attachment, Filename = a.Filename, Index = i })
.ToList()
.ForEach(a =>
{
formData.Add(new StringContent(a.Attachment.Filename), string.Format("Attachments[{0}].Filename", a.Index));
formData.Add(new StringContent(a.Attachment.MimeType), string.Format("Attachments[{0}].MimeType", a.Index));
formData.Add(new StringContent(a.Attachment.Timestamp.ToISO8601()), string.Format("Attachments[{0}].CreatedDate", a.Index));
if (a.Attachment.DocumentTemplateId != null)
formData.Add(new StringContent(a.Attachment.DocumentTemplateId), string.Format("Attachments[{0}].DocumentTemplateId", a.Index));
if (a.Attachment.Comments != null)
formData.Add(new StringContent(a.Attachment.Comments), string.Format("Attachments[{0}].Comments", a.Index));
formData.Add(new ByteArrayContent(File.ReadAllBytes(a.Filename)), string.Format("Attachments[{0}].File", a.Index), a.Attachment.Filename);
});
}
var response = httpClient.PostAsync(url, formData).Result;
response.EnsureSuccessStatusCode();
var resultJson = response.Content.ReadAsStringAsync().Result;
var result = JsonConvert.DeserializeObject<PublishJobResult>(resultJson);
return result;
}
}
}
public static PublishJobResult UpdateRecipientReference(DiscoDataContext Database, Job Job, int PublishedJobId, string PublishedJobSecret, string RecipientReference)
{
var url = ServiceUrl("UpdateRecipientReference");
using (var httpClient = new HttpClient())
{
using (var formData = new FormUrlEncodedContent(new KeyValuePair<string, string>[] {
new KeyValuePair<string, string>("PublishedJobId", PublishedJobId.ToString()),
new KeyValuePair<string, string>("PublishedJobSecret", PublishedJobSecret),
new KeyValuePair<string, string>("RecipientReference", RecipientReference)
}))
{
var response = httpClient.PostAsync(url, formData).Result;
response.EnsureSuccessStatusCode();
var resultJson = response.Content.ReadAsStringAsync().Result;
var result = JsonConvert.DeserializeObject<PublishJobResult>(resultJson);
return result;
}
}
}
}
}
@@ -0,0 +1,149 @@
using Disco.Data.Repository;
using Disco.Models.Services.Interop.DiscoServices;
using Disco.Services.Tasks;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Web;
namespace Disco.Services.Interop.DiscoServices
{
public static class PluginLibrary
{
private static string UpdateUrl()
{
return string.Concat(DiscoServiceHelpers.ServicesUrl, "API/Plugins/Library/V2");
}
public static string InitialManifestFilename()
{
return HttpContext.Current.Server.MapPath("~/ClientBin/DiscoServices.InitialPluginLibraryManifest.json");
}
public static string ManifestFilename(DiscoDataContext Database)
{
return Path.Combine(Database.DiscoConfiguration.PluginPackagesLocation, "LibraryManifest.json");
}
public static PluginLibraryManifestV2 LoadManifest(DiscoDataContext Database)
{
var manifestFile = ManifestFilename(Database);
if (File.Exists(manifestFile))
{
return JsonConvert.DeserializeObject<PluginLibraryManifestV2>(File.ReadAllText(manifestFile));
}
else
{
// Use Initial Plugin Library Manifest
manifestFile = InitialManifestFilename();
if (File.Exists(manifestFile))
return JsonConvert.DeserializeObject<PluginLibraryManifestV2>(File.ReadAllText(manifestFile));
throw new FileNotFoundException("No plugin library manifest file was found", manifestFile);
}
}
public static PluginLibraryIncompatibility LoadIncompatibilityData(this PluginLibraryManifestV2 LibraryManifest)
{
var pluginAssembly = typeof(PluginLibrary).Assembly;
Version hostVersion = pluginAssembly.GetName().Version;
return new PluginLibraryIncompatibility()
{
IncompatiblePlugins = LibraryManifest.Plugins.SelectMany(p => p.Releases, (p, r) =>
{
var rVersion = Version.Parse(r.Version);
if (r.Blocked)
return new PluginIncompatibility() { PluginId = r.PluginId, Version = rVersion, Reason = "This plugin release is blocked by Disco ICT Online Services" };
if (r.HostMinVersion != null && hostVersion < Version.Parse(r.HostMinVersion))
return new PluginIncompatibility() { PluginId = r.PluginId, Version = rVersion, Reason = string.Format("This plugin requires v{0} or newer", r.HostMinVersion) };
if (r.HostMaxVersion != null && hostVersion > Version.Parse(r.HostMaxVersion))
return new PluginIncompatibility() { PluginId = r.PluginId, Version = rVersion, Reason = string.Format("This plugin requires v{0} or older", r.HostMaxVersion) };
return null;
}).Where(i => i != null).ToList()
};
}
public static PluginLibraryManifestV2 UpdateManifest(DiscoDataContext Database, IScheduledTaskStatus Status)
{
Status.UpdateStatus(10, "Sending Request");
PluginLibraryManifestV2 result;
var discoVersion = UpdateQuery.CurrentDiscoVersionFormatted();
var url = UpdateUrl();
using (var httpClient = new HttpClient())
{
using (var formData = new FormUrlEncodedContent(new KeyValuePair<string, string>[] {
new KeyValuePair<string, string>("DeploymentId", Database.DiscoConfiguration.DeploymentId),
new KeyValuePair<string, string>("DiscoVersion", discoVersion)
}))
{
var response = httpClient.PostAsync(url, formData).Result;
response.EnsureSuccessStatusCode();
Status.UpdateStatus(50, "Waiting for Response");
var resultJson = response.Content.ReadAsStringAsync().Result;
Status.UpdateStatus(90, "Processing Response");
result = JsonConvert.DeserializeObject<PluginLibraryManifestV2>(resultJson);
}
}
var manifestJson = JsonConvert.SerializeObject(result);
var manifestFile = PluginLibrary.ManifestFilename(Database);
if (!Directory.Exists(Path.GetDirectoryName(manifestFile)))
Directory.CreateDirectory(Path.GetDirectoryName(manifestFile));
File.WriteAllText(manifestFile, manifestJson);
return result;
}
public static PluginLibraryItemReleaseV2 LatestCompatibleRelease(this PluginLibraryItemV2 LibraryItem, PluginLibraryIncompatibility Incompatibility)
{
return LibraryItem.Releases.OrderByDescending(r => Version.Parse(r.Version)).FirstOrDefault(r => Incompatibility.IsCompatible(r));
}
public static bool IsCompatible(this PluginLibraryIncompatibility IncompatibilityLibrary, PluginLibraryItemReleaseV2 Release)
{
PluginIncompatibility incompatibility;
return IsCompatible(IncompatibilityLibrary, Release, out incompatibility);
}
public static bool IsCompatible(this PluginLibraryIncompatibility IncompatibilityLibrary, PluginLibraryItemReleaseV2 Release, out PluginIncompatibility Incompatibility)
{
return IsCompatible(IncompatibilityLibrary, Release.PluginId, Version.Parse(Release.Version), out Incompatibility);
}
public static bool IsCompatible(this PluginLibraryIncompatibility IncompatibilityLibrary, string PluginId, Version Version)
{
PluginIncompatibility incompatibility;
return IsCompatible(IncompatibilityLibrary, PluginId, Version, out incompatibility);
}
public static bool IsCompatible(this PluginLibraryIncompatibility IncompatibilityLibrary, string PluginId, Version Version, out PluginIncompatibility Incompatibility)
{
Incompatibility = IncompatibilityLibrary.IncompatiblePlugins.FirstOrDefault(i => i.PluginId.Equals(PluginId, StringComparison.OrdinalIgnoreCase) && i.Version == Version);
return Incompatibility == null;
}
}
}
@@ -0,0 +1,63 @@
using Disco.Data.Repository;
using Disco.Services.Tasks;
using Newtonsoft.Json;
using Quartz;
using System;
using System.IO;
using System.Linq;
namespace Disco.Services.Interop.DiscoServices
{
public class PluginLibraryUpdateTask : ScheduledTask
{
public override string TaskName { get { return "Disco ICT - Update Plugin Library"; } }
public override bool SingleInstanceTask { get { return true; } }
public override bool CancelInitiallySupported { get { return false; } }
public override void InitalizeScheduledTask(DiscoDataContext Database)
{
// Random time between midday and midnight.
var rnd = new Random();
var rndHour = rnd.Next(12, 23);
var rndMinute = rnd.Next(0, 59);
TriggerBuilder triggerBuilder = TriggerBuilder.Create().
WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(rndHour, rndMinute));
this.ScheduleTask(triggerBuilder);
}
protected override void ExecuteTask()
{
using (DiscoDataContext database = new DiscoDataContext())
{
Status.UpdateStatus(1, "Updating Plugin Library Manifest", "Initializing");
var manifest = PluginLibrary.UpdateManifest(database, this.Status);
Status.SetFinishedMessage("The Plugin Library Manifest was updated successfully");
}
}
public static ScheduledTaskStatus ScheduleNow()
{
var taskStatus = RunningStatus;
if (taskStatus != null)
return taskStatus;
else
{
var task = new PluginLibraryUpdateTask();
return task.ScheduleTask();
}
}
public static ScheduledTaskStatus RunningStatus
{
get
{
return ScheduledTasks.GetTaskStatuses(typeof(PluginLibraryUpdateTask)).Where(ts => ts.IsRunning).FirstOrDefault();
}
}
}
}
@@ -0,0 +1,231 @@
using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Models.Services.Interop.DiscoServices;
using Disco.Services.Tasks;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
namespace Disco.Services.Interop.DiscoServices
{
using StatisticInt = UpdateRequestV2.StatisticInt;
using StatisticJob = UpdateRequestV2.StatisticJob;
using StatisticString = UpdateRequestV2.StatisticString;
using StatisticIntPair = UpdateRequestV2.StatisticIntPair;
public static class UpdateQuery
{
private static string UpdateUrl()
{
return string.Concat(DiscoServiceHelpers.ServicesUrl, "API/Update/V2");
}
public static Version CurrentDiscoVersion()
{
return typeof(UpdateQuery).Assembly.GetName().Version;
}
public static string CurrentDiscoVersionFormatted()
{
var v = CurrentDiscoVersion();
return FormatVersion(v);
}
public static string FormatVersion(Version Version)
{
return string.Format("{0}.{1}.{2:0000}.{3:0000}", Version.Major, Version.Minor, Version.Build, Version.Revision);
}
public static string HashDeploymentData(DiscoDataContext Database, string Data)
{
if (Data == null)
return null;
string clearText = Database.DiscoConfiguration.DeploymentSecret + Data;
byte[] clearTextBytes = Encoding.Unicode.GetBytes(clearText);
byte[] hashBytes;
using (var hashAlgorithm = SHA1.Create())
{
hashBytes = hashAlgorithm.ComputeHash(clearTextBytes);
}
return Convert.ToBase64String(hashBytes);
}
public static UpdateResponseV2 Check(DiscoDataContext Database, bool UseProxy, IScheduledTaskStatus Status)
{
Status.UpdateStatus(10, "Gathering statistics and building update request");
var updateRequest = BuildRequest(Database);
Status.UpdateStatus(40, "Sending statistics and update request");
var discoVersion = CurrentDiscoVersionFormatted();
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(UpdateUrl());
// Fix for Proxy Servers which don't support KeepAlive
request.KeepAlive = false;
if (!UseProxy)
request.Proxy = new WebProxy();
request.ContentType = "application/json; charset=utf-8; encoding=gzip";
request.Method = WebRequestMethods.Http.Post;
request.UserAgent = string.Format("Disco/{0} (Update)", discoVersion);
using (var requestStream = request.GetRequestStream())
{
using (var compressedStream = new GZipStream(requestStream, CompressionLevel.Optimal))
{
using (var requestStreamWriter = new StreamWriter(compressedStream, Encoding.UTF8))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(requestStreamWriter, updateRequest);
requestStreamWriter.Flush();
}
}
}
Status.UpdateStatus(50, "Waiting for update response");
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode == HttpStatusCode.OK)
{
Status.UpdateStatus(90, "Reading update response");
string updateResultJson;
UpdateResponseV2 updateResult;
using (var responseStream = response.GetResponseStream())
{
using (var responseReader = new StreamReader(responseStream))
{
updateResultJson = responseReader.ReadToEnd();
}
}
updateResult = JsonConvert.DeserializeObject<UpdateResponseV2>(updateResultJson);
Database.DiscoConfiguration.UpdateLastCheckResponse = updateResult;
Database.SaveChanges();
Status.SetFinishedMessage(string.Format("The update server reported Version {0} is the latest.", updateResult.LatestVersion));
return updateResult;
}
else
{
Status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", response.StatusCode, response.StatusDescription)));
return null;
}
}
}
private static UpdateRequestV2 BuildRequest(DiscoDataContext Database)
{
var lastUpdate = Database.DiscoConfiguration.UpdateLastCheckResponse;
var m = new UpdateRequestV2();
m.DeploymentId = Guid.Parse(Database.DiscoConfiguration.DeploymentId);
m.RequestDate = DateTime.Now;
m.VersionCurrent = CurrentDiscoVersionFormatted();
m.IsBetaDeployment = Database.DiscoConfiguration.UpdateBetaDeployment;
m.OrganisationName = Database.DiscoConfiguration.OrganisationName;
var whoAmIResponse = VicEduDept.VicSmart.WhoAmI();
if (whoAmIResponse != null && !string.IsNullOrWhiteSpace(whoAmIResponse.Item1))
m.VicEduDeptWanId = whoAmIResponse.Item1;
m.Stat_JobCounts = Database.Jobs.GroupBy(j => j.JobTypeId).Select(g => new StatisticInt() { Key = g.Key, Value = g.Count() }).ToList();
m.Stat_OpenJobCounts = Database.Jobs.Where(j => j.ClosedDate == null).GroupBy(j => j.JobTypeId).Select(g => new StatisticInt() { Key = g.Key, Value = g.Count() }).ToList();
m.Stat_DeviceModelCounts = Database.DeviceModels.Select(dm => new StatisticInt() { Key = dm.Manufacturer + ";" + dm.Model, Value = dm.Devices.Count(d => d.DecommissionedDate == null) }).ToList();
var activeThreshold = DateTime.Now.AddDays(-60);
m.Stat_ActiveDeviceModelCounts = Database.DeviceModels.Select(dm => new StatisticInt() { Key = dm.Manufacturer + ";" + dm.Model, Value = dm.Devices.Count(d => d.DecommissionedDate == null && (d.LastNetworkLogonDate == null || d.LastNetworkLogonDate > activeThreshold)) }).ToList();
m.Stat_UserCounts = new List<StatisticInt>() {
new StatisticInt() { Key = "All", Value = Database.Users.Count() },
new StatisticInt() { Key = "Assigned Current", Value = Database.Users.Where(u => u.DeviceUserAssignments.Any(dua => !dua.UnassignedDate.HasValue)).Count() },
new StatisticInt() { Key = "Assigned Ever", Value = Database.Users.Where(u => u.DeviceUserAssignments.Any()).Count() },
new StatisticInt() { Key = "Job Technicians", Value = Database.Jobs.Select(j => j.OpenedTechUserId).Distinct().ToList().Concat(Database.Jobs.Select(j => j.ClosedTechUserId).Distinct().ToList()).Distinct().Count() },
new StatisticInt() { Key = "Job Users", Value = Database.Jobs.Where(j => j.UserId != null).Select(j => j.UserId).Distinct().Count() }
};
var jobIds = Database.Jobs.OrderBy(j => j.Id).Select(j => j.Id).ToList();
if (jobIds.Count > 0)
{
m.Stat_JobIdentifiers = new List<StatisticIntPair>();
var jobIdSequenceBegin = jobIds.First();
jobIds.Skip(1).Aggregate(jobIdSequenceBegin, (last, current) =>
{
if (current == last + 1)
return current;
else
{
m.Stat_JobIdentifiers.Add(new StatisticIntPair() { Begin = jobIdSequenceBegin, End = last });
jobIdSequenceBegin = current;
}
return current;
});
m.Stat_JobIdentifiers.Add(new StatisticIntPair() { Begin = jobIdSequenceBegin, End = jobIds.Last() });
IQueryable<Job> jobs;
if (lastUpdate == null)
jobs = Database.Jobs;
else
{
var lastUpdateDate = lastUpdate.UpdateResponseDate.Date;
jobs = Database.Jobs.Where(j => j.OpenedDate >= lastUpdateDate || (j.ClosedDate.HasValue && j.ClosedDate.Value >= lastUpdateDate));
}
var reportedJobs = jobs.Select(j => new
{
Id = j.Id,
OpenedDate = j.OpenedDate,
ClosedDate = j.ClosedDate,
JobType = j.JobTypeId,
JobSubTypes = j.JobSubTypes.Select(jst => jst.Id),
DeviceModelManufacturer = j.Device.DeviceModel.Manufacturer,
DeviceModelModel = j.Device.DeviceModel.Model,
DeviceSerialNumber = j.DeviceSerialNumber,
UserId = j.UserId,
JobTechnicianId = j.OpenedTechUserId,
WarrantyRepairer = j.JobMetaWarranty.ExternalName,
WarrantyRepairerLoggedDate = j.JobMetaWarranty.ExternalLoggedDate,
WarrantyRepairerCompletedDate = j.JobMetaWarranty.ExternalCompletedDate,
Repairer = j.JobMetaNonWarranty.RepairerName,
RepairerLoggedDate = j.JobMetaNonWarranty.RepairerLoggedDate,
RepairerCompletedDate = j.JobMetaNonWarranty.RepairerCompletedDate,
}).ToList();
m.Stat_Jobs = reportedJobs.Select(j => new StatisticJob()
{
Identifier = j.Id,
OpenedDate = j.OpenedDate,
ClosedDate = j.ClosedDate,
Type = j.JobType,
SubTypes = j.JobSubTypes == null ? null : string.Join(";", j.JobSubTypes),
DeviceIdentifier = HashDeploymentData(Database, j.DeviceSerialNumber),
UserIdentifier = HashDeploymentData(Database, j.UserId),
TechnicianIdentifier = HashDeploymentData(Database, j.JobTechnicianId),
DeviceModel = string.Format("{0};{1}", j.DeviceModelManufacturer, j.DeviceModelModel),
Repairer = j.JobType == JobType.JobTypeIds.HWar ? j.WarrantyRepairer : j.Repairer,
RepairerLogged = j.JobType == JobType.JobTypeIds.HWar ? j.WarrantyRepairerLoggedDate : j.RepairerLoggedDate,
RepairerCompleted = j.JobType == JobType.JobTypeIds.HWar ? j.WarrantyRepairerCompletedDate : j.RepairerCompletedDate
}).ToList();
}
m.InstalledPlugins = Disco.Services.Plugins.Plugins.GetPlugins().Select(manifest => new StatisticString() { Key = manifest.Id, Value = manifest.VersionFormatted }).ToList();
return m;
}
}
}
@@ -4,52 +4,15 @@ using Quartz;
using System;
using System.Linq;
namespace Disco.BI.Interop.Community
namespace Disco.Services.Interop.DiscoServices
{
public class UpdateCheckTask : ScheduledTask
public class UpdateQueryTask : ScheduledTask
{
public override string TaskName { get { return "Disco Community - Check for Update"; } }
public override string TaskName { get { return "Disco ICT - Check for Update"; } }
public override bool SingleInstanceTask { get { return true; } }
public override bool CancelInitiallySupported { get { return false; } }
public static ScheduledTaskStatus ScheduleNow()
{
var runningTasks = ScheduledTasks.GetTaskStatuses(typeof(UpdateCheckTask)).Where(ts => ts.IsRunning).ToList();
if (runningTasks.Count > 0)
return runningTasks.First();
else
{
var t = new UpdateCheckTask();
return t.ScheduleTask();
}
}
public static ScheduledTaskStatus RunningStatus
{
get
{
return ScheduledTasks.GetTaskStatuses(typeof(UpdateCheckTask)).Where(ts => ts.IsRunning).FirstOrDefault();
}
}
public static DateTime? NextScheduled
{
get
{
var runningTasks = ScheduledTasks.GetTaskStatuses(typeof(UpdateCheckTask)).ToList();
DateTime timestamp = DateTime.MaxValue;
foreach (var t in runningTasks)
{
if (t.NextScheduledTimestamp != null && t.NextScheduledTimestamp.Value < timestamp)
timestamp = t.NextScheduledTimestamp.Value;
}
if (timestamp == DateTime.MaxValue)
return null;
else
return timestamp;
}
}
public override void InitalizeScheduledTask(Data.Repository.DiscoDataContext Database)
public override void InitalizeScheduledTask(DiscoDataContext Database)
{
// Random time between midday and midnight.
var rnd = new Random();
@@ -69,15 +32,55 @@ namespace Disco.BI.Interop.Community
{
try
{
UpdateCheck.Check(database, true, this.Status);
UpdateQuery.Check(database, true, this.Status);
}
catch (Exception ex)
{
ScheduledTasksLog.LogScheduledTaskException(this.Status.TaskName, this.Status.SessionId, this.Status.TaskType, ex);
// Could be proxy error - try again without proxy:
UpdateCheck.Check(database, false, this.Status);
UpdateQuery.Check(database, false, this.Status);
}
}
}
public static ScheduledTaskStatus ScheduleNow()
{
var taskStatus = RunningStatus;
if (taskStatus != null)
return taskStatus;
else
{
var task = new UpdateQueryTask();
return task.ScheduleTask();
}
}
public static DateTime? NextScheduled
{
get
{
DateTime timestamp = DateTime.MaxValue;
var tasks = ScheduledTasks.GetTaskStatuses(typeof(UpdateQueryTask)).ToList();
foreach (var t in tasks)
if (t.NextScheduledTimestamp != null && t.NextScheduledTimestamp.Value < timestamp)
timestamp = t.NextScheduledTimestamp.Value;
if (timestamp != DateTime.MaxValue)
return timestamp;
else
return null;
}
}
public static ScheduledTaskStatus RunningStatus
{
get
{
return ScheduledTasks.GetTaskStatuses(typeof(UpdateQueryTask)).Where(ts => ts.IsRunning).FirstOrDefault();
}
}
}
}
}
@@ -0,0 +1,88 @@
using Disco.Services.Interop.DiscoServices;
using System;
using System.IO;
using System.Net;
using System.Xml.Linq;
namespace Disco.Services.Interop.VicEduDept
{
public class VicSmart
{
/// <summary>
/// Queries DoE VicSmart Service to detect the current site.
/// </summary>
/// <returns>A Tuple where Item1 is the Site Number and Item2 is the Site Name</returns>
public static Tuple<string, string> WhoAmI()
{
// DnsQuery for broadband.doe.wan
IPHostEntry doeWanDnsEntry;
try
{
doeWanDnsEntry = Dns.GetHostEntry("broadband.doe.wan");
}
catch (Exception)
{ return null; } // Fail on error
// Try using IPSearch feature
XDocument doeWanIPSearchResult = TryIPWhoAmISearch(false);
if (doeWanIPSearchResult == null)
doeWanIPSearchResult = TryIPWhoAmISearch(true);
if (doeWanIPSearchResult == null)
return null;
try
{
var site = doeWanIPSearchResult.Element("resultset").Element("site");
var siteNumber = site.Element("number").Value.ToLower();
var siteName = site.Element("name").Value.ToLower();
return Tuple.Create(siteNumber, siteName);
}
catch (Exception)
{ return null; } // Fail on error
}
private static XDocument TryIPWhoAmISearch(bool useProxy)
{
try
{
var DiscoBIVersion = UpdateQuery.CurrentDiscoVersionFormatted();
HttpWebRequest wReq = (HttpWebRequest)HttpWebRequest.Create("http://broadband.doe.wan/ipsearch/showresult.php");
// Fix for Proxy Servers which don't support KeepAlive
wReq.KeepAlive = false;
if (!useProxy)
wReq.Proxy = new WebProxy(); // Empty Proxy Config
wReq.Method = WebRequestMethods.Http.Post;
wReq.ContentType = "application/x-www-form-urlencoded";
wReq.UserAgent = string.Format("Disco/{0}", DiscoBIVersion);
using (var wrStream = wReq.GetRequestStream())
{
using (var wrStreamWriter = new StreamWriter(wrStream))
{
wrStreamWriter.Write("mode=whoami");
}
}
using (HttpWebResponse wRes = (HttpWebResponse)wReq.GetResponse())
{
if (wRes.StatusCode == HttpStatusCode.OK)
{
using (var wResStream = wRes.GetResponseStream())
{
return XDocument.Load(wResStream);
}
}
else
return null;
}
}
catch (Exception)
{ return null; } // Fail on error
}
}
}
@@ -98,14 +98,14 @@ namespace Disco.Services.Jobs.JobQueues
JobId = jqj.JobId,
TechUserId = jqj.AddedUserId,
Timestamp = jqj.AddedDate,
Comments = string.Format("Added to Job Queue: {1}{0}Priority: {2}{0}Comment: {3}", Environment.NewLine, queue.Name, jqj.Priority.ToString(), string.IsNullOrWhiteSpace(jqj.AddedComment) ? "<none>" : jqj.AddedComment)
Comments = string.Format("# Added to Queue\r\n**{0}**\r\nPriority: **{1}**\r\n{2}", Environment.NewLine, queue.Name, jqj.Priority.ToString(), string.IsNullOrWhiteSpace(jqj.AddedComment) ? "<no comment>" : jqj.AddedComment)
});
Database.JobLogs.Add(new JobLog()
{
JobId = jqj.JobId,
TechUserId = jqj.RemovedUserId,
Timestamp = jqj.RemovedDate.Value,
Comments = string.Format("Removed from Job Queue: {1}{0}Comment: {2}", Environment.NewLine, queue.Name, string.IsNullOrWhiteSpace(jqj.RemovedComment) ? "<none>" : jqj.RemovedComment)
Comments = string.Format("# Removed from Queue\r\n**{0}**\r\n{1}", queue.Name, string.IsNullOrWhiteSpace(jqj.RemovedComment) ? "<no comment>" : jqj.RemovedComment)
});
// Delete JQJ
+102 -78
View File
@@ -5,7 +5,9 @@ using Disco.Models.Services.Jobs.Noticeboards;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using System.Reactive.Subjects;
namespace Disco.Services.Jobs.Noticeboards
{
@@ -41,10 +43,19 @@ namespace Disco.Services.Jobs.Noticeboards
"DisplayName"
};
private static Subject<Tuple<List<string>, List<string>>> BufferedUpdateStream;
static HeldDevices()
{
BufferedUpdateStream = new Subject<Tuple<List<string>, List<string>>>();
BufferedUpdateStream
.DelayBuffer(TimeSpan.FromMilliseconds(500))
.SubscribeOn(TaskPoolScheduler.Default)
.Subscribe(ProcessUpdates);
// Subscribe to Repository Notifications
RepositoryMonitor.StreamAfterCommit.Where(e =>
RepositoryMonitor.StreamBeforeCommit.Where(e =>
(e.EntityType == typeof(Job) &&
(e.EventType == RepositoryMonitorEventType.Added ||
e.EventType == RepositoryMonitorEventType.Deleted ||
@@ -65,93 +76,105 @@ namespace Disco.Services.Jobs.Noticeboards
(e.EventType == RepositoryMonitorEventType.Modified && e.ModifiedProperties.Any(p => MonitorUserProperties.Contains(p)))
)
)
.DelayBuffer(TimeSpan.FromMilliseconds(500))
.Subscribe(RepositoryEvent);
}
private static void RepositoryEvent(IEnumerable<RepositoryMonitorEvent> e)
private static void RepositoryEvent(RepositoryMonitorEvent i)
{
List<string> deviceSerialNumbers = new List<string>();
List<string> userIds = new List<string>();
using (DiscoDataContext Database = new DiscoDataContext())
if (i.EntityType == typeof(Job))
{
foreach (var i in e)
if (i.EventType == RepositoryMonitorEventType.Modified &&
i.ModifiedProperties.Contains("DeviceSerialNumber"))
{
if (i.EntityType == typeof(Job))
{
if (i.EventType == RepositoryMonitorEventType.Modified &&
i.ModifiedProperties.Contains("DeviceSerialNumber"))
{
var p = i.GetPreviousPropertyValue<string>("DeviceSerialNumber");
if (p != null)
deviceSerialNumbers.Add(p);
}
var j = (Job)i.Entity;
if (j.DeviceSerialNumber != null)
deviceSerialNumbers.Add(j.DeviceSerialNumber);
}
else if (i.EntityType == typeof(JobMetaNonWarranty))
{
var jmnw = (JobMetaNonWarranty)i.Entity;
if (jmnw.Job != null)
{
if (jmnw.Job.DeviceSerialNumber != null)
deviceSerialNumbers.Add(jmnw.Job.DeviceSerialNumber);
}
else
{
var sn = Database.Jobs.Where(j => j.Id == jmnw.JobId).Select(j => j.DeviceSerialNumber).FirstOrDefault();
if (sn != null)
deviceSerialNumbers.Add(sn);
}
}
else if (i.EntityType == typeof(Device))
{
var d = (Device)i.Entity;
deviceSerialNumbers.Add(d.SerialNumber);
if (i.EventType == RepositoryMonitorEventType.Modified &&
i.ModifiedProperties.Contains("AssignedUserId"))
{
var p = i.GetPreviousPropertyValue<string>("AssignedUserId");
if (p != null)
userIds.Add(p);
}
}
else if (i.EntityType == typeof(DeviceProfile))
{
var dp = (DeviceProfile)i.Entity;
deviceSerialNumbers.AddRange(
Database.Jobs
.Where(j => !j.ClosedDate.HasValue && j.Device.DeviceProfileId == dp.Id)
.Select(j => j.DeviceSerialNumber)
);
}
else if (i.EntityType == typeof(User))
{
var u = (User)i.Entity;
deviceSerialNumbers.AddRange(
Database.Jobs
.Where(j => !j.ClosedDate.HasValue && j.Device.AssignedUserId == u.UserId)
.Select(j => j.DeviceSerialNumber)
);
}
var p = i.GetPreviousPropertyValue<string>("DeviceSerialNumber");
if (p != null)
deviceSerialNumbers.Add(p);
}
deviceSerialNumbers = deviceSerialNumbers.Distinct().ToList();
var j = (Job)i.Entity;
if (j.DeviceSerialNumber != null)
deviceSerialNumbers.Add(j.DeviceSerialNumber);
}
else if (i.EntityType == typeof(JobMetaNonWarranty))
{
var jmnw = (JobMetaNonWarranty)i.Entity;
if (jmnw.Job != null)
{
if (jmnw.Job.DeviceSerialNumber != null)
deviceSerialNumbers.Add(jmnw.Job.DeviceSerialNumber);
}
else
{
var sn = i.Database.Jobs.Where(j => j.Id == jmnw.JobId).Select(j => j.DeviceSerialNumber).FirstOrDefault();
if (sn != null)
deviceSerialNumbers.Add(sn);
}
}
else if (i.EntityType == typeof(Device))
{
var d = (Device)i.Entity;
deviceSerialNumbers.Add(d.SerialNumber);
if (i.EventType == RepositoryMonitorEventType.Modified &&
i.ModifiedProperties.Contains("AssignedUserId"))
{
var p = i.GetPreviousPropertyValue<string>("AssignedUserId");
if (p != null)
userIds.Add(p);
}
}
else if (i.EntityType == typeof(DeviceProfile))
{
var dp = (DeviceProfile)i.Entity;
deviceSerialNumbers.AddRange(
i.Database.Jobs
.Where(j => !j.ClosedDate.HasValue && j.Device.DeviceProfileId == dp.Id)
.Select(j => j.DeviceSerialNumber)
);
}
else if (i.EntityType == typeof(User))
{
var u = (User)i.Entity;
deviceSerialNumbers.AddRange(
i.Database.Jobs
.Where(j => !j.ClosedDate.HasValue && j.Device.AssignedUserId == u.UserId)
.Select(j => j.DeviceSerialNumber)
);
}
if (deviceSerialNumbers.Count > 0 || userIds.Count > 0)
{
i.ExecuteAfterCommit(e =>
{
BufferedUpdateStream.OnNext(Tuple.Create(deviceSerialNumbers, userIds));
});
}
}
private static void ProcessUpdates(IEnumerable<Tuple<List<string>, List<string>>> e)
{
using (DiscoDataContext Database = new DiscoDataContext())
{
var deviceSerialNumbers = e.SelectMany(i => i.Item1).Distinct().ToList();
var userIds = e.SelectMany(i => i.Item2).Distinct().ToList();
// Determine Held Devices for Users
userIds.AddRange(
Database.Devices
.Where(d => d.AssignedUserId != null && deviceSerialNumbers.Contains(d.SerialNumber))
.Select(d => d.AssignedUserId)
);
userIds = userIds.Distinct().ToList();
if (deviceSerialNumbers.Count > 0)
{
userIds.AddRange(
Database.Devices
.Where(d => d.AssignedUserId != null && deviceSerialNumbers.Contains(d.SerialNumber))
.Select(d => d.AssignedUserId)
);
}
if (userIds.Count > 0)
userIds = userIds.Distinct().ToList();
// Notify Held Devices
@@ -172,8 +195,9 @@ namespace Disco.Services.Jobs.Noticeboards
{
var updates = DeviceSerialNumbers
.Skip(skipAmount).Take(30)
.ToDictionary(dsn => dsn,
dsn => {
.ToDictionary(dsn => dsn,
dsn =>
{
IHeldDeviceItem item;
items.TryGetValue(dsn, out item);
return item;
@@ -185,7 +209,7 @@ namespace Disco.Services.Jobs.Noticeboards
}
}
private static IEnumerable<IHeldDeviceItem> GetHeldDevices(IQueryable<Job> query)
public static IEnumerable<IHeldDeviceItem> GetHeldDevices(IQueryable<Job> query)
{
var jobs = query
.Where(j =>
@@ -38,7 +38,7 @@ namespace Disco.Services.Jobs.Noticeboards
}
}
private static IEnumerable<IHeldDeviceItem> GetHeldDevicesForUsers(IQueryable<Job> query)
public static IEnumerable<IHeldDeviceItem> GetHeldDevicesForUsers(IQueryable<Job> query)
{
var jobs = query
.Where(j =>
@@ -36,5 +36,10 @@ namespace Disco.Services.Jobs.Noticeboards
return base.OnConnected();
}
public static void SetTheme(string ThemeName)
{
HubContext.Clients.All.setTheme(ThemeName);
}
}
}
+3 -1
View File
@@ -54,9 +54,11 @@ namespace Disco.Services.Logging
LogModules = new Dictionary<int, LogBase>();
// Load all LogModules (Only from Disco Assemblies)
var appDomain = AppDomain.CurrentDomain;
var servicesAssemblyName = typeof(LogContext).Assembly.GetName().Name;
var logModuleTypes = (from a in appDomain.GetAssemblies()
where !a.GlobalAssemblyCache && !a.IsDynamic && a.FullName.StartsWith("Disco.", StringComparison.OrdinalIgnoreCase)
where !a.GlobalAssemblyCache && !a.IsDynamic &&
(a.GetName().Name == servicesAssemblyName || a.GetReferencedAssemblies().Any(ra => ra.Name == servicesAssemblyName))
from type in a.GetTypes()
where typeof(LogBase).IsAssignableFrom(type) && !type.IsAbstract
select type);
+5 -3
View File
@@ -1,8 +1,8 @@
using System;
using Disco.Services.Logging.Models;
using Exceptionless;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Disco.Services.Logging.Models;
namespace Disco.Services.Logging
{
@@ -44,6 +44,8 @@ namespace Disco.Services.Logging
}
public static void LogException(string Component, Exception ex)
{
ex.ToExceptionless().Submit();
// Handle Special-Case Errors
if (ex is System.Data.Entity.Validation.DbEntityValidationException)
{
@@ -1,217 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Disco.Data.Repository;
using Disco.Services.Plugins;
using Disco.Services.Tasks;
using Disco.Models.BI.Interop.Community;
using System.Net;
using System.Xml.Serialization;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Quartz;
namespace Disco.Services.Plugins.CommunityInterop
{
public class PluginLibraryUpdateTask : ScheduledTask
{
public override string TaskName { get { return "Disco Community - Update Plugin Library"; } }
public static string CurrentDiscoVersion()
{
var AssemblyVersion = typeof(PluginLibraryUpdateTask).Assembly.GetName().Version;
return string.Format("{0}.{1}.{2:0000}.{3:0000}", AssemblyVersion.Major, AssemblyVersion.Minor, AssemblyVersion.Build, AssemblyVersion.Revision);
}
protected override void ExecuteTask()
{
ExecuteTaskInternal(this.Status);
Status.SetFinishedMessage("The Plugin Library Catalogue was updated.");
}
internal static void ExecuteTaskInternal(ScheduledTaskStatus Status)
{
PluginLibraryUpdateRequest updateRequestBody;
PluginLibraryUpdateResponse updateResult;
string catalogueFile;
PluginLibraryCompatibilityRequest compatRequestBody;
PluginLibraryCompatibilityResponse compatResult;
string compatibilityFile;
var DiscoBIVersion = CurrentDiscoVersion();
HttpWebRequest webRequest;
#region Update
Status.UpdateStatus(1, "Updating Plugin Library Catalogue", "Building Request");
using (DiscoDataContext database = new DiscoDataContext())
{
catalogueFile = Plugins.CatalogueFile(database);
updateRequestBody = new PluginLibraryUpdateRequest()
{
DeploymentId = database.DiscoConfiguration.DeploymentId,
HostVersion = typeof(Plugins).Assembly.GetName().Version.ToString(4)
};
}
Status.UpdateStatus(10, "Sending Request");
webRequest = (HttpWebRequest)HttpWebRequest.Create(PluginLibraryUpdateUrl());
webRequest.KeepAlive = false;
webRequest.ContentType = "application/xml";
webRequest.Method = WebRequestMethods.Http.Post;
webRequest.UserAgent = string.Format("Disco/{0} (PluginLibrary)", DiscoBIVersion);
using (var wrStream = webRequest.GetRequestStream())
{
XmlSerializer xml = new XmlSerializer(typeof(PluginLibraryUpdateRequest));
xml.Serialize(wrStream, updateRequestBody);
}
Status.UpdateStatus(20, "Waiting for Response");
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{
if (webResponse.StatusCode == HttpStatusCode.OK)
{
Status.UpdateStatus(45, "Reading Response");
using (var wResStream = webResponse.GetResponseStream())
{
XmlSerializer xml = new XmlSerializer(typeof(PluginLibraryUpdateResponse));
updateResult = (PluginLibraryUpdateResponse)xml.Deserialize(wResStream);
}
}
else
{
Status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
return;
}
}
if (!Directory.Exists(Path.GetDirectoryName(catalogueFile)))
Directory.CreateDirectory(Path.GetDirectoryName(catalogueFile));
using (FileStream fs = new FileStream(catalogueFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (StreamWriter fsWriter = new StreamWriter(fs))
{
fsWriter.Write(JsonConvert.SerializeObject(updateResult));
fsWriter.Flush();
}
}
#endregion
#region Compatibility
Status.UpdateStatus(50, "Updating Plugin Library Compatibility", "Building Request");
using (DiscoDataContext database = new DiscoDataContext())
{
compatibilityFile = Plugins.CompatibilityFile(database);
compatRequestBody = new PluginLibraryCompatibilityRequest()
{
DeploymentId = database.DiscoConfiguration.DeploymentId,
HostVersion = typeof(Plugins).Assembly.GetName().Version.ToString(4)
};
}
Status.UpdateStatus(60, "Sending Request");
webRequest = (HttpWebRequest)HttpWebRequest.Create(PluginLibraryCompatibilityUrl());
webRequest.KeepAlive = false;
webRequest.ContentType = "application/json";
webRequest.Method = WebRequestMethods.Http.Post;
webRequest.UserAgent = string.Format("Disco/{0} (PluginLibrary)", DiscoBIVersion);
using (var wrStream = webRequest.GetRequestStream())
{
XmlSerializer xml = new XmlSerializer(typeof(PluginLibraryCompatibilityRequest));
xml.Serialize(wrStream, compatRequestBody);
}
Status.UpdateStatus(70, "Waiting for Response");
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{
if (webResponse.StatusCode == HttpStatusCode.OK)
{
Status.UpdateStatus(95, "Reading Response");
using (var wResStream = webResponse.GetResponseStream())
{
XmlSerializer xml = new XmlSerializer(typeof(PluginLibraryCompatibilityResponse));
compatResult = (PluginLibraryCompatibilityResponse)xml.Deserialize(wResStream);
}
}
else
{
Status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
return;
}
}
if (!Directory.Exists(Path.GetDirectoryName(compatibilityFile)))
Directory.CreateDirectory(Path.GetDirectoryName(compatibilityFile));
using (FileStream fs = new FileStream(compatibilityFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (StreamWriter fsWriter = new StreamWriter(fs))
{
fsWriter.Write(JsonConvert.SerializeObject(compatResult));
fsWriter.Flush();
}
}
#endregion
}
private static string PluginLibraryUpdateUrl()
{
return string.Concat(Disco.Data.Configuration.CommunityHelpers.CommunityUrl(), "DiscoPluginLibrary/V1");
}
private static string PluginLibraryCompatibilityUrl()
{
return string.Concat(Disco.Data.Configuration.CommunityHelpers.CommunityUrl(), "DiscoPluginLibrary/CompatibilityV1");
}
public static ScheduledTaskStatus ScheduleNow()
{
var taskStatus = ScheduledTasks.GetTaskStatuses(typeof(PluginLibraryUpdateTask)).Where(ts => ts.IsRunning).FirstOrDefault();
if (taskStatus != null)
return taskStatus;
else
{
var t = new PluginLibraryUpdateTask();
return t.ScheduleTask();
}
}
public static ScheduledTaskStatus RunningStatus
{
get
{
return ScheduledTasks.GetTaskStatuses(typeof(PluginLibraryUpdateTask)).Where(ts => ts.IsRunning).FirstOrDefault();
}
}
public override void InitalizeScheduledTask(DiscoDataContext Database)
{
// Random time between midday and midnight.
var rnd = new Random();
var rndHour = rnd.Next(12, 23);
var rndMinute = rnd.Next(0, 59);
TriggerBuilder triggerBuilder = TriggerBuilder.Create().
WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(rndHour, rndMinute));
this.ScheduleTask(triggerBuilder);
}
}
}
@@ -0,0 +1,94 @@
using Disco.Data.Repository;
using Disco.Models.BI.Config;
using Disco.Models.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace Disco.Services.Plugins.Features.RepairProvider
{
[PluginFeatureCategory(DisplayName = "Repair Providers")]
public abstract class RepairProviderFeature : PluginFeature
{
/// <summary>
/// The repairer identifier. Used to link this provider to any <see cref="Disco.Models.Repository.RepairerName"/>. This identifier is used to automatically set the RepairerName when a job is submitted using this plugin.
/// </summary>
public abstract string ProviderId { get; }
#region Job Submission
/// <summary>
/// Called when a user selects this plugin to repair and allows a plugin to inject a View to collect additional information.
/// </summary>
/// <returns>A Tuple consisting of the Razor View type and a View Model</returns>
public virtual Tuple<Type, dynamic> SubmitJobBegin(DiscoDataContext Database, Controller controller, Job Job, OrganisationAddress Address, User TechUser)
{
return null;
}
/// <summary>
/// Called after the RepairDescription is completed and allows the plugin to parse any data collected from SubmitJobBegin.
/// </summary>
/// <returns>A Dictionary of key/value items which are persisted throughout the submission and passed into the final SubmitJob method.</returns>
public virtual Dictionary<string, string> SubmitJobParseProperties(DiscoDataContext Database, FormCollection form, Controller controller, Job Job, OrganisationAddress Address, User TechUser, string RepairDescription)
{
return null;
}
/// <summary>
/// Plugins are required to disclose any information that will be transmitted to any external party. This method is expected to return a clear list all data which will be transmitted.
/// </summary>
/// <returns>A Dictionary of key/value items which contain all information which will be disclosed to the plugin provider.</returns>
public abstract Dictionary<string, string> SubmitJobDiscloseInfo(DiscoDataContext Database, Job Job, OrganisationAddress Address, User TechUser, string RepairDescription, Dictionary<string, string> ProviderProperties);
/// <summary>
/// Called when the plugin should submit the job to the external party.
/// </summary>
/// <returns>A reference number/identifier from the external party which is stored in <see cref="Disco.Models.Repository.RepairerReference"/></returns>
public abstract string SubmitJob(DiscoDataContext Database, Job Job, OrganisationAddress Address, User TechUser, string RepairDescription, Dictionary<string, string> ProviderProperties);
#endregion
#region Job Details
/// <summary>
/// <see cref="true"/> when additional Job Details are supported by the external party. When <see cref="true"/>, JobDetailsViewModel must be implemented.
/// </summary>
public abstract bool JobDetailsSupported { get; }
/// <summary>
/// Called when a job repair information is shown. Allows a plugin to inject a View to display additional information.
/// </summary>
/// <returns>A Tuple consisting of the Razor View type and a View Model</returns>
public virtual Tuple<Type, dynamic> JobDetails(DiscoDataContext Database, Controller controller, Job Job)
{
return null;
}
#endregion
public static PluginFeatureManifest FindPluginFeature(string PluginIdOrRepairProviderId)
{
var defs = Plugins.GetPluginFeatures(typeof(RepairProviderFeature));
var def = defs.FirstOrDefault(d => d.PluginManifest.Id.Equals(PluginIdOrRepairProviderId, StringComparison.OrdinalIgnoreCase));
if (def != null)
return def;
else
foreach (var d in defs)
{
using (var providerInstance = d.CreateInstance<RepairProviderFeature>())
{
if (providerInstance.ProviderId != null && providerInstance.ProviderId.Equals(PluginIdOrRepairProviderId, StringComparison.OrdinalIgnoreCase))
{
return d;
}
}
}
return null;
}
}
}
@@ -0,0 +1,12 @@
using System;
namespace Disco.Services.Plugins.Features.RepairProvider
{
public class RepairProviderSubmitJobException : Exception
{
public RepairProviderSubmitJobException(string Message)
: base(Message)
{
}
}
}
+25 -33
View File
@@ -1,14 +1,13 @@
using System;
using System.Collections.Generic;
using Disco.Data.Repository;
using Disco.Models.Services.Interop.DiscoServices;
using Disco.Services.Interop.DiscoServices;
using Disco.Services.Tasks;
using Quartz;
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Disco.Data.Repository;
using Disco.Services.Tasks;
using Quartz;
using System.Net.Http;
namespace Disco.Services.Plugins
{
@@ -36,31 +35,17 @@ namespace Disco.Services.Plugins
Directory.CreateDirectory(Path.GetDirectoryName(packageFilePath));
// Need to Download the Package
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(packageUrlPath);
webRequest.KeepAlive = false;
webRequest.ContentType = "application/xml";
webRequest.Method = WebRequestMethods.Http.Get;
webRequest.UserAgent = string.Format("Disco/{0} (PluginLibrary)", Disco.Services.Plugins.CommunityInterop.PluginLibraryUpdateTask.CurrentDiscoVersion());
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
using (HttpClient httpClient = new HttpClient())
{
if (webResponse.StatusCode == HttpStatusCode.OK)
using (var httpResponse = httpClient.GetAsync(packageUrlPath).Result)
{
Status.UpdateStatus(0, "Downloading...");
using (var wResStream = webResponse.GetResponseStream())
httpResponse.EnsureSuccessStatusCode();
using (FileStream fsOut = new FileStream(packageFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (FileStream fsOut = new FileStream(packageFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
{
wResStream.CopyTo(fsOut);
}
httpResponse.Content.ReadAsStreamAsync().Result.CopyTo(fsOut);
}
}
else
{
Status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
return;
}
}
}
@@ -100,16 +85,23 @@ namespace Disco.Services.Plugins
string packagePath = Path.Combine(database.DiscoConfiguration.PluginsLocation, packageManifest.Id);
// Check for Compatibility
var compatibilityData = Plugins.LoadCompatibilityData(database);
var pluginCompatibility = compatibilityData.Plugins.FirstOrDefault(i => i.Id.Equals(packageManifest.Id, StringComparison.OrdinalIgnoreCase) && packageManifest.Version == Version.Parse(i.Version));
if (pluginCompatibility != null && !pluginCompatibility.Compatible)
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", packageManifest.Id, packageManifest.VersionFormatted, pluginCompatibility.Reason));
var libraryIncompatibility = PluginLibrary.LoadManifest(database).LoadIncompatibilityData();
PluginIncompatibility incompatibility;
if (!libraryIncompatibility.IsCompatible(packageManifest.Id, packageManifest.Version, out incompatibility))
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", packageManifest.Id, packageManifest.VersionFormatted, incompatibility.Reason));
// Force Delete of Existing Folder
if (Directory.Exists(packagePath))
{
this.Status.UpdateStatus(25, "Removing Existing Files");
Directory.Delete(packagePath, true);
try
{
Directory.Delete(packagePath, true);
}
catch (UnauthorizedAccessException)
{
throw new InvalidOperationException("Unable to delete existing plugin files, they may be locked by another process. Please restart Disco ICT and try installing the plugin again.");
}
}
Directory.CreateDirectory(packagePath);
+4
View File
@@ -145,8 +145,12 @@ namespace Disco.Services.Plugins
"Disco.Web",
"Disco.Web.Extensions",
"EntityFramework",
"Exceptionless",
"Exceptionless.Models",
"Exceptionless.Mvc",
"itextsharp",
"LumenWorks.Framework.IO",
"MarkdownSharp",
"Microsoft.AspNet.SignalR.Core",
"Microsoft.AspNet.SignalR.SystemWeb",
"Microsoft.Owin",
+19 -101
View File
@@ -1,16 +1,15 @@
using System;
using Disco.Data.Repository;
using Disco.Models.Services.Interop.DiscoServices;
using Disco.Services.Interop.DiscoServices;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Disco.Data.Repository;
using System.IO.Compression;
using Disco.Models.BI.Interop.Community;
using System.Web;
using Newtonsoft.Json;
using System.Threading;
using System.Web;
namespace Disco.Services.Plugins
{
@@ -250,81 +249,6 @@ namespace Disco.Services.Plugins
throw new InvalidOperationException(string.Format("Unknown Plugin Feature Category Type: [{0}]", FeatureCategoryType.Name));
}
public static string CatalogueFile(DiscoDataContext Database)
{
return Path.Combine(Database.DiscoConfiguration.PluginPackagesLocation, "Catalogue.json");
}
public static string CompatibilityFile(DiscoDataContext Database)
{
return Path.Combine(Database.DiscoConfiguration.PluginPackagesLocation, "Compatibility.json");
}
public static PluginLibraryUpdateResponse LoadCatalogue(DiscoDataContext Database)
{
var catalogueFile = CatalogueFile(Database);
if (!File.Exists(catalogueFile))
return null;
return JsonConvert.DeserializeObject<PluginLibraryUpdateResponse>(File.ReadAllText(catalogueFile));
}
public static PluginLibraryCompatibilityResponse LoadCompatibilityData(DiscoDataContext Database)
{
var pluginAssembly = typeof(Plugins).Assembly;
Version hostVersion = pluginAssembly.GetName().Version;
PluginLibraryCompatibilityResponse Data = null;
var localCompatFile = Path.Combine(Path.GetDirectoryName(pluginAssembly.Location), "ReleasePluginCompatibility.json");
var serverCompatFile = CompatibilityFile(Database);
if (File.Exists(localCompatFile))
{
Data = JsonConvert.DeserializeObject<PluginLibraryCompatibilityResponse>(File.ReadAllText(localCompatFile));
Data.HostVersion = hostVersion.ToString(4);
}
if (File.Exists(serverCompatFile))
{
var serverData = JsonConvert.DeserializeObject<PluginLibraryCompatibilityResponse>(File.ReadAllText(serverCompatFile));
if (Version.Parse(serverData.HostVersion) == hostVersion)
{
if (Data == null)
{
// No Local Compatibility File
Data = serverData;
}
else
{
// Join Compatibility Files
var localItems = Data.Plugins;
var localItemVersions = localItems.ToDictionary(i => i, i => Version.Parse(i.Version));
var joinedItems = localItems.ToList();
Data.ResponseTimestamp = serverData.ResponseTimestamp;
foreach (var serverItem in serverData.Plugins)
{
var serverItemVersion = Version.Parse(serverItem.Version);
var localItem = localItems.FirstOrDefault(i => i.Id.Equals(serverItem.Id, StringComparison.OrdinalIgnoreCase) && serverItemVersion == localItemVersions[i]);
if (localItem != null)
joinedItems.Remove(localItem);
joinedItems.Add(serverItem);
}
Data.Plugins = joinedItems;
}
}
}
if (Data == null)
{
Data = new PluginLibraryCompatibilityResponse()
{
HostVersion = hostVersion.ToString(4),
Plugins = new List<PluginLibraryCompatibilityItem>(),
ResponseTimestamp = new DateTime(2011, 7, 1)
};
}
return Data;
}
public static void InitalizePlugins(DiscoDataContext Database)
{
if (_PluginManifests == null)
@@ -334,7 +258,7 @@ namespace Disco.Services.Plugins
if (_PluginManifests == null)
{
Version hostVersion = typeof(Plugins).Assembly.GetName().Version;
var compatibilityData = new Lazy<PluginLibraryCompatibilityResponse>(() => LoadCompatibilityData(Database));
var compatibilityData = new Lazy<PluginLibraryIncompatibility>(() => PluginLibrary.LoadManifest(Database).LoadIncompatibilityData());
Dictionary<string, PluginManifest> loadedPlugins = new Dictionary<string, PluginManifest>();
PluginPath = Database.DiscoConfiguration.PluginsLocation;
@@ -373,9 +297,9 @@ namespace Disco.Services.Plugins
if (pluginManifest != null)
{
// Check Version Compatibility
var pluginCompatibility = compatibilityData.Value.Plugins.FirstOrDefault(i => i.Id.Equals(pluginManifest.Id, StringComparison.OrdinalIgnoreCase) && pluginManifest.Version == Version.Parse(i.Version));
if (pluginCompatibility != null && !pluginCompatibility.Compatible)
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", pluginManifest.Id, pluginManifest.VersionFormatted, pluginCompatibility.Reason));
var pluginIncompatible = compatibilityData.Value.IncompatiblePlugins.FirstOrDefault(i => i.PluginId.Equals(pluginManifest.Id, StringComparison.OrdinalIgnoreCase) && pluginManifest.Version == i.Version);
if (pluginIncompatible != null)
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", pluginManifest.Id, pluginManifest.VersionFormatted, pluginIncompatible.Reason));
if (pluginManifest.HostVersionMin != null && pluginManifest.HostVersionMin > hostVersion)
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] does not support this version of Disco (Requires v{2} or greater)", pluginManifest.Id, pluginManifest.VersionFormatted, pluginManifest.HostVersionMin.ToString()));
@@ -443,13 +367,13 @@ namespace Disco.Services.Plugins
_PluginAssemblyManifests = _PluginManifests.Values.ToDictionary(p => p.PluginAssembly, p => p);
}
public static PluginManifest UpdatePlugin(DiscoDataContext Database, PluginManifest ExistingManifest, String UpdatePluginPackageFilePath, PluginLibraryCompatibilityResponse CompatibilityData = null)
public static PluginManifest UpdatePlugin(DiscoDataContext Database, PluginManifest ExistingManifest, String UpdatePluginPackageFilePath, PluginLibraryIncompatibility PluginLibraryIncompatibility = null)
{
PluginManifest updatedManifest;
using (var packageStream = File.OpenRead(UpdatePluginPackageFilePath))
{
updatedManifest = UpdatePlugin(Database, ExistingManifest, packageStream, CompatibilityData);
updatedManifest = UpdatePlugin(Database, ExistingManifest, packageStream, PluginLibraryIncompatibility);
}
// Remove Update after processing
@@ -458,7 +382,7 @@ namespace Disco.Services.Plugins
return updatedManifest;
}
public static PluginManifest UpdatePlugin(DiscoDataContext Database, PluginManifest ExistingManifest, Stream UpdatePluginPackage, PluginLibraryCompatibilityResponse CompatibilityData = null)
public static PluginManifest UpdatePlugin(DiscoDataContext Database, PluginManifest ExistingManifest, Stream UpdatePluginPackage, PluginLibraryIncompatibility PluginLibraryIncompatibility = null)
{
using (MemoryStream packageStream = new MemoryStream())
{
@@ -482,23 +406,17 @@ namespace Disco.Services.Plugins
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");
}
// Check Compatibility
if (CompatibilityData == null)
CompatibilityData = LoadCompatibilityData(Database);
var pluginCompatibility = CompatibilityData.Plugins.FirstOrDefault(i => i.Id.Equals(packageManifest.Id, StringComparison.OrdinalIgnoreCase) && packageManifest.Version == Version.Parse(i.Version));
if (pluginCompatibility != null && !pluginCompatibility.Compatible)
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", packageManifest.Id, packageManifest.VersionFormatted, pluginCompatibility.Reason));
if (PluginLibraryIncompatibility == null)
PluginLibraryIncompatibility = PluginLibrary.LoadManifest(Database).LoadIncompatibilityData();
var pluginIncompatibility = PluginLibraryIncompatibility.IncompatiblePlugins.FirstOrDefault(i => i.PluginId.Equals(packageManifest.Id, StringComparison.OrdinalIgnoreCase) && packageManifest.Version == i.Version);
if (pluginIncompatibility != null)
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", packageManifest.Id, packageManifest.VersionFormatted, pluginIncompatibility.Reason));
string packagePath = Path.Combine(Database.DiscoConfiguration.PluginsLocation, packageManifest.Id);
+5
View File
@@ -5,6 +5,7 @@ using System.Text;
using Disco.Services.Logging;
using Disco.Services.Logging.Models;
using System.Reflection;
using Exceptionless;
namespace Disco.Services.Plugins
{
@@ -123,6 +124,8 @@ namespace Disco.Services.Plugins
public static void LogInitializeException(string PluginFilename, Exception ex)
{
ex.ToExceptionless().AddObject(PluginFilename, "PluginFilename").Submit();
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);
@@ -135,6 +138,8 @@ namespace Disco.Services.Plugins
public static void LogPluginException(string Component, Exception ex)
{
ex.ToExceptionless().AddObject(Component, "Component").Submit();
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);
+68 -60
View File
@@ -1,17 +1,14 @@
using System;
using Disco.Data.Repository;
using Disco.Models.Services.Interop.DiscoServices;
using Disco.Services.Interop.DiscoServices;
using Disco.Services.Tasks;
using Quartz;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using Disco.Data.Repository;
using Disco.Models.BI.Interop.Community;
using Disco.Services.Tasks;
using Quartz;
using System.Net.Http;
namespace Disco.Services.Plugins
{
@@ -24,17 +21,19 @@ namespace Disco.Services.Plugins
string pluginId = (string)this.ExecutionContext.JobDetail.JobDataMap["PluginId"];
string packageFilePath = (string)this.ExecutionContext.JobDetail.JobDataMap["PackageFilePath"];
PluginLibraryUpdateResponse catalogue;
PluginLibraryManifestV2 libraryManifest;
PluginLibraryIncompatibility libraryIncompatibility;
string pluginPackagesLocation;
if (!Plugins.PluginsLoaded)
throw new InvalidOperationException("Plugins have not been initialized");
List<Tuple<PluginManifest, string, PluginLibraryItem>> updatePlugins;
List<Tuple<PluginManifest, string, PluginLibraryItemV2, PluginLibraryItemReleaseV2>> updatePlugins;
using (DiscoDataContext database = new DiscoDataContext())
{
catalogue = Plugins.LoadCatalogue(database);
libraryManifest = PluginLibrary.LoadManifest(database);
libraryIncompatibility = libraryManifest.LoadIncompatibilityData();
pluginPackagesLocation = database.DiscoConfiguration.PluginPackagesLocation;
}
@@ -44,30 +43,41 @@ namespace Disco.Services.Plugins
{
// Update Single from Catalogue
PluginManifest existingManifest = Plugins.GetPlugin(pluginId);
var catalogueItem = catalogue.Plugins.FirstOrDefault(p => p.Id == existingManifest.Id);
var libraryItem = libraryManifest.Plugins.FirstOrDefault(p => p.Id == existingManifest.Id);
if (catalogueItem == null)
throw new InvalidOperationException("No updates are available for this Plugin");
if (Version.Parse(catalogueItem.LatestVersion) <= existingManifest.Version)
if (libraryItem == null)
throw new InvalidOperationException("This item isn't in the plugin library manifest");
var libraryItemRelease = libraryItem.LatestCompatibleRelease(libraryIncompatibility);
if (Version.Parse(libraryItemRelease.Version) <= existingManifest.Version)
throw new InvalidOperationException("Only newer versions can be used to update a plugin");
updatePlugins = new List<Tuple<PluginManifest, string, PluginLibraryItem>>() {
new Tuple<PluginManifest,string,PluginLibraryItem>(existingManifest, null, catalogueItem)
updatePlugins = new List<Tuple<PluginManifest, string, PluginLibraryItemV2, PluginLibraryItemReleaseV2>>() {
Tuple.Create(existingManifest, (string)null, libraryItem, libraryItemRelease)
};
}
else
{
// Update Single from Local
PluginManifest existingManifest = Plugins.GetPlugin(pluginId);
updatePlugins = new List<Tuple<PluginManifest, string, PluginLibraryItem>>() {
new Tuple<PluginManifest,string,PluginLibraryItem>(existingManifest, packageFilePath, null)
updatePlugins = new List<Tuple<PluginManifest, string, PluginLibraryItemV2, PluginLibraryItemReleaseV2>>() {
Tuple.Create(existingManifest, packageFilePath, (PluginLibraryItemV2)null, (PluginLibraryItemReleaseV2)null)
};
}
}
else
{
// Update All
updatePlugins = Plugins.GetPlugins().Join((IEnumerable<PluginLibraryItem>)catalogue.Plugins, manifest => manifest.Id, update => update.Id, (manifest, update) => new Tuple<PluginManifest, string, PluginLibraryItem>(manifest, null, update)).Where(i => Version.Parse(i.Item3.LatestVersion) > i.Item1.Version).ToList();
updatePlugins = Plugins.GetPlugins()
.Join(
libraryManifest.Plugins,
manifest => manifest.Id,
libraryItem => libraryItem.Id,
(manifest, libraryItem) => Tuple.Create(manifest, (string)null, libraryItem, libraryItem.LatestCompatibleRelease(libraryIncompatibility)),
StringComparer.OrdinalIgnoreCase)
.Where(i => Version.Parse(i.Item4.Version) > i.Item1.Version)
.ToList();
}
if (updatePlugins == null || updatePlugins.Count == 0)
@@ -115,31 +125,40 @@ namespace Disco.Services.Plugins
internal static void UpdateOffline(ScheduledTaskStatus Status)
{
PluginLibraryUpdateResponse pluginCatalogue = null;
PluginLibraryManifestV2 libraryManifest = null;
PluginLibraryIncompatibility libraryIncompatibility = null;
List<PluginManifest> installedPluginManifests;
string pluginPackagesLocation;
List<Tuple<PluginManifest, string, PluginLibraryItem>> updatePlugins = new List<Tuple<PluginManifest, string, PluginLibraryItem>>();
List<Tuple<PluginManifest, string, PluginLibraryItemV2, PluginLibraryItemReleaseV2>> updatePlugins =
new List<Tuple<PluginManifest, string, PluginLibraryItemV2, PluginLibraryItemReleaseV2>>();
using (DiscoDataContext database = new DiscoDataContext())
{
pluginPackagesLocation = database.DiscoConfiguration.PluginPackagesLocation;
installedPluginManifests = OfflineInstalledPlugins(database);
if (installedPluginManifests.Count > 0)
pluginCatalogue = Plugins.LoadCatalogue(database);
if (installedPluginManifests.Count > 0){
libraryManifest = PluginLibrary.LoadManifest(database);
libraryIncompatibility = libraryManifest.LoadIncompatibilityData();
}
}
if (pluginCatalogue != null && installedPluginManifests.Count > 0)
if (libraryManifest != null && installedPluginManifests.Count > 0)
{
foreach (var pluginManifest in installedPluginManifests)
{
// Check for Update
var catalogueItem = pluginCatalogue.Plugins.FirstOrDefault(i => i.Id == pluginManifest.Id && Version.Parse(i.LatestVersion) > pluginManifest.Version);
var libraryItem = libraryManifest.Plugins.FirstOrDefault(i => i.Id == pluginManifest.Id);
if (catalogueItem != null)
{ // Update Available
updatePlugins.Add(new Tuple<PluginManifest, string, PluginLibraryItem>(pluginManifest, null, catalogueItem));
if (libraryItem != null)
{
var libraryItemRelease = libraryItem.LatestCompatibleRelease(libraryIncompatibility);
if (libraryItemRelease != null && Version.Parse(libraryItemRelease.Version) > pluginManifest.Version)
{ // Update Available
updatePlugins.Add(Tuple.Create(pluginManifest, (string)null, libraryItem, libraryItemRelease));
}
}
}
}
@@ -150,18 +169,19 @@ namespace Disco.Services.Plugins
}
}
internal static void ExecuteTaskInternal(ScheduledTaskStatus Status, string pluginPackagesLocation, List<Tuple<PluginManifest, string, PluginLibraryItem>> UpdatePlugins)
internal static void ExecuteTaskInternal(ScheduledTaskStatus Status, string pluginPackagesLocation, List<Tuple<PluginManifest, string, PluginLibraryItemV2, PluginLibraryItemReleaseV2>> UpdatePlugins)
{
while (UpdatePlugins.Count > 0)
{
var updatePlugin = UpdatePlugins[0];
var existingManifest = updatePlugin.Item1;
var packageTempFilePath = updatePlugin.Item2;
var catalogueItem = updatePlugin.Item3;
var libraryItem = updatePlugin.Item3;
var libraryItemRelease = updatePlugin.Item4;
UpdatePlugins.Remove(updatePlugin);
var pluginId = existingManifest != null ? existingManifest.Id : catalogueItem.Id;
var pluginName = existingManifest != null ? existingManifest.Name : catalogueItem.Name;
var pluginId = existingManifest != null ? existingManifest.Id : libraryItemRelease.PluginId;
var pluginName = existingManifest != null ? existingManifest.Name : libraryItem.Name;
if (string.IsNullOrEmpty(packageTempFilePath))
{
@@ -176,31 +196,19 @@ namespace Disco.Services.Plugins
Directory.CreateDirectory(Path.GetDirectoryName(packageTempFilePath));
// Need to Download the Package
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(catalogueItem.LatestDownloadUrl);
webRequest.KeepAlive = false;
webRequest.ContentType = "application/xml";
webRequest.Method = WebRequestMethods.Http.Get;
webRequest.UserAgent = string.Format("Disco/{0} (PluginLibrary)", Disco.Services.Plugins.CommunityInterop.PluginLibraryUpdateTask.CurrentDiscoVersion());
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
using (HttpClient httpClient = new HttpClient())
{
if (webResponse.StatusCode == HttpStatusCode.OK)
Status.UpdateStatus(0, "Downloading...");
using (var httpResponse = httpClient.GetAsync(libraryItemRelease.DownloadUrl).Result)
{
Status.UpdateStatus(0, "Downloading...");
using (var wResStream = webResponse.GetResponseStream())
httpResponse.EnsureSuccessStatusCode();
using (FileStream fsOut = new FileStream(packageTempFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (FileStream fsOut = new FileStream(packageTempFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
{
wResStream.CopyTo(fsOut);
}
httpResponse.Content.ReadAsStreamAsync().Result.CopyTo(fsOut);
}
}
else
{
Status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
return;
}
}
}
@@ -234,10 +242,10 @@ namespace Disco.Services.Plugins
using (DiscoDataContext database = new DiscoDataContext())
{
// Check for Compatibility
var compatibilityData = Plugins.LoadCompatibilityData(database);
var pluginCompatibility = compatibilityData.Plugins.FirstOrDefault(i => i.Id.Equals(updateManifest.Id, StringComparison.OrdinalIgnoreCase) && updateManifest.Version == Version.Parse(i.Version));
if (pluginCompatibility != null && !pluginCompatibility.Compatible)
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", updateManifest.Id, updateManifest.VersionFormatted, pluginCompatibility.Reason));
var incompatibilityLibrary = PluginLibrary.LoadManifest(database).LoadIncompatibilityData();
PluginIncompatibility incompatibility;
if (!incompatibilityLibrary.IsCompatible(updateManifest.Id, updateManifest.Version, out incompatibility))
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", updateManifest.Id, updateManifest.VersionFormatted, incompatibility.Reason));
var updatePluginPath = Path.Combine(database.DiscoConfiguration.PluginsLocation, string.Format("{0}.discoPlugin", updateManifest.Id));
File.Move(packageTempFilePath, updatePluginPath);
@@ -1,9 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Disco.Data.Repository;
using Disco.Services.Interop.DiscoServices;
using Disco.Services.Tasks;
using System;
using System.Linq;
namespace Disco.Services.Plugins
{
@@ -20,12 +19,15 @@ namespace Disco.Services.Plugins
// Wait for App to Load (10 Seconds)
for (int i = 0; i < 10; i++)
{
this.Status.UpdateStatus(10 * i);
this.Status.UpdateStatus(10 * i);
System.Threading.Thread.Sleep(1000);
}
// Update Catalogue
CommunityInterop.PluginLibraryUpdateTask.ExecuteTaskInternal(this.Status);
using (DiscoDataContext database = new DiscoDataContext())
{
PluginLibrary.UpdateManifest(database, this.Status);
}
// Update all Plugins
UpdatePluginTask.UpdateOffline(this.Status);
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.0.0626.0000")]
[assembly: AssemblyFileVersion("2.0.0626.0000")]
[assembly: AssemblyVersion("2.0.0918.1700")]
[assembly: AssemblyFileVersion("2.0.0918.1700")]
+10 -6
View File
@@ -22,6 +22,8 @@ namespace Disco.Services.Searching
IQueryable<Job> query = default(IQueryable<Job>);
string userIdTerm = Term.Contains('\\') ? Term : ActiveDirectory.ParseDomainAccountId(Term);
if (int.TryParse(Term, out termInt))
{
// Term is a Number (int)
@@ -29,7 +31,7 @@ namespace Disco.Services.Searching
j.Id == termInt ||
j.Device.SerialNumber.Contains(Term) ||
j.Device.AssetNumber.Contains(Term) ||
j.User.UserId == Term ||
j.User.UserId == userIdTerm ||
j.User.DisplayName.Contains(Term));
}
else
@@ -37,7 +39,7 @@ namespace Disco.Services.Searching
query = Database.Jobs.Where(j =>
j.Device.SerialNumber.Contains(Term) ||
j.Device.AssetNumber.Contains(Term) ||
j.User.UserId == Term ||
j.User.UserId == userIdTerm ||
j.User.DisplayName.Contains(Term));
}
@@ -65,6 +67,8 @@ namespace Disco.Services.Searching
IQueryable<Job> query = default(IQueryable<Job>);
string userIdTerm = Term.Contains('\\') ? Term : ActiveDirectory.ParseDomainAccountId(Term);
if (int.TryParse(Term, out termInt))
{
// Term is a Number (int)
@@ -75,7 +79,7 @@ namespace Disco.Services.Searching
j.DeviceHeldLocation.Contains(Term) ||
j.Device.SerialNumber.Contains(Term) ||
j.Device.AssetNumber.Contains(Term) ||
j.User.UserId == Term ||
j.User.UserId == userIdTerm ||
j.User.Surname.Contains(Term) ||
j.User.GivenName.Contains(Term) ||
j.User.DisplayName.Contains(Term) ||
@@ -89,7 +93,7 @@ namespace Disco.Services.Searching
j.DeviceHeldLocation.Contains(Term) ||
j.Device.SerialNumber.Contains(Term) ||
j.Device.AssetNumber.Contains(Term) ||
j.User.UserId == Term ||
j.User.UserId == userIdTerm ||
j.User.Surname.Contains(Term) ||
j.User.GivenName.Contains(Term) ||
j.User.DisplayName.Contains(Term));
@@ -103,7 +107,7 @@ namespace Disco.Services.Searching
j.DeviceHeldLocation.Contains(Term) ||
j.Device.SerialNumber.Contains(Term) ||
j.Device.AssetNumber.Contains(Term) ||
j.User.UserId == Term ||
j.User.UserId == userIdTerm ||
j.User.Surname.Contains(Term) ||
j.User.GivenName.Contains(Term) ||
j.User.DisplayName.Contains(Term) ||
@@ -116,7 +120,7 @@ namespace Disco.Services.Searching
j.DeviceHeldLocation.Contains(Term) ||
j.Device.SerialNumber.Contains(Term) ||
j.Device.AssetNumber.Contains(Term) ||
j.User.UserId == Term ||
j.User.UserId == userIdTerm ||
j.User.Surname.Contains(Term) ||
j.User.GivenName.Contains(Term) ||
j.User.DisplayName.Contains(Term));

Some files were not shown because too many files have changed in this diff Show More