Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5f4cb20900 | |||
| aee467cb53 | |||
| 6ce6e2cccf | |||
| cd858c2215 | |||
| 7e07c07171 | |||
| 15e2806731 | |||
| 53baf4eb78 | |||
| 8c48ab6ecd | |||
| 8afe4195a9 | |||
| dcc4fcb984 | |||
| 4631903019 | |||
| 85d51c0e45 | |||
| 974a07f3bb | |||
| b576aec641 | |||
| a2aaa4c913 | |||
| 318a70d9a3 | |||
| 53e57d4017 | |||
| 143dc1b3e6 | |||
| a4f18d1d49 | |||
| 46222f2a78 | |||
| 2e091383ec | |||
| 7ace4d1c7e | |||
| f901d45d78 | |||
| 028d1ccc64 | |||
| 7b6a44921d | |||
| 23406e5e39 | |||
| 83557e6f0c | |||
| 1c90c89158 | |||
| 9924153e82 | |||
| 3ec2ea7d37 | |||
| b6945d9bbd | |||
| 6740a7479a | |||
| a3fb09440d | |||
| 7353405b16 | |||
| 6fcb1a1eae | |||
| e204ea4d5f |
@@ -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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Entity;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using Disco.BI.Extensions;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.BI.Expressions;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Documents;
|
||||
using Disco.Models.Services.Expressions.Extensions;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Documents;
|
||||
using Disco.Services.Expressions;
|
||||
@@ -268,16 +268,15 @@ namespace Disco.BI.Interop.Pdf
|
||||
var pageUniqueIdBytes = pageUniqueId.ToQRCodeBytes();
|
||||
|
||||
// Encode to QRCode byte array
|
||||
var pageUniqueIdWidth = (int)pdfFieldPosition.position.Width;
|
||||
var pageUniqueIdHeight = (int)pdfFieldPosition.position.Height;
|
||||
var pageUniqueIdEncoded = QRCodeBinaryEncoder.Encode(pageUniqueIdBytes, pageUniqueIdWidth, pageUniqueIdHeight);
|
||||
var pageUniqueIdEncoded = QRCodeBinaryEncoder.Encode(pageUniqueIdBytes, out var qrWidth, out var qrHeight);
|
||||
|
||||
// Encode byte array to Image
|
||||
var pageUniqueIdImageData = CCITTG4Encoder.Compress(pageUniqueIdEncoded, pageUniqueIdWidth, pageUniqueIdHeight);
|
||||
var pageUniqueIdImage = iTextSharp.text.Image.GetInstance(pageUniqueIdWidth, pageUniqueIdHeight, false, 256, 1, pageUniqueIdImageData, null);
|
||||
var pageUniqueIdImageData = CCITTG4Encoder.Compress(pageUniqueIdEncoded, qrWidth, qrHeight);
|
||||
var pageUniqueIdImage = iTextSharp.text.Image.GetInstance(qrWidth, qrHeight, false, 256, 1, pageUniqueIdImageData, null);
|
||||
|
||||
// Add to the pdf page
|
||||
pageUniqueIdImage.SetAbsolutePosition(pdfFieldPosition.position.Left, pdfFieldPosition.position.Bottom);
|
||||
pageUniqueIdImage.ScaleToFit(pdfFieldPosition.position.Width, pdfFieldPosition.position.Height);
|
||||
pdfStamper.GetOverContent(pdfFieldPosition.page).AddImage(pageUniqueIdImage);
|
||||
}
|
||||
// Hide Fields
|
||||
@@ -315,7 +314,22 @@ namespace Disco.BI.Interop.Pdf
|
||||
for (int pdfFieldOrdinal = 0; pdfFieldOrdinal < fields.Size; 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.ScaleToFit(pdfFieldPosition.position.Width, pdfFieldPosition.position.Height);
|
||||
pdfStamper.GetOverContent(pdfFieldPosition.page).AddImage(pdfImage);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using iTextSharp.text;
|
||||
using iTextSharp.text.pdf;
|
||||
using iTextSharp.text.pdf.codec;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
@@ -7,6 +9,11 @@ namespace Disco.BI.Interop.Pdf
|
||||
{
|
||||
public static class Utilities
|
||||
{
|
||||
public static Func<byte[], int, int, byte[]> GetCCITTG4EncoderCompressDelegate()
|
||||
{
|
||||
return CCITTG4Encoder.Compress;
|
||||
}
|
||||
|
||||
public static Stream JoinPdfs(bool InsertBlankPages, List<Stream> Pdfs)
|
||||
{
|
||||
if (Pdfs.Count == 0)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Disco</RootNamespace>
|
||||
<AssemblyName>Disco.BI</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 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
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("2.2.16326.0500")]
|
||||
[assembly: AssemblyFileVersion("2.2.16326.0500")]
|
||||
[assembly: AssemblyVersion("2.3.23161.0650")]
|
||||
[assembly: AssemblyFileVersion("2.3.23161.0650")]
|
||||
+1
-1
@@ -19,7 +19,7 @@ namespace Disco.Properties {
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// 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.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
+22
-22
@@ -1,56 +1,56 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<!-- 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>
|
||||
<system.serviceModel>
|
||||
<bindings />
|
||||
<client />
|
||||
<bindings/>
|
||||
<client/>
|
||||
</system.serviceModel>
|
||||
<entityFramework>
|
||||
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
|
||||
<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>
|
||||
</defaultConnectionFactory>
|
||||
</entityFramework>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
|
||||
</startup>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
|
||||
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
|
||||
<assemblyIdentity name="System.Web.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<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" />
|
||||
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
|
||||
<assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0" />
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0" />
|
||||
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
@@ -331,7 +331,7 @@ namespace Disco.Client.Interop
|
||||
}
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace Disco.Client.Interop
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace Disco.Client.Interop
|
||||
}
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 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
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("2.2.16326.0500")]
|
||||
[assembly: AssemblyFileVersion("2.2.16326.0500")]
|
||||
[assembly: AssemblyVersion("2.3.23161.0650")]
|
||||
[assembly: AssemblyFileVersion("2.3.23161.0650")]
|
||||
@@ -85,12 +85,12 @@ namespace Disco.ClientBootstrapper
|
||||
|
||||
// Check for Network Connectivity
|
||||
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_WriteAdapterInfo();
|
||||
|
||||
if (!Interop.NetworkInterop.PingDisco(DiscoServerName))
|
||||
if (!Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
|
||||
{
|
||||
// Check for Wireless
|
||||
var hasWireless = (Interop.NetworkInterop.NetworkAdapters.Count(na => na.IsWireless) > 0);
|
||||
@@ -105,17 +105,17 @@ namespace Disco.ClientBootstrapper
|
||||
statusUI_WriteAdapterInfo();
|
||||
statusUI.UpdateStatus(null, null, null, true, i);
|
||||
Program.SleepThread(500, false);
|
||||
if (Interop.NetworkInterop.PingDisco(DiscoServerName))
|
||||
if (Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
|
||||
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);
|
||||
Program.SleepThread(3000, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Interop.NetworkInterop.PingDisco(DiscoServerName))
|
||||
if (!Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
|
||||
{
|
||||
// Instruct user to connect network cable
|
||||
statusUI.UpdateStatus(null, "Please connect the network cable", null);
|
||||
@@ -124,13 +124,13 @@ namespace Disco.ClientBootstrapper
|
||||
statusUI_WriteAdapterInfo();
|
||||
statusUI.UpdateStatus(null, null, null, true, i);
|
||||
Program.SleepThread(500, false);
|
||||
if (Interop.NetworkInterop.PingDisco(DiscoServerName))
|
||||
if (Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Interop.NetworkInterop.PingDisco(DiscoServerName))
|
||||
if (!Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
|
||||
{
|
||||
// Client Failed
|
||||
if (this.mLoopCompleteCallback != null)
|
||||
|
||||
@@ -8,4 +8,4 @@ BootstrapperLocation = Mid(WScript.ScriptFullName, 1, InStrRev(WScript.ScriptFul
|
||||
|
||||
Call objShell.Run("""" & BootstrapperLocation & """ /Install", , True)
|
||||
|
||||
WScript.Echo "Disco Client Bootstrapper Installed"
|
||||
WScript.Echo "Disco ICT Client Bootstrapper Installed"
|
||||
+2
-2
@@ -85,7 +85,7 @@
|
||||
this.labelVersion.Name = "labelVersion";
|
||||
this.labelVersion.Size = new System.Drawing.Size(167, 20);
|
||||
this.labelVersion.TabIndex = 0;
|
||||
this.labelVersion.Text = "Disco Bootstrapper v";
|
||||
this.labelVersion.Text = "Disco ICT Bootstrapper v";
|
||||
this.labelVersion.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||
//
|
||||
// FormStatus
|
||||
@@ -106,7 +106,7 @@
|
||||
this.ShowIcon = false;
|
||||
this.ShowInTaskbar = false;
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "Disco - Client Bootstrapper";
|
||||
this.Text = "Disco ICT - Client Bootstrapper";
|
||||
this.TopMost = true;
|
||||
this.TransparencyKey = System.Drawing.Color.Magenta;
|
||||
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())
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 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
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("2.2.16326.0500")]
|
||||
[assembly: AssemblyFileVersion("2.2.16326.0500")]
|
||||
[assembly: AssemblyVersion("2.3.23161.0650")]
|
||||
[assembly: AssemblyFileVersion("2.3.23161.0650")]
|
||||
@@ -15,6 +15,6 @@
|
||||
</defaultConnectionFactory>
|
||||
</entityFramework>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
@@ -10,7 +10,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Disco.Data</RootNamespace>
|
||||
<AssemblyName>Disco.Data</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
@@ -175,6 +175,10 @@
|
||||
<Compile Include="Migrations\202304150715559_DBv22.Designer.cs">
|
||||
<DependentUpon>202304150715559_DBv22.cs</DependentUpon>
|
||||
</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\DiscoDataMigrator.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
@@ -256,6 +260,9 @@
|
||||
<EmbeddedResource Include="Migrations\202304150715559_DBv22.resx">
|
||||
<DependentUpon>202304150715559_DBv22.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Migrations\202401130531317_DBv23.resx">
|
||||
<DependentUpon>202401130531317_DBv23.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
|
||||
@@ -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
@@ -1,4 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 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
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("2.2.16326.0500")]
|
||||
[assembly: AssemblyFileVersion("2.2.16326.0500")]
|
||||
[assembly: AssemblyVersion("2.3.23161.0650")]
|
||||
[assembly: AssemblyFileVersion("2.3.23161.0650")]
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 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
|
||||
// the code is regenerated.
|
||||
@@ -19,7 +19,7 @@ namespace Disco.Data.Properties {
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// 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.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.Repository;
|
||||
using System;
|
||||
using System.Data.Entity;
|
||||
using Disco.Models.Repository;
|
||||
using System.Data.Entity.ModelConfiguration.Conventions;
|
||||
|
||||
namespace Disco.Data.Repository
|
||||
@@ -38,6 +35,8 @@ namespace Disco.Data.Repository
|
||||
public virtual DbSet<DeviceBatchAttachment> DeviceBatchAttachments { get; set; }
|
||||
public virtual DbSet<DeviceComponent> DeviceComponents { 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; }
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
using System.DirectoryServices.ActiveDirectory;
|
||||
using System.DirectoryServices;
|
||||
using System.DirectoryServices.ActiveDirectory;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.Data.Repository
|
||||
{
|
||||
@@ -370,7 +368,7 @@ DELETE [Users] WHERE [Id]=@IdExisting;";
|
||||
string defaultNamingContext;
|
||||
using (Domain d = Domain.GetComputerDomain())
|
||||
{
|
||||
string ldapPath = string.Format("LDAP://{0}/", d.Name);
|
||||
string ldapPath = $"LDAP://{d.Name}/";
|
||||
string configurationNamingContext;
|
||||
|
||||
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))
|
||||
{
|
||||
var configSearchFilter = string.Format("(&(objectcategory=Crossref)(dnsRoot={0})(netBIOSName=*))", d.Name);
|
||||
var configSearchFilter = $"(&(objectcategory=Crossref)(dnsRoot={d.Name})(netBIOSName=*))";
|
||||
var configSearchLoadProperites = new string[] { "NetBIOSName" };
|
||||
|
||||
using (var configSearcher = new DirectorySearcher(configSearchRoot, configSearchFilter, configSearchLoadProperites, SearchScope.OneLevel))
|
||||
@@ -403,14 +401,14 @@ DELETE [Users] WHERE [Id]=@IdExisting;";
|
||||
// Authorization Roles
|
||||
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)
|
||||
authRole.SubjectIds = ids;
|
||||
}
|
||||
// Job Queues
|
||||
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)
|
||||
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())
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(deviceProfile.OrganisationalUnit))
|
||||
deviceProfile.OrganisationalUnit = string.Format("CN=Computers,{0}", defaultNamingContext);
|
||||
deviceProfile.OrganisationalUnit = $"CN=Computers,{defaultNamingContext}";
|
||||
else
|
||||
deviceProfile.OrganisationalUnit = string.Format("{0},{1}", deviceProfile.OrganisationalUnit, defaultNamingContext);
|
||||
deviceProfile.OrganisationalUnit = $"{deviceProfile.OrganisationalUnit},{defaultNamingContext}";
|
||||
}
|
||||
Database.SaveChanges();
|
||||
|
||||
@@ -451,7 +449,7 @@ DELETE [Users] WHERE [Id]=@IdExisting;";
|
||||
// MIGRATE DEVICES
|
||||
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();
|
||||
|
||||
@@ -462,7 +460,7 @@ DELETE [Users] WHERE [Id]=@IdExisting;";
|
||||
idExisting.Value = user.UserId;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace Disco.Data.Repository
|
||||
var connectionString = DiscoDataContextConnectionString;
|
||||
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)
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
</defaultConnectionFactory>
|
||||
</entityFramework>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
@@ -10,7 +10,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Disco.Models</RootNamespace>
|
||||
<AssemblyName>Disco.Models</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
@@ -49,6 +49,14 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<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\Battery.cs" />
|
||||
<Compile Include="ClientServices\EnrolmentInformation\Bios.cs" />
|
||||
@@ -65,13 +73,13 @@
|
||||
<Compile Include="ClientServices\EnrolmentInformation\WirelessProfileStore.cs" />
|
||||
<Compile Include="ClientServices\EnrolmentInformation\WirelessProfileTransformation.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\IDeviceImportDataReader.cs" />
|
||||
<Compile Include="Services\Documents\DocumentField.cs" />
|
||||
<Compile Include="Services\Documents\DocumentFieldType.cs" />
|
||||
<Compile Include="Services\Documents\DocumentTemplatePackage.cs" />
|
||||
<Compile Include="Services\Documents\OnImportUserFlagRule.cs" />
|
||||
<Compile Include="Exporting\IExportOptions.cs" />
|
||||
<Compile Include="Services\Jobs\LocationModes.cs" />
|
||||
<Compile Include="ClientServices\EnrolmentInformation\Certificate.cs" />
|
||||
<Compile Include="ClientServices\Register.cs" />
|
||||
@@ -86,7 +94,7 @@
|
||||
<Compile Include="Services\Authorization\IClaimNavigatorItem.cs" />
|
||||
<Compile Include="Services\Authorization\IRoleToken.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="ClientServices\EnrolResponse.cs" />
|
||||
<Compile Include="ClientServices\MacEnrol.cs" />
|
||||
@@ -125,7 +133,7 @@
|
||||
<Compile Include="Repository\User\UserDetail.cs" />
|
||||
<Compile Include="Repository\User\AuthorizationRole.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\DeviceExportOptions.cs" />
|
||||
<Compile Include="Services\Devices\Importing\DeviceImportFieldTypes.cs" />
|
||||
@@ -154,6 +162,8 @@
|
||||
<Compile Include="Services\Searching\ISearchResultItem.cs" />
|
||||
<Compile Include="Services\Searching\JobSearchResultItem.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\Config\AuthorizationRole\ConfigAuthorizationRoleCreateModel.cs" />
|
||||
<Compile Include="UI\Config\AuthorizationRole\ConfigAuthorizationRoleIndexModel.cs" />
|
||||
@@ -192,9 +202,14 @@
|
||||
<Compile Include="UI\Config\Shared\ConfigSharedDeviceGroupDocumentTemplateBulkGenerate.cs" />
|
||||
<Compile Include="UI\Config\Shared\ConfigSharedTaskStatusModel.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\ConfigUserFlagIndexModel.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\DeviceExportModel.cs" />
|
||||
<Compile Include="UI\Device\DeviceImportHeadersModel.cs" />
|
||||
|
||||
+5
-5
@@ -1,16 +1,16 @@
|
||||
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 ColumnName { 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 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;
|
||||
ValueType = valueType;
|
||||
@@ -18,7 +18,7 @@ namespace Disco.Models.Services.Devices.Exporting
|
||||
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)
|
||||
{
|
||||
ColumnName = columnName;
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Disco.Models.Exporting
|
||||
{
|
||||
public enum ExportFormat
|
||||
{
|
||||
Csv,
|
||||
Xlsx,
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Disco.Models.Exporting
|
||||
{
|
||||
public interface IExportRecord
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 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
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("2.2.16326.0500")]
|
||||
[assembly: AssemblyFileVersion("2.2.16326.0500")]
|
||||
[assembly: AssemblyVersion("2.3.23161.0650")]
|
||||
[assembly: AssemblyFileVersion("2.3.23161.0650")]
|
||||
@@ -51,6 +51,7 @@ namespace Disco.Models.Repository
|
||||
|
||||
[InverseProperty("DeviceSerialNumber")]
|
||||
public virtual IList<Job> Jobs { get; set; }
|
||||
public virtual IList<DeviceFlagAssignment> DeviceFlagAssignments { get; set; }
|
||||
|
||||
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
|
||||
{
|
||||
public class DeviceExportOptions
|
||||
public class DeviceExportOptions : IExportOptions
|
||||
{
|
||||
public DeviceExportTypes ExportType { 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
|
||||
[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; }
|
||||
[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")]
|
||||
[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")]
|
||||
[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")]
|
||||
[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")]
|
||||
[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; }
|
||||
@@ -136,7 +141,7 @@ namespace Disco.Models.Services.Devices.Exporting
|
||||
return new DeviceExportOptions()
|
||||
{
|
||||
ExportType = DeviceExportTypes.All,
|
||||
ExcelFormat = true,
|
||||
Format = ExportFormat.Xlsx,
|
||||
DeviceSerialNumber = true,
|
||||
ModelId = true,
|
||||
ProfileId = true,
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
using Disco.Models.ClientServices.EnrolmentInformation;
|
||||
using Disco.Models.Exporting;
|
||||
using Disco.Models.Repository;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Disco.Models.Services.Devices.Exporting
|
||||
{
|
||||
public class DeviceExportRecord
|
||||
public class DeviceExportRecord : IExportRecord
|
||||
{
|
||||
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;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Disco.Models.Services.Devices.Exporting
|
||||
namespace Disco.Models.Services.Devices.Exporting
|
||||
{
|
||||
public enum DeviceExportTypes
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Disco.Models.Services.Devices.Importing
|
||||
DeviceLocation,
|
||||
[Display(Name = "Device Enrolment Trusted", Description = "The device is trusted to complete an unauthenticated enrolment")]
|
||||
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,
|
||||
[Display(Name = "Device Decommissioned Reason", Description = "The reason the device was decommissioned")]
|
||||
DeviceDecommissionedReason,
|
||||
|
||||
+4
-4
@@ -1,13 +1,13 @@
|
||||
using System.IO;
|
||||
|
||||
namespace Disco.Models.BI.Expressions
|
||||
namespace Disco.Models.Services.Expressions.Extensions
|
||||
{
|
||||
public interface IImageExpressionResult
|
||||
{
|
||||
Stream GetImage(int Width, int Height);
|
||||
Stream GetImage();
|
||||
MemoryStream GetImage(int width, int height);
|
||||
MemoryStream GetImage(out int width, out int height);
|
||||
byte Quality { get; set; }
|
||||
bool LosslessFormat { get; set; }
|
||||
ImageExpressionFormat Format { get; set; }
|
||||
bool ShowField { get; set; }
|
||||
string BackgroundColour { 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.Linq;
|
||||
using System.Text;
|
||||
@@ -44,6 +45,7 @@ namespace Disco.Models.Services.Searching
|
||||
public string DeviceBatchName { get; set; }
|
||||
public int JobCount { get; set; }
|
||||
public DateTime? DecommissionedDate { get; set; }
|
||||
public IList<DeviceFlagAssignment> DeviceFlagAssignments { get; set; }
|
||||
|
||||
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; }
|
||||
OrganisationAddress DefaultOrganisationAddress { get; set; }
|
||||
|
||||
List<OrganisationAddress> OrganisationAddresses { get; set; }
|
||||
|
||||
string FriendlyOrganisationalUnitName { get; }
|
||||
bool OrganisationalUnitExists { get; set; }
|
||||
|
||||
int DeviceCount { 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; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Disco.Models.Services.Devices.Exporting;
|
||||
using Disco.Models.Services.Exporting;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Disco.Models.UI.Device
|
||||
@@ -8,7 +9,7 @@ namespace Disco.Models.UI.Device
|
||||
DeviceExportOptions Options { 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>> DeviceModels { get; set; }
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Disco.Models.BI.Config;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Documents;
|
||||
using Disco.Models.Services.Jobs.JobLists;
|
||||
using System.Collections.Generic;
|
||||
@@ -10,9 +11,11 @@ namespace Disco.Models.UI.Device
|
||||
Repository.Device Device { get; set; }
|
||||
|
||||
List<Repository.DeviceProfile> DeviceProfiles { get; set; }
|
||||
HashSet<int> DecommissionedDeviceProfileIds { get; set; }
|
||||
OrganisationAddress DeviceProfileDefaultOrganisationAddress { get; set; }
|
||||
|
||||
List<Repository.DeviceBatch> DeviceBatches { get; set; }
|
||||
HashSet<int> DecommissionedDeviceBatchIds { get; set; }
|
||||
|
||||
JobTableModel Jobs { get; set; }
|
||||
|
||||
@@ -20,6 +23,9 @@ namespace Disco.Models.UI.Device
|
||||
|
||||
List<Repository.DocumentTemplate> DocumentTemplates { get; set; }
|
||||
List<DocumentTemplatePackage> DocumentTemplatePackages { get; set; }
|
||||
|
||||
List<DeviceFlag> AvailableDeviceFlags { get; set; }
|
||||
|
||||
Dictionary<string, string> AssignedUserDetails { get; set; }
|
||||
bool HasAssignedUserPhoto { get; set; }
|
||||
}
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
|
||||
</startup>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
|
||||
<assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0" />
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0" />
|
||||
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
|
||||
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<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" />
|
||||
<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"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
+2
-1
@@ -9,9 +9,10 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Disco.Services.Plugins.ManifestGenerator</RootNamespace>
|
||||
<AssemblyName>Disco.Services.Plugins.ManifestGenerator</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Disco.Services.Plugins.ManifestGenerator
|
||||
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.AssemblyResolve += CurrentDomain_AssemblyResolve;
|
||||
@@ -55,7 +55,7 @@ namespace Disco.Services.Plugins.ManifestGenerator
|
||||
}
|
||||
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());
|
||||
|
||||
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 packageFilePath = Path.Combine(assemblyFileInfo.DirectoryName, packageFileName);
|
||||
@@ -81,7 +81,7 @@ namespace Disco.Services.Plugins.ManifestGenerator
|
||||
existingPackages.Delete();
|
||||
}
|
||||
|
||||
// Exclude Disco Provided Assemblies
|
||||
// Exclude Disco ICT Provided Assemblies
|
||||
List<string> excludedFiles = PluginManifest.PluginExcludedAssemblies.ToList();
|
||||
|
||||
// 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.InteropServices;
|
||||
|
||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("2.0.16326.0500")]
|
||||
[assembly: AssemblyFileVersion("2.0.16326.0500")]
|
||||
[assembly: AssemblyVersion("2.3.23161.0650")]
|
||||
[assembly: AssemblyFileVersion("2.3.23161.0650")]
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</defaultConnectionFactory>
|
||||
</entityFramework>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
|
||||
</startup>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Disco.Services.Authorization
|
||||
{
|
||||
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
|
||||
{
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Disco.Services.Authorization
|
||||
#region Token Accessors
|
||||
|
||||
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 RequireMessageSingleTemplate = RequireMessageTemplate + "This feature requires the following permission:\r\n- {0}";
|
||||
internal const string RequireAllMessageTemplate = RequireMessageTemplate + "This feature requires permission for:\r\n- {0}";
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
|
||||
|
||||
|
||||
// <auto-generated />
|
||||
// <auto-generated />
|
||||
// This file was generated by a T4 template.
|
||||
// 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.
|
||||
@@ -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.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.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.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) },
|
||||
@@ -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.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.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.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) },
|
||||
@@ -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.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.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.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.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.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.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.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.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.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.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.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) },
|
||||
@@ -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.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) },
|
||||
{ "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
|
||||
|
||||
#region Role Claim Navigator
|
||||
_claimNavigator =
|
||||
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.Configure", 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.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.ConfigureComponents", 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.Create", false),
|
||||
new ClaimNavigatorItem("Config.UserFlag.Delete", false),
|
||||
new ClaimNavigatorItem("Config.UserFlag.Export", false),
|
||||
new ClaimNavigatorItem("Config.UserFlag.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.Actions", "Actions", "Permissions related to Device Actions", false, new List<IClaimNavigatorItem>() {
|
||||
new ClaimNavigatorItem("Device.Actions.AddAttachments", false),
|
||||
new ClaimNavigatorItem("Device.Actions.AddFlags", false),
|
||||
new ClaimNavigatorItem("Device.Actions.AllowUnauthenticatedEnrol", false),
|
||||
new ClaimNavigatorItem("Device.Actions.AssignUser", false),
|
||||
new ClaimNavigatorItem("Device.Actions.Decommission", false),
|
||||
new ClaimNavigatorItem("Device.Actions.Delete", false),
|
||||
new ClaimNavigatorItem("Device.Actions.EditFlags", false),
|
||||
new ClaimNavigatorItem("Device.Actions.EnrolDevices", false),
|
||||
new ClaimNavigatorItem("Device.Actions.Export", false),
|
||||
new ClaimNavigatorItem("Device.Actions.GenerateDocuments", false),
|
||||
new ClaimNavigatorItem("Device.Actions.Import", false),
|
||||
new ClaimNavigatorItem("Device.Actions.Recommission", false),
|
||||
new ClaimNavigatorItem("Device.Actions.RemoveAnyAttachments", false),
|
||||
new ClaimNavigatorItem("Device.Actions.RemoveFlags", false),
|
||||
new ClaimNavigatorItem("Device.Actions.RemoveOwnAttachments", false)
|
||||
}),
|
||||
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.ShowCertificates", false),
|
||||
new ClaimNavigatorItem("Device.ShowDetails", false),
|
||||
new ClaimNavigatorItem("Device.ShowFlagAssignments", false),
|
||||
new ClaimNavigatorItem("Device.Show", false),
|
||||
new ClaimNavigatorItem("Device.ShowJobs", false)
|
||||
}),
|
||||
@@ -550,6 +569,11 @@ namespace Disco.Services.Authorization
|
||||
c.Config.DeviceBatch.Delete = true;
|
||||
c.Config.DeviceBatch.Show = 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.Configure = true;
|
||||
c.Config.DeviceModel.Delete = true;
|
||||
@@ -593,6 +617,7 @@ namespace Disco.Services.Authorization
|
||||
c.Config.UserFlag.Configure = true;
|
||||
c.Config.UserFlag.Create = true;
|
||||
c.Config.UserFlag.Delete = true;
|
||||
c.Config.UserFlag.Export = true;
|
||||
c.Config.UserFlag.Show = true;
|
||||
c.Config.Show = true;
|
||||
c.Job.Lists.AllOpen = true;
|
||||
@@ -701,22 +726,26 @@ namespace Disco.Services.Authorization
|
||||
c.Device.Properties.DeviceProfile = true;
|
||||
c.Device.Properties.Location = true;
|
||||
c.Device.Actions.AddAttachments = true;
|
||||
c.Device.Actions.AddFlags = true;
|
||||
c.Device.Actions.AllowUnauthenticatedEnrol = true;
|
||||
c.Device.Actions.AssignUser = true;
|
||||
c.Device.Actions.Decommission = true;
|
||||
c.Device.Actions.Delete = true;
|
||||
c.Device.Actions.EditFlags = true;
|
||||
c.Device.Actions.EnrolDevices = true;
|
||||
c.Device.Actions.Export = true;
|
||||
c.Device.Actions.GenerateDocuments = true;
|
||||
c.Device.Actions.Import = true;
|
||||
c.Device.Actions.Recommission = true;
|
||||
c.Device.Actions.RemoveAnyAttachments = true;
|
||||
c.Device.Actions.RemoveFlags = true;
|
||||
c.Device.Actions.RemoveOwnAttachments = true;
|
||||
c.Device.Search = true;
|
||||
c.Device.ShowAssignmentHistory = true;
|
||||
c.Device.ShowAttachments = true;
|
||||
c.Device.ShowCertificates = true;
|
||||
c.Device.ShowDetails = true;
|
||||
c.Device.ShowFlagAssignments = true;
|
||||
c.Device.Show = true;
|
||||
c.Device.ShowJobs = true;
|
||||
c.User.Actions.AddAttachments = true;
|
||||
@@ -749,7 +778,7 @@ namespace Disco.Services.Authorization
|
||||
#region Role Claim Constants
|
||||
|
||||
/// <summary>Configuration
|
||||
/// <para>Permissions related to Disco Configuration</para>
|
||||
/// <para>Permissions related to Disco ICT Configuration</para>
|
||||
/// </summary>
|
||||
public static class Config
|
||||
{
|
||||
@@ -825,6 +854,38 @@ namespace Disco.Services.Authorization
|
||||
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
|
||||
/// <para>Permissions related to Device Models</para>
|
||||
/// </summary>
|
||||
@@ -1109,6 +1170,11 @@ namespace Disco.Services.Authorization
|
||||
/// </summary>
|
||||
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
|
||||
/// <para>Can show user flags</para>
|
||||
/// </summary>
|
||||
@@ -1726,6 +1792,11 @@ namespace Disco.Services.Authorization
|
||||
/// </summary>
|
||||
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
|
||||
/// <para>Can allow devices to enrol without authentication</para>
|
||||
/// </summary>
|
||||
@@ -1746,6 +1817,11 @@ namespace Disco.Services.Authorization
|
||||
/// </summary>
|
||||
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
|
||||
/// <para>Can add devices offline and enrol devices with the Bootstrapper</para>
|
||||
/// </summary>
|
||||
@@ -1776,6 +1852,11 @@ namespace Disco.Services.Authorization
|
||||
/// </summary>
|
||||
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
|
||||
/// <para>Can remove own attachments from devices</para>
|
||||
/// </summary>
|
||||
@@ -1807,6 +1888,11 @@ namespace Disco.Services.Authorization
|
||||
/// </summary>
|
||||
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
|
||||
/// <para>Can show devices</para>
|
||||
/// </summary>
|
||||
@@ -1918,7 +2004,7 @@ namespace Disco.Services.Authorization
|
||||
public const string ComputerAccount = "ComputerAccount";
|
||||
|
||||
/// <summary>Disco Administrator Account
|
||||
/// <para>Represents a Disco Administrator account</para>
|
||||
/// <para>Represents a Disco ICT Administrator account</para>
|
||||
/// </summary>
|
||||
public const string DiscoAdminAccount = "DiscoAdminAccount";
|
||||
#endregion
|
||||
|
||||
@@ -20,9 +20,6 @@
|
||||
<#@ import namespace="System.Runtime.InteropServices.CustomMarshalers" #>
|
||||
<#@ import namespace="System.Runtime.InteropServices" #>
|
||||
<#@ import namespace="System.Reflection" #>
|
||||
|
||||
|
||||
|
||||
<#
|
||||
// Get the DTE service from the host
|
||||
EnvDTE.DTE Dte = null;
|
||||
|
||||
@@ -14,7 +14,7 @@ using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.UserFlag;
|
||||
|
||||
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 ConfigClaims()
|
||||
@@ -22,6 +22,7 @@ namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration
|
||||
DeviceCertificate = new DeviceCertificateClaims();
|
||||
Enrolment = new EnrolmentClaims();
|
||||
DeviceBatch = new DeviceBatchClaims();
|
||||
DeviceFlag = new DeviceFlagClaims();
|
||||
DeviceModel = new DeviceModelClaims();
|
||||
DeviceProfile = new DeviceProfileClaims();
|
||||
DocumentTemplate = new DocumentTemplateClaims();
|
||||
@@ -43,6 +44,8 @@ namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration
|
||||
|
||||
public DeviceBatchClaims DeviceBatch { get; set; }
|
||||
|
||||
public DeviceFlagClaims DeviceFlag { get; set; }
|
||||
|
||||
public DeviceModelClaims DeviceModel { get; set; }
|
||||
|
||||
public DeviceProfileClaims DeviceProfile { get; set; }
|
||||
|
||||
+20
@@ -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; }
|
||||
}
|
||||
}
|
||||
+2
@@ -11,6 +11,8 @@
|
||||
|
||||
[ClaimDetails("Delete User Flags", "Can delete user flags")]
|
||||
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")]
|
||||
public bool Show { get; set; }
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
|
||||
[ClaimDetails("Generate Documents", "Can generate documents for jobs")]
|
||||
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")]
|
||||
public bool EnrolDevices { get; set; }
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
public bool ShowJobs { get; set; }
|
||||
[ClaimDetails("Show Assignment History", "Can show the assignment history for devices")]
|
||||
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; }
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ namespace Disco.Services.Authorization.Roles
|
||||
}
|
||||
|
||||
/// <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.
|
||||
/// </summary>
|
||||
private static void MigrateAuthorizationRoles(DiscoDataContext Database)
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Disco.Services.Authorization.Roles
|
||||
[ClaimDetails("Computer Account", "Represents a computer account", true)]
|
||||
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 ConfigClaims Config { get; set; }
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Disco.Services
|
||||
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
EnrolResponse response = DeviceEnrolment.Enrol(database, username, request);
|
||||
EnrolResponse response = WindowsDeviceEnrolment.Enrol(database, username, request);
|
||||
database.SaveChanges();
|
||||
return response;
|
||||
}
|
||||
@@ -61,7 +61,7 @@ namespace Disco.Services
|
||||
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
MacEnrolResponse response = DeviceEnrolment.MacEnrol(database, request, false);
|
||||
MacEnrolResponse response = MacDeviceEnrolment.Enrol(database, request, false);
|
||||
database.SaveChanges();
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using Disco.Services.Authorization;
|
||||
using Disco.Services.Documents;
|
||||
using Disco.Services.Expressions;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Logging;
|
||||
using Disco.Services.Users;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -189,8 +190,17 @@ namespace Disco.Services
|
||||
{
|
||||
var adMachineAccount = ActiveDirectory.RetrieveADMachineAccount(d.DeviceDomainId);
|
||||
if (adMachineAccount != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
adMachineAccount.SetDescription(d);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SystemLog.LogWarning($"Unable to update AD Machine Account Description for {d.DeviceDomainId}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Task - Added Device",
|
||||
Format = "Creating Disco Device {1}",
|
||||
Format = "Creating Disco ICT Device {1}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
@@ -419,7 +419,7 @@ namespace Disco.Services.Devices.Enrolment
|
||||
Id = (int)EventTypeIds.SessionTaskUpdatingDevice,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Task - Updating Device",
|
||||
Format = "Updating Disco Device {1}",
|
||||
Format = "Updating Disco ICT Device {1}",
|
||||
Severity = 0,
|
||||
UseLive = 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
-293
@@ -4,295 +4,14 @@ using Disco.Models.Repository;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Users;
|
||||
using PListNet;
|
||||
using PListNet.Nodes;
|
||||
using Renci.SshNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
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)
|
||||
{
|
||||
ADMachineAccount adMachineAccount = null;
|
||||
@@ -330,7 +49,7 @@ namespace Disco.Services.Devices.Enrolment
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 13, "Loading Device Data");
|
||||
|
||||
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 (!authenticatedToken.Has(Claims.Device.Actions.EnrolDevices))
|
||||
@@ -392,7 +111,6 @@ namespace Disco.Services.Devices.Enrolment
|
||||
EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.SerialNumber);
|
||||
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
|
||||
|
||||
|
||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.Hardware.Manufacturer, Request.Hardware.Model, Request.Hardware.ModelType);
|
||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||
if (deviceModelResult.Item2)
|
||||
@@ -400,13 +118,10 @@ namespace Disco.Services.Devices.Enrolment
|
||||
else
|
||||
EnrolmentLog.LogSessionDevice(sessionId, Request.SerialNumber, deviceModel.Id);
|
||||
|
||||
if (domain == null)
|
||||
domain = ActiveDirectory.Context.GetDomainByName(Request.DNSDomainName);
|
||||
|
||||
RepoDevice = new Device
|
||||
{
|
||||
SerialNumber = Request.SerialNumber,
|
||||
DeviceDomainId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.ComputerName),
|
||||
DeviceDomainId = domain == null ? Request.ComputerName : $@"{domain.NetBiosName}\{Request.ComputerName}",
|
||||
DeviceProfile = deviceProfile,
|
||||
DeviceModel = deviceModel,
|
||||
AllowUnauthenticatedEnrol = false,
|
||||
@@ -438,6 +153,10 @@ namespace Disco.Services.Devices.Enrolment
|
||||
|
||||
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 wlanMacAddresses = string.Join("; ", Request.Hardware.NetworkAdapters?.Where(na => na.IsWlanAdapter).Select(na => na.MACAddress));
|
||||
if (!string.IsNullOrEmpty(lanMacAddresses))
|
||||
@@ -481,6 +200,11 @@ namespace Disco.Services.Devices.Enrolment
|
||||
|
||||
if (string.IsNullOrEmpty(RepoDevice.DeviceDomainId) || RepoDevice.DeviceProfile.EnforceComputerNameConvention)
|
||||
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;
|
||||
EnrolmentLog.LogSessionTaskProvisioningADAccount(sessionId, RepoDevice.SerialNumber, RepoDevice.DeviceDomainId);
|
||||
@@ -497,12 +221,8 @@ namespace Disco.Services.Devices.Enrolment
|
||||
response.ComputerName = adMachineAccount.Name;
|
||||
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.ComputerName = accountUsername;
|
||||
}
|
||||
@@ -579,12 +299,19 @@ namespace Disco.Services.Devices.Enrolment
|
||||
if (adMachineAccount != null && !adMachineAccount.IsCriticalSystemObject)
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 75, "Updating Active Directory Computer Account Properties");
|
||||
try
|
||||
{
|
||||
// Use non-Wlan Adapter with fastest speed
|
||||
var macAddress = Request.Hardware?.NetworkAdapters?.Where(na => !na.IsWlanAdapter).OrderByDescending(na => na.Speed).Select(na => na.MACAddress).FirstOrDefault();
|
||||
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.AssignedUser == null)
|
||||
@@ -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.Services.Devices.Exporting;
|
||||
using Disco.Models.Services.Exporting;
|
||||
using Disco.Services.Plugins.Features.DetailsProvider;
|
||||
using Disco.Services.Tasks;
|
||||
using Disco.Services.Users;
|
||||
@@ -12,25 +13,57 @@ using System.Data;
|
||||
using System.Data.Entity;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Disco.Services.Devices.Exporting
|
||||
{
|
||||
using Metadata = ExportFieldMetadata<DeviceExportRecord>;
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
TaskStatus.UpdateStatus(15, "Extracting records from the database");
|
||||
|
||||
var devices = Database.Devices
|
||||
var deviceQuery = Database.Devices
|
||||
.Include(d => d.AssignedUser.UserDetails)
|
||||
.Include(d => d.DeviceDetails);
|
||||
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
|
||||
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);
|
||||
|
||||
if (metadata.Count == 0)
|
||||
throw new ArgumentException("At least one export field must be specified", "Options");
|
||||
|
||||
// Update Users
|
||||
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();
|
||||
TaskStatus.UpdateStatus(80, $"Formatting {records.Count} records for export");
|
||||
|
||||
users.Select((user, index) =>
|
||||
{
|
||||
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();
|
||||
return ExportHelpers.WriteExport(Options, TaskStatus, metadata, records);
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
@@ -152,62 +128,11 @@ namespace Disco.Services.Devices.Exporting
|
||||
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"));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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 memoryMaxCount = Math.Max(1, records.Max(r => r.DeviceDetailPhysicalMemory?.Count ?? 0));
|
||||
@@ -263,7 +188,7 @@ namespace Disco.Services.Devices.Exporting
|
||||
if (options.AssignedUserDetailCustom)
|
||||
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()
|
||||
.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))
|
||||
.SelectMany(p =>
|
||||
{
|
||||
var fieldMetadata = allAssessors[p.property.Name];
|
||||
var fieldMetadata = allAccessors[p.property.Name];
|
||||
fieldMetadata.ForEach(f =>
|
||||
{
|
||||
if (f.ColumnName == null)
|
||||
@@ -285,7 +210,7 @@ namespace Disco.Services.Devices.Exporting
|
||||
}).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 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> csvNullableDateTimeEncoded = (o) => ((DateTime?)o).HasValue ? csvDateTimeEncoded(o) : null;
|
||||
|
||||
var metadata = new Dictionary<string, List<DeviceExportFieldMetadata>>();
|
||||
var metadata = new Dictionary<string, List<Metadata>>();
|
||||
|
||||
// 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.DeviceAssetNumber), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(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.DeviceComputerName), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(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.DeviceCreatedDate), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(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.DeviceLastEnrolledDate), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(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.DeviceDecommissionedDate), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(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.DeviceSerialNumber), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.DeviceSerialNumber), typeof(string), r => r.Device.SerialNumber, 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<Metadata>() { new Metadata(nameof(DeviceExportOptions.DeviceLocation), typeof(string), r => r.Device.Location, 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<Metadata>() { new Metadata(nameof(DeviceExportOptions.DeviceLastNetworkLogon), typeof(DateTime), r => r.Device.LastNetworkLogonDate, csvNullableDateTimeEncoded) });
|
||||
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<Metadata>() { new Metadata(nameof(DeviceExportOptions.DeviceFirstEnrolledDate), typeof(DateTime), r => r.Device.EnrolledDate, 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<Metadata>() { new Metadata(nameof(DeviceExportOptions.DeviceAllowUnauthenticatedEnrol), typeof(bool), r => r.Device.AllowUnauthenticatedEnrol, csvToStringEncoded) });
|
||||
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<Metadata>() { new Metadata(nameof(DeviceExportOptions.DeviceDecommissionedReason), typeof(string), r => r.Device.DecommissionReason, csvToStringEncoded) });
|
||||
|
||||
// Model
|
||||
metadata.Add(nameof(DeviceExportOptions.ModelId), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(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.ModelManufacturer), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(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.ModelType), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.ModelType), typeof(string), r => r.ModelType, csvStringEncoded) });
|
||||
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<Metadata>() { new Metadata(nameof(DeviceExportOptions.ModelDescription), typeof(string), r => r.ModelDescription, 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<Metadata>() { new Metadata(nameof(DeviceExportOptions.ModelModel), typeof(string), r => r.ModelModel, csvStringEncoded) });
|
||||
metadata.Add(nameof(DeviceExportOptions.ModelType), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.ModelType), typeof(string), r => r.ModelType, csvStringEncoded) });
|
||||
|
||||
// Batch
|
||||
metadata.Add(nameof(DeviceExportOptions.BatchId), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(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.BatchPurchaseDate), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(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.BatchUnitCost), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(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.BatchInsuredDate), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(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.BatchInsuredUntilDate), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.BatchInsuredUntilDate), typeof(DateTime), r => r.BatchInsuredUntilDate, csvNullableDateEncoded) });
|
||||
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<Metadata>() { new Metadata(nameof(DeviceExportOptions.BatchName), typeof(string), r => r.BatchName, csvStringEncoded) });
|
||||
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<Metadata>() { new Metadata(nameof(DeviceExportOptions.BatchSupplier), typeof(string), r => r.BatchSupplier, csvStringEncoded) });
|
||||
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<Metadata>() { new Metadata(nameof(DeviceExportOptions.BatchWarrantyValidUntilDate), typeof(DateTime), r => r.BatchWarrantyValidUntilDate, 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<Metadata>() { new Metadata(nameof(DeviceExportOptions.BatchInsuranceSupplier), typeof(string), r => r.BatchInsuranceSupplier, csvStringEncoded) });
|
||||
metadata.Add(nameof(DeviceExportOptions.BatchInsuredUntilDate), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.BatchInsuredUntilDate), typeof(DateTime), r => r.BatchInsuredUntilDate, csvNullableDateEncoded) });
|
||||
|
||||
// Profile
|
||||
metadata.Add(nameof(DeviceExportOptions.ProfileId), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(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.ProfileShortName), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(nameof(DeviceExportOptions.ProfileShortName), typeof(string), r => r.ProfileShortName, csvStringEncoded) });
|
||||
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<Metadata>() { new Metadata(nameof(DeviceExportOptions.ProfileName), typeof(string), r => r.ProfileName, csvStringEncoded) });
|
||||
metadata.Add(nameof(DeviceExportOptions.ProfileShortName), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.ProfileShortName), typeof(string), r => r.ProfileShortName, csvStringEncoded) });
|
||||
|
||||
// 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.AssignedUserDate), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(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.AssignedUserSurname), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(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.AssignedUserPhoneNumber), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(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.AssignedUserId), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.AssignedUserId), typeof(string), r => r.AssignedUser?.UserId, csvStringEncoded) });
|
||||
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<Metadata>() { new Metadata(nameof(DeviceExportOptions.AssignedUserDisplayName), typeof(string), r => r.AssignedUser?.DisplayName, 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<Metadata>() { new Metadata(nameof(DeviceExportOptions.AssignedUserGivenName), typeof(string), r => r.AssignedUser?.GivenName, 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<Metadata>() { new Metadata(nameof(DeviceExportOptions.AssignedUserEmailAddress), typeof(string), r => r.AssignedUser?.EmailAddress, csvStringEncoded) });
|
||||
if (assignedUserDetailCustomKeys != null)
|
||||
{
|
||||
var assignedUserDetailCustomFields = new List<DeviceExportFieldMetadata>();
|
||||
var assignedUserDetailCustomFields = new List<Metadata>();
|
||||
foreach (var detailKey in assignedUserDetailCustomKeys.OrderBy(k => k, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
// Jobs
|
||||
metadata.Add(nameof(DeviceExportOptions.JobsTotalCount), new List<DeviceExportFieldMetadata>() { new DeviceExportFieldMetadata(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.JobsTotalCount), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.JobsTotalCount), typeof(int), r => r.JobsTotalCount, csvToStringEncoded) });
|
||||
metadata.Add(nameof(DeviceExportOptions.JobsOpenCount), new List<Metadata>() { new Metadata(nameof(DeviceExportOptions.JobsOpenCount), typeof(int), r => r.JobsOpenCount, csvToStringEncoded) });
|
||||
|
||||
// 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
|
||||
var certificateFields = new List<DeviceExportFieldMetadata>(certificateMaxCount * 4);
|
||||
var certificateFields = new List<Metadata>(certificateMaxCount * 4);
|
||||
for (int i = 0; i < certificateMaxCount; i++)
|
||||
{
|
||||
var v = i;
|
||||
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 DeviceExportFieldMetadata($"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 DeviceExportFieldMetadata($"Certificate{index}ProviderId", $"Certificate {index} Provider Id", typeof(string), r => r.DeviceCertificates.Skip(v).FirstOrDefault()?.ProviderId, csvStringEncoded));
|
||||
certificateFields.Add(new Metadata($"Certificate{index}Name", $"Certificate {index} Name", typeof(string), r => r.DeviceCertificates.Skip(v).FirstOrDefault()?.Name, csvStringEncoded));
|
||||
certificateFields.Add(new Metadata($"Certificate{index}AllocationDate", $"Certificate {index} Allocation Date", typeof(DateTime), r => r.DeviceCertificates.Skip(v).FirstOrDefault()?.AllocatedDate, 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 Metadata($"Certificate{index}ProviderId", $"Certificate {index} Provider Id", typeof(string), r => r.DeviceCertificates.Skip(v).FirstOrDefault()?.ProviderId, csvStringEncoded));
|
||||
}
|
||||
metadata.Add(nameof(DeviceExportOptions.Certificates), certificateFields);
|
||||
|
||||
// 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 DeviceExportFieldMetadata("BIOSSerialNumber", "BIOS Serial Number", typeof(string), r => r.DeviceDetailBios?.FirstOrDefault()?.SerialNumber, csvStringEncoded),
|
||||
new DeviceExportFieldMetadata("BIOSVersion", "BIOS Version", typeof(string), r => {
|
||||
new Metadata("BIOSManufacturer", "BIOS Manufacturer", typeof(string), r => r.DeviceDetailBios?.FirstOrDefault()?.Manufacturer, csvStringEncoded),
|
||||
new Metadata("BIOSSerialNumber", "BIOS Serial Number", typeof(string), r => r.DeviceDetailBios?.FirstOrDefault()?.SerialNumber, csvStringEncoded),
|
||||
new Metadata("BIOSVersion", "BIOS Version", typeof(string), r => {
|
||||
var bios = r.DeviceDetailBios?.FirstOrDefault();
|
||||
if (bios?.SMBIOSBIOSVersion != null)
|
||||
return $"{bios.SMBIOSBIOSVersion} {bios.SMBIOSMajorVersion}.{bios.SMBIOSMinorVersion}";
|
||||
else
|
||||
return null;
|
||||
}, csvStringEncoded),
|
||||
new DeviceExportFieldMetadata("BIOSSystemVersion", "BIOS System Version", typeof(string), r => {
|
||||
new Metadata("BIOSSystemVersion", "BIOS System Version", typeof(string), r => {
|
||||
var bios = r.DeviceDetailBios?.FirstOrDefault();
|
||||
if (bios?.SystemBiosMajorVersion.HasValue ?? false)
|
||||
return $"{bios.SystemBiosMajorVersion}.{bios.SystemBiosMinorVersion}";
|
||||
else
|
||||
return null;
|
||||
}, 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);
|
||||
|
||||
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 DeviceExportFieldMetadata("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 DeviceExportFieldMetadata("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 DeviceExportFieldMetadata("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("BaseBoardManufacturer", "Base Board Manufacturer", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.Manufacturer, csvStringEncoded),
|
||||
new Metadata("BaseBoardModel", "Base Board Model", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.Model, csvStringEncoded),
|
||||
new Metadata("BaseBoardProduct", "Base Board Product", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.Product, csvStringEncoded),
|
||||
new Metadata("BaseBoardPartNumber", "Base Board Part Number", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.PartNumber, csvStringEncoded),
|
||||
new Metadata("BaseBoardSKU", "Base Board SKU", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.SKU, csvStringEncoded),
|
||||
new Metadata("BaseBoardSerialNumber", "Base Board Serial Number", typeof(string), r => r.DeviceDetailBaseBoard?.FirstOrDefault()?.SerialNumber, csvStringEncoded),
|
||||
new Metadata("BaseBoardConfigOptions", "Base Board Config Options", typeof(string), r => {
|
||||
var baseBoard = r.DeviceDetailBaseBoard?.FirstOrDefault();
|
||||
if (baseBoard?.ConfigOptions != null)
|
||||
return string.Join("; ", baseBoard.ConfigOptions);
|
||||
else
|
||||
return null;
|
||||
}, 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);
|
||||
|
||||
var computerSystemFields = new List<DeviceExportFieldMetadata>()
|
||||
var computerSystemFields = new List<Metadata>()
|
||||
{
|
||||
new DeviceExportFieldMetadata("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 DeviceExportFieldMetadata("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 DeviceExportFieldMetadata("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 DeviceExportFieldMetadata("ComputerSystemSystemSKU", "System SKU", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.SystemSKUNumber, csvStringEncoded),
|
||||
new DeviceExportFieldMetadata("ComputerSystemOEMReference", "System OEM Reference", typeof(string), r => {
|
||||
new Metadata("ComputerSystemDescription", "System Description", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.Description, csvStringEncoded),
|
||||
new Metadata("ComputerSystemPCSystemType", "System Form Factor", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.PCSystemType, csvStringEncoded),
|
||||
new Metadata("ComputerSystemSystemType", "System Type", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.SystemType, csvStringEncoded),
|
||||
new Metadata("ComputerSystemPrimaryOwnerName", "System Primary Owner Name", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.PrimaryOwnerName, csvStringEncoded),
|
||||
new Metadata("ComputerSystemPrimaryOwnerContact", "System Primary Owner Contact", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.PrimaryOwnerContact, csvStringEncoded),
|
||||
new Metadata("ComputerSystemChassisSKU", "System Chassis SKU", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.ChassisSKUNumber, csvStringEncoded),
|
||||
new Metadata("ComputerSystemSystemSKU", "System SKU", typeof(string), r => r.DeviceDetailComputerSystem?.FirstOrDefault()?.SystemSKUNumber, csvStringEncoded),
|
||||
new Metadata("ComputerSystemOEMReference", "System OEM Reference", typeof(string), r => {
|
||||
var computerSystem = r.DeviceDetailComputerSystem?.FirstOrDefault();
|
||||
if (computerSystem?.OEMStringArray != null)
|
||||
return string.Join("; ", computerSystem.OEMStringArray);
|
||||
else
|
||||
return null;
|
||||
}, csvStringEncoded),
|
||||
new DeviceExportFieldMetadata("ComputerSystemCurrentTimeZone", "System Time Zone", typeof(string), r => {
|
||||
new Metadata("ComputerSystemCurrentTimeZone", "System Time Zone", typeof(string), r => {
|
||||
var computerSystem = r.DeviceDetailComputerSystem?.FirstOrDefault();
|
||||
if (computerSystem?.CurrentTimeZone.HasValue ?? false)
|
||||
return $"{computerSystem.CurrentTimeZone.Value / 60:00}:{Math.Abs(computerSystem.CurrentTimeZone.Value % 60):00}";
|
||||
else
|
||||
return null;
|
||||
}, csvStringEncoded),
|
||||
new DeviceExportFieldMetadata("ComputerSystemRoles", "System Roles", typeof(string), r => {
|
||||
new Metadata("ComputerSystemRoles", "System Roles", typeof(string), r => {
|
||||
var computerSystem = r.DeviceDetailComputerSystem?.FirstOrDefault();
|
||||
if (computerSystem?.Roles != null)
|
||||
return string.Join("; ", computerSystem.Roles);
|
||||
@@ -450,88 +375,88 @@ namespace Disco.Services.Devices.Exporting
|
||||
};
|
||||
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++)
|
||||
{
|
||||
var v = i;
|
||||
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 DeviceExportFieldMetadata($"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 DeviceExportFieldMetadata($"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 DeviceExportFieldMetadata($"Processor{index}LogicalProcessors", $"Processor {index} Logical Processors", typeof(int), r => r.DeviceDetailProcessors?.Skip(v).FirstOrDefault()?.NumberOfLogicalProcessors, csvToStringEncoded));
|
||||
processorFields.Add(new Metadata($"Processor{index}Name", $"Processor {index} Name", typeof(string), r => r.DeviceDetailProcessors?.Skip(v).FirstOrDefault()?.Name, csvStringEncoded));
|
||||
processorFields.Add(new Metadata($"Processor{index}Description", $"Processor {index} Description", typeof(string), r => r.DeviceDetailProcessors?.Skip(v).FirstOrDefault()?.Description, csvStringEncoded));
|
||||
processorFields.Add(new Metadata($"Processor{index}Architecture", $"Processor {index} Architecture", typeof(string), r => r.DeviceDetailProcessors?.Skip(v).FirstOrDefault()?.Architecture, 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 Metadata($"Processor{index}Cores", $"Processor {index} Cores", typeof(int), r => r.DeviceDetailProcessors?.Skip(v).FirstOrDefault()?.NumberOfCores, 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);
|
||||
var memoryFields = new List<DeviceExportFieldMetadata>((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));
|
||||
var memoryFields = new List<Metadata>((memoryMaxCount * 6) + 1);
|
||||
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++)
|
||||
{
|
||||
var v = i;
|
||||
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 DeviceExportFieldMetadata($"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 DeviceExportFieldMetadata($"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 DeviceExportFieldMetadata($"Memory{index}ConfiguredClockSpeed", $"Memory {index} Clock Speed", typeof(int), r => r.DeviceDetailPhysicalMemory?.Skip(v).FirstOrDefault()?.ConfiguredClockSpeed, csvToStringEncoded));
|
||||
memoryFields.Add(new Metadata($"Memory{index}Location", $"Memory {index} Location", typeof(string), r => r.DeviceDetailPhysicalMemory?.Skip(v).FirstOrDefault()?.DeviceLocator, csvStringEncoded));
|
||||
memoryFields.Add(new Metadata($"Memory{index}Manufacturer", $"Memory {index} Manufacturer", typeof(string), r => r.DeviceDetailPhysicalMemory?.Skip(v).FirstOrDefault()?.Manufacturer, 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 Metadata($"Memory{index}SerialNumber", $"Memory {index} Serial Number", typeof(string), r => r.DeviceDetailPhysicalMemory?.Skip(v).FirstOrDefault()?.SerialNumber, csvStringEncoded));
|
||||
memoryFields.Add(new Metadata($"Memory{index}Capacity", $"Memory {index} Capacity", typeof(string), r => r.DeviceDetailPhysicalMemory?.Skip(v).FirstOrDefault()?.CapacityFriendly(), csvStringEncoded));
|
||||
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);
|
||||
var diskFields = new List<DeviceExportFieldMetadata>(diskDriveMaxCount * 6);
|
||||
var diskFields = new List<Metadata>(diskDriveMaxCount * 6);
|
||||
for (int i = 0; i < diskDriveMaxCount; i++)
|
||||
{
|
||||
var v = i;
|
||||
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 DeviceExportFieldMetadata($"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 DeviceExportFieldMetadata($"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 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}Manufacturer", $"Disk {index} Manufacturer", typeof(string), r => r.DeviceDetailDiskDrives?.Skip(v).FirstOrDefault()?.Manufacturer, csvStringEncoded));
|
||||
diskFields.Add(new Metadata($"Disk{index}Model", $"Disk {index} Model", typeof(string), r => r.DeviceDetailDiskDrives?.Skip(v).FirstOrDefault()?.Model, 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 Metadata($"Disk{index}Firmware", $"Disk {index} Firmware", typeof(string), r => r.DeviceDetailDiskDrives?.Skip(v).FirstOrDefault()?.FirmwareRevision, csvStringEncoded));
|
||||
diskFields.Add(new Metadata($"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} 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);
|
||||
var lanAdapterFields = new List<DeviceExportFieldMetadata>(lanAdapterMaxCount * 5);
|
||||
var lanAdapterFields = new List<Metadata>(lanAdapterMaxCount * 5);
|
||||
for (int i = 0; i < lanAdapterMaxCount; i++)
|
||||
{
|
||||
var v = i;
|
||||
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 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 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 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 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}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}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}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}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}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);
|
||||
var fields = new List<DeviceExportFieldMetadata>(wlanAdapterMaxCount * 5);
|
||||
var fields = new List<Metadata>(wlanAdapterMaxCount * 5);
|
||||
for (int i = 0; i < wlanAdapterMaxCount; i++)
|
||||
{
|
||||
var v = i;
|
||||
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 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 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 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 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}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}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}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}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}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.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.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) });
|
||||
var batteriesFields = new List<DeviceExportFieldMetadata>(processorMaxCount * 6);
|
||||
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<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<Metadata>(processorMaxCount * 6);
|
||||
for (int i = 0; i < batteriesMaxCount; i++)
|
||||
{
|
||||
var v = i;
|
||||
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 DeviceExportFieldMetadata($"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 DeviceExportFieldMetadata($"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 DeviceExportFieldMetadata($"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}Name", $"Battery {index} Name", typeof(string), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.Name, csvStringEncoded));
|
||||
batteriesFields.Add(new Metadata($"Batteries{index}Description", $"Battery {index} Description", typeof(string), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.Description, csvStringEncoded));
|
||||
batteriesFields.Add(new Metadata($"Batteries{index}Availability", $"Battery {index} Availability", typeof(string), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.Availability, csvStringEncoded));
|
||||
batteriesFields.Add(new Metadata($"Batteries{index}Chemistry", $"Battery {index} Chemistry", typeof(string), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.Chemistry, csvStringEncoded));
|
||||
batteriesFields.Add(new Metadata($"Batteries{index}DesignVoltage", $"Battery {index} Design Voltage", typeof(long), r => r.DeviceDetailBatteries?.Skip(v).FirstOrDefault()?.DesignVoltage, 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 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.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;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Disco.Services.Tasks;
|
||||
using Quartz;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Services.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 CancelInitiallySupported { get { return false; } }
|
||||
|
||||
public static DeviceExportTaskContext ScheduleNow(DeviceExportOptions Options)
|
||||
public static ExportTaskContext<DeviceExportOptions> ScheduleNow(DeviceExportOptions Options)
|
||||
{
|
||||
// Build Context
|
||||
var context = new DeviceExportTaskContext(Options);
|
||||
var context = new ExportTaskContext<DeviceExportOptions>(Options);
|
||||
|
||||
// Build Data Map
|
||||
var task = new DeviceExportTask();
|
||||
@@ -30,7 +31,7 @@ namespace Disco.Services.Devices.Exporting
|
||||
|
||||
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...");
|
||||
|
||||
|
||||
@@ -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.Services.Devices.Importing;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Logging;
|
||||
using Disco.Services.Users;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -146,8 +147,16 @@ namespace Disco.Services.Devices.Importing.Fields
|
||||
var adAccount = Device.ActiveDirectoryAccount();
|
||||
|
||||
if (adAccount != null && !adAccount.IsCriticalSystemObject)
|
||||
{
|
||||
try
|
||||
{
|
||||
adAccount.SetDescription(Device);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SystemLog.LogWarning($"Unable to update AD Machine Account Description for {Device.DeviceDomainId}: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
DeviceADDescriptionSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,10 @@ namespace Disco.Services.Devices.Importing.Fields
|
||||
|
||||
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")
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Devices.Importing;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
@@ -115,8 +116,16 @@ namespace Disco.Services.Devices.Importing.Fields
|
||||
}
|
||||
|
||||
if (!DeviceADDescriptionSet)
|
||||
{
|
||||
try
|
||||
{
|
||||
adAccount.SetDescription(Device);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SystemLog.LogWarning($"Unable to update AD Machine Account Description for {Device.DeviceDomainId}: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
DeviceADDescriptionSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Devices.Importing;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
@@ -119,8 +120,16 @@ namespace Disco.Services.Devices.Importing.Fields
|
||||
}
|
||||
|
||||
if (!DeviceADDescriptionSet)
|
||||
{
|
||||
try
|
||||
{
|
||||
adAccount.SetDescription(Device);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SystemLog.LogWarning($"Unable to update AD Machine Account Description for {Device.DeviceDomainId}: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
DeviceADDescriptionSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Devices.Importing;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
@@ -93,8 +94,16 @@ namespace Disco.Services.Devices.Importing.Fields
|
||||
var adAccount = Device.ActiveDirectoryAccount();
|
||||
|
||||
if (adAccount != null && !adAccount.IsCriticalSystemObject)
|
||||
{
|
||||
try
|
||||
{
|
||||
adAccount.SetDescription(Device);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SystemLog.LogWarning($"Unable to update AD Machine Account Description for {Device.DeviceDomainId}: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
DeviceADDescriptionSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Devices.Importing;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
@@ -89,8 +90,16 @@ namespace Disco.Services.Devices.Importing.Fields
|
||||
var adAccount = Device.ActiveDirectoryAccount();
|
||||
|
||||
if (adAccount != null && !adAccount.IsCriticalSystemObject)
|
||||
{
|
||||
try
|
||||
{
|
||||
adAccount.SetDescription(Device);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SystemLog.LogWarning($"Unable to update AD Machine Account Description for {Device.DeviceDomainId}: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
DeviceADDescriptionSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Disco.Services</RootNamespace>
|
||||
<AssemblyName>Disco.Services</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
@@ -94,8 +94,8 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\RazorGenerator.Mvc.2.2.3\lib\net40\RazorGenerator.Mvc.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Renci.SshNet">
|
||||
<HintPath>..\..\..\Resources\Libraries\SshNet\Renci.SshNet.dll</HintPath>
|
||||
<Reference Include="Renci.SshNet, Version=2023.0.0.0, Culture=neutral, PublicKeyToken=1cee9f8bde3db106, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SSH.NET.2023.0.0\lib\net462\Renci.SshNet.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Spring.Core">
|
||||
<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\DeviceBatch\DeviceBatchClaims.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\DeviceProfile\DeviceProfileClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\DocumentTemplate\DocumentTemplateClaims.cs" />
|
||||
@@ -240,14 +241,25 @@
|
||||
<Compile Include="Devices\DeviceProfileExtensions.cs" />
|
||||
<Compile Include="Devices\DeviceBatchUpdatesHub.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\EnrolmentSafeException.cs" />
|
||||
<Compile Include="Devices\Enrolment\EnrolmentTypes.cs" />
|
||||
<Compile Include="Devices\Enrolment\LogMacAddressImportingTask.cs" />
|
||||
<Compile Include="Devices\Enrolment\MacDeviceEnrolment.cs" />
|
||||
<Compile Include="Devices\Exporting\DeviceExport.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\CsvDeviceImportDataReader.cs" />
|
||||
<Compile Include="Devices\Importing\DeviceImport.cs" />
|
||||
@@ -317,6 +329,7 @@
|
||||
<Compile Include="Expressions\Extensions\ImageResultImplementations\BitmapImageExpressionResult.cs" />
|
||||
<Compile Include="Expressions\Extensions\ImageResultImplementations\FileImageExpressionResult.cs" />
|
||||
<Compile Include="Expressions\Extensions\ImageResultImplementations\FileMontageImageExpressionResult.cs" />
|
||||
<Compile Include="Expressions\Extensions\ImageResultImplementations\QrCodeImageExpressionResult.cs" />
|
||||
<Compile Include="Expressions\Extensions\UserExt.cs" />
|
||||
<Compile Include="Expressions\IExpressionPart.cs" />
|
||||
<Compile Include="Expressions\LazyDictionary.cs" />
|
||||
@@ -343,6 +356,7 @@
|
||||
<Compile Include="Interop\ActiveDirectory\ADMachineAccount.cs" />
|
||||
<Compile Include="Interop\ActiveDirectory\ADManagedGroup.cs" />
|
||||
<Compile Include="Interop\ActiveDirectory\ADManagedGroupsSyncTask.cs" />
|
||||
<Compile Include="Interop\ActiveDirectory\ADEnforceDeviceProfileOrganisationalUnitTask.cs" />
|
||||
<Compile Include="Interop\ActiveDirectory\ADOrganisationalUnit.cs" />
|
||||
<Compile Include="Interop\ActiveDirectory\ADSearchResult.cs" />
|
||||
<Compile Include="Interop\ActiveDirectory\ADSite.cs" />
|
||||
@@ -459,6 +473,8 @@
|
||||
<Compile Include="Users\Contact\UserContactService.cs" />
|
||||
<Compile Include="Users\UserExtensions.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\UserFlagUserDevicesManagedGroup.cs" />
|
||||
<Compile Include="Users\UserFlags\UserFlagUsersManagedGroup.cs" />
|
||||
|
||||
@@ -113,18 +113,42 @@ namespace Disco.Services.Documents.AttachmentImport
|
||||
{
|
||||
var qrReader = new QRCodeMultiReader();
|
||||
|
||||
var qrReaderHints = new Dictionary<DecodeHintType, object>() {
|
||||
{ DecodeHintType.TRY_HARDER, true }
|
||||
};
|
||||
|
||||
var qrImageSource = new BitmapLuminanceSource((Bitmap)Image);
|
||||
|
||||
var qrBinarizer = new HybridBinarizer(qrImageSource);
|
||||
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
|
||||
{
|
||||
qrCodeResult = qrReader.decodeMultiple(qrBinaryBitmap, qrReaderHints)?.FirstOrDefault();
|
||||
qrCodeResult = DetectDocumentUniqueIdentifier(qrBinaryBitmap);
|
||||
qrCodeResultScale = 1F;
|
||||
}
|
||||
catch (ReaderException)
|
||||
@@ -148,7 +172,7 @@ namespace Disco.Services.Documents.AttachmentImport
|
||||
|
||||
try
|
||||
{
|
||||
qrCodeResult = qrReader.decodeMultiple(qrBinaryBitmap, qrReaderHints)?.FirstOrDefault();
|
||||
qrCodeResult = DetectDocumentUniqueIdentifier(qrBinaryBitmap);
|
||||
qrCodeResultScale = 1.75F;
|
||||
}
|
||||
catch (ReaderException)
|
||||
@@ -171,7 +195,7 @@ namespace Disco.Services.Documents.AttachmentImport
|
||||
|
||||
try
|
||||
{
|
||||
qrCodeResult = qrReader.decodeMultiple(qrBinaryBitmap, qrReaderHints)?.FirstOrDefault();
|
||||
qrCodeResult = DetectDocumentUniqueIdentifier(qrBinaryBitmap);
|
||||
qrCodeResultScale = 2F;
|
||||
}
|
||||
catch (ReaderException)
|
||||
|
||||
@@ -8,8 +8,24 @@ namespace Disco.Services.Documents
|
||||
{
|
||||
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 bits = new BitArray();
|
||||
@@ -17,7 +33,7 @@ namespace Disco.Services.Documents
|
||||
var mode = Mode.BYTE;
|
||||
var bitsNeeded = 4 +
|
||||
mode.getCharacterCountBits(ZXing.QrCode.Internal.Version.getVersionForNumber(1)) +
|
||||
(Content.Length * 8);
|
||||
(content.Length * 8);
|
||||
|
||||
var version = ChooseVersion(bitsNeeded, out ecLevel);
|
||||
var ecBlocks = version.getECBlocksForLevel(ecLevel);
|
||||
@@ -28,12 +44,12 @@ namespace Disco.Services.Documents
|
||||
bits.appendBits(mode.Bits, 4);
|
||||
|
||||
// Write the number of bytes
|
||||
bits.appendBits(Content.Length, mode.getCharacterCountBits(version));
|
||||
bits.appendBits(content.Length, mode.getCharacterCountBits(version));
|
||||
|
||||
// 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
|
||||
@@ -72,7 +88,10 @@ namespace Disco.Services.Documents
|
||||
MatrixUtil.buildMatrix(finalBits, ecLevel, version, maskPattern, matrix);
|
||||
|
||||
// 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)
|
||||
@@ -242,17 +261,17 @@ namespace Disco.Services.Documents
|
||||
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 matrixHeight = matrix.Length;
|
||||
Width = Math.Max(Width, matrixWidth);
|
||||
Height = Math.Max(Height, matrixHeight);
|
||||
var byteColumns = (Width + 7) / 8;
|
||||
var outputBytes = new byte[byteColumns * Height];
|
||||
var scale = Math.Min(Width / (matrixWidth + 1), Height / (matrixHeight + 1));
|
||||
var offsetX = (Width - (matrixWidth * scale)) / 2;
|
||||
var offsetY = (Height - (matrixHeight * scale)) / 2;
|
||||
width = Math.Max(width, matrixWidth);
|
||||
height = Math.Max(height, matrixHeight);
|
||||
var byteColumns = (width + 7) / 8;
|
||||
var outputBytes = new byte[byteColumns * height];
|
||||
var scale = Math.Max(1, Math.Min(width / (matrixWidth + 1), height / (matrixHeight + 1)));
|
||||
var offsetX = (width - (matrixWidth * scale)) / 2;
|
||||
var offsetY = (height - (matrixHeight * scale)) / 2;
|
||||
// initialize output bytes
|
||||
for (int i = 0; i < outputBytes.Length; i++)
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user