36 Commits

Author SHA1 Message Date
Gary Sharp 5f4cb20900 #138 display device flags where appropriate in the UI 2024-01-14 19:13:09 +11:00
Gary Sharp aee467cb53 #138 add/remove individual device flags UI 2024-01-14 18:29:58 +11:00
Gary Sharp 6ce6e2cccf #138 device flags configuration API and UI 2024-01-14 17:59:30 +11:00
Gary Sharp cd858c2215 #138 device flag searching 2024-01-14 17:56:20 +11:00
Gary Sharp 7e07c07171 #138 device flag export service 2024-01-14 17:55:20 +11:00
Gary Sharp 15e2806731 #138 device flag services 2024-01-14 17:54:06 +11:00
Gary Sharp 53baf4eb78 #138 device flag authorization claims 2024-01-13 16:56:23 +11:00
Gary Sharp 8c48ab6ecd #138 device flag models 2024-01-13 16:33:03 +11:00
Gary Sharp 8afe4195a9 #107 allow moving of device OU when changing profile 2024-01-12 12:53:50 +11:00
Gary Sharp dcc4fcb984 #107 support moving profiles devices when changing the organisational unit 2024-01-12 12:52:39 +11:00
Gary Sharp 4631903019 refactor: split windows/mac enrolment 2024-01-12 11:13:48 +11:00
Gary Sharp 85d51c0e45 Fix #141 preserve computer names for non-domain joined devices 2024-01-11 16:27:40 +11:00
Gary Sharp 974a07f3bb show a warning when a device profile OU couuld not be found 2023-11-24 12:58:12 +11:00
Gary Sharp b576aec641 feature: computer name template testing 2023-11-24 11:57:26 +11:00
Gary Sharp a2aaa4c913 #140 make additional fontawesome icons available for user flags 2023-11-12 21:25:16 +11:00
Gary Sharp 318a70d9a3 #140 upgrade fontawesome 2023-11-12 21:24:16 +11:00
Gary Sharp 53e57d4017 feature: user flag assignment exporting 2023-11-11 20:04:52 +11:00
Gary Sharp 143dc1b3e6 bug fix: when exporting devices refresh details before extracting records instead of after 2023-11-11 18:59:59 +11:00
Gary Sharp a4f18d1d49 initial refactor of device export so it can be reused for future exporting 2023-11-11 17:52:24 +11:00
Gary Sharp 46222f2a78 hide decommissioned device profiles and batches by default when updating a devices batch or profile 2023-11-09 20:48:16 +11:00
Gary Sharp 2e091383ec fixes #134 - hide decommissioned device profiles by default 2023-11-09 20:05:25 +11:00
Gary Sharp 7ace4d1c7e add padding row to device batch list to maintain alternating row styles 2023-11-09 19:55:22 +11:00
Gary Sharp f901d45d78 support Firefox checkbox inside anchor element when logging warranty 2023-11-09 14:05:48 +11:00
Gary Sharp 028d1ccc64 remove localhost-only requirement for post upgrade maintenance 2023-11-09 13:43:51 +11:00
Gary Sharp 7b6a44921d plugin library: link to configuration instead of disabled "installed" button 2023-11-09 13:43:09 +11:00
Gary Sharp 23406e5e39 include more inner exception data in system logging 2023-11-08 16:51:08 +11:00
Gary Sharp 83557e6f0c include external job references in detailed search 2023-11-08 16:49:19 +11:00
Gary Sharp 1c90c89158 upgrade ssh.net 2023-11-06 11:25:38 +11:00
Gary Sharp 9924153e82 upgrade dotnet framework 4.5 to 4.6 2023-11-06 11:24:58 +11:00
Gary Sharp 3ec2ea7d37 add job log when re-opening 2023-11-03 15:50:01 +11:00
Gary Sharp b6945d9bbd fix #135 avoid failing device import/enrol when unable to set AD description 2023-10-12 17:37:42 +11:00
Gary Sharp 6740a7479a bug: disable image (camera) attachment upload unless over HTTPS
Browser restriction: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#privacy_and_security
2023-10-12 16:34:35 +11:00
Gary Sharp a3fb09440d feature: document template QR Code image extensions 2023-10-12 16:07:14 +11:00
Gary Sharp 7353405b16 use native media devices to capture webcam images 2023-10-08 16:25:32 +11:00
Gary Sharp 6fcb1a1eae fixup Disco -> Disco ICT 2023-07-26 19:01:31 +10:00
Gary Sharp e204ea4d5f version bump for release candidate 2023-06-10 17:18:04 +10:00
381 changed files with 23052 additions and 6810 deletions
+4
View File
@@ -0,0 +1,4 @@
[*.cs]
# VSSpell001: Spell Check
dotnet_diagnostic.VSSpell001.severity = suggestion
@@ -9,7 +9,6 @@ using Disco.Services.Interop.ActiveDirectory;
using iTextSharp.text.pdf; using iTextSharp.text.pdf;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data.Entity;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
+21 -7
View File
@@ -1,8 +1,8 @@
using Disco.BI.Extensions; using Disco.BI.Extensions;
using Disco.Data.Repository; using Disco.Data.Repository;
using Disco.Models.BI.Expressions;
using Disco.Models.Repository; using Disco.Models.Repository;
using Disco.Models.Services.Documents; using Disco.Models.Services.Documents;
using Disco.Models.Services.Expressions.Extensions;
using Disco.Services; using Disco.Services;
using Disco.Services.Documents; using Disco.Services.Documents;
using Disco.Services.Expressions; using Disco.Services.Expressions;
@@ -268,16 +268,15 @@ namespace Disco.BI.Interop.Pdf
var pageUniqueIdBytes = pageUniqueId.ToQRCodeBytes(); var pageUniqueIdBytes = pageUniqueId.ToQRCodeBytes();
// Encode to QRCode byte array // Encode to QRCode byte array
var pageUniqueIdWidth = (int)pdfFieldPosition.position.Width; var pageUniqueIdEncoded = QRCodeBinaryEncoder.Encode(pageUniqueIdBytes, out var qrWidth, out var qrHeight);
var pageUniqueIdHeight = (int)pdfFieldPosition.position.Height;
var pageUniqueIdEncoded = QRCodeBinaryEncoder.Encode(pageUniqueIdBytes, pageUniqueIdWidth, pageUniqueIdHeight);
// Encode byte array to Image // Encode byte array to Image
var pageUniqueIdImageData = CCITTG4Encoder.Compress(pageUniqueIdEncoded, pageUniqueIdWidth, pageUniqueIdHeight); var pageUniqueIdImageData = CCITTG4Encoder.Compress(pageUniqueIdEncoded, qrWidth, qrHeight);
var pageUniqueIdImage = iTextSharp.text.Image.GetInstance(pageUniqueIdWidth, pageUniqueIdHeight, false, 256, 1, pageUniqueIdImageData, null); var pageUniqueIdImage = iTextSharp.text.Image.GetInstance(qrWidth, qrHeight, false, 256, 1, pageUniqueIdImageData, null);
// Add to the pdf page // Add to the pdf page
pageUniqueIdImage.SetAbsolutePosition(pdfFieldPosition.position.Left, pdfFieldPosition.position.Bottom); pageUniqueIdImage.SetAbsolutePosition(pdfFieldPosition.position.Left, pdfFieldPosition.position.Bottom);
pageUniqueIdImage.ScaleToFit(pdfFieldPosition.position.Width, pdfFieldPosition.position.Height);
pdfStamper.GetOverContent(pdfFieldPosition.page).AddImage(pageUniqueIdImage); pdfStamper.GetOverContent(pdfFieldPosition.page).AddImage(pageUniqueIdImage);
} }
// Hide Fields // Hide Fields
@@ -315,7 +314,22 @@ namespace Disco.BI.Interop.Pdf
for (int pdfFieldOrdinal = 0; pdfFieldOrdinal < fields.Size; pdfFieldOrdinal++) for (int pdfFieldOrdinal = 0; pdfFieldOrdinal < fields.Size; pdfFieldOrdinal++)
{ {
AcroFields.FieldPosition pdfFieldPosition = pdfFieldPositions[pdfFieldOrdinal]; AcroFields.FieldPosition pdfFieldPosition = pdfFieldPositions[pdfFieldOrdinal];
iTextSharp.text.Image pdfImage = iTextSharp.text.Image.GetInstance(imageResult.GetImage((int)(pdfFieldPosition.position.Width * 1.6), (int)(pdfFieldPosition.position.Height * 1.6)));
iTextSharp.text.Image pdfImage;
var imageWidth = (int)(pdfFieldPosition.position.Width * 1.6);
var imageHeight = (int)(pdfFieldPosition.position.Height * 1.6);
if (imageResult.Format == ImageExpressionFormat.Jpeg || imageResult.Format == ImageExpressionFormat.Png)
{
pdfImage = iTextSharp.text.Image.GetInstance(imageResult.GetImage(imageWidth, imageHeight));
}
else if (imageResult.Format == ImageExpressionFormat.CcittG4)
{
var imageData = imageResult.GetImage(out imageWidth, out imageHeight);
pdfImage = iTextSharp.text.Image.GetInstance(imageWidth, imageHeight, false, 256, 1, imageData.GetBuffer(), null);
}
else
throw new NotSupportedException($"Unexpected image format {imageResult.Format}");
pdfImage.SetAbsolutePosition(pdfFieldPosition.position.Left, pdfFieldPosition.position.Bottom); pdfImage.SetAbsolutePosition(pdfFieldPosition.position.Left, pdfFieldPosition.position.Bottom);
pdfImage.ScaleToFit(pdfFieldPosition.position.Width, pdfFieldPosition.position.Height); pdfImage.ScaleToFit(pdfFieldPosition.position.Width, pdfFieldPosition.position.Height);
pdfStamper.GetOverContent(pdfFieldPosition.page).AddImage(pdfImage); pdfStamper.GetOverContent(pdfFieldPosition.page).AddImage(pdfImage);
+7
View File
@@ -1,5 +1,7 @@
using iTextSharp.text; using iTextSharp.text;
using iTextSharp.text.pdf; using iTextSharp.text.pdf;
using iTextSharp.text.pdf.codec;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@@ -7,6 +9,11 @@ namespace Disco.BI.Interop.Pdf
{ {
public static class Utilities public static class Utilities
{ {
public static Func<byte[], int, int, byte[]> GetCCITTG4EncoderCompressDelegate()
{
return CCITTG4Encoder.Compress;
}
public static Stream JoinPdfs(bool InsertBlankPages, List<Stream> Pdfs) public static Stream JoinPdfs(bool InsertBlankPages, List<Stream> Pdfs)
{ {
if (Pdfs.Count == 0) if (Pdfs.Count == 0)
+1 -1
View File
@@ -10,7 +10,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Disco</RootNamespace> <RootNamespace>Disco</RootNamespace>
<AssemblyName>Disco.BI</AssemblyName> <AssemblyName>Disco.BI</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<TargetFrameworkProfile /> <TargetFrameworkProfile />
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir> <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+3 -3
View File
@@ -1,4 +1,4 @@
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.2.16326.0500")] [assembly: AssemblyVersion("2.3.23161.0650")]
[assembly: AssemblyFileVersion("2.2.16326.0500")] [assembly: AssemblyFileVersion("2.3.23161.0650")]
+1 -1
View File
@@ -19,7 +19,7 @@ namespace Disco.Properties {
// class via a tool like ResGen or Visual Studio. // class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen // To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project. // with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources { internal class Resources {
+23 -23
View File
@@ -1,57 +1,57 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<configuration> <configuration>
<configSections> <configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
</configSections> </configSections>
<system.serviceModel> <system.serviceModel>
<bindings /> <bindings/>
<client /> <client/>
</system.serviceModel> </system.serviceModel>
<entityFramework> <entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework"> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
<parameters> <parameters>
<parameter value="Data Source=(localdb)\v11.0; Integrated Security=True; MultipleActiveResultSets=True" /> <parameter value="Data Source=(localdb)\v11.0; Integrated Security=True; MultipleActiveResultSets=True"/>
</parameters> </parameters>
</defaultConnectionFactory> </defaultConnectionFactory>
</entityFramework> </entityFramework>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
</startup> </startup>
<runtime> <runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" /> <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" /> <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" /> <bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="System.Web.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <assemblyIdentity name="System.Web.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" /> <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <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" /> <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral" /> <assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" /> <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0" /> <bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0" /> <bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0"/>
</dependentAssembly> </dependentAssembly>
</assemblyBinding> </assemblyBinding>
</runtime> </runtime>
</configuration> </configuration>
+5 -5
View File
@@ -331,7 +331,7 @@ namespace Disco.Client.Interop
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new Exception("Disco Client was unable to retrieve BIOS information from WMI", ex); throw new Exception("Disco ICT Client was unable to retrieve BIOS information from WMI", ex);
} }
} }
@@ -394,7 +394,7 @@ namespace Disco.Client.Interop
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new Exception("Disco Client was unable to retrieve ComputerSystem information from WMI", ex); throw new Exception("Disco ICT Client was unable to retrieve ComputerSystem information from WMI", ex);
} }
} }
@@ -427,7 +427,7 @@ namespace Disco.Client.Interop
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new Exception("Disco Client was unable to retrieve ComputerSystem information from WMI", ex); throw new Exception("Disco ICT Client was unable to retrieve ComputerSystem information from WMI", ex);
} }
} }
@@ -504,7 +504,7 @@ namespace Disco.Client.Interop
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new Exception("Disco Client was unable to retrieve BaseBoard information from WMI", ex); throw new Exception("Disco ICT Client was unable to retrieve BaseBoard information from WMI", ex);
} }
} }
@@ -556,7 +556,7 @@ namespace Disco.Client.Interop
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new Exception("Disco Client was unable to retrieve ComputerSystemProduct information from WMI", ex); throw new Exception("Disco ICT Client was unable to retrieve ComputerSystemProduct information from WMI", ex);
} }
} }
+1 -1
View File
@@ -68,7 +68,7 @@ namespace Disco.Client.Interop
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new Exception("Disco Client was unable to retrieve NetworkAdapter information from WMI", ex); throw new Exception("Disco ICT Client was unable to retrieve NetworkAdapter information from WMI", ex);
} }
} }
+3 -3
View File
@@ -61,7 +61,7 @@ namespace Disco.Client.Interop
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new Exception("Disco Client was unable to retrieve Wireless NetworkAdapter information from WlanApi", ex); throw new Exception("Disco ICT Client was unable to retrieve Wireless NetworkAdapter information from WlanApi", ex);
} }
} }
@@ -102,7 +102,7 @@ namespace Disco.Client.Interop
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new Exception("Disco Client was unable to retrieve Wireless Profiles from WlanApi", ex); throw new Exception("Disco ICT Client was unable to retrieve Wireless Profiles from WlanApi", ex);
} }
} }
@@ -356,7 +356,7 @@ namespace Disco.Client.Interop
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new Exception("Disco Client was unable to apply Wireless Profile Changes using WlanApi", ex); throw new Exception("Disco ICT Client was unable to apply Wireless Profile Changes using WlanApi", ex);
} }
} }
+3 -3
View File
@@ -1,4 +1,4 @@
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.2.16326.0500")] [assembly: AssemblyVersion("2.3.23161.0650")]
[assembly: AssemblyFileVersion("2.2.16326.0500")] [assembly: AssemblyFileVersion("2.3.23161.0650")]
+7 -7
View File
@@ -85,12 +85,12 @@ namespace Disco.ClientBootstrapper
// Check for Network Connectivity // Check for Network Connectivity
statusUI.UpdateStatus(null, "Detecting Network", "Checking network connectivity, Please wait...", true, -1); statusUI.UpdateStatus(null, "Detecting Network", "Checking network connectivity, Please wait...", true, -1);
if (!Interop.NetworkInterop.PingDisco(DiscoServerName)) if (!Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
{ {
statusUI.UpdateStatus(null, "Detecting Network", "No network connectivity detected, Diagnosing...", true, -1); statusUI.UpdateStatus(null, "Detecting Network", "No network connectivity detected, Diagnosing...", true, -1);
statusUI_WriteAdapterInfo(); statusUI_WriteAdapterInfo();
if (!Interop.NetworkInterop.PingDisco(DiscoServerName)) if (!Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
{ {
// Check for Wireless // Check for Wireless
var hasWireless = (Interop.NetworkInterop.NetworkAdapters.Count(na => na.IsWireless) > 0); var hasWireless = (Interop.NetworkInterop.NetworkAdapters.Count(na => na.IsWireless) > 0);
@@ -105,17 +105,17 @@ namespace Disco.ClientBootstrapper
statusUI_WriteAdapterInfo(); statusUI_WriteAdapterInfo();
statusUI.UpdateStatus(null, null, null, true, i); statusUI.UpdateStatus(null, null, null, true, i);
Program.SleepThread(500, false); Program.SleepThread(500, false);
if (Interop.NetworkInterop.PingDisco(DiscoServerName)) if (Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
break; break;
} }
if (!Interop.NetworkInterop.PingDisco(DiscoServerName)) if (!Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
{ {
statusUI.UpdateStatus(null, "Wireless Network Failed", "Unable to connect to the wireless network, please connect the network cable...", false); statusUI.UpdateStatus(null, "Wireless Network Failed", "Unable to connect to the wireless network, please connect the network cable...", false);
Program.SleepThread(3000, false); Program.SleepThread(3000, false);
} }
} }
if (!Interop.NetworkInterop.PingDisco(DiscoServerName)) if (!Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
{ {
// Instruct user to connect network cable // Instruct user to connect network cable
statusUI.UpdateStatus(null, "Please connect the network cable", null); statusUI.UpdateStatus(null, "Please connect the network cable", null);
@@ -124,13 +124,13 @@ namespace Disco.ClientBootstrapper
statusUI_WriteAdapterInfo(); statusUI_WriteAdapterInfo();
statusUI.UpdateStatus(null, null, null, true, i); statusUI.UpdateStatus(null, null, null, true, i);
Program.SleepThread(500, false); Program.SleepThread(500, false);
if (Interop.NetworkInterop.PingDisco(DiscoServerName)) if (Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
break; break;
} }
} }
} }
if (!Interop.NetworkInterop.PingDisco(DiscoServerName)) if (!Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
{ {
// Client Failed // Client Failed
if (this.mLoopCompleteCallback != null) if (this.mLoopCompleteCallback != null)
@@ -8,4 +8,4 @@ BootstrapperLocation = Mid(WScript.ScriptFullName, 1, InStrRev(WScript.ScriptFul
Call objShell.Run("""" & BootstrapperLocation & """ /Install", , True) Call objShell.Run("""" & BootstrapperLocation & """ /Install", , True)
WScript.Echo "Disco Client Bootstrapper Installed" WScript.Echo "Disco ICT Client Bootstrapper Installed"
+2 -2
View File
@@ -85,7 +85,7 @@
this.labelVersion.Name = "labelVersion"; this.labelVersion.Name = "labelVersion";
this.labelVersion.Size = new System.Drawing.Size(167, 20); this.labelVersion.Size = new System.Drawing.Size(167, 20);
this.labelVersion.TabIndex = 0; this.labelVersion.TabIndex = 0;
this.labelVersion.Text = "Disco Bootstrapper v"; this.labelVersion.Text = "Disco ICT Bootstrapper v";
this.labelVersion.TextAlign = System.Drawing.ContentAlignment.TopRight; this.labelVersion.TextAlign = System.Drawing.ContentAlignment.TopRight;
// //
// FormStatus // FormStatus
@@ -106,7 +106,7 @@
this.ShowIcon = false; this.ShowIcon = false;
this.ShowInTaskbar = false; this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Disco - Client Bootstrapper"; this.Text = "Disco ICT - Client Bootstrapper";
this.TopMost = true; this.TopMost = true;
this.TransparencyKey = System.Drawing.Color.Magenta; this.TransparencyKey = System.Drawing.Color.Magenta;
this.ResumeLayout(false); this.ResumeLayout(false);
@@ -165,7 +165,7 @@ namespace Disco.ClientBootstrapper.Interop
} }
} }
public static bool PingDisco(string ServerName) public static bool PingDiscoIct(string ServerName)
{ {
using (Ping p = new Ping()) using (Ping p = new Ping())
{ {
@@ -1,4 +1,4 @@
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.2.16326.0500")] [assembly: AssemblyVersion("2.3.23161.0650")]
[assembly: AssemblyFileVersion("2.2.16326.0500")] [assembly: AssemblyFileVersion("2.3.23161.0650")]
+2 -2
View File
@@ -15,6 +15,6 @@
</defaultConnectionFactory> </defaultConnectionFactory>
</entityFramework> </entityFramework>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
</startup> </startup>
</configuration> </configuration>
+8 -1
View File
@@ -10,7 +10,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Disco.Data</RootNamespace> <RootNamespace>Disco.Data</RootNamespace>
<AssemblyName>Disco.Data</AssemblyName> <AssemblyName>Disco.Data</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<TargetFrameworkProfile /> <TargetFrameworkProfile />
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir> <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
@@ -175,6 +175,10 @@
<Compile Include="Migrations\202304150715559_DBv22.Designer.cs"> <Compile Include="Migrations\202304150715559_DBv22.Designer.cs">
<DependentUpon>202304150715559_DBv22.cs</DependentUpon> <DependentUpon>202304150715559_DBv22.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Migrations\202401130531317_DBv23.cs" />
<Compile Include="Migrations\202401130531317_DBv23.Designer.cs">
<DependentUpon>202401130531317_DBv23.cs</DependentUpon>
</Compile>
<Compile Include="Migrations\Configuration.cs" /> <Compile Include="Migrations\Configuration.cs" />
<Compile Include="Migrations\DiscoDataMigrator.cs" /> <Compile Include="Migrations\DiscoDataMigrator.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
@@ -256,6 +260,9 @@
<EmbeddedResource Include="Migrations\202304150715559_DBv22.resx"> <EmbeddedResource Include="Migrations\202304150715559_DBv22.resx">
<DependentUpon>202304150715559_DBv22.cs</DependentUpon> <DependentUpon>202304150715559_DBv22.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Migrations\202401130531317_DBv23.resx">
<DependentUpon>202401130531317_DBv23.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx"> <EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+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 DBv23 : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(DBv23));
string IMigrationMetadata.Id
{
get { return "202401130531317_DBv23"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
}
}
}
@@ -0,0 +1,67 @@
namespace Disco.Data.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class DBv23 : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.DeviceFlagAssignments",
c => new
{
Id = c.Int(nullable: false, identity: true),
DeviceFlagId = c.Int(nullable: false),
DeviceSerialNumber = c.String(nullable: false, maxLength: 60),
AddedDate = c.DateTime(nullable: false),
AddedUserId = c.String(nullable: false, maxLength: 50),
RemovedDate = c.DateTime(),
RemovedUserId = c.String(maxLength: 50),
Comments = c.String(),
OnAssignmentExpressionResult = c.String(),
OnUnassignmentExpressionResult = c.String(),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.DeviceFlags", t => t.DeviceFlagId)
.ForeignKey("dbo.Devices", t => t.DeviceSerialNumber)
.ForeignKey("dbo.Users", t => t.AddedUserId)
.ForeignKey("dbo.Users", t => t.RemovedUserId)
.Index(t => t.DeviceFlagId)
.Index(t => t.DeviceSerialNumber)
.Index(t => t.AddedUserId)
.Index(t => t.RemovedUserId);
CreateTable(
"dbo.DeviceFlags",
c => new
{
Id = c.Int(nullable: false, identity: true),
Name = c.String(nullable: false, maxLength: 100),
Description = c.String(maxLength: 500),
Icon = c.String(nullable: false, maxLength: 25),
IconColour = c.String(nullable: false, maxLength: 10),
DevicesLinkedGroup = c.String(),
DeviceUsersLinkedGroup = c.String(),
OnAssignmentExpression = c.String(),
OnUnassignmentExpression = c.String(),
})
.PrimaryKey(t => t.Id);
}
public override void Down()
{
DropIndex("dbo.DeviceFlagAssignments", new[] { "RemovedUserId" });
DropIndex("dbo.DeviceFlagAssignments", new[] { "AddedUserId" });
DropIndex("dbo.DeviceFlagAssignments", new[] { "DeviceSerialNumber" });
DropIndex("dbo.DeviceFlagAssignments", new[] { "DeviceFlagId" });
DropForeignKey("dbo.DeviceFlagAssignments", "RemovedUserId", "dbo.Users");
DropForeignKey("dbo.DeviceFlagAssignments", "AddedUserId", "dbo.Users");
DropForeignKey("dbo.DeviceFlagAssignments", "DeviceSerialNumber", "dbo.Devices");
DropForeignKey("dbo.DeviceFlagAssignments", "DeviceFlagId", "dbo.DeviceFlags");
DropTable("dbo.DeviceFlags");
DropTable("dbo.DeviceFlagAssignments");
}
}
}
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -1,4 +1,4 @@
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.2.16326.0500")] [assembly: AssemblyVersion("2.3.23161.0650")]
[assembly: AssemblyFileVersion("2.2.16326.0500")] [assembly: AssemblyFileVersion("2.3.23161.0650")]
+2 -2
View File
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
// Runtime Version:4.0.30319.17929 // Runtime Version:4.0.30319.42000
// //
// Changes to this file may cause incorrect behavior and will be lost if // Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. // the code is regenerated.
@@ -19,7 +19,7 @@ namespace Disco.Data.Properties {
// class via a tool like ResGen or Visual Studio. // class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen // To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project. // with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources { internal class Resources {
+4 -5
View File
@@ -1,9 +1,6 @@
using System; using Disco.Models.Repository;
using System.Collections.Generic; using System;
using System.Linq;
using System.Text;
using System.Data.Entity; using System.Data.Entity;
using Disco.Models.Repository;
using System.Data.Entity.ModelConfiguration.Conventions; using System.Data.Entity.ModelConfiguration.Conventions;
namespace Disco.Data.Repository namespace Disco.Data.Repository
@@ -38,6 +35,8 @@ namespace Disco.Data.Repository
public virtual DbSet<DeviceBatchAttachment> DeviceBatchAttachments { get; set; } public virtual DbSet<DeviceBatchAttachment> DeviceBatchAttachments { get; set; }
public virtual DbSet<DeviceComponent> DeviceComponents { get; set; } public virtual DbSet<DeviceComponent> DeviceComponents { get; set; }
public virtual DbSet<DeviceAttachment> DeviceAttachments { get; set; } public virtual DbSet<DeviceAttachment> DeviceAttachments { get; set; }
public virtual DbSet<DeviceFlag> DeviceFlags { get; set; }
public virtual DbSet<DeviceFlagAssignment> DeviceFlagAssignments { get; set; }
public virtual DbSet<DeviceCertificate> DeviceCertificates { get; set; } public virtual DbSet<DeviceCertificate> DeviceCertificates { get; set; }
+12 -14
View File
@@ -1,11 +1,9 @@
using System; using Disco.Models.Repository;
using System.Collections.Generic; using System;
using System.Linq;
using System.Text;
using Disco.Models.Repository;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.DirectoryServices.ActiveDirectory;
using System.DirectoryServices; using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
using System.Linq;
namespace Disco.Data.Repository namespace Disco.Data.Repository
{ {
@@ -370,7 +368,7 @@ DELETE [Users] WHERE [Id]=@IdExisting;";
string defaultNamingContext; string defaultNamingContext;
using (Domain d = Domain.GetComputerDomain()) using (Domain d = Domain.GetComputerDomain())
{ {
string ldapPath = string.Format("LDAP://{0}/", d.Name); string ldapPath = $"LDAP://{d.Name}/";
string configurationNamingContext; string configurationNamingContext;
using (var adRootDSE = new DirectoryEntry(ldapPath + "RootDSE")) using (var adRootDSE = new DirectoryEntry(ldapPath + "RootDSE"))
@@ -381,7 +379,7 @@ DELETE [Users] WHERE [Id]=@IdExisting;";
using (var configSearchRoot = new DirectoryEntry(ldapPath + "CN=Partitions," + configurationNamingContext)) using (var configSearchRoot = new DirectoryEntry(ldapPath + "CN=Partitions," + configurationNamingContext))
{ {
var configSearchFilter = string.Format("(&(objectcategory=Crossref)(dnsRoot={0})(netBIOSName=*))", d.Name); var configSearchFilter = $"(&(objectcategory=Crossref)(dnsRoot={d.Name})(netBIOSName=*))";
var configSearchLoadProperites = new string[] { "NetBIOSName" }; var configSearchLoadProperites = new string[] { "NetBIOSName" };
using (var configSearcher = new DirectorySearcher(configSearchRoot, configSearchFilter, configSearchLoadProperites, SearchScope.OneLevel)) using (var configSearcher = new DirectorySearcher(configSearchRoot, configSearchFilter, configSearchLoadProperites, SearchScope.OneLevel))
@@ -403,14 +401,14 @@ DELETE [Users] WHERE [Id]=@IdExisting;";
// Authorization Roles // Authorization Roles
foreach (var authRole in Database.AuthorizationRoles.Where(ar => ar.SubjectIds != null).ToList()) foreach (var authRole in Database.AuthorizationRoles.Where(ar => ar.SubjectIds != null).ToList())
{ {
var ids = string.Join(",", authRole.SubjectIds.Split(',').Select(id => id.Contains('\\') ? id : string.Format("{0}\\{1}", netBiosName, id))); var ids = string.Join(",", authRole.SubjectIds.Split(',').Select(id => id.Contains('\\') ? id : $@"{netBiosName}\{id}"));
if (ids != authRole.SubjectIds) if (ids != authRole.SubjectIds)
authRole.SubjectIds = ids; authRole.SubjectIds = ids;
} }
// Job Queues // Job Queues
foreach (var jobQueue in Database.JobQueues.Where(jq => jq.SubjectIds != null).ToList()) foreach (var jobQueue in Database.JobQueues.Where(jq => jq.SubjectIds != null).ToList())
{ {
var ids = string.Join(",", jobQueue.SubjectIds.Split(',').Select(id => id.Contains('\\') ? id : string.Format("{0}\\{1}", netBiosName, id))); var ids = string.Join(",", jobQueue.SubjectIds.Split(',').Select(id => id.Contains('\\') ? id : $@"{netBiosName}\{id}"));
if (ids != jobQueue.SubjectIds) if (ids != jobQueue.SubjectIds)
jobQueue.SubjectIds = ids; jobQueue.SubjectIds = ids;
} }
@@ -418,9 +416,9 @@ DELETE [Users] WHERE [Id]=@IdExisting;";
foreach (var deviceProfile in Database.DeviceProfiles.Where(dp => dp.OrganisationalUnit == null || !dp.OrganisationalUnit.Contains(@"DC=")).ToList()) foreach (var deviceProfile in Database.DeviceProfiles.Where(dp => dp.OrganisationalUnit == null || !dp.OrganisationalUnit.Contains(@"DC=")).ToList())
{ {
if (string.IsNullOrWhiteSpace(deviceProfile.OrganisationalUnit)) if (string.IsNullOrWhiteSpace(deviceProfile.OrganisationalUnit))
deviceProfile.OrganisationalUnit = string.Format("CN=Computers,{0}", defaultNamingContext); deviceProfile.OrganisationalUnit = $"CN=Computers,{defaultNamingContext}";
else else
deviceProfile.OrganisationalUnit = string.Format("{0},{1}", deviceProfile.OrganisationalUnit, defaultNamingContext); deviceProfile.OrganisationalUnit = $"{deviceProfile.OrganisationalUnit},{defaultNamingContext}";
} }
Database.SaveChanges(); Database.SaveChanges();
@@ -451,7 +449,7 @@ DELETE [Users] WHERE [Id]=@IdExisting;";
// MIGRATE DEVICES // MIGRATE DEVICES
foreach (var device in Database.Devices.Where(d => d.DeviceDomainId != null && !d.DeviceDomainId.Contains(@"\")).ToList()) foreach (var device in Database.Devices.Where(d => d.DeviceDomainId != null && !d.DeviceDomainId.Contains(@"\")).ToList())
{ {
device.DeviceDomainId = string.Format("{0}\\{1}", netBiosName, device.DeviceDomainId); device.DeviceDomainId = $@"{netBiosName}\{device.DeviceDomainId}";
} }
Database.SaveChanges(); Database.SaveChanges();
@@ -462,7 +460,7 @@ DELETE [Users] WHERE [Id]=@IdExisting;";
idExisting.Value = user.UserId; idExisting.Value = user.UserId;
SqlParameter idNew = new SqlParameter("@IdNew", System.Data.SqlDbType.NVarChar, 50); SqlParameter idNew = new SqlParameter("@IdNew", System.Data.SqlDbType.NVarChar, 50);
idNew.Value = string.Format("{0}\\{1}", netBiosName, user.UserId); idNew.Value = $@"{netBiosName}\{user.UserId}";
Database.Database.ExecuteSqlCommand(MigratePreDomainUsers_Sql, idExisting, idNew); Database.Database.ExecuteSqlCommand(MigratePreDomainUsers_Sql, idExisting, idNew);
} }
@@ -71,7 +71,7 @@ namespace Disco.Data.Repository
var connectionString = DiscoDataContextConnectionString; var connectionString = DiscoDataContextConnectionString;
if (connectionString == null) if (connectionString == null)
{ {
throw new InvalidOperationException("The Disco DataContext Connection String has not been configured"); throw new InvalidOperationException("The Disco ICT DataContext Connection String has not been configured");
} }
// Build DiscoDataContext - Use Default Connection Factory (SQLClient) // Build DiscoDataContext - Use Default Connection Factory (SQLClient)
+2 -2
View File
@@ -12,6 +12,6 @@
</defaultConnectionFactory> </defaultConnectionFactory>
</entityFramework> </entityFramework>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
</startup> </startup>
</configuration> </configuration>
+19 -4
View File
@@ -10,7 +10,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Disco.Models</RootNamespace> <RootNamespace>Disco.Models</RootNamespace>
<AssemblyName>Disco.Models</AssemblyName> <AssemblyName>Disco.Models</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<TargetFrameworkProfile /> <TargetFrameworkProfile />
</PropertyGroup> </PropertyGroup>
@@ -49,6 +49,14 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="BI\Config\OrganisationAddress.cs" /> <Compile Include="BI\Config\OrganisationAddress.cs" />
<Compile Include="Exporting\ExportFieldMetadata.cs" />
<Compile Include="Exporting\ExportFormat.cs" />
<Compile Include="Exporting\IExportRecord.cs" />
<Compile Include="Repository\Device\Flag\DeviceFlag.cs" />
<Compile Include="Repository\Device\Flag\DeviceFlagAssignment.cs" />
<Compile Include="Services\Devices\DeviceFlags\DeviceFlagExportOptions.cs" />
<Compile Include="Services\Devices\DeviceFlags\DeviceFlagExportRecord.cs" />
<Compile Include="Services\Expressions\Extensions\ImageExpressionFormat.cs" />
<Compile Include="ClientServices\EnrolmentInformation\BaseBoard.cs" /> <Compile Include="ClientServices\EnrolmentInformation\BaseBoard.cs" />
<Compile Include="ClientServices\EnrolmentInformation\Battery.cs" /> <Compile Include="ClientServices\EnrolmentInformation\Battery.cs" />
<Compile Include="ClientServices\EnrolmentInformation\Bios.cs" /> <Compile Include="ClientServices\EnrolmentInformation\Bios.cs" />
@@ -65,13 +73,13 @@
<Compile Include="ClientServices\EnrolmentInformation\WirelessProfileStore.cs" /> <Compile Include="ClientServices\EnrolmentInformation\WirelessProfileStore.cs" />
<Compile Include="ClientServices\EnrolmentInformation\WirelessProfileTransformation.cs" /> <Compile Include="ClientServices\EnrolmentInformation\WirelessProfileTransformation.cs" />
<Compile Include="Repository\Device\DeviceBatchAttachment.cs" /> <Compile Include="Repository\Device\DeviceBatchAttachment.cs" />
<Compile Include="Services\Devices\Exporting\DeviceExportFieldMetadata.cs" />
<Compile Include="Services\Devices\Importing\IDeviceImportColumn.cs" /> <Compile Include="Services\Devices\Importing\IDeviceImportColumn.cs" />
<Compile Include="Services\Devices\Importing\IDeviceImportDataReader.cs" /> <Compile Include="Services\Devices\Importing\IDeviceImportDataReader.cs" />
<Compile Include="Services\Documents\DocumentField.cs" /> <Compile Include="Services\Documents\DocumentField.cs" />
<Compile Include="Services\Documents\DocumentFieldType.cs" /> <Compile Include="Services\Documents\DocumentFieldType.cs" />
<Compile Include="Services\Documents\DocumentTemplatePackage.cs" /> <Compile Include="Services\Documents\DocumentTemplatePackage.cs" />
<Compile Include="Services\Documents\OnImportUserFlagRule.cs" /> <Compile Include="Services\Documents\OnImportUserFlagRule.cs" />
<Compile Include="Exporting\IExportOptions.cs" />
<Compile Include="Services\Jobs\LocationModes.cs" /> <Compile Include="Services\Jobs\LocationModes.cs" />
<Compile Include="ClientServices\EnrolmentInformation\Certificate.cs" /> <Compile Include="ClientServices\EnrolmentInformation\Certificate.cs" />
<Compile Include="ClientServices\Register.cs" /> <Compile Include="ClientServices\Register.cs" />
@@ -86,7 +94,7 @@
<Compile Include="Services\Authorization\IClaimNavigatorItem.cs" /> <Compile Include="Services\Authorization\IClaimNavigatorItem.cs" />
<Compile Include="Services\Authorization\IRoleToken.cs" /> <Compile Include="Services\Authorization\IRoleToken.cs" />
<Compile Include="Services\Documents\DocumentState.cs" /> <Compile Include="Services\Documents\DocumentState.cs" />
<Compile Include="BI\Expressions\IImageExpressionResult.cs" /> <Compile Include="Services\Expressions\Extensions\IImageExpressionResult.cs" />
<Compile Include="Services\Jobs\Statistics\DailyOpenedClosedItem.cs" /> <Compile Include="Services\Jobs\Statistics\DailyOpenedClosedItem.cs" />
<Compile Include="ClientServices\EnrolResponse.cs" /> <Compile Include="ClientServices\EnrolResponse.cs" />
<Compile Include="ClientServices\MacEnrol.cs" /> <Compile Include="ClientServices\MacEnrol.cs" />
@@ -125,7 +133,7 @@
<Compile Include="Repository\User\UserDetail.cs" /> <Compile Include="Repository\User\UserDetail.cs" />
<Compile Include="Repository\User\AuthorizationRole.cs" /> <Compile Include="Repository\User\AuthorizationRole.cs" />
<Compile Include="Services\Devices\Exporting\DeviceExportRecord.cs" /> <Compile Include="Services\Devices\Exporting\DeviceExportRecord.cs" />
<Compile Include="Services\Devices\Exporting\DeviceExportResult.cs" /> <Compile Include="Exporting\ExportResult.cs" />
<Compile Include="Services\Devices\Exporting\DeviceExportTypes.cs" /> <Compile Include="Services\Devices\Exporting\DeviceExportTypes.cs" />
<Compile Include="Services\Devices\Exporting\DeviceExportOptions.cs" /> <Compile Include="Services\Devices\Exporting\DeviceExportOptions.cs" />
<Compile Include="Services\Devices\Importing\DeviceImportFieldTypes.cs" /> <Compile Include="Services\Devices\Importing\DeviceImportFieldTypes.cs" />
@@ -154,6 +162,8 @@
<Compile Include="Services\Searching\ISearchResultItem.cs" /> <Compile Include="Services\Searching\ISearchResultItem.cs" />
<Compile Include="Services\Searching\JobSearchResultItem.cs" /> <Compile Include="Services\Searching\JobSearchResultItem.cs" />
<Compile Include="Services\Searching\UserSearchResultItem.cs" /> <Compile Include="Services\Searching\UserSearchResultItem.cs" />
<Compile Include="Services\Users\UserFlags\UserFlagExportOptions.cs" />
<Compile Include="Services\Users\UserFlags\UserFlagExportRecord.cs" />
<Compile Include="UI\BaseUIModel.cs" /> <Compile Include="UI\BaseUIModel.cs" />
<Compile Include="UI\Config\AuthorizationRole\ConfigAuthorizationRoleCreateModel.cs" /> <Compile Include="UI\Config\AuthorizationRole\ConfigAuthorizationRoleCreateModel.cs" />
<Compile Include="UI\Config\AuthorizationRole\ConfigAuthorizationRoleIndexModel.cs" /> <Compile Include="UI\Config\AuthorizationRole\ConfigAuthorizationRoleIndexModel.cs" />
@@ -192,9 +202,14 @@
<Compile Include="UI\Config\Shared\ConfigSharedDeviceGroupDocumentTemplateBulkGenerate.cs" /> <Compile Include="UI\Config\Shared\ConfigSharedDeviceGroupDocumentTemplateBulkGenerate.cs" />
<Compile Include="UI\Config\Shared\ConfigSharedTaskStatusModel.cs" /> <Compile Include="UI\Config\Shared\ConfigSharedTaskStatusModel.cs" />
<Compile Include="UI\Config\Organisation\ConfigOrganisationIndexModel.cs" /> <Compile Include="UI\Config\Organisation\ConfigOrganisationIndexModel.cs" />
<Compile Include="UI\Config\DeviceFlag\ConfigDeviceFlagCreateModel.cs" />
<Compile Include="UI\Config\DeviceFlag\ConfigDeviceFlagExportModel.cs" />
<Compile Include="UI\Config\DeviceFlag\ConfigDeviceFlagIndexModel.cs" />
<Compile Include="UI\Config\DeviceFlag\ConfigDeviceFlagShowModel.cs" />
<Compile Include="UI\Config\UserFlag\ConfigUserFlagCreateModel.cs" /> <Compile Include="UI\Config\UserFlag\ConfigUserFlagCreateModel.cs" />
<Compile Include="UI\Config\UserFlag\ConfigUserFlagIndexModel.cs" /> <Compile Include="UI\Config\UserFlag\ConfigUserFlagIndexModel.cs" />
<Compile Include="UI\Config\UserFlag\ConfigUserFlagShowModel.cs" /> <Compile Include="UI\Config\UserFlag\ConfigUserFlagShowModel.cs" />
<Compile Include="UI\Config\UserFlag\ConfigUserFlagExportModel.cs" />
<Compile Include="UI\Device\DeviceAddOfflineModel.cs" /> <Compile Include="UI\Device\DeviceAddOfflineModel.cs" />
<Compile Include="UI\Device\DeviceExportModel.cs" /> <Compile Include="UI\Device\DeviceExportModel.cs" />
<Compile Include="UI\Device\DeviceImportHeadersModel.cs" /> <Compile Include="UI\Device\DeviceImportHeadersModel.cs" />
@@ -1,16 +1,16 @@
using System; using System;
namespace Disco.Models.Services.Devices.Exporting namespace Disco.Models.Exporting
{ {
public class DeviceExportFieldMetadata public class ExportFieldMetadata<T> where T : IExportRecord
{ {
public string Name { get; set; } public string Name { get; set; }
public string ColumnName { get; set; } public string ColumnName { get; set; }
public Type ValueType { get; set; } public Type ValueType { get; set; }
public Func<DeviceExportRecord, object> Accessor { get; set; } public Func<T, object> Accessor { get; set; }
public Func<object, string> CsvEncoder { get; set; } public Func<object, string> CsvEncoder { get; set; }
public DeviceExportFieldMetadata(string name, Type valueType, Func<DeviceExportRecord, object> accessor, Func<object, string> csvEncoder) public ExportFieldMetadata(string name, Type valueType, Func<T, object> accessor, Func<object, string> csvEncoder)
{ {
Name = name; Name = name;
ValueType = valueType; ValueType = valueType;
@@ -18,7 +18,7 @@ namespace Disco.Models.Services.Devices.Exporting
CsvEncoder = csvEncoder; CsvEncoder = csvEncoder;
} }
public DeviceExportFieldMetadata(string name, string columnName, Type valueType, Func<DeviceExportRecord, object> accessor, Func<object, string> csvEncoder) public ExportFieldMetadata(string name, string columnName, Type valueType, Func<T, object> accessor, Func<object, string> csvEncoder)
: this(name, valueType, accessor, csvEncoder) : this(name, valueType, accessor, csvEncoder)
{ {
ColumnName = columnName; ColumnName = columnName;
+8
View File
@@ -0,0 +1,8 @@
namespace Disco.Models.Exporting
{
public enum ExportFormat
{
Csv,
Xlsx,
}
}
+12
View File
@@ -0,0 +1,12 @@
using System.IO;
namespace Disco.Models.Services.Exporting
{
public class ExportResult
{
public MemoryStream Result { get; set; }
public string Filename { get; set; }
public string MimeType { get; set; }
public int RecordCount { get; set; }
}
}
+12
View File
@@ -0,0 +1,12 @@
using Disco.Models.Exporting;
namespace Disco.Models.Services.Exporting
{
public interface IExportOptions
{
ExportFormat Format { get; }
string FilenamePrefix { get; }
string ExcelWorksheetName { get; }
string ExcelTableName { get; }
}
}
+6
View File
@@ -0,0 +1,6 @@
namespace Disco.Models.Exporting
{
public interface IExportRecord
{
}
}
+3 -3
View File
@@ -1,4 +1,4 @@
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.2.16326.0500")] [assembly: AssemblyVersion("2.3.23161.0650")]
[assembly: AssemblyFileVersion("2.2.16326.0500")] [assembly: AssemblyFileVersion("2.3.23161.0650")]
+1
View File
@@ -51,6 +51,7 @@ namespace Disco.Models.Repository
[InverseProperty("DeviceSerialNumber")] [InverseProperty("DeviceSerialNumber")]
public virtual IList<Job> Jobs { get; set; } public virtual IList<Job> Jobs { get; set; }
public virtual IList<DeviceFlagAssignment> DeviceFlagAssignments { get; set; }
public override string ToString() public override string ToString()
{ {
@@ -0,0 +1,37 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Disco.Models.Repository
{
public class DeviceFlag
{
[Key]
public int Id { get; set; }
[Required, StringLength(100)]
public string Name { get; set; }
[StringLength(500), DataType(DataType.MultilineText)]
public string Description { get; set; }
[Required, StringLength(25)]
public string Icon { get; set; }
[Required, StringLength(10)]
public string IconColour { get; set; }
public string DevicesLinkedGroup { get; set; }
public string DeviceUsersLinkedGroup { get; set; }
[DataType(DataType.MultilineText)]
public string OnAssignmentExpression { get; set; }
[DataType(DataType.MultilineText)]
public string OnUnassignmentExpression { get; set; }
public virtual IList<DeviceFlagAssignment> DeviceFlagAssignments { get; set; }
public override string ToString()
{
return Name;
}
}
}
@@ -0,0 +1,44 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Disco.Models.Repository
{
public class DeviceFlagAssignment
{
[Key]
public int Id { get; set; }
[Required]
public int DeviceFlagId { get; set; }
[Required]
public string DeviceSerialNumber { get; set; }
[Required]
public DateTime AddedDate { get; set; }
[Required]
public string AddedUserId { get; set; }
public DateTime? RemovedDate { get; set; }
public string RemovedUserId { get; set; }
public string Comments { get; set; }
public string OnAssignmentExpressionResult { get; set; }
public string OnUnassignmentExpressionResult { get; set; }
[ForeignKey(nameof(DeviceFlagId)), InverseProperty("DeviceFlagAssignments")]
public virtual DeviceFlag DeviceFlag { get; set; }
[ForeignKey(nameof(DeviceSerialNumber)), InverseProperty("DeviceFlagAssignments")]
public virtual Device Device { get; set; }
[ForeignKey("AddedUserId")]
public virtual User AddedUser { get; set; }
[ForeignKey("RemovedUserId")]
public virtual User RemovedUser { get; set; }
public override string ToString()
{
return $"Device Flag Id: {DeviceFlagId}; Device Serial Number: {DeviceSerialNumber}; Added: {AddedDate:s}";
}
}
}
@@ -0,0 +1,192 @@
using Disco.Models.Exporting;
using Disco.Models.Services.Exporting;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Disco.Models.Services.Devices.DeviceFlag
{
public class DeviceFlagExportOptions : IExportOptions
{
public ExportFormat Format { get; set; }
public string FilenamePrefix { get; } = "DiscoDeviceFlagExport";
public string ExcelWorksheetName { get; } = "DeviceFlagExport";
public string ExcelTableName { get; } = "DeviceFlags";
[Required]
public List<int> DeviceFlagIds { get; set; } = new List<int>();
[Display(Name = "Current Only")]
public bool CurrentOnly { get; set; }
// Device Flag
[Display(ShortName = "Device Flag", Name = "Identifier", Description = "The identifier of the device flag")]
public bool Id { get; set; }
[Display(ShortName = "Device Flag", Name = "Name", Description = "The name of the device flag")]
public bool Name { get; set; }
[Display(ShortName = "Device Flag", Name = "Description", Description = "The description of the device flag")]
public bool Description { get; set; }
[Display(ShortName = "Device Flag", Name = "Icon", Description = "The icon assigned to the device flag")]
public bool Icon { get; set; }
[Display(ShortName = "Device Flag", Name = "Icon Colour", Description = "The icon colour assigned to the device flag")]
public bool IconColour { get; set; }
[Display(ShortName = "Device Flag", Name = "Assignment Identifier", Description = "The identifier of the device flag assignment")]
public bool AssignmentId { get; set; }
[Display(ShortName = "Device Flag", Name = "Added Date", Description = "The date the device flag was assigned to the user")]
public bool AddedDate { get; set; }
[Display(ShortName = "Device Flag", Name = "Added User Identifier", Description = "The identifier of the user who assigned the device flag")]
public bool AddedUserId { get; set; }
[Display(ShortName = "Device Flag", Name = "Removed Date", Description = "The date the device flag was unassigned from the user")]
public bool RemovedDate { get; set; }
[Display(ShortName = "Device Flag", Name = "Removed User Identifier", Description = "The identifier of the user who unassigned the device flag")]
public bool RemovedUserId { get; set; }
[Display(ShortName = "Device Flag", Name = "Comments", Description = "The comments associated with the device flag assignment")]
public bool Comments { get; set; }
// Device
[Display(ShortName = "Device", Name = "Serial Number", Description = "The device serial number")]
public bool DeviceSerialNumber { get; set; }
[Display(ShortName = "Device", Name = "Asset Number", Description = "The device asset number")]
public bool DeviceAssetNumber { get; set; }
[Display(ShortName = "Device", Name = "Location", Description = "The device location")]
public bool DeviceLocation { get; set; }
[Display(ShortName = "Device", Name = "Computer Name", Description = "The device computer name")]
public bool DeviceComputerName { get; set; }
[Display(ShortName = "Device", Name = "Last Network Logon", Description = "The last recorded time the device access the network")]
public bool DeviceLastNetworkLogon { get; set; }
[Display(ShortName = "Device", Name = "Created Date", Description = "The date the device was created in Disco ICT")]
public bool DeviceCreatedDate { get; set; }
[Display(ShortName = "Device", Name = "First Enrolled Date", Description = "The date the device was first enrolled in Disco ICT")]
public bool DeviceFirstEnrolledDate { get; set; }
[Display(ShortName = "Device", Name = "Last Enrolled Date", Description = "The date the device was last enrolled in Disco ICT")]
public bool DeviceLastEnrolledDate { get; set; }
[Display(ShortName = "Device", Name = "Enrolment Trusted", Description = "The device is trusted to complete an unauthenticated enrolment")]
public bool DeviceAllowUnauthenticatedEnrol { get; set; }
[Display(ShortName = "Device", Name = "Decommissioned Date", Description = "The date the device was decommissioned in Disco ICT")]
public bool DeviceDecommissionedDate { get; set; }
[Display(ShortName = "Device", Name = "Decommissioned Reason", Description = "The reason the device was decommissioned")]
public bool DeviceDecommissionedReason { get; set; }
public bool HasDeviceOptions()
{
return DeviceSerialNumber ||
DeviceAssetNumber ||
DeviceLocation ||
DeviceComputerName ||
DeviceLastNetworkLogon ||
DeviceCreatedDate ||
DeviceFirstEnrolledDate ||
DeviceLastEnrolledDate ||
DeviceAllowUnauthenticatedEnrol ||
DeviceDecommissionedDate ||
DeviceDecommissionedReason;
}
// Model
[Display(ShortName = "Model", Name = "Identifier", Description = "The identifier of the device model associated with the device")]
public bool ModelId { get; set; }
[Display(ShortName = "Model", Name = "Description", Description = "The description of the device model associated with the device")]
public bool ModelDescription { get; set; }
[Display(ShortName = "Model", Name = "Manufacturer", Description = "The manufacturer of the device model associated with the device")]
public bool ModelManufacturer { get; set; }
[Display(ShortName = "Model", Name = "Model", Description = "The model of the device model associated with the device")]
public bool ModelModel { get; set; }
[Display(ShortName = "Model", Name = "Type", Description = "The type of device model associated with the device")]
public bool ModelType { get; set; }
public bool HasDeviceModelOptions()
{
return ModelId ||
ModelDescription ||
ModelManufacturer ||
ModelModel ||
ModelType;
}
// Batch
[Display(ShortName = "Batch", Name = "Identifier", Description = "The identifier of the device batch associated with the device")]
public bool BatchId { get; set; }
[Display(ShortName = "Batch", Name = "Name", Description = "The name of the device batch associated with the device")]
public bool BatchName { get; set; }
[Display(ShortName = "Batch", Name = "Purchase Date", Description = "The purchase date of the device batch associated with the device")]
public bool BatchPurchaseDate { get; set; }
[Display(ShortName = "Batch", Name = "Supplier", Description = "The supplier of the device batch associated with the device")]
public bool BatchSupplier { get; set; }
[Display(ShortName = "Batch", Name = "Unit Cost", Description = "The unit cost of the device batch associated with the device")]
public bool BatchUnitCost { get; set; }
[Display(ShortName = "Batch", Name = "Warranty Valid Until Date", Description = "The warranty valid until date of the device batch associated with the device")]
public bool BatchWarrantyValidUntilDate { get; set; }
[Display(ShortName = "Batch", Name = "Insured Date", Description = "The insured date of the device batch associated with the device")]
public bool BatchInsuredDate { get; set; }
[Display(ShortName = "Batch", Name = "Insurance Supplier", Description = "The insurance supplier of the device batch associated with the device")]
public bool BatchInsuranceSupplier { get; set; }
[Display(ShortName = "Batch", Name = "Insured Until Date", Description = "The insured until date of the device batch associated with the device")]
public bool BatchInsuredUntilDate { get; set; }
public bool HasDeviceBatchOptions()
{
return BatchId ||
BatchName ||
BatchPurchaseDate ||
BatchSupplier ||
BatchUnitCost ||
BatchWarrantyValidUntilDate ||
BatchInsuredDate ||
BatchInsuranceSupplier ||
BatchInsuredUntilDate;
}
// Profile
[Display(ShortName = "Profile", Name = "Identifier", Description = "The identifier of the device profile associated with the device")]
public bool ProfileId { get; set; }
[Display(ShortName = "Profile", Name = "Name", Description = "The name of the device profile associated with the device")]
public bool ProfileName { get; set; }
[Display(ShortName = "Profile", Name = "Short Name", Description = "The short name of the device profile associated with the device")]
public bool ProfileShortName { get; set; }
public bool HasDeviceProfileOptions()
{
return ProfileId ||
ProfileName ||
ProfileShortName;
}
// Assigned User
[Display(ShortName = "Assigned User", Name = "Identifier", Description = "The identifier of the user assigned to the device flag")]
public bool AssignedUserId { get; set; }
[Display(ShortName = "Assigned User", Name = "Display Name", Description = "The display name of the user assigned to the device flag")]
public bool AssignedUserDisplayName { get; set; }
[Display(ShortName = "Assigned User", Name = "Surname", Description = "The surname of the user assigned to the device flag")]
public bool AssignedUserSurname { get; set; }
[Display(ShortName = "Assigned User", Name = "Given Name", Description = "The given name of the user assigned to the device flag")]
public bool AssignedUserGivenName { get; set; }
[Display(ShortName = "Assigned User", Name = "Phone Number", Description = "The phone number of the user assigned to the device flag")]
public bool AssignedUserPhoneNumber { get; set; }
[Display(ShortName = "Assigned User", Name = "Email Address", Description = "The email address of the user assigned to the device flag")]
public bool AssignedUserEmailAddress { get; set; }
[Display(ShortName = "Assigned User", Name = "Custom Details", Description = "The custom details provided by plugins for the user assigned to the device flag")]
public bool AssignedUserDetailCustom { get; set; }
public bool HasAssignedUserOptions()
{
return AssignedUserId ||
AssignedUserDisplayName ||
AssignedUserSurname ||
AssignedUserGivenName ||
AssignedUserPhoneNumber ||
AssignedUserEmailAddress;
}
public static DeviceFlagExportOptions DefaultOptions()
{
return new DeviceFlagExportOptions()
{
Format = ExportFormat.Xlsx,
CurrentOnly = true,
Name = true,
AddedDate = true,
DeviceSerialNumber = true,
ModelDescription = true,
ProfileName = true,
AssignedUserId = true,
AssignedUserDisplayName = true,
Comments = true,
};
}
}
}
@@ -0,0 +1,12 @@
using Disco.Models.Exporting;
using Disco.Models.Repository;
using System.Collections.Generic;
namespace Disco.Models.Services.Devices.DeviceFlag
{
public class DeviceFlagExportRecord : IExportRecord
{
public DeviceFlagAssignment Assignment { get; set; }
public Dictionary<string, string> AssignedUserCustomDetails { get; set; }
}
}
@@ -1,13 +1,18 @@
using System.ComponentModel.DataAnnotations; using Disco.Models.Exporting;
using Disco.Models.Services.Exporting;
using System.ComponentModel.DataAnnotations;
namespace Disco.Models.Services.Devices.Exporting namespace Disco.Models.Services.Devices.Exporting
{ {
public class DeviceExportOptions public class DeviceExportOptions : IExportOptions
{ {
public DeviceExportTypes ExportType { get; set; } public DeviceExportTypes ExportType { get; set; }
public int? ExportTypeTargetId { get; set; } public int? ExportTypeTargetId { get; set; }
public bool ExcelFormat { get; set; } public ExportFormat Format { get; set; }
public string FilenamePrefix { get; } = "DiscoDeviceExport";
public string ExcelWorksheetName { get; } = "DeviceExport";
public string ExcelTableName { get; } = "Devices";
// Device // Device
[Display(ShortName = "Device", Name = "Serial Number", Description = "The device serial number")] [Display(ShortName = "Device", Name = "Serial Number", Description = "The device serial number")]
@@ -20,15 +25,15 @@ namespace Disco.Models.Services.Devices.Exporting
public bool DeviceComputerName { get; set; } public bool DeviceComputerName { get; set; }
[Display(ShortName = "Device", Name = "Last Network Logon", Description = "The last recorded time the device access the network")] [Display(ShortName = "Device", Name = "Last Network Logon", Description = "The last recorded time the device access the network")]
public bool DeviceLastNetworkLogon { get; set; } public bool DeviceLastNetworkLogon { get; set; }
[Display(ShortName = "Device", Name = "Created Date", Description = "The date the device was created in Disco")] [Display(ShortName = "Device", Name = "Created Date", Description = "The date the device was created in Disco ICT")]
public bool DeviceCreatedDate { get; set; } public bool DeviceCreatedDate { get; set; }
[Display(ShortName = "Device", Name = "First Enrolled Date", Description = "The date the device was first enrolled in Disco")] [Display(ShortName = "Device", Name = "First Enrolled Date", Description = "The date the device was first enrolled in Disco ICT")]
public bool DeviceFirstEnrolledDate { get; set; } public bool DeviceFirstEnrolledDate { get; set; }
[Display(ShortName = "Device", Name = "Last Enrolled Date", Description = "The date the device was last enrolled in Disco")] [Display(ShortName = "Device", Name = "Last Enrolled Date", Description = "The date the device was last enrolled in Disco ICT")]
public bool DeviceLastEnrolledDate { get; set; } public bool DeviceLastEnrolledDate { get; set; }
[Display(ShortName = "Device", Name = "Enrolment Trusted", Description = "The device is trusted to complete an unauthenticated enrolment")] [Display(ShortName = "Device", Name = "Enrolment Trusted", Description = "The device is trusted to complete an unauthenticated enrolment")]
public bool DeviceAllowUnauthenticatedEnrol { get; set; } public bool DeviceAllowUnauthenticatedEnrol { get; set; }
[Display(ShortName = "Device", Name = "Decommissioned Date", Description = "The date the device was decommissioned in Disco")] [Display(ShortName = "Device", Name = "Decommissioned Date", Description = "The date the device was decommissioned in Disco ICT")]
public bool DeviceDecommissionedDate { get; set; } public bool DeviceDecommissionedDate { get; set; }
[Display(ShortName = "Device", Name = "Decommissioned Reason", Description = "The reason the device was decommissioned")] [Display(ShortName = "Device", Name = "Decommissioned Reason", Description = "The reason the device was decommissioned")]
public bool DeviceDecommissionedReason { get; set; } public bool DeviceDecommissionedReason { get; set; }
@@ -136,7 +141,7 @@ namespace Disco.Models.Services.Devices.Exporting
return new DeviceExportOptions() return new DeviceExportOptions()
{ {
ExportType = DeviceExportTypes.All, ExportType = DeviceExportTypes.All,
ExcelFormat = true, Format = ExportFormat.Xlsx,
DeviceSerialNumber = true, DeviceSerialNumber = true,
ModelId = true, ModelId = true,
ProfileId = true, ProfileId = true,
@@ -1,11 +1,12 @@
using Disco.Models.ClientServices.EnrolmentInformation; using Disco.Models.ClientServices.EnrolmentInformation;
using Disco.Models.Exporting;
using Disco.Models.Repository; using Disco.Models.Repository;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Disco.Models.Services.Devices.Exporting namespace Disco.Models.Services.Devices.Exporting
{ {
public class DeviceExportRecord public class DeviceExportRecord : IExportRecord
{ {
public Device Device { get; set; } public Device Device { get; set; }
@@ -1,10 +0,0 @@
using System.IO;
namespace Disco.Models.Services.Devices.Exporting
{
public class DeviceExportResult
{
public MemoryStream Result { get; set; }
public int RecordCount { get; set; }
}
}
@@ -1,10 +1,4 @@
using System; namespace Disco.Models.Services.Devices.Exporting
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Models.Services.Devices.Exporting
{ {
public enum DeviceExportTypes public enum DeviceExportTypes
{ {
@@ -14,7 +14,7 @@ namespace Disco.Models.Services.Devices.Importing
DeviceLocation, DeviceLocation,
[Display(Name = "Device Enrolment Trusted", Description = "The device is trusted to complete an unauthenticated enrolment")] [Display(Name = "Device Enrolment Trusted", Description = "The device is trusted to complete an unauthenticated enrolment")]
DeviceAllowUnauthenticatedEnrol, DeviceAllowUnauthenticatedEnrol,
[Display(Name = "Device Decommissioned Date", Description = "The date the device was decommissioned in Disco")] [Display(Name = "Device Decommissioned Date", Description = "The date the device was decommissioned in Disco ICT")]
DeviceDecommissionedDate, DeviceDecommissionedDate,
[Display(Name = "Device Decommissioned Reason", Description = "The reason the device was decommissioned")] [Display(Name = "Device Decommissioned Reason", Description = "The reason the device was decommissioned")]
DeviceDecommissionedReason, DeviceDecommissionedReason,
@@ -1,13 +1,13 @@
using System.IO; using System.IO;
namespace Disco.Models.BI.Expressions namespace Disco.Models.Services.Expressions.Extensions
{ {
public interface IImageExpressionResult public interface IImageExpressionResult
{ {
Stream GetImage(int Width, int Height); MemoryStream GetImage(int width, int height);
Stream GetImage(); MemoryStream GetImage(out int width, out int height);
byte Quality { get; set; } byte Quality { get; set; }
bool LosslessFormat { get; set; } ImageExpressionFormat Format { get; set; }
bool ShowField { get; set; } bool ShowField { get; set; }
string BackgroundColour { get; set; } string BackgroundColour { get; set; }
bool BackgroundPreferTransparent { get; set; } bool BackgroundPreferTransparent { get; set; }
@@ -0,0 +1,9 @@
namespace Disco.Models.Services.Expressions.Extensions
{
public enum ImageExpressionFormat
{
Jpeg,
Png,
CcittG4,
}
}
@@ -1,4 +1,5 @@
using System; using Disco.Models.Repository;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@@ -44,6 +45,7 @@ namespace Disco.Models.Services.Searching
public string DeviceBatchName { get; set; } public string DeviceBatchName { get; set; }
public int JobCount { get; set; } public int JobCount { get; set; }
public DateTime? DecommissionedDate { get; set; } public DateTime? DecommissionedDate { get; set; }
public IList<DeviceFlagAssignment> DeviceFlagAssignments { get; set; }
private string[] BuildScoreValues() private string[] BuildScoreValues()
{ {
@@ -0,0 +1,76 @@
using Disco.Models.Exporting;
using Disco.Models.Services.Exporting;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Disco.Models.Services.Users.UserFlags
{
public class UserFlagExportOptions : IExportOptions
{
public ExportFormat Format { get; set; }
public string FilenamePrefix { get; } = "DiscoUserFlagExport";
public string ExcelWorksheetName { get; } = "UserFlagExport";
public string ExcelTableName { get; } = "UserFlags";
[Required]
public List<int> UserFlagIds { get; set; } = new List<int>();
[Display(Name = "Current Only")]
public bool CurrentOnly { get; set; }
// User Flag
[Display(ShortName = "User Flag", Name = "Identifier", Description = "The identifier of the user flag")]
public bool Id { get; set; }
[Display(ShortName = "User Flag", Name = "Name", Description = "The name of the user flag")]
public bool Name { get; set; }
[Display(ShortName = "User Flag", Name = "Description", Description = "The description of the user flag")]
public bool Description { get; set; }
[Display(ShortName = "User Flag", Name = "Icon", Description = "The icon assigned to the user flag")]
public bool Icon { get; set; }
[Display(ShortName = "User Flag", Name = "Icon Colour", Description = "The icon colour assigned to the user flag")]
public bool IconColour { get; set; }
[Display(ShortName = "User Flag", Name = "Assignment Identifier", Description = "The identifier of the user flag assignment")]
public bool AssignmentId { get; set; }
[Display(ShortName = "User Flag", Name = "Added Date", Description = "The date the user flag was assigned to the user")]
public bool AddedDate { get; set; }
[Display(ShortName = "User Flag", Name = "Added User Identifier", Description = "The identifier of the user who assigned the user flag")]
public bool AddedUserId { get; set; }
[Display(ShortName = "User Flag", Name = "Removed Date", Description = "The date the user flag was unassigned from the user")]
public bool RemovedDate { get; set; }
[Display(ShortName = "User Flag", Name = "Removed User Identifier", Description = "The identifier of the user who unassigned the user flag")]
public bool RemovedUserId { get; set; }
[Display(ShortName = "User Flag", Name = "Comments", Description = "The comments associated with the user flag assignment")]
public bool Comments { get; set; }
// User
[Display(ShortName = "User", Name = "Identifier", Description = "The identifier of the user assigned to the user flag")]
public bool UserId { get; set; }
[Display(ShortName = "User", Name = "Display Name", Description = "The display name of the user assigned to the user flag")]
public bool UserDisplayName { get; set; }
[Display(ShortName = "User", Name = "Surname", Description = "The surname of the user assigned to the user flag")]
public bool UserSurname { get; set; }
[Display(ShortName = "User", Name = "Given Name", Description = "The given name of the user assigned to the user flag")]
public bool UserGivenName { get; set; }
[Display(ShortName = "User", Name = "Phone Number", Description = "The phone number of the user assigned to the user flag")]
public bool UserPhoneNumber { get; set; }
[Display(ShortName = "User", Name = "Email Address", Description = "The email address of the user assigned to the user flag")]
public bool UserEmailAddress { get; set; }
[Display(ShortName = "User", Name = "Custom Details", Description = "The custom details provided by plugins for the user assigned to the user flag")]
public bool UserDetailCustom { get; set; }
public static UserFlagExportOptions DefaultOptions()
{
return new UserFlagExportOptions()
{
Format = ExportFormat.Xlsx,
CurrentOnly = true,
Name = true,
AddedDate = true,
UserId = true,
UserDisplayName = true,
Comments = true,
};
}
}
}
@@ -0,0 +1,12 @@
using Disco.Models.Exporting;
using Disco.Models.Repository;
using System.Collections.Generic;
namespace Disco.Models.Services.Users.UserFlags
{
public class UserFlagExportRecord : IExportRecord
{
public UserFlagAssignment Assignment { get; set; }
public Dictionary<string, string> UserCustomDetails { get; set; }
}
}
@@ -0,0 +1,7 @@
namespace Disco.Models.UI.Config.DeviceFlag
{
public interface ConfigDeviceFlagCreateModel : BaseUIModel
{
Repository.DeviceFlag DeviceFlag { get; set; }
}
}
@@ -0,0 +1,17 @@
using Disco.Models.Services.Devices.DeviceFlag;
using Disco.Models.Services.Exporting;
using Disco.Models.UI;
using System.Collections.Generic;
namespace Disco.Models.Areas.Config.UI.DeviceFlag
{
public interface ConfigDeviceFlagExportModel : BaseUIModel
{
DeviceFlagExportOptions Options { get; set; }
string ExportSessionId { get; set; }
ExportResult ExportSessionResult { get; set; }
List<Repository.DeviceFlag> DeviceFlags { get; set; }
}
}
@@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace Disco.Models.UI.Config.DeviceFlag
{
public interface ConfigDeviceFlagIndexModel : BaseUIModel
{
Dictionary<Repository.DeviceFlag, int> DeviceFlags { get; set; }
}
}
@@ -0,0 +1,15 @@
using System.Collections.Generic;
namespace Disco.Models.UI.Config.DeviceFlag
{
public interface ConfigDeviceFlagShowModel : BaseUIModel
{
Repository.DeviceFlag DeviceFlag { get; set; }
int CurrentAssignmentCount { get; set; }
int TotalAssignmentCount { get; set; }
IEnumerable<KeyValuePair<string, string>> Icons { get; set; }
IEnumerable<KeyValuePair<string, string>> ThemeColours { get; set; }
}
}
@@ -8,9 +8,11 @@ namespace Disco.Models.UI.Config.DeviceProfile
{ {
Repository.DeviceProfile DeviceProfile { get; set; } Repository.DeviceProfile DeviceProfile { get; set; }
OrganisationAddress DefaultOrganisationAddress { get; set; } OrganisationAddress DefaultOrganisationAddress { get; set; }
List<OrganisationAddress> OrganisationAddresses { get; set; } List<OrganisationAddress> OrganisationAddresses { get; set; }
string FriendlyOrganisationalUnitName { get; }
bool OrganisationalUnitExists { get; set; }
int DeviceCount { get; set; } int DeviceCount { get; set; }
int DeviceDecommissionedCount { get; set; } int DeviceDecommissionedCount { get; set; }
@@ -0,0 +1,17 @@
using Disco.Models.Services.Exporting;
using Disco.Models.Services.Users.UserFlags;
using Disco.Models.UI;
using System.Collections.Generic;
namespace Disco.Models.Areas.Config.UI.UserFlag
{
public interface ConfigUserFlagExportModel : BaseUIModel
{
UserFlagExportOptions Options { get; set; }
string ExportSessionId { get; set; }
ExportResult ExportSessionResult { get; set; }
List<Repository.UserFlag> UserFlags { get; set; }
}
}
+2 -1
View File
@@ -1,4 +1,5 @@
using Disco.Models.Services.Devices.Exporting; using Disco.Models.Services.Devices.Exporting;
using Disco.Models.Services.Exporting;
using System.Collections.Generic; using System.Collections.Generic;
namespace Disco.Models.UI.Device namespace Disco.Models.UI.Device
@@ -8,7 +9,7 @@ namespace Disco.Models.UI.Device
DeviceExportOptions Options { get; set; } DeviceExportOptions Options { get; set; }
string ExportSessionId { get; set; } string ExportSessionId { get; set; }
DeviceExportResult ExportSessionResult { get; set; } ExportResult ExportSessionResult { get; set; }
IEnumerable<KeyValuePair<int, string>> DeviceBatches { get; set; } IEnumerable<KeyValuePair<int, string>> DeviceBatches { get; set; }
IEnumerable<KeyValuePair<int, string>> DeviceModels { get; set; } IEnumerable<KeyValuePair<int, string>> DeviceModels { get; set; }
@@ -1,4 +1,5 @@
using Disco.Models.BI.Config; using Disco.Models.BI.Config;
using Disco.Models.Repository;
using Disco.Models.Services.Documents; using Disco.Models.Services.Documents;
using Disco.Models.Services.Jobs.JobLists; using Disco.Models.Services.Jobs.JobLists;
using System.Collections.Generic; using System.Collections.Generic;
@@ -10,9 +11,11 @@ namespace Disco.Models.UI.Device
Repository.Device Device { get; set; } Repository.Device Device { get; set; }
List<Repository.DeviceProfile> DeviceProfiles { get; set; } List<Repository.DeviceProfile> DeviceProfiles { get; set; }
HashSet<int> DecommissionedDeviceProfileIds { get; set; }
OrganisationAddress DeviceProfileDefaultOrganisationAddress { get; set; } OrganisationAddress DeviceProfileDefaultOrganisationAddress { get; set; }
List<Repository.DeviceBatch> DeviceBatches { get; set; } List<Repository.DeviceBatch> DeviceBatches { get; set; }
HashSet<int> DecommissionedDeviceBatchIds { get; set; }
JobTableModel Jobs { get; set; } JobTableModel Jobs { get; set; }
@@ -20,6 +23,9 @@ namespace Disco.Models.UI.Device
List<Repository.DocumentTemplate> DocumentTemplates { get; set; } List<Repository.DocumentTemplate> DocumentTemplates { get; set; }
List<DocumentTemplatePackage> DocumentTemplatePackages { get; set; } List<DocumentTemplatePackage> DocumentTemplatePackages { get; set; }
List<DeviceFlag> AvailableDeviceFlags { get; set; }
Dictionary<string, string> AssignedUserDetails { get; set; } Dictionary<string, string> AssignedUserDetails { get; set; }
bool HasAssignedUserPhoto { get; set; } bool HasAssignedUserPhoto { get; set; }
} }
@@ -1,38 +1,38 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<configuration> <configuration>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
</startup> </startup>
<runtime> <runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral" /> <assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" /> <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0" /> <bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0" /> <bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" /> <bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" /> <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" /> <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="Microsoft.AspNet.SignalR.Core" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <assemblyIdentity name="Microsoft.AspNet.SignalR.Core" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.1.1.0" newVersion="2.1.1.0" /> <bindingRedirect oldVersion="0.0.0.0-2.1.1.0" newVersion="2.1.1.0"/>
</dependentAssembly> </dependentAssembly>
</assemblyBinding> </assemblyBinding>
</runtime> </runtime>
</configuration> </configuration>
@@ -9,9 +9,10 @@
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Disco.Services.Plugins.ManifestGenerator</RootNamespace> <RootNamespace>Disco.Services.Plugins.ManifestGenerator</RootNamespace>
<AssemblyName>Disco.Services.Plugins.ManifestGenerator</AssemblyName> <AssemblyName>Disco.Services.Plugins.ManifestGenerator</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
@@ -25,7 +25,7 @@ namespace Disco.Services.Plugins.ManifestGenerator
throw new ArgumentException($"File not found at: {assemblyFileInfo.FullName}"); throw new ArgumentException($"File not found at: {assemblyFileInfo.FullName}");
} }
Console.WriteLine("Disco Plugin: Generating Manifest"); Console.WriteLine("Disco ICT Plugin: Generating Manifest");
AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad; AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad;
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
@@ -55,7 +55,7 @@ namespace Disco.Services.Plugins.ManifestGenerator
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine($"Disco Plugin: Warning: Unable to load reference '{referenceAssembly.FullName}'; {ex.Message}"); Console.WriteLine($"Disco ICT Plugin: Warning: Unable to load reference '{referenceAssembly.FullName}'; {ex.Message}");
} }
} }
} }
@@ -68,9 +68,9 @@ namespace Disco.Services.Plugins.ManifestGenerator
File.WriteAllText(manifestFilePath, manifest.ToManifestFile()); File.WriteAllText(manifestFilePath, manifest.ToManifestFile());
Console.WriteLine("Disco Plugin: Manifest Created"); Console.WriteLine("Disco ICT Plugin: Manifest Created");
Console.WriteLine("Disco Plugin: Building Package"); Console.WriteLine("Disco ICT Plugin: Building Package");
var packageFileName = $"{manifest.Id}-{manifest.Version}.discoPlugin"; var packageFileName = $"{manifest.Id}-{manifest.Version}.discoPlugin";
var packageFilePath = Path.Combine(assemblyFileInfo.DirectoryName, packageFileName); var packageFilePath = Path.Combine(assemblyFileInfo.DirectoryName, packageFileName);
@@ -81,7 +81,7 @@ namespace Disco.Services.Plugins.ManifestGenerator
existingPackages.Delete(); existingPackages.Delete();
} }
// Exclude Disco Provided Assemblies // Exclude Disco ICT Provided Assemblies
List<string> excludedFiles = PluginManifest.PluginExcludedAssemblies.ToList(); List<string> excludedFiles = PluginManifest.PluginExcludedAssemblies.ToList();
// Exclude the Package File // Exclude the Package File
@@ -95,7 +95,7 @@ namespace Disco.Services.Plugins.ManifestGenerator
} }
} }
Console.WriteLine($"Disco Plugin: Package Build: '{packageFileName}'"); Console.WriteLine($"Disco ICT Plugin: Package Build: '{packageFileName}'");
} }
@@ -1,4 +1,4 @@
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.0.16326.0500")] [assembly: AssemblyVersion("2.3.23161.0650")]
[assembly: AssemblyFileVersion("2.0.16326.0500")] [assembly: AssemblyFileVersion("2.3.23161.0650")]
+1 -1
View File
@@ -12,7 +12,7 @@
</defaultConnectionFactory> </defaultConnectionFactory>
</entityFramework> </entityFramework>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup> </startup>
<runtime> <runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
@@ -19,7 +19,7 @@ namespace Disco.Services.Authorization
{ {
if (message == null) if (message == null)
{ {
return "Your account does not have the required permission to access this Disco feature."; return "Your account does not have the required permission to access this Disco ICT feature.";
} }
else else
{ {
@@ -44,7 +44,7 @@ namespace Disco.Services.Authorization
#region Token Accessors #region Token Accessors
internal const string RequireAuthenticationMessage = "This feature requires authentication."; internal const string RequireAuthenticationMessage = "This feature requires authentication.";
internal const string RequireDiscoAuthorizationMessage = "Your account does not have the required permission to access this feature. This feature requires your account to be included in at least one Disco Authorization Role."; internal const string RequireDiscoAuthorizationMessage = "Your account does not have the required permission to access this feature. This feature requires your account to be included in at least one Disco ICT Authorization Role.";
internal const string RequireMessageTemplate = "Your account does not have the required permission to access this feature.\r\n"; internal const string RequireMessageTemplate = "Your account does not have the required permission to access this feature.\r\n";
internal const string RequireMessageSingleTemplate = RequireMessageTemplate + "This feature requires the following permission:\r\n- {0}"; internal const string RequireMessageSingleTemplate = RequireMessageTemplate + "This feature requires the following permission:\r\n- {0}";
internal const string RequireAllMessageTemplate = RequireMessageTemplate + "This feature requires permission for:\r\n- {0}"; internal const string RequireAllMessageTemplate = RequireMessageTemplate + "This feature requires permission for:\r\n- {0}";
+94 -8
View File
@@ -1,7 +1,4 @@
 // <auto-generated />
// <auto-generated />
// This file was generated by a T4 template. // This file was generated by a T4 template.
// Don't change it directly as your change would get overwritten. Instead, make changes // Don't change it directly as your change would get overwritten. Instead, make changes
// to the .tt file (i.e. the T4 template) and save it to regenerate this file. // to the .tt file (i.e. the T4 template) and save it to regenerate this file.
@@ -34,6 +31,11 @@ namespace Disco.Services.Authorization
{ "Config.DeviceBatch.Delete", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceBatch.Delete, (c, v) => c.Config.DeviceBatch.Delete = v, "Delete Device Batches", "Can delete device batches", false) }, { "Config.DeviceBatch.Delete", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceBatch.Delete, (c, v) => c.Config.DeviceBatch.Delete = v, "Delete Device Batches", "Can delete device batches", false) },
{ "Config.DeviceBatch.Show", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceBatch.Show, (c, v) => c.Config.DeviceBatch.Show = v, "Show Device Batches", "Can show device batches", false) }, { "Config.DeviceBatch.Show", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceBatch.Show, (c, v) => c.Config.DeviceBatch.Show = v, "Show Device Batches", "Can show device batches", false) },
{ "Config.DeviceBatch.ShowTimeline", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceBatch.ShowTimeline, (c, v) => c.Config.DeviceBatch.ShowTimeline = v, "Show Timeline", "Can show device batch timeline", false) }, { "Config.DeviceBatch.ShowTimeline", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceBatch.ShowTimeline, (c, v) => c.Config.DeviceBatch.ShowTimeline = v, "Show Timeline", "Can show device batch timeline", false) },
{ "Config.DeviceFlag.Configure", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceFlag.Configure, (c, v) => c.Config.DeviceFlag.Configure = v, "Configure Device Flags", "Can configure device flags", false) },
{ "Config.DeviceFlag.Create", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceFlag.Create, (c, v) => c.Config.DeviceFlag.Create = v, "Create Device Flags", "Can create device flags", false) },
{ "Config.DeviceFlag.Delete", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceFlag.Delete, (c, v) => c.Config.DeviceFlag.Delete = v, "Delete Device Flags", "Can delete device flags", false) },
{ "Config.DeviceFlag.Export", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceFlag.Export, (c, v) => c.Config.DeviceFlag.Export = v, "Export Device Flag Assignments", "Can export user device assignments", false) },
{ "Config.DeviceFlag.Show", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceFlag.Show, (c, v) => c.Config.DeviceFlag.Show = v, "Show Device Flags", "Can show device flags", false) },
{ "Config.DeviceModel.ConfigureComponents", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceModel.ConfigureComponents, (c, v) => c.Config.DeviceModel.ConfigureComponents = v, "Configure Device Model Components", "Can configure device model components", false) }, { "Config.DeviceModel.ConfigureComponents", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceModel.ConfigureComponents, (c, v) => c.Config.DeviceModel.ConfigureComponents = v, "Configure Device Model Components", "Can configure device model components", false) },
{ "Config.DeviceModel.Configure", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceModel.Configure, (c, v) => c.Config.DeviceModel.Configure = v, "Configure Device Models", "Can configure device models", false) }, { "Config.DeviceModel.Configure", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceModel.Configure, (c, v) => c.Config.DeviceModel.Configure = v, "Configure Device Models", "Can configure device models", false) },
{ "Config.DeviceModel.Delete", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceModel.Delete, (c, v) => c.Config.DeviceModel.Delete = v, "Delete Device Models", "Can delete device models", false) }, { "Config.DeviceModel.Delete", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceModel.Delete, (c, v) => c.Config.DeviceModel.Delete = v, "Delete Device Models", "Can delete device models", false) },
@@ -77,6 +79,7 @@ namespace Disco.Services.Authorization
{ "Config.UserFlag.Configure", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.UserFlag.Configure, (c, v) => c.Config.UserFlag.Configure = v, "Configure User Flags", "Can configure user flags", false) }, { "Config.UserFlag.Configure", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.UserFlag.Configure, (c, v) => c.Config.UserFlag.Configure = v, "Configure User Flags", "Can configure user flags", false) },
{ "Config.UserFlag.Create", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.UserFlag.Create, (c, v) => c.Config.UserFlag.Create = v, "Create User Flags", "Can create user flags", false) }, { "Config.UserFlag.Create", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.UserFlag.Create, (c, v) => c.Config.UserFlag.Create = v, "Create User Flags", "Can create user flags", false) },
{ "Config.UserFlag.Delete", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.UserFlag.Delete, (c, v) => c.Config.UserFlag.Delete = v, "Delete User Flags", "Can delete user flags", false) }, { "Config.UserFlag.Delete", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.UserFlag.Delete, (c, v) => c.Config.UserFlag.Delete = v, "Delete User Flags", "Can delete user flags", false) },
{ "Config.UserFlag.Export", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.UserFlag.Export, (c, v) => c.Config.UserFlag.Export = v, "Export User Flag Assignments", "Can export user flag assignments", false) },
{ "Config.UserFlag.Show", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.UserFlag.Show, (c, v) => c.Config.UserFlag.Show = v, "Show User Flags", "Can show user flags", false) }, { "Config.UserFlag.Show", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.UserFlag.Show, (c, v) => c.Config.UserFlag.Show = v, "Show User Flags", "Can show user flags", false) },
{ "Config.Show", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.Show, (c, v) => c.Config.Show = v, "Show Configuration", "Can show the configuration menu", false) }, { "Config.Show", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.Show, (c, v) => c.Config.Show = v, "Show Configuration", "Can show the configuration menu", false) },
{ "Job.Lists.AllOpen", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Lists.AllOpen, (c, v) => c.Job.Lists.AllOpen = v, "All Open List", "Can show list", false) }, { "Job.Lists.AllOpen", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Lists.AllOpen, (c, v) => c.Job.Lists.AllOpen = v, "All Open List", "Can show list", false) },
@@ -185,22 +188,26 @@ namespace Disco.Services.Authorization
{ "Device.Properties.DeviceProfile", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Properties.DeviceProfile, (c, v) => c.Device.Properties.DeviceProfile = v, "Device Profile Property", "Can update property", false) }, { "Device.Properties.DeviceProfile", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Properties.DeviceProfile, (c, v) => c.Device.Properties.DeviceProfile = v, "Device Profile Property", "Can update property", false) },
{ "Device.Properties.Location", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Properties.Location, (c, v) => c.Device.Properties.Location = v, "Location Property", "Can update property", false) }, { "Device.Properties.Location", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Properties.Location, (c, v) => c.Device.Properties.Location = v, "Location Property", "Can update property", false) },
{ "Device.Actions.AddAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.AddAttachments, (c, v) => c.Device.Actions.AddAttachments = v, "Add Attachments", "Can add attachments to devices", false) }, { "Device.Actions.AddAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.AddAttachments, (c, v) => c.Device.Actions.AddAttachments = v, "Add Attachments", "Can add attachments to devices", false) },
{ "Device.Actions.AddFlags", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.AddFlags, (c, v) => c.Device.Actions.AddFlags = v, "Add Device Flags", "Can add device flags", false) },
{ "Device.Actions.AllowUnauthenticatedEnrol", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.AllowUnauthenticatedEnrol, (c, v) => c.Device.Actions.AllowUnauthenticatedEnrol = v, "Allow Unauthenticated Enrol", "Can allow devices to enrol without authentication", false) }, { "Device.Actions.AllowUnauthenticatedEnrol", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.AllowUnauthenticatedEnrol, (c, v) => c.Device.Actions.AllowUnauthenticatedEnrol = v, "Allow Unauthenticated Enrol", "Can allow devices to enrol without authentication", false) },
{ "Device.Actions.AssignUser", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.AssignUser, (c, v) => c.Device.Actions.AssignUser = v, "Assign User", "Can update the user assignment of devices", false) }, { "Device.Actions.AssignUser", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.AssignUser, (c, v) => c.Device.Actions.AssignUser = v, "Assign User", "Can update the user assignment of devices", false) },
{ "Device.Actions.Decommission", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.Decommission, (c, v) => c.Device.Actions.Decommission = v, "Decommission", "Can decommission devices", false) }, { "Device.Actions.Decommission", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.Decommission, (c, v) => c.Device.Actions.Decommission = v, "Decommission", "Can decommission devices", false) },
{ "Device.Actions.Delete", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.Delete, (c, v) => c.Device.Actions.Delete = v, "Delete", "Can delete devices", false) }, { "Device.Actions.Delete", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.Delete, (c, v) => c.Device.Actions.Delete = v, "Delete", "Can delete devices", false) },
{ "Device.Actions.EditFlags", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.EditFlags, (c, v) => c.Device.Actions.EditFlags = v, "Edit Device Flags", "Can edit device flags", false) },
{ "Device.Actions.EnrolDevices", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.EnrolDevices, (c, v) => c.Device.Actions.EnrolDevices = v, "Enrol Devices", "Can add devices offline and enrol devices with the Bootstrapper", false) }, { "Device.Actions.EnrolDevices", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.EnrolDevices, (c, v) => c.Device.Actions.EnrolDevices = v, "Enrol Devices", "Can add devices offline and enrol devices with the Bootstrapper", false) },
{ "Device.Actions.Export", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.Export, (c, v) => c.Device.Actions.Export = v, "Export Devices", "Can export devices in a bulk format", false) }, { "Device.Actions.Export", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.Export, (c, v) => c.Device.Actions.Export = v, "Export Devices", "Can export devices in a bulk format", false) },
{ "Device.Actions.GenerateDocuments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.GenerateDocuments, (c, v) => c.Device.Actions.GenerateDocuments = v, "Generate Documents", "Can generate documents for jobs", false) }, { "Device.Actions.GenerateDocuments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.GenerateDocuments, (c, v) => c.Device.Actions.GenerateDocuments = v, "Generate Documents", "Can generate documents for jobs", false) },
{ "Device.Actions.Import", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.Import, (c, v) => c.Device.Actions.Import = v, "Import Devices", "Can bulk import devices", false) }, { "Device.Actions.Import", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.Import, (c, v) => c.Device.Actions.Import = v, "Import Devices", "Can bulk import devices", false) },
{ "Device.Actions.Recommission", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.Recommission, (c, v) => c.Device.Actions.Recommission = v, "Recommission", "Can recommission devices", false) }, { "Device.Actions.Recommission", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.Recommission, (c, v) => c.Device.Actions.Recommission = v, "Recommission", "Can recommission devices", false) },
{ "Device.Actions.RemoveAnyAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.RemoveAnyAttachments, (c, v) => c.Device.Actions.RemoveAnyAttachments = v, "Remove Any Attachments", "Can remove any attachments from devices", false) }, { "Device.Actions.RemoveAnyAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.RemoveAnyAttachments, (c, v) => c.Device.Actions.RemoveAnyAttachments = v, "Remove Any Attachments", "Can remove any attachments from devices", false) },
{ "Device.Actions.RemoveFlags", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.RemoveFlags, (c, v) => c.Device.Actions.RemoveFlags = v, "Remove Device Flags", "Can remove device flags", false) },
{ "Device.Actions.RemoveOwnAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.RemoveOwnAttachments, (c, v) => c.Device.Actions.RemoveOwnAttachments = v, "Remove Own Attachments", "Can remove own attachments from devices", false) }, { "Device.Actions.RemoveOwnAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.RemoveOwnAttachments, (c, v) => c.Device.Actions.RemoveOwnAttachments = v, "Remove Own Attachments", "Can remove own attachments from devices", false) },
{ "Device.Search", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Search, (c, v) => c.Device.Search = v, "Search Devices", "Can search devices", false) }, { "Device.Search", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Search, (c, v) => c.Device.Search = v, "Search Devices", "Can search devices", false) },
{ "Device.ShowAssignmentHistory", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowAssignmentHistory, (c, v) => c.Device.ShowAssignmentHistory = v, "Show Assignment History", "Can show the assignment history for devices", false) }, { "Device.ShowAssignmentHistory", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowAssignmentHistory, (c, v) => c.Device.ShowAssignmentHistory = v, "Show Assignment History", "Can show the assignment history for devices", false) },
{ "Device.ShowAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowAttachments, (c, v) => c.Device.ShowAttachments = v, "Show Attachments", "Can show device attachments", false) }, { "Device.ShowAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowAttachments, (c, v) => c.Device.ShowAttachments = v, "Show Attachments", "Can show device attachments", false) },
{ "Device.ShowCertificates", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowCertificates, (c, v) => c.Device.ShowCertificates = v, "Show Certificates", "Can show certificates associated with devices", false) }, { "Device.ShowCertificates", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowCertificates, (c, v) => c.Device.ShowCertificates = v, "Show Certificates", "Can show certificates associated with devices", false) },
{ "Device.ShowDetails", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowDetails, (c, v) => c.Device.ShowDetails = v, "Show Details", "Can show details associated with devices", false) }, { "Device.ShowDetails", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowDetails, (c, v) => c.Device.ShowDetails = v, "Show Details", "Can show details associated with devices", false) },
{ "Device.ShowFlagAssignments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowFlagAssignments, (c, v) => c.Device.ShowFlagAssignments = v, "Show Device Flag Assignments", "Can show flags associated with devices", false) },
{ "Device.Show", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Show, (c, v) => c.Device.Show = v, "Show Devices", "Can show devices", false) }, { "Device.Show", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Show, (c, v) => c.Device.Show = v, "Show Devices", "Can show devices", false) },
{ "Device.ShowJobs", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowJobs, (c, v) => c.Device.ShowJobs = v, "Show Devices Jobs", "Can show jobs associated with devices", false) }, { "Device.ShowJobs", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowJobs, (c, v) => c.Device.ShowJobs = v, "Show Devices Jobs", "Can show jobs associated with devices", false) },
{ "User.Actions.AddAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.User.Actions.AddAttachments, (c, v) => c.User.Actions.AddAttachments = v, "Add Attachments", "Can add attachments to users", false) }, { "User.Actions.AddAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.User.Actions.AddAttachments, (c, v) => c.User.Actions.AddAttachments = v, "Add Attachments", "Can add attachments to users", false) },
@@ -220,14 +227,14 @@ namespace Disco.Services.Authorization
{ "User.ShowFlagAssignments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.User.ShowFlagAssignments, (c, v) => c.User.ShowFlagAssignments = v, "Show Users Flag Assignments", "Can show flags associated with users", false) }, { "User.ShowFlagAssignments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.User.ShowFlagAssignments, (c, v) => c.User.ShowFlagAssignments = v, "Show Users Flag Assignments", "Can show flags associated with users", false) },
{ "User.ShowJobs", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.User.ShowJobs, (c, v) => c.User.ShowJobs = v, "Show Users Jobs", "Can show jobs associated with users", false) }, { "User.ShowJobs", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.User.ShowJobs, (c, v) => c.User.ShowJobs = v, "Show Users Jobs", "Can show jobs associated with users", false) },
{ "ComputerAccount", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.ComputerAccount, (c, v) => c.ComputerAccount = v, "Computer Account", "Represents a computer account", true) }, { "ComputerAccount", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.ComputerAccount, (c, v) => c.ComputerAccount = v, "Computer Account", "Represents a computer account", true) },
{ "DiscoAdminAccount", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.DiscoAdminAccount, (c, v) => c.DiscoAdminAccount = v, "Disco Administrator Account", "Represents a Disco Administrator account", true) } { "DiscoAdminAccount", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.DiscoAdminAccount, (c, v) => c.DiscoAdminAccount = v, "Disco Administrator Account", "Represents a Disco ICT Administrator account", true) }
}; };
#endregion #endregion
#region Role Claim Navigator #region Role Claim Navigator
_claimNavigator = _claimNavigator =
new ClaimNavigatorItem("Claims", "Permissions", "Top-level node for all permissions", false, new List<IClaimNavigatorItem>() { new ClaimNavigatorItem("Claims", "Permissions", "Top-level node for all permissions", false, new List<IClaimNavigatorItem>() {
new ClaimNavigatorItem("Config", "Configuration", "Permissions related to Disco Configuration", false, new List<IClaimNavigatorItem>() { new ClaimNavigatorItem("Config", "Configuration", "Permissions related to Disco ICT Configuration", false, new List<IClaimNavigatorItem>() {
new ClaimNavigatorItem("Config.DeviceBatch", "Device Batches", "Permissions related to Device Batches", false, new List<IClaimNavigatorItem>() { new ClaimNavigatorItem("Config.DeviceBatch", "Device Batches", "Permissions related to Device Batches", false, new List<IClaimNavigatorItem>() {
new ClaimNavigatorItem("Config.DeviceBatch.Configure", false), new ClaimNavigatorItem("Config.DeviceBatch.Configure", false),
new ClaimNavigatorItem("Config.DeviceBatch.Create", false), new ClaimNavigatorItem("Config.DeviceBatch.Create", false),
@@ -238,6 +245,13 @@ namespace Disco.Services.Authorization
new ClaimNavigatorItem("Config.DeviceCertificate", "Device Certificates", "Permissions related to Device Certificates", false, new List<IClaimNavigatorItem>() { new ClaimNavigatorItem("Config.DeviceCertificate", "Device Certificates", "Permissions related to Device Certificates", false, new List<IClaimNavigatorItem>() {
new ClaimNavigatorItem("Config.DeviceCertificate.DownloadCertificates", false) new ClaimNavigatorItem("Config.DeviceCertificate.DownloadCertificates", false)
}), }),
new ClaimNavigatorItem("Config.DeviceFlag", "Device Flags", "Permissions related to Device Flags", false, new List<IClaimNavigatorItem>() {
new ClaimNavigatorItem("Config.DeviceFlag.Configure", false),
new ClaimNavigatorItem("Config.DeviceFlag.Create", false),
new ClaimNavigatorItem("Config.DeviceFlag.Delete", false),
new ClaimNavigatorItem("Config.DeviceFlag.Export", false),
new ClaimNavigatorItem("Config.DeviceFlag.Show", false)
}),
new ClaimNavigatorItem("Config.DeviceModel", "Device Models", "Permissions related to Device Models", false, new List<IClaimNavigatorItem>() { new ClaimNavigatorItem("Config.DeviceModel", "Device Models", "Permissions related to Device Models", false, new List<IClaimNavigatorItem>() {
new ClaimNavigatorItem("Config.DeviceModel.ConfigureComponents", false), new ClaimNavigatorItem("Config.DeviceModel.ConfigureComponents", false),
new ClaimNavigatorItem("Config.DeviceModel.Configure", false), new ClaimNavigatorItem("Config.DeviceModel.Configure", false),
@@ -306,6 +320,7 @@ namespace Disco.Services.Authorization
new ClaimNavigatorItem("Config.UserFlag.Configure", false), new ClaimNavigatorItem("Config.UserFlag.Configure", false),
new ClaimNavigatorItem("Config.UserFlag.Create", false), new ClaimNavigatorItem("Config.UserFlag.Create", false),
new ClaimNavigatorItem("Config.UserFlag.Delete", false), new ClaimNavigatorItem("Config.UserFlag.Delete", false),
new ClaimNavigatorItem("Config.UserFlag.Export", false),
new ClaimNavigatorItem("Config.UserFlag.Show", false) new ClaimNavigatorItem("Config.UserFlag.Show", false)
}), }),
new ClaimNavigatorItem("Config.Show", false) new ClaimNavigatorItem("Config.Show", false)
@@ -429,16 +444,19 @@ namespace Disco.Services.Authorization
new ClaimNavigatorItem("Device", "Device", "Permissions related to Devices", false, new List<IClaimNavigatorItem>() { new ClaimNavigatorItem("Device", "Device", "Permissions related to Devices", false, new List<IClaimNavigatorItem>() {
new ClaimNavigatorItem("Device.Actions", "Actions", "Permissions related to Device Actions", false, new List<IClaimNavigatorItem>() { new ClaimNavigatorItem("Device.Actions", "Actions", "Permissions related to Device Actions", false, new List<IClaimNavigatorItem>() {
new ClaimNavigatorItem("Device.Actions.AddAttachments", false), new ClaimNavigatorItem("Device.Actions.AddAttachments", false),
new ClaimNavigatorItem("Device.Actions.AddFlags", false),
new ClaimNavigatorItem("Device.Actions.AllowUnauthenticatedEnrol", false), new ClaimNavigatorItem("Device.Actions.AllowUnauthenticatedEnrol", false),
new ClaimNavigatorItem("Device.Actions.AssignUser", false), new ClaimNavigatorItem("Device.Actions.AssignUser", false),
new ClaimNavigatorItem("Device.Actions.Decommission", false), new ClaimNavigatorItem("Device.Actions.Decommission", false),
new ClaimNavigatorItem("Device.Actions.Delete", false), new ClaimNavigatorItem("Device.Actions.Delete", false),
new ClaimNavigatorItem("Device.Actions.EditFlags", false),
new ClaimNavigatorItem("Device.Actions.EnrolDevices", false), new ClaimNavigatorItem("Device.Actions.EnrolDevices", false),
new ClaimNavigatorItem("Device.Actions.Export", false), new ClaimNavigatorItem("Device.Actions.Export", false),
new ClaimNavigatorItem("Device.Actions.GenerateDocuments", false), new ClaimNavigatorItem("Device.Actions.GenerateDocuments", false),
new ClaimNavigatorItem("Device.Actions.Import", false), new ClaimNavigatorItem("Device.Actions.Import", false),
new ClaimNavigatorItem("Device.Actions.Recommission", false), new ClaimNavigatorItem("Device.Actions.Recommission", false),
new ClaimNavigatorItem("Device.Actions.RemoveAnyAttachments", false), new ClaimNavigatorItem("Device.Actions.RemoveAnyAttachments", false),
new ClaimNavigatorItem("Device.Actions.RemoveFlags", false),
new ClaimNavigatorItem("Device.Actions.RemoveOwnAttachments", false) new ClaimNavigatorItem("Device.Actions.RemoveOwnAttachments", false)
}), }),
new ClaimNavigatorItem("Device.Properties", "Device Properties", "Permissions related to Device Properties", false, new List<IClaimNavigatorItem>() { new ClaimNavigatorItem("Device.Properties", "Device Properties", "Permissions related to Device Properties", false, new List<IClaimNavigatorItem>() {
@@ -453,6 +471,7 @@ namespace Disco.Services.Authorization
new ClaimNavigatorItem("Device.ShowAttachments", false), new ClaimNavigatorItem("Device.ShowAttachments", false),
new ClaimNavigatorItem("Device.ShowCertificates", false), new ClaimNavigatorItem("Device.ShowCertificates", false),
new ClaimNavigatorItem("Device.ShowDetails", false), new ClaimNavigatorItem("Device.ShowDetails", false),
new ClaimNavigatorItem("Device.ShowFlagAssignments", false),
new ClaimNavigatorItem("Device.Show", false), new ClaimNavigatorItem("Device.Show", false),
new ClaimNavigatorItem("Device.ShowJobs", false) new ClaimNavigatorItem("Device.ShowJobs", false)
}), }),
@@ -550,6 +569,11 @@ namespace Disco.Services.Authorization
c.Config.DeviceBatch.Delete = true; c.Config.DeviceBatch.Delete = true;
c.Config.DeviceBatch.Show = true; c.Config.DeviceBatch.Show = true;
c.Config.DeviceBatch.ShowTimeline = true; c.Config.DeviceBatch.ShowTimeline = true;
c.Config.DeviceFlag.Configure = true;
c.Config.DeviceFlag.Create = true;
c.Config.DeviceFlag.Delete = true;
c.Config.DeviceFlag.Export = true;
c.Config.DeviceFlag.Show = true;
c.Config.DeviceModel.ConfigureComponents = true; c.Config.DeviceModel.ConfigureComponents = true;
c.Config.DeviceModel.Configure = true; c.Config.DeviceModel.Configure = true;
c.Config.DeviceModel.Delete = true; c.Config.DeviceModel.Delete = true;
@@ -593,6 +617,7 @@ namespace Disco.Services.Authorization
c.Config.UserFlag.Configure = true; c.Config.UserFlag.Configure = true;
c.Config.UserFlag.Create = true; c.Config.UserFlag.Create = true;
c.Config.UserFlag.Delete = true; c.Config.UserFlag.Delete = true;
c.Config.UserFlag.Export = true;
c.Config.UserFlag.Show = true; c.Config.UserFlag.Show = true;
c.Config.Show = true; c.Config.Show = true;
c.Job.Lists.AllOpen = true; c.Job.Lists.AllOpen = true;
@@ -701,22 +726,26 @@ namespace Disco.Services.Authorization
c.Device.Properties.DeviceProfile = true; c.Device.Properties.DeviceProfile = true;
c.Device.Properties.Location = true; c.Device.Properties.Location = true;
c.Device.Actions.AddAttachments = true; c.Device.Actions.AddAttachments = true;
c.Device.Actions.AddFlags = true;
c.Device.Actions.AllowUnauthenticatedEnrol = true; c.Device.Actions.AllowUnauthenticatedEnrol = true;
c.Device.Actions.AssignUser = true; c.Device.Actions.AssignUser = true;
c.Device.Actions.Decommission = true; c.Device.Actions.Decommission = true;
c.Device.Actions.Delete = true; c.Device.Actions.Delete = true;
c.Device.Actions.EditFlags = true;
c.Device.Actions.EnrolDevices = true; c.Device.Actions.EnrolDevices = true;
c.Device.Actions.Export = true; c.Device.Actions.Export = true;
c.Device.Actions.GenerateDocuments = true; c.Device.Actions.GenerateDocuments = true;
c.Device.Actions.Import = true; c.Device.Actions.Import = true;
c.Device.Actions.Recommission = true; c.Device.Actions.Recommission = true;
c.Device.Actions.RemoveAnyAttachments = true; c.Device.Actions.RemoveAnyAttachments = true;
c.Device.Actions.RemoveFlags = true;
c.Device.Actions.RemoveOwnAttachments = true; c.Device.Actions.RemoveOwnAttachments = true;
c.Device.Search = true; c.Device.Search = true;
c.Device.ShowAssignmentHistory = true; c.Device.ShowAssignmentHistory = true;
c.Device.ShowAttachments = true; c.Device.ShowAttachments = true;
c.Device.ShowCertificates = true; c.Device.ShowCertificates = true;
c.Device.ShowDetails = true; c.Device.ShowDetails = true;
c.Device.ShowFlagAssignments = true;
c.Device.Show = true; c.Device.Show = true;
c.Device.ShowJobs = true; c.Device.ShowJobs = true;
c.User.Actions.AddAttachments = true; c.User.Actions.AddAttachments = true;
@@ -749,7 +778,7 @@ namespace Disco.Services.Authorization
#region Role Claim Constants #region Role Claim Constants
/// <summary>Configuration /// <summary>Configuration
/// <para>Permissions related to Disco Configuration</para> /// <para>Permissions related to Disco ICT Configuration</para>
/// </summary> /// </summary>
public static class Config public static class Config
{ {
@@ -825,6 +854,38 @@ namespace Disco.Services.Authorization
public const string ShowTimeline = "Config.DeviceBatch.ShowTimeline"; public const string ShowTimeline = "Config.DeviceBatch.ShowTimeline";
} }
/// <summary>Device Flags
/// <para>Permissions related to Device Flags</para>
/// </summary>
public static class DeviceFlag
{
/// <summary>Configure Device Flags
/// <para>Can configure device flags</para>
/// </summary>
public const string Configure = "Config.DeviceFlag.Configure";
/// <summary>Create Device Flags
/// <para>Can create device flags</para>
/// </summary>
public const string Create = "Config.DeviceFlag.Create";
/// <summary>Delete Device Flags
/// <para>Can delete device flags</para>
/// </summary>
public const string Delete = "Config.DeviceFlag.Delete";
/// <summary>Export Device Flag Assignments
/// <para>Can export user device assignments</para>
/// </summary>
public const string Export = "Config.DeviceFlag.Export";
/// <summary>Show Device Flags
/// <para>Can show device flags</para>
/// </summary>
public const string Show = "Config.DeviceFlag.Show";
}
/// <summary>Device Models /// <summary>Device Models
/// <para>Permissions related to Device Models</para> /// <para>Permissions related to Device Models</para>
/// </summary> /// </summary>
@@ -1109,6 +1170,11 @@ namespace Disco.Services.Authorization
/// </summary> /// </summary>
public const string Delete = "Config.UserFlag.Delete"; public const string Delete = "Config.UserFlag.Delete";
/// <summary>Export User Flag Assignments
/// <para>Can export user flag assignments</para>
/// </summary>
public const string Export = "Config.UserFlag.Export";
/// <summary>Show User Flags /// <summary>Show User Flags
/// <para>Can show user flags</para> /// <para>Can show user flags</para>
/// </summary> /// </summary>
@@ -1726,6 +1792,11 @@ namespace Disco.Services.Authorization
/// </summary> /// </summary>
public const string AddAttachments = "Device.Actions.AddAttachments"; public const string AddAttachments = "Device.Actions.AddAttachments";
/// <summary>Add Device Flags
/// <para>Can add device flags</para>
/// </summary>
public const string AddFlags = "Device.Actions.AddFlags";
/// <summary>Allow Unauthenticated Enrol /// <summary>Allow Unauthenticated Enrol
/// <para>Can allow devices to enrol without authentication</para> /// <para>Can allow devices to enrol without authentication</para>
/// </summary> /// </summary>
@@ -1746,6 +1817,11 @@ namespace Disco.Services.Authorization
/// </summary> /// </summary>
public const string Delete = "Device.Actions.Delete"; public const string Delete = "Device.Actions.Delete";
/// <summary>Edit Device Flags
/// <para>Can edit device flags</para>
/// </summary>
public const string EditFlags = "Device.Actions.EditFlags";
/// <summary>Enrol Devices /// <summary>Enrol Devices
/// <para>Can add devices offline and enrol devices with the Bootstrapper</para> /// <para>Can add devices offline and enrol devices with the Bootstrapper</para>
/// </summary> /// </summary>
@@ -1776,6 +1852,11 @@ namespace Disco.Services.Authorization
/// </summary> /// </summary>
public const string RemoveAnyAttachments = "Device.Actions.RemoveAnyAttachments"; public const string RemoveAnyAttachments = "Device.Actions.RemoveAnyAttachments";
/// <summary>Remove Device Flags
/// <para>Can remove device flags</para>
/// </summary>
public const string RemoveFlags = "Device.Actions.RemoveFlags";
/// <summary>Remove Own Attachments /// <summary>Remove Own Attachments
/// <para>Can remove own attachments from devices</para> /// <para>Can remove own attachments from devices</para>
/// </summary> /// </summary>
@@ -1807,6 +1888,11 @@ namespace Disco.Services.Authorization
/// </summary> /// </summary>
public const string ShowDetails = "Device.ShowDetails"; public const string ShowDetails = "Device.ShowDetails";
/// <summary>Show Device Flag Assignments
/// <para>Can show flags associated with devices</para>
/// </summary>
public const string ShowFlagAssignments = "Device.ShowFlagAssignments";
/// <summary>Show Devices /// <summary>Show Devices
/// <para>Can show devices</para> /// <para>Can show devices</para>
/// </summary> /// </summary>
@@ -1918,7 +2004,7 @@ namespace Disco.Services.Authorization
public const string ComputerAccount = "ComputerAccount"; public const string ComputerAccount = "ComputerAccount";
/// <summary>Disco Administrator Account /// <summary>Disco Administrator Account
/// <para>Represents a Disco Administrator account</para> /// <para>Represents a Disco ICT Administrator account</para>
/// </summary> /// </summary>
public const string DiscoAdminAccount = "DiscoAdminAccount"; public const string DiscoAdminAccount = "DiscoAdminAccount";
#endregion #endregion
-3
View File
@@ -20,9 +20,6 @@
<#@ import namespace="System.Runtime.InteropServices.CustomMarshalers" #> <#@ import namespace="System.Runtime.InteropServices.CustomMarshalers" #>
<#@ import namespace="System.Runtime.InteropServices" #> <#@ import namespace="System.Runtime.InteropServices" #>
<#@ import namespace="System.Reflection" #> <#@ import namespace="System.Reflection" #>
<# <#
// Get the DTE service from the host // Get the DTE service from the host
EnvDTE.DTE Dte = null; EnvDTE.DTE Dte = null;
@@ -14,7 +14,7 @@ using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.UserFlag;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration
{ {
[ClaimDetails("Configuration", "Permissions related to Disco Configuration")] [ClaimDetails("Configuration", "Permissions related to Disco ICT Configuration")]
public class ConfigClaims : BaseRoleClaimGroup public class ConfigClaims : BaseRoleClaimGroup
{ {
public ConfigClaims() public ConfigClaims()
@@ -22,6 +22,7 @@ namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration
DeviceCertificate = new DeviceCertificateClaims(); DeviceCertificate = new DeviceCertificateClaims();
Enrolment = new EnrolmentClaims(); Enrolment = new EnrolmentClaims();
DeviceBatch = new DeviceBatchClaims(); DeviceBatch = new DeviceBatchClaims();
DeviceFlag = new DeviceFlagClaims();
DeviceModel = new DeviceModelClaims(); DeviceModel = new DeviceModelClaims();
DeviceProfile = new DeviceProfileClaims(); DeviceProfile = new DeviceProfileClaims();
DocumentTemplate = new DocumentTemplateClaims(); DocumentTemplate = new DocumentTemplateClaims();
@@ -43,6 +44,8 @@ namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration
public DeviceBatchClaims DeviceBatch { get; set; } public DeviceBatchClaims DeviceBatch { get; set; }
public DeviceFlagClaims DeviceFlag { get; set; }
public DeviceModelClaims DeviceModel { get; set; } public DeviceModelClaims DeviceModel { get; set; }
public DeviceProfileClaims DeviceProfile { get; set; } public DeviceProfileClaims DeviceProfile { get; set; }
@@ -0,0 +1,20 @@
namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.UserFlag
{
[ClaimDetails("Device Flags", "Permissions related to Device Flags")]
public class DeviceFlagClaims : BaseRoleClaimGroup
{
[ClaimDetails("Configure Device Flags", "Can configure device flags")]
public bool Configure { get; set; }
[ClaimDetails("Create Device Flags", "Can create device flags")]
public bool Create { get; set; }
[ClaimDetails("Delete Device Flags", "Can delete device flags")]
public bool Delete { get; set; }
[ClaimDetails("Export Device Flag Assignments", "Can export user device assignments")]
public bool Export { get; set; }
[ClaimDetails("Show Device Flags", "Can show device flags")]
public bool Show { get; set; }
}
}
@@ -11,6 +11,8 @@
[ClaimDetails("Delete User Flags", "Can delete user flags")] [ClaimDetails("Delete User Flags", "Can delete user flags")]
public bool Delete { get; set; } public bool Delete { get; set; }
[ClaimDetails("Export User Flag Assignments", "Can export user flag assignments")]
public bool Export { get; set; }
[ClaimDetails("Show User Flags", "Can show user flags")] [ClaimDetails("Show User Flags", "Can show user flags")]
public bool Show { get; set; } public bool Show { get; set; }
@@ -25,6 +25,12 @@
[ClaimDetails("Generate Documents", "Can generate documents for jobs")] [ClaimDetails("Generate Documents", "Can generate documents for jobs")]
public bool GenerateDocuments { get; set; } public bool GenerateDocuments { get; set; }
[ClaimDetails("Add Device Flags", "Can add device flags")]
public bool AddFlags { get; set; }
[ClaimDetails("Remove Device Flags", "Can remove device flags")]
public bool RemoveFlags { get; set; }
[ClaimDetails("Edit Device Flags", "Can edit device flags")]
public bool EditFlags { get; set; }
[ClaimDetails("Enrol Devices", "Can add devices offline and enrol devices with the Bootstrapper")] [ClaimDetails("Enrol Devices", "Can add devices offline and enrol devices with the Bootstrapper")]
public bool EnrolDevices { get; set; } public bool EnrolDevices { get; set; }
@@ -25,7 +25,8 @@
public bool ShowJobs { get; set; } public bool ShowJobs { get; set; }
[ClaimDetails("Show Assignment History", "Can show the assignment history for devices")] [ClaimDetails("Show Assignment History", "Can show the assignment history for devices")]
public bool ShowAssignmentHistory { get; set; } public bool ShowAssignmentHistory { get; set; }
[ClaimDetails("Show Device Flag Assignments", "Can show flags associated with devices")]
public bool ShowFlagAssignments { get; set; }
public DevicePropertiesClaims Properties { get; set; } public DevicePropertiesClaims Properties { get; set; }
@@ -149,7 +149,7 @@ namespace Disco.Services.Authorization.Roles
} }
/// <summary> /// <summary>
/// Migrates authorization role claims to conform with changes to Disco since the last release. /// Migrates authorization role claims to conform with changes to Disco ICT since the last release.
/// Claims are only added when the meaning of an existing claim has changed (or expanded/contracted) to improve the migration experience. /// Claims are only added when the meaning of an existing claim has changed (or expanded/contracted) to improve the migration experience.
/// </summary> /// </summary>
private static void MigrateAuthorizationRoles(DiscoDataContext Database) private static void MigrateAuthorizationRoles(DiscoDataContext Database)
@@ -19,7 +19,7 @@ namespace Disco.Services.Authorization.Roles
[ClaimDetails("Computer Account", "Represents a computer account", true)] [ClaimDetails("Computer Account", "Represents a computer account", true)]
public bool ComputerAccount { get; set; } public bool ComputerAccount { get; set; }
[ClaimDetails("Disco Administrator Account", "Represents a Disco Administrator account", true)] [ClaimDetails("Disco Administrator Account", "Represents a Disco ICT Administrator account", true)]
public bool DiscoAdminAccount { get; set; } public bool DiscoAdminAccount { get; set; }
public ConfigClaims Config { get; set; } public ConfigClaims Config { get; set; }
@@ -22,7 +22,7 @@ namespace Disco.Services
using (DiscoDataContext database = new DiscoDataContext()) using (DiscoDataContext database = new DiscoDataContext())
{ {
EnrolResponse response = DeviceEnrolment.Enrol(database, username, request); EnrolResponse response = WindowsDeviceEnrolment.Enrol(database, username, request);
database.SaveChanges(); database.SaveChanges();
return response; return response;
} }
@@ -61,7 +61,7 @@ namespace Disco.Services
using (DiscoDataContext database = new DiscoDataContext()) using (DiscoDataContext database = new DiscoDataContext())
{ {
MacEnrolResponse response = DeviceEnrolment.MacEnrol(database, request, false); MacEnrolResponse response = MacDeviceEnrolment.Enrol(database, request, false);
database.SaveChanges(); database.SaveChanges();
return response; return response;
} }
+11 -1
View File
@@ -5,6 +5,7 @@ using Disco.Services.Authorization;
using Disco.Services.Documents; using Disco.Services.Documents;
using Disco.Services.Expressions; using Disco.Services.Expressions;
using Disco.Services.Interop.ActiveDirectory; using Disco.Services.Interop.ActiveDirectory;
using Disco.Services.Logging;
using Disco.Services.Users; using Disco.Services.Users;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -189,7 +190,16 @@ namespace Disco.Services
{ {
var adMachineAccount = ActiveDirectory.RetrieveADMachineAccount(d.DeviceDomainId); var adMachineAccount = ActiveDirectory.RetrieveADMachineAccount(d.DeviceDomainId);
if (adMachineAccount != null) if (adMachineAccount != null)
adMachineAccount.SetDescription(d); {
try
{
adMachineAccount.SetDescription(d);
}
catch (Exception ex)
{
SystemLog.LogWarning($"Unable to update AD Machine Account Description for {d.DeviceDomainId}: {ex.Message}");
}
}
} }
return newDua; return newDua;
@@ -0,0 +1,61 @@
using Disco.Data.Repository;
using Disco.Models.Repository;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
namespace Disco.Services.Devices.DeviceFlags
{
internal class Cache
{
private ConcurrentDictionary<int, DeviceFlag> _Cache;
public Cache(DiscoDataContext Database)
{
Initialize(Database);
}
public void ReInitialize(DiscoDataContext Database)
{
Initialize(Database);
}
private void Initialize(DiscoDataContext Database)
{
// Queues from Database
var flags = Database.DeviceFlags.ToList();
// Add Queues to In-Memory Cache
_Cache = new ConcurrentDictionary<int, DeviceFlag>(flags.Select(f => new KeyValuePair<int, DeviceFlag>(f.Id, f)));
}
public DeviceFlag GetDeviceFlag(int deviceFlagId)
{
if (_Cache.TryGetValue(deviceFlagId, out var item))
return item;
else
return null;
}
public List<DeviceFlag> GetDeviceFlags()
{
return _Cache.Values.ToList();
}
public void AddOrUpdate(DeviceFlag flag)
{
_Cache.AddOrUpdate(flag.Id, flag, (key, existingItem) => flag);
}
public DeviceFlag Remove(int deviceFlagId)
{
if (_Cache.TryRemove(deviceFlagId, out var item))
return item;
else
return null;
}
public DeviceFlag Remove(DeviceFlag deviceFlag)
{
return Remove(deviceFlag.Id);
}
}
}
@@ -0,0 +1,184 @@
using Disco.Data.Repository;
using Disco.Data.Repository.Monitor;
using Disco.Models.Repository;
using Disco.Models.Services.Interop.ActiveDirectory;
using Disco.Services.Interop.ActiveDirectory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
namespace Disco.Services.Devices.DeviceFlags
{
public class DeviceFlagDeviceAssignedUsersManagedGroup : ADManagedGroup
{
private const string KeyFormat = "DeviceFlag_{0}_DeviceAssignedUsers";
private const string DescriptionFormat = "User associated with devices which have the {0} Flag will be added to this Active Directory group.";
private const string CategoryDescriptionFormat = "Device Assigned Users Linked Group";
private const string GroupDescriptionFormat = "{0} [Device Flag Device Assigned Users]";
private IDisposable repositorySubscription;
private int deviceFlagId;
private string deviceFlagName;
public override string Description { get { return string.Format(DescriptionFormat, deviceFlagName); } }
public override string CategoryDescription { get { return CategoryDescriptionFormat; } }
public override string GroupDescription { get { return string.Format(GroupDescriptionFormat, deviceFlagName); } }
public override bool IncludeFilterBeginDate { get { return true; } }
private DeviceFlagDeviceAssignedUsersManagedGroup(string Key, ADManagedGroupConfiguration Configuration, DeviceFlag deviceFlag)
: base(Key, Configuration)
{
deviceFlagId = deviceFlag.Id;
deviceFlagName = deviceFlag.Name;
}
public override void Initialize()
{
// Subscribe to changes
repositorySubscription = DeviceFlagService.DeviceFlagAssignmentRepositoryEvents.Value
.Where(e =>
(((DeviceFlagAssignment)e.Entity).DeviceFlagId == deviceFlagId))
.Subscribe(ProcessRepositoryEvent);
}
public static string GetKey(DeviceFlag deviceFlag)
{
return string.Format(KeyFormat, deviceFlag.Id);
}
public static string GetDescription(DeviceFlag deviceFlag)
{
return string.Format(DescriptionFormat, deviceFlag.Name);
}
public static string GetCategoryDescription(DeviceFlag deviceFlag)
{
return CategoryDescriptionFormat;
}
public static bool TryGetManagedGroup(DeviceFlag deviceFlag, out DeviceFlagDeviceAssignedUsersManagedGroup managedGroup)
{
return ActiveDirectory.Context.ManagedGroups.TryGetValue(GetKey(deviceFlag), out managedGroup);
}
public static DeviceFlagDeviceAssignedUsersManagedGroup Initialize(DeviceFlag deviceFlag)
{
if (deviceFlag.Id > 0)
{
var key = GetKey(deviceFlag);
if (!string.IsNullOrEmpty(deviceFlag.DeviceUsersLinkedGroup))
{
var config = ConfigurationFromJson(deviceFlag.DeviceUsersLinkedGroup);
if (config != null && !string.IsNullOrWhiteSpace(config.GroupId))
{
var group = new DeviceFlagDeviceAssignedUsersManagedGroup(
key,
config,
deviceFlag);
// Add to AD Context
ActiveDirectory.Context.ManagedGroups.AddOrUpdate(group);
return group;
}
}
// Remove from AD Context
ActiveDirectory.Context.ManagedGroups.Remove(key);
}
return null;
}
public override IEnumerable<string> DetermineMembers(DiscoDataContext Database)
{
var query = (IQueryable<User>)Database.Users;
if (Configuration.FilterBeginDate.HasValue)
{
query = query
.Where(u => u.DeviceUserAssignments.Any(a =>
a.UnassignedDate == null &&
a.Device.DeviceFlagAssignments.Any(fa =>
fa.DeviceFlagId == deviceFlagId &&
!fa.RemovedDate.HasValue &&
fa.AddedDate >= Configuration.FilterBeginDate)));
}
else
{
query = query
.Where(u => u.DeviceUserAssignments.Any(a =>
a.UnassignedDate == null &&
a.Device.DeviceFlagAssignments.Any(fa =>
fa.DeviceFlagId == deviceFlagId &&
!fa.RemovedDate.HasValue)));
}
return query.Select(u => u.UserId)
.Distinct()
.ToList()
.Where(ActiveDirectory.IsValidDomainAccountId)
.ToList();
}
private void ProcessRepositoryEvent(RepositoryMonitorEvent Event)
{
var assignment = (DeviceFlagAssignment)Event.Entity;
string userId = assignment.Device?.AssignedUserId;
if (!ActiveDirectory.IsValidDomainAccountId(userId))
return;
switch (Event.EventType)
{
case RepositoryMonitorEventType.Added:
if (Configuration.FilterBeginDate.HasValue)
{
if (!assignment.RemovedDate.HasValue && assignment.AddedDate >= Configuration.FilterBeginDate)
{
AddMember(userId);
}
}
else
{
if (!assignment.RemovedDate.HasValue)
{
AddMember(userId);
}
}
break;
case RepositoryMonitorEventType.Modified:
if (!Configuration.FilterBeginDate.HasValue || assignment.AddedDate >= Configuration.FilterBeginDate)
{
if (assignment.RemovedDate.HasValue)
RemoveMember(userId, (database) =>
{
if (database.Users.Any(u => u.DeviceUserAssignments.Any(a =>
a.UnassignedDate == null &&
a.Device.DeviceFlagAssignments.Any(fa =>
fa.DeviceFlagId == deviceFlagId &&
!fa.RemovedDate.HasValue))))
{
return null;
}
else
{
return new[] { userId };
}
}
);
else
AddMember(userId);
}
break;
}
}
public override void Dispose()
{
if (repositorySubscription != null)
repositorySubscription.Dispose();
}
}
}
@@ -0,0 +1,202 @@
using Disco.Data.Repository;
using Disco.Data.Repository.Monitor;
using Disco.Models.Repository;
using Disco.Models.Services.Interop.ActiveDirectory;
using Disco.Services.Interop.ActiveDirectory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
namespace Disco.Services.Devices.DeviceFlags
{
public class DeviceFlagDevicesManagedGroup : ADManagedGroup
{
private const string KeyFormat = "DeviceFlag_{0}_Devices";
private const string DescriptionFormat = "Devices associated with the {0} Flag will be added to this Active Directory group.";
private const string CategoryDescriptionFormat = "Assigned Devices Linked Group";
private const string GroupDescriptionFormat = "{0} [Device Flag Devices]";
private IDisposable repositorySubscription;
private int deviceFlagId;
private string deviceFlagName;
public override string Description { get { return string.Format(DescriptionFormat, deviceFlagName); } }
public override string CategoryDescription { get { return CategoryDescriptionFormat; } }
public override string GroupDescription { get { return string.Format(GroupDescriptionFormat, deviceFlagName); } }
public override bool IncludeFilterBeginDate { get { return true; } }
private DeviceFlagDevicesManagedGroup(string Key, ADManagedGroupConfiguration Configuration, DeviceFlag DeviceFlag)
: base(Key, Configuration)
{
deviceFlagId = DeviceFlag.Id;
deviceFlagName = DeviceFlag.Name;
}
public override void Initialize()
{
// Subscribe to changes
repositorySubscription = DeviceFlagService.DeviceFlagAssignmentRepositoryEvents.Value
.Where(e =>
((DeviceFlagAssignment)e.Entity).DeviceFlagId == deviceFlagId)
.Subscribe(ProcessRepositoryEvent);
}
public static string GetKey(DeviceFlag deviceFlag)
{
return string.Format(KeyFormat, deviceFlag.Id);
}
public static string GetDescription(DeviceFlag deviceFlag)
{
return string.Format(DescriptionFormat, deviceFlag.Name);
}
public static string GetCategoryDescription(DeviceFlag deviceFlag)
{
return CategoryDescriptionFormat;
}
public static bool TryGetManagedGroup(DeviceFlag deviceFlag, out DeviceFlagDevicesManagedGroup managedGroup)
{
return ActiveDirectory.Context.ManagedGroups.TryGetValue(GetKey(deviceFlag), out managedGroup);
}
public static DeviceFlagDevicesManagedGroup Initialize(DeviceFlag deviceFlag)
{
if (deviceFlag.Id > 0)
{
var key = GetKey(deviceFlag);
if (!string.IsNullOrEmpty(deviceFlag.DevicesLinkedGroup))
{
var config = ConfigurationFromJson(deviceFlag.DevicesLinkedGroup);
if (config != null && !string.IsNullOrWhiteSpace(config.GroupId))
{
var group = new DeviceFlagDevicesManagedGroup(
key,
config,
deviceFlag);
// Add to AD Context
ActiveDirectory.Context.ManagedGroups.AddOrUpdate(group);
return group;
}
}
// Remove from AD Context
ActiveDirectory.Context.ManagedGroups.Remove(key);
}
return null;
}
public override IEnumerable<string> DetermineMembers(DiscoDataContext Database)
{
var query = Database.DeviceFlagAssignments
.Where(a => a.DeviceFlagId == deviceFlagId && !a.RemovedDate.HasValue && a.Device.DeviceDomainId != null);
if (Configuration.FilterBeginDate.HasValue)
query = query.Where(a => a.AddedDate >= Configuration.FilterBeginDate);
return query
.Select(a => a.Device.DeviceDomainId)
.ToList()
.Where(ActiveDirectory.IsValidDomainAccountId)
.Select(id => id + "$");
}
private void ProcessRepositoryEvent(RepositoryMonitorEvent Event)
{
var assignment = (DeviceFlagAssignment)Event.Entity;
var domainId = assignment.Device?.DeviceDomainId;
if (!ActiveDirectory.IsValidDomainAccountId(domainId))
return;
domainId += "$";
switch (Event.EventType)
{
case RepositoryMonitorEventType.Added:
if (Configuration.FilterBeginDate.HasValue)
{
if (!assignment.RemovedDate.HasValue && assignment.AddedDate >= Configuration.FilterBeginDate)
{
AddMember(domainId);
}
}
else
{
if (!assignment.RemovedDate.HasValue)
{
AddMember(domainId);
}
}
break;
case RepositoryMonitorEventType.Modified:
if (Configuration.FilterBeginDate.HasValue)
{
if (assignment.AddedDate >= Configuration.FilterBeginDate)
{
if (assignment.RemovedDate.HasValue)
{
RemoveMember(domainId);
}
else
{
AddMember(domainId);
}
}
}
else
{
if (assignment.RemovedDate.HasValue)
{
RemoveMember(domainId);
}
else
{
AddMember(domainId);
}
}
break;
case RepositoryMonitorEventType.Deleted:
// Remove the device if no other (non-removed) assignments exist.
var serialNumber = assignment.DeviceSerialNumber;
RemoveMember(domainId, (database) =>
{
if (Configuration.FilterBeginDate.HasValue)
{
if (database.DeviceFlagAssignments.Any(a => a.DeviceFlagId == deviceFlagId && a.DeviceSerialNumber == serialNumber && !a.RemovedDate.HasValue && a.AddedDate >= Configuration.FilterBeginDate))
{
return null;
}
else
{
return new string[] { domainId };
}
}
else
{
if (database.DeviceFlagAssignments.Any(a => a.DeviceFlagId == deviceFlagId && a.DeviceSerialNumber == serialNumber && !a.RemovedDate.HasValue))
{
return null;
}
else
{
return new string[] { domainId };
}
}
});
break;
}
}
public override void Dispose()
{
if (repositorySubscription != null)
repositorySubscription.Dispose();
}
}
}
@@ -0,0 +1,229 @@
using Disco.Data.Repository;
using Disco.Models.Exporting;
using Disco.Models.Services.Devices.DeviceFlag;
using Disco.Models.Services.Exporting;
using Disco.Services.Plugins.Features.DetailsProvider;
using Disco.Services.Tasks;
using Disco.Services.Users;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Linq;
namespace Disco.Services.Devices.DeviceFlags
{
using Metadata = ExportFieldMetadata<DeviceFlagExportRecord>;
public class DeviceFlagExport
{
private readonly DiscoDataContext database;
private readonly DeviceFlagExportOptions options;
public DeviceFlagExport(DiscoDataContext database, DeviceFlagExportOptions options)
{
this.database = database;
this.options = options;
}
public ExportResult Generate(IScheduledTaskStatus status)
{
var records = BuildRecords(status);
var metadata = BuildMetadata(records, status);
if (metadata.Count == 0)
throw new ArgumentException("At least one export field must be specified", nameof(options));
status.UpdateStatus(90, $"Formatting {records.Count} records for export");
return ExportHelpers.WriteExport(options, status, metadata, records);
}
private List<DeviceFlagExportRecord> BuildRecords(IScheduledTaskStatus status)
{
var query = database.DeviceFlagAssignments
.Include(a => a.DeviceFlag);
if (options.HasDeviceOptions())
query = query.Include(a => a.Device);
if (options.HasDeviceModelOptions())
query = query.Include(a => a.Device.DeviceModel);
if (options.HasDeviceBatchOptions())
query = query.Include(a => a.Device.DeviceBatch);
if (options.HasDeviceProfileOptions())
query = query.Include(a => a.Device.DeviceProfile);
if (options.HasAssignedUserOptions())
query = query.Include(a => a.Device.AssignedUser);
if (options.AssignedUserDetailCustom)
query = query.Include(a => a.Device.AssignedUser.UserDetails);
query = query.Where(a => options.DeviceFlagIds.Contains(a.DeviceFlagId));
if (options.CurrentOnly)
{
query = query.Where(a => !a.RemovedDate.HasValue);
}
// Update Users
if (options.HasAssignedUserOptions())
{
status.UpdateStatus(5, "Refreshing user details from Active Directory");
var userIds = query.Where(d => d.Device.AssignedUserId != null).Select(d => d.Device.AssignedUserId).Distinct().ToList();
foreach (var userId in userIds)
{
try
{
UserService.GetUser(userId, database);
}
catch (Exception) { } // Ignore Errors
}
}
status.UpdateStatus(15, "Extracting records from the database");
var records = query.Select(a => new DeviceFlagExportRecord()
{
Assignment = a
}).ToList();
if (options.AssignedUserDetailCustom)
{
status.UpdateStatus(50, "Extracting custom user detail records");
var detailsService = new DetailsProviderService(database);
var cache = new Dictionary<string, Dictionary<string, string>>(StringComparer.Ordinal);
foreach (var record in records)
{
var userId = record.Assignment.Device.AssignedUserId;
if (userId == null)
continue;
if (!cache.TryGetValue(userId, out var details))
details = detailsService.GetDetails(record.Assignment.Device.AssignedUser);
record.AssignedUserCustomDetails = details;
}
}
return records;
}
private List<Metadata> BuildMetadata(List<DeviceFlagExportRecord> records, IScheduledTaskStatus status)
{
status.UpdateStatus(80, "Building metadata");
IEnumerable<string> userDetailCustomKeys = null;
if (options.AssignedUserDetailCustom)
userDetailCustomKeys = records.Where(r => r.AssignedUserCustomDetails != null).SelectMany(r => r.AssignedUserCustomDetails.Keys).Distinct(StringComparer.OrdinalIgnoreCase).ToList();
var accessors = BuildAccessors(userDetailCustomKeys);
return typeof(DeviceFlagExportOptions).GetProperties()
.Where(p => p.PropertyType == typeof(bool))
.Select(p => new
{
property = p,
details = (DisplayAttribute)p.GetCustomAttributes(typeof(DisplayAttribute), false).FirstOrDefault()
})
.Where(p => p.details != null && p.property.Name != nameof(options.CurrentOnly) && (bool)p.property.GetValue(options))
.SelectMany(p =>
{
var fieldMetadata = accessors[p.property.Name];
fieldMetadata.ForEach(f =>
{
if (f.ColumnName == null)
f.ColumnName = (p.details.ShortName == "Device Flag") ? p.details.Name : $"{p.details.ShortName} {p.details.Name}";
});
return fieldMetadata;
}).ToList();
}
private static Dictionary<string, List<Metadata>> BuildAccessors(IEnumerable<string> userDetailsCustomKeys)
{
const string DateFormat = "yyyy-MM-dd";
const string DateTimeFormat = DateFormat + " HH:mm:ss";
Func<object, string> csvStringEncoded = (o) => o == null ? null : $"\"{((string)o).Replace("\"", "\"\"")}\"";
Func<object, string> csvToStringEncoded = (o) => o == null ? null : o.ToString();
Func<object, string> csvCurrencyEncoded = (o) => ((decimal?)o).HasValue ? ((decimal?)o).Value.ToString("C") : null;
Func<object, string> csvDateEncoded = (o) => ((DateTime)o).ToString(DateFormat);
Func<object, string> csvDateTimeEncoded = (o) => ((DateTime)o).ToString(DateTimeFormat);
Func<object, string> csvNullableDateEncoded = (o) => ((DateTime?)o).HasValue ? csvDateEncoded(o) : null;
Func<object, string> csvNullableDateTimeEncoded = (o) => ((DateTime?)o).HasValue ? csvDateTimeEncoded(o) : null;
var metadata = new Dictionary<string, List<Metadata>>();
// Device Flag
metadata.Add(nameof(DeviceFlagExportOptions.Id), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.Id), typeof(string), r => r.Assignment.DeviceFlagId, csvToStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.Name), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.Name), typeof(string), r => r.Assignment.DeviceFlag.Name, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.Description), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.Description), typeof(string), r => r.Assignment.DeviceFlag.Description, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.Icon), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.Icon), typeof(string), r => r.Assignment.DeviceFlag.Icon, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.IconColour), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.IconColour), typeof(string), r => r.Assignment.DeviceFlag.IconColour, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.AssignmentId), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.AssignmentId), typeof(string), r => r.Assignment.Id, csvToStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.AddedDate), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.AddedDate), typeof(string), r => r.Assignment.AddedDate, csvDateTimeEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.AddedUserId), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.AddedUserId), typeof(string), r => r.Assignment.AddedUserId, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.RemovedUserId), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.RemovedUserId), typeof(string), r => r.Assignment.RemovedUserId, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.RemovedDate), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.RemovedDate), typeof(string), r => r.Assignment.RemovedDate, csvNullableDateTimeEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.Comments), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.Comments), typeof(string), r => r.Assignment.Comments, csvStringEncoded) });
// Device
metadata.Add(nameof(DeviceFlagExportOptions.DeviceSerialNumber), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.DeviceSerialNumber), typeof(string), r => r.Assignment.Device.SerialNumber, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.DeviceAssetNumber), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.DeviceAssetNumber), typeof(string), r => r.Assignment.Device.AssetNumber, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.DeviceLocation), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.DeviceLocation), typeof(string), r => r.Assignment.Device.Location, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.DeviceComputerName), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.DeviceComputerName), typeof(string), r => r.Assignment.Device.DeviceDomainId, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.DeviceLastNetworkLogon), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.DeviceLastNetworkLogon), typeof(DateTime), r => r.Assignment.Device.LastNetworkLogonDate, csvNullableDateTimeEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.DeviceCreatedDate), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.DeviceCreatedDate), typeof(DateTime), r => r.Assignment.Device.CreatedDate, csvDateTimeEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.DeviceFirstEnrolledDate), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.DeviceFirstEnrolledDate), typeof(DateTime), r => r.Assignment.Device.EnrolledDate, csvNullableDateTimeEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.DeviceLastEnrolledDate), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.DeviceLastEnrolledDate), typeof(DateTime), r => r.Assignment.Device.LastEnrolDate, csvNullableDateTimeEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.DeviceAllowUnauthenticatedEnrol), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.DeviceAllowUnauthenticatedEnrol), typeof(bool), r => r.Assignment.Device.AllowUnauthenticatedEnrol, csvToStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.DeviceDecommissionedDate), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.DeviceDecommissionedDate), typeof(DateTime), r => r.Assignment.Device.DecommissionedDate, csvNullableDateTimeEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.DeviceDecommissionedReason), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.DeviceDecommissionedReason), typeof(string), r => r.Assignment.Device.DecommissionReason, csvToStringEncoded) });
// Model
metadata.Add(nameof(DeviceFlagExportOptions.ModelId), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.ModelId), typeof(int), r => r.Assignment.Device.DeviceModel.Id, csvToStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.ModelDescription), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.ModelDescription), typeof(string), r => r.Assignment.Device.DeviceModel.Description, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.ModelManufacturer), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.ModelManufacturer), typeof(string), r => r.Assignment.Device.DeviceModel.Manufacturer, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.ModelModel), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.ModelModel), typeof(string), r => r.Assignment.Device.DeviceModel.Model, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.ModelType), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.ModelType), typeof(string), r => r.Assignment.Device.DeviceModel.ModelType, csvStringEncoded) });
// Batch
metadata.Add(nameof(DeviceFlagExportOptions.BatchId), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.BatchId), typeof(int), r => r.Assignment.Device.DeviceBatch?.Id, csvToStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.BatchName), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.BatchName), typeof(string), r => r.Assignment.Device.DeviceBatch?.Name, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.BatchPurchaseDate), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.BatchPurchaseDate), typeof(DateTime), r => r.Assignment.Device.DeviceBatch?.PurchaseDate, csvNullableDateEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.BatchSupplier), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.BatchSupplier), typeof(string), r => r.Assignment.Device.DeviceBatch?.Supplier, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.BatchUnitCost), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.BatchUnitCost), typeof(decimal), r => r.Assignment.Device.DeviceBatch?.UnitCost, csvCurrencyEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.BatchWarrantyValidUntilDate), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.BatchWarrantyValidUntilDate), typeof(DateTime), r => r.Assignment.Device.DeviceBatch?.WarrantyValidUntil, csvNullableDateEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.BatchInsuredDate), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.BatchInsuredDate), typeof(DateTime), r => r.Assignment.Device.DeviceBatch?.InsuredDate, csvNullableDateEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.BatchInsuranceSupplier), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.BatchInsuranceSupplier), typeof(string), r => r.Assignment.Device.DeviceBatch?.InsuranceSupplier, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.BatchInsuredUntilDate), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.BatchInsuredUntilDate), typeof(DateTime), r => r.Assignment.Device.DeviceBatch?.InsuredUntil, csvNullableDateEncoded) });
// Profile
metadata.Add(nameof(DeviceFlagExportOptions.ProfileId), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.ProfileId), typeof(int), r => r.Assignment.Device.DeviceProfile?.Id, csvToStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.ProfileName), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.ProfileName), typeof(string), r => r.Assignment.Device.DeviceProfile?.Name, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.ProfileShortName), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.ProfileShortName), typeof(string), r => r.Assignment.Device.DeviceProfile?.ShortName, csvStringEncoded) });
// User
metadata.Add(nameof(DeviceFlagExportOptions.AssignedUserId), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.AssignedUserId), typeof(string), r => r.Assignment.Device?.AssignedUser?.UserId, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.AssignedUserDisplayName), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.AssignedUserDisplayName), typeof(string), r => r.Assignment.Device?.AssignedUser?.DisplayName, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.AssignedUserSurname), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.AssignedUserSurname), typeof(string), r => r.Assignment.Device?.AssignedUser?.Surname, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.AssignedUserGivenName), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.AssignedUserGivenName), typeof(string), r => r.Assignment.Device?.AssignedUser?.GivenName, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.AssignedUserPhoneNumber), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.AssignedUserPhoneNumber), typeof(string), r => r.Assignment.Device?.AssignedUser?.PhoneNumber, csvStringEncoded) });
metadata.Add(nameof(DeviceFlagExportOptions.AssignedUserEmailAddress), new List<Metadata>() { new Metadata(nameof(DeviceFlagExportOptions.AssignedUserEmailAddress), typeof(string), r => r.Assignment.Device?.AssignedUser?.EmailAddress, csvStringEncoded) });
if (userDetailsCustomKeys != null)
{
var userDetailCustomFields = new List<Metadata>();
foreach (var detailKey in userDetailsCustomKeys.OrderBy(k => k, StringComparer.OrdinalIgnoreCase))
{
var key = detailKey;
userDetailCustomFields.Add(new Metadata(detailKey, detailKey, typeof(string), r => r.AssignedUserCustomDetails != null && r.AssignedUserCustomDetails.TryGetValue(key, out var value) ? value : null, csvStringEncoded));
}
metadata.Add(nameof(DeviceFlagExportOptions.AssignedUserDetailCustom), userDetailCustomFields);
}
return metadata;
}
}
}
@@ -0,0 +1,46 @@
using Disco.Data.Repository;
using Disco.Models.Services.Devices.DeviceFlag;
using Disco.Services.Exporting;
using Disco.Services.Tasks;
using Quartz;
namespace Disco.Services.Devices.DeviceFlags
{
public class DeviceFlagExportTask : ScheduledTask
{
private const string JobDataMapContext = "Context";
public override string TaskName { get; } = "Export Device Flags";
public override bool SingleInstanceTask { get { return false; } }
public override bool CancelInitiallySupported { get { return false; } }
public static ExportTaskContext<DeviceFlagExportOptions> ScheduleNow(DeviceFlagExportOptions options)
{
// Build Context
var context = new ExportTaskContext<DeviceFlagExportOptions>(options);
// Build Data Map
var task = new DeviceFlagExportTask();
JobDataMap taskData = new JobDataMap() { { JobDataMapContext, context } };
// Schedule Task
context.TaskStatus = task.ScheduleTask(taskData);
return context;
}
protected override void ExecuteTask()
{
var context = (ExportTaskContext<DeviceFlagExportOptions>)ExecutionContext.JobDetail.JobDataMap[JobDataMapContext];
Status.UpdateStatus(10, "Exporting Device Flag Records", "Starting...");
using (DiscoDataContext Database = new DiscoDataContext())
{
var export = new DeviceFlagExport(Database, context.Options);
context.Result = export.Generate(Status);
}
}
}
}
@@ -0,0 +1,196 @@
using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Services.Authorization;
using Disco.Services.Expressions;
using Disco.Services.Logging;
using Disco.Services.Users;
using System;
using System.Collections;
using System.Data.Entity;
using System.Linq;
namespace Disco.Services
{
public static class DeviceFlagExtensions
{
#region Edit Comments
public static bool CanEditComments(this DeviceFlagAssignment fa)
{
return UserService.CurrentAuthorization.Has(Claims.Device.Actions.EditFlags);
}
public static void OnEditComments(this DeviceFlagAssignment fa, string Comments)
{
if (!fa.CanEditComments())
throw new InvalidOperationException("Editing comments for device flags is denied");
fa.Comments = string.IsNullOrWhiteSpace(Comments) ? null : Comments.Trim();
}
#endregion
#region Remove
public static bool CanRemove(this DeviceFlagAssignment fa)
{
if (fa.RemovedDate.HasValue)
return false;
return UserService.CurrentAuthorization.Has(Claims.Device.Actions.RemoveFlags);
}
public static void OnRemove(this DeviceFlagAssignment fa, DiscoDataContext Database, User RemovingUser)
{
if (!fa.CanRemove())
throw new InvalidOperationException("Removing device flags is denied");
fa.OnRemoveUnsafe(Database, RemovingUser);
}
public static void OnRemoveUnsafe(this DeviceFlagAssignment fa, DiscoDataContext Database, User RemovingUser)
{
fa = Database.DeviceFlagAssignments
.Include(a => a.DeviceFlag)
.First(a => a.Id == fa.Id);
RemovingUser = Database.Users.First(u => u.UserId == RemovingUser.UserId);
fa.RemovedDate = DateTime.Now;
fa.RemovedUserId = RemovingUser.UserId;
if (!string.IsNullOrWhiteSpace(fa.DeviceFlag.OnUnassignmentExpression))
{
try
{
Database.SaveChanges();
var expressionResult = fa.EvaluateOnUnassignmentExpression(Database, RemovingUser, fa.AddedDate);
if (!string.IsNullOrWhiteSpace(expressionResult))
{
fa.OnUnassignmentExpressionResult = expressionResult;
Database.SaveChanges();
}
}
catch (Exception ex)
{
SystemLog.LogException("Device Flag Expression - OnUnassignmentExpression", ex);
}
}
}
#endregion
#region Add
public static bool CanAddDeviceFlags(this Device d)
{
return UserService.CurrentAuthorization.Has(Claims.Device.Actions.AddFlags);
}
public static bool CanAddDeviceFlag(this Device d, DeviceFlag flag)
{
// Shortcut
if (!d.CanAddDeviceFlags())
return false;
// Already has Device Flag?
if (d.DeviceFlagAssignments.Any(fa => !fa.RemovedDate.HasValue && fa.DeviceFlagId == flag.Id))
return false;
return true;
}
public static DeviceFlagAssignment OnAddDeviceFlag(this Device d, DiscoDataContext Database, DeviceFlag flag, User AddingUser, string Comments)
{
if (!d.CanAddDeviceFlag(flag))
throw new InvalidOperationException("Adding device flag is denied");
return d.OnAddDeviceFlagUnsafe(Database, flag, AddingUser, Comments);
}
public static DeviceFlagAssignment OnAddDeviceFlagUnsafe(this Device d, DiscoDataContext Database, DeviceFlag flag, User AddingUser, string Comments)
{
flag = Database.DeviceFlags.First(f => f.Id == flag.Id);
d = Database.Devices.First(de => de.SerialNumber == d.SerialNumber);
AddingUser = Database.Users.First(user => user.UserId == AddingUser.UserId);
var fa = new DeviceFlagAssignment()
{
DeviceFlag = flag,
Device = d,
AddedDate = DateTime.Now,
AddedUser = AddingUser,
AddedUserId = AddingUser.UserId,
Comments = string.IsNullOrWhiteSpace(Comments) ? null : Comments.Trim()
};
Database.DeviceFlagAssignments.Add(fa);
if (!string.IsNullOrWhiteSpace(flag.OnAssignmentExpression))
{
try
{
Database.SaveChanges();
var expressionResult = fa.EvaluateOnAssignmentExpression(Database, AddingUser, fa.AddedDate);
if (!string.IsNullOrWhiteSpace(expressionResult))
{
fa.OnAssignmentExpressionResult = expressionResult;
Database.SaveChanges();
}
}
catch (Exception ex)
{
SystemLog.LogException("Device Flag Expression - OnAssignmentExpression", ex);
}
}
return fa;
}
#endregion
#region Expressions
public static Expression OnAssignmentExpressionFromCache(this DeviceFlag uf)
{
return ExpressionCache.GetOrCreateSingleExpressions($"DeviceFlag_OnAssignmentExpression_{uf.Id}", () => Expression.TokenizeSingleDynamic(null, uf.OnAssignmentExpression, 0));
}
public static void OnAssignmentExpressionInvalidateCache(this DeviceFlag uf)
{
ExpressionCache.InvalidateSingleCache($"DeviceFlag_OnAssignmentExpression_{uf.Id}");
}
public static string EvaluateOnAssignmentExpression(this DeviceFlagAssignment dfa, DiscoDataContext Database, User AddingUser, DateTime TimeStamp)
{
if (!string.IsNullOrEmpty(dfa.DeviceFlag.OnAssignmentExpression))
{
Expression compiledExpression = dfa.DeviceFlag.OnAssignmentExpressionFromCache();
IDictionary evaluatorVariables = Expression.StandardVariables(null, Database, AddingUser, TimeStamp, null, dfa.Device);
object result = compiledExpression.EvaluateFirst<object>(dfa, evaluatorVariables);
if (result == null)
return null;
else
return result.ToString();
}
return null;
}
public static Expression OnUnassignmentExpressionFromCache(this DeviceFlag df)
{
return ExpressionCache.GetOrCreateSingleExpressions($"DeviceFlag_OnUnassignmentExpression_{df.Id}", () => Expression.TokenizeSingleDynamic(null, df.OnUnassignmentExpression, 0));
}
public static void OnUnassignmentExpressionInvalidateCache(this DeviceFlag df)
{
ExpressionCache.InvalidateSingleCache($"DeviceFlag_OnUnassignmentExpression_{df.Id}");
}
public static string EvaluateOnUnassignmentExpression(this DeviceFlagAssignment dfa, DiscoDataContext Database, User RemovingUser, DateTime TimeStamp)
{
if (!string.IsNullOrEmpty(dfa.DeviceFlag.OnUnassignmentExpression))
{
Expression compiledExpression = dfa.DeviceFlag.OnUnassignmentExpressionFromCache();
IDictionary evaluatorVariables = Expression.StandardVariables(null, Database, RemovingUser, TimeStamp, null, dfa.Device);
object result = compiledExpression.EvaluateFirst<object>(dfa, evaluatorVariables);
if (result == null)
return null;
else
return result.ToString();
}
return null;
}
#endregion
}
}
@@ -0,0 +1,241 @@
using Disco.Data.Repository;
using Disco.Data.Repository.Monitor;
using Disco.Models.Repository;
using Disco.Services.Extensions;
using Disco.Services.Tasks;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Reactive.Linq;
namespace Disco.Services.Devices.DeviceFlags
{
public static class DeviceFlagService
{
private static Cache _cache;
internal static Lazy<IObservable<RepositoryMonitorEvent>> DeviceFlagAssignmentRepositoryEvents;
static DeviceFlagService()
{
// Statically defined (lazy) Assignment Repository Definition
DeviceFlagAssignmentRepositoryEvents =
new Lazy<IObservable<RepositoryMonitorEvent>>(() =>
RepositoryMonitor.StreamAfterCommit.Where(e =>
e.EntityType == typeof(DeviceFlagAssignment) &&
(e.EventType != RepositoryMonitorEventType.Modified ||
e.ModifiedProperties.Contains(nameof(DeviceFlagAssignment.RemovedDate)))
)
);
}
public static void Initialize(DiscoDataContext database)
{
_cache = new Cache(database);
// Initialize Managed Groups (if configured)
_cache.GetDeviceFlags().ForEach(uf =>
{
DeviceFlagDevicesManagedGroup.Initialize(uf);
DeviceFlagDeviceAssignedUsersManagedGroup.Initialize(uf);
});
}
public static List<DeviceFlag> GetDeviceFlags() { return _cache.GetDeviceFlags(); }
public static DeviceFlag GetDeviceFlag(int deviceFlagId) { return _cache.GetDeviceFlag(deviceFlagId); }
#region Device Flag Maintenance
public static DeviceFlag CreateDeviceFlag(DiscoDataContext database, DeviceFlag deviceFlag)
{
// Verify
if (string.IsNullOrWhiteSpace(deviceFlag.Name))
throw new ArgumentException("The Device Flag Name is required", nameof(deviceFlag));
// Name Unique
if (_cache.GetDeviceFlags().Any(f => f.Name == deviceFlag.Name))
throw new ArgumentException("Another Device Flag already exists with that name", nameof(deviceFlag));
// Clone to break reference
var flag = new DeviceFlag()
{
Name = deviceFlag.Name,
Description = deviceFlag.Description,
Icon = deviceFlag.Icon,
IconColour = deviceFlag.IconColour,
DevicesLinkedGroup = deviceFlag.DevicesLinkedGroup,
DeviceUsersLinkedGroup = deviceFlag.DeviceUsersLinkedGroup,
};
database.DeviceFlags.Add(flag);
database.SaveChanges();
_cache.AddOrUpdate(flag);
return flag;
}
public static DeviceFlag Update(DiscoDataContext database, DeviceFlag deviceFlag)
{
// Verify
if (string.IsNullOrWhiteSpace(deviceFlag.Name))
throw new ArgumentException("The Device Flag Name is required", nameof(deviceFlag));
// Name Unique
if (_cache.GetDeviceFlags().Any(f => f.Id != deviceFlag.Id && f.Name == deviceFlag.Name))
throw new ArgumentException("Another Device Flag already exists with that name", nameof(deviceFlag));
database.SaveChanges();
_cache.AddOrUpdate(deviceFlag);
DeviceFlagDevicesManagedGroup.Initialize(deviceFlag);
DeviceFlagDeviceAssignedUsersManagedGroup.Initialize(deviceFlag);
return deviceFlag;
}
public static void DeleteDeviceFlag(DiscoDataContext database, int deviceFlagId, IScheduledTaskStatus status)
{
var flag = database.DeviceFlags.Find(deviceFlagId);
// Dispose of AD Managed Groups
Interop.ActiveDirectory.ActiveDirectory.Context.ManagedGroups.Remove(DeviceFlagDeviceAssignedUsersManagedGroup.GetKey(flag));
Interop.ActiveDirectory.ActiveDirectory.Context.ManagedGroups.Remove(DeviceFlagDevicesManagedGroup.GetKey(flag));
// Delete Assignments
status.UpdateStatus(0, $"Removing '{flag.Name}' [{flag.Id}] Device Flag", "Starting");
var flagAssignments = database.DeviceFlagAssignments.Where(fa => fa.DeviceFlagId == flag.Id).ToList();
if (flagAssignments.Count > 0)
{
status.UpdateStatus(20, "Removing flag from devices");
flagAssignments.ForEach(flagAssignment => database.DeviceFlagAssignments.Remove(flagAssignment));
database.SaveChanges();
}
// Delete Flag
status.UpdateStatus(90, "Deleting Device Flag");
database.DeviceFlags.Remove(flag);
database.SaveChanges();
// Remove from Cache
_cache.Remove(deviceFlagId);
status.Finished($"Successfully Deleted Device Flag: '{flag.Name}' [{flag.Id}]");
}
#endregion
#region Bulk Assignment
public static IEnumerable<DeviceFlagAssignment> BulkAssignAddDevices(DiscoDataContext database, DeviceFlag deviceFlag, User technician, string comments, List<Device> devices, IScheduledTaskStatus status)
{
if (devices.Count > 0)
{
double progressInterval;
const int databaseChunkSize = 100;
comments = string.IsNullOrWhiteSpace(comments) ? null : comments.Trim();
var addDevices = devices.Where(d => !d.DeviceFlagAssignments.Any(a => a.DeviceFlagId == deviceFlag.Id && !a.RemovedDate.HasValue)).ToList();
progressInterval = (double)100 / addDevices.Count;
var addedDeviceAssignments = addDevices.Chunk(databaseChunkSize).SelectMany((chunk, chunkIndex) =>
{
var chunkIndexOffset = databaseChunkSize * chunkIndex;
var chunkResults = chunk.Select((device, index) =>
{
status.UpdateStatus((chunkIndexOffset + index) * progressInterval, $"Assigning Flag: {device}");
return device.OnAddDeviceFlag(database, deviceFlag, technician, comments);
}).ToList();
// Save Chunk Items to Database
database.SaveChanges();
return chunkResults;
}).Where(fa => fa != null).ToList();
status.SetFinishedMessage($"{addDevices.Count} Devices/s Added; {(devices.Count - addDevices.Count)} Devices/s Skipped");
return addedDeviceAssignments;
}
else
{
status.SetFinishedMessage("No changes found");
return Enumerable.Empty<DeviceFlagAssignment>();
}
}
public static IEnumerable<DeviceFlagAssignment> BulkAssignOverrideDevices(DiscoDataContext database, DeviceFlag deviceFlag, User technician, string comments, List<Device> devices, IScheduledTaskStatus status)
{
double progressInterval;
const int databaseChunkSize = 100;
comments = string.IsNullOrWhiteSpace(comments) ? null : comments.Trim();
status.UpdateStatus(0, "Calculating assignment changes");
var currentAssignments = database.DeviceFlagAssignments.Include(fa => fa.Device).Where(a => a.DeviceFlagId == deviceFlag.Id && !a.RemovedDate.HasValue).ToList();
var removeAssignments = currentAssignments.Where(ca => !devices.Any(d => d.SerialNumber.Equals(ca.DeviceSerialNumber, StringComparison.OrdinalIgnoreCase))).ToList();
var addAssignments = devices.Where(d => !currentAssignments.Any(ca => ca.DeviceSerialNumber.Equals(d.SerialNumber, StringComparison.OrdinalIgnoreCase))).ToList();
if (removeAssignments.Count > 0 || addAssignments.Count > 0)
{
progressInterval = (double)100 / (removeAssignments.Count + addAssignments.Count);
var removedDateTime = DateTime.Now;
// Remove Assignments
removeAssignments.Chunk(databaseChunkSize).SelectMany((chunk, chunkIndex) =>
{
var chunkIndexOffset = (chunkIndex * databaseChunkSize) + removeAssignments.Count;
var chunkResults = chunk.Select((flagAssignment, index) =>
{
status.UpdateStatus((chunkIndexOffset + index) * progressInterval, $"Removing Flag: {flagAssignment.Device}");
flagAssignment.OnRemoveUnsafe(database, technician);
return flagAssignment;
}).ToList();
// Save Chunk Items to Database
database.SaveChanges();
return chunkResults;
}).ToList();
// Add Assignments
var addedAssignments = addAssignments.Chunk(databaseChunkSize).SelectMany((chunk, chunkIndex) =>
{
var chunkIndexOffset = (chunkIndex * databaseChunkSize) + removeAssignments.Count;
var chunkResults = chunk.Select((device, index) =>
{
status.UpdateStatus((chunkIndexOffset + index) * progressInterval, $"Assigning Flag: {device}");
return device.OnAddDeviceFlag(database, deviceFlag, technician, comments);
}).ToList();
// Save Chunk Items to Database
database.SaveChanges();
return chunkResults;
}).ToList();
status.SetFinishedMessage($"{addAssignments.Count} Devices/s Added; {removeAssignments.Count} Devices/s Removed; {(devices.Count - addAssignments.Count)} Devices/s Skipped");
return addedAssignments;
}
else
{
status.SetFinishedMessage("No changes found");
return Enumerable.Empty<DeviceFlagAssignment>();
}
}
#endregion
public static string RandomUnusedIcon()
{
return UIHelpers.RandomIcon(_cache.GetDeviceFlags().Select(f => f.Icon));
}
public static string RandomUnusedThemeColour()
{
return UIHelpers.RandomThemeColour(_cache.GetDeviceFlags().Select(f => f.IconColour));
}
}
}
@@ -0,0 +1,84 @@
using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Services.Tasks;
using Quartz;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
namespace Disco.Services.Devices.DeviceFlags
{
public class DeviceFlagBulkAssignTask : ScheduledTask
{
public override string TaskName { get { return "Device Flags - Bulk Assign Devices"; } }
public override bool SingleInstanceTask { get { return false; } }
public override bool CancelInitiallySupported { get { return false; } }
public override bool LogExceptionsOnly { get { return true; } }
protected override void ExecuteTask()
{
int deviceFlagId = (int)ExecutionContext.JobDetail.JobDataMap["DeviceFlagId"];
string technicianUserId = (string)ExecutionContext.JobDetail.JobDataMap["TechnicianUserId"];
string comments = (string)ExecutionContext.JobDetail.JobDataMap["Comments"];
List<string> deviceSerialNumbers = (List<string>)ExecutionContext.JobDetail.JobDataMap["DeviceSerialNumbers"];
bool @override = (bool)ExecutionContext.JobDetail.JobDataMap["Override"];
using (DiscoDataContext Database = new DiscoDataContext())
{
// Load Flag
var flag = Database.DeviceFlags.FirstOrDefault(uf => uf.Id == deviceFlagId);
if (flag == null)
throw new Exception("Invalid Device Flag Id");
Status.UpdateStatus(0, string.Format("Bulk Assigning Devices to Device Flag: {0}", flag.Name), "Preparing to start");
// Load Technician
var technician = Database.Users.FirstOrDefault(user => user.UserId == technicianUserId);
if (technician == null)
throw new Exception("Invalid Technician User Id");
// Parse Devices
Status.UpdateStatus(10, "Loading devices from the database");
var devices = Database.Devices
.Include(d => d.DeviceFlagAssignments)
.Where(d => deviceSerialNumbers.Contains(d.SerialNumber)).ToList();
var missingDevices = deviceSerialNumbers.Where(sn => !devices.Any(u => string.Equals(sn, u.SerialNumber, StringComparison.OrdinalIgnoreCase))).ToList();
if (missingDevices.Count > 0)
{
throw new InvalidOperationException(string.Format("Bulk assignment aborted, invalid Serial Numbers: {0}", string.Join(", ", missingDevices)));
}
devices = devices.OrderBy(d => d.SerialNumber).ToList();
Status.ProgressOffset = 50;
Status.ProgressMultiplier = 0.5;
if (@override)
{
DeviceFlagService.BulkAssignOverrideDevices(Database, flag, technician, comments, devices, Status);
}
else
{
DeviceFlagService.BulkAssignAddDevices(Database, flag, technician, comments, devices, Status);
}
}
}
public static ScheduledTaskStatus ScheduleBulkAssignDevices(DeviceFlag deviceFlag, User technician, string comments, List<string> deviceSerialNumbers, bool @override)
{
JobDataMap taskData = new JobDataMap() {
{"DeviceFlagId", deviceFlag.Id },
{"TechnicianUserId", technician.UserId },
{"Comments", comments },
{"DeviceSerialNumbers", deviceSerialNumbers },
{"Override", @override }
};
var instance = new DeviceFlagBulkAssignTask();
return instance.ScheduleTask(taskData);
}
}
}
@@ -0,0 +1,34 @@
using Disco.Data.Repository;
using Disco.Services.Tasks;
using Quartz;
namespace Disco.Services.Devices.DeviceFlags
{
public class DeviceFlagDeleteTask : ScheduledTask
{
public override string TaskName { get { return "Device Flags - Delete Flag"; } }
public override bool SingleInstanceTask { get { return false; }}
public override bool CancelInitiallySupported { get { return false; } }
public override bool LogExceptionsOnly { get { return true; } }
protected override void ExecuteTask()
{
int deviceFlagId = (int)ExecutionContext.JobDetail.JobDataMap["DeviceFlagId"];
using (DiscoDataContext Database = new DiscoDataContext())
{
DeviceFlagService.DeleteDeviceFlag(Database, deviceFlagId, Status);
}
}
public static ScheduledTaskStatus ScheduleNow(int deviceFlagId)
{
var taskData = new JobDataMap() { { "DeviceFlagId", deviceFlagId } };
var instance = new DeviceFlagDeleteTask();
return instance.ScheduleTask(taskData);
}
}
}
@@ -408,7 +408,7 @@ namespace Disco.Services.Devices.Enrolment
Id = (int)EventTypeIds.SessionTaskAddedDevice, Id = (int)EventTypeIds.SessionTaskAddedDevice,
ModuleId = _ModuleId, ModuleId = _ModuleId,
Name = "Task - Added Device", Name = "Task - Added Device",
Format = "Creating Disco Device {1}", Format = "Creating Disco ICT Device {1}",
Severity = 0, Severity = 0,
UseLive = true, UseLive = true,
UsePersist = true, UsePersist = true,
@@ -419,7 +419,7 @@ namespace Disco.Services.Devices.Enrolment
Id = (int)EventTypeIds.SessionTaskUpdatingDevice, Id = (int)EventTypeIds.SessionTaskUpdatingDevice,
ModuleId = _ModuleId, ModuleId = _ModuleId,
Name = "Task - Updating Device", Name = "Task - Updating Device",
Format = "Updating Disco Device {1}", Format = "Updating Disco ICT Device {1}",
Severity = 0, Severity = 0,
UseLive = true, UseLive = true,
UsePersist = true, UsePersist = true,
@@ -0,0 +1,293 @@
using Disco.Data.Repository;
using Disco.Models.ClientServices;
using Disco.Models.Repository;
using Disco.Services.Interop.ActiveDirectory;
using PListNet;
using PListNet.Nodes;
using Renci.SshNet;
using System;
using System.IO;
using System.Linq;
using System.Text;
namespace Disco.Services.Devices.Enrolment
{
public static class MacDeviceEnrolment
{
public static MacSecureEnrolResponse SecureEnrol(DiscoDataContext Database, string Host)
{
MacEnrol trustedRequest = new MacEnrol();
string sessionId = Guid.NewGuid().ToString("B");
MacSecureEnrolResponse MacSecureEnrol;
try
{
EnrolmentLog.LogSessionStarting(sessionId, Host, EnrolmentTypes.MacSecure);
EnrolmentLog.LogSessionProgress(sessionId, 0, $"Connecting to '{Host}' as '{Database.DiscoConfiguration.Bootstrapper.MacSshUsername}'");
var sshConnectionInfo = new KeyboardInteractiveConnectionInfo(Host, Database.DiscoConfiguration.Bootstrapper.MacSshUsername);
sshConnectionInfo.AuthenticationPrompt += (sender, e) =>
{
foreach (var prompt in e.Prompts)
{
if (prompt.Request.StartsWith("Password", StringComparison.OrdinalIgnoreCase))
{
EnrolmentLog.LogSessionProgress(sessionId, 10, $"Authenticating at '{Host}' as '{Database.DiscoConfiguration.Bootstrapper.MacSshUsername}'");
prompt.Response = Database.DiscoConfiguration.Bootstrapper.MacSshPassword;
}
}
};
using (var sshClient = new SshClient(sshConnectionInfo))
{
sshClient.Connect();
try
{
EnrolmentLog.LogSessionProgress(sessionId, 30, "Retrieving System Profile Information");
var sshResult = sshClient.RunCommand("system_profiler -xml SPHardwareDataType SPNetworkDataType SPSoftwareDataType");
ArrayNode profilerData;
using (var sshResultStream = new MemoryStream())
{
using (var sshResultWriter = new StreamWriter(sshResultStream, Encoding.UTF8, 0x400, true))
{
sshResultWriter.Write(sshResult.Result);
}
sshResultStream.Position = 0;
profilerData = PList.Load(sshResultStream) as ArrayNode;
}
EnrolmentLog.LogSessionProgress(sessionId, 90, "Processing System Profile Information");
DictionaryNode profilerDataHardware = null;
ArrayNode profilerDataNetwork = null;
DictionaryNode profilerDataSoftware = null;
if (profilerData == null)
throw new InvalidOperationException("System Profiler didn't return the expected response");
foreach (var node in profilerData.OfType<DictionaryNode>())
{
var nodeItems = ((ArrayNode)node["_items"]);
PNode nodeDataType;
if (node.TryGetValue("_dataType", out nodeDataType) && nodeDataType is StringNode)
{
switch (((StringNode)nodeDataType).Value)
{
case "SPHardwareDataType":
profilerDataHardware = (DictionaryNode)nodeItems[0];
break;
case "SPNetworkDataType":
profilerDataNetwork = nodeItems;
break;
case "SPSoftwareDataType":
profilerDataSoftware = (DictionaryNode)nodeItems[0];
break;
}
}
}
if (profilerDataHardware == null || profilerDataNetwork == null || profilerDataSoftware == null)
throw new InvalidOperationException("System Profiler didn't return information for a requested data type");
trustedRequest.DeviceSerialNumber = ((StringNode)profilerDataHardware["serial_number"]).Value;
trustedRequest.DeviceUUID = ((StringNode)profilerDataHardware["platform_UUID"]).Value;
trustedRequest.DeviceComputerName = ((StringNode)profilerDataSoftware["local_host_name"]).Value;
var profilerDataNetworkEthernet = profilerDataNetwork.OfType<DictionaryNode>().FirstOrDefault(e => ((StringNode)e["_name"]).Value == "Ethernet");
if (profilerDataNetworkEthernet != null)
{
trustedRequest.DeviceLanMacAddress = ((StringNode)((DictionaryNode)profilerDataNetworkEthernet["Ethernet"])["MAC Address"]).Value;
}
var profilerDataNetworkWiFi = profilerDataNetwork.OfType<DictionaryNode>().FirstOrDefault(e => ((StringNode)e["_name"]).Value == "Wi-Fi");
if (profilerDataNetworkWiFi != null)
{
trustedRequest.DeviceWlanMacAddress = ((StringNode)((DictionaryNode)profilerDataNetworkWiFi["Ethernet"])["MAC Address"]).Value;
}
trustedRequest.DeviceManufacturer = "Apple Inc.";
trustedRequest.DeviceModel = ((StringNode)profilerDataHardware["machine_model"]).Value;
trustedRequest.DeviceModelType = ParseMacModelType(((StringNode)profilerDataHardware["machine_name"]).Value);
EnrolmentLog.LogSessionProgress(sessionId, 99, "Disconnecting");
sshClient.Disconnect();
}
catch (Exception)
{
throw;
}
finally
{
if (sshClient != null)
{
bool connected = sshClient.IsConnected;
if (connected)
{
sshClient.Disconnect();
}
}
}
}
EnrolmentLog.LogSessionProgress(sessionId, 100, "Disconnected, Starting Disco ICT Enrolment");
MacSecureEnrolResponse response = MacSecureEnrolResponse.FromMacEnrolResponse(Enrol(Database, trustedRequest, true, sessionId));
EnrolmentLog.LogSessionFinished(sessionId);
MacSecureEnrol = response;
}
catch (System.Exception ex)
{
EnrolmentLog.LogSessionError(sessionId, ex);
throw ex;
}
return MacSecureEnrol;
}
#region "Mac Enrol Helpers"
private static string ParseMacModelType(string ModelName)
{
string ParseMacModelType;
if (!string.IsNullOrWhiteSpace(ModelName))
{
string mn = ModelName.ToLower();
if (mn.Contains("imac") || mn.Contains("mini"))
{
ParseMacModelType = "Desktop";
return ParseMacModelType;
}
if (mn.Contains("macbook"))
{
ParseMacModelType = "Mobile";
return ParseMacModelType;
}
if (mn.Contains("xserve"))
{
ParseMacModelType = "Server";
return ParseMacModelType;
}
}
ParseMacModelType = "Unknown";
return ParseMacModelType;
}
#endregion
public static MacEnrolResponse Enrol(DiscoDataContext Database, MacEnrol Request, bool Trusted, string OpenSessionId = null)
{
string sessionId;
if (OpenSessionId == null)
{
sessionId = Guid.NewGuid().ToString("B");
EnrolmentLog.LogSessionStarting(sessionId, Request.DeviceSerialNumber, EnrolmentTypes.Mac);
}
else
{
sessionId = OpenSessionId;
}
EnrolmentLog.LogSessionDeviceInfo(sessionId, Request);
MacEnrolResponse response = new MacEnrolResponse();
try
{
if (Request.DeviceSerialNumber.Contains("/") || Request.DeviceSerialNumber.Contains(@"\"))
throw new EnrolmentSafeException(@"The serial number cannot contain '/' or '\' characters.");
EnrolmentLog.LogSessionProgress(sessionId, 10, "Querying Database");
Device RepoDevice = Database.Devices.Include("AssignedUser").Include("DeviceProfile").Include("DeviceProfile").Where(d => d.SerialNumber == Request.DeviceSerialNumber).FirstOrDefault();
if (!Trusted)
{
if (RepoDevice == null)
throw new EnrolmentSafeException(string.Format("Unknown Device Serial Number (SN: '{0}')", Request.DeviceSerialNumber));
if (!RepoDevice.AllowUnauthenticatedEnrol)
throw new EnrolmentSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.DeviceSerialNumber));
}
if (RepoDevice == null)
{
EnrolmentLog.LogSessionProgress(sessionId, 50, "New Device, Building Disco Instance");
EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.DeviceSerialNumber);
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer, Request.DeviceModel, Request.DeviceModelType);
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 = new Device
{
SerialNumber = Request.DeviceSerialNumber,
DeviceDomainId = Request.DeviceComputerName,
DeviceProfile = deviceProfile,
DeviceModel = deviceModel,
AllowUnauthenticatedEnrol = false,
CreatedDate = DateTime.Now,
EnrolledDate = DateTime.Now
};
Database.Devices.Add(RepoDevice);
}
else
{
EnrolmentLog.LogSessionProgress(sessionId, 50, "Existing Device, Updating Disco Instance");
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer, Request.DeviceModel, Request.DeviceModelType);
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;
RepoDevice.DeviceDomainId = Request.DeviceComputerName;
if (!RepoDevice.EnrolledDate.HasValue)
{
RepoDevice.EnrolledDate = DateTime.Now;
}
}
RepoDevice.LastEnrolDate = DateTime.Now;
RepoDevice.AllowUnauthenticatedEnrol = false;
// Removed 2012-06-14 G# - Properties moved to DeviceProfile model & DB Migrated in DBv3.
//DeviceProfileConfiguration RepoDeviceProfileContext = RepoDevice.DeviceProfile.Configuration(Context);
EnrolmentLog.LogSessionProgress(sessionId, 90, "Building Response");
//if (RepoDeviceProfileContext.DistributionType == DeviceProfileConfiguration.DeviceProfileDistributionTypes.OneToOne && RepoDevice.AssignedUser != null)
if (RepoDevice.DeviceProfile.DistributionType == DeviceProfile.DistributionTypes.OneToOne && RepoDevice.AssignedUser != null)
{
ADUserAccount AssignedUserInfo = ActiveDirectory.RetrieveADUserAccount(RepoDevice.AssignedUser.UserId);
EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.SamAccountName, AssignedUserInfo.Domain.NetBiosName, AssignedUserInfo.SecurityIdentifier.ToString());
response.DeviceAssignedUserUsername = AssignedUserInfo.SamAccountName;
response.DeviceAssignedUserDomain = AssignedUserInfo.Domain.NetBiosName;
response.DeviceAssignedUserName = AssignedUserInfo.DisplayName;
response.DeviceAssignedUserSID = AssignedUserInfo.SecurityIdentifier.ToString();
}
response.DeviceComputerName = RepoDevice.DeviceDomainId;
EnrolmentLog.LogSessionProgress(sessionId, 100, "Completed Successfully");
}
catch (EnrolmentSafeException ex)
{
EnrolmentLog.LogSessionError(sessionId, ex);
return new MacEnrolResponse { ErrorMessage = ex.Message };
}
catch (Exception ex2)
{
EnrolmentLog.LogSessionError(sessionId, ex2);
throw ex2;
}
finally
{
if (OpenSessionId == null)
EnrolmentLog.LogSessionFinished(sessionId);
}
return response;
}
}
}
@@ -4,295 +4,14 @@ using Disco.Models.Repository;
using Disco.Services.Authorization; using Disco.Services.Authorization;
using Disco.Services.Interop.ActiveDirectory; using Disco.Services.Interop.ActiveDirectory;
using Disco.Services.Users; using Disco.Services.Users;
using PListNet;
using PListNet.Nodes;
using Renci.SshNet;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Text;
namespace Disco.Services.Devices.Enrolment namespace Disco.Services.Devices.Enrolment
{ {
public static class DeviceEnrolment public static class WindowsDeviceEnrolment
{ {
public static MacSecureEnrolResponse MacSecureEnrol(DiscoDataContext Database, string Host)
{
MacEnrol trustedRequest = new MacEnrol();
string sessionId = Guid.NewGuid().ToString("B");
MacSecureEnrolResponse MacSecureEnrol;
try
{
EnrolmentLog.LogSessionStarting(sessionId, Host, EnrolmentTypes.MacSecure);
EnrolmentLog.LogSessionProgress(sessionId, 0, $"Connecting to '{Host}' as '{Database.DiscoConfiguration.Bootstrapper.MacSshUsername}'");
var sshConnectionInfo = new KeyboardInteractiveConnectionInfo(Host, Database.DiscoConfiguration.Bootstrapper.MacSshUsername);
sshConnectionInfo.AuthenticationPrompt += (sender, e) =>
{
foreach (var prompt in e.Prompts)
{
if (prompt.Request.StartsWith("Password", StringComparison.OrdinalIgnoreCase))
{
EnrolmentLog.LogSessionProgress(sessionId, 10, $"Authenticating at '{Host}' as '{Database.DiscoConfiguration.Bootstrapper.MacSshUsername}'");
prompt.Response = Database.DiscoConfiguration.Bootstrapper.MacSshPassword;
}
}
};
using (var sshClient = new SshClient(sshConnectionInfo))
{
sshClient.Connect();
try
{
EnrolmentLog.LogSessionProgress(sessionId, 30, "Retrieving System Profile Information");
var sshResult = sshClient.RunCommand("system_profiler -xml SPHardwareDataType SPNetworkDataType SPSoftwareDataType");
ArrayNode profilerData;
using (var sshResultStream = new MemoryStream())
{
using (var sshResultWriter = new StreamWriter(sshResultStream, Encoding.UTF8, 0x400, true))
{
sshResultWriter.Write(sshResult.Result);
}
sshResultStream.Position = 0;
profilerData = PList.Load(sshResultStream) as ArrayNode;
}
EnrolmentLog.LogSessionProgress(sessionId, 90, "Processing System Profile Information");
DictionaryNode profilerDataHardware = null;
ArrayNode profilerDataNetwork = null;
DictionaryNode profilerDataSoftware = null;
if (profilerData == null)
throw new InvalidOperationException("System Profiler didn't return the expected response");
foreach (var node in profilerData.OfType<DictionaryNode>())
{
var nodeItems = ((ArrayNode)node["_items"]);
PNode nodeDataType;
if (node.TryGetValue("_dataType", out nodeDataType) && nodeDataType is StringNode)
{
switch (((StringNode)nodeDataType).Value)
{
case "SPHardwareDataType":
profilerDataHardware = (DictionaryNode)nodeItems[0];
break;
case "SPNetworkDataType":
profilerDataNetwork = nodeItems;
break;
case "SPSoftwareDataType":
profilerDataSoftware = (DictionaryNode)nodeItems[0];
break;
}
}
}
if (profilerDataHardware == null || profilerDataNetwork == null || profilerDataSoftware == null)
throw new InvalidOperationException("System Profiler didn't return information for a requested data type");
trustedRequest.DeviceSerialNumber = ((StringNode)profilerDataHardware["serial_number"]).Value;
trustedRequest.DeviceUUID = ((StringNode)profilerDataHardware["platform_UUID"]).Value;
trustedRequest.DeviceComputerName = ((StringNode)profilerDataSoftware["local_host_name"]).Value;
var profilerDataNetworkEthernet = profilerDataNetwork.OfType<DictionaryNode>().FirstOrDefault(e => ((StringNode)e["_name"]).Value == "Ethernet");
if (profilerDataNetworkEthernet != null)
{
trustedRequest.DeviceLanMacAddress = ((StringNode)((DictionaryNode)profilerDataNetworkEthernet["Ethernet"])["MAC Address"]).Value;
}
var profilerDataNetworkWiFi = profilerDataNetwork.OfType<DictionaryNode>().FirstOrDefault(e => ((StringNode)e["_name"]).Value == "Wi-Fi");
if (profilerDataNetworkWiFi != null)
{
trustedRequest.DeviceWlanMacAddress = ((StringNode)((DictionaryNode)profilerDataNetworkWiFi["Ethernet"])["MAC Address"]).Value;
}
trustedRequest.DeviceManufacturer = "Apple Inc.";
trustedRequest.DeviceModel = ((StringNode)profilerDataHardware["machine_model"]).Value;
trustedRequest.DeviceModelType = ParseMacModelType(((StringNode)profilerDataHardware["machine_name"]).Value);
EnrolmentLog.LogSessionProgress(sessionId, 99, "Disconnecting");
sshClient.Disconnect();
}
catch (Exception)
{
throw;
}
finally
{
if (sshClient != null)
{
bool connected = sshClient.IsConnected;
if (connected)
{
sshClient.Disconnect();
}
}
}
}
EnrolmentLog.LogSessionProgress(sessionId, 100, "Disconnected, Starting Disco Enrolment");
MacSecureEnrolResponse response = MacSecureEnrolResponse.FromMacEnrolResponse(MacEnrol(Database, trustedRequest, true, sessionId));
EnrolmentLog.LogSessionFinished(sessionId);
MacSecureEnrol = response;
}
catch (System.Exception ex)
{
EnrolmentLog.LogSessionError(sessionId, ex);
throw ex;
}
return MacSecureEnrol;
}
#region "Mac Enrol Helpers"
private static string ParseMacModelType(string ModelName)
{
string ParseMacModelType;
if (!string.IsNullOrWhiteSpace(ModelName))
{
string mn = ModelName.ToLower();
if (mn.Contains("imac") || mn.Contains("mini"))
{
ParseMacModelType = "Desktop";
return ParseMacModelType;
}
if (mn.Contains("macbook"))
{
ParseMacModelType = "Mobile";
return ParseMacModelType;
}
if (mn.Contains("xserve"))
{
ParseMacModelType = "Server";
return ParseMacModelType;
}
}
ParseMacModelType = "Unknown";
return ParseMacModelType;
}
#endregion
public static MacEnrolResponse MacEnrol(DiscoDataContext Database, MacEnrol Request, bool Trusted, string OpenSessionId = null)
{
string sessionId;
if (OpenSessionId == null)
{
sessionId = Guid.NewGuid().ToString("B");
EnrolmentLog.LogSessionStarting(sessionId, Request.DeviceSerialNumber, EnrolmentTypes.Mac);
}
else
{
sessionId = OpenSessionId;
}
EnrolmentLog.LogSessionDeviceInfo(sessionId, Request);
MacEnrolResponse response = new MacEnrolResponse();
try
{
if (Request.DeviceSerialNumber.Contains("/") || Request.DeviceSerialNumber.Contains(@"\"))
throw new EnrolmentSafeException(@"The serial number cannot contain '/' or '\' characters.");
EnrolmentLog.LogSessionProgress(sessionId, 10, "Querying Database");
Device RepoDevice = Database.Devices.Include("AssignedUser").Include("DeviceProfile").Include("DeviceProfile").Where(d => d.SerialNumber == Request.DeviceSerialNumber).FirstOrDefault();
if (!Trusted)
{
if (RepoDevice == null)
throw new EnrolmentSafeException(string.Format("Unknown Device Serial Number (SN: '{0}')", Request.DeviceSerialNumber));
if (!RepoDevice.AllowUnauthenticatedEnrol)
throw new EnrolmentSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.DeviceSerialNumber));
}
if (RepoDevice == null)
{
EnrolmentLog.LogSessionProgress(sessionId, 50, "New Device, Building Disco Instance");
EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.DeviceSerialNumber);
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer, Request.DeviceModel, Request.DeviceModelType);
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 = new Device
{
SerialNumber = Request.DeviceSerialNumber,
DeviceDomainId = Request.DeviceComputerName,
DeviceProfile = deviceProfile,
DeviceModel = deviceModel,
AllowUnauthenticatedEnrol = false,
CreatedDate = DateTime.Now,
EnrolledDate = DateTime.Now
};
Database.Devices.Add(RepoDevice);
}
else
{
EnrolmentLog.LogSessionProgress(sessionId, 50, "Existing Device, Updating Disco Instance");
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer, Request.DeviceModel, Request.DeviceModelType);
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;
RepoDevice.DeviceDomainId = Request.DeviceComputerName;
if (!RepoDevice.EnrolledDate.HasValue)
{
RepoDevice.EnrolledDate = DateTime.Now;
}
}
RepoDevice.LastEnrolDate = DateTime.Now;
RepoDevice.AllowUnauthenticatedEnrol = false;
// Removed 2012-06-14 G# - Properties moved to DeviceProfile model & DB Migrated in DBv3.
//DeviceProfileConfiguration RepoDeviceProfileContext = RepoDevice.DeviceProfile.Configuration(Context);
EnrolmentLog.LogSessionProgress(sessionId, 90, "Building Response");
//if (RepoDeviceProfileContext.DistributionType == DeviceProfileConfiguration.DeviceProfileDistributionTypes.OneToOne && RepoDevice.AssignedUser != null)
if (RepoDevice.DeviceProfile.DistributionType == DeviceProfile.DistributionTypes.OneToOne && RepoDevice.AssignedUser != null)
{
ADUserAccount AssignedUserInfo = ActiveDirectory.RetrieveADUserAccount(RepoDevice.AssignedUser.UserId);
EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.SamAccountName, AssignedUserInfo.Domain.NetBiosName, AssignedUserInfo.SecurityIdentifier.ToString());
response.DeviceAssignedUserUsername = AssignedUserInfo.SamAccountName;
response.DeviceAssignedUserDomain = AssignedUserInfo.Domain.NetBiosName;
response.DeviceAssignedUserName = AssignedUserInfo.DisplayName;
response.DeviceAssignedUserSID = AssignedUserInfo.SecurityIdentifier.ToString();
}
response.DeviceComputerName = RepoDevice.DeviceDomainId;
EnrolmentLog.LogSessionProgress(sessionId, 100, "Completed Successfully");
}
catch (EnrolmentSafeException ex)
{
EnrolmentLog.LogSessionError(sessionId, ex);
return new MacEnrolResponse { ErrorMessage = ex.Message };
}
catch (Exception ex2)
{
EnrolmentLog.LogSessionError(sessionId, ex2);
throw ex2;
}
finally
{
if (OpenSessionId == null)
EnrolmentLog.LogSessionFinished(sessionId);
}
return response;
}
public static EnrolResponse Enrol(DiscoDataContext Database, string Username, Enrol Request) public static EnrolResponse Enrol(DiscoDataContext Database, string Username, Enrol Request)
{ {
ADMachineAccount adMachineAccount = null; ADMachineAccount adMachineAccount = null;
@@ -330,7 +49,7 @@ namespace Disco.Services.Devices.Enrolment
EnrolmentLog.LogSessionProgress(sessionId, 13, "Loading Device Data"); EnrolmentLog.LogSessionProgress(sessionId, 13, "Loading Device Data");
Device RepoDevice = Database.Devices.Include("AssignedUser").Include("DeviceModel").Include("DeviceProfile").Where(d => d.SerialNumber == Request.SerialNumber).FirstOrDefault(); Device RepoDevice = Database.Devices.Include("AssignedUser").Include("DeviceModel").Include("DeviceProfile").Where(d => d.SerialNumber == Request.SerialNumber).FirstOrDefault();
EnrolmentLog.LogSessionProgress(sessionId, 15, "Discovering User/Device Disco Permissions"); EnrolmentLog.LogSessionProgress(sessionId, 15, "Discovering User/Device Disco ICT Permissions");
if (isAuthenticated) if (isAuthenticated)
{ {
if (!authenticatedToken.Has(Claims.Device.Actions.EnrolDevices)) if (!authenticatedToken.Has(Claims.Device.Actions.EnrolDevices))
@@ -392,7 +111,6 @@ namespace Disco.Services.Devices.Enrolment
EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.SerialNumber); EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.SerialNumber);
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId); DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.Hardware.Manufacturer, Request.Hardware.Model, Request.Hardware.ModelType); var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.Hardware.Manufacturer, Request.Hardware.Model, Request.Hardware.ModelType);
DeviceModel deviceModel = deviceModelResult.Item1; DeviceModel deviceModel = deviceModelResult.Item1;
if (deviceModelResult.Item2) if (deviceModelResult.Item2)
@@ -400,13 +118,10 @@ namespace Disco.Services.Devices.Enrolment
else else
EnrolmentLog.LogSessionDevice(sessionId, Request.SerialNumber, deviceModel.Id); EnrolmentLog.LogSessionDevice(sessionId, Request.SerialNumber, deviceModel.Id);
if (domain == null)
domain = ActiveDirectory.Context.GetDomainByName(Request.DNSDomainName);
RepoDevice = new Device RepoDevice = new Device
{ {
SerialNumber = Request.SerialNumber, SerialNumber = Request.SerialNumber,
DeviceDomainId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.ComputerName), DeviceDomainId = domain == null ? Request.ComputerName : $@"{domain.NetBiosName}\{Request.ComputerName}",
DeviceProfile = deviceProfile, DeviceProfile = deviceProfile,
DeviceModel = deviceModel, DeviceModel = deviceModel,
AllowUnauthenticatedEnrol = false, AllowUnauthenticatedEnrol = false,
@@ -438,6 +153,10 @@ namespace Disco.Services.Devices.Enrolment
RepoDevice.DeviceModel = deviceModel; RepoDevice.DeviceModel = deviceModel;
var deviceDomainId = domain == null ? Request.ComputerName : $@"{domain.NetBiosName}\{Request.ComputerName}";
if (!string.Equals(RepoDevice.DeviceDomainId, deviceDomainId, StringComparison.Ordinal))
RepoDevice.DeviceDomainId = deviceDomainId;
var lanMacAddresses = string.Join("; ", Request.Hardware.NetworkAdapters?.Where(na => !na.IsWlanAdapter).Select(na => na.MACAddress)); var lanMacAddresses = string.Join("; ", Request.Hardware.NetworkAdapters?.Where(na => !na.IsWlanAdapter).Select(na => na.MACAddress));
var wlanMacAddresses = string.Join("; ", Request.Hardware.NetworkAdapters?.Where(na => na.IsWlanAdapter).Select(na => na.MACAddress)); var wlanMacAddresses = string.Join("; ", Request.Hardware.NetworkAdapters?.Where(na => na.IsWlanAdapter).Select(na => na.MACAddress));
if (!string.IsNullOrEmpty(lanMacAddresses)) if (!string.IsNullOrEmpty(lanMacAddresses))
@@ -481,6 +200,11 @@ namespace Disco.Services.Devices.Enrolment
if (string.IsNullOrEmpty(RepoDevice.DeviceDomainId) || RepoDevice.DeviceProfile.EnforceComputerNameConvention) if (string.IsNullOrEmpty(RepoDevice.DeviceDomainId) || RepoDevice.DeviceProfile.EnforceComputerNameConvention)
RepoDevice.DeviceDomainId = RepoDevice.ComputerNameRender(Database, domain); RepoDevice.DeviceDomainId = RepoDevice.ComputerNameRender(Database, domain);
else if (!ActiveDirectory.IsValidDomainAccountId(RepoDevice.DeviceDomainId))
if (RepoDevice.DeviceProfile.EnforceComputerNameConvention)
RepoDevice.DeviceDomainId = RepoDevice.ComputerNameRender(Database, domain);
else
RepoDevice.DeviceDomainId = $@"{domain.NetBiosName}\{Request.ComputerName}";
string offlineProvisionDiagnosicInfo; string offlineProvisionDiagnosicInfo;
EnrolmentLog.LogSessionTaskProvisioningADAccount(sessionId, RepoDevice.SerialNumber, RepoDevice.DeviceDomainId); EnrolmentLog.LogSessionTaskProvisioningADAccount(sessionId, RepoDevice.SerialNumber, RepoDevice.DeviceDomainId);
@@ -497,12 +221,8 @@ namespace Disco.Services.Devices.Enrolment
response.ComputerName = adMachineAccount.Name; response.ComputerName = adMachineAccount.Name;
response.DomainName = adMachineAccount.Domain.NetBiosName; response.DomainName = adMachineAccount.Domain.NetBiosName;
} }
else if (ActiveDirectory.IsValidDomainAccountId(RepoDevice.DeviceDomainId)) else if (ActiveDirectory.IsValidDomainAccountId(RepoDevice.DeviceDomainId, out var accountUsername, out var accountDomain))
{ {
string accountUsername;
ADDomain accountDomain;
ActiveDirectory.ParseDomainAccountId(RepoDevice.DeviceDomainId, out accountUsername, out accountDomain);
response.DomainName = accountDomain == null ? null : accountDomain.NetBiosName; response.DomainName = accountDomain == null ? null : accountDomain.NetBiosName;
response.ComputerName = accountUsername; response.ComputerName = accountUsername;
} }
@@ -579,11 +299,18 @@ namespace Disco.Services.Devices.Enrolment
if (adMachineAccount != null && !adMachineAccount.IsCriticalSystemObject) if (adMachineAccount != null && !adMachineAccount.IsCriticalSystemObject)
{ {
EnrolmentLog.LogSessionProgress(sessionId, 75, "Updating Active Directory Computer Account Properties"); EnrolmentLog.LogSessionProgress(sessionId, 75, "Updating Active Directory Computer Account Properties");
// Use non-Wlan Adapter with fastest speed try
var macAddress = Request.Hardware?.NetworkAdapters?.Where(na => !na.IsWlanAdapter).OrderByDescending(na => na.Speed).Select(na => na.MACAddress).FirstOrDefault(); {
adMachineAccount.UpdateNetbootGUID(Request.Hardware.UUID, macAddress); // Use non-Wlan Adapter with fastest speed
if (RepoDevice.AssignedUser != null) var macAddress = Request.Hardware?.NetworkAdapters?.Where(na => !na.IsWlanAdapter).OrderByDescending(na => na.Speed).Select(na => na.MACAddress).FirstOrDefault();
adMachineAccount.SetDescription(RepoDevice); adMachineAccount.UpdateNetbootGUID(Request.Hardware.UUID, macAddress);
if (RepoDevice.AssignedUser != null)
adMachineAccount.SetDescription(RepoDevice);
}
catch (Exception ex)
{
EnrolmentLog.LogSessionWarning(sessionId, $"Unable to update AD Machine Account attributes: {ex.Message}");
}
} }
if (RepoDevice.DeviceProfile.DistributionType == DeviceProfile.DistributionTypes.OneToOne) if (RepoDevice.DeviceProfile.DistributionType == DeviceProfile.DistributionTypes.OneToOne)
{ {
+169 -244
View File
@@ -1,7 +1,8 @@
using ClosedXML.Excel; using Disco.Data.Repository;
using Disco.Data.Repository; using Disco.Models.Exporting;
using Disco.Models.Repository; using Disco.Models.Repository;
using Disco.Models.Services.Devices.Exporting; using Disco.Models.Services.Devices.Exporting;
using Disco.Models.Services.Exporting;
using Disco.Services.Plugins.Features.DetailsProvider; using Disco.Services.Plugins.Features.DetailsProvider;
using Disco.Services.Tasks; using Disco.Services.Tasks;
using Disco.Services.Users; using Disco.Services.Users;
@@ -12,25 +13,57 @@ using System.Data;
using System.Data.Entity; using System.Data.Entity;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
namespace Disco.Services.Devices.Exporting namespace Disco.Services.Devices.Exporting
{ {
using Metadata = ExportFieldMetadata<DeviceExportRecord>;
public static class DeviceExport public static class DeviceExport
{ {
public static DeviceExportResult GenerateExport(DiscoDataContext Database, Func<IQueryable<Device>, IQueryable<Device>> Filter, DeviceExportOptions Options, IScheduledTaskStatus TaskStatus) public static ExportResult GenerateExport(DiscoDataContext Database, Func<IQueryable<Device>, IQueryable<Device>> Filter, DeviceExportOptions Options, IScheduledTaskStatus TaskStatus)
{ {
var deviceQuery = Database.Devices
TaskStatus.UpdateStatus(15, "Extracting records from the database");
var devices = Database.Devices
.Include(d => d.AssignedUser.UserDetails) .Include(d => d.AssignedUser.UserDetails)
.Include(d => d.DeviceDetails); .Include(d => d.DeviceDetails);
if (Filter != null) if (Filter != null)
devices = Filter(devices); deviceQuery = Filter(deviceQuery);
// Update Users
if (Options.AssignedUserDisplayName ||
Options.AssignedUserSurname ||
Options.AssignedUserGivenName ||
Options.AssignedUserPhoneNumber ||
Options.AssignedUserEmailAddress)
{
TaskStatus.UpdateStatus(5, "Refreshing user details from Active Directory");
var userIds = deviceQuery.Where(d => d.AssignedUserId != null).Select(d => d.AssignedUserId).Distinct().ToList();
foreach (var userId in userIds)
{
try
{
UserService.GetUser(userId, Database);
}
catch (Exception) { } // Ignore Errors
}
}
// Update Last Network Logon Date
if (Options.DeviceLastNetworkLogon)
{
TaskStatus.UpdateStatus(15, "Refreshing device last network logon dates from Active Directory");
try
{
Interop.ActiveDirectory.ADNetworkLogonDatesUpdateTask.UpdateLastNetworkLogonDates(Database, ScheduledTaskMockStatus.Create("UpdateLastNetworkLogonDates"));
Database.SaveChanges();
}
catch (Exception) { } // Ignore Errors
}
TaskStatus.UpdateStatus(25, "Extracting records from the database");
var records = BuildRecords(deviceQuery).ToList();
var records = BuildRecords(devices).ToList();
// materialize device details // materialize device details
records.ForEach(r => records.ForEach(r =>
{ {
@@ -65,75 +98,18 @@ namespace Disco.Services.Devices.Exporting
} }
}); });
TaskStatus.UpdateStatus(40, "Building metadata and database query"); TaskStatus.UpdateStatus(70, "Building metadata");
var metadata = Options.BuildMetadata(records); var metadata = Options.BuildMetadata(records);
if (metadata.Count == 0) if (metadata.Count == 0)
throw new ArgumentException("At least one export field must be specified", "Options"); throw new ArgumentException("At least one export field must be specified", "Options");
// Update Users TaskStatus.UpdateStatus(80, $"Formatting {records.Count} records for export");
if (Options.AssignedUserDisplayName ||
Options.AssignedUserSurname ||
Options.AssignedUserGivenName ||
Options.AssignedUserPhoneNumber ||
Options.AssignedUserEmailAddress)
{
TaskStatus.UpdateStatus(45, "Updating Assigned User details");
var users = records.Where(d => d.AssignedUser != null).Select(d => d.AssignedUser).Distinct().ToList();
users.Select((user, index) => return ExportHelpers.WriteExport(Options, TaskStatus, metadata, records);
{
TaskStatus.UpdateStatus(20 + (((double)20 / users.Count) * index), string.Format("Updating Assigned User details: {0}", user.UserId));
try
{
return UserService.GetUser(user.UserId, Database);
}
catch (Exception) { return null; } // Ignore Errors
}).ToList();
}
// Update Last Network Logon Date
if (Options.DeviceLastNetworkLogon)
{
TaskStatus.UpdateStatus(50, "Updating device last network logon dates");
try
{
TaskStatus.IgnoreCurrentProcessChanges = true;
TaskStatus.ProgressMultiplier = (double)30 / 100;
TaskStatus.ProgressOffset = 50;
Interop.ActiveDirectory.ADNetworkLogonDatesUpdateTask.UpdateLastNetworkLogonDates(Database, TaskStatus);
Database.SaveChanges();
TaskStatus.IgnoreCurrentProcessChanges = false;
TaskStatus.ProgressMultiplier = 1;
TaskStatus.ProgressOffset = 0;
}
catch (Exception) { } // Ignore Errors
}
var stream = new MemoryStream();
TaskStatus.UpdateStatus(80, string.Format("Formatting {0} records for export", records.Count));
if (Options.ExcelFormat)
{
WriteXlsx(stream, metadata, records);
}
else
{
WriteCSV(stream, metadata, records);
}
stream.Position = 0;
return new DeviceExportResult()
{
Result = stream,
RecordCount = records.Count
};
} }
public static DeviceExportResult GenerateExport(DiscoDataContext Database, DeviceExportOptions Options, IScheduledTaskStatus TaskStatus) public static ExportResult GenerateExport(DiscoDataContext Database, DeviceExportOptions Options, IScheduledTaskStatus TaskStatus)
{ {
switch (Options.ExportType) switch (Options.ExportType)
{ {
@@ -152,62 +128,11 @@ namespace Disco.Services.Devices.Exporting
throw new ArgumentException(string.Format("Unknown Device Export Type", Options.ExportType.ToString()), "Options"); throw new ArgumentException(string.Format("Unknown Device Export Type", Options.ExportType.ToString()), "Options");
} }
} }
public static DeviceExportResult GenerateExport(DiscoDataContext Database, DeviceExportOptions Options) public static ExportResult GenerateExport(DiscoDataContext Database, DeviceExportOptions Options)
{ {
return GenerateExport(Database, Options, ScheduledTaskMockStatus.Create("Device Export")); return GenerateExport(Database, Options, ScheduledTaskMockStatus.Create("Device Export"));
} }
private static void WriteCSV(Stream OutputStream, List<DeviceExportFieldMetadata> Metadata, List<DeviceExportRecord> Records)
{
using (StreamWriter writer = new StreamWriter(OutputStream, Encoding.Default, 0x400, true))
{
// Header
writer.Write('"');
writer.Write(string.Join("\",\"", Metadata.Select(m => m.ColumnName)));
writer.Write('"');
// Records
foreach (var record in Records)
{
writer.WriteLine();
for (int i = 0; i < Metadata.Count; i++)
{
if (i != 0)
{
writer.Write(',');
}
var value = Metadata[i].Accessor(record);
writer.Write(Metadata[i].CsvEncoder(value));
}
}
}
}
private static void WriteXlsx(Stream OutputStream, List<DeviceExportFieldMetadata> Metadata, List<DeviceExportRecord> Records)
{
// Create DataTable
var dataTable = new DataTable();
foreach (var field in Metadata)
{
dataTable.Columns.Add(field.ColumnName, field.ValueType);
}
foreach (var record in Records)
{
dataTable.Rows.Add(Metadata.Select(m => m.Accessor(record)).ToArray());
}
using (var xlWorkbook = new XLWorkbook())
{
var sheet = xlWorkbook.AddWorksheet("DeviceExport");
var table = sheet.Cell(1, 1).InsertTable(dataTable, "Devices");
table.Theme = XLTableTheme.TableStyleMedium2;
table.Columns().ForEach(c => c.WorksheetColumn().AdjustToContents(2, 15, 30));
xlWorkbook.SaveAs(OutputStream);
}
}
private static IEnumerable<DeviceExportRecord> BuildRecords(IQueryable<Device> Devices) private static IEnumerable<DeviceExportRecord> BuildRecords(IQueryable<Device> Devices)
{ {
return Devices.Select(d => new DeviceExportRecord() return Devices.Select(d => new DeviceExportRecord()
@@ -249,7 +174,7 @@ namespace Disco.Services.Devices.Exporting
}); });
} }
private static List<DeviceExportFieldMetadata> BuildMetadata(this DeviceExportOptions options, List<DeviceExportRecord> records) private static List<Metadata> BuildMetadata(this DeviceExportOptions options, List<DeviceExportRecord> records)
{ {
var processorMaxCount = Math.Max(1, records.Max(r => r.DeviceDetailProcessors?.Count ?? 0)); var processorMaxCount = Math.Max(1, records.Max(r => r.DeviceDetailProcessors?.Count ?? 0));
var memoryMaxCount = Math.Max(1, records.Max(r => r.DeviceDetailPhysicalMemory?.Count ?? 0)); var memoryMaxCount = Math.Max(1, records.Max(r => r.DeviceDetailPhysicalMemory?.Count ?? 0));
@@ -263,7 +188,7 @@ namespace Disco.Services.Devices.Exporting
if (options.AssignedUserDetailCustom) if (options.AssignedUserDetailCustom)
assignedUserDetailCustomKeys = records.Where(r => r.AssignedUserCustomDetails != null).SelectMany(r => r.AssignedUserCustomDetails.Keys).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); assignedUserDetailCustomKeys = records.Where(r => r.AssignedUserCustomDetails != null).SelectMany(r => r.AssignedUserCustomDetails.Keys).Distinct(StringComparer.OrdinalIgnoreCase).ToList();
var allAssessors = BuildRecordAccessors(processorMaxCount, memoryMaxCount, diskDriveMaxCount, lanAdapterMaxCount, wlanAdapterMaxCount, certificateMaxCount, batteriesMaxCount, assignedUserDetailCustomKeys); var allAccessors = BuildRecordAccessors(processorMaxCount, memoryMaxCount, diskDriveMaxCount, lanAdapterMaxCount, wlanAdapterMaxCount, certificateMaxCount, batteriesMaxCount, assignedUserDetailCustomKeys);
return typeof(DeviceExportOptions).GetProperties() return typeof(DeviceExportOptions).GetProperties()
.Where(p => p.PropertyType == typeof(bool)) .Where(p => p.PropertyType == typeof(bool))
@@ -275,7 +200,7 @@ namespace Disco.Services.Devices.Exporting
.Where(p => p.details != null && (bool)p.property.GetValue(options)) .Where(p => p.details != null && (bool)p.property.GetValue(options))
.SelectMany(p => .SelectMany(p =>
{ {
var fieldMetadata = allAssessors[p.property.Name]; var fieldMetadata = allAccessors[p.property.Name];
fieldMetadata.ForEach(f => fieldMetadata.ForEach(f =>
{ {
if (f.ColumnName == null) if (f.ColumnName == null)
@@ -285,7 +210,7 @@ namespace Disco.Services.Devices.Exporting
}).ToList(); }).ToList();
} }
private static Dictionary<string, List<DeviceExportFieldMetadata>> BuildRecordAccessors(int processorMaxCount, int memoryMaxCount, int diskDriveMaxCount, int lanAdapterMaxCount, int wlanAdapterMaxCount, int certificateMaxCount, int batteriesMaxCount, IEnumerable<string> assignedUserDetailCustomKeys) private static Dictionary<string, List<Metadata>> BuildRecordAccessors(int processorMaxCount, int memoryMaxCount, int diskDriveMaxCount, int lanAdapterMaxCount, int wlanAdapterMaxCount, int certificateMaxCount, int batteriesMaxCount, IEnumerable<string> assignedUserDetailCustomKeys)
{ {
const string DateFormat = "yyyy-MM-dd"; const string DateFormat = "yyyy-MM-dd";
const string DateTimeFormat = DateFormat + " HH:mm:ss"; const string DateTimeFormat = DateFormat + " HH:mm:ss";
@@ -298,149 +223,149 @@ namespace Disco.Services.Devices.Exporting
Func<object, string> csvNullableDateEncoded = (o) => ((DateTime?)o).HasValue ? csvDateEncoded(o) : null; Func<object, string> csvNullableDateEncoded = (o) => ((DateTime?)o).HasValue ? csvDateEncoded(o) : null;
Func<object, string> csvNullableDateTimeEncoded = (o) => ((DateTime?)o).HasValue ? csvDateTimeEncoded(o) : null; Func<object, string> csvNullableDateTimeEncoded = (o) => ((DateTime?)o).HasValue ? csvDateTimeEncoded(o) : null;
var metadata = new Dictionary<string, List<DeviceExportFieldMetadata>>(); var metadata = new Dictionary<string, List<Metadata>>();
// Device // Device
metadata.Add(nameof(DeviceExportOptions.DeviceSerialNumber), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.DeviceSerialNumber), typeof(string), r => r.Device.SerialNumber, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.DeviceSerialNumber), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.DeviceSerialNumber), typeof(string), r => r.Device.SerialNumber, csvStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.DeviceAssetNumber), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.DeviceAssetNumber), typeof(string), r => r.Device.AssetNumber, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.DeviceAssetNumber), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.DeviceAssetNumber), typeof(string), r => r.Device.AssetNumber, csvStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.DeviceLocation), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.DeviceLocation), typeof(string), r => r.Device.Location, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.DeviceLocation), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.DeviceLocation), typeof(string), r => r.Device.Location, csvStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.DeviceComputerName), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.DeviceComputerName), typeof(string), r => r.Device.DeviceDomainId, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.DeviceComputerName), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.DeviceComputerName), typeof(string), r => r.Device.DeviceDomainId, csvStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.DeviceLastNetworkLogon), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.DeviceLastNetworkLogon), typeof(DateTime), r => r.Device.LastNetworkLogonDate, csvNullableDateTimeEncoded) }); metadata.Add(nameof(DeviceExportOptions.DeviceLastNetworkLogon), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.DeviceLastNetworkLogon), typeof(DateTime), r => r.Device.LastNetworkLogonDate, csvNullableDateTimeEncoded) });
metadata.Add(nameof(DeviceExportOptions.DeviceCreatedDate), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.DeviceCreatedDate), typeof(DateTime), r => r.Device.CreatedDate, csvDateTimeEncoded) }); metadata.Add(nameof(DeviceExportOptions.DeviceCreatedDate), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.DeviceCreatedDate), typeof(DateTime), r => r.Device.CreatedDate, csvDateTimeEncoded) });
metadata.Add(nameof(DeviceExportOptions.DeviceFirstEnrolledDate), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.DeviceFirstEnrolledDate), typeof(DateTime), r => r.Device.EnrolledDate, csvNullableDateTimeEncoded) }); metadata.Add(nameof(DeviceExportOptions.DeviceFirstEnrolledDate), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.DeviceFirstEnrolledDate), typeof(DateTime), r => r.Device.EnrolledDate, csvNullableDateTimeEncoded) });
metadata.Add(nameof(DeviceExportOptions.DeviceLastEnrolledDate), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.DeviceLastEnrolledDate), typeof(DateTime), r => r.Device.LastEnrolDate, csvNullableDateTimeEncoded) }); metadata.Add(nameof(DeviceExportOptions.DeviceLastEnrolledDate), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.DeviceLastEnrolledDate), typeof(DateTime), r => r.Device.LastEnrolDate, csvNullableDateTimeEncoded) });
metadata.Add(nameof(DeviceExportOptions.DeviceAllowUnauthenticatedEnrol), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.DeviceAllowUnauthenticatedEnrol), typeof(bool), r => r.Device.AllowUnauthenticatedEnrol, csvToStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.DeviceAllowUnauthenticatedEnrol), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.DeviceAllowUnauthenticatedEnrol), typeof(bool), r => r.Device.AllowUnauthenticatedEnrol, csvToStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.DeviceDecommissionedDate), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.DeviceDecommissionedDate), typeof(DateTime), r => r.Device.DecommissionedDate, csvNullableDateTimeEncoded) }); metadata.Add(nameof(DeviceExportOptions.DeviceDecommissionedDate), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.DeviceDecommissionedDate), typeof(DateTime), r => r.Device.DecommissionedDate, csvNullableDateTimeEncoded) });
metadata.Add(nameof(DeviceExportOptions.DeviceDecommissionedReason), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.DeviceDecommissionedReason), typeof(string), r => r.Device.DecommissionReason, csvToStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.DeviceDecommissionedReason), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.DeviceDecommissionedReason), typeof(string), r => r.Device.DecommissionReason, csvToStringEncoded) });
// Model // Model
metadata.Add(nameof(DeviceExportOptions.ModelId), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.ModelId), typeof(int), r => r.ModelId, csvToStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.ModelId), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.ModelId), typeof(int), r => r.ModelId, csvToStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.ModelDescription), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.ModelDescription), typeof(string), r => r.ModelDescription, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.ModelDescription), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.ModelDescription), typeof(string), r => r.ModelDescription, csvStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.ModelManufacturer), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.ModelManufacturer), typeof(string), r => r.ModelManufacturer, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.ModelManufacturer), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.ModelManufacturer), typeof(string), r => r.ModelManufacturer, csvStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.ModelModel), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.ModelModel), typeof(string), r => r.ModelModel, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.ModelModel), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.ModelModel), typeof(string), r => r.ModelModel, csvStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.ModelType), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.ModelType), typeof(string), r => r.ModelType, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.ModelType), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.ModelType), typeof(string), r => r.ModelType, csvStringEncoded) });
// Batch // Batch
metadata.Add(nameof(DeviceExportOptions.BatchId), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.BatchId), typeof(int), r => r.BatchId, csvToStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.BatchId), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.BatchId), typeof(int), r => r.BatchId, csvToStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.BatchName), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.BatchName), typeof(string), r => r.BatchName, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.BatchName), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.BatchName), typeof(string), r => r.BatchName, csvStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.BatchPurchaseDate), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.BatchPurchaseDate), typeof(DateTime), r => r.BatchPurchaseDate, csvNullableDateEncoded) }); metadata.Add(nameof(DeviceExportOptions.BatchPurchaseDate), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.BatchPurchaseDate), typeof(DateTime), r => r.BatchPurchaseDate, csvNullableDateEncoded) });
metadata.Add(nameof(DeviceExportOptions.BatchSupplier), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.BatchSupplier), typeof(string), r => r.BatchSupplier, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.BatchSupplier), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.BatchSupplier), typeof(string), r => r.BatchSupplier, csvStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.BatchUnitCost), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.BatchUnitCost), typeof(decimal), r => r.BatchUnitCost, csvCurrencyEncoded) }); metadata.Add(nameof(DeviceExportOptions.BatchUnitCost), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.BatchUnitCost), typeof(decimal), r => r.BatchUnitCost, csvCurrencyEncoded) });
metadata.Add(nameof(DeviceExportOptions.BatchWarrantyValidUntilDate), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.BatchWarrantyValidUntilDate), typeof(DateTime), r => r.BatchWarrantyValidUntilDate, csvNullableDateEncoded) }); metadata.Add(nameof(DeviceExportOptions.BatchWarrantyValidUntilDate), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.BatchWarrantyValidUntilDate), typeof(DateTime), r => r.BatchWarrantyValidUntilDate, csvNullableDateEncoded) });
metadata.Add(nameof(DeviceExportOptions.BatchInsuredDate), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.BatchInsuredDate), typeof(DateTime), r => r.BatchInsuredDate, csvNullableDateEncoded) }); metadata.Add(nameof(DeviceExportOptions.BatchInsuredDate), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.BatchInsuredDate), typeof(DateTime), r => r.BatchInsuredDate, csvNullableDateEncoded) });
metadata.Add(nameof(DeviceExportOptions.BatchInsuranceSupplier), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.BatchInsuranceSupplier), typeof(string), r => r.BatchInsuranceSupplier, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.BatchInsuranceSupplier), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.BatchInsuranceSupplier), typeof(string), r => r.BatchInsuranceSupplier, csvStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.BatchInsuredUntilDate), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.BatchInsuredUntilDate), typeof(DateTime), r => r.BatchInsuredUntilDate, csvNullableDateEncoded) }); metadata.Add(nameof(DeviceExportOptions.BatchInsuredUntilDate), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.BatchInsuredUntilDate), typeof(DateTime), r => r.BatchInsuredUntilDate, csvNullableDateEncoded) });
// Profile // Profile
metadata.Add(nameof(DeviceExportOptions.ProfileId), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.ProfileId), typeof(int), r => r.ProfileId, csvToStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.ProfileId), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.ProfileId), typeof(int), r => r.ProfileId, csvToStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.ProfileName), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.ProfileName), typeof(string), r => r.ProfileName, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.ProfileName), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.ProfileName), typeof(string), r => r.ProfileName, csvStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.ProfileShortName), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.ProfileShortName), typeof(string), r => r.ProfileShortName, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.ProfileShortName), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.ProfileShortName), typeof(string), r => r.ProfileShortName, csvStringEncoded) });
// User // User
metadata.Add(nameof(DeviceExportOptions.AssignedUserId), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.AssignedUserId), typeof(string), r => r.AssignedUser?.UserId, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.AssignedUserId), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.AssignedUserId), typeof(string), r => r.AssignedUser?.UserId, csvStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.AssignedUserDate), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.AssignedUserDate), typeof(DateTime), r => r.DeviceUserAssignment?.AssignedDate, csvNullableDateTimeEncoded) }); metadata.Add(nameof(DeviceExportOptions.AssignedUserDate), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.AssignedUserDate), typeof(DateTime), r => r.DeviceUserAssignment?.AssignedDate, csvNullableDateTimeEncoded) });
metadata.Add(nameof(DeviceExportOptions.AssignedUserDisplayName), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.AssignedUserDisplayName), typeof(string), r => r.AssignedUser?.DisplayName, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.AssignedUserDisplayName), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.AssignedUserDisplayName), typeof(string), r => r.AssignedUser?.DisplayName, csvStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.AssignedUserSurname), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.AssignedUserSurname), typeof(string), r => r.AssignedUser?.Surname, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.AssignedUserSurname), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.AssignedUserSurname), typeof(string), r => r.AssignedUser?.Surname, csvStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.AssignedUserGivenName), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.AssignedUserGivenName), typeof(string), r => r.AssignedUser?.GivenName, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.AssignedUserGivenName), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.AssignedUserGivenName), typeof(string), r => r.AssignedUser?.GivenName, csvStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.AssignedUserPhoneNumber), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.AssignedUserPhoneNumber), typeof(string), r => r.AssignedUser?.PhoneNumber, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.AssignedUserPhoneNumber), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.AssignedUserPhoneNumber), typeof(string), r => r.AssignedUser?.PhoneNumber, csvStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.AssignedUserEmailAddress), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.AssignedUserEmailAddress), typeof(string), r => r.AssignedUser?.EmailAddress, csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.AssignedUserEmailAddress), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.AssignedUserEmailAddress), typeof(string), r => r.AssignedUser?.EmailAddress, csvStringEncoded) });
if (assignedUserDetailCustomKeys != null) if (assignedUserDetailCustomKeys != null)
{ {
var assignedUserDetailCustomFields = new List<DeviceExportFieldMetadata>(); var assignedUserDetailCustomFields = new List<Metadata>();
foreach (var detailKey in assignedUserDetailCustomKeys.OrderBy(k => k, StringComparer.OrdinalIgnoreCase)) foreach (var detailKey in assignedUserDetailCustomKeys.OrderBy(k => k, StringComparer.OrdinalIgnoreCase))
{ {
var key = detailKey; var key = detailKey;
assignedUserDetailCustomFields.Add(new DeviceExportFieldMetadata(detailKey, detailKey, typeof(string), r => r.AssignedUserCustomDetails != null && r.AssignedUserCustomDetails.TryGetValue(key, out var value) ? value : null, csvStringEncoded)); assignedUserDetailCustomFields.Add(new Metadata(detailKey, detailKey, typeof(string), r => r.AssignedUserCustomDetails != null && r.AssignedUserCustomDetails.TryGetValue(key, out var value) ? value : null, csvStringEncoded));
} }
metadata.Add(nameof(DeviceExportOptions.AssignedUserDetailCustom), assignedUserDetailCustomFields); metadata.Add(nameof(DeviceExportOptions.AssignedUserDetailCustom), assignedUserDetailCustomFields);
} }
// Jobs // Jobs
metadata.Add(nameof(DeviceExportOptions.JobsTotalCount), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.JobsTotalCount), typeof(int), r => r.JobsTotalCount, csvToStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.JobsTotalCount), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.JobsTotalCount), typeof(int), r => r.JobsTotalCount, csvToStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.JobsOpenCount), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.JobsOpenCount), typeof(int), r => r.JobsOpenCount, csvToStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.JobsOpenCount), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.JobsOpenCount), typeof(int), r => r.JobsOpenCount, csvToStringEncoded) });
// Attachments // Attachments
metadata.Add(nameof(DeviceExportOptions.AttachmentsCount), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.AttachmentsCount), typeof(int), r => r.AttachmentsCount, csvToStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.AttachmentsCount), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.AttachmentsCount), typeof(int), r => r.AttachmentsCount, csvToStringEncoded) });
// Certificates // Certificates
var certificateFields = new List<DeviceExportFieldMetadata>(certificateMaxCount * 4); var certificateFields = new List<Metadata>(certificateMaxCount * 4);
for (int i = 0; i < certificateMaxCount; i++) for (int i = 0; i < certificateMaxCount; i++)
{ {
var v = i; var v = i;
var index = i + 1; var index = i + 1;
certificateFields.Add(new DeviceExportFieldMetadata($"Certificate{index}Name", $"Certificate {index} Name", typeof(string), r => r.DeviceCertificates.Skip(v).FirstOrDefault()?.Name, csvStringEncoded)); certificateFields.Add(new Metadata($"Certificate{index}Name", $"Certificate {index} Name", typeof(string), r => r.DeviceCertificates.Skip(v).FirstOrDefault()?.Name, csvStringEncoded));
certificateFields.Add(new DeviceExportFieldMetadata($"Certificate{index}AllocationDate", $"Certificate {index} Allocation Date", typeof(DateTime), r => r.DeviceCertificates.Skip(v).FirstOrDefault()?.AllocatedDate, csvNullableDateTimeEncoded)); certificateFields.Add(new Metadata($"Certificate{index}AllocationDate", $"Certificate {index} Allocation Date", typeof(DateTime), r => r.DeviceCertificates.Skip(v).FirstOrDefault()?.AllocatedDate, csvNullableDateTimeEncoded));
certificateFields.Add(new DeviceExportFieldMetadata($"Certificate{index}ExpirationDate", $"Certificate {index} Expiration Date", typeof(DateTime), r => r.DeviceCertificates.Skip(v).FirstOrDefault()?.ExpirationDate, csvNullableDateTimeEncoded)); certificateFields.Add(new Metadata($"Certificate{index}ExpirationDate", $"Certificate {index} Expiration Date", typeof(DateTime), r => r.DeviceCertificates.Skip(v).FirstOrDefault()?.ExpirationDate, csvNullableDateTimeEncoded));
certificateFields.Add(new DeviceExportFieldMetadata($"Certificate{index}ProviderId", $"Certificate {index} Provider Id", typeof(string), r => r.DeviceCertificates.Skip(v).FirstOrDefault()?.ProviderId, csvStringEncoded)); certificateFields.Add(new Metadata($"Certificate{index}ProviderId", $"Certificate {index} Provider Id", typeof(string), r => r.DeviceCertificates.Skip(v).FirstOrDefault()?.ProviderId, csvStringEncoded));
} }
metadata.Add(nameof(DeviceExportOptions.Certificates), certificateFields); metadata.Add(nameof(DeviceExportOptions.Certificates), certificateFields);
// Details // Details
var biosFields = new List<DeviceExportFieldMetadata>() var biosFields = new List<Metadata>()
{ {
new DeviceExportFieldMetadata("BIOSManufacturer", "BIOS Manufacturer", typeof(string), r => r.DeviceDetailBios?.FirstOrDefault()?.Manufacturer, csvStringEncoded), new Metadata("BIOSManufacturer", "BIOS Manufacturer", typeof(string), r => r.DeviceDetailBios?.FirstOrDefault()?.Manufacturer, csvStringEncoded),
new DeviceExportFieldMetadata("BIOSSerialNumber", "BIOS Serial Number", typeof(string), r => r.DeviceDetailBios?.FirstOrDefault()?.SerialNumber, csvStringEncoded), new Metadata("BIOSSerialNumber", "BIOS Serial Number", typeof(string), r => r.DeviceDetailBios?.FirstOrDefault()?.SerialNumber, csvStringEncoded),
new DeviceExportFieldMetadata("BIOSVersion", "BIOS Version", typeof(string), r => { new Metadata("BIOSVersion", "BIOS Version", typeof(string), r => {
var bios = r.DeviceDetailBios?.FirstOrDefault(); var bios = r.DeviceDetailBios?.FirstOrDefault();
if (bios?.SMBIOSBIOSVersion != null) if (bios?.SMBIOSBIOSVersion != null)
return $"{bios.SMBIOSBIOSVersion} {bios.SMBIOSMajorVersion}.{bios.SMBIOSMinorVersion}"; return $"{bios.SMBIOSBIOSVersion} {bios.SMBIOSMajorVersion}.{bios.SMBIOSMinorVersion}";
else else
return null; return null;
}, csvStringEncoded), }, csvStringEncoded),
new DeviceExportFieldMetadata("BIOSSystemVersion", "BIOS System Version", typeof(string), r => { new Metadata("BIOSSystemVersion", "BIOS System Version", typeof(string), r => {
var bios = r.DeviceDetailBios?.FirstOrDefault(); var bios = r.DeviceDetailBios?.FirstOrDefault();
if (bios?.SystemBiosMajorVersion.HasValue ?? false) if (bios?.SystemBiosMajorVersion.HasValue ?? false)
return $"{bios.SystemBiosMajorVersion}.{bios.SystemBiosMinorVersion}"; return $"{bios.SystemBiosMajorVersion}.{bios.SystemBiosMinorVersion}";
else else
return null; return null;
}, csvStringEncoded), }, csvStringEncoded),
new DeviceExportFieldMetadata("BIOSReleaseDate", "BIOS Release Date", typeof(DateTime), r => r.DeviceDetailBios?.FirstOrDefault()?.ReleaseDate, csvNullableDateTimeEncoded), new Metadata("BIOSReleaseDate", "BIOS Release Date", typeof(DateTime), r => r.DeviceDetailBios?.FirstOrDefault()?.ReleaseDate, csvNullableDateTimeEncoded),
}; };
metadata.Add(nameof(DeviceExportOptions.DetailBios), biosFields); metadata.Add(nameof(DeviceExportOptions.DetailBios), biosFields);
var baseBoardFields = new List<DeviceExportFieldMetadata>() var baseBoardFields = new List<Metadata>()
{ {
new DeviceExportFieldMetadata("BaseBoardManufacturer", "Base Board Manufacturer", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.Manufacturer, csvStringEncoded), new Metadata("BaseBoardManufacturer", "Base Board Manufacturer", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.Manufacturer, csvStringEncoded),
new DeviceExportFieldMetadata("BaseBoardModel", "Base Board Model", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.Model, csvStringEncoded), new Metadata("BaseBoardModel", "Base Board Model", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.Model, csvStringEncoded),
new DeviceExportFieldMetadata("BaseBoardProduct", "Base Board Product", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.Product, csvStringEncoded), new Metadata("BaseBoardProduct", "Base Board Product", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.Product, csvStringEncoded),
new DeviceExportFieldMetadata("BaseBoardPartNumber", "Base Board Part Number", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.PartNumber, csvStringEncoded), new Metadata("BaseBoardPartNumber", "Base Board Part Number", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.PartNumber, csvStringEncoded),
new DeviceExportFieldMetadata("BaseBoardSKU", "Base Board SKU", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.SKU, csvStringEncoded), new Metadata("BaseBoardSKU", "Base Board SKU", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.SKU, csvStringEncoded),
new DeviceExportFieldMetadata("BaseBoardSerialNumber", "Base Board Serial Number", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.SerialNumber, csvStringEncoded), new Metadata("BaseBoardSerialNumber", "Base Board Serial Number", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.SerialNumber, csvStringEncoded),
new DeviceExportFieldMetadata("BaseBoardConfigOptions", "Base Board Config Options", typeof(string), r => { new Metadata("BaseBoardConfigOptions", "Base Board Config Options", typeof(string), r => {
var baseBoard = r.DeviceDetailBaseBoard?.FirstOrDefault(); var baseBoard = r.DeviceDetailBaseBoard?.FirstOrDefault();
if (baseBoard?.ConfigOptions != null) if (baseBoard?.ConfigOptions != null)
return string.Join("; ", baseBoard.ConfigOptions); return string.Join("; ", baseBoard.ConfigOptions);
else else
return null; return null;
}, csvStringEncoded), }, csvStringEncoded),
new DeviceExportFieldMetadata("BaseBoardVersion", "Base Board Version", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.Version, csvStringEncoded), new Metadata("BaseBoardVersion", "Base Board Version", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.Version, csvStringEncoded),
}; };
metadata.Add(nameof(DeviceExportOptions.DetailBaseBoard), baseBoardFields); metadata.Add(nameof(DeviceExportOptions.DetailBaseBoard), baseBoardFields);
var computerSystemFields = new List<DeviceExportFieldMetadata>() var computerSystemFields = new List<Metadata>()
{ {
new DeviceExportFieldMetadata("ComputerSystemDescription", "System Description", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.Description, csvStringEncoded), new Metadata("ComputerSystemDescription", "System Description", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.Description, csvStringEncoded),
new DeviceExportFieldMetadata("ComputerSystemPCSystemType", "System Form Factor", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.PCSystemType, csvStringEncoded), new Metadata("ComputerSystemPCSystemType", "System Form Factor", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.PCSystemType, csvStringEncoded),
new DeviceExportFieldMetadata("ComputerSystemSystemType", "System Type", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.SystemType, csvStringEncoded), new Metadata("ComputerSystemSystemType", "System Type", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.SystemType, csvStringEncoded),
new DeviceExportFieldMetadata("ComputerSystemPrimaryOwnerName", "System Primary Owner Name", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.PrimaryOwnerName, csvStringEncoded), new Metadata("ComputerSystemPrimaryOwnerName", "System Primary Owner Name", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.PrimaryOwnerName, csvStringEncoded),
new DeviceExportFieldMetadata("ComputerSystemPrimaryOwnerContact", "System Primary Owner Contact", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.PrimaryOwnerContact, csvStringEncoded), new Metadata("ComputerSystemPrimaryOwnerContact", "System Primary Owner Contact", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.PrimaryOwnerContact, csvStringEncoded),
new DeviceExportFieldMetadata("ComputerSystemChassisSKU", "System Chassis SKU", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.ChassisSKUNumber, csvStringEncoded), new Metadata("ComputerSystemChassisSKU", "System Chassis SKU", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.ChassisSKUNumber, csvStringEncoded),
new DeviceExportFieldMetadata("ComputerSystemSystemSKU", "System SKU", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.SystemSKUNumber, csvStringEncoded), new Metadata("ComputerSystemSystemSKU", "System SKU", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.SystemSKUNumber, csvStringEncoded),
new DeviceExportFieldMetadata("ComputerSystemOEMReference", "System OEM Reference", typeof(string), r => { new Metadata("ComputerSystemOEMReference", "System OEM Reference", typeof(string), r => {
var computerSystem = r.DeviceDetailComputerSystem?.FirstOrDefault(); var computerSystem = r.DeviceDetailComputerSystem?.FirstOrDefault();
if (computerSystem?.OEMStringArray != null) if (computerSystem?.OEMStringArray != null)
return string.Join("; ", computerSystem.OEMStringArray); return string.Join("; ", computerSystem.OEMStringArray);
else else
return null; return null;
}, csvStringEncoded), }, csvStringEncoded),
new DeviceExportFieldMetadata("ComputerSystemCurrentTimeZone", "System Time Zone", typeof(string), r => { new Metadata("ComputerSystemCurrentTimeZone", "System Time Zone", typeof(string), r => {
var computerSystem = r.DeviceDetailComputerSystem?.FirstOrDefault(); var computerSystem = r.DeviceDetailComputerSystem?.FirstOrDefault();
if (computerSystem?.CurrentTimeZone.HasValue ?? false) if (computerSystem?.CurrentTimeZone.HasValue ?? false)
return $"{computerSystem.CurrentTimeZone.Value / 60:00}:{Math.Abs(computerSystem.CurrentTimeZone.Value % 60):00}"; return $"{computerSystem.CurrentTimeZone.Value / 60:00}:{Math.Abs(computerSystem.CurrentTimeZone.Value % 60):00}";
else else
return null; return null;
}, csvStringEncoded), }, csvStringEncoded),
new DeviceExportFieldMetadata("ComputerSystemRoles", "System Roles", typeof(string), r => { new Metadata("ComputerSystemRoles", "System Roles", typeof(string), r => {
var computerSystem = r.DeviceDetailComputerSystem?.FirstOrDefault(); var computerSystem = r.DeviceDetailComputerSystem?.FirstOrDefault();
if (computerSystem?.Roles != null) if (computerSystem?.Roles != null)
return string.Join("; ", computerSystem.Roles); return string.Join("; ", computerSystem.Roles);
@@ -450,88 +375,88 @@ namespace Disco.Services.Devices.Exporting
}; };
metadata.Add(nameof(DeviceExportOptions.DetailComputerSystem), computerSystemFields); metadata.Add(nameof(DeviceExportOptions.DetailComputerSystem), computerSystemFields);
var processorFields = new List<DeviceExportFieldMetadata>(processorMaxCount * 6); var processorFields = new List<Metadata>(processorMaxCount * 6);
for (int i = 0; i < processorMaxCount; i++) for (int i = 0; i < processorMaxCount; i++)
{ {
var v = i; var v = i;
var index = i + 1; var index = i + 1;
processorFields.Add(new DeviceExportFieldMetadata($"Processor{index}Name", $"Processor {index} Name", typeof(string), r => r.DeviceDetailProcessors?.Skip(v).FirstOrDefault()?.Name, csvStringEncoded)); processorFields.Add(new Metadata($"Processor{index}Name", $"Processor {index} Name", typeof(string), r => r.DeviceDetailProcessors?.Skip(v).FirstOrDefault()?.Name, csvStringEncoded));
processorFields.Add(new DeviceExportFieldMetadata($"Processor{index}Description", $"Processor {index} Description", typeof(string), r => r.DeviceDetailProcessors?.Skip(v).FirstOrDefault()?.Description, csvStringEncoded)); processorFields.Add(new Metadata($"Processor{index}Description", $"Processor {index} Description", typeof(string), r => r.DeviceDetailProcessors?.Skip(v).FirstOrDefault()?.Description, csvStringEncoded));
processorFields.Add(new DeviceExportFieldMetadata($"Processor{index}Architecture", $"Processor {index} Architecture", typeof(string), r => r.DeviceDetailProcessors?.Skip(v).FirstOrDefault()?.Architecture, csvStringEncoded)); processorFields.Add(new Metadata($"Processor{index}Architecture", $"Processor {index} Architecture", typeof(string), r => r.DeviceDetailProcessors?.Skip(v).FirstOrDefault()?.Architecture, csvStringEncoded));
processorFields.Add(new DeviceExportFieldMetadata($"Processor{index}ClockSpeed", $"Processor {index} Clock Speed", typeof(string), r => r.DeviceDetailProcessors?.Skip(v).FirstOrDefault()?.MaxClockSpeedFriendly(), csvStringEncoded)); processorFields.Add(new Metadata($"Processor{index}ClockSpeed", $"Processor {index} Clock Speed", typeof(string), r => r.DeviceDetailProcessors?.Skip(v).FirstOrDefault()?.MaxClockSpeedFriendly(), csvStringEncoded));
processorFields.Add(new DeviceExportFieldMetadata($"Processor{index}Cores", $"Processor {index} Cores", typeof(int), r => r.DeviceDetailProcessors?.Skip(v).FirstOrDefault()?.NumberOfCores, csvToStringEncoded)); processorFields.Add(new Metadata($"Processor{index}Cores", $"Processor {index} Cores", typeof(int), r => r.DeviceDetailProcessors?.Skip(v).FirstOrDefault()?.NumberOfCores, csvToStringEncoded));
processorFields.Add(new DeviceExportFieldMetadata($"Processor{index}LogicalProcessors", $"Processor {index} Logical Processors", typeof(int), r => r.DeviceDetailProcessors?.Skip(v).FirstOrDefault()?.NumberOfLogicalProcessors, csvToStringEncoded)); processorFields.Add(new Metadata($"Processor{index}LogicalProcessors", $"Processor {index} Logical Processors", typeof(int), r => r.DeviceDetailProcessors?.Skip(v).FirstOrDefault()?.NumberOfLogicalProcessors, csvToStringEncoded));
} }
metadata.Add(nameof(DeviceExportOptions.DetailProcessors), processorFields); metadata.Add(nameof(DeviceExportOptions.DetailProcessors), processorFields);
var memoryFields = new List<DeviceExportFieldMetadata>((memoryMaxCount * 6) + 1); var memoryFields = new List<Metadata>((memoryMaxCount * 6) + 1);
memoryFields.Add(new DeviceExportFieldMetadata($"MemoryTotalCapacity", $"Memory Total Capacity", typeof(string), r => MeasurementUnitExtensions.ByteSizeToFriendly((ulong)(r.DeviceDetailPhysicalMemory?.Sum(m => (long)m.Capacity) ?? 0L)), csvStringEncoded)); memoryFields.Add(new Metadata($"MemoryTotalCapacity", $"Memory Total Capacity", typeof(string), r => MeasurementUnitExtensions.ByteSizeToFriendly((ulong)(r.DeviceDetailPhysicalMemory?.Sum(m => (long)m.Capacity) ?? 0L)), csvStringEncoded));
for (int i = 0; i < memoryMaxCount; i++) for (int i = 0; i < memoryMaxCount; i++)
{ {
var v = i; var v = i;
var index = i + 1; var index = i + 1;
memoryFields.Add(new DeviceExportFieldMetadata($"Memory{index}Location", $"Memory {index} Location", typeof(string), r => r.DeviceDetailPhysicalMemory?.Skip(v).FirstOrDefault()?.DeviceLocator, csvStringEncoded)); memoryFields.Add(new Metadata($"Memory{index}Location", $"Memory {index} Location", typeof(string), r => r.DeviceDetailPhysicalMemory?.Skip(v).FirstOrDefault()?.DeviceLocator, csvStringEncoded));
memoryFields.Add(new DeviceExportFieldMetadata($"Memory{index}Manufacturer", $"Memory {index} Manufacturer", typeof(string), r => r.DeviceDetailPhysicalMemory?.Skip(v).FirstOrDefault()?.Manufacturer, csvStringEncoded)); memoryFields.Add(new Metadata($"Memory{index}Manufacturer", $"Memory {index} Manufacturer", typeof(string), r => r.DeviceDetailPhysicalMemory?.Skip(v).FirstOrDefault()?.Manufacturer, csvStringEncoded));
memoryFields.Add(new DeviceExportFieldMetadata($"Memory{index}PartNumber", $"Memory {index} Part Number", typeof(string), r => r.DeviceDetailPhysicalMemory?.Skip(v).FirstOrDefault()?.PartNumber, csvStringEncoded)); memoryFields.Add(new Metadata($"Memory{index}PartNumber", $"Memory {index} Part Number", typeof(string), r => r.DeviceDetailPhysicalMemory?.Skip(v).FirstOrDefault()?.PartNumber, csvStringEncoded));
memoryFields.Add(new DeviceExportFieldMetadata($"Memory{index}SerialNumber", $"Memory {index} Serial Number", typeof(string), r => r.DeviceDetailPhysicalMemory?.Skip(v).FirstOrDefault()?.SerialNumber, csvStringEncoded)); memoryFields.Add(new Metadata($"Memory{index}SerialNumber", $"Memory {index} Serial Number", typeof(string), r => r.DeviceDetailPhysicalMemory?.Skip(v).FirstOrDefault()?.SerialNumber, csvStringEncoded));
memoryFields.Add(new DeviceExportFieldMetadata($"Memory{index}Capacity", $"Memory {index} Capacity", typeof(string), r => r.DeviceDetailPhysicalMemory?.Skip(v).FirstOrDefault()?.CapacityFriendly(), csvStringEncoded)); memoryFields.Add(new Metadata($"Memory{index}Capacity", $"Memory {index} Capacity", typeof(string), r => r.DeviceDetailPhysicalMemory?.Skip(v).FirstOrDefault()?.CapacityFriendly(), csvStringEncoded));
memoryFields.Add(new DeviceExportFieldMetadata($"Memory{index}ConfiguredClockSpeed", $"Memory {index} Clock Speed", typeof(int), r => r.DeviceDetailPhysicalMemory?.Skip(v).FirstOrDefault()?.ConfiguredClockSpeed, csvToStringEncoded)); memoryFields.Add(new Metadata($"Memory{index}ConfiguredClockSpeed", $"Memory {index} Clock Speed", typeof(int), r => r.DeviceDetailPhysicalMemory?.Skip(v).FirstOrDefault()?.ConfiguredClockSpeed, csvToStringEncoded));
} }
metadata.Add(nameof(DeviceExportOptions.DetailMemory), memoryFields); metadata.Add(nameof(DeviceExportOptions.DetailMemory), memoryFields);
var diskFields = new List<DeviceExportFieldMetadata>(diskDriveMaxCount * 6); var diskFields = new List<Metadata>(diskDriveMaxCount * 6);
for (int i = 0; i < diskDriveMaxCount; i++) for (int i = 0; i < diskDriveMaxCount; i++)
{ {
var v = i; var v = i;
var index = i + 1; var index = i + 1;
diskFields.Add(new DeviceExportFieldMetadata($"Disk{index}Manufacturer", $"Disk {index} Manufacturer", typeof(string), r => r.DeviceDetailDiskDrives?.Skip(v).FirstOrDefault()?.Manufacturer, csvStringEncoded)); diskFields.Add(new Metadata($"Disk{index}Manufacturer", $"Disk {index} Manufacturer", typeof(string), r => r.DeviceDetailDiskDrives?.Skip(v).FirstOrDefault()?.Manufacturer, csvStringEncoded));
diskFields.Add(new DeviceExportFieldMetadata($"Disk{index}Model", $"Disk {index} Model", typeof(string), r => r.DeviceDetailDiskDrives?.Skip(v).FirstOrDefault()?.Model, csvStringEncoded)); diskFields.Add(new Metadata($"Disk{index}Model", $"Disk {index} Model", typeof(string), r => r.DeviceDetailDiskDrives?.Skip(v).FirstOrDefault()?.Model, csvStringEncoded));
diskFields.Add(new DeviceExportFieldMetadata($"Disk{index}SerialNumber", $"Disk {index} Serial Number", typeof(string), r => r.DeviceDetailDiskDrives?.Skip(v).FirstOrDefault()?.SerialNumber, csvStringEncoded)); diskFields.Add(new Metadata($"Disk{index}SerialNumber", $"Disk {index} Serial Number", typeof(string), r => r.DeviceDetailDiskDrives?.Skip(v).FirstOrDefault()?.SerialNumber, csvStringEncoded));
diskFields.Add(new DeviceExportFieldMetadata($"Disk{index}Firmware", $"Disk {index} Firmware", typeof(string), r => r.DeviceDetailDiskDrives?.Skip(v).FirstOrDefault()?.FirmwareRevision, csvStringEncoded)); diskFields.Add(new Metadata($"Disk{index}Firmware", $"Disk {index} Firmware", typeof(string), r => r.DeviceDetailDiskDrives?.Skip(v).FirstOrDefault()?.FirmwareRevision, csvStringEncoded));
diskFields.Add(new DeviceExportFieldMetadata($"Disk{index}Capacity", $"Disk {index} Size", typeof(string), r => r.DeviceDetailDiskDrives?.Skip(v).FirstOrDefault()?.SizeFriendly(), csvStringEncoded)); diskFields.Add(new Metadata($"Disk{index}Capacity", $"Disk {index} Size", typeof(string), r => r.DeviceDetailDiskDrives?.Skip(v).FirstOrDefault()?.SizeFriendly(), csvStringEncoded));
diskFields.Add(new DeviceExportFieldMetadata($"Disk{index}Capacity", $"Disk {index} Total Free Space", typeof(string), r => MeasurementUnitExtensions.ByteSizeToFriendly((ulong)(r.DeviceDetailDiskDrives?.Skip(v).FirstOrDefault()?.Partitions?.Sum(p => (long)(p.LogicalDisk?.FreeSpace ?? 0L)) ?? 0L)), csvStringEncoded)); diskFields.Add(new Metadata($"Disk{index}Capacity", $"Disk {index} Total Free Space", typeof(string), r => MeasurementUnitExtensions.ByteSizeToFriendly((ulong)(r.DeviceDetailDiskDrives?.Skip(v).FirstOrDefault()?.Partitions?.Sum(p => (long)(p.LogicalDisk?.FreeSpace ?? 0L)) ?? 0L)), csvStringEncoded));
} }
metadata.Add(nameof(DeviceExportOptions.DetailDiskDrives), diskFields); metadata.Add(nameof(DeviceExportOptions.DetailDiskDrives), diskFields);
var lanAdapterFields = new List<DeviceExportFieldMetadata>(lanAdapterMaxCount * 5); var lanAdapterFields = new List<Metadata>(lanAdapterMaxCount * 5);
for (int i = 0; i < lanAdapterMaxCount; i++) for (int i = 0; i < lanAdapterMaxCount; i++)
{ {
var v = i; var v = i;
var index = i + 1; var index = i + 1;
lanAdapterFields.Add(new DeviceExportFieldMetadata($"LanAdapter{index}Connection", $"Lan Adapter {index} Connection", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => !a.IsWlanAdapter).Skip(v).FirstOrDefault()?.NetConnectionID, csvStringEncoded)); lanAdapterFields.Add(new Metadata($"LanAdapter{index}Connection", $"Lan Adapter {index} Connection", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => !a.IsWlanAdapter).Skip(v).FirstOrDefault()?.NetConnectionID, csvStringEncoded));
lanAdapterFields.Add(new DeviceExportFieldMetadata($"LanAdapter{index}Manufacturer", $"Lan Adapter {index} Manufacturer", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => !a.IsWlanAdapter).Skip(v).FirstOrDefault()?.Manufacturer, csvStringEncoded)); lanAdapterFields.Add(new Metadata($"LanAdapter{index}Manufacturer", $"Lan Adapter {index} Manufacturer", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => !a.IsWlanAdapter).Skip(v).FirstOrDefault()?.Manufacturer, csvStringEncoded));
lanAdapterFields.Add(new DeviceExportFieldMetadata($"LanAdapter{index}ProductName", $"Lan Adapter {index} Product Name", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => !a.IsWlanAdapter).Skip(v).FirstOrDefault()?.ProductName, csvStringEncoded)); lanAdapterFields.Add(new Metadata($"LanAdapter{index}ProductName", $"Lan Adapter {index} Product Name", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => !a.IsWlanAdapter).Skip(v).FirstOrDefault()?.ProductName, csvStringEncoded));
lanAdapterFields.Add(new DeviceExportFieldMetadata($"LanAdapter{index}Speed", $"Lan Adapter {index} Speed", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => !a.IsWlanAdapter).Skip(v).FirstOrDefault()?.SpeedFriendly(), csvStringEncoded)); lanAdapterFields.Add(new Metadata($"LanAdapter{index}Speed", $"Lan Adapter {index} Speed", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => !a.IsWlanAdapter).Skip(v).FirstOrDefault()?.SpeedFriendly(), csvStringEncoded));
lanAdapterFields.Add(new DeviceExportFieldMetadata($"LanAdapter{index}MacAddress", $"Lan Adapter {index} Mac Address", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => !a.IsWlanAdapter).Skip(v).FirstOrDefault()?.MACAddress ?? r.DeviceDetailLanMacAddresses?.Skip(v).FirstOrDefault(), csvStringEncoded)); lanAdapterFields.Add(new Metadata($"LanAdapter{index}MacAddress", $"Lan Adapter {index} Mac Address", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => !a.IsWlanAdapter).Skip(v).FirstOrDefault()?.MACAddress ?? r.DeviceDetailLanMacAddresses?.Skip(v).FirstOrDefault(), csvStringEncoded));
} }
metadata.Add(nameof(DeviceExportOptions.DetailLanAdapters), lanAdapterFields); metadata.Add(nameof(DeviceExportOptions.DetailLanAdapters), lanAdapterFields);
var fields = new List<DeviceExportFieldMetadata>(wlanAdapterMaxCount * 5); var fields = new List<Metadata>(wlanAdapterMaxCount * 5);
for (int i = 0; i < wlanAdapterMaxCount; i++) for (int i = 0; i < wlanAdapterMaxCount; i++)
{ {
var v = i; var v = i;
var wlanAdapterFields = i + 1; var wlanAdapterFields = i + 1;
fields.Add(new DeviceExportFieldMetadata($"WlanAdapter{wlanAdapterFields}Connection", $"Wlan Adapter {wlanAdapterFields} Connection", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => a.IsWlanAdapter).Skip(v).FirstOrDefault()?.NetConnectionID, csvStringEncoded)); fields.Add(new Metadata($"WlanAdapter{wlanAdapterFields}Connection", $"Wlan Adapter {wlanAdapterFields} Connection", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => a.IsWlanAdapter).Skip(v).FirstOrDefault()?.NetConnectionID, csvStringEncoded));
fields.Add(new DeviceExportFieldMetadata($"WlanAdapter{wlanAdapterFields}Manufacturer", $"Wlan Adapter {wlanAdapterFields} Manufacturer", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => a.IsWlanAdapter).Skip(v).FirstOrDefault()?.Manufacturer, csvStringEncoded)); fields.Add(new Metadata($"WlanAdapter{wlanAdapterFields}Manufacturer", $"Wlan Adapter {wlanAdapterFields} Manufacturer", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => a.IsWlanAdapter).Skip(v).FirstOrDefault()?.Manufacturer, csvStringEncoded));
fields.Add(new DeviceExportFieldMetadata($"WlanAdapter{wlanAdapterFields}ProductName", $"Wlan Adapter {wlanAdapterFields} Product Name", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => a.IsWlanAdapter).Skip(v).FirstOrDefault()?.ProductName, csvStringEncoded)); fields.Add(new Metadata($"WlanAdapter{wlanAdapterFields}ProductName", $"Wlan Adapter {wlanAdapterFields} Product Name", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => a.IsWlanAdapter).Skip(v).FirstOrDefault()?.ProductName, csvStringEncoded));
fields.Add(new DeviceExportFieldMetadata($"WlanAdapter{wlanAdapterFields}Speed", $"Wlan Adapter {wlanAdapterFields} Speed", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => a.IsWlanAdapter).Skip(v).FirstOrDefault()?.SpeedFriendly(), csvStringEncoded)); fields.Add(new Metadata($"WlanAdapter{wlanAdapterFields}Speed", $"Wlan Adapter {wlanAdapterFields} Speed", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => a.IsWlanAdapter).Skip(v).FirstOrDefault()?.SpeedFriendly(), csvStringEncoded));
fields.Add(new DeviceExportFieldMetadata($"WlanAdapter{wlanAdapterFields}MacAddress", $"Wlan Adapter {wlanAdapterFields} Mac Address", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => a.IsWlanAdapter).Skip(v).FirstOrDefault()?.MACAddress ?? r.DeviceDetailWlanMacAddresses?.Skip(v).FirstOrDefault(), csvStringEncoded)); fields.Add(new Metadata($"WlanAdapter{wlanAdapterFields}MacAddress", $"Wlan Adapter {wlanAdapterFields} Mac Address", typeof(string), r => r.DeviceDetailNetworkAdapters?.Where(a => a.IsWlanAdapter).Skip(v).FirstOrDefault()?.MACAddress ?? r.DeviceDetailWlanMacAddresses?.Skip(v).FirstOrDefault(), csvStringEncoded));
} }
metadata.Add(nameof(DeviceExportOptions.DetailWLanAdapters), fields); metadata.Add(nameof(DeviceExportOptions.DetailWLanAdapters), fields);
metadata.Add(nameof(DeviceExportOptions.DetailACAdapter), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.DetailACAdapter), typeof(string), r => r.DeviceDetails.Where(dd => dd.Key == DeviceDetail.HardwareKeyACAdapter).Select(dd => dd.Value).FirstOrDefault(), csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.DetailACAdapter), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.DetailACAdapter), typeof(string), r => r.DeviceDetails.Where(dd => dd.Key == DeviceDetail.HardwareKeyACAdapter).Select(dd => dd.Value).FirstOrDefault(), csvStringEncoded) });
metadata.Add(nameof(DeviceExportOptions.DetailBattery), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.DetailBattery), typeof(string), r => r.DeviceDetails.Where(dd => dd.Key == DeviceDetail.HardwareKeyBattery).Select(dd => dd.Value).FirstOrDefault(), csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.DetailBattery), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.DetailBattery), typeof(string), r => r.DeviceDetails.Where(dd => dd.Key == DeviceDetail.HardwareKeyBattery).Select(dd => dd.Value).FirstOrDefault(), csvStringEncoded) });
var batteriesFields = new List<DeviceExportFieldMetadata>(processorMaxCount * 6); var batteriesFields = new List<Metadata>(processorMaxCount * 6);
for (int i = 0; i < batteriesMaxCount; i++) for (int i = 0; i < batteriesMaxCount; i++)
{ {
var v = i; var v = i;
var index = i + 1; var index = i + 1;
batteriesFields.Add(new DeviceExportFieldMetadata($"Batteries{index}Name", $"Battery {index} Name", typeof(string), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.Name, csvStringEncoded)); batteriesFields.Add(new Metadata($"Batteries{index}Name", $"Battery {index} Name", typeof(string), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.Name, csvStringEncoded));
batteriesFields.Add(new DeviceExportFieldMetadata($"Batteries{index}Description", $"Battery {index} Description", typeof(string), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.Description, csvStringEncoded)); batteriesFields.Add(new Metadata($"Batteries{index}Description", $"Battery {index} Description", typeof(string), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.Description, csvStringEncoded));
batteriesFields.Add(new DeviceExportFieldMetadata($"Batteries{index}Availability", $"Battery {index} Availability", typeof(string), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.Availability, csvStringEncoded)); batteriesFields.Add(new Metadata($"Batteries{index}Availability", $"Battery {index} Availability", typeof(string), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.Availability, csvStringEncoded));
batteriesFields.Add(new DeviceExportFieldMetadata($"Batteries{index}Chemistry", $"Battery {index} Chemistry", typeof(string), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.Chemistry, csvStringEncoded)); batteriesFields.Add(new Metadata($"Batteries{index}Chemistry", $"Battery {index} Chemistry", typeof(string), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.Chemistry, csvStringEncoded));
batteriesFields.Add(new DeviceExportFieldMetadata($"Batteries{index}DesignVoltage", $"Battery {index} Design Voltage", typeof(long), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.DesignVoltage, csvToStringEncoded)); batteriesFields.Add(new Metadata($"Batteries{index}DesignVoltage", $"Battery {index} Design Voltage", typeof(long), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.DesignVoltage, csvToStringEncoded));
batteriesFields.Add(new DeviceExportFieldMetadata($"Batteries{index}DesignCapacity", $"Battery {index} Design Capacity", typeof(int), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.DesignCapacity, csvToStringEncoded)); batteriesFields.Add(new Metadata($"Batteries{index}DesignCapacity", $"Battery {index} Design Capacity", typeof(int), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.DesignCapacity, csvToStringEncoded));
batteriesFields.Add(new DeviceExportFieldMetadata($"Batteries{index}FullChargeCapacity", $"Battery {index} Capacity", typeof(int), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.FullChargeCapacity, csvToStringEncoded)); batteriesFields.Add(new Metadata($"Batteries{index}FullChargeCapacity", $"Battery {index} Capacity", typeof(int), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.FullChargeCapacity, csvToStringEncoded));
} }
metadata.Add(nameof(DeviceExportOptions.DetailBatteries), batteriesFields); metadata.Add(nameof(DeviceExportOptions.DetailBatteries), batteriesFields);
metadata.Add(nameof(DeviceExportOptions.DetailKeyboard), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.DetailKeyboard), typeof(string), r => r.DeviceDetails.Where(dd => dd.Key == DeviceDetail.HardwareKeyKeyboard).Select(dd => dd.Value).FirstOrDefault(), csvStringEncoded) }); metadata.Add(nameof(DeviceExportOptions.DetailKeyboard), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.DetailKeyboard), typeof(string), r => r.DeviceDetails.Where(dd => dd.Key == DeviceDetail.HardwareKeyKeyboard).Select(dd => dd.Value).FirstOrDefault(), csvStringEncoded) });
return metadata; return metadata;
} }
@@ -2,6 +2,7 @@
using Disco.Services.Tasks; using Disco.Services.Tasks;
using Quartz; using Quartz;
using Disco.Data.Repository; using Disco.Data.Repository;
using Disco.Services.Exporting;
namespace Disco.Services.Devices.Exporting namespace Disco.Services.Devices.Exporting
{ {
@@ -13,10 +14,10 @@ namespace Disco.Services.Devices.Exporting
public override bool SingleInstanceTask { get { return false; } } public override bool SingleInstanceTask { get { return false; } }
public override bool CancelInitiallySupported { get { return false; } } public override bool CancelInitiallySupported { get { return false; } }
public static DeviceExportTaskContext ScheduleNow(DeviceExportOptions Options) public static ExportTaskContext<DeviceExportOptions> ScheduleNow(DeviceExportOptions Options)
{ {
// Build Context // Build Context
var context = new DeviceExportTaskContext(Options); var context = new ExportTaskContext<DeviceExportOptions>(Options);
// Build Data Map // Build Data Map
var task = new DeviceExportTask(); var task = new DeviceExportTask();
@@ -30,7 +31,7 @@ namespace Disco.Services.Devices.Exporting
protected override void ExecuteTask() protected override void ExecuteTask()
{ {
var context = (DeviceExportTaskContext)ExecutionContext.JobDetail.JobDataMap[JobDataMapContext]; var context = (ExportTaskContext<DeviceExportOptions>)ExecutionContext.JobDetail.JobDataMap[JobDataMapContext];
Status.UpdateStatus(10, "Exporting Device Records", "Starting..."); Status.UpdateStatus(10, "Exporting Device Records", "Starting...");
@@ -1,19 +0,0 @@
using Disco.Models.Services.Devices.Exporting;
using Disco.Services.Tasks;
namespace Disco.Services.Devices.Exporting
{
public class DeviceExportTaskContext
{
public DeviceExportOptions Options { get; private set; }
public ScheduledTaskStatus TaskStatus { get; set; }
public DeviceExportResult Result { get; set; }
public DeviceExportTaskContext(DeviceExportOptions Options)
{
this.Options = Options;
}
}
}
@@ -2,6 +2,7 @@
using Disco.Models.Repository; using Disco.Models.Repository;
using Disco.Models.Services.Devices.Importing; using Disco.Models.Services.Devices.Importing;
using Disco.Services.Interop.ActiveDirectory; using Disco.Services.Interop.ActiveDirectory;
using Disco.Services.Logging;
using Disco.Services.Users; using Disco.Services.Users;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -147,7 +148,15 @@ namespace Disco.Services.Devices.Importing.Fields
if (adAccount != null && !adAccount.IsCriticalSystemObject) if (adAccount != null && !adAccount.IsCriticalSystemObject)
{ {
adAccount.SetDescription(Device); try
{
adAccount.SetDescription(Device);
}
catch (Exception ex)
{
SystemLog.LogWarning($"Unable to update AD Machine Account Description for {Device.DeviceDomainId}: {ex.Message}");
throw;
}
DeviceADDescriptionSet = true; DeviceADDescriptionSet = true;
} }
} }
@@ -35,7 +35,10 @@ namespace Disco.Services.Devices.Importing.Fields
try try
{ {
parsedValue = ActiveDirectory.ParseDomainAccountId(parsedValue); if (ActiveDirectory.IsValidDomainAccountId(parsedValue, out var accountUsername, out var accountDomain))
parsedValue = $@"{accountDomain.NetBiosName}\{accountUsername}";
else
return Error(@"The expected format is 'DOMAIN\ComputerName'");
} }
catch (ArgumentException ex) when (ex.ParamName == "NetBiosName") catch (ArgumentException ex) when (ex.ParamName == "NetBiosName")
{ {
@@ -2,6 +2,7 @@
using Disco.Models.Repository; using Disco.Models.Repository;
using Disco.Models.Services.Devices.Importing; using Disco.Models.Services.Devices.Importing;
using Disco.Services.Interop.ActiveDirectory; using Disco.Services.Interop.ActiveDirectory;
using Disco.Services.Logging;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
@@ -116,7 +117,15 @@ namespace Disco.Services.Devices.Importing.Fields
if (!DeviceADDescriptionSet) if (!DeviceADDescriptionSet)
{ {
adAccount.SetDescription(Device); try
{
adAccount.SetDescription(Device);
}
catch (Exception ex)
{
SystemLog.LogWarning($"Unable to update AD Machine Account Description for {Device.DeviceDomainId}: {ex.Message}");
throw;
}
DeviceADDescriptionSet = true; DeviceADDescriptionSet = true;
} }
} }
@@ -2,6 +2,7 @@
using Disco.Models.Repository; using Disco.Models.Repository;
using Disco.Models.Services.Devices.Importing; using Disco.Models.Services.Devices.Importing;
using Disco.Services.Interop.ActiveDirectory; using Disco.Services.Interop.ActiveDirectory;
using Disco.Services.Logging;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
@@ -120,7 +121,15 @@ namespace Disco.Services.Devices.Importing.Fields
if (!DeviceADDescriptionSet) if (!DeviceADDescriptionSet)
{ {
adAccount.SetDescription(Device); try
{
adAccount.SetDescription(Device);
}
catch (Exception ex)
{
SystemLog.LogWarning($"Unable to update AD Machine Account Description for {Device.DeviceDomainId}: {ex.Message}");
throw;
}
DeviceADDescriptionSet = true; DeviceADDescriptionSet = true;
} }
} }
@@ -2,6 +2,7 @@
using Disco.Models.Repository; using Disco.Models.Repository;
using Disco.Models.Services.Devices.Importing; using Disco.Models.Services.Devices.Importing;
using Disco.Services.Interop.ActiveDirectory; using Disco.Services.Interop.ActiveDirectory;
using Disco.Services.Logging;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
@@ -94,7 +95,15 @@ namespace Disco.Services.Devices.Importing.Fields
if (adAccount != null && !adAccount.IsCriticalSystemObject) if (adAccount != null && !adAccount.IsCriticalSystemObject)
{ {
adAccount.SetDescription(Device); try
{
adAccount.SetDescription(Device);
}
catch (Exception ex)
{
SystemLog.LogWarning($"Unable to update AD Machine Account Description for {Device.DeviceDomainId}: {ex.Message}");
throw;
}
DeviceADDescriptionSet = true; DeviceADDescriptionSet = true;
} }
} }
@@ -2,6 +2,7 @@
using Disco.Models.Repository; using Disco.Models.Repository;
using Disco.Models.Services.Devices.Importing; using Disco.Models.Services.Devices.Importing;
using Disco.Services.Interop.ActiveDirectory; using Disco.Services.Interop.ActiveDirectory;
using Disco.Services.Logging;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
@@ -90,7 +91,15 @@ namespace Disco.Services.Devices.Importing.Fields
if (adAccount != null && !adAccount.IsCriticalSystemObject) if (adAccount != null && !adAccount.IsCriticalSystemObject)
{ {
adAccount.SetDescription(Device); try
{
adAccount.SetDescription(Device);
}
catch (Exception ex)
{
SystemLog.LogWarning($"Unable to update AD Machine Account Description for {Device.DeviceDomainId}: {ex.Message}");
throw;
}
DeviceADDescriptionSet = true; DeviceADDescriptionSet = true;
} }
} }
+21 -5
View File
@@ -11,7 +11,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Disco.Services</RootNamespace> <RootNamespace>Disco.Services</RootNamespace>
<AssemblyName>Disco.Services</AssemblyName> <AssemblyName>Disco.Services</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<TargetFrameworkProfile /> <TargetFrameworkProfile />
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir> <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
@@ -94,8 +94,8 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\RazorGenerator.Mvc.2.2.3\lib\net40\RazorGenerator.Mvc.dll</HintPath> <HintPath>..\packages\RazorGenerator.Mvc.2.2.3\lib\net40\RazorGenerator.Mvc.dll</HintPath>
</Reference> </Reference>
<Reference Include="Renci.SshNet"> <Reference Include="Renci.SshNet, Version=2023.0.0.0, Culture=neutral, PublicKeyToken=1cee9f8bde3db106, processorArchitecture=MSIL">
<HintPath>..\..\..\Resources\Libraries\SshNet\Renci.SshNet.dll</HintPath> <HintPath>..\packages\SSH.NET.2023.0.0\lib\net462\Renci.SshNet.dll</HintPath>
</Reference> </Reference>
<Reference Include="Spring.Core"> <Reference Include="Spring.Core">
<HintPath>..\..\..\Resources\Libraries\Spring.NET\Spring.Core.dll</HintPath> <HintPath>..\..\..\Resources\Libraries\Spring.NET\Spring.Core.dll</HintPath>
@@ -194,6 +194,7 @@
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\ConfigClaims.cs" /> <Compile Include="Authorization\Roles\ClaimGroups\Configuration\ConfigClaims.cs" />
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\DeviceBatch\DeviceBatchClaims.cs" /> <Compile Include="Authorization\Roles\ClaimGroups\Configuration\DeviceBatch\DeviceBatchClaims.cs" />
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\DeviceCertificate\DeviceCertificateClaims.cs" /> <Compile Include="Authorization\Roles\ClaimGroups\Configuration\DeviceCertificate\DeviceCertificateClaims.cs" />
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\DeviceFlag\DeviceFlagClaims.cs" />
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\DeviceModel\DeviceModelClaims.cs" /> <Compile Include="Authorization\Roles\ClaimGroups\Configuration\DeviceModel\DeviceModelClaims.cs" />
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\DeviceProfile\DeviceProfileClaims.cs" /> <Compile Include="Authorization\Roles\ClaimGroups\Configuration\DeviceProfile\DeviceProfileClaims.cs" />
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\DocumentTemplate\DocumentTemplateClaims.cs" /> <Compile Include="Authorization\Roles\ClaimGroups\Configuration\DocumentTemplate\DocumentTemplateClaims.cs" />
@@ -240,14 +241,25 @@
<Compile Include="Devices\DeviceProfileExtensions.cs" /> <Compile Include="Devices\DeviceProfileExtensions.cs" />
<Compile Include="Devices\DeviceBatchUpdatesHub.cs" /> <Compile Include="Devices\DeviceBatchUpdatesHub.cs" />
<Compile Include="Devices\DeviceWirelessProfileExtensions.cs" /> <Compile Include="Devices\DeviceWirelessProfileExtensions.cs" />
<Compile Include="Devices\Enrolment\DeviceEnrolment.cs" /> <Compile Include="Devices\Enrolment\WindowsDeviceEnrolment.cs" />
<Compile Include="Devices\Enrolment\EnrolmentLog.cs" /> <Compile Include="Devices\Enrolment\EnrolmentLog.cs" />
<Compile Include="Devices\Enrolment\EnrolmentSafeException.cs" /> <Compile Include="Devices\Enrolment\EnrolmentSafeException.cs" />
<Compile Include="Devices\Enrolment\EnrolmentTypes.cs" /> <Compile Include="Devices\Enrolment\EnrolmentTypes.cs" />
<Compile Include="Devices\Enrolment\LogMacAddressImportingTask.cs" /> <Compile Include="Devices\Enrolment\LogMacAddressImportingTask.cs" />
<Compile Include="Devices\Enrolment\MacDeviceEnrolment.cs" />
<Compile Include="Devices\Exporting\DeviceExport.cs" /> <Compile Include="Devices\Exporting\DeviceExport.cs" />
<Compile Include="Devices\Exporting\DeviceExportTask.cs" /> <Compile Include="Devices\Exporting\DeviceExportTask.cs" />
<Compile Include="Devices\Exporting\DeviceExportTaskContext.cs" /> <Compile Include="Devices\DeviceFlags\Cache.cs" />
<Compile Include="Devices\DeviceFlags\DeviceFlagExport.cs" />
<Compile Include="Devices\DeviceFlags\DeviceFlagExportTask.cs" />
<Compile Include="Devices\DeviceFlags\DeviceFlagExtensions.cs" />
<Compile Include="Devices\DeviceFlags\DeviceFlagsBulkAssignTask.cs" />
<Compile Include="Devices\DeviceFlags\DeviceFlagsDeleteTask.cs" />
<Compile Include="Devices\DeviceFlags\DeviceFlagService.cs" />
<Compile Include="Devices\DeviceFlags\DeviceFlagDeviceAssignedUsersManagedGroup.cs" />
<Compile Include="Devices\DeviceFlags\DeviceFlagDevicesManagedGroup.cs" />
<Compile Include="Exporting\ExportHelpers.cs" />
<Compile Include="Exporting\ExportTaskContext.cs" />
<Compile Include="Devices\Importing\BaseDeviceImportContext.cs" /> <Compile Include="Devices\Importing\BaseDeviceImportContext.cs" />
<Compile Include="Devices\Importing\CsvDeviceImportDataReader.cs" /> <Compile Include="Devices\Importing\CsvDeviceImportDataReader.cs" />
<Compile Include="Devices\Importing\DeviceImport.cs" /> <Compile Include="Devices\Importing\DeviceImport.cs" />
@@ -317,6 +329,7 @@
<Compile Include="Expressions\Extensions\ImageResultImplementations\BitmapImageExpressionResult.cs" /> <Compile Include="Expressions\Extensions\ImageResultImplementations\BitmapImageExpressionResult.cs" />
<Compile Include="Expressions\Extensions\ImageResultImplementations\FileImageExpressionResult.cs" /> <Compile Include="Expressions\Extensions\ImageResultImplementations\FileImageExpressionResult.cs" />
<Compile Include="Expressions\Extensions\ImageResultImplementations\FileMontageImageExpressionResult.cs" /> <Compile Include="Expressions\Extensions\ImageResultImplementations\FileMontageImageExpressionResult.cs" />
<Compile Include="Expressions\Extensions\ImageResultImplementations\QrCodeImageExpressionResult.cs" />
<Compile Include="Expressions\Extensions\UserExt.cs" /> <Compile Include="Expressions\Extensions\UserExt.cs" />
<Compile Include="Expressions\IExpressionPart.cs" /> <Compile Include="Expressions\IExpressionPart.cs" />
<Compile Include="Expressions\LazyDictionary.cs" /> <Compile Include="Expressions\LazyDictionary.cs" />
@@ -343,6 +356,7 @@
<Compile Include="Interop\ActiveDirectory\ADMachineAccount.cs" /> <Compile Include="Interop\ActiveDirectory\ADMachineAccount.cs" />
<Compile Include="Interop\ActiveDirectory\ADManagedGroup.cs" /> <Compile Include="Interop\ActiveDirectory\ADManagedGroup.cs" />
<Compile Include="Interop\ActiveDirectory\ADManagedGroupsSyncTask.cs" /> <Compile Include="Interop\ActiveDirectory\ADManagedGroupsSyncTask.cs" />
<Compile Include="Interop\ActiveDirectory\ADEnforceDeviceProfileOrganisationalUnitTask.cs" />
<Compile Include="Interop\ActiveDirectory\ADOrganisationalUnit.cs" /> <Compile Include="Interop\ActiveDirectory\ADOrganisationalUnit.cs" />
<Compile Include="Interop\ActiveDirectory\ADSearchResult.cs" /> <Compile Include="Interop\ActiveDirectory\ADSearchResult.cs" />
<Compile Include="Interop\ActiveDirectory\ADSite.cs" /> <Compile Include="Interop\ActiveDirectory\ADSite.cs" />
@@ -459,6 +473,8 @@
<Compile Include="Users\Contact\UserContactService.cs" /> <Compile Include="Users\Contact\UserContactService.cs" />
<Compile Include="Users\UserExtensions.cs" /> <Compile Include="Users\UserExtensions.cs" />
<Compile Include="Users\UserFlags\Cache.cs" /> <Compile Include="Users\UserFlags\Cache.cs" />
<Compile Include="Users\UserFlags\UserFlagExport.cs" />
<Compile Include="Users\UserFlags\UserFlagExportTask.cs" />
<Compile Include="Users\UserFlags\UserFlagExtensions.cs" /> <Compile Include="Users\UserFlags\UserFlagExtensions.cs" />
<Compile Include="Users\UserFlags\UserFlagUserDevicesManagedGroup.cs" /> <Compile Include="Users\UserFlags\UserFlagUserDevicesManagedGroup.cs" />
<Compile Include="Users\UserFlags\UserFlagUsersManagedGroup.cs" /> <Compile Include="Users\UserFlags\UserFlagUsersManagedGroup.cs" />
@@ -113,18 +113,42 @@ namespace Disco.Services.Documents.AttachmentImport
{ {
var qrReader = new QRCodeMultiReader(); var qrReader = new QRCodeMultiReader();
var qrReaderHints = new Dictionary<DecodeHintType, object>() {
{ DecodeHintType.TRY_HARDER, true }
};
var qrImageSource = new BitmapLuminanceSource((Bitmap)Image); var qrImageSource = new BitmapLuminanceSource((Bitmap)Image);
var qrBinarizer = new HybridBinarizer(qrImageSource); var qrBinarizer = new HybridBinarizer(qrImageSource);
var qrBinaryBitmap = new BinaryBitmap(qrBinarizer); var qrBinaryBitmap = new BinaryBitmap(qrBinarizer);
Result DetectDocumentUniqueIdentifier(BinaryBitmap bitmap)
{
var qrReaderHints = new Dictionary<DecodeHintType, object>() {
{ DecodeHintType.TRY_HARDER, true }
};
var qrCodeResults = qrReader.decodeMultiple(bitmap, qrReaderHints);
if (qrCodeResults != null && qrCodeResults.Length > 0)
{
if (qrCodeResults.Length > 1)
{
// multiple qr codes on page, test for byte-mark
foreach (var qr in qrCodeResults)
{
if (qr.ResultMetadata.TryGetValue(ResultMetadataType.BYTE_SEGMENTS, out var byteSegments))
{
var qrBytes = ((List<byte[]>)byteSegments)[0];
if (DocumentUniqueIdentifier.IsDocumentUniqueIdentifier(qrBytes))
return qr;
}
}
}
return qrCodeResults[0];
}
return null;
}
try try
{ {
qrCodeResult = qrReader.decodeMultiple(qrBinaryBitmap, qrReaderHints)?.FirstOrDefault(); qrCodeResult = DetectDocumentUniqueIdentifier(qrBinaryBitmap);
qrCodeResultScale = 1F; qrCodeResultScale = 1F;
} }
catch (ReaderException) catch (ReaderException)
@@ -148,7 +172,7 @@ namespace Disco.Services.Documents.AttachmentImport
try try
{ {
qrCodeResult = qrReader.decodeMultiple(qrBinaryBitmap, qrReaderHints)?.FirstOrDefault(); qrCodeResult = DetectDocumentUniqueIdentifier(qrBinaryBitmap);
qrCodeResultScale = 1.75F; qrCodeResultScale = 1.75F;
} }
catch (ReaderException) catch (ReaderException)
@@ -171,7 +195,7 @@ namespace Disco.Services.Documents.AttachmentImport
try try
{ {
qrCodeResult = qrReader.decodeMultiple(qrBinaryBitmap, qrReaderHints)?.FirstOrDefault(); qrCodeResult = DetectDocumentUniqueIdentifier(qrBinaryBitmap);
qrCodeResultScale = 2F; qrCodeResultScale = 2F;
} }
catch (ReaderException) catch (ReaderException)
+33 -14
View File
@@ -8,8 +8,24 @@ namespace Disco.Services.Documents
{ {
public static class QRCodeBinaryEncoder public static class QRCodeBinaryEncoder
{ {
public static byte[] Encode(string content, ErrorCorrectionLevel ecLevel, out int width, out int height)
{
var code = Encoder.encode(content, ecLevel, null);
public static byte[] Encode(byte[] Content, int Width, int Height) var array = code.Matrix.Array;
width = code.Matrix.Width;
height = code.Matrix.Height;
return scaleMatrix(code.Matrix.Array, width, height);
}
public static byte[] Encode(string content, ErrorCorrectionLevel ecLevel, int width, int height)
{
var code = Encoder.encode(content, ecLevel, null);
return scaleMatrix(code.Matrix.Array, width, height);
}
public static byte[] Encode(byte[] content, out int width, out int height)
{ {
var ecLevel = ErrorCorrectionLevel.L; var ecLevel = ErrorCorrectionLevel.L;
var bits = new BitArray(); var bits = new BitArray();
@@ -17,7 +33,7 @@ namespace Disco.Services.Documents
var mode = Mode.BYTE; var mode = Mode.BYTE;
var bitsNeeded = 4 + var bitsNeeded = 4 +
mode.getCharacterCountBits(ZXing.QrCode.Internal.Version.getVersionForNumber(1)) + mode.getCharacterCountBits(ZXing.QrCode.Internal.Version.getVersionForNumber(1)) +
(Content.Length * 8); (content.Length * 8);
var version = ChooseVersion(bitsNeeded, out ecLevel); var version = ChooseVersion(bitsNeeded, out ecLevel);
var ecBlocks = version.getECBlocksForLevel(ecLevel); var ecBlocks = version.getECBlocksForLevel(ecLevel);
@@ -28,12 +44,12 @@ namespace Disco.Services.Documents
bits.appendBits(mode.Bits, 4); bits.appendBits(mode.Bits, 4);
// Write the number of bytes // Write the number of bytes
bits.appendBits(Content.Length, mode.getCharacterCountBits(version)); bits.appendBits(content.Length, mode.getCharacterCountBits(version));
// Write the bytes // Write the bytes
for (int i = 0; i < Content.Length; i++) for (int i = 0; i < content.Length; i++)
{ {
bits.appendBits(Content[i], 8); bits.appendBits(content[i], 8);
} }
// Terminate the bit stream // Terminate the bit stream
@@ -72,7 +88,10 @@ namespace Disco.Services.Documents
MatrixUtil.buildMatrix(finalBits, ecLevel, version, maskPattern, matrix); MatrixUtil.buildMatrix(finalBits, ecLevel, version, maskPattern, matrix);
// Render matrix to bytes // Render matrix to bytes
return scaleMatrix(matrix.Array, Width, Height); width = matrix.Width;
height = matrix.Height;
return scaleMatrix(matrix.Array, width, height);
//return FlattenMatrix(matrix.Array, width, height);
} }
private static ZXing.QrCode.Internal.Version ChooseVersion(int RequiredBits, out ErrorCorrectionLevel ECLevel) private static ZXing.QrCode.Internal.Version ChooseVersion(int RequiredBits, out ErrorCorrectionLevel ECLevel)
@@ -242,17 +261,17 @@ namespace Disco.Services.Documents
return bestMaskPattern; return bestMaskPattern;
} }
private static byte[] scaleMatrix(byte[][] matrix, int Width, int Height) private static byte[] scaleMatrix(byte[][] matrix, int width, int height)
{ {
var matrixWidth = matrix[0].Length; var matrixWidth = matrix[0].Length;
var matrixHeight = matrix.Length; var matrixHeight = matrix.Length;
Width = Math.Max(Width, matrixWidth); width = Math.Max(width, matrixWidth);
Height = Math.Max(Height, matrixHeight); height = Math.Max(height, matrixHeight);
var byteColumns = (Width + 7) / 8; var byteColumns = (width + 7) / 8;
var outputBytes = new byte[byteColumns * Height]; var outputBytes = new byte[byteColumns * height];
var scale = Math.Min(Width / (matrixWidth + 1), Height / (matrixHeight + 1)); var scale = Math.Max(1, Math.Min(width / (matrixWidth + 1), height / (matrixHeight + 1)));
var offsetX = (Width - (matrixWidth * scale)) / 2; var offsetX = (width - (matrixWidth * scale)) / 2;
var offsetY = (Height - (matrixHeight * scale)) / 2; var offsetY = (height - (matrixHeight * scale)) / 2;
// initialize output bytes // initialize output bytes
for (int i = 0; i < outputBytes.Length; i++) for (int i = 0; i < outputBytes.Length; i++)
{ {

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