From 27c21175d73f5b060fd02d91f1fddeec970abc2a Mon Sep 17 00:00:00 2001 From: Gary Sharp Date: Wed, 28 Sep 2016 20:16:25 +1000 Subject: [PATCH] Certificate/wireless plugins; major refactoring Migrate much of BI to Services. Added Wireless Profile Provider plugin feature. Added Certificate Authority Provider plugin feature. Modified Certificate Provider plugin feature. Database migration v17, for Device Profiles. Enrolment Client Updated to support CA Certificates, Wireless Profiles and Hardware Info. New Client Enrolment Protocol to support new features. Plugin Manifest Generator added to main solution. Improved AD search performance. --- Disco.BI/BI/DeviceBI/EnrolSafeException.cs | 14 - Disco.BI/BI/DeviceBI/EnrolmentLog.cs | 486 --- Disco.BI/BI/DisposableImageCollection.cs | 21 - .../Extensions/AttachmentActionExtensions.cs | 96 - .../Extensions/DeviceCertificateExtensions.cs | 38 - .../BI/Extensions/DeviceModelExtensions.cs | 53 - .../Extensions/DocumentTemplateExtensions.cs | 2 +- Disco.BI/BI/Extensions/JobExtensions.cs | 200 - Disco.BI/BI/Extensions/UserExtensions.cs | 36 - Disco.BI/BI/Extensions/UtilityExtensions.cs | 27 - .../WirelessCertificateExtensions.cs | 18 - Disco.BI/BI/Interop/Pdf/PdfGenerator.cs | 2 +- .../Pdf}/Utilities.cs | 2 +- Disco.BI/Disco.BI.csproj | 91 +- Disco.BI/Properties/AssemblyInfo.cs | 4 +- Disco.BI/Properties/Resources.Designer.cs | 52 +- Disco.BI/Properties/Resources.resx | 16 - Disco.BI/Resources/EmptyLogo.png | Bin 30171 -> 0 bytes Disco.BI/Resources/MimeType-doc48.png | Bin 5814 -> 0 bytes Disco.BI/Resources/MimeType-img16.png | Bin 3206 -> 0 bytes Disco.BI/Resources/MimeType-pdf16.png | Bin 3306 -> 0 bytes Disco.BI/Resources/MimeType-pdf48.png | Bin 5178 -> 0 bytes Disco.BI/Resources/MimeType-unknown48.png | Bin 4317 -> 0 bytes Disco.BI/packages.config | 7 - Disco.Client/Disco.Client.csproj | 48 +- Disco.Client/ErrorReporting.cs | 2 +- .../Extensions/ClientServiceException.cs | 4 - .../Extensions/ClientServicesExtensions.cs | 41 +- Disco.Client/Extensions/EnrolExtensions.cs | 119 +- Disco.Client/Interop/Certificates.cs | 151 +- Disco.Client/Interop/Hardware.cs | 277 ++ Disco.Client/Interop/LocalAuthentication.cs | 35 +- .../Native/NetworkConnectionStatuses.cs | 24 + .../Interop/Native/ProfileInfoFlags.cs | 11 + .../Interop/Native/WLAN_INTERFACE_INFO.cs | 30 + .../Native/WLAN_INTERFACE_INFO_LIST.cs | 51 + .../Interop/Native/WLAN_INTERFACE_STATE.cs | 43 + .../Interop/Native/WLAN_PROFILE_INFO.cs | 24 + .../Interop/Native/WLAN_PROFILE_INFO_LIST.cs | 47 + Disco.Client/Interop/Native/WlanApi.cs | 207 ++ Disco.Client/Interop/Network.cs | 376 +- Disco.Client/Interop/SystemAudit.cs | 201 - Disco.Client/Interop/WirelessNetwork.cs | 362 ++ Disco.Client/Presentation.cs | 9 +- Disco.Client/Program.cs | 15 +- Disco.Client/Properties/AssemblyInfo.cs | 4 +- Disco.ClientBootstrapper/BootstrapperLoop.cs | 28 +- .../Disco.ClientBootstrapper.csproj | 1 + .../Interop/NetworkInterop.cs | 4 +- .../Properties/AssemblyInfo.cs | 4 +- .../Modules/ActiveDirectoryConfiguration.cs | 2 +- .../Modules/JobPreferencesConfiguration.cs | 6 +- .../Configuration/SystemConfiguration.cs | 12 +- Disco.Data/Disco.Data.csproj | 8 + .../201609260741183_DBv17.Designer.cs | 27 + .../Migrations/201609260741183_DBv17.cs | 27 + .../Migrations/201609260741183_DBv17.resx | 123 + Disco.Data/Properties/AssemblyInfo.cs | 4 +- Disco.Data/Repository/DiscoDataSeeder.cs | 6 - Disco.Models/BI/Device/ImportDevice.cs | 35 - Disco.Models/BI/Device/ImportDeviceSession.cs | 11 - Disco.Models/ClientServices/Enrol.cs | 29 +- Disco.Models/ClientServices/EnrolResponse.cs | 31 +- .../EnrolmentInformation/Certificate.cs | 19 + .../EnrolmentInformation/CertificateStore.cs | 16 + .../EnrolmentInformation/DeviceHardware.cs | 20 + .../EnrolmentInformation/DiskDrive.cs | 20 + .../DiskDrivePartition.cs | 16 + .../EnrolmentInformation/DiskLogical.cs | 23 + .../EnrolmentInformation/NetworkAdapter.cs | 25 + .../EnrolmentInformation/PhysicalMemory.cs | 23 + .../EnrolmentInformation/Processor.cs | 21 + .../EnrolmentInformation/WirelessProfile.cs | 35 + .../WirelessProfileStore.cs | 24 + .../WirelessProfileTransformation.cs | 22 + Disco.Models/ClientServices/WhoAmIResponse.cs | 2 +- Disco.Models/Disco.Models.csproj | 25 +- Disco.Models/Properties/AssemblyInfo.cs | 4 +- .../Repository/Device/DeviceProfile.cs | 12 +- .../Job => Services/Jobs}/LocationModes.cs | 9 +- .../Jobs}/Statistics/DailyOpenedClosedItem.cs | 2 +- .../ConfigDeviceProfileShowModel.cs | 11 +- .../ConfigJobPreferencesIndexModel.cs | 6 +- .../ConfigOrganisationIndexModel.cs | 7 +- Disco.Models/UI/Device/DeviceShowModel.cs | 15 +- Disco.Models/UI/Job/JobShowModel.cs | 2 +- .../App.config | 34 + ....Services.Plugins.ManifestGenerator.csproj | 103 + .../Program.cs | 144 + .../Properties/AssemblyInfo.cs | 36 + .../packages.config | 6 + .../Attachments/AttachmentActionExtensions.cs | 100 +- .../AuthorizationRoleExtensions.cs | 11 +- .../ClientServicesExtensions.cs | 25 +- .../Devices}/DeviceActionExtensions.cs | 5 +- .../Devices}/DeviceBatchExtensions.cs | 2 +- .../Devices/DeviceBatches.cs | 12 +- .../Devices/DeviceCertificateExtensions.cs | 116 + .../Devices}/DeviceDetailExtensions.cs | 5 +- .../Devices}/DeviceExtensions.cs | 9 +- .../Devices/DeviceModelExtensions.cs | 62 +- .../Devices}/DeviceProfileExtensions.cs | 51 +- Disco.Services/Devices/DeviceUpdatesHub.cs | 10 +- .../DeviceWirelessProfileExtensions.cs | 67 + .../Devices/Enrolment/DeviceEnrolment.cs | 397 +- .../Devices/Enrolment/EnrolmentLog.cs | 503 +++ .../Enrolment/EnrolmentSafeException.cs | 11 + .../Devices/Enrolment/EnrolmentTypes.cs | 16 + .../Enrolment/LogMacAddressImportingTask.cs | 17 +- .../Devices/Exporting/DeviceExport.cs | 4 +- Disco.Services/Disco.Services.csproj | 41 + .../AttachmentImport/ThumbnailUpdateTask.cs | 128 + .../DocumentTemplateDevicesManagedGroup.cs | 2 +- .../DocumentTemplateManagedGroups.cs | 2 +- .../DocumentTemplateUsersManagedGroup.cs | 2 +- .../Interop/ActiveDirectory/ADGroup.cs | 2 +- .../Interop/ActiveDirectory/ADUserAccount.cs | 2 +- .../ActiveDirectory/ActiveDirectoryContext.cs | 28 +- .../Interop/DiscoServices/PluginLibrary.cs | 2 +- .../Jobs}/JobActionExtensions.cs | 22 +- Disco.Services/Jobs/JobExtensions.cs | 192 +- .../Jobs}/JobFlagExtensions.cs | 9 +- .../Jobs/JobQueues/JobQueueExtensions.cs | 6 +- .../Jobs/Jobs.cs | 13 +- .../Jobs}/Statistics/DailyOpenedClosed.cs | 21 +- .../CertificateAuthorityProviderFeature.cs | 14 + .../ProvisionAuthorityCertificatesResult.cs | 41 + .../CertificateProviderFeature.cs | 12 +- .../CertificateProviderLog.cs | 642 ++-- .../ProvisionPersonalCertificateResult.cs | 31 + .../ProvisionWirelessProfilesResult.cs | 37 + .../WirelessProfile.cs | 29 + .../WirelessProfileProviderFeature.cs | 16 + .../WirelessProfileTransformation.cs | 25 + Disco.Services/Plugins/PluginManifest.cs | 10 +- Disco.Services/Plugins/Plugins.cs | 17 +- Disco.Services/Properties/AssemblyInfo.cs | 4 +- Disco.Services/Tasks/IScheduledTaskStatus.cs | 3 + .../Tasks/ScheduledTaskMockStatus.cs | 27 +- Disco.Services/Tasks/ScheduledTaskStatus.cs | 10 + Disco.Services/Tasks/ScheduledTasksLog.cs | 38 +- Disco.Services/Users/UserExtensions.cs | 30 +- .../Users/UserFlags/UserFlagExtensions.cs | 7 +- Disco.Services/packages.config | 1 + .../BIModelExtensions/PluginExtensions.cs | 34 +- .../Disco.Web.Extensions.csproj | 1 + .../Properties/AssemblyInfo.cs | 4 +- Disco.Web/App_Code/CommonHelpers.cshtml | 16 +- Disco.Web/App_Code/CommonHelpers.generated.cs | 1124 +++--- Disco.Web/App_Start/AppConfig.cs | 10 +- Disco.Web/App_Start/RouteConfig.cs | 11 +- .../AuthorizationRoleController.cs | 5 +- .../API/Controllers/DeviceBatchController.cs | 3 +- .../Areas/API/Controllers/DeviceController.cs | 2 +- .../API/Controllers/DeviceModelController.cs | 3 +- .../Controllers/DeviceProfileController.cs | 144 +- .../Controllers/DocumentTemplateController.cs | 5 +- .../Areas/API/Controllers/JobController.cs | 12 +- .../Controllers/JobPreferencesController.cs | 3 +- .../API/Controllers/JobQueueController.cs | 5 +- .../API/Controllers/JobQueueJobController.cs | 4 +- .../Areas/API/Controllers/SystemController.cs | 61 +- .../UserFlagAssignmentController.cs | 8 +- .../Controllers/DeviceBatchController.cs | 7 +- .../Controllers/DeviceModelController.cs | 4 +- .../Controllers/DeviceProfileController.cs | 8 +- .../Controllers/DocumentTemplateController.cs | 4 +- .../Config/Models/DeviceProfile/IndexModel.cs | 7 +- .../Config/Models/DeviceProfile/ShowModel.cs | 2 + .../Models/DocumentTemplate/ShowModel.cs | 4 +- .../DocumentTemplate/UndetectedPagesModel.cs | 11 +- .../Models/JobPreferences/IndexModel.cs | 2 +- .../Config/Models/SystemConfig/IndexModel.cs | 3 + .../Config/Views/DeviceProfile/Show.cshtml | 920 +++-- .../Views/DeviceProfile/Show.generated.cs | 3237 ++++++++++------- .../Config/Views/DocumentTemplate/Show.cshtml | 2 +- .../Views/DocumentTemplate/Show.generated.cs | 91 +- .../Areas/Config/Views/Enrolment/Index.cshtml | 2 +- .../Config/Views/Enrolment/Index.generated.cs | 5 +- .../Config/Views/Enrolment/Status.cshtml | 2 +- .../Views/Enrolment/Status.generated.cs | 5 +- .../Config/Views/SystemConfig/Index.cshtml | 431 ++- .../Views/SystemConfig/Index.generated.cs | 998 ++--- Disco.Web/Areas/Config/Views/Web.config | 1 - .../UserHeldDevices/HeldJobDeviceModel.cs | 9 +- Disco.Web/Areas/Public/Views/Web.config | 1 - .../Services/Controllers/ClientController.cs | 82 +- Disco.Web/Controllers/DeviceController.cs | 14 +- Disco.Web/Controllers/JobController.cs | 11 +- Disco.Web/Controllers/UpdateController.cs | 13 +- Disco.Web/Controllers/UserController.cs | 3 +- Disco.Web/Disco.Web.csproj | 2 + .../API.DeviceProfileController.generated.cs | 90 +- .../API.JobPreferencesController.generated.cs | 4 +- .../T4MVC/API.SystemController.generated.cs | 30 + Disco.Web/Models/Device/ShowModel.cs | 16 +- Disco.Web/Models/Job/CreateModel.cs | 5 +- Disco.Web/Models/Job/IndexModel.cs | 10 +- Disco.Web/Models/Job/ShowModel.cs | 2 +- Disco.Web/Properties/AssemblyInfo.cs | 4 +- .../Views/Device/DeviceParts/_Subject.cshtml | 232 +- .../Device/DeviceParts/_Subject.generated.cs | 895 +++-- Disco.Web/Views/Job/JobParts/_Subject.cshtml | 13 +- .../Views/Job/JobParts/_Subject.generated.cs | 629 ++-- Disco.Web/Views/Shared/_Layout.cshtml | 2 +- Disco.Web/Views/Shared/_Layout.generated.cs | 7 +- Disco.Web/Views/Shared/_PublicLayout.cshtml | 2 +- .../Views/Shared/_PublicLayout.generated.cs | 13 +- Disco.Web/Views/Web.config | 1 - Disco.sln | 31 +- 210 files changed, 9822 insertions(+), 6675 deletions(-) delete mode 100644 Disco.BI/BI/DeviceBI/EnrolSafeException.cs delete mode 100644 Disco.BI/BI/DeviceBI/EnrolmentLog.cs delete mode 100644 Disco.BI/BI/DisposableImageCollection.cs delete mode 100644 Disco.BI/BI/Extensions/AttachmentActionExtensions.cs delete mode 100644 Disco.BI/BI/Extensions/DeviceCertificateExtensions.cs delete mode 100644 Disco.BI/BI/Extensions/DeviceModelExtensions.cs delete mode 100644 Disco.BI/BI/Extensions/JobExtensions.cs delete mode 100644 Disco.BI/BI/Extensions/UserExtensions.cs delete mode 100644 Disco.BI/BI/Extensions/UtilityExtensions.cs delete mode 100644 Disco.BI/BI/Extensions/WirelessCertificateExtensions.cs rename Disco.BI/BI/{DocumentTemplateBI => Interop/Pdf}/Utilities.cs (97%) delete mode 100644 Disco.BI/Resources/EmptyLogo.png delete mode 100644 Disco.BI/Resources/MimeType-doc48.png delete mode 100644 Disco.BI/Resources/MimeType-img16.png delete mode 100644 Disco.BI/Resources/MimeType-pdf16.png delete mode 100644 Disco.BI/Resources/MimeType-pdf48.png delete mode 100644 Disco.BI/Resources/MimeType-unknown48.png create mode 100644 Disco.Client/Interop/Hardware.cs create mode 100644 Disco.Client/Interop/Native/NetworkConnectionStatuses.cs create mode 100644 Disco.Client/Interop/Native/ProfileInfoFlags.cs create mode 100644 Disco.Client/Interop/Native/WLAN_INTERFACE_INFO.cs create mode 100644 Disco.Client/Interop/Native/WLAN_INTERFACE_INFO_LIST.cs create mode 100644 Disco.Client/Interop/Native/WLAN_INTERFACE_STATE.cs create mode 100644 Disco.Client/Interop/Native/WLAN_PROFILE_INFO.cs create mode 100644 Disco.Client/Interop/Native/WLAN_PROFILE_INFO_LIST.cs create mode 100644 Disco.Client/Interop/Native/WlanApi.cs delete mode 100644 Disco.Client/Interop/SystemAudit.cs create mode 100644 Disco.Client/Interop/WirelessNetwork.cs create mode 100644 Disco.Data/Migrations/201609260741183_DBv17.Designer.cs create mode 100644 Disco.Data/Migrations/201609260741183_DBv17.cs create mode 100644 Disco.Data/Migrations/201609260741183_DBv17.resx delete mode 100644 Disco.Models/BI/Device/ImportDevice.cs delete mode 100644 Disco.Models/BI/Device/ImportDeviceSession.cs create mode 100644 Disco.Models/ClientServices/EnrolmentInformation/Certificate.cs create mode 100644 Disco.Models/ClientServices/EnrolmentInformation/CertificateStore.cs create mode 100644 Disco.Models/ClientServices/EnrolmentInformation/DeviceHardware.cs create mode 100644 Disco.Models/ClientServices/EnrolmentInformation/DiskDrive.cs create mode 100644 Disco.Models/ClientServices/EnrolmentInformation/DiskDrivePartition.cs create mode 100644 Disco.Models/ClientServices/EnrolmentInformation/DiskLogical.cs create mode 100644 Disco.Models/ClientServices/EnrolmentInformation/NetworkAdapter.cs create mode 100644 Disco.Models/ClientServices/EnrolmentInformation/PhysicalMemory.cs create mode 100644 Disco.Models/ClientServices/EnrolmentInformation/Processor.cs create mode 100644 Disco.Models/ClientServices/EnrolmentInformation/WirelessProfile.cs create mode 100644 Disco.Models/ClientServices/EnrolmentInformation/WirelessProfileStore.cs create mode 100644 Disco.Models/ClientServices/EnrolmentInformation/WirelessProfileTransformation.cs rename Disco.Models/{BI/Job => Services/Jobs}/LocationModes.cs (55%) rename Disco.Models/{BI/Job => Services/Jobs}/Statistics/DailyOpenedClosedItem.cs (84%) create mode 100644 Disco.Services.Plugins.ManifestGenerator/App.config create mode 100644 Disco.Services.Plugins.ManifestGenerator/Disco.Services.Plugins.ManifestGenerator.csproj create mode 100644 Disco.Services.Plugins.ManifestGenerator/Program.cs create mode 100644 Disco.Services.Plugins.ManifestGenerator/Properties/AssemblyInfo.cs create mode 100644 Disco.Services.Plugins.ManifestGenerator/packages.config rename {Disco.BI/BI/Extensions => Disco.Services/Authorization}/AuthorizationRoleExtensions.cs (78%) rename {Disco.BI/BI/Extensions => Disco.Services/ClientServices}/ClientServicesExtensions.cs (71%) rename {Disco.BI/BI/Extensions => Disco.Services/Devices}/DeviceActionExtensions.cs (99%) rename {Disco.BI/BI/Extensions => Disco.Services/Devices}/DeviceBatchExtensions.cs (97%) rename Disco.BI/BI/DeviceBI/BatchUtilities.cs => Disco.Services/Devices/DeviceBatches.cs (58%) create mode 100644 Disco.Services/Devices/DeviceCertificateExtensions.cs rename {Disco.BI/BI/Extensions => Disco.Services/Devices}/DeviceDetailExtensions.cs (98%) rename {Disco.BI/BI/Extensions => Disco.Services/Devices}/DeviceExtensions.cs (98%) rename Disco.BI/BI/DeviceBI/DeviceModelBI.cs => Disco.Services/Devices/DeviceModelExtensions.cs (59%) rename {Disco.BI/BI/Extensions => Disco.Services/Devices}/DeviceProfileExtensions.cs (53%) create mode 100644 Disco.Services/Devices/DeviceWirelessProfileExtensions.cs rename Disco.BI/BI/DeviceBI/Enrol.cs => Disco.Services/Devices/Enrolment/DeviceEnrolment.cs (62%) create mode 100644 Disco.Services/Devices/Enrolment/EnrolmentLog.cs create mode 100644 Disco.Services/Devices/Enrolment/EnrolmentSafeException.cs create mode 100644 Disco.Services/Devices/Enrolment/EnrolmentTypes.cs rename Disco.BI/BI/DeviceBI/Migration/LogMacAddressImporting.cs => Disco.Services/Devices/Enrolment/LogMacAddressImportingTask.cs (89%) create mode 100644 Disco.Services/Documents/AttachmentImport/ThumbnailUpdateTask.cs rename {Disco.BI/BI/DocumentTemplateBI => Disco.Services/Documents}/ManagedGroups/DocumentTemplateDevicesManagedGroup.cs (99%) rename {Disco.BI/BI/DocumentTemplateBI => Disco.Services/Documents}/ManagedGroups/DocumentTemplateManagedGroups.cs (99%) rename {Disco.BI/BI/DocumentTemplateBI => Disco.Services/Documents}/ManagedGroups/DocumentTemplateUsersManagedGroup.cs (99%) rename {Disco.BI/BI/Extensions => Disco.Services/Jobs}/JobActionExtensions.cs (99%) rename {Disco.BI/BI/Extensions => Disco.Services/Jobs}/JobFlagExtensions.cs (96%) rename Disco.BI/BI/Extensions/JobQueueActionExtensions.cs => Disco.Services/Jobs/JobQueues/JobQueueExtensions.cs (98%) rename Disco.BI/BI/JobBI/Utilities.cs => Disco.Services/Jobs/Jobs.cs (97%) rename {Disco.BI/BI/JobBI => Disco.Services/Jobs}/Statistics/DailyOpenedClosed.cs (96%) create mode 100644 Disco.Services/Plugins/Features/CertificateAuthorityProvider/CertificateAuthorityProviderFeature.cs create mode 100644 Disco.Services/Plugins/Features/CertificateAuthorityProvider/ProvisionAuthorityCertificatesResult.cs create mode 100644 Disco.Services/Plugins/Features/CertificateProvider/ProvisionPersonalCertificateResult.cs create mode 100644 Disco.Services/Plugins/Features/WirelessProfileProvider/ProvisionWirelessProfilesResult.cs create mode 100644 Disco.Services/Plugins/Features/WirelessProfileProvider/WirelessProfile.cs create mode 100644 Disco.Services/Plugins/Features/WirelessProfileProvider/WirelessProfileProviderFeature.cs create mode 100644 Disco.Services/Plugins/Features/WirelessProfileProvider/WirelessProfileTransformation.cs rename Disco.BI/BI/Extensions/UserFlagActionExtensions.cs => Disco.Services/Users/UserFlags/UserFlagExtensions.cs (94%) diff --git a/Disco.BI/BI/DeviceBI/EnrolSafeException.cs b/Disco.BI/BI/DeviceBI/EnrolSafeException.cs deleted file mode 100644 index daf15bd1..00000000 --- a/Disco.BI/BI/DeviceBI/EnrolSafeException.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Threading; -namespace Disco.BI -{ - public class EnrolSafeException : System.Exception - { - public EnrolSafeException(string Message) : base(Message) - { - } - } -} diff --git a/Disco.BI/BI/DeviceBI/EnrolmentLog.cs b/Disco.BI/BI/DeviceBI/EnrolmentLog.cs deleted file mode 100644 index 4d805b0c..00000000 --- a/Disco.BI/BI/DeviceBI/EnrolmentLog.cs +++ /dev/null @@ -1,486 +0,0 @@ -using Disco.Services.Logging; -using Disco.Services.Logging.Models; -using Disco.Models.ClientServices; -using System; -using System.Collections.Generic; -using System.Diagnostics; -namespace Disco.BI.DeviceBI -{ - public class EnrolmentLog : LogBase - { - public enum EventTypeIds - { - SessionStarting = 10, - SessionProgress, - SessionDevice, - SessionDeviceInfo, - SessionFinished = 20, - SessionDiagnosticInformation, - SessionWarning, - SessionError, - SessionErrorWithInner, - SessionClientError, - SessionTaskAddedDevice = 50, - SessionTaskUpdatingDevice, - SessionTaskCreatedDeviceModel = 56, - SessionTaskProvisioningADAccount = 58, - SessionTaskAssigningUser = 60, - SessionTaskProvisioningWirelessCertificate = 62, - SessionTaskRenamingDevice = 64, - SessionTaskMovingDeviceOrganisationUnit = 66, - ClientError = 400 - } - private const int _ModuleId = 50; - public static EnrolmentLog Current - { - get - { - return (EnrolmentLog)LogContext.LogModules[50]; - } - } - public override string ModuleDescription - { - get - { - return "Device Enrolment"; - } - } - public override int ModuleId - { - get - { - return 50; - } - } - public override string ModuleName - { - get - { - return "DeviceEnrolment"; - } - } - [System.Diagnostics.DebuggerNonUserCode] - public EnrolmentLog() - { - } - private static void Log(EnrolmentLog.EventTypeIds EventTypeId, params object[] Args) - { - EnrolmentLog.Current.Log((int)EventTypeId, Args); - } - public static void LogSessionStarting(string SessionId, string HostId, DeviceEnrol.EnrolmentTypes EnrolmentType) - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionStarting, new object[] - { - SessionId, - HostId, - System.Enum.GetName(EnrolmentType.GetType(), EnrolmentType) - }); - } - public static void LogSessionDevice(string SessionId, string DeviceSerialNumber, int? DeviceModelId) - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionDevice, new object[] - { - SessionId, - DeviceSerialNumber, - DeviceModelId - }); - } - public static void LogSessionDeviceInfo(string SessionId, string SerialNumber, string UUID, string ComputerName, string LanMacAddress, string WlanMacAddress, string Manufacturer, string Model, string ModelType) - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionDeviceInfo, new object[] - { - SessionId, - SerialNumber, - UUID, - ComputerName, - LanMacAddress, - WlanMacAddress, - Manufacturer, - Model, - ModelType - }); - } - public static void LogSessionDeviceInfo(string SessionId, MacEnrol Request) - { - EnrolmentLog.LogSessionDeviceInfo(SessionId, Request.DeviceSerialNumber, Request.DeviceUUID, Request.DeviceComputerName, Request.DeviceLanMacAddress, Request.DeviceWlanMacAddress, Request.DeviceManufacturer, Request.DeviceModel, Request.DeviceModelType); - } - public static void LogSessionDeviceInfo(string SessionId, Models.ClientServices.Enrol Request) - { - EnrolmentLog.LogSessionDeviceInfo(SessionId, Request.DeviceSerialNumber, Request.DeviceUUID, Request.DeviceComputerName, Request.DeviceLanMacAddress, Request.DeviceWlanMacAddress, Request.DeviceManufacturer, Request.DeviceModel, Request.DeviceModelType); - } - public static void LogSessionDeviceInfo(string SessionId, Models.ClientServices.Register Request) - { - EnrolmentLog.LogSessionDeviceInfo(SessionId, Request.DeviceSerialNumber, Request.DeviceUUID, Request.DeviceComputerName, null, null, Request.DeviceManufacturer, Request.DeviceModel, Request.DeviceModelType); - } - public static void LogSessionProgress(string SessionId, int Progress, string Status) - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionProgress, new object[] - { - SessionId, - Progress, - Status - }); - } - public static void LogSessionFinished(string SessionId) - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionFinished, new object[] - { - SessionId - }); - } - public static void LogSessionDiagnosticInformation(string SessionId, string Message) - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionDiagnosticInformation, new object[] - { - SessionId, - Message - }); - } - public static void LogSessionWarning(string SessionId, string Message) - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionWarning, new object[] - { - SessionId, - Message - }); - } - public static void LogSessionError(string SessionId, System.Exception Ex) - { - if (Ex.InnerException == null) - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionError, new object[] - { - SessionId, - Ex.GetType().Name, - Ex.Message, - Ex.StackTrace - }); - } - else - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionErrorWithInner, new object[] - { - SessionId, - Ex.GetType().Name, - Ex.Message, - Ex.InnerException.GetType().Name, - Ex.InnerException.Message, - Ex.StackTrace, - Ex.InnerException.StackTrace - }); - } - } - public static void LogSessionClientError(string SessionId, string ClientIP, string ClientIdentifier, string ClientVersion, string Error, string RawError) - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionClientError, new object[] - { - SessionId, - ClientIP, - ClientIdentifier, - ClientVersion, - Error, - RawError - }); - } - public static void LogSessionTaskAddedDevice(string SessionId, string DeviceSerialNumber) - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskAddedDevice, new object[] - { - SessionId, - DeviceSerialNumber - }); - } - public static void LogSessionTaskUpdatingDevice(string SessionId, string DeviceSerialNumber) - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskUpdatingDevice, new object[] - { - SessionId, - DeviceSerialNumber - }); - } - public static void LogSessionTaskCreatedDeviceModel(string SessionId, string DeviceSerialNumber, string Manufacturer, string Model) - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskCreatedDeviceModel, new object[] - { - SessionId, - DeviceSerialNumber, - Manufacturer, - Model - }); - } - public static void LogSessionTaskProvisioningADAccount(string SessionId, string DeviceSerialNumber, string ADAccountName) - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskProvisioningADAccount, new object[] - { - SessionId, - DeviceSerialNumber, - ADAccountName - }); - } - public static void LogSessionTaskAssigningUser(string SessionId, string DeviceSerialNumber, string UserDisplayName, string UserUsername, string UserDomain, string UserSID) - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskAssigningUser, new object[] - { - SessionId, - DeviceSerialNumber, - UserDisplayName, - UserUsername, - UserDomain, - UserSID - }); - } - public static void LogSessionTaskProvisioningWirelessCertificate(string SessionId, string DeviceSerialNumber, string CertificateName) - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskProvisioningWirelessCertificate, new object[] - { - SessionId, - DeviceSerialNumber, - CertificateName - }); - } - public static void LogSessionTaskRenamingDevice(string SessionId, string OldComputerName, string NewComputerName) - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskRenamingDevice, new object[] - { - SessionId, - OldComputerName, - NewComputerName - }); - } - public static void LogSessionTaskMovingDeviceOrganisationUnit(string SessionId, string OldOrganisationUnit, string NewOrganisationUnit) - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskMovingDeviceOrganisationUnit, new object[] - { - SessionId, - OldOrganisationUnit, - NewOrganisationUnit - }); - } - public static void LogClientError(string ClientIP, string ClientIdentifier, string ClientVersion, string Error, string RawError) - { - EnrolmentLog.Log(EnrolmentLog.EventTypeIds.ClientError, new object[] - { - ClientIP, - ClientIdentifier, - ClientVersion, - Error, - RawError - }); - } - protected override System.Collections.Generic.List LoadEventTypes() - { - return new System.Collections.Generic.List - { - new LogEventType - { - Id = 10, - ModuleId = 50, - Name = "Session Starting", - Format = "Starting '{2}' Enrolment for {1} (Session# {0})", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = 12, - ModuleId = 50, - Name = "Session Device", - Format = null, - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = false - }, - new LogEventType - { - Id = 11, - ModuleId = 50, - Name = "Session Progress", - Format = "Processing Session# {0}; {1}% Complete; Status: {2}", - Severity = 0, - UseLive = true, - UsePersist = false, - UseDisplay = false - }, - new LogEventType - { - Id = 13, - ModuleId = 50, - Name = "Session Device Info", - Format = null, - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = 20, - ModuleId = 50, - Name = "Session Finished", - Format = "Finished Session# {0}", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = 21, - ModuleId = 50, - Name = "Session Diagnostic Information", - Format = null, - Severity = 0, - UseLive = true, - UsePersist = false, - UseDisplay = false - }, - new LogEventType - { - Id = 22, - ModuleId = 50, - Name = "Session Warning", - Format = null, - Severity = 1, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = 23, - ModuleId = 50, - Name = "Session Error", - Format = "An Error Occurred: [{1}] {2}", - Severity = 2, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = 24, - ModuleId = 50, - Name = "Session Error with Internal", - Format = "An Error Occurred: [{1}] {2}; Internal Error: [{3}] {4}", - Severity = 2, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = (int)EventTypeIds.SessionClientError, - ModuleId = _ModuleId, - Name = "Client Error", - Format = "IP: {1}; Device ID: {2}; Version: {3} Error: {4}; Session# {0}", - Severity = (int)LogEventType.Severities.Error, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = 50, - ModuleId = 50, - Name = "Task - Added Device", - Format = "Creating Disco Device {1}", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = 51, - ModuleId = 50, - Name = "Task - Updating Device", - Format = "Updating Disco Device {1}", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = 56, - ModuleId = 50, - Name = "Task - Creating Device Model", - Format = "Creating Device Model '{2} {3}' for Device {1}", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = 58, - ModuleId = 50, - Name = "Task - Provisioning Active Directory Account", - Format = "Provisioning Active Directory Account '{2}' for Device {1}", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = 60, - ModuleId = 50, - Name = "Task - Assigning User", - Format = "Assigning User '{2}' ({4}\\{3} {{{5}}}) for Device {1}", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = 62, - ModuleId = 50, - Name = "Task - Provisioning Wireless Certificate", - Format = "Provisioning Wireless Certificate '{2}' for Device {1}", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = 64, - ModuleId = 50, - Name = "Task - Renaming Device", - Format = "Renaming Device '{1}' to '{2}'", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = 66, - ModuleId = 50, - Name = "Task - Moving Device Organisation Unit", - Format = "Moving Device Organisation Unit '{1}' to '{2}'", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = (int)EventTypeIds.ClientError, - ModuleId = _ModuleId, - Name = "Client Error", - Format = "IP: {0}; Device ID: {1}; Version: {2} Error: {3}", - Severity = (int)LogEventType.Severities.Error, - UseLive = true, - UsePersist = true, - UseDisplay = true - } - }; - } - } -} diff --git a/Disco.BI/BI/DisposableImageCollection.cs b/Disco.BI/BI/DisposableImageCollection.cs deleted file mode 100644 index 5db5f777..00000000 --- a/Disco.BI/BI/DisposableImageCollection.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Drawing; - -namespace Disco.BI -{ - public class DisposableImageCollection : List, IDisposable - { - public void Dispose() - { - foreach (Image i in this) - { - if (i != null) - i.Dispose(); - } - } - - } -} diff --git a/Disco.BI/BI/Extensions/AttachmentActionExtensions.cs b/Disco.BI/BI/Extensions/AttachmentActionExtensions.cs deleted file mode 100644 index b394bbe0..00000000 --- a/Disco.BI/BI/Extensions/AttachmentActionExtensions.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Disco.Models.Repository; -using Disco.Data.Repository; -using Disco.Services.Users; -using Disco.Services.Authorization; -using Disco.BI.DocumentTemplateBI.ManagedGroups; -using Disco.Services; - -namespace Disco.BI.Extensions -{ - public static class AttachmentActionExtensions - { - - #region Delete - public static bool CanDelete(this DeviceAttachment da) - { - if (UserService.CurrentAuthorization.Has(Claims.Device.Actions.RemoveAnyAttachments)) - return true; - - if (UserService.CurrentAuthorization.Has(Claims.Device.Actions.RemoveOwnAttachments) - && da.TechUserId.Equals(UserService.CurrentUserId, StringComparison.OrdinalIgnoreCase)) - return true; - - return false; - } - public static void OnDelete(this DeviceAttachment da, DiscoDataContext Database) - { - if (!da.CanDelete()) - throw new InvalidOperationException("Deletion of Attachment is Denied"); - - var attachmentId = da.Id; - var documentTemplateId = da.DocumentTemplateId; - var deviceSerialNumber = da.DeviceSerialNumber; - - da.RepositoryDelete(Database); - Database.DeviceAttachments.Remove(da); - - DocumentTemplateManagedGroups.TriggerDeviceAttachmentDeleted(Database, attachmentId, documentTemplateId, deviceSerialNumber); - } - public static bool CanDelete(this JobAttachment ja) - { - if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.RemoveAnyAttachments)) - return true; - - if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.RemoveOwnAttachments) - && ja.TechUserId.Equals(UserService.CurrentUserId, StringComparison.OrdinalIgnoreCase)) - return true; - - return false; - } - public static void OnDelete(this JobAttachment ja, DiscoDataContext Database) - { - if (!ja.CanDelete()) - throw new InvalidOperationException("Deletion of Attachment is Denied"); - - var attachmentId = ja.Id; - var documentTemplateId = ja.DocumentTemplateId; - var jobId = ja.JobId; - - ja.RepositoryDelete(Database); - Database.JobAttachments.Remove(ja); - - DocumentTemplateManagedGroups.TriggerJobAttachmentDeleted(Database, attachmentId, documentTemplateId, jobId); - } - public static bool CanDelete(this UserAttachment ua) - { - if (UserService.CurrentAuthorization.Has(Claims.User.Actions.RemoveAnyAttachments)) - return true; - - if (UserService.CurrentAuthorization.Has(Claims.User.Actions.RemoveOwnAttachments) - && ua.TechUserId.Equals(UserService.CurrentUserId, StringComparison.OrdinalIgnoreCase)) - return true; - - return false; - } - public static void OnDelete(this UserAttachment ua, DiscoDataContext Database) - { - if (!ua.CanDelete()) - throw new InvalidOperationException("Deletion of Attachment is Denied"); - - var attachmentId = ua.Id; - var documentTemplateId = ua.DocumentTemplateId; - var userId = ua.UserId; - - ua.RepositoryDelete(Database); - Database.UserAttachments.Remove(ua); - - DocumentTemplateManagedGroups.TriggerUserAttachmentDeleted(Database, attachmentId, documentTemplateId, userId); - } - #endregion - - } -} diff --git a/Disco.BI/BI/Extensions/DeviceCertificateExtensions.cs b/Disco.BI/BI/Extensions/DeviceCertificateExtensions.cs deleted file mode 100644 index 3e806cd9..00000000 --- a/Disco.BI/BI/Extensions/DeviceCertificateExtensions.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Linq; -using Disco.Data.Repository; -using Disco.Models.Repository; -using Disco.Services.Plugins; -using Disco.Services.Plugins.Features.CertificateProvider; -using System; -using System.Collections.Generic; - -namespace Disco.BI.Extensions -{ - public static class DeviceCertificateExtensions - { - - public static Tuple> AllocateCertificate(this Device device, DiscoDataContext Database) - { - if (!string.IsNullOrEmpty(device.DeviceProfile.CertificateProviderId)) - { - // Load Plugin - PluginFeatureManifest featureManifest = Plugins.GetPluginFeature(device.DeviceProfile.CertificateProviderId, typeof(CertificateProviderFeature)); - - using (CertificateProviderFeature providerFeature = featureManifest.CreateInstance()) - { - // REMOVED 2012-07-18 G# - Plugin is responsible for checking - // Already Allocated Certificate - //if (deviceCertificates.Count > 0) - // return new Tuple>(deviceCertificates[0], providerPlugin.RemoveExistingCertificateNames()); - //else - - return providerFeature.AllocateCertificate(Database, device); - } - } - - // Device Profile does not allow certificate allocation - return null; - } - - } -} diff --git a/Disco.BI/BI/Extensions/DeviceModelExtensions.cs b/Disco.BI/BI/Extensions/DeviceModelExtensions.cs deleted file mode 100644 index d4599d33..00000000 --- a/Disco.BI/BI/Extensions/DeviceModelExtensions.cs +++ /dev/null @@ -1,53 +0,0 @@ -using Disco.Data.Repository; -using Disco.Models.Repository; -using Disco.Services; -using Disco.Services.Authorization; -using Disco.Services.Users; -using System; -using System.IO; -using System.Linq; - -namespace Disco.BI.Extensions -{ - public static class DeviceModelExtensions - { - #region Actions - public static bool CanDelete(this DeviceModel dm, DiscoDataContext Database) - { - if (!UserService.CurrentAuthorization.Has(Claims.Config.DeviceModel.Delete)) - return false; - - // Can't Delete Default Model (Id: 1) - if (dm.Id == 1) - return false; - - // Can't Delete if Contains Devices - if (Database.Devices.Count(d => d.DeviceModelId == dm.Id) > 0) - return false; - - return true; - } - public static void Delete(this DeviceModel dm, DiscoDataContext Database) - { - if (!dm.CanDelete(Database)) - throw new InvalidOperationException("The state of this Device Model doesn't allow it to be deleted"); - - // Delete Image - var deviceModelImagePath = dm.ImageFilePath(); - if (File.Exists(deviceModelImagePath)) - File.Delete(deviceModelImagePath); - - // Delete any Device Model Components - foreach (var deviceModelComponent in Database.DeviceComponents.Where(dc => dc.DeviceModelId == dm.Id).ToList()) - { - Database.DeviceComponents.Remove(deviceModelComponent); - } - - // Delete Model - Database.DeviceModels.Remove(dm); - } - // End Added 2012-11-26 G# - #endregion - - } -} diff --git a/Disco.BI/BI/Extensions/DocumentTemplateExtensions.cs b/Disco.BI/BI/Extensions/DocumentTemplateExtensions.cs index d597363e..0e8db1d4 100644 --- a/Disco.BI/BI/Extensions/DocumentTemplateExtensions.cs +++ b/Disco.BI/BI/Extensions/DocumentTemplateExtensions.cs @@ -1,9 +1,9 @@ -using Disco.BI.DocumentTemplateBI.ManagedGroups; using Disco.Data.Repository; using Disco.Models.Repository; using Disco.Models.Services.Documents; using Disco.Services; using Disco.Services.Documents; +using Disco.Services.Documents.ManagedGroups; using Disco.Services.Expressions; using Disco.Services.Interop.ActiveDirectory; using iTextSharp.text.pdf; diff --git a/Disco.BI/BI/Extensions/JobExtensions.cs b/Disco.BI/BI/Extensions/JobExtensions.cs deleted file mode 100644 index 5b94193f..00000000 --- a/Disco.BI/BI/Extensions/JobExtensions.cs +++ /dev/null @@ -1,200 +0,0 @@ -using Disco.Data.Repository; -using Disco.Models.Repository; -using Disco.Models.Services.Documents; -using Disco.Services; -using Disco.Services.Authorization; -using Disco.Services.Plugins; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Disco.BI.Extensions -{ - public static class JobExtensions - { - public static List AvailableDocumentTemplates(this Job j, DiscoDataContext Database, User User, DateTime TimeStamp) - { - var dts = Database.DocumentTemplates.Include("JobSubTypes") - .Where(dt => dt.Scope == DocumentTemplate.DocumentTemplateScopes.Job) - .ToList(); - - foreach (var dt in dts.ToArray()) - { - if (dt.JobSubTypes.Count != 0) - { // Filter Applied - bool match = false; - foreach (var st in j.JobSubTypes) - { - if (dt.JobSubTypes.Contains(st)) - { - match = true; - break; - } - } - if (!match) - dts.Remove(dt); - } - } - - // Evaluate Filters - dts = dts.Where(dt => dt.FilterExpressionMatches(j, Database, User, TimeStamp, DocumentState.DefaultState())).ToList(); - - return dts; - } - - public static DateTime ValidateDateAfterOpened(this Job j, DateTime d) - { - if (d < j.OpenedDate) - { - if (d > j.OpenedDate.AddMinutes(-1)) - return j.OpenedDate; - else - throw new ArgumentException("The Date must be >= the Open Date.", "d"); - } - return d; - } - - public static string GenerateFaultDescription(this Job j, DiscoDataContext Database) - { - StringBuilder sb = new StringBuilder(); - - sb.AppendLine("Faulty Components:"); - foreach (var jst in j.JobSubTypes) - sb.Append("- ").AppendLine(jst.Description).AppendLine(" - "); - - return sb.ToString(); - } - - public static string GenerateFaultDescriptionFooter(this Job j, DiscoDataContext Database, PluginFeatureManifest WarrantyProviderDefinition) - { - var versionDisco = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; - return string.Format("Automation by Disco v{0}.{1}.{2:0000}.{3:0000} (Provider: {4} v{5})", - versionDisco.Major, versionDisco.Minor, versionDisco.Build, versionDisco.Revision, WarrantyProviderDefinition.Id, WarrantyProviderDefinition.PluginManifest.Version.ToString(4)); - } - - public static void UpdateSubTypes(this Job j, DiscoDataContext Database, List SubTypes, bool AddComponents, User TechUser) - { - if (SubTypes == null || SubTypes.Count == 0) - throw new ArgumentException("The Job must contain at least one Sub Type"); - - List addedSubTypes = new List(); - List removedSubTypes = new List(); - - // Removed Sub Types - foreach (var t in j.JobSubTypes.ToArray()) - if (!SubTypes.Contains(t)) - { - removedSubTypes.Add(t); - j.JobSubTypes.Remove(t); - } - // Added Sub Types - foreach (var t in SubTypes) - if (!j.JobSubTypes.Contains(t)) - { - addedSubTypes.Add(t); - j.JobSubTypes.Add(t); - } - - // Write Log - if (addedSubTypes.Count > 0 || removedSubTypes.Count > 0) - { - StringBuilder logBuilder = new StringBuilder(); - logBuilder.AppendLine("# Updated Job Sub Types"); - if (removedSubTypes.Count > 0) - { - logBuilder.AppendLine().AppendLine("Removed:"); - foreach (var t in removedSubTypes) - logBuilder.Append("- **").Append(t.ToString()).AppendLine("**"); - } - if (addedSubTypes.Count > 0) - { - logBuilder.AppendLine().AppendLine("Added:"); - foreach (var t in addedSubTypes) - logBuilder.Append("- **").Append(t.ToString()).AppendLine("**"); - } - Database.JobLogs.Add(new JobLog() - { - JobId = j.Id, - TechUserId = TechUser.UserId, - Timestamp = DateTime.Now, - Comments = logBuilder.ToString() - }); - } - - // Add Components - if (AddComponents && addedSubTypes.Count > 0 && j.DeviceSerialNumber != null) - { - var components = Database.DeviceComponents.Include("JobSubTypes").Where(c => !c.DeviceModelId.HasValue || c.DeviceModelId == j.Device.DeviceModelId); - var addedComponents = new List(); - foreach (var c in components) - { - foreach (var st in c.JobSubTypes) - { - foreach (var jst in addedSubTypes) - { - if (st.JobTypeId == jst.JobTypeId && st.Id == jst.Id) - { - addedComponents.Add(c); - break; - } - } - if (addedComponents.Contains(c)) - break; - } - } - foreach (var c in addedComponents) - { - if (!j.JobComponents.Any(jc => jc.Description.Equals(c.Description, StringComparison.OrdinalIgnoreCase))) - { // Job Component with matching Description doesn't exist. - Database.JobComponents.Add(new JobComponent() - { - Job = j, - TechUserId = TechUser.UserId, - Cost = c.Cost, - Description = c.Description - }); - } - } - } - } - - private static List FilterCreatableTypePermissions(AuthorizationToken Authorization) - { - if (!Authorization.HasAll(Claims.Job.Types.CreateHMisc, Claims.Job.Types.CreateHNWar, Claims.Job.Types.CreateHWar, Claims.Job.Types.CreateSApp, Claims.Job.Types.CreateSImg, Claims.Job.Types.CreateSOS, Claims.Job.Types.CreateUMgmt)) - { - // Must Filter - List allowedTypes = new List(6); - if (Authorization.Has(Claims.Job.Types.CreateHMisc)) - allowedTypes.Add(JobType.JobTypeIds.HMisc); - if (Authorization.Has(Claims.Job.Types.CreateHNWar)) - allowedTypes.Add(JobType.JobTypeIds.HNWar); - if (Authorization.Has(Claims.Job.Types.CreateHWar)) - allowedTypes.Add(JobType.JobTypeIds.HWar); - if (Authorization.Has(Claims.Job.Types.CreateSApp)) - allowedTypes.Add(JobType.JobTypeIds.SApp); - if (Authorization.Has(Claims.Job.Types.CreateSImg)) - allowedTypes.Add(JobType.JobTypeIds.SImg); - if (Authorization.Has(Claims.Job.Types.CreateSOS)) - allowedTypes.Add(JobType.JobTypeIds.SOS); - if (Authorization.Has(Claims.Job.Types.CreateUMgmt)) - allowedTypes.Add(JobType.JobTypeIds.UMgmt); - - return allowedTypes; - } - return null; - } - - public static IQueryable FilterCreatableTypePermissions(this IQueryable JobTypes, AuthorizationToken Authorization) - { - var allowedTypes = FilterCreatableTypePermissions(Authorization); - - if (allowedTypes != null) - { - return JobTypes.Where(jt => allowedTypes.Contains(jt.Id)); - } - - return JobTypes; - } - } -} diff --git a/Disco.BI/BI/Extensions/UserExtensions.cs b/Disco.BI/BI/Extensions/UserExtensions.cs deleted file mode 100644 index 713717e4..00000000 --- a/Disco.BI/BI/Extensions/UserExtensions.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Disco.Data.Repository; -using Disco.Models.Repository; -using Disco.Models.Services.Documents; -using Disco.Services; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Disco.BI.Extensions -{ - public static class UserExtensions - { - public static List AvailableDocumentTemplates(this User u, DiscoDataContext Database, User User, DateTime TimeStamp) - { - var dts = Database.DocumentTemplates.Include("JobSubTypes") - .Where(dt => dt.Scope == DocumentTemplate.DocumentTemplateScopes.User) - .ToArray() - .Where(dt => dt.FilterExpressionMatches(u, Database, User, TimeStamp, DocumentState.DefaultState())).ToList(); - - return dts; - } - - public static List CurrentDeviceUserAssignments(this User u) - { - return u.DeviceUserAssignments.Where(dua => !dua.UnassignedDate.HasValue).ToList(); - } - - public static bool CanCreateJob(this User u) - { - if (!JobActionExtensions.CanCreate()) - return false; - - return true; - } - } -} diff --git a/Disco.BI/BI/Extensions/UtilityExtensions.cs b/Disco.BI/BI/Extensions/UtilityExtensions.cs deleted file mode 100644 index d335c0e5..00000000 --- a/Disco.BI/BI/Extensions/UtilityExtensions.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.IO; -using System.Drawing.Imaging; - -namespace Disco.BI.Extensions -{ - public static class UtilityExtensions - { - - public static string StreamToString(this System.IO.Stream stream) - { - if (stream.Position != 0 && stream.CanSeek) - { - stream.Position = 0; - } - using (System.IO.StreamReader sr = new System.IO.StreamReader(stream)) - { - return sr.ReadToEnd(); - } - } - - } -} diff --git a/Disco.BI/BI/Extensions/WirelessCertificateExtensions.cs b/Disco.BI/BI/Extensions/WirelessCertificateExtensions.cs deleted file mode 100644 index f47cc816..00000000 --- a/Disco.BI/BI/Extensions/WirelessCertificateExtensions.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Disco.Models.Repository; -using System; -using System.Security.Cryptography.X509Certificates; -namespace Disco.BI.Extensions -{ - public static class WirelessCertificateExtensions - { - public static System.DateTime? CertificateExpirationDate(this DeviceCertificate wc) - { - if (wc.Content == null || wc.Content.Length == 0) - { - return null; - } - X509Certificate2 c = new X509Certificate2(wc.Content, "password"); - return c.NotAfter; - } - } -} diff --git a/Disco.BI/BI/Interop/Pdf/PdfGenerator.cs b/Disco.BI/BI/Interop/Pdf/PdfGenerator.cs index 9d58cbd0..d1a664e5 100644 --- a/Disco.BI/BI/Interop/Pdf/PdfGenerator.cs +++ b/Disco.BI/BI/Interop/Pdf/PdfGenerator.cs @@ -42,7 +42,7 @@ namespace Disco.BI.Interop.Pdf } else { - Stream bulkPdf = DocumentTemplateBI.Utilities.JoinPdfs(generatedPdfs.ToArray()); + Stream bulkPdf = Utilities.JoinPdfs(generatedPdfs.ToArray()); foreach (Stream singlePdf in generatedPdfs) singlePdf.Dispose(); return bulkPdf; diff --git a/Disco.BI/BI/DocumentTemplateBI/Utilities.cs b/Disco.BI/BI/Interop/Pdf/Utilities.cs similarity index 97% rename from Disco.BI/BI/DocumentTemplateBI/Utilities.cs rename to Disco.BI/BI/Interop/Pdf/Utilities.cs index 5e66e0aa..3a46edbf 100644 --- a/Disco.BI/BI/DocumentTemplateBI/Utilities.cs +++ b/Disco.BI/BI/Interop/Pdf/Utilities.cs @@ -1,7 +1,7 @@ using iTextSharp.text; using iTextSharp.text.pdf; -namespace Disco.BI.DocumentTemplateBI +namespace Disco.BI.Interop.Pdf { public static class Utilities { diff --git a/Disco.BI/Disco.BI.csproj b/Disco.BI/Disco.BI.csproj index fb809c58..7978bc58 100644 --- a/Disco.BI/Disco.BI.csproj +++ b/Disco.BI/Disco.BI.csproj @@ -15,6 +15,7 @@ ..\ true + 2.2.16272.1003 true @@ -37,33 +38,15 @@ false - - ..\Resources\Libraries\LibTiff.NET\BitMiracle.LibTiff.NET.dll - ..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll - - False - ..\packages\Exceptionless.1.5.2092\lib\net45\Exceptionless.dll - - - False - ..\packages\Exceptionless.1.5.2092\lib\net45\Exceptionless.Models.dll - ..\Resources\Libraries\iTextSharp\itextsharp.dll - - ..\packages\plist.net.1.0\lib\Net35\PList.dll - True - ..\Resources\Libraries\Quartz\Quartz.dll - - ..\..\..\Resources\Libraries\SshNet\Renci.SshNet.dll - @@ -72,29 +55,15 @@ - + ..\packages\Microsoft.Net.Http.2.2.22\lib\net45\System.Net.Http.Extensions.dll + True - + ..\packages\Microsoft.Net.Http.2.2.22\lib\net45\System.Net.Http.Primitives.dll + True - - False - ..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll - - - False - ..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll - - - False - ..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll - - - False - ..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll - @@ -105,39 +74,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - True @@ -170,24 +109,6 @@ Designer - - - - - - - - - - - - - - - - - - diff --git a/Disco.BI/Properties/AssemblyInfo.cs b/Disco.BI/Properties/AssemblyInfo.cs index c905096b..2f4590eb 100644 --- a/Disco.BI/Properties/AssemblyInfo.cs +++ b/Disco.BI/Properties/AssemblyInfo.cs @@ -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.1.0.0")] -[assembly: AssemblyFileVersion("2.1.0.0")] \ No newline at end of file +[assembly: AssemblyVersion("2.2.16272.1003")] +[assembly: AssemblyFileVersion("2.2.16272.1003")] \ No newline at end of file diff --git a/Disco.BI/Properties/Resources.Designer.cs b/Disco.BI/Properties/Resources.Designer.cs index 6878efb3..70d245f4 100644 --- a/Disco.BI/Properties/Resources.Designer.cs +++ b/Disco.BI/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // 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. @@ -59,55 +59,5 @@ namespace Disco.Properties { resourceCulture = value; } } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap MimeType_doc48 { - get { - object obj = ResourceManager.GetObject("MimeType_doc48", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap MimeType_img16 { - get { - object obj = ResourceManager.GetObject("MimeType_img16", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap MimeType_pdf16 { - get { - object obj = ResourceManager.GetObject("MimeType_pdf16", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap MimeType_pdf48 { - get { - object obj = ResourceManager.GetObject("MimeType_pdf48", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap MimeType_unknown48 { - get { - object obj = ResourceManager.GetObject("MimeType_unknown48", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } } } diff --git a/Disco.BI/Properties/Resources.resx b/Disco.BI/Properties/Resources.resx index 0088f8e5..1af7de15 100644 --- a/Disco.BI/Properties/Resources.resx +++ b/Disco.BI/Properties/Resources.resx @@ -117,20 +117,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\MimeType-doc48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\MimeType-img16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\MimeType-pdf16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\MimeType-pdf48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\MimeType-unknown48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - \ No newline at end of file diff --git a/Disco.BI/Resources/EmptyLogo.png b/Disco.BI/Resources/EmptyLogo.png deleted file mode 100644 index 766f006f20babcefb4f484653ba726edea2d9e0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30171 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%0DDmkGBA%yR*oZ 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 diff --git a/Disco.BI/Resources/MimeType-doc48.png b/Disco.BI/Resources/MimeType-doc48.png deleted file mode 100644 index cf7caee90be7bb5d26974b74220cb9974a726af1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5814 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 AasU7T diff --git a/Disco.BI/Resources/MimeType-img16.png b/Disco.BI/Resources/MimeType-img16.png deleted file mode 100644 index 60d7f35beff80883bfaf2bb4b36fde42154ddf31..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3206 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 diff --git a/Disco.BI/Resources/MimeType-pdf16.png b/Disco.BI/Resources/MimeType-pdf16.png deleted file mode 100644 index 9d115de1836685828efe484bed32a3668ff11572..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3306 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 diff --git a/Disco.BI/Resources/MimeType-pdf48.png b/Disco.BI/Resources/MimeType-pdf48.png deleted file mode 100644 index 34f1b26c0e613d89df51f77f12e5f587b1177b38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5178 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 diff --git a/Disco.BI/Resources/MimeType-unknown48.png b/Disco.BI/Resources/MimeType-unknown48.png deleted file mode 100644 index ccbf7b3a747bd73237c8ee0ee9b591f2dbc488c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4317 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 LNkvXXu0mjfdEy)_ diff --git a/Disco.BI/packages.config b/Disco.BI/packages.config index 24f60da5..2dcee567 100644 --- a/Disco.BI/packages.config +++ b/Disco.BI/packages.config @@ -1,14 +1,7 @@  - - - - - - - \ No newline at end of file diff --git a/Disco.Client/Disco.Client.csproj b/Disco.Client/Disco.Client.csproj index ff44ad7f..a3a0ff23 100644 --- a/Disco.Client/Disco.Client.csproj +++ b/Disco.Client/Disco.Client.csproj @@ -14,6 +14,7 @@ Client ..\ true + 2.2.16272.1003 AnyCPU @@ -65,6 +66,42 @@ Models\ClientServices\Enrol.cs + + Models\ClientServices\EnrolmentInformation\Certificate.cs + + + Models\ClientServices\EnrolmentInformation\CertificateStore.cs + + + Models\ClientServices\EnrolmentInformation\DeviceHardware.cs + + + Models\ClientServices\EnrolmentInformation\DiskDrive.cs + + + Models\ClientServices\EnrolmentInformation\DiskDrivePartition.cs + + + Models\ClientServices\EnrolmentInformation\DiskLogical.cs + + + Models\ClientServices\EnrolmentInformation\NetworkAdapter.cs + + + Models\ClientServices\EnrolmentInformation\PhysicalMemory.cs + + + Models\ClientServices\EnrolmentInformation\Processor.cs + + + Models\ClientServices\EnrolmentInformation\WirelessProfile.cs + + + Models\ClientServices\EnrolmentInformation\WirelessProfileStore.cs + + + Models\ClientServices\EnrolmentInformation\WirelessProfileTransformation.cs + Models\ClientServices\EnrolResponse.cs @@ -92,10 +129,19 @@ + + + + + + + + + + - diff --git a/Disco.Client/ErrorReporting.cs b/Disco.Client/ErrorReporting.cs index 44afd2a3..738ed849 100644 --- a/Disco.Client/ErrorReporting.cs +++ b/Disco.Client/ErrorReporting.cs @@ -89,7 +89,7 @@ namespace Disco.Client string reportResponse; HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(ServicePathTemplate); - request.UserAgent = string.Format("Disco-Client/{0}", Assembly.GetExecutingAssembly().GetName().Version.ToString(3)); + request.UserAgent = $"Disco-Client/{Assembly.GetExecutingAssembly().GetName().Version.ToString(3)}"; request.ContentType = "application/json"; request.Method = WebRequestMethods.Http.Post; request.UseDefaultCredentials = true; diff --git a/Disco.Client/Extensions/ClientServiceException.cs b/Disco.Client/Extensions/ClientServiceException.cs index 752155de..904cdda7 100644 --- a/Disco.Client/Extensions/ClientServiceException.cs +++ b/Disco.Client/Extensions/ClientServiceException.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Disco.Client.Extensions { diff --git a/Disco.Client/Extensions/ClientServicesExtensions.cs b/Disco.Client/Extensions/ClientServicesExtensions.cs index 01fe367f..9ac506ab 100644 --- a/Disco.Client/Extensions/ClientServicesExtensions.cs +++ b/Disco.Client/Extensions/ClientServicesExtensions.cs @@ -1,55 +1,60 @@ -using System; -using System.Collections.Generic; +using Disco.Models.ClientServices; +using Newtonsoft.Json; using System.IO; -using System.Linq; using System.Net; using System.Reflection; -using System.Text; -using System.Threading.Tasks; -using Disco.Models.ClientServices; -using Newtonsoft.Json; namespace Disco.Client.Extensions { public static class ClientServicesExtensions { +#if DEBUG + public const string ServicePathAuthenticatedTemplate = "http://WS-GSHARP:57252/Services/Client/Authenticated/{0}"; + public const string ServicePathUnauthenticatedTemplate = "http://WS-GSHARP:57252/Services/Client/Unauthenticated/{0}"; +#else public const string ServicePathAuthenticatedTemplate = "http://DISCO:9292/Services/Client/Authenticated/{0}"; public const string ServicePathUnauthenticatedTemplate = "http://DISCO:9292/Services/Client/Unauthenticated/{0}"; +#endif public static ResponseType Post(this ServiceBase Service, bool Authenticated) { - string jsonResponse; + ResponseType serviceResponse; string serviceUrl; + if (Authenticated) serviceUrl = string.Format(ServicePathAuthenticatedTemplate, Service.Feature); else serviceUrl = string.Format(ServicePathUnauthenticatedTemplate, Service.Feature); HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(serviceUrl); - request.UserAgent = string.Format("Disco-Client/{0}", Assembly.GetExecutingAssembly().GetName().Version.ToString(3)); + request.UserAgent = $"Disco-Client/{Assembly.GetExecutingAssembly().GetName().Version.ToString(3)}"; request.ContentType = "application/json"; request.Method = WebRequestMethods.Http.Post; request.UseDefaultCredentials = true; request.Timeout = 300000; // 5 Minutes - string jsonRequest = JsonConvert.SerializeObject(Service); - using (StreamWriter requestWriter = new StreamWriter(request.GetRequestStream())) + var jsonSerializer = new JsonSerializer(); + + using (var requestWriter = new StreamWriter(request.GetRequestStream())) { - requestWriter.Write(jsonRequest); + using (var jsonWriter = new JsonTextWriter(requestWriter)) + { + jsonSerializer.Serialize(jsonWriter, Service); + } } using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { - using (StreamReader responseReader = new StreamReader(response.GetResponseStream())) + using (var responseReader = new StreamReader(response.GetResponseStream())) { - jsonResponse = responseReader.ReadToEnd(); + using (var jsonReader = new JsonTextReader(responseReader)) + { + serviceResponse = jsonSerializer.Deserialize(jsonReader); + } } } - if (string.IsNullOrEmpty(jsonResponse)) - return default(ResponseType); - else - return JsonConvert.DeserializeObject(jsonResponse); + return serviceResponse; } } diff --git a/Disco.Client/Extensions/EnrolExtensions.cs b/Disco.Client/Extensions/EnrolExtensions.cs index 6655c702..8063c5ef 100644 --- a/Disco.Client/Extensions/EnrolExtensions.cs +++ b/Disco.Client/Extensions/EnrolExtensions.cs @@ -1,13 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using Disco.Client.Interop; using Disco.Models.ClientServices; -using System.Security.Cryptography.X509Certificates; -using System.IO; -using System.Diagnostics; using Microsoft.Win32; -using System.Text.RegularExpressions; +using System; +using System.Diagnostics; +using System.IO; namespace Disco.Client.Extensions { @@ -16,26 +12,23 @@ namespace Disco.Client.Extensions public static void Build(this Enrol enrol) { - enrol.DeviceUUID = Interop.SystemAudit.DeviceUUID; - enrol.DeviceSerialNumber = Interop.SystemAudit.DeviceSerialNumber; + enrol.ComputerName = Environment.MachineName; + enrol.RunningUserDomain = Environment.UserDomainName; + enrol.RunningUserName = Environment.UserName; + enrol.RunningInteractively = Environment.UserInteractive; - enrol.DeviceComputerName = Interop.LocalAuthentication.ComputerName; + // Hardware Audit + enrol.Hardware = Hardware.Information; + enrol.SerialNumber = enrol.Hardware.SerialNumber; - enrol.DeviceManufacturer = Interop.SystemAudit.DeviceManufacturer; - enrol.DeviceModel = Interop.SystemAudit.DeviceModel; - enrol.DeviceModelType = Interop.SystemAudit.DeviceType; - - enrol.DeviceIsPartOfDomain = Interop.SystemAudit.DeviceIsPartOfDomain; - enrol.DeviceDNSDomainName = Interop.SystemAudit.DeviceDNSDomainName; - - // LAN - enrol.DeviceLanMacAddress = Interop.Network.PrimaryLanMacAddress; - - // WAN - enrol.DeviceWlanMacAddress = Interop.Network.PrimaryWlanMacAddress; + // Apply System Information + enrol.ApplySystemInformation(); // Certificates - enrol.DeviceCertificates = Interop.Certificates.GetCertificateSubjects(StoreName.My, StoreLocation.LocalMachine); + enrol.Certificates = Certificates.GetAllCertificates(); + + // Wireless Profiles + enrol.WirelessProfiles = WirelessNetwork.GetWirelessProfiles(); } public static void Process(this EnrolResponse enrolResponse) @@ -51,12 +44,14 @@ namespace Disco.Client.Extensions // Offline Domain Join bool requireReboot = enrolResponse.ApplyOfflineDomainJoin(); - // Certificates - enrolResponse.ApplyDeviceCertificates(); - // Device Owner enrolResponse.ApplyDeviceAssignedUser(); + // Certificates + enrolResponse.ApplyDeviceCertificates(); + + // Wireless Profiles + enrolResponse.ApplyWirelessProfiles(); Presentation.UpdateStatus("Enrolling Device", "Device Enrolment Successfully Completed", false, 0, 1500); @@ -71,15 +66,15 @@ namespace Disco.Client.Extensions /// Boolean indicating whether a reboot is required. private static bool ApplyOfflineDomainJoin(this EnrolResponse enrolResponse) { - if (!string.IsNullOrWhiteSpace(enrolResponse.OfflineDomainJoin)) + if (!string.IsNullOrWhiteSpace(enrolResponse.OfflineDomainJoinManifest)) { - Presentation.UpdateStatus("Enrolling Device", string.Format("Performing Offline Domain Join:{0}Renaming Computer: {1} -> {2}", Environment.NewLine, Interop.LocalAuthentication.ComputerName, enrolResponse.DeviceComputerName), true, -1, 1500); + Presentation.UpdateStatus("Enrolling Device", $"Performing Offline Domain Join:\r\nRenaming Computer: {Environment.MachineName} -> {enrolResponse.ComputerName}", true, -1, 1500); string odjFile = Path.GetTempFileName(); - File.WriteAllBytes(odjFile, Convert.FromBase64String(enrolResponse.OfflineDomainJoin)); + File.WriteAllBytes(odjFile, Convert.FromBase64String(enrolResponse.OfflineDomainJoinManifest)); string odjWindowsPath = Environment.GetEnvironmentVariable("SystemRoot"); - string odjProcessArguments = string.Format("/REQUESTODJ /LOADFILE \"{0}\" /WINDOWSPATH \"{1}\" /LOCALOS", odjFile, odjWindowsPath); + string odjProcessArguments = $"/REQUESTODJ /LOADFILE \"{odjFile}\" /WINDOWSPATH \"{odjWindowsPath}\" /LOCALOS"; ProcessStartInfo odjProcessStartInfo = new ProcessStartInfo("DJOIN.EXE", odjProcessArguments) { @@ -95,17 +90,17 @@ namespace Disco.Client.Extensions odjResult = odjProcess.StandardOutput.ReadToEnd(); odjProcess.WaitForExit(20000); // 20 Seconds } - Presentation.UpdateStatus("Enrolling Device", string.Format("Offline Domain Join Result:{0}{1}", Environment.NewLine, odjResult), true, -1, 3000); + Presentation.UpdateStatus("Enrolling Device", $"Offline Domain Join Result:\r\n{odjResult}", true, -1, 3000); if (File.Exists(odjFile)) File.Delete(odjFile); // Flush Logged-On History - if (!string.IsNullOrEmpty(enrolResponse.DeviceDomainName)) + if (!string.IsNullOrEmpty(enrolResponse.DomainName)) { using (RegistryKey regWinlogon = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true)) { - regWinlogon.SetValue("DefaultDomainName", enrolResponse.DeviceDomainName, RegistryValueKind.String); + regWinlogon.SetValue("DefaultDomainName", enrolResponse.DomainName, RegistryValueKind.String); regWinlogon.SetValue("DefaultUserName", String.Empty, RegistryValueKind.String); } using (RegistryKey regLogonUI = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI", true)) @@ -130,62 +125,44 @@ namespace Disco.Client.Extensions private static void ApplyDeviceAssignedUser(this EnrolResponse enrolResponse) { // Only run task if Assigned User was specified - if (!string.IsNullOrWhiteSpace(enrolResponse.DeviceAssignedUserSID)) + if (!string.IsNullOrWhiteSpace(enrolResponse.AssignedUserSID)) { - Presentation.UpdateStatus("Enrolling Device", string.Format(@"Configuring the device owner:{0}{1} ({2}\{3})", Environment.NewLine, enrolResponse.DeviceAssignedUserName, enrolResponse.DeviceAssignedUserDomain, enrolResponse.DeviceAssignedUserUsername), true, -1, 3000); + Presentation.UpdateStatus("Enrolling Device", $"Configuring the device owner:\r\n{enrolResponse.AssignedUserDescription} ({enrolResponse.AssignedUserDomain}\\{enrolResponse.AssignedUserUsername})", true, -1, 3000); - if (enrolResponse.DeviceAssignedUserIsLocalAdmin) - Interop.LocalAuthentication.AddLocalGroupMembership("Administrators", enrolResponse.DeviceAssignedUserSID, enrolResponse.DeviceAssignedUserUsername, enrolResponse.DeviceAssignedUserDomain); + if (enrolResponse.AssignedUserIsLocalAdmin) + Interop.LocalAuthentication.AddLocalGroupMembership("Administrators", enrolResponse.AssignedUserSID, enrolResponse.AssignedUserUsername, enrolResponse.AssignedUserDomain); // Make Windows think this user was the last to logon using (RegistryKey regWinlogon = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true)) { - regWinlogon.SetValue("DefaultDomainName", enrolResponse.DeviceAssignedUserDomain, RegistryValueKind.String); - regWinlogon.SetValue("DefaultUserName", enrolResponse.DeviceAssignedUserUsername, RegistryValueKind.String); + regWinlogon.SetValue("DefaultDomainName", enrolResponse.AssignedUserDomain, RegistryValueKind.String); + regWinlogon.SetValue("DefaultUserName", enrolResponse.AssignedUserUsername, RegistryValueKind.String); } using (RegistryKey regLogonUI = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI", true)) { - regLogonUI.SetValue("LastLoggedOnUser", string.Format(@"{0}\{1}", enrolResponse.DeviceAssignedUserDomain, enrolResponse.DeviceAssignedUserUsername), RegistryValueKind.String); + regLogonUI.SetValue("LastLoggedOnUser", $@"{enrolResponse.AssignedUserDomain}\{enrolResponse.AssignedUserUsername}", RegistryValueKind.String); } } } - /// - /// Processes a Client Service Enrol Response for Device Certificate Actions - /// - /// private static void ApplyDeviceCertificates(this EnrolResponse enrolResponse) { - // Only run if a Certificate was supplied - if (!string.IsNullOrEmpty(enrolResponse.DeviceCertificate)) + if (enrolResponse.Certificates != null) { - Presentation.UpdateStatus("Enrolling Device", "Configuring Wireless Certificates", true, -1, 1000); + Presentation.UpdateStatus("Enrolling Device", "Configuring Certificates", true, -1, 1000); - var certPersonalBytes = Convert.FromBase64String(enrolResponse.DeviceCertificate); - var certPersonal = new X509Certificate2(certPersonalBytes, "password", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet); - if (certPersonal == null) - throw new ClientServiceException("Enrolment > Device Certificate", "Unable to Import Device Certificate Provided, possibly check password."); - - // Certificate Removal - if (enrolResponse.DeviceCertificateRemoveExisting != null && enrolResponse.DeviceCertificateRemoveExisting.Count > 0) - { - List regExMatchesSubject = new List(); - foreach (var subjectRegEx in enrolResponse.DeviceCertificateRemoveExisting) - regExMatchesSubject.Add(new Regex(subjectRegEx, RegexOptions.IgnoreCase)); - - // Remove from 'My' Store - Interop.Certificates.RemoveCertificates(StoreName.My, StoreLocation.LocalMachine, regExMatchesSubject, certPersonal); - // Remove from 'Root' Store - Interop.Certificates.RemoveCertificates(StoreName.Root, StoreLocation.LocalMachine, regExMatchesSubject, certPersonal); - // Remove from 'CertificateAuthority' Store - Interop.Certificates.RemoveCertificates(StoreName.CertificateAuthority, StoreLocation.LocalMachine, regExMatchesSubject, certPersonal); - } - - // Add Certificate - Presentation.UpdateStatus("Enrolling Device", string.Format("Configuring Wireless Certificates{0}Installing Certificate: {1}", Environment.NewLine, Interop.Certificates.GetCertificateFriendlyName(certPersonal)), true, -1); - Interop.Certificates.AddCertificate(StoreName.My, StoreLocation.LocalMachine, certPersonal); + enrolResponse.Certificates.Apply(); } } + private static void ApplyWirelessProfiles(this EnrolResponse enrolResponse) + { + if (enrolResponse.WirelessProfiles != null) + { + Presentation.UpdateStatus("Enrolling Device", "Configuring Wireless Profiles", true, -1, 1000); + + enrolResponse.WirelessProfiles.Apply(); + } + } } } diff --git a/Disco.Client/Interop/Certificates.cs b/Disco.Client/Interop/Certificates.cs index e42f0142..1e481d61 100644 --- a/Disco.Client/Interop/Certificates.cs +++ b/Disco.Client/Interop/Certificates.cs @@ -1,103 +1,130 @@ -using System; +using Disco.Models.ClientServices.EnrolmentInformation; +using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography.X509Certificates; -using System.Text; -using System.Text.RegularExpressions; namespace Disco.Client.Interop { public static class Certificates { - - public static string GetCertificateFriendlyName(X509Certificate2 Certificate) + public static List GetAllCertificates() { - string subject = Certificate.Subject; - return subject.Substring(subject.IndexOf("=") + 1, subject.IndexOf(",") - subject.IndexOf("=") - 1); + var certificates = new List(); + + // Trusted Root Certificates + certificates.AddRange(GetCertificates(StoreName.Root, "TrustedRoot")); + + // Intermediate Certificates + certificates.AddRange(GetCertificates(StoreName.CertificateAuthority, "Intermediate")); + + // Personal Certificates + certificates.AddRange(GetCertificates(StoreName.My, "Personal")); + + return certificates; } - public static List GetCertificateSubjects(StoreName StoreName, StoreLocation StoreLocation) + private static IEnumerable GetCertificates(StoreName StoreName, string StoreDescription) { - X509Store certStore = new X509Store(StoreName, StoreLocation); - certStore.Open(OpenFlags.ReadOnly); - var certSubjects = certStore.Certificates.Cast().Select(c => c.Subject).ToList(); - certStore.Close(); - return certSubjects; - } - - public static bool AddCertificate(StoreName StoreName, StoreLocation StoreLocation, X509Certificate2 Certificate) - { - X509Store certStore = new X509Store(StoreName, StoreLocation); - bool certAlreadyAdded = false; - - certStore.Open(OpenFlags.ReadWrite); - + var store = new X509Store(StoreName, StoreLocation.LocalMachine); + store.Open(OpenFlags.ReadOnly); try { - foreach (X509Certificate2 cert in certStore.Certificates) + foreach (var certificate in store.Certificates) { - if (cert.SerialNumber.Equals(Certificate.SerialNumber)) + yield return new Certificate() { - certAlreadyAdded = true; - break; - } - } - - if (!certAlreadyAdded) - { - Presentation.UpdateStatus("Enrolling Device", string.Format("Configuring Wireless Certificates{0}Adding Certificate: '{1}' from {2}@{3}", Environment.NewLine, GetCertificateFriendlyName(Certificate), StoreName.ToString(), StoreLocation.ToString()), true, -1, 3000); - certStore.Add(Certificate); + Store = StoreDescription, + SubjectName = certificate.SubjectName.Name, + Thumbprint = certificate.Thumbprint, + FriendlyName = certificate.FriendlyName, + DnsName = certificate.GetNameInfo(X509NameType.DnsName, false), + Version = certificate.Version, + SignatureAlgorithm = certificate.SignatureAlgorithm.FriendlyName, + Issuer = certificate.IssuerName.Name, + NotAfter = certificate.NotAfter, + NotBefore = certificate.NotBefore, + HasPrivateKey = certificate.HasPrivateKey + }; } } - catch (Exception) { throw; } finally { - certStore.Close(); + store.Close(); } - return !certAlreadyAdded; } - public static List RemoveCertificates(StoreName StoreName, StoreLocation StoreLocation, List RegExMatchesSubject, X509Certificate2 CertificateException) + public static void Apply(this CertificateStore EnrolStore) { - X509Store certStore = new X509Store(StoreName, StoreLocation); - List results = new List(); - List certStoreRemove = new List(); - - certStore.Open(OpenFlags.ReadWrite); - - try + if (EnrolStore != null) { - foreach (X509Certificate2 cert in certStore.Certificates) + // Apply Trusted Root + ApplyToStore(StoreName.Root, EnrolStore.TrustedRootCertificates, EnrolStore.TrustedRootRemoveThumbprints); + + // Apply Intermediate + ApplyToStore(StoreName.CertificateAuthority, EnrolStore.IntermediateCertificates, EnrolStore.IntermediateRemoveThumbprints); + + // Apply Personal + ApplyToStore(StoreName.My, EnrolStore.PersonalCertificates, EnrolStore.PersonalRemoveThumbprints); + } + } + + private static void ApplyToStore(StoreName StoreName, List Certificates, List RemoveThumbprints) + { + + if ((Certificates != null && Certificates.Count > 0) || + (RemoveThumbprints != null && RemoveThumbprints.Count > 0)) + { + var store = new X509Store(StoreName, StoreLocation.LocalMachine); + store.Open(OpenFlags.ReadWrite); + try { - if (!cert.SerialNumber.Equals(CertificateException.SerialNumber)) + var addedThumbprints = new List(); + var existingThumbprints = store.Certificates.Cast().GroupBy(c => c.Thumbprint).ToDictionary(c => c.Key, c => c.ToList(), StringComparer.OrdinalIgnoreCase); + + // Add + if (Certificates != null && Certificates.Count > 0) { - foreach (var subjectRegEx in RegExMatchesSubject) + foreach (var certificateBytes in Certificates) { - if (subjectRegEx.IsMatch(cert.Subject)) + var certificate = new X509Certificate2(certificateBytes, "password", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet); + + // check if it already exists + if (!existingThumbprints.ContainsKey(certificate.Thumbprint) && !addedThumbprints.Contains(certificate.Thumbprint)) { - certStoreRemove.Add(cert); - break; + Presentation.UpdateStatus("Enrolling Device", $"Configuring Certificates\r\nAdding Certificate: '{certificate.GetNameInfo(X509NameType.DnsName, false)}' from {store.Name}@{store.Location}", true, -1, 1000); + store.Add(certificate); + addedThumbprints.Add(certificate.Thumbprint); + } + } + } + + // Remove + if (RemoveThumbprints != null && RemoveThumbprints.Count > 0) + { + foreach (var thumbprint in RemoveThumbprints) + { + List certificates; + if (existingThumbprints.TryGetValue(thumbprint, out certificates) && !addedThumbprints.Contains(thumbprint)) + { + foreach (var certificate in certificates) + { + Presentation.UpdateStatus("Enrolling Device", $"Configuring Certificates\r\nRemoving Certificate: '{certificate.GetNameInfo(X509NameType.DnsName, false)}' from {store.Name}@{store.Location}", true, -1, 1000); + store.Remove(certificate); + existingThumbprints.Remove(thumbprint); + } } } } } - - foreach (var cert in certStoreRemove) + finally { - results.Add(cert.Subject); - - Presentation.UpdateStatus("Enrolling Device", string.Format("Configuring Wireless Certificates{0}Removing Certificate: '{1}' from {2}@{3}", Environment.NewLine, GetCertificateFriendlyName(cert), StoreName.ToString(), StoreLocation.ToString()), true, -1, 1500); - certStore.Remove(cert); + store.Close(); } } - catch (Exception) { throw; } - finally - { - certStore.Close(); - } - return results; } + } } diff --git a/Disco.Client/Interop/Hardware.cs b/Disco.Client/Interop/Hardware.cs new file mode 100644 index 00000000..133700a8 --- /dev/null +++ b/Disco.Client/Interop/Hardware.cs @@ -0,0 +1,277 @@ +using Disco.Models.ClientServices; +using Disco.Models.ClientServices.EnrolmentInformation; +using System; +using System.Linq; +using System.Management; + +namespace Disco.Client.Interop +{ + public static class Hardware + { + private static DeviceHardware information; + + public static DeviceHardware Information + { + get + { + if (information == null) + { + information = GatherInformation(); + } + return information; + } + } + + private static DeviceHardware GatherInformation() + { + var audit = new DeviceHardware(); + + audit.ApplyBIOSInformation(); + audit.ApplySystemInformation(); + audit.ApplyBaseBoardInformation(); + audit.ApplySystemProductInformation(); + + if (string.IsNullOrWhiteSpace(audit.SerialNumber)) + { + throw new Exception("This device has no serial number stored in BIOS or BaseBoard"); + } + if (audit.SerialNumber.Length > 60) + { + throw new Exception($"The serial number reported by this device is over 60 characters long:\r\n{audit.SerialNumber}"); + } + +#warning TODO: Processors, PhysicalMemory, DiskDrives, etc + + audit.NetworkAdapters = Network.GetNetworkAdapters(); + + return audit; + } + + private static void ApplyBIOSInformation(this DeviceHardware DeviceHardware) + { + try + { + using (var mSearcher = new ManagementObjectSearcher("SELECT SerialNumber, SMBIOSBIOSVersion FROM Win32_BIOS WHERE PrimaryBios=true")) + { + using (var mResults = mSearcher.Get()) + { + using (var mItem = mResults.Cast().FirstOrDefault()) + { + if (mItem != null) + { + var serialNumber = (string)mItem.GetPropertyValue("SerialNumber"); + if (!string.IsNullOrWhiteSpace(serialNumber)) + { + DeviceHardware.SerialNumber = serialNumber.Trim(); + } + + ErrorReporting.DeviceIdentifier = DeviceHardware.SerialNumber; + } + else + { + throw new Exception("No Win32_BIOS WHERE PrimaryBios=true was found"); + } + } + } + } + } + catch (Exception ex) + { + throw new Exception("Disco Client was unable to retrieve BIOS information from WMI", ex); + } + } + + private static void ApplySystemInformation(this DeviceHardware DeviceHardware) + { + try + { + using (var mSearcher = new ManagementObjectSearcher("SELECT Manufacturer, Model, PartOfDomain, PCSystemType, Domain FROM Win32_ComputerSystem")) + { + using (var mResults = mSearcher.Get()) + { + using (var mItem = mResults.Cast().FirstOrDefault()) + { + if (mItem != null) + { + var manufacturer = (string)mItem.GetPropertyValue("Manufacturer"); + if (!string.IsNullOrWhiteSpace(manufacturer)) + { + DeviceHardware.Manufacturer = manufacturer.Trim(); + } + + var model = (string)mItem.GetPropertyValue("Model"); + if (!string.IsNullOrWhiteSpace(model)) + { + DeviceHardware.Model = model.ToString(); + } + + DeviceHardware.ModelType = ((PCSystemTypes)mItem.GetPropertyValue("PCSystemType")).Description(); + } + else + { + throw new Exception("No Win32_ComputerSystem was found"); + } + } + } + } + } + catch (Exception ex) + { + throw new Exception("Disco Client was unable to retrieve ComputerSystem information from WMI", ex); + } + } + + public static void ApplySystemInformation(this Enrol Enrol) + { + try + { + using (var mSearcher = new ManagementObjectSearcher("SELECT PartOfDomain, Domain FROM Win32_ComputerSystem")) + { + using (var mResults = mSearcher.Get()) + { + using (var mItem = mResults.Cast().FirstOrDefault()) + { + if (mItem != null) + { + Enrol.IsPartOfDomain = (bool)mItem.GetPropertyValue("PartOfDomain"); + + if (Enrol.IsPartOfDomain) + { + Enrol.DNSDomainName = (string)mItem.GetPropertyValue("Domain"); + } + } + else + { + throw new Exception("No Win32_ComputerSystem was found"); + } + } + } + } + } + catch (Exception ex) + { + throw new Exception("Disco Client was unable to retrieve ComputerSystem information from WMI", ex); + } + } + + private static void ApplyBaseBoardInformation(this DeviceHardware DeviceHardware) + { + // Added 2012-11-22 G# - Lenovo IdeaPad Serial SHIM + // http://www.discoict.com.au/forum/feature-requests/2012/11/serial-number-detection-on-ideapads.aspx + if (string.IsNullOrWhiteSpace(DeviceHardware.SerialNumber) || + (DeviceHardware.Manufacturer.Equals("LENOVO", StringComparison.OrdinalIgnoreCase) && + (DeviceHardware.Model.Equals("S10-3", StringComparison.OrdinalIgnoreCase) // S10-3 + || DeviceHardware.Model.Equals("2957", StringComparison.OrdinalIgnoreCase)))) // S10-2 + { + try + { + using (var mSearcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BaseBoard")) + { + using (var mResults = mSearcher.Get()) + { + using (var mItem = mResults.Cast().FirstOrDefault()) + { + if (mItem != null) + { + var serialNumber = (string)mItem.GetPropertyValue("SerialNumber"); + if (!string.IsNullOrWhiteSpace(serialNumber)) + { + DeviceHardware.SerialNumber = serialNumber.Trim(); + ErrorReporting.DeviceIdentifier = DeviceHardware.SerialNumber; + } + } + else + { + throw new Exception("No Win32_BaseBoard was found"); + } + } + } + } + } + catch (Exception ex) + { + throw new Exception("Disco Client was unable to retrieve BaseBoard information from WMI", ex); + } + } + } + + private static void ApplySystemProductInformation(this DeviceHardware DeviceHardware) + { + try + { + using (var mSearcher = new ManagementObjectSearcher("SELECT IdentifyingNumber, UUID FROM Win32_ComputerSystemProduct")) + { + using (var mResults = mSearcher.Get()) + { + using (var mItem = mResults.Cast().FirstOrDefault()) + { + if (mItem != null) + { + if (DeviceHardware.SerialNumber == null) + { + var serialNumber = mItem.GetPropertyValue("IdentifyingNumber") as string; + if (!string.IsNullOrWhiteSpace(serialNumber)) + { + DeviceHardware.SerialNumber = serialNumber.Trim(); + ErrorReporting.DeviceIdentifier = DeviceHardware.SerialNumber; + } + } + + var uUID = (string)mItem.GetPropertyValue("UUID"); + if (!string.IsNullOrWhiteSpace(uUID)) + DeviceHardware.UUID = uUID.Trim(); + } + else + { + throw new Exception("No Win32_ComputerSystemProduct was found"); + } + } + } + } + } + catch (Exception ex) + { + throw new Exception("Disco Client was unable to retrieve ComputerSystemProduct information from WMI", ex); + } + } + + private static string Description(this PCSystemTypes type) + { + switch (type) + { + case PCSystemTypes.Desktop: + return "Desktop"; + case PCSystemTypes.Mobile: + return "Mobile"; + case PCSystemTypes.Workstation: + return "Workstation"; + case PCSystemTypes.EnterpriseServer: + return "Enterprise Server"; + case PCSystemTypes.SmallOfficeAndHomeOfficeServer: + return "Small Office And Home Office Server"; + case PCSystemTypes.AppliancePC: + return "Appliance PC"; + case PCSystemTypes.PerformanceServer: + return "Performance Server"; + case PCSystemTypes.Maximum: + return "Maximum"; + case PCSystemTypes.Unknown: + default: + return "Unknown"; + } + } + + private enum PCSystemTypes : ushort + { + Unknown = 0, + Desktop, + Mobile, + Workstation, + EnterpriseServer, + SmallOfficeAndHomeOfficeServer, + AppliancePC, + PerformanceServer, + Maximum + } + } +} diff --git a/Disco.Client/Interop/LocalAuthentication.cs b/Disco.Client/Interop/LocalAuthentication.cs index 361d9402..6dd7ccd0 100644 --- a/Disco.Client/Interop/LocalAuthentication.cs +++ b/Disco.Client/Interop/LocalAuthentication.cs @@ -1,10 +1,6 @@ using System; using System.Collections; -using System.Collections.Generic; using System.DirectoryServices; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Disco.Client.Interop { @@ -14,7 +10,7 @@ namespace Disco.Client.Interop public static bool AddLocalGroupMembership(string GroupName, string UserSID, string Username, string UserDomain) { - using (DirectoryEntry group = new DirectoryEntry(string.Format("WinNT://./{0},group", GroupName))) + using (DirectoryEntry group = new DirectoryEntry($"WinNT://./{GroupName},group")) { // Check to see if the User is already a member foreach (object memberRef in (IEnumerable)group.Invoke("Members")) @@ -22,38 +18,15 @@ namespace Disco.Client.Interop using (DirectoryEntry member = new DirectoryEntry(memberRef)) { var memberPath = member.Path; - if (memberPath.Equals(string.Format("WinNT://{0}/{1}", UserDomain, Username), StringComparison.OrdinalIgnoreCase) || - memberPath.Equals(string.Format("WinNT://{0}", UserSID), StringComparison.OrdinalIgnoreCase)) + if (memberPath.Equals($"WinNT://{UserDomain}/{Username}", StringComparison.OrdinalIgnoreCase) || + memberPath.Equals($"WinNT://{UserSID}", StringComparison.OrdinalIgnoreCase)) return false; } } - group.Invoke("Add", string.Format("WinNT://{0}", UserSID)); + group.Invoke("Add", $"WinNT://{UserSID}"); } return true; } - public static string CurrentUserDomain - { - get - { - return Environment.UserDomainName; - } - } - public static string CurrentUserName - { - get - { - return Environment.UserName; - } - } - - public static string ComputerName - { - get - { - return Environment.MachineName; - } - } - } } diff --git a/Disco.Client/Interop/Native/NetworkConnectionStatuses.cs b/Disco.Client/Interop/Native/NetworkConnectionStatuses.cs new file mode 100644 index 00000000..e07bda77 --- /dev/null +++ b/Disco.Client/Interop/Native/NetworkConnectionStatuses.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Disco.Client.Interop.Native +{ + public enum NetworkConnectionStatuses : ushort + { + Disconnected = 0, + Connecting, + Connected, + Disconnecting, + HardwareNotPresent, + HardwareDisabled, + HardwareMalfunction, + MediaDisconnected, + Authenticating, + AuthenticationSucceeded, + AuthenticationFailed, + InvalidAddress, + CredentialsRequired + } +} diff --git a/Disco.Client/Interop/Native/ProfileInfoFlags.cs b/Disco.Client/Interop/Native/ProfileInfoFlags.cs new file mode 100644 index 00000000..ca2a40a4 --- /dev/null +++ b/Disco.Client/Interop/Native/ProfileInfoFlags.cs @@ -0,0 +1,11 @@ +using System; + +namespace Disco.Client.Interop.Native +{ + [Flags] + public enum ProfileInfoFlags : uint + { + WLAN_PROFILE_GROUP_POLICY = 1, + WLAN_PROFILE_USER = 2 + } +} diff --git a/Disco.Client/Interop/Native/WLAN_INTERFACE_INFO.cs b/Disco.Client/Interop/Native/WLAN_INTERFACE_INFO.cs new file mode 100644 index 00000000..d179a674 --- /dev/null +++ b/Disco.Client/Interop/Native/WLAN_INTERFACE_INFO.cs @@ -0,0 +1,30 @@ +using System; +using System.Runtime.InteropServices; + +namespace Disco.Client.Interop.Native +{ + /// + /// The WLAN_INTERFACE_INFO structure contains information about a wireless LAN interface. + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct WLAN_INTERFACE_INFO + { + /// + /// Contains the GUID of the interface. + /// + public Guid InterfaceGuid; + + /// + /// Contains the description of the interface. + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string strInterfaceDescription; + + /// + /// Contains a WLAN_INTERFACE_STATE value that indicates the current state of the interface. + /// Windows XP with SP3 and Wireless LAN API for Windows XP with SP2:  Only the wlan_interface_state_connected, + /// wlan_interface_state_disconnected, and wlan_interface_state_authenticating values are supported. + /// + public WLAN_INTERFACE_STATE isState; + } +} diff --git a/Disco.Client/Interop/Native/WLAN_INTERFACE_INFO_LIST.cs b/Disco.Client/Interop/Native/WLAN_INTERFACE_INFO_LIST.cs new file mode 100644 index 00000000..2c90e7c3 --- /dev/null +++ b/Disco.Client/Interop/Native/WLAN_INTERFACE_INFO_LIST.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace Disco.Client.Interop.Native +{ + /// + /// The WLAN_INTERFACE_INFO_LIST structure contains an array of NIC interface information. + /// + [StructLayout(LayoutKind.Sequential)] + public struct WLAN_INTERFACE_INFO_LIST + { + /// + /// Contains the number of items in the InterfaceInfo member. + /// + public uint dwNumberOfItems; + /// + /// The index of the current item. The index of the first item is 0. dwIndex must be less than dwNumberOfItems. + /// This member is not used by the wireless service. Applications can use this member when processing individual + /// interfaces in the WLAN_INTERFACE_INFO_LIST structure. When an application passes this structure from one + /// function to another, it can set the value of dwIndex to the index of the item currently being processed. + /// This can help an application maintain state. + /// dwIndex should always be initialized before use. + /// + public uint dwIndex; + + private IntPtr InterfaceInfoPtr; + + /// + /// An array of WLAN_INTERFACE_INFO structures containing interface information. + /// + public IEnumerable InterfaceInfo + { + get + { + var size = Marshal.SizeOf(typeof(WLAN_INTERFACE_INFO)); + for (int i = 0; i < dwNumberOfItems; i++) + { + yield return (WLAN_INTERFACE_INFO)Marshal.PtrToStructure(InterfaceInfoPtr + (i * size), typeof(WLAN_INTERFACE_INFO)); + } + } + } + + public WLAN_INTERFACE_INFO_LIST(IntPtr Pointer) + { + dwNumberOfItems = (uint)Marshal.ReadInt32(Pointer, 0); + dwIndex = (uint)Marshal.ReadInt32(Pointer, 4); + InterfaceInfoPtr = Pointer + 8; + } + } +} diff --git a/Disco.Client/Interop/Native/WLAN_INTERFACE_STATE.cs b/Disco.Client/Interop/Native/WLAN_INTERFACE_STATE.cs new file mode 100644 index 00000000..c7408cbb --- /dev/null +++ b/Disco.Client/Interop/Native/WLAN_INTERFACE_STATE.cs @@ -0,0 +1,43 @@ +namespace Disco.Client.Interop.Native +{ + /// + /// The WLAN_INTERFACE_STATE enumerated type indicates the state of an interface. + /// Windows XP with SP3 and Wireless LAN API for Windows XP with SP2:  Only the wlan_interface_state_connected, + /// wlan_interface_state_disconnected, and wlan_interface_state_authenticating values are supported. + /// + public enum WLAN_INTERFACE_STATE + { + /// + /// The interface is not ready to operate. + /// + wlan_interface_state_not_ready = 0, + /// + /// The interface is connected to a network. + /// + wlan_interface_state_connected = 1, + /// + /// The interface is the first node in an ad hoc network. No peer has connected. + /// + wlan_interface_state_ad_hoc_network_formed = 2, + /// + /// The interface is disconnecting from the current network. + /// + wlan_interface_state_disconnecting = 3, + /// + /// The interface is not connected to any network. + /// + wlan_interface_state_disconnected = 4, + /// + /// The interface is attempting to associate with a network. + /// + wlan_interface_state_associating = 5, + /// + /// Auto configuration is discovering the settings for the network. + /// + wlan_interface_state_discovering = 6, + /// + /// The interface is in the process of authenticating. + /// + wlan_interface_state_authenticating = 7, + } +} diff --git a/Disco.Client/Interop/Native/WLAN_PROFILE_INFO.cs b/Disco.Client/Interop/Native/WLAN_PROFILE_INFO.cs new file mode 100644 index 00000000..8c5505d2 --- /dev/null +++ b/Disco.Client/Interop/Native/WLAN_PROFILE_INFO.cs @@ -0,0 +1,24 @@ +using System.Runtime.InteropServices; + +namespace Disco.Client.Interop.Native +{ + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct WLAN_PROFILE_INFO + { + /// + /// The name of the profile. This value may be the name of a domain if the profile is for provisioning. Profile names are case-sensitive. + /// This string must be NULL-terminated. + /// Windows XP with SP3 and Wireless LAN API for Windows XP with SP2:  The name of the profile is derived automatically from + /// the SSID of the wireless network. For infrastructure network profiles, the name of the profile is the SSID of the network. + /// For ad hoc network profiles, the name of the profile is the SSID of the ad hoc network followed by -adhoc. + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string strInterfaceDescription; + + /// + /// A set of flags specifying settings for wireless profile. These values are defined in the Wlanapi.h header file. + /// Windows XP with SP3 and Wireless LAN API for Windows XP with SP2:  dwFlags must be 0. Per-user profiles are not supported. + /// + public ProfileInfoFlags dwFlags; + } +} diff --git a/Disco.Client/Interop/Native/WLAN_PROFILE_INFO_LIST.cs b/Disco.Client/Interop/Native/WLAN_PROFILE_INFO_LIST.cs new file mode 100644 index 00000000..f843de70 --- /dev/null +++ b/Disco.Client/Interop/Native/WLAN_PROFILE_INFO_LIST.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace Disco.Client.Interop.Native +{ + public struct WLAN_PROFILE_INFO_LIST + { + /// + /// The number of wireless profile entries in the ProfileInfo member. + /// + public uint dwNumberOfItems; + + /// + /// The index of the current item. The index of the first item is 0. The dwIndex member must be less than the dwNumberOfItems member. + /// This member is not used by the wireless service. Applications can use this member when processing individual profiles in the + /// WLAN_PROFILE_INFO_LIST structure. When an application passes this structure from one function to another, it can set the value + /// of dwIndex to the index of the item currently being processed. This can help an application maintain state. + /// dwIndex should always be initialized before use. + /// + public uint dwIndex; + + private IntPtr ProfileInfoPointer; + + /// + /// An array of WLAN_PROFILE_INFO structures containing interface information. The number of items in the array is specified in the dwNumberOfItems member. + /// + public IEnumerable ProfileInfo + { + get + { + var size = Marshal.SizeOf(typeof(WLAN_PROFILE_INFO)); + for (int i = 0; i < dwNumberOfItems; i++) + { + yield return (WLAN_PROFILE_INFO)Marshal.PtrToStructure(ProfileInfoPointer + (i * size), typeof(WLAN_PROFILE_INFO)); + } + } + } + + public WLAN_PROFILE_INFO_LIST(IntPtr Pointer) + { + dwNumberOfItems = (uint)Marshal.ReadInt32(Pointer, 0); + dwIndex = (uint)Marshal.ReadInt32(Pointer, 4); + ProfileInfoPointer = Pointer + 8; + } + } +} diff --git a/Disco.Client/Interop/Native/WlanApi.cs b/Disco.Client/Interop/Native/WlanApi.cs new file mode 100644 index 00000000..ad726bd1 --- /dev/null +++ b/Disco.Client/Interop/Native/WlanApi.cs @@ -0,0 +1,207 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace Disco.Client.Interop.Native +{ + public static class WlanApi + { + + public const uint WLAN_API_VERSION_2_0 = 2; // Windows Vista WiFi API Version + public const int ERROR_SUCCESS = 0; + public const int ERROR_INVALID_PARAMETER = 87; + public const int ERROR_NOT_ENOUGH_MEMORY = 8; + + /// + /// The WlanOpenHandle function opens a connection to the server. + /// + /// The highest version of the WLAN API that the client supports. + /// 1 = Client version for Windows XP with SP3 and Wireless LAN API for Windows XP with SP2. + /// 2 = Client version for Windows Vista and Windows Server 2008 + /// Reserved for future use. Must be set to NULL. + /// The version of the WLAN API that will be used in this session. This value is usually the highest version supported by both the client and server. + /// A handle for the client to use in this session. This handle is used by other functions throughout the session. + /// + /// If the function succeeds, the return value is ERROR_SUCCESS. + /// If the function fails, the return value may be one of the following return codes. + /// ERROR_INVALID_PARAMETER: pdwNegotiatedVersion is NULL, phClientHandle is NULL, or pReserved is not NULL. + /// ERROR_NOT_ENOUGH_MEMORY: Failed to allocate memory to create the client context. + /// RPC_STATUS: Various error codes. + /// ERROR_REMOTE_SESSION_LIMIT_EXCEEDED: Too many handles have been issued by the server. + /// + /// + /// The version number specified by dwClientVersion and pdwNegotiatedVersion is a composite version number + /// made up of both major and minor versions. The major version is specified by the low-order word, and the + /// minor version is specified by the high-order word. The macros WLAN_API_VERSION_MAJOR(_v) and + /// WLAN_API_VERSION_MINOR(_v) return the major and minor version numbers respectively. + /// You can construct a version number using the macro WLAN_API_MAKE_VERSION(_major, _minor). + /// Windows XP with SP3 and Wireless LAN API for Windows XP with SP2:  WlanOpenHandle will return an + /// error message if the Wireless Zero Configuration (WZC) service has not been started or if the WZC service is not responsive. + /// + [DllImport("Wlanapi.dll")] + public static extern uint WlanOpenHandle(uint dwClientVersion, IntPtr pReserved, out uint pdwNegotiatedVersion, out IntPtr phClientHandle); + + /// + /// The WlanCloseHandle function closes a connection to the server. + /// + /// The client's session handle, which identifies the connection to be closed. This handle was obtained by a previous call to the WlanOpenHandle function. + /// Reserved for future use. Set this parameter to NULL. + /// + /// If the function succeeds, the return value is ERROR_SUCCESS. + /// If the function fails, the return value may be one of the following return codes. + /// ERROR_INVALID_PARAMETER: hClientHandle is NULL or invalid, or pReserved is not NULL. + /// ERROR_INVALID_HANDLE: The handle hClientHandle was not found in the handle table. + /// RPC_STATUS: Various error codes. + /// + /// + /// After a connection has been closed, any attempted use of the closed handle can cause unexpected errors. + /// Upon closing, all outstanding notifications are discarded. + /// Do not call WlanCloseHandle from a callback function. If the client is in the middle of a + /// notification callback when WlanCloseHandle is called, the function waits for the callback to + /// finish before returning a value. Calling this function inside a callback function will result in + /// the call never completing. If both the callback function and the thread that closes the handle try + /// to acquire the same lock, a deadlock may occur. In addition, do not call WlanCloseHandle from + /// the DllMain function in an application DLL. This could also cause a deadlock. + /// + [DllImport("Wlanapi")] + public static extern uint WlanCloseHandle(IntPtr hClientHandle, IntPtr pReserved); + + /// + /// The WlanEnumInterfaces function enumerates all of the wireless LAN interfaces currently enabled on the local computer. + /// + /// The client's session handle, obtained by a previous call to the WlanOpenHandle function. + /// Reserved for future use. This parameter must be set to NULL. + /// + /// A pointer to storage for a pointer to receive the returned list of wireless LAN interfaces in a WLAN_INTERFACE_INFO_LIST structure. + /// The buffer for the WLAN_INTERFACE_INFO_LIST returned is allocated by the WlanEnumInterfaces function if the call succeeds. + /// + /// + /// If the function succeeds, the return value is ERROR_SUCCESS. + /// If the function fails, the return value may be one of the following return codes. + /// ERROR_INVALID_PARAMETER: A parameter is incorrect. This error is returned if the hClientHandle or ppInterfaceList parameter is NULL. This error is returned if the pReserved is not NULL. + /// This error is also returned if the hClientHandle parameter is not valid. + /// ERROR_INVALID_HANDLE: The handle hClientHandle was not found in the handle table. + /// RPC_STATUS: Various error codes. + /// ERROR_NOT_ENOUGH_MEMORY: Not enough memory is available to process this request and allocate memory for the query results. + /// + /// + /// The WlanEnumInterfaces function allocates memory for the list of returned interfaces that is returned in the + /// buffer pointed to by the ppInterfaceList parameter when the function succeeds. The memory used for the buffer + /// pointed to by ppInterfaceList parameter should be released by calling the WlanFreeMemory function + /// after the buffer is no longer needed. + /// + [DllImport("Wlanapi")] + public static extern uint WlanEnumInterfaces(IntPtr hClientHandle, IntPtr pReserved, out IntPtr ppInterfaceList); + + /// + /// The WlanGetProfileList function retrieves the list of profiles in preference order. + /// + /// The client's session handle, obtained by a previous call to the WlanOpenHandle function. + /// The GUID of the wireless interface. + /// Reserved for future use. Must be set to NULL. + /// A PWLAN_PROFILE_INFO_LIST structure that contains the list of profile information. + /// + /// If the function succeeds, the return value is ERROR_SUCCESS. + /// If the function fails, the return value may be one of the following return codes. + /// ERROR_INVALID_HANDLE: The handle hClientHandle was not found in the handle table. + /// ERROR_INVALID_PARAMETER: A parameter is incorrect. + /// ERROR_NOT_ENOUGH_MEMORY: Not enough memory is available to process this request and allocate memory for the query results. + /// RPC_STATUS: Various error codes. + /// + /// + /// The WlanGetProfileList function returns only the basic information on the wireless profiles on a wireless interface. + /// The list of wireless profiles on a wireless interface are retrieved in the preference order. The WlanSetProfilePosition + /// can be used to change the preference order for the wireless profiles on a wireless interface. + /// More detailed information for a wireless profile on a wireless interface can be retrieved by using the WlanGetProfile + /// function. The WlanGetProfileCustomUserData function can be used to retrieve custom user data for a wireless profile on + /// a wireless interface. A list of the wireless interfaces and associated GUIDs on the local computer can be retrieved + /// using the WlanEnumInterfaces function. + /// The WlanGetProfileList function allocates memory for the list of profiles returned in the buffer pointed to by the + /// ppProfileList parameter. The caller is responsible for freeing this memory using the WlanFreeMemory function when + /// this buffer is no longer needed. + /// Windows XP with SP3 and Wireless LAN API for Windows XP with SP2:  Guest profiles, profiles with Wireless Provisioning + /// Service (WPS) authentication, and profiles with Wi-Fi Protected Access-None (WPA-None) authentication are not + /// supported. These types of profiles are not returned by WlanGetProfileList, even if a profile of this type appears + /// on the preferred profile list. + /// + [DllImport("Wlanapi")] + public static extern uint WlanGetProfileList(IntPtr hClientHandle, Guid pInterfaceGuid, IntPtr pReserved, out IntPtr ppProfileList); + + /// + /// The WlanGetProfile function retrieves all information about a specified wireless profile. + /// + /// The client's session handle, obtained by a previous call to the WlanOpenHandle function. + /// The GUID of the wireless interface. + /// The name of the profile. Profile names are case-sensitive. This string must be NULL-terminated. The maximum length of the profile name is 255 characters. This means that the maximum length of this string, including the NULL terminator, is 256 characters. + /// Reserved for future use. Must be set to NULL. + /// A string that is the XML representation of the queried profile. There is no predefined maximum string length. + /// On input, a pointer to the address location used to provide additional information about the request. If this parameter is NULL on input, then no information on profile flags will be returned. On output, a pointer to the address location used to receive profile flags. + /// The access mask of the all-user profile. + /// If the function succeeds, the return value is ERROR_SUCCESS. + [DllImport("Wlanapi", CharSet = CharSet.Unicode)] + public static extern uint WlanGetProfile(IntPtr hClientHandle, Guid pInterfaceGuid, [MarshalAs(UnmanagedType.LPWStr)] string strProfileName, IntPtr pReserved, out IntPtr pstrProfileXml, out uint pdwFlags, out IntPtr pdwGrantedAccess); + + /// + /// The WlanSetProfile function sets the content of a specific profile. + /// + /// The client's session handle, obtained by a previous call to the WlanOpenHandle function. + /// The GUID of the interface. + /// The flags to set on the profile. + /// Contains the XML representation of the profile. The WLANProfile element is the root profile element. To view sample profiles, see Wireless Profile Samples. There is no predefined maximum string length. + /// Sets the security descriptor string on the all-user profile. For more information about profile permissions, see the Remarks section. + /// Specifies whether this profile is overwriting an existing profile. If this parameter is FALSE and the profile already exists, the existing profile will not be overwritten and an error will be returned. + /// Reserved for future use. Must be set to NULL. + /// A WLAN_REASON_CODE value that indicates why the profile is not valid. + /// If the function succeeds, the return value is ERROR_SUCCESS. + [DllImport("Wlanapi", CharSet = CharSet.Unicode)] + public static extern uint WlanSetProfile(IntPtr hClientHandle, Guid pInterfaceGuid, uint dwFlags, [MarshalAs(UnmanagedType.LPWStr)] string strProfileXml, [MarshalAs(UnmanagedType.LPWStr)] string strAllUserProfileSecurity, bool bOverwrite, IntPtr pReserved, out uint pdwReasonCode); + + /// + /// The WlanDeleteProfile function deletes a wireless profile for a wireless interface on the local computer. + /// + /// The client's session handle, obtained by a previous call to the WlanOpenHandle function. + /// The GUID of the interface from which to delete the profile. + /// The name of the profile to be deleted. Profile names are case-sensitive. This string must be NULL-terminated. + /// Reserved for future use. Must be set to NULL. + /// + /// If the function succeeds, the return value is ERROR_SUCCESS. + /// If the function fails, the return value may be one of the following return codes. + /// ERROR_INVALID_PARAMETER: The hClientHandle parameter is NULL or not valid, the pInterfaceGuid parameter is NULL, the strProfileName parameter is NULL, or pReserved is not NULL. + /// ERROR_INVALID_HANDLE: The handle specified in the hClientHandle parameter was not found in the handle table. + /// ERROR_NOT_FOUND: The wireless profile specified by strProfileName was not found in the profile store. + /// ERROR_ACCESS_DENIED: The caller does not have sufficient permissions to delete the profile. + /// RPC_STATUS: Various error codes. + /// + /// + /// The WlanDeleteProfile function deletes a wireless profile for a wireless interface on the local computer. + /// All wireless LAN functions require an interface GUID for the wireless interface when performing profile operations. + /// When a wireless interface is removed, its state is cleared from Wireless LAN Service (WLANSVC) and no profile operations are possible. + /// The WlanDeleteProfile function can fail with ERROR_INVALID_PARAMETER if the wireless interface specified in the pInterfaceGuid parameter + /// for the wireless LAN profile has been removed from the system (a USB wireless adapter that has been removed, for example). + /// + [DllImport("Wlanapi", CharSet = CharSet.Unicode)] + public static extern uint WlanDeleteProfile(IntPtr hClientHandle, Guid pInterfaceGuid, [MarshalAs(UnmanagedType.LPWStr)] string strProfileName, IntPtr pReserved); + + /// + /// The WlanReasonCodeToString function retrieves a string that describes a specified reason code. + /// + /// A WLAN_REASON_CODE value of which the string description is requested. + /// The size of the buffer used to store the string, in WCHAR. If the reason code string is longer than the buffer, it will be truncated and NULL-terminated. If dwBufferSize is larger than the actual amount of memory allocated to pStringBuffer, then an access violation will occur in the calling program. + /// Pointer to a buffer that will receive the string. The caller must allocate memory to pStringBuffer before calling WlanReasonCodeToString. + /// Reserved for future use. Must be set to NULL. + /// If the function succeeds, the return value is a pointer to a constant string. + [DllImport("Wlanapi", CharSet = CharSet.Unicode)] + public static extern uint WlanReasonCodeToString(uint dwReasonCode, uint dwBufferSize, ref StringBuilder pStringBuffer, IntPtr pReserved); + + /// + /// The WlanFreeMemory function frees memory. Any memory returned from Native Wifi functions must be freed. + /// + /// Pointer to the memory to be freed. + /// + /// If pMemory points to memory that has already been freed, an access violation or heap corruption may occur. + /// + [DllImport("Wlanapi")] + public static extern void WlanFreeMemory(IntPtr pMemory); + + } +} diff --git a/Disco.Client/Interop/Network.cs b/Disco.Client/Interop/Network.cs index 8c9c6a19..17804f5e 100644 --- a/Disco.Client/Interop/Network.cs +++ b/Disco.Client/Interop/Network.cs @@ -1,73 +1,68 @@ -using System; +using Disco.Client.Interop.Native; +using Disco.Models.ClientServices.EnrolmentInformation; +using System; using System.Collections.Generic; using System.Linq; using System.Management; -using System.Runtime.InteropServices; -using System.Text; namespace Disco.Client.Interop { public static class Network { - private static List NetworkAdapters { get; set; } - private static NetworkAdapterInfo PrimaryLanNetworkAdapter { get; set; } - private static NetworkAdapterInfo PrimaryWlanNetworkAdapter { get; set; } - - public static void Initialize() + public static List GetNetworkAdapters() { - // Get All Adapters - RetrieveLanAdapters(); + var adapters = GetWmiNetworkAdapters(); - if (NetworkAdapters.Count > 0) + if (adapters != null && adapters.Count > 0) { - // Only Retrieve Wlan Adapters if at least one adapter was found by WMI - try - { - RetrieveWlanAdapters(); - } - catch (DllNotFoundException) - { - // Ignore DllNotFoundException - // This which indicates 'Wlanapi.dll' isn't present (eg. Windows Servers) - } - - // Determine Primary Adapters - - // Lan - PrimaryLanNetworkAdapter = NetworkAdapters.Where(n => !n.IsWLanAdapter && n.NetConnectionId.StartsWith("Local Area Connection", StringComparison.OrdinalIgnoreCase)).OrderByDescending(n => n.Speed).FirstOrDefault(); - // Might be too restrictive - remove name restriction just in case. - if (PrimaryLanNetworkAdapter == null) - PrimaryLanNetworkAdapter = NetworkAdapters.Where(n => !n.IsWLanAdapter).OrderByDescending(n => n.Speed).FirstOrDefault(); - - // Wan - PrimaryWlanNetworkAdapter = NetworkAdapters.Where(n => n.IsWLanAdapter).OrderByDescending(n => n.Speed).FirstOrDefault(); + // Apply Wlan Information + adapters.ApplyWlanInformation(); } - } - private static void RetrieveLanAdapters() + return adapters; + } + + private static List GetWmiNetworkAdapters() { - // Get NetworkAdapter Information try { - using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT Index, GUID, MACAddress, Name, NetConnectionID, Speed FROM Win32_NetworkAdapter WHERE PhysicalAdapter=true AND MACAddress IS NOT NULL AND Name IS NOT NULL AND NetConnectionID IS NOT NULL AND Speed IS NOT NULL")) + // Load Physical Adapters + using (var wmiSearcher = new ManagementObjectSearcher("SELECT DeviceID, GUID, Manufacturer, ProductName, AdapterType, MACAddress, Speed, NetConnectionID, NetConnectionStatus, NetEnabled FROM Win32_NetworkAdapter WHERE PhysicalAdapter=true AND MACAddress IS NOT NULL AND NetConnectionID IS NOT NULL AND Speed IS NOT NULL")) { - using (ManagementObjectCollection mResults = mSearcher.Get()) + using (var wmiResults = wmiSearcher.Get()) { - NetworkAdapters = new List(); - foreach (var mResult in mResults.Cast()) - { - NetworkAdapterInfo nic = new NetworkAdapterInfo() + return wmiResults + .Cast() + .Select(wmiResult => { - Index = (UInt32)mResult.GetPropertyValue("Index"), - Guid = Guid.Parse((string)mResult.GetPropertyValue("GUID")), - MacAddress = mResult.GetPropertyValue("MACAddress").ToString(), - Name = mResult.GetPropertyValue("Name").ToString(), - NetConnectionId = mResult.GetPropertyValue("NetConnectionID").ToString(), - Speed = Convert.ToUInt64(mResult.GetPropertyValue("Speed")), - IsWLanAdapter = false - }; - NetworkAdapters.Add(nic); - } + var adapter = new NetworkAdapter() + { + DeviceID = (string)wmiResult.GetPropertyValue("DeviceID"), + ConnectionIdentifier = Guid.Parse((string)wmiResult.GetPropertyValue("GUID")), + Manufacturer = (string)wmiResult.GetPropertyValue("Manufacturer"), + ProductName = (string)wmiResult.GetPropertyValue("ProductName"), + AdapterType = (string)wmiResult.GetPropertyValue("AdapterType"), + MACAddress = (string)wmiResult.GetPropertyValue("MACAddress"), + Speed = (ulong)wmiResult.GetPropertyValue("Speed"), + NetConnectionID = (string)wmiResult.GetPropertyValue("NetConnectionID"), + NetConnectionStatus = ((NetworkConnectionStatuses)wmiResult.GetPropertyValue("NetConnectionStatus")).Description(), + NetEnabled = (bool)wmiResult.GetPropertyValue("NetEnabled") + }; + + using (var wmiRelatedResults = wmiResult.GetRelated("Win32_NetworkAdapterConfiguration", "Win32_NetworkAdapterSetting", null, null, null, null, false, null)) + { + var wmiConfiguration = wmiRelatedResults.Cast().First(); + + adapter.IPEnabled = (bool)wmiConfiguration.GetPropertyValue("IPEnabled"); + if (adapter.IPEnabled) + { + adapter.IPAddresses = ((string[])wmiConfiguration.GetPropertyValue("IPAddress")).ToList(); + } + } + + return adapter; + }) + .ToList(); } } } @@ -77,259 +72,40 @@ namespace Disco.Client.Interop } } - private static void RetrieveWlanAdapters() + public static string Description(this NetworkConnectionStatuses Status) { - WLAN_INTERFACE_INFO_LIST wlanApiInterfaceList; - - IntPtr wlanApiHandle = IntPtr.Zero; - uint wlanApiServiceVersion = 0; - - if (WlanOpenHandle(WLAN_API_VERSION_2_0, IntPtr.Zero, out wlanApiServiceVersion, ref wlanApiHandle) == ERROR_SUCCESS) + switch (Status) { - IntPtr wlanApiInterfaceListPointer = IntPtr.Zero; - - if (WlanEnumInterfaces(wlanApiHandle, IntPtr.Zero, ref wlanApiInterfaceListPointer) == ERROR_SUCCESS) - { - wlanApiInterfaceList = new WLAN_INTERFACE_INFO_LIST(wlanApiInterfaceListPointer); - WlanFreeMemory(wlanApiInterfaceListPointer); - } - else - { - // Error - No Wlan Adapters Reported - WlanCloseHandle(wlanApiHandle, IntPtr.Zero); - return; - } - - WlanCloseHandle(wlanApiHandle, IntPtr.Zero); - } - else - { - // Error - No Wlan Adapters Reported - return; - } - - if (wlanApiInterfaceList.InterfaceInfo != null) - { - foreach (var wlanApiAdapter in wlanApiInterfaceList.InterfaceInfo) - { - var wlanApiAdapterInfo = wlanApiAdapter; - var wmiAdapterInfo = NetworkAdapters.FirstOrDefault(n => n.Guid == wlanApiAdapterInfo.InterfaceGuid); - if (wmiAdapterInfo != null) - { - wmiAdapterInfo.IsWLanAdapter = true; - wmiAdapterInfo.WlanState = wlanApiAdapterInfo.isState; - } - } + case NetworkConnectionStatuses.Disconnected: + return "Disconnected"; + case NetworkConnectionStatuses.Connecting: + return "Connecting"; + case NetworkConnectionStatuses.Connected: + return "Connected"; + case NetworkConnectionStatuses.Disconnecting: + return "Disconnecting"; + case NetworkConnectionStatuses.HardwareNotPresent: + return "Hardware Not Present"; + case NetworkConnectionStatuses.HardwareDisabled: + return "Hardware Disabled"; + case NetworkConnectionStatuses.HardwareMalfunction: + return "Hardware Malfunction"; + case NetworkConnectionStatuses.MediaDisconnected: + return "Media Disconnected"; + case NetworkConnectionStatuses.Authenticating: + return "Authenticating"; + case NetworkConnectionStatuses.AuthenticationSucceeded: + return "Authentication Succeeded"; + case NetworkConnectionStatuses.AuthenticationFailed: + return "Authentication Failed"; + case NetworkConnectionStatuses.InvalidAddress: + return "Invalid Address"; + case NetworkConnectionStatuses.CredentialsRequired: + return "Credentials Required"; + default: + return "Unknown"; } } - public static string PrimaryLanMacAddress - { - get - { - // Return null if no Primary LAN Network Adapter found on this Device - - return (PrimaryLanNetworkAdapter == null) ? null : PrimaryLanNetworkAdapter.MacAddress; - } - } - public static string PrimaryWlanMacAddress - { - get - { - // Return null if no Primary WLAN Network Adapter found on this Device - - return (PrimaryWlanNetworkAdapter == null) ? null : PrimaryWlanNetworkAdapter.MacAddress; - } - } - - private class NetworkAdapterInfo - { - public UInt32 Index { get; set; } - public Guid Guid { get; set; } - public string Name { get; set; } - public string NetConnectionId { get; set; } - public string MacAddress { get; set; } - public UInt64 Speed { get; set; } - - public bool IsWLanAdapter { get; set; } - public WLAN_INTERFACE_STATE WlanState { get; set; } - - public string WlanStateDescription - { - get - { - switch (WlanState) - { - case WLAN_INTERFACE_STATE.wlan_interface_state_not_ready: - return "Not Ready"; - case WLAN_INTERFACE_STATE.wlan_interface_state_connected: - return "Connected"; - case WLAN_INTERFACE_STATE.wlan_interface_state_ad_hoc_network_formed: - return "Ad Hoc Network Formed"; - case WLAN_INTERFACE_STATE.wlan_interface_state_disconnecting: - return "Disconnecting"; - case WLAN_INTERFACE_STATE.wlan_interface_state_disconnected: - return "Disconnected"; - case WLAN_INTERFACE_STATE.wlan_interface_state_associating: - return "Associating"; - case WLAN_INTERFACE_STATE.wlan_interface_state_discovering: - return "Discovering"; - case WLAN_INTERFACE_STATE.wlan_interface_state_authenticating: - return "Authenticating"; - default: - return "Unknown"; - } - } - } - } - - #region Wlan Win32 Interop - - private const uint WLAN_API_VERSION_2_0 = 2; // Windows Vista WiFi API Version - private const int ERROR_SUCCESS = 0; - - /// - /// Opens a connection to the server - /// - [DllImport("Wlanapi.dll")] - private static extern int WlanOpenHandle( - uint dwClientVersion, - IntPtr pReserved, //not in MSDN but required - [Out] out uint pdwNegotiatedVersion, - ref IntPtr ClientHandle); - - /// - /// Closes a connection to the server - /// - [DllImport("Wlanapi", EntryPoint = "WlanCloseHandle")] - private static extern uint WlanCloseHandle( - [In] IntPtr hClientHandle, - IntPtr pReserved); - - /// - /// Enumerates all wireless interfaces in the laptop - /// - [DllImport("Wlanapi", EntryPoint = "WlanEnumInterfaces")] - private static extern uint WlanEnumInterfaces( - [In] IntPtr hClientHandle, - IntPtr pReserved, - ref IntPtr ppInterfaceList); - - /// - /// Frees memory returned by native WiFi functions - /// - [DllImport("Wlanapi", EntryPoint = "WlanFreeMemory")] - private static extern void WlanFreeMemory([In] IntPtr pMemory); - - /// - /// Defines the state of the interface. e.g. connected, disconnected. - /// - private enum WLAN_INTERFACE_STATE - { - /// - /// wlan_interface_state_not_ready -> 0 - /// - wlan_interface_state_not_ready = 0, - /// - /// wlan_interface_state_connected -> 1 - /// - wlan_interface_state_connected = 1, - /// - /// wlan_interface_state_ad_hoc_network_formed -> 2 - /// - wlan_interface_state_ad_hoc_network_formed = 2, - /// - /// wlan_interface_state_disconnecting -> 3 - /// - wlan_interface_state_disconnecting = 3, - /// - /// wlan_interface_state_disconnected -> 4 - /// - wlan_interface_state_disconnected = 4, - /// - /// wlan_interface_state_associating -> 5 - /// - wlan_interface_state_associating = 5, - /// - /// wlan_interface_state_discovering -> 6 - /// - wlan_interface_state_discovering = 6, - /// - /// wlan_interface_state_authenticating -> 7 - /// - wlan_interface_state_authenticating = 7, - } - - - /// - /// Stores interface info - /// - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - private struct WLAN_INTERFACE_INFO - { - /// GUID->_GUID - public Guid InterfaceGuid; - - /// WCHAR[256] - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] - public string strInterfaceDescription; - - /// WLAN_INTERFACE_STATE->_WLAN_INTERFACE_STATE - public WLAN_INTERFACE_STATE isState; - } - - /// - /// Contains an array of NIC information - /// - [StructLayout(LayoutKind.Sequential)] - private struct WLAN_INTERFACE_INFO_LIST - { - /// - /// Length of array - /// - public Int32 dwNumberOfItems; - /// - /// This member is not used by the wireless service. Applications can use this member when processing individual interfaces. - /// - public Int32 dwIndex; - /// - /// Array of WLAN interfaces. - /// - public WLAN_INTERFACE_INFO[] InterfaceInfo; - - /// - /// Constructor for WLAN_INTERFACE_INFO_LIST. - /// Constructor is needed because the InterfaceInfo member varies based on how many adapters are in the system. - /// - /// the unmanaged pointer containing the list. - public WLAN_INTERFACE_INFO_LIST(IntPtr pList) - { - // The first 4 bytes are the number of WLAN_INTERFACE_INFO structures. - dwNumberOfItems = Marshal.ReadInt32(pList, 0); - - // The next 4 bytes are the index of the current item in the unmanaged API. - dwIndex = Marshal.ReadInt32(pList, 4); - - // Construct the array of WLAN_INTERFACE_INFO structures. - InterfaceInfo = new WLAN_INTERFACE_INFO[dwNumberOfItems]; - - for (int i = 0; i <= dwNumberOfItems - 1; i++) - { - // The offset of the array of structures is 8 bytes past the beginning. - // Then, take the index and multiply it by the number of bytes in the - // structure. - // The length of the WLAN_INTERFACE_INFO structure is 532 bytes - this - // was determined by doing a Marshall.SizeOf(WLAN_INTERFACE_INFO) - IntPtr pItemList = new IntPtr(pList.ToInt64() + (i * 532) + 8); - - // Construct the WLAN_INTERFACE_INFO structure, marshal the unmanaged - // structure into it, then copy it to the array of structures. - InterfaceInfo[i] = (WLAN_INTERFACE_INFO)Marshal.PtrToStructure(pItemList, typeof(WLAN_INTERFACE_INFO)); - } - } - } - - #endregion - } } diff --git a/Disco.Client/Interop/SystemAudit.cs b/Disco.Client/Interop/SystemAudit.cs deleted file mode 100644 index 7190c9df..00000000 --- a/Disco.Client/Interop/SystemAudit.cs +++ /dev/null @@ -1,201 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Management; -using System.Text; -using System.Threading.Tasks; - -namespace Disco.Client.Interop -{ - public static class SystemAudit - { - - public static string DeviceSerialNumber { get; private set; } - public static string DeviceSMBIOSVersion { get; private set; } - public static string DeviceManufacturer { get; private set; } - public static string DeviceModel { get; private set; } - public static string DeviceType { get; private set; } - public static string DeviceUUID { get; private set; } - public static bool DeviceIsPartOfDomain { get; private set; } - public static string DeviceDNSDomainName { get; private set; } - - public static void Initialize() - { - // Get BIOS Information - try - { - using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT SerialNumber, SMBIOSBIOSVersion FROM Win32_BIOS WHERE PrimaryBios=true")) - { - using (ManagementObjectCollection mResults = mSearcher.Get()) - { - using (var mItem = mResults.Cast().FirstOrDefault()) - { - if (mItem != null) - { - DeviceSerialNumber = mItem.GetPropertyValue("SerialNumber") as string; - if (!string.IsNullOrEmpty(DeviceSerialNumber)) - DeviceSerialNumber = DeviceSerialNumber.Trim(); - - ErrorReporting.DeviceIdentifier = DeviceSerialNumber; - DeviceSMBIOSVersion = mItem.GetPropertyValue("SMBIOSBIOSVersion") as string; - if (!string.IsNullOrEmpty(DeviceSMBIOSVersion)) - DeviceSMBIOSVersion = DeviceSMBIOSVersion.Trim(); - } - else - { - throw new Exception("No Win32_BIOS WHERE PrimaryBios=true was found"); - } - } - } - } - } - catch (Exception ex) - { - throw new Exception("Disco Client was unable to retrieve BIOS information from WMI", ex); - } - - // Get System Information - try - { - using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT Manufacturer, Model, PartOfDomain, PCSystemType, Domain FROM Win32_ComputerSystem")) - { - using (ManagementObjectCollection mResults = mSearcher.Get()) - { - using (var mItem = mResults.Cast().FirstOrDefault()) - { - if (mItem != null) - { - DeviceManufacturer = mItem.GetPropertyValue("Manufacturer") as string; - if (!string.IsNullOrEmpty(DeviceManufacturer)) - DeviceManufacturer = DeviceManufacturer.Trim(); - - DeviceModel = mItem.GetPropertyValue("Model") as string; - if (!string.IsNullOrEmpty(DeviceModel)) - DeviceModel = DeviceModel.Trim(); - - DeviceIsPartOfDomain = (bool)mItem.GetPropertyValue("PartOfDomain"); - DeviceType = PCSystemTypeToString((UInt16)mItem.GetPropertyValue("PCSystemType")); - - DeviceDNSDomainName = DeviceIsPartOfDomain ? mItem.GetPropertyValue("Domain") as string : null; - } - else - { - throw new Exception("No Win32_ComputerSystem was found"); - } - } - } - } - } - catch (Exception ex) - { - throw new Exception("Disco Client was unable to retrieve ComputerSystem information from WMI", ex); - } - - // Get System Product Information - string ComputerSystemProductSerialNumber; - try - { - using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT IdentifyingNumber, UUID FROM Win32_ComputerSystemProduct")) - { - using (ManagementObjectCollection mResults = mSearcher.Get()) - { - using (var mItem = mResults.Cast().FirstOrDefault()) - { - if (mItem != null) - { - ComputerSystemProductSerialNumber = mItem.GetPropertyValue("IdentifyingNumber") as string; - if (!string.IsNullOrEmpty(ComputerSystemProductSerialNumber)) - ComputerSystemProductSerialNumber = ComputerSystemProductSerialNumber.Trim(); - - DeviceUUID = mItem.GetPropertyValue("UUID") as string; - if (!string.IsNullOrEmpty(DeviceUUID)) - DeviceUUID = DeviceUUID.Trim(); - } - else - { - throw new Exception("No Win32_ComputerSystemProduct was found"); - } - } - } - } - } - catch (Exception ex) - { - throw new Exception("Disco Client was unable to retrieve ComputerSystemProduct information from WMI", ex); - } - - // Added 2012-11-22 G# - Lenovo IdeaPad Serial SHIM - // http://www.discoict.com.au/forum/feature-requests/2012/11/serial-number-detection-on-ideapads.aspx - if (string.IsNullOrWhiteSpace(DeviceSerialNumber) || - (DeviceManufacturer.Equals("LENOVO", StringComparison.OrdinalIgnoreCase) && - (DeviceModel.Equals("S10-3", StringComparison.OrdinalIgnoreCase) // S10-3 - || DeviceModel.Equals("2957", StringComparison.OrdinalIgnoreCase)))) // S10-2 - { - try - { - using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BaseBoard")) - { - using (ManagementObjectCollection mResults = mSearcher.Get()) - { - using (var mItem = mResults.Cast().FirstOrDefault()) - { - if (mItem != null) - { - DeviceSerialNumber = mItem.GetPropertyValue("SerialNumber") as string; - if (!string.IsNullOrEmpty(DeviceSerialNumber)) - DeviceSerialNumber = DeviceSerialNumber.Trim(); - } - else - { - throw new Exception("No Win32_BaseBoard was found"); - } - } - } - } - } - catch (Exception ex) - { - throw new Exception("Disco Client was unable to retrieve BaseBoard information from WMI", ex); - } - if (string.IsNullOrWhiteSpace(DeviceSerialNumber)) - DeviceSerialNumber = ComputerSystemProductSerialNumber; - } - // End Added 2012-11-22 G# - - ErrorReporting.DeviceIdentifier = DeviceSerialNumber; - - // Validate Device 'State' - if (string.IsNullOrWhiteSpace(DeviceSerialNumber)) - throw new Exception("This device has no serial number stored in BIOS or BaseBoard"); - if (DeviceSerialNumber.Length > 60) - throw new Exception(string.Format("The serial number reported by this device is over 60 characters long:{0}{1}", Environment.NewLine, DeviceSerialNumber)); - } - - private static string PCSystemTypeToString(UInt16 PCSystemType) - { - switch (PCSystemType) - { - case 0: - return "Unknown"; - case 1: - return "Desktop"; - case 2: - return "Mobile"; - case 3: - return "Workstation"; - case 4: - return "EnterpriseServer"; - case 5: - return "SmallOfficeAndHomeOfficeServer"; - case 6: - return "AppliancePC"; - case 7: - return "PerformanceServer"; - case 8: - return "Maximum"; - default: - return "Unknown"; - } - } - } -} diff --git a/Disco.Client/Interop/WirelessNetwork.cs b/Disco.Client/Interop/WirelessNetwork.cs new file mode 100644 index 00000000..dcb0f904 --- /dev/null +++ b/Disco.Client/Interop/WirelessNetwork.cs @@ -0,0 +1,362 @@ +using Disco.Client.Interop.Native; +using Disco.Models.ClientServices.EnrolmentInformation; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml.Linq; + +namespace Disco.Client.Interop +{ + public static class WirelessNetwork + { + + public static void ApplyWlanInformation(this List Adapters) + { + try + { + IntPtr wlanHandle; + uint wlanServiceVersion; + + if (WlanApi.WlanOpenHandle(WlanApi.WLAN_API_VERSION_2_0, IntPtr.Zero, out wlanServiceVersion, out wlanHandle) == WlanApi.ERROR_SUCCESS) + { + try + { + IntPtr wlanInterfacesPtr; + + if (WlanApi.WlanEnumInterfaces(wlanHandle, IntPtr.Zero, out wlanInterfacesPtr) == WlanApi.ERROR_SUCCESS) + { + try + { + var wlanInterfaces = new WLAN_INTERFACE_INFO_LIST(wlanInterfacesPtr); + + foreach (var wlanInterface in wlanInterfaces.InterfaceInfo) + { + var adapter = Adapters.FirstOrDefault(a => a.ConnectionIdentifier == wlanInterface.InterfaceGuid); + if (adapter != null) + { + adapter.IsWlanAdapter = true; + adapter.WlanStatus = wlanInterface.isState.Description(); + } + } + } + finally + { + WlanApi.WlanFreeMemory(wlanInterfacesPtr); + } + } + } + finally + { + WlanApi.WlanCloseHandle(wlanHandle, IntPtr.Zero); + } + } + } + catch (DllNotFoundException) + { + // Ignore + // Indicates 'Wlanapi.dll' isn't present (ie. Servers) + } + } + + public static List GetWirelessProfiles() + { + try + { + IntPtr wlanHandle; + uint wlanServiceVersion; + uint interopResult; + + // Connect to wireless service + interopResult = WlanApi.WlanOpenHandle(WlanApi.WLAN_API_VERSION_2_0, IntPtr.Zero, out wlanServiceVersion, out wlanHandle); + if (interopResult != WlanApi.ERROR_SUCCESS) + { + throw new Exception($"Unable to connect to local wireless service. WlanOpenHandle returned: {interopResult}"); + } + try + { + return GetWirelessProfiles(wlanHandle); + } + finally + { + WlanApi.WlanCloseHandle(wlanHandle, IntPtr.Zero); + } + } + catch (DllNotFoundException) + { + // Indicates 'Wlanapi.dll' isn't present (ie. Servers) + return null; + } + } + + private static List GetWirelessProfiles(IntPtr wlanHandle) + { + uint interopResult; + IntPtr wlanInterfacesPtr; + + // Enumerate wireless interfaces + interopResult = WlanApi.WlanEnumInterfaces(wlanHandle, IntPtr.Zero, out wlanInterfacesPtr); + if (interopResult != WlanApi.ERROR_SUCCESS) + { + throw new Exception($"Unable to list interfaces with the local wireless service. WlanEnumInterfaces returned: {interopResult}"); + } + try + { + var wlanInterfaces = new WLAN_INTERFACE_INFO_LIST(wlanInterfacesPtr); + var profiles = new List(); + + foreach (var wlanInterface in wlanInterfaces.InterfaceInfo) + { + IntPtr wlanProfilesPtr; + // Enumerate wireless profiles for interface + interopResult = WlanApi.WlanGetProfileList(wlanHandle, wlanInterface.InterfaceGuid, IntPtr.Zero, out wlanProfilesPtr); + if (interopResult != WlanApi.ERROR_SUCCESS) + { + throw new Exception($"Unable to list wireless profiles for the {wlanInterface.InterfaceGuid} interface with the local wireless service. WlanGetProfileList returned: {interopResult}"); + } + try + { + var wlanProfiles = new WLAN_PROFILE_INFO_LIST(wlanProfilesPtr); + + foreach (var wlanProfile in wlanProfiles.ProfileInfo) + { + profiles.Add(new WirelessProfile() + { + Name = wlanProfile.strInterfaceDescription, + InterfaceGuid = wlanInterface.InterfaceGuid, + IsGroupPolicy = wlanProfile.dwFlags.HasFlag(ProfileInfoFlags.WLAN_PROFILE_GROUP_POLICY) + }); + } + } + finally + { + WlanApi.WlanFreeMemory(wlanProfilesPtr); + } + } + + return profiles; + } + finally + { + WlanApi.WlanFreeMemory(wlanInterfacesPtr); + } + } + + public static void Apply(this WirelessProfileStore ProfileStore) + { + var adapters = Network.GetNetworkAdapters().Where(a => a.IsWlanAdapter).ToList(); + + try + { + IntPtr wlanHandle; + uint wlanServiceVersion; + uint interopResult; + + // Connect to wireless service + interopResult = WlanApi.WlanOpenHandle(WlanApi.WLAN_API_VERSION_2_0, IntPtr.Zero, out wlanServiceVersion, out wlanHandle); + if (interopResult != WlanApi.ERROR_SUCCESS) + { + throw new Exception($"Unable to connect to local wireless service. WlanOpenHandle returned: {interopResult}"); + } + try + { + var existingProfiles = GetWirelessProfiles(wlanHandle); + var addedProfiles = new List(); + + // Remove Profiles + if (ProfileStore.RemoveNames != null && ProfileStore.RemoveNames.Count > 0) + { + var profileRemoved = false; + + foreach (var removeName in ProfileStore.RemoveNames) + { + var foundProfiles = existingProfiles.Where(p => p.Name == removeName); + foreach (var profile in foundProfiles) + { + var adapter = adapters.FirstOrDefault(a => a.ConnectionIdentifier == profile.InterfaceGuid); + + if (profile.IsGroupPolicy == true) + { + Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nUnable to remove Group Policy Wireless Profile '{removeName}' from '{adapter?.NetConnectionID ?? profile.InterfaceGuid.ToString()}'", true, -1, 3000); + } + else + { + Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nRemoving Wireless Profile '{removeName}' from '{adapter?.NetConnectionID ?? profile.InterfaceGuid.ToString()}'", true, -1, 1000); + + interopResult = WlanApi.WlanDeleteProfile(wlanHandle, profile.InterfaceGuid.Value, profile.Name, IntPtr.Zero); + + if (interopResult != WlanApi.ERROR_SUCCESS) + { + Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nFailed to remove Wireless Profile '{removeName}' from '{adapter?.NetConnectionID ?? profile.InterfaceGuid.ToString()}'; WlanDeleteProfile returned: {interopResult}", true, -1, 3000); + } + profileRemoved = true; + } + } + } + + if (profileRemoved) + { + existingProfiles = GetWirelessProfiles(wlanHandle); + } + } + + // Add Profiles + if (ProfileStore.Profiles != null && ProfileStore.Profiles.Count > 0) + { + foreach (var addProfile in ProfileStore.Profiles) + { + foreach (var adapter in adapters) + { + var existingProfile = existingProfiles.FirstOrDefault(p => p.Name == addProfile.Name && p.InterfaceGuid == adapter.ConnectionIdentifier); + + if (addProfile.ForceDeployment.Value || + existingProfile == null) + { + if (existingProfile != null && existingProfile.IsGroupPolicy.Value) + { + Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nUnable to replace Group Policy Wireless Profile '{addProfile.Name}' on '{adapter.NetConnectionID}'", true, -1, 3000); + } + else + { + uint pdwReasonCode; + Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nAdding Wireless Profile '{addProfile.Name}' on '{adapter.NetConnectionID}'", true, -1, 1000); + interopResult = WlanApi.WlanSetProfile(wlanHandle, adapter.ConnectionIdentifier, 0, addProfile.ProfileXml, null, true, IntPtr.Zero, out pdwReasonCode); + + if (interopResult != WlanApi.ERROR_SUCCESS) + { + // Get Reason Code + var reason = new StringBuilder(256); + WlanApi.WlanReasonCodeToString(pdwReasonCode, (uint)reason.Capacity, ref reason, IntPtr.Zero); + + Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nFailed to add Wireless Profile '{addProfile.Name}' on '{adapter.NetConnectionID}'; WlanSetProfile returned: {interopResult}; {reason.ToString()}", true, -1, 3000); + } + } + addedProfiles.Add(addProfile.Name); + } + } + } + } + + // Transform Profiles + if (ProfileStore.Transformations != null && ProfileStore.Transformations.Count > 0) + { + foreach (var transformGroup in ProfileStore.Transformations.GroupBy(t => t.Name)) + { + var profileName = transformGroup.Key; + + // Don't transform if just added + if (!addedProfiles.Contains(transformGroup.Key)) + { + foreach (var adapter in adapters) + { + var existingProfile = existingProfiles.FirstOrDefault(p => p.Name == profileName && p.InterfaceGuid == adapter.ConnectionIdentifier); + + if (existingProfile != null) + { + if (existingProfile.IsGroupPolicy.Value) + { + Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nUnable to modify Group Policy Wireless Profile '{profileName}' on '{adapter.NetConnectionID}'", true, -1, 3000); + } + else + { + // Load profile + IntPtr pstrProfileXml; + uint pdwFlags; + IntPtr pdwGrantAccess; + + interopResult = WlanApi.WlanGetProfile(wlanHandle, adapter.ConnectionIdentifier, profileName, IntPtr.Zero, out pstrProfileXml, out pdwFlags, out pdwGrantAccess); + + if (interopResult == WlanApi.ERROR_SUCCESS) + { + try + { + var profileXml = Marshal.PtrToStringUni(pstrProfileXml); + var originalProfileXml = XElement.Parse(profileXml); + var transformProfileXml = originalProfileXml.ToString(SaveOptions.DisableFormatting); + + // Apply Transforms + foreach (var transform in transformGroup) + { + var regex = new Regex(transform.RegularExpression, RegexOptions.Singleline); + transformProfileXml = regex.Replace(transformProfileXml, transform.RegularExpressionReplacement); + } + + // Compare XML + var transformedProfileXml = XElement.Parse(transformProfileXml); + + if (!XNode.DeepEquals(originalProfileXml, transformedProfileXml)) + { + // Set Profile + uint pdwReasonCode; + Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nModifying Wireless Profile '{profileName}' on '{adapter.NetConnectionID}'", true, -1, 1000); + transformProfileXml = transformedProfileXml.ToString(SaveOptions.None); + interopResult = WlanApi.WlanSetProfile(wlanHandle, adapter.ConnectionIdentifier, 0, transformProfileXml, null, true, IntPtr.Zero, out pdwReasonCode); + + if (interopResult != WlanApi.ERROR_SUCCESS) + { + // Get Reason Code + var reason = new StringBuilder(256); + WlanApi.WlanReasonCodeToString(pdwReasonCode, (uint)reason.Capacity, ref reason, IntPtr.Zero); + + Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nFailed to modify Wireless Profile '{profileName}' to '{adapter.NetConnectionID}'; WlanSetProfile returned: {interopResult}; {reason.ToString()}", true, -1, 3000); + } + } + } + finally + { + WlanApi.WlanFreeMemory(pstrProfileXml); + } + } + else + { + Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nFailed to transform Wireless Profile '{profileName}' on '{adapter.NetConnectionID}'; WlanGetProfile returned: {interopResult}", true, -1, 3000); + } + } + } + } + } + } + } + + } + finally + { + WlanApi.WlanCloseHandle(wlanHandle, IntPtr.Zero); + } + } + catch (DllNotFoundException) + { + // Indicates 'Wlanapi.dll' isn't present (ie. Servers) + // Ignore policies + } + + } + + public static string Description(this WLAN_INTERFACE_STATE State) + { + switch (State) + { + case WLAN_INTERFACE_STATE.wlan_interface_state_not_ready: + return "Not Ready"; + case WLAN_INTERFACE_STATE.wlan_interface_state_connected: + return "Connected"; + case WLAN_INTERFACE_STATE.wlan_interface_state_ad_hoc_network_formed: + return "Ad Hoc Network"; + case WLAN_INTERFACE_STATE.wlan_interface_state_disconnecting: + return "Disconnecting"; + case WLAN_INTERFACE_STATE.wlan_interface_state_disconnected: + return "Disconnected"; + case WLAN_INTERFACE_STATE.wlan_interface_state_associating: + return "Associating"; + case WLAN_INTERFACE_STATE.wlan_interface_state_discovering: + return "Discovering"; + case WLAN_INTERFACE_STATE.wlan_interface_state_authenticating: + return "Authenticating"; + default: + return "Unknown"; + } + } + } +} diff --git a/Disco.Client/Presentation.cs b/Disco.Client/Presentation.cs index 791c5241..40211d37 100644 --- a/Disco.Client/Presentation.cs +++ b/Disco.Client/Presentation.cs @@ -5,6 +5,7 @@ using System.Reflection; using System.Text; using System.Threading; using Disco.Client.Extensions; +using Disco.Client.Interop; namespace Disco.Client { @@ -38,8 +39,8 @@ namespace Disco.Client public static void WriteBanner() { StringBuilder message = new StringBuilder(); - message.Append("Version: ").AppendLine(Assembly.GetExecutingAssembly().GetName().Version.ToString(3)); - message.Append("Device: ").Append(Interop.SystemAudit.DeviceSerialNumber).Append(" (").Append(Interop.SystemAudit.DeviceManufacturer).Append(" ").Append(Interop.SystemAudit.DeviceModel).AppendLine(")"); + message.AppendLine($"Version: {Assembly.GetExecutingAssembly().GetName().Version.ToString(3)}"); + message.AppendLine($"Device: {Hardware.Information.SerialNumber} ({Hardware.Information.Manufacturer} {Hardware.Information.Model})"); Console.ForegroundColor = ConsoleColor.Yellow; UpdateStatus("Preparation Client Started", message.ToString(), false, 0); Console.ForegroundColor = ConsoleColor.White; @@ -52,8 +53,8 @@ namespace Disco.Client ClientServiceException clientServiceException = ex as ClientServiceException; if (clientServiceException != null) { - UpdateStatus(string.Format("An error occurred during {0}", clientServiceException.ServiceFeature), - clientServiceException.Message, false, 0); + UpdateStatus($"An error occurred during {clientServiceException.ServiceFeature}", + clientServiceException.Message, false, 0); } else { diff --git a/Disco.Client/Program.cs b/Disco.Client/Program.cs index 8c515e72..ef388e68 100644 --- a/Disco.Client/Program.cs +++ b/Disco.Client/Program.cs @@ -20,6 +20,17 @@ namespace Disco.Client { bool keepProcessing; +#if DEBUG + if (args != null && args.Any(a => a.Equals("debug", StringComparison.OrdinalIgnoreCase))) + { + do + { + Console.WriteLine("Waiting for Debugger to Attach"); + System.Threading.Thread.Sleep(1000); + } while (!System.Diagnostics.Debugger.IsAttached); + } +#endif + // Initialize Environment Settings SetupEnvironment(); @@ -59,10 +70,6 @@ namespace Disco.Client { Presentation.DelayUI = true; // Add Delays on Error } - - // Initialize Interop - Interop.SystemAudit.Initialize(); - Interop.Network.Initialize(); } public static bool WhoAmI() diff --git a/Disco.Client/Properties/AssemblyInfo.cs b/Disco.Client/Properties/AssemblyInfo.cs index d94c1932..cf441eaa 100644 --- a/Disco.Client/Properties/AssemblyInfo.cs +++ b/Disco.Client/Properties/AssemblyInfo.cs @@ -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.1.0.0")] -[assembly: AssemblyFileVersion("2.1.0.0")] \ No newline at end of file +[assembly: AssemblyVersion("2.2.16272.1003")] +[assembly: AssemblyFileVersion("2.2.16272.1003")] \ No newline at end of file diff --git a/Disco.ClientBootstrapper/BootstrapperLoop.cs b/Disco.ClientBootstrapper/BootstrapperLoop.cs index beba5a08..7e419d8d 100644 --- a/Disco.ClientBootstrapper/BootstrapperLoop.cs +++ b/Disco.ClientBootstrapper/BootstrapperLoop.cs @@ -1,6 +1,4 @@ -//#define Debug - -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -22,6 +20,14 @@ namespace Disco.ClientBootstrapper private StringBuilder errorMessage; private Process clientProcess; +#if DEBUG + public const string DiscoServerName = "WS-GSHARP"; + public const int DiscoServerPort = 57252; +#else + public const string DiscoServerName = "DISCO"; + public const int DiscoServerPort = 9292; +#endif + public BootstrapperLoop(IStatus StatusUI, LoopCompleteCallback Callback) { this.statusUI = StatusUI; @@ -79,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()) + if (!Interop.NetworkInterop.PingDisco(DiscoServerName)) { statusUI.UpdateStatus(null, "Detecting Network", "No network connectivity detected, Diagnosing...", true, -1); statusUI_WriteAdapterInfo(); - if (!Interop.NetworkInterop.PingDisco()) + if (!Interop.NetworkInterop.PingDisco(DiscoServerName)) { // Check for Wireless var hasWireless = (Interop.NetworkInterop.NetworkAdapters.Count(na => na.IsWireless) > 0); @@ -99,17 +105,17 @@ namespace Disco.ClientBootstrapper statusUI_WriteAdapterInfo(); statusUI.UpdateStatus(null, null, null, true, i); Program.SleepThread(500, false); - if (Interop.NetworkInterop.PingDisco()) + if (Interop.NetworkInterop.PingDisco(DiscoServerName)) break; } - if (!Interop.NetworkInterop.PingDisco()) + if (!Interop.NetworkInterop.PingDisco(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()) + if (!Interop.NetworkInterop.PingDisco(DiscoServerName)) { // Instruct user to connect network cable statusUI.UpdateStatus(null, "Please connect the network cable", null); @@ -118,13 +124,13 @@ namespace Disco.ClientBootstrapper statusUI_WriteAdapterInfo(); statusUI.UpdateStatus(null, null, null, true, i); Program.SleepThread(500, false); - if (Interop.NetworkInterop.PingDisco()) + if (Interop.NetworkInterop.PingDisco(DiscoServerName)) break; } } } - if (!Interop.NetworkInterop.PingDisco()) + if (!Interop.NetworkInterop.PingDisco(DiscoServerName)) { // Client Failed if (this.mLoopCompleteCallback != null) @@ -143,7 +149,7 @@ namespace Disco.ClientBootstrapper // Don't use a proxy when downloading the Client webClient.Proxy = new WebProxy(); - webClient.DownloadFile("http://disco:9292/Services/Client/PreparationClient", clientSourceLocation); + webClient.DownloadFile($"http://{DiscoServerName}:{DiscoServerPort}/Services/Client/PreparationClient", clientSourceLocation); } // Unzip Client diff --git a/Disco.ClientBootstrapper/Disco.ClientBootstrapper.csproj b/Disco.ClientBootstrapper/Disco.ClientBootstrapper.csproj index 8f6d5337..b9953299 100644 --- a/Disco.ClientBootstrapper/Disco.ClientBootstrapper.csproj +++ b/Disco.ClientBootstrapper/Disco.ClientBootstrapper.csproj @@ -28,6 +28,7 @@ false false true + 2.2.16272.1003 x86 diff --git a/Disco.ClientBootstrapper/Interop/NetworkInterop.cs b/Disco.ClientBootstrapper/Interop/NetworkInterop.cs index ad95b258..2419abc2 100644 --- a/Disco.ClientBootstrapper/Interop/NetworkInterop.cs +++ b/Disco.ClientBootstrapper/Interop/NetworkInterop.cs @@ -165,13 +165,13 @@ namespace Disco.ClientBootstrapper.Interop } } - public static bool PingDisco() + public static bool PingDisco(string ServerName) { using (Ping p = new Ping()) { try { - PingReply pr = p.Send("disco", 2000); + PingReply pr = p.Send(ServerName, 2000); if (pr.Status == IPStatus.Success) return true; else diff --git a/Disco.ClientBootstrapper/Properties/AssemblyInfo.cs b/Disco.ClientBootstrapper/Properties/AssemblyInfo.cs index 7050517b..42c0ab66 100644 --- a/Disco.ClientBootstrapper/Properties/AssemblyInfo.cs +++ b/Disco.ClientBootstrapper/Properties/AssemblyInfo.cs @@ -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.1.0.0")] -[assembly: AssemblyFileVersion("2.1.0.0")] \ No newline at end of file +[assembly: AssemblyVersion("2.2.16272.1003")] +[assembly: AssemblyFileVersion("2.2.16272.1003")] \ No newline at end of file diff --git a/Disco.Data/Configuration/Modules/ActiveDirectoryConfiguration.cs b/Disco.Data/Configuration/Modules/ActiveDirectoryConfiguration.cs index 93f8a13c..f4f0e454 100644 --- a/Disco.Data/Configuration/Modules/ActiveDirectoryConfiguration.cs +++ b/Disco.Data/Configuration/Modules/ActiveDirectoryConfiguration.cs @@ -36,7 +36,7 @@ namespace Disco.Data.Configuration.Modules /// public bool SearchWildcardSuffixOnly { - get { return Get(false); } + get { return Get(true); } set { Set(value); } } } diff --git a/Disco.Data/Configuration/Modules/JobPreferencesConfiguration.cs b/Disco.Data/Configuration/Modules/JobPreferencesConfiguration.cs index 784dde15..925114ce 100644 --- a/Disco.Data/Configuration/Modules/JobPreferencesConfiguration.cs +++ b/Disco.Data/Configuration/Modules/JobPreferencesConfiguration.cs @@ -1,5 +1,5 @@ using Disco.Data.Repository; -using Disco.Models.BI.Job; +using Disco.Models.Services.Job; using System; using System.Collections.Generic; @@ -59,13 +59,13 @@ namespace Disco.Data.Configuration.Modules public LocationModes LocationMode { - get { return Get(LocationModes.Unrestricted); } + get { return Get(LocationModes.Unrestricted); } set { Set(value); } } public List LocationList { - get { return Get>(new List()); } + get { return Get(new List()); } set { Set(value); } } } diff --git a/Disco.Data/Configuration/SystemConfiguration.cs b/Disco.Data/Configuration/SystemConfiguration.cs index 9252c230..60b6d7e1 100644 --- a/Disco.Data/Configuration/SystemConfiguration.cs +++ b/Disco.Data/Configuration/SystemConfiguration.cs @@ -284,12 +284,12 @@ namespace Disco.Data.Configuration return (short)(BitConverter.ToInt16(deploymentIdBytes, 0) ^ BitConverter.ToInt16(deploymentIdBytes, 2) ^ - BitConverter.ToInt16(deploymentIdBytes, 2) ^ - BitConverter.ToInt16(deploymentIdBytes, 2) ^ - BitConverter.ToInt16(deploymentIdBytes, 2) ^ - BitConverter.ToInt16(deploymentIdBytes, 2) ^ - BitConverter.ToInt16(deploymentIdBytes, 2) ^ - BitConverter.ToInt16(deploymentIdBytes, 2)); + BitConverter.ToInt16(deploymentIdBytes, 4) ^ + BitConverter.ToInt16(deploymentIdBytes, 6) ^ + BitConverter.ToInt16(deploymentIdBytes, 8) ^ + BitConverter.ToInt16(deploymentIdBytes, 10) ^ + BitConverter.ToInt16(deploymentIdBytes, 12) ^ + BitConverter.ToInt16(deploymentIdBytes, 14)); } } public UpdateResponseV2 UpdateLastCheckResponse diff --git a/Disco.Data/Disco.Data.csproj b/Disco.Data/Disco.Data.csproj index ef31d263..54b9c92f 100644 --- a/Disco.Data/Disco.Data.csproj +++ b/Disco.Data/Disco.Data.csproj @@ -15,6 +15,7 @@ ..\ true + 2.2.16272.1003 true @@ -150,6 +151,10 @@ 201407260624238_DBv16.cs + + + 201609260741183_DBv17.cs + @@ -213,6 +218,9 @@ 201407260624238_DBv16.cs + + 201609260741183_DBv17.cs + ResXFileCodeGenerator Resources.Designer.cs diff --git a/Disco.Data/Migrations/201609260741183_DBv17.Designer.cs b/Disco.Data/Migrations/201609260741183_DBv17.Designer.cs new file mode 100644 index 00000000..93725c9f --- /dev/null +++ b/Disco.Data/Migrations/201609260741183_DBv17.Designer.cs @@ -0,0 +1,27 @@ +// +namespace Disco.Data.Migrations +{ + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + public sealed partial class DBv17 : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(DBv17)); + + string IMigrationMetadata.Id + { + get { return "201609260741183_DBv17"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/Disco.Data/Migrations/201609260741183_DBv17.cs b/Disco.Data/Migrations/201609260741183_DBv17.cs new file mode 100644 index 00000000..3e69a5b8 --- /dev/null +++ b/Disco.Data/Migrations/201609260741183_DBv17.cs @@ -0,0 +1,27 @@ +namespace Disco.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class DBv17 : DbMigration + { + public override void Up() + { + RenameColumn("dbo.DeviceProfiles", "CertificateProviderId", "CertificateProviders"); + AlterColumn("dbo.DeviceProfiles", "CertificateProviders", c => c.String(maxLength: 200)); + AddColumn("dbo.DeviceProfiles", "CertificateAuthorityProviders", c => c.String(maxLength: 200)); + AddColumn("dbo.DeviceProfiles", "WirelessProfileProviders", c => c.String(maxLength: 200)); + + // Migration support for eduSTAR.net plugin + Sql("UPDATE [DeviceProfiles] SET [CertificateAuthorityProviders]='EduSTARnetCertificateAuthorityProvider', [WirelessProfileProviders]='EduSTARnetWirelessProfileProvider' WHERE [CertificateProviders]='EduSTARnetCertificateProvider'"); + } + + public override void Down() + { + AddColumn("dbo.DeviceProfiles", "CertificateProviderId", c => c.String(maxLength: 64)); + DropColumn("dbo.DeviceProfiles", "WirelessProfileProviders"); + DropColumn("dbo.DeviceProfiles", "CertificateAuthorityProviders"); + DropColumn("dbo.DeviceProfiles", "CertificateProviders"); + } + } +} diff --git a/Disco.Data/Migrations/201609260741183_DBv17.resx b/Disco.Data/Migrations/201609260741183_DBv17.resx new file mode 100644 index 00000000..5f724ae2 --- /dev/null +++ b/Disco.Data/Migrations/201609260741183_DBv17.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + \ No newline at end of file diff --git a/Disco.Data/Properties/AssemblyInfo.cs b/Disco.Data/Properties/AssemblyInfo.cs index e3f3970a..b129d1d5 100644 --- a/Disco.Data/Properties/AssemblyInfo.cs +++ b/Disco.Data/Properties/AssemblyInfo.cs @@ -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.1.0.0")] -[assembly: AssemblyFileVersion("2.1.0.0")] \ No newline at end of file +[assembly: AssemblyVersion("2.2.16272.1003")] +[assembly: AssemblyFileVersion("2.2.16272.1003")] \ No newline at end of file diff --git a/Disco.Data/Repository/DiscoDataSeeder.cs b/Disco.Data/Repository/DiscoDataSeeder.cs index 258942b3..0a1139de 100644 --- a/Disco.Data/Repository/DiscoDataSeeder.cs +++ b/Disco.Data/Repository/DiscoDataSeeder.cs @@ -273,12 +273,6 @@ namespace Disco.Data.Repository case "OrganisationalUnit": dp.OrganisationalUnit = configurationItem.Value; break; - case "AllocateWirelessCertificate": - if (bool.Parse(configurationItem.Value)) - dp.CertificateProviderId = ""; - else - dp.CertificateProviderId = null; - break; default: continue; // Unknown Configuration Item - Leave in DB & Ignore } diff --git a/Disco.Models/BI/Device/ImportDevice.cs b/Disco.Models/BI/Device/ImportDevice.cs deleted file mode 100644 index bfb9f1de..00000000 --- a/Disco.Models/BI/Device/ImportDevice.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; - -namespace Disco.Models.BI.Device -{ - public class ImportDevice - { - [Required, StringLength(60)] - public string SerialNumber { get; set; } - - public int? DeviceModelId { get; set; } - - [Range(1, int.MaxValue, ErrorMessage = "A valid Device Profile is Required")] - public int DeviceProfileId { get; set; } - - public int? DeviceBatchId { get; set; } - - [StringLength(50)] - public string AssignedUserId { get; set; } - - [StringLength(250)] - public string Location { get; set; } - - [StringLength(40)] - public string AssetNumber { get; set; } - - public Repository.Device Device { get; set; } - public Repository.DeviceModel DeviceModel { get; set; } - public Repository.DeviceProfile DeviceProfile { get; set; } - public Repository.DeviceBatch DeviceBatch { get; set; } - public Repository.User AssignedUser { get; set; } - - public Dictionary Errors { get; set; } - } -} diff --git a/Disco.Models/BI/Device/ImportDeviceSession.cs b/Disco.Models/BI/Device/ImportDeviceSession.cs deleted file mode 100644 index 297716d7..00000000 --- a/Disco.Models/BI/Device/ImportDeviceSession.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; - -namespace Disco.Models.BI.Device -{ - public class ImportDeviceSession - { - public string ImportParseTaskId { get; set; } - public string ImportFilename { get; set; } - public List ImportDevices { get; set; } - } -} \ No newline at end of file diff --git a/Disco.Models/ClientServices/Enrol.cs b/Disco.Models/ClientServices/Enrol.cs index 70af19d2..f8ef91e9 100644 --- a/Disco.Models/ClientServices/Enrol.cs +++ b/Disco.Models/ClientServices/Enrol.cs @@ -1,7 +1,5 @@ -using System; +using Disco.Models.ClientServices.EnrolmentInformation; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Disco.Models.ClientServices { @@ -12,21 +10,20 @@ namespace Disco.Models.ClientServices get { return "Enrol"; } } - public string DeviceSerialNumber { get; set; } - public string DeviceUUID { get; set; } + public string SerialNumber { get; set; } - public string DeviceDNSDomainName { get; set; } - public string DeviceComputerName { get; set; } - public bool DeviceIsPartOfDomain { get; set; } - - public string DeviceManufacturer { get; set; } - public string DeviceModel { get; set; } - public string DeviceModelType { get; set; } + public string DNSDomainName { get; set; } + public string ComputerName { get; set; } + public bool IsPartOfDomain { get; set; } - public string DeviceLanMacAddress { get; set; } - - public string DeviceWlanMacAddress { get; set; } + public string RunningUserName { get; set; } + public string RunningUserDomain { get; set; } + public bool RunningInteractively { get; internal set; } - public List DeviceCertificates { get; set; } + public DeviceHardware Hardware { get; set; } + + public List Certificates { get; set; } + + public List WirelessProfiles { get; set; } } } diff --git a/Disco.Models/ClientServices/EnrolResponse.cs b/Disco.Models/ClientServices/EnrolResponse.cs index eb531f89..11da53f6 100644 --- a/Disco.Models/ClientServices/EnrolResponse.cs +++ b/Disco.Models/ClientServices/EnrolResponse.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using Disco.Models.ClientServices.EnrolmentInformation; namespace Disco.Models.ClientServices { @@ -9,22 +6,22 @@ namespace Disco.Models.ClientServices { public string SessionId { get; set; } - public string DeviceDomainName { get; set; } - public string DeviceComputerName { get; set; } - - public string DeviceAssignedUserDomain { get; set; } - public string DeviceAssignedUserName { get; set; } - public string DeviceAssignedUserSID { get; set; } - public string DeviceAssignedUserUsername { get; set; } + public string DomainName { get; set; } + public string ComputerName { get; set; } - public bool DeviceAssignedUserIsLocalAdmin { get; set; } + public string AssignedUserDomain { get; set; } + public string AssignedUserUsername { get; set; } + public string AssignedUserSID { get; set; } + public string AssignedUserDescription { get; set; } - public string OfflineDomainJoin { get; set; } - - public string DeviceCertificate { get; set; } - public List DeviceCertificateRemoveExisting { get; set; } + public bool AssignedUserIsLocalAdmin { get; set; } + + public string OfflineDomainJoinManifest { get; set; } + + public CertificateStore Certificates { get; set; } + + public WirelessProfileStore WirelessProfiles { get; set; } - // Actions public bool AllowBootstrapperUninstall { get; set; } public bool RequireReboot { get; set; } diff --git a/Disco.Models/ClientServices/EnrolmentInformation/Certificate.cs b/Disco.Models/ClientServices/EnrolmentInformation/Certificate.cs new file mode 100644 index 00000000..85901c46 --- /dev/null +++ b/Disco.Models/ClientServices/EnrolmentInformation/Certificate.cs @@ -0,0 +1,19 @@ +using System; + +namespace Disco.Models.ClientServices.EnrolmentInformation +{ + public class Certificate + { + public string Store { get; set; } + public string SubjectName { get; set; } + public string Thumbprint { get; set; } + public string FriendlyName { get; set; } + public string DnsName { get; set; } + public int Version { get; set; } + public string SignatureAlgorithm { get; set; } + public string Issuer { get; set; } + public DateTime NotAfter { get; set; } + public DateTime NotBefore { get; set; } + public bool HasPrivateKey { get; set; } + } +} diff --git a/Disco.Models/ClientServices/EnrolmentInformation/CertificateStore.cs b/Disco.Models/ClientServices/EnrolmentInformation/CertificateStore.cs new file mode 100644 index 00000000..3d8dcaf4 --- /dev/null +++ b/Disco.Models/ClientServices/EnrolmentInformation/CertificateStore.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; + +namespace Disco.Models.ClientServices.EnrolmentInformation +{ + public class CertificateStore + { + public List TrustedRootCertificates { get; set; } + public List TrustedRootRemoveThumbprints { get; set; } + + public List IntermediateCertificates { get; set; } + public List IntermediateRemoveThumbprints { get; set; } + + public List PersonalCertificates { get; set; } + public List PersonalRemoveThumbprints { get; set; } + } +} diff --git a/Disco.Models/ClientServices/EnrolmentInformation/DeviceHardware.cs b/Disco.Models/ClientServices/EnrolmentInformation/DeviceHardware.cs new file mode 100644 index 00000000..9f129383 --- /dev/null +++ b/Disco.Models/ClientServices/EnrolmentInformation/DeviceHardware.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; + +namespace Disco.Models.ClientServices.EnrolmentInformation +{ + public class DeviceHardware + { + public string SerialNumber { get; set; } + public string UUID { get; set; } + + public string Manufacturer { get; set; } + public string Model { get; set; } + public string ModelType { get; set; } + + public List Processors { get; set; } + public List PhysicalMemory { get; set; } + public List DiskDrives { get; set; } + public List NetworkAdapters { get; set; } + + } +} diff --git a/Disco.Models/ClientServices/EnrolmentInformation/DiskDrive.cs b/Disco.Models/ClientServices/EnrolmentInformation/DiskDrive.cs new file mode 100644 index 00000000..f4f23d6d --- /dev/null +++ b/Disco.Models/ClientServices/EnrolmentInformation/DiskDrive.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; + +namespace Disco.Models.ClientServices.EnrolmentInformation +{ + public class DiskDrive + { + public string DeviceID { get; set; } + public string Manufacturer { get; set; } + public string Model { get; set; } + public string MediaType { get; set; } + public string InterfaceType { get; set; } + public string SerialNumber { get; set; } + public string FirmwareRevision { get; set; } + public DateTime InstallDate { get; set; } + public ulong Size { get; set; } + + public List Partitions { get; set; } + } +} diff --git a/Disco.Models/ClientServices/EnrolmentInformation/DiskDrivePartition.cs b/Disco.Models/ClientServices/EnrolmentInformation/DiskDrivePartition.cs new file mode 100644 index 00000000..8a0f07a7 --- /dev/null +++ b/Disco.Models/ClientServices/EnrolmentInformation/DiskDrivePartition.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; + +namespace Disco.Models.ClientServices.EnrolmentInformation +{ + public class DiskDrivePartition + { + public bool DeviceID { get; set; } + public bool Bootable { get; set; } + public bool BootPartition { get; set; } + public bool PrimaryParition { get; set; } + public ulong Size { get; set; } + public ulong StartingOffset { get; set; } + + public List LogicalDisks { get; set; } + } +} diff --git a/Disco.Models/ClientServices/EnrolmentInformation/DiskLogical.cs b/Disco.Models/ClientServices/EnrolmentInformation/DiskLogical.cs new file mode 100644 index 00000000..56b45bad --- /dev/null +++ b/Disco.Models/ClientServices/EnrolmentInformation/DiskLogical.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Disco.Models.ClientServices.EnrolmentInformation +{ + public class DiskLogical + { + + public string DeviceID { get; set; } + public string Description { get; set; } + public int DriveType { get; set; } + public int MediaType { get; set; } + public string FileSystem { get; set; } + public ulong Size { get; set; } + public ulong FreeSpace { get; set; } + public string VolumeName { get; set; } + public string VolumeSerialNumber { get; set; } + + } +} diff --git a/Disco.Models/ClientServices/EnrolmentInformation/NetworkAdapter.cs b/Disco.Models/ClientServices/EnrolmentInformation/NetworkAdapter.cs new file mode 100644 index 00000000..ace2e025 --- /dev/null +++ b/Disco.Models/ClientServices/EnrolmentInformation/NetworkAdapter.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; + +namespace Disco.Models.ClientServices.EnrolmentInformation +{ + public class NetworkAdapter + { + public string DeviceID { get; set; } + public Guid ConnectionIdentifier { get; set; } + public bool IsWlanAdapter { get; set; } + public string Manufacturer { get; set; } + public string ProductName { get; set; } + public string AdapterType { get; set; } + + public string MACAddress { get; set; } + public ulong Speed { get; set; } + public string NetConnectionID { get; set; } + public string NetConnectionStatus { get; set; } + public string WlanStatus { get; set; } + public bool NetEnabled { get; set; } + public bool IPEnabled { get; set; } + + public List IPAddresses { get; set; } + } +} diff --git a/Disco.Models/ClientServices/EnrolmentInformation/PhysicalMemory.cs b/Disco.Models/ClientServices/EnrolmentInformation/PhysicalMemory.cs new file mode 100644 index 00000000..7ebe7e62 --- /dev/null +++ b/Disco.Models/ClientServices/EnrolmentInformation/PhysicalMemory.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Disco.Models.ClientServices.EnrolmentInformation +{ + public class PhysicalMemory + { + public string Tag { get; set; } + public string SerialNumber { get; set; } + public string Manufacturer { get; set; } + public string PartNumber { get; set; } + + public ulong Capacity { get; set; } + public int ClockSpeed { get; set; } + public int Voltage { get; set; } + + public string Location { get; set; } + + } +} diff --git a/Disco.Models/ClientServices/EnrolmentInformation/Processor.cs b/Disco.Models/ClientServices/EnrolmentInformation/Processor.cs new file mode 100644 index 00000000..f4d0eb1f --- /dev/null +++ b/Disco.Models/ClientServices/EnrolmentInformation/Processor.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Disco.Models.ClientServices.EnrolmentInformation +{ + public class Processor + { + public string DeviceID { get; set; } + public string Manufacturer { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public string Architecture { get; set; } + public short Family { get; set; } + public int MaxClockSpeed { get; set; } + public int NumberOfCores { get; set; } + public int NumberOfLogicalProcessors { get; set; } + } +} diff --git a/Disco.Models/ClientServices/EnrolmentInformation/WirelessProfile.cs b/Disco.Models/ClientServices/EnrolmentInformation/WirelessProfile.cs new file mode 100644 index 00000000..d7b6c4a5 --- /dev/null +++ b/Disco.Models/ClientServices/EnrolmentInformation/WirelessProfile.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; + +namespace Disco.Models.ClientServices.EnrolmentInformation +{ + public class WirelessProfile + { + + /// + /// The name of the wireless profile, typically the SSID + /// + public string Name { get; set; } + + /// + /// The guid of the associated interface. + /// + public Guid? InterfaceGuid { get; set; } + + /// + /// Indicates the profile is deployed via Group Policy and therefore read-only + /// + public bool? IsGroupPolicy { get; set; } + + /// + /// Indicates the profile should be overwritten even if it already exists + /// + public bool? ForceDeployment { get; set; } + + /// + /// The wireless profile XML definition + /// + public string ProfileXml { get; set; } + + } +} diff --git a/Disco.Models/ClientServices/EnrolmentInformation/WirelessProfileStore.cs b/Disco.Models/ClientServices/EnrolmentInformation/WirelessProfileStore.cs new file mode 100644 index 00000000..d266c56d --- /dev/null +++ b/Disco.Models/ClientServices/EnrolmentInformation/WirelessProfileStore.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; + +namespace Disco.Models.ClientServices.EnrolmentInformation +{ + public class WirelessProfileStore + { + + /// + /// A list of wireless profiles to add to the client device. + /// + public List Profiles { get; set; } + + /// + /// A list of transformations to be applied to existing XML wireless profiles found on the client device. + /// + public List Transformations { get; set; } + + /// + /// A list of wireless profile names to be removed from the client device. + /// + public List RemoveNames { get; set; } + + } +} diff --git a/Disco.Models/ClientServices/EnrolmentInformation/WirelessProfileTransformation.cs b/Disco.Models/ClientServices/EnrolmentInformation/WirelessProfileTransformation.cs new file mode 100644 index 00000000..77a5af10 --- /dev/null +++ b/Disco.Models/ClientServices/EnrolmentInformation/WirelessProfileTransformation.cs @@ -0,0 +1,22 @@ +namespace Disco.Models.ClientServices.EnrolmentInformation +{ + public class WirelessProfileTransformation + { + + /// + /// The name of the wireless profile related to this transformation, typically the SSID + /// + public string Name { get; set; } + + /// + /// The regular expression to evaluate against the wireless profile XML + /// + public string RegularExpression { get; set; } + + /// + /// The replacement string used when evaluating the regular expression + /// + public string RegularExpressionReplacement { get; set; } + + } +} diff --git a/Disco.Models/ClientServices/WhoAmIResponse.cs b/Disco.Models/ClientServices/WhoAmIResponse.cs index d008a83d..108b6487 100644 --- a/Disco.Models/ClientServices/WhoAmIResponse.cs +++ b/Disco.Models/ClientServices/WhoAmIResponse.cs @@ -13,7 +13,7 @@ namespace Disco.Models.ClientServices public override string ToString() { - return string.Format("{0} ({1})", DisplayName, Username); + return $"{DisplayName} ({Username})"; } } } diff --git a/Disco.Models/Disco.Models.csproj b/Disco.Models/Disco.Models.csproj index f1c31c49..77629eba 100644 --- a/Disco.Models/Disco.Models.csproj +++ b/Disco.Models/Disco.Models.csproj @@ -13,6 +13,7 @@ v4.5 512 + 2.2.16272.1003 true @@ -48,7 +49,20 @@ - + + + + + + + + + + + + + + @@ -60,12 +74,9 @@ - - - - + @@ -184,9 +195,7 @@ - - - + + \ No newline at end of file diff --git a/Disco.Services.Plugins.ManifestGenerator/Program.cs b/Disco.Services.Plugins.ManifestGenerator/Program.cs new file mode 100644 index 00000000..41dc12e4 --- /dev/null +++ b/Disco.Services.Plugins.ManifestGenerator/Program.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Reflection; + +namespace Disco.Services.Plugins.ManifestGenerator +{ + class Program + { + static void Main(string[] args) + { + if (args.Length != 1) + { + throw new ArgumentException("Only one command-line argument is expected, the path to the plugin assembly"); + } + + var assemblyPath = args[0]; + var assemblyFileInfo = new FileInfo(assemblyPath); + + // Ensure File Exists + if (!assemblyFileInfo.Exists) + { + throw new ArgumentException($"File not found at: {assemblyFileInfo.FullName}"); + } + + Console.WriteLine("Disco Plugin: Generating Manifest"); + + AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad; + AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; + + // Load Plugin Assembly + Assembly assembly; + try + { + assembly = Assembly.LoadFile(assemblyFileInfo.FullName); + } + catch (Exception ex) + { + throw new Exception($"Unable to load the Assembly: {assemblyFileInfo.FullName}", ex); + } + + // Load Reference Assemblies + foreach (var referenceAssembly in assemblyFileInfo.Directory.GetFiles("*.dll")) + { + if (referenceAssembly.FullName != assemblyFileInfo.FullName) + { + if (!PluginManifest.PluginExcludedAssemblies.Any(excludeAssembly => referenceAssembly.Name.StartsWith(excludeAssembly, StringComparison.OrdinalIgnoreCase))) + { + try + { + + Assembly.LoadFile(referenceAssembly.FullName); + } + catch (Exception ex) + { + Console.WriteLine($"Disco Plugin: Warning: Unable to load reference '{referenceAssembly.FullName}'; {ex.Message}"); + } + } + } + } + + // Create Manifest + var manifest = PluginManifest.FromPluginAssembly(assembly); + + var manifestFilePath = Path.Combine(assemblyFileInfo.DirectoryName, "manifest.json"); + + File.WriteAllText(manifestFilePath, manifest.ToManifestFile()); + + Console.WriteLine("Disco Plugin: Manifest Created"); + + Console.WriteLine("Disco Plugin: Building Package"); + + var packageFileName = $"{manifest.Id}-{manifest.Version}.discoPlugin"; + var packageFilePath = Path.Combine(assemblyFileInfo.DirectoryName, packageFileName); + + // Delete Existing Package Files + foreach (var existingPackages in assemblyFileInfo.Directory.EnumerateFiles($"{manifest.Id}*.discoPlugin")) + { + existingPackages.Delete(); + } + + // Exclude Disco Provided Assemblies + List excludedFiles = PluginManifest.PluginExcludedAssemblies.ToList(); + + // Exclude the Package File + excludedFiles.Add(packageFileName); + + using (FileStream packageStream = new FileStream(packageFilePath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None)) + { + using (ZipArchive package = new ZipArchive(packageStream, ZipArchiveMode.Create)) + { + BuildZipPackage(package, string.Empty, assemblyFileInfo.Directory, excludedFiles); + } + } + + Console.WriteLine($"Disco Plugin: Package Build: '{packageFileName}'"); + + } + + static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) + { + Console.WriteLine("CurrentDomain_AssemblyResolve: {0} - {1}", args.Name, args.RequestingAssembly.FullName); + + foreach (var loadedAssembly in AppDomain.CurrentDomain.GetAssemblies()) + { + if (loadedAssembly.FullName == args.Name) + return loadedAssembly; + } + + return null; + } + + static void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args) + { + Console.WriteLine("CurrentDomain_AssemblyLoad: {0} - {1}", args.LoadedAssembly.FullName, args.LoadedAssembly.Location); + } + + static void BuildZipPackage(ZipArchive package, string relativePath, DirectoryInfo directory, List excludedFiles) + { + foreach (var subDirectory in directory.EnumerateDirectories()) + { + BuildZipPackage(package, string.Concat(relativePath, subDirectory.Name, "\\"), subDirectory, excludedFiles); + } + + foreach (var file in directory.EnumerateFiles()) + { + if (!excludedFiles.Any(excludeRule => file.Name.StartsWith(excludeRule, StringComparison.OrdinalIgnoreCase))) + { + var archiveEntry = package.CreateEntry(string.Concat(relativePath, file.Name), CompressionLevel.Fastest); + + using (var archiveStream = archiveEntry.Open()) + { + using (var fileStream = file.OpenRead()) + { + fileStream.CopyTo(archiveStream); + } + } + } + } + } + } +} diff --git a/Disco.Services.Plugins.ManifestGenerator/Properties/AssemblyInfo.cs b/Disco.Services.Plugins.ManifestGenerator/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..b76839b9 --- /dev/null +++ b/Disco.Services.Plugins.ManifestGenerator/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Disco ICT - Plugin Manifest Generator")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("https://discoict.com.au")] +[assembly: AssemblyProduct("Disco ICT")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("35e90902-d5a6-4c14-ba6b-2df976e4b96a")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("2.0.16272.1003")] +[assembly: AssemblyFileVersion("2.0.16272.1003")] diff --git a/Disco.Services.Plugins.ManifestGenerator/packages.config b/Disco.Services.Plugins.ManifestGenerator/packages.config new file mode 100644 index 00000000..81d448fb --- /dev/null +++ b/Disco.Services.Plugins.ManifestGenerator/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Disco.Services/Attachments/AttachmentActionExtensions.cs b/Disco.Services/Attachments/AttachmentActionExtensions.cs index a21b15dc..1e9b766f 100644 --- a/Disco.Services/Attachments/AttachmentActionExtensions.cs +++ b/Disco.Services/Attachments/AttachmentActionExtensions.cs @@ -1,18 +1,95 @@ using Disco.Data.Repository; using Disco.Models.Repository; +using Disco.Services.Authorization; +using Disco.Services.Documents.ManagedGroups; +using Disco.Services.Users; using Exceptionless; using System; -using System.Collections.Generic; using System.Drawing; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Disco.Services { public static class AttachmentActionExtensions { + #region Delete + public static bool CanDelete(this DeviceAttachment da) + { + if (UserService.CurrentAuthorization.Has(Claims.Device.Actions.RemoveAnyAttachments)) + return true; + + if (UserService.CurrentAuthorization.Has(Claims.Device.Actions.RemoveOwnAttachments) + && da.TechUserId.Equals(UserService.CurrentUserId, StringComparison.OrdinalIgnoreCase)) + return true; + + return false; + } + public static void OnDelete(this DeviceAttachment da, DiscoDataContext Database) + { + if (!da.CanDelete()) + throw new InvalidOperationException("Deletion of Attachment is Denied"); + + var attachmentId = da.Id; + var documentTemplateId = da.DocumentTemplateId; + var deviceSerialNumber = da.DeviceSerialNumber; + + da.RepositoryDelete(Database); + Database.DeviceAttachments.Remove(da); + + DocumentTemplateManagedGroups.TriggerDeviceAttachmentDeleted(Database, attachmentId, documentTemplateId, deviceSerialNumber); + } + public static bool CanDelete(this JobAttachment ja) + { + if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.RemoveAnyAttachments)) + return true; + + if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.RemoveOwnAttachments) + && ja.TechUserId.Equals(UserService.CurrentUserId, StringComparison.OrdinalIgnoreCase)) + return true; + + return false; + } + public static void OnDelete(this JobAttachment ja, DiscoDataContext Database) + { + if (!ja.CanDelete()) + throw new InvalidOperationException("Deletion of Attachment is Denied"); + + var attachmentId = ja.Id; + var documentTemplateId = ja.DocumentTemplateId; + var jobId = ja.JobId; + + ja.RepositoryDelete(Database); + Database.JobAttachments.Remove(ja); + + DocumentTemplateManagedGroups.TriggerJobAttachmentDeleted(Database, attachmentId, documentTemplateId, jobId); + } + public static bool CanDelete(this UserAttachment ua) + { + if (UserService.CurrentAuthorization.Has(Claims.User.Actions.RemoveAnyAttachments)) + return true; + + if (UserService.CurrentAuthorization.Has(Claims.User.Actions.RemoveOwnAttachments) + && ua.TechUserId.Equals(UserService.CurrentUserId, StringComparison.OrdinalIgnoreCase)) + return true; + + return false; + } + public static void OnDelete(this UserAttachment ua, DiscoDataContext Database) + { + if (!ua.CanDelete()) + throw new InvalidOperationException("Deletion of Attachment is Denied"); + + var attachmentId = ua.Id; + var documentTemplateId = ua.DocumentTemplateId; + var userId = ua.UserId; + + ua.RepositoryDelete(Database); + Database.UserAttachments.Remove(ua); + + DocumentTemplateManagedGroups.TriggerUserAttachmentDeleted(Database, attachmentId, documentTemplateId, userId); + } + #endregion + public static DeviceAttachment CreateAttachment(this Device Device, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, Image PdfThumbnail = null) { if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.OrdinalIgnoreCase)) @@ -149,8 +226,8 @@ namespace Disco.Services { using (Image sourceImage = Image.FromStream(Source)) { - Thumbnail = sourceImage.ResizeImage(48, 48); - using (Image mimeTypeIcon = Disco.Services.Properties.Resources.MimeType_img16) + Thumbnail = sourceImage.ResizeImage(48, 48, Brushes.Black); + using (Image mimeTypeIcon = Properties.Resources.MimeType_img16) { Thumbnail.EmbedIconOverlay(mimeTypeIcon); } @@ -177,8 +254,15 @@ namespace Disco.Services var pageSize = pdfiumDocument.PageSizes[0]; var size = ImagingExtensions.CalculateResize((int)pageSize.Width, (int)pageSize.Height, 48, 48); - Thumbnail = pdfiumDocument.Render(0, (int)size.Width, (int)size.Height, 72, 72, true); - return true; + using (var sourceImage = pdfiumDocument.Render(0, (int)size.Width, (int)size.Height, 72, 72, true)) + { + Thumbnail = sourceImage.ResizeImage(48, 48, Brushes.White); + using (Image mimeTypeIcon = Properties.Resources.MimeType_pdf16) + { + Thumbnail.EmbedIconOverlay(mimeTypeIcon); + } + return true; + } } } } diff --git a/Disco.BI/BI/Extensions/AuthorizationRoleExtensions.cs b/Disco.Services/Authorization/AuthorizationRoleExtensions.cs similarity index 78% rename from Disco.BI/BI/Extensions/AuthorizationRoleExtensions.cs rename to Disco.Services/Authorization/AuthorizationRoleExtensions.cs index 401e36e9..91102f3e 100644 --- a/Disco.BI/BI/Extensions/AuthorizationRoleExtensions.cs +++ b/Disco.Services/Authorization/AuthorizationRoleExtensions.cs @@ -1,21 +1,16 @@ using Disco.Data.Repository; -using Disco.Models.Services.Authorization; using Disco.Models.Repository; +using Disco.Models.Services.Authorization; using Disco.Services.Users; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -namespace Disco.BI.Extensions +namespace Disco.Services { public static class AuthorizationRoleExtensions { public static void Delete(this IRoleToken roleToken, DiscoDataContext Database) { - var role = Database.AuthorizationRoles.Find(roleToken.Role.Id); + var role = Database.AuthorizationRoles.Find(roleToken.Role.Id); UserService.DeleteAuthorizationRole(Database, roleToken.Role); } diff --git a/Disco.BI/BI/Extensions/ClientServicesExtensions.cs b/Disco.Services/ClientServices/ClientServicesExtensions.cs similarity index 71% rename from Disco.BI/BI/Extensions/ClientServicesExtensions.cs rename to Disco.Services/ClientServices/ClientServicesExtensions.cs index 88f3a376..0b035a6a 100644 --- a/Disco.BI/BI/Extensions/ClientServicesExtensions.cs +++ b/Disco.Services/ClientServices/ClientServicesExtensions.cs @@ -1,14 +1,16 @@ using Disco.Data.Repository; using Disco.Models.ClientServices; using Disco.Services.Authorization; +using Disco.Services.Devices.Enrolment; using Disco.Services.Users; using System; using System.Web; -namespace Disco.BI.Extensions +namespace Disco.Services { public static class ClientServicesExtensions { + public static EnrolResponse BuildResponse(this Enrol request) { if (HttpContext.Current == null) @@ -20,7 +22,7 @@ namespace Disco.BI.Extensions using (DiscoDataContext database = new DiscoDataContext()) { - EnrolResponse response = DeviceBI.DeviceEnrol.Enrol(database, username, request); + EnrolResponse response = DeviceEnrolment.Enrol(database, username, request); database.SaveChanges(); return response; } @@ -59,24 +61,7 @@ namespace Disco.BI.Extensions using (DiscoDataContext database = new DiscoDataContext()) { - MacEnrolResponse response = DeviceBI.DeviceEnrol.MacEnrol(database, request, false); - database.SaveChanges(); - return response; - } - } - - public static RegisterResponse BuildResponse(this Register request) - { - if (HttpContext.Current == null) - throw new PlatformNotSupportedException("This function can only be accessed from within ASP.NET"); - - string username = null; - if (HttpContext.Current.Request.IsAuthenticated) - username = HttpContext.Current.User.Identity.Name; - - using (DiscoDataContext database = new DiscoDataContext()) - { - RegisterResponse response = DeviceBI.DeviceEnrol.Register(database, username, request); + MacEnrolResponse response = DeviceEnrolment.MacEnrol(database, request, false); database.SaveChanges(); return response; } diff --git a/Disco.BI/BI/Extensions/DeviceActionExtensions.cs b/Disco.Services/Devices/DeviceActionExtensions.cs similarity index 99% rename from Disco.BI/BI/Extensions/DeviceActionExtensions.cs rename to Disco.Services/Devices/DeviceActionExtensions.cs index 56bc8624..59f5f2bb 100644 --- a/Disco.BI/BI/Extensions/DeviceActionExtensions.cs +++ b/Disco.Services/Devices/DeviceActionExtensions.cs @@ -1,16 +1,16 @@ using Disco.Data.Repository; using Disco.Models.Repository; -using Disco.Services; using Disco.Services.Authorization; using Disco.Services.Interop.ActiveDirectory; using Disco.Services.Users; using System; using System.Linq; -namespace Disco.BI.Extensions +namespace Disco.Services { public static class DeviceActionExtensions { + public static bool IsDecommissioned(this Device d) { return d.DecommissionedDate.HasValue; @@ -187,5 +187,6 @@ namespace Disco.BI.Extensions Database.Devices.Remove(d); } #endregion + } } diff --git a/Disco.BI/BI/Extensions/DeviceBatchExtensions.cs b/Disco.Services/Devices/DeviceBatchExtensions.cs similarity index 97% rename from Disco.BI/BI/Extensions/DeviceBatchExtensions.cs rename to Disco.Services/Devices/DeviceBatchExtensions.cs index 7634b28c..a09c4c19 100644 --- a/Disco.BI/BI/Extensions/DeviceBatchExtensions.cs +++ b/Disco.Services/Devices/DeviceBatchExtensions.cs @@ -7,7 +7,7 @@ using Disco.Services.Users; using System; using System.Linq; -namespace Disco.BI.Extensions +namespace Disco.Services { public static class DeviceBatchExtensions { diff --git a/Disco.BI/BI/DeviceBI/BatchUtilities.cs b/Disco.Services/Devices/DeviceBatches.cs similarity index 58% rename from Disco.BI/BI/DeviceBI/BatchUtilities.cs rename to Disco.Services/Devices/DeviceBatches.cs index ca6a630a..e1cfaab9 100644 --- a/Disco.BI/BI/DeviceBI/BatchUtilities.cs +++ b/Disco.Services/Devices/DeviceBatches.cs @@ -1,14 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using Disco.Data.Repository; using Disco.Models.Repository; -using Disco.Data.Repository; +using System; -namespace Disco.BI.DeviceBI +namespace Disco.Services.Devices { - public static class BatchUtilities + public static class DeviceBatches { + public static DeviceBatch DefaultNewDeviceBatch(DiscoDataContext Database) { return new DeviceBatch() diff --git a/Disco.Services/Devices/DeviceCertificateExtensions.cs b/Disco.Services/Devices/DeviceCertificateExtensions.cs new file mode 100644 index 00000000..743be2f3 --- /dev/null +++ b/Disco.Services/Devices/DeviceCertificateExtensions.cs @@ -0,0 +1,116 @@ +using Disco.Data.Repository; +using Disco.Models.ClientServices; +using Disco.Models.ClientServices.EnrolmentInformation; +using Disco.Models.Repository; +using Disco.Services.Plugins.Features.CertificateAuthorityProvider; +using Disco.Services.Plugins.Features.CertificateProvider; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.X509Certificates; + +namespace Disco.Services +{ + public static class DeviceCertificateExtensions + { + public static CertificateStore ProvisionCertificates(this Device device, DiscoDataContext Database, Enrol Enrolment, out List ProvisionedCertificates) + { + var personalCertificates = new List(); + var personalCertificatesRemove = new List(); + + var intermediateCertificates = new List(); + var intermediateCertificatesRemove = new List(); + + var trustedRootCertificates = new List(); + var trustedRootCertificatesRemove = new List(); + + ProvisionedCertificates = new List(); + + foreach (var pluginFeature in device.DeviceProfile.GetCertificateProviders()) + { + using (var providerFeature = pluginFeature.CreateInstance()) + { + var personalResult = providerFeature.ProvisionPersonalCertificate(Database, device, Enrolment); + + if (personalResult != null) + { + if (personalResult.AllocatedCertificates != null && personalResult.AllocatedCertificates.Count > 0) + { + // Avoid transporting certificates if they are already installed + foreach (var certificate in personalResult.AllocatedCertificates) + { + var x509Certificate = new X509Certificate2(certificate.Content, "password"); + if (!Enrolment.Certificates.Any(c => c.Thumbprint.Equals(x509Certificate.Thumbprint, StringComparison.OrdinalIgnoreCase))) + { + personalCertificates.Add(certificate.Content); + ProvisionedCertificates.Add(certificate); + } + } + } + if (personalResult.RemoveCertificateThumbprints != null && personalResult.RemoveCertificateThumbprints.Count > 0) + { + personalCertificatesRemove.AddRange(personalResult.RemoveCertificateThumbprints); + } + } + } + } + + foreach (var pluginFeature in device.DeviceProfile.GetCertificateAuthorityProviders()) + { + using (var providerFeature = pluginFeature.CreateInstance()) + { + var caResult = providerFeature.ProvisionAuthorityCertificates(Database, device, Enrolment); + + if (caResult.TrustedRootCertificates != null && caResult.TrustedRootCertificates.Count > 0) + { + trustedRootCertificates.AddRange(caResult.TrustedRootCertificates); + } + if (caResult.TrustedRootCertificateRemoveThumbprints != null && caResult.TrustedRootCertificateRemoveThumbprints.Count > 0) + { + trustedRootCertificatesRemove.AddRange(caResult.TrustedRootCertificateRemoveThumbprints); + } + if (caResult.IntermediateCertificates != null && caResult.IntermediateCertificates.Count > 0) + { + intermediateCertificates.AddRange(caResult.IntermediateCertificates); + } + if (caResult.IntermediateCertificateRemoveThumbprints != null && caResult.IntermediateCertificateRemoveThumbprints.Count > 0) + { + intermediateCertificatesRemove.AddRange(caResult.IntermediateCertificateRemoveThumbprints); + } + } + } + + if (personalCertificates.Count == 0 && personalCertificatesRemove.Count == 0 && + intermediateCertificates.Count == 0 && intermediateCertificatesRemove.Count == 0 && + trustedRootCertificates.Count == 0 && trustedRootCertificatesRemove.Count == 0) + { + return null; + } + else + { + return new CertificateStore() + { + TrustedRootCertificates = trustedRootCertificates.Count > 0 ? trustedRootCertificates : null, + TrustedRootRemoveThumbprints = trustedRootCertificatesRemove.Count > 0 ? trustedRootCertificatesRemove : null, + + IntermediateCertificates = intermediateCertificates.Count > 0 ? intermediateCertificates : null, + IntermediateRemoveThumbprints = intermediateCertificatesRemove.Count > 0 ? intermediateCertificatesRemove : null, + + PersonalCertificates = personalCertificates.Count > 0 ? personalCertificates : null, + PersonalRemoveThumbprints = personalCertificatesRemove.Count > 0 ? personalCertificatesRemove : null + }; + } + } + + public static DateTime? CertificateExpirationDate(this DeviceCertificate wc) + { + if (wc.Content == null || wc.Content.Length == 0) + { + return null; + } + var c = new X509Certificate2(wc.Content, "password"); + return c.NotAfter; + } + + } +} diff --git a/Disco.BI/BI/Extensions/DeviceDetailExtensions.cs b/Disco.Services/Devices/DeviceDetailExtensions.cs similarity index 98% rename from Disco.BI/BI/Extensions/DeviceDetailExtensions.cs rename to Disco.Services/Devices/DeviceDetailExtensions.cs index cce2a4de..a123bb25 100644 --- a/Disco.BI/BI/Extensions/DeviceDetailExtensions.cs +++ b/Disco.Services/Devices/DeviceDetailExtensions.cs @@ -2,11 +2,8 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; -namespace Disco.BI.Extensions +namespace Disco.Services { public static class DeviceDetailExtensions { diff --git a/Disco.BI/BI/Extensions/DeviceExtensions.cs b/Disco.Services/Devices/DeviceExtensions.cs similarity index 98% rename from Disco.BI/BI/Extensions/DeviceExtensions.cs rename to Disco.Services/Devices/DeviceExtensions.cs index 5ae41af8..40b25a86 100644 --- a/Disco.BI/BI/Extensions/DeviceExtensions.cs +++ b/Disco.Services/Devices/DeviceExtensions.cs @@ -1,22 +1,21 @@ -using Disco.Data.Repository; +using Disco.Data.Repository; using Disco.Models.Repository; using Disco.Models.Services.Documents; -using Disco.Services; using Disco.Services.Authorization; using Disco.Services.Expressions; using Disco.Services.Interop.ActiveDirectory; using Disco.Services.Users; using Exceptionless; using System; -using System.Collections; using System.Collections.Generic; using System.Linq; +using System.Text; +using System.Threading.Tasks; -namespace Disco.BI.Extensions +namespace Disco.Services { public static class DeviceExtensions { - public static string ComputerNameRender(this Device device, DiscoDataContext Database, ADDomain Domain) { if (Domain == null) diff --git a/Disco.BI/BI/DeviceBI/DeviceModelBI.cs b/Disco.Services/Devices/DeviceModelExtensions.cs similarity index 59% rename from Disco.BI/BI/DeviceBI/DeviceModelBI.cs rename to Disco.Services/Devices/DeviceModelExtensions.cs index 8c95458e..e12b9094 100644 --- a/Disco.BI/BI/DeviceBI/DeviceModelBI.cs +++ b/Disco.Services/Devices/DeviceModelExtensions.cs @@ -1,22 +1,53 @@ -using System; -using System.Collections.Generic; -using System.Data.Entity; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Disco.Data.Repository; +using Disco.Data.Repository; using Disco.Models.Repository; +using Disco.Services.Authorization; +using Disco.Services.Users; +using System; +using System.Data.Entity; +using System.IO; +using System.Linq; -namespace Disco.BI +namespace Disco.Services { - public static class DeviceModelBI + public static class DeviceModelExtensions { - - // Added: 2013-02-07 G# - // Ensure Duplicate Device Models are not created by creating only one Device Model at a time - // http://www.discoict.com.au/forum/support/2013/2/duplicate-device-models.aspx - // Thanks to Michael Vorster for reporting this problem. private static object _CreateDeviceModelLock = new object(); + + public static bool CanDelete(this DeviceModel dm, DiscoDataContext Database) + { + if (!UserService.CurrentAuthorization.Has(Claims.Config.DeviceModel.Delete)) + return false; + + // Can't Delete Default Model (Id: 1) + if (dm.Id == 1) + return false; + + // Can't Delete if Contains Devices + if (Database.Devices.Count(d => d.DeviceModelId == dm.Id) > 0) + return false; + + return true; + } + public static void Delete(this DeviceModel dm, DiscoDataContext Database) + { + if (!dm.CanDelete(Database)) + throw new InvalidOperationException("The state of this Device Model doesn't allow it to be deleted"); + + // Delete Image + var deviceModelImagePath = dm.ImageFilePath(); + if (File.Exists(deviceModelImagePath)) + File.Delete(deviceModelImagePath); + + // Delete any Device Model Components + foreach (var deviceModelComponent in Database.DeviceComponents.Where(dc => dc.DeviceModelId == dm.Id).ToList()) + { + Database.DeviceComponents.Remove(deviceModelComponent); + } + + // Delete Model + Database.DeviceModels.Remove(dm); + } + public static Tuple GetOrCreateDeviceModel(this DbSet DeviceModelsSet, string Manufacturer, string Model, string ModelType) { // Already Exists? @@ -58,9 +89,8 @@ namespace Disco.BI deviceModel.ModelType = ModelType; } - return new Tuple(deviceModel, false); + return new Tuple(deviceModel, false); } - // Added: 2013-02-07 G# } } diff --git a/Disco.BI/BI/Extensions/DeviceProfileExtensions.cs b/Disco.Services/Devices/DeviceProfileExtensions.cs similarity index 53% rename from Disco.BI/BI/Extensions/DeviceProfileExtensions.cs rename to Disco.Services/Devices/DeviceProfileExtensions.cs index b89844f8..714a666c 100644 --- a/Disco.BI/BI/Extensions/DeviceProfileExtensions.cs +++ b/Disco.Services/Devices/DeviceProfileExtensions.cs @@ -5,11 +5,16 @@ using Disco.Services.Authorization; using Disco.Services.Devices.ManagedGroups; using Disco.Services.Expressions; using Disco.Services.Interop.ActiveDirectory; +using Disco.Services.Plugins; +using Disco.Services.Plugins.Features.CertificateAuthorityProvider; +using Disco.Services.Plugins.Features.CertificateProvider; +using Disco.Services.Plugins.Features.WirelessProfileProvider; using Disco.Services.Users; using System; +using System.Collections.Generic; using System.Linq; -namespace Disco.BI.Extensions +namespace Disco.Services { public static class DeviceProfileExtensions { @@ -65,6 +70,50 @@ namespace Disco.BI.Extensions // Delete Profile Database.DeviceProfiles.Remove(dp); } + + public static IEnumerable GetCertificateProviders(this DeviceProfile dp) + { + if (!string.IsNullOrEmpty(dp.CertificateProviders)) + { + foreach (var certificateProviderId in dp.CertificateProviders.Split(',')) + { + PluginFeatureManifest featureManifest = null; + if (Plugins.Plugins.TryGetPluginFeature(certificateProviderId.Trim(), typeof(CertificateProviderFeature), out featureManifest)) + { + yield return featureManifest; + } + } + } + } + public static IEnumerable GetCertificateAuthorityProviders(this DeviceProfile dp) + { + if (!string.IsNullOrEmpty(dp.CertificateAuthorityProviders)) + { + foreach (var certificateAuthorityProviderId in dp.CertificateAuthorityProviders.Split(',')) + { + PluginFeatureManifest featureManifest = null; + if (Plugins.Plugins.TryGetPluginFeature(certificateAuthorityProviderId.Trim(), typeof(CertificateAuthorityProviderFeature), out featureManifest)) + { + yield return featureManifest; + } + } + } + } + + public static IEnumerable GetWirelessProfileProviders(this DeviceProfile dp) + { + if (!string.IsNullOrEmpty(dp.WirelessProfileProviders)) + { + foreach (var wirelessProfileProviderId in dp.WirelessProfileProviders.Split(',')) + { + PluginFeatureManifest featureManifest = null; + if (Plugins.Plugins.TryGetPluginFeature(wirelessProfileProviderId.Trim(), typeof(WirelessProfileProviderFeature), out featureManifest)) + { + yield return featureManifest; + } + } + } + } } } diff --git a/Disco.Services/Devices/DeviceUpdatesHub.cs b/Disco.Services/Devices/DeviceUpdatesHub.cs index 3a487262..fccba73c 100644 --- a/Disco.Services/Devices/DeviceUpdatesHub.cs +++ b/Disco.Services/Devices/DeviceUpdatesHub.cs @@ -1,16 +1,14 @@ -using Disco.Data.Repository.Monitor; +using Disco.Data.Repository; +using Disco.Data.Repository.Monitor; +using Disco.Models.Repository; using Disco.Services.Authorization; using Disco.Services.Web.Signalling; using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Hubs; using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Reactive.Linq; -using Disco.Models.Repository; -using Disco.Data.Repository; +using System.Threading.Tasks; namespace Disco.Services.Devices { diff --git a/Disco.Services/Devices/DeviceWirelessProfileExtensions.cs b/Disco.Services/Devices/DeviceWirelessProfileExtensions.cs new file mode 100644 index 00000000..84e138a3 --- /dev/null +++ b/Disco.Services/Devices/DeviceWirelessProfileExtensions.cs @@ -0,0 +1,67 @@ +using Disco.Data.Repository; +using Disco.Models.ClientServices; +using Disco.Models.ClientServices.EnrolmentInformation; +using Disco.Models.Repository; +using Disco.Services.Plugins.Features.WirelessProfileProvider; +using System.Collections.Generic; +using System.Linq; + +namespace Disco.Services +{ + public static class DeviceWirelessProfileExtensions + { + + public static WirelessProfileStore ProvisionWirelessProfiles(this Device device, DiscoDataContext Database, Enrol Enrolment) + { + var profiles = new List(); + var transformations = new List(); + var removeNames = new List(); + + foreach (var pluginFeature in device.DeviceProfile.GetWirelessProfileProviders()) + { + using (var providerFeature = pluginFeature.CreateInstance()) + { + var pluginResult = providerFeature.ProvisionWirelessProfiles(Database, device, Enrolment); + + if (pluginResult.Profiles != null) + { + profiles.AddRange(pluginResult.Profiles.Select(p => new Models.ClientServices.EnrolmentInformation.WirelessProfile() + { + Name = p.Name, + ProfileXml = p.ProfileXml, + ForceDeployment = p.ForceDeployment + })); + } + if (pluginResult.Transformations != null) + { + transformations.AddRange(pluginResult.Transformations.Select(p => new Models.ClientServices.EnrolmentInformation.WirelessProfileTransformation() + { + Name = p.Name, + RegularExpression = p.RegularExpression, + RegularExpressionReplacement = p.RegularExpressionReplacement + })); + } + if (pluginResult.RemoveNames != null) + { + removeNames.AddRange(pluginResult.RemoveNames); + } + } + } + + if (profiles.Count == 0 && transformations.Count == 0 && removeNames.Count == 0) + { + return null; + } + else + { + return new WirelessProfileStore() + { + Profiles = profiles.Count > 0 ? profiles : null, + Transformations = transformations.Count > 0 ? transformations : null, + RemoveNames = removeNames.Count > 0 ? removeNames : null + }; + } + } + + } +} diff --git a/Disco.BI/BI/DeviceBI/Enrol.cs b/Disco.Services/Devices/Enrolment/DeviceEnrolment.cs similarity index 62% rename from Disco.BI/BI/DeviceBI/Enrol.cs rename to Disco.Services/Devices/Enrolment/DeviceEnrolment.cs index 35f2b48b..fdd6450f 100644 --- a/Disco.BI/BI/DeviceBI/Enrol.cs +++ b/Disco.Services/Devices/Enrolment/DeviceEnrolment.cs @@ -1,32 +1,25 @@ -using Disco.BI.Extensions; -using Disco.Data.Repository; +using Disco.Data.Repository; using Disco.Models.ClientServices; using Disco.Models.Repository; using Disco.Services.Authorization; using Disco.Services.Interop.ActiveDirectory; using Disco.Services.Users; using Exceptionless; +using PList; +using Renci.SshNet; using System; using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; -using Renci.SshNet; -using PList; using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; using System.Xml; using System.Xml.Serialization; -namespace Disco.BI.DeviceBI +namespace Disco.Services.Devices.Enrolment { - public class DeviceEnrol + public static class DeviceEnrolment { - public enum EnrolmentTypes - { - Normal, - Mac = 5, - MacSecure, - Register = 30 - } public static MacSecureEnrolResponse MacSecureEnrol(DiscoDataContext Database, string Host) { @@ -204,9 +197,9 @@ namespace Disco.BI.DeviceBI if (!Trusted) { if (RepoDevice == null) - throw new EnrolSafeException(string.Format("Unknown Device Serial Number (SN: '{0}')", Request.DeviceSerialNumber)); + throw new EnrolmentSafeException(string.Format("Unknown Device Serial Number (SN: '{0}')", Request.DeviceSerialNumber)); if (!RepoDevice.AllowUnauthenticatedEnrol) - throw new EnrolSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.DeviceSerialNumber)); + throw new EnrolmentSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.DeviceSerialNumber)); } if (RepoDevice == null) { @@ -271,7 +264,7 @@ namespace Disco.BI.DeviceBI response.DeviceComputerName = RepoDevice.DeviceDomainId; EnrolmentLog.LogSessionProgress(sessionId, 100, "Completed Successfully"); } - catch (EnrolSafeException ex) + catch (EnrolmentSafeException ex) { EnrolmentLog.LogSessionError(sessionId, ex); return new MacEnrolResponse { ErrorMessage = ex.Message }; @@ -289,7 +282,7 @@ namespace Disco.BI.DeviceBI } return response; } - public static EnrolResponse Enrol(DiscoDataContext Database, string Username, Models.ClientServices.Enrol Request) + public static EnrolResponse Enrol(DiscoDataContext Database, string Username, Enrol Request) { ADMachineAccount adMachineAccount = null; @@ -309,7 +302,7 @@ namespace Disco.BI.DeviceBI string sessionId = System.Guid.NewGuid().ToString("B"); response.SessionId = sessionId; - EnrolmentLog.LogSessionStarting(sessionId, Request.DeviceSerialNumber, EnrolmentTypes.Normal); + EnrolmentLog.LogSessionStarting(sessionId, Request.SerialNumber, EnrolmentTypes.Normal); EnrolmentLog.LogSessionDeviceInfo(sessionId, Request); try @@ -322,27 +315,27 @@ namespace Disco.BI.DeviceBI } EnrolmentLog.LogSessionProgress(sessionId, 13, "Loading Device Data"); - Device RepoDevice = Database.Devices.Include("AssignedUser").Include("DeviceModel").Include("DeviceProfile").Where(d => d.SerialNumber == Request.DeviceSerialNumber).FirstOrDefault(); + Device RepoDevice = Database.Devices.Include("AssignedUser").Include("DeviceModel").Include("DeviceProfile").Where(d => d.SerialNumber == Request.SerialNumber).FirstOrDefault(); EnrolmentLog.LogSessionProgress(sessionId, 15, "Discovering User/Device Disco Permissions"); if (isAuthenticated) { if (!authenticatedToken.Has(Claims.Device.Actions.EnrolDevices)) { if (!authenticatedToken.Has(Claims.ComputerAccount)) - throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.UserId)); + throw new EnrolmentSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.SerialNumber, authenticatedToken.User.UserId)); if (domain == null) - domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName); + domain = ActiveDirectory.Context.GetDomainByName(Request.DNSDomainName); - if (!authenticatedToken.User.UserId.Equals(string.Format(@"{0}\{1}$", domain.NetBiosName, Request.DeviceComputerName), System.StringComparison.OrdinalIgnoreCase)) - throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.UserId)); + if (!authenticatedToken.User.UserId.Equals(string.Format(@"{0}\{1}$", domain.NetBiosName, Request.ComputerName), System.StringComparison.OrdinalIgnoreCase)) + throw new EnrolmentSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.SerialNumber, authenticatedToken.User.UserId)); } } else { if (RepoDevice == null) { - throw new EnrolSafeException(string.Format("Unknown Device Serial Number (SN: '{0}')", Request.DeviceSerialNumber)); + throw new EnrolmentSafeException(string.Format("Unknown Device Serial Number (SN: '{0}')", Request.SerialNumber)); } if (!RepoDevice.AllowUnauthenticatedEnrol) { @@ -350,53 +343,56 @@ namespace Disco.BI.DeviceBI { if (Database.Jobs.Count(j => j.DeviceSerialNumber == RepoDevice.SerialNumber && j.JobTypeId == JobType.JobTypeIds.SImg && !j.ClosedDate.HasValue) == 0) { - throw new EnrolSafeException(string.Format("Device has no open 'Software - Reimage' job (SN: '{0}')", Request.DeviceSerialNumber)); + throw new EnrolmentSafeException(string.Format("Device has no open 'Software - Reimage' job (SN: '{0}')", Request.SerialNumber)); } } else { - throw new EnrolSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.DeviceSerialNumber)); + throw new EnrolmentSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.SerialNumber)); } } } - if (Request.DeviceIsPartOfDomain && !string.IsNullOrWhiteSpace(Request.DeviceComputerName)) + if (Request.IsPartOfDomain && !string.IsNullOrWhiteSpace(Request.ComputerName)) { EnrolmentLog.LogSessionProgress(sessionId, 20, "Loading Active Directory Computer Account"); System.Guid? uuidGuid = null; System.Guid? macAddressGuid = null; - if (!string.IsNullOrEmpty(Request.DeviceUUID)) - uuidGuid = ADMachineAccount.NetbootGUIDFromUUID(Request.DeviceUUID); - if (!string.IsNullOrEmpty(Request.DeviceLanMacAddress)) - macAddressGuid = ADMachineAccount.NetbootGUIDFromMACAddress(Request.DeviceLanMacAddress); + if (!string.IsNullOrEmpty(Request.Hardware.UUID)) + uuidGuid = ADMachineAccount.NetbootGUIDFromUUID(Request.Hardware.UUID); + + // 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(); + if (!string.IsNullOrEmpty(macAddress)) + macAddressGuid = ADMachineAccount.NetbootGUIDFromMACAddress(macAddress); if (domain == null) - domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName); + domain = ActiveDirectory.Context.GetDomainByName(Request.DNSDomainName); - var requestDeviceId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.DeviceComputerName); + var requestDeviceId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.ComputerName); adMachineAccount = domainController.Value.RetrieveADMachineAccount(requestDeviceId, uuidGuid, macAddressGuid); } if (RepoDevice == null) { EnrolmentLog.LogSessionProgress(sessionId, 30, "New Device, Creating Disco Instance"); - EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.DeviceSerialNumber); + EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.SerialNumber); DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId); - var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim()); + var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.Hardware.Manufacturer.Trim(), Request.Hardware.Model.Trim(), Request.Hardware.ModelType.Trim()); DeviceModel deviceModel = deviceModelResult.Item1; if (deviceModelResult.Item2) - EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model); + EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.SerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model); else - EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id); + EnrolmentLog.LogSessionDevice(sessionId, Request.SerialNumber, deviceModel.Id); if (domain == null) - domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName); + domain = ActiveDirectory.Context.GetDomainByName(Request.DNSDomainName); RepoDevice = new Device { - SerialNumber = Request.DeviceSerialNumber, - DeviceDomainId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.DeviceComputerName), + SerialNumber = Request.SerialNumber, + DeviceDomainId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.ComputerName), DeviceProfile = deviceProfile, DeviceModel = deviceModel, AllowUnauthenticatedEnrol = false, @@ -407,29 +403,33 @@ namespace Disco.BI.DeviceBI }; Database.Devices.Add(RepoDevice); - if (!string.IsNullOrEmpty(Request.DeviceLanMacAddress)) - RepoDevice.DeviceDetails.LanMacAddress(RepoDevice, Request.DeviceLanMacAddress); - if (!string.IsNullOrEmpty(Request.DeviceWlanMacAddress)) - RepoDevice.DeviceDetails.WLanMacAddress(RepoDevice, Request.DeviceWlanMacAddress); + 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)) + RepoDevice.DeviceDetails.LanMacAddress(RepoDevice, lanMacAddresses); + if (!string.IsNullOrEmpty(wlanMacAddresses)) + RepoDevice.DeviceDetails.WLanMacAddress(RepoDevice, wlanMacAddresses); } else { EnrolmentLog.LogSessionProgress(sessionId, 30, "Existing Device, Updating Disco Instance"); - EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber); + EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.SerialNumber); - var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim()); + var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.Hardware.Manufacturer.Trim(), Request.Hardware.Model.Trim(), Request.Hardware.ModelType.Trim()); DeviceModel deviceModel = deviceModelResult.Item1; if (deviceModelResult.Item2) - EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model); + EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.SerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model); else - EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id); + EnrolmentLog.LogSessionDevice(sessionId, Request.SerialNumber, deviceModel.Id); RepoDevice.DeviceModel = deviceModel; - if (!string.IsNullOrEmpty(Request.DeviceLanMacAddress)) - RepoDevice.DeviceDetails.LanMacAddress(RepoDevice, Request.DeviceLanMacAddress); - if (!string.IsNullOrEmpty(Request.DeviceWlanMacAddress)) - RepoDevice.DeviceDetails.WLanMacAddress(RepoDevice, Request.DeviceWlanMacAddress); + 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)) + RepoDevice.DeviceDetails.LanMacAddress(RepoDevice, lanMacAddresses); + if (!string.IsNullOrEmpty(wlanMacAddresses)) + RepoDevice.DeviceDetails.WLanMacAddress(RepoDevice, wlanMacAddresses); if (!RepoDevice.EnrolledDate.HasValue) RepoDevice.EnrolledDate = DateTime.Now; @@ -454,7 +454,7 @@ namespace Disco.BI.DeviceBI EnrolmentLog.LogSessionTaskProvisioningADAccount(sessionId, RepoDevice.SerialNumber, RepoDevice.DeviceDomainId); adMachineAccount = domainController.Value.RetrieveADMachineAccount(RepoDevice.DeviceDomainId); - response.OfflineDomainJoin = domainController.Value.OfflineDomainJoinProvision(RepoDevice.DeviceDomainId, RepoDevice.DeviceProfile.OrganisationalUnit, ref adMachineAccount, out offlineProvisionDiagnosicInfo); + response.OfflineDomainJoinManifest = domainController.Value.OfflineDomainJoinProvision(RepoDevice.DeviceDomainId, RepoDevice.DeviceProfile.OrganisationalUnit, ref adMachineAccount, out offlineProvisionDiagnosicInfo); EnrolmentLog.LogSessionDiagnosticInformation(sessionId, offlineProvisionDiagnosicInfo); @@ -462,8 +462,8 @@ namespace Disco.BI.DeviceBI } if (adMachineAccount != null) { - response.DeviceComputerName = adMachineAccount.Name; - response.DeviceDomainName = adMachineAccount.Domain.NetBiosName; + response.ComputerName = adMachineAccount.Name; + response.DomainName = adMachineAccount.Domain.NetBiosName; } else if (ActiveDirectory.IsValidDomainAccountId(RepoDevice.DeviceDomainId)) { @@ -471,20 +471,20 @@ namespace Disco.BI.DeviceBI ADDomain accountDomain; ActiveDirectory.ParseDomainAccountId(RepoDevice.DeviceDomainId, out accountUsername, out accountDomain); - response.DeviceDomainName = accountDomain == null ? null : accountDomain.NetBiosName; - response.DeviceComputerName = accountUsername; + response.DomainName = accountDomain == null ? null : accountDomain.NetBiosName; + response.ComputerName = accountUsername; } else { - response.DeviceDomainName = Request.DeviceDNSDomainName; - response.DeviceComputerName = Request.DeviceComputerName; + response.DomainName = Request.DNSDomainName; + response.ComputerName = Request.ComputerName; } } else { RepoDevice.DeviceDomainId = adMachineAccount.Id.Trim('$'); - response.DeviceComputerName = adMachineAccount.Name; - response.DeviceDomainName = adMachineAccount.Domain.NetBiosName; + response.ComputerName = adMachineAccount.Name; + response.DomainName = adMachineAccount.Domain.NetBiosName; // Enforce Computer Name Convention if (!adMachineAccount.IsCriticalSystemObject && RepoDevice.DeviceProfile.EnforceComputerNameConvention) @@ -498,19 +498,19 @@ namespace Disco.BI.DeviceBI string calculatedAccountUsername; ActiveDirectory.ParseDomainAccountId(calculatedComputerName, out calculatedAccountUsername); - if (!Request.DeviceComputerName.Equals(calculatedAccountUsername, StringComparison.OrdinalIgnoreCase)) + if (!Request.ComputerName.Equals(calculatedAccountUsername, StringComparison.OrdinalIgnoreCase)) { - EnrolmentLog.LogSessionProgress(sessionId, 50, string.Format("Renaming Device: {0} -> {1}", Request.DeviceComputerName, calculatedComputerName)); - EnrolmentLog.LogSessionTaskRenamingDevice(sessionId, Request.DeviceComputerName, calculatedComputerName); + EnrolmentLog.LogSessionProgress(sessionId, 50, string.Format("Renaming Device: {0} -> {1}", Request.ComputerName, calculatedComputerName)); + EnrolmentLog.LogSessionTaskRenamingDevice(sessionId, Request.ComputerName, calculatedComputerName); RepoDevice.DeviceDomainId = calculatedComputerName; - response.DeviceDomainName = domain.NetBiosName; - response.DeviceComputerName = calculatedAccountUsername; + response.DomainName = domain.NetBiosName; + response.ComputerName = calculatedAccountUsername; // Create New Account string offlineProvisionDiagnosicInfo; - response.OfflineDomainJoin = domainController.Value.OfflineDomainJoinProvision(RepoDevice.DeviceDomainId, RepoDevice.DeviceProfile.OrganisationalUnit, ref adMachineAccount, out offlineProvisionDiagnosicInfo); + response.OfflineDomainJoinManifest = domainController.Value.OfflineDomainJoinProvision(RepoDevice.DeviceDomainId, RepoDevice.DeviceProfile.OrganisationalUnit, ref adMachineAccount, out offlineProvisionDiagnosicInfo); EnrolmentLog.LogSessionDiagnosticInformation(sessionId, offlineProvisionDiagnosicInfo); @@ -519,7 +519,7 @@ namespace Disco.BI.DeviceBI } // Enforce Organisational Unit - if (!adMachineAccount.IsCriticalSystemObject && response.OfflineDomainJoin == null && RepoDevice.DeviceProfile.EnforceOrganisationalUnit) + if (!adMachineAccount.IsCriticalSystemObject && response.OfflineDomainJoinManifest == null && RepoDevice.DeviceProfile.EnforceOrganisationalUnit) { var parentDistinguishedName = adMachineAccount.ParentDistinguishedName; if (string.IsNullOrWhiteSpace(RepoDevice.DeviceProfile.OrganisationalUnit)) @@ -547,7 +547,9 @@ namespace Disco.BI.DeviceBI if (adMachineAccount != null && !adMachineAccount.IsCriticalSystemObject) { EnrolmentLog.LogSessionProgress(sessionId, 75, "Updating Active Directory Computer Account Properties"); - adMachineAccount.UpdateNetbootGUID(Request.DeviceUUID, Request.DeviceLanMacAddress); + // 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); } @@ -563,44 +565,54 @@ namespace Disco.BI.DeviceBI ADUserAccount AssignedUserInfo = ActiveDirectory.RetrieveADUserAccount(RepoDevice.AssignedUser.UserId); EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.SamAccountName, AssignedUserInfo.Domain.NetBiosName, AssignedUserInfo.SecurityIdentifier.ToString()); response.AllowBootstrapperUninstall = true; - response.DeviceAssignedUserIsLocalAdmin = RepoDevice.DeviceProfile.AssignedUserLocalAdmin; - response.DeviceAssignedUserUsername = AssignedUserInfo.SamAccountName; - response.DeviceAssignedUserDomain = AssignedUserInfo.Domain.NetBiosName; - response.DeviceAssignedUserName = AssignedUserInfo.DisplayName; - response.DeviceAssignedUserSID = AssignedUserInfo.SecurityIdentifier.ToString(); + response.AssignedUserIsLocalAdmin = RepoDevice.DeviceProfile.AssignedUserLocalAdmin; + response.AssignedUserUsername = AssignedUserInfo.SamAccountName; + response.AssignedUserDomain = AssignedUserInfo.Domain.NetBiosName; + response.AssignedUserDescription = AssignedUserInfo.DisplayName; + response.AssignedUserSID = AssignedUserInfo.SecurityIdentifier.ToString(); } } else { response.AllowBootstrapperUninstall = true; } - if (!string.IsNullOrEmpty(Request.DeviceWlanMacAddress) && !string.IsNullOrEmpty(RepoDevice.DeviceProfile.CertificateProviderId)) - { - EnrolmentLog.LogSessionProgress(sessionId, 90, "Provisioning a Wireless Certificate"); - var allocationResult = RepoDevice.AllocateCertificate(Database); - var deviceCertificate = allocationResult.Item1; - if (deviceCertificate != null) + // Provision Certificates + if (!string.IsNullOrEmpty(RepoDevice.DeviceProfile.CertificateProviders) || + !string.IsNullOrEmpty(RepoDevice.DeviceProfile.CertificateAuthorityProviders)) + { + EnrolmentLog.LogSessionProgress(sessionId, 90, "Provisioning Certificates"); + + List provisionedCertificates; + var provisionResult = RepoDevice.ProvisionCertificates(Database, Request, out provisionedCertificates); + + if (provisionedCertificates != null && provisionedCertificates.Count > 0) { - bool certAlreadyInstalled = false; - if (Request.DeviceCertificates != null && Request.DeviceCertificates.Count > 0) + foreach (var deviceCertificate in provisionedCertificates) { - foreach (string existingCertName in Request.DeviceCertificates) - { - if (existingCertName.Contains(deviceCertificate.Name)) - { - certAlreadyInstalled = true; - break; - } - } - } - if (!certAlreadyInstalled) - { - EnrolmentLog.LogSessionTaskProvisioningWirelessCertificate(sessionId, RepoDevice.SerialNumber, deviceCertificate.Name); - response.DeviceCertificate = System.Convert.ToBase64String(deviceCertificate.Content); + EnrolmentLog.LogSessionTaskProvisioningCertificate(sessionId, RepoDevice.SerialNumber, deviceCertificate.Name); } } - response.DeviceCertificateRemoveExisting = allocationResult.Item2; + + response.Certificates = provisionResult; + } + + // Provision Wireless Profiles + if (!string.IsNullOrEmpty(RepoDevice.DeviceProfile.WirelessProfileProviders)) + { + EnrolmentLog.LogSessionProgress(sessionId, 95, "Provisioning Wireless Profiles"); + + var provisionResult = RepoDevice.ProvisionWirelessProfiles(Database, Request); + + if (provisionResult != null && provisionResult.Profiles != null) + { + foreach (var wirelessProfiles in provisionResult.Profiles) + { + EnrolmentLog.LogSessionTaskProvisioningCertificate(sessionId, RepoDevice.SerialNumber, wirelessProfiles.Name); + } + } + + response.WirelessProfiles = provisionResult; } // Reset 'AllowUnauthenticatedEnrol' @@ -609,7 +621,7 @@ namespace Disco.BI.DeviceBI EnrolmentLog.LogSessionProgress(sessionId, 100, "Completed Successfully"); } - catch (EnrolSafeException ex) + catch (EnrolmentSafeException ex) { EnrolmentLog.LogSessionError(sessionId, ex); return new EnrolResponse @@ -631,190 +643,5 @@ namespace Disco.BI.DeviceBI return response; } - public static RegisterResponse Register(DiscoDataContext Database, string Username, Register Request) - { - RegisterResponse response = new RegisterResponse(); - ADMachineAccount adMachineAccount = null; - AuthorizationToken authenticatedToken = null; - - ADDomain domain = null; - Lazy domainController = new Lazy(() => - { - if (domain == null) - throw new InvalidOperationException("The [domain] variable must be initialized first"); - return domain.GetAvailableDomainController(RequireWritable: true); - }); - - string sessionId = System.Guid.NewGuid().ToString("B"); - response.SessionId = sessionId; - - EnrolmentLog.LogSessionStarting(sessionId, Request.DeviceSerialNumber, EnrolmentTypes.Register); - EnrolmentLog.LogSessionDeviceInfo(sessionId, Request); - - try - { - EnrolmentLog.LogSessionProgress(sessionId, 10, "Loading User Data"); - if (!string.IsNullOrWhiteSpace(Username)) - { - authenticatedToken = UserService.GetAuthorization(Username, Database); - } - EnrolmentLog.LogSessionProgress(sessionId, 13, "Loading Device Data"); - - Device RepoDevice = Database.Devices.Include("AssignedUser").Include("DeviceModel").Include("DeviceProfile").Where(d => d.SerialNumber == Request.DeviceSerialNumber).FirstOrDefault(); - EnrolmentLog.LogSessionProgress(sessionId, 15, "Discovering User/Device Disco Permissions"); - if (authenticatedToken != null) - { - if (!authenticatedToken.Has(Claims.Device.Actions.EnrolDevices)) - { - if (!authenticatedToken.Has(Claims.ComputerAccount)) - throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.UserId)); - - if (domain == null) - domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName); - - if (!authenticatedToken.User.UserId.Equals(string.Format(@"{0}\{1}$", domain.NetBiosName, Request.DeviceComputerName), System.StringComparison.OrdinalIgnoreCase)) - throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.UserId)); - } - } - else - { - if (RepoDevice == null) - { - throw new EnrolSafeException(string.Format("Unknown Device Serial Number (SN: '{0}')", Request.DeviceSerialNumber)); - } - if (!RepoDevice.AllowUnauthenticatedEnrol) - { - if (RepoDevice.DeviceProfile.AllowUntrustedReimageJobEnrolment) - { - if (Database.Jobs.Count(j => j.DeviceSerialNumber == RepoDevice.SerialNumber && j.JobTypeId == JobType.JobTypeIds.SImg && !j.ClosedDate.HasValue) == 0) - { - throw new EnrolSafeException(string.Format("Device has no open 'Software - Reimage' job (SN: '{0}')", Request.DeviceSerialNumber)); - } - } - else - { - throw new EnrolSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.DeviceSerialNumber)); - } - } - } - if (Request.DeviceIsPartOfDomain && !string.IsNullOrWhiteSpace(Request.DeviceComputerName)) - { - EnrolmentLog.LogSessionProgress(sessionId, 20, "Loading Active Directory Computer Account"); - System.Guid? uuidGuid = null; - if (!string.IsNullOrEmpty(Request.DeviceUUID)) - uuidGuid = ADMachineAccount.NetbootGUIDFromUUID(Request.DeviceUUID); - - if (domain == null) - domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName); - - var requestDeviceId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.DeviceComputerName); - - adMachineAccount = domainController.Value.RetrieveADMachineAccount(requestDeviceId, uuidGuid); - } - if (RepoDevice == null) - { - EnrolmentLog.LogSessionProgress(sessionId, 30, "New Device, Creating Disco Instance"); - EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.DeviceSerialNumber); - DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId); - - var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim()); - DeviceModel deviceModel = deviceModelResult.Item1; - if (deviceModelResult.Item2) - EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model); - else - EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id); - - if (domain == null) - domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName); - - RepoDevice = new Device - { - SerialNumber = Request.DeviceSerialNumber, - DeviceDomainId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.DeviceComputerName), - DeviceProfile = deviceProfile, - DeviceModel = deviceModel, - AllowUnauthenticatedEnrol = false, - CreatedDate = DateTime.Now, - EnrolledDate = DateTime.Now, - LastEnrolDate = DateTime.Now, - DeviceDetails = new List() - }; - Database.Devices.Add(RepoDevice); - } - else - { - EnrolmentLog.LogSessionProgress(sessionId, 30, "Existing Device, Updating Disco Instance"); - EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber); - - var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim()); - DeviceModel deviceModel = deviceModelResult.Item1; - if (deviceModelResult.Item2) - EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model); - else - EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id); - - RepoDevice.DeviceModel = deviceModel; - - if (!RepoDevice.EnrolledDate.HasValue) - RepoDevice.EnrolledDate = DateTime.Now; - RepoDevice.LastEnrolDate = DateTime.Now; - } - - if (adMachineAccount == null) - { - if (adMachineAccount != null) - { - response.DeviceComputerName = adMachineAccount.Name; - response.DeviceDomainName = adMachineAccount.Domain.NetBiosName; - } - else if (ActiveDirectory.IsValidDomainAccountId(RepoDevice.DeviceDomainId)) - { - string accountUsername; - ADDomain accountDomain; - ActiveDirectory.ParseDomainAccountId(RepoDevice.DeviceDomainId, out accountUsername, out accountDomain); - - response.DeviceDomainName = accountDomain == null ? null : accountDomain.NetBiosName; - response.DeviceComputerName = accountUsername; - } - else - { - response.DeviceDomainName = Request.DeviceDNSDomainName; - response.DeviceComputerName = Request.DeviceComputerName; - } - } - else - { - RepoDevice.DeviceDomainId = adMachineAccount.Id.Trim('$'); - response.DeviceComputerName = adMachineAccount.Name; - response.DeviceDomainName = adMachineAccount.Domain.NetBiosName; - } - - // Reset 'AllowUnauthenticatedEnrol' - if (RepoDevice.AllowUnauthenticatedEnrol) - RepoDevice.AllowUnauthenticatedEnrol = false; - - EnrolmentLog.LogSessionProgress(sessionId, 100, "Completed Successfully"); - } - catch (EnrolSafeException ex) - { - EnrolmentLog.LogSessionError(sessionId, ex); - return new RegisterResponse - { - SessionId = sessionId, - ErrorMessage = ex.Message - }; - } - catch (System.Exception ex2) - { - ex2.ToExceptionless().Submit(); - EnrolmentLog.LogSessionError(sessionId, ex2); - throw ex2; - } - finally - { - EnrolmentLog.LogSessionFinished(sessionId); - } - return response; - } } -} \ No newline at end of file +} diff --git a/Disco.Services/Devices/Enrolment/EnrolmentLog.cs b/Disco.Services/Devices/Enrolment/EnrolmentLog.cs new file mode 100644 index 00000000..bf11ff44 --- /dev/null +++ b/Disco.Services/Devices/Enrolment/EnrolmentLog.cs @@ -0,0 +1,503 @@ +using Disco.Models.ClientServices; +using Disco.Services.Logging; +using Disco.Services.Logging.Models; +using System.Collections.Generic; + +namespace Disco.Services.Devices.Enrolment +{ + public class EnrolmentLog : LogBase + { + public enum EventTypeIds + { + SessionStarting = 10, + SessionProgress, + SessionDevice, + SessionDeviceInfo, + SessionFinished = 20, + SessionDiagnosticInformation, + SessionWarning, + SessionError, + SessionErrorWithInner, + SessionClientError, + SessionTaskAddedDevice = 50, + SessionTaskUpdatingDevice, + SessionTaskCreatedDeviceModel = 56, + SessionTaskProvisioningADAccount = 58, + SessionTaskAssigningUser = 60, + SessionTaskProvisioningCertificate = 62, + SessionTaskProvisioningWirelessProfile = 63, + SessionTaskRenamingDevice = 64, + SessionTaskMovingDeviceOrganisationUnit = 66, + ClientError = 400 + } + private const int _ModuleId = 50; + public static EnrolmentLog Current + { + get + { + return (EnrolmentLog)LogContext.LogModules[50]; + } + } + public override string ModuleDescription + { + get + { + return "Device Enrolment"; + } + } + public override int ModuleId + { + get + { + return 50; + } + } + public override string ModuleName + { + get + { + return "DeviceEnrolment"; + } + } + [System.Diagnostics.DebuggerNonUserCode] + public EnrolmentLog() + { + } + private static void Log(EnrolmentLog.EventTypeIds EventTypeId, params object[] Args) + { + EnrolmentLog.Current.Log((int)EventTypeId, Args); + } + public static void LogSessionStarting(string SessionId, string HostId, EnrolmentTypes EnrolmentType) + { + Log(EventTypeIds.SessionStarting, new object[] + { + SessionId, + HostId, + System.Enum.GetName(EnrolmentType.GetType(), EnrolmentType) + }); + } + public static void LogSessionDevice(string SessionId, string DeviceSerialNumber, int? DeviceModelId) + { + Log(EventTypeIds.SessionDevice, new object[] + { + SessionId, + DeviceSerialNumber, + DeviceModelId + }); + } + public static void LogSessionDeviceInfo(string SessionId, string SerialNumber, string UUID, string ComputerName, string LanMacAddress, string WlanMacAddress, string Manufacturer, string Model, string ModelType) + { + Log(EventTypeIds.SessionDeviceInfo, new object[] + { + SessionId, + SerialNumber, + UUID, + ComputerName, + LanMacAddress, + WlanMacAddress, + Manufacturer, + Model, + ModelType + }); + } + public static void LogSessionDeviceInfo(string SessionId, MacEnrol Request) + { + EnrolmentLog.LogSessionDeviceInfo(SessionId, Request.DeviceSerialNumber, Request.DeviceUUID, Request.DeviceComputerName, Request.DeviceLanMacAddress, Request.DeviceWlanMacAddress, Request.DeviceManufacturer, Request.DeviceModel, Request.DeviceModelType); + } + public static void LogSessionDeviceInfo(string SessionId, Enrol Request) + { + EnrolmentLog.LogSessionDeviceInfo(SessionId, Request.SerialNumber, Request.Hardware.UUID, Request.ComputerName, null, null, Request.Hardware.Manufacturer, Request.Hardware.Model, Request.Hardware.ModelType); + } + + public static void LogSessionProgress(string SessionId, int Progress, string Status) + { + Log(EventTypeIds.SessionProgress, new object[] + { + SessionId, + Progress, + Status + }); + } + public static void LogSessionFinished(string SessionId) + { + Log(EventTypeIds.SessionFinished, new object[] + { + SessionId + }); + } + public static void LogSessionDiagnosticInformation(string SessionId, string Message) + { + Log(EventTypeIds.SessionDiagnosticInformation, new object[] + { + SessionId, + Message + }); + } + public static void LogSessionWarning(string SessionId, string Message) + { + Log(EventTypeIds.SessionWarning, new object[] + { + SessionId, + Message + }); + } + public static void LogSessionError(string SessionId, System.Exception Ex) + { + if (Ex.InnerException == null) + { + Log(EventTypeIds.SessionError, new object[] + { + SessionId, + Ex.GetType().Name, + Ex.Message, + Ex.StackTrace + }); + } + else + { + Log(EventTypeIds.SessionErrorWithInner, new object[] + { + SessionId, + Ex.GetType().Name, + Ex.Message, + Ex.InnerException.GetType().Name, + Ex.InnerException.Message, + Ex.StackTrace, + Ex.InnerException.StackTrace + }); + } + } + public static void LogSessionClientError(string SessionId, string ClientIP, string ClientIdentifier, string ClientVersion, string Error, string RawError) + { + Log(EventTypeIds.SessionClientError, new object[] + { + SessionId, + ClientIP, + ClientIdentifier, + ClientVersion, + Error, + RawError + }); + } + public static void LogSessionTaskAddedDevice(string SessionId, string DeviceSerialNumber) + { + Log(EventTypeIds.SessionTaskAddedDevice, new object[] + { + SessionId, + DeviceSerialNumber + }); + } + public static void LogSessionTaskUpdatingDevice(string SessionId, string DeviceSerialNumber) + { + Log(EventTypeIds.SessionTaskUpdatingDevice, new object[] + { + SessionId, + DeviceSerialNumber + }); + } + public static void LogSessionTaskCreatedDeviceModel(string SessionId, string DeviceSerialNumber, string Manufacturer, string Model) + { + Log(EventTypeIds.SessionTaskCreatedDeviceModel, new object[] + { + SessionId, + DeviceSerialNumber, + Manufacturer, + Model + }); + } + public static void LogSessionTaskProvisioningADAccount(string SessionId, string DeviceSerialNumber, string ADAccountName) + { + Log(EventTypeIds.SessionTaskProvisioningADAccount, new object[] + { + SessionId, + DeviceSerialNumber, + ADAccountName + }); + } + public static void LogSessionTaskAssigningUser(string SessionId, string DeviceSerialNumber, string UserDisplayName, string UserUsername, string UserDomain, string UserSID) + { + Log(EventTypeIds.SessionTaskAssigningUser, new object[] + { + SessionId, + DeviceSerialNumber, + UserDisplayName, + UserUsername, + UserDomain, + UserSID + }); + } + public static void LogSessionTaskProvisioningCertificate(string SessionId, string DeviceSerialNumber, string CertificateName) + { + Log(EventTypeIds.SessionTaskProvisioningCertificate, new object[] + { + SessionId, + DeviceSerialNumber, + CertificateName + }); + } + public static void LogSessionTaskProvisioningWirelessProfile(string SessionId, string DeviceSerialNumber, string WirelessProfileName) + { + Log(EventTypeIds.SessionTaskProvisioningWirelessProfile, new object[] + { + SessionId, + DeviceSerialNumber, + WirelessProfileName + }); + } + public static void LogSessionTaskRenamingDevice(string SessionId, string OldComputerName, string NewComputerName) + { + Log(EventTypeIds.SessionTaskRenamingDevice, new object[] + { + SessionId, + OldComputerName, + NewComputerName + }); + } + public static void LogSessionTaskMovingDeviceOrganisationUnit(string SessionId, string OldOrganisationUnit, string NewOrganisationUnit) + { + Log(EventTypeIds.SessionTaskMovingDeviceOrganisationUnit, new object[] + { + SessionId, + OldOrganisationUnit, + NewOrganisationUnit + }); + } + public static void LogClientError(string ClientIP, string ClientIdentifier, string ClientVersion, string Error, string RawError) + { + Log(EventTypeIds.ClientError, new object[] + { + ClientIP, + ClientIdentifier, + ClientVersion, + Error, + RawError + }); + } + protected override List LoadEventTypes() + { + return new List + { + new LogEventType + { + Id = (int)EventTypeIds.SessionStarting, + ModuleId = _ModuleId, + Name = "Session Starting", + Format = "Starting '{2}' Enrolment for {1} (Session# {0})", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.SessionProgress, + ModuleId = _ModuleId, + Name = "Session Progress", + Format = "Processing Session# {0}; {1}% Complete; Status: {2}", + Severity = 0, + UseLive = true, + UsePersist = false, + UseDisplay = false + }, + new LogEventType + { + Id = (int)EventTypeIds.SessionDevice, + ModuleId = _ModuleId, + Name = "Session Device", + Format = null, + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = false + }, + new LogEventType + { + Id = (int)EventTypeIds.SessionDeviceInfo, + ModuleId = _ModuleId, + Name = "Session Device Info", + Format = null, + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.SessionFinished, + ModuleId = _ModuleId, + Name = "Session Finished", + Format = "Finished Session# {0}", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.SessionDiagnosticInformation, + ModuleId = _ModuleId, + Name = "Session Diagnostic Information", + Format = null, + Severity = 0, + UseLive = true, + UsePersist = false, + UseDisplay = false + }, + new LogEventType + { + Id = (int)EventTypeIds.SessionWarning, + ModuleId = _ModuleId, + Name = "Session Warning", + Format = null, + Severity = 1, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.SessionError, + ModuleId = _ModuleId, + Name = "Session Error", + Format = "An Error Occurred: [{1}] {2}", + Severity = 2, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.SessionErrorWithInner, + ModuleId = _ModuleId, + Name = "Session Error with Internal", + Format = "An Error Occurred: [{1}] {2}; Internal Error: [{3}] {4}", + Severity = 2, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.SessionClientError, + ModuleId = _ModuleId, + Name = "Client Error", + Format = "IP: {1}; Device ID: {2}; Version: {3} Error: {4}; Session# {0}", + Severity = (int)LogEventType.Severities.Error, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.SessionTaskAddedDevice, + ModuleId = _ModuleId, + Name = "Task - Added Device", + Format = "Creating Disco Device {1}", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.SessionTaskUpdatingDevice, + ModuleId = _ModuleId, + Name = "Task - Updating Device", + Format = "Updating Disco Device {1}", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.SessionTaskCreatedDeviceModel, + ModuleId = _ModuleId, + Name = "Task - Creating Device Model", + Format = "Creating Device Model '{2} {3}' for Device {1}", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.SessionTaskProvisioningADAccount, + ModuleId = _ModuleId, + Name = "Task - Provisioning Active Directory Account", + Format = "Provisioning Active Directory Account '{2}' for Device {1}", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.SessionTaskAssigningUser, + ModuleId = _ModuleId, + Name = "Task - Assigning User", + Format = "Assigning User '{2}' ({4}\\{3} {{{5}}}) for Device {1}", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.SessionTaskProvisioningCertificate, + ModuleId = _ModuleId, + Name = "Task - Provisioning Certificate", + Format = "Provisioning Certificate '{2}' for Device {1}", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.SessionTaskProvisioningWirelessProfile, + ModuleId = _ModuleId, + Name = "Task - Provisioning Wireless Profile", + Format = "Provisioning Wireless Profile '{2}' for Device {1}", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.SessionTaskRenamingDevice, + ModuleId = _ModuleId, + Name = "Task - Renaming Device", + Format = "Renaming Device '{1}' to '{2}'", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.SessionTaskMovingDeviceOrganisationUnit, + ModuleId = _ModuleId, + Name = "Task - Moving Device Organisation Unit", + Format = "Moving Device Organisation Unit '{1}' to '{2}'", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.ClientError, + ModuleId = _ModuleId, + Name = "Client Error", + Format = "IP: {0}; Device ID: {1}; Version: {2} Error: {3}", + Severity = (int)LogEventType.Severities.Error, + UseLive = true, + UsePersist = true, + UseDisplay = true + } + }; + } + } +} diff --git a/Disco.Services/Devices/Enrolment/EnrolmentSafeException.cs b/Disco.Services/Devices/Enrolment/EnrolmentSafeException.cs new file mode 100644 index 00000000..d510dfab --- /dev/null +++ b/Disco.Services/Devices/Enrolment/EnrolmentSafeException.cs @@ -0,0 +1,11 @@ +using System; + +namespace Disco.Services.Devices.Enrolment +{ + public class EnrolmentSafeException : Exception + { + public EnrolmentSafeException(string Message) : base(Message) + { + } + } +} diff --git a/Disco.Services/Devices/Enrolment/EnrolmentTypes.cs b/Disco.Services/Devices/Enrolment/EnrolmentTypes.cs new file mode 100644 index 00000000..1849fb28 --- /dev/null +++ b/Disco.Services/Devices/Enrolment/EnrolmentTypes.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Disco.Services.Devices.Enrolment +{ + public enum EnrolmentTypes + { + Normal, + Mac = 5, + MacSecure, + Register = 30 + } +} diff --git a/Disco.BI/BI/DeviceBI/Migration/LogMacAddressImporting.cs b/Disco.Services/Devices/Enrolment/LogMacAddressImportingTask.cs similarity index 89% rename from Disco.BI/BI/DeviceBI/Migration/LogMacAddressImporting.cs rename to Disco.Services/Devices/Enrolment/LogMacAddressImportingTask.cs index 3f63ef53..2574c8dc 100644 --- a/Disco.BI/BI/DeviceBI/Migration/LogMacAddressImporting.cs +++ b/Disco.Services/Devices/Enrolment/LogMacAddressImportingTask.cs @@ -1,17 +1,14 @@ -using Disco.BI.Extensions; -using Disco.Data.Repository; +using Disco.Data.Repository; using Disco.Services.Logging; using Disco.Services.Tasks; using Quartz; using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; -namespace Disco.BI.DeviceBI.Migration +namespace Disco.Services.Devices.Enrolment { - public class LogMacAddressImporting : ScheduledTask + public class LogMacAddressImportingTask : ScheduledTask { public override string TaskName { get { return "Migration: Logs to Device Mac Address Details"; } } @@ -63,11 +60,11 @@ namespace Disco.BI.DeviceBI.Migration public static ScheduledTaskStatus ScheduleImmediately() { - var existingTask = ScheduledTasks.GetTaskStatuses(typeof(LogMacAddressImporting)).Where(s => s.IsRunning).FirstOrDefault(); + var existingTask = ScheduledTasks.GetTaskStatuses(typeof(LogMacAddressImportingTask)).Where(s => s.IsRunning).FirstOrDefault(); if (existingTask != null) return existingTask; - var instance = new LogMacAddressImporting(); + var instance = new LogMacAddressImportingTask(); return instance.ScheduleTask(); } @@ -79,8 +76,8 @@ namespace Disco.BI.DeviceBI.Migration // Load Logs var logRetriever = new ReadLogContext() { - Module = DeviceBI.EnrolmentLog.Current.ModuleId, - EventTypes = new List() { (int)DeviceBI.EnrolmentLog.EventTypeIds.SessionDeviceInfo } + Module = EnrolmentLog.Current.ModuleId, + EventTypes = new List() { (int)EnrolmentLog.EventTypeIds.SessionDeviceInfo } }; var results = logRetriever.Query(database); diff --git a/Disco.Services/Devices/Exporting/DeviceExport.cs b/Disco.Services/Devices/Exporting/DeviceExport.cs index 92bfd512..f98e2515 100644 --- a/Disco.Services/Devices/Exporting/DeviceExport.cs +++ b/Disco.Services/Devices/Exporting/DeviceExport.cs @@ -110,7 +110,7 @@ namespace Disco.Services.Devices.Exporting } public static DeviceExportResult GenerateExport(DiscoDataContext Database, IQueryable Devices, DeviceExportOptions Options) { - return GenerateExport(Database, Devices, Options, ScheduledTaskMockStatus.Create()); + return GenerateExport(Database, Devices, Options, ScheduledTaskMockStatus.Create("Device Export")); } public static DeviceExportResult GenerateExport(DiscoDataContext Database, DeviceExportOptions Options, IScheduledTaskStatus TaskStatus) @@ -134,7 +134,7 @@ namespace Disco.Services.Devices.Exporting } public static DeviceExportResult GenerateExport(DiscoDataContext Database, DeviceExportOptions Options) { - return GenerateExport(Database, Options, ScheduledTaskMockStatus.Create()); + return GenerateExport(Database, Options, ScheduledTaskMockStatus.Create("Device Export")); } private static IEnumerable BuildRecords(IQueryable Devices) diff --git a/Disco.Services/Disco.Services.csproj b/Disco.Services/Disco.Services.csproj index 953b1b36..2bf2dd76 100644 --- a/Disco.Services/Disco.Services.csproj +++ b/Disco.Services/Disco.Services.csproj @@ -15,6 +15,7 @@ ..\ true + 2.2.16272.1003 true @@ -82,6 +83,10 @@ ..\packages\PDFsharp.1.50.4000-beta3b\lib\net20\PdfSharp.Charting.dll True + + ..\packages\plist.net.1.0\lib\Net35\PList.dll + True + ..\Resources\Libraries\Quartz\Quartz.dll @@ -89,6 +94,9 @@ False ..\packages\RazorGenerator.Mvc.2.2.3\lib\net40\RazorGenerator.Mvc.dll + + ..\..\..\Resources\Libraries\SshNet\Renci.SshNet.dll + ..\..\..\Resources\Libraries\Spring.NET\Spring.Core.dll @@ -177,6 +185,7 @@ + @@ -220,8 +229,23 @@ + + + + + + + + + + + + + + + @@ -260,12 +284,16 @@ + + + + @@ -319,18 +347,23 @@ + + + + + @@ -343,6 +376,12 @@ + + + + + + @@ -352,6 +391,7 @@ + @@ -400,6 +440,7 @@ + diff --git a/Disco.Services/Documents/AttachmentImport/ThumbnailUpdateTask.cs b/Disco.Services/Documents/AttachmentImport/ThumbnailUpdateTask.cs new file mode 100644 index 00000000..a29fc35e --- /dev/null +++ b/Disco.Services/Documents/AttachmentImport/ThumbnailUpdateTask.cs @@ -0,0 +1,128 @@ +using Disco.Data.Repository; +using Disco.Models.Repository; +using Disco.Services.Tasks; +using Quartz; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; + +namespace Disco.Services.Documents.AttachmentImport +{ + public class ThumbnailUpdateTask : ScheduledTask + { + public override string TaskName { get { return "Migration: PDF Attachment Thumbnail Update"; } } + + public override bool SingleInstanceTask { get { return true; } } + public override bool CancelInitiallySupported { get { return false; } } + + #region Required Helpers + private static string RequiredFilePath(DiscoDataContext Database) + { + if (Database.DiscoConfiguration.DataStoreLocation != null) + return Path.Combine(Database.DiscoConfiguration.DataStoreLocation, "_ThumbnailUpdateRequired.txt"); + else + return null; + } + + public static bool IsRequired(DiscoDataContext Database) + { + var requiredFilePath = RequiredFilePath(Database); + + if (requiredFilePath == null) + return false; + else + return File.Exists(requiredFilePath); + } + public static void SetRequired(DiscoDataContext Database) + { + var requiredFilePath = RequiredFilePath(Database); + + if (requiredFilePath != null) + { + File.WriteAllText(requiredFilePath, "This file exists to indicate a Thumbnail Update is required. It will automatically be deleted when the update completes."); + File.SetAttributes(requiredFilePath, FileAttributes.Hidden); + } + } + #endregion + + public override void InitalizeScheduledTask(DiscoDataContext Database) + { + if (IsRequired(Database)) + { + // Schedule in 5mins + var trigger = TriggerBuilder.Create() + .StartAt(DateTimeOffset.Now.AddMinutes(5)); + + this.ScheduleTask(trigger); + } + } + + public static ScheduledTaskStatus ScheduleImmediately() + { + var existingTask = ScheduledTasks.GetTaskStatuses(typeof(ThumbnailUpdateTask)).Where(s => s.IsRunning).FirstOrDefault(); + if (existingTask != null) + return existingTask; + + var instance = new ThumbnailUpdateTask(); + return instance.ScheduleTask(); + } + + protected override void ExecuteTask() + { + using (DiscoDataContext database = new DiscoDataContext()) + { + Status.UpdateStatus(0, "Updating Attachment PDF Thumbnails", "Reading Attachments"); + + // Attachments + List attachments = database + .DeviceAttachments.Where(da => da.MimeType == "application/pdf").ToList().Cast() + .Concat(database.UserAttachments.Where(da => da.MimeType == "application/pdf").ToList().Cast()) + .Concat(database.JobAttachments.Where(da => da.MimeType == "application/pdf").ToList().Cast()) + .ToList(); + + int failedTotal = 0; + int notFoundTotal = 0; + int completedTotal = 0; + + attachments.AsParallel().ForAll(a => + { + var completed = Interlocked.Increment(ref completedTotal); + if ((completed % 10) == 0) + { + Status.UpdateStatus((100D / attachments.Count) * completed, $"Processing: {a.AttachmentType} Attachment, Id: {a.Id}"); + } + try + { + var fileName = a.RepositoryFilename(database); + if (!File.Exists(fileName)) + { + Interlocked.Increment(ref notFoundTotal); + Status.LogWarning($"Attachment not found in the Data Store. [{a.AttachmentType} Attachment, Id {a.Id}] expected at: '{fileName}'"); + } + else + { + a.GenerateThumbnail(database); + } + } + catch (Exception ex) + { + Interlocked.Increment(ref failedTotal); + Status.LogWarning($"Error when generating thumbnail for [{a.AttachmentType} Attachment, Id {a.Id}]: [{ex.GetType().Name}] {ex.Message}"); + } + }); + + // Finished - Remove Placeholder File + var requiredFilePath = RequiredFilePath(database); + if (requiredFilePath != null && File.Exists(requiredFilePath)) + File.Delete(requiredFilePath); + + Status.SetFinishedMessage($"Finished updating thumbnails for {attachments.Count:N0}. {notFoundTotal:N0} were not found. {failedTotal:N0} failed."); + Status.LogInformation(Status.FinishedMessage); + Status.Finished(); + } + } + + } +} diff --git a/Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateDevicesManagedGroup.cs b/Disco.Services/Documents/ManagedGroups/DocumentTemplateDevicesManagedGroup.cs similarity index 99% rename from Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateDevicesManagedGroup.cs rename to Disco.Services/Documents/ManagedGroups/DocumentTemplateDevicesManagedGroup.cs index 0b16ed4d..9cd5c96b 100644 --- a/Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateDevicesManagedGroup.cs +++ b/Disco.Services/Documents/ManagedGroups/DocumentTemplateDevicesManagedGroup.cs @@ -8,7 +8,7 @@ using System.Collections.Generic; using System.Linq; using System.Reactive.Linq; -namespace Disco.BI.DocumentTemplateBI.ManagedGroups +namespace Disco.Services.Documents.ManagedGroups { public class DocumentTemplateDevicesManagedGroup : ADManagedGroup { diff --git a/Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateManagedGroups.cs b/Disco.Services/Documents/ManagedGroups/DocumentTemplateManagedGroups.cs similarity index 99% rename from Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateManagedGroups.cs rename to Disco.Services/Documents/ManagedGroups/DocumentTemplateManagedGroups.cs index 69629c1d..52566103 100644 --- a/Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateManagedGroups.cs +++ b/Disco.Services/Documents/ManagedGroups/DocumentTemplateManagedGroups.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Reactive.Linq; using System.Reactive.Subjects; -namespace Disco.BI.DocumentTemplateBI.ManagedGroups +namespace Disco.Services.Documents.ManagedGroups { public static class DocumentTemplateManagedGroups { diff --git a/Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateUsersManagedGroup.cs b/Disco.Services/Documents/ManagedGroups/DocumentTemplateUsersManagedGroup.cs similarity index 99% rename from Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateUsersManagedGroup.cs rename to Disco.Services/Documents/ManagedGroups/DocumentTemplateUsersManagedGroup.cs index e796e4fa..e9824fb3 100644 --- a/Disco.BI/BI/DocumentTemplateBI/ManagedGroups/DocumentTemplateUsersManagedGroup.cs +++ b/Disco.Services/Documents/ManagedGroups/DocumentTemplateUsersManagedGroup.cs @@ -8,7 +8,7 @@ using System.Collections.Generic; using System.Linq; using System.Reactive.Linq; -namespace Disco.BI.DocumentTemplateBI.ManagedGroups +namespace Disco.Services.Documents.ManagedGroups { public class DocumentTemplateUsersManagedGroup : ADManagedGroup { diff --git a/Disco.Services/Interop/ActiveDirectory/ADGroup.cs b/Disco.Services/Interop/ActiveDirectory/ADGroup.cs index b2d39d3c..dc7c0fc0 100644 --- a/Disco.Services/Interop/ActiveDirectory/ADGroup.cs +++ b/Disco.Services/Interop/ActiveDirectory/ADGroup.cs @@ -9,7 +9,7 @@ namespace Disco.Services.Interop.ActiveDirectory public class ADGroup : IADObject { internal static readonly string[] LoadProperties = { "name", "distinguishedName", "sAMAccountName", "objectSid", "memberOf" }; - internal static string LdapSearchFilterTemplate = "(&(objectCategory=Group)(|(sAMAccountName=*{0}*)(name=*{0}*)(cn=*{0}*)))"; + internal static string LdapSearchFilterTemplate = "(&(objectCategory=Group)(|(sAMAccountName={0}*)(name={0}*)(cn={0}*)))"; internal const string LdapSamAccountNameFilterTemplate = "(&(objectCategory=Group)(sAMAccountName={0}))"; internal const string LdapSecurityIdentifierFilterTemplate = "(&(objectCategory=Group)(objectSid={0}))"; diff --git a/Disco.Services/Interop/ActiveDirectory/ADUserAccount.cs b/Disco.Services/Interop/ActiveDirectory/ADUserAccount.cs index 6cfb7bc9..ebda6949 100644 --- a/Disco.Services/Interop/ActiveDirectory/ADUserAccount.cs +++ b/Disco.Services/Interop/ActiveDirectory/ADUserAccount.cs @@ -9,7 +9,7 @@ namespace Disco.Services.Interop.ActiveDirectory public class ADUserAccount : IADObject { internal const string LdapSamAccountNameFilterTemplate = "(&(objectCategory=Person)(sAMAccountName={0}))"; - internal static string LdapSearchFilterTemplate = "(&(objectCategory=Person)(objectClass=user)(|(sAMAccountName=*{0}*)(displayName=*{0}*)(sn=*{0}*)(givenName=*{0}*)))"; + internal static string LdapSearchFilterTemplate = "(&(objectCategory=Person)(objectClass=user)(|(sAMAccountName={0}*)(displayName={0}*)(sn={0}*)(givenName={0}*)))"; internal static readonly string[] LoadProperties = { "name", "distinguishedName", "sAMAccountName", "objectSid", "displayName", "sn", "givenName", "memberOf", "primaryGroupID", "mail", "telephoneNumber" }; internal static readonly string[] QuickLoadProperties = { "name", "distinguishedName", "sAMAccountName", "objectSid", "displayName", "sn", "givenName", "mail", "telephoneNumber" }; diff --git a/Disco.Services/Interop/ActiveDirectory/ActiveDirectoryContext.cs b/Disco.Services/Interop/ActiveDirectory/ActiveDirectoryContext.cs index c24f9d74..7d9606de 100644 --- a/Disco.Services/Interop/ActiveDirectory/ActiveDirectoryContext.cs +++ b/Disco.Services/Interop/ActiveDirectory/ActiveDirectoryContext.cs @@ -38,7 +38,7 @@ namespace Disco.Services.Interop.ActiveDirectory } } - #region Contructor/Initializing + #region Constructor/Initializing private ActiveDirectoryContext() { @@ -56,11 +56,7 @@ namespace Disco.Services.Interop.ActiveDirectory this._SearchAllForestServers = Database.DiscoConfiguration.ActiveDirectory.SearchAllForestServers ?? true; // Set Search LDAP Filters - if (Database.DiscoConfiguration.ActiveDirectory.SearchWildcardSuffixOnly) - { - ADGroup.LdapSearchFilterTemplate = "(&(objectCategory=Group)(|(sAMAccountName={0}*)(name={0}*)(cn={0}*)))"; - ADUserAccount.LdapSearchFilterTemplate = "(&(objectCategory=Person)(objectClass=user)(|(sAMAccountName={0}*)(displayName={0}*)(sn={0}*)(givenName={0}*)))"; - } + InitializeWildcardSearchSufixOnly(Database.DiscoConfiguration.ActiveDirectory.SearchWildcardSuffixOnly); // Determine Site var computerSite = ActiveDirectorySite.GetComputerSite(); @@ -235,6 +231,26 @@ namespace Disco.Services.Interop.ActiveDirectory #region Configuration + public void UpdateWildcardSearchSuffixOnly(DiscoDataContext Database, bool SearchWildcardSuffixOnly) + { + Database.DiscoConfiguration.ActiveDirectory.SearchWildcardSuffixOnly = SearchWildcardSuffixOnly; + InitializeWildcardSearchSufixOnly(SearchWildcardSuffixOnly); + } + + private void InitializeWildcardSearchSufixOnly(bool SearchWildcardSuffixOnly) + { + if (SearchWildcardSuffixOnly) + { + ADGroup.LdapSearchFilterTemplate = "(&(objectCategory=Group)(|(sAMAccountName={0}*)(name={0}*)(cn={0}*)))"; + ADUserAccount.LdapSearchFilterTemplate = "(&(objectCategory=Person)(objectClass=user)(|(sAMAccountName={0}*)(displayName={0}*)(sn={0}*)(givenName={0}*)))"; + } + else + { + ADGroup.LdapSearchFilterTemplate = "(&(objectCategory=Group)(|(sAMAccountName=*{0}*)(name=*{0}*)(cn=*{0}*)))"; + ADUserAccount.LdapSearchFilterTemplate = "(&(objectCategory=Person)(objectClass=user)(|(sAMAccountName=*{0}*)(displayName=*{0}*)(sn=*{0}*)(givenName=*{0}*)))"; + } + } + public bool UpdateSearchAllForestServers(DiscoDataContext Database, bool SearchAllForestServers) { if (SearchAllForestServers == false) diff --git a/Disco.Services/Interop/DiscoServices/PluginLibrary.cs b/Disco.Services/Interop/DiscoServices/PluginLibrary.cs index 3b3c269c..85646879 100644 --- a/Disco.Services/Interop/DiscoServices/PluginLibrary.cs +++ b/Disco.Services/Interop/DiscoServices/PluginLibrary.cs @@ -103,7 +103,7 @@ namespace Disco.Services.Interop.DiscoServices } } - var manifestJson = JsonConvert.SerializeObject(result); + var manifestJson = JsonConvert.SerializeObject(result, Formatting.Indented); var manifestFile = PluginLibrary.ManifestFilename(Database); diff --git a/Disco.BI/BI/Extensions/JobActionExtensions.cs b/Disco.Services/Jobs/JobActionExtensions.cs similarity index 99% rename from Disco.BI/BI/Extensions/JobActionExtensions.cs rename to Disco.Services/Jobs/JobActionExtensions.cs index cd2cde55..4d21df38 100644 --- a/Disco.BI/BI/Extensions/JobActionExtensions.cs +++ b/Disco.Services/Jobs/JobActionExtensions.cs @@ -1,24 +1,23 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Exceptionless; -using Disco.Data.Repository; +using Disco.Data.Repository; using Disco.Models.BI.Config; using Disco.Models.Repository; +using Disco.Services.Authorization; using Disco.Services.Plugins; +using Disco.Services.Plugins.Features.RepairProvider; using Disco.Services.Plugins.Features.WarrantyProvider; using Disco.Services.Users; -using Disco.Services.Authorization; -using Disco.Services.Plugins.Features.RepairProvider; - -using PublishJobResult = Disco.Models.Services.Interop.DiscoServices.PublishJobResult; +using Exceptionless; +using System; +using System.Collections.Generic; +using System.Linq; using DiscoServicesJobs = Disco.Services.Interop.DiscoServices.Jobs; -using Disco.Services; +using PublishJobResult = Disco.Models.Services.Interop.DiscoServices.PublishJobResult; -namespace Disco.BI.Extensions +namespace Disco.Services { public static class JobActionExtensions { + #region Create public static bool CanCreate() { @@ -721,5 +720,6 @@ namespace Disco.BI.Extensions Database.Jobs.Remove(j); } #endregion + } } diff --git a/Disco.Services/Jobs/JobExtensions.cs b/Disco.Services/Jobs/JobExtensions.cs index f915dad6..fd548e7d 100644 --- a/Disco.Services/Jobs/JobExtensions.cs +++ b/Disco.Services/Jobs/JobExtensions.cs @@ -1,11 +1,14 @@ -using Disco.Models.Repository; +using Disco.Data.Repository; +using Disco.Models.Repository; +using Disco.Models.Services.Documents; using Disco.Models.Services.Jobs.JobLists; +using Disco.Services.Authorization; using Disco.Services.Interop.ActiveDirectory; +using Disco.Services.Plugins; using System; using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; namespace Disco.Services { @@ -195,5 +198,190 @@ namespace Disco.Services var statusId = j.CalculateStatusId(); return new Tuple(statusId, JobStatusDescription(statusId, j)); } + + public static List AvailableDocumentTemplates(this Job j, DiscoDataContext Database, User User, DateTime TimeStamp) + { + var dts = Database.DocumentTemplates.Include("JobSubTypes") + .Where(dt => dt.Scope == DocumentTemplate.DocumentTemplateScopes.Job) + .ToList(); + + foreach (var dt in dts.ToArray()) + { + if (dt.JobSubTypes.Count != 0) + { // Filter Applied + bool match = false; + foreach (var st in j.JobSubTypes) + { + if (dt.JobSubTypes.Contains(st)) + { + match = true; + break; + } + } + if (!match) + dts.Remove(dt); + } + } + + // Evaluate Filters + dts = dts.Where(dt => dt.FilterExpressionMatches(j, Database, User, TimeStamp, DocumentState.DefaultState())).ToList(); + + return dts; + } + + public static DateTime ValidateDateAfterOpened(this Job j, DateTime d) + { + if (d < j.OpenedDate) + { + if (d > j.OpenedDate.AddMinutes(-1)) + return j.OpenedDate; + else + throw new ArgumentException("The Date must be >= the Open Date.", "d"); + } + return d; + } + + public static string GenerateFaultDescription(this Job j, DiscoDataContext Database) + { + StringBuilder sb = new StringBuilder(); + + sb.AppendLine("Faulty Components:"); + foreach (var jst in j.JobSubTypes) + sb.Append("- ").AppendLine(jst.Description).AppendLine(" - "); + + return sb.ToString(); + } + + public static string GenerateFaultDescriptionFooter(this Job j, DiscoDataContext Database, PluginFeatureManifest WarrantyProviderDefinition) + { + var versionDisco = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; + return string.Format("Automation by Disco v{0}.{1}.{2:0000}.{3:0000} (Provider: {4} v{5})", + versionDisco.Major, versionDisco.Minor, versionDisco.Build, versionDisco.Revision, WarrantyProviderDefinition.Id, WarrantyProviderDefinition.PluginManifest.Version.ToString(4)); + } + + public static void UpdateSubTypes(this Job j, DiscoDataContext Database, List SubTypes, bool AddComponents, User TechUser) + { + if (SubTypes == null || SubTypes.Count == 0) + throw new ArgumentException("The Job must contain at least one Sub Type"); + + List addedSubTypes = new List(); + List removedSubTypes = new List(); + + // Removed Sub Types + foreach (var t in j.JobSubTypes.ToArray()) + if (!SubTypes.Contains(t)) + { + removedSubTypes.Add(t); + j.JobSubTypes.Remove(t); + } + // Added Sub Types + foreach (var t in SubTypes) + if (!j.JobSubTypes.Contains(t)) + { + addedSubTypes.Add(t); + j.JobSubTypes.Add(t); + } + + // Write Log + if (addedSubTypes.Count > 0 || removedSubTypes.Count > 0) + { + StringBuilder logBuilder = new StringBuilder(); + logBuilder.AppendLine("# Updated Job Sub Types"); + if (removedSubTypes.Count > 0) + { + logBuilder.AppendLine().AppendLine("Removed:"); + foreach (var t in removedSubTypes) + logBuilder.Append("- **").Append(t.ToString()).AppendLine("**"); + } + if (addedSubTypes.Count > 0) + { + logBuilder.AppendLine().AppendLine("Added:"); + foreach (var t in addedSubTypes) + logBuilder.Append("- **").Append(t.ToString()).AppendLine("**"); + } + Database.JobLogs.Add(new JobLog() + { + JobId = j.Id, + TechUserId = TechUser.UserId, + Timestamp = DateTime.Now, + Comments = logBuilder.ToString() + }); + } + + // Add Components + if (AddComponents && addedSubTypes.Count > 0 && j.DeviceSerialNumber != null) + { + var components = Database.DeviceComponents.Include("JobSubTypes").Where(c => !c.DeviceModelId.HasValue || c.DeviceModelId == j.Device.DeviceModelId); + var addedComponents = new List(); + foreach (var c in components) + { + foreach (var st in c.JobSubTypes) + { + foreach (var jst in addedSubTypes) + { + if (st.JobTypeId == jst.JobTypeId && st.Id == jst.Id) + { + addedComponents.Add(c); + break; + } + } + if (addedComponents.Contains(c)) + break; + } + } + foreach (var c in addedComponents) + { + if (!j.JobComponents.Any(jc => jc.Description.Equals(c.Description, StringComparison.OrdinalIgnoreCase))) + { // Job Component with matching Description doesn't exist. + Database.JobComponents.Add(new JobComponent() + { + Job = j, + TechUserId = TechUser.UserId, + Cost = c.Cost, + Description = c.Description + }); + } + } + } + } + + private static List FilterCreatableTypePermissions(AuthorizationToken Authorization) + { + if (!Authorization.HasAll(Claims.Job.Types.CreateHMisc, Claims.Job.Types.CreateHNWar, Claims.Job.Types.CreateHWar, Claims.Job.Types.CreateSApp, Claims.Job.Types.CreateSImg, Claims.Job.Types.CreateSOS, Claims.Job.Types.CreateUMgmt)) + { + // Must Filter + List allowedTypes = new List(6); + if (Authorization.Has(Claims.Job.Types.CreateHMisc)) + allowedTypes.Add(JobType.JobTypeIds.HMisc); + if (Authorization.Has(Claims.Job.Types.CreateHNWar)) + allowedTypes.Add(JobType.JobTypeIds.HNWar); + if (Authorization.Has(Claims.Job.Types.CreateHWar)) + allowedTypes.Add(JobType.JobTypeIds.HWar); + if (Authorization.Has(Claims.Job.Types.CreateSApp)) + allowedTypes.Add(JobType.JobTypeIds.SApp); + if (Authorization.Has(Claims.Job.Types.CreateSImg)) + allowedTypes.Add(JobType.JobTypeIds.SImg); + if (Authorization.Has(Claims.Job.Types.CreateSOS)) + allowedTypes.Add(JobType.JobTypeIds.SOS); + if (Authorization.Has(Claims.Job.Types.CreateUMgmt)) + allowedTypes.Add(JobType.JobTypeIds.UMgmt); + + return allowedTypes; + } + return null; + } + + public static IQueryable FilterCreatableTypePermissions(this IQueryable JobTypes, AuthorizationToken Authorization) + { + var allowedTypes = FilterCreatableTypePermissions(Authorization); + + if (allowedTypes != null) + { + return JobTypes.Where(jt => allowedTypes.Contains(jt.Id)); + } + + return JobTypes; + } + } } diff --git a/Disco.BI/BI/Extensions/JobFlagExtensions.cs b/Disco.Services/Jobs/JobFlagExtensions.cs similarity index 96% rename from Disco.BI/BI/Extensions/JobFlagExtensions.cs rename to Disco.Services/Jobs/JobFlagExtensions.cs index 9269c164..8542d845 100644 --- a/Disco.BI/BI/Extensions/JobFlagExtensions.cs +++ b/Disco.Services/Jobs/JobFlagExtensions.cs @@ -1,11 +1,10 @@ -using System; +using Disco.Models.Repository; +using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using Disco.Models.Repository; using System.ComponentModel.DataAnnotations; +using System.Linq; -namespace Disco.BI.Extensions +namespace Disco.Services { public static class JobFlagExtensions { diff --git a/Disco.BI/BI/Extensions/JobQueueActionExtensions.cs b/Disco.Services/Jobs/JobQueues/JobQueueExtensions.cs similarity index 98% rename from Disco.BI/BI/Extensions/JobQueueActionExtensions.cs rename to Disco.Services/Jobs/JobQueues/JobQueueExtensions.cs index 6568d53c..bfb0eb6d 100644 --- a/Disco.BI/BI/Extensions/JobQueueActionExtensions.cs +++ b/Disco.Services/Jobs/JobQueues/JobQueueExtensions.cs @@ -6,9 +6,9 @@ using Disco.Services.Users; using System; using System.Linq; -namespace Disco.BI.Extensions +namespace Disco.Services { - public static class JobQueueActionExtensions + public static class JobQueueExtensions { #region Edit Sla @@ -41,7 +41,7 @@ namespace Disco.BI.Extensions throw new ArgumentException("The SLA Expires Date must be greater than the Added Date", "SLAExpiresDate"); jqj.SLAExpiresDate = SlaExpiresDate; - } + } #endregion #region Edit Priority diff --git a/Disco.BI/BI/JobBI/Utilities.cs b/Disco.Services/Jobs/Jobs.cs similarity index 97% rename from Disco.BI/BI/JobBI/Utilities.cs rename to Disco.Services/Jobs/Jobs.cs index 89339b2f..66069306 100644 --- a/Disco.BI/BI/JobBI/Utilities.cs +++ b/Disco.Services/Jobs/Jobs.cs @@ -1,15 +1,15 @@ -using System; +using Disco.Data.Repository; +using Disco.Models.Repository; +using System; using System.Collections.Generic; using System.Linq; using System.Text; -using Disco.Models.Repository; -using Disco.Data.Repository; -using Disco.Models.BI.Job; -namespace Disco.BI.JobBI +namespace Disco.Services.Jobs { - public static class Utilities + public static class Jobs { + public static Job Create(DiscoDataContext Database, Device device, User user, JobType type, List subTypes, User initialTech, bool addAutoQueues = true) { Job j = new Job() @@ -119,5 +119,6 @@ namespace Disco.BI.JobBI return j; } + } } diff --git a/Disco.BI/BI/JobBI/Statistics/DailyOpenedClosed.cs b/Disco.Services/Jobs/Statistics/DailyOpenedClosed.cs similarity index 96% rename from Disco.BI/BI/JobBI/Statistics/DailyOpenedClosed.cs rename to Disco.Services/Jobs/Statistics/DailyOpenedClosed.cs index fb5c1428..402a3c80 100644 --- a/Disco.BI/BI/JobBI/Statistics/DailyOpenedClosed.cs +++ b/Disco.Services/Jobs/Statistics/DailyOpenedClosed.cs @@ -1,17 +1,15 @@ -using System; +using Disco.Data.Repository; +using Disco.Data.Repository.Monitor; +using Disco.Models.Repository; +using Disco.Models.Services.Job.Statistics; +using Disco.Services.Tasks; +using Quartz; +using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using Quartz; -using Disco.Models.BI.Job.Statistics; -using Disco.Data.Repository; -using Quartz.Impl; -using Disco.Services.Tasks; using System.Reactive.Linq; -using Disco.Models.Repository; -using Disco.Data.Repository.Monitor; -namespace Disco.BI.JobBI.Statistics +namespace Disco.Services.Jobs.Statistics { public class DailyOpenedClosed : ScheduledTask { @@ -80,7 +78,7 @@ namespace Disco.BI.JobBI.Statistics // Subscribe to Live Repository Events if (_streamSubscription != null) _streamSubscription.Dispose(); - _streamSubscription = Disco.Data.Repository.Monitor.RepositoryMonitor.StreamBeforeCommit.Where( + _streamSubscription = RepositoryMonitor.StreamBeforeCommit.Where( e => e.EntityType == typeof(Job) && (e.EventType == RepositoryMonitorEventType.Added || (e.EventType == RepositoryMonitorEventType.Modified && e.ModifiedProperties.Contains("ClosedDate")))).Subscribe(RepositoryEvent_JobChange); } @@ -169,5 +167,6 @@ namespace Disco.BI.JobBI.Statistics return resultData; } + } } diff --git a/Disco.Services/Plugins/Features/CertificateAuthorityProvider/CertificateAuthorityProviderFeature.cs b/Disco.Services/Plugins/Features/CertificateAuthorityProvider/CertificateAuthorityProviderFeature.cs new file mode 100644 index 00000000..790da661 --- /dev/null +++ b/Disco.Services/Plugins/Features/CertificateAuthorityProvider/CertificateAuthorityProviderFeature.cs @@ -0,0 +1,14 @@ +using Disco.Data.Repository; +using Disco.Models.ClientServices; +using Disco.Models.Repository; + +namespace Disco.Services.Plugins.Features.CertificateAuthorityProvider +{ + [PluginFeatureCategory(DisplayName = "Certificate Authority Providers")] + public abstract class CertificateAuthorityProviderFeature : PluginFeature + { + public abstract string CertificateProviderId { get; } + + public abstract ProvisionAuthorityCertificatesResult ProvisionAuthorityCertificates(DiscoDataContext Database, Device Device, Enrol Enrolment); + } +} diff --git a/Disco.Services/Plugins/Features/CertificateAuthorityProvider/ProvisionAuthorityCertificatesResult.cs b/Disco.Services/Plugins/Features/CertificateAuthorityProvider/ProvisionAuthorityCertificatesResult.cs new file mode 100644 index 00000000..c01d7781 --- /dev/null +++ b/Disco.Services/Plugins/Features/CertificateAuthorityProvider/ProvisionAuthorityCertificatesResult.cs @@ -0,0 +1,41 @@ +using Disco.Models.ClientServices; +using Disco.Models.Repository; +using System.Collections.Generic; + +namespace Disco.Services.Plugins.Features.CertificateAuthorityProvider +{ + public class ProvisionAuthorityCertificatesResult + { + /// + /// The associated with the provision result. + /// + public Device Device { get; set; } + + /// + /// The associated with the provision result. + /// + public Enrol Enrolment { get; set; } + + /// + /// A list of certificate thumbprints to be removed from the Trusted Root Certification Authorities store + /// Matching certificates will be removed unless they match the . + /// + public List TrustedRootCertificateRemoveThumbprints { get; set; } + + /// + /// A list of certificates to be added to the Trusted Root Certification Authorities store on the client device. + /// + public List TrustedRootCertificates { get; set; } + + /// + /// A list of certificate thumbprints to be removed from the Intermedate Certificate Authorities store. + /// Matching certificates will be removed unless they match the . + /// + public List IntermediateCertificateRemoveThumbprints { get; set; } + + /// + /// A list of certificates to be added to the Intermedate Certificate Authorities store on the client device. + /// + public List IntermediateCertificates { get; set; } + } +} diff --git a/Disco.Services/Plugins/Features/CertificateProvider/CertificateProviderFeature.cs b/Disco.Services/Plugins/Features/CertificateProvider/CertificateProviderFeature.cs index 9badac55..4312e2d8 100644 --- a/Disco.Services/Plugins/Features/CertificateProvider/CertificateProviderFeature.cs +++ b/Disco.Services/Plugins/Features/CertificateProvider/CertificateProviderFeature.cs @@ -1,9 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Disco.Data.Repository; +using Disco.Data.Repository; +using Disco.Models.ClientServices; using Disco.Models.Repository; namespace Disco.Services.Plugins.Features.CertificateProvider @@ -11,8 +7,8 @@ namespace Disco.Services.Plugins.Features.CertificateProvider [PluginFeatureCategory(DisplayName = "Certificate Providers")] public abstract class CertificateProviderFeature : PluginFeature { - // Certificate Plugin Requirements public abstract string CertificateProviderId { get; } - public abstract Tuple> AllocateCertificate(DiscoDataContext Database, Device Device); + + public abstract ProvisionPersonalCertificateResult ProvisionPersonalCertificate(DiscoDataContext Database, Device Device, Enrol Enrolment); } } diff --git a/Disco.Services/Plugins/Features/CertificateProvider/CertificateProviderLog.cs b/Disco.Services/Plugins/Features/CertificateProvider/CertificateProviderLog.cs index 6ac70ce3..f180e682 100644 --- a/Disco.Services/Plugins/Features/CertificateProvider/CertificateProviderLog.cs +++ b/Disco.Services/Plugins/Features/CertificateProvider/CertificateProviderLog.cs @@ -1,129 +1,127 @@ using Disco.Models.Repository; using Disco.Services.Logging; using Disco.Services.Logging.Models; -using System; -using System.Collections.Generic; -using System.Diagnostics; + namespace Disco.Services.Plugins.Features.CertificateProvider { - public class CertificateProvidersLog : LogBase - { - public enum EventTypeIds - { - RetrievalStarting = 10, - RetrievalProgress, - RetrievalFinished, - RetrievalWarning = 15, - RetrievalError, - RetrievalCertificateStarting = 20, - RetrievalCertificateFinished = 22, - RetrievalCertificateWarning = 25, - RetrievalCertificateError, - Allocated = 40, - AllocationFailed = 50, + public class CertificateProvidersLog : LogBase + { + public enum EventTypeIds + { + RetrievalStarting = 10, + RetrievalProgress, + RetrievalFinished, + RetrievalWarning = 15, + RetrievalError, + RetrievalCertificateStarting = 20, + RetrievalCertificateFinished = 22, + RetrievalCertificateWarning = 25, + RetrievalCertificateError, + Allocated = 40, + AllocationFailed = 50, DisabledCertificate = 100, EnabledCertificate = 110, DeletedCertificate = 120, UpdatedCertificate = 130 - } - private const int _ModuleId = 60; - private static bool _IsCertificateRetrievalProcessing; - private static string _CertificateRetrievalStatus; - private static int _CertificateRetrievalProgress; - public static CertificateProvidersLog Current - { - get - { - return (CertificateProvidersLog)LogContext.LogModules[60]; - } - } - public static bool IsCertificateRetrievalProcessing - { - get - { - return CertificateProvidersLog._IsCertificateRetrievalProcessing; - } - } - public override string ModuleDescription - { - get - { - return "Certificate Providers"; - } - } - public override int ModuleId - { - get - { - return 60; - } - } - public override string ModuleName - { - get - { - return "CertificateProviders"; - } - } - [System.Diagnostics.DebuggerNonUserCode] - public CertificateProvidersLog() - { - } - private static void Log(CertificateProvidersLog.EventTypeIds EventTypeId, params object[] Args) - { - CertificateProvidersLog.Current.Log((int)EventTypeId, Args); - } - public static void LogRetrievalStarting(int CertificateCount, int CertificateIdFrom, int CertificateIdTo) - { - CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.RetrievalStarting, new object[] - { - CertificateCount, - CertificateIdFrom, - CertificateIdTo - }); - } - public static void LogRetrievalFinished() - { - CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.RetrievalFinished, new object[0]); - } - public static void LogRetrievalWarning(string Message) - { - CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.RetrievalWarning, new object[] - { - Message - }); - } - public static void LogRetrievalError(string Message) - { - CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.RetrievalError, new object[] - { - Message - }); - } - public static void LogRetrievalCertificateStarting(string CertificateId) - { - CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.RetrievalCertificateStarting, CertificateId); - } - public static void LogRetrievalCertificateFinished(string CertificateId) - { - CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.RetrievalCertificateFinished, CertificateId); - } - public static void LogRetrievalCertificateWarning(string CertificateId, string Message) - { - CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.RetrievalCertificateWarning, CertificateId, Message); - } - public static void LogRetrievalCertificateError(string CertificateId, string Message) - { - CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.RetrievalCertificateError, CertificateId, Message); - } - public static void LogAllocated(string CertificateId, string DeviceSerialNumber) - { - CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.Allocated, CertificateId, DeviceSerialNumber); - } - public static void LogAllocationFailed(string DeviceSerialNumber) - { - CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.AllocationFailed, DeviceSerialNumber); - } + } + private const int _ModuleId = 60; + private static bool _IsCertificateRetrievalProcessing; + private static string _CertificateRetrievalStatus; + private static int _CertificateRetrievalProgress; + public static CertificateProvidersLog Current + { + get + { + return (CertificateProvidersLog)LogContext.LogModules[60]; + } + } + public static bool IsCertificateRetrievalProcessing + { + get + { + return CertificateProvidersLog._IsCertificateRetrievalProcessing; + } + } + public override string ModuleDescription + { + get + { + return "Certificate Providers"; + } + } + public override int ModuleId + { + get + { + return 60; + } + } + public override string ModuleName + { + get + { + return "CertificateProviders"; + } + } + [System.Diagnostics.DebuggerNonUserCode] + public CertificateProvidersLog() + { + } + private static void Log(CertificateProvidersLog.EventTypeIds EventTypeId, params object[] Args) + { + CertificateProvidersLog.Current.Log((int)EventTypeId, Args); + } + public static void LogRetrievalStarting(int CertificateCount, int CertificateIdFrom, int CertificateIdTo) + { + CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.RetrievalStarting, new object[] + { + CertificateCount, + CertificateIdFrom, + CertificateIdTo + }); + } + public static void LogRetrievalFinished() + { + CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.RetrievalFinished, new object[0]); + } + public static void LogRetrievalWarning(string Message) + { + CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.RetrievalWarning, new object[] + { + Message + }); + } + public static void LogRetrievalError(string Message) + { + CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.RetrievalError, new object[] + { + Message + }); + } + public static void LogRetrievalCertificateStarting(string CertificateId) + { + CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.RetrievalCertificateStarting, CertificateId); + } + public static void LogRetrievalCertificateFinished(string CertificateId) + { + CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.RetrievalCertificateFinished, CertificateId); + } + public static void LogRetrievalCertificateWarning(string CertificateId, string Message) + { + CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.RetrievalCertificateWarning, CertificateId, Message); + } + public static void LogRetrievalCertificateError(string CertificateId, string Message) + { + CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.RetrievalCertificateError, CertificateId, Message); + } + public static void LogAllocated(string CertificateId, string DeviceSerialNumber) + { + CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.Allocated, CertificateId, DeviceSerialNumber); + } + public static void LogAllocationFailed(string DeviceSerialNumber) + { + CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.AllocationFailed, DeviceSerialNumber); + } public static void LogDisabledCertificate(DeviceCertificate Certificate, string Reason) { CertificateProvidersLog.Log(EventTypeIds.DisabledCertificate, Certificate.Name, Certificate.Id, Reason); @@ -140,210 +138,210 @@ namespace Disco.Services.Plugins.Features.CertificateProvider { CertificateProvidersLog.Log(EventTypeIds.UpdatedCertificate, Certificate.Name, Certificate.Id, Reason); } - - public static void LogCertificateRetrievalProgress(bool? IsProcessing, int? Progress, string Status) - { - bool flag = IsProcessing.HasValue; - if (flag) - { - CertificateProvidersLog._IsCertificateRetrievalProcessing = IsProcessing.Value; - } - flag = CertificateProvidersLog._IsCertificateRetrievalProcessing; - if (flag) - { - bool flag2 = Status != null; - if (flag2) - { - CertificateProvidersLog._CertificateRetrievalStatus = Status; - } - flag2 = Progress.HasValue; - if (flag2) - { - CertificateProvidersLog._CertificateRetrievalProgress = Progress.Value; - } - } - else - { - CertificateProvidersLog._CertificateRetrievalStatus = null; - CertificateProvidersLog._CertificateRetrievalProgress = 0; - } - CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.RetrievalProgress, new object[] - { - CertificateProvidersLog._IsCertificateRetrievalProcessing, - CertificateProvidersLog._CertificateRetrievalProgress, - CertificateProvidersLog._CertificateRetrievalStatus - }); - } - protected override System.Collections.Generic.List LoadEventTypes() - { - return new System.Collections.Generic.List - { - new LogEventType - { - Id = (int)EventTypeIds.RetrievalStarting, - ModuleId = 60, - Name = "Retrieval Starting", - Format = "Starting retrieval of {0} certificate/s ({1} to {2})", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = (int)EventTypeIds.RetrievalProgress, - ModuleId = 60, - Name = "Retrieval Progress", - Format = "Processing: {0}; {1}% Complete; Status: {2}", - Severity = 0, - UseLive = true, - UsePersist = false, - UseDisplay = false - }, - new LogEventType - { - Id = (int)EventTypeIds.RetrievalFinished, - ModuleId = 60, - Name = "Retrieval Finished", - Format = "Retrieval of Certificates Complete", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = (int)EventTypeIds.RetrievalWarning, - ModuleId = 60, - Name = "Retrieval Warning", - Format = "Retrieval Warning: {0}", - Severity = 1, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = (int)EventTypeIds.RetrievalError, - ModuleId = 60, - Name = "Retrieval Error", - Format = "Retrieval Error: {0}", - Severity = 2, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = (int)EventTypeIds.RetrievalCertificateStarting, - ModuleId = 60, - Name = "Retrieval Certificate Starting", - Format = "Retrieving Certificate: {0}", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = (int)EventTypeIds.RetrievalCertificateFinished, - ModuleId = 60, - Name = "Retrieval Certificate Finished", - Format = "Certificate Retrieved: {0}", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = (int)EventTypeIds.RetrievalCertificateWarning, - ModuleId = 60, - Name = "Retrieval Certificate Warning", - Format = "{0} Certificate Warning: {1}", - Severity = 1, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = (int)EventTypeIds.RetrievalCertificateError, - ModuleId = 60, - Name = "Retrieval Certificate Error", - Format = "{0} Certificate Error: {1}", - Severity = 2, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = (int)EventTypeIds.Allocated, - ModuleId = 60, - Name = "Allocated", - Format = "Certificate {0} allocated to {1}", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = (int)EventTypeIds.AllocationFailed, - ModuleId = 60, - Name = "Allocation Failed", - Format = "No certificates available for Device: {0}", - Severity = 2, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = (int)EventTypeIds.DisabledCertificate, - ModuleId = 60, - Name = "Disabled Certificate", - Format = "Certificate Disabled: {0} [{1}], Reason: {2}", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, + + public static void LogCertificateRetrievalProgress(bool? IsProcessing, int? Progress, string Status) + { + bool flag = IsProcessing.HasValue; + if (flag) + { + CertificateProvidersLog._IsCertificateRetrievalProcessing = IsProcessing.Value; + } + flag = CertificateProvidersLog._IsCertificateRetrievalProcessing; + if (flag) + { + bool flag2 = Status != null; + if (flag2) + { + CertificateProvidersLog._CertificateRetrievalStatus = Status; + } + flag2 = Progress.HasValue; + if (flag2) + { + CertificateProvidersLog._CertificateRetrievalProgress = Progress.Value; + } + } + else + { + CertificateProvidersLog._CertificateRetrievalStatus = null; + CertificateProvidersLog._CertificateRetrievalProgress = 0; + } + CertificateProvidersLog.Log(CertificateProvidersLog.EventTypeIds.RetrievalProgress, new object[] + { + CertificateProvidersLog._IsCertificateRetrievalProcessing, + CertificateProvidersLog._CertificateRetrievalProgress, + CertificateProvidersLog._CertificateRetrievalStatus + }); + } + protected override System.Collections.Generic.List LoadEventTypes() + { + return new System.Collections.Generic.List + { new LogEventType - { - Id = (int)EventTypeIds.EnabledCertificate, - ModuleId = 60, - Name = "Enabled Certificate", - Format = "Certificate Disabled: {0} [{1}], Reason: {2}", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = (int)EventTypeIds.DeletedCertificate, - ModuleId = 60, - Name = "Deleted Certificate", - Format = "Certificate Deleted: {0} [{1}], Reason: {2}", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - }, - new LogEventType - { - Id = (int)EventTypeIds.UpdatedCertificate, - ModuleId = 60, - Name = "Updated Certificate", - Format = "Certificate Updated: {0} [{1}], Reason: {2}", - Severity = 0, - UseLive = true, - UsePersist = true, - UseDisplay = true - } - }; - } - } + { + Id = (int)EventTypeIds.RetrievalStarting, + ModuleId = 60, + Name = "Retrieval Starting", + Format = "Starting retrieval of {0} certificate/s ({1} to {2})", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.RetrievalProgress, + ModuleId = 60, + Name = "Retrieval Progress", + Format = "Processing: {0}; {1}% Complete; Status: {2}", + Severity = 0, + UseLive = true, + UsePersist = false, + UseDisplay = false + }, + new LogEventType + { + Id = (int)EventTypeIds.RetrievalFinished, + ModuleId = 60, + Name = "Retrieval Finished", + Format = "Retrieval of Certificates Complete", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.RetrievalWarning, + ModuleId = 60, + Name = "Retrieval Warning", + Format = "Retrieval Warning: {0}", + Severity = 1, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.RetrievalError, + ModuleId = 60, + Name = "Retrieval Error", + Format = "Retrieval Error: {0}", + Severity = 2, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.RetrievalCertificateStarting, + ModuleId = 60, + Name = "Retrieval Certificate Starting", + Format = "Retrieving Certificate: {0}", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.RetrievalCertificateFinished, + ModuleId = 60, + Name = "Retrieval Certificate Finished", + Format = "Certificate Retrieved: {0}", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.RetrievalCertificateWarning, + ModuleId = 60, + Name = "Retrieval Certificate Warning", + Format = "{0} Certificate Warning: {1}", + Severity = 1, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.RetrievalCertificateError, + ModuleId = 60, + Name = "Retrieval Certificate Error", + Format = "{0} Certificate Error: {1}", + Severity = 2, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.Allocated, + ModuleId = 60, + Name = "Allocated", + Format = "Certificate {0} allocated to {1}", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.AllocationFailed, + ModuleId = 60, + Name = "Allocation Failed", + Format = "No certificates available for Device: {0}", + Severity = 2, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.DisabledCertificate, + ModuleId = 60, + Name = "Disabled Certificate", + Format = "Certificate Disabled: {0} [{1}], Reason: {2}", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.EnabledCertificate, + ModuleId = 60, + Name = "Enabled Certificate", + Format = "Certificate Disabled: {0} [{1}], Reason: {2}", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.DeletedCertificate, + ModuleId = 60, + Name = "Deleted Certificate", + Format = "Certificate Deleted: {0} [{1}], Reason: {2}", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.UpdatedCertificate, + ModuleId = 60, + Name = "Updated Certificate", + Format = "Certificate Updated: {0} [{1}], Reason: {2}", + Severity = 0, + UseLive = true, + UsePersist = true, + UseDisplay = true + } + }; + } + } } diff --git a/Disco.Services/Plugins/Features/CertificateProvider/ProvisionPersonalCertificateResult.cs b/Disco.Services/Plugins/Features/CertificateProvider/ProvisionPersonalCertificateResult.cs new file mode 100644 index 00000000..43a29424 --- /dev/null +++ b/Disco.Services/Plugins/Features/CertificateProvider/ProvisionPersonalCertificateResult.cs @@ -0,0 +1,31 @@ +using Disco.Models.ClientServices; +using Disco.Models.Repository; +using System.Collections.Generic; + +namespace Disco.Services.Plugins.Features.CertificateProvider +{ + public class ProvisionPersonalCertificateResult + { + /// + /// The associated with the provision result. + /// + public Device Device { get; set; } + + /// + /// The associated with the provision result. + /// + public Enrol Enrolment { get; set; } + + /// + /// A list of assigned to the device. + /// + public List AllocatedCertificates { get; set; } + + /// + /// A list of certificate thumbprints to be removed from the Personal Certificate store. + /// Matching certificates will be removed unless they match the . + /// + public List RemoveCertificateThumbprints { get; set; } + + } +} diff --git a/Disco.Services/Plugins/Features/WirelessProfileProvider/ProvisionWirelessProfilesResult.cs b/Disco.Services/Plugins/Features/WirelessProfileProvider/ProvisionWirelessProfilesResult.cs new file mode 100644 index 00000000..dc21ebae --- /dev/null +++ b/Disco.Services/Plugins/Features/WirelessProfileProvider/ProvisionWirelessProfilesResult.cs @@ -0,0 +1,37 @@ +using Disco.Models.ClientServices; +using Disco.Models.Repository; +using System.Collections.Generic; + +namespace Disco.Services.Plugins.Features.WirelessProfileProvider +{ + public class ProvisionWirelessProfilesResult + { + + /// + /// The associated with the provision result. + /// + public Device Device { get; set; } + + /// + /// The associated with the provision result. + /// + public Enrol Enrolment { get; set; } + + /// + /// A list of wireless profiles to add to the client device. + /// If the wireless profile already exists it will be ignored. + /// + public List Profiles { get; set; } + + /// + /// A list of transformations to be applied to existing XML wireless profiles found on the client device. + /// + public List Transformations { get; set; } + + /// + /// A list of wireless profile names to be removed from the client device. + /// + public List RemoveNames { get; set; } + + } +} diff --git a/Disco.Services/Plugins/Features/WirelessProfileProvider/WirelessProfile.cs b/Disco.Services/Plugins/Features/WirelessProfileProvider/WirelessProfile.cs new file mode 100644 index 00000000..a9ea19ee --- /dev/null +++ b/Disco.Services/Plugins/Features/WirelessProfileProvider/WirelessProfile.cs @@ -0,0 +1,29 @@ +using System; + +namespace Disco.Services.Plugins.Features.WirelessProfileProvider +{ + public class WirelessProfile + { + + /// + /// The name of the wireless profile, typically the SSID + /// + public string Name { get; set; } + + /// + /// The guid of the associated interface. Null to deploy to all supported interfaces. + /// + public Guid? InterfaceGuid { get; set; } + + /// + /// Indicates the profile should be overwritten even if it already exists + /// + public bool ForceDeployment { get; set; } + + /// + /// The wireless profile XML definition + /// + public string ProfileXml { get; set; } + + } +} diff --git a/Disco.Services/Plugins/Features/WirelessProfileProvider/WirelessProfileProviderFeature.cs b/Disco.Services/Plugins/Features/WirelessProfileProvider/WirelessProfileProviderFeature.cs new file mode 100644 index 00000000..137b8257 --- /dev/null +++ b/Disco.Services/Plugins/Features/WirelessProfileProvider/WirelessProfileProviderFeature.cs @@ -0,0 +1,16 @@ +using Disco.Data.Repository; +using Disco.Models.ClientServices; +using Disco.Models.Repository; + +namespace Disco.Services.Plugins.Features.WirelessProfileProvider +{ + [PluginFeatureCategory(DisplayName = "Wireless Profile Providers")] + public abstract class WirelessProfileProviderFeature : PluginFeature + { + + public abstract string WirelessProfileProviderId { get; } + + public abstract ProvisionWirelessProfilesResult ProvisionWirelessProfiles(DiscoDataContext Database, Device Device, Enrol Enrolment); + + } +} diff --git a/Disco.Services/Plugins/Features/WirelessProfileProvider/WirelessProfileTransformation.cs b/Disco.Services/Plugins/Features/WirelessProfileProvider/WirelessProfileTransformation.cs new file mode 100644 index 00000000..94bdef7e --- /dev/null +++ b/Disco.Services/Plugins/Features/WirelessProfileProvider/WirelessProfileTransformation.cs @@ -0,0 +1,25 @@ +namespace Disco.Services.Plugins.Features.WirelessProfileProvider +{ + /// + /// A transform to be applied to the matching . + /// + public class WirelessProfileTransformation + { + + /// + /// The name of the wireless profile related to this transformation, typically the SSID + /// + public string Name { get; set; } + + /// + /// The regular expression to evaluate against the wireless profile XML + /// + public string RegularExpression { get; set; } + + /// + /// The replacement string used when evaluating the regular expression + /// + public string RegularExpressionReplacement { get; set; } + + } +} diff --git a/Disco.Services/Plugins/PluginManifest.cs b/Disco.Services/Plugins/PluginManifest.cs index 109dfd9a..b15bdf1b 100644 --- a/Disco.Services/Plugins/PluginManifest.cs +++ b/Disco.Services/Plugins/PluginManifest.cs @@ -134,10 +134,8 @@ namespace Disco.Services.Plugins { return new List() { - "BitMiracle.LibTiff.NET", "C5", "Common.Logging", - "DiffieHellman", "Disco.BI", "Disco.Data", "Disco.Models", @@ -154,14 +152,17 @@ namespace Disco.Services.Plugins "Microsoft.AspNet.SignalR.Core", "Microsoft.AspNet.SignalR.SystemWeb", "Microsoft.Owin", - "Microsoft.Owin.Security", "Microsoft.Owin.Host.SystemWeb", + "Microsoft.Owin.Security", "Microsoft.Web.Infrastructure", "Newtonsoft.Json", - "Org.Mentalis.Security", "Owin", + "PdfiumViewer", + "PdfSharp", + "PList", "Quartz", "RazorGenerator.Mvc", + "Renci.SshNet", "Spring.Core", "System.Data.SqlServerCe", "System.Data.SqlServerCe.Entity", @@ -181,7 +182,6 @@ namespace Disco.Services.Plugins "System.Web.WebPages", "System.Web.WebPages.Razor", "T4MVCExtensions", - "Tamir.SharpSSH", "WebActivatorEx", "zxing" }; diff --git a/Disco.Services/Plugins/Plugins.cs b/Disco.Services/Plugins/Plugins.cs index 2bce21dd..ab4d2e3f 100644 --- a/Disco.Services/Plugins/Plugins.cs +++ b/Disco.Services/Plugins/Plugins.cs @@ -1,7 +1,6 @@ using Disco.Data.Repository; using Disco.Models.Services.Interop.DiscoServices; using Disco.Services.Interop.DiscoServices; -using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; @@ -187,15 +186,22 @@ namespace Disco.Services.Plugins } public static bool TryGetPluginFeature(string PluginFeatureId, Type CategoryType, out PluginFeatureManifest PluginFeatureManifest) { - PluginFeatureManifest = null; - if (_PluginManifests == null) + { + PluginFeatureManifest = null; return false; + } - var featureManifest = _PluginManifests.Values.SelectMany(pm => pm.Features).Where(fm => fm.Id == PluginFeatureId).FirstOrDefault(); + var featureManifest = _PluginManifests.Values + .SelectMany(pm => pm.Features) + .Where(fm => fm.Id == PluginFeatureId) + .FirstOrDefault(); if (featureManifest == null) + { + PluginFeatureManifest = null; return false; + } if (CategoryType == null) { @@ -210,7 +216,10 @@ namespace Disco.Services.Plugins return true; } else + { + PluginFeatureManifest = null; return false; + } } } public static PluginFeatureManifest GetPluginFeature(string PluginFeatureId) diff --git a/Disco.Services/Properties/AssemblyInfo.cs b/Disco.Services/Properties/AssemblyInfo.cs index d1ab544f..8b6a8433 100644 --- a/Disco.Services/Properties/AssemblyInfo.cs +++ b/Disco.Services/Properties/AssemblyInfo.cs @@ -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.1.0.0")] -[assembly: AssemblyFileVersion("2.1.0.0")] \ No newline at end of file +[assembly: AssemblyVersion("2.2.16272.1003")] +[assembly: AssemblyFileVersion("2.2.16272.1003")] \ No newline at end of file diff --git a/Disco.Services/Tasks/IScheduledTaskStatus.cs b/Disco.Services/Tasks/IScheduledTaskStatus.cs index 26586395..6a01899f 100644 --- a/Disco.Services/Tasks/IScheduledTaskStatus.cs +++ b/Disco.Services/Tasks/IScheduledTaskStatus.cs @@ -37,5 +37,8 @@ namespace Disco.Services.Tasks void Finished(string FinishedMessage, string FinishedUrl); void SetTaskException(Exception TaskException); + + void LogWarning(string Message); + void LogInformation(string Message); } } diff --git a/Disco.Services/Tasks/ScheduledTaskMockStatus.cs b/Disco.Services/Tasks/ScheduledTaskMockStatus.cs index 8adef281..1ad96bfa 100644 --- a/Disco.Services/Tasks/ScheduledTaskMockStatus.cs +++ b/Disco.Services/Tasks/ScheduledTaskMockStatus.cs @@ -1,13 +1,11 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Disco.Services.Tasks { public class ScheduledTaskMockStatus : IScheduledTaskStatus { + public string TaskName { get; private set; } + public byte Progress { get; set; } public string CurrentProcess { get; set; } public string CurrentDescription { get; set; } @@ -22,6 +20,11 @@ namespace Disco.Services.Tasks public Exception TaskException { get; set; } + public ScheduledTaskMockStatus(string TaskName) + { + this.TaskName = TaskName; + } + private byte CalculateProgressValue(byte Progress) { return (byte)((Progress * this.ProgressMultiplier) + this.ProgressOffset); @@ -90,11 +93,25 @@ namespace Disco.Services.Tasks this.TaskException = TaskException; } + public void LogWarning(string Message) + { + ScheduledTasksLog.LogScheduledTaskWarning(TaskName, null, Message); + } + public void LogInformation(string Message) + { + ScheduledTasksLog.LogScheduledTaskInformation(TaskName, null, Message); + } + [Obsolete("Use the constructor which requires a TaskName instead")] public static ScheduledTaskMockStatus Create() { - return new ScheduledTaskMockStatus(); + return new ScheduledTaskMockStatus("Unknown Task"); + } + + public static ScheduledTaskMockStatus Create(string TaskName) + { + return new ScheduledTaskMockStatus(TaskName); } } } diff --git a/Disco.Services/Tasks/ScheduledTaskStatus.cs b/Disco.Services/Tasks/ScheduledTaskStatus.cs index 6d406453..39645fc8 100644 --- a/Disco.Services/Tasks/ScheduledTaskStatus.cs +++ b/Disco.Services/Tasks/ScheduledTaskStatus.cs @@ -111,6 +111,16 @@ namespace Disco.Services.Tasks this._progress = 0; } + public void LogWarning(string Message) + { + ScheduledTasksLog.LogScheduledTaskWarning(TaskName, SessionId, Message); + } + + public void LogInformation(string Message) + { + ScheduledTasksLog.LogScheduledTaskInformation(TaskName, SessionId, Message); + } + #region Progress Actions private byte CalculateProgressValue(byte Progress) { diff --git a/Disco.Services/Tasks/ScheduledTasksLog.cs b/Disco.Services/Tasks/ScheduledTasksLog.cs index 7cd0e678..312f86f7 100644 --- a/Disco.Services/Tasks/ScheduledTasksLog.cs +++ b/Disco.Services/Tasks/ScheduledTasksLog.cs @@ -25,6 +25,8 @@ namespace Disco.Services.Tasks InitializeScheduledTasksExceptionWithInner, ScheduledTasksException = 30, ScheduledTasksExceptionWithInner, + ScheduledTasksWarning, + ScheduledTasksInformation, ScheduledTaskExecuted = 50, ScheduledTaskFinished = 80, } @@ -98,6 +100,16 @@ namespace Disco.Services.Tasks } } + public static void LogScheduledTaskInformation(string ScheduledTaskName, string SessionId, string Message) + { + Log(EventTypeIds.ScheduledTasksInformation, ScheduledTaskName, SessionId, Message); + } + + public static void LogScheduledTaskWarning(string ScheduledTaskName, string SessionId, string Message) + { + Log(EventTypeIds.ScheduledTasksWarning, ScheduledTaskName, SessionId, Message); + } + protected override List LoadEventTypes() { return new System.Collections.Generic.List @@ -178,7 +190,29 @@ namespace Disco.Services.Tasks UseLive = true, UsePersist = true, UseDisplay = true - }, + }, + new LogEventType + { + Id = (int)EventTypeIds.ScheduledTasksWarning, + ModuleId = _ModuleId, + Name = "Scheduled Task Warning", + Format = "Scheduled Task '{0}' Warning: {2}; Session Id: {1}", + Severity = (int)LogEventType.Severities.Warning, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, + new LogEventType + { + Id = (int)EventTypeIds.ScheduledTasksInformation, + ModuleId = _ModuleId, + Name = "Scheduled Task Information", + Format = "Scheduled Task '{0}' Information: {2}; Session Id: {1}", + Severity = (int)LogEventType.Severities.Information, + UseLive = true, + UsePersist = true, + UseDisplay = true + }, new LogEventType { Id = (int)EventTypeIds.ScheduledTaskExecuted, @@ -201,7 +235,7 @@ namespace Disco.Services.Tasks UsePersist = true, UseDisplay = true } - }; + }; } } } diff --git a/Disco.Services/Users/UserExtensions.cs b/Disco.Services/Users/UserExtensions.cs index 5e84590f..72edb2ba 100644 --- a/Disco.Services/Users/UserExtensions.cs +++ b/Disco.Services/Users/UserExtensions.cs @@ -1,6 +1,10 @@ -using Disco.Models.Repository; +using Disco.Data.Repository; +using Disco.Models.Repository; +using Disco.Models.Services.Documents; using Disco.Services.Interop.ActiveDirectory; using System; +using System.Collections.Generic; +using System.Linq; namespace Disco.Services { @@ -20,5 +24,29 @@ namespace Disco.Services { return ActiveDirectory.FriendlyAccountId(u.UserId); } + + public static List AvailableDocumentTemplates(this User u, DiscoDataContext Database, User User, DateTime TimeStamp) + { + var dts = Database.DocumentTemplates.Include("JobSubTypes") + .Where(dt => dt.Scope == DocumentTemplate.DocumentTemplateScopes.User) + .ToArray() + .Where(dt => dt.FilterExpressionMatches(u, Database, User, TimeStamp, DocumentState.DefaultState())).ToList(); + + return dts; + } + + public static List CurrentDeviceUserAssignments(this User u) + { + return u.DeviceUserAssignments.Where(dua => !dua.UnassignedDate.HasValue).ToList(); + } + + public static bool CanCreateJob(this User u) + { + if (!JobActionExtensions.CanCreate()) + return false; + + return true; + } + } } diff --git a/Disco.BI/BI/Extensions/UserFlagActionExtensions.cs b/Disco.Services/Users/UserFlags/UserFlagExtensions.cs similarity index 94% rename from Disco.BI/BI/Extensions/UserFlagActionExtensions.cs rename to Disco.Services/Users/UserFlags/UserFlagExtensions.cs index aae008bb..76b71dfa 100644 --- a/Disco.BI/BI/Extensions/UserFlagActionExtensions.cs +++ b/Disco.Services/Users/UserFlags/UserFlagExtensions.cs @@ -3,14 +3,11 @@ using Disco.Models.Repository; using Disco.Services.Authorization; using Disco.Services.Users; using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; -namespace Disco.BI.Extensions +namespace Disco.Services { - public static class UserFlagActionExtensions + public static class UserFlagExtensions { #region Edit Comments diff --git a/Disco.Services/packages.config b/Disco.Services/packages.config index 05b75e64..12f91a3a 100644 --- a/Disco.Services/packages.config +++ b/Disco.Services/packages.config @@ -18,6 +18,7 @@ + diff --git a/Disco.Web.Extensions/BIModelExtensions/PluginExtensions.cs b/Disco.Web.Extensions/BIModelExtensions/PluginExtensions.cs index 675f50eb..7228f208 100644 --- a/Disco.Web.Extensions/BIModelExtensions/PluginExtensions.cs +++ b/Disco.Web.Extensions/BIModelExtensions/PluginExtensions.cs @@ -11,12 +11,12 @@ namespace Disco.Web.Extensions { public static List ToSelectListItems(this IEnumerable PluginFeatureDefinitions, PluginFeatureManifest SelectedItem) { - string selectedId = default(string); + return PluginFeatureDefinitions.ToSelectListItems(SelectedItem?.Id, false, null); + } - if (SelectedItem != null) - selectedId = SelectedItem.Id; - - return PluginFeatureDefinitions.ToSelectListItems(selectedId, false, null); + public static List ToSelectListItems(this IEnumerable PluginFeatureDefinitions, IEnumerable SelectedItems) + { + return PluginFeatureDefinitions.ToSelectListItems(SelectedItems?.Select(i => i.Id), false, null); } public static List ToSelectListItems(this IEnumerable PluginDefinitions, string SelectedId = null, bool IncludeInstructionFirst = false, string InstructionMessage = "Select a Plugin") @@ -24,18 +24,36 @@ namespace Disco.Web.Extensions return ToSelectListItems(PluginDefinitions, SelectedId, IncludeInstructionFirst, InstructionMessage, null); } + public static List ToSelectListItems(this IEnumerable PluginDefinitions, IEnumerable SelectedIds = null, bool IncludeInstructionFirst = false, string InstructionMessage = "Select a Plugin") + { + return ToSelectListItems(PluginDefinitions, SelectedIds, IncludeInstructionFirst, InstructionMessage, null); + } + public static List ToSelectListItems(this IEnumerable PluginDefinitions, string SelectedId = null, bool IncludeInstructionFirst = false, string InstructionMessage = "Select a Plugin", Dictionary AdditionalItems = null) { + string[] selectedIds = null; + if (SelectedId != null) + { + selectedIds = new string[] { SelectedId }; + } + + return ToSelectListItems(PluginDefinitions, selectedIds, IncludeInstructionFirst, InstructionMessage, AdditionalItems); + } + + public static List ToSelectListItems(this IEnumerable PluginDefinitions, IEnumerable SelectedIds = null, bool IncludeInstructionFirst = false, string InstructionMessage = "Select a Plugin", Dictionary AdditionalItems = null) + { + var selectedIds = SelectedIds?.ToList(); + var items = PluginDefinitions - .Select(wpd => new SelectListItem { Value = wpd.Id, Text = wpd.Name, Selected = (SelectedId != null && SelectedId.Equals(wpd.Id)) }); + .Select(wpd => new SelectListItem { Value = wpd.Id, Text = wpd.Name, Selected = (selectedIds?.Contains(wpd.Id, StringComparer.Ordinal) ?? false) }); if (AdditionalItems != null) - items = items.Concat(AdditionalItems.Select(i => new SelectListItem { Value = i.Key, Text = i.Value, Selected = (SelectedId != null && SelectedId.Equals(i.Key)) })); + items = items.Concat(AdditionalItems.Select(i => new SelectListItem { Value = i.Key, Text = i.Value, Selected = (selectedIds?.Contains(i.Key, StringComparer.Ordinal) ?? false) })); var selectItems = items.OrderBy(i => i.Text).ToList(); if (IncludeInstructionFirst) - selectItems.Insert(0, new SelectListItem() { Value = String.Empty, Text = String.Format("<{0}>", InstructionMessage), Selected = String.IsNullOrEmpty(SelectedId) }); + selectItems.Insert(0, new SelectListItem() { Value = String.Empty, Text = String.Format("<{0}>", InstructionMessage), Selected = (selectedIds?.Count ?? 0) != 0 }); return selectItems; } diff --git a/Disco.Web.Extensions/Disco.Web.Extensions.csproj b/Disco.Web.Extensions/Disco.Web.Extensions.csproj index ab713f1d..df3040cd 100644 --- a/Disco.Web.Extensions/Disco.Web.Extensions.csproj +++ b/Disco.Web.Extensions/Disco.Web.Extensions.csproj @@ -15,6 +15,7 @@ ..\ true + 2.2.16272.1003 true diff --git a/Disco.Web.Extensions/Properties/AssemblyInfo.cs b/Disco.Web.Extensions/Properties/AssemblyInfo.cs index 49334fc9..2d0594d8 100644 --- a/Disco.Web.Extensions/Properties/AssemblyInfo.cs +++ b/Disco.Web.Extensions/Properties/AssemblyInfo.cs @@ -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.1.0.0")] -[assembly: AssemblyFileVersion("2.1.0.0")] \ No newline at end of file +[assembly: AssemblyVersion("2.2.16272.1003")] +[assembly: AssemblyFileVersion("2.2.16272.1003")] \ No newline at end of file diff --git a/Disco.Web/App_Code/CommonHelpers.cshtml b/Disco.Web/App_Code/CommonHelpers.cshtml index 50573b85..2a0abe9e 100644 --- a/Disco.Web/App_Code/CommonHelpers.cshtml +++ b/Disco.Web/App_Code/CommonHelpers.cshtml @@ -66,11 +66,19 @@ @helper RadioButtonList(string id, List items, int columns = 1) { - @ItemList("radio", id, items, columns) + @ItemList(null, "radio", id, items, columns) +} +@helper RadioButtonList(string containerName, string id, List items, int columns = 1) +{ + @ItemList(containerName, "radio", id, items, columns) } @helper CheckBoxList(string id, List items, int columns = 1, bool alignEven = true, int? forceUniqueIds = null, bool htmlEncodeText = true) { - @ItemList("checkbox", id, items, columns, alignEven, forceUniqueIds, htmlEncodeText) + @ItemList(null, "checkbox", id, items, columns, alignEven, forceUniqueIds, htmlEncodeText) +} +@helper CheckBoxList(string containerName, string id, List items, int columns = 1, bool alignEven = true, int? forceUniqueIds = null, bool htmlEncodeText = true) +{ + @ItemList(containerName, "checkbox", id, items, columns, alignEven, forceUniqueIds, htmlEncodeText) } @helper CheckboxBulkSelect(string BulkSelectContainerId, string ParentJQuerySelector = null) {Html.GetPageHelper().BundleDeferred("~/ClientScripts/Modules/Disco-jQueryExtensions"); @@ -85,12 +93,12 @@ } } -@helper ItemList(string inputType, string id, List items, int columns = 1, bool alignEven = true, int? forceUniqueIds = null, bool htmlEncodeText = true) +@helper ItemList(string containerId, string inputType, string id, List items, int columns = 1, bool alignEven = true, int? forceUniqueIds = null, bool htmlEncodeText = true) { int itemsPerColumn = items.Count / columns; int columnWidth = (100 / columns); var itemNextId = 0; - +
@for (int i = 0; i < columns; i++) { diff --git a/Disco.Web/App_Code/CommonHelpers.generated.cs b/Disco.Web/App_Code/CommonHelpers.generated.cs index 97db9500..1a93c415 100644 --- a/Disco.Web/App_Code/CommonHelpers.generated.cs +++ b/Disco.Web/App_Code/CommonHelpers.generated.cs @@ -2,7 +2,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -76,542 +76,552 @@ namespace Disco.Web public class CommonHelpers : System.Web.WebPages.HelperPage { +#line 11 "..\..\App_Code\CommonHelpers.cshtml" public static System.Web.WebPages.HelperResult FriendlyDate(DateTime d, string ElementId = null, bool WithoutSuffix = false) { +#line default +#line hidden return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - - -WriteLiteralTo(@__razor_helper_writer, ""); - +WriteLiteralTo(__razor_helper_writer, ""); #line 12 "..\..\App_Code\CommonHelpers.cshtml" + #line default #line hidden - }); - } - +#line 12 "..\..\App_Code\CommonHelpers.cshtml" +} +#line default +#line hidden +#line 13 "..\..\App_Code\CommonHelpers.cshtml" public static System.Web.WebPages.HelperResult FriendlyDate(DateTime? d, string NullValue = "n/a", string ElementId = null, bool WithoutSuffix = false) { +#line default +#line hidden return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - - -WriteLiteralTo(@__razor_helper_writer, ""); - +WriteLiteralTo(__razor_helper_writer, ""); #line 14 "..\..\App_Code\CommonHelpers.cshtml" + +#line default +#line hidden +}); + +#line 14 "..\..\App_Code\CommonHelpers.cshtml" +} #line default #line hidden -}); - - } - - +#line 15 "..\..\App_Code\CommonHelpers.cshtml" public static System.Web.WebPages.HelperResult FriendlyDateAndUser(DateTime? d, User u, string DateNullValue = "n/a", bool WithoutSuffix = false) { +#line default +#line hidden return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - #line 16 "..\..\App_Code\CommonHelpers.cshtml" + #line default #line hidden - #line 17 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, FriendlyDate(d, DateNullValue, WithoutSuffix: WithoutSuffix)); +WriteTo(__razor_helper_writer, FriendlyDate(d, DateNullValue, WithoutSuffix: WithoutSuffix)); + #line default #line hidden - #line 17 "..\..\App_Code\CommonHelpers.cshtml" ; + #line default #line hidden - #line 18 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, FriendlyUser(u, null, " by")); +WriteTo(__razor_helper_writer, FriendlyUser(u, null, " by")); + #line default #line hidden - #line 18 "..\..\App_Code\CommonHelpers.cshtml" ; + +#line default +#line hidden +}); + +#line 19 "..\..\App_Code\CommonHelpers.cshtml" +} #line default #line hidden -}); - -} - - +#line 20 "..\..\App_Code\CommonHelpers.cshtml" public static System.Web.WebPages.HelperResult FriendlyDateAndUser(DateTime d, User u, bool WithoutSuffix = false) { +#line default +#line hidden return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - #line 21 "..\..\App_Code\CommonHelpers.cshtml" + #line default #line hidden - #line 22 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, FriendlyDate(d, WithoutSuffix: WithoutSuffix)); +WriteTo(__razor_helper_writer, FriendlyDate(d, WithoutSuffix: WithoutSuffix)); + #line default #line hidden - #line 22 "..\..\App_Code\CommonHelpers.cshtml" ; + #line default #line hidden - #line 23 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, FriendlyUser(u, null, " by")); +WriteTo(__razor_helper_writer, FriendlyUser(u, null, " by")); + #line default #line hidden - #line 23 "..\..\App_Code\CommonHelpers.cshtml" ; + +#line default +#line hidden +}); + +#line 24 "..\..\App_Code\CommonHelpers.cshtml" +} #line default #line hidden -}); - -} - - +#line 25 "..\..\App_Code\CommonHelpers.cshtml" public static System.Web.WebPages.HelperResult FriendlyDateAndUser(DateTime? d, string UserId, string DateNullValue = "n/a", bool WithoutSuffix = false) { +#line default +#line hidden return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - #line 26 "..\..\App_Code\CommonHelpers.cshtml" + #line default #line hidden - #line 27 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, FriendlyDate(d, DateNullValue, WithoutSuffix: WithoutSuffix)); +WriteTo(__razor_helper_writer, FriendlyDate(d, DateNullValue, WithoutSuffix: WithoutSuffix)); + #line default #line hidden - #line 27 "..\..\App_Code\CommonHelpers.cshtml" ; + #line default #line hidden - #line 28 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, FriendlyUser(UserId, null, " by")); +WriteTo(__razor_helper_writer, FriendlyUser(UserId, null, " by")); + #line default #line hidden - #line 28 "..\..\App_Code\CommonHelpers.cshtml" ; + +#line default +#line hidden +}); + +#line 29 "..\..\App_Code\CommonHelpers.cshtml" +} #line default #line hidden -}); - -} - - +#line 30 "..\..\App_Code\CommonHelpers.cshtml" public static System.Web.WebPages.HelperResult FriendlyDateAndUser(DateTime d, string UserId, bool WithoutSuffix = false) { +#line default +#line hidden return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - #line 31 "..\..\App_Code\CommonHelpers.cshtml" + #line default #line hidden - #line 32 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, FriendlyDate(d, WithoutSuffix: WithoutSuffix)); +WriteTo(__razor_helper_writer, FriendlyDate(d, WithoutSuffix: WithoutSuffix)); + #line default #line hidden - #line 32 "..\..\App_Code\CommonHelpers.cshtml" ; + #line default #line hidden - #line 33 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, FriendlyUser(UserId, null, " by")); +WriteTo(__razor_helper_writer, FriendlyUser(UserId, null, " by")); + #line default #line hidden - #line 33 "..\..\App_Code\CommonHelpers.cshtml" ; + +#line default +#line hidden +}); + +#line 34 "..\..\App_Code\CommonHelpers.cshtml" +} #line default #line hidden -}); - -} - - +#line 35 "..\..\App_Code\CommonHelpers.cshtml" public static System.Web.WebPages.HelperResult FriendlyDateAndTitleUser(DateTime? d, User u, string DateNullValue = "n/a", bool WithoutSuffix = false) { +#line default +#line hidden return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - #line 36 "..\..\App_Code\CommonHelpers.cshtml" + #line default #line hidden +WriteLiteralTo(__razor_helper_writer, " (d.ToFullDateTime(DateNullValue) + +#line default +#line hidden +, 1941), false) +, Tuple.Create(Tuple.Create(" ", 1973), Tuple.Create("by", 1974), true) + +#line 37 "..\..\App_Code\CommonHelpers.cshtml" +, Tuple.Create(Tuple.Create(" ", 1976), Tuple.Create(u + +#line default +#line hidden +, 1977), false) +); + +WriteLiteralTo(__razor_helper_writer, " data-livestamp=\""); #line 37 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, d.ToFullDateTime(DateNullValue)); + WriteTo(__razor_helper_writer, d.ToUnixEpoc()); + #line default #line hidden +WriteLiteralTo(__razor_helper_writer, "\""); -WriteLiteralTo(@__razor_helper_writer, " by "); +WriteAttributeTo(__razor_helper_writer, "class", Tuple.Create(" class=\"", 2013), Tuple.Create("\"", 2075) +, Tuple.Create(Tuple.Create("", 2021), Tuple.Create("date", 2021), true) +, Tuple.Create(Tuple.Create(" ", 2025), Tuple.Create("nowrap", 2026), true) +#line 37 "..\..\App_Code\CommonHelpers.cshtml" + , Tuple.Create(Tuple.Create("", 2032), Tuple.Create(WithoutSuffix ? " noMomentSuffix" : null + +#line default +#line hidden +, 2032), false) +); + +WriteLiteralTo(__razor_helper_writer, ">"); #line 37 "..\..\App_Code\CommonHelpers.cshtml" - WriteTo(@__razor_helper_writer, u); + WriteTo(__razor_helper_writer, d.ToFullDateTime(DateNullValue)); + #line default #line hidden - -WriteLiteralTo(@__razor_helper_writer, "\" data-livestamp=\""); - - - -#line 37 "..\..\App_Code\CommonHelpers.cshtml" - WriteTo(@__razor_helper_writer, d.ToUnixEpoc()); - -#line default -#line hidden - -WriteLiteralTo(@__razor_helper_writer, "\" class=\"date nowrap"); - - - -#line 37 "..\..\App_Code\CommonHelpers.cshtml" - WriteTo(@__razor_helper_writer, WithoutSuffix ? " noMomentSuffix" : null); - -#line default -#line hidden - -WriteLiteralTo(@__razor_helper_writer, "\">"); - - - -#line 37 "..\..\App_Code\CommonHelpers.cshtml" - WriteTo(@__razor_helper_writer, d.ToFullDateTime(DateNullValue)); - -#line default -#line hidden - -WriteLiteralTo(@__razor_helper_writer, "\r\n"); - +WriteLiteralTo(__razor_helper_writer, "\r\n"); #line 38 "..\..\App_Code\CommonHelpers.cshtml" + +#line default +#line hidden +}); + +#line 38 "..\..\App_Code\CommonHelpers.cshtml" +} #line default #line hidden -}); - -} - - +#line 39 "..\..\App_Code\CommonHelpers.cshtml" public static System.Web.WebPages.HelperResult FriendlyDateAndTitleUser(DateTime d, User u, bool WithoutSuffix = false) { +#line default +#line hidden return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - #line 40 "..\..\App_Code\CommonHelpers.cshtml" + #line default #line hidden +WriteLiteralTo(__razor_helper_writer, " (d.ToFullDateTime() + +#line default +#line hidden +, 2223), false) +, Tuple.Create(Tuple.Create(" ", 2242), Tuple.Create("by", 2243), true) + +#line 41 "..\..\App_Code\CommonHelpers.cshtml" +, Tuple.Create(Tuple.Create(" ", 2245), Tuple.Create(u + +#line default +#line hidden +, 2246), false) +); + +WriteLiteralTo(__razor_helper_writer, " data-livestamp=\""); #line 41 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, d.ToFullDateTime()); + WriteTo(__razor_helper_writer, d.ToUnixEpoc()); + #line default #line hidden +WriteLiteralTo(__razor_helper_writer, "\""); -WriteLiteralTo(@__razor_helper_writer, " by "); +WriteAttributeTo(__razor_helper_writer, "class", Tuple.Create(" class=\"", 2282), Tuple.Create("\"", 2344) +, Tuple.Create(Tuple.Create("", 2290), Tuple.Create("date", 2290), true) +, Tuple.Create(Tuple.Create(" ", 2294), Tuple.Create("nowrap", 2295), true) +#line 41 "..\..\App_Code\CommonHelpers.cshtml" + , Tuple.Create(Tuple.Create("", 2301), Tuple.Create(WithoutSuffix ? " noMomentSuffix" : null + +#line default +#line hidden +, 2301), false) +); + +WriteLiteralTo(__razor_helper_writer, ">"); #line 41 "..\..\App_Code\CommonHelpers.cshtml" - WriteTo(@__razor_helper_writer, u); + WriteTo(__razor_helper_writer, d.ToFullDateTime()); + #line default #line hidden - -WriteLiteralTo(@__razor_helper_writer, "\" data-livestamp=\""); - - - -#line 41 "..\..\App_Code\CommonHelpers.cshtml" - WriteTo(@__razor_helper_writer, d.ToUnixEpoc()); - -#line default -#line hidden - -WriteLiteralTo(@__razor_helper_writer, "\" class=\"date nowrap"); - - - -#line 41 "..\..\App_Code\CommonHelpers.cshtml" - WriteTo(@__razor_helper_writer, WithoutSuffix ? " noMomentSuffix" : null); - -#line default -#line hidden - -WriteLiteralTo(@__razor_helper_writer, "\">"); - - - -#line 41 "..\..\App_Code\CommonHelpers.cshtml" - WriteTo(@__razor_helper_writer, d.ToFullDateTime()); - -#line default -#line hidden - -WriteLiteralTo(@__razor_helper_writer, "\r\n"); - +WriteLiteralTo(__razor_helper_writer, "\r\n"); #line 42 "..\..\App_Code\CommonHelpers.cshtml" + +#line default +#line hidden +}); + +#line 42 "..\..\App_Code\CommonHelpers.cshtml" +} #line default #line hidden -}); - -} - - +#line 43 "..\..\App_Code\CommonHelpers.cshtml" public static System.Web.WebPages.HelperResult FriendlyUser(User u, string nullValue = null, string prepend = null) { +#line default +#line hidden return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - #line 44 "..\..\App_Code\CommonHelpers.cshtml" if (u != null) { + #line default #line hidden +#line 47 "..\..\App_Code\CommonHelpers.cshtml" +WriteTo(__razor_helper_writer, prepend); + + +#line default +#line hidden +WriteLiteralTo(__razor_helper_writer, " (u + +#line default +#line hidden +, 2512), false) +); + +WriteLiteralTo(__razor_helper_writer, ">"); + #line 47 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, prepend); +WriteTo(__razor_helper_writer, u.FriendlyId()); + #line default #line hidden - - -WriteLiteralTo(@__razor_helper_writer, " \r\n"); - +WriteLiteralTo(__razor_helper_writer, "\r\n"); #line 48 "..\..\App_Code\CommonHelpers.cshtml" @@ -619,68 +629,66 @@ WriteLiteralTo(@__razor_helper_writer, "\r\n"); else { + #line default #line hidden - -WriteLiteralTo(@__razor_helper_writer, " "); - +WriteLiteralTo(__razor_helper_writer, " "); #line 51 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, nullValue); +WriteTo(__razor_helper_writer, nullValue); + #line default #line hidden - -WriteLiteralTo(@__razor_helper_writer, "\r\n"); - +WriteLiteralTo(__razor_helper_writer, "\r\n"); #line 52 "..\..\App_Code\CommonHelpers.cshtml" } + +#line default +#line hidden +}); + +#line 53 "..\..\App_Code\CommonHelpers.cshtml" +} #line default #line hidden -}); - -} - - +#line 54 "..\..\App_Code\CommonHelpers.cshtml" public static System.Web.WebPages.HelperResult FriendlyUser(string UserId, string nullValue = null, string prepend = null) { +#line default +#line hidden return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - #line 55 "..\..\App_Code\CommonHelpers.cshtml" if (UserId != null) { + #line default #line hidden +#line 58 "..\..\App_Code\CommonHelpers.cshtml" +WriteTo(__razor_helper_writer, prepend); + + +#line default +#line hidden +WriteLiteralTo(__razor_helper_writer, " "); + #line 58 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, prepend); +WriteTo(__razor_helper_writer, Disco.Services.Interop.ActiveDirectory.ActiveDirectory.FriendlyAccountId(UserId)); + #line default #line hidden - - -WriteLiteralTo(@__razor_helper_writer, " "); - - - -#line 58 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, Disco.Services.Interop.ActiveDirectory.ActiveDirectory.FriendlyAccountId(UserId)); - -#line default -#line hidden - -WriteLiteralTo(@__razor_helper_writer, "\r\n"); - +WriteLiteralTo(__razor_helper_writer, "\r\n"); #line 59 "..\..\App_Code\CommonHelpers.cshtml" @@ -688,236 +696,352 @@ WriteLiteralTo(@__razor_helper_writer, "\r\n"); else { + #line default #line hidden - -WriteLiteralTo(@__razor_helper_writer, " "); - +WriteLiteralTo(__razor_helper_writer, " "); #line 62 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, nullValue); +WriteTo(__razor_helper_writer, nullValue); + #line default #line hidden - -WriteLiteralTo(@__razor_helper_writer, "\r\n"); - +WriteLiteralTo(__razor_helper_writer, "\r\n"); #line 63 "..\..\App_Code\CommonHelpers.cshtml" } + +#line default +#line hidden +}); + +#line 64 "..\..\App_Code\CommonHelpers.cshtml" +} #line default #line hidden -}); - -} - - +#line 67 "..\..\App_Code\CommonHelpers.cshtml" public static System.Web.WebPages.HelperResult RadioButtonList(string id, List items, int columns = 1) { +#line default +#line hidden return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - #line 68 "..\..\App_Code\CommonHelpers.cshtml" + #line default #line hidden - #line 69 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, ItemList("radio", id, items, columns)); +WriteTo(__razor_helper_writer, ItemList(null, "radio", id, items, columns)); + #line default #line hidden - #line 69 "..\..\App_Code\CommonHelpers.cshtml" - + + #line default #line hidden - }); +#line 70 "..\..\App_Code\CommonHelpers.cshtml" } +#line default +#line hidden - -public static System.Web.WebPages.HelperResult CheckBoxList(string id, List items, int columns = 1, bool alignEven = true, int? forceUniqueIds = null, bool htmlEncodeText = true) +#line 71 "..\..\App_Code\CommonHelpers.cshtml" +public static System.Web.WebPages.HelperResult RadioButtonList(string containerName, string id, List items, int columns = 1) { +#line default +#line hidden return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - #line 72 "..\..\App_Code\CommonHelpers.cshtml" + #line default #line hidden - #line 73 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, ItemList("checkbox", id, items, columns, alignEven, forceUniqueIds, htmlEncodeText)); +WriteTo(__razor_helper_writer, ItemList(containerName, "radio", id, items, columns)); + #line default #line hidden - #line 73 "..\..\App_Code\CommonHelpers.cshtml" - + + #line default #line hidden - }); +#line 74 "..\..\App_Code\CommonHelpers.cshtml" } +#line default +#line hidden - -public static System.Web.WebPages.HelperResult CheckboxBulkSelect(string BulkSelectContainerId, string ParentJQuerySelector = null) +#line 75 "..\..\App_Code\CommonHelpers.cshtml" +public static System.Web.WebPages.HelperResult CheckBoxList(string id, List items, int columns = 1, bool alignEven = true, int? forceUniqueIds = null, bool htmlEncodeText = true) { +#line default +#line hidden return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - #line 76 "..\..\App_Code\CommonHelpers.cshtml" - Html.GetPageHelper().BundleDeferred("~/ClientScripts/Modules/Disco-jQueryExtensions"); + + #line default #line hidden -WriteLiteralTo(@__razor_helper_writer, " \r\n"); - - - -#line 87 "..\..\App_Code\CommonHelpers.cshtml" #line default #line hidden +WriteLiteralTo(__razor_helper_writer, " \r\n"); + +#line 95 "..\..\App_Code\CommonHelpers.cshtml" + + +#line default +#line hidden }); +#line 95 "..\..\App_Code\CommonHelpers.cshtml" } +#line default +#line hidden - -public static System.Web.WebPages.HelperResult ItemList(string inputType, string id, List items, int columns = 1, bool alignEven = true, int? forceUniqueIds = null, bool htmlEncodeText = true) +#line 96 "..\..\App_Code\CommonHelpers.cshtml" +public static System.Web.WebPages.HelperResult ItemList(string containerId, string inputType, string id, List items, int columns = 1, bool alignEven = true, int? forceUniqueIds = null, bool htmlEncodeText = true) { +#line default +#line hidden return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - -#line 89 "..\..\App_Code\CommonHelpers.cshtml" +#line 97 "..\..\App_Code\CommonHelpers.cshtml" int itemsPerColumn = items.Count / columns; int columnWidth = (100 / columns); var itemNextId = 0; + +#line default +#line hidden +WriteLiteralTo(__razor_helper_writer, " (containerId + +#line default +#line hidden +, 4847), false) +); + +WriteLiteralTo(__razor_helper_writer, " class=\"none\""); + +WriteLiteralTo(__razor_helper_writer, ">\r\n \r\n"); + + +#line 103 "..\..\App_Code\CommonHelpers.cshtml" + + #line default #line hidden -WriteLiteralTo(@__razor_helper_writer, "
\r\n \r\n"); - - - -#line 95 "..\..\App_Code\CommonHelpers.cshtml" +#line 103 "..\..\App_Code\CommonHelpers.cshtml" for (int i = 0; i < columns; i++) { + #line default #line hidden - -WriteLiteralTo(@__razor_helper_writer, " \r\n
\r\n"); - - - -#line 118 "..\..\App_Code\CommonHelpers.cshtml" #line default #line hidden +WriteLiteralTo(__razor_helper_writer, " \r\n \r\n"); + +#line 126 "..\..\App_Code\CommonHelpers.cshtml" + + +#line default +#line hidden }); +#line 126 "..\..\App_Code\CommonHelpers.cshtml" } +#line default +#line hidden - +#line 129 "..\..\App_Code\CommonHelpers.cshtml" public static System.Web.WebPages.HelperResult Breadcrumbs(List> BreadCrumbs) { +#line default +#line hidden return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - -#line 122 "..\..\App_Code\CommonHelpers.cshtml" +#line 130 "..\..\App_Code\CommonHelpers.cshtml" for (int index = 0; index < BreadCrumbs.Count; index++) { @@ -1081,97 +1201,102 @@ return new System.Web.WebPages.HelperResult(__razor_helper_writer => { if (index != 0) { + #line default #line hidden - -WriteLiteralTo(@__razor_helper_writer, " >\r\n"); +WriteLiteralTo(__razor_helper_writer, " >\r\n"); - -#line 129 "..\..\App_Code\CommonHelpers.cshtml" +#line 137 "..\..\App_Code\CommonHelpers.cshtml" } if (breadCrumb.Item2 == null) { -#line default -#line hidden - - -#line 132 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, breadCrumb.Item1); #line default #line hidden +#line 140 "..\..\App_Code\CommonHelpers.cshtml" +WriteTo(__razor_helper_writer, breadCrumb.Item1); -#line 132 "..\..\App_Code\CommonHelpers.cshtml" + +#line default +#line hidden + +#line 140 "..\..\App_Code\CommonHelpers.cshtml" } else { -#line default -#line hidden - - -#line 136 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, Html.GetPageHelper().ActionLink(breadCrumb.Item1, breadCrumb.Item2)); #line default #line hidden +#line 144 "..\..\App_Code\CommonHelpers.cshtml" +WriteTo(__razor_helper_writer, Html.GetPageHelper().ActionLink(breadCrumb.Item1, breadCrumb.Item2)); -#line 136 "..\..\App_Code\CommonHelpers.cshtml" + +#line default +#line hidden + +#line 144 "..\..\App_Code\CommonHelpers.cshtml" } } + +#line default +#line hidden +}); + +#line 147 "..\..\App_Code\CommonHelpers.cshtml" +} #line default #line hidden -}); - -} - - +#line 148 "..\..\App_Code\CommonHelpers.cshtml" public static System.Web.WebPages.HelperResult Breadcrumbs(string Title) { +#line default +#line hidden return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - -#line 141 "..\..\App_Code\CommonHelpers.cshtml" +#line 149 "..\..\App_Code\CommonHelpers.cshtml" -#line default -#line hidden - - -#line 142 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, Title); #line default #line hidden +#line 150 "..\..\App_Code\CommonHelpers.cshtml" +WriteTo(__razor_helper_writer, Title); -#line 142 "..\..\App_Code\CommonHelpers.cshtml" + +#line default +#line hidden + +#line 150 "..\..\App_Code\CommonHelpers.cshtml" + +#line default +#line hidden +}); + +#line 151 "..\..\App_Code\CommonHelpers.cshtml" +} #line default #line hidden -}); - -} - - +#line 152 "..\..\App_Code\CommonHelpers.cshtml" public static System.Web.WebPages.HelperResult BreadcrumbsTitle(List> BreadCrumbs) { +#line default +#line hidden return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - -#line 145 "..\..\App_Code\CommonHelpers.cshtml" +#line 153 "..\..\App_Code\CommonHelpers.cshtml" for (int index = 0; index < BreadCrumbs.Count; index++) { @@ -1179,74 +1304,79 @@ return new System.Web.WebPages.HelperResult(__razor_helper_writer => { if (index != 0) { -#line default -#line hidden - - -#line 151 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, new HtmlString(" > ")); #line default #line hidden +#line 159 "..\..\App_Code\CommonHelpers.cshtml" +WriteTo(__razor_helper_writer, new HtmlString(" > ")); -#line 151 "..\..\App_Code\CommonHelpers.cshtml" + +#line default +#line hidden + +#line 159 "..\..\App_Code\CommonHelpers.cshtml" } -#line default -#line hidden - - -#line 153 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, breadCrumb.Item1); #line default #line hidden +#line 161 "..\..\App_Code\CommonHelpers.cshtml" +WriteTo(__razor_helper_writer, breadCrumb.Item1); -#line 153 "..\..\App_Code\CommonHelpers.cshtml" + +#line default +#line hidden + +#line 161 "..\..\App_Code\CommonHelpers.cshtml" } + +#line default +#line hidden +}); + +#line 163 "..\..\App_Code\CommonHelpers.cshtml" +} #line default #line hidden -}); - -} - - +#line 164 "..\..\App_Code\CommonHelpers.cshtml" public static System.Web.WebPages.HelperResult BreadcrumbsTitle(string Title) { +#line default +#line hidden return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - -#line 157 "..\..\App_Code\CommonHelpers.cshtml" +#line 165 "..\..\App_Code\CommonHelpers.cshtml" -#line default -#line hidden - - -#line 158 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, Title); #line default #line hidden +#line 166 "..\..\App_Code\CommonHelpers.cshtml" +WriteTo(__razor_helper_writer, Title); -#line 158 "..\..\App_Code\CommonHelpers.cshtml" + +#line default +#line hidden + +#line 166 "..\..\App_Code\CommonHelpers.cshtml" + #line default #line hidden - }); +#line 167 "..\..\App_Code\CommonHelpers.cshtml" } - +#line default +#line hidden public CommonHelpers() { diff --git a/Disco.Web/App_Start/AppConfig.cs b/Disco.Web/App_Start/AppConfig.cs index 0701d939..421c4bef 100644 --- a/Disco.Web/App_Start/AppConfig.cs +++ b/Disco.Web/App_Start/AppConfig.cs @@ -77,7 +77,7 @@ namespace Disco.Web // Initialize Satellite Managed Groups (which don't belong to any other component) Disco.Services.Devices.ManagedGroups.DeviceManagedGroups.Initialize(Database); - Disco.BI.DocumentTemplateBI.ManagedGroups.DocumentTemplateManagedGroups.Initialize(Database); + Disco.Services.Documents.ManagedGroups.DocumentTemplateManagedGroups.Initialize(Database); // Initialize Plugins Disco.Services.Plugins.Plugins.InitalizePlugins(Database); @@ -105,11 +105,15 @@ namespace Disco.Web InitalizeCoreEnvironment(Database); // Initialize Scheduled Tasks - Disco.Services.Tasks.ScheduledTasks.InitalizeScheduledTasks(Database, DiscoApplication.SchedulerFactory, true); + Disco.Services.Tasks.ScheduledTasks.InitalizeScheduledTasks(Database, DiscoApplication.SchedulerFactory, false); // Import MAC Address Migration if (PreviousVersion != null && PreviousVersion < new Version(1, 2, 910, 0)) - Disco.BI.DeviceBI.Migration.LogMacAddressImporting.SetRequired(Database); + Services.Devices.Enrolment.LogMacAddressImportingTask.SetRequired(Database); + + // Attachment PDF Thumbnail Update + if (PreviousVersion != null && PreviousVersion < new Version(2, 2, 0, 0)) + Services.Documents.AttachmentImport.ThumbnailUpdateTask.SetRequired(Database); } public static void DisposeEnvironment() diff --git a/Disco.Web/App_Start/RouteConfig.cs b/Disco.Web/App_Start/RouteConfig.cs index 5f8a8028..4684d461 100644 --- a/Disco.Web/App_Start/RouteConfig.cs +++ b/Disco.Web/App_Start/RouteConfig.cs @@ -1,10 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Mvc; +using System.Web.Mvc; using System.Web.Routing; -using Microsoft.AspNet.SignalR; namespace Disco.Web { @@ -84,8 +79,8 @@ namespace Disco.Web // Update Route routes.MapRoute( name: "Update", // Route name - url: "{controller}/{action}/{id}", // URL with parameters - defaults: new { controller = "Update", action = "Index", id = UrlParameter.Optional }, // Parameter defaults + url: "{action}", // URL with parameters + defaults: new { controller = "Update", action = "Index" }, // Parameter defaults namespaces: new string[] { "Disco.Web.Controllers" } // Controllers Namespace Only ); } diff --git a/Disco.Web/Areas/API/Controllers/AuthorizationRoleController.cs b/Disco.Web/Areas/API/Controllers/AuthorizationRoleController.cs index 816cf549..491699b2 100644 --- a/Disco.Web/Areas/API/Controllers/AuthorizationRoleController.cs +++ b/Disco.Web/Areas/API/Controllers/AuthorizationRoleController.cs @@ -1,12 +1,11 @@ -using Disco.BI.Extensions; -using Disco.Models.Repository; +using Disco.Models.Repository; +using Disco.Services; using Disco.Services.Authorization; using Disco.Services.Authorization.Roles; using Disco.Services.Interop.ActiveDirectory; using Disco.Services.Users; using Disco.Services.Web; using System; -using System.Collections.Generic; using System.Linq; using System.Web.Mvc; diff --git a/Disco.Web/Areas/API/Controllers/DeviceBatchController.cs b/Disco.Web/Areas/API/Controllers/DeviceBatchController.cs index 4868321c..36755cee 100644 --- a/Disco.Web/Areas/API/Controllers/DeviceBatchController.cs +++ b/Disco.Web/Areas/API/Controllers/DeviceBatchController.cs @@ -1,5 +1,4 @@ -using Disco.BI.Extensions; -using Disco.Models.Repository; +using Disco.Models.Repository; using Disco.Services; using Disco.Services.Authorization; using Disco.Services.Devices.ManagedGroups; diff --git a/Disco.Web/Areas/API/Controllers/DeviceController.cs b/Disco.Web/Areas/API/Controllers/DeviceController.cs index 34d4992a..1fa87277 100644 --- a/Disco.Web/Areas/API/Controllers/DeviceController.cs +++ b/Disco.Web/Areas/API/Controllers/DeviceController.cs @@ -703,7 +703,7 @@ namespace Disco.Web.Areas.API.Controllers [DiscoAuthorize(Claims.DiscoAdminAccount)] public virtual ActionResult MigrateDeviceMacAddressesFromLog() { - var taskStatus = Disco.BI.DeviceBI.Migration.LogMacAddressImporting.ScheduleImmediately(); + var taskStatus = Disco.Services.Devices.Enrolment.LogMacAddressImportingTask.ScheduleImmediately(); return RedirectToAction(MVC.Config.Logging.TaskStatus(taskStatus.SessionId)); } } diff --git a/Disco.Web/Areas/API/Controllers/DeviceModelController.cs b/Disco.Web/Areas/API/Controllers/DeviceModelController.cs index 3dc6bf92..3d2e4156 100644 --- a/Disco.Web/Areas/API/Controllers/DeviceModelController.cs +++ b/Disco.Web/Areas/API/Controllers/DeviceModelController.cs @@ -1,5 +1,4 @@ -using Disco.BI.Extensions; -using Disco.Models.Repository; +using Disco.Models.Repository; using Disco.Services; using Disco.Services.Authorization; using Disco.Services.Plugins; diff --git a/Disco.Web/Areas/API/Controllers/DeviceProfileController.cs b/Disco.Web/Areas/API/Controllers/DeviceProfileController.cs index 406167a3..8a9532ec 100644 --- a/Disco.Web/Areas/API/Controllers/DeviceProfileController.cs +++ b/Disco.Web/Areas/API/Controllers/DeviceProfileController.cs @@ -1,11 +1,17 @@ -using Disco.BI.Extensions; -using Disco.Models.Repository; +using Disco.Models.Repository; +using Disco.Services; using Disco.Services.Authorization; using Disco.Services.Devices.ManagedGroups; using Disco.Services.Interop.ActiveDirectory; +using Disco.Services.Plugins; +using Disco.Services.Plugins.Features.CertificateAuthorityProvider; +using Disco.Services.Plugins.Features.CertificateProvider; +using Disco.Services.Plugins.Features.WirelessProfileProvider; using Disco.Services.Tasks; using Disco.Services.Web; using System; +using System.Collections.Generic; +using System.Linq; using System.Web.Mvc; namespace Disco.Web.Areas.API.Controllers @@ -16,7 +22,9 @@ namespace Disco.Web.Areas.API.Controllers const string pName = "name"; const string pShortName = "shortname"; const string pDistributionType = "distributiontype"; - const string pCertificateProviderId = "certificateproviderid"; + const string pCertificateProviders = "certificateproviders"; + const string pCertificateAuthorityProviders = "certificateauthorityproviders"; + const string pWirelessProfileProviders = "wirelessprofileproviders"; const string pOrganisationalUnit = "organisationalunit"; const string pDefaultOrganisationAddress = "defaultorganisationaddress"; const string pComputerNameTemplate = "computernametemplate"; @@ -56,8 +64,14 @@ namespace Disco.Web.Areas.API.Controllers case pDistributionType: UpdateDistributionType(deviceProfile, value); break; - case pCertificateProviderId: - UpdateCertificateProviderId(deviceProfile, value); + case pCertificateProviders: + UpdateCertificateProviders(deviceProfile, value); + break; + case pCertificateAuthorityProviders: + UpdateCertificateAuthorityProviders(deviceProfile, value); + break; + case pWirelessProfileProviders: + UpdateWirelessProfileProviders(deviceProfile, value); break; case pOrganisationalUnit: UpdateOrganisationalUnit(deviceProfile, value); @@ -139,9 +153,21 @@ namespace Disco.Web.Areas.API.Controllers } [DiscoAuthorize(Claims.Config.DeviceProfile.Configure)] - public virtual ActionResult UpdateCertificateProviderId(int id, string CertificateProviderId = null, Nullable redirect = null) + public virtual ActionResult UpdateCertificateProviders(int id, string CertificateProviders = null, Nullable redirect = null) { - return Update(id, pCertificateProviderId, CertificateProviderId, redirect); + return Update(id, pCertificateProviders, CertificateProviders, redirect); + } + + [DiscoAuthorize(Claims.Config.DeviceProfile.Configure)] + public virtual ActionResult UpdateCertificateAuthorityProviders(int id, string CertificateAuthorityProviders = null, Nullable redirect = null) + { + return Update(id, pCertificateAuthorityProviders, CertificateAuthorityProviders, redirect); + } + + [DiscoAuthorize(Claims.Config.DeviceProfile.Configure)] + public virtual ActionResult UpdateWirelessProfileProviders(int id, string WirelessProfileProviders = null, Nullable redirect = null) + { + return Update(id, pWirelessProfileProviders, WirelessProfileProviders, redirect); } [DiscoAuthorize(Claims.Config.DeviceProfile.Configure)] @@ -298,21 +324,111 @@ namespace Disco.Web.Areas.API.Controllers throw new Exception("Invalid Distribution Type Number"); } - private void UpdateCertificateProviderId(Disco.Models.Repository.DeviceProfile deviceProfile, string CertificateProviderId) + private void UpdateCertificateProviders(DeviceProfile deviceProfile, string CertificateProviderIds) { - if (string.IsNullOrWhiteSpace(CertificateProviderId)) + if (string.IsNullOrWhiteSpace(CertificateProviderIds)) { - deviceProfile.CertificateProviderId = null; + deviceProfile.CertificateProviders = null; } else { // Validate - var featureManifest = Disco.Services.Plugins.Plugins.GetPluginFeature(CertificateProviderId, typeof(Disco.Services.Plugins.Features.CertificateProvider.CertificateProviderFeature)); - if (featureManifest == null) - throw new Exception(string.Format("Invalid Certificate Provider Plugin Id: [{0}]", CertificateProviderId)); + var validatedProviders = new List(); + foreach (var certificateProviderId in CertificateProviderIds.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) + { + var featureManifest = Plugins.GetPluginFeature(certificateProviderId, typeof(CertificateProviderFeature)); + if (featureManifest == null) + { + throw new Exception(string.Format("Invalid Certificate Provider Plugin Id: [{0}]", certificateProviderId)); + } + else + { + validatedProviders.Add(featureManifest); + } + } + + if (validatedProviders.Count > 0) + { + deviceProfile.CertificateProviders = string.Join(",", validatedProviders.Select(p => p.Id)); + } else - deviceProfile.CertificateProviderId = featureManifest.Id; + { + deviceProfile.CertificateProviders = null; + } } + + Database.SaveChanges(); + } + + private void UpdateCertificateAuthorityProviders(DeviceProfile deviceProfile, string CertificateAuthorityProviderIds) + { + if (string.IsNullOrWhiteSpace(CertificateAuthorityProviderIds)) + { + deviceProfile.CertificateAuthorityProviders = null; + } + else + { + // Validate + var validatedProviders = new List(); + foreach (var certificateAuthorityProviderId in CertificateAuthorityProviderIds.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) + { + var featureManifest = Plugins.GetPluginFeature(certificateAuthorityProviderId, typeof(CertificateAuthorityProviderFeature)); + if (featureManifest == null) + { + throw new Exception(string.Format("Invalid Certificate Authority Provider Plugin Id: [{0}]", certificateAuthorityProviderId)); + } + else + { + validatedProviders.Add(featureManifest); + } + } + + if (validatedProviders.Count > 0) + { + deviceProfile.CertificateAuthorityProviders = string.Join(",", validatedProviders.Select(p => p.Id)); + } + else + { + deviceProfile.CertificateAuthorityProviders = null; + } + } + + Database.SaveChanges(); + } + + private void UpdateWirelessProfileProviders(DeviceProfile deviceProfile, string WirelessProfileProviderIds) + { + if (string.IsNullOrWhiteSpace(WirelessProfileProviderIds)) + { + deviceProfile.WirelessProfileProviders = null; + } + else + { + // Validate + var validatedProviders = new List(); + foreach (var wirelessProfileProviderId in WirelessProfileProviderIds.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) + { + var featureManifest = Plugins.GetPluginFeature(wirelessProfileProviderId, typeof(WirelessProfileProviderFeature)); + if (featureManifest == null) + { + throw new Exception(string.Format("Invalid Wireless Profile Provider Plugin Id: [{0}]", wirelessProfileProviderId)); + } + else + { + validatedProviders.Add(featureManifest); + } + } + + if (validatedProviders.Count > 0) + { + deviceProfile.WirelessProfileProviders = string.Join(",", validatedProviders.Select(p => p.Id)); + } + else + { + deviceProfile.WirelessProfileProviders = null; + } + } + Database.SaveChanges(); } diff --git a/Disco.Web/Areas/API/Controllers/DocumentTemplateController.cs b/Disco.Web/Areas/API/Controllers/DocumentTemplateController.cs index 080d2566..48bf3ec9 100644 --- a/Disco.Web/Areas/API/Controllers/DocumentTemplateController.cs +++ b/Disco.Web/Areas/API/Controllers/DocumentTemplateController.cs @@ -1,10 +1,9 @@ -using Disco.BI; -using Disco.BI.DocumentTemplateBI.ManagedGroups; -using Disco.BI.Extensions; +using Disco.BI.Extensions; using Disco.Models.Repository; using Disco.Services; using Disco.Services.Authorization; using Disco.Services.Documents; +using Disco.Services.Documents.ManagedGroups; using Disco.Services.Interop.ActiveDirectory; using Disco.Services.Tasks; using Disco.Services.Users; diff --git a/Disco.Web/Areas/API/Controllers/JobController.cs b/Disco.Web/Areas/API/Controllers/JobController.cs index 79900dcc..cb315000 100644 --- a/Disco.Web/Areas/API/Controllers/JobController.cs +++ b/Disco.Web/Areas/API/Controllers/JobController.cs @@ -1,11 +1,13 @@ using Disco.BI.Extensions; using Disco.Models.Repository; using Disco.Models.Services.Documents; +using Disco.Models.Services.Job; using Disco.Models.Services.Jobs.JobLists; using Disco.Services; using Disco.Services.Authorization; using Disco.Services.Interop; using Disco.Services.Jobs.JobLists; +using Disco.Services.Jobs.Statistics; using Disco.Services.Users; using Disco.Services.Web; using Disco.Web.Extensions; @@ -528,7 +530,7 @@ namespace Disco.Web.Areas.API.Controllers private void UpdateDeviceHeldLocation(Job job, string DeviceHeldLocation) { if (!string.IsNullOrWhiteSpace(DeviceHeldLocation) && - Database.DiscoConfiguration.JobPreferences.LocationMode == Disco.Models.BI.Job.LocationModes.RestrictedList) + Database.DiscoConfiguration.JobPreferences.LocationMode == LocationModes.RestrictedList) { // Enforce Restricted List Mode var value = DeviceHeldLocation.Trim(); @@ -2076,7 +2078,7 @@ namespace Disco.Web.Areas.API.Controllers [DiscoAuthorize(Claims.Job.Show)] public virtual ActionResult StatisticsDailyOpenedClosed() { - var result = BI.JobBI.Statistics.DailyOpenedClosed.Data(Database, true); + var result = DailyOpenedClosed.Data(Database, true); return Json(result, JsonRequestBehavior.AllowGet); } @@ -2123,12 +2125,12 @@ namespace Disco.Web.Areas.API.Controllers switch (Database.DiscoConfiguration.JobPreferences.LocationMode) { - case Disco.Models.BI.Job.LocationModes.Unrestricted: + case LocationModes.Unrestricted: var jobDateThreshold = DateTime.Now.AddYears(-1); locations = Database.Jobs.Where(j => (j.OpenedDate > jobDateThreshold || !j.ClosedDate.HasValue) && j.DeviceHeldLocation != null).Select(j => j.DeviceHeldLocation).Distinct().OrderBy(l => l).ToList().Where(l => !string.IsNullOrWhiteSpace(l)).Select(l => l.Trim()).Distinct(StringComparer.OrdinalIgnoreCase).OrderBy(l => l).ToList(); break; - case Disco.Models.BI.Job.LocationModes.OptionalList: - case Disco.Models.BI.Job.LocationModes.RestrictedList: + case LocationModes.OptionalList: + case LocationModes.RestrictedList: locations = Database.DiscoConfiguration.JobPreferences.LocationList; break; default: diff --git a/Disco.Web/Areas/API/Controllers/JobPreferencesController.cs b/Disco.Web/Areas/API/Controllers/JobPreferencesController.cs index 4e4f6d0a..3ba62f93 100644 --- a/Disco.Web/Areas/API/Controllers/JobPreferencesController.cs +++ b/Disco.Web/Areas/API/Controllers/JobPreferencesController.cs @@ -1,10 +1,9 @@ -using Disco.Models.BI.Job; +using Disco.Models.Services.Job; using Disco.Services.Authorization; using Disco.Services.Web; using System; using System.Collections.Generic; using System.Linq; -using System.Web; using System.Web.Mvc; namespace Disco.Web.Areas.API.Controllers diff --git a/Disco.Web/Areas/API/Controllers/JobQueueController.cs b/Disco.Web/Areas/API/Controllers/JobQueueController.cs index 55a523bf..85c97a84 100644 --- a/Disco.Web/Areas/API/Controllers/JobQueueController.cs +++ b/Disco.Web/Areas/API/Controllers/JobQueueController.cs @@ -1,13 +1,12 @@ using Disco.Models.Repository; using Disco.Services.Authorization; +using Disco.Services.Interop.ActiveDirectory; using Disco.Services.Jobs.JobQueues; using Disco.Services.Web; -using Disco.BI.Extensions; using System; +using System.Collections.Generic; using System.Linq; using System.Web.Mvc; -using System.Collections.Generic; -using Disco.Services.Interop.ActiveDirectory; namespace Disco.Web.Areas.API.Controllers { diff --git a/Disco.Web/Areas/API/Controllers/JobQueueJobController.cs b/Disco.Web/Areas/API/Controllers/JobQueueJobController.cs index d7b6dfc6..5355f6c7 100644 --- a/Disco.Web/Areas/API/Controllers/JobQueueJobController.cs +++ b/Disco.Web/Areas/API/Controllers/JobQueueJobController.cs @@ -1,12 +1,10 @@ using Disco.Models.Repository; +using Disco.Services; using Disco.Services.Authorization; using Disco.Services.Jobs.JobQueues; -using Disco.BI.Extensions; using Disco.Services.Web; using System; -using System.Collections.Generic; using System.Linq; -using System.Web; using System.Web.Mvc; namespace Disco.Web.Areas.API.Controllers diff --git a/Disco.Web/Areas/API/Controllers/SystemController.cs b/Disco.Web/Areas/API/Controllers/SystemController.cs index 4b23fce4..b610b3c2 100644 --- a/Disco.Web/Areas/API/Controllers/SystemController.cs +++ b/Disco.Web/Areas/API/Controllers/SystemController.cs @@ -1,5 +1,4 @@ -using Disco.BI.Extensions; -using Disco.Data.Configuration; +using Disco.Data.Configuration; using Disco.Services; using Disco.Services.Authorization; using Disco.Services.Interop.ActiveDirectory; @@ -29,40 +28,9 @@ namespace Disco.Web.Areas.API.Controllers [DiscoAuthorize(Claims.DiscoAdminAccount)] public virtual ActionResult UpdateAttachmentThumbnails() { - // Device Attachments - var das = Database.DeviceAttachments.Where(da => da.MimeType == "application/pdf"); - foreach (var da in das) - { - var fileName = da.RepositoryThumbnailFilename(Database); - if (!System.IO.File.Exists(fileName)) - { - da.GenerateThumbnail(Database); - } - } - - // User Attachments - var uas = Database.UserAttachments.Where(ua => ua.MimeType == "application/pdf"); - foreach (var ua in uas) - { - var fileName = ua.RepositoryThumbnailFilename(Database); - if (!System.IO.File.Exists(fileName)) - { - ua.GenerateThumbnail(Database); - } - } - - // Job Attachments - var jas = Database.JobAttachments.Where(ja => ja.MimeType == "application/pdf"); - foreach (var ja in jas) - { - var fileName = ja.RepositoryThumbnailFilename(Database); - if (!System.IO.File.Exists(fileName)) - { - ja.GenerateThumbnail(Database); - } - } - - return Content("Done", "text/text"); + var ts = Disco.Services.Documents.AttachmentImport.ThumbnailUpdateTask.ScheduleImmediately(); + ts.SetFinishedUrl(Url.Action(MVC.Config.SystemConfig.Index())); + return RedirectToAction(MVC.Config.Logging.TaskStatus(ts.SessionId)); } [DiscoAuthorize(Claims.Config.System.Show)] @@ -243,7 +211,7 @@ namespace Disco.Web.Areas.API.Controllers try { var result = ActiveDirectory.Context.UpdateSearchAllForestServers(Database, SearchAllForestServers); - + Database.SaveChanges(); if (!result) @@ -269,11 +237,24 @@ namespace Disco.Web.Areas.API.Controllers } } + [DiscoAuthorize(Claims.Config.System.ConfigureActiveDirectory)] + public virtual ActionResult UpdateActiveDirectorySearchWildcardSuffixOnly(bool SearchWildcardSuffixOnly, bool redirect = false) + { + ActiveDirectory.Context.UpdateWildcardSearchSuffixOnly(Database, SearchWildcardSuffixOnly); + + Database.SaveChanges(); + + if (redirect) + return RedirectToAction(MVC.Config.SystemConfig.Index()); + else + return Json("OK", JsonRequestBehavior.AllowGet); + } + [DiscoAuthorizeAny(Claims.Config.System.ConfigureActiveDirectory, Claims.Config.DeviceProfile.Configure)] public virtual ActionResult DomainOrganisationalUnits() { var domainOUs = ActiveDirectory.RetrieveADOrganisationalUnitStructure() - .Select(d => new Models.System.DomainOrganisationalUnitsModel() { Domain = d.Item1, OrganisationalUnits = d.Item2}) + .Select(d => new Models.System.DomainOrganisationalUnitsModel() { Domain = d.Item1, OrganisationalUnits = d.Item2 }) .Select(ous => ous.ToFancyTreeNode()).ToList(); return new JsonResult() @@ -322,12 +303,12 @@ namespace Disco.Web.Areas.API.Controllers public virtual ActionResult SyncActiveDirectoryManagedGroup(string id, string redirectUrl = null) { ADManagedGroup managedGroup; - + if (!ActiveDirectory.Context.ManagedGroups.TryGetValue(id, out managedGroup)) throw new ArgumentException("Unknown Managed Group Key"); var taskStatus = ADManagedGroupsSyncTask.ScheduleSync(managedGroup); - + if (redirectUrl != null) taskStatus.SetFinishedUrl(redirectUrl); diff --git a/Disco.Web/Areas/API/Controllers/UserFlagAssignmentController.cs b/Disco.Web/Areas/API/Controllers/UserFlagAssignmentController.cs index 7a8e1bdc..f90f4eec 100644 --- a/Disco.Web/Areas/API/Controllers/UserFlagAssignmentController.cs +++ b/Disco.Web/Areas/API/Controllers/UserFlagAssignmentController.cs @@ -1,5 +1,5 @@ -using Disco.BI.Extensions; -using Disco.Models.Repository; +using Disco.Models.Repository; +using Disco.Services; using Disco.Services.Authorization; using Disco.Services.Users.UserFlags; using Disco.Services.Web; @@ -13,7 +13,7 @@ namespace Disco.Web.Areas.API.Controllers { const string pComments = "comments"; - public virtual ActionResult Update(int id, string key, string value = null, Nullable redirect = null) + public virtual ActionResult Update(int id, string key, string value = null, bool? redirect = null) { try { @@ -53,7 +53,7 @@ namespace Disco.Web.Areas.API.Controllers #region Update Shortcut Methods [DiscoAuthorizeAny(Claims.User.Actions.EditFlags)] - public virtual ActionResult UpdateComments(int id, string Comments = null, Nullable redirect = null) + public virtual ActionResult UpdateComments(int id, string Comments = null, bool? redirect = null) { return Update(id, pComments, Comments, redirect); } diff --git a/Disco.Web/Areas/Config/Controllers/DeviceBatchController.cs b/Disco.Web/Areas/Config/Controllers/DeviceBatchController.cs index 71f28658..53b0ad0a 100644 --- a/Disco.Web/Areas/Config/Controllers/DeviceBatchController.cs +++ b/Disco.Web/Areas/Config/Controllers/DeviceBatchController.cs @@ -1,6 +1,7 @@ -using Disco.BI.Extensions; -using Disco.Models.UI.Config.DeviceBatch; +using Disco.Models.UI.Config.DeviceBatch; +using Disco.Services; using Disco.Services.Authorization; +using Disco.Services.Devices; using Disco.Services.Devices.ManagedGroups; using Disco.Services.Plugins.Features.UIExtension; using Disco.Services.Web; @@ -79,7 +80,7 @@ namespace Disco.Web.Areas.Config.Controllers // Default Batch var m = new Models.DeviceBatch.CreateModel() { - DeviceBatch = BI.DeviceBI.BatchUtilities.DefaultNewDeviceBatch(Database) + DeviceBatch = DeviceBatches.DefaultNewDeviceBatch(Database) }; // UI Extensions diff --git a/Disco.Web/Areas/Config/Controllers/DeviceModelController.cs b/Disco.Web/Areas/Config/Controllers/DeviceModelController.cs index 10f40a22..2edb6219 100644 --- a/Disco.Web/Areas/Config/Controllers/DeviceModelController.cs +++ b/Disco.Web/Areas/Config/Controllers/DeviceModelController.cs @@ -1,5 +1,5 @@ -using Disco.BI.Extensions; -using Disco.Models.UI.Config.DeviceModel; +using Disco.Models.UI.Config.DeviceModel; +using Disco.Services; using Disco.Services.Authorization; using Disco.Services.Plugins; using Disco.Services.Plugins.Features.RepairProvider; diff --git a/Disco.Web/Areas/Config/Controllers/DeviceProfileController.cs b/Disco.Web/Areas/Config/Controllers/DeviceProfileController.cs index e908f28f..81cbc8cc 100644 --- a/Disco.Web/Areas/Config/Controllers/DeviceProfileController.cs +++ b/Disco.Web/Areas/Config/Controllers/DeviceProfileController.cs @@ -1,12 +1,14 @@ -using Disco.BI.Extensions; -using Disco.Models.Repository; +using Disco.Models.Repository; using Disco.Models.UI.Config.DeviceProfile; +using Disco.Services; using Disco.Services.Authorization; using Disco.Services.Devices.ManagedGroups; using Disco.Services.Interop.ActiveDirectory; using Disco.Services.Plugins; +using Disco.Services.Plugins.Features.CertificateAuthorityProvider; using Disco.Services.Plugins.Features.CertificateProvider; using Disco.Services.Plugins.Features.UIExtension; +using Disco.Services.Plugins.Features.WirelessProfileProvider; using Disco.Services.Web; using System; using System.Collections.Generic; @@ -45,6 +47,8 @@ namespace Disco.Web.Areas.Config.Controllers m.DevicesLinkedGroup = devicesManagedGroup; m.CertificateProviders = Plugins.GetPluginFeatures(typeof(CertificateProviderFeature)); + m.CertificateAuthorityProviders = Plugins.GetPluginFeatures(typeof(CertificateAuthorityProviderFeature)); + m.WirelessProfileProviders = Plugins.GetPluginFeatures(typeof(WirelessProfileProviderFeature)); var DistributionValues = Enum.GetValues(typeof(Disco.Models.Repository.DeviceProfile.DistributionTypes)); m.DeviceProfileDistributionTypes = new List(); diff --git a/Disco.Web/Areas/Config/Controllers/DocumentTemplateController.cs b/Disco.Web/Areas/Config/Controllers/DocumentTemplateController.cs index 7c70dacd..ec9b61fc 100644 --- a/Disco.Web/Areas/Config/Controllers/DocumentTemplateController.cs +++ b/Disco.Web/Areas/Config/Controllers/DocumentTemplateController.cs @@ -1,8 +1,8 @@ -using Disco.BI.DocumentTemplateBI.ManagedGroups; -using Disco.BI.Extensions; +using Disco.BI.Extensions; using Disco.Models.UI.Config.DocumentTemplate; using Disco.Services; using Disco.Services.Authorization; +using Disco.Services.Documents.ManagedGroups; using Disco.Services.Expressions; using Disco.Services.Plugins.Features.UIExtension; using Disco.Services.Web; diff --git a/Disco.Web/Areas/Config/Models/DeviceProfile/IndexModel.cs b/Disco.Web/Areas/Config/Models/DeviceProfile/IndexModel.cs index 6293c1a5..f740ca20 100644 --- a/Disco.Web/Areas/Config/Models/DeviceProfile/IndexModel.cs +++ b/Disco.Web/Areas/Config/Models/DeviceProfile/IndexModel.cs @@ -1,10 +1,7 @@ -using System; +using Disco.Data.Repository; +using Disco.Models.UI.Config.DeviceProfile; using System.Collections.Generic; using System.Linq; -using System.Web; -using Disco.Data.Repository; -using Disco.BI.Extensions; -using Disco.Models.UI.Config.DeviceProfile; namespace Disco.Web.Areas.Config.Models.DeviceProfile { diff --git a/Disco.Web/Areas/Config/Models/DeviceProfile/ShowModel.cs b/Disco.Web/Areas/Config/Models/DeviceProfile/ShowModel.cs index b4a48ff3..f1eafb06 100644 --- a/Disco.Web/Areas/Config/Models/DeviceProfile/ShowModel.cs +++ b/Disco.Web/Areas/Config/Models/DeviceProfile/ShowModel.cs @@ -35,6 +35,8 @@ namespace Disco.Web.Areas.Config.Models.DeviceProfile } public List CertificateProviders { get; set; } + public List CertificateAuthorityProviders { get; set; } + public List WirelessProfileProviders { get; set; } public int DeviceCount { get; set; } public int DeviceDecommissionedCount { get; set; } diff --git a/Disco.Web/Areas/Config/Models/DocumentTemplate/ShowModel.cs b/Disco.Web/Areas/Config/Models/DocumentTemplate/ShowModel.cs index e292354d..54aec2c3 100644 --- a/Disco.Web/Areas/Config/Models/DocumentTemplate/ShowModel.cs +++ b/Disco.Web/Areas/Config/Models/DocumentTemplate/ShowModel.cs @@ -1,7 +1,7 @@ -using Disco.BI.DocumentTemplateBI.ManagedGroups; -using Disco.Data.Repository; +using Disco.Data.Repository; using Disco.Models.Repository; using Disco.Models.UI.Config.DocumentTemplate; +using Disco.Services.Documents.ManagedGroups; using Disco.Services.Expressions; using System.Collections.Generic; using System.Linq; diff --git a/Disco.Web/Areas/Config/Models/DocumentTemplate/UndetectedPagesModel.cs b/Disco.Web/Areas/Config/Models/DocumentTemplate/UndetectedPagesModel.cs index 6f3eab07..a5dbff4c 100644 --- a/Disco.Web/Areas/Config/Models/DocumentTemplate/UndetectedPagesModel.cs +++ b/Disco.Web/Areas/Config/Models/DocumentTemplate/UndetectedPagesModel.cs @@ -1,12 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Mvc; -using Disco.BI; -using Disco.BI.Extensions; +using Disco.Models.UI.Config.DocumentTemplate; using Disco.Web.Extensions; -using Disco.Models.UI.Config.DocumentTemplate; +using System.Collections.Generic; +using System.Web.Mvc; namespace Disco.Web.Areas.Config.Models.DocumentTemplate { diff --git a/Disco.Web/Areas/Config/Models/JobPreferences/IndexModel.cs b/Disco.Web/Areas/Config/Models/JobPreferences/IndexModel.cs index 1ea59e87..65bd51ed 100644 --- a/Disco.Web/Areas/Config/Models/JobPreferences/IndexModel.cs +++ b/Disco.Web/Areas/Config/Models/JobPreferences/IndexModel.cs @@ -1,5 +1,5 @@ using Disco.Data.Repository; -using Disco.Models.BI.Job; +using Disco.Models.Services.Job; using Disco.Models.UI.Config.JobPreferences; using Disco.Services.Extensions; using System; diff --git a/Disco.Web/Areas/Config/Models/SystemConfig/IndexModel.cs b/Disco.Web/Areas/Config/Models/SystemConfig/IndexModel.cs index c8c0d81d..8a141da8 100644 --- a/Disco.Web/Areas/Config/Models/SystemConfig/IndexModel.cs +++ b/Disco.Web/Areas/Config/Models/SystemConfig/IndexModel.cs @@ -84,6 +84,8 @@ namespace Disco.Web.Areas.Config.Models.SystemConfig public ADSite ADSite { get; set; } public List ADServers { get; set; } public List> ADSearchContainers { get; set; } + [Display(Name = "Search With Suffix Wildcard Only")] + public bool ADSearchWildcardSuffixOnly { get; set; } public List ADForestServers { get; set; } #endregion @@ -126,6 +128,7 @@ namespace Disco.Web.Areas.Config.Models.SystemConfig m.ADPrimaryDomain = ActiveDirectory.Context.PrimaryDomain; m.ADSite = ActiveDirectory.Context.Site; m.ADServers = ActiveDirectory.Context.Domains.SelectMany(d => d.DomainControllers).ToList(); + m.ADSearchWildcardSuffixOnly = config.ActiveDirectory.SearchWildcardSuffixOnly; var configSearchContainers = config.ActiveDirectory.SearchContainers; m.ADSearchContainers = configSearchContainers == null ? null : configSearchContainers.SelectMany(d => d.Value, (k, c) => { diff --git a/Disco.Web/Areas/Config/Views/DeviceProfile/Show.cshtml b/Disco.Web/Areas/Config/Views/DeviceProfile/Show.cshtml index b50a54e0..8ffe2419 100644 --- a/Disco.Web/Areas/Config/Views/DeviceProfile/Show.cshtml +++ b/Disco.Web/Areas/Config/Views/DeviceProfile/Show.cshtml @@ -25,84 +25,91 @@
- - - - - - - @@ -117,156 +124,222 @@ - - - - - - - - - - - - + + + + + + + + - - - - + + + + @if (hideAdvanced) @@ -552,7 +737,8 @@ } - \r\n <" + @@ -2081,16 +2080,16 @@ WriteLiteral(" id=\"dialogBulkGenerate\""); WriteLiteral(" class=\"hiddenDialog\""); -WriteAttribute("title", Tuple.Create(" title=\"", 40430), Tuple.Create("\"", 40481) -, Tuple.Create(Tuple.Create("", 40438), Tuple.Create("Bulk", 40438), true) -, Tuple.Create(Tuple.Create(" ", 40442), Tuple.Create("Generate:", 40443), true) +WriteAttribute("title", Tuple.Create(" title=\"", 40427), Tuple.Create("\"", 40478) +, Tuple.Create(Tuple.Create("", 40435), Tuple.Create("Bulk", 40435), true) +, Tuple.Create(Tuple.Create(" ", 40439), Tuple.Create("Generate:", 40440), true) #line 722 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" -, Tuple.Create(Tuple.Create(" ", 40452), Tuple.Create(Model.DocumentTemplate.Id +, Tuple.Create(Tuple.Create(" ", 40449), Tuple.Create(Model.DocumentTemplate.Id #line default #line hidden -, 40453), false) +, 40450), false) ); WriteLiteral(">\r\n // This code was generated by a tool. -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -27,7 +27,6 @@ namespace Disco.Web.Areas.Config.Views.Enrolment using System.Web.UI; using System.Web.WebPages; using Disco; - using Disco.BI.Extensions; using Disco.Models.Repository; using Disco.Services; using Disco.Services.Authorization; @@ -423,7 +422,7 @@ Write(Html.Partial(MVC.Config.Shared.Views.LogEvents, new Disco.Web.Areas.Config IsLive = true, TakeFilter = 100, StartFilter = DateTime.Today.AddDays(-1), - ModuleFilter = Disco.BI.DeviceBI.EnrolmentLog.Current, + ModuleFilter = Disco.Services.Devices.Enrolment.EnrolmentLog.Current, ViewPortHeight = 250 })); diff --git a/Disco.Web/Areas/Config/Views/Enrolment/Status.cshtml b/Disco.Web/Areas/Config/Views/Enrolment/Status.cshtml index 40763630..2790e485 100644 --- a/Disco.Web/Areas/Config/Views/Enrolment/Status.cshtml +++ b/Disco.Web/Areas/Config/Views/Enrolment/Status.cshtml @@ -326,7 +326,7 @@ logHub = $.connection.logNotifications; logHub.client.receiveLog = parseLog - $.connection.hub.qs = { LogModules: '@(Disco.BI.DeviceBI.EnrolmentLog.Current.LiveLogGroupName)' }; + $.connection.hub.qs = { LogModules: '@(Disco.Services.Devices.Enrolment.EnrolmentLog.Current.LiveLogGroupName)' }; $.connection.hub.error(onHubFailed); $.connection.hub.start() diff --git a/Disco.Web/Areas/Config/Views/Enrolment/Status.generated.cs b/Disco.Web/Areas/Config/Views/Enrolment/Status.generated.cs index 63eaeb36..112eec78 100644 --- a/Disco.Web/Areas/Config/Views/Enrolment/Status.generated.cs +++ b/Disco.Web/Areas/Config/Views/Enrolment/Status.generated.cs @@ -2,7 +2,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -27,7 +27,6 @@ namespace Disco.Web.Areas.Config.Views.Enrolment using System.Web.UI; using System.Web.WebPages; using Disco; - using Disco.BI.Extensions; using Disco.Models.Repository; using Disco.Services; using Disco.Services.Authorization; @@ -514,7 +513,7 @@ WriteLiteral(@"', #line 329 "..\..\Areas\Config\Views\Enrolment\Status.cshtml" - Write(Disco.BI.DeviceBI.EnrolmentLog.Current.LiveLogGroupName); + Write(Disco.Services.Devices.Enrolment.EnrolmentLog.Current.LiveLogGroupName); #line default diff --git a/Disco.Web/Areas/Config/Views/SystemConfig/Index.cshtml b/Disco.Web/Areas/Config/Views/SystemConfig/Index.cshtml index 9be0c192..e102f38c 100644 --- a/Disco.Web/Areas/Config/Views/SystemConfig/Index.cshtml +++ b/Disco.Web/Areas/Config/Views/SystemConfig/Index.cshtml @@ -17,7 +17,8 @@
Id: + + Id: @Html.DisplayFor(model => model.DeviceProfile.Id)
Name: + + Name: @if (canConfig) - { - @Html.TextBoxFor(model => model.DeviceProfile.Name) - @AjaxHelpers.AjaxSave() - @AjaxHelpers.AjaxLoader() - + + @if (canConfig) + { + @Html.TextBoxFor(model => model.DeviceProfile.Name) + @AjaxHelpers.AjaxSave() + @AjaxHelpers.AjaxLoader() + } else { - @Model.DeviceProfile.Name + @Model.DeviceProfile.Name }
Short Name: + + Short Name: @if (canConfig) + + @if (canConfig) { - @Html.TextBoxFor(model => model.DeviceProfile.ShortName) - @AjaxHelpers.AjaxSave() - @AjaxHelpers.AjaxLoader() - + @Html.TextBoxFor(model => model.DeviceProfile.ShortName) + @AjaxHelpers.AjaxSave() + @AjaxHelpers.AjaxLoader() + } else { - @Model.DeviceProfile.ShortName + @Model.DeviceProfile.ShortName }
Description: + + Description: @if (canConfig) + + @if (canConfig) { - @Html.EditorFor(model => model.DeviceProfile.Description) - @AjaxHelpers.AjaxSave() - @AjaxHelpers.AjaxLoader() - + @Html.EditorFor(model => model.DeviceProfile.Description) + @AjaxHelpers.AjaxSave() + @AjaxHelpers.AjaxLoader() + } else { - @Model.DeviceProfile.Description + @Model.DeviceProfile.Description }
Distribution Type: + + Distribution Type: @if (canConfig) + + @if (canConfig) { - @Html.DropDownList("DeviceProfile_DistributionType", Model.DeviceProfileDistributionTypes) - @AjaxHelpers.AjaxLoader() - + @Html.DropDownList("DeviceProfile_DistributionType", Model.DeviceProfileDistributionTypes) + @AjaxHelpers.AjaxLoader() + } else { - @Model.DeviceProfile.DistributionType.ToString() + @Model.DeviceProfile.DistributionType.ToString() } +
+

+ One-to-many devices are typically shared. + One-to-one devices are typically assigned to a user; + enrolment with a one-to-one device isn't considered complete until it is assigned. +

+
Address: + + Address: @if (canConfig) + + @if (canConfig) { - @Html.DropDownListFor(m => m.DeviceProfile.DefaultOrganisationAddress, Model.OrganisationAddresses.ToSelectListItems(Model.DeviceProfile.DefaultOrganisationAddress, true, "None")) - @AjaxHelpers.AjaxLoader() - + @Html.DropDownListFor(m => m.DeviceProfile.DefaultOrganisationAddress, Model.OrganisationAddresses.ToSelectListItems(Model.DeviceProfile.DefaultOrganisationAddress, true, "None")) + @AjaxHelpers.AjaxLoader() + } else { if (Model.DefaultOrganisationAddress == null) - { - <None Specified> - } - else - { - @Model.DefaultOrganisationAddress.ToString() - } - } -
Allocate Certificates: - @if (canConfig && Model.CertificateProviders.Count > 0) - { - @Html.DropDownListFor(model => model.DeviceProfile.CertificateProviderId, Model.CertificateProviders.ToSelectListItems(null, true, "Not Allocated")) - @AjaxHelpers.AjaxLoader() - - } - else - { - if (string.IsNullOrEmpty(Model.DeviceProfile.CertificateProviderId)) - { - <None Allocated> - } - else - { - var cp = Model.CertificateProviders.FirstOrDefault(p => p.Id == Model.DeviceProfile.CertificateProviderId); - if (cp == null) - { - <None Allocated> - } - else - { - @cp.Name - } - } - } - @if (canViewPlugins) - { -
-

- View the Plugin Catalogue to discover and install certificate provider plugins. -

-
- } -
Computer Name
- Template Expression: -
@if (canConfig && canConfigExpression) - { - @Html.EditorFor(model => model.DeviceProfile.ComputerNameTemplate) - @AjaxHelpers.AjaxSave() - @AjaxHelpers.AjaxLoader() -   - - } - else - { -
- @if (string.IsNullOrWhiteSpace(Model.DeviceProfile.ComputerNameTemplate)) { <None Specified> } else { - @Model.DeviceProfile.ComputerNameTemplate + @Model.DefaultOrganisationAddress.ToString() } + } +
+

+ The profile address is used to separate jobs for multi-site mode. + It is also suggested as the default address for warranty/repair actions. +

+
Policies +
+ @if (canConfig) + { + + + } + else + { + + } + + @AjaxHelpers.AjaxLoader() +
+

+ When enabled an Active Directory account will be provisioned for the device when enrolment occurs + and the device will be joined to the domain (refer to the Computer Name Template Expression and the + Organisational Unit configuration options below). +

+
+
+
+ @if (canConfig) + { + + + } + else + { + + } + + @AjaxHelpers.AjaxLoader() +
+

+ When enabled the user assigned to the device will be added to the Local Administrators group during device enrolment. +

+
+
+
+ @if (canConfig) + { + + + } + else + { + + } + + @AjaxHelpers.AjaxLoader() +
+

+ When enabled an untrusted device enrolment will be allowed if a Software - Reimage job is open for the device. +

+
+
+
+ Computer Name
+ Template Expression: +
+ @if (canConfig && canConfigExpression) + { + @Html.EditorFor(model => model.DeviceProfile.ComputerNameTemplate) + @AjaxHelpers.AjaxSave() + @AjaxHelpers.AjaxLoader() +   + + } + else + { +
+ @if (string.IsNullOrWhiteSpace(Model.DeviceProfile.ComputerNameTemplate)) + { + <None Specified> + } + else + { + @Model.DeviceProfile.ComputerNameTemplate + } +
}
@if (canConfig) { - + - } - else - { - - } - - @AjaxHelpers.AjaxLoader() -
-
- @if (canConfig) - { - - - } - else - { - - } - - @AjaxHelpers.AjaxLoader() -
-
- @if (canConfig) - { - - - } - else - { - - } - - @AjaxHelpers.AjaxLoader() -
-
Organisational Unit: + + Organisational Unit: @if (canConfig) + + @if (canConfig) { -
- - @Model.FriendlyOrganisationalUnitName - -
- Change@AjaxHelpers.AjaxLoader() -
-
- @AjaxHelpers.AjaxLoader() Loading Organisational Units +
+ + @Model.FriendlyOrganisationalUnitName +
-
+ Change@AjaxHelpers.AjaxLoader() +
+
+ @AjaxHelpers.AjaxLoader() Loading Organisational Units +
+
+
-
- + $('#changeOrganisationalUnit').click(ouChange); + }); + } else { -
- - @Model.FriendlyOrganisationalUnitName - -
+
+ + @Model.FriendlyOrganisationalUnitName + +
}
@if (canConfig) { - + + } + @if (canConfig && Model.CertificateProviders.Count > 0) + { + + } + +
+

Device/Machine Certificates

+ @if (canConfig && Model.CertificateProviders.Count > 0) + { + @CommonHelpers.CheckBoxList("DeviceProfile_CertificateProviders", "DeviceProfile_CertificateProviders", Model.CertificateProviders.ToSelectListItems(Model.DeviceProfile.GetCertificateProviders())) + } + else + { + var certificateProviders = Model.DeviceProfile.GetCertificateProviders().ToList(); + + if (certificateProviders.Count == 0) + { + <None Allocated> + } + else + { +
    + @foreach (var certificateProvider in certificateProviders) + { +
  • @certificateProvider.Name
  • + } +
+ } + } +

Authority Certificates

+ @if (canConfig && Model.CertificateAuthorityProviders.Count > 0) + { + @CommonHelpers.CheckBoxList("DeviceProfile_CertificateAuthorityProviders", "DeviceProfile_CertificateAuthorityProviders", Model.CertificateAuthorityProviders.ToSelectListItems(Model.DeviceProfile.GetCertificateAuthorityProviders())) + } + else + { + var certificateProviders = Model.DeviceProfile.GetCertificateAuthorityProviders().ToList(); + + if (certificateProviders.Count == 0) + { + <None Allocated> + } + else + { +
    + @foreach (var certificateProvider in certificateProviders) + { +
  • @certificateProvider.Name
  • + } +
+ } + } + @if (canViewPlugins) + { +
+

+ View the Plugin Catalogue to discover and install certificate provider plugins. +

+
+ } +
+ Provision Wireless Profiles: + @if (canConfig && Model.WirelessProfileProviders.Count > 0) + { +
+ @AjaxHelpers.AjaxLoader("DeviceProfile_WirelessProfileProviders") + + } +
+ @if (canConfig && Model.WirelessProfileProviders.Count > 0) + { + @CommonHelpers.CheckBoxList("DeviceProfile_WirelessProfileProviders", "DeviceProfile_WirelessProfileProviders", Model.WirelessProfileProviders.ToSelectListItems(Model.DeviceProfile.GetWirelessProfileProviders())) + } + else + { + var wirelessProfileProviders = Model.DeviceProfile.GetWirelessProfileProviders().ToList(); + + if (wirelessProfileProviders.Count == 0) + { + <None Allocated> + } + else + { +
    + @foreach (var wirelessProfileProvider in wirelessProfileProviders) + { +
  • @wirelessProfileProvider.Name
  • + } +
+ } + } + @if (canViewPlugins) + { +
+

+ View the Plugin Catalogue to discover and install wireless profile provider plugins. +

+
+ }
Linked Groups: + + Linked Groups:
@@ -620,7 +806,7 @@ }
@if (canDelete) - { + { @Html.ActionLinkButton("Delete", MVC.API.DeviceProfile.Delete(Model.DeviceProfile.Id, true), "buttonDelete") } @if (Authorization.Has(Claims.Device.Actions.Export)) diff --git a/Disco.Web/Areas/Config/Views/DeviceProfile/Show.generated.cs b/Disco.Web/Areas/Config/Views/DeviceProfile/Show.generated.cs index 060212cc..6f1112be 100644 --- a/Disco.Web/Areas/Config/Views/DeviceProfile/Show.generated.cs +++ b/Disco.Web/Areas/Config/Views/DeviceProfile/Show.generated.cs @@ -2,7 +2,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -27,7 +27,6 @@ namespace Disco.Web.Areas.Config.Views.DeviceProfile using System.Web.UI; using System.Web.WebPages; using Disco; - using Disco.BI.Extensions; using Disco.Models.Repository; using Disco.Services; using Disco.Services.Authorization; @@ -103,299 +102,322 @@ WriteLiteral(">\r\n \r\n \r\n Id:\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n " \r\n \r\n \r\n WriteLiteral(" "); - #line 112 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 119 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" Write(Model.DeviceCount == 1 ? "devices is a member" : "devices are members"); @@ -423,13 +445,13 @@ WriteLiteral(" "); WriteLiteral(" of this profile.\r\n"); - #line 113 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 120 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" #line default #line hidden - #line 113 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 120 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" if (Model.DeviceDecommissionedCount > 0) { @@ -443,7 +465,7 @@ WriteLiteral(" class=\"smallMessage\""); WriteLiteral(">"); - #line 115 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 122 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" Write(Model.DeviceDecommissionedCount.ToString("n0")); @@ -452,7 +474,7 @@ WriteLiteral(">"); WriteLiteral(" "); - #line 115 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 122 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" Write(Model.DeviceDecommissionedCount == 1 ? "device is" : "devices are"); @@ -461,154 +483,193 @@ WriteLiteral(" "); WriteLiteral(" decommissioned.\r\n"); - #line 116 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 123 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" } #line default #line hidden -WriteLiteral(" \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n + + + + \r\n \r\n \r\n \r\n + + + + + + + + + + + + + + + \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n"); - #line 225 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - if (canConfig && canConfigExpression) - { - - - #line default - #line hidden - - #line 227 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Html.EditorFor(model => model.DeviceProfile.ComputerNameTemplate)); - - - #line default - #line hidden - - #line 227 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - - - #line default - #line hidden - - #line 228 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(AjaxHelpers.AjaxSave()); - - - #line default - #line hidden - - #line 228 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - - - #line default - #line hidden - - #line 229 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(AjaxHelpers.AjaxLoader()); - - - #line default - #line hidden - - #line 229 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - - - #line default - #line hidden -WriteLiteral(" (Url.Action(MVC.Config.DocumentTemplate.ExpressionBrowser()) - - #line default - #line hidden -, 9570), false) -); - -WriteLiteral("> \r\n"); - -WriteLiteral(" - $(function () { - var field = $('#DeviceProfile_ComputerNameTemplate'); - var fieldOriginalWidth, fieldOriginalHeight; - - document.DiscoFunctions.PropertyChangeHelper( - field, - 'None', - '"); - - - #line 239 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Url.Action(MVC.API.DeviceProfile.UpdateComputerNameTemplate(Model.DeviceProfile.Id))); - - - #line default - #line hidden -WriteLiteral(@"', - 'ComputerNameTemplate' - ); - - field.focus(function () { - fieldOriginalWidth = field.width(); - fieldOriginalHeight = field.height(); - field.css('overflow', 'visible').animate({ width: field.parent().width() - 52, height: 75 }, 200); - }).blur(function () { - field.css('overflow', 'hidden').animate({ width: fieldOriginalWidth, height: fieldOriginalHeight }, 200); - }).attr('placeholder', 'None').attr('spellcheck', 'false'); - }); - -"); - - - #line 252 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - } - else - { - - - #line default - #line hidden -WriteLiteral(" \r\n"); - - - #line 256 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - - #line default - #line hidden - - #line 256 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - if (string.IsNullOrWhiteSpace(Model.DeviceProfile.ComputerNameTemplate)) - { - - - #line default - #line hidden -WriteLiteral(" <None Specified>\r\n"); - - - #line 259 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - } - else - { - - - #line default - #line hidden - - #line 262 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Model.DeviceProfile.ComputerNameTemplate); - - - #line default - #line hidden - - #line 262 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - } - - - #line default - #line hidden -WriteLiteral(" \r\n"); - - - #line 265 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - } - - - #line default - #line hidden -WriteLiteral(" \r\n"); - - - #line 267 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - - #line default - #line hidden - - #line 267 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - if (canConfig) - { - - - #line default - #line hidden -WriteLiteral(" \r\n \r\n \r\n \r\n \r\n " + -" \r\n \r\n \r\n"); - - - #line 537 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 722 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" #line default #line hidden - #line 537 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 722 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" if (hideAdvanced) { @@ -1811,7 +2460,7 @@ WriteLiteral(@">Show Advanced Options "); - #line 553 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 738 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" } @@ -1821,13 +2470,13 @@ WriteLiteral(" \r\n \r\n \r\n " + +" \r\n \r\n
\r\n"); +WriteLiteral(">\r\n Id:\r\n \r\n \r\n"); WriteLiteral(" "); - #line 31 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 32 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" Write(Html.DisplayFor(model => model.DeviceProfile.Id)); #line default #line hidden -WriteLiteral("\r\n
Name:\r\n " + -" "); +WriteLiteral("\r\n
\r\n " + +" Name:\r\n \r\n"); - #line 37 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 40 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + #line default + #line hidden + + #line 40 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" if (canConfig) - { - + { + #line default #line hidden - #line 39 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Html.TextBoxFor(model => model.DeviceProfile.Name)); + #line 42 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Html.TextBoxFor(model => model.DeviceProfile.Name)); #line default #line hidden - #line 39 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - + #line 42 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + #line default #line hidden - #line 40 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(AjaxHelpers.AjaxSave()); + #line 43 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(AjaxHelpers.AjaxSave()); #line default #line hidden - #line 40 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - + #line 43 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + #line default #line hidden - #line 41 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(AjaxHelpers.AjaxLoader()); + #line 44 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(AjaxHelpers.AjaxLoader()); #line default #line hidden - #line 41 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - + #line 44 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line default #line hidden -WriteLiteral(" \r\n $(function () {\r\n document.DiscoFun" + -"ctions.PropertyChangeHelper(\r\n $(\'#DeviceProfile_Name" + -"\'),\r\n \'Name\',\r\n \'"); +WriteLiteral(">\r\n $(function () {\r\n document." + +"DiscoFunctions.PropertyChangeHelper(\r\n $(\'#Device" + +"Profile_Name\'),\r\n \'Name\',\r\n " + +" \'"); - #line 47 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Url.Action(MVC.API.DeviceProfile.UpdateName(Model.DeviceProfile.Id))); + #line 50 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Url.Action(MVC.API.DeviceProfile.UpdateName(Model.DeviceProfile.Id))); #line default #line hidden -WriteLiteral("\',\r\n \'ProfileName\'\r\n );\r\n " + -" });\r\n \r\n"); +WriteLiteral("\',\r\n \'ProfileName\'\r\n );" + +"\r\n });\r\n \r\n"); - #line 52 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 55 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" } else { - + #line default #line hidden - #line 55 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Model.DeviceProfile.Name); + #line 58 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Model.DeviceProfile.Name); #line default #line hidden - #line 55 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - + #line 58 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } #line default #line hidden -WriteLiteral("
Short Name:\r\n " + -" "); +WriteLiteral("
\r\n " + +" Short Name:\r\n \r\n"); - #line 62 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 67 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + #line default + #line hidden + + #line 67 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" if (canConfig) { - + #line default #line hidden - #line 64 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Html.TextBoxFor(model => model.DeviceProfile.ShortName)); + #line 69 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Html.TextBoxFor(model => model.DeviceProfile.ShortName)); #line default #line hidden - #line 64 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - + #line 69 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + #line default #line hidden - #line 65 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(AjaxHelpers.AjaxSave()); + #line 70 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(AjaxHelpers.AjaxSave()); #line default #line hidden - #line 65 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - + #line 70 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + #line default #line hidden - #line 66 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(AjaxHelpers.AjaxLoader()); + #line 71 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(AjaxHelpers.AjaxLoader()); #line default #line hidden - #line 66 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - + #line 71 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line default #line hidden -WriteLiteral(" \r\n $(function () {\r\n document.DiscoFun" + -"ctions.PropertyChangeHelper(\r\n $(\'#DeviceProfile_Shor" + -"tName\'),\r\n \'Short Name\',\r\n " + -" \'"); - - - #line 72 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Url.Action(MVC.API.DeviceProfile.UpdateShortName(Model.DeviceProfile.Id))); - - - #line default - #line hidden -WriteLiteral("\',\r\n \'ShortName\'\r\n );\r\n " + -" });\r\n \r\n"); +WriteLiteral(@"> + $(function () { + document.DiscoFunctions.PropertyChangeHelper( + $('#DeviceProfile_ShortName'), + 'Short Name', + '"); #line 77 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Url.Action(MVC.API.DeviceProfile.UpdateShortName(Model.DeviceProfile.Id))); + + + #line default + #line hidden +WriteLiteral("\',\r\n \'ShortName\'\r\n );\r\n" + +" });\r\n \r\n"); + + + #line 82 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" } else { - + #line default #line hidden - #line 80 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Model.DeviceProfile.ShortName); + #line 85 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Model.DeviceProfile.ShortName); #line default #line hidden - #line 80 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - + #line 85 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } #line default #line hidden -WriteLiteral("
Description:\r\n " + -" "); +WriteLiteral("
\r\n " + +" Description:\r\n \r\n"); - #line 87 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 94 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + #line default + #line hidden + + #line 94 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" if (canConfig) { - + #line default #line hidden - #line 89 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Html.EditorFor(model => model.DeviceProfile.Description)); + #line 96 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Html.EditorFor(model => model.DeviceProfile.Description)); #line default #line hidden - #line 89 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - + #line 96 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + #line default #line hidden - #line 90 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(AjaxHelpers.AjaxSave()); + #line 97 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(AjaxHelpers.AjaxSave()); #line default #line hidden - #line 90 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - + #line 97 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + #line default #line hidden - #line 91 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(AjaxHelpers.AjaxLoader()); + #line 98 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(AjaxHelpers.AjaxLoader()); #line default #line hidden - #line 91 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - + #line 98 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line default #line hidden -WriteLiteral(" \r\n $(function () {\r\n document.DiscoFun" + -"ctions.PropertyChangeHelper(\r\n $(\'#DeviceProfile_Desc" + -"ription\'),\r\n \'Description\',\r\n " + -" \'"); +WriteLiteral(@"> + $(function () { + document.DiscoFunctions.PropertyChangeHelper( + $('#DeviceProfile_Description'), + 'Description', + '"); - #line 97 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Url.Action(MVC.API.DeviceProfile.UpdateDescription(Model.DeviceProfile.Id))); + #line 104 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Url.Action(MVC.API.DeviceProfile.UpdateDescription(Model.DeviceProfile.Id))); #line default #line hidden -WriteLiteral("\',\r\n \'Description\'\r\n );\r\n " + -" });\r\n \r\n"); +WriteLiteral("\',\r\n \'Description\'\r\n );" + +"\r\n });\r\n \r\n"); - #line 102 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 109 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" } else { - + #line default #line hidden - #line 105 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Model.DeviceProfile.Description); + #line 112 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Model.DeviceProfile.Description); #line default #line hidden - #line 105 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - + #line 112 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } @@ -405,7 +427,7 @@ WriteLiteral("
\r\n
"); - #line 112 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 119 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" Write(Model.DeviceCount.ToString("n0")); @@ -414,7 +436,7 @@ WriteLiteral("
Distribution Type" + -":\r\n "); - - - #line 122 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - if (canConfig) - { - - - #line default - #line hidden - - #line 124 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Html.DropDownList("DeviceProfile_DistributionType", Model.DeviceProfileDistributionTypes)); - - - #line default - #line hidden - - #line 124 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - - - #line default - #line hidden - - #line 125 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(AjaxHelpers.AjaxLoader()); - - - #line default - #line hidden - - #line 125 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - - - #line default - #line hidden -WriteLiteral(" \r\n $(function () {\r\n document.DiscoFun" + -"ctions.PropertyChangeHelper(\r\n $(\'#DeviceProfile_Dist" + -"ributionType\'),\r\n null,\r\n " + -"\'"); +WriteLiteral("
\r\n " + +" Distribution Type:\r\n \r\n"); #line 131 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Url.Action(MVC.API.DeviceProfile.UpdateDistributionType(Model.DeviceProfile.Id))); - - - #line default - #line hidden -WriteLiteral("\',\r\n \'DistributionType\'\r\n );\r\n " + -" });\r\n \r\n"); - - - #line 136 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - } - else - { #line default #line hidden - #line 139 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Model.DeviceProfile.DistributionType.ToString()); - - - #line default - #line hidden - - #line 139 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - } - - - #line default - #line hidden -WriteLiteral("
Address:\r\n " + -" "); - - - #line 146 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 131 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" if (canConfig) { - + #line default #line hidden - #line 148 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Html.DropDownListFor(m => m.DeviceProfile.DefaultOrganisationAddress, Model.OrganisationAddresses.ToSelectListItems(Model.DeviceProfile.DefaultOrganisationAddress, true, "None"))); + #line 133 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Html.DropDownList("DeviceProfile_DistributionType", Model.DeviceProfileDistributionTypes)); #line default #line hidden - #line 148 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - + #line 133 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + #line default #line hidden - #line 149 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(AjaxHelpers.AjaxLoader()); + #line 134 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(AjaxHelpers.AjaxLoader()); #line default #line hidden - #line 149 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - + #line 134 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line default #line hidden -WriteLiteral(" \r\n $(function () {\r\n document.DiscoFun" + -"ctions.PropertyChangeHelper(\r\n $(\'#DeviceProfile_Defa" + -"ultOrganisationAddress\'),\r\n null,\r\n " + -" \'"); +WriteLiteral(@"> + $(function () { + document.DiscoFunctions.PropertyChangeHelper( + $('#DeviceProfile_DistributionType'), + null, + '"); - #line 155 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Url.Action(MVC.API.DeviceProfile.UpdateDefaultOrganisationAddress(Model.DeviceProfile.Id))); + #line 140 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Url.Action(MVC.API.DeviceProfile.UpdateDistributionType(Model.DeviceProfile.Id))); #line default #line hidden -WriteLiteral("\',\r\n \'DefaultOrganisationAddress\'\r\n " + -" );\r\n });\r\n \r\n"); +WriteLiteral("\',\r\n \'DistributionType\'\r\n " + +" );\r\n });\r\n \r\n"); - #line 160 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 145 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } + else + { + + + #line default + #line hidden + + #line 148 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Model.DeviceProfile.DistributionType.ToString()); + + + #line default + #line hidden + + #line 148 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + } + + + #line default + #line hidden +WriteLiteral(" \r\n \r\n One-to-many devices are typically shared. + One-to-one devices are typically assigned to a user; + enrolment with a one-to-one device isn't considered complete until it is assigned. +

+ +
+ Address: + +"); + + + #line 164 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + #line default + #line hidden + + #line 164 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + if (canConfig) + { + + + #line default + #line hidden + + #line 166 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Html.DropDownListFor(m => m.DeviceProfile.DefaultOrganisationAddress, Model.OrganisationAddresses.ToSelectListItems(Model.DeviceProfile.DefaultOrganisationAddress, true, "None"))); + + + #line default + #line hidden + + #line 166 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + + #line default + #line hidden + + #line 167 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(AjaxHelpers.AjaxLoader()); + + + #line default + #line hidden + + #line 167 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + + #line default + #line hidden +WriteLiteral(" + $(function () { + document.DiscoFunctions.PropertyChangeHelper( + $('#DeviceProfile_DefaultOrganisationAddress'), + null, + '"); + + + #line 173 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Url.Action(MVC.API.DeviceProfile.UpdateDefaultOrganisationAddress(Model.DeviceProfile.Id))); + + + #line default + #line hidden +WriteLiteral("\',\r\n \'DefaultOrganisationAddress\'\r\n " + +" );\r\n });\r\n \r\n"); + + + #line 178 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" } else { @@ -618,150 +679,1472 @@ WriteLiteral("\',\r\n \'DefaultOrganisationAddress\'\ #line default #line hidden -WriteLiteral(" <None Specified>\r\n"); - #line 166 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 184 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" } else { - + #line default #line hidden - #line 169 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Model.DefaultOrganisationAddress.ToString()); + #line 187 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Model.DefaultOrganisationAddress.ToString()); #line default #line hidden - #line 169 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - + #line 187 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } } #line default #line hidden -WriteLiteral("
Allocate Certific" + -"ates:\r\n "); +WriteLiteral(" \r\n \r\n The profile address is used to separate jobs for (Url.Action(MVC.Config.Organisation.Index()) + + #line default + #line hidden +, 8099), false) +); + +WriteLiteral(@">multi-site mode. + It is also suggested as the default address for warranty/repair actions. +

+ +
Policies +
+"); - #line 177 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - if (canConfig && Model.CertificateProviders.Count > 0) - { - + #line 202 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line default #line hidden - #line 179 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Html.DropDownListFor(model => model.DeviceProfile.CertificateProviderId, Model.CertificateProviders.ToSelectListItems(null, true, "Not Allocated"))); - - - #line default - #line hidden - - #line 179 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - - - #line default - #line hidden - - #line 180 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(AjaxHelpers.AjaxLoader()); - - - #line default - #line hidden - - #line 180 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - - - #line default - #line hidden -WriteLiteral(" \r\n $(function () {\r\n document.DiscoFun" + -"ctions.PropertyChangeHelper(\r\n $(\'#DeviceProfile_Cert" + -"ificateProviderId\'),\r\n null,\r\n " + -" \'"); - - - #line 186 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(Url.Action(MVC.API.DeviceProfile.UpdateCertificateProviderId(Model.DeviceProfile.Id))); - - - #line default - #line hidden -WriteLiteral("\',\r\n \'CertificateProviderId\'\r\n " + -");\r\n });\r\n \r\n"); - - - #line 191 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - } - else - { - if (string.IsNullOrEmpty(Model.DeviceProfile.CertificateProviderId)) + #line 202 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + if (canConfig) { #line default #line hidden -WriteLiteral(" <None Allocated>\r\n"); +WriteLiteral(" type=\"checkbox\""); - - #line 197 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - } - else - { - var cp = Model.CertificateProviders.FirstOrDefault(p => p.Id == Model.DeviceProfile.CertificateProviderId); - if (cp == null) - { - - - #line default - #line hidden -WriteLiteral(" <None Allocated>\r\n"); +WriteLiteral(" "); #line 204 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - } - else - { + Write(Model.DeviceProfile.ProvisionADAccount ? new MvcHtmlString("checked=\"checked\" ") : new MvcHtmlString(string.Empty)); + + + #line default + #line hidden +WriteLiteral(" />\r\n"); + +WriteLiteral(" + $(function () { + document.DiscoFunctions.PropertyChangeHelper( + $('#DeviceProfile_ProvisionADAccount'), + null, + '"); + + + #line 210 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Url.Action(MVC.API.DeviceProfile.UpdateProvisionADAccount(Model.DeviceProfile.Id))); + + + #line default + #line hidden +WriteLiteral("\',\r\n \'ProvisionADAccount\'\r\n " + +" );\r\n });\r\n \r\n"); + + + #line 215 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } + else + { + + + #line default + #line hidden +WriteLiteral("
+ + \r\n"); + + + #line 233 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + #line default + #line hidden + + #line 233 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + if (canConfig) + { + + + #line default + #line hidden +WriteLiteral("
+ Computer Name
+ Template Expression: +
+"); + + + #line 298 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" #line default #line hidden - #line 207 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - Write(cp.Name); + #line 298 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + if (canConfig && canConfigExpression) + { + + + #line default + #line hidden + + #line 300 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Html.EditorFor(model => model.DeviceProfile.ComputerNameTemplate)); #line default #line hidden - #line 207 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 300 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + + #line default + #line hidden + + #line 301 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(AjaxHelpers.AjaxSave()); + + + #line default + #line hidden + + #line 301 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + + #line default + #line hidden + + #line 302 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(AjaxHelpers.AjaxLoader()); + + + #line default + #line hidden + + #line 302 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + + #line default + #line hidden +WriteLiteral(" (Url.Action(MVC.Config.DocumentTemplate.ExpressionBrowser()) + + #line default + #line hidden +, 14674), false) +); + +WriteLiteral("> \r\n"); + +WriteLiteral(" + $(function () { + var field = $('#DeviceProfile_ComputerNameTemplate'); + var fieldOriginalWidth, fieldOriginalHeight; + + document.DiscoFunctions.PropertyChangeHelper( + field, + 'None', + '"); + + + #line 312 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Url.Action(MVC.API.DeviceProfile.UpdateComputerNameTemplate(Model.DeviceProfile.Id))); + + + #line default + #line hidden +WriteLiteral(@"', + 'ComputerNameTemplate' + ); + + field.focus(function () { + fieldOriginalWidth = field.width(); + fieldOriginalHeight = field.height(); + field.css('overflow', 'visible').animate({ width: field.parent().width() - 52, height: 75 }, 200); + }).blur(function () { + field.css('overflow', 'hidden').animate({ width: fieldOriginalWidth, height: fieldOriginalHeight }, 200); + }).attr('placeholder', 'None').attr('spellcheck', 'false'); + }); + +"); + + + #line 325 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } + else + { + + + #line default + #line hidden +WriteLiteral(" \r\n"); + + + #line 329 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + #line default + #line hidden + + #line 329 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + if (string.IsNullOrWhiteSpace(Model.DeviceProfile.ComputerNameTemplate)) + { + + + #line default + #line hidden +WriteLiteral(" <None Specified>\r\n"); + + + #line 332 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" } + else + { + + + #line default + #line hidden + + #line 335 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Model.DeviceProfile.ComputerNameTemplate); + + + #line default + #line hidden + + #line 335 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + } + + + #line default + #line hidden +WriteLiteral(" \r\n"); + + + #line 338 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } + + + #line default + #line hidden +WriteLiteral(" \r\n"); + + + #line 340 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + #line default + #line hidden + + #line 340 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + if (canConfig) + { + + + #line default + #line hidden +WriteLiteral("
+ Organisational Unit: + +"); + + + #line 376 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + #line default + #line hidden + + #line 376 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + if (canConfig) + { + + + #line default + #line hidden +WriteLiteral("
+ Provision Certificates: +"); + + + #line 548 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + #line default + #line hidden + + #line 548 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + if (canConfig && (Model.CertificateProviders.Count > 0 || Model.CertificateAuthorityProviders.Count > 0)) + { + + + #line default + #line hidden +WriteLiteral("
\r\n"); + + + #line 551 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + #line default + #line hidden + + #line 551 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(AjaxHelpers.AjaxLoader("DeviceProfile_CertificateProviders")); + + + #line default + #line hidden + + #line 551 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + } + + + #line default + #line hidden +WriteLiteral(" "); + + + #line 553 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + if (canConfig && Model.CertificateProviders.Count > 0) + { + + + #line default + #line hidden +WriteLiteral(" + $(function () { + var $container = $('#DeviceProfile_CertificateProviders'); + + $container.on('change', 'input', function () { + var $ajaxLoading = $('#DeviceProfile_CertificateProviders_loading').show(); + + var data = { + CertificateProviders: $('input:checked', $container).map(function () { return $(this).val() }).get().join(',') + }; + $.getJSON('"); + + + #line 565 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Url.Action(MVC.API.DeviceProfile.UpdateCertificateProviders(Model.DeviceProfile.Id))); + + + #line default + #line hidden +WriteLiteral(@"', data, function (response, result) { + if (result != 'success' || response != 'OK') { + alert('Unable to change property ""CertificateProviders"":\n' + response); + $ajaxLoading.hide(); + } else { + $ajaxLoading.hide().next('.ajaxOk').show().delay('fast').fadeOut('slow'); + } + }) + }) + }); + +"); + + + #line 576 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } + + + #line default + #line hidden +WriteLiteral(" "); + + + #line 577 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + if (canConfig && Model.CertificateProviders.Count > 0) + { + + + #line default + #line hidden +WriteLiteral(" + $(function () { + var $container = $('#DeviceProfile_CertificateAuthorityProviders'); + + $container.on('change', 'input', function () { + var $ajaxLoading = $('#DeviceProfile_CertificateProviders_loading').show(); + + var data = { + CertificateAuthorityProviders: $('input:checked', $container).map(function () { return $(this).val() }).get().join(',') + }; + $.getJSON('"); + + + #line 589 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Url.Action(MVC.API.DeviceProfile.UpdateCertificateAuthorityProviders(Model.DeviceProfile.Id))); + + + #line default + #line hidden +WriteLiteral(@"', data, function (response, result) { + if (result != 'success' || response != 'OK') { + alert('Unable to change property ""CertificateAuthorityProviders"":\n' + response); + $ajaxLoading.hide(); + } else { + $ajaxLoading.hide().next('.ajaxOk').show().delay('fast').fadeOut('slow'); + } + }) + }) + }); + +"); + + + #line 600 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } + + + #line default + #line hidden +WriteLiteral("
\r\n

Device/Machine Certifica" + +"tes

\r\n"); + + + #line 604 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + #line default + #line hidden + + #line 604 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + if (canConfig && Model.CertificateProviders.Count > 0) + { + + + #line default + #line hidden + + #line 606 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(CommonHelpers.CheckBoxList("DeviceProfile_CertificateProviders", "DeviceProfile_CertificateProviders", Model.CertificateProviders.ToSelectListItems(Model.DeviceProfile.GetCertificateProviders()))); + + + #line default + #line hidden + + #line 606 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + } + else + { + var certificateProviders = Model.DeviceProfile.GetCertificateProviders().ToList(); + + if (certificateProviders.Count == 0) + { + + + #line default + #line hidden +WriteLiteral(" <None Allocated>\r\n"); + + + #line 615 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } + else + { + + + #line default + #line hidden +WriteLiteral("
    \r\n"); + + + #line 619 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + #line default + #line hidden + + #line 619 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + foreach (var certificateProvider in certificateProviders) + { + + + #line default + #line hidden +WriteLiteral("
  • "); + + + #line 621 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(certificateProvider.Name); + + + #line default + #line hidden +WriteLiteral("
  • \r\n"); + + + #line 622 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } + + + #line default + #line hidden +WriteLiteral("
\r\n"); + + + #line 624 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } + } + + + #line default + #line hidden +WriteLiteral(" Authority Certificates\r\n"); + + + #line 627 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + #line default + #line hidden + + #line 627 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + if (canConfig && Model.CertificateAuthorityProviders.Count > 0) + { + + + #line default + #line hidden + + #line 629 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(CommonHelpers.CheckBoxList("DeviceProfile_CertificateAuthorityProviders", "DeviceProfile_CertificateAuthorityProviders", Model.CertificateAuthorityProviders.ToSelectListItems(Model.DeviceProfile.GetCertificateAuthorityProviders()))); + + + #line default + #line hidden + + #line 629 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + } + else + { + var certificateProviders = Model.DeviceProfile.GetCertificateAuthorityProviders().ToList(); + + if (certificateProviders.Count == 0) + { + + + #line default + #line hidden +WriteLiteral(" <None Allocated>\r\n"); + + + #line 638 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } + else + { + + + #line default + #line hidden +WriteLiteral("
    \r\n"); + + + #line 642 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + #line default + #line hidden + + #line 642 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + foreach (var certificateProvider in certificateProviders) + { + + + #line default + #line hidden +WriteLiteral("
  • "); + + + #line 644 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(certificateProvider.Name); + + + #line default + #line hidden +WriteLiteral("
  • \r\n"); + + + #line 645 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } + + + #line default + #line hidden +WriteLiteral("
\r\n"); + + + #line 647 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" } } @@ -771,7 +2154,229 @@ WriteLiteral("><None Allocated>\r\n"); WriteLiteral(" "); - #line 211 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 649 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + if (canViewPlugins) + { + + + #line default + #line hidden +WriteLiteral(" \r\n \r\n View the (Url.Action(MVC.Config.Plugins.Install()) + + #line default + #line hidden +, 34303), false) +); + +WriteLiteral(">Plugin Catalogue to discover and install certificate provider plugins.\r\n " + +"

\r\n \r\n"); + + + #line 656 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } + + + #line default + #line hidden +WriteLiteral("
\r\n " + +" Provision Wireless Profiles:\r\n"); + + + #line 662 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + #line default + #line hidden + + #line 662 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + if (canConfig && Model.WirelessProfileProviders.Count > 0) + { + + + #line default + #line hidden +WriteLiteral("
\r\n"); + + + #line 665 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + #line default + #line hidden + + #line 665 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(AjaxHelpers.AjaxLoader("DeviceProfile_WirelessProfileProviders")); + + + #line default + #line hidden + + #line 665 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + + #line default + #line hidden +WriteLiteral(" + $(function () { + var $container = $('#DeviceProfile_WirelessProfileProviders'); + + $container.on('change', 'input', function () { + var $ajaxLoading = $('#DeviceProfile_WirelessProfileProviders_loading').show(); + + var data = { + WirelessProfileProviders: $('input:checked', $container).map(function () { return $(this).val() }).get().join(',') + }; + $.getJSON('"); + + + #line 676 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(Url.Action(MVC.API.DeviceProfile.UpdateWirelessProfileProviders(Model.DeviceProfile.Id))); + + + #line default + #line hidden +WriteLiteral(@"', data, function (response, result) { + if (result != 'success' || response != 'OK') { + alert('Unable to change property ""WirelessProfileProviders"":\n' + response); + $ajaxLoading.hide(); + } else { + $ajaxLoading.hide().next('.ajaxOk').show().delay('fast').fadeOut('slow'); + } + }) + }) + }); + +"); + + + #line 687 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } + + + #line default + #line hidden +WriteLiteral("
\r\n"); + + + #line 690 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + #line default + #line hidden + + #line 690 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + if (canConfig && Model.WirelessProfileProviders.Count > 0) + { + + + #line default + #line hidden + + #line 692 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(CommonHelpers.CheckBoxList("DeviceProfile_WirelessProfileProviders", "DeviceProfile_WirelessProfileProviders", Model.WirelessProfileProviders.ToSelectListItems(Model.DeviceProfile.GetWirelessProfileProviders()))); + + + #line default + #line hidden + + #line 692 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + } + else + { + var wirelessProfileProviders = Model.DeviceProfile.GetWirelessProfileProviders().ToList(); + + if (wirelessProfileProviders.Count == 0) + { + + + #line default + #line hidden +WriteLiteral(" <None Allocated>\r\n"); + + + #line 701 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } + else + { + + + #line default + #line hidden +WriteLiteral("
    \r\n"); + + + #line 705 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + + + #line default + #line hidden + + #line 705 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + foreach (var wirelessProfileProvider in wirelessProfileProviders) + { + + + #line default + #line hidden +WriteLiteral("
  • "); + + + #line 707 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + Write(wirelessProfileProvider.Name); + + + #line default + #line hidden +WriteLiteral("
  • \r\n"); + + + #line 708 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } + + + #line default + #line hidden +WriteLiteral("
\r\n"); + + + #line 710 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + } + } + + + #line default + #line hidden +WriteLiteral(" "); + + + #line 712 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" if (canViewPlugins) { @@ -792,992 +2397,36 @@ WriteLiteral(" class=\"fa fa-info-circle\""); WriteLiteral(">View the (Url.Action(MVC.Config.Plugins.Install()) + #line 716 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" +, Tuple.Create(Tuple.Create("", 37549), Tuple.Create(Url.Action(MVC.Config.Plugins.Install()) #line default #line hidden -, 8933), false) +, 37549), false) ); -WriteLiteral(">Plugin Catalogue to discover and install certificate provider plugins.\r\n " + -"

\r\n \r\n"); +WriteLiteral(">Plugin Catalogue to discover and install wireless profile provider plugins.\r" + +"\n

\r\n \r\n"); - #line 218 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 719 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" } #line default #line hidden -WriteLiteral("
Computer Name
\r\n Template Expression:\r\n
"); +WriteLiteral("
Policies\r\n " + -"
\r\n"); - - - #line 299 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - - #line default - #line hidden - - #line 299 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - if (canConfig) - { - - - #line default - #line hidden -WriteLiteral("
\r\n \r\n"); - - - #line 323 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - - - #line default - #line hidden - - #line 323 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - if (canConfig) - { - - - #line default - #line hidden -WriteLiteral("
Organisational Unit:\r\n "); - - - #line 375 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" - if (canConfig) - { - - - #line default - #line hidden -WriteLiteral("
Linked Groups:\r\n \r\n " + -"
\r\n"); +WriteLiteral(">\r\n
\r\n Linked Groups:\r\n \r\n
\r\n"); WriteLiteral(" "); - #line 559 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 745 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" Write(Html.Partial(MVC.Config.Shared.Views.LinkedGroupInstance, new LinkedGroupModel() { CanConfigure = canConfig, @@ -1845,7 +2494,7 @@ WriteLiteral("\r\n"); WriteLiteral(" "); - #line 567 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 753 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" Write(Html.Partial(MVC.Config.Shared.Views.LinkedGroupInstance, new LinkedGroupModel() { CanConfigure = canConfig, @@ -1861,13 +2510,13 @@ WriteLiteral(" "); WriteLiteral("\r\n"); - #line 575 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 761 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" #line default #line hidden - #line 575 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 761 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" if (canConfig) { @@ -1875,14 +2524,14 @@ WriteLiteral("\r\n"); #line default #line hidden - #line 577 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 763 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" Write(Html.Partial(MVC.Config.Shared.Views.LinkedGroupShared)); #line default #line hidden - #line 577 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 763 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" } @@ -1892,7 +2541,7 @@ WriteLiteral("\r\n"); WriteLiteral("
\r\n
\r\n
\r\n"); - #line 584 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 770 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" if (canDelete) { @@ -1947,7 +2596,7 @@ WriteLiteral(@"> "); - #line 620 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 806 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" } @@ -1960,28 +2609,28 @@ WriteLiteral(" class=\"actionBar\""); WriteLiteral(">\r\n"); - #line 622 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 808 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" #line default #line hidden - #line 622 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 808 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" if (canDelete) - { + { #line default #line hidden - #line 624 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 810 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" Write(Html.ActionLinkButton("Delete", MVC.API.DeviceProfile.Delete(Model.DeviceProfile.Id, true), "buttonDelete")); #line default #line hidden - #line 624 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 810 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" } @@ -1991,7 +2640,7 @@ WriteLiteral(">\r\n"); WriteLiteral(" "); - #line 626 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 812 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" if (Authorization.Has(Claims.Device.Actions.Export)) { @@ -1999,14 +2648,14 @@ WriteLiteral(" "); #line default #line hidden - #line 628 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 814 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" Write(Html.ActionLinkButton("Export Devices", MVC.Device.Export(null, Disco.Models.Services.Devices.Exporting.DeviceExportTypes.Profile, Model.DeviceProfile.Id))); #line default #line hidden - #line 628 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 814 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" } @@ -2016,7 +2665,7 @@ WriteLiteral(" "); WriteLiteral(" "); - #line 630 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 816 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" if (Authorization.Has(Claims.Device.Search) && Model.DeviceCount > 0) { @@ -2024,14 +2673,14 @@ WriteLiteral(" "); #line default #line hidden - #line 632 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 818 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" Write(Html.ActionLinkButton(string.Format("View {0} Device{1}", Model.DeviceCount, (Model.DeviceCount != 1 ? "s" : null)), MVC.Search.Query(Model.DeviceProfile.Id.ToString(), "DeviceProfile"))); #line default #line hidden - #line 632 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" + #line 818 "..\..\Areas\Config\Views\DeviceProfile\Show.cshtml" } diff --git a/Disco.Web/Areas/Config/Views/DocumentTemplate/Show.cshtml b/Disco.Web/Areas/Config/Views/DocumentTemplate/Show.cshtml index a675dbef..cb22a1f0 100644 --- a/Disco.Web/Areas/Config/Views/DocumentTemplate/Show.cshtml +++ b/Disco.Web/Areas/Config/Views/DocumentTemplate/Show.cshtml @@ -1,5 +1,5 @@ @model Disco.Web.Areas.Config.Models.DocumentTemplate.ShowModel -@using Disco.BI.DocumentTemplateBI.ManagedGroups; +@using Disco.Services.Documents.ManagedGroups; @using Disco.Services.Interop.ActiveDirectory; @using Disco.Web.Areas.Config.Models.Shared; @{ diff --git a/Disco.Web/Areas/Config/Views/DocumentTemplate/Show.generated.cs b/Disco.Web/Areas/Config/Views/DocumentTemplate/Show.generated.cs index 0f0a2cc6..5b5acbc3 100644 --- a/Disco.Web/Areas/Config/Views/DocumentTemplate/Show.generated.cs +++ b/Disco.Web/Areas/Config/Views/DocumentTemplate/Show.generated.cs @@ -27,17 +27,16 @@ namespace Disco.Web.Areas.Config.Views.DocumentTemplate using System.Web.UI; using System.Web.WebPages; using Disco; - - #line 2 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" - using Disco.BI.DocumentTemplateBI.ManagedGroups; - - #line default - #line hidden - using Disco.BI.Extensions; using Disco.Models.Repository; using Disco.Services; using Disco.Services.Authorization; + #line 2 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + using Disco.Services.Documents.ManagedGroups; + + #line default + #line hidden + #line 3 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" using Disco.Services.Interop.ActiveDirectory; @@ -112,14 +111,14 @@ WriteLiteral("\r\n(hideAdvanced ? "Config_HideAdvanced" : null +, Tuple.Create(Tuple.Create("", 2032), Tuple.Create(hideAdvanced ? "Config_HideAdvanced" : null #line default #line hidden -, 2035), false) +, 2032), false) ); WriteLiteral(">\r\n This template is generated from "); #line hidden WriteLiteral("s. Any expressions within the Template PDF will be evaluated within the (Url.Action(MVC.Config.DocumentTemplate.ExpressionBrowser()) + , Tuple.Create(Tuple.Create("", 7006), Tuple.Create(Url.Action(MVC.Config.DocumentTemplate.ExpressionBrowser()) #line default #line hidden -, 7009), false) -, Tuple.Create(Tuple.Create("", 7071), Tuple.Create("#", 7071), true) +, 7006), false) +, Tuple.Create(Tuple.Create("", 7068), Tuple.Create("#", 7068), true) #line 143 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" - , Tuple.Create(Tuple.Create("", 7072), Tuple.Create(Model.DocumentTemplate.Scope + , Tuple.Create(Tuple.Create("", 7069), Tuple.Create(Model.DocumentTemplate.Scope #line default #line hidden -, 7072), false) -, Tuple.Create(Tuple.Create("", 7103), Tuple.Create("Scope", 7103), true) +, 7069), false) +, Tuple.Create(Tuple.Create("", 7100), Tuple.Create("Scope", 7100), true) ); WriteLiteral(">"); @@ -568,24 +567,24 @@ WriteLiteral(">\r\n"); #line hidden WriteLiteral(" (scope +, Tuple.Create(Tuple.Create("", 8225), Tuple.Create(scope #line default #line hidden -, 8228), false) +, 8225), false) ); -WriteAttribute("selected", Tuple.Create(" selected=\"", 8235), Tuple.Create("\"", 8306) +WriteAttribute("selected", Tuple.Create(" selected=\"", 8232), Tuple.Create("\"", 8303) #line 159 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" - , Tuple.Create(Tuple.Create("", 8246), Tuple.Create(scope == Model.DocumentTemplate.Scope ? "selected" : null + , Tuple.Create(Tuple.Create("", 8243), Tuple.Create(scope == Model.DocumentTemplate.Scope ? "selected" : null #line default #line hidden -, 8246), false) +, 8243), false) ); WriteLiteral(">"); @@ -923,29 +922,29 @@ WriteLiteral(" class=\"jobTypes\""); WriteLiteral(">\r\n

\r\n " + " (jt.Id +, Tuple.Create(Tuple.Create("", 14959), Tuple.Create(jt.Id #line default #line hidden -, 14962), false) +, 14959), false) ); WriteLiteral(" class=\"jobType\""); WriteLiteral(" type=\"checkbox\""); -WriteAttribute("value", Tuple.Create(" value=\"", 15003), Tuple.Create("\"", 15019) +WriteAttribute("value", Tuple.Create(" value=\"", 15000), Tuple.Create("\"", 15016) #line 257 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" - , Tuple.Create(Tuple.Create("", 15011), Tuple.Create(jt.Id + , Tuple.Create(Tuple.Create("", 15008), Tuple.Create(jt.Id #line default #line hidden -, 15011), false) +, 15008), false) ); WriteLiteral(" "); @@ -959,15 +958,15 @@ WriteLiteral(" "); #line hidden WriteLiteral(" />(jt.Id + , Tuple.Create(Tuple.Create("", 15099), Tuple.Create(jt.Id #line default #line hidden -, 15102), false) +, 15099), false) ); WriteLiteral(">"); @@ -982,15 +981,15 @@ WriteLiteral(">"); WriteLiteral("\r\n

\r\n " + " (jt.Id +, Tuple.Create(Tuple.Create("", 15263), Tuple.Create(jt.Id #line default #line hidden -, 15266), false) +, 15263), false) ); WriteLiteral(" class=\"jobSubTypes\""); @@ -1111,14 +1110,14 @@ WriteLiteral(">\r\n (Url.Action(MVC.API.DocumentTemplate.TemplatePreview(Model.DocumentTemplate.Id)) +, Tuple.Create(Tuple.Create("", 20219), Tuple.Create(Url.Action(MVC.API.DocumentTemplate.TemplatePreview(Model.DocumentTemplate.Id)) #line default #line hidden -, 20222), false) +, 20219), false) ); WriteLiteral(" />\r\n
\r\n
- - - - - - + + + + } else { - - - - + + + + if (Model.UpdateAvailable) { - - - - + + + + } else { - - - - + + + + } } } @@ -123,13 +130,13 @@ @{ if (Model.UpdateRunningStatus == null) { - @Html.ActionLinkSmallButton("Check Now", MVC.API.System.UpdateCheck()) - [Will run automatically @CommonHelpers.FriendlyDate(Model.UpdateNextScheduled, "Unknown")] + @Html.ActionLinkSmallButton("Check Now", MVC.API.System.UpdateCheck()) + [Will run automatically @CommonHelpers.FriendlyDate(Model.UpdateNextScheduled, "Unknown")] } else { - @Html.ActionLink("View Status", MVC.Config.Logging.TaskStatus(Model.UpdateRunningStatus.SessionId)) - [Running Now] + @Html.ActionLink("View Status", MVC.Config.Logging.TaskStatus(Model.UpdateRunningStatus.SessionId)) + [Running Now] } } @if (Model.UpdateBetaDeployment) @@ -145,14 +152,16 @@

Active Directory

Disco Version: + + Disco Version:
@@ -29,7 +30,8 @@
Database Connection: + + Database Connection: @@ -46,18 +48,19 @@ @{if (Model.DatabaseSqlAuthUsername != null) - { - - - - - } + { + + + + + } }
@Model.DatabaseAuthentication
SQL User:@Model.DatabaseSqlAuthUsername
SQL User:@Model.DatabaseSqlAuthUsername
Data Store Location: + + Data Store Location: @Model.DataStoreLocation @@ -71,49 +74,53 @@ @{ if (Model.UpdateLatestResponse == null) { -
Last Check: - -
 Never
-
+ Last Check: + +
 Never
+
Last Run: - - @CommonHelpers.FriendlyDate(Model.UpdateLatestResponse.UpdateResponseDate.ToLocalTime()) -
+ Last Run: + + @CommonHelpers.FriendlyDate(Model.UpdateLatestResponse.UpdateResponseDate.ToLocalTime()) +
Update Available: - -
-  Version @(Model.UpdateLatestResponse.LatestVersion) is available -
-
- [Released @(CommonHelpers.FriendlyDate(Model.UpdateLatestResponse.ReleasedDate))] -
-
@(new HtmlString(Model.UpdateLatestResponse.Description))
- Download Now -
+ Update Available: + +
+  Version @(Model.UpdateLatestResponse.LatestVersion) is available +
+
+ [Released @(CommonHelpers.FriendlyDate(Model.UpdateLatestResponse.ReleasedDate))] +
+
@(new HtmlString(Model.UpdateLatestResponse.Description))
+ Download Now +
Status: - -  The latest version is installed -
+ Status: + +  The latest version is installed +
- - - - - + + + + + - + + +
Primary Domain: + + Primary Domain: @Model.ADPrimaryDomain.Name [@Model.ADPrimaryDomain.NetBiosName]
Additional Domains: + + Additional Domains: @if (Model.ADDomains.Count > 1) @@ -162,10 +171,10 @@ @adDomainFirst.Name [@adDomainFirst.NetBiosName] foreach (var adDomain in adAdditionalDomains.Skip(1)) { -
-
- @adDomain.Name [@adDomain.NetBiosName] -
+
+
+ @adDomain.Name [@adDomain.NetBiosName] +
} } else @@ -175,14 +184,16 @@
Site: + + Site: @Model.ADSite.Name
Servers: + + Servers:
@@ -229,7 +240,8 @@
Forest: + + Forest: @if (Model.ADForestServers == null) @@ -249,60 +261,66 @@ if (canConfigAD) { var canSearchEntireForest = (Model.ADForestServers.Count <= Disco.Services.Interop.ActiveDirectory.ActiveDirectory.MaxForestServerSearch); -
- @if (!canSearchEntireForest) - { - @Html.CheckBoxFor(m => m.ADSearchAllForestServers, new { disabled = "disabled" }) @Html.LabelFor(m => m.ADSearchAllForestServers) -
-

- Disco will not search entire forests which consist of more than @(Disco.Services.Interop.ActiveDirectory.ActiveDirectory.MaxForestServerSearch) servers. Only servers within this site will be searched. -

-
- } - else - { - @Html.CheckBoxFor(m => m.ADSearchAllForestServers) @Html.LabelFor(m => m.ADSearchAllForestServers) @AjaxHelpers.AjaxLoader() -
- If this setting is enabled, Disco will query all servers within the forest rather than only servers within this site. -
- - } -
+
+ @if (!canSearchEntireForest) + { + @Html.CheckBoxFor(m => m.ADSearchAllForestServers, new { disabled = "disabled" }) @Html.LabelFor(m => m.ADSearchAllForestServers) +
+

+ Disco will not search entire forests which consist of more than @(Disco.Services.Interop.ActiveDirectory.ActiveDirectory.MaxForestServerSearch) servers. Only servers within this site will be searched. +

+
+ } + else + { + @Html.CheckBoxFor(m => m.ADSearchAllForestServers) @Html.LabelFor(m => m.ADSearchAllForestServers) @AjaxHelpers.AjaxLoader() +
+

+ If this setting is enabled, Disco will query all servers within the forest rather than only servers within this site. +

+
+ + } +
} else { -
- @Html.CheckBoxFor(m => m.ADSearchAllForestServers, new { disabled = "disabled" }) @Html.LabelFor(m => m.ADSearchAllForestServers) -
- If this setting is enabled, Disco will search all servers within the forest rather than only servers within this site. +
+ @Html.CheckBoxFor(m => m.ADSearchAllForestServers, new { disabled = "disabled" }) @Html.LabelFor(m => m.ADSearchAllForestServers) +
+

+ If this setting is enabled, Disco will query all servers within the forest rather than only servers within this site. +

+
-
}

All Servers:
    @{ - var domainIndex = Model.ADDomains.ToDictionary(d => d.Name, StringComparer.OrdinalIgnoreCase); - foreach (var server in Model.ADForestServers.OrderBy(s => s)) - { - var isSiteServer = Model.ADServers.Any(s => s.IsSiteServer && s.Name.Equals(server, StringComparison.OrdinalIgnoreCase)); - var serverDescription = server; - if (server.Contains('.')) - { - Disco.Services.Interop.ActiveDirectory.ADDomain serverDomain; - if (domainIndex.TryGetValue(server.Substring(server.IndexOf('.') + 1), out serverDomain)) - { - serverDescription = string.Format("{0} [{1}]", server.Substring(0, server.IndexOf('.')), serverDomain.NetBiosName); - } - } -
  • @serverDescription@if (isSiteServer) - { }
  • - } + var domainIndex = Model.ADDomains.ToDictionary(d => d.Name, StringComparer.OrdinalIgnoreCase); + foreach (var server in Model.ADForestServers.OrderBy(s => s)) + { + var isSiteServer = Model.ADServers.Any(s => s.IsSiteServer && s.Name.Equals(server, StringComparison.OrdinalIgnoreCase)); + var serverDescription = server; + if (server.Contains('.')) + { + Disco.Services.Interop.ActiveDirectory.ADDomain serverDomain; + if (domainIndex.TryGetValue(server.Substring(server.IndexOf('.') + 1), out serverDomain)) + { + serverDescription = string.Format("{0} [{1}]", server.Substring(0, server.IndexOf('.')), serverDomain.NetBiosName); + } + } +
  • + @serverDescription@if (isSiteServer) + { } +
  • + } }
+ } +
+ Searching: + + @{ + object ADSearchWildcardSuffixOnlyAttributes = null; + if (!canConfigAD) + { + ADSearchWildcardSuffixOnlyAttributes = new + { + disabled = "disabled" + }; + } + } + @Html.CheckBoxFor(m => m.ADSearchWildcardSuffixOnly, ADSearchWildcardSuffixOnlyAttributes) @Html.LabelFor(m => m.ADSearchWildcardSuffixOnly) @AjaxHelpers.AjaxLoader() +
+

+ If this setting is enabled, Disco will utilize Active Directory indexes to greatly improve search performance. + If disabled, more results may be returned however performance will be reduced especially in large Active Directory domains. +

+
+ @if (canConfigAD) + { + }
Search Scope: + + Search Scope: @if (Model.ADSearchContainers != null && Model.ADSearchContainers.Count > 0) @@ -347,8 +399,12 @@ } else { -
No restrictions are in effect.
-
When searching, the entire domain will be queried. This is suitable for most single-domain deployments.
+
No Organisational Unit restrictions are in effect.
+
+

+ When searching, the entire domain will be queried. This is suitable for most single-domain deployments. +

+
} @if (canConfigAD) { @@ -475,88 +531,96 @@ }
@if (canConfigProxy) { using (Html.BeginForm(MVC.API.System.UpdateProxySettings())) - { -
-

Proxy Settings

- - - - - - - - - - - - - - - - - - - - - -
Address: - - @Html.EditorFor(m => m.ProxyAddress)
- @Html.ValidationMessageFor(m => m.ProxyAddress) -
Port: - - @Html.EditorFor(m => m.ProxyPort)
- @Html.ValidationMessageFor(m => m.ProxyPort) -
Username: - - @Html.EditorFor(m => m.ProxyUsername)
- @Html.ValidationMessageFor(m => m.ProxyUsername) -
Password: - - @Html.EditorFor(m => m.ProxyPassword)
- @Html.ValidationMessageFor(m => m.ProxyPassword) -
  - - @AjaxHelpers.AjaxLoader() - -
-
+ + + + + } } else @@ -565,30 +629,35 @@ else

Proxy Settings

- - - - -
Address: + + Address: @Html.DisplayFor(m => m.ProxyAddress)
Port: + + Port: @Html.DisplayFor(m => m.ProxyPort)
Username: + + Username: @Html.DisplayFor(m => m.ProxyUsername)
Password: + + Password: ******** + + ********
diff --git a/Disco.Web/Areas/Config/Views/SystemConfig/Index.generated.cs b/Disco.Web/Areas/Config/Views/SystemConfig/Index.generated.cs index 0fd4c4fa..768e9278 100644 --- a/Disco.Web/Areas/Config/Views/SystemConfig/Index.generated.cs +++ b/Disco.Web/Areas/Config/Views/SystemConfig/Index.generated.cs @@ -2,7 +2,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -27,7 +27,6 @@ namespace Disco.Web.Areas.Config.Views.SystemConfig using System.Web.UI; using System.Web.WebPages; using Disco; - using Disco.BI.Extensions; using Disco.Models.Repository; using Disco.Services; using Disco.Services.Authorization; @@ -74,11 +73,11 @@ WriteLiteral(">\r\n \r\n \r\n Disco Version:\r\n \r\n \r\n \r WriteLiteral(" style=\"width: 135px\""); -WriteLiteral(">Database Connection:\r\n \r\n \r\n \r\n < " \r\n \r\n \r\n < WriteLiteral("\r\n \r\n"); - #line 48 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 50 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" #line default #line hidden - #line 48 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 50 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" if (Model.DatabaseSqlAuthUsername != null) - { + { #line default #line hidden -WriteLiteral(" \r\n " + -"\r\n \r\n \r\n \r\n"); +WriteLiteral("\r\n \r\n"); - #line 54 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - } + #line 56 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + } #line default @@ -199,15 +188,15 @@ WriteLiteral("\r\n
\r\n
\r\n " + -" "); +WriteLiteral(">\r\n Disco Version:\r\n \r\n
\r\n " + +"
\r\n "); - #line 24 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 25 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(Model.DiscoVersion.ToString(4)); @@ -88,20 +87,10 @@ WriteLiteral("\r\n
\r\n (Model.DiscoVersionBuilt.ToFullDateTime() - - #line default - #line hidden -, 961), false) -); - WriteLiteral(">\r\n Built "); - #line 27 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 28 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(CommonHelpers.FriendlyDate(Model.DiscoVersionBuilt, "Unknown")); @@ -112,8 +101,8 @@ WriteLiteral("\r\n \r\n
\r\n \r\n Database Connection:\r\n \r\n \r\n " + +" "); - #line 38 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 40 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(Model.DatabaseServer); @@ -139,7 +128,7 @@ WriteLiteral(" class=\"code\""); WriteLiteral(">"); - #line 42 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 44 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(Model.DatabaseName); @@ -149,7 +138,7 @@ WriteLiteral("
Authentication:"); - #line 46 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 48 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(Model.DatabaseAuthentication); @@ -158,38 +147,38 @@ WriteLiteral("
SQL User:\r\n SQL Us" + +"er:"); - #line 52 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(Model.DatabaseSqlAuthUsername); + #line 54 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Model.DatabaseSqlAuthUsername); #line default #line hidden -WriteLiteral("
\r\n \r\n WriteLiteral(" style=\"width: 135px\""); -WriteLiteral(">Data Store Location:\r\n \r\n \r\n \r\n Data Store Location:\r\n \r\n \r\n " + +" "); - #line 63 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 66 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(Model.DataStoreLocation); @@ -222,13 +211,13 @@ WriteLiteral(" style=\"width: 450px; margin-top: 15px;\""); WriteLiteral(">\r\n

Updates

\r\n \r\n"); - #line 71 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 74 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" #line default #line hidden - #line 71 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 74 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" if (Model.UpdateLatestResponse == null) { @@ -236,12 +225,12 @@ WriteLiteral(">\r\n

Updates

\r\n
\r\n"); #line default #line hidden -WriteLiteral(" \r\n \r\n Last Check:\r\n \r\n \r\n \r\n"); +WriteLiteral("> Never\r\n \r\n \r\n"); - #line 81 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 85 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } else { @@ -260,92 +249,94 @@ WriteLiteral("> Never\r\n \r\n \r\n \r\n Last Run:\r\n \r\n \r\n \r\n"); +WriteLiteral("\r\n \r\n \r\n"); - #line 91 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 96 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" if (Model.UpdateAvailable) { #line default #line hidden -WriteLiteral(" \r\n \r\n Update Available:\r\n \r\n \r\n \r\n"); +WriteLiteral(">Download Now\r\n \r\n \r\n"); - #line 107 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 113 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } else { @@ -353,19 +344,20 @@ WriteLiteral(">Download Now\r\n \r\n \r\ #line default #line hidden -WriteLiteral(" \r\n \r\n Status:\r\n \r\n \r\n " + -" \r\n"); +WriteLiteral("> The latest version is installed\r\n " + +"\r\n \r\n"); - #line 117 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 124 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } } @@ -379,13 +371,13 @@ WriteLiteral(" style=\"width: 135px\""); WriteLiteral(">Check for Update:\r\n \r\n\r\n\r\n\r\n \r\n
\r\n \r\n Last Check:\r\n \r\n " + +" \r\n  Never\r\n
\r\n "); +WriteLiteral(">\r\n Last Run:\r\n \r\n " + +" \r\n "); - #line 88 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(CommonHelpers.FriendlyDate(Model.UpdateLatestResponse.UpdateResponseDate.ToLocalTime())); + #line 93 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(CommonHelpers.FriendlyDate(Model.UpdateLatestResponse.UpdateResponseDate.ToLocalTime())); #line default #line hidden -WriteLiteral("\r\n
\r\n " + -"
\r\n \r\n Update Available:\r\n \r\n" + +"
\r\n
\r\n " + +"  Version "); - #line 98 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(Model.UpdateLatestResponse.LatestVersion); + #line 104 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Model.UpdateLatestResponse.LatestVersion); #line default #line hidden -WriteLiteral(" is available\r\n
\r\n \r\n \r\n [Released "); +WriteLiteral(">\r\n [Released "); - #line 101 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(CommonHelpers.FriendlyDate(Model.UpdateLatestResponse.ReleasedDate)); + #line 107 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(CommonHelpers.FriendlyDate(Model.UpdateLatestResponse.ReleasedDate)); #line default #line hidden -WriteLiteral("]\r\n \r\n \r\n "); - #line 103 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(new HtmlString(Model.UpdateLatestResponse.Description)); + #line 109 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(new HtmlString(Model.UpdateLatestResponse.Description)); #line default #line hidden -WriteLiteral("\r\n \r\n (Model.UpdateLatestResponse.UrlLink + #line 110 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" +, Tuple.Create(Tuple.Create("", 4200), Tuple.Create(Model.UpdateLatestResponse.UrlLink #line default #line hidden -, 3948), false) +, 4200), false) ); WriteLiteral(" target=\"_blank\""); -WriteLiteral(">Download Now\r\n
\r\n \r\n Status:\r\n \r\n " + +" \r\n  The latest version is installed\r\n
\r\n"); - #line 123 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 130 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" #line default #line hidden - #line 123 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 130 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" if (Model.UpdateRunningStatus == null) { @@ -393,26 +385,26 @@ WriteLiteral(">Check for Update:\r\n \r\n"); #line default #line hidden -WriteLiteral(" "); +WriteLiteral(" "); - #line 126 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(Html.ActionLinkSmallButton("Check Now", MVC.API.System.UpdateCheck())); + #line 133 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Html.ActionLinkSmallButton("Check Now", MVC.API.System.UpdateCheck())); #line default #line hidden WriteLiteral("\r\n"); -WriteLiteral(" [Will run automatically "); - #line 127 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(CommonHelpers.FriendlyDate(Model.UpdateNextScheduled, "Unknown")); + #line 134 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(CommonHelpers.FriendlyDate(Model.UpdateNextScheduled, "Unknown")); #line default @@ -420,7 +412,7 @@ WriteLiteral(">[Will run automatically "); WriteLiteral("]\r\n"); - #line 128 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 135 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } else { @@ -428,25 +420,25 @@ WriteLiteral("]\r\n"); #line default #line hidden -WriteLiteral(" "); +WriteLiteral(" "); - #line 131 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(Html.ActionLink("View Status", MVC.Config.Logging.TaskStatus(Model.UpdateRunningStatus.SessionId))); + #line 138 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Html.ActionLink("View Status", MVC.Config.Logging.TaskStatus(Model.UpdateRunningStatus.SessionId))); #line default #line hidden WriteLiteral("\r\n"); -WriteLiteral(" [Running Now]\r\n"); - #line 133 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 140 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } @@ -455,13 +447,13 @@ WriteLiteral(">[Running Now]\r\n"); WriteLiteral("\r\n"); - #line 135 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 142 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" #line default #line hidden - #line 135 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 142 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" if (Model.UpdateBetaDeployment) { @@ -481,7 +473,7 @@ WriteLiteral(" class=\"fa fa-info-circle fa-lg\""); WriteLiteral("> Beta Deployment\r\n"); - #line 139 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 146 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } @@ -497,11 +489,11 @@ WriteLiteral(">\r\n

Active Directory

\r\n \r\n \ WriteLiteral(" style=\"width: 135px\""); -WriteLiteral(">Primary Domain:\r\n \r\n \r\n \r\n < WriteLiteral(" style=\"width: 135px\""); -WriteLiteral(">Additional Domains:\r\n \r\n \r\n \r\n \r\n WriteLiteral(" style=\"width: 135px\""); -WriteLiteral(">Site:\r\n \r\n \r\n \r\n WriteLiteral(" style=\"width: 135px\""); -WriteLiteral(">Servers:\r\n \r\n \r\n \r\n WriteLiteral(" style=\"width: 135px\""); -WriteLiteral(">Forest:\r\n \r\n \r\n\r\n \r\n \r\n \r\n Searching:\r\n \r\n \r\n \r\n \r\n WriteLiteral(" style=\"width: 135px\""); -WriteLiteral(">Search Scope:\r\n \r\n \r\n \r\n
\r\n "); +WriteLiteral(">\r\n Primary Domain:\r\n \r\n \r\n " + +" "); - #line 151 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 159 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(Model.ADPrimaryDomain.Name); @@ -510,7 +502,7 @@ WriteLiteral(">Primary Domain:\r\n \r\n \r\n WriteLiteral(" ["); - #line 151 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 159 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(Model.ADPrimaryDomain.NetBiosName); @@ -520,16 +512,16 @@ WriteLiteral("]\r\n
\r\n"); +WriteLiteral(">\r\n Additional Domains:\r\n \r\n \r\n"); - #line 158 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 167 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" #line default #line hidden - #line 158 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 167 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" if (Model.ADDomains.Count > 1) { var adAdditionalDomains = Model.ADDomains.Where(d => d != Model.ADPrimaryDomain).OrderBy(d => d.Name).ToList(); @@ -541,7 +533,7 @@ WriteLiteral(">Additional Domains:\r\n \r\n \r\n" WriteLiteral(" "); - #line 162 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 171 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(adDomainFirst.Name); @@ -550,7 +542,7 @@ WriteLiteral(" "); WriteLiteral(" ["); - #line 162 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 171 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(adDomainFirst.NetBiosName); @@ -559,20 +551,20 @@ WriteLiteral(" ["); WriteLiteral("]\r\n"); - #line 163 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 172 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" foreach (var adDomain in adAdditionalDomains.Skip(1)) { #line default #line hidden -WriteLiteral("
\r\n"); +WriteLiteral("
\r\n"); -WriteLiteral("
\r\n "); +WriteLiteral("
\r\n "); - #line 167 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(adDomain.Name); + #line 176 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(adDomain.Name); #line default @@ -580,16 +572,16 @@ WriteLiteral("
\r\n "); WriteLiteral(" ["); - #line 167 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(adDomain.NetBiosName); + #line 176 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(adDomain.NetBiosName); #line default #line hidden -WriteLiteral("]\r\n
\r\n"); +WriteLiteral("]
\r\n
\r\n"); - #line 169 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 178 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } } else @@ -605,7 +597,7 @@ WriteLiteral(" class=\"smallMessage\""); WriteLiteral("><None>\r\n"); - #line 174 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 183 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } @@ -615,10 +607,11 @@ WriteLiteral("
\r\n "); +WriteLiteral(">\r\n Site:\r\n \r\n \r\n "); - #line 181 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 191 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(Model.ADSite.Name); @@ -629,16 +622,17 @@ WriteLiteral("\r\n
\r\n
\r\n"); +WriteLiteral(">\r\n Servers:\r\n \r\n
\r\n " + +"
\r\n"); - #line 189 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 200 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" #line default #line hidden - #line 189 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 200 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" if (Model.ADServers.Count > 0) { @@ -652,13 +646,13 @@ WriteLiteral(" class=\"none\""); WriteLiteral(">\r\n"); - #line 192 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 203 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" #line default #line hidden - #line 192 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 203 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" foreach (var server in Model.ADServers) { var serverDescription = string.Format("{0} [{1}]", server.Name.EndsWith(server.Domain.Name, StringComparison.OrdinalIgnoreCase) ? server.Name.Substring(0, server.Name.Length - server.Domain.Name.Length - 1) : server.Name, server.Domain.NetBiosName); @@ -670,13 +664,13 @@ WriteLiteral(">\r\n"); WriteLiteral("
  • \r\n"); - #line 197 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 208 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" #line default #line hidden - #line 197 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 208 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" if (server.IsAvailable) { @@ -692,7 +686,7 @@ WriteLiteral(" title=\"Available\""); WriteLiteral(">\r\n"); - #line 200 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 211 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } else { @@ -704,24 +698,24 @@ WriteLiteral(" (server.AvailableWhen.Value.ToLongTimeString() + #line 214 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + , Tuple.Create(Tuple.Create(" ", 8658), Tuple.Create(server.AvailableWhen.Value.ToLongTimeString() #line default #line hidden -, 8201), false) +, 8659), false) ); WriteLiteral(">\r\n"); - #line 204 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 215 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } @@ -730,7 +724,7 @@ WriteLiteral(">\r\n"); WriteLiteral(" "); - #line 205 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 216 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(serverDescription); @@ -739,13 +733,13 @@ WriteLiteral(" "); WriteLiteral("\r\n"); - #line 206 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 217 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" #line default #line hidden - #line 206 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 217 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" if (server.IsSiteServer) { @@ -761,7 +755,7 @@ WriteLiteral(" title=\"Site Server\""); WriteLiteral(">\r\n"); - #line 209 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 220 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } else { @@ -778,7 +772,7 @@ WriteLiteral(" title=\"Not a Site Server\""); WriteLiteral(">\r\n"); - #line 213 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 224 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } @@ -787,7 +781,7 @@ WriteLiteral(">\r\n"); WriteLiteral(" "); - #line 214 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 225 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" if (server.IsWritable) { @@ -803,7 +797,7 @@ WriteLiteral(" title=\"Writable Domain Controller\""); WriteLiteral(">\r\n"); - #line 217 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 228 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } @@ -812,7 +806,7 @@ WriteLiteral(">\r\n"); WriteLiteral("
  • \r\n"); - #line 219 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 230 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } @@ -821,7 +815,7 @@ WriteLiteral(" \r\n"); WriteLiteral(" \r\n"); - #line 221 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 232 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } else { @@ -840,7 +834,7 @@ WriteLiteral(" class=\"fa fa-exclamation-circle fa-lg\""); WriteLiteral("> None Found\r\n
    \r\n"); - #line 227 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 238 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } @@ -851,16 +845,16 @@ WriteLiteral(" \r\n
    \r\n"); +WriteLiteral(">\r\n Forest:\r\n \r\n \r\n"); - #line 235 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 247 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" #line default #line hidden - #line 235 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 247 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" if (Model.ADForestServers == null) { @@ -872,7 +866,7 @@ WriteLiteral("
    \r\n"); WriteLiteral(" "); - #line 238 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 250 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(Html.CheckBoxFor(m => m.ADSearchAllForestServers, new { disabled = "disabled" })); @@ -881,7 +875,7 @@ WriteLiteral(" "); WriteLiteral(" "); - #line 238 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 250 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(Html.LabelFor(m => m.ADSearchAllForestServers)); @@ -906,7 +900,7 @@ WriteLiteral(">Forest servers are currently being retrieved.
    \r\n "
    \r\n"); - #line 246 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 258 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } else { @@ -917,50 +911,191 @@ WriteLiteral(">Forest servers are currently being retrieved.
    \r\n #line default #line hidden -WriteLiteral("
    \r\n"); +WriteLiteral("
    \r\n"); - #line 253 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - - - #line default - #line hidden - - #line 253 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - if (!canSearchEntireForest) - { + #line 265 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" #line default #line hidden - #line 255 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 265 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + if (!canSearchEntireForest) + { + + + #line default + #line hidden + + #line 267 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Html.CheckBoxFor(m => m.ADSearchAllForestServers, new { disabled = "disabled" })); + + + #line default + #line hidden + + #line 267 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + + + #line default + #line hidden + + #line 267 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Html.LabelFor(m => m.ADSearchAllForestServers)); + + + #line default + #line hidden + + #line 267 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + + + + #line default + #line hidden +WriteLiteral(" \r\n \r\n Disco will not search entire forests which consist of more than "); + + + #line 270 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Disco.Services.Interop.ActiveDirectory.ActiveDirectory.MaxForestServerSearch); + + + #line default + #line hidden +WriteLiteral(" servers. Only servers within this site will be searched.\r\n " + +"

    \r\n
    \r\n"); + + + #line 273 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + } + else + { + + + #line default + #line hidden + + #line 276 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Html.CheckBoxFor(m => m.ADSearchAllForestServers)); + + + #line default + #line hidden + + #line 276 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + + + #line default + #line hidden + + #line 276 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Html.LabelFor(m => m.ADSearchAllForestServers)); + + + #line default + #line hidden + + #line 276 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + + + #line default + #line hidden + + #line 276 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(AjaxHelpers.AjaxLoader()); + + + #line default + #line hidden + + #line 276 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + + + + #line default + #line hidden +WriteLiteral(" \r\n \r\n If this setting is enabled, Disco will query all servers within the forest r" + +"ather than only servers within this site.\r\n <" + +"/p>\r\n
    \r\n"); + +WriteLiteral(" \r\n"); + + + #line 287 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + } + + + #line default + #line hidden +WriteLiteral(" \r\n"); + + + #line 289 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + } + else + { + + + #line default + #line hidden +WriteLiteral("
    \r\n"); + +WriteLiteral(" "); + + + #line 293 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(Html.CheckBoxFor(m => m.ADSearchAllForestServers, new { disabled = "disabled" })); #line default #line hidden +WriteLiteral(" "); + - #line 255 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - - - #line default - #line hidden - - #line 255 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 293 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(Html.LabelFor(m => m.ADSearchAllForestServers)); #line default #line hidden - - #line 255 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - - - - #line default - #line hidden -WriteLiteral(" \r\n Disco will not search entire forests which consist of more than "); +WriteLiteral(">If this setting is enabled, Disco will query all servers within the forest r" + +"ather than only servers within this site.\r\n

    \r" + +"\n
    \r\n \r\n"); - #line 258 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(Disco.Services.Interop.ActiveDirectory.ActiveDirectory.MaxForestServerSearch); - - - #line default - #line hidden -WriteLiteral(" servers. Only servers within this site will be searched.\r\n " + -"

    \r\n \r\n"); - - - #line 261 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - } - else - { - - - #line default - #line hidden - - #line 264 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(Html.CheckBoxFor(m => m.ADSearchAllForestServers)); - - - #line default - #line hidden - - #line 264 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - - - #line default - #line hidden - - #line 264 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(Html.LabelFor(m => m.ADSearchAllForestServers)); - - - #line default - #line hidden - - #line 264 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - - - #line default - #line hidden - - #line 264 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(AjaxHelpers.AjaxLoader()); - - - #line default - #line hidden - - #line 264 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - - - - #line default - #line hidden -WriteLiteral(" \r\n If this setting is enabled, Disco will query a" + -"ll servers within the forest rather than only servers within this site.\r\n " + -" \r\n"); - -WriteLiteral(" \r\n"); - - - #line 273 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - } - - - #line default - #line hidden -WriteLiteral(" \r\n"); - - - #line 275 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - } - else - { - - - #line default - #line hidden -WriteLiteral("
    \r\n"); - -WriteLiteral(" "); - - - #line 279 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(Html.CheckBoxFor(m => m.ADSearchAllForestServers, new { disabled = "disabled" })); - - - #line default - #line hidden -WriteLiteral(" "); - - - #line 279 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(Html.LabelFor(m => m.ADSearchAllForestServers)); - - - #line default - #line hidden -WriteLiteral("\r\n \r\n If this setting is enabled, Disco will search all " + -"servers within the forest rather than only servers within this site.\r\n " + -"
    \r\n \r\n"); - - - #line 284 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 300 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } @@ -1118,36 +1128,37 @@ WriteLiteral(" class=\"none\""); WriteLiteral(">\r\n"); - #line 289 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 305 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" #line default #line hidden - #line 289 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 305 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - var domainIndex = Model.ADDomains.ToDictionary(d => d.Name, StringComparer.OrdinalIgnoreCase); - foreach (var server in Model.ADForestServers.OrderBy(s => s)) - { - var isSiteServer = Model.ADServers.Any(s => s.IsSiteServer && s.Name.Equals(server, StringComparison.OrdinalIgnoreCase)); - var serverDescription = server; - if (server.Contains('.')) - { - Disco.Services.Interop.ActiveDirectory.ADDomain serverDomain; - if (domainIndex.TryGetValue(server.Substring(server.IndexOf('.') + 1), out serverDomain)) - { - serverDescription = string.Format("{0} [{1}]", server.Substring(0, server.IndexOf('.')), serverDomain.NetBiosName); - } - } + var domainIndex = Model.ADDomains.ToDictionary(d => d.Name, StringComparer.OrdinalIgnoreCase); + foreach (var server in Model.ADForestServers.OrderBy(s => s)) + { + var isSiteServer = Model.ADServers.Any(s => s.IsSiteServer && s.Name.Equals(server, StringComparison.OrdinalIgnoreCase)); + var serverDescription = server; + if (server.Contains('.')) + { + Disco.Services.Interop.ActiveDirectory.ADDomain serverDomain; + if (domainIndex.TryGetValue(server.Substring(server.IndexOf('.') + 1), out serverDomain)) + { + serverDescription = string.Format("{0} [{1}]", server.Substring(0, server.IndexOf('.')), serverDomain.NetBiosName); + } + } #line default #line hidden -WriteLiteral("
  • "); +WriteLiteral("
  • \r\n " + +" "); - #line 303 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(serverDescription); + #line 320 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(serverDescription); #line default @@ -1155,9 +1166,9 @@ WriteLiteral("
  • "); WriteLiteral(""); - #line 303 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - if (isSiteServer) - { + #line 320 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + if (isSiteServer) + { #line default #line hidden @@ -1170,16 +1181,17 @@ WriteLiteral(" title=\"Site Server\""); WriteLiteral("> "); - #line 304 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - } + #line 321 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + } + #line default #line hidden -WriteLiteral("
  • \r\n"); +WriteLiteral(" \r\n"); - #line 305 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - } + #line 323 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + } #line default @@ -1212,7 +1224,116 @@ WriteLiteral(@" "); - #line 331 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 349 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + } + + + #line default + #line hidden +WriteLiteral("
    \r\n"); + + + #line 358 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + + + #line default + #line hidden + + #line 358 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + + object ADSearchWildcardSuffixOnlyAttributes = null; + if (!canConfigAD) + { + ADSearchWildcardSuffixOnlyAttributes = new + { + disabled = "disabled" + }; + } + + + #line default + #line hidden +WriteLiteral("\r\n"); + +WriteLiteral(" "); + + + #line 368 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Html.CheckBoxFor(m => m.ADSearchWildcardSuffixOnly, ADSearchWildcardSuffixOnlyAttributes)); + + + #line default + #line hidden +WriteLiteral(" "); + + + #line 368 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Html.LabelFor(m => m.ADSearchWildcardSuffixOnly)); + + + #line default + #line hidden +WriteLiteral(" "); + + + #line 368 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(AjaxHelpers.AjaxLoader()); + + + #line default + #line hidden +WriteLiteral("\r\n \r\n \r\n If this setting is enabled, Disco will utilize Active Directory indexes to greatly improve search performance. + If disabled, more results may be returned however performance will be reduced especially in large Active Directory domains. +

    + +"); + + + #line 375 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + + + #line default + #line hidden + + #line 375 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + if (canConfigAD) + { + + + #line default + #line hidden +WriteLiteral(" \r\n"); + + + #line 382 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } @@ -1222,16 +1343,16 @@ WriteLiteral("
    \r\n"); +WriteLiteral(">\r\n Search Scope:\r\n \r\n \r\n"); - #line 338 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 390 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" #line default #line hidden - #line 338 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 390 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" if (Model.ADSearchContainers != null && Model.ADSearchContainers.Count > 0) { @@ -1248,13 +1369,13 @@ WriteLiteral(" id=\"Config_System_AD_SearchScope_DistinguishedNames\""); WriteLiteral(">\r\n"); - #line 342 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 394 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" #line default #line hidden - #line 342 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 394 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" foreach (var adContainer in Model.ADSearchContainers) { @@ -1266,7 +1387,7 @@ WriteLiteral(" "); - #line 344 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 396 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(adContainer.Item3); @@ -1286,7 +1407,7 @@ WriteLiteral(">"); WriteLiteral("\r\n"); - #line 345 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 397 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } @@ -1295,7 +1416,7 @@ WriteLiteral("\r\n"); WriteLiteral(" \r\n"); - #line 347 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 399 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } else { @@ -1303,17 +1424,27 @@ WriteLiteral(" \r\n"); #line default #line hidden -WriteLiteral("
    No restrictions are in effect.
    \r\n"); +WriteLiteral("
    No Organisational Unit restrictions are in effect.<" + +"/div>\r\n"); WriteLiteral(" When searching, the entire domain will be queried. This is suitable for most sin" + -"gle-domain deployments.
    \r\n"); +WriteLiteral(">\r\n \r\n When searching, the entire domain will be queried. This is suitable for most" + +" single-domain deployments.\r\n

    \r\n <" + +"/div>\r\n"); - #line 352 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 408 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } @@ -1322,7 +1453,7 @@ WriteLiteral(">When searching, the entire domain will be queried. This is suitab WriteLiteral(" "); - #line 353 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 409 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" if (canConfigAD) { @@ -1357,7 +1488,7 @@ WriteLiteral(">\r\n"); WriteLiteral(" "); - #line 361 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 417 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(AjaxHelpers.AjaxLoader()); @@ -1373,13 +1504,13 @@ WriteLiteral(" class=\"organisationalUnitTree\""); WriteLiteral(">\r\n \r\n"); - #line 365 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 421 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" #line default #line hidden - #line 365 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 421 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" using (Html.BeginForm(MVC.API.System.UpdateActiveDirectorySearchScope(null, redirect: true))) { } @@ -1426,7 +1557,7 @@ WriteLiteral(" \r\n"); - #line 476 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 532 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } #line default #line hidden -WriteLiteral("
    \r\n\r\n"); +WriteLiteral("
    \r\n\r\n"); - #line 481 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 540 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" if (canConfigProxy) { using (Html.BeginForm(MVC.API.System.UpdateProxySettings())) - { + { #line default #line hidden -WriteLiteral(" \r\n

    Proxy Settings

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

    Proxy Settings

    \r\n
    \r\n " + +"\r\n Address:\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n " + +" Port:\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n " + +" Username:\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n " + +" Password:\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n " + +"  \r\n \r\n \r\n \r\n \r\n \r\n"); +WriteLiteral("\';\r\n var data = {\r\n " + +" ProxyAddress: $(\'#ProxyAddress\').val(),\r\n " + +" ProxyPort: $(\'#ProxyPort\').val(),\r\n " + +" ProxyUsername: $(\'#ProxyUsername\').val(),\r\n " + +" ProxyPassword: $(\'#ProxyPassword\').val()\r\n " + +" }\r\n var ajaxLoading = button.next(\'" + +".ajaxLoading\').first().show();\r\n\r\n $.ajax({\r\n" + +" type: \'POST\',\r\n " + +" dataType: \'json\',\r\n url: u" + +"rl,\r\n data: data,\r\n " + +" success: function (response, result) {\r\n " + +" if (result != \'success\' || response != \'OK\') {\r\n " + +" alert(\'Unable to change property \"\' + Upda" + +"tePropertyName + \'\":\\n\' + response);\r\n " + +" ajaxLoading.hide();\r\n } else {\r" + +"\n ajaxLoading.hide().next(\'.ajaxO" + +"k\').show().delay(\'fast\').fadeOut(\'slow\');\r\n " + +" }\r\n }\r\n " + +" });\r\n });\r\n }" + +");\r\n \r\n \r\n " + +" \r\n
    \r\n"); +WriteLiteral(">\r\n Address:\r\n \r\n " + +" \r\n"); -WriteLiteral(" "); +WriteLiteral(" "); - #line 492 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(Html.EditorFor(m => m.ProxyAddress)); + #line 552 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Html.EditorFor(m => m.ProxyAddress)); #line default #line hidden WriteLiteral("
    \r\n"); -WriteLiteral(" "); +WriteLiteral(" "); - #line 493 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(Html.ValidationMessageFor(m => m.ProxyAddress)); + #line 553 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Html.ValidationMessageFor(m => m.ProxyAddress)); #line default #line hidden -WriteLiteral("\r\n
    \r\n"); +WriteLiteral(">\r\n Port:\r\n \r\n " + +"\r\n"); -WriteLiteral(" "); +WriteLiteral(" "); - #line 500 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(Html.EditorFor(m => m.ProxyPort)); + #line 561 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Html.EditorFor(m => m.ProxyPort)); #line default #line hidden WriteLiteral("
    \r\n"); -WriteLiteral(" "); +WriteLiteral(" "); - #line 501 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(Html.ValidationMessageFor(m => m.ProxyPort)); + #line 562 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Html.ValidationMessageFor(m => m.ProxyPort)); #line default #line hidden -WriteLiteral("\r\n
    \r\n"); +WriteLiteral(">\r\n Username:\r\n \r\n " + +" \r\n"); -WriteLiteral(" "); +WriteLiteral(" "); - #line 508 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(Html.EditorFor(m => m.ProxyUsername)); + #line 570 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Html.EditorFor(m => m.ProxyUsername)); #line default #line hidden WriteLiteral("
    \r\n"); -WriteLiteral(" "); +WriteLiteral(" "); - #line 509 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(Html.ValidationMessageFor(m => m.ProxyUsername)); + #line 571 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Html.ValidationMessageFor(m => m.ProxyUsername)); #line default #line hidden -WriteLiteral("\r\n
    \r\n"); +WriteLiteral(">\r\n Password:\r\n \r\n " + +" \r\n"); -WriteLiteral(" "); +WriteLiteral(" "); - #line 516 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(Html.EditorFor(m => m.ProxyPassword)); + #line 579 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Html.EditorFor(m => m.ProxyPassword)); #line default #line hidden WriteLiteral("
    \r\n"); -WriteLiteral(" "); +WriteLiteral(" "); - #line 517 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(Html.ValidationMessageFor(m => m.ProxyPassword)); + #line 580 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(Html.ValidationMessageFor(m => m.ProxyPassword)); #line default #line hidden -WriteLiteral("\r\n
    \r\n \r\n  \r\n \r\n " + +" \r\n Save Proxy Settings"); - #line 524 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" - Write(AjaxHelpers.AjaxLoader()); + #line 588 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + Write(AjaxHelpers.AjaxLoader()); #line default #line hidden -WriteLiteral("\r\n \r\n
    \r\n \r\n"); - #line 560 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 624 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } } else @@ -1681,12 +1820,12 @@ WriteLiteral(">\r\n

    Proxy Settings

    \r\n \r\n WriteLiteral(" style=\"width: 135px\""); -WriteLiteral(">Address:\r\n \r\n \r\n \r\n WriteLiteral(" style=\"width: 135px\""); -WriteLiteral(">Port:\r\n \r\n \r\n \r\n WriteLiteral(" style=\"width: 135px\""); -WriteLiteral(">Username:\r\n \r\n \r\n \r\n WriteLiteral(" style=\"width: 135px\""); -WriteLiteral(">Password:\r\n \r\n \r\n \r\n
    \r\n"); +WriteLiteral(">\r\n Address:\r\n \r\n \r\n"); WriteLiteral(" "); - #line 571 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 636 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(Html.DisplayFor(m => m.ProxyAddress)); @@ -1697,12 +1836,12 @@ WriteLiteral("\r\n
    \r\n"); +WriteLiteral(">\r\n Port:\r\n \r\n \r\n"); WriteLiteral(" "); - #line 578 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 644 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(Html.DisplayFor(m => m.ProxyPort)); @@ -1713,12 +1852,12 @@ WriteLiteral("\r\n
    \r\n"); +WriteLiteral(">\r\n Username:\r\n \r\n \r\n"); WriteLiteral(" "); - #line 585 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 652 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(Html.DisplayFor(m => m.ProxyUsername)); @@ -1729,11 +1868,12 @@ WriteLiteral("\r\n
    ********\r\n " + -"
    \r\n \r\n"); +WriteLiteral(">\r\n Password:\r\n \r\n \r\n " + +" ********\r\n \r\n \r\n \r\n \r\n"); - #line 596 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 665 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" } @@ -1748,7 +1888,7 @@ WriteLiteral(">\r\n"); WriteLiteral(" "); - #line 598 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" + #line 667 "..\..\Areas\Config\Views\SystemConfig\Index.cshtml" Write(Html.ActionLinkButton("Update Device Last Network Logons", MVC.API.System.UpdateLastNetworkLogonDates())); diff --git a/Disco.Web/Areas/Config/Views/Web.config b/Disco.Web/Areas/Config/Views/Web.config index 055e8782..d8adb6f9 100644 --- a/Disco.Web/Areas/Config/Views/Web.config +++ b/Disco.Web/Areas/Config/Views/Web.config @@ -13,7 +13,6 @@ - diff --git a/Disco.Web/Areas/Public/Models/UserHeldDevices/HeldJobDeviceModel.cs b/Disco.Web/Areas/Public/Models/UserHeldDevices/HeldJobDeviceModel.cs index f3b6fa99..ab7724a5 100644 --- a/Disco.Web/Areas/Public/Models/UserHeldDevices/HeldJobDeviceModel.cs +++ b/Disco.Web/Areas/Public/Models/UserHeldDevices/HeldJobDeviceModel.cs @@ -1,10 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using Disco.BI; -using Disco.BI.Extensions; -using Disco.Data.Repository; +using Disco.Data.Repository; +using System; namespace Disco.Web.Areas.Public.Models.UserHeldDevices { diff --git a/Disco.Web/Areas/Public/Views/Web.config b/Disco.Web/Areas/Public/Views/Web.config index 13a39f1d..2dcaf25b 100644 --- a/Disco.Web/Areas/Public/Views/Web.config +++ b/Disco.Web/Areas/Public/Views/Web.config @@ -12,7 +12,6 @@ - diff --git a/Disco.Web/Areas/Services/Controllers/ClientController.cs b/Disco.Web/Areas/Services/Controllers/ClientController.cs index dc840d1e..487089f7 100644 --- a/Disco.Web/Areas/Services/Controllers/ClientController.cs +++ b/Disco.Web/Areas/Services/Controllers/ClientController.cs @@ -1,12 +1,12 @@ -using Disco.BI.Extensions; -using Disco.Data.Repository; +using Disco.Data.Repository; using Disco.Models.ClientServices; +using Disco.Services; using Disco.Services.Authorization; +using Disco.Services.Devices.Enrolment; using Newtonsoft.Json; using System; -using System.Web; +using System.IO; using System.Web.Mvc; -using System.Web.Script.Serialization; namespace Disco.Web.Areas.Services.Controllers { @@ -34,8 +34,31 @@ namespace Disco.Web.Areas.Services.Controllers { case "enrol": { - JavaScriptSerializer serializer = new JavaScriptSerializer(); - Enrol enrolRequest = serializer.Deserialize(base.Request.InputStream.StreamToString()); + // Ensure supported version + if (Request.UserAgent.StartsWith(@"Disco-Client/", StringComparison.OrdinalIgnoreCase)) + { + Version clientVersion; + if (Version.TryParse(Request.UserAgent.Substring(13), out clientVersion)) + { + if (clientVersion < new Version(2, 2)) + { + return new HttpStatusCodeResult(400, "Disco Client not compatible"); + } + } + } + + var serializer = new JsonSerializer(); + Enrol enrolRequest; + + Request.InputStream.Position = 0; + using (var streamReader = new StreamReader(Request.InputStream)) + { + using (var jsonReader = new JsonTextReader(streamReader)) + { + enrolRequest = serializer.Deserialize(jsonReader); + } + } + EnrolResponse enrolResponse = enrolRequest.BuildResponse(); return Json(enrolResponse); } @@ -58,18 +81,11 @@ namespace Disco.Web.Areas.Services.Controllers using (var database = new DiscoDataContext()) { var host = HttpContext.Request.UserHostAddress; - MacSecureEnrolResponse enrolResponse = BI.DeviceBI.DeviceEnrol.MacSecureEnrol(database, host); + MacSecureEnrolResponse enrolResponse = DeviceEnrolment.MacSecureEnrol(database, host); database.SaveChanges(); return Json(enrolResponse, JsonRequestBehavior.AllowGet); } } - case "register": - { - Register registerRequest = new Register(); - this.UpdateModel(registerRequest); - RegisterResponse registerResponse = registerRequest.BuildResponse(); - return Json(registerResponse); - } } throw new MissingMethodException(string.Format("Unknown Feature: {0}", feature)); } @@ -91,18 +107,34 @@ namespace Disco.Web.Areas.Services.Controllers } case "enrol": { - JavaScriptSerializer serializer = new JavaScriptSerializer(); - Enrol enrolRequest = serializer.Deserialize(base.Request.InputStream.StreamToString()); + // Ensure supported version + if (Request.UserAgent.StartsWith(@"Disco-Client/", StringComparison.OrdinalIgnoreCase)) + { + Version clientVersion; + if (Version.TryParse(Request.UserAgent.Substring(13), out clientVersion)) + { + if (clientVersion < new Version(2, 2)) + { + return new HttpStatusCodeResult(400, "Disco Client not compatible"); + } + } + } + + var serializer = new JsonSerializer(); + Enrol enrolRequest; + + Request.InputStream.Position = 0; + using (var streamReader = new StreamReader(Request.InputStream)) + { + using (var jsonReader = new JsonTextReader(streamReader)) + { + enrolRequest = serializer.Deserialize(jsonReader); + } + } + EnrolResponse enrolResponse = enrolRequest.BuildResponse(); return Json(enrolResponse); } - case "register": - { - Register registerRequest = new Register(); - this.UpdateModel(registerRequest); - RegisterResponse registerResponse = registerRequest.BuildResponse(); - return Json(registerResponse); - } } throw new MissingMethodException(string.Format("Unknown Feature: {0}", feature)); } @@ -133,9 +165,9 @@ namespace Disco.Web.Areas.Services.Controllers } if (string.IsNullOrEmpty(SessionId)) - Disco.BI.DeviceBI.EnrolmentLog.LogClientError(clientIP, DeviceIdentifier, clientVersion, errorMessage, JsonException); + EnrolmentLog.LogClientError(clientIP, DeviceIdentifier, clientVersion, errorMessage, JsonException); else - Disco.BI.DeviceBI.EnrolmentLog.LogSessionClientError(SessionId, clientIP, DeviceIdentifier, clientVersion, errorMessage, JsonException); + EnrolmentLog.LogSessionClientError(SessionId, clientIP, DeviceIdentifier, clientVersion, errorMessage, JsonException); return Content("Error Message Logged"); } diff --git a/Disco.Web/Controllers/DeviceController.cs b/Disco.Web/Controllers/DeviceController.cs index 93da3705..c2968520 100644 --- a/Disco.Web/Controllers/DeviceController.cs +++ b/Disco.Web/Controllers/DeviceController.cs @@ -1,5 +1,4 @@ -using Disco.BI.Extensions; -using Disco.Models.Repository; +using Disco.Models.Repository; using Disco.Models.Services.Devices.Exporting; using Disco.Models.Services.Jobs.JobLists; using Disco.Models.UI.Device; @@ -247,9 +246,14 @@ namespace Disco.Web.Controllers m.DeviceProfileDefaultOrganisationAddress = m.Device.DeviceProfile.DefaultOrganisationAddressDetails(Database); - PluginFeatureManifest deviceProfileCertificateProvider; - if (Disco.Services.Plugins.Plugins.TryGetPluginFeature(m.Device.DeviceProfile.CertificateProviderId, out deviceProfileCertificateProvider)) - m.DeviceProfileCertificateProvider = deviceProfileCertificateProvider; + if (m.Device.DeviceProfile.CertificateProviders != null) + { + m.DeviceProfileCertificateProviders = m.Device.DeviceProfile.GetCertificateProviders().ToList(); + } + if (m.Device.DeviceProfile.WirelessProfileProviders != null) + { + m.DeviceProfileWirelessProfileProviders = m.Device.DeviceProfile.GetWirelessProfileProviders().ToList(); + } // UI Extensions UIExtensions.ExecuteExtensions(this.ControllerContext, m); diff --git a/Disco.Web/Controllers/JobController.cs b/Disco.Web/Controllers/JobController.cs index 0d2bbb0c..4e5436a0 100644 --- a/Disco.Web/Controllers/JobController.cs +++ b/Disco.Web/Controllers/JobController.cs @@ -1,12 +1,13 @@ -using Disco.BI.Extensions; -using Disco.Models.BI.Job; -using Disco.Models.Repository; +using Disco.Models.Repository; +using Disco.Models.Services.Job; using Disco.Models.Services.Jobs.JobLists; using Disco.Models.UI.Job; using Disco.Services; using Disco.Services.Authorization; +using Disco.Services.Jobs; using Disco.Services.Jobs.JobLists; using Disco.Services.Jobs.JobQueues; +using Disco.Services.Jobs.Statistics; using Disco.Services.Plugins.Features.RepairProvider; using Disco.Services.Plugins.Features.UIExtension; using Disco.Services.Plugins.Features.WarrantyProvider; @@ -41,7 +42,7 @@ namespace Disco.Web.Controllers m.StaleJobs.ShowDates = false; } if (Authorization.Has(Claims.Job.ShowDailyChart)) - m.DailyOpenedClosedStatistics = Disco.BI.JobBI.Statistics.DailyOpenedClosed.Data(Database, true); + m.DailyOpenedClosedStatistics = DailyOpenedClosed.Data(Database, true); // UI Extensions UIExtensions.ExecuteExtensions(this.ControllerContext, m); @@ -404,7 +405,7 @@ namespace Disco.Web.Controllers && m.QuickLog.HasValue && m.QuickLog.Value && m.QuickLogTaskTimeMinutes.HasValue && m.QuickLogTaskTimeMinutes.Value > 0); - var j = BI.JobBI.Utilities.Create(Database, m.Device, m.User, m.GetJobType, m.GetJobSubTypes, currentUser, addAutoQueues); + var j = Jobs.Create(Database, m.Device, m.User, m.GetJobType, m.GetJobSubTypes, currentUser, addAutoQueues); if (m.DeviceHeld.Value) { diff --git a/Disco.Web/Controllers/UpdateController.cs b/Disco.Web/Controllers/UpdateController.cs index 51d36e6b..91202b70 100644 --- a/Disco.Web/Controllers/UpdateController.cs +++ b/Disco.Web/Controllers/UpdateController.cs @@ -1,16 +1,5 @@ -using System; -using System.Data.SqlClient; -using System.Threading; +using Disco.Services.Plugins; using System.Web.Mvc; -using Disco.Web.Models.InitialConfig; -using Disco.Data.Repository; -using System.Linq; -using System.IO; -using System.Text.RegularExpressions; -using System.IO.Compression; -using System.Management; -using System.Web; -using Disco.Services.Plugins; namespace Disco.Web.Controllers { diff --git a/Disco.Web/Controllers/UserController.cs b/Disco.Web/Controllers/UserController.cs index 154bc6a4..58336013 100644 --- a/Disco.Web/Controllers/UserController.cs +++ b/Disco.Web/Controllers/UserController.cs @@ -1,5 +1,4 @@ -using Disco.BI.Extensions; -using Disco.Models.Services.Jobs.JobLists; +using Disco.Models.Services.Jobs.JobLists; using Disco.Models.UI.User; using Disco.Services; using Disco.Services.Authorization; diff --git a/Disco.Web/Disco.Web.csproj b/Disco.Web/Disco.Web.csproj index 3f793691..98421320 100644 --- a/Disco.Web/Disco.Web.csproj +++ b/Disco.Web/Disco.Web.csproj @@ -22,6 +22,8 @@ ..\ true + 2.2.16272.1003 +
    true diff --git a/Disco.Web/Extensions/T4MVC/API.DeviceProfileController.generated.cs b/Disco.Web/Extensions/T4MVC/API.DeviceProfileController.generated.cs index 8fffc5eb..668dddf4 100644 --- a/Disco.Web/Extensions/T4MVC/API.DeviceProfileController.generated.cs +++ b/Disco.Web/Extensions/T4MVC/API.DeviceProfileController.generated.cs @@ -89,9 +89,21 @@ namespace Disco.Web.Areas.API.Controllers } [NonAction] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] - public virtual System.Web.Mvc.ActionResult UpdateCertificateProviderId() + public virtual System.Web.Mvc.ActionResult UpdateCertificateProviders() { - return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateCertificateProviderId); + return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateCertificateProviders); + } + [NonAction] + [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] + public virtual System.Web.Mvc.ActionResult UpdateCertificateAuthorityProviders() + { + return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateCertificateAuthorityProviders); + } + [NonAction] + [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] + public virtual System.Web.Mvc.ActionResult UpdateWirelessProfileProviders() + { + return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateWirelessProfileProviders); } [NonAction] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] @@ -192,7 +204,9 @@ namespace Disco.Web.Areas.API.Controllers public readonly string UpdateName = "UpdateName"; public readonly string UpdateShortName = "UpdateShortName"; public readonly string UpdateDistributionType = "UpdateDistributionType"; - public readonly string UpdateCertificateProviderId = "UpdateCertificateProviderId"; + public readonly string UpdateCertificateProviders = "UpdateCertificateProviders"; + public readonly string UpdateCertificateAuthorityProviders = "UpdateCertificateAuthorityProviders"; + public readonly string UpdateWirelessProfileProviders = "UpdateWirelessProfileProviders"; public readonly string UpdateOrganisationalUnit = "UpdateOrganisationalUnit"; public readonly string UpdateDefaultOrganisationAddress = "UpdateDefaultOrganisationAddress"; public readonly string UpdateComputerNameTemplate = "UpdateComputerNameTemplate"; @@ -216,7 +230,9 @@ namespace Disco.Web.Areas.API.Controllers public const string UpdateName = "UpdateName"; public const string UpdateShortName = "UpdateShortName"; public const string UpdateDistributionType = "UpdateDistributionType"; - public const string UpdateCertificateProviderId = "UpdateCertificateProviderId"; + public const string UpdateCertificateProviders = "UpdateCertificateProviders"; + public const string UpdateCertificateAuthorityProviders = "UpdateCertificateAuthorityProviders"; + public const string UpdateWirelessProfileProviders = "UpdateWirelessProfileProviders"; public const string UpdateOrganisationalUnit = "UpdateOrganisationalUnit"; public const string UpdateDefaultOrganisationAddress = "UpdateDefaultOrganisationAddress"; public const string UpdateComputerNameTemplate = "UpdateComputerNameTemplate"; @@ -284,14 +300,34 @@ namespace Disco.Web.Areas.API.Controllers public readonly string DistributionType = "DistributionType"; public readonly string redirect = "redirect"; } - static readonly ActionParamsClass_UpdateCertificateProviderId s_params_UpdateCertificateProviderId = new ActionParamsClass_UpdateCertificateProviderId(); + static readonly ActionParamsClass_UpdateCertificateProviders s_params_UpdateCertificateProviders = new ActionParamsClass_UpdateCertificateProviders(); [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] - public ActionParamsClass_UpdateCertificateProviderId UpdateCertificateProviderIdParams { get { return s_params_UpdateCertificateProviderId; } } + public ActionParamsClass_UpdateCertificateProviders UpdateCertificateProvidersParams { get { return s_params_UpdateCertificateProviders; } } [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] - public class ActionParamsClass_UpdateCertificateProviderId + public class ActionParamsClass_UpdateCertificateProviders { public readonly string id = "id"; - public readonly string CertificateProviderId = "CertificateProviderId"; + public readonly string CertificateProviders = "CertificateProviders"; + public readonly string redirect = "redirect"; + } + static readonly ActionParamsClass_UpdateCertificateAuthorityProviders s_params_UpdateCertificateAuthorityProviders = new ActionParamsClass_UpdateCertificateAuthorityProviders(); + [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] + public ActionParamsClass_UpdateCertificateAuthorityProviders UpdateCertificateAuthorityProvidersParams { get { return s_params_UpdateCertificateAuthorityProviders; } } + [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] + public class ActionParamsClass_UpdateCertificateAuthorityProviders + { + public readonly string id = "id"; + public readonly string CertificateAuthorityProviders = "CertificateAuthorityProviders"; + public readonly string redirect = "redirect"; + } + static readonly ActionParamsClass_UpdateWirelessProfileProviders s_params_UpdateWirelessProfileProviders = new ActionParamsClass_UpdateWirelessProfileProviders(); + [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] + public ActionParamsClass_UpdateWirelessProfileProviders UpdateWirelessProfileProvidersParams { get { return s_params_UpdateWirelessProfileProviders; } } + [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] + public class ActionParamsClass_UpdateWirelessProfileProviders + { + public readonly string id = "id"; + public readonly string WirelessProfileProviders = "WirelessProfileProviders"; public readonly string redirect = "redirect"; } static readonly ActionParamsClass_UpdateOrganisationalUnit s_params_UpdateOrganisationalUnit = new ActionParamsClass_UpdateOrganisationalUnit(); @@ -512,16 +548,44 @@ namespace Disco.Web.Areas.API.Controllers } [NonAction] - partial void UpdateCertificateProviderIdOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id, string CertificateProviderId, bool? redirect); + partial void UpdateCertificateProvidersOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id, string CertificateProviders, bool? redirect); [NonAction] - public override System.Web.Mvc.ActionResult UpdateCertificateProviderId(int id, string CertificateProviderId, bool? redirect) + public override System.Web.Mvc.ActionResult UpdateCertificateProviders(int id, string CertificateProviders, bool? redirect) { - var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateCertificateProviderId); + var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateCertificateProviders); ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "id", id); - ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "CertificateProviderId", CertificateProviderId); + ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "CertificateProviders", CertificateProviders); ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "redirect", redirect); - UpdateCertificateProviderIdOverride(callInfo, id, CertificateProviderId, redirect); + UpdateCertificateProvidersOverride(callInfo, id, CertificateProviders, redirect); + return callInfo; + } + + [NonAction] + partial void UpdateCertificateAuthorityProvidersOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id, string CertificateAuthorityProviders, bool? redirect); + + [NonAction] + public override System.Web.Mvc.ActionResult UpdateCertificateAuthorityProviders(int id, string CertificateAuthorityProviders, bool? redirect) + { + var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateCertificateAuthorityProviders); + ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "id", id); + ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "CertificateAuthorityProviders", CertificateAuthorityProviders); + ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "redirect", redirect); + UpdateCertificateAuthorityProvidersOverride(callInfo, id, CertificateAuthorityProviders, redirect); + return callInfo; + } + + [NonAction] + partial void UpdateWirelessProfileProvidersOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id, string WirelessProfileProviders, bool? redirect); + + [NonAction] + public override System.Web.Mvc.ActionResult UpdateWirelessProfileProviders(int id, string WirelessProfileProviders, bool? redirect) + { + var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateWirelessProfileProviders); + ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "id", id); + ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "WirelessProfileProviders", WirelessProfileProviders); + ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "redirect", redirect); + UpdateWirelessProfileProvidersOverride(callInfo, id, WirelessProfileProviders, redirect); return callInfo; } diff --git a/Disco.Web/Extensions/T4MVC/API.JobPreferencesController.generated.cs b/Disco.Web/Extensions/T4MVC/API.JobPreferencesController.generated.cs index a8e3de4f..be534288 100644 --- a/Disco.Web/Extensions/T4MVC/API.JobPreferencesController.generated.cs +++ b/Disco.Web/Extensions/T4MVC/API.JobPreferencesController.generated.cs @@ -244,10 +244,10 @@ namespace Disco.Web.Areas.API.Controllers } [NonAction] - partial void UpdateLocationModeOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, Disco.Models.BI.Job.LocationModes LocationMode, bool redirect); + partial void UpdateLocationModeOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, Disco.Models.Services.Job.LocationModes LocationMode, bool redirect); [NonAction] - public override System.Web.Mvc.ActionResult UpdateLocationMode(Disco.Models.BI.Job.LocationModes LocationMode, bool redirect) + public override System.Web.Mvc.ActionResult UpdateLocationMode(Disco.Models.Services.Job.LocationModes LocationMode, bool redirect) { var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateLocationMode); ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "LocationMode", LocationMode); diff --git a/Disco.Web/Extensions/T4MVC/API.SystemController.generated.cs b/Disco.Web/Extensions/T4MVC/API.SystemController.generated.cs index fe0fbacb..f0430318 100644 --- a/Disco.Web/Extensions/T4MVC/API.SystemController.generated.cs +++ b/Disco.Web/Extensions/T4MVC/API.SystemController.generated.cs @@ -95,6 +95,12 @@ namespace Disco.Web.Areas.API.Controllers } [NonAction] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] + public virtual System.Web.Mvc.ActionResult UpdateActiveDirectorySearchWildcardSuffixOnly() + { + return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateActiveDirectorySearchWildcardSuffixOnly); + } + [NonAction] + [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] public virtual System.Web.Mvc.ActionResult SearchSubjects() { return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.SearchSubjects); @@ -149,6 +155,7 @@ namespace Disco.Web.Areas.API.Controllers public readonly string UpdateMultiSiteMode = "UpdateMultiSiteMode"; public readonly string UpdateActiveDirectorySearchScope = "UpdateActiveDirectorySearchScope"; public readonly string UpdateActiveDirectorySearchAllForestServers = "UpdateActiveDirectorySearchAllForestServers"; + public readonly string UpdateActiveDirectorySearchWildcardSuffixOnly = "UpdateActiveDirectorySearchWildcardSuffixOnly"; public readonly string DomainOrganisationalUnits = "DomainOrganisationalUnits"; public readonly string SearchSubjects = "SearchSubjects"; public readonly string SearchGroupSubjects = "SearchGroupSubjects"; @@ -170,6 +177,7 @@ namespace Disco.Web.Areas.API.Controllers public const string UpdateMultiSiteMode = "UpdateMultiSiteMode"; public const string UpdateActiveDirectorySearchScope = "UpdateActiveDirectorySearchScope"; public const string UpdateActiveDirectorySearchAllForestServers = "UpdateActiveDirectorySearchAllForestServers"; + public const string UpdateActiveDirectorySearchWildcardSuffixOnly = "UpdateActiveDirectorySearchWildcardSuffixOnly"; public const string DomainOrganisationalUnits = "DomainOrganisationalUnits"; public const string SearchSubjects = "SearchSubjects"; public const string SearchGroupSubjects = "SearchGroupSubjects"; @@ -246,6 +254,15 @@ namespace Disco.Web.Areas.API.Controllers public readonly string SearchAllForestServers = "SearchAllForestServers"; public readonly string redirect = "redirect"; } + static readonly ActionParamsClass_UpdateActiveDirectorySearchWildcardSuffixOnly s_params_UpdateActiveDirectorySearchWildcardSuffixOnly = new ActionParamsClass_UpdateActiveDirectorySearchWildcardSuffixOnly(); + [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] + public ActionParamsClass_UpdateActiveDirectorySearchWildcardSuffixOnly UpdateActiveDirectorySearchWildcardSuffixOnlyParams { get { return s_params_UpdateActiveDirectorySearchWildcardSuffixOnly; } } + [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] + public class ActionParamsClass_UpdateActiveDirectorySearchWildcardSuffixOnly + { + public readonly string SearchWildcardSuffixOnly = "SearchWildcardSuffixOnly"; + public readonly string redirect = "redirect"; + } static readonly ActionParamsClass_SearchSubjects s_params_SearchSubjects = new ActionParamsClass_SearchSubjects(); [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] public ActionParamsClass_SearchSubjects SearchSubjectsParams { get { return s_params_SearchSubjects; } } @@ -449,6 +466,19 @@ namespace Disco.Web.Areas.API.Controllers return callInfo; } + [NonAction] + partial void UpdateActiveDirectorySearchWildcardSuffixOnlyOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, bool SearchWildcardSuffixOnly, bool redirect); + + [NonAction] + public override System.Web.Mvc.ActionResult UpdateActiveDirectorySearchWildcardSuffixOnly(bool SearchWildcardSuffixOnly, bool redirect) + { + var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateActiveDirectorySearchWildcardSuffixOnly); + ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "SearchWildcardSuffixOnly", SearchWildcardSuffixOnly); + ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "redirect", redirect); + UpdateActiveDirectorySearchWildcardSuffixOnlyOverride(callInfo, SearchWildcardSuffixOnly, redirect); + return callInfo; + } + [NonAction] partial void DomainOrganisationalUnitsOverride(T4MVC_System_Web_Mvc_ActionResult callInfo); diff --git a/Disco.Web/Models/Device/ShowModel.cs b/Disco.Web/Models/Device/ShowModel.cs index ff2d1ce8..8213243e 100644 --- a/Disco.Web/Models/Device/ShowModel.cs +++ b/Disco.Web/Models/Device/ShowModel.cs @@ -1,14 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Mvc; -using Disco.BI; -using Disco.BI.Extensions; +using Disco.Models.Services.Jobs.JobLists; using Disco.Models.UI.Device; -using Disco.Web.Extensions; using Disco.Services.Plugins; -using Disco.Models.Services.Jobs.JobLists; +using Disco.Web.Extensions; +using System.Collections.Generic; +using System.Web.Mvc; namespace Disco.Web.Models.Device { @@ -18,7 +13,8 @@ namespace Disco.Web.Models.Device public List DeviceProfiles { get; set; } public Disco.Models.BI.Config.OrganisationAddress DeviceProfileDefaultOrganisationAddress { get; set; } - public PluginFeatureManifest DeviceProfileCertificateProvider { get; set; } + public List DeviceProfileCertificateProviders { get; set; } + public List DeviceProfileWirelessProfileProviders { get; set; } public List DeviceBatches { get; set; } public JobTableModel Jobs { get; set; } diff --git a/Disco.Web/Models/Job/CreateModel.cs b/Disco.Web/Models/Job/CreateModel.cs index b0134ac9..a05ff091 100644 --- a/Disco.Web/Models/Job/CreateModel.cs +++ b/Disco.Web/Models/Job/CreateModel.cs @@ -1,12 +1,11 @@ -using Disco.BI.Extensions; -using Disco.Data.Repository; +using Disco.Data.Repository; using Disco.Models.UI.Job; +using Disco.Services; using Disco.Services.Authorization; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -using System.Web; namespace Disco.Web.Models.Job { diff --git a/Disco.Web/Models/Job/IndexModel.cs b/Disco.Web/Models/Job/IndexModel.cs index 97af952d..1b032b55 100644 --- a/Disco.Web/Models/Job/IndexModel.cs +++ b/Disco.Web/Models/Job/IndexModel.cs @@ -1,9 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using Disco.Models.UI.Job; +using Disco.Models.Services.Job.Statistics; using Disco.Models.Services.Jobs.JobLists; +using Disco.Models.UI.Job; +using System.Collections.Generic; namespace Disco.Web.Models.Job { @@ -12,6 +10,6 @@ namespace Disco.Web.Models.Job public JobTableModel MyJobs { get; set; } public JobTableModel StaleJobs { get; set; } - public List DailyOpenedClosedStatistics { get; set; } + public List DailyOpenedClosedStatistics { get; set; } } } \ No newline at end of file diff --git a/Disco.Web/Models/Job/ShowModel.cs b/Disco.Web/Models/Job/ShowModel.cs index e349327d..8bec7a38 100644 --- a/Disco.Web/Models/Job/ShowModel.cs +++ b/Disco.Web/Models/Job/ShowModel.cs @@ -1,4 +1,4 @@ -using Disco.Models.BI.Job; +using Disco.Models.Services.Job; using Disco.Models.Services.Jobs.JobLists; using Disco.Models.UI.Job; using Disco.Web.Extensions; diff --git a/Disco.Web/Properties/AssemblyInfo.cs b/Disco.Web/Properties/AssemblyInfo.cs index 5eadfd6f..f5d6230e 100644 --- a/Disco.Web/Properties/AssemblyInfo.cs +++ b/Disco.Web/Properties/AssemblyInfo.cs @@ -30,5 +30,5 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("2.1.0.0")] -[assembly: AssemblyFileVersion("2.1.0.0")] \ No newline at end of file +[assembly: AssemblyVersion("2.2.16272.1003")] +[assembly: AssemblyFileVersion("2.2.16272.1003")] \ No newline at end of file diff --git a/Disco.Web/Views/Device/DeviceParts/_Subject.cshtml b/Disco.Web/Views/Device/DeviceParts/_Subject.cshtml index 837681dd..fdb124e4 100644 --- a/Disco.Web/Views/Device/DeviceParts/_Subject.cshtml +++ b/Disco.Web/Views/Device/DeviceParts/_Subject.cshtml @@ -12,28 +12,32 @@
    - - - - @@ -65,7 +69,7 @@
    Name: + + Name: @if (string.IsNullOrWhiteSpace(Model.Device.ComputerName)) + + @if (string.IsNullOrWhiteSpace(Model.Device.ComputerName)) { - <Unknown/None> + <Unknown/None> } else { -

    @Model.Device.ComputerName

    +

    @Model.Device.ComputerName

    }
    Domain: + + Domain: @if (string.IsNullOrWhiteSpace(Model.Device.ComputerDomainName)) + + @if (string.IsNullOrWhiteSpace(Model.Device.ComputerDomainName)) { - <None> + <None> } else { -

    @Model.Device.ComputerDomainName

    +

    @Model.Device.ComputerDomainName

    }
    @if (Authorization.HasAny(Claims.Device.Properties.AssetNumber, Claims.Device.Properties.Location)) - { + { - } + } @if (Model.Device.CanUpdateTrustEnrol()) { @Html.ActionLinkSmallButton("Trust Enrol", MVC.API.Device.UpdateAllowUnauthenticatedEnrol(Model.Device.SerialNumber, true.ToString(), true), "Device_Show_Device_Actions_TrustEnrol_Button") @@ -742,7 +790,7 @@ } @if (Model.Device.CanDecommission()) - { + { @Html.ActionLinkSmallButton("Decommission", MVC.API.Device.Decommission(), "Device_Show_Device_Actions_Decommission_Button")
    @@ -754,7 +802,7 @@ {
  • + name="Device_Show_Device_Actions_Decommission_Reason" value="@((int)decommissionReason)" @((decommissionReason == DecommissionReasons.EndOfLife) ? "checked=\"checked\"" : string.Empty) />
  • } @@ -803,7 +851,7 @@ } @if (Model.Device.CanRecommission()) - { + { @Html.ActionLinkSmallButton("Recommission", MVC.API.Device.Recommission(Model.Device.SerialNumber, true), "Device_Show_Device_Actions_Recommission_Button")

    @@ -841,7 +889,7 @@ } @if (Model.Device.CanDelete()) - { + { @Html.ActionLinkSmallButton("Delete Device", MVC.API.Device.Delete(Model.Device.SerialNumber, true), "Device_Show_Device_Actions_Delete_Button")

    diff --git a/Disco.Web/Views/Device/DeviceParts/_Subject.generated.cs b/Disco.Web/Views/Device/DeviceParts/_Subject.generated.cs index c9577751..ee1f20b7 100644 --- a/Disco.Web/Views/Device/DeviceParts/_Subject.generated.cs +++ b/Disco.Web/Views/Device/DeviceParts/_Subject.generated.cs @@ -2,7 +2,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -27,7 +27,6 @@ namespace Disco.Web.Views.Device.DeviceParts using System.Web.UI; using System.Web.WebPages; using Disco; - using Disco.BI.Extensions; using Disco.Models.Repository; using Disco.Services; using Disco.Services.Authorization; @@ -43,9 +42,9 @@ namespace Disco.Web.Views.Device.DeviceParts [System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "2.0.0.0")] [System.Web.WebPages.PageVirtualPathAttribute("~/Views/Device/DeviceParts/_Subject.cshtml")] - public partial class Subject : Disco.Services.Web.WebViewPage + public partial class _Subject : Disco.Services.Web.WebViewPage { - public Subject() + public _Subject() { } public override void Execute() @@ -76,22 +75,29 @@ WriteLiteral(">\r\n \r\n \r\n \r\n \r\n \r\n " + +" Name:\r\n \r\n "); +">\r\n"); - #line 17 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 19 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + + + #line default + #line hidden + + #line 19 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (string.IsNullOrWhiteSpace(Model.Device.ComputerName)) { #line default #line hidden -WriteLiteral(" <Unknown/None>\r\n"); - #line 20 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 22 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } else { @@ -110,7 +116,7 @@ WriteLiteral("><Unknown/None>\r\n"); #line default #line hidden -WriteLiteral(" "); - #line 23 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - Write(Model.Device.ComputerName); + #line 25 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + Write(Model.Device.ComputerName); #line default @@ -128,29 +134,36 @@ WriteLiteral(">"); WriteLiteral("\r\n"); - #line 24 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 26 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } #line default #line hidden WriteLiteral(" \r\n \r\n " + -" \r\n \r\n \r\n " + +" Domain:\r\n \r\n <" + -"td>"); +"td>\r\n"); - #line 30 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 34 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + + + #line default + #line hidden + + #line 34 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (string.IsNullOrWhiteSpace(Model.Device.ComputerDomainName)) { #line default #line hidden -WriteLiteral(" <None>\r\n"); - #line 33 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 37 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } else { @@ -169,7 +182,7 @@ WriteLiteral("><None>\r\n"); #line default #line hidden -WriteLiteral(" "); - #line 36 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - Write(Model.Device.ComputerDomainName); + #line 40 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + Write(Model.Device.ComputerDomainName); #line default @@ -187,7 +200,7 @@ WriteLiteral(">"); WriteLiteral("\r\n"); - #line 37 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 41 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } @@ -198,13 +211,13 @@ WriteLiteral(" \r\n " \r\n"); - #line 43 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 47 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 43 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 47 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (Authorization.Has(Claims.Device.Properties.AssetNumber)) { @@ -212,40 +225,40 @@ WriteLiteral(" \r\n #line default #line hidden - #line 45 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 49 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(Html.TextBoxFor(m => m.Device.AssetNumber, new { @class = "small discreet" })); #line default #line hidden - #line 45 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 49 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 45 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 49 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(AjaxHelpers.AjaxSave()); #line default #line hidden - #line 45 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 49 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 45 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 49 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(AjaxHelpers.AjaxLoader()); #line default #line hidden - #line 45 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 49 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } else @@ -261,7 +274,7 @@ WriteLiteral(" class=\"small discreet\""); WriteLiteral(">"); - #line 49 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 53 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(Model.Device.AssetNumber ?? "Unknown"); @@ -270,7 +283,7 @@ WriteLiteral(">"); WriteLiteral("\r\n"); - #line 50 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 54 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } @@ -281,13 +294,13 @@ WriteLiteral(" \r\n " \r\n"); - #line 56 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 60 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 56 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 60 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (Authorization.Has(Claims.Device.Properties.Location)) { @@ -295,40 +308,40 @@ WriteLiteral(" \r\n #line default #line hidden - #line 58 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 62 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(Html.TextBoxFor(m => m.Device.Location, new { @class = "small discreet" })); #line default #line hidden - #line 58 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 62 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 58 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 62 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(AjaxHelpers.AjaxSave()); #line default #line hidden - #line 58 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 62 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 58 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 62 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(AjaxHelpers.AjaxLoader()); #line default #line hidden - #line 58 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 62 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } else @@ -344,7 +357,7 @@ WriteLiteral(" class=\"small discreet\""); WriteLiteral(">"); - #line 62 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 66 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(Model.Device.Location ?? "Unknown"); @@ -353,7 +366,7 @@ WriteLiteral(">"); WriteLiteral("\r\n"); - #line 63 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 67 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } @@ -363,15 +376,15 @@ WriteLiteral(" \r\n " \r\n"); - #line 67 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 71 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 67 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 71 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (Authorization.HasAny(Claims.Device.Properties.AssetNumber, Claims.Device.Properties.Location)) - { + { #line default @@ -379,13 +392,13 @@ WriteLiteral(" \r\n WriteLiteral(" \r\n"); - #line 77 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 81 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } @@ -456,15 +469,16 @@ WriteLiteral(">\r\n \r\n \r\n Created:\r\n " + -" \r\n \r\n \r\n \r\n " + +" Created:\r\n \r\n " + +" "); - #line 84 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 89 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(CommonHelpers.FriendlyDate(Model.Device.CreatedDate)); @@ -473,29 +487,29 @@ WriteLiteral(">"); WriteLiteral("\r\n \r\n"); - #line 86 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 91 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 86 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 91 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (Model.Device.DecommissionedDate.HasValue) { #line default #line hidden -WriteLiteral(" \r\n Decommissio" + -"ned:\r\n \r\n \r\n \r\n " + +" Decommissioned:\r\n \r\n "); - #line 91 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 97 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(CommonHelpers.FriendlyDate(Model.Device.DecommissionedDate)); @@ -504,23 +518,24 @@ WriteLiteral(">"); WriteLiteral("\r\n \r\n"); - #line 93 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 99 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } #line default #line hidden -WriteLiteral("\r\n \r\n Enrolled:\r\n " + -" \r\n \r\n"); +WriteLiteral("\r\n \r\n \r\n " + +" Enrolled:\r\n \r\n " + +" \r\n"); - #line 99 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 106 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 99 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 106 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (Model.Device.EnrolledDate.HasValue) { @@ -538,7 +553,7 @@ WriteLiteral(" id=\"Device_Show_Details_Asset_Enrolled_First\""); WriteLiteral(">"); - #line 101 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 108 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(CommonHelpers.FriendlyDate(Model.Device.EnrolledDate)); @@ -547,14 +562,14 @@ WriteLiteral(">"); WriteLiteral("\r\n"); - #line 102 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 109 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (Model.Device.LastEnrolDate.HasValue && Model.Device.EnrolledDate.Value != Model.Device.LastEnrolDate.Value) { #line default #line hidden -WriteLiteral("
    "); +WriteLiteral("
    "); WriteLiteral("Last: "); @@ -565,8 +580,8 @@ WriteLiteral(" id=\"Device_Show_Details_Asset_Enrolled_Last\""); WriteLiteral(">"); - #line 104 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - Write(CommonHelpers.FriendlyDate(Model.Device.LastEnrolDate)); + #line 111 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + Write(CommonHelpers.FriendlyDate(Model.Device.LastEnrolDate)); #line default @@ -574,7 +589,7 @@ WriteLiteral(">"); WriteLiteral("\r\n"); - #line 105 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 112 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } } else @@ -592,7 +607,7 @@ WriteLiteral(" class=\"smallMessage\""); WriteLiteral(">Never\r\n"); - #line 110 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 117 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } @@ -601,7 +616,7 @@ WriteLiteral(">Never\r\n"); WriteLiteral(" "); - #line 111 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 118 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (Model.Device.AllowUnauthenticatedEnrol) { @@ -617,7 +632,7 @@ WriteLiteral(" title=\"Trusted Unauthenticated Enrolment is Allowed\""); WriteLiteral(">\r\n"); - #line 114 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 121 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } @@ -634,32 +649,39 @@ WriteLiteral(">\r\n \r\n \r\n \r\n \r\n \r\n " + +" Last Seen:\r\n \r\n " + -" "); +" \r\n"); - #line 125 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 134 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + + + #line default + #line hidden + + #line 134 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - string lastSeenClass = null; - if (Model.Device.LastNetworkLogonDate.HasValue) - { - if (Model.Device.LastNetworkLogonDate.Value < DateTime.Now.AddDays(-30)) + string lastSeenClass = null; + if (Model.Device.LastNetworkLogonDate.HasValue) { - lastSeenClass = "error"; - } - else - { - if (Model.Device.LastNetworkLogonDate.Value < DateTime.Now.AddDays(-7)) + if (Model.Device.LastNetworkLogonDate.Value < DateTime.Now.AddDays(-30)) { - lastSeenClass = "alert"; + lastSeenClass = "error"; + } + else + { + if (Model.Device.LastNetworkLogonDate.Value < DateTime.Now.AddDays(-7)) + { + lastSeenClass = "alert"; + } } } - } - + #line default #line hidden @@ -667,35 +689,35 @@ WriteLiteral("\r\n (lastSeenClass + #line 151 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + , Tuple.Create(Tuple.Create("", 8462), Tuple.Create(lastSeenClass #line default #line hidden -, 8076), false) +, 8462), false) ); WriteLiteral(">"); - #line 142 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 151 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(CommonHelpers.FriendlyDate(Model.Device.LastNetworkLogonDate)); #line default #line hidden -WriteLiteral("\r\n"); +WriteLiteral("\r\n \r\n"); - #line 143 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 153 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 143 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 153 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (!string.IsNullOrEmpty(Model.Device.ComputerName)) { @@ -715,7 +737,7 @@ WriteLiteral(@"> $.getJSON('"); - #line 151 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 161 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(Url.Action(MVC.API.Device.LastNetworkLogonDate(Model.Device.SerialNumber))); @@ -747,7 +769,7 @@ WriteLiteral("\', function (response, result) {\r\n " \r\n"); - #line 176 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 186 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } @@ -761,13 +783,13 @@ WriteLiteral(" class=\"status\""); WriteLiteral(">\r\n"); - #line 181 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 191 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 181 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 191 "..\..\Views\Device\DeviceParts\_Subject.cshtml" var assignedUser = Model.Device.AssignedUser; @@ -778,17 +800,18 @@ WriteLiteral("\r\n \r\n \r\n Assignment:\r\n " + -" \r\n \r\n"); +WriteLiteral(">\r\n \r\n \r\n " + +" Assignment:\r\n \r\n " + +" \r\n"); - #line 189 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 200 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 189 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 200 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (assignedUser != null) { @@ -808,13 +831,13 @@ WriteLiteral(" title=\"Display Name\""); WriteLiteral(">\r\n"); - #line 193 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 204 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 193 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 204 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (Authorization.Has(Claims.User.Show)) { @@ -822,14 +845,14 @@ WriteLiteral(">\r\n"); #line default #line hidden - #line 195 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 206 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(Html.ActionLink(assignedUser.DisplayName, MVC.User.Show(assignedUser.UserId))); #line default #line hidden - #line 195 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 206 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } else @@ -839,14 +862,14 @@ WriteLiteral(">\r\n"); #line default #line hidden - #line 199 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 210 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(assignedUser.DisplayName); #line default #line hidden - #line 199 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 210 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } @@ -863,7 +886,7 @@ WriteLiteral(" title=\"Id\""); WriteLiteral(">"); - #line 202 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 213 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(assignedUser.FriendlyId()); @@ -872,13 +895,13 @@ WriteLiteral(">"); WriteLiteral("

    \r\n"); - #line 203 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 214 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 203 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 214 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (Authorization.Has(Claims.User.ShowDetails)) { if (!string.IsNullOrWhiteSpace(assignedUser.PhoneNumber)) @@ -887,7 +910,7 @@ WriteLiteral("
    \r\n"); #line default #line hidden -WriteLiteral(" "); - #line 207 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - Write(assignedUser.PhoneNumber); + #line 218 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + Write(assignedUser.PhoneNumber); #line default @@ -905,7 +928,7 @@ WriteLiteral(">"); WriteLiteral("
    \r\n"); - #line 208 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 219 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } if (!string.IsNullOrWhiteSpace(assignedUser.EmailAddress)) { @@ -913,7 +936,7 @@ WriteLiteral("
    \r\n"); #line default #line hidden -WriteLiteral(" (Model.Device.AssignedUser.EmailAddress + #line 222 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + , Tuple.Create(Tuple.Create("", 13233), Tuple.Create(Model.Device.AssignedUser.EmailAddress #line default #line hidden -, 12775), false) +, 13233), false) ); WriteLiteral(">"); - #line 211 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - Write(assignedUser.EmailAddress); + #line 222 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + Write(assignedUser.EmailAddress); #line default @@ -944,7 +967,7 @@ WriteLiteral(">"); WriteLiteral("
    \r\n"); - #line 212 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 223 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } } @@ -954,7 +977,7 @@ WriteLiteral("\r\n"); WriteLiteral(" "); - #line 214 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 225 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (Authorization.Has(Claims.User.ShowFlagAssignments)) { @@ -968,13 +991,13 @@ WriteLiteral(" id=\"Device_Show_User_Flags\""); WriteLiteral(">\r\n"); - #line 217 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 228 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 217 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 228 "..\..\Views\Device\DeviceParts\_Subject.cshtml" foreach (var flag in assignedUser.UserFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, UserFlagService.GetUserFlag(f.UserFlagId)))) { @@ -983,41 +1006,41 @@ WriteLiteral(">\r\n"); #line hidden WriteLiteral(" (flag.Item2.Icon + #line 230 "..\..\Views\Device\DeviceParts\_Subject.cshtml" +, Tuple.Create(Tuple.Create("", 13961), Tuple.Create(flag.Item2.Icon #line default #line hidden -, 13503), false) -, Tuple.Create(Tuple.Create(" ", 13521), Tuple.Create("fa-fw", 13522), true) -, Tuple.Create(Tuple.Create(" ", 13527), Tuple.Create("d-", 13528), true) +, 13961), false) +, Tuple.Create(Tuple.Create(" ", 13979), Tuple.Create("fa-fw", 13980), true) +, Tuple.Create(Tuple.Create(" ", 13985), Tuple.Create("d-", 13986), true) - #line 219 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - , Tuple.Create(Tuple.Create("", 13530), Tuple.Create(flag.Item2.IconColour + #line 230 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + , Tuple.Create(Tuple.Create("", 13988), Tuple.Create(flag.Item2.IconColour #line default #line hidden -, 13530), false) +, 13988), false) ); -WriteLiteral(">\r\n \r\n "); - #line 219 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - Write(flag.Item2.Name); + #line 232 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + Write(flag.Item2.Name); #line default @@ -1025,9 +1048,9 @@ WriteLiteral(">"); WriteLiteral(""); - #line 219 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - if (flag.Item1.Comments != null) - { + #line 232 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + if (flag.Item1.Comments != null) + { #line default #line hidden @@ -1038,8 +1061,8 @@ WriteLiteral(" class=\"comments\""); WriteLiteral(">"); - #line 220 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - Write(flag.Item1.Comments.ToHtmlComment()); + #line 233 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + Write(flag.Item1.Comments.ToHtmlComment()); #line default @@ -1047,8 +1070,8 @@ WriteLiteral(">"); WriteLiteral(""); - #line 220 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - } + #line 233 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + } #line default #line hidden @@ -1059,16 +1082,17 @@ WriteLiteral(" class=\"added\""); WriteLiteral(">"); - #line 220 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - Write(CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUserId)); + #line 233 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + Write(CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUserId)); #line default #line hidden -WriteLiteral("\r\n"); +WriteLiteral("\r\n \r\n " + +" \r\n"); - #line 221 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 236 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } @@ -1111,7 +1135,7 @@ WriteLiteral(">\r\n $(functio " \r\n \r\n"); - #line 253 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 268 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } @@ -1120,7 +1144,7 @@ WriteLiteral(">\r\n $(functio WriteLiteral(" \r\n"); - #line 255 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 270 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } else { @@ -1135,7 +1159,7 @@ WriteLiteral(" class=\"smallMessage\""); WriteLiteral(">Not Assigned\r\n"); - #line 259 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 274 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } @@ -1145,13 +1169,13 @@ WriteLiteral(" \r\n " \r\n \r\n"); - #line 264 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 279 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 264 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 279 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (Authorization.Has(Claims.Device.Actions.GenerateDocuments)) { @@ -1169,7 +1193,7 @@ WriteLiteral(">\r\n"); WriteLiteral(" "); - #line 267 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 282 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(Html.DropDownList("Device_Show_GenerateDocument", Model.DocumentTemplatesSelectListItems)); @@ -1183,7 +1207,7 @@ WriteLiteral(">\r\n $(function () {\r\n "ar generatePdfUrl = \'"); - #line 270 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 285 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(Url.Action(MVC.API.Device.GeneratePdf(Model.Device.SerialNumber.ToString(), null))); @@ -1216,7 +1240,7 @@ WriteLiteral("?DocumentTemplateId=\';\r\n var $do " });\r\n \r\n \r\n"); - #line 302 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 317 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } @@ -1236,91 +1260,108 @@ WriteLiteral(">\r\n "); +WriteLiteral(">\r\n"); - #line 308 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - if (Authorization.Has(Claims.Config.DeviceProfile.Show)) - { + #line 324 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 310 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - Write(Html.ActionLink(Model.Device.DeviceProfile.Name, MVC.Config.DeviceProfile.Index(Model.Device.DeviceProfileId))); + #line 324 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + if (Authorization.Has(Claims.Config.DeviceProfile.Show)) + { + + + #line default + #line hidden + + #line 326 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + Write(Html.ActionLink(Model.Device.DeviceProfile.Name, MVC.Config.DeviceProfile.Index(Model.Device.DeviceProfileId))); #line default #line hidden - #line 310 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - - } - else - { - + #line 326 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + + } + else + { + #line default #line hidden - #line 314 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - Write(Model.Device.DeviceProfile.Name); + #line 330 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + Write(Model.Device.DeviceProfile.Name); #line default #line hidden - #line 314 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - - } + #line 330 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + + } + #line default #line hidden -WriteLiteral("\r\n \r\n \r\n \r\n \r\n \r\n \r\n " + +" Distribution:\r\n \r\n " + -" "); +" \r\n"); + +WriteLiteral(" "); - #line 320 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 339 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(Model.Device.DeviceProfile.DistributionType.ToString()); #line default #line hidden WriteLiteral("\r\n \r\n \r\n " + -" \r\n \r\n \r\n " + +" Address:\r\n \r\n " + -""); +"\r\n"); - #line 326 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 347 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + + + #line default + #line hidden + + #line 347 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - if (Model.DeviceProfileDefaultOrganisationAddress != null) - { + if (Model.DeviceProfileDefaultOrganisationAddress != null) + { #line default #line hidden -WriteLiteral(" "); - #line 329 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - Write(Model.DeviceProfileDefaultOrganisationAddress.Name); + #line 350 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + Write(Model.DeviceProfileDefaultOrganisationAddress.Name); #line default @@ -1328,15 +1369,15 @@ WriteLiteral(">"); WriteLiteral("\r\n"); - #line 330 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - } - else - { + #line 351 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + } + else + { #line default #line hidden -WriteLiteral(" None\r\n"); - #line 334 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - } - + #line 355 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + } + #line default #line hidden WriteLiteral("\r\n \r\n \r\n " + -" \r\n \r\n \r\n " + +" Provision Account:\r\n \r\n " + -" "); +" \r\n"); + +WriteLiteral(" "); - #line 341 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 364 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(Model.Device.DeviceProfile.ProvisionADAccount ? "Active Directory" : "No"); #line default #line hidden WriteLiteral("\r\n \r\n \r\n " + -" \r\n \r\n \r\n " + +" Allocate Certificate:\r\n \r\n " + -" "); +WriteLiteral(">Certificates:\r\n \r\n " + +" \r\n"); + +WriteLiteral(" "); - #line 347 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - Write(Model.DeviceProfileCertificateProvider != null ? Model.DeviceProfileCertificateProvider.Name : "No"); + #line 372 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + Write(Model.DeviceProfileCertificateProviders != null ? string.Join(", ", Model.DeviceProfileCertificateProviders.Select(c => c.Name)) : "None Provisioned"); + + + #line default + #line hidden +WriteLiteral("\r\n \r\n \r\n " + +" \r\n Wireless Profiles:\r\n \r\n " + +" \r\n"); + +WriteLiteral(" "); + + + #line 379 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + Write(Model.DeviceProfileWirelessProfileProviders != null ? string.Join(", ", Model.DeviceProfileWirelessProfileProviders.Select(c => c.Name)) : "None Provisioned"); #line default @@ -1385,13 +1449,13 @@ WriteLiteral("\r\n \r\n < " \r\n"); - #line 351 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 383 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 351 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 383 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (Model.Device.CanUpdateDeviceProfile()) { @@ -1399,14 +1463,14 @@ WriteLiteral("\r\n \r\n < #line default #line hidden - #line 353 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 385 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Update Profile", MVC.API.Device.UpdateDeviceProfileId(Model.Device.SerialNumber, redirect: true), "Device_Show_Policies_Profile_Actions_Update_Button")); #line default #line hidden - #line 353 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 385 "..\..\Views\Device\DeviceParts\_Subject.cshtml" @@ -1428,15 +1492,15 @@ WriteLiteral(" class=\"none\""); WriteLiteral(">\r\n"); - #line 358 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 390 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 358 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 390 "..\..\Views\Device\DeviceParts\_Subject.cshtml" foreach (var dp in Model.DeviceProfiles.OrderBy(i => i.Name)) - { + { #line default @@ -1449,7 +1513,7 @@ WriteLiteral(" type=\"radio\""); WriteLiteral(" data-deviceprofileid=\""); - #line 361 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 393 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(dp.Id); @@ -1459,54 +1523,54 @@ WriteLiteral("\""); WriteLiteral(" name=\"DeviceProfile\""); -WriteAttribute("id", Tuple.Create(" id=\"", 23070), Tuple.Create("\"", 23097) -, Tuple.Create(Tuple.Create("", 23075), Tuple.Create("DeviceProfile_", 23075), true) +WriteAttribute("id", Tuple.Create(" id=\"", 24364), Tuple.Create("\"", 24391) +, Tuple.Create(Tuple.Create("", 24369), Tuple.Create("DeviceProfile_", 24369), true) - #line 361 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - , Tuple.Create(Tuple.Create("", 23089), Tuple.Create(dp.Id + #line 393 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + , Tuple.Create(Tuple.Create("", 24383), Tuple.Create(dp.Id #line default #line hidden -, 23089), false) +, 24383), false) ); WriteLiteral(" />(dp.Id + #line 393 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + , Tuple.Create(Tuple.Create("", 24421), Tuple.Create(dp.Id #line default #line hidden -, 23127), false) +, 24421), false) ); -WriteAttribute("title", Tuple.Create(" title=\"", 23136), Tuple.Create("\"", 23180) -, Tuple.Create(Tuple.Create("", 23144), Tuple.Create("Distribution:", 23144), true) +WriteAttribute("title", Tuple.Create(" title=\"", 24430), Tuple.Create("\"", 24474) +, Tuple.Create(Tuple.Create("", 24438), Tuple.Create("Distribution:", 24438), true) - #line 361 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - , Tuple.Create(Tuple.Create(" ", 23157), Tuple.Create(dp.DistributionType + #line 393 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + , Tuple.Create(Tuple.Create(" ", 24451), Tuple.Create(dp.DistributionType #line default #line hidden -, 23158), false) +, 24452), false) ); WriteLiteral(">"); - #line 361 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 393 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(dp.Name); #line default #line hidden -WriteLiteral(" \r\n"); +WriteLiteral("\r\n \r\n"); - #line 362 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 395 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } @@ -1519,7 +1583,7 @@ WriteLiteral(" \r\n"); - #line 700 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 748 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } @@ -2363,7 +2456,7 @@ WriteLiteral(">\r\n $(function () {\r\n WriteLiteral(" "); - #line 701 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 749 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (Model.Device.CanUpdateUntrustEnrol()) { @@ -2371,14 +2464,14 @@ WriteLiteral(" "); #line default #line hidden - #line 703 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 751 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Untrust Enrol", MVC.API.Device.UpdateAllowUnauthenticatedEnrol(Model.Device.SerialNumber, false.ToString(), true), "Device_Show_Device_Actions_UntrustEnrol_Button")); #line default #line hidden - #line 703 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 751 "..\..\Views\Device\DeviceParts\_Subject.cshtml" @@ -2449,7 +2542,7 @@ WriteLiteral(@"> "); - #line 743 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 791 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } @@ -2458,22 +2551,22 @@ WriteLiteral(@"> WriteLiteral(" "); - #line 744 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 792 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (Model.Device.CanDecommission()) - { + { #line default #line hidden - #line 746 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 794 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Decommission", MVC.API.Device.Decommission(), "Device_Show_Device_Actions_Decommission_Button")); #line default #line hidden - #line 746 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 794 "..\..\Views\Device\DeviceParts\_Subject.cshtml" @@ -2505,13 +2598,13 @@ WriteLiteral(" class=\"none\""); WriteLiteral(">\r\n"); - #line 753 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 801 "..\..\Views\Device\DeviceParts\_Subject.cshtml" #line default #line hidden - #line 753 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 801 "..\..\Views\Device\DeviceParts\_Subject.cshtml" foreach (DecommissionReasons decommissionReason in Enum.GetValues(typeof(DecommissionReasons)).Cast().OrderBy(r => r.ToString())) { @@ -2522,56 +2615,56 @@ WriteLiteral("
  • \r\n WriteLiteral(" type=\"radio\""); -WriteAttribute("id", Tuple.Create(" id=\"", 47619), Tuple.Create("\"", 47697) -, Tuple.Create(Tuple.Create("", 47624), Tuple.Create("Device_Show_Device_Actions_Decommission_Reason_", 47624), true) +WriteAttribute("id", Tuple.Create(" id=\"", 48980), Tuple.Create("\"", 49058) +, Tuple.Create(Tuple.Create("", 48985), Tuple.Create("Device_Show_Device_Actions_Decommission_Reason_", 48985), true) - #line 756 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - , Tuple.Create(Tuple.Create("", 47671), Tuple.Create((int)decommissionReason + #line 804 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + , Tuple.Create(Tuple.Create("", 49032), Tuple.Create((int)decommissionReason #line default #line hidden -, 47671), false) +, 49032), false) ); -WriteLiteral("\r\n name=\"Device_Show_Device_Actions_Decomm" + -"ission_Reason\""); +WriteLiteral("\r\n name=\"Device_Show_Device_Actions_Dec" + +"ommission_Reason\""); -WriteAttribute("value", Tuple.Create(" value=\"", 47793), Tuple.Create("\"", 47827) +WriteAttribute("value", Tuple.Create(" value=\"", 49157), Tuple.Create("\"", 49191) - #line 757 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - , Tuple.Create(Tuple.Create("", 47801), Tuple.Create((int)decommissionReason + #line 805 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + , Tuple.Create(Tuple.Create("", 49165), Tuple.Create((int)decommissionReason #line default #line hidden -, 47801), false) +, 49165), false) ); WriteLiteral(" "); - #line 757 "..\..\Views\Device\DeviceParts\_Subject.cshtml" - Write((decommissionReason == DecommissionReasons.EndOfLife) ? "checked=\"checked\"" : string.Empty); + #line 805 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + Write((decommissionReason == DecommissionReasons.EndOfLife) ? "checked=\"checked\"" : string.Empty); #line default #line hidden -WriteLiteral("/>\r\n \r\n ((int)decommissionReason + #line 806 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + , Tuple.Create(Tuple.Create("", 49388), Tuple.Create((int)decommissionReason #line default #line hidden -, 48023), false) +, 49388), false) ); WriteLiteral(">"); - #line 758 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 806 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(decommissionReason.ReasonMessage()); @@ -2580,7 +2673,7 @@ WriteLiteral(">"); WriteLiteral("\r\n
  • \r\n"); - #line 760 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 808 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } @@ -2598,7 +2691,7 @@ WriteLiteral(">\r\n $(function () {\r\n "uttonDialog = null;\r\n var deviceSerialNumber = \'"); - #line 768 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 816 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(Model.Device.SerialNumber); @@ -2631,7 +2724,7 @@ WriteLiteral("\';\r\n\r\n button.click(function () {\r\n\ " });\r\n \r\n"); - #line 804 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 852 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } @@ -2640,22 +2733,22 @@ WriteLiteral("\';\r\n\r\n button.click(function () {\r\n\ WriteLiteral(" "); - #line 805 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 853 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (Model.Device.CanRecommission()) - { + { #line default #line hidden - #line 807 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 855 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Recommission", MVC.API.Device.Recommission(Model.Device.SerialNumber, true), "Device_Show_Device_Actions_Recommission_Button")); #line default #line hidden - #line 807 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 855 "..\..\Views\Device\DeviceParts\_Subject.cshtml" @@ -2709,7 +2802,7 @@ WriteLiteral(@"> "); - #line 842 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 890 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } @@ -2718,22 +2811,22 @@ WriteLiteral(@"> WriteLiteral(" "); - #line 843 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 891 "..\..\Views\Device\DeviceParts\_Subject.cshtml" if (Model.Device.CanDelete()) - { + { #line default #line hidden - #line 845 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 893 "..\..\Views\Device\DeviceParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Delete Device", MVC.API.Device.Delete(Model.Device.SerialNumber, true), "Device_Show_Device_Actions_Delete_Button")); #line default #line hidden - #line 845 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 893 "..\..\Views\Device\DeviceParts\_Subject.cshtml" @@ -2793,7 +2886,7 @@ WriteLiteral(@"> "); - #line 883 "..\..\Views\Device\DeviceParts\_Subject.cshtml" + #line 931 "..\..\Views\Device\DeviceParts\_Subject.cshtml" } diff --git a/Disco.Web/Views/Job/JobParts/_Subject.cshtml b/Disco.Web/Views/Job/JobParts/_Subject.cshtml index f16645bd..9442ae0c 100644 --- a/Disco.Web/Views/Job/JobParts/_Subject.cshtml +++ b/Disco.Web/Views/Job/JobParts/_Subject.cshtml @@ -1,4 +1,5 @@ @model Disco.Web.Models.Job.ShowModel +@using Disco.Models.Services.Job; @using Disco.Services.Users.UserFlags; @{ Authorization.Require(Claims.Job.Show); @@ -293,11 +294,11 @@ { switch (Model.LocationMode) { - case Disco.Models.BI.Job.LocationModes.Unrestricted: - case Disco.Models.BI.Job.LocationModes.OptionalList: + case LocationModes.Unrestricted: + case LocationModes.OptionalList: @Html.TextBoxFor(m => m.Job.DeviceHeldLocation, new { @class = "small discreet" }) break; - case Disco.Models.BI.Job.LocationModes.RestrictedList: + case LocationModes.RestrictedList: List listOptions = new List() { new SelectListItem() { Value = "", Text = "" } }; if (!string.IsNullOrWhiteSpace(Model.Job.DeviceHeldLocation) && !Model.LocationOptions.Any(l => l.Location.Equals(Model.Job.DeviceHeldLocation))) { @@ -345,8 +346,8 @@ $(function () { @switch (Model.LocationMode) { - case Disco.Models.BI.Job.LocationModes.Unrestricted: - case Disco.Models.BI.Job.LocationModes.OptionalList: + case LocationModes.Unrestricted: + case LocationModes.OptionalList: var $deviceHeldLocation = $('#Job_DeviceHeldLocation'); var $ajaxSave = $deviceHeldLocation.next('.ajaxSave'); @@ -430,7 +431,7 @@ }); break; - case Disco.Models.BI.Job.LocationModes.RestrictedList: + case LocationModes.RestrictedList: document.DiscoFunctions.PropertyChangeHelper( $('#Job_DeviceHeldLocation'), diff --git a/Disco.Web/Views/Job/JobParts/_Subject.generated.cs b/Disco.Web/Views/Job/JobParts/_Subject.generated.cs index fe26814e..0cf9a881 100644 --- a/Disco.Web/Views/Job/JobParts/_Subject.generated.cs +++ b/Disco.Web/Views/Job/JobParts/_Subject.generated.cs @@ -2,7 +2,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -27,12 +27,17 @@ namespace Disco.Web.Views.Job.JobParts using System.Web.UI; using System.Web.WebPages; using Disco; - using Disco.BI.Extensions; using Disco.Models.Repository; + + #line 2 "..\..\Views\Job\JobParts\_Subject.cshtml" + using Disco.Models.Services.Job; + + #line default + #line hidden using Disco.Services; using Disco.Services.Authorization; - #line 2 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 3 "..\..\Views\Job\JobParts\_Subject.cshtml" using Disco.Services.Users.UserFlags; #line default @@ -43,15 +48,15 @@ namespace Disco.Web.Views.Job.JobParts [System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "2.0.0.0")] [System.Web.WebPages.PageVirtualPathAttribute("~/Views/Job/JobParts/_Subject.cshtml")] - public partial class Subject : Disco.Services.Web.WebViewPage + public partial class _Subject : Disco.Services.Web.WebViewPage { - public Subject() + public _Subject() { } public override void Execute() { - #line 3 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 4 "..\..\Views\Job\JobParts\_Subject.cshtml" Authorization.Require(Claims.Job.Show); @@ -82,7 +87,7 @@ WriteLiteral(" id=\"Job_Show_Job_Dates_Opened\""); WriteLiteral(">"); - #line 15 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 16 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(CommonHelpers.FriendlyDateAndTitleUser(Model.Job.OpenedDate, Model.Job.OpenedTechUser)); @@ -91,13 +96,13 @@ WriteLiteral(">"); WriteLiteral("\r\n \r\n"); - #line 17 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 18 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 17 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 18 "..\..\Views\Job\JobParts\_Subject.cshtml" if (!Model.Job.ClosedDate.HasValue || Model.Job.ExpectedClosedDate.HasValue) { @@ -113,7 +118,7 @@ WriteLiteral(">Expected:\r\n \r\n " "); - #line 23 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 24 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Authorization.Has(Claims.Job.Properties.ExpectedClosedDate)) { @@ -121,40 +126,40 @@ WriteLiteral(">Expected:\r\n \r\n #line default #line hidden - #line 25 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 26 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.TextBoxFor(m => m.Job.ExpectedClosedDate, "{0:yyyy/MM/dd hh:mm tt}", new { @class = "small discreet" })); #line default #line hidden - #line 25 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 26 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 25 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 26 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(AjaxHelpers.AjaxSave()); #line default #line hidden - #line 25 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 26 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 25 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 26 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(AjaxHelpers.AjaxLoader()); #line default #line hidden - #line 25 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 26 "..\..\Views\Job\JobParts\_Subject.cshtml" @@ -178,7 +183,7 @@ WriteLiteral(@"> minDate: "); - #line 37 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 38 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Model.Job.OpenedDate.ToJavascriptDate()); @@ -202,7 +207,7 @@ WriteLiteral(@", $.getJSON('"); - #line 52 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 53 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Url.Action(MVC.API.Job.UpdateExpectedClosedDate(Model.Job.Id, null))); @@ -225,7 +230,7 @@ WriteLiteral(@"', data, function (response, result) { "); - #line 66 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 67 "..\..\Views\Job\JobParts\_Subject.cshtml" } else { @@ -234,14 +239,14 @@ WriteLiteral(@"', data, function (response, result) { #line default #line hidden - #line 69 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 70 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(CommonHelpers.FriendlyDate(Model.Job.ExpectedClosedDate)); #line default #line hidden - #line 69 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 70 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -251,7 +256,7 @@ WriteLiteral(@"', data, function (response, result) { WriteLiteral(" \r\n \r\n"); - #line 73 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 74 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -260,7 +265,7 @@ WriteLiteral(" \r\n WriteLiteral(" "); - #line 74 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 75 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.ClosedDate.HasValue) { @@ -275,7 +280,7 @@ WriteLiteral(" id=\"Job_Show_Job_Dates_Closed\""); WriteLiteral(">"); - #line 79 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 80 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(CommonHelpers.FriendlyDateAndTitleUser(Model.Job.ClosedDate, Model.Job.ClosedTechUser)); @@ -284,7 +289,7 @@ WriteLiteral(">"); WriteLiteral("\r\n \r\n"); - #line 81 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 82 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -298,20 +303,20 @@ WriteLiteral(" class=\"status\""); WriteLiteral(">\r\n (Model.Job.JobType.Id + #line 86 "..\..\Views\Job\JobParts\_Subject.cshtml" +, Tuple.Create(Tuple.Create("", 5660), Tuple.Create(Model.Job.JobType.Id #line default #line hidden -, 5625), false) +, 5660), false) ); WriteLiteral(">"); - #line 85 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 86 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Model.Job.JobType.Description); @@ -324,13 +329,13 @@ WriteLiteral(" class=\"none\""); WriteLiteral(">\r\n \r\n"); - #line 88 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 89 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 88 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 89 "..\..\Views\Job\JobParts\_Subject.cshtml" var jobSubTypeFirst = (int)Math.Ceiling((double)(Model.Job.JobSubTypes.Count + 1) / 2); @@ -344,13 +349,13 @@ WriteLiteral(" id=\"Job_Show_Job_SubTypes_1\""); WriteLiteral(">\r\n"); - #line 93 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 94 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 93 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 94 "..\..\Views\Job\JobParts\_Subject.cshtml" foreach (var jobSubType in Model.Job.JobSubTypes.Take(jobSubTypeFirst)) { @@ -359,20 +364,20 @@ WriteLiteral(">\r\n"); #line hidden WriteLiteral(" (jobSubType.Id + #line 96 "..\..\Views\Job\JobParts\_Subject.cshtml" +, Tuple.Create(Tuple.Create("", 6277), Tuple.Create(jobSubType.Id #line default #line hidden -, 6242), false) +, 6277), false) ); WriteLiteral(">"); - #line 95 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 96 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(jobSubType.Description); @@ -381,7 +386,7 @@ WriteLiteral(">"); WriteLiteral("\r\n"); - #line 96 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 97 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -395,13 +400,13 @@ WriteLiteral(" id=\"Job_Show_Job_SubTypes_2\""); WriteLiteral(">\r\n"); - #line 101 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 102 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 101 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 102 "..\..\Views\Job\JobParts\_Subject.cshtml" foreach (var jobSubType in Model.Job.JobSubTypes.Skip(jobSubTypeFirst)) { @@ -410,20 +415,20 @@ WriteLiteral(">\r\n"); #line hidden WriteLiteral(" (jobSubType.Id + #line 104 "..\..\Views\Job\JobParts\_Subject.cshtml" +, Tuple.Create(Tuple.Create("", 6737), Tuple.Create(jobSubType.Id #line default #line hidden -, 6702), false) +, 6737), false) ); WriteLiteral(">"); - #line 103 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 104 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(jobSubType.Description); @@ -432,7 +437,7 @@ WriteLiteral(">"); WriteLiteral("\r\n"); - #line 104 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 105 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -441,13 +446,13 @@ WriteLiteral("\r\n"); WriteLiteral(" \r\n"); - #line 106 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 107 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 106 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 107 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Authorization.Has(Claims.Job.Actions.UpdateSubTypes) && !Model.Job.ClosedDate.HasValue) { @@ -463,7 +468,7 @@ WriteLiteral(" id=\"Job_Show_Job_SubTypes_Update\""); WriteLiteral(">Update Sub Types\r\n"); - #line 109 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 110 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -473,13 +478,13 @@ WriteLiteral(" \r\n " \r\n"); - #line 113 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 114 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 113 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 114 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Authorization.Has(Claims.Job.Actions.UpdateSubTypes)) { @@ -497,7 +502,7 @@ WriteLiteral(">\r\n
    \r\n WriteLiteral(" "); - #line 118 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 119 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Model.Job.JobType.Description); @@ -506,13 +511,13 @@ WriteLiteral(" "); WriteLiteral("\r\n"); - #line 119 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 120 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 119 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 120 "..\..\Views\Job\JobParts\_Subject.cshtml" using (Html.BeginForm(MVC.API.Job.UpdateSubTypes(Model.Job.Id, redirect: true), FormMethod.Post, new { id = "formUpdateJobTypes" })) { @@ -520,14 +525,14 @@ WriteLiteral("\r\n"); #line default #line hidden - #line 121 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 122 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(CommonHelpers.CheckBoxList("SubTypes", Model.UpdatableJobSubTypes.ToSelectListItems(Model.Job.JobSubTypes.ToList()), 3)); #line default #line hidden - #line 121 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 122 "..\..\Views\Job\JobParts\_Subject.cshtml" @@ -556,7 +561,7 @@ WriteLiteral(">Add Components for newly added Sub Types\r\n "
    \r\n"); - #line 127 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 128 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -588,7 +593,7 @@ WriteLiteral(" \r\n"); - #line 159 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 160 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -597,13 +602,13 @@ WriteLiteral(" \r\n \r\n"); - #line 199 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 200 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -677,13 +682,13 @@ WriteLiteral("?DocumentTemplateId=\';\r\n var $do WriteLiteral(" \r\n \r\n"); - #line 202 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 203 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 202 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 203 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.Device != null) { @@ -703,21 +708,21 @@ WriteLiteral(" title=\"Serial Number\""); WriteLiteral(">"); - #line 206 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 207 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Authorization.Has(Claims.Device.Show)) { #line default #line hidden - #line 207 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 208 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.ActionLink(Model.Job.DeviceSerialNumber, MVC.Device.Show(Model.Job.DeviceSerialNumber))); #line default #line hidden - #line 207 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 208 "..\..\Views\Job\JobParts\_Subject.cshtml" } else { @@ -725,14 +730,14 @@ WriteLiteral(">"); #line default #line hidden - #line 209 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 210 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Model.Job.DeviceSerialNumber); #line default #line hidden - #line 209 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 210 "..\..\Views\Job\JobParts\_Subject.cshtml" } #line default @@ -751,14 +756,14 @@ WriteLiteral(" id=\"Job_Show_Device_Model_Image\""); WriteLiteral(" alt=\"Model Image\""); -WriteAttribute("src", Tuple.Create(" src=\"", 13601), Tuple.Create("\"", 13719) +WriteAttribute("src", Tuple.Create(" src=\"", 13636), Tuple.Create("\"", 13754) - #line 212 "..\..\Views\Job\JobParts\_Subject.cshtml" - , Tuple.Create(Tuple.Create("", 13607), Tuple.Create(Url.Action(MVC.API.DeviceModel.Image(Model.Job.Device.DeviceModelId, Model.Job.Device.DeviceModel.ImageHash())) + #line 213 "..\..\Views\Job\JobParts\_Subject.cshtml" + , Tuple.Create(Tuple.Create("", 13642), Tuple.Create(Url.Action(MVC.API.DeviceModel.Image(Model.Job.Device.DeviceModelId, Model.Job.Device.DeviceModel.ImageHash())) #line default #line hidden -, 13607), false) +, 13642), false) ); WriteLiteral(" />\r\n "); - #line 213 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 214 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Model.Job.Device.ComputerName); @@ -785,7 +790,7 @@ WriteLiteral(" title=\"Model\""); WriteLiteral(">"); - #line 214 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 215 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.ActionLink(Model.Job.Device.DeviceModel.ToString(), MVC.Config.DeviceModel.Index(Model.Job.Device.DeviceModelId))); @@ -794,13 +799,13 @@ WriteLiteral(">"); WriteLiteral("\r\n"); - #line 215 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 216 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 215 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 216 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.Device.DeviceBatch != null) { @@ -816,7 +821,7 @@ WriteLiteral(" title=\"Batch\""); WriteLiteral(">"); - #line 217 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 218 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.ActionLink(Model.Job.Device.DeviceBatch.Name, MVC.Config.DeviceBatch.Index(Model.Job.Device.DeviceBatchId))); @@ -825,7 +830,7 @@ WriteLiteral(">"); WriteLiteral("\r\n"); - #line 218 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 219 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -834,13 +839,13 @@ WriteLiteral("\r\n"); WriteLiteral(" \r\n"); - #line 220 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 221 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 220 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 221 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.Device.DeviceBatch != null) { if (Model.Job.JobTypeId == JobType.JobTypeIds.HWar) @@ -861,7 +866,7 @@ WriteLiteral(" id=\"Job_Show_Device_Details_HWar_ValidUntil\""); WriteLiteral(" data-livestamp=\""); - #line 226 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 227 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Model.Job.Device.DeviceBatch.WarrantyValidUntil.ToUnixEpoc()); @@ -872,7 +877,7 @@ WriteLiteral("\""); WriteLiteral(">"); - #line 226 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 227 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Model.Job.Device.DeviceBatch.WarrantyValidUntil.ToFullDateTime("Unknown")); @@ -881,13 +886,13 @@ WriteLiteral(">"); WriteLiteral("\r\n"); - #line 227 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 228 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 227 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 228 "..\..\Views\Job\JobParts\_Subject.cshtml" if (!string.IsNullOrWhiteSpace(Model.Job.Device.DeviceBatch.WarrantyDetails)) { @@ -908,23 +913,23 @@ WriteLiteral(" id=\"Job_Show_Device_Details_HWar_Details_Dialog\""); WriteLiteral(" class=\"dialog\""); -WriteAttribute("title", Tuple.Create(" title=\"", 15383), Tuple.Create("\"", 15448) -, Tuple.Create(Tuple.Create("", 15391), Tuple.Create("Warranty", 15391), true) -, Tuple.Create(Tuple.Create(" ", 15399), Tuple.Create("Details", 15400), true) -, Tuple.Create(Tuple.Create(" ", 15407), Tuple.Create("for", 15408), true) +WriteAttribute("title", Tuple.Create(" title=\"", 15418), Tuple.Create("\"", 15483) +, Tuple.Create(Tuple.Create("", 15426), Tuple.Create("Warranty", 15426), true) +, Tuple.Create(Tuple.Create(" ", 15434), Tuple.Create("Details", 15435), true) +, Tuple.Create(Tuple.Create(" ", 15442), Tuple.Create("for", 15443), true) - #line 230 "..\..\Views\Job\JobParts\_Subject.cshtml" - , Tuple.Create(Tuple.Create(" ", 15411), Tuple.Create(Model.Job.Device.DeviceBatch.Name + #line 231 "..\..\Views\Job\JobParts\_Subject.cshtml" + , Tuple.Create(Tuple.Create(" ", 15446), Tuple.Create(Model.Job.Device.DeviceBatch.Name #line default #line hidden -, 15412), false) +, 15447), false) ); WriteLiteral(">\r\n
    "); - #line 231 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 232 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(new HtmlString(Model.Job.Device.DeviceBatch.WarrantyDetails)); @@ -954,7 +959,7 @@ WriteLiteral(@"> "); - #line 248 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 249 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -963,7 +968,7 @@ WriteLiteral(@"> WriteLiteral("
    \r\n"); - #line 250 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 251 "..\..\Views\Job\JobParts\_Subject.cshtml" } if (Model.Job.JobTypeId == JobType.JobTypeIds.HNWar) { @@ -983,7 +988,7 @@ WriteLiteral(" id=\"Job_Show_Device_Details_HNWar_InsuranceSupplier\""); WriteLiteral(">"); - #line 255 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 256 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Model.Job.Device.DeviceBatch.InsuranceSupplier); @@ -996,7 +1001,7 @@ WriteLiteral(" id=\"Job_Show_Device_Details_HNWar_ValidUntil\""); WriteLiteral(" data-livestamp=\""); - #line 256 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 257 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Model.Job.Device.DeviceBatch.InsuredUntil.ToUnixEpoc()); @@ -1007,7 +1012,7 @@ WriteLiteral("\""); WriteLiteral(">"); - #line 256 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 257 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Model.Job.Device.DeviceBatch.InsuredUntil.ToFullDateTime("Unknown")); @@ -1016,13 +1021,13 @@ WriteLiteral(">"); WriteLiteral("\r\n"); - #line 257 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 258 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 257 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 258 "..\..\Views\Job\JobParts\_Subject.cshtml" if (!string.IsNullOrWhiteSpace(Model.Job.Device.DeviceBatch.InsuranceDetails)) { @@ -1043,23 +1048,23 @@ WriteLiteral(" id=\"Job_Show_Device_Details_HNWar_Details_Dialog\""); WriteLiteral(" class=\"dialog\""); -WriteAttribute("title", Tuple.Create(" title=\"", 17711), Tuple.Create("\"", 17777) -, Tuple.Create(Tuple.Create("", 17719), Tuple.Create("Insurance", 17719), true) -, Tuple.Create(Tuple.Create(" ", 17728), Tuple.Create("Details", 17729), true) -, Tuple.Create(Tuple.Create(" ", 17736), Tuple.Create("for", 17737), true) +WriteAttribute("title", Tuple.Create(" title=\"", 17746), Tuple.Create("\"", 17812) +, Tuple.Create(Tuple.Create("", 17754), Tuple.Create("Insurance", 17754), true) +, Tuple.Create(Tuple.Create(" ", 17763), Tuple.Create("Details", 17764), true) +, Tuple.Create(Tuple.Create(" ", 17771), Tuple.Create("for", 17772), true) - #line 260 "..\..\Views\Job\JobParts\_Subject.cshtml" - , Tuple.Create(Tuple.Create(" ", 17740), Tuple.Create(Model.Job.Device.DeviceBatch.Name + #line 261 "..\..\Views\Job\JobParts\_Subject.cshtml" + , Tuple.Create(Tuple.Create(" ", 17775), Tuple.Create(Model.Job.Device.DeviceBatch.Name #line default #line hidden -, 17741), false) +, 17776), false) ); WriteLiteral(">\r\n
    "); - #line 261 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 262 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(new HtmlString(Model.Job.Device.DeviceBatch.InsuranceDetails)); @@ -1089,7 +1094,7 @@ WriteLiteral(@"> "); - #line 278 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 279 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -1098,7 +1103,7 @@ WriteLiteral(@"> WriteLiteral("
    \r\n"); - #line 280 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 281 "..\..\Views\Job\JobParts\_Subject.cshtml" } } @@ -1108,13 +1113,13 @@ WriteLiteral(" \r\n"); WriteLiteral(" \r\n"); - #line 283 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 284 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 283 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 284 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.DeviceHeld.HasValue) { var canEditLocation = Authorization.Has(Claims.Job.Properties.DeviceHeldLocation); @@ -1141,35 +1146,35 @@ WriteLiteral(" id=\"Job_Show_Device_DeviceHeld_Location\""); WriteLiteral(">\r\n"); - #line 292 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 293 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 292 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 293 "..\..\Views\Job\JobParts\_Subject.cshtml" if (canEditLocation) { switch (Model.LocationMode) { - case Disco.Models.BI.Job.LocationModes.Unrestricted: - case Disco.Models.BI.Job.LocationModes.OptionalList: + case LocationModes.Unrestricted: + case LocationModes.OptionalList: #line default #line hidden - #line 298 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 299 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.TextBoxFor(m => m.Job.DeviceHeldLocation, new { @class = "small discreet" })); #line default #line hidden - #line 298 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 299 "..\..\Views\Job\JobParts\_Subject.cshtml" break; - case Disco.Models.BI.Job.LocationModes.RestrictedList: + case LocationModes.RestrictedList: List listOptions = new List() { new SelectListItem() { Value = "", Text = "" } }; if (!string.IsNullOrWhiteSpace(Model.Job.DeviceHeldLocation) && !Model.LocationOptions.Any(l => l.Location.Equals(Model.Job.DeviceHeldLocation))) { @@ -1181,14 +1186,14 @@ WriteLiteral(">\r\n"); #line default #line hidden - #line 307 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 308 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.DropDownListFor(m => m.Job.DeviceHeldLocation, listOptions, new { @class = "small discreet" })); #line default #line hidden - #line 307 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 308 "..\..\Views\Job\JobParts\_Subject.cshtml" ; break; } @@ -1197,27 +1202,27 @@ WriteLiteral(">\r\n"); #line default #line hidden - #line 310 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 311 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(AjaxHelpers.AjaxSave()); #line default #line hidden - #line 310 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 311 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 310 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 311 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(AjaxHelpers.AjaxLoader()); #line default #line hidden - #line 310 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 311 "..\..\Views\Job\JobParts\_Subject.cshtml" } else if (string.IsNullOrEmpty(Model.Job.DeviceHeldLocation)) @@ -1233,7 +1238,7 @@ WriteLiteral(" class=\"smallMessage\""); WriteLiteral("><None/Unknown>\r\n"); - #line 315 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 316 "..\..\Views\Job\JobParts\_Subject.cshtml" } else { @@ -1242,14 +1247,14 @@ WriteLiteral("><None/Unknown>\r\n"); #line default #line hidden - #line 318 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 319 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Model.Job.DeviceHeldLocation); #line default #line hidden - #line 318 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 319 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -1268,7 +1273,7 @@ WriteLiteral(" id=\"Job_Show_Device_DeviceHeld_DeviceHeld\""); WriteLiteral(">"); - #line 325 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 326 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(CommonHelpers.FriendlyDateAndTitleUser(Model.Job.DeviceHeld, Model.Job.DeviceHeldTechUser)); @@ -1277,13 +1282,13 @@ WriteLiteral(">"); WriteLiteral("\r\n \r\n"); - #line 327 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 328 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 327 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 328 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.DeviceReadyForReturn.HasValue) { @@ -1298,7 +1303,7 @@ WriteLiteral(" id=\"Job_Show_Device_DeviceHeld_DeviceReadyForReturn\""); WriteLiteral(">"); - #line 331 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 332 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(CommonHelpers.FriendlyDateAndTitleUser(Model.Job.DeviceReadyForReturn, Model.Job.DeviceReadyForReturnTechUser)); @@ -1307,7 +1312,7 @@ WriteLiteral(">"); WriteLiteral("\r\n \r\n"); - #line 333 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 334 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -1316,7 +1321,7 @@ WriteLiteral("\r\n \r\n"); WriteLiteral(" "); - #line 334 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 335 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.DeviceReturnedDate.HasValue) { @@ -1331,7 +1336,7 @@ WriteLiteral(" id=\"Job_Show_Device_DeviceHeld_DeviceReturnedDate\""); WriteLiteral(">"); - #line 338 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 339 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(CommonHelpers.FriendlyDateAndTitleUser(Model.Job.DeviceReturnedDate, Model.Job.DeviceReturnedTechUser)); @@ -1340,7 +1345,7 @@ WriteLiteral(">"); WriteLiteral("\r\n \r\n"); - #line 340 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 341 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -1349,13 +1354,13 @@ WriteLiteral("\r\n \r\n"); WriteLiteral(" \r\n"); - #line 342 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 343 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 342 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 343 "..\..\Views\Job\JobParts\_Subject.cshtml" if (canEditLocation) { @@ -1369,17 +1374,17 @@ WriteLiteral(" type=\"text/javascript\""); WriteLiteral(">\r\n $(function () {\r\n"); - #line 346 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 347 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 346 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 347 "..\..\Views\Job\JobParts\_Subject.cshtml" switch (Model.LocationMode) { - case Disco.Models.BI.Job.LocationModes.Unrestricted: - case Disco.Models.BI.Job.LocationModes.OptionalList: + case LocationModes.Unrestricted: + case LocationModes.OptionalList: #line default @@ -1402,7 +1407,7 @@ WriteLiteral(@" url: '"); - #line 363 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 364 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Url.Action(MVC.API.Job.DeviceHeldLocations())); @@ -1460,7 +1465,7 @@ WriteLiteral("\',\r\n dat " url: \'"); - #line 414 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 415 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Url.Action(MVC.API.Job.UpdateDeviceHeldLocation(Model.Job.Id, null))); @@ -1488,9 +1493,9 @@ WriteLiteral(@"', WriteLiteral("\r\n"); - #line 432 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 433 "..\..\Views\Job\JobParts\_Subject.cshtml" break; - case Disco.Models.BI.Job.LocationModes.RestrictedList: + case LocationModes.RestrictedList: #line default @@ -1504,7 +1509,7 @@ WriteLiteral(@" '"); - #line 438 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 439 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Url.Action(MVC.API.Job.UpdateDeviceHeldLocation(Model.Job.Id, null))); @@ -1516,7 +1521,7 @@ WriteLiteral("\',\r\n \'DeviceHeldLoc WriteLiteral("\r\n"); - #line 441 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 442 "..\..\Views\Job\JobParts\_Subject.cshtml" break; } @@ -1527,7 +1532,7 @@ WriteLiteral("\r\n \r\n ");\r\n \r\n"); - #line 447 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 448 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -1536,7 +1541,7 @@ WriteLiteral("\r\n \r\n WriteLiteral(" \r\n"); - #line 449 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 450 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -1545,7 +1550,7 @@ WriteLiteral(" \r\n"); WriteLiteral(" \r\n \r\n"); - #line 452 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 453 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -1554,7 +1559,7 @@ WriteLiteral(" \r\n \r\n"); WriteLiteral(" "); - #line 453 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 454 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.User != null) { @@ -1574,21 +1579,21 @@ WriteLiteral(" title=\"Display Name\""); WriteLiteral(">"); - #line 457 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 458 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Authorization.Has(Claims.User.Show)) { #line default #line hidden - #line 458 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 459 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.ActionLink(Model.Job.User.DisplayName, MVC.User.Show(Model.Job.UserId))); #line default #line hidden - #line 458 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 459 "..\..\Views\Job\JobParts\_Subject.cshtml" } else { @@ -1596,14 +1601,14 @@ WriteLiteral(">"); #line default #line hidden - #line 460 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 461 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Model.Job.User.DisplayName); #line default #line hidden - #line 460 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 461 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -1618,7 +1623,7 @@ WriteLiteral(" title=\"Id\""); WriteLiteral(">"); - #line 462 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 463 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Model.Job.User.FriendlyId()); @@ -1627,13 +1632,13 @@ WriteLiteral(">"); WriteLiteral("\r\n"); - #line 463 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 464 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 463 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 464 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Authorization.Has(Claims.User.ShowDetails)) { if (!string.IsNullOrWhiteSpace(Model.Job.User.PhoneNumber)) @@ -1650,7 +1655,7 @@ WriteLiteral(" title=\"Phone Number\""); WriteLiteral(">Phone: "); - #line 466 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 467 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Model.Job.User.PhoneNumber); @@ -1659,7 +1664,7 @@ WriteLiteral(">Phone: "); WriteLiteral(""); - #line 466 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 467 "..\..\Views\Job\JobParts\_Subject.cshtml" } if (!string.IsNullOrWhiteSpace(Model.Job.User.EmailAddress)) { @@ -1674,21 +1679,21 @@ WriteLiteral(" title=\"Email Address\""); WriteLiteral(">Email: (Model.Job.User.EmailAddress + #line 469 "..\..\Views\Job\JobParts\_Subject.cshtml" + , Tuple.Create(Tuple.Create("", 32911), Tuple.Create(Model.Job.User.EmailAddress #line default #line hidden -, 32996), false) +, 32911), false) ); WriteLiteral(">"); - #line 468 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 469 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Model.Job.User.EmailAddress); @@ -1697,7 +1702,7 @@ WriteLiteral(">"); WriteLiteral(""); - #line 468 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 469 "..\..\Views\Job\JobParts\_Subject.cshtml" } } @@ -1707,7 +1712,7 @@ WriteLiteral(""); WriteLiteral(" "); - #line 470 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 471 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Authorization.Has(Claims.User.ShowFlagAssignments)) { @@ -1721,13 +1726,13 @@ WriteLiteral(" id=\"Job_Show_User_Flags\""); WriteLiteral(">\r\n"); - #line 473 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 474 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 473 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 474 "..\..\Views\Job\JobParts\_Subject.cshtml" foreach (var flag in Model.Job.User.UserFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, UserFlagService.GetUserFlag(f.UserFlagId)))) { @@ -1736,26 +1741,26 @@ WriteLiteral(">\r\n"); #line hidden WriteLiteral(" (flag.Item2.Icon + #line 476 "..\..\Views\Job\JobParts\_Subject.cshtml" +, Tuple.Create(Tuple.Create("", 33443), Tuple.Create(flag.Item2.Icon #line default #line hidden -, 33528), false) -, Tuple.Create(Tuple.Create(" ", 33546), Tuple.Create("fa-fw", 33547), true) -, Tuple.Create(Tuple.Create(" ", 33552), Tuple.Create("d-", 33553), true) +, 33443), false) +, Tuple.Create(Tuple.Create(" ", 33461), Tuple.Create("fa-fw", 33462), true) +, Tuple.Create(Tuple.Create(" ", 33467), Tuple.Create("d-", 33468), true) - #line 475 "..\..\Views\Job\JobParts\_Subject.cshtml" -, Tuple.Create(Tuple.Create("", 33555), Tuple.Create(flag.Item2.IconColour + #line 476 "..\..\Views\Job\JobParts\_Subject.cshtml" +, Tuple.Create(Tuple.Create("", 33470), Tuple.Create(flag.Item2.IconColour #line default #line hidden -, 33555), false) +, 33470), false) ); WriteLiteral(">"); - #line 475 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 476 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(flag.Item2.Name); @@ -1778,7 +1783,7 @@ WriteLiteral(">"); WriteLiteral(""); - #line 475 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 476 "..\..\Views\Job\JobParts\_Subject.cshtml" if (flag.Item1.Comments != null) { @@ -1791,7 +1796,7 @@ WriteLiteral(" class=\"comments\""); WriteLiteral(">"); - #line 476 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 477 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(flag.Item1.Comments.ToHtmlComment()); @@ -1800,7 +1805,7 @@ WriteLiteral(">"); WriteLiteral(""); - #line 476 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 477 "..\..\Views\Job\JobParts\_Subject.cshtml" } #line default @@ -1812,7 +1817,7 @@ WriteLiteral(" class=\"added\""); WriteLiteral(">"); - #line 476 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 477 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUserId)); @@ -1821,7 +1826,7 @@ WriteLiteral(">"); WriteLiteral("\r\n"); - #line 477 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 478 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -1857,7 +1862,7 @@ WriteLiteral(">\r\n $(function () {\r\n " \r\n"); - #line 509 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 510 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -1866,7 +1871,7 @@ WriteLiteral(">\r\n $(function () {\r\n WriteLiteral(" "); - #line 510 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 511 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.WaitingForUserAction.HasValue) { @@ -1885,7 +1890,7 @@ WriteLiteral(">\r\n

    Awaiting Action

    \r\n WriteLiteral(" data-livestamp=\""); - #line 514 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 515 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Model.Job.WaitingForUserAction.ToUnixEpoc()); @@ -1896,7 +1901,7 @@ WriteLiteral("\""); WriteLiteral(">"); - #line 514 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 515 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Model.Job.WaitingForUserAction.ToFullDateTime()); @@ -1905,7 +1910,7 @@ WriteLiteral(">"); WriteLiteral("\r\n \r\n"); - #line 516 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 517 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -1914,7 +1919,7 @@ WriteLiteral("\r\n \r\n"); WriteLiteral(" \r\n \r\n"); - #line 519 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 520 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -1931,13 +1936,13 @@ WriteLiteral(" id=\"Job_Show_Job_Actions\""); WriteLiteral(">\r\n"); - #line 523 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 524 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 523 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 524 "..\..\Views\Job\JobParts\_Subject.cshtml" List CanCloseForcedReasons; if (Model.Job.CanCloseForced(out CanCloseForcedReasons)) @@ -1947,14 +1952,14 @@ WriteLiteral(">\r\n"); #line default #line hidden - #line 527 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 528 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Forcibly Close", MVC.API.Job.Close(Model.Job.Id, true), "Job_Show_Job_Actions_ForceClose_Button")); #line default #line hidden - #line 527 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 528 "..\..\Views\Job\JobParts\_Subject.cshtml" @@ -1984,13 +1989,13 @@ WriteLiteral(">Are you sure?\r\n

    \r\n"); - #line 534 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 535 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 534 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 535 "..\..\Views\Job\JobParts\_Subject.cshtml" foreach (var reason in CanCloseForcedReasons) { @@ -2000,7 +2005,7 @@ WriteLiteral(">Are you sure?\r\n

    "); - #line 536 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 537 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(reason); @@ -2009,7 +2014,7 @@ WriteLiteral("
  • "); WriteLiteral("
  • \r\n"); - #line 537 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 538 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2018,13 +2023,13 @@ WriteLiteral("\r\n"); WriteLiteral(" \r\n \r\n"); - #line 540 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 541 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 540 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 541 "..\..\Views\Job\JobParts\_Subject.cshtml" using (Html.BeginForm(MVC.API.Job.ForceClose(Model.Job.Id, null, true))) { @@ -2042,7 +2047,7 @@ WriteLiteral(" class=\"block\""); WriteLiteral(">\r\n

    \r\n"); - #line 546 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 547 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2075,7 +2080,7 @@ WriteLiteral(">\r\n $(function () {\r\n " });\r\n });\r\n \r\n"); - #line 579 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 580 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2084,13 +2089,13 @@ WriteLiteral(">\r\n $(function () {\r\n WriteLiteral("\r\n\r\n"); - #line 582 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 583 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 582 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 583 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.CanCloseNormally()) { @@ -2098,14 +2103,14 @@ WriteLiteral("\r\n\r\n"); #line default #line hidden - #line 584 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 585 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Close", MVC.API.Job.Close(Model.Job.Id, true), "Job_Show_Job_Actions_Close_Button")); #line default #line hidden - #line 584 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 585 "..\..\Views\Job\JobParts\_Subject.cshtml" @@ -2151,7 +2156,7 @@ WriteLiteral(">\r\n $(function () {\r\n " });\r\n });\r\n \r\n"); - #line 621 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 622 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2160,7 +2165,7 @@ WriteLiteral(">\r\n $(function () {\r\n WriteLiteral(" "); - #line 622 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 623 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.CanReopen()) { @@ -2168,14 +2173,14 @@ WriteLiteral(" "); #line default #line hidden - #line 624 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 625 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Reopen Job", MVC.API.Job.Reopen(Model.Job.Id, true), "Job_Show_Job_Actions_Reopen_Button")); #line default #line hidden - #line 624 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 625 "..\..\Views\Job\JobParts\_Subject.cshtml" @@ -2222,7 +2227,7 @@ WriteLiteral(">\r\n $(function () {\r\n " });\r\n \r\n"); - #line 662 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 663 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2231,7 +2236,7 @@ WriteLiteral(">\r\n $(function () {\r\n WriteLiteral(" "); - #line 663 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 664 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.CanDelete()) { @@ -2239,14 +2244,14 @@ WriteLiteral(" "); #line default #line hidden - #line 665 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 666 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Delete", MVC.API.Job.Delete(Model.Job.Id, true), "Job_Show_Job_Actions_Delete_Button")); #line default #line hidden - #line 665 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 666 "..\..\Views\Job\JobParts\_Subject.cshtml" @@ -2294,7 +2299,7 @@ WriteLiteral(">\r\n $(function () {\r\n " \r\n"); - #line 703 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 704 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2303,7 +2308,7 @@ WriteLiteral(">\r\n $(function () {\r\n WriteLiteral(" "); - #line 704 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 705 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.CanAddQueues() && Model.AvailableQueues != null && Model.AvailableQueues.Count > 0) { @@ -2317,14 +2322,14 @@ WriteLiteral(" "); #line default #line hidden - #line 712 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 713 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Add to Queue", MVC.API.JobQueueJob.AddJob(), "Job_Show_Job_Actions_AddQueue_Button")); #line default #line hidden - #line 712 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 713 "..\..\Views\Job\JobParts\_Subject.cshtml" @@ -2341,13 +2346,13 @@ WriteLiteral(" title=\"Add Job to Queue\""); WriteLiteral(">\r\n"); - #line 714 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 715 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 714 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 715 "..\..\Views\Job\JobParts\_Subject.cshtml" using (Html.BeginForm(MVC.API.JobQueueJob.AddJob())) { @@ -2372,14 +2377,14 @@ WriteLiteral(" type=\"hidden\""); WriteLiteral(" name=\"JobId\""); -WriteAttribute("value", Tuple.Create(" value=\"", 47072), Tuple.Create("\"", 47093) +WriteAttribute("value", Tuple.Create(" value=\"", 46987), Tuple.Create("\"", 47008) - #line 717 "..\..\Views\Job\JobParts\_Subject.cshtml" - , Tuple.Create(Tuple.Create("", 47080), Tuple.Create(Model.Job.Id + #line 718 "..\..\Views\Job\JobParts\_Subject.cshtml" + , Tuple.Create(Tuple.Create("", 46995), Tuple.Create(Model.Job.Id #line default #line hidden -, 47080), false) +, 46995), false) ); WriteLiteral(" />\r\n"); @@ -2391,13 +2396,13 @@ WriteLiteral(" class=\"queuePicker\""); WriteLiteral(">\r\n"); - #line 719 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 720 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 719 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 720 "..\..\Views\Job\JobParts\_Subject.cshtml" foreach (var jobQueue in Model.AvailableQueues.OrderBy(jq => jq.Name)) { @@ -2411,7 +2416,7 @@ WriteLiteral(" class=\"queue\""); WriteLiteral(" data-queueid=\""); - #line 721 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 722 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(jobQueue.Id); @@ -2422,7 +2427,7 @@ WriteLiteral("\""); WriteLiteral(" data-queuesla=\""); - #line 721 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 722 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(jobQueue.DefaultSLAExpiry.HasValue ? jobQueue.DefaultSLAExpiry.Value.ToString() : null); @@ -2433,7 +2438,7 @@ WriteLiteral("\""); WriteLiteral(" data-queuepriority=\""); - #line 721 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 722 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(jobQueue.Priority.ToString()); @@ -2443,32 +2448,32 @@ WriteLiteral("\""); WriteLiteral(">\r\n (jobQueue.Icon + #line 723 "..\..\Views\Job\JobParts\_Subject.cshtml" +, Tuple.Create(Tuple.Create("", 47491), Tuple.Create(jobQueue.Icon #line default #line hidden -, 47576), false) -, Tuple.Create(Tuple.Create(" ", 47592), Tuple.Create("fa-fw", 47593), true) -, Tuple.Create(Tuple.Create(" ", 47598), Tuple.Create("fa-lg", 47599), true) -, Tuple.Create(Tuple.Create(" ", 47604), Tuple.Create("d-", 47605), true) +, 47491), false) +, Tuple.Create(Tuple.Create(" ", 47507), Tuple.Create("fa-fw", 47508), true) +, Tuple.Create(Tuple.Create(" ", 47513), Tuple.Create("fa-lg", 47514), true) +, Tuple.Create(Tuple.Create(" ", 47519), Tuple.Create("d-", 47520), true) - #line 722 "..\..\Views\Job\JobParts\_Subject.cshtml" - , Tuple.Create(Tuple.Create("", 47607), Tuple.Create(jobQueue.IconColour + #line 723 "..\..\Views\Job\JobParts\_Subject.cshtml" + , Tuple.Create(Tuple.Create("", 47522), Tuple.Create(jobQueue.IconColour #line default #line hidden -, 47607), false) +, 47522), false) ); WriteLiteral(">"); - #line 722 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 723 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(jobQueue.Name); @@ -2477,7 +2482,7 @@ WriteLiteral(">"); WriteLiteral("\r\n \r\n"); - #line 724 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 725 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2495,7 +2500,7 @@ WriteLiteral(">\r\n
    \r\n WriteLiteral(" "); - #line 729 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 730 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.DropDownList("Priority", priorityItems, new { id = "Job_Show_Job_Actions_AddQueue_Priority" })); @@ -2503,27 +2508,27 @@ WriteLiteral(" "); #line hidden WriteLiteral(" (priorityValue.ToLower() + #line 730 "..\..\Views\Job\JobParts\_Subject.cshtml" + , Tuple.Create(Tuple.Create("", 47963), Tuple.Create(priorityValue.ToLower() #line default #line hidden -, 48048), false) +, 47963), false) ); -WriteAttribute("title", Tuple.Create(" title=\"", 48075), Tuple.Create("\"", 48108) +WriteAttribute("title", Tuple.Create(" title=\"", 47990), Tuple.Create("\"", 48023) - #line 729 "..\..\Views\Job\JobParts\_Subject.cshtml" - , Tuple.Create(Tuple.Create("", 48083), Tuple.Create(priorityValue + #line 730 "..\..\Views\Job\JobParts\_Subject.cshtml" + , Tuple.Create(Tuple.Create("", 47998), Tuple.Create(priorityValue #line default #line hidden -, 48083), false) -, Tuple.Create(Tuple.Create(" ", 48099), Tuple.Create("Priority", 48100), true) +, 47998), false) +, Tuple.Create(Tuple.Create(" ", 48014), Tuple.Create("Priority", 48015), true) ); WriteLiteral(">\r\n
    \r\n
    \r\n " + @@ -2532,7 +2537,7 @@ WriteLiteral(">\r\n
    \r\n WriteLiteral(" "); - #line 733 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 734 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.DropDownList("SLAExpiresMinutes", slaOptions, new { id = "Job_Show_Job_Actions_AddQueue_SLAExpiresMinutes" })); @@ -2550,7 +2555,7 @@ WriteLiteral(">\r\n \r\n "\n"); - #line 740 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 741 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2613,7 +2618,7 @@ WriteLiteral(">\r\n $(function () {\r\n " });\r\n \r\n"); - #line 819 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 820 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2622,7 +2627,7 @@ WriteLiteral(">\r\n $(function () {\r\n WriteLiteral(" "); - #line 820 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 821 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.CanLogWarranty()) { @@ -2630,14 +2635,14 @@ WriteLiteral(" "); #line default #line hidden - #line 822 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 823 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Log Warranty", MVC.Job.LogWarranty(Model.Job.Id, null, null), "Job_Show_Job_Actions_LogWarranty_Button")); #line default #line hidden - #line 822 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 823 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2647,7 +2652,7 @@ WriteLiteral(" "); WriteLiteral(" "); - #line 824 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 825 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.CanWarrantyCompleted()) { @@ -2655,14 +2660,14 @@ WriteLiteral(" "); #line default #line hidden - #line 826 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 827 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Warranty Complete", MVC.API.Job.UpdateWarrantyExternalCompletedDate(Model.Job.Id, "Now", true), "Job_Show_Job_Actions_WarrantyComplete_Button", "alert")); #line default #line hidden - #line 826 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 827 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2672,7 +2677,7 @@ WriteLiteral(" "); WriteLiteral(" "); - #line 828 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 829 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.CanInsuranceClaimFormSent()) { @@ -2680,14 +2685,14 @@ WriteLiteral(" "); #line default #line hidden - #line 830 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 831 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Insurance Claim Sent", MVC.API.Job.UpdateInsuranceClaimFormSentDate(Model.Job.Id, "Now", true), "Job_Show_Job_Actions_InsuranceClaimSent_Button", "alert")); #line default #line hidden - #line 830 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 831 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2697,7 +2702,7 @@ WriteLiteral(" "); WriteLiteral(" "); - #line 832 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 833 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.CanLogRepair()) { @@ -2705,14 +2710,14 @@ WriteLiteral(" "); #line default #line hidden - #line 834 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 835 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Log Repair", MVC.Job.LogRepair(Model.Job.Id, null, null), "Job_Show_Job_Actions_LogRepair_Button")); #line default #line hidden - #line 834 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 835 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2722,7 +2727,7 @@ WriteLiteral(" "); WriteLiteral(" "); - #line 836 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 837 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.CanRepairComplete()) { @@ -2730,14 +2735,14 @@ WriteLiteral(" "); #line default #line hidden - #line 838 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 839 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Repairs Complete", MVC.API.Job.UpdateNonWarrantyRepairerCompletedDate(Model.Job.Id, "Now", true), "Job_Show_Job_Actions_RepairComplete_Button", "alert")); #line default #line hidden - #line 838 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 839 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2747,7 +2752,7 @@ WriteLiteral(" "); WriteLiteral(" "); - #line 840 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 841 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.CanConvertHWarToHNWar()) { @@ -2755,14 +2760,14 @@ WriteLiteral(" "); #line default #line hidden - #line 842 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 843 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Convert to Non-Warranty", MVC.API.Job.ConvertHWarToHNWar(Model.Job.Id, true), "Job_Show_Job_Actions_ConvertToHNWar_Button")); #line default #line hidden - #line 842 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 843 "..\..\Views\Job\JobParts\_Subject.cshtml" @@ -2810,7 +2815,7 @@ WriteLiteral(">\r\n $(function () {\r\n " \r\n });\r\n \r\n"); - #line 882 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 883 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2819,13 +2824,13 @@ WriteLiteral(">\r\n $(function () {\r\n WriteLiteral(" \r\n"); - #line 884 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 885 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 884 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 885 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.Device != null) { @@ -2839,13 +2844,13 @@ WriteLiteral(" id=\"Job_Show_Device_Actions\""); WriteLiteral(">\r\n"); - #line 887 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 888 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 887 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 888 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.CanDeviceHeld()) { @@ -2853,14 +2858,14 @@ WriteLiteral(">\r\n"); #line default #line hidden - #line 889 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 890 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Device Held", MVC.API.Job.DeviceHeld(Model.Job.Id, true), "Job_Show_Device_Actions_Held_Button")); #line default #line hidden - #line 889 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 890 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2870,7 +2875,7 @@ WriteLiteral(">\r\n"); WriteLiteral(" "); - #line 891 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 892 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.CanDeviceReadyForReturn()) { @@ -2878,14 +2883,14 @@ WriteLiteral(" "); #line default #line hidden - #line 893 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 894 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Device Ready For Return", MVC.API.Job.DeviceReadyForReturn(Model.Job.Id, true), "Job_Show_Device_Actions_DeviceReadyForReturn_Button", "alert")); #line default #line hidden - #line 893 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 894 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2895,7 +2900,7 @@ WriteLiteral(" "); WriteLiteral(" "); - #line 895 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 896 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.CanDeviceReturned()) { @@ -2903,14 +2908,14 @@ WriteLiteral(" "); #line default #line hidden - #line 897 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 898 "..\..\Views\Job\JobParts\_Subject.cshtml" Write(Html.ActionLinkSmallButton("Device Returned", MVC.API.Job.DeviceReturned(Model.Job.Id, true), "Job_Show_Device_Actions_DeviceReturned_Button", Model.Job.CanDeviceReadyForReturn() ? null : "alert")); #line default #line hidden - #line 897 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 898 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2920,7 +2925,7 @@ WriteLiteral(" "); WriteLiteral(" \r\n"); - #line 900 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 901 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -2929,7 +2934,7 @@ WriteLiteral(" \r\n"); WriteLiteral(" "); - #line 901 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 902 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.User != null) { @@ -2943,13 +2948,13 @@ WriteLiteral(" id=\"Job_Show_User_Actions\""); WriteLiteral(">\r\n\r\n\r\n"); - #line 906 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 907 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 906 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 907 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.CanWaitingForUserAction()) { @@ -2977,13 +2982,13 @@ WriteLiteral(" title=\"Waiting for User Action\""); WriteLiteral(">\r\n"); - #line 910 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 911 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 910 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 911 "..\..\Views\Job\JobParts\_Subject.cshtml" using (Html.BeginForm(MVC.API.Job.WaitingForUserAction(Model.Job.Id, null, true))) { @@ -3001,7 +3006,7 @@ WriteLiteral(" class=\"block\""); WriteLiteral(">\r\n

    \r\n"); - #line 916 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 917 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -3036,7 +3041,7 @@ WriteLiteral(">\r\n $(function () {\r\n " });\r\n \r\n"); - #line 949 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 950 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -3045,7 +3050,7 @@ WriteLiteral(">\r\n $(function () {\r\n WriteLiteral(" "); - #line 950 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 951 "..\..\Views\Job\JobParts\_Subject.cshtml" if (Model.Job.CanNotWaitingForUserAction()) { @@ -3073,13 +3078,13 @@ WriteLiteral(" title=\"Not Waiting for User Action\""); WriteLiteral(">\r\n"); - #line 954 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 955 "..\..\Views\Job\JobParts\_Subject.cshtml" #line default #line hidden - #line 954 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 955 "..\..\Views\Job\JobParts\_Subject.cshtml" using (Html.BeginForm(MVC.API.Job.NotWaitingForUserAction(Model.Job.Id, null, true))) { @@ -3097,7 +3102,7 @@ WriteLiteral(" class=\"block\""); WriteLiteral(">\r\n

    \r\n"); - #line 960 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 961 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -3133,7 +3138,7 @@ WriteLiteral(">\r\n $(function () {\r\n " });\r\n \r\n"); - #line 994 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 995 "..\..\Views\Job\JobParts\_Subject.cshtml" } @@ -3142,7 +3147,7 @@ WriteLiteral(">\r\n $(function () {\r\n WriteLiteral("\r\n \r\n"); - #line 997 "..\..\Views\Job\JobParts\_Subject.cshtml" + #line 998 "..\..\Views\Job\JobParts\_Subject.cshtml" } diff --git a/Disco.Web/Views/Shared/_Layout.cshtml b/Disco.Web/Views/Shared/_Layout.cshtml index 19f844bc..2d41b8f5 100644 --- a/Disco.Web/Views/Shared/_Layout.cshtml +++ b/Disco.Web/Views/Shared/_Layout.cshtml @@ -138,7 +138,7 @@ @RenderBody()
    - Disco v@(Disco.Web.DiscoApplication.Version) @@ @(Disco.Web.DiscoApplication.OrganisationName) | discoict.com.au | @Html.ActionLink("Credits", MVC.Public.Public.Credits()) | @Html.ActionLink("Licence", MVC.Public.Public.Licence())
    diff --git a/Disco.Web/Views/Shared/_Layout.generated.cs b/Disco.Web/Views/Shared/_Layout.generated.cs index 07a9b3d2..001e4786 100644 --- a/Disco.Web/Views/Shared/_Layout.generated.cs +++ b/Disco.Web/Views/Shared/_Layout.generated.cs @@ -27,7 +27,6 @@ namespace Disco.Web.Views.Shared using System.Web.UI; using System.Web.WebPages; using Disco; - using Disco.BI.Extensions; using Disco.Models.Repository; using Disco.Services; using Disco.Services.Authorization; @@ -956,11 +955,11 @@ WriteLiteral(" "); #line default #line hidden -WriteLiteral("\r\n \r\n