diff --git a/Disco.Models/Services/Devices/Exporting/DeviceExportOptions.cs b/Disco.Models/Services/Devices/Exporting/DeviceExportOptions.cs index f3b1eea5..ef8dbad1 100644 --- a/Disco.Models/Services/Devices/Exporting/DeviceExportOptions.cs +++ b/Disco.Models/Services/Devices/Exporting/DeviceExportOptions.cs @@ -34,6 +34,8 @@ namespace Disco.Models.Services.Devices.Exporting public bool DeviceFirstEnrolledDate { get; set; } [Display(ShortName = "Device", Name = "Last Enrolled Date", Description = "The date the device was last enrolled in Disco")] 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")] public bool DeviceDecommissionedDate { get; set; } [Display(ShortName = "Device", Name = "Decommissioned Reason", Description = "The reason the device was decommissioned")] diff --git a/Disco.Models/Services/Devices/Importing/DeviceImportFieldTypes.cs b/Disco.Models/Services/Devices/Importing/DeviceImportFieldTypes.cs index d3e26d40..fa7aeb23 100644 --- a/Disco.Models/Services/Devices/Importing/DeviceImportFieldTypes.cs +++ b/Disco.Models/Services/Devices/Importing/DeviceImportFieldTypes.cs @@ -15,6 +15,8 @@ namespace Disco.Models.Services.Devices.Importing DeviceAssetNumber, [Display(Name = "Device Location", Description = "The device location")] 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")] DeviceDecommissionedDate, [Display(Name = "Device Decommissioned Reason", Description = "The reason the device was decommissioned")] diff --git a/Disco.Services/Devices/Exporting/DeviceExport.cs b/Disco.Services/Devices/Exporting/DeviceExport.cs index b2ea5afc..618ba74b 100644 --- a/Disco.Services/Devices/Exporting/DeviceExport.cs +++ b/Disco.Services/Devices/Exporting/DeviceExport.cs @@ -203,6 +203,7 @@ namespace Disco.Services.Devices.Exporting yield return new Tuple, bool>("DeviceCreatedDate", r => r.Device.CreatedDate.ToString(DateTimeFormat), false); yield return new Tuple, bool>("DeviceFirstEnrolledDate", r => r.Device.EnrolledDate.HasValue ? r.Device.EnrolledDate.Value.ToString(DateTimeFormat) : null, false); yield return new Tuple, bool>("DeviceLastEnrolledDate", r => r.Device.LastEnrolDate.HasValue ? r.Device.LastEnrolDate.Value.ToString(DateTimeFormat) : null, false); + yield return new Tuple, bool>("DeviceAllowUnauthenticatedEnrol", r => r.Device.AllowUnauthenticatedEnrol.ToString(), false); yield return new Tuple, bool>("DeviceDecommissionedDate", r => r.Device.DecommissionedDate.HasValue ? r.Device.DecommissionedDate.Value.ToString(DateTimeFormat) : null, false); yield return new Tuple, bool>("DeviceDecommissionedReason", r => r.Device.DecommissionReason.HasValue ? r.Device.DecommissionReason.Value.ToString() : null, true); diff --git a/Disco.Services/Devices/Importing/DeviceImport.cs b/Disco.Services/Devices/Importing/DeviceImport.cs index 2d1cccda..c91f4a14 100644 --- a/Disco.Services/Devices/Importing/DeviceImport.cs +++ b/Disco.Services/Devices/Importing/DeviceImport.cs @@ -24,6 +24,7 @@ namespace Disco.Services.Devices.Importing { DeviceImportFieldTypes.DeviceSerialNumber, typeof(DeviceSerialNumberImportField) }, { DeviceImportFieldTypes.DeviceAssetNumber, typeof(DeviceAssetNumberImportField) }, { DeviceImportFieldTypes.DeviceLocation, typeof(DeviceLocationImportField) }, + { DeviceImportFieldTypes.DeviceAllowUnauthenticatedEnrol, typeof(DeviceAllowUnauthenticatedEnrolImportField) }, { DeviceImportFieldTypes.DeviceDecommissionedDate, typeof(DeviceDecommissionedDateImportField) }, { DeviceImportFieldTypes.DeviceDecommissionedReason, typeof(DeviceDecommissionedReasonImportField) }, diff --git a/Disco.Services/Devices/Importing/Fields/DeviceAllowUnauthenticatedEnrolImportField.cs b/Disco.Services/Devices/Importing/Fields/DeviceAllowUnauthenticatedEnrolImportField.cs new file mode 100644 index 00000000..26a91836 --- /dev/null +++ b/Disco.Services/Devices/Importing/Fields/DeviceAllowUnauthenticatedEnrolImportField.cs @@ -0,0 +1,129 @@ +using Disco.Data.Repository; +using Disco.Models.Repository; +using Disco.Models.Services.Devices.Importing; +using Disco.Services.Users; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; + +namespace Disco.Services.Devices.Importing.Fields +{ + internal class DeviceAllowUnauthenticatedEnrolImportField : DeviceImportFieldBase + { + private static string[] TrueValues = { "true", "1", "yes", "-1", "on" }; + private static string[] FalseValues = { "false", "0", "no", "off" }; + private bool parsedValue; + private string friendlyValue; + private string friendlyPreviousValue; + + public override DeviceImportFieldTypes FieldType { get { return DeviceImportFieldTypes.DeviceAllowUnauthenticatedEnrol; } } + + public override object RawParsedValue { get { return parsedValue; } } + public override string FriendlyValue { get { return friendlyValue; } } + public override string FriendlyPreviousValue { get { return friendlyPreviousValue; } } + + public override bool Parse(DiscoDataContext Database, IDeviceImportCache Cache, DeviceImportContext Context, int RecordIndex, string DeviceSerialNumber, Device ExistingDevice, Dictionary Values, string Value) + { + friendlyValue = Value; + + if (!ParseBoolean(Value, out parsedValue)) + return Error("Expected a Boolean expression (True, 1, Yes, On, False, 0, No, Off)"); + + friendlyValue = parsedValue.ToString(); + + if (parsedValue == true) + { + // Check Decommissioned + bool? importDecommissioning = null; + if (Values.ContainsKey(DeviceImportFieldTypes.DeviceDecommissionedDate) || Values.ContainsKey(DeviceImportFieldTypes.DeviceDecommissionedReason)) + importDecommissioning = Values.ContainsKey(DeviceImportFieldTypes.DeviceDecommissionedDate) && !string.IsNullOrWhiteSpace(Values[DeviceImportFieldTypes.DeviceDecommissionedDate]) || + Values.ContainsKey(DeviceImportFieldTypes.DeviceDecommissionedReason) && !string.IsNullOrWhiteSpace(Values[DeviceImportFieldTypes.DeviceDecommissionedReason]); + + if (importDecommissioning.HasValue && importDecommissioning.Value) + return Error("Cannot enrol a device being decommissioned"); + + if (ExistingDevice != null && ExistingDevice.DecommissionedDate.HasValue && !importDecommissioning.HasValue) + { + return Error("Cannot enrol a decommissioned device"); + } + } + + if (ExistingDevice == null && parsedValue != false) // Default: True + { + return Success(EntityState.Added); + } + else if (ExistingDevice != null && ExistingDevice.AllowUnauthenticatedEnrol != parsedValue) + { + friendlyPreviousValue = ExistingDevice.AllowUnauthenticatedEnrol.ToString(); + + return Success(EntityState.Modified); + } + else + return Success(EntityState.Unchanged); + } + + public override bool Apply(DiscoDataContext Database, Device Device) + { + if (this.FieldAction == EntityState.Modified || + this.FieldAction == EntityState.Added) + { + Device.AllowUnauthenticatedEnrol = parsedValue; + + return true; + } + else + { + return false; + } + } + + public override int? GuessHeader(DiscoDataContext Database, DeviceImportContext Context) + { + // column name + var possibleColumns = Context.Header + .Select((h, i) => Tuple.Create(h, i)) + .Where(h => h.Item1.Item2 == DeviceImportFieldTypes.IgnoreColumn && + h.Item1.Item1.IndexOf("trust enrol", System.StringComparison.OrdinalIgnoreCase) >= 0 || + h.Item1.Item1.IndexOf("enrolment trusted", System.StringComparison.OrdinalIgnoreCase) >= 0 || + h.Item1.Item1.IndexOf("trust", System.StringComparison.OrdinalIgnoreCase) >= 0 + ); + + // All Boolean + possibleColumns = possibleColumns.Where(h => + { + bool lastValue; + return Context.RawData.Select(v => v[h.Item2]).Take(100).Where(v => !string.IsNullOrWhiteSpace(v)).All(v => ParseBoolean(v, out lastValue)); + }).ToList(); + + return possibleColumns.Select(h => (int?)h.Item2).FirstOrDefault(); + } + + private static bool ParseBoolean(string value, out bool result) + { + if (string.IsNullOrWhiteSpace(value)) + { + result = false; + return false; + } + + value = value.Trim(); + + if (TrueValues.Contains(value, StringComparer.OrdinalIgnoreCase)) + { + result = true; + return true; + } + else if (FalseValues.Contains(value, StringComparer.OrdinalIgnoreCase)) + { + result = false; + return true; + } + else + { + result = false; + return false; + } + } + } +} diff --git a/Disco.Services/Disco.Services.csproj b/Disco.Services/Disco.Services.csproj index cf4fa595..cafef053 100644 --- a/Disco.Services/Disco.Services.csproj +++ b/Disco.Services/Disco.Services.csproj @@ -188,6 +188,7 @@ + diff --git a/Disco.Web/Views/Device/Export.cshtml b/Disco.Web/Views/Device/Export.cshtml index 55e03c6e..55dae634 100644 --- a/Disco.Web/Views/Device/Export.cshtml +++ b/Disco.Web/Views/Device/Export.cshtml @@ -13,7 +13,7 @@
@using (Html.BeginForm(MVC.API.Device.Export())) { -
+

Export Type

@@ -40,7 +40,7 @@
-
+

Export Fields (Defaults)

@foreach (var optionGroup in optionGroups) diff --git a/Disco.Web/Views/Device/Export.generated.cs b/Disco.Web/Views/Device/Export.generated.cs index 25da5c66..bdf262ed 100644 --- a/Disco.Web/Views/Device/Export.generated.cs +++ b/Disco.Web/Views/Device/Export.generated.cs @@ -96,7 +96,7 @@ WriteLiteral(" id=\"Devices_Export_Type\""); WriteLiteral(" class=\"form\""); -WriteLiteral(" style=\"width: 530px\""); +WriteLiteral(" style=\"width: 570px\""); WriteLiteral(">\r\n

Export Type

\r\n
\r\n \r\n " + " \r\n

Export Fields