Compare commits
113 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 83e9b7a832 | |||
| a3a92245ae | |||
| 045fb0b65d | |||
| 304ffd7ee1 | |||
| 8b74dbabf5 | |||
| 7f8ed7e752 | |||
| 84a4ba281f | |||
| 34842012b7 | |||
| a819d2722a | |||
| ebf78dd08d | |||
| 6186237028 | |||
| 513397779d | |||
| 815216fd73 | |||
| 8254e7ec5a | |||
| 4c3a68da30 | |||
| b64ac3b16f | |||
| d040ab094c | |||
| a0e18ef963 | |||
| 830a9c8d05 | |||
| ea51ba1f88 | |||
| 5510d34885 | |||
| be25569245 | |||
| 7af6a2220c | |||
| 4cd57f4a90 | |||
| f6fae26bc7 | |||
| 7cad69598f | |||
| 4e69253852 | |||
| 825627e345 | |||
| e9042f7666 | |||
| 6a45348bdb | |||
| f3351af9e8 | |||
| a5e38406d1 | |||
| 3c759ac4d7 | |||
| f70261aa25 | |||
| 3fdb4f1053 | |||
| 53ca13c7f4 | |||
| 185c4682f0 | |||
| 39c3bf9fc7 | |||
| c87ee6a0e7 | |||
| 4a08c8c275 | |||
| fb6067afc3 | |||
| 6b2cd47610 | |||
| 392de396df | |||
| 3cf6d5475d | |||
| 74df073b29 | |||
| 09c2a24222 | |||
| 43fc622121 | |||
| b8ec44293f | |||
| 36100bfef5 | |||
| b77bdf16f5 | |||
| 5aede7153c | |||
| 4fc6c3ca9f | |||
| d86280ae3e | |||
| 2281313966 | |||
| 740e806ef0 | |||
| f35f9d3661 | |||
| 201acc1976 | |||
| a4f4b7d0b3 | |||
| 41dc002ef8 | |||
| e984221c95 | |||
| 3238a916a2 | |||
| db73cc1a12 | |||
| b841c6b2c0 | |||
| 69091e0785 | |||
| 3d5f71aba9 | |||
| da166e5cd2 | |||
| 74775e9e3d | |||
| 96c5860080 | |||
| 6ac87633ac | |||
| 0db43d9200 | |||
| a82e039140 | |||
| bfa3bf1e94 | |||
| 5be747afbc | |||
| ed7caf8b4a | |||
| 7027b33fe2 | |||
| 68256d7abd | |||
| 2ac3a9bdd3 | |||
| a6a65c54c7 | |||
| 7bdbeb6a82 | |||
| c4cc54d316 | |||
| 3ae657f2ba | |||
| 2e7b66ee5b | |||
| 6d54f3f972 | |||
| cd31ba4a6c | |||
| 9ea0273936 | |||
| 7748f15d76 | |||
| eea71e6eb0 | |||
| 3bc8b63700 | |||
| 6bacf6e3a5 | |||
| cc4682875b | |||
| bfcbcf9da2 | |||
| ad28729a85 | |||
| 3f63281dc4 | |||
| bdb3e1e6b4 | |||
| 10394c4e39 | |||
| 2ddf4b7bd9 | |||
| 35391ad1a1 | |||
| ab553a05cb | |||
| 20263905f9 | |||
| f1ee2937cd | |||
| ec118a3395 | |||
| 551b1d3a41 | |||
| 214ecf6212 | |||
| fad8eae9f4 | |||
| 2dd3f5f9ab | |||
| 8ace60f10d | |||
| 136c371b01 | |||
| a5c051916e | |||
| 4f4dbabf8b | |||
| e4c86f1cc1 | |||
| eabd9671f0 | |||
| 9b34abfa29 | |||
| d1007266c9 |
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Microsoft.AspNet.SignalR.Utils" version="2.1.0" />
|
||||||
|
</packages>
|
||||||
@@ -15,10 +15,10 @@ namespace Disco.BI.AttachmentBI
|
|||||||
if (Source != null)
|
if (Source != null)
|
||||||
{
|
{
|
||||||
// GDI+ (jpg, png, gif, bmp)
|
// GDI+ (jpg, png, gif, bmp)
|
||||||
if (SourceMimeType.Equals("image/jpeg", StringComparison.InvariantCultureIgnoreCase) || SourceMimeType.Contains("jpg") ||
|
if (SourceMimeType.Equals("image/jpeg", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("jpg") ||
|
||||||
SourceMimeType.Equals("image/png", StringComparison.InvariantCultureIgnoreCase) || SourceMimeType.Contains("png") ||
|
SourceMimeType.Equals("image/png", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("png") ||
|
||||||
SourceMimeType.Equals("image/gif", StringComparison.InvariantCultureIgnoreCase) || SourceMimeType.Contains("gif") ||
|
SourceMimeType.Equals("image/gif", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("gif") ||
|
||||||
SourceMimeType.Equals("image/bmp", StringComparison.InvariantCultureIgnoreCase) || SourceMimeType.Contains("bmp"))
|
SourceMimeType.Equals("image/bmp", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("bmp"))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -42,7 +42,7 @@ namespace Disco.BI.AttachmentBI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PDF
|
// PDF
|
||||||
if (SourceMimeType.Equals("application/pdf", StringComparison.InvariantCultureIgnoreCase) || SourceMimeType.Contains("pdf"))
|
if (SourceMimeType.Equals("application/pdf", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("pdf"))
|
||||||
{
|
{
|
||||||
PdfReader pdfReader = new PdfReader(Source);
|
PdfReader pdfReader = new PdfReader(Source);
|
||||||
try
|
try
|
||||||
|
|||||||
+122
-61
@@ -1,13 +1,13 @@
|
|||||||
using Disco.BI.Extensions;
|
using Disco.BI.Extensions;
|
||||||
using Disco.BI.Interop.ActiveDirectory;
|
|
||||||
using Disco.Data.Repository;
|
using Disco.Data.Repository;
|
||||||
using Disco.Models.ClientServices;
|
using Disco.Models.ClientServices;
|
||||||
using Disco.Models.Interop.ActiveDirectory;
|
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
using Disco.Services.Users;
|
using Disco.Services.Users;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.DirectoryServices.ActiveDirectory;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Tamir.SharpSsh;
|
using Tamir.SharpSsh;
|
||||||
@@ -242,7 +242,7 @@ namespace Disco.BI.DeviceBI
|
|||||||
EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.DeviceSerialNumber);
|
EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.DeviceSerialNumber);
|
||||||
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
|
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
|
||||||
|
|
||||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModel.Trim());
|
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
|
||||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||||
if (deviceModelResult.Item2)
|
if (deviceModelResult.Item2)
|
||||||
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
||||||
@@ -252,7 +252,7 @@ namespace Disco.BI.DeviceBI
|
|||||||
RepoDevice = new Device
|
RepoDevice = new Device
|
||||||
{
|
{
|
||||||
SerialNumber = Request.DeviceSerialNumber,
|
SerialNumber = Request.DeviceSerialNumber,
|
||||||
ComputerName = Request.DeviceComputerName,
|
DeviceDomainId = Request.DeviceComputerName,
|
||||||
DeviceProfile = deviceProfile,
|
DeviceProfile = deviceProfile,
|
||||||
DeviceModel = deviceModel,
|
DeviceModel = deviceModel,
|
||||||
AllowUnauthenticatedEnrol = false,
|
AllowUnauthenticatedEnrol = false,
|
||||||
@@ -267,7 +267,7 @@ namespace Disco.BI.DeviceBI
|
|||||||
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
|
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
|
||||||
if (!RepoDevice.DeviceModelId.HasValue || RepoDevice.DeviceModelId.Value == 1)
|
if (!RepoDevice.DeviceModelId.HasValue || RepoDevice.DeviceModelId.Value == 1)
|
||||||
{
|
{
|
||||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModel.Trim());
|
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
|
||||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||||
if (deviceModelResult.Item2)
|
if (deviceModelResult.Item2)
|
||||||
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
||||||
@@ -280,7 +280,7 @@ namespace Disco.BI.DeviceBI
|
|||||||
{
|
{
|
||||||
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, RepoDevice.DeviceModelId);
|
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, RepoDevice.DeviceModelId);
|
||||||
}
|
}
|
||||||
RepoDevice.ComputerName = Request.DeviceComputerName;
|
RepoDevice.DeviceDomainId = Request.DeviceComputerName;
|
||||||
if (!RepoDevice.EnrolledDate.HasValue)
|
if (!RepoDevice.EnrolledDate.HasValue)
|
||||||
{
|
{
|
||||||
RepoDevice.EnrolledDate = DateTime.Now;
|
RepoDevice.EnrolledDate = DateTime.Now;
|
||||||
@@ -294,14 +294,14 @@ namespace Disco.BI.DeviceBI
|
|||||||
//if (RepoDeviceProfileContext.DistributionType == DeviceProfileConfiguration.DeviceProfileDistributionTypes.OneToOne && RepoDevice.AssignedUser != null)
|
//if (RepoDeviceProfileContext.DistributionType == DeviceProfileConfiguration.DeviceProfileDistributionTypes.OneToOne && RepoDevice.AssignedUser != null)
|
||||||
if (RepoDevice.DeviceProfile.DistributionType == DeviceProfile.DistributionTypes.OneToOne && RepoDevice.AssignedUser != null)
|
if (RepoDevice.DeviceProfile.DistributionType == DeviceProfile.DistributionTypes.OneToOne && RepoDevice.AssignedUser != null)
|
||||||
{
|
{
|
||||||
ActiveDirectoryUserAccount AssignedUserInfo = ActiveDirectory.GetUserAccount(RepoDevice.AssignedUser.Id);
|
ADUserAccount AssignedUserInfo = ActiveDirectory.RetrieveADUserAccount(RepoDevice.AssignedUser.UserId);
|
||||||
EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.SamAccountName, AssignedUserInfo.Domain, AssignedUserInfo.SecurityIdentifier);
|
EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.SamAccountName, AssignedUserInfo.Domain.NetBiosName, AssignedUserInfo.SecurityIdentifier.ToString());
|
||||||
response.DeviceAssignedUserUsername = AssignedUserInfo.SamAccountName;
|
response.DeviceAssignedUserUsername = AssignedUserInfo.SamAccountName;
|
||||||
response.DeviceAssignedUserDomain = AssignedUserInfo.Domain;
|
response.DeviceAssignedUserDomain = AssignedUserInfo.Domain.NetBiosName;
|
||||||
response.DeviceAssignedUserName = AssignedUserInfo.DisplayName;
|
response.DeviceAssignedUserName = AssignedUserInfo.DisplayName;
|
||||||
response.DeviceAssignedUserSID = AssignedUserInfo.SecurityIdentifier;
|
response.DeviceAssignedUserSID = AssignedUserInfo.SecurityIdentifier.ToString();
|
||||||
}
|
}
|
||||||
response.DeviceComputerName = RepoDevice.ComputerName;
|
response.DeviceComputerName = RepoDevice.DeviceDomainId;
|
||||||
EnrolmentLog.LogSessionProgress(sessionId, 100, "Completed Successfully");
|
EnrolmentLog.LogSessionProgress(sessionId, 100, "Completed Successfully");
|
||||||
}
|
}
|
||||||
catch (EnrolSafeException ex)
|
catch (EnrolSafeException ex)
|
||||||
@@ -323,14 +323,27 @@ namespace Disco.BI.DeviceBI
|
|||||||
}
|
}
|
||||||
public static EnrolResponse Enrol(DiscoDataContext Database, string Username, Models.ClientServices.Enrol Request)
|
public static EnrolResponse Enrol(DiscoDataContext Database, string Username, Models.ClientServices.Enrol Request)
|
||||||
{
|
{
|
||||||
ActiveDirectoryMachineAccount MachineInfo = null;
|
ADMachineAccount adMachineAccount = null;
|
||||||
|
|
||||||
EnrolResponse response = new EnrolResponse();
|
EnrolResponse response = new EnrolResponse();
|
||||||
|
|
||||||
AuthorizationToken authenticatedToken = null;
|
AuthorizationToken authenticatedToken = null;
|
||||||
bool isAuthenticated = false;
|
bool isAuthenticated = false;
|
||||||
|
|
||||||
|
ADDomain domain = null;
|
||||||
|
Lazy<ADDomainController> domainController = new Lazy<ADDomainController>(() =>
|
||||||
|
{
|
||||||
|
if (domain == null)
|
||||||
|
throw new InvalidOperationException("The [domain] variable must be initialized first");
|
||||||
|
return domain.GetAvailableDomainController(RequireWritable: true);
|
||||||
|
});
|
||||||
|
|
||||||
string sessionId = System.Guid.NewGuid().ToString("B");
|
string sessionId = System.Guid.NewGuid().ToString("B");
|
||||||
response.SessionId = sessionId;
|
response.SessionId = sessionId;
|
||||||
|
|
||||||
EnrolmentLog.LogSessionStarting(sessionId, Request.DeviceSerialNumber, EnrolmentTypes.Normal);
|
EnrolmentLog.LogSessionStarting(sessionId, Request.DeviceSerialNumber, EnrolmentTypes.Normal);
|
||||||
EnrolmentLog.LogSessionDeviceInfo(sessionId, Request);
|
EnrolmentLog.LogSessionDeviceInfo(sessionId, Request);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
EnrolmentLog.LogSessionProgress(sessionId, 10, "Loading User Data");
|
EnrolmentLog.LogSessionProgress(sessionId, 10, "Loading User Data");
|
||||||
@@ -348,9 +361,13 @@ namespace Disco.BI.DeviceBI
|
|||||||
if (!authenticatedToken.Has(Claims.Device.Actions.EnrolDevices))
|
if (!authenticatedToken.Has(Claims.Device.Actions.EnrolDevices))
|
||||||
{
|
{
|
||||||
if (!authenticatedToken.Has(Claims.ComputerAccount))
|
if (!authenticatedToken.Has(Claims.ComputerAccount))
|
||||||
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.Id));
|
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.UserId));
|
||||||
if (!authenticatedToken.User.Id.Equals(string.Format("{0}$", Request.DeviceComputerName), System.StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.Id));
|
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
|
else
|
||||||
@@ -380,10 +397,16 @@ namespace Disco.BI.DeviceBI
|
|||||||
System.Guid? uuidGuid = null;
|
System.Guid? uuidGuid = null;
|
||||||
System.Guid? macAddressGuid = null;
|
System.Guid? macAddressGuid = null;
|
||||||
if (!string.IsNullOrEmpty(Request.DeviceUUID))
|
if (!string.IsNullOrEmpty(Request.DeviceUUID))
|
||||||
uuidGuid = ActiveDirectoryMachineAccountExtensions.NetbootGUIDFromUUID(Request.DeviceUUID);
|
uuidGuid = ADMachineAccount.NetbootGUIDFromUUID(Request.DeviceUUID);
|
||||||
if (!string.IsNullOrEmpty(Request.DeviceLanMacAddress))
|
if (!string.IsNullOrEmpty(Request.DeviceLanMacAddress))
|
||||||
macAddressGuid = ActiveDirectoryMachineAccountExtensions.NetbootGUIDFromMACAddress(Request.DeviceLanMacAddress);
|
macAddressGuid = ADMachineAccount.NetbootGUIDFromMACAddress(Request.DeviceLanMacAddress);
|
||||||
MachineInfo = ActiveDirectory.GetMachineAccount(Request.DeviceComputerName, uuidGuid, macAddressGuid);
|
|
||||||
|
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, macAddressGuid);
|
||||||
}
|
}
|
||||||
if (RepoDevice == null)
|
if (RepoDevice == null)
|
||||||
{
|
{
|
||||||
@@ -392,17 +415,20 @@ namespace Disco.BI.DeviceBI
|
|||||||
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
|
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
|
||||||
|
|
||||||
|
|
||||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModel.Trim());
|
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
|
||||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||||
if (deviceModelResult.Item2)
|
if (deviceModelResult.Item2)
|
||||||
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
||||||
else
|
else
|
||||||
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id);
|
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id);
|
||||||
|
|
||||||
|
if (domain == null)
|
||||||
|
domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName);
|
||||||
|
|
||||||
RepoDevice = new Device
|
RepoDevice = new Device
|
||||||
{
|
{
|
||||||
SerialNumber = Request.DeviceSerialNumber,
|
SerialNumber = Request.DeviceSerialNumber,
|
||||||
ComputerName = Request.DeviceComputerName,
|
DeviceDomainId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.DeviceComputerName),
|
||||||
DeviceProfile = deviceProfile,
|
DeviceProfile = deviceProfile,
|
||||||
DeviceModel = deviceModel,
|
DeviceModel = deviceModel,
|
||||||
AllowUnauthenticatedEnrol = false,
|
AllowUnauthenticatedEnrol = false,
|
||||||
@@ -423,7 +449,7 @@ namespace Disco.BI.DeviceBI
|
|||||||
EnrolmentLog.LogSessionProgress(sessionId, 30, "Existing Device, Updating Disco Instance");
|
EnrolmentLog.LogSessionProgress(sessionId, 30, "Existing Device, Updating Disco Instance");
|
||||||
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
|
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
|
||||||
|
|
||||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModel.Trim());
|
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
|
||||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||||
if (deviceModelResult.Item2)
|
if (deviceModelResult.Item2)
|
||||||
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
||||||
@@ -442,88 +468,123 @@ namespace Disco.BI.DeviceBI
|
|||||||
RepoDevice.LastEnrolDate = DateTime.Now;
|
RepoDevice.LastEnrolDate = DateTime.Now;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MachineInfo == null)
|
if (adMachineAccount == null)
|
||||||
{
|
{
|
||||||
if (isAuthenticated || RepoDevice.AllowUnauthenticatedEnrol)
|
if (isAuthenticated || RepoDevice.AllowUnauthenticatedEnrol)
|
||||||
{
|
{
|
||||||
if (RepoDevice.DeviceProfile.ProvisionADAccount)
|
if (RepoDevice.DeviceProfile.ProvisionADAccount)
|
||||||
{
|
{
|
||||||
EnrolmentLog.LogSessionProgress(sessionId, 50, "Provisioning an Active Directory Computer Account");
|
EnrolmentLog.LogSessionProgress(sessionId, 50, "Provisioning an Active Directory Computer Account");
|
||||||
if (string.IsNullOrEmpty(RepoDevice.ComputerName) || RepoDevice.DeviceProfile.EnforceComputerNameConvention)
|
|
||||||
RepoDevice.ComputerName = RepoDevice.ComputerNameRender(Database);
|
if (string.IsNullOrWhiteSpace(RepoDevice.DeviceProfile.OrganisationalUnit))
|
||||||
EnrolmentLog.LogSessionTaskProvisioningADAccount(sessionId, RepoDevice.SerialNumber, RepoDevice.ComputerName);
|
throw new InvalidOperationException("No Organisational Unit has been set in the device profile");
|
||||||
MachineInfo = ActiveDirectory.GetMachineAccount(RepoDevice.ComputerName);
|
if (domain == null)
|
||||||
response.OfflineDomainJoin = ActiveDirectory.OfflineDomainJoinProvision(ref MachineInfo, RepoDevice.ComputerName, RepoDevice.DeviceProfile.OrganisationalUnit, sessionId);
|
domain = ActiveDirectory.Context.GetDomainFromDistinguishedName(RepoDevice.DeviceProfile.OrganisationalUnit);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(RepoDevice.DeviceDomainId) || RepoDevice.DeviceProfile.EnforceComputerNameConvention)
|
||||||
|
RepoDevice.DeviceDomainId = RepoDevice.ComputerNameRender(Database, domain);
|
||||||
|
|
||||||
|
string offlineProvisionDiagnosicInfo;
|
||||||
|
EnrolmentLog.LogSessionTaskProvisioningADAccount(sessionId, RepoDevice.SerialNumber, RepoDevice.DeviceDomainId);
|
||||||
|
adMachineAccount = domainController.Value.RetrieveADMachineAccount(RepoDevice.DeviceDomainId);
|
||||||
|
|
||||||
|
response.OfflineDomainJoin = domainController.Value.OfflineDomainJoinProvision(RepoDevice.DeviceDomainId, RepoDevice.DeviceProfile.OrganisationalUnit, ref adMachineAccount, out offlineProvisionDiagnosicInfo);
|
||||||
|
|
||||||
|
EnrolmentLog.LogSessionDiagnosticInformation(sessionId, offlineProvisionDiagnosicInfo);
|
||||||
|
|
||||||
response.RequireReboot = true;
|
response.RequireReboot = true;
|
||||||
}
|
}
|
||||||
if (MachineInfo != null)
|
if (adMachineAccount != null)
|
||||||
{
|
{
|
||||||
response.DeviceComputerName = MachineInfo.Name;
|
response.DeviceComputerName = adMachineAccount.Name;
|
||||||
response.DeviceDomainName = MachineInfo.Domain;
|
response.DeviceDomainName = adMachineAccount.Domain.NetBiosName;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
response.DeviceComputerName = RepoDevice.ComputerName;
|
string accountUsername;
|
||||||
response.DeviceDomainName = RepoDevice.ComputerName;
|
ADDomain accountDomain;
|
||||||
|
ActiveDirectory.ParseDomainAccountId(RepoDevice.DeviceDomainId, out accountUsername, out accountDomain);
|
||||||
|
|
||||||
|
response.DeviceDomainName = accountDomain == null ? null : accountDomain.NetBiosName;
|
||||||
|
response.DeviceComputerName = accountUsername;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RepoDevice.ComputerName = Request.DeviceComputerName;
|
|
||||||
response.DeviceComputerName = Request.DeviceComputerName;
|
response.DeviceComputerName = Request.DeviceComputerName;
|
||||||
response.DeviceDomainName = RepoDevice.ComputerName;
|
response.DeviceDomainName = Request.DeviceDNSDomainName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RepoDevice.ComputerName = MachineInfo.Name;
|
RepoDevice.DeviceDomainId = adMachineAccount.Id.Trim('$');
|
||||||
response.DeviceComputerName = MachineInfo.Name;
|
response.DeviceComputerName = adMachineAccount.Name;
|
||||||
response.DeviceDomainName = MachineInfo.Domain;
|
response.DeviceDomainName = adMachineAccount.Domain.NetBiosName;
|
||||||
|
|
||||||
// Enforce Computer Name Convention
|
// Enforce Computer Name Convention
|
||||||
if (!MachineInfo.IsCriticalSystemObject && RepoDevice.DeviceProfile.EnforceComputerNameConvention)
|
if (!adMachineAccount.IsCriticalSystemObject && RepoDevice.DeviceProfile.EnforceComputerNameConvention)
|
||||||
{
|
{
|
||||||
var calculatedComputerName = RepoDevice.ComputerNameRender(Database);
|
if (string.IsNullOrWhiteSpace(RepoDevice.DeviceProfile.OrganisationalUnit))
|
||||||
if (!Request.DeviceComputerName.Equals(calculatedComputerName, StringComparison.InvariantCultureIgnoreCase))
|
throw new InvalidOperationException("No Organisational Unit has been set in the device profile");
|
||||||
|
if (domain == null)
|
||||||
|
domain = ActiveDirectory.Context.GetDomainFromDistinguishedName(RepoDevice.DeviceProfile.OrganisationalUnit);
|
||||||
|
|
||||||
|
var calculatedComputerName = RepoDevice.ComputerNameRender(Database, domain);
|
||||||
|
string calculatedAccountUsername;
|
||||||
|
ActiveDirectory.ParseDomainAccountId(calculatedComputerName, out calculatedAccountUsername);
|
||||||
|
|
||||||
|
if (!Request.DeviceComputerName.Equals(calculatedAccountUsername, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
EnrolmentLog.LogSessionProgress(sessionId, 50, string.Format("Renaming Device: {0} -> {1}", Request.DeviceComputerName, calculatedComputerName));
|
EnrolmentLog.LogSessionProgress(sessionId, 50, string.Format("Renaming Device: {0} -> {1}", Request.DeviceComputerName, calculatedComputerName));
|
||||||
EnrolmentLog.LogSessionTaskRenamingDevice(sessionId, Request.DeviceComputerName, calculatedComputerName);
|
EnrolmentLog.LogSessionTaskRenamingDevice(sessionId, Request.DeviceComputerName, calculatedComputerName);
|
||||||
|
|
||||||
RepoDevice.ComputerName = calculatedComputerName;
|
RepoDevice.DeviceDomainId = calculatedComputerName;
|
||||||
response.DeviceComputerName = calculatedComputerName;
|
response.DeviceDomainName = domain.NetBiosName;
|
||||||
|
response.DeviceComputerName = calculatedAccountUsername;
|
||||||
|
|
||||||
// Create New Account
|
// Create New Account
|
||||||
response.OfflineDomainJoin = ActiveDirectory.OfflineDomainJoinProvision(ref MachineInfo, RepoDevice.ComputerName, RepoDevice.DeviceProfile.OrganisationalUnit, sessionId);
|
string offlineProvisionDiagnosicInfo;
|
||||||
|
|
||||||
|
response.OfflineDomainJoin = domainController.Value.OfflineDomainJoinProvision(RepoDevice.DeviceDomainId, RepoDevice.DeviceProfile.OrganisationalUnit, ref adMachineAccount, out offlineProvisionDiagnosicInfo);
|
||||||
|
|
||||||
|
EnrolmentLog.LogSessionDiagnosticInformation(sessionId, offlineProvisionDiagnosicInfo);
|
||||||
|
|
||||||
response.RequireReboot = true;
|
response.RequireReboot = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enforce Organisation Unit
|
// Enforce Organisational Unit
|
||||||
if (!MachineInfo.IsCriticalSystemObject && response.OfflineDomainJoin == null && RepoDevice.DeviceProfile.EnforceOrganisationalUnit)
|
if (!adMachineAccount.IsCriticalSystemObject && response.OfflineDomainJoin == null && RepoDevice.DeviceProfile.EnforceOrganisationalUnit)
|
||||||
{
|
{
|
||||||
var parentDistinguishedName = MachineInfo.ParentDistinguishedName();
|
var parentDistinguishedName = adMachineAccount.ParentDistinguishedName;
|
||||||
|
if (string.IsNullOrWhiteSpace(RepoDevice.DeviceProfile.OrganisationalUnit))
|
||||||
|
throw new InvalidOperationException(string.Format("The Organisational Unit for the Device Profile '{0}' [{1}] is not set.", RepoDevice.DeviceProfile.Name, RepoDevice.DeviceProfile.Id));
|
||||||
|
|
||||||
if ((RepoDevice.DeviceProfile.OrganisationalUnit == null && parentDistinguishedName != null
|
if (!parentDistinguishedName.Equals(RepoDevice.DeviceProfile.OrganisationalUnit, StringComparison.OrdinalIgnoreCase)) // Custom OU
|
||||||
&& parentDistinguishedName.Equals("CN=Computers", StringComparison.InvariantCultureIgnoreCase)) // Null (Default) OU
|
|
||||||
|| !parentDistinguishedName.Equals(RepoDevice.DeviceProfile.OrganisationalUnit, StringComparison.InvariantCultureIgnoreCase)) // Custom OU
|
|
||||||
{
|
{
|
||||||
string newOU = RepoDevice.DeviceProfile.OrganisationalUnit ?? "CN=Computers";
|
var proposedDomain = ActiveDirectory.Context.GetDomainFromDistinguishedName(RepoDevice.DeviceProfile.OrganisationalUnit);
|
||||||
|
var currentDomain = ActiveDirectory.Context.GetDomainFromDistinguishedName(parentDistinguishedName);
|
||||||
|
if (currentDomain != proposedDomain)
|
||||||
|
throw new NotSupportedException("Unable to move the devices organisational unit when the source and destination domains are different.");
|
||||||
|
if (domain == null)
|
||||||
|
domain = proposedDomain;
|
||||||
|
else if (domain != proposedDomain)
|
||||||
|
throw new NotSupportedException("To many domains involved in this enrolment, contact support regarding your scenario.");
|
||||||
|
|
||||||
EnrolmentLog.LogSessionProgress(sessionId, 65, string.Format("Moving Device Organisation Unit: {0} -> {1}", parentDistinguishedName, newOU));
|
EnrolmentLog.LogSessionProgress(sessionId, 65, string.Format("Moving Device Organisational Unit: {0} -> {1}", parentDistinguishedName, RepoDevice.DeviceProfile.OrganisationalUnit));
|
||||||
EnrolmentLog.LogSessionTaskMovingDeviceOrganisationUnit(sessionId, parentDistinguishedName, newOU);
|
EnrolmentLog.LogSessionTaskMovingDeviceOrganisationUnit(sessionId, parentDistinguishedName, RepoDevice.DeviceProfile.OrganisationalUnit);
|
||||||
MachineInfo.MoveOrganisationUnit(RepoDevice.DeviceProfile.OrganisationalUnit);
|
adMachineAccount.MoveOrganisationalUnit(domainController.Value, RepoDevice.DeviceProfile.OrganisationalUnit);
|
||||||
MachineInfo = ActiveDirectory.GetMachineAccount(MachineInfo.SamAccountName);
|
|
||||||
response.RequireReboot = true;
|
response.RequireReboot = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (MachineInfo != null && !MachineInfo.IsCriticalSystemObject)
|
if (adMachineAccount != null && !adMachineAccount.IsCriticalSystemObject)
|
||||||
{
|
{
|
||||||
EnrolmentLog.LogSessionProgress(sessionId, 75, "Updating Active Directory Computer Account Properties");
|
EnrolmentLog.LogSessionProgress(sessionId, 75, "Updating Active Directory Computer Account Properties");
|
||||||
MachineInfo.UpdateNetbootGUID(Request.DeviceUUID, Request.DeviceLanMacAddress);
|
adMachineAccount.UpdateNetbootGUID(Request.DeviceUUID, Request.DeviceLanMacAddress);
|
||||||
if (RepoDevice.AssignedUser != null)
|
if (RepoDevice.AssignedUser != null)
|
||||||
MachineInfo.SetDescription(RepoDevice);
|
adMachineAccount.SetDescription(RepoDevice);
|
||||||
}
|
}
|
||||||
if (RepoDevice.DeviceProfile.DistributionType == DeviceProfile.DistributionTypes.OneToOne)
|
if (RepoDevice.DeviceProfile.DistributionType == DeviceProfile.DistributionTypes.OneToOne)
|
||||||
{
|
{
|
||||||
@@ -534,14 +595,14 @@ namespace Disco.BI.DeviceBI
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
EnrolmentLog.LogSessionProgress(sessionId, 80, "Retrieving Active Directory Assigned User Account");
|
EnrolmentLog.LogSessionProgress(sessionId, 80, "Retrieving Active Directory Assigned User Account");
|
||||||
ActiveDirectoryUserAccount AssignedUserInfo = ActiveDirectory.GetUserAccount(RepoDevice.AssignedUser.Id);
|
ADUserAccount AssignedUserInfo = ActiveDirectory.RetrieveADUserAccount(RepoDevice.AssignedUser.UserId);
|
||||||
EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.SamAccountName, AssignedUserInfo.Domain, AssignedUserInfo.SecurityIdentifier);
|
EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.SamAccountName, AssignedUserInfo.Domain.NetBiosName, AssignedUserInfo.SecurityIdentifier.ToString());
|
||||||
response.AllowBootstrapperUninstall = true;
|
response.AllowBootstrapperUninstall = true;
|
||||||
response.DeviceAssignedUserIsLocalAdmin = RepoDevice.DeviceProfile.AssignedUserLocalAdmin;
|
response.DeviceAssignedUserIsLocalAdmin = RepoDevice.DeviceProfile.AssignedUserLocalAdmin;
|
||||||
response.DeviceAssignedUserUsername = AssignedUserInfo.SamAccountName;
|
response.DeviceAssignedUserUsername = AssignedUserInfo.SamAccountName;
|
||||||
response.DeviceAssignedUserDomain = AssignedUserInfo.Domain;
|
response.DeviceAssignedUserDomain = AssignedUserInfo.Domain.NetBiosName;
|
||||||
response.DeviceAssignedUserName = AssignedUserInfo.DisplayName;
|
response.DeviceAssignedUserName = AssignedUserInfo.DisplayName;
|
||||||
response.DeviceAssignedUserSID = AssignedUserInfo.SecurityIdentifier;
|
response.DeviceAssignedUserSID = AssignedUserInfo.SecurityIdentifier.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,102 +0,0 @@
|
|||||||
using Disco.Models.BI.Device;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Disco.BI.DeviceBI.Importing
|
|
||||||
{
|
|
||||||
public static class Export
|
|
||||||
{
|
|
||||||
private const string ExportHeader = "Serial Number,Device Model,Device Profile,Device Batch,Assigned User,Location,Asset Number";
|
|
||||||
|
|
||||||
public static MemoryStream GenerateExport(IQueryable<Device> Devices)
|
|
||||||
{
|
|
||||||
var devices = Devices.Select(d => new ImportDevice()
|
|
||||||
{
|
|
||||||
SerialNumber = d.SerialNumber,
|
|
||||||
DeviceModelId = d.DeviceModelId,
|
|
||||||
DeviceProfileId = d.DeviceProfileId,
|
|
||||||
DeviceBatchId = d.DeviceBatchId,
|
|
||||||
AssignedUserId = d.AssignedUserId,
|
|
||||||
Location = d.Location,
|
|
||||||
AssetNumber = d.AssetNumber
|
|
||||||
});
|
|
||||||
|
|
||||||
MemoryStream exportStream = new MemoryStream();
|
|
||||||
|
|
||||||
StreamWriter exportWriter = new StreamWriter(exportStream);
|
|
||||||
// Write Header
|
|
||||||
exportWriter.WriteLine(ExportHeader);
|
|
||||||
|
|
||||||
foreach (var device in devices)
|
|
||||||
device.ExportCsv(exportWriter);
|
|
||||||
|
|
||||||
exportWriter.Flush();
|
|
||||||
|
|
||||||
exportStream.Position = 0;
|
|
||||||
return exportStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ExportCsv(this ImportDevice device, StreamWriter writer)
|
|
||||||
{
|
|
||||||
// SERIAL NUMBER
|
|
||||||
writer.Write('"');
|
|
||||||
writer.Write(device.SerialNumber.Replace("\"", "\"\""));
|
|
||||||
writer.Write('"');
|
|
||||||
|
|
||||||
writer.Write(',');
|
|
||||||
|
|
||||||
// DEVICE MODEL
|
|
||||||
if (device.DeviceModelId.HasValue)
|
|
||||||
writer.Write(device.DeviceModelId.Value);
|
|
||||||
|
|
||||||
writer.Write(',');
|
|
||||||
|
|
||||||
// DEVICE PROFILE
|
|
||||||
writer.Write(device.DeviceProfileId);
|
|
||||||
|
|
||||||
writer.Write(',');
|
|
||||||
|
|
||||||
// DEVICE BATCH
|
|
||||||
if (device.DeviceBatchId.HasValue)
|
|
||||||
writer.Write(device.DeviceBatchId.Value);
|
|
||||||
|
|
||||||
writer.Write(',');
|
|
||||||
|
|
||||||
// ASSIGNED USER
|
|
||||||
if (device.AssignedUserId != null)
|
|
||||||
{
|
|
||||||
writer.Write('"');
|
|
||||||
writer.Write(device.AssignedUserId.Replace("\"", "\"\""));
|
|
||||||
writer.Write('"');
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.Write(',');
|
|
||||||
|
|
||||||
// LOCATION
|
|
||||||
if (!string.IsNullOrWhiteSpace(device.Location))
|
|
||||||
{
|
|
||||||
writer.Write('"');
|
|
||||||
writer.Write(device.Location.Replace("\"", "\"\""));
|
|
||||||
writer.Write('"');
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.Write(',');
|
|
||||||
|
|
||||||
// ASSET NUMBER
|
|
||||||
if (!string.IsNullOrWhiteSpace(device.AssetNumber))
|
|
||||||
{
|
|
||||||
writer.Write('"');
|
|
||||||
writer.Write(device.AssetNumber.Replace("\"", "\"\""));
|
|
||||||
writer.Write('"');
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.WriteLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,266 +0,0 @@
|
|||||||
using Disco.BI.Extensions;
|
|
||||||
using Disco.Data.Repository;
|
|
||||||
using Disco.Models.BI.Device;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
using Disco.Services.Users;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Web;
|
|
||||||
using PopulateRecordReferences = System.Tuple<System.Collections.Generic.Dictionary<int, Disco.Models.Repository.DeviceModel>, System.Collections.Generic.Dictionary<int, Disco.Models.Repository.DeviceProfile>, System.Collections.Generic.Dictionary<int, Disco.Models.Repository.DeviceBatch>>;
|
|
||||||
|
|
||||||
namespace Disco.BI.DeviceBI.Importing
|
|
||||||
{
|
|
||||||
public static class Import
|
|
||||||
{
|
|
||||||
internal const string ImportParseCacheKey = "ImportParseResults_{0}";
|
|
||||||
|
|
||||||
public static ImportDeviceSession GetSession(string ImportParseTaskId)
|
|
||||||
{
|
|
||||||
string parseKey = string.Format(ImportParseCacheKey, ImportParseTaskId);
|
|
||||||
|
|
||||||
return (ImportDeviceSession)HttpRuntime.Cache.Get(parseKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static bool ImportRecord(this ImportDevice device, DiscoDataContext Database, PopulateRecordReferences references)
|
|
||||||
{
|
|
||||||
// Skips If Errors
|
|
||||||
if (device.Errors == null || device.Errors.Count == 0)
|
|
||||||
{
|
|
||||||
// Re-Populate & Skip If Errors
|
|
||||||
device.PopulateRecord(Database, references);
|
|
||||||
if (device.Errors == null || device.Errors.Count == 0)
|
|
||||||
{
|
|
||||||
Device discoDevice = device.Device;
|
|
||||||
|
|
||||||
if (discoDevice == null)
|
|
||||||
{
|
|
||||||
// New Device
|
|
||||||
discoDevice = new Device()
|
|
||||||
{
|
|
||||||
SerialNumber = device.SerialNumber.ToUpper(),
|
|
||||||
CreatedDate = DateTime.Now,
|
|
||||||
AllowUnauthenticatedEnrol = true,
|
|
||||||
};
|
|
||||||
Database.Devices.Add(discoDevice);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (discoDevice.DeviceModelId != device.DeviceModelId)
|
|
||||||
discoDevice.DeviceModelId = device.DeviceModelId;
|
|
||||||
if (discoDevice.DeviceProfileId != device.DeviceProfileId)
|
|
||||||
discoDevice.DeviceProfileId = device.DeviceProfileId;
|
|
||||||
if (discoDevice.DeviceBatchId != device.DeviceBatchId)
|
|
||||||
discoDevice.DeviceBatchId = device.DeviceBatchId;
|
|
||||||
if (discoDevice.Location != device.Location)
|
|
||||||
discoDevice.Location = device.Location;
|
|
||||||
if (discoDevice.AssetNumber != device.AssetNumber)
|
|
||||||
discoDevice.AssetNumber = device.AssetNumber;
|
|
||||||
|
|
||||||
if (discoDevice.AssignedUserId != device.AssignedUserId)
|
|
||||||
{
|
|
||||||
discoDevice.AssignDevice(Database, device.AssignedUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
Database.SaveChanges();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static PopulateRecordReferences GetPopulateRecordReferences(DiscoDataContext Database)
|
|
||||||
{
|
|
||||||
return new PopulateRecordReferences(
|
|
||||||
Database.DeviceModels.ToDictionary(dm => dm.Id),
|
|
||||||
Database.DeviceProfiles.ToDictionary(dp => dp.Id),
|
|
||||||
Database.DeviceBatches.ToDictionary(db => db.Id)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void PopulateRecord(this ImportDevice device, DiscoDataContext Database, PopulateRecordReferences references)
|
|
||||||
{
|
|
||||||
|
|
||||||
var deviceModels = references.Item1;
|
|
||||||
var deviceProfiles = references.Item2;
|
|
||||||
var deviceBatches = references.Item3;
|
|
||||||
|
|
||||||
// SERIAL NUMBER - Existing Device
|
|
||||||
if (!device.Errors.ContainsKey("SerialNumber"))
|
|
||||||
{
|
|
||||||
device.Device = Database.Devices.Find(device.SerialNumber);
|
|
||||||
if (device.Device != null && device.Device.DecommissionedDate.HasValue)
|
|
||||||
device.Errors.Add("SerialNumber", "The device is decommissioned");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// DEVICE MODEL
|
|
||||||
if (!device.Errors.ContainsKey("DeviceModelId"))
|
|
||||||
{
|
|
||||||
DeviceModel deviceModel;
|
|
||||||
|
|
||||||
if (!device.DeviceModelId.HasValue)
|
|
||||||
device.DeviceModelId = 1; // Default 'Unknown Device Model'
|
|
||||||
|
|
||||||
if (!deviceModels.TryGetValue(device.DeviceModelId.Value, out deviceModel))
|
|
||||||
device.Errors.Add("DeviceModelId", string.Format("Unknown device model id: {0}", device.DeviceModelId));
|
|
||||||
else
|
|
||||||
device.DeviceModel = deviceModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEVICE PROFILE
|
|
||||||
if (!device.Errors.ContainsKey("DeviceProfileId"))
|
|
||||||
{
|
|
||||||
DeviceProfile deviceProfile;
|
|
||||||
if (!deviceProfiles.TryGetValue(device.DeviceProfileId, out deviceProfile))
|
|
||||||
device.Errors.Add("DeviceProfileId", string.Format("Unknown device profile id: {0}", device.DeviceProfileId));
|
|
||||||
else
|
|
||||||
device.DeviceProfile = deviceProfile;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEVICE BATCH
|
|
||||||
if (!device.Errors.ContainsKey("DeviceBatchId") && device.DeviceBatchId.HasValue)
|
|
||||||
{
|
|
||||||
DeviceBatch deviceBatch;
|
|
||||||
if (!deviceBatches.TryGetValue(device.DeviceBatchId.Value, out deviceBatch))
|
|
||||||
device.Errors.Add("DeviceBatchId", string.Format("Unknown device Batch id: {0}", device.DeviceBatchId));
|
|
||||||
else
|
|
||||||
device.DeviceBatch = deviceBatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ASSIGNED USER
|
|
||||||
if (!device.Errors.ContainsKey("AssignedUserId") && device.AssignedUserId != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
device.AssignedUser = UserService.GetUser(device.AssignedUserId, Database, true);
|
|
||||||
}
|
|
||||||
catch (ArgumentException)
|
|
||||||
{
|
|
||||||
device.Errors.Add("AssignedUserId", string.Format("Unknown user id: {0}", device.AssignedUserId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static ImportDevice ParseRecord(this string[] record)
|
|
||||||
{
|
|
||||||
int csvFieldCount = record.Length;
|
|
||||||
if (csvFieldCount < 1)
|
|
||||||
throw new ArgumentException("At least one CSV field is required (Serial Number)");
|
|
||||||
|
|
||||||
string csvSerialNumber;
|
|
||||||
string csvDeviceModelId;
|
|
||||||
int deviceModelId = 1; // Default 'Unknown Device Model'
|
|
||||||
string csvDeviceProfileId;
|
|
||||||
int deviceProfileId = 1; // 'Default' Profile
|
|
||||||
string csvDeviceBatchId;
|
|
||||||
int deviceBatchId = 0; // No Batch
|
|
||||||
string csvAssignedUserId = null;
|
|
||||||
string csvLocation = null;
|
|
||||||
string csvAssetNumber = null;
|
|
||||||
Dictionary<string, string> errors = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
// SERIAL NUMBER
|
|
||||||
csvSerialNumber = record[0];
|
|
||||||
if (string.IsNullOrWhiteSpace(csvSerialNumber))
|
|
||||||
errors.Add("SerialNumber", "The serial number is required");
|
|
||||||
else if (csvSerialNumber.Trim().Length > 60)
|
|
||||||
errors.Add("SerialNumber", "The serial number must be less than or equal to 60 characters");
|
|
||||||
|
|
||||||
if (csvFieldCount > 1)
|
|
||||||
{
|
|
||||||
// DEVICE MODEL
|
|
||||||
csvDeviceModelId = record[1];
|
|
||||||
if (!string.IsNullOrWhiteSpace(csvDeviceModelId))
|
|
||||||
if (!int.TryParse(csvDeviceModelId, out deviceModelId))
|
|
||||||
errors.Add("DeviceModelId", "The device model is optional, but when supplied must be a number");
|
|
||||||
else if (deviceModelId < 1)
|
|
||||||
errors.Add("DeviceModelId", "The device model is optional, but when supplied must be greater than 0");
|
|
||||||
|
|
||||||
if (csvFieldCount > 2)
|
|
||||||
{
|
|
||||||
// DEVICE PROFILE
|
|
||||||
csvDeviceProfileId = record[2];
|
|
||||||
if (!string.IsNullOrWhiteSpace(csvDeviceProfileId))
|
|
||||||
if (!int.TryParse(csvDeviceProfileId, out deviceProfileId))
|
|
||||||
errors.Add("DeviceProfileId", "The device profile is optional, but when supplied must be a number");
|
|
||||||
else if (deviceProfileId < 1)
|
|
||||||
errors.Add("DeviceProfileId", "The device profile is optional, but when supplied must be greater than 0");
|
|
||||||
|
|
||||||
if (csvFieldCount > 3)
|
|
||||||
{
|
|
||||||
// DEVICE BATCH
|
|
||||||
csvDeviceBatchId = record[3];
|
|
||||||
if (!string.IsNullOrWhiteSpace(csvDeviceBatchId))
|
|
||||||
if (!int.TryParse(csvDeviceBatchId, out deviceBatchId))
|
|
||||||
errors.Add("DeviceBatchId", "The device batch is optional, but when supplied must be a number");
|
|
||||||
else if (deviceBatchId < 1)
|
|
||||||
errors.Add("DeviceBatchId", "The device batch is optional, but when supplied must be greater than 0");
|
|
||||||
|
|
||||||
if (csvFieldCount > 4)
|
|
||||||
{
|
|
||||||
// ASSIGNED USER
|
|
||||||
csvAssignedUserId = record[4];
|
|
||||||
if (string.IsNullOrWhiteSpace(csvAssignedUserId))
|
|
||||||
csvAssignedUserId = null; // Not Assigned
|
|
||||||
else if (csvAssignedUserId.Length > 50)
|
|
||||||
errors.Add("AssignedUserId", "The assigned user must be less than or equal to 50 characters");
|
|
||||||
|
|
||||||
if (csvFieldCount > 5)
|
|
||||||
{
|
|
||||||
// LOCATION
|
|
||||||
csvLocation = record[5];
|
|
||||||
if (string.IsNullOrWhiteSpace(csvLocation))
|
|
||||||
csvLocation = null; // No Location Specified
|
|
||||||
else if (csvLocation.Length > 250)
|
|
||||||
errors.Add("Location", "The location must be less than or equal to 250 characters");
|
|
||||||
|
|
||||||
if (csvFieldCount > 6)
|
|
||||||
{
|
|
||||||
// ASSET NUMBER
|
|
||||||
csvAssetNumber = record[6];
|
|
||||||
if (string.IsNullOrWhiteSpace(csvAssetNumber))
|
|
||||||
csvAssetNumber = null; // No Location Specified
|
|
||||||
else if (csvAssetNumber.Length > 40)
|
|
||||||
errors.Add("AssetNumber", "The asset number must be less than or equal to 40 characters");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ImportDevice()
|
|
||||||
{
|
|
||||||
SerialNumber = csvSerialNumber.Trim(),
|
|
||||||
DeviceModelId = deviceModelId,
|
|
||||||
DeviceProfileId = deviceProfileId,
|
|
||||||
DeviceBatchId = deviceBatchId == 0 ? (int?)null : deviceBatchId,
|
|
||||||
AssignedUserId = csvAssignedUserId,
|
|
||||||
Location = csvLocation,
|
|
||||||
AssetNumber = csvAssetNumber,
|
|
||||||
Errors = errors
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#region ImportDevice Extensions
|
|
||||||
|
|
||||||
public static string ImportStatus(this ImportDevice device)
|
|
||||||
{
|
|
||||||
if (device.Errors.Count > 0)
|
|
||||||
return "Error";
|
|
||||||
|
|
||||||
if (device.Device != null)
|
|
||||||
return "Update";
|
|
||||||
|
|
||||||
return "New";
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
using Disco.Data.Repository;
|
|
||||||
using Disco.Models.BI.Device;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
using Disco.Services.Tasks;
|
|
||||||
using LumenWorks.Framework.IO.Csv;
|
|
||||||
using Quartz;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Web;
|
|
||||||
using System.Web.Caching;
|
|
||||||
|
|
||||||
namespace Disco.BI.DeviceBI.Importing
|
|
||||||
{
|
|
||||||
public class ImportParseTask : ScheduledTask
|
|
||||||
{
|
|
||||||
public override string TaskName { get { return "Import Devices - Parsing"; } }
|
|
||||||
|
|
||||||
public override bool SingleInstanceTask { get { return false; } }
|
|
||||||
public override bool CancelInitiallySupported { get { return false; } }
|
|
||||||
|
|
||||||
protected override void ExecuteTask()
|
|
||||||
{
|
|
||||||
string csvFilename = (string)this.ExecutionContext.JobDetail.JobDataMap["CsvFilename"];
|
|
||||||
MemoryStream csvStream = (MemoryStream)this.ExecutionContext.JobDetail.JobDataMap["CsvImport"];
|
|
||||||
|
|
||||||
this.Status.UpdateStatus(0, "Parsing CSV File", "Loading Records");
|
|
||||||
|
|
||||||
List<ImportDevice> records;
|
|
||||||
|
|
||||||
using (TextReader csvTextReader = new StreamReader(csvStream))
|
|
||||||
{
|
|
||||||
using (CsvReader csvReader = new CsvReader(csvTextReader, true))
|
|
||||||
{
|
|
||||||
csvReader.DefaultParseErrorAction = ParseErrorAction.ThrowException;
|
|
||||||
csvReader.MissingFieldAction = MissingFieldAction.ReplaceByNull;
|
|
||||||
|
|
||||||
records = csvReader.Select(record => record.ParseRecord()).ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
csvStream.Dispose();
|
|
||||||
|
|
||||||
this.Status.UpdateStatus(20, "Parsing CSV File", string.Format("Linking {0} Records", records.Count));
|
|
||||||
|
|
||||||
using (DiscoDataContext database = new DiscoDataContext())
|
|
||||||
{
|
|
||||||
var populateReferences = Import.GetPopulateRecordReferences(database);
|
|
||||||
|
|
||||||
DateTime lastUpdate = DateTime.Now;
|
|
||||||
foreach (var record in records)
|
|
||||||
{
|
|
||||||
record.PopulateRecord(database, populateReferences);
|
|
||||||
|
|
||||||
if (DateTime.Now.Subtract(lastUpdate).TotalSeconds > 1)
|
|
||||||
{
|
|
||||||
// Update every second
|
|
||||||
this.Status.UpdateStatus((int)Math.Floor((((double)(records.IndexOf(record) + 1) / records.Count) * 80)));
|
|
||||||
lastUpdate = DateTime.Now;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Session Result
|
|
||||||
ImportDeviceSession session = new ImportDeviceSession()
|
|
||||||
{
|
|
||||||
ImportParseTaskId = this.Status.SessionId,
|
|
||||||
ImportFilename = csvFilename,
|
|
||||||
ImportDevices = records
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set Results to Cache
|
|
||||||
string key = string.Format(Import.ImportParseCacheKey, this.Status.SessionId);
|
|
||||||
HttpRuntime.Cache.Insert(key, session, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(60), CacheItemPriority.NotRemovable, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ScheduledTaskStatus Run(Stream CsvImport, String CsvFilename)
|
|
||||||
{
|
|
||||||
|
|
||||||
MemoryStream csvStream = new MemoryStream();
|
|
||||||
CsvImport.CopyTo(csvStream);
|
|
||||||
csvStream.Position = 0;
|
|
||||||
|
|
||||||
var task = new ImportParseTask();
|
|
||||||
JobDataMap taskData = new JobDataMap() { { "CsvImport", csvStream }, { "CsvFilename", CsvFilename } };
|
|
||||||
return task.ScheduleTask(taskData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
using Disco.Data.Repository;
|
|
||||||
using Disco.Models.BI.Device;
|
|
||||||
using Disco.Services.Tasks;
|
|
||||||
using Quartz;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Web;
|
|
||||||
|
|
||||||
namespace Disco.BI.DeviceBI.Importing
|
|
||||||
{
|
|
||||||
public class ImportProcessTask : ScheduledTask
|
|
||||||
{
|
|
||||||
public override string TaskName { get { return "Import Devices - Processing Changes"; } }
|
|
||||||
|
|
||||||
public override bool SingleInstanceTask { get { return false; } }
|
|
||||||
public override bool CancelInitiallySupported { get { return false; } }
|
|
||||||
|
|
||||||
protected override void ExecuteTask()
|
|
||||||
{
|
|
||||||
string importParseTaskId = (string)this.ExecutionContext.JobDetail.JobDataMap["ImportParseTaskId"];
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(importParseTaskId))
|
|
||||||
throw new ArgumentNullException("ImportParseTaskId");
|
|
||||||
|
|
||||||
ImportDeviceSession session = Import.GetSession(importParseTaskId);
|
|
||||||
|
|
||||||
if (session == null)
|
|
||||||
throw new InvalidOperationException("The session timed out (60 minutes), try importing again");
|
|
||||||
|
|
||||||
List<ImportDevice> records = session.ImportDevices;
|
|
||||||
int recordsImported = 0;
|
|
||||||
|
|
||||||
this.Status.UpdateStatus(0, "Processing Device Import", "Importing Devices");
|
|
||||||
|
|
||||||
using (DiscoDataContext database = new DiscoDataContext())
|
|
||||||
{
|
|
||||||
var populateReferences = Import.GetPopulateRecordReferences(database);
|
|
||||||
|
|
||||||
DateTime lastUpdate = DateTime.Now;
|
|
||||||
foreach (var record in records)
|
|
||||||
{
|
|
||||||
if (record.ImportRecord(database, populateReferences))
|
|
||||||
recordsImported++;
|
|
||||||
|
|
||||||
if (DateTime.Now.Subtract(lastUpdate).TotalSeconds > 1)
|
|
||||||
{
|
|
||||||
// Update every second
|
|
||||||
this.Status.UpdateStatus((int)Math.Floor((((double)(records.IndexOf(record) + 1) / records.Count) * 100)), string.Format("Importing: {0} ({1} of {2})", record.SerialNumber, records.IndexOf(record) + 1, records.Count));
|
|
||||||
lastUpdate = DateTime.Now;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Status.SetFinishedMessage(string.Format("Imported {0} of {1} Devices", recordsImported, records.Count));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ScheduledTaskStatus Run(string ImportParseTaskId)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(ImportParseTaskId))
|
|
||||||
throw new ArgumentNullException("ImportParseTaskId");
|
|
||||||
|
|
||||||
var task = new ImportProcessTask();
|
|
||||||
JobDataMap taskData = new JobDataMap() { { "ImportParseTaskId", ImportParseTaskId } };
|
|
||||||
return task.ScheduleTask(taskData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Disco.Models.BI.Search;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
using Disco.Data.Repository;
|
|
||||||
|
|
||||||
namespace Disco.BI.DeviceBI
|
|
||||||
{
|
|
||||||
public static class Searching
|
|
||||||
{
|
|
||||||
private static List<DeviceSearchResultItem> Search_SelectDeviceSearchResultItem(IQueryable<Device> Query, int? LimitCount = null)
|
|
||||||
{
|
|
||||||
if (LimitCount.HasValue)
|
|
||||||
Query = Query.Take(LimitCount.Value);
|
|
||||||
|
|
||||||
return Query.Select(d => new DeviceSearchResultItem()
|
|
||||||
{
|
|
||||||
SerialNumber = d.SerialNumber,
|
|
||||||
AssetNumber = d.AssetNumber,
|
|
||||||
ComputerName = d.ComputerName,
|
|
||||||
DeviceModelDescription = d.DeviceModel.Description,
|
|
||||||
DeviceProfileDescription = d.DeviceProfile.Description,
|
|
||||||
DecommissionedDate = d.DecommissionedDate,
|
|
||||||
AssignedUserId = d.AssignedUserId,
|
|
||||||
AssignedUserDisplayName = d.AssignedUser.DisplayName,
|
|
||||||
JobCount = d.Jobs.Count()
|
|
||||||
}).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<DeviceSearchResultItem> Search(DiscoDataContext Database, string Term, int? LimitCount = null, bool SearchDetails = false)
|
|
||||||
{
|
|
||||||
IQueryable<Device> query;
|
|
||||||
|
|
||||||
query = null;
|
|
||||||
|
|
||||||
if (SearchDetails)
|
|
||||||
{
|
|
||||||
query = Database.Devices.Where(d =>
|
|
||||||
d.AssetNumber.Contains(Term) ||
|
|
||||||
d.ComputerName.Contains(Term) ||
|
|
||||||
d.SerialNumber.Contains(Term) ||
|
|
||||||
d.Location.Contains(Term) ||
|
|
||||||
Term.Contains(d.SerialNumber) ||
|
|
||||||
d.DeviceDetails.Any(dd => dd.Value.Contains(Term))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
query = Database.Devices.Where(d =>
|
|
||||||
d.AssetNumber.Contains(Term) ||
|
|
||||||
d.ComputerName.Contains(Term) ||
|
|
||||||
d.SerialNumber.Contains(Term) ||
|
|
||||||
d.Location.Contains(Term) ||
|
|
||||||
Term.Contains(d.SerialNumber));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Search_SelectDeviceSearchResultItem(query, LimitCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<DeviceSearchResultItem> SearchDeviceModel(DiscoDataContext Database, int DeviceModelId, int? LimitCount = null)
|
|
||||||
{
|
|
||||||
return Search_SelectDeviceSearchResultItem(Database.Devices.Where(d => d.DeviceModelId == DeviceModelId), LimitCount);
|
|
||||||
}
|
|
||||||
public static List<DeviceSearchResultItem> SearchDeviceProfile(DiscoDataContext Database, int DeviceProfileId, int? LimitCount = null)
|
|
||||||
{
|
|
||||||
return Search_SelectDeviceSearchResultItem(Database.Devices.Where(d => d.DeviceProfileId == DeviceProfileId), LimitCount);
|
|
||||||
}
|
|
||||||
public static List<DeviceSearchResultItem> SearchDeviceBatch(DiscoDataContext Database, int DeviceBatchId, int? LimitCount = null)
|
|
||||||
{
|
|
||||||
return Search_SelectDeviceSearchResultItem(Database.Devices.Where(d => d.DeviceBatchId == DeviceBatchId), LimitCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using Disco.Data.Repository;
|
using Disco.Data.Repository;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
using System;
|
using System;
|
||||||
namespace Disco.BI.DocumentTemplateBI
|
namespace Disco.BI.DocumentTemplateBI
|
||||||
{
|
{
|
||||||
@@ -61,14 +62,14 @@ namespace Disco.BI.DocumentTemplateBI
|
|||||||
public string DataScope { get; private set; }
|
public string DataScope { get; private set; }
|
||||||
public static bool IsDocumentUniqueIdentifier(string UniqueIdentifier)
|
public static bool IsDocumentUniqueIdentifier(string UniqueIdentifier)
|
||||||
{
|
{
|
||||||
return UniqueIdentifier.StartsWith("Disco|", System.StringComparison.InvariantCultureIgnoreCase);
|
return UniqueIdentifier.StartsWith("Disco|", System.StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
public DocumentUniqueIdentifier(string TemplateTypeId, string DataId, string CreatorId, DateTime TimeStamp, int? Page = null, string Tag = null)
|
public DocumentUniqueIdentifier(string TemplateTypeId, string DataId, string CreatorId, DateTime TimeStamp, int? Page = null, string Tag = null)
|
||||||
{
|
{
|
||||||
this.Tag = Tag;
|
this.Tag = Tag;
|
||||||
this.TemplateTypeId = TemplateTypeId;
|
this.TemplateTypeId = TemplateTypeId;
|
||||||
this.DataId = DataId;
|
this.DataId = DataId;
|
||||||
this.CreatorId = CreatorId;
|
this.CreatorId = ActiveDirectory.ParseDomainAccountId(CreatorId);
|
||||||
this.TimeStamp = TimeStamp;
|
this.TimeStamp = TimeStamp;
|
||||||
this.Page = Page ?? 0;
|
this.Page = Page ?? 0;
|
||||||
}
|
}
|
||||||
@@ -93,7 +94,7 @@ namespace Disco.BI.DocumentTemplateBI
|
|||||||
}
|
}
|
||||||
if (s.Length >= 5)
|
if (s.Length >= 5)
|
||||||
{
|
{
|
||||||
this.CreatorId = s[4];
|
this.CreatorId = ActiveDirectory.ParseDomainAccountId(s[4]);
|
||||||
}
|
}
|
||||||
if (s.Length >= 6)
|
if (s.Length >= 6)
|
||||||
{
|
{
|
||||||
@@ -180,7 +181,7 @@ namespace Disco.BI.DocumentTemplateBI
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DocumentTemplate.DocumentTemplateScopes.User:
|
case DocumentTemplate.DocumentTemplateScopes.User:
|
||||||
User u = Database.Users.Find(this.DataId);
|
User u = Database.Users.Find(ActiveDirectory.ParseDomainAccountId(this.DataId));
|
||||||
if (u != null)
|
if (u != null)
|
||||||
{
|
{
|
||||||
this._data = u;
|
this._data = u;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace Disco.BI.DocumentTemplateBI.Importer
|
|||||||
|
|
||||||
public override bool SingleInstanceTask { get { return true; } }
|
public override bool SingleInstanceTask { get { return true; } }
|
||||||
public override bool CancelInitiallySupported { get { return false; } }
|
public override bool CancelInitiallySupported { get { return false; } }
|
||||||
|
public override bool LogExceptionsOnly { get { return true; } }
|
||||||
|
|
||||||
public override void InitalizeScheduledTask(DiscoDataContext Database)
|
public override void InitalizeScheduledTask(DiscoDataContext Database)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,486 @@
|
|||||||
|
using Disco.Data.Repository;
|
||||||
|
using Disco.Data.Repository.Monitor;
|
||||||
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Models.Services.Interop.ActiveDirectory;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reactive.Linq;
|
||||||
|
|
||||||
|
namespace Disco.BI.DocumentTemplateBI.ManagedGroups
|
||||||
|
{
|
||||||
|
public class DocumentTemplateDevicesManagedGroup : ADManagedGroup
|
||||||
|
{
|
||||||
|
private const string KeyFormat = "DocumentTemplate_{0}_Devices";
|
||||||
|
private const string DeviceDescriptionFormat = "Devices with a {0} attachment will be added to this Active Directory group.";
|
||||||
|
private const string DescriptionFormat = "{0}s with a {1} attachment will have any associated devices added to this Active Directory group.";
|
||||||
|
private const string CategoryDescriptionFormat = "Related Devices Linked Group";
|
||||||
|
private const string GroupDescriptionFormat = "{0} [Document Template Devices]";
|
||||||
|
|
||||||
|
private IDisposable repositoryAddSubscription;
|
||||||
|
private IDisposable repositoryRemoveSubscription;
|
||||||
|
private IDisposable deviceRenameRepositorySubscription;
|
||||||
|
private IDisposable jobCloseRepositorySubscription;
|
||||||
|
private IDisposable deviceAssignmentRepositorySubscription;
|
||||||
|
private string DocumentTemplateId;
|
||||||
|
private string DocumentTemplateDescription;
|
||||||
|
private string DocumentTemplateScope;
|
||||||
|
|
||||||
|
public override string Description { get { return GetDescription(DocumentTemplateScope, DocumentTemplateDescription); } }
|
||||||
|
public override string CategoryDescription { get { return CategoryDescriptionFormat; } }
|
||||||
|
public override string GroupDescription { get { return string.Format(GroupDescriptionFormat, DocumentTemplateDescription); } }
|
||||||
|
public override bool IncludeFilterBeginDate { get { return true; } }
|
||||||
|
|
||||||
|
private DocumentTemplateDevicesManagedGroup(string Key, ADManagedGroupConfiguration Configuration, DocumentTemplate DocumentTemplate)
|
||||||
|
: base(Key, Configuration)
|
||||||
|
{
|
||||||
|
this.DocumentTemplateId = DocumentTemplate.Id;
|
||||||
|
this.DocumentTemplateDescription = DocumentTemplate.Description;
|
||||||
|
this.DocumentTemplateScope = DocumentTemplate.Scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
// Subscribe to changes
|
||||||
|
switch (DocumentTemplateScope)
|
||||||
|
{
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.Device:
|
||||||
|
// Observe Device Attachments
|
||||||
|
repositoryAddSubscription = DocumentTemplateManagedGroups.DeviceAttachmentAddRepositoryEvents.Value
|
||||||
|
.Where(e => ((DeviceAttachment)e.Entity).DocumentTemplateId == DocumentTemplateId)
|
||||||
|
.Subscribe(ProcessDeviceAttachmentAddEvent);
|
||||||
|
repositoryRemoveSubscription = DocumentTemplateManagedGroups.DeviceAttachmentRemoveEvents.Value
|
||||||
|
.Where(e => e.Item3 == DocumentTemplateId)
|
||||||
|
.Subscribe(ProcessDeviceAttachmentRemoveEvent);
|
||||||
|
break;
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.Job:
|
||||||
|
// Observe Job Attachments
|
||||||
|
repositoryAddSubscription = DocumentTemplateManagedGroups.JobAttachmentAddRepositoryEvents.Value
|
||||||
|
.Where(e => ((JobAttachment)e.Entity).DocumentTemplateId == DocumentTemplateId)
|
||||||
|
.Subscribe(ProcessJobAttachmentAddEvent);
|
||||||
|
repositoryRemoveSubscription = DocumentTemplateManagedGroups.JobAttachmentRemoveEvents.Value
|
||||||
|
.Where(e => e.Item3 == DocumentTemplateId)
|
||||||
|
.Subscribe(ProcessJobAttachmentRemoveEvent);
|
||||||
|
// Observe Job Close/Reopen
|
||||||
|
jobCloseRepositorySubscription = DocumentTemplateManagedGroups.JobCloseRepositoryEvents.Value
|
||||||
|
.Subscribe(ProcessJobCloseRepositoryEvent);
|
||||||
|
break;
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.User:
|
||||||
|
// Observe User Attachments
|
||||||
|
repositoryAddSubscription = DocumentTemplateManagedGroups.UserAttachmentAddRepositoryEvents.Value
|
||||||
|
.Where(e => ((UserAttachment)e.Entity).DocumentTemplateId == DocumentTemplateId)
|
||||||
|
.Subscribe(ProcessUserAttachmentAddEvent);
|
||||||
|
repositoryRemoveSubscription = DocumentTemplateManagedGroups.UserAttachmentRemoveEvents.Value
|
||||||
|
.Where(e => e.Item3 == DocumentTemplateId)
|
||||||
|
.Subscribe(ProcessUserAttachmentRemoveEvent);
|
||||||
|
// Observe Device Assignments
|
||||||
|
deviceAssignmentRepositorySubscription = DocumentTemplateManagedGroups.DeviceAssignmentRepositoryEvents.Value
|
||||||
|
.Subscribe(ProcessDeviceAssignmentRepositoryEvent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Observe Device Renaming (DeviceDomainId)
|
||||||
|
deviceRenameRepositorySubscription = DocumentTemplateManagedGroups.DeviceRenameRepositoryEvents.Value
|
||||||
|
.Subscribe(ProcessDeviceRenameRepositoryEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetKey(DocumentTemplate DocumentTemplate)
|
||||||
|
{
|
||||||
|
return string.Format(KeyFormat, DocumentTemplate.Id);
|
||||||
|
}
|
||||||
|
private static string GetDescription(string DocumentTemplateScope, string DocumentTemplateDescription)
|
||||||
|
{
|
||||||
|
switch (DocumentTemplateScope)
|
||||||
|
{
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.Device:
|
||||||
|
return string.Format(DeviceDescriptionFormat, DocumentTemplateDescription);
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.Job:
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.User:
|
||||||
|
return string.Format(DescriptionFormat, DocumentTemplateScope, DocumentTemplateDescription);
|
||||||
|
default:
|
||||||
|
throw new ArgumentException("Unknown Document Template Scope", "Scope");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static string GetDescription(DocumentTemplate DocumentTemplate)
|
||||||
|
{
|
||||||
|
return GetDescription(DocumentTemplate.Scope, DocumentTemplate.Description);
|
||||||
|
}
|
||||||
|
public static string GetCategoryDescription(DocumentTemplate DocumentTemplate)
|
||||||
|
{
|
||||||
|
return CategoryDescriptionFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetManagedGroup(DocumentTemplate DocumentTemplate, out DocumentTemplateDevicesManagedGroup ManagedGroup)
|
||||||
|
{
|
||||||
|
ADManagedGroup managedGroup;
|
||||||
|
string key = GetKey(DocumentTemplate);
|
||||||
|
|
||||||
|
if (ActiveDirectory.Context.ManagedGroups.TryGetValue(key, out managedGroup))
|
||||||
|
{
|
||||||
|
ManagedGroup = (DocumentTemplateDevicesManagedGroup)managedGroup;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ManagedGroup = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DocumentTemplateDevicesManagedGroup Initialize(DocumentTemplate Template)
|
||||||
|
{
|
||||||
|
var key = GetKey(Template);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(Template.DevicesLinkedGroup))
|
||||||
|
{
|
||||||
|
var config = ADManagedGroup.ConfigurationFromJson(Template.DevicesLinkedGroup);
|
||||||
|
|
||||||
|
if (config != null && !string.IsNullOrWhiteSpace(config.GroupId))
|
||||||
|
{
|
||||||
|
var group = new DocumentTemplateDevicesManagedGroup(
|
||||||
|
key,
|
||||||
|
config,
|
||||||
|
Template);
|
||||||
|
|
||||||
|
// Add to AD Context
|
||||||
|
ActiveDirectory.Context.ManagedGroups.AddOrUpdate(group);
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove from AD Context
|
||||||
|
ActiveDirectory.Context.ManagedGroups.Remove(key);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<string> DetermineMembers(DiscoDataContext Database)
|
||||||
|
{
|
||||||
|
switch (DocumentTemplateScope)
|
||||||
|
{
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.Device:
|
||||||
|
return Database.Devices
|
||||||
|
.Where(d => d.DeviceDomainId != null && d.DeviceAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId))
|
||||||
|
.Select(d => d.DeviceDomainId)
|
||||||
|
.ToList()
|
||||||
|
.Where(ActiveDirectory.IsValidDomainAccountId)
|
||||||
|
.Select(id => id + "$");
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.Job:
|
||||||
|
return Database.Jobs
|
||||||
|
.Where(j => !j.ClosedDate.HasValue && j.Device.DeviceDomainId != null && j.JobAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId))
|
||||||
|
.Select(j => j.Device.DeviceDomainId)
|
||||||
|
.Distinct()
|
||||||
|
.ToList()
|
||||||
|
.Where(ActiveDirectory.IsValidDomainAccountId)
|
||||||
|
.Select(id => id + "$");
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.User:
|
||||||
|
return Database.Users
|
||||||
|
.Where(u => u.UserAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId))
|
||||||
|
.SelectMany(u => u.DeviceUserAssignments.Where(dua => !dua.UnassignedDate.HasValue && dua.Device.DeviceDomainId != null), (u, dua) => dua.Device.DeviceDomainId)
|
||||||
|
.ToList()
|
||||||
|
.Where(ActiveDirectory.IsValidDomainAccountId)
|
||||||
|
.Select(id => id + "$");
|
||||||
|
default:
|
||||||
|
return Enumerable.Empty<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Device Scope
|
||||||
|
private bool DeviceContainsAttachment(DiscoDataContext Database, string DeviceSerialNumber, out string DeviceAccountId)
|
||||||
|
{
|
||||||
|
var result = Database.Devices
|
||||||
|
.Where(d => d.SerialNumber == DeviceSerialNumber && d.DeviceDomainId != null)
|
||||||
|
.Select(d => new Tuple<string, bool>(d.DeviceDomainId, d.DeviceAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId)))
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
DeviceAccountId = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ActiveDirectory.IsValidDomainAccountId(result.Item1))
|
||||||
|
{
|
||||||
|
DeviceAccountId = result.Item1 + "$";
|
||||||
|
return result.Item2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DeviceAccountId = result.Item1 + "$";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessDeviceAttachmentAddEvent(RepositoryMonitorEvent e)
|
||||||
|
{
|
||||||
|
var attachment = (DeviceAttachment)e.Entity;
|
||||||
|
|
||||||
|
string deviceAccountId;
|
||||||
|
if (DeviceContainsAttachment(e.Database, attachment.DeviceSerialNumber, out deviceAccountId))
|
||||||
|
AddMember(attachment.DeviceSerialNumber, (database) => new string[] { deviceAccountId });
|
||||||
|
}
|
||||||
|
private void ProcessDeviceAttachmentRemoveEvent(Tuple<DiscoDataContext, int, string, string> e)
|
||||||
|
{
|
||||||
|
var deviceSerialNumber = e.Item3;
|
||||||
|
|
||||||
|
RemoveMember(deviceSerialNumber, (database) =>
|
||||||
|
{
|
||||||
|
string deviceAccountId;
|
||||||
|
if (!DeviceContainsAttachment(database, deviceSerialNumber, out deviceAccountId) && deviceAccountId != null)
|
||||||
|
return new string[] { deviceAccountId };
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Job Scope
|
||||||
|
private bool JobsContainAttachment(DiscoDataContext Database, int JobId, out string DeviceAccountId, out string DeviceSerialNumber)
|
||||||
|
{
|
||||||
|
var result = Database.Jobs
|
||||||
|
.Where(j => j.Id == JobId && j.Device.DeviceDomainId != null)
|
||||||
|
.Select(j => new Tuple<string, string, bool>(
|
||||||
|
j.Device.DeviceDomainId,
|
||||||
|
j.Device.SerialNumber,
|
||||||
|
j.Device.Jobs.Where(dj => !dj.ClosedDate.HasValue).Any(dj => dj.JobAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId)))
|
||||||
|
).FirstOrDefault();
|
||||||
|
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
DeviceAccountId = null;
|
||||||
|
DeviceSerialNumber = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ActiveDirectory.IsValidDomainAccountId(result.Item1))
|
||||||
|
{
|
||||||
|
DeviceAccountId = result.Item1 + "$";
|
||||||
|
DeviceSerialNumber = result.Item2;
|
||||||
|
return result.Item3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DeviceAccountId = result.Item1 + "$";
|
||||||
|
DeviceSerialNumber = result.Item2;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessJobAttachmentAddEvent(RepositoryMonitorEvent e)
|
||||||
|
{
|
||||||
|
var attachment = (JobAttachment)e.Entity;
|
||||||
|
|
||||||
|
string deviceAccountId;
|
||||||
|
string deviceSerialNumber;
|
||||||
|
if (JobsContainAttachment(e.Database, attachment.JobId, out deviceAccountId, out deviceSerialNumber))
|
||||||
|
AddMember(deviceSerialNumber, (database) => new string[] { deviceAccountId });
|
||||||
|
}
|
||||||
|
private void ProcessJobAttachmentRemoveEvent(Tuple<DiscoDataContext, int, string, int> e)
|
||||||
|
{
|
||||||
|
var jobId = e.Item4;
|
||||||
|
string deviceSerialNumber = e.Item1.Jobs.Where(j => j.Id == jobId && j.DeviceSerialNumber != null).Select(j => j.DeviceSerialNumber).FirstOrDefault();
|
||||||
|
|
||||||
|
if (deviceSerialNumber != null)
|
||||||
|
{
|
||||||
|
RemoveMember(deviceSerialNumber, (database) =>
|
||||||
|
{
|
||||||
|
string deviceAccountId;
|
||||||
|
if (!JobsContainAttachment(database, jobId, out deviceAccountId, out deviceSerialNumber) &&
|
||||||
|
deviceSerialNumber != null && deviceAccountId != null)
|
||||||
|
return new string[] { deviceAccountId };
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region User Scope
|
||||||
|
private bool DeviceUserContainAttachment(DiscoDataContext Database, string UserId, out List<Tuple<string, string>> Devices)
|
||||||
|
{
|
||||||
|
var result = Database.Users
|
||||||
|
.Where(u => u.UserId == UserId)
|
||||||
|
.Select(u => new Tuple<bool, IEnumerable<Tuple<string, string>>>(
|
||||||
|
u.UserAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId),
|
||||||
|
u.DeviceUserAssignments
|
||||||
|
.Where(dua => !dua.UnassignedDate.HasValue && dua.Device.DeviceDomainId != null)
|
||||||
|
.Select(dua => new Tuple<string, string>(dua.Device.DeviceDomainId, dua.Device.SerialNumber)))
|
||||||
|
).FirstOrDefault();
|
||||||
|
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
Devices = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Devices = result.Item2
|
||||||
|
.Where(d => ActiveDirectory.IsValidDomainAccountId(d.Item1))
|
||||||
|
.Select(d => Tuple.Create(d.Item1 + "$", d.Item2))
|
||||||
|
.ToList();
|
||||||
|
return result.Item1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessUserAttachmentAddEvent(RepositoryMonitorEvent e)
|
||||||
|
{
|
||||||
|
var attachment = (UserAttachment)e.Entity;
|
||||||
|
|
||||||
|
List<Tuple<string, string>> devices;
|
||||||
|
if (DeviceUserContainAttachment(e.Database, attachment.UserId, out devices) && devices != null)
|
||||||
|
devices.ForEach(d => AddMember(d.Item2, (database) => new string[] { d.Item1 }));
|
||||||
|
}
|
||||||
|
private void ProcessUserAttachmentRemoveEvent(Tuple<DiscoDataContext, int, string, string> e)
|
||||||
|
{
|
||||||
|
var userId = e.Item4;
|
||||||
|
|
||||||
|
RemoveMember(userId, (database) =>
|
||||||
|
{
|
||||||
|
List<Tuple<string, string>> devices;
|
||||||
|
if (!DeviceUserContainAttachment(database, userId, out devices) && devices != null)
|
||||||
|
return devices.Select(d => d.Item1);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void ProcessDeviceRenameRepositoryEvent(RepositoryMonitorEvent Event)
|
||||||
|
{
|
||||||
|
var device = (Device)Event.Entity;
|
||||||
|
var deviceSerialNumber = device.SerialNumber;
|
||||||
|
var deviceAccountId = device.DeviceDomainId;
|
||||||
|
var deviceAccountIdValid = ActiveDirectory.IsValidDomainAccountId(deviceAccountId);
|
||||||
|
var devicePreviousAccountId = Event.GetPreviousPropertyValue<string>("DeviceDomainId");
|
||||||
|
var devicePreviousAccountIdValid = ActiveDirectory.IsValidDomainAccountId(devicePreviousAccountId);
|
||||||
|
|
||||||
|
if (deviceAccountIdValid || devicePreviousAccountIdValid)
|
||||||
|
{
|
||||||
|
Event.ExecuteAfterCommit(e =>
|
||||||
|
{
|
||||||
|
switch (DocumentTemplateScope)
|
||||||
|
{
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.Device:
|
||||||
|
if (DeviceContainsAttachment(e.Database, device.SerialNumber, out deviceAccountId))
|
||||||
|
{
|
||||||
|
if (deviceAccountIdValid)
|
||||||
|
AddMember(device.SerialNumber, (database) => new string[] { deviceAccountId });
|
||||||
|
if (devicePreviousAccountIdValid)
|
||||||
|
RemoveMember(device.SerialNumber, (database) => new string[] { devicePreviousAccountId + "$" });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.Job:
|
||||||
|
var jobsHaveTemplate = e.Database.Jobs
|
||||||
|
.Where(j => !j.ClosedDate.HasValue && j.DeviceSerialNumber == deviceSerialNumber)
|
||||||
|
.Any(j => j.JobAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId));
|
||||||
|
|
||||||
|
if (jobsHaveTemplate)
|
||||||
|
{
|
||||||
|
if (deviceAccountIdValid)
|
||||||
|
AddMember(device.SerialNumber, (database) => new string[] { deviceAccountId + "$" });
|
||||||
|
if (devicePreviousAccountIdValid)
|
||||||
|
RemoveMember(device.SerialNumber, (database) => new string[] { devicePreviousAccountId + "$" });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.User:
|
||||||
|
var userHasTemplate = e.Database.Devices
|
||||||
|
.Where(d => d.SerialNumber == deviceSerialNumber)
|
||||||
|
.Select(d => d.AssignedUser)
|
||||||
|
.Any(u => u.UserAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId));
|
||||||
|
|
||||||
|
if (userHasTemplate)
|
||||||
|
{
|
||||||
|
if (deviceAccountIdValid)
|
||||||
|
AddMember(device.SerialNumber, (database) => new string[] { deviceAccountId + "$" });
|
||||||
|
if (devicePreviousAccountIdValid)
|
||||||
|
RemoveMember(device.SerialNumber, (database) => new string[] { devicePreviousAccountId + "$" });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessJobCloseRepositoryEvent(RepositoryMonitorEvent e)
|
||||||
|
{
|
||||||
|
var job = (Job)e.Entity;
|
||||||
|
|
||||||
|
if (job.DeviceSerialNumber != null)
|
||||||
|
{
|
||||||
|
var jobId = job.Id;
|
||||||
|
|
||||||
|
var relevantJob = e.Database.Jobs
|
||||||
|
.Where(j => j.Id == jobId && j.JobAttachments.Any(ja => ja.DocumentTemplateId == this.DocumentTemplateId))
|
||||||
|
.Any();
|
||||||
|
|
||||||
|
if (relevantJob)
|
||||||
|
{
|
||||||
|
string deviceAccountId;
|
||||||
|
string deviceSerialNumber;
|
||||||
|
if (JobsContainAttachment(e.Database, jobId, out deviceAccountId, out deviceSerialNumber))
|
||||||
|
AddMember(deviceSerialNumber, (database) => new string[] { deviceAccountId });
|
||||||
|
else
|
||||||
|
RemoveMember(deviceSerialNumber, (database) => new string[] { deviceAccountId });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessDeviceAssignmentRepositoryEvent(RepositoryMonitorEvent Event)
|
||||||
|
{
|
||||||
|
var device = (Device)Event.Entity;
|
||||||
|
var deviceSerialNumber = device.SerialNumber;
|
||||||
|
var deviceAccountId = device.DeviceDomainId;
|
||||||
|
|
||||||
|
if (ActiveDirectory.IsValidDomainAccountId(deviceAccountId))
|
||||||
|
{
|
||||||
|
var deviceCurrentAssignedUserId = device.AssignedUserId;
|
||||||
|
var devicePreviousAssignedUserId = Event.GetPreviousPropertyValue<string>("AssignedUserId");
|
||||||
|
|
||||||
|
Event.ExecuteAfterCommit(e =>
|
||||||
|
{
|
||||||
|
bool previousUserHasTemplate = false;
|
||||||
|
bool currentUserHasTemplate = false;
|
||||||
|
|
||||||
|
if (devicePreviousAssignedUserId != null)
|
||||||
|
previousUserHasTemplate = e.Database.Users
|
||||||
|
.Where(u => u.UserId == devicePreviousAssignedUserId && u.UserAttachments.Any(ua => ua.DocumentTemplateId == this.DocumentTemplateId))
|
||||||
|
.Any();
|
||||||
|
|
||||||
|
if (deviceCurrentAssignedUserId != null)
|
||||||
|
currentUserHasTemplate = e.Database.Users
|
||||||
|
.Where(u => u.UserId == deviceCurrentAssignedUserId && u.UserAttachments.Any(ua => ua.DocumentTemplateId == this.DocumentTemplateId))
|
||||||
|
.Any();
|
||||||
|
|
||||||
|
if (!previousUserHasTemplate && currentUserHasTemplate)
|
||||||
|
AddMember(deviceSerialNumber, (database) => new string[] { deviceAccountId + "$" });
|
||||||
|
else if (previousUserHasTemplate && !currentUserHasTemplate)
|
||||||
|
RemoveMember(deviceSerialNumber, (database) => new string[] { deviceAccountId + "$" });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
if (repositoryAddSubscription != null)
|
||||||
|
repositoryAddSubscription.Dispose();
|
||||||
|
|
||||||
|
if (repositoryRemoveSubscription != null)
|
||||||
|
repositoryRemoveSubscription.Dispose();
|
||||||
|
|
||||||
|
if (deviceRenameRepositorySubscription != null)
|
||||||
|
deviceRenameRepositorySubscription.Dispose();
|
||||||
|
|
||||||
|
if (jobCloseRepositorySubscription != null)
|
||||||
|
jobCloseRepositorySubscription.Dispose();
|
||||||
|
|
||||||
|
if (deviceAssignmentRepositorySubscription != null)
|
||||||
|
deviceAssignmentRepositorySubscription.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
using Disco.Data.Repository;
|
||||||
|
using Disco.Data.Repository.Monitor;
|
||||||
|
using Disco.Models.Repository;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reactive.Linq;
|
||||||
|
using System.Reactive.Subjects;
|
||||||
|
|
||||||
|
namespace Disco.BI.DocumentTemplateBI.ManagedGroups
|
||||||
|
{
|
||||||
|
public static class DocumentTemplateManagedGroups
|
||||||
|
{
|
||||||
|
internal static Lazy<IObservable<RepositoryMonitorEvent>> DeviceAttachmentAddRepositoryEvents;
|
||||||
|
internal static Lazy<IObservable<RepositoryMonitorEvent>> JobAttachmentAddRepositoryEvents;
|
||||||
|
internal static Lazy<IObservable<RepositoryMonitorEvent>> UserAttachmentAddRepositoryEvents;
|
||||||
|
|
||||||
|
internal static Lazy<Subject<Tuple<DiscoDataContext, int, string, string>>> DeviceAttachmentRemoveEvents;
|
||||||
|
internal static Lazy<Subject<Tuple<DiscoDataContext, int, string, int>>> JobAttachmentRemoveEvents;
|
||||||
|
internal static Lazy<Subject<Tuple<DiscoDataContext, int, string, string>>> UserAttachmentRemoveEvents;
|
||||||
|
|
||||||
|
internal static Lazy<IObservable<RepositoryMonitorEvent>> DeviceRenameRepositoryEvents;
|
||||||
|
internal static Lazy<IObservable<RepositoryMonitorEvent>> JobCloseRepositoryEvents;
|
||||||
|
internal static Lazy<IObservable<RepositoryMonitorEvent>> DeviceAssignmentRepositoryEvents;
|
||||||
|
|
||||||
|
static DocumentTemplateManagedGroups()
|
||||||
|
{
|
||||||
|
DeviceAttachmentAddRepositoryEvents =
|
||||||
|
new Lazy<IObservable<RepositoryMonitorEvent>>(() =>
|
||||||
|
RepositoryMonitor.StreamAfterCommit.Where(e =>
|
||||||
|
e.EntityType == typeof(DeviceAttachment) &&
|
||||||
|
((DeviceAttachment)e.Entity).DocumentTemplateId != null &&
|
||||||
|
e.EventType == RepositoryMonitorEventType.Added
|
||||||
|
));
|
||||||
|
JobAttachmentAddRepositoryEvents =
|
||||||
|
new Lazy<IObservable<RepositoryMonitorEvent>>(() =>
|
||||||
|
RepositoryMonitor.StreamAfterCommit.Where(e =>
|
||||||
|
e.EntityType == typeof(JobAttachment) &&
|
||||||
|
((JobAttachment)e.Entity).DocumentTemplateId != null &&
|
||||||
|
e.EventType == RepositoryMonitorEventType.Added
|
||||||
|
));
|
||||||
|
UserAttachmentAddRepositoryEvents =
|
||||||
|
new Lazy<IObservable<RepositoryMonitorEvent>>(() =>
|
||||||
|
RepositoryMonitor.StreamAfterCommit.Where(e =>
|
||||||
|
e.EntityType == typeof(UserAttachment) &&
|
||||||
|
((UserAttachment)e.Entity).DocumentTemplateId != null &&
|
||||||
|
e.EventType == RepositoryMonitorEventType.Added
|
||||||
|
));
|
||||||
|
|
||||||
|
DeviceAttachmentRemoveEvents =
|
||||||
|
new Lazy<Subject<Tuple<DiscoDataContext, int, string, string>>>(() => new Subject<Tuple<DiscoDataContext, int, string, string>>());
|
||||||
|
JobAttachmentRemoveEvents =
|
||||||
|
new Lazy<Subject<Tuple<DiscoDataContext, int, string, int>>>(() => new Subject<Tuple<DiscoDataContext, int, string, int>>());
|
||||||
|
UserAttachmentRemoveEvents =
|
||||||
|
new Lazy<Subject<Tuple<DiscoDataContext, int, string, string>>>(() => new Subject<Tuple<DiscoDataContext, int, string, string>>());
|
||||||
|
|
||||||
|
DeviceRenameRepositoryEvents =
|
||||||
|
new Lazy<IObservable<RepositoryMonitorEvent>>(() =>
|
||||||
|
RepositoryMonitor.StreamBeforeCommit.Where(e =>
|
||||||
|
e.EntityType == typeof(Device) &&
|
||||||
|
e.EventType == RepositoryMonitorEventType.Modified &&
|
||||||
|
e.ModifiedProperties.Contains("DeviceDomainId")
|
||||||
|
));
|
||||||
|
JobCloseRepositoryEvents =
|
||||||
|
new Lazy<IObservable<RepositoryMonitorEvent>>(() =>
|
||||||
|
RepositoryMonitor.StreamAfterCommit.Where(e =>
|
||||||
|
e.EntityType == typeof(Job) &&
|
||||||
|
(((Job)e.Entity).DeviceSerialNumber != null || ((Job)e.Entity).UserId != null) &&
|
||||||
|
e.EventType == RepositoryMonitorEventType.Modified &&
|
||||||
|
e.ModifiedProperties.Contains("ClosedDate")
|
||||||
|
));
|
||||||
|
DeviceAssignmentRepositoryEvents =
|
||||||
|
new Lazy<IObservable<RepositoryMonitorEvent>>(() =>
|
||||||
|
RepositoryMonitor.StreamBeforeCommit.Where(e =>
|
||||||
|
e.EntityType == typeof(Device) &&
|
||||||
|
e.EventType == RepositoryMonitorEventType.Modified &&
|
||||||
|
e.ModifiedProperties.Contains("AssignedUserId")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Initialize(DiscoDataContext Database)
|
||||||
|
{
|
||||||
|
Database.DocumentTemplates
|
||||||
|
.Where(dp => dp.DevicesLinkedGroup != null || dp.UsersLinkedGroup != null)
|
||||||
|
.ToList()
|
||||||
|
.ForEach(dp =>
|
||||||
|
{
|
||||||
|
DocumentTemplateDevicesManagedGroup.Initialize(dp);
|
||||||
|
DocumentTemplateUsersManagedGroup.Initialize(dp);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void TriggerDeviceAttachmentDeleted(DiscoDataContext Database, int AttachmentId, string DocumentTemplateId, string DeviceSerialNumber)
|
||||||
|
{
|
||||||
|
if (DocumentTemplateId != null)
|
||||||
|
DeviceAttachmentRemoveEvents.Value.OnNext(Tuple.Create(Database, AttachmentId, DocumentTemplateId, DeviceSerialNumber));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void TriggerJobAttachmentDeleted(DiscoDataContext Database, int AttachmentId, string DocumentTemplateId, int JobId)
|
||||||
|
{
|
||||||
|
if (DocumentTemplateId != null)
|
||||||
|
JobAttachmentRemoveEvents.Value.OnNext(Tuple.Create(Database, AttachmentId, DocumentTemplateId, JobId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void TriggerUserAttachmentDeleted(DiscoDataContext Database, int AttachmentId, string DocumentTemplateId, string UserId)
|
||||||
|
{
|
||||||
|
if (DocumentTemplateId != null)
|
||||||
|
UserAttachmentRemoveEvents.Value.OnNext(Tuple.Create(Database, AttachmentId, DocumentTemplateId, UserId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,365 @@
|
|||||||
|
using Disco.Data.Repository;
|
||||||
|
using Disco.Data.Repository.Monitor;
|
||||||
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Models.Services.Interop.ActiveDirectory;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reactive.Linq;
|
||||||
|
|
||||||
|
namespace Disco.BI.DocumentTemplateBI.ManagedGroups
|
||||||
|
{
|
||||||
|
public class DocumentTemplateUsersManagedGroup : ADManagedGroup
|
||||||
|
{
|
||||||
|
private const string KeyFormat = "DocumentTemplate_{0}_Users";
|
||||||
|
private const string UserDescriptionFormat = "Users with a {0} attachment will be added to this Active Directory group.";
|
||||||
|
private const string DescriptionFormat = "{0}s with a {1} attachment will have any associated users added to this Active Directory group.";
|
||||||
|
private const string CategoryDescriptionFormat = "Related Users Linked Group";
|
||||||
|
private const string GroupDescriptionFormat = "{0} [Document Template Users]";
|
||||||
|
|
||||||
|
private IDisposable repositoryAddSubscription;
|
||||||
|
private IDisposable repositoryRemoveSubscription;
|
||||||
|
private IDisposable jobCloseRepositorySubscription;
|
||||||
|
private IDisposable deviceAssignmentRepositorySubscription;
|
||||||
|
private string DocumentTemplateId;
|
||||||
|
private string DocumentTemplateDescription;
|
||||||
|
private string DocumentTemplateScope;
|
||||||
|
|
||||||
|
public override string Description { get { return GetDescription(DocumentTemplateScope, DocumentTemplateDescription); } }
|
||||||
|
public override string CategoryDescription { get { return CategoryDescriptionFormat; } }
|
||||||
|
public override string GroupDescription { get { return string.Format(GroupDescriptionFormat, DocumentTemplateDescription); } }
|
||||||
|
public override bool IncludeFilterBeginDate { get { return true; } }
|
||||||
|
|
||||||
|
private DocumentTemplateUsersManagedGroup(string Key, ADManagedGroupConfiguration Configuration, DocumentTemplate DocumentTemplate)
|
||||||
|
: base(Key, Configuration)
|
||||||
|
{
|
||||||
|
this.DocumentTemplateId = DocumentTemplate.Id;
|
||||||
|
this.DocumentTemplateDescription = DocumentTemplate.Description;
|
||||||
|
this.DocumentTemplateScope = DocumentTemplate.Scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
// Subscribe to changes
|
||||||
|
switch (DocumentTemplateScope)
|
||||||
|
{
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.Device:
|
||||||
|
// Observe Device Attachments
|
||||||
|
repositoryAddSubscription = DocumentTemplateManagedGroups.DeviceAttachmentAddRepositoryEvents.Value
|
||||||
|
.Where(e => ((DeviceAttachment)e.Entity).DocumentTemplateId == DocumentTemplateId)
|
||||||
|
.Subscribe(ProcessDeviceAttachmentAddEvent);
|
||||||
|
repositoryRemoveSubscription = DocumentTemplateManagedGroups.DeviceAttachmentRemoveEvents.Value
|
||||||
|
.Where(e => e.Item3 == DocumentTemplateId)
|
||||||
|
.Subscribe(ProcessDeviceAttachmentRemoveEvent);
|
||||||
|
// Observe Device Assignments
|
||||||
|
deviceAssignmentRepositorySubscription = DocumentTemplateManagedGroups.DeviceAssignmentRepositoryEvents.Value
|
||||||
|
.Subscribe(ProcessDeviceAssignmentRepositoryEvent);
|
||||||
|
break;
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.Job:
|
||||||
|
// Observe Job Attachments
|
||||||
|
repositoryAddSubscription = DocumentTemplateManagedGroups.UserAttachmentAddRepositoryEvents.Value
|
||||||
|
.Where(e => ((JobAttachment)e.Entity).DocumentTemplateId == DocumentTemplateId)
|
||||||
|
.Subscribe(ProcessJobAttachmentAddEvent);
|
||||||
|
repositoryRemoveSubscription = DocumentTemplateManagedGroups.JobAttachmentRemoveEvents.Value
|
||||||
|
.Where(e => e.Item3 == DocumentTemplateId)
|
||||||
|
.Subscribe(ProcessJobAttachmentRemoveEvent);
|
||||||
|
// Observe Job Close/Reopen
|
||||||
|
jobCloseRepositorySubscription = DocumentTemplateManagedGroups.JobCloseRepositoryEvents.Value
|
||||||
|
.Subscribe(ProcessJobCloseRepositoryEvent);
|
||||||
|
break;
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.User:
|
||||||
|
// Observe User Attachments
|
||||||
|
repositoryAddSubscription = DocumentTemplateManagedGroups.UserAttachmentAddRepositoryEvents.Value
|
||||||
|
.Where(e => ((UserAttachment)e.Entity).DocumentTemplateId == DocumentTemplateId)
|
||||||
|
.Subscribe(ProcessUserAttachmentAddEvent);
|
||||||
|
repositoryRemoveSubscription = DocumentTemplateManagedGroups.UserAttachmentRemoveEvents.Value
|
||||||
|
.Where(e => e.Item3 == DocumentTemplateId)
|
||||||
|
.Subscribe(ProcessUserAttachmentRemoveEvent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetKey(DocumentTemplate DocumentTemplate)
|
||||||
|
{
|
||||||
|
return string.Format(KeyFormat, DocumentTemplate.Id);
|
||||||
|
}
|
||||||
|
private static string GetDescription(string DocumentTemplateScope, string DocumentTemplateDescription)
|
||||||
|
{
|
||||||
|
switch (DocumentTemplateScope)
|
||||||
|
{
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.Device:
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.Job:
|
||||||
|
return string.Format(DescriptionFormat, DocumentTemplateScope, DocumentTemplateDescription);
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.User:
|
||||||
|
return string.Format(UserDescriptionFormat, DocumentTemplateDescription);
|
||||||
|
default:
|
||||||
|
throw new ArgumentException("Unknown Document Template Scope", "Scope");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static string GetDescription(DocumentTemplate DocumentTemplate)
|
||||||
|
{
|
||||||
|
return GetDescription(DocumentTemplate.Scope, DocumentTemplate.Description);
|
||||||
|
}
|
||||||
|
public static string GetCategoryDescription(DocumentTemplate DocumentTemplate)
|
||||||
|
{
|
||||||
|
return CategoryDescriptionFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetManagedGroup(DocumentTemplate DocumentTemplate, out DocumentTemplateUsersManagedGroup ManagedGroup)
|
||||||
|
{
|
||||||
|
ADManagedGroup managedGroup;
|
||||||
|
string key = GetKey(DocumentTemplate);
|
||||||
|
|
||||||
|
if (ActiveDirectory.Context.ManagedGroups.TryGetValue(key, out managedGroup))
|
||||||
|
{
|
||||||
|
ManagedGroup = (DocumentTemplateUsersManagedGroup)managedGroup;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ManagedGroup = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DocumentTemplateUsersManagedGroup Initialize(DocumentTemplate Template)
|
||||||
|
{
|
||||||
|
var key = GetKey(Template);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(Template.UsersLinkedGroup))
|
||||||
|
{
|
||||||
|
var config = ADManagedGroup.ConfigurationFromJson(Template.UsersLinkedGroup);
|
||||||
|
|
||||||
|
if (config != null && !string.IsNullOrWhiteSpace(config.GroupId))
|
||||||
|
{
|
||||||
|
var group = new DocumentTemplateUsersManagedGroup(
|
||||||
|
key,
|
||||||
|
config,
|
||||||
|
Template);
|
||||||
|
|
||||||
|
// Add to AD Context
|
||||||
|
ActiveDirectory.Context.ManagedGroups.AddOrUpdate(group);
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove from AD Context
|
||||||
|
ActiveDirectory.Context.ManagedGroups.Remove(key);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<string> DetermineMembers(DiscoDataContext Database)
|
||||||
|
{
|
||||||
|
switch (DocumentTemplateScope)
|
||||||
|
{
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.Device:
|
||||||
|
return Database.Devices
|
||||||
|
.Where(d => d.AssignedUserId != null && d.DeviceAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId))
|
||||||
|
.Select(d => d.AssignedUserId);
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.Job:
|
||||||
|
return Database.Jobs
|
||||||
|
.Where(j => !j.ClosedDate.HasValue && j.UserId != null && j.JobAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId))
|
||||||
|
.Select(j => j.UserId)
|
||||||
|
.Distinct();
|
||||||
|
case DocumentTemplate.DocumentTemplateScopes.User:
|
||||||
|
return Database.Users
|
||||||
|
.Where(u => u.UserAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId))
|
||||||
|
.Select(u => u.UserId);
|
||||||
|
default:
|
||||||
|
return Enumerable.Empty<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Device Scope
|
||||||
|
private bool DeviceContainsAttachment(DiscoDataContext Database, string DeviceSerialNumber, out string UserId)
|
||||||
|
{
|
||||||
|
var result = Database.Devices
|
||||||
|
.Where(d => d.SerialNumber == DeviceSerialNumber && d.AssignedUser != null)
|
||||||
|
.Select(d => new Tuple<string, bool>(d.AssignedUserId, d.DeviceAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId)))
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
UserId = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UserId = result.Item1;
|
||||||
|
return result.Item2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessDeviceAttachmentAddEvent(RepositoryMonitorEvent e)
|
||||||
|
{
|
||||||
|
var attachment = (DeviceAttachment)e.Entity;
|
||||||
|
|
||||||
|
string userId;
|
||||||
|
if (DeviceContainsAttachment(e.Database, attachment.DeviceSerialNumber, out userId) && userId != null)
|
||||||
|
AddMember(userId, (database) => new string[] { userId });
|
||||||
|
}
|
||||||
|
private void ProcessDeviceAttachmentRemoveEvent(Tuple<DiscoDataContext, int, string, string> e)
|
||||||
|
{
|
||||||
|
var deviceSerialNumber = e.Item4;
|
||||||
|
string userId = e.Item1.Devices.Where(d => d.SerialNumber == deviceSerialNumber && d.AssignedUserId != null).Select(j => j.AssignedUserId).FirstOrDefault();
|
||||||
|
|
||||||
|
if (userId != null)
|
||||||
|
{
|
||||||
|
RemoveMember(userId, (database) =>
|
||||||
|
{
|
||||||
|
if (DeviceContainsAttachment(database, deviceSerialNumber, out userId) && userId != null)
|
||||||
|
return new string[] { userId };
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Job Scope
|
||||||
|
private bool JobsContainAttachment(DiscoDataContext Database, int JobId, out string UserId)
|
||||||
|
{
|
||||||
|
var result = Database.Jobs
|
||||||
|
.Where(j => j.Id == JobId && j.UserId != null)
|
||||||
|
.Select(j => new Tuple<string, bool>(
|
||||||
|
j.UserId,
|
||||||
|
j.User.Jobs.Where(uj => !uj.ClosedDate.HasValue).Any(uj => uj.JobAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId)))
|
||||||
|
).FirstOrDefault();
|
||||||
|
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
UserId = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UserId = result.Item1;
|
||||||
|
return result.Item2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessJobAttachmentAddEvent(RepositoryMonitorEvent e)
|
||||||
|
{
|
||||||
|
var attachment = (JobAttachment)e.Entity;
|
||||||
|
|
||||||
|
string userId;
|
||||||
|
if (JobsContainAttachment(e.Database, attachment.JobId, out userId) && userId != null)
|
||||||
|
AddMember(userId, (database) => new string[] { userId });
|
||||||
|
}
|
||||||
|
private void ProcessJobAttachmentRemoveEvent(Tuple<DiscoDataContext, int, string, int> e)
|
||||||
|
{
|
||||||
|
var jobId = e.Item4;
|
||||||
|
string userId = e.Item1.Jobs.Where(j => j.Id == jobId && j.UserId != null).Select(j => j.UserId).FirstOrDefault();
|
||||||
|
|
||||||
|
if (userId != null)
|
||||||
|
{
|
||||||
|
RemoveMember(userId, (database) =>
|
||||||
|
{
|
||||||
|
if (JobsContainAttachment(database, jobId, out userId) && userId != null)
|
||||||
|
return new string[] { userId };
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region User Scope
|
||||||
|
private bool UserContainAttachment(DiscoDataContext Database, string UserId)
|
||||||
|
{
|
||||||
|
var result = Database.Users
|
||||||
|
.Where(u => u.UserId == UserId)
|
||||||
|
.Any(u => u.UserAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessUserAttachmentAddEvent(RepositoryMonitorEvent e)
|
||||||
|
{
|
||||||
|
var attachment = (UserAttachment)e.Entity;
|
||||||
|
var userId = attachment.UserId;
|
||||||
|
|
||||||
|
if (UserContainAttachment(e.Database, userId) && userId != null)
|
||||||
|
AddMember(userId, (database) => new string[] { userId });
|
||||||
|
}
|
||||||
|
private void ProcessUserAttachmentRemoveEvent(Tuple<DiscoDataContext, int, string, string> e)
|
||||||
|
{
|
||||||
|
var userId = e.Item4;
|
||||||
|
|
||||||
|
RemoveMember(userId, (database) =>
|
||||||
|
{
|
||||||
|
if (!UserContainAttachment(database, userId))
|
||||||
|
return new string[] { userId };
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void ProcessJobCloseRepositoryEvent(RepositoryMonitorEvent e)
|
||||||
|
{
|
||||||
|
var job = (Job)e.Entity;
|
||||||
|
|
||||||
|
if (job.UserId != null)
|
||||||
|
{
|
||||||
|
var jobId = job.Id;
|
||||||
|
|
||||||
|
var relevantJob = e.Database.Jobs
|
||||||
|
.Where(j => j.Id == jobId && j.JobAttachments.Any(ja => ja.DocumentTemplateId == this.DocumentTemplateId))
|
||||||
|
.Any();
|
||||||
|
|
||||||
|
if (relevantJob)
|
||||||
|
{
|
||||||
|
string userId;
|
||||||
|
if (JobsContainAttachment(e.Database, jobId, out userId))
|
||||||
|
AddMember(userId, (database) => new string[] { userId });
|
||||||
|
else
|
||||||
|
RemoveMember(userId, (database) => new string[] { userId });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessDeviceAssignmentRepositoryEvent(RepositoryMonitorEvent Event)
|
||||||
|
{
|
||||||
|
var device = (Device)Event.Entity;
|
||||||
|
var deviceSerialNumber = device.SerialNumber;
|
||||||
|
|
||||||
|
var relevantDevice = Event.Database.Devices
|
||||||
|
.Where(d => d.SerialNumber == deviceSerialNumber && d.DeviceAttachments.Any(ja => ja.DocumentTemplateId == this.DocumentTemplateId))
|
||||||
|
.Any();
|
||||||
|
|
||||||
|
if (relevantDevice)
|
||||||
|
{
|
||||||
|
var deviceCurrentAssignedUserId = device.AssignedUserId;
|
||||||
|
var devicePreviousAssignedUserId = Event.GetPreviousPropertyValue<string>("AssignedUserId");
|
||||||
|
|
||||||
|
Event.ExecuteAfterCommit(e =>
|
||||||
|
{
|
||||||
|
if (devicePreviousAssignedUserId != null)
|
||||||
|
RemoveMember(devicePreviousAssignedUserId, (database) => new string[] { devicePreviousAssignedUserId });
|
||||||
|
|
||||||
|
if (deviceCurrentAssignedUserId != null)
|
||||||
|
AddMember(deviceCurrentAssignedUserId, (database) => new string[] { deviceCurrentAssignedUserId });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
if (repositoryAddSubscription != null)
|
||||||
|
repositoryAddSubscription.Dispose();
|
||||||
|
|
||||||
|
if (repositoryRemoveSubscription != null)
|
||||||
|
repositoryRemoveSubscription.Dispose();
|
||||||
|
|
||||||
|
if (jobCloseRepositorySubscription != null)
|
||||||
|
jobCloseRepositorySubscription.Dispose();
|
||||||
|
|
||||||
|
if (deviceAssignmentRepositorySubscription != null)
|
||||||
|
deviceAssignmentRepositorySubscription.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,9 @@
|
|||||||
using System;
|
using Disco.BI.Extensions;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Disco.Services.Tasks;
|
|
||||||
using Disco.Data.Repository;
|
using Disco.Data.Repository;
|
||||||
|
using Disco.Services.Tasks;
|
||||||
using Quartz;
|
using Quartz;
|
||||||
using Disco.BI.Extensions;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Disco.BI.Expressions
|
namespace Disco.BI.Expressions
|
||||||
{
|
{
|
||||||
@@ -16,10 +13,11 @@ namespace Disco.BI.Expressions
|
|||||||
public override string TaskName { get { return "Expression Cache - Preload Task"; } }
|
public override string TaskName { get { return "Expression Cache - Preload Task"; } }
|
||||||
public override bool SingleInstanceTask { get { return true; } }
|
public override bool SingleInstanceTask { get { return true; } }
|
||||||
public override bool CancelInitiallySupported { get { return false; } }
|
public override bool CancelInitiallySupported { get { return false; } }
|
||||||
|
public override bool LogExceptionsOnly { get { return true; } }
|
||||||
|
|
||||||
public override void InitalizeScheduledTask(DiscoDataContext Database)
|
public override void InitalizeScheduledTask(DiscoDataContext Database)
|
||||||
{
|
{
|
||||||
// Run in Background 1 Second after Scheduled (on App Startup)
|
// Run in Background 5 Second after Scheduled (on App Startup)
|
||||||
TriggerBuilder triggerBuilder = TriggerBuilder.Create().StartAt(new DateTimeOffset(DateTime.Now).AddSeconds(5));
|
TriggerBuilder triggerBuilder = TriggerBuilder.Create().StartAt(new DateTimeOffset(DateTime.Now).AddSeconds(5));
|
||||||
|
|
||||||
this.ScheduleTask(triggerBuilder);
|
this.ScheduleTask(triggerBuilder);
|
||||||
@@ -36,8 +34,6 @@ namespace Disco.BI.Expressions
|
|||||||
documentTemplate.FilterExpressionFromCache();
|
documentTemplate.FilterExpressionFromCache();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
using System;
|
using Disco.BI.Extensions;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
using Disco.BI.Extensions;
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
using Disco.BI.Interop.ActiveDirectory;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Disco.BI.Expressions.Extensions
|
namespace Disco.BI.Expressions.Extensions
|
||||||
{
|
{
|
||||||
@@ -14,7 +12,7 @@ namespace Disco.BI.Expressions.Extensions
|
|||||||
{
|
{
|
||||||
var adMachineAccount = Device.ActiveDirectoryAccount(PropertyName);
|
var adMachineAccount = Device.ActiveDirectoryAccount(PropertyName);
|
||||||
if (adMachineAccount != null)
|
if (adMachineAccount != null)
|
||||||
return adMachineAccount.GetPropertyValue(PropertyName, Index);
|
return adMachineAccount.GetPropertyValues<object>(PropertyName).Skip(Index).FirstOrDefault();
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace Disco.BI.Expressions.Extensions
|
|||||||
}
|
}
|
||||||
public static FileImageExpressionResult JobAttachmentFirstImage(Job Job, DiscoDataContext Database)
|
public static FileImageExpressionResult JobAttachmentFirstImage(Job Job, DiscoDataContext Database)
|
||||||
{
|
{
|
||||||
var attachment = Job.JobAttachments.FirstOrDefault(ja => ja.MimeType.StartsWith("image/", StringComparison.InvariantCultureIgnoreCase));
|
var attachment = Job.JobAttachments.FirstOrDefault(ja => ja.MimeType.StartsWith("image/", StringComparison.OrdinalIgnoreCase));
|
||||||
if (attachment != null)
|
if (attachment != null)
|
||||||
{
|
{
|
||||||
var filename = attachment.RepositoryFilename(Database);
|
var filename = attachment.RepositoryFilename(Database);
|
||||||
@@ -39,7 +39,7 @@ namespace Disco.BI.Expressions.Extensions
|
|||||||
}
|
}
|
||||||
public static FileImageExpressionResult JobAttachmentLastImage(Job Job, DiscoDataContext Database)
|
public static FileImageExpressionResult JobAttachmentLastImage(Job Job, DiscoDataContext Database)
|
||||||
{
|
{
|
||||||
var attachment = Job.JobAttachments.LastOrDefault(ja => ja.MimeType.StartsWith("image/", StringComparison.InvariantCultureIgnoreCase));
|
var attachment = Job.JobAttachments.LastOrDefault(ja => ja.MimeType.StartsWith("image/", StringComparison.OrdinalIgnoreCase));
|
||||||
if (attachment != null)
|
if (attachment != null)
|
||||||
{
|
{
|
||||||
var filename = attachment.RepositoryFilename(Database);
|
var filename = attachment.RepositoryFilename(Database);
|
||||||
@@ -52,7 +52,7 @@ namespace Disco.BI.Expressions.Extensions
|
|||||||
{
|
{
|
||||||
if (JobAttachment == null)
|
if (JobAttachment == null)
|
||||||
throw new ArgumentNullException("JobAttachment");
|
throw new ArgumentNullException("JobAttachment");
|
||||||
if (!JobAttachment.MimeType.StartsWith("image/", StringComparison.InvariantCultureIgnoreCase))
|
if (!JobAttachment.MimeType.StartsWith("image/", StringComparison.OrdinalIgnoreCase))
|
||||||
throw new ArgumentException("Invalid Image MimeType for Attachment");
|
throw new ArgumentException("Invalid Image MimeType for Attachment");
|
||||||
|
|
||||||
var filename = JobAttachment.RepositoryFilename(Database);
|
var filename = JobAttachment.RepositoryFilename(Database);
|
||||||
@@ -65,7 +65,7 @@ namespace Disco.BI.Expressions.Extensions
|
|||||||
if (Job.JobAttachments == null)
|
if (Job.JobAttachments == null)
|
||||||
throw new ArgumentException("Job.JobAttachments is null", "Job");
|
throw new ArgumentException("Job.JobAttachments is null", "Job");
|
||||||
|
|
||||||
var attachments = Job.JobAttachments.Where(a => a.MimeType.StartsWith("image/", StringComparison.InvariantCultureIgnoreCase)).ToList();
|
var attachments = Job.JobAttachments.Where(a => a.MimeType.StartsWith("image/", StringComparison.OrdinalIgnoreCase)).ToList();
|
||||||
|
|
||||||
if (attachments.Count > 0)
|
if (attachments.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -81,7 +81,7 @@ namespace Disco.BI.Expressions.Extensions
|
|||||||
if (JobAttachments == null)
|
if (JobAttachments == null)
|
||||||
throw new ArgumentNullException("JobAttachments");
|
throw new ArgumentNullException("JobAttachments");
|
||||||
|
|
||||||
var attachments = JobAttachments.Cast<JobAttachment>().Where(a => a.MimeType.StartsWith("image/", StringComparison.InvariantCultureIgnoreCase)).ToList();
|
var attachments = JobAttachments.Cast<JobAttachment>().Where(a => a.MimeType.StartsWith("image/", StringComparison.OrdinalIgnoreCase)).ToList();
|
||||||
|
|
||||||
if (attachments.Count > 0)
|
if (attachments.Count > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
using System;
|
using Disco.BI.Extensions;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
using Disco.BI.Extensions;
|
using Disco.Services.Users;
|
||||||
using Disco.BI.Interop.ActiveDirectory;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Disco.BI.Expressions.Extensions
|
namespace Disco.BI.Expressions.Extensions
|
||||||
{
|
{
|
||||||
public static class UserExt
|
public static class UserExt
|
||||||
{
|
{
|
||||||
|
#region Active Directory Extensions
|
||||||
public static object GetActiveDirectoryObjectValue(User User, string PropertyName, int Index = 0)
|
public static object GetActiveDirectoryObjectValue(User User, string PropertyName, int Index = 0)
|
||||||
{
|
{
|
||||||
var adUserAccount = User.ActiveDirectoryAccount(PropertyName);
|
var adUserAccount = User.ActiveDirectoryAccount(PropertyName);
|
||||||
if (adUserAccount != null)
|
if (adUserAccount != null)
|
||||||
return adUserAccount.GetPropertyValue(PropertyName, Index);
|
return adUserAccount.GetPropertyValues<object>(PropertyName).Skip(Index).FirstOrDefault();
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -47,5 +46,29 @@ namespace Disco.BI.Expressions.Extensions
|
|||||||
return intValue;
|
return intValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Authorization Testing Extensions
|
||||||
|
public static bool HasAuthorization(User User, string Claim)
|
||||||
|
{
|
||||||
|
var authorization = UserService.GetAuthorization(User.UserId);
|
||||||
|
|
||||||
|
return authorization.Has(Claim);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HasAuthorizationAll(User User, params string[] Claims)
|
||||||
|
{
|
||||||
|
var authorization = UserService.GetAuthorization(User.UserId);
|
||||||
|
|
||||||
|
return authorization.HasAll(Claims);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HasAuthorizationAny(User User, params string[] Claims)
|
||||||
|
{
|
||||||
|
var authorization = UserService.GetAuthorization(User.UserId);
|
||||||
|
|
||||||
|
return authorization.HasAny(Claims);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Disco.Models.Repository;
|
|||||||
using Disco.Data.Repository;
|
using Disco.Data.Repository;
|
||||||
using Disco.Services.Users;
|
using Disco.Services.Users;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
|
using Disco.BI.DocumentTemplateBI.ManagedGroups;
|
||||||
|
|
||||||
namespace Disco.BI.Extensions
|
namespace Disco.BI.Extensions
|
||||||
{
|
{
|
||||||
@@ -29,8 +30,14 @@ namespace Disco.BI.Extensions
|
|||||||
if (!da.CanDelete())
|
if (!da.CanDelete())
|
||||||
throw new InvalidOperationException("Deletion of Attachment is Denied");
|
throw new InvalidOperationException("Deletion of Attachment is Denied");
|
||||||
|
|
||||||
|
var attachmentId = da.Id;
|
||||||
|
var documentTemplateId = da.DocumentTemplateId;
|
||||||
|
var deviceSerialNumber = da.DeviceSerialNumber;
|
||||||
|
|
||||||
da.RepositoryDelete(Database);
|
da.RepositoryDelete(Database);
|
||||||
Database.DeviceAttachments.Remove(da);
|
Database.DeviceAttachments.Remove(da);
|
||||||
|
|
||||||
|
DocumentTemplateManagedGroups.TriggerDeviceAttachmentDeleted(Database, attachmentId, documentTemplateId, deviceSerialNumber);
|
||||||
}
|
}
|
||||||
public static bool CanDelete(this JobAttachment ja)
|
public static bool CanDelete(this JobAttachment ja)
|
||||||
{
|
{
|
||||||
@@ -48,8 +55,14 @@ namespace Disco.BI.Extensions
|
|||||||
if (!ja.CanDelete())
|
if (!ja.CanDelete())
|
||||||
throw new InvalidOperationException("Deletion of Attachment is Denied");
|
throw new InvalidOperationException("Deletion of Attachment is Denied");
|
||||||
|
|
||||||
|
var attachmentId = ja.Id;
|
||||||
|
var documentTemplateId = ja.DocumentTemplateId;
|
||||||
|
var jobId = ja.JobId;
|
||||||
|
|
||||||
ja.RepositoryDelete(Database);
|
ja.RepositoryDelete(Database);
|
||||||
Database.JobAttachments.Remove(ja);
|
Database.JobAttachments.Remove(ja);
|
||||||
|
|
||||||
|
DocumentTemplateManagedGroups.TriggerJobAttachmentDeleted(Database, attachmentId, documentTemplateId, jobId);
|
||||||
}
|
}
|
||||||
public static bool CanDelete(this UserAttachment ua)
|
public static bool CanDelete(this UserAttachment ua)
|
||||||
{
|
{
|
||||||
@@ -67,8 +80,14 @@ namespace Disco.BI.Extensions
|
|||||||
if (!ua.CanDelete())
|
if (!ua.CanDelete())
|
||||||
throw new InvalidOperationException("Deletion of Attachment is Denied");
|
throw new InvalidOperationException("Deletion of Attachment is Denied");
|
||||||
|
|
||||||
|
var attachmentId = ua.Id;
|
||||||
|
var documentTemplateId = ua.DocumentTemplateId;
|
||||||
|
var userId = ua.UserId;
|
||||||
|
|
||||||
ua.RepositoryDelete(Database);
|
ua.RepositoryDelete(Database);
|
||||||
Database.UserAttachments.Remove(ua);
|
Database.UserAttachments.Remove(ua);
|
||||||
|
|
||||||
|
DocumentTemplateManagedGroups.TriggerUserAttachmentDeleted(Database, attachmentId, documentTemplateId, userId);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace Disco.BI.Extensions
|
|||||||
|
|
||||||
if (documentTemplate == null)
|
if (documentTemplate == null)
|
||||||
{
|
{
|
||||||
filename = string.Format("{0}_{1:yyyyMMdd-HHmmss}.pdf", UniqueIdentifier.DataId, UniqueIdentifier.TimeStamp);
|
filename = string.Format("{0}_{1:yyyyMMdd-HHmmss}.pdf", UniqueIdentifier.DataId.Replace('\\', '_'), UniqueIdentifier.TimeStamp);
|
||||||
comments = string.Format("Uploaded: {0:s}", UniqueIdentifier.TimeStamp);
|
comments = string.Format("Uploaded: {0:s}", UniqueIdentifier.TimeStamp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -68,7 +68,7 @@ namespace Disco.BI.Extensions
|
|||||||
}
|
}
|
||||||
public static string RepositoryFilename(this UserAttachment ua, DiscoDataContext Database)
|
public static string RepositoryFilename(this UserAttachment ua, DiscoDataContext Database)
|
||||||
{
|
{
|
||||||
return Path.Combine(DataStore.CreateLocation(Database, "UserAttachments", ua.Timestamp), string.Format("{0}_{1}_file", ua.UserId, ua.Id));
|
return Path.Combine(DataStore.CreateLocation(Database, "UserAttachments", ua.Timestamp), string.Format("{0}_{1}_file", ua.UserId.Replace('\\', '_'), ua.Id));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string RepositoryThumbnailFilenameInternal(string DirectoryPath, string Filename)
|
private static string RepositoryThumbnailFilenameInternal(string DirectoryPath, string Filename)
|
||||||
@@ -85,7 +85,7 @@ namespace Disco.BI.Extensions
|
|||||||
}
|
}
|
||||||
public static string RepositoryThumbnailFilename(this UserAttachment ua, DiscoDataContext Database)
|
public static string RepositoryThumbnailFilename(this UserAttachment ua, DiscoDataContext Database)
|
||||||
{
|
{
|
||||||
return RepositoryThumbnailFilenameInternal(DataStore.CreateLocation(Database, "UserAttachments", ua.Timestamp), string.Format("{0}_{1}_thumb.jpg", ua.UserId, ua.Id));
|
return RepositoryThumbnailFilenameInternal(DataStore.CreateLocation(Database, "UserAttachments", ua.Timestamp), string.Format("{0}_{1}_thumb.jpg", ua.UserId.Replace('\\', '_'), ua.Id));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RepositoryDelete(this DeviceAttachment da, DiscoDataContext Database)
|
public static void RepositoryDelete(this DeviceAttachment da, DiscoDataContext Database)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using Disco.Data.Repository;
|
using Disco.Data.Repository;
|
||||||
using Disco.Models.Authorization;
|
using Disco.Models.Services.Authorization;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
using Disco.Services.Users;
|
using Disco.Services.Users;
|
||||||
using System;
|
using System;
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ namespace Disco.BI.Extensions
|
|||||||
|
|
||||||
WhoAmIResponse response = new WhoAmIResponse()
|
WhoAmIResponse response = new WhoAmIResponse()
|
||||||
{
|
{
|
||||||
Username = token.User.Id,
|
Username = token.User.UserId,
|
||||||
DisplayName = token.User.DisplayName,
|
DisplayName = token.User.DisplayName,
|
||||||
Type = token.Has(Claims.ComputerAccount) ? "Computer Account" : "User Account"
|
Type = token.Has(Claims.ComputerAccount) ? "Computer Account" : "User Account"
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
using System;
|
using Disco.Data.Repository;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
using Disco.Data.Repository;
|
|
||||||
using Disco.BI.Interop.ActiveDirectory;
|
|
||||||
using Disco.Services.Users;
|
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
|
using Disco.Services.Users;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Disco.BI.Extensions
|
namespace Disco.BI.Extensions
|
||||||
{
|
{
|
||||||
@@ -19,7 +17,7 @@ namespace Disco.BI.Extensions
|
|||||||
|
|
||||||
public static bool CanCreateJob(this Device d)
|
public static bool CanCreateJob(this Device d)
|
||||||
{
|
{
|
||||||
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.Create))
|
if (!JobActionExtensions.CanCreate())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return !d.IsDecommissioned();
|
return !d.IsDecommissioned();
|
||||||
@@ -81,7 +79,7 @@ namespace Disco.BI.Extensions
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
public static void OnDecommission(this Device d, Disco.Models.Repository.Device.DecommissionReasons Reason)
|
public static void OnDecommission(this Device d, Disco.Models.Repository.DecommissionReasons Reason)
|
||||||
{
|
{
|
||||||
if (!d.CanDecommission())
|
if (!d.CanDecommission())
|
||||||
throw new InvalidOperationException("Decommission of Device is Denied");
|
throw new InvalidOperationException("Decommission of Device is Denied");
|
||||||
@@ -90,7 +88,7 @@ namespace Disco.BI.Extensions
|
|||||||
d.DecommissionReason = Reason;
|
d.DecommissionReason = Reason;
|
||||||
|
|
||||||
// Disable AD Account
|
// Disable AD Account
|
||||||
if (d.ComputerName != null)
|
if (d.DeviceDomainId != null)
|
||||||
{
|
{
|
||||||
var adAccount = d.ActiveDirectoryAccount();
|
var adAccount = d.ActiveDirectoryAccount();
|
||||||
if (adAccount != null && !adAccount.IsCriticalSystemObject)
|
if (adAccount != null && !adAccount.IsCriticalSystemObject)
|
||||||
@@ -117,7 +115,7 @@ namespace Disco.BI.Extensions
|
|||||||
d.DecommissionReason = null;
|
d.DecommissionReason = null;
|
||||||
|
|
||||||
// Enable AD Account
|
// Enable AD Account
|
||||||
if (d.ComputerName != null)
|
if (d.DeviceDomainId != null)
|
||||||
{
|
{
|
||||||
var adAccount = d.ActiveDirectoryAccount();
|
var adAccount = d.ActiveDirectoryAccount();
|
||||||
if (adAccount != null && !adAccount.IsCriticalSystemObject)
|
if (adAccount != null && !adAccount.IsCriticalSystemObject)
|
||||||
@@ -157,10 +155,10 @@ namespace Disco.BI.Extensions
|
|||||||
JobLog jobLog = new JobLog()
|
JobLog jobLog = new JobLog()
|
||||||
{
|
{
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
TechUserId = UserService.CurrentUser.Id,
|
TechUserId = UserService.CurrentUser.UserId,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
Comments = string.Format("Device Deleted{0}{0}Serial Number: {1}{0}Computer Name: {2}{0}Model: {3}{0}Profile: {4}",
|
Comments = string.Format("Device Deleted{0}{0}Serial Number: {1}{0}Computer Name: {2}{0}Model: {3}{0}Profile: {4}",
|
||||||
Environment.NewLine, d.SerialNumber, d.ComputerName, d.DeviceModel, d.DeviceProfile)
|
Environment.NewLine, d.SerialNumber, d.DeviceDomainId, d.DeviceModel, d.DeviceProfile)
|
||||||
};
|
};
|
||||||
Database.JobLogs.Add(jobLog);
|
Database.JobLogs.Add(jobLog);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,13 +10,6 @@ namespace Disco.BI.Extensions
|
|||||||
{
|
{
|
||||||
public static class DeviceDetailExtensions
|
public static class DeviceDetailExtensions
|
||||||
{
|
{
|
||||||
|
|
||||||
#region Scope Declaration
|
|
||||||
|
|
||||||
public const string ScopeHardware = "Hardware";
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Helpers
|
#region Helpers
|
||||||
private static string GetDetail(this IEnumerable<DeviceDetail> details, string Scope, string Key)
|
private static string GetDetail(this IEnumerable<DeviceDetail> details, string Scope, string Key)
|
||||||
{
|
{
|
||||||
@@ -77,61 +70,93 @@ namespace Disco.BI.Extensions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region LanMacAddress
|
#region LanMacAddress
|
||||||
public const string KeyLanMacAddress = "LanMacAddress";
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the LanMacAddress Device Detail Value
|
/// Gets the LanMacAddress Device Detail Value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The LanMacAddress or null</returns>
|
/// <returns>The LanMacAddress or null</returns>
|
||||||
public static string LanMacAddress(this IEnumerable<DeviceDetail> details)
|
public static string LanMacAddress(this IEnumerable<DeviceDetail> details)
|
||||||
{
|
{
|
||||||
return details.GetDetail(ScopeHardware, KeyLanMacAddress);
|
return details.GetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyLanMacAddress);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the LanMacAddress Device Detail Value
|
/// Sets the LanMacAddress Device Detail Value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void LanMacAddress(this IEnumerable<DeviceDetail> details, Device device, string LanMacAddress)
|
public static void LanMacAddress(this IEnumerable<DeviceDetail> details, Device device, string LanMacAddress)
|
||||||
{
|
{
|
||||||
device.SetDetail(ScopeHardware, KeyLanMacAddress, LanMacAddress);
|
device.SetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyLanMacAddress, LanMacAddress);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region WLanMacAddress
|
#region WLanMacAddress
|
||||||
public const string KeyWLanMacAddress = "WLanMacAddress";
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the WLanMacAddress Device Detail Value
|
/// Gets the WLanMacAddress Device Detail Value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The WLanMacAddress or null</returns>
|
/// <returns>The WLanMacAddress or null</returns>
|
||||||
public static string WLanMacAddress(this IEnumerable<DeviceDetail> details)
|
public static string WLanMacAddress(this IEnumerable<DeviceDetail> details)
|
||||||
{
|
{
|
||||||
return details.GetDetail(ScopeHardware, KeyWLanMacAddress);
|
return details.GetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyWLanMacAddress);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the WLanMacAddress Device Detail Value
|
/// Sets the WLanMacAddress Device Detail Value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void WLanMacAddress(this IEnumerable<DeviceDetail> details, Device device, string WLanMacAddress)
|
public static void WLanMacAddress(this IEnumerable<DeviceDetail> details, Device device, string WLanMacAddress)
|
||||||
{
|
{
|
||||||
device.SetDetail(ScopeHardware, KeyWLanMacAddress, WLanMacAddress);
|
device.SetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyWLanMacAddress, WLanMacAddress);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ACAdapter
|
#region ACAdapter
|
||||||
public const string KeyACAdapter = "ACAdapter";
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the ACAdapter Device Detail Value
|
/// Gets the ACAdapter Device Detail Value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The ACAdapter or null</returns>
|
/// <returns>The ACAdapter or null</returns>
|
||||||
public static string ACAdapter(this IEnumerable<DeviceDetail> details)
|
public static string ACAdapter(this IEnumerable<DeviceDetail> details)
|
||||||
{
|
{
|
||||||
return details.GetDetail(ScopeHardware, KeyACAdapter);
|
return details.GetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyACAdapter);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the ACAdapter Device Detail Value
|
/// Sets the ACAdapter Device Detail Value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void ACAdapter(this IEnumerable<DeviceDetail> details, Device device, string ACAdapter)
|
public static void ACAdapter(this IEnumerable<DeviceDetail> details, Device device, string ACAdapter)
|
||||||
{
|
{
|
||||||
device.SetDetail(ScopeHardware, KeyACAdapter, ACAdapter);
|
device.SetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyACAdapter, ACAdapter);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Battery
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Battery Device Detail Value
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The Battery or null</returns>
|
||||||
|
public static string Battery(this IEnumerable<DeviceDetail> details)
|
||||||
|
{
|
||||||
|
return details.GetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyBattery);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the Battery Device Detail Value
|
||||||
|
/// </summary>
|
||||||
|
public static void Battery(this IEnumerable<DeviceDetail> details, Device device, string Battery)
|
||||||
|
{
|
||||||
|
device.SetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyBattery, Battery);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Keyboard
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Keyboard Device Detail Value
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The Keyboard or null</returns>
|
||||||
|
public static string Keyboard(this IEnumerable<DeviceDetail> details)
|
||||||
|
{
|
||||||
|
return details.GetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyKeyboard);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the Keyboard Device Detail Value
|
||||||
|
/// </summary>
|
||||||
|
public static void Keyboard(this IEnumerable<DeviceDetail> details, Device device, string Keyboard)
|
||||||
|
{
|
||||||
|
device.SetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyKeyboard, Keyboard);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Disco.BI.Interop.ActiveDirectory;
|
|
||||||
using Disco.Data.Configuration;
|
using Disco.Data.Configuration;
|
||||||
using Disco.Data.Repository;
|
using Disco.Data.Repository;
|
||||||
using Disco.Models.BI.DocumentTemplates;
|
using Disco.Models.BI.DocumentTemplates;
|
||||||
@@ -7,17 +6,20 @@ using Disco.Models.Repository;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Disco.Models.Interop.ActiveDirectory;
|
|
||||||
using Disco.Services.Users;
|
using Disco.Services.Users;
|
||||||
using Disco.Services.Authorization;
|
using Disco.Services.Authorization;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
|
|
||||||
namespace Disco.BI.Extensions
|
namespace Disco.BI.Extensions
|
||||||
{
|
{
|
||||||
public static class DeviceExtensions
|
public static class DeviceExtensions
|
||||||
{
|
{
|
||||||
|
|
||||||
public static string ComputerNameRender(this Device device, DiscoDataContext Database)
|
public static string ComputerNameRender(this Device device, DiscoDataContext Database, ADDomain Domain)
|
||||||
{
|
{
|
||||||
|
if (Domain == null)
|
||||||
|
throw new ArgumentNullException("Domain");
|
||||||
|
|
||||||
DeviceProfile deviceProfile = device.DeviceProfile;
|
DeviceProfile deviceProfile = device.DeviceProfile;
|
||||||
Expressions.Expression computerNameTemplateExpression = null;
|
Expressions.Expression computerNameTemplateExpression = null;
|
||||||
computerNameTemplateExpression = Expressions.ExpressionCache.GetValue(DeviceProfileExtensions.ComputerNameExpressionCacheModule, deviceProfile.Id.ToString(), () =>
|
computerNameTemplateExpression = Expressions.ExpressionCache.GetValue(DeviceProfileExtensions.ComputerNameExpressionCacheModule, deviceProfile.Id.ToString(), () =>
|
||||||
@@ -40,7 +42,8 @@ namespace Disco.BI.Extensions
|
|||||||
{
|
{
|
||||||
throw new System.InvalidOperationException("The rendered computer name would be invalid or longer than 24 characters");
|
throw new System.InvalidOperationException("The rendered computer name would be invalid or longer than 24 characters");
|
||||||
}
|
}
|
||||||
return rendered.ToString();
|
|
||||||
|
return string.Format(@"{0}\{1}", Domain.NetBiosName, rendered);
|
||||||
}
|
}
|
||||||
public static System.Collections.Generic.List<DocumentTemplate> AvailableDocumentTemplates(this Device d, DiscoDataContext Database, User User, System.DateTime TimeStamp)
|
public static System.Collections.Generic.List<DocumentTemplate> AvailableDocumentTemplates(this Device d, DiscoDataContext Database, User User, System.DateTime TimeStamp)
|
||||||
{
|
{
|
||||||
@@ -52,18 +55,18 @@ namespace Disco.BI.Extensions
|
|||||||
|
|
||||||
public static bool UpdateLastNetworkLogonDate(this Device Device)
|
public static bool UpdateLastNetworkLogonDate(this Device Device)
|
||||||
{
|
{
|
||||||
return ActiveDirectoryUpdateLastNetworkLogonDateJob.UpdateLastNetworkLogonDate(Device);
|
return Disco.Services.Interop.ActiveDirectory.ADNetworkLogonDatesUpdateTask.UpdateLastNetworkLogonDate(Device);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DeviceAttachment CreateAttachment(this Device Device, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
|
public static DeviceAttachment CreateAttachment(this Device Device, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.InvariantCultureIgnoreCase))
|
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.OrdinalIgnoreCase))
|
||||||
MimeType = Interop.MimeTypes.ResolveMimeType(Filename);
|
MimeType = Interop.MimeTypes.ResolveMimeType(Filename);
|
||||||
|
|
||||||
DeviceAttachment da = new DeviceAttachment()
|
DeviceAttachment da = new DeviceAttachment()
|
||||||
{
|
{
|
||||||
DeviceSerialNumber = Device.SerialNumber,
|
DeviceSerialNumber = Device.SerialNumber,
|
||||||
TechUserId = CreatorUser.Id,
|
TechUserId = CreatorUser.UserId,
|
||||||
Filename = Filename,
|
Filename = Filename,
|
||||||
MimeType = MimeType,
|
MimeType = MimeType,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
@@ -139,7 +142,7 @@ namespace Disco.BI.Extensions
|
|||||||
Database.Devices.Add(d2);
|
Database.Devices.Add(d2);
|
||||||
if (!string.IsNullOrEmpty(d.AssignedUserId))
|
if (!string.IsNullOrEmpty(d.AssignedUserId))
|
||||||
{
|
{
|
||||||
User u = UserService.GetUser(d.AssignedUserId, Database, true);
|
User u = UserService.GetUser(ActiveDirectory.ParseDomainAccountId(d.AssignedUserId), Database, true);
|
||||||
d2.AssignDevice(Database, u);
|
d2.AssignDevice(Database, u);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,12 +163,12 @@ namespace Disco.BI.Extensions
|
|||||||
newDua = new DeviceUserAssignment()
|
newDua = new DeviceUserAssignment()
|
||||||
{
|
{
|
||||||
DeviceSerialNumber = d.SerialNumber,
|
DeviceSerialNumber = d.SerialNumber,
|
||||||
AssignedUserId = u.Id,
|
AssignedUserId = u.UserId,
|
||||||
AssignedDate = DateTime.Now
|
AssignedDate = DateTime.Now
|
||||||
};
|
};
|
||||||
Database.DeviceUserAssignments.Add(newDua);
|
Database.DeviceUserAssignments.Add(newDua);
|
||||||
|
|
||||||
d.AssignedUserId = u.Id;
|
d.AssignedUserId = u.UserId;
|
||||||
d.AssignedUser = u;
|
d.AssignedUser = u;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -174,9 +177,9 @@ namespace Disco.BI.Extensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update AD Account
|
// Update AD Account
|
||||||
if (!string.IsNullOrEmpty(d.ComputerName) && d.ComputerName.Length <= 24)
|
if (!string.IsNullOrEmpty(d.DeviceDomainId))
|
||||||
{
|
{
|
||||||
var adMachineAccount = Interop.ActiveDirectory.ActiveDirectory.GetMachineAccount(d.ComputerName);
|
var adMachineAccount = ActiveDirectory.RetrieveADMachineAccount(d.DeviceDomainId);
|
||||||
if (adMachineAccount != null)
|
if (adMachineAccount != null)
|
||||||
{
|
{
|
||||||
adMachineAccount.SetDescription(d);
|
adMachineAccount.SetDescription(d);
|
||||||
@@ -186,36 +189,36 @@ namespace Disco.BI.Extensions
|
|||||||
return newDua;
|
return newDua;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ActiveDirectoryMachineAccount ActiveDirectoryAccount(this Device Device, params string[] AdditionalProperties)
|
public static ADMachineAccount ActiveDirectoryAccount(this Device Device, params string[] AdditionalProperties)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(Device.ComputerName))
|
if (!string.IsNullOrEmpty(Device.DeviceDomainId))
|
||||||
return Interop.ActiveDirectory.ActiveDirectory.GetMachineAccount(Device.ComputerName, AdditionalProperties: AdditionalProperties);
|
return ActiveDirectory.RetrieveADMachineAccount(Device.DeviceDomainId, AdditionalProperties: AdditionalProperties);
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ReasonMessage(this Disco.Models.Repository.Device.DecommissionReasons r)
|
public static string ReasonMessage(this Disco.Models.Repository.DecommissionReasons r)
|
||||||
{
|
{
|
||||||
switch (r)
|
switch (r)
|
||||||
{
|
{
|
||||||
case Device.DecommissionReasons.EndOfLife:
|
case DecommissionReasons.EndOfLife:
|
||||||
return "End of Life";
|
return "End of Life";
|
||||||
case Device.DecommissionReasons.Sold:
|
case DecommissionReasons.Sold:
|
||||||
return "Sold";
|
return "Sold";
|
||||||
case Device.DecommissionReasons.Stolen:
|
case DecommissionReasons.Stolen:
|
||||||
return "Stolen";
|
return "Stolen";
|
||||||
case Device.DecommissionReasons.Lost:
|
case DecommissionReasons.Lost:
|
||||||
return "Lost";
|
return "Lost";
|
||||||
case Device.DecommissionReasons.Damaged:
|
case DecommissionReasons.Damaged:
|
||||||
return "Damaged";
|
return "Damaged";
|
||||||
case Device.DecommissionReasons.Donated:
|
case DecommissionReasons.Donated:
|
||||||
return "Donated";
|
return "Donated";
|
||||||
default:
|
default:
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ReasonMessage(this Disco.Models.Repository.Device.DecommissionReasons? r)
|
public static string ReasonMessage(this Disco.Models.Repository.DecommissionReasons? r)
|
||||||
{
|
{
|
||||||
if (!r.HasValue)
|
if (!r.HasValue)
|
||||||
return "Not Decommissioned";
|
return "Not Decommissioned";
|
||||||
@@ -223,6 +226,17 @@ namespace Disco.BI.Extensions
|
|||||||
return r.Value.ReasonMessage();
|
return r.Value.ReasonMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string StatusCode(this Device Device)
|
||||||
|
{
|
||||||
|
if (Device.DecommissionedDate.HasValue)
|
||||||
|
return "Decommissioned";
|
||||||
|
|
||||||
|
if (!Device.EnrolledDate.HasValue)
|
||||||
|
return "NotEnrolled";
|
||||||
|
|
||||||
|
return "Active";
|
||||||
|
}
|
||||||
|
|
||||||
public static string Status(this Device Device)
|
public static string Status(this Device Device)
|
||||||
{
|
{
|
||||||
if (Device.DecommissionedDate.HasValue)
|
if (Device.DecommissionedDate.HasValue)
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ namespace Disco.BI.Extensions
|
|||||||
if (!(Data is User))
|
if (!(Data is User))
|
||||||
throw new ArgumentException("This Document Template is configured for Users only", "Data");
|
throw new ArgumentException("This Document Template is configured for Users only", "Data");
|
||||||
User d3 = (User)Data;
|
User d3 = (User)Data;
|
||||||
return d3.Id;
|
return d3.UserId;
|
||||||
default:
|
default:
|
||||||
throw new InvalidOperationException("Invalid Document Template Scope");
|
throw new InvalidOperationException("Invalid Document Template Scope");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,18 @@ namespace Disco.BI.Extensions
|
|||||||
{
|
{
|
||||||
public static class JobActionExtensions
|
public static class JobActionExtensions
|
||||||
{
|
{
|
||||||
|
#region Create
|
||||||
|
public static bool CanCreate()
|
||||||
|
{
|
||||||
|
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.Create))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!UserService.CurrentAuthorization.HasAny(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))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Device Held
|
#region Device Held
|
||||||
public static bool CanDeviceHeld(this Job j)
|
public static bool CanDeviceHeld(this Job j)
|
||||||
@@ -29,7 +41,7 @@ namespace Disco.BI.Extensions
|
|||||||
throw new InvalidOperationException("Holding Device was Denied");
|
throw new InvalidOperationException("Holding Device was Denied");
|
||||||
|
|
||||||
j.DeviceHeld = DateTime.Now;
|
j.DeviceHeld = DateTime.Now;
|
||||||
j.DeviceHeldTechUserId = Technician.Id;
|
j.DeviceHeldTechUserId = Technician.UserId;
|
||||||
j.DeviceReadyForReturn = null;
|
j.DeviceReadyForReturn = null;
|
||||||
j.DeviceReadyForReturnTechUserId = null;
|
j.DeviceReadyForReturnTechUserId = null;
|
||||||
j.DeviceReturnedDate = null;
|
j.DeviceReturnedDate = null;
|
||||||
@@ -52,7 +64,7 @@ namespace Disco.BI.Extensions
|
|||||||
throw new InvalidOperationException("Device Ready for Return was Denied");
|
throw new InvalidOperationException("Device Ready for Return was Denied");
|
||||||
|
|
||||||
j.DeviceReadyForReturn = DateTime.Now;
|
j.DeviceReadyForReturn = DateTime.Now;
|
||||||
j.DeviceReadyForReturnTechUserId = Technician.Id;
|
j.DeviceReadyForReturnTechUserId = Technician.UserId;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -71,7 +83,7 @@ namespace Disco.BI.Extensions
|
|||||||
throw new InvalidOperationException("Device Return was Denied");
|
throw new InvalidOperationException("Device Return was Denied");
|
||||||
|
|
||||||
j.DeviceReturnedDate = DateTime.Now;
|
j.DeviceReturnedDate = DateTime.Now;
|
||||||
j.DeviceReturnedTechUserId = Technician.Id;
|
j.DeviceReturnedTechUserId = Technician.UserId;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -94,7 +106,7 @@ namespace Disco.BI.Extensions
|
|||||||
JobLog jobLog = new JobLog()
|
JobLog jobLog = new JobLog()
|
||||||
{
|
{
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
TechUserId = Technician.Id,
|
TechUserId = Technician.UserId,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
Comments = string.Format("Waiting on User Action{0}Reason: {1}", Environment.NewLine, Reason)
|
Comments = string.Format("Waiting on User Action{0}Reason: {1}", Environment.NewLine, Reason)
|
||||||
};
|
};
|
||||||
@@ -121,7 +133,7 @@ namespace Disco.BI.Extensions
|
|||||||
JobLog jobLog = new JobLog()
|
JobLog jobLog = new JobLog()
|
||||||
{
|
{
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
TechUserId = Technician.Id,
|
TechUserId = Technician.UserId,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
Comments = string.Format("User Action Resolved{0}Resolution: {1}", Environment.NewLine, Resolution)
|
Comments = string.Format("User Action Resolved{0}Resolution: {1}", Environment.NewLine, Resolution)
|
||||||
};
|
};
|
||||||
@@ -138,7 +150,7 @@ namespace Disco.BI.Extensions
|
|||||||
return !j.ClosedDate.HasValue &&
|
return !j.ClosedDate.HasValue &&
|
||||||
(j.DeviceSerialNumber != null) &&
|
(j.DeviceSerialNumber != null) &&
|
||||||
j.JobTypeId == JobType.JobTypeIds.HWar &&
|
j.JobTypeId == JobType.JobTypeIds.HWar &&
|
||||||
string.IsNullOrEmpty(j.JobMetaWarranty.ExternalReference);
|
!j.JobMetaWarranty.ExternalLoggedDate.HasValue;
|
||||||
}
|
}
|
||||||
public static void OnLogWarranty(this Job j, DiscoDataContext Database, string FaultDescription, PluginFeatureManifest WarrantyProviderDefinition, OrganisationAddress Address, User TechUser, Dictionary<string, string> WarrantyProviderProperties)
|
public static void OnLogWarranty(this Job j, DiscoDataContext Database, string FaultDescription, PluginFeatureManifest WarrantyProviderDefinition, OrganisationAddress Address, User TechUser, Dictionary<string, string> WarrantyProviderProperties)
|
||||||
{
|
{
|
||||||
@@ -166,7 +178,7 @@ namespace Disco.BI.Extensions
|
|||||||
JobLog jobLog = new JobLog()
|
JobLog jobLog = new JobLog()
|
||||||
{
|
{
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
TechUserId = TechUser.Id,
|
TechUserId = TechUser.UserId,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
Comments = string.Format("Warranty Claim Submitted{0}{0}Provider: {1}{0}Repair Address: {2}{0}Provider Reference: {3}{0}{0}{4}", Environment.NewLine, WarrantyProvider.Manifest.Name, Address.Name, providerRef, FaultDescription)
|
Comments = string.Format("Warranty Claim Submitted{0}{0}Provider: {1}{0}Repair Address: {2}{0}Provider Reference: {3}{0}{0}{4}", Environment.NewLine, WarrantyProvider.Manifest.Name, Address.Name, providerRef, FaultDescription)
|
||||||
};
|
};
|
||||||
@@ -210,7 +222,7 @@ namespace Disco.BI.Extensions
|
|||||||
var jobComponents = new List<DeviceComponent>();
|
var jobComponents = new List<DeviceComponent>();
|
||||||
foreach (var component in components)
|
foreach (var component in components)
|
||||||
{
|
{
|
||||||
if (!component.DeviceModelId.HasValue)
|
if (component.JobSubTypes.Count == 0)
|
||||||
{
|
{
|
||||||
jobComponents.Add(component);
|
jobComponents.Add(component);
|
||||||
}
|
}
|
||||||
@@ -236,7 +248,7 @@ namespace Disco.BI.Extensions
|
|||||||
Database.JobComponents.Add(new JobComponent()
|
Database.JobComponents.Add(new JobComponent()
|
||||||
{
|
{
|
||||||
Job = j,
|
Job = j,
|
||||||
TechUserId = techUser.Id,
|
TechUserId = techUser.UserId,
|
||||||
Cost = component.Cost,
|
Cost = component.Cost,
|
||||||
Description = component.Description
|
Description = component.Description
|
||||||
});
|
});
|
||||||
@@ -246,7 +258,7 @@ namespace Disco.BI.Extensions
|
|||||||
JobLog jobLog = new JobLog()
|
JobLog jobLog = new JobLog()
|
||||||
{
|
{
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
TechUserId = techUser.Id,
|
TechUserId = techUser.UserId,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
Comments = string.Format("Job Type Converted{0}From: {1}{0}To: {2}", Environment.NewLine, Database.JobTypes.Find(JobType.JobTypeIds.HWar), Database.JobTypes.Find(JobType.JobTypeIds.HNWar))
|
Comments = string.Format("Job Type Converted{0}From: {1}{0}To: {2}", Environment.NewLine, Database.JobTypes.Find(JobType.JobTypeIds.HWar), Database.JobTypes.Find(JobType.JobTypeIds.HNWar))
|
||||||
};
|
};
|
||||||
@@ -290,7 +302,7 @@ namespace Disco.BI.Extensions
|
|||||||
var techUser = UserService.CurrentUser;
|
var techUser = UserService.CurrentUser;
|
||||||
|
|
||||||
j.JobMetaInsurance.ClaimFormSentDate = DateTime.Now;
|
j.JobMetaInsurance.ClaimFormSentDate = DateTime.Now;
|
||||||
j.JobMetaInsurance.ClaimFormSentUserId = techUser.Id;
|
j.JobMetaInsurance.ClaimFormSentUserId = techUser.UserId;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -338,20 +350,56 @@ namespace Disco.BI.Extensions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Close
|
#region Close
|
||||||
public static bool CanClose(this Job j)
|
public static void OnCloseNormally(this Job j, User Technician)
|
||||||
|
{
|
||||||
|
if (!j.CanCloseNormally())
|
||||||
|
throw new InvalidOperationException("Close was Denied");
|
||||||
|
|
||||||
|
j.ClosedDate = DateTime.Now;
|
||||||
|
j.ClosedTechUserId = Technician.UserId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool CanCloseNever(this Job j, JobQueueJob IgnoreJobQueueJob = null)
|
||||||
{
|
{
|
||||||
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.Close))
|
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.Close))
|
||||||
return false;
|
return true;
|
||||||
|
|
||||||
if (j.ClosedDate.HasValue)
|
if (j.ClosedDate.HasValue)
|
||||||
return false; // Job already Closed
|
return true; // Job already Closed
|
||||||
|
|
||||||
if (j.DeviceHeld.HasValue && !j.DeviceReturnedDate.HasValue)
|
if (j.DeviceHeld.HasValue && !j.DeviceReturnedDate.HasValue)
|
||||||
return false; // Device not returned to User
|
return true; // Device not returned to User
|
||||||
|
|
||||||
if (j.WaitingForUserAction.HasValue)
|
if (j.WaitingForUserAction.HasValue)
|
||||||
return false; // Job waiting on User Action
|
return true; // Job waiting on User Action
|
||||||
|
|
||||||
|
if (j.JobQueues != null)
|
||||||
|
{
|
||||||
|
if (IgnoreJobQueueJob == null)
|
||||||
|
{
|
||||||
|
if (j.JobQueues.Any(jqj => !jqj.RemovedDate.HasValue))
|
||||||
|
return true; // Job associated with a Job Queue
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (j.JobQueues.Any(jqj => jqj.Id != IgnoreJobQueueJob.Id && !jqj.RemovedDate.HasValue))
|
||||||
|
return true; // Job associated with a Job Queue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CanCloseNormally(this Job j)
|
||||||
|
{
|
||||||
|
if (j.CanCloseNever())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return j.CanCloseNormallyInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool CanCloseNormallyInternal(this Job j)
|
||||||
|
{
|
||||||
switch (j.JobTypeId)
|
switch (j.JobTypeId)
|
||||||
{
|
{
|
||||||
case JobType.JobTypeIds.HWar:
|
case JobType.JobTypeIds.HWar:
|
||||||
@@ -374,36 +422,27 @@ namespace Disco.BI.Extensions
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
public static void OnClose(this Job j, User Technician)
|
|
||||||
{
|
|
||||||
if (!j.CanClose())
|
|
||||||
throw new InvalidOperationException("Close was Denied");
|
|
||||||
|
|
||||||
j.ClosedDate = DateTime.Now;
|
public static bool CanCloseJobNormallyAfterRemoved(this JobQueueJob jqj)
|
||||||
j.ClosedTechUserId = Technician.Id;
|
{
|
||||||
|
if (jqj.Job.CanCloseNever(jqj))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return jqj.Job.CanCloseNormallyInternal();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Force Close
|
#region Force Close
|
||||||
public static bool CanForceClose(this Job j)
|
public static bool CanCloseForced(this Job j)
|
||||||
{
|
{
|
||||||
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.ForceClose))
|
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.ForceClose))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var canCloseNormally = j.CanClose();
|
if (j.CanCloseNever())
|
||||||
|
|
||||||
if (canCloseNormally)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check for Override
|
if (j.CanCloseNormally())
|
||||||
if (j.ClosedDate.HasValue)
|
return false;
|
||||||
return false; // Job already Closed
|
|
||||||
|
|
||||||
if (j.DeviceHeld.HasValue && !j.DeviceReturnedDate.HasValue)
|
|
||||||
return false; // Device not returned to User
|
|
||||||
|
|
||||||
if (j.WaitingForUserAction.HasValue)
|
|
||||||
return false; // Job waiting on User Action
|
|
||||||
|
|
||||||
switch (j.JobTypeId)
|
switch (j.JobTypeId)
|
||||||
{
|
{
|
||||||
@@ -427,23 +466,23 @@ namespace Disco.BI.Extensions
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
public static void OnForceClose(this Job j, DiscoDataContext Database, User Technician, string Reason)
|
public static void OnCloseForced(this Job j, DiscoDataContext Database, User Technician, string Reason)
|
||||||
{
|
{
|
||||||
if (!j.CanForceClose())
|
if (!j.CanCloseForced())
|
||||||
throw new InvalidOperationException("Force Close was Denied");
|
throw new InvalidOperationException("Force Close was Denied");
|
||||||
|
|
||||||
// Write Log
|
// Write Log
|
||||||
JobLog jobLog = new JobLog()
|
JobLog jobLog = new JobLog()
|
||||||
{
|
{
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
TechUserId = Technician.Id,
|
TechUserId = Technician.UserId,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
Comments = string.Format("Job Forcibly Closed{0}Reason: {1}", Environment.NewLine, Reason)
|
Comments = string.Format("Job Forcibly Closed{0}Reason: {1}", Environment.NewLine, Reason)
|
||||||
};
|
};
|
||||||
Database.JobLogs.Add(jobLog);
|
Database.JobLogs.Add(jobLog);
|
||||||
|
|
||||||
j.ClosedDate = DateTime.Now;
|
j.ClosedDate = DateTime.Now;
|
||||||
j.ClosedTechUserId = Technician.Id;
|
j.ClosedTechUserId = Technician.UserId;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -488,6 +527,11 @@ namespace Disco.BI.Extensions
|
|||||||
Database.JobComponents.Remove(jc);
|
Database.JobComponents.Remove(jc);
|
||||||
j.JobComponents.Clear();
|
j.JobComponents.Clear();
|
||||||
|
|
||||||
|
// Job Queue Jobs
|
||||||
|
foreach (var jqj in j.JobQueues.ToArray())
|
||||||
|
Database.JobQueueJobs.Remove(jqj);
|
||||||
|
j.JobQueues.Clear();
|
||||||
|
|
||||||
// Job Logs
|
// Job Logs
|
||||||
foreach (var jl in j.JobLogs.ToArray())
|
foreach (var jl in j.JobLogs.ToArray())
|
||||||
Database.JobLogs.Remove(jl);
|
Database.JobLogs.Remove(jl);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using System.IO;
|
|||||||
using Disco.Models.BI.DocumentTemplates;
|
using Disco.Models.BI.DocumentTemplates;
|
||||||
using Disco.Services.Plugins;
|
using Disco.Services.Plugins;
|
||||||
using Disco.Models.BI.Job;
|
using Disco.Models.BI.Job;
|
||||||
|
using Disco.Services.Authorization;
|
||||||
|
|
||||||
namespace Disco.BI.Extensions
|
namespace Disco.BI.Extensions
|
||||||
{
|
{
|
||||||
@@ -15,13 +16,13 @@ namespace Disco.BI.Extensions
|
|||||||
{
|
{
|
||||||
public static JobAttachment CreateAttachment(this Job Job, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
|
public static JobAttachment CreateAttachment(this Job Job, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.InvariantCultureIgnoreCase))
|
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.OrdinalIgnoreCase))
|
||||||
MimeType = Interop.MimeTypes.ResolveMimeType(Filename);
|
MimeType = Interop.MimeTypes.ResolveMimeType(Filename);
|
||||||
|
|
||||||
JobAttachment ja = new JobAttachment()
|
JobAttachment ja = new JobAttachment()
|
||||||
{
|
{
|
||||||
JobId = Job.Id,
|
JobId = Job.Id,
|
||||||
TechUserId = CreatorUser.Id,
|
TechUserId = CreatorUser.UserId,
|
||||||
Filename = Filename,
|
Filename = Filename,
|
||||||
MimeType = MimeType,
|
MimeType = MimeType,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
@@ -44,108 +45,6 @@ namespace Disco.BI.Extensions
|
|||||||
return ja;
|
return ja;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Tuple<string, string> Status(this Job j)
|
|
||||||
{
|
|
||||||
var statusId = j.CalculateStatusId();
|
|
||||||
return new Tuple<string, string>(statusId, JobBI.Utilities.JobStatusDescription(statusId, j));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JobTableModel.JobTableItemModelIncludeStatus ToJobTableItemModelIncludeStatus(this Job j)
|
|
||||||
{
|
|
||||||
var i = new JobTableModel.JobTableItemModelIncludeStatus()
|
|
||||||
{
|
|
||||||
Id = j.Id,
|
|
||||||
OpenedDate = j.OpenedDate,
|
|
||||||
ClosedDate = j.ClosedDate,
|
|
||||||
TypeId = j.JobTypeId,
|
|
||||||
TypeDescription = j.JobType.Description,
|
|
||||||
Location = j.DeviceHeldLocation,
|
|
||||||
|
|
||||||
WaitingForUserAction = j.WaitingForUserAction,
|
|
||||||
DeviceReadyForReturn = j.DeviceReadyForReturn,
|
|
||||||
DeviceHeld = j.DeviceHeld,
|
|
||||||
DeviceReturnedDate = j.DeviceReturnedDate
|
|
||||||
};
|
|
||||||
|
|
||||||
if (j.Device != null)
|
|
||||||
{
|
|
||||||
i.DeviceSerialNumber = j.DeviceSerialNumber;
|
|
||||||
i.DeviceModelDescription = j.Device.DeviceModel.Description;
|
|
||||||
i.DeviceAddressId = j.Device.DeviceProfile.DefaultOrganisationAddress;
|
|
||||||
|
|
||||||
if (j.JobMetaWarranty != null)
|
|
||||||
{
|
|
||||||
i.JobMetaWarranty_ExternalReference = j.JobMetaWarranty.ExternalReference;
|
|
||||||
i.JobMetaWarranty_ExternalCompletedDate = j.JobMetaWarranty.ExternalCompletedDate;
|
|
||||||
i.JobMetaWarranty_ExternalName = j.JobMetaWarranty.ExternalName;
|
|
||||||
}
|
|
||||||
if (j.JobMetaNonWarranty != null)
|
|
||||||
{
|
|
||||||
i.JobMetaNonWarranty_RepairerLoggedDate = j.JobMetaNonWarranty.RepairerLoggedDate;
|
|
||||||
i.JobMetaNonWarranty_RepairerCompletedDate = j.JobMetaNonWarranty.RepairerCompletedDate;
|
|
||||||
i.JobMetaNonWarranty_AccountingChargeAddedDate = j.JobMetaNonWarranty.AccountingChargeAddedDate;
|
|
||||||
i.JobMetaNonWarranty_AccountingChargePaidDate = j.JobMetaNonWarranty.AccountingChargePaidDate;
|
|
||||||
i.JobMetaNonWarranty_AccountingChargeRequiredDate = j.JobMetaNonWarranty.AccountingChargeRequiredDate;
|
|
||||||
i.JobMetaNonWarranty_IsInsuranceClaim = j.JobMetaNonWarranty.IsInsuranceClaim;
|
|
||||||
i.JobMetaNonWarranty_RepairerName = j.JobMetaNonWarranty.RepairerName;
|
|
||||||
if (j.JobMetaInsurance != null)
|
|
||||||
{
|
|
||||||
i.JobMetaInsurance_ClaimFormSentDate = j.JobMetaInsurance.ClaimFormSentDate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if (j.User != null)
|
|
||||||
{
|
|
||||||
i.UserId = j.UserId;
|
|
||||||
i.UserDisplayName = j.User.DisplayName;
|
|
||||||
}
|
|
||||||
if (j.OpenedTechUser != null)
|
|
||||||
{
|
|
||||||
i.OpenedTechUserId = j.OpenedTechUserId;
|
|
||||||
i.OpenedTechUserDisplayName = j.OpenedTechUser.DisplayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string CalculateStatusId(this Job j)
|
|
||||||
{
|
|
||||||
return j.ToJobTableItemModelIncludeStatus().CalculateStatusId();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string CalculateStatusId(this JobTableModel.JobTableItemModelIncludeStatus j)
|
|
||||||
{
|
|
||||||
if (j.ClosedDate.HasValue)
|
|
||||||
return Job.JobStatusIds.Closed;
|
|
||||||
|
|
||||||
if (j.TypeId == JobType.JobTypeIds.HWar)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(j.JobMetaWarranty_ExternalReference) && !j.JobMetaWarranty_ExternalCompletedDate.HasValue)
|
|
||||||
return Job.JobStatusIds.AwaitingWarrantyRepair; // Job Logged - but not marked as completed
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j.TypeId == JobType.JobTypeIds.HNWar)
|
|
||||||
{
|
|
||||||
if (j.JobMetaNonWarranty_RepairerLoggedDate.HasValue && !j.JobMetaNonWarranty_RepairerCompletedDate.HasValue)
|
|
||||||
return Job.JobStatusIds.AwaitingRepairs; // Repairs logged - but not complete
|
|
||||||
if (j.JobMetaNonWarranty_AccountingChargeAddedDate.HasValue && !j.JobMetaNonWarranty_AccountingChargePaidDate.HasValue)
|
|
||||||
return Job.JobStatusIds.AwaitingAccountingPayment; // Accounting Charge Added, but not paid
|
|
||||||
if (j.JobMetaNonWarranty_AccountingChargeRequiredDate.HasValue && (!j.JobMetaNonWarranty_AccountingChargePaidDate.HasValue || !j.JobMetaNonWarranty_AccountingChargeAddedDate.HasValue))
|
|
||||||
return Job.JobStatusIds.AwaitingAccountingCharge; // Accounting Charge Required, but not added or paid
|
|
||||||
if (j.JobMetaNonWarranty_RepairerLoggedDate.HasValue && j.JobMetaNonWarranty_IsInsuranceClaim.Value && !j.JobMetaInsurance_ClaimFormSentDate.HasValue)
|
|
||||||
return Job.JobStatusIds.AwaitingInsuranceProcessing; // Is insurance claim, but no Claim Form Sent
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j.WaitingForUserAction.HasValue)
|
|
||||||
return Job.JobStatusIds.AwaitingUserAction; // Awaiting for User
|
|
||||||
|
|
||||||
if (j.DeviceReadyForReturn.HasValue && !j.DeviceReturnedDate.HasValue)
|
|
||||||
return Job.JobStatusIds.AwaitingDeviceReturn; // Device not returned to User
|
|
||||||
|
|
||||||
return Job.JobStatusIds.Open;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<DocumentTemplate> AvailableDocumentTemplates(this Job j, DiscoDataContext Database, User User, DateTime TimeStamp)
|
public static List<DocumentTemplate> AvailableDocumentTemplates(this Job j, DiscoDataContext Database, User User, DateTime TimeStamp)
|
||||||
{
|
{
|
||||||
var dts = Database.DocumentTemplates.Include("JobSubTypes")
|
var dts = Database.DocumentTemplates.Include("JobSubTypes")
|
||||||
@@ -249,7 +148,7 @@ namespace Disco.BI.Extensions
|
|||||||
Database.JobLogs.Add(new JobLog()
|
Database.JobLogs.Add(new JobLog()
|
||||||
{
|
{
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
TechUserId = TechUser.Id,
|
TechUserId = TechUser.UserId,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
Comments = logBuilder.ToString()
|
Comments = logBuilder.ToString()
|
||||||
});
|
});
|
||||||
@@ -278,12 +177,12 @@ namespace Disco.BI.Extensions
|
|||||||
}
|
}
|
||||||
foreach (var c in addedComponents)
|
foreach (var c in addedComponents)
|
||||||
{
|
{
|
||||||
if (!j.JobComponents.Any(jc => jc.Description.Equals(c.Description, StringComparison.InvariantCultureIgnoreCase)))
|
if (!j.JobComponents.Any(jc => jc.Description.Equals(c.Description, StringComparison.OrdinalIgnoreCase)))
|
||||||
{ // Job Component with matching Description doesn't exist.
|
{ // Job Component with matching Description doesn't exist.
|
||||||
Database.JobComponents.Add(new JobComponent()
|
Database.JobComponents.Add(new JobComponent()
|
||||||
{
|
{
|
||||||
Job = j,
|
Job = j,
|
||||||
TechUserId = TechUser.Id,
|
TechUserId = TechUser.UserId,
|
||||||
Cost = c.Cost,
|
Cost = c.Cost,
|
||||||
Description = c.Description
|
Description = c.Description
|
||||||
});
|
});
|
||||||
@@ -292,5 +191,42 @@ namespace Disco.BI.Extensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<string> 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<string> allowedTypes = new List<string>(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<JobType> FilterCreatableTypePermissions(this IQueryable<JobType> JobTypes, AuthorizationToken Authorization)
|
||||||
|
{
|
||||||
|
var allowedTypes = FilterCreatableTypePermissions(Authorization);
|
||||||
|
|
||||||
|
if (allowedTypes != null)
|
||||||
|
{
|
||||||
|
return JobTypes.Where(jt => allowedTypes.Contains(jt.Id));
|
||||||
|
}
|
||||||
|
|
||||||
|
return JobTypes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,213 @@
|
|||||||
|
using Disco.Data.Repository;
|
||||||
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services.Authorization;
|
||||||
|
using Disco.Services.Jobs.JobQueues;
|
||||||
|
using Disco.Services.Users;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Disco.BI.Extensions
|
||||||
|
{
|
||||||
|
public static class JobQueueActionExtensions
|
||||||
|
{
|
||||||
|
|
||||||
|
#region Edit Sla
|
||||||
|
public static bool CanEditSla(this JobQueueJob jqj)
|
||||||
|
{
|
||||||
|
if (jqj.RemovedDate.HasValue)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditAnySLA))
|
||||||
|
{
|
||||||
|
// Can edit ANY queue
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditOwnSLA))
|
||||||
|
{
|
||||||
|
// Can edit from OWN queue
|
||||||
|
return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jqj.JobQueueId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void OnEditSla(this JobQueueJob jqj, DateTime? SlaExpiresDate)
|
||||||
|
{
|
||||||
|
if (!jqj.CanEditSla())
|
||||||
|
throw new InvalidOperationException("Editing job SLA for this queue is denied");
|
||||||
|
|
||||||
|
if (SlaExpiresDate.HasValue && jqj.AddedDate > SlaExpiresDate.Value)
|
||||||
|
throw new ArgumentException("The SLA Expires Date must be greater than the Added Date", "SLAExpiresDate");
|
||||||
|
|
||||||
|
jqj.SLAExpiresDate = SlaExpiresDate;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Edit Priority
|
||||||
|
public static bool CanEditPriority(this JobQueueJob jqj)
|
||||||
|
{
|
||||||
|
if (jqj.RemovedDate.HasValue)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditAnyPriority))
|
||||||
|
{
|
||||||
|
// Can edit ANY queue
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditOwnPriority))
|
||||||
|
{
|
||||||
|
// Can edit from OWN queue
|
||||||
|
return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jqj.JobQueueId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void OnEditPriority(this JobQueueJob jqj, JobQueuePriority Priority)
|
||||||
|
{
|
||||||
|
if (!jqj.CanEditPriority())
|
||||||
|
throw new InvalidOperationException("Editing job priority for this queue is denied");
|
||||||
|
|
||||||
|
jqj.Priority = Priority;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Edit Comments
|
||||||
|
private static bool CanEditComments(this JobQueueJob jqj)
|
||||||
|
{
|
||||||
|
if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditAnyComments))
|
||||||
|
{
|
||||||
|
// Can edit ANY queue
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditOwnComments))
|
||||||
|
{
|
||||||
|
// Can edit from OWN queue
|
||||||
|
return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jqj.JobQueueId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static bool CanEditAddedComment(this JobQueueJob jqj)
|
||||||
|
{
|
||||||
|
return jqj.CanEditComments();
|
||||||
|
}
|
||||||
|
public static bool CanEditRemovedComment(this JobQueueJob jqj)
|
||||||
|
{
|
||||||
|
if (!jqj.RemovedDate.HasValue)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return jqj.CanEditComments();
|
||||||
|
}
|
||||||
|
public static void OnEditAddedComment(this JobQueueJob jqj, string AddedComment)
|
||||||
|
{
|
||||||
|
if (!jqj.CanEditAddedComment())
|
||||||
|
throw new InvalidOperationException("Editing job added comments for this queue is denied");
|
||||||
|
|
||||||
|
jqj.AddedComment = string.IsNullOrWhiteSpace(AddedComment) ? null : AddedComment.Trim();
|
||||||
|
}
|
||||||
|
public static void OnEditRemovedComment(this JobQueueJob jqj, string RemovedComment)
|
||||||
|
{
|
||||||
|
if (!jqj.CanEditRemovedComment())
|
||||||
|
throw new InvalidOperationException("Editing job removed comments for this queue is denied");
|
||||||
|
|
||||||
|
jqj.RemovedComment = string.IsNullOrWhiteSpace(RemovedComment) ? null : RemovedComment.Trim();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Remove
|
||||||
|
public static bool CanRemove(this JobQueueJob jqj)
|
||||||
|
{
|
||||||
|
if (jqj.RemovedDate.HasValue)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.RemoveAnyQueues))
|
||||||
|
{
|
||||||
|
// Can remove from ANY queue
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.RemoveOwnQueues))
|
||||||
|
{
|
||||||
|
// Can remove from OWN queue
|
||||||
|
return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jqj.JobQueueId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void OnRemove(this JobQueueJob jqj, User Technician, string Comment)
|
||||||
|
{
|
||||||
|
if (!jqj.CanRemove())
|
||||||
|
throw new InvalidOperationException("Removing job from queue is denied");
|
||||||
|
|
||||||
|
jqj.RemovedDate = DateTime.Now;
|
||||||
|
jqj.RemovedUserId = Technician.UserId;
|
||||||
|
jqj.RemovedComment = string.IsNullOrWhiteSpace(Comment) ? null : Comment.Trim();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Add
|
||||||
|
public static bool CanAddQueues(this Job j)
|
||||||
|
{
|
||||||
|
// Job Closed?
|
||||||
|
if (j.ClosedDate.HasValue)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (UserService.CurrentAuthorization.HasAny(Claims.Job.Actions.AddAnyQueues, Claims.Job.Actions.AddOwnQueues))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public static bool CanAddQueue(this Job j, JobQueue jq)
|
||||||
|
{
|
||||||
|
// Shortcut
|
||||||
|
if (!j.CanAddQueues())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Already in Queue?
|
||||||
|
if (j.JobQueues.Any(jjq => !jjq.RemovedDate.HasValue && jjq.JobQueueId == jq.Id))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Can add ANY queue
|
||||||
|
if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.AddAnyQueues))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Can add OWN queue
|
||||||
|
if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.AddOwnQueues))
|
||||||
|
{
|
||||||
|
return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jq.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public static JobQueueJob OnAddQueue(this Job j, DiscoDataContext Database, JobQueue jq, User Technician, string Comment, DateTime? SLAExpires, JobQueuePriority Priority)
|
||||||
|
{
|
||||||
|
if (!j.CanAddQueue(jq))
|
||||||
|
throw new InvalidOperationException("Adding job to queue is denied");
|
||||||
|
|
||||||
|
if (SLAExpires.HasValue && SLAExpires.Value < DateTime.Now)
|
||||||
|
throw new ArgumentException("The SLA Date must be greater than the current time", "SLAExpires");
|
||||||
|
|
||||||
|
var jqj = new JobQueueJob()
|
||||||
|
{
|
||||||
|
JobQueueId = jq.Id,
|
||||||
|
JobId = j.Id,
|
||||||
|
AddedDate = DateTime.Now,
|
||||||
|
AddedUserId = Technician.UserId,
|
||||||
|
AddedComment = string.IsNullOrWhiteSpace(Comment) ? null : Comment.Trim(),
|
||||||
|
SLAExpiresDate = SLAExpires,
|
||||||
|
Priority = Priority
|
||||||
|
};
|
||||||
|
|
||||||
|
Database.JobQueueJobs.Add(jqj);
|
||||||
|
return jqj;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,181 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Disco.Models.BI.Job;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
using Disco.Data.Repository;
|
|
||||||
using Disco.Services.Users;
|
|
||||||
using Disco.Services.Authorization;
|
|
||||||
|
|
||||||
namespace Disco.BI.Extensions
|
|
||||||
{
|
|
||||||
public static class JobTableExtensions
|
|
||||||
{
|
|
||||||
private static List<string> FilterAllowedTypes(AuthorizationToken Authorization)
|
|
||||||
{
|
|
||||||
if (!Authorization.HasAll(Claims.Job.Types.ShowHMisc, Claims.Job.Types.ShowHNWar, Claims.Job.Types.ShowHWar, Claims.Job.Types.ShowSApp, Claims.Job.Types.ShowSImg, Claims.Job.Types.ShowSOS, Claims.Job.Types.ShowUMgmt))
|
|
||||||
{
|
|
||||||
// Must Filter
|
|
||||||
List<string> allowedTypes = new List<string>(6);
|
|
||||||
if (Authorization.Has(Claims.Job.Types.ShowHMisc))
|
|
||||||
allowedTypes.Add(JobType.JobTypeIds.HMisc);
|
|
||||||
if (Authorization.Has(Claims.Job.Types.ShowHNWar))
|
|
||||||
allowedTypes.Add(JobType.JobTypeIds.HNWar);
|
|
||||||
if (Authorization.Has(Claims.Job.Types.ShowHWar))
|
|
||||||
allowedTypes.Add(JobType.JobTypeIds.HWar);
|
|
||||||
if (Authorization.Has(Claims.Job.Types.ShowSApp))
|
|
||||||
allowedTypes.Add(JobType.JobTypeIds.SApp);
|
|
||||||
if (Authorization.Has(Claims.Job.Types.ShowSImg))
|
|
||||||
allowedTypes.Add(JobType.JobTypeIds.SImg);
|
|
||||||
if (Authorization.Has(Claims.Job.Types.ShowSOS))
|
|
||||||
allowedTypes.Add(JobType.JobTypeIds.SOS);
|
|
||||||
if (Authorization.Has(Claims.Job.Types.ShowUMgmt))
|
|
||||||
allowedTypes.Add(JobType.JobTypeIds.UMgmt);
|
|
||||||
|
|
||||||
return allowedTypes;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IQueryable<Job> FilterPermissions(this JobTableModel model, IQueryable<Job> Jobs, AuthorizationToken Authorization)
|
|
||||||
{
|
|
||||||
var allowedTypes = FilterAllowedTypes(Authorization);
|
|
||||||
|
|
||||||
if (allowedTypes != null)
|
|
||||||
{
|
|
||||||
return Jobs.Where(j => allowedTypes.Contains(j.JobTypeId));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Jobs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<JobTableModel.JobTableItemModel> PermissionsFiltered(this List<JobTableModel.JobTableItemModel> Items, AuthorizationToken Authorization)
|
|
||||||
{
|
|
||||||
if (Items != null && Items.Count > 0)
|
|
||||||
{
|
|
||||||
var allowedTypes = FilterAllowedTypes(Authorization);
|
|
||||||
|
|
||||||
if (allowedTypes != null)
|
|
||||||
{
|
|
||||||
return Items.Where(j => allowedTypes.Contains(j.TypeId)).ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Items;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<JobTableModel.JobTableItemModel> DetermineItems(this JobTableModel model, DiscoDataContext Database, IQueryable<Job> Jobs)
|
|
||||||
{
|
|
||||||
List<JobTableModel.JobTableItemModel> items;
|
|
||||||
|
|
||||||
// Permissions
|
|
||||||
var auth = UserService.CurrentAuthorization;
|
|
||||||
if (!auth.HasAll(Claims.Job.Types.ShowHMisc, Claims.Job.Types.ShowHNWar, Claims.Job.Types.ShowHWar, Claims.Job.Types.ShowSApp, Claims.Job.Types.ShowSImg, Claims.Job.Types.ShowSOS, Claims.Job.Types.ShowUMgmt))
|
|
||||||
{
|
|
||||||
// Must Filter
|
|
||||||
List<string> allowedTypes = new List<string>(6);
|
|
||||||
if (auth.Has(Claims.Job.Types.ShowHMisc))
|
|
||||||
allowedTypes.Add(JobType.JobTypeIds.HMisc);
|
|
||||||
if (auth.Has(Claims.Job.Types.ShowHNWar))
|
|
||||||
allowedTypes.Add(JobType.JobTypeIds.HNWar);
|
|
||||||
if (auth.Has(Claims.Job.Types.ShowHWar))
|
|
||||||
allowedTypes.Add(JobType.JobTypeIds.HWar);
|
|
||||||
if (auth.Has(Claims.Job.Types.ShowSApp))
|
|
||||||
allowedTypes.Add(JobType.JobTypeIds.SApp);
|
|
||||||
if (auth.Has(Claims.Job.Types.ShowSImg))
|
|
||||||
allowedTypes.Add(JobType.JobTypeIds.SImg);
|
|
||||||
if (auth.Has(Claims.Job.Types.ShowSOS))
|
|
||||||
allowedTypes.Add(JobType.JobTypeIds.SOS);
|
|
||||||
if (auth.Has(Claims.Job.Types.ShowUMgmt))
|
|
||||||
allowedTypes.Add(JobType.JobTypeIds.UMgmt);
|
|
||||||
|
|
||||||
Jobs = Jobs.Where(j => allowedTypes.Contains(j.JobTypeId));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (model.ShowStatus)
|
|
||||||
{
|
|
||||||
|
|
||||||
var jobItems = Jobs.Select(j => new JobTableModel.JobTableItemModelIncludeStatus()
|
|
||||||
{
|
|
||||||
Id = j.Id,
|
|
||||||
OpenedDate = j.OpenedDate,
|
|
||||||
ClosedDate = j.ClosedDate,
|
|
||||||
TypeId = j.JobTypeId,
|
|
||||||
TypeDescription = j.JobType.Description,
|
|
||||||
DeviceSerialNumber = j.Device.SerialNumber,
|
|
||||||
DeviceProfileId = j.Device.DeviceProfileId,
|
|
||||||
DeviceModelId = j.Device.DeviceModelId,
|
|
||||||
DeviceModelDescription = j.Device.DeviceModel.Description,
|
|
||||||
DeviceAddressId = j.Device.DeviceProfile.DefaultOrganisationAddress,
|
|
||||||
UserId = j.UserId,
|
|
||||||
UserDisplayName = j.User.DisplayName,
|
|
||||||
OpenedTechUserId = j.OpenedTechUserId,
|
|
||||||
OpenedTechUserDisplayName = j.OpenedTechUser.DisplayName,
|
|
||||||
Location = j.DeviceHeldLocation,
|
|
||||||
|
|
||||||
JobMetaWarranty_ExternalReference = j.JobMetaWarranty.ExternalReference,
|
|
||||||
JobMetaWarranty_ExternalCompletedDate = j.JobMetaWarranty.ExternalCompletedDate,
|
|
||||||
JobMetaNonWarranty_RepairerLoggedDate = j.JobMetaNonWarranty.RepairerLoggedDate,
|
|
||||||
JobMetaNonWarranty_RepairerCompletedDate = j.JobMetaNonWarranty.RepairerCompletedDate,
|
|
||||||
JobMetaNonWarranty_AccountingChargeAddedDate = j.JobMetaNonWarranty.AccountingChargeAddedDate,
|
|
||||||
JobMetaNonWarranty_AccountingChargePaidDate = j.JobMetaNonWarranty.AccountingChargePaidDate,
|
|
||||||
JobMetaNonWarranty_AccountingChargeRequiredDate = j.JobMetaNonWarranty.AccountingChargeRequiredDate,
|
|
||||||
JobMetaNonWarranty_IsInsuranceClaim = j.JobMetaNonWarranty.IsInsuranceClaim,
|
|
||||||
JobMetaInsurance_ClaimFormSentDate = j.JobMetaInsurance.ClaimFormSentDate,
|
|
||||||
|
|
||||||
WaitingForUserAction = j.WaitingForUserAction,
|
|
||||||
DeviceReadyForReturn = j.DeviceReadyForReturn,
|
|
||||||
DeviceHeld = j.DeviceHeld,
|
|
||||||
DeviceReturnedDate = j.DeviceReturnedDate,
|
|
||||||
JobMetaWarranty_ExternalName = j.JobMetaWarranty.ExternalName,
|
|
||||||
JobMetaNonWarranty_RepairerName = j.JobMetaNonWarranty.RepairerName
|
|
||||||
});
|
|
||||||
|
|
||||||
items = new List<JobTableModel.JobTableItemModel>();
|
|
||||||
foreach (var j in jobItems)
|
|
||||||
{
|
|
||||||
j.StatusId = j.CalculateStatusId();
|
|
||||||
j.StatusDescription = JobBI.Utilities.JobStatusDescription(j.StatusId, j);
|
|
||||||
|
|
||||||
items.Add(j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
items = Jobs.Select(j => new JobTableModel.JobTableItemModel()
|
|
||||||
{
|
|
||||||
Id = j.Id,
|
|
||||||
OpenedDate = j.OpenedDate,
|
|
||||||
ClosedDate = j.ClosedDate,
|
|
||||||
TypeId = j.JobTypeId,
|
|
||||||
TypeDescription = j.JobType.Description,
|
|
||||||
DeviceSerialNumber = j.Device.SerialNumber,
|
|
||||||
DeviceProfileId = j.Device.DeviceProfileId,
|
|
||||||
DeviceModelId = j.Device.DeviceModelId,
|
|
||||||
DeviceModelDescription = j.Device.DeviceModel.Description,
|
|
||||||
DeviceAddressId = j.Device.DeviceProfile.DefaultOrganisationAddress,
|
|
||||||
UserId = j.UserId,
|
|
||||||
UserDisplayName = j.User.DisplayName,
|
|
||||||
OpenedTechUserId = j.OpenedTechUserId,
|
|
||||||
OpenedTechUserDisplayName = j.OpenedTechUser.DisplayName,
|
|
||||||
Location = j.DeviceHeldLocation
|
|
||||||
}).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!model.ShowDeviceAddress.HasValue)
|
|
||||||
model.ShowDeviceAddress = Database.DiscoConfiguration.MultiSiteMode;
|
|
||||||
|
|
||||||
foreach (var j in items)
|
|
||||||
if (j.DeviceAddressId.HasValue)
|
|
||||||
j.DeviceAddress = Database.DiscoConfiguration.OrganisationAddresses.GetAddress(j.DeviceAddressId.Value).Name;
|
|
||||||
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Fill(this JobTableModel model, DiscoDataContext Database, IQueryable<Job> Jobs)
|
|
||||||
{
|
|
||||||
model.Items = model.DetermineItems(Database, Jobs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,7 @@ using Disco.Models.Repository;
|
|||||||
using Disco.Data.Repository;
|
using Disco.Data.Repository;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Disco.Models.BI.DocumentTemplates;
|
using Disco.Models.BI.DocumentTemplates;
|
||||||
using Disco.Models.Interop.ActiveDirectory;
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
|
|
||||||
namespace Disco.BI.Extensions
|
namespace Disco.BI.Extensions
|
||||||
{
|
{
|
||||||
@@ -14,13 +14,13 @@ namespace Disco.BI.Extensions
|
|||||||
{
|
{
|
||||||
public static UserAttachment CreateAttachment(this User User, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
|
public static UserAttachment CreateAttachment(this User User, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.InvariantCultureIgnoreCase))
|
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.OrdinalIgnoreCase))
|
||||||
MimeType = Interop.MimeTypes.ResolveMimeType(Filename);
|
MimeType = Interop.MimeTypes.ResolveMimeType(Filename);
|
||||||
|
|
||||||
UserAttachment ua = new UserAttachment()
|
UserAttachment ua = new UserAttachment()
|
||||||
{
|
{
|
||||||
UserId = User.Id,
|
UserId = User.UserId,
|
||||||
TechUserId = CreatorUser.Id,
|
TechUserId = CreatorUser.UserId,
|
||||||
Filename = Filename,
|
Filename = Filename,
|
||||||
MimeType = MimeType,
|
MimeType = MimeType,
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
@@ -57,9 +57,17 @@ namespace Disco.BI.Extensions
|
|||||||
{
|
{
|
||||||
return u.DeviceUserAssignments.Where(dua => !dua.UnassignedDate.HasValue).ToList();
|
return u.DeviceUserAssignments.Where(dua => !dua.UnassignedDate.HasValue).ToList();
|
||||||
}
|
}
|
||||||
public static ActiveDirectoryUserAccount ActiveDirectoryAccount(this User User, params string[] AdditionalProperties)
|
public static ADUserAccount ActiveDirectoryAccount(this User User, params string[] AdditionalProperties)
|
||||||
{
|
{
|
||||||
return Interop.ActiveDirectory.ActiveDirectory.GetUserAccount(User.Id, AdditionalProperties);
|
return ActiveDirectory.RetrieveADUserAccount(User.UserId, AdditionalProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CanCreateJob(this User u)
|
||||||
|
{
|
||||||
|
if (!JobActionExtensions.CanCreate())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
using Disco.Data.Repository;
|
||||||
|
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
|
||||||
|
{
|
||||||
|
public static class UserFlagActionExtensions
|
||||||
|
{
|
||||||
|
|
||||||
|
#region Edit Comments
|
||||||
|
public static bool CanEditComments(this UserFlagAssignment fa)
|
||||||
|
{
|
||||||
|
return UserService.CurrentAuthorization.Has(Claims.User.Actions.EditFlags);
|
||||||
|
}
|
||||||
|
public static void OnEditComments(this UserFlagAssignment fa, string Comments)
|
||||||
|
{
|
||||||
|
if (!fa.CanEditComments())
|
||||||
|
throw new InvalidOperationException("Editing comments for user flags is denied");
|
||||||
|
|
||||||
|
fa.Comments = string.IsNullOrWhiteSpace(Comments) ? null : Comments.Trim();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Remove
|
||||||
|
public static bool CanRemove(this UserFlagAssignment fa)
|
||||||
|
{
|
||||||
|
if (fa.RemovedDate.HasValue)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return UserService.CurrentAuthorization.Has(Claims.User.Actions.RemoveFlags);
|
||||||
|
}
|
||||||
|
public static void OnRemove(this UserFlagAssignment fa, User Technician)
|
||||||
|
{
|
||||||
|
if (!fa.CanRemove())
|
||||||
|
throw new InvalidOperationException("Removing user flags is denied");
|
||||||
|
|
||||||
|
fa.RemovedDate = DateTime.Now;
|
||||||
|
fa.RemovedUserId = Technician.UserId;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Add
|
||||||
|
public static bool CanAddUserFlags(this User u)
|
||||||
|
{
|
||||||
|
return UserService.CurrentAuthorization.Has(Claims.User.Actions.AddFlags);
|
||||||
|
}
|
||||||
|
public static bool CanAddUserFlag(this User u, UserFlag flag)
|
||||||
|
{
|
||||||
|
// Shortcut
|
||||||
|
if (!u.CanAddUserFlags())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Already has User Flag?
|
||||||
|
if (u.UserFlagAssignments.Any(fa => !fa.RemovedDate.HasValue && fa.UserFlagId == flag.Id))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public static UserFlagAssignment OnAddUserFlag(this User u, DiscoDataContext Database, UserFlag flag, User Technician, string Comments)
|
||||||
|
{
|
||||||
|
if (!u.CanAddUserFlag(flag))
|
||||||
|
throw new InvalidOperationException("Adding user flag is denied");
|
||||||
|
|
||||||
|
var fa = new UserFlagAssignment()
|
||||||
|
{
|
||||||
|
UserFlagId = flag.Id,
|
||||||
|
UserId = u.UserId,
|
||||||
|
AddedDate = DateTime.Now,
|
||||||
|
AddedUserId = Technician.UserId,
|
||||||
|
Comments = string.IsNullOrWhiteSpace(Comments) ? null : Comments.Trim()
|
||||||
|
};
|
||||||
|
|
||||||
|
Database.UserFlagAssignments.Add(fa);
|
||||||
|
return fa;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,117 +23,6 @@ namespace Disco.BI.Extensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Date/Time Extensions
|
|
||||||
public static string ToFuzzy(this DateTime d)
|
|
||||||
{
|
|
||||||
var n = DateTime.Now;
|
|
||||||
|
|
||||||
// Today
|
|
||||||
if (d.Date == n.Date)
|
|
||||||
{
|
|
||||||
if (d < n)
|
|
||||||
{
|
|
||||||
// Earlier
|
|
||||||
if (d > n.AddMinutes(-1))
|
|
||||||
return "A moment ago";
|
|
||||||
|
|
||||||
if (d > n.AddMinutes(-10))
|
|
||||||
return "A few minutes ago";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Later
|
|
||||||
if (d < n.AddMinutes(1))
|
|
||||||
return "In a moment";
|
|
||||||
|
|
||||||
if (d < n.AddMinutes(10))
|
|
||||||
return "In a few minutes";
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Format("Today at {0:h:mm tt}", d);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d.Date < n.Date)
|
|
||||||
{
|
|
||||||
// PAST
|
|
||||||
var dif = n.Subtract(d);
|
|
||||||
|
|
||||||
// Yesterday
|
|
||||||
if (d.Date == n.Date.AddDays(-1))
|
|
||||||
return string.Format("Yesterday at {0:h:mm tt}", d);
|
|
||||||
// Last Week
|
|
||||||
if (dif.TotalDays <= 7)
|
|
||||||
return string.Format("Last {0:dddd} at {0:h:mm tt}", d);
|
|
||||||
// Within 8 Weeks
|
|
||||||
if (d > n.Date.AddMonths(-2))
|
|
||||||
return string.Format("{0} Weeks ago, {1:ddd, d MMM}", (int)(dif.TotalDays / 7), d);
|
|
||||||
// Same Year
|
|
||||||
if (d.Year == n.Year)
|
|
||||||
return string.Format("{0} Months ago, {1:ddd, d MMM}", (int)(dif.TotalDays / 30), d);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Future
|
|
||||||
var dif = d.Subtract(n);
|
|
||||||
|
|
||||||
// Tomorrow
|
|
||||||
if (d.Date == n.Date.AddDays(1))
|
|
||||||
return string.Format("Tomorrow at {0:h:mm tt}", d);
|
|
||||||
// Next Week
|
|
||||||
if (dif.TotalDays <= 7)
|
|
||||||
return string.Format("Next {0:dddd} at {0:h:mm tt}", d);
|
|
||||||
// < 2 Month
|
|
||||||
if (d < n.Date.AddMonths(2))
|
|
||||||
return string.Format("In {0} Weeks, {1:ddd, d MMM}", (int)(dif.TotalDays / 7), d);
|
|
||||||
// Same Year
|
|
||||||
if (d.Year == n.Year)
|
|
||||||
return string.Format("In {0} Months, {1:ddd, d MMM}", (int)(dif.TotalDays / 30), d);
|
|
||||||
}
|
|
||||||
|
|
||||||
return d.ToString("ddd, d MMM yyyy");
|
|
||||||
}
|
|
||||||
public static string ToFuzzy(this DateTime? d, string NullValue = "N/A")
|
|
||||||
{
|
|
||||||
if (d.HasValue)
|
|
||||||
return ToFuzzy(d.Value);
|
|
||||||
else
|
|
||||||
return NullValue;
|
|
||||||
}
|
|
||||||
public static string ToFullDateTime(this DateTime d)
|
|
||||||
{
|
|
||||||
return d.ToString("ddd, d MMM yyyy @ h:mm:sstt");
|
|
||||||
}
|
|
||||||
public static string ToFullDateTime(this DateTime? d, string NullValue = "N/A")
|
|
||||||
{
|
|
||||||
if (d.HasValue)
|
|
||||||
return ToFullDateTime(d.Value);
|
|
||||||
else
|
|
||||||
return NullValue;
|
|
||||||
}
|
|
||||||
public static long ToSortableDateTime(this DateTime? d)
|
|
||||||
{
|
|
||||||
if (d.HasValue)
|
|
||||||
return d.Value.ToBinary();
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
public static long ToSortableDateTime(this DateTime d)
|
|
||||||
{
|
|
||||||
return d.ToBinary();
|
|
||||||
}
|
|
||||||
public static string ToJavascriptDateTime(this DateTime d)
|
|
||||||
{
|
|
||||||
return d.ToString("yyyy/MM/dd hh:mm tt");
|
|
||||||
}
|
|
||||||
public static string ToJavascriptDateTime(this DateTime? d)
|
|
||||||
{
|
|
||||||
if (d.HasValue)
|
|
||||||
return d.Value.ToString("yyyy/MM/dd hh:mm tt");
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Image Extensions
|
#region Image Extensions
|
||||||
|
|
||||||
public static Bitmap RotateImage(this Image Source, float Angle, Brush BackgroundColor = null, bool ResizeIfOver45Deg = true)
|
public static Bitmap RotateImage(this Image Source, float Angle, Brush BackgroundColor = null, bool ResizeIfOver45Deg = true)
|
||||||
@@ -277,7 +166,7 @@ namespace Disco.BI.Extensions
|
|||||||
}
|
}
|
||||||
public static void SaveJpg(this Image Source, int Quality, Stream OutStream)
|
public static void SaveJpg(this Image Source, int Quality, Stream OutStream)
|
||||||
{
|
{
|
||||||
ImageCodecInfo jpgCodec = ImageCodecInfo.GetImageEncoders().Where(c => c.MimeType.Equals("image/jpeg", StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
|
ImageCodecInfo jpgCodec = ImageCodecInfo.GetImageEncoders().Where(c => c.MimeType.Equals("image/jpeg", StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
|
||||||
if (jpgCodec != null)
|
if (jpgCodec != null)
|
||||||
{
|
{
|
||||||
if (Quality < 0 || Quality > 100)
|
if (Quality < 0 || Quality > 100)
|
||||||
|
|||||||
@@ -1,562 +0,0 @@
|
|||||||
using Disco.Models.Interop.ActiveDirectory;
|
|
||||||
using Disco.BI.DeviceBI;
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.DirectoryServices;
|
|
||||||
using System.Linq;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace Disco.BI.Interop.ActiveDirectory
|
|
||||||
{
|
|
||||||
public static class ActiveDirectory
|
|
||||||
{
|
|
||||||
#region Machine Accounts
|
|
||||||
|
|
||||||
private static readonly string[] MachineLoadProperties = {
|
|
||||||
"name",
|
|
||||||
"distinguishedName",
|
|
||||||
"sAMAccountName",
|
|
||||||
"objectSid",
|
|
||||||
"dNSHostName",
|
|
||||||
"netbootGUID",
|
|
||||||
"isCriticalSystemObject"
|
|
||||||
};
|
|
||||||
public static ActiveDirectoryMachineAccount GetMachineAccount(string ComputerName, System.Guid? UUIDNetbootGUID = null, System.Guid? MacAddressNetbootGUID = null, params string[] AdditionalProperties)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(ComputerName))
|
|
||||||
throw new System.ArgumentException("Invalid Computer Name - Empty", "ComputerName");
|
|
||||||
if (ComputerName.Contains("\\"))
|
|
||||||
ComputerName = ComputerName.Substring(checked(ComputerName.IndexOf("\\") + 1));
|
|
||||||
if (ComputerName.Length > 24)
|
|
||||||
throw new System.ArgumentException("Invalid Computer Name - Length > 24", "ComputerName");
|
|
||||||
string sAMAccountName = ComputerName;
|
|
||||||
if (!sAMAccountName.EndsWith("$"))
|
|
||||||
sAMAccountName = string.Format("{0}$", sAMAccountName);
|
|
||||||
|
|
||||||
using (DirectoryEntry dRootEntry = ActiveDirectoryHelpers.DefaultLdapRoot)
|
|
||||||
{
|
|
||||||
var loadProperties = AdditionalProperties == null ? MachineLoadProperties : MachineLoadProperties.Concat(AdditionalProperties).ToArray();
|
|
||||||
|
|
||||||
using (DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, string.Format("(&(objectCategory=computer)(sAMAccountName={0}))", ActiveDirectoryHelpers.EscapeLdapQuery(sAMAccountName)), loadProperties, SearchScope.Subtree))
|
|
||||||
{
|
|
||||||
SearchResult dResult = dSearcher.FindOne();
|
|
||||||
if (dResult != null)
|
|
||||||
{
|
|
||||||
return ActiveDirectory.ActiveDirectoryMachineAccountFromSearchResult(dResult, AdditionalProperties);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UUIDNetbootGUID.HasValue)
|
|
||||||
{
|
|
||||||
using (DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, string.Format("(&(objectCategory=computer)(netbootGUID={0}))", ActiveDirectoryHelpers.FormatGuidForLdapQuery(UUIDNetbootGUID.Value)), loadProperties, SearchScope.Subtree))
|
|
||||||
{
|
|
||||||
SearchResult dResult = dSearcher.FindOne();
|
|
||||||
if (dResult != null)
|
|
||||||
{
|
|
||||||
return ActiveDirectory.ActiveDirectoryMachineAccountFromSearchResult(dResult, AdditionalProperties);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (MacAddressNetbootGUID.HasValue)
|
|
||||||
{
|
|
||||||
using (DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, string.Format("(&(objectCategory=computer)(netbootGUID={0}))", ActiveDirectoryHelpers.FormatGuidForLdapQuery(MacAddressNetbootGUID.Value)), loadProperties, SearchScope.Subtree))
|
|
||||||
{
|
|
||||||
SearchResult dResult = dSearcher.FindOne();
|
|
||||||
if (dResult != null)
|
|
||||||
{
|
|
||||||
return ActiveDirectory.ActiveDirectoryMachineAccountFromSearchResult(dResult, AdditionalProperties);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
private static ActiveDirectoryMachineAccount ActiveDirectoryMachineAccountFromSearchResult(SearchResult result, params string[] AdditionalProperties)
|
|
||||||
{
|
|
||||||
string name = result.Properties["name"][0].ToString();
|
|
||||||
string sAMAccountName = result.Properties["sAMAccountName"][0].ToString();
|
|
||||||
string distinguishedName = result.Properties["distinguishedName"][0].ToString();
|
|
||||||
string objectSid = ActiveDirectoryHelpers.ConvertBytesToSDDLString((byte[])result.Properties["objectSid"][0]);
|
|
||||||
|
|
||||||
var dNSNameProperty = result.Properties["dNSHostName"];
|
|
||||||
string dNSName = null;
|
|
||||||
if (dNSNameProperty.Count > 0)
|
|
||||||
dNSName = dNSNameProperty[0].ToString();
|
|
||||||
else
|
|
||||||
dNSName = string.Format("{0}.{1}", sAMAccountName.TrimEnd('$'), ActiveDirectoryHelpers.DefaultDomainQualifiedName);
|
|
||||||
|
|
||||||
bool isCriticalSystemObject = (bool)result.Properties["isCriticalSystemObject"][0];
|
|
||||||
|
|
||||||
System.Guid netbootGUIDResult = default(System.Guid);
|
|
||||||
ResultPropertyValueCollection netbootGUIDProp = result.Properties["netbootGUID"];
|
|
||||||
if (netbootGUIDProp.Count > 0)
|
|
||||||
{
|
|
||||||
netbootGUIDResult = new System.Guid((byte[])netbootGUIDProp[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Additional Properties
|
|
||||||
Dictionary<string, object[]> additionalProperties = new Dictionary<string, object[]>();
|
|
||||||
if (AdditionalProperties != null)
|
|
||||||
foreach (string propertyName in AdditionalProperties)
|
|
||||||
{
|
|
||||||
var property = result.Properties[propertyName];
|
|
||||||
var propertyValues = new List<object>();
|
|
||||||
for (int index = 0; index < property.Count; index++)
|
|
||||||
propertyValues.Add(property[index]);
|
|
||||||
additionalProperties.Add(propertyName, propertyValues.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ActiveDirectoryMachineAccount
|
|
||||||
{
|
|
||||||
Name = name,
|
|
||||||
DistinguishedName = distinguishedName,
|
|
||||||
SamAccountName = sAMAccountName,
|
|
||||||
SecurityIdentifier = objectSid,
|
|
||||||
NetbootGUID = netbootGUIDResult,
|
|
||||||
Path = result.Path,
|
|
||||||
Domain = ActiveDirectoryHelpers.DefaultDomainNetBiosName,
|
|
||||||
DnsName = dNSName,
|
|
||||||
IsCriticalSystemObject = isCriticalSystemObject,
|
|
||||||
LoadedProperties = additionalProperties
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public static string OfflineDomainJoinProvision(ref ActiveDirectoryMachineAccount ExistingAccount, string ComputerName, string OrganisationalUnit = null, string EnrolSessionId = null)
|
|
||||||
{
|
|
||||||
if (ExistingAccount != null && ExistingAccount.IsCriticalSystemObject)
|
|
||||||
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", ExistingAccount.DistinguishedName));
|
|
||||||
|
|
||||||
string DJoinResult = null;
|
|
||||||
if (string.IsNullOrWhiteSpace(ComputerName) || ComputerName.Length > 24)
|
|
||||||
throw new System.ArgumentException("Invalid Computer Name; > 0 and <= 24", "ComputerName");
|
|
||||||
|
|
||||||
// Added 2012-10-25 G#
|
|
||||||
// Ensure Specified OU Exists
|
|
||||||
if (!string.IsNullOrEmpty(OrganisationalUnit))
|
|
||||||
{
|
|
||||||
var ouPath = string.Format("{0}{1},{2}", ActiveDirectoryHelpers.DefaultLdapPath, OrganisationalUnit, ActiveDirectoryHelpers.DefaultDomainQualifiedName);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (DirectoryEntry ou = new DirectoryEntry(ouPath))
|
|
||||||
{
|
|
||||||
if (ou == null)
|
|
||||||
{
|
|
||||||
throw new Exception("OU's Directory Entry couldn't be found");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new ArgumentException(string.Format("An error occurred while trying to locate the specified OU: {0}", ouPath), "OrganisationalUnit", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// End Added 2012-10-25 G#
|
|
||||||
|
|
||||||
// Delete Existing
|
|
||||||
if (ExistingAccount != null)
|
|
||||||
ExistingAccount.DeleteAccount();
|
|
||||||
|
|
||||||
string tempFileName = System.IO.Path.GetTempFileName();
|
|
||||||
string argumentOU = (!string.IsNullOrWhiteSpace(OrganisationalUnit)) ? string.Format(" /MACHINEOU \"{0},{1}\"", OrganisationalUnit, ActiveDirectoryHelpers.DefaultDomainQualifiedName) : string.Empty;
|
|
||||||
string arguments = string.Format("/PROVISION /DOMAIN \"{0}\" /DCNAME \"{1}\" /MACHINE \"{2}\"{3} /REUSE /SAVEFILE \"{4}\"",
|
|
||||||
ActiveDirectoryHelpers.DefaultDomainName,
|
|
||||||
ActiveDirectoryHelpers.DefaultDomainPDCName,
|
|
||||||
ComputerName,
|
|
||||||
argumentOU,
|
|
||||||
tempFileName
|
|
||||||
);
|
|
||||||
ProcessStartInfo commandStarter = new ProcessStartInfo("DJOIN.EXE", arguments)
|
|
||||||
{
|
|
||||||
CreateNoWindow = true,
|
|
||||||
ErrorDialog = false,
|
|
||||||
LoadUserProfile = false,
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
RedirectStandardError = true,
|
|
||||||
UseShellExecute = false
|
|
||||||
};
|
|
||||||
if (EnrolSessionId != null)
|
|
||||||
{
|
|
||||||
EnrolmentLog.LogSessionDiagnosticInformation(EnrolSessionId, string.Format("{0} {1}{2}", "DJOIN.EXE", arguments, System.Environment.NewLine));
|
|
||||||
}
|
|
||||||
|
|
||||||
string stdOutput;
|
|
||||||
string stdError;
|
|
||||||
using (Process commandProc = Process.Start(commandStarter))
|
|
||||||
{
|
|
||||||
commandProc.WaitForExit(20000);
|
|
||||||
stdOutput = commandProc.StandardOutput.ReadToEnd();
|
|
||||||
stdError = commandProc.StandardError.ReadToEnd();
|
|
||||||
}
|
|
||||||
if (EnrolSessionId != null)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrWhiteSpace(stdOutput))
|
|
||||||
EnrolmentLog.LogSessionDiagnosticInformation(EnrolSessionId, stdOutput + System.Environment.NewLine);
|
|
||||||
if (!string.IsNullOrWhiteSpace(stdError))
|
|
||||||
EnrolmentLog.LogSessionDiagnosticInformation(EnrolSessionId, stdError + System.Environment.NewLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (System.IO.File.Exists(tempFileName))
|
|
||||||
{
|
|
||||||
DJoinResult = System.Convert.ToBase64String(System.IO.File.ReadAllBytes(tempFileName));
|
|
||||||
System.IO.File.Delete(tempFileName);
|
|
||||||
}
|
|
||||||
if (string.IsNullOrWhiteSpace(DJoinResult))
|
|
||||||
throw new System.InvalidOperationException(string.Format("Domain Join Unsuccessful{0}Error: {1}{0}Output: {2}", System.Environment.NewLine, stdError, stdOutput));
|
|
||||||
ExistingAccount = ActiveDirectory.GetMachineAccount(ComputerName);
|
|
||||||
return DJoinResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Users
|
|
||||||
|
|
||||||
private static readonly string[] UserLoadProperties = {
|
|
||||||
"name",
|
|
||||||
"distinguishedName",
|
|
||||||
"sAMAccountName",
|
|
||||||
"objectSid",
|
|
||||||
"displayName",
|
|
||||||
"sn",
|
|
||||||
"givenName",
|
|
||||||
"memberOf",
|
|
||||||
"primaryGroupID",
|
|
||||||
"mail",
|
|
||||||
"telephoneNumber"
|
|
||||||
};
|
|
||||||
public static List<ActiveDirectoryUserAccount> SearchUsers(string term)
|
|
||||||
{
|
|
||||||
List<ActiveDirectoryUserAccount> users = new List<ActiveDirectoryUserAccount>();
|
|
||||||
string defaultQualifiedDomainName = ActiveDirectoryHelpers.DefaultDomainQualifiedName;
|
|
||||||
string defaultNetBiosDomainName = ActiveDirectoryHelpers.DefaultDomainNetBiosName;
|
|
||||||
term = ActiveDirectoryHelpers.EscapeLdapQuery(term);
|
|
||||||
using (DirectoryEntry entry = new DirectoryEntry(string.Format("LDAP://{0}", defaultQualifiedDomainName)))
|
|
||||||
{
|
|
||||||
using (DirectorySearcher searcher = new DirectorySearcher(entry, string.Format("(&(objectCategory=Person)(objectCategory=Person)(|(sAMAccountName=*{0}*)(displayName=*{0}*)))", term), UserLoadProperties, SearchScope.Subtree))
|
|
||||||
{
|
|
||||||
searcher.SizeLimit = 30;
|
|
||||||
SearchResultCollection results = searcher.FindAll();
|
|
||||||
foreach (SearchResult result in results)
|
|
||||||
{
|
|
||||||
users.Add(ActiveDirectory.ActiveDirectoryUserAccountFromSearchResult(result));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return users;
|
|
||||||
}
|
|
||||||
private static ActiveDirectoryUserAccount ActiveDirectoryUserAccountFromSearchResult(SearchResult result, params string[] AdditionalProperties)
|
|
||||||
{
|
|
||||||
string name = result.Properties["name"][0].ToString();
|
|
||||||
string username = result.Properties["sAMAccountName"][0].ToString();
|
|
||||||
string distinguishedName = result.Properties["distinguishedName"][0].ToString();
|
|
||||||
byte[] objectSid = (byte[])result.Properties["objectSid"][0];
|
|
||||||
string objectSidSDDL = ActiveDirectoryHelpers.ConvertBytesToSDDLString(objectSid);
|
|
||||||
|
|
||||||
ResultPropertyValueCollection displayNameProp = result.Properties["displayName"];
|
|
||||||
string displayName = username;
|
|
||||||
if (displayNameProp.Count > 0)
|
|
||||||
displayName = displayNameProp[0].ToString();
|
|
||||||
string surname = null;
|
|
||||||
ResultPropertyValueCollection surnameProp = result.Properties["sn"];
|
|
||||||
if (surnameProp.Count > 0)
|
|
||||||
surname = surnameProp[0].ToString();
|
|
||||||
string givenName = null;
|
|
||||||
ResultPropertyValueCollection givenNameProp = result.Properties["givenName"];
|
|
||||||
if (givenNameProp.Count > 0)
|
|
||||||
givenName = givenNameProp[0].ToString();
|
|
||||||
string email = null;
|
|
||||||
ResultPropertyValueCollection emailProp = result.Properties["mail"];
|
|
||||||
if (emailProp.Count > 0)
|
|
||||||
email = emailProp[0].ToString();
|
|
||||||
string phone = null;
|
|
||||||
ResultPropertyValueCollection phoneProp = result.Properties["telephoneNumber"];
|
|
||||||
if (phoneProp.Count > 0)
|
|
||||||
phone = phoneProp[0].ToString();
|
|
||||||
|
|
||||||
int primaryGroupID = (int)result.Properties["primaryGroupID"][0];
|
|
||||||
string primaryGroupSid = ActiveDirectoryHelpers.ConvertBytesToSDDLString(ActiveDirectoryHelpers.BuildPrimaryGroupSid(objectSid, primaryGroupID));
|
|
||||||
var groupDistinguishedNames = result.Properties["memberOf"].Cast<string>().ToList();
|
|
||||||
groupDistinguishedNames.Add(ActiveDirectoryCachedGroups.GetGroupsDistinguishedNameForSecurityIdentifier(primaryGroupSid));
|
|
||||||
List<string> groups = ActiveDirectoryCachedGroups.GetGroups(groupDistinguishedNames).ToList();
|
|
||||||
|
|
||||||
//foreach (string groupCN in result.Properties["memberOf"])
|
|
||||||
//{
|
|
||||||
// Removed 2012-11-30 G# - Moved to Recursive Cache
|
|
||||||
//var groupCNlower = groupCN.ToLower();
|
|
||||||
//if (groupCNlower.StartsWith("cn="))
|
|
||||||
// groups.Add(groupCNlower.Substring(3, groupCNlower.IndexOf(",") - 3));
|
|
||||||
// End Removed 2012-11-30 G#
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Additional Properties
|
|
||||||
Dictionary<string, object[]> additionalProperties = new Dictionary<string, object[]>();
|
|
||||||
if (AdditionalProperties != null)
|
|
||||||
foreach (string propertyName in AdditionalProperties)
|
|
||||||
{
|
|
||||||
var property = result.Properties[propertyName];
|
|
||||||
var propertyValues = new List<object>();
|
|
||||||
for (int index = 0; index < property.Count; index++)
|
|
||||||
propertyValues.Add(property[index]);
|
|
||||||
additionalProperties.Add(propertyName, propertyValues.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ActiveDirectoryUserAccount
|
|
||||||
{
|
|
||||||
Domain = ActiveDirectoryHelpers.DefaultDomainNetBiosName,
|
|
||||||
Name = name,
|
|
||||||
Surname = surname,
|
|
||||||
GivenName = givenName,
|
|
||||||
Email = email,
|
|
||||||
Phone = phone,
|
|
||||||
DistinguishedName = distinguishedName,
|
|
||||||
SamAccountName = username,
|
|
||||||
DisplayName = displayName,
|
|
||||||
SecurityIdentifier = objectSidSDDL,
|
|
||||||
Groups = groups,
|
|
||||||
Path = result.Path,
|
|
||||||
LoadedProperties = additionalProperties
|
|
||||||
};
|
|
||||||
}
|
|
||||||
public static ActiveDirectoryUserAccount GetUserAccount(string Username, params string[] AdditionalProperties)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(Username))
|
|
||||||
throw new System.ArgumentException("Invalid User Account", "Username");
|
|
||||||
string sAMAccountName = Username;
|
|
||||||
if (sAMAccountName.Contains("\\"))
|
|
||||||
sAMAccountName = sAMAccountName.Substring(checked(sAMAccountName.IndexOf("\\") + 1));
|
|
||||||
|
|
||||||
using (DirectoryEntry dRootEntry = ActiveDirectoryHelpers.DefaultLdapRoot)
|
|
||||||
{
|
|
||||||
var loadProperties = AdditionalProperties == null ? UserLoadProperties : UserLoadProperties.Concat(AdditionalProperties).ToArray();
|
|
||||||
|
|
||||||
using (DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, string.Format("(&(objectCategory=Person)(sAMAccountName={0}))", ActiveDirectoryHelpers.EscapeLdapQuery(sAMAccountName)), loadProperties, SearchScope.Subtree))
|
|
||||||
{
|
|
||||||
SearchResult dResult = dSearcher.FindOne();
|
|
||||||
if (dResult != null)
|
|
||||||
return ActiveDirectory.ActiveDirectoryUserAccountFromSearchResult(dResult, AdditionalProperties);
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Organisation Units
|
|
||||||
|
|
||||||
public static List<ActiveDirectoryOrganisationalUnit> GetOrganisationalUnitStructure()
|
|
||||||
{
|
|
||||||
ActiveDirectoryOrganisationalUnit DomainOUs = new ActiveDirectoryOrganisationalUnit
|
|
||||||
{
|
|
||||||
Children = new System.Collections.Generic.List<ActiveDirectoryOrganisationalUnit>()
|
|
||||||
};
|
|
||||||
string defaultQualifiedDomainName = ActiveDirectoryHelpers.DefaultDomainQualifiedName;
|
|
||||||
|
|
||||||
using (DirectoryEntry entry = new DirectoryEntry(string.Format("LDAP://{0}", defaultQualifiedDomainName)))
|
|
||||||
{
|
|
||||||
ActiveDirectory.GetOrganisationalUnitStructure_Recursive(ref DomainOUs, entry);
|
|
||||||
}
|
|
||||||
return DomainOUs.Children;
|
|
||||||
}
|
|
||||||
private static void GetOrganisationalUnitStructure_Recursive(ref ActiveDirectoryOrganisationalUnit ParentOU, DirectoryEntry Container)
|
|
||||||
{
|
|
||||||
using (DirectorySearcher searcher = new DirectorySearcher(Container, "(objectCategory=organizationalUnit)", new string[]
|
|
||||||
{
|
|
||||||
"name",
|
|
||||||
"distinguishedName"
|
|
||||||
}, SearchScope.OneLevel))
|
|
||||||
{
|
|
||||||
using (SearchResultCollection results = searcher.FindAll())
|
|
||||||
{
|
|
||||||
foreach (SearchResult result in results)
|
|
||||||
{
|
|
||||||
string i = result.Properties["name"][0].ToString();
|
|
||||||
string dn = result.Properties["distinguishedName"][0].ToString();
|
|
||||||
ActiveDirectoryOrganisationalUnit ChildOU = new ActiveDirectoryOrganisationalUnit
|
|
||||||
{
|
|
||||||
Name = i,
|
|
||||||
Path = dn.Substring(0, dn.IndexOf(",DC=")),
|
|
||||||
Children = new List<ActiveDirectoryOrganisationalUnit>()
|
|
||||||
};
|
|
||||||
ActiveDirectory.GetOrganisationalUnitStructure_Recursive(ref ChildOU, result.GetDirectoryEntry());
|
|
||||||
if (ChildOU.Children.Count == 0)
|
|
||||||
ChildOU.Children = null;
|
|
||||||
ParentOU.Children.Add(ChildOU);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Groups
|
|
||||||
|
|
||||||
private static readonly string[] GroupLoadProperties = {
|
|
||||||
"name",
|
|
||||||
"distinguishedName",
|
|
||||||
"cn",
|
|
||||||
"sAMAccountName",
|
|
||||||
"objectSid",
|
|
||||||
"memberOf"
|
|
||||||
};
|
|
||||||
public static ActiveDirectoryGroup GetGroup(string SamAccountName)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(SamAccountName))
|
|
||||||
throw new System.ArgumentException("Invalid Group Account", "SamAccountName");
|
|
||||||
string sAMAccountName = SamAccountName;
|
|
||||||
if (sAMAccountName.Contains("\\"))
|
|
||||||
sAMAccountName = sAMAccountName.Substring(checked(sAMAccountName.IndexOf("\\") + 1));
|
|
||||||
|
|
||||||
using (DirectoryEntry dRootEntry = ActiveDirectoryHelpers.DefaultLdapRoot)
|
|
||||||
{
|
|
||||||
using (DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, string.Format("(&(objectCategory=Group)(objectSid={0}))", ActiveDirectoryHelpers.EscapeLdapQuery(sAMAccountName)), GroupLoadProperties, SearchScope.Subtree))
|
|
||||||
{
|
|
||||||
SearchResult dResult = dSearcher.FindOne();
|
|
||||||
if (dResult != null)
|
|
||||||
{
|
|
||||||
return ActiveDirectoryGroupFromSearchResult(dResult);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static ActiveDirectoryGroup GetGroupFromDistinguishedName(string DistinguishedName)
|
|
||||||
{
|
|
||||||
ActiveDirectoryGroup group = null;
|
|
||||||
|
|
||||||
using (DirectoryEntry groupDE = new DirectoryEntry(string.Concat(ActiveDirectoryHelpers.DefaultLdapPath, DistinguishedName)))
|
|
||||||
{
|
|
||||||
if (groupDE != null)
|
|
||||||
{
|
|
||||||
return ActiveDirectoryGroupFromDirectoryEntry(groupDE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
public static ActiveDirectoryGroup GetGroupFromSecurityIdentifier(string SecurityIdentifier)
|
|
||||||
{
|
|
||||||
using (DirectoryEntry dRootEntry = ActiveDirectoryHelpers.DefaultLdapRoot)
|
|
||||||
{
|
|
||||||
var sidBytes = ActiveDirectoryHelpers.ConvertSDDLStringToBytes(SecurityIdentifier);
|
|
||||||
var sidBinaryString = ActiveDirectoryHelpers.ConvertBytesToBinarySidString(sidBytes);
|
|
||||||
|
|
||||||
using (DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, string.Format("(&(objectCategory=Group)(objectSid={0}))", sidBinaryString), GroupLoadProperties, SearchScope.Subtree))
|
|
||||||
{
|
|
||||||
SearchResult dResult = dSearcher.FindOne();
|
|
||||||
if (dResult != null)
|
|
||||||
{
|
|
||||||
return ActiveDirectoryGroupFromSearchResult(dResult);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<ActiveDirectoryGroup> SearchGroups(string term)
|
|
||||||
{
|
|
||||||
List<ActiveDirectoryGroup> results = new List<ActiveDirectoryGroup>();
|
|
||||||
string defaultQualifiedDomainName = ActiveDirectoryHelpers.DefaultDomainQualifiedName;
|
|
||||||
string defaultNetBiosDomainName = ActiveDirectoryHelpers.DefaultDomainNetBiosName;
|
|
||||||
term = ActiveDirectoryHelpers.EscapeLdapQuery(term);
|
|
||||||
using (DirectoryEntry entry = new DirectoryEntry(string.Format("LDAP://{0}", defaultQualifiedDomainName)))
|
|
||||||
{
|
|
||||||
using (DirectorySearcher searcher = new DirectorySearcher(entry, string.Format("(&(objectCategory=Group)(|(sAMAccountName=*{0}*)(name=*{0}*)(cn=*{0}*)))", term), GroupLoadProperties, SearchScope.Subtree))
|
|
||||||
{
|
|
||||||
searcher.SizeLimit = 30;
|
|
||||||
SearchResultCollection searchResults = searcher.FindAll();
|
|
||||||
foreach (SearchResult result in searchResults)
|
|
||||||
{
|
|
||||||
results.Add(ActiveDirectory.ActiveDirectoryGroupFromSearchResult(result));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ActiveDirectoryGroup ActiveDirectoryGroupFromDirectoryEntry(DirectoryEntry entry)
|
|
||||||
{
|
|
||||||
var name = (string)entry.Properties["name"].Value;
|
|
||||||
var distinguishedName = (string)entry.Properties["distinguishedName"].Value;
|
|
||||||
var cn = (string)entry.Properties["cn"].Value;
|
|
||||||
var sAMAccountName = (string)entry.Properties["sAMAccountName"].Value;
|
|
||||||
var objectSid = ActiveDirectoryHelpers.ConvertBytesToSDDLString((byte[])entry.Properties["objectSid"].Value);
|
|
||||||
var memberOf = entry.Properties["memberOf"].Cast<string>().ToList();
|
|
||||||
|
|
||||||
return new ActiveDirectoryGroup()
|
|
||||||
{
|
|
||||||
Name = name,
|
|
||||||
DistinguishedName = distinguishedName,
|
|
||||||
CommonName = cn,
|
|
||||||
SamAccountName = sAMAccountName,
|
|
||||||
SecurityIdentifier = objectSid,
|
|
||||||
MemberOf = memberOf
|
|
||||||
};
|
|
||||||
}
|
|
||||||
private static ActiveDirectoryGroup ActiveDirectoryGroupFromSearchResult(SearchResult result)
|
|
||||||
{
|
|
||||||
var name = (string)result.Properties["name"][0];
|
|
||||||
var distinguishedName = (string)result.Properties["distinguishedName"][0];
|
|
||||||
var cn = (string)result.Properties["cn"][0];
|
|
||||||
var sAMAccountName = (string)result.Properties["sAMAccountName"][0];
|
|
||||||
var objectSid = ActiveDirectoryHelpers.ConvertBytesToSDDLString((byte[])result.Properties["objectSid"][0]);
|
|
||||||
var memberOf = result.Properties["memberOf"].Cast<string>().ToList();
|
|
||||||
|
|
||||||
return new ActiveDirectoryGroup()
|
|
||||||
{
|
|
||||||
Name = name,
|
|
||||||
DistinguishedName = distinguishedName,
|
|
||||||
CommonName = cn,
|
|
||||||
SamAccountName = sAMAccountName,
|
|
||||||
SecurityIdentifier = objectSid,
|
|
||||||
MemberOf = memberOf
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private static readonly string[] ObjectLoadProperties = { "objectCategory" };
|
|
||||||
private static readonly string[] ObjectLoadPropertiesAll = ObjectLoadProperties.Concat(UserLoadProperties).Concat(MachineLoadProperties).Concat(GroupLoadProperties).Distinct().ToArray();
|
|
||||||
|
|
||||||
public static IActiveDirectoryObject GetObject(string SamAccountName)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(SamAccountName))
|
|
||||||
throw new System.ArgumentException("Invalid Object Account Name", "SamAccountName");
|
|
||||||
string sAMAccountName = SamAccountName;
|
|
||||||
if (sAMAccountName.Contains("\\"))
|
|
||||||
sAMAccountName = sAMAccountName.Substring(checked(sAMAccountName.IndexOf("\\") + 1));
|
|
||||||
|
|
||||||
using (DirectoryEntry dRootEntry = ActiveDirectoryHelpers.DefaultLdapRoot)
|
|
||||||
{
|
|
||||||
using (DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, string.Format("(&(|(objectCategory=Person)(objectCategory=Computer)(objectCategory=Group))(sAMAccountName={0}))", ActiveDirectoryHelpers.EscapeLdapQuery(sAMAccountName)), ObjectLoadPropertiesAll, SearchScope.Subtree))
|
|
||||||
{
|
|
||||||
SearchResult dResult = dSearcher.FindOne();
|
|
||||||
if (dResult != null)
|
|
||||||
{
|
|
||||||
var objectCategory = (string)dResult.Properties["objectCategory"][0];
|
|
||||||
objectCategory = objectCategory.Substring(0, objectCategory.IndexOf(',')).ToLower();
|
|
||||||
switch (objectCategory)
|
|
||||||
{
|
|
||||||
case "cn=person":
|
|
||||||
return ActiveDirectoryUserAccountFromSearchResult(dResult);
|
|
||||||
case "cn=computer":
|
|
||||||
return ActiveDirectoryMachineAccountFromSearchResult(dResult);
|
|
||||||
case "cn=group":
|
|
||||||
return ActiveDirectoryGroupFromSearchResult(dResult);
|
|
||||||
default:
|
|
||||||
throw new InvalidOperationException("Unexpected objectCategory");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,229 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.DirectoryServices;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Disco.Data.Repository;
|
|
||||||
using Disco.Services.Tasks;
|
|
||||||
using Quartz;
|
|
||||||
using Disco.Models.Interop.ActiveDirectory;
|
|
||||||
|
|
||||||
namespace Disco.BI.Interop.ActiveDirectory
|
|
||||||
{
|
|
||||||
public class ActiveDirectoryCachedGroups : ScheduledTask
|
|
||||||
{
|
|
||||||
private static ConcurrentDictionary<string, Tuple<ActiveDirectoryGroup, DateTime>> _SecurityIdentifierCache = new ConcurrentDictionary<string, Tuple<ActiveDirectoryGroup, DateTime>>();
|
|
||||||
private static ConcurrentDictionary<string, Tuple<ActiveDirectoryGroup, DateTime>> _DistinguishedNameCache = new ConcurrentDictionary<string, Tuple<ActiveDirectoryGroup, DateTime>>();
|
|
||||||
private const long CacheTimeoutTicks = 6000000000; // 10 Minutes
|
|
||||||
|
|
||||||
public static IEnumerable<string> GetGroups(IEnumerable<string> DistinguishedNames)
|
|
||||||
{
|
|
||||||
List<ActiveDirectoryGroup> groups = new List<ActiveDirectoryGroup>();
|
|
||||||
|
|
||||||
foreach (var distinguishedName in DistinguishedNames)
|
|
||||||
foreach (var group in GetGroupsRecursive(distinguishedName, new Stack<ActiveDirectoryGroup>()))
|
|
||||||
if (!groups.Contains(group))
|
|
||||||
{
|
|
||||||
groups.Add(group);
|
|
||||||
yield return group.SamAccountName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static IEnumerable<string> GetGroups(string DistinguishedName)
|
|
||||||
{
|
|
||||||
foreach (var group in GetGroupsRecursive(DistinguishedName, new Stack<ActiveDirectoryGroup>()))
|
|
||||||
yield return group.SamAccountName;
|
|
||||||
}
|
|
||||||
public static string GetGroupsDistinguishedNameForSecurityIdentifier(string SecurityIdentifier)
|
|
||||||
{
|
|
||||||
var group = GetGroupBySecurityIdentifier(SecurityIdentifier);
|
|
||||||
if (group == null)
|
|
||||||
return null;
|
|
||||||
else
|
|
||||||
return group.DistinguishedName;
|
|
||||||
}
|
|
||||||
private static IEnumerable<ActiveDirectoryGroup> GetGroupsRecursive(string DistinguishedName, Stack<ActiveDirectoryGroup> RecursiveTree)
|
|
||||||
{
|
|
||||||
var group = GetGroup(DistinguishedName);
|
|
||||||
|
|
||||||
if (group != null && !RecursiveTree.Contains(group))
|
|
||||||
{
|
|
||||||
yield return group;
|
|
||||||
|
|
||||||
if (group.MemberOf != null)
|
|
||||||
{
|
|
||||||
RecursiveTree.Push(group);
|
|
||||||
|
|
||||||
foreach (var parentDistinguishedName in group.MemberOf)
|
|
||||||
foreach (var parentGroup in GetGroupsRecursive(parentDistinguishedName, RecursiveTree))
|
|
||||||
yield return parentGroup;
|
|
||||||
|
|
||||||
RecursiveTree.Pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ActiveDirectoryGroup GetGroup(string DistinguishedName)
|
|
||||||
{
|
|
||||||
// Check Cache
|
|
||||||
Tuple<ActiveDirectoryGroup, DateTime> groupRecord = TryCache(DistinguishedName);
|
|
||||||
|
|
||||||
if (groupRecord == null)
|
|
||||||
{
|
|
||||||
// Load from AD
|
|
||||||
var group = ActiveDirectory.GetGroupFromDistinguishedName(DistinguishedName);
|
|
||||||
SetValue(group);
|
|
||||||
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Return from Cache
|
|
||||||
return groupRecord.Item1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static ActiveDirectoryGroup GetGroupBySecurityIdentifier(string SecurityIdentifier)
|
|
||||||
{
|
|
||||||
// Check Cache
|
|
||||||
Tuple<ActiveDirectoryGroup, DateTime> groupRecord = TrySecurityIdentifierCache(SecurityIdentifier);
|
|
||||||
|
|
||||||
if (groupRecord == null)
|
|
||||||
{
|
|
||||||
// Load from AD
|
|
||||||
var group = ActiveDirectory.GetGroupFromSecurityIdentifier(SecurityIdentifier);
|
|
||||||
SetValue(group);
|
|
||||||
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Return from Cache
|
|
||||||
return groupRecord.Item1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Tuple<ActiveDirectoryGroup, DateTime> TryCache(string DistinguishedName)
|
|
||||||
{
|
|
||||||
string distinguishedName = DistinguishedName.ToLower();
|
|
||||||
Tuple<ActiveDirectoryGroup, DateTime> groupRecord;
|
|
||||||
if (_DistinguishedNameCache.TryGetValue(distinguishedName, out groupRecord))
|
|
||||||
{
|
|
||||||
if (groupRecord.Item2 > DateTime.Now)
|
|
||||||
return groupRecord;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_DistinguishedNameCache.TryRemove(distinguishedName, out groupRecord))
|
|
||||||
_SecurityIdentifierCache.TryRemove(groupRecord.Item1.SecurityIdentifier, out groupRecord);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
private static Tuple<ActiveDirectoryGroup, DateTime> TrySecurityIdentifierCache(string SecurityIdentifier)
|
|
||||||
{
|
|
||||||
Tuple<ActiveDirectoryGroup, DateTime> groupRecord;
|
|
||||||
if (_SecurityIdentifierCache.TryGetValue(SecurityIdentifier, out groupRecord))
|
|
||||||
{
|
|
||||||
if (groupRecord.Item2 > DateTime.Now)
|
|
||||||
return groupRecord;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_SecurityIdentifierCache.TryRemove(SecurityIdentifier, out groupRecord))
|
|
||||||
_DistinguishedNameCache.TryRemove(groupRecord.Item1.DistinguishedName.ToLower(), out groupRecord);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
private static bool SetValue(ActiveDirectoryGroup Group)
|
|
||||||
{
|
|
||||||
Tuple<ActiveDirectoryGroup, DateTime> groupRecord = new Tuple<ActiveDirectoryGroup, DateTime>(Group, DateTime.Now.AddTicks(CacheTimeoutTicks));
|
|
||||||
Tuple<ActiveDirectoryGroup, DateTime> oldGroupRecord;
|
|
||||||
|
|
||||||
string key = Group.DistinguishedName.ToLower();
|
|
||||||
if (_DistinguishedNameCache.ContainsKey(key))
|
|
||||||
{
|
|
||||||
if (_DistinguishedNameCache.TryGetValue(key, out oldGroupRecord))
|
|
||||||
{
|
|
||||||
_DistinguishedNameCache.TryUpdate(key, groupRecord, oldGroupRecord);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_DistinguishedNameCache.TryAdd(key, groupRecord);
|
|
||||||
}
|
|
||||||
|
|
||||||
string securityIdentifier = Group.SecurityIdentifier;
|
|
||||||
if (_SecurityIdentifierCache.ContainsKey(securityIdentifier))
|
|
||||||
{
|
|
||||||
if (_SecurityIdentifierCache.TryGetValue(securityIdentifier, out oldGroupRecord))
|
|
||||||
{
|
|
||||||
_SecurityIdentifierCache.TryUpdate(securityIdentifier, groupRecord, oldGroupRecord);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_SecurityIdentifierCache.TryAdd(securityIdentifier, groupRecord);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CleanStaleCache()
|
|
||||||
{
|
|
||||||
// Clean Cache
|
|
||||||
var groupKeys = _DistinguishedNameCache.Keys.ToArray();
|
|
||||||
foreach (string groupKey in groupKeys)
|
|
||||||
{
|
|
||||||
Tuple<ActiveDirectoryGroup, DateTime> groupRecord;
|
|
||||||
if (_DistinguishedNameCache.TryGetValue(groupKey, out groupRecord))
|
|
||||||
{
|
|
||||||
if (groupRecord.Item2 <= DateTime.Now)
|
|
||||||
{
|
|
||||||
_DistinguishedNameCache.TryRemove(groupKey, out groupRecord);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean SID Cache
|
|
||||||
groupKeys = _SecurityIdentifierCache.Keys.ToArray();
|
|
||||||
foreach (string groupKey in groupKeys)
|
|
||||||
{
|
|
||||||
Tuple<ActiveDirectoryGroup, DateTime> groupRecord;
|
|
||||||
if (_SecurityIdentifierCache.TryGetValue(groupKey, out groupRecord))
|
|
||||||
{
|
|
||||||
if (groupRecord.Item2 <= DateTime.Now)
|
|
||||||
{
|
|
||||||
_SecurityIdentifierCache.TryRemove(groupKey, out groupRecord);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string TaskName { get { return "AD Group Cache - Clean Stale Cache"; } }
|
|
||||||
|
|
||||||
public override bool SingleInstanceTask { get { return true; } }
|
|
||||||
public override bool CancelInitiallySupported { get { return false; } }
|
|
||||||
public override bool LogExceptionsOnly { get { return true; } }
|
|
||||||
|
|
||||||
public override void InitalizeScheduledTask(DiscoDataContext Database)
|
|
||||||
{
|
|
||||||
// Run @ every 15mins
|
|
||||||
|
|
||||||
// Next 15min interval
|
|
||||||
DateTime now = DateTime.Now;
|
|
||||||
int mins = (15 - (now.Minute % 15));
|
|
||||||
if (mins < 10)
|
|
||||||
mins += 15;
|
|
||||||
DateTimeOffset startAt = new DateTimeOffset(now).AddMinutes(mins).AddSeconds(now.Second * -1).AddMilliseconds(now.Millisecond * -1);
|
|
||||||
|
|
||||||
TriggerBuilder triggerBuilder = TriggerBuilder.Create().StartAt(startAt).
|
|
||||||
WithSchedule(SimpleScheduleBuilder.RepeatMinutelyForever(15));
|
|
||||||
|
|
||||||
this.ScheduleTask(triggerBuilder);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void ExecuteTask()
|
|
||||||
{
|
|
||||||
CleanStaleCache();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
using Disco.Models.Interop.ActiveDirectory;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Disco.BI.Interop.ActiveDirectory
|
|
||||||
{
|
|
||||||
public static class ActiveDirectoryGroupExtensions
|
|
||||||
{
|
|
||||||
|
|
||||||
public static IEnumerable<Tuple<string, string>> GetMembers(ActiveDirectoryGroup group)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,198 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.DirectoryServices;
|
|
||||||
using System.DirectoryServices.ActiveDirectory;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Security.Principal;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace Disco.BI.Interop.ActiveDirectory
|
|
||||||
{
|
|
||||||
internal static class ActiveDirectoryHelpers
|
|
||||||
{
|
|
||||||
#region Static Cached Properties
|
|
||||||
private static string _DefaultDomainName;
|
|
||||||
private static string _DefaultDomainPDCName;
|
|
||||||
private static System.Collections.Generic.List<string> _DefaultDomainDCNames;
|
|
||||||
private static string _DefaultDomainNetBiosName;
|
|
||||||
private static string _DefaultDomainQualifiedName;
|
|
||||||
private static string _DefaultLdapPath;
|
|
||||||
private static bool _DetermineDomainProperties_Loaded = false;
|
|
||||||
private static object _DetermineDomainProperties_Lock = new object();
|
|
||||||
internal static string DefaultDomainName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
ActiveDirectoryHelpers.DetermineDomainProperties();
|
|
||||||
return ActiveDirectoryHelpers._DefaultDomainName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
internal static string DefaultDomainPDCName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
ActiveDirectoryHelpers.DetermineDomainProperties();
|
|
||||||
return ActiveDirectoryHelpers._DefaultDomainPDCName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
internal static System.Collections.Generic.List<string> DefaultDomainDCNames
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
ActiveDirectoryHelpers.DetermineDomainProperties();
|
|
||||||
return ActiveDirectoryHelpers._DefaultDomainDCNames;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
internal static string DefaultDomainNetBiosName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
ActiveDirectoryHelpers.DetermineDomainProperties();
|
|
||||||
return ActiveDirectoryHelpers._DefaultDomainNetBiosName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
internal static string DefaultDomainQualifiedName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
ActiveDirectoryHelpers.DetermineDomainProperties();
|
|
||||||
return ActiveDirectoryHelpers._DefaultDomainQualifiedName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
internal static string DefaultLdapPath
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
ActiveDirectoryHelpers.DetermineDomainProperties();
|
|
||||||
return ActiveDirectoryHelpers._DefaultLdapPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
internal static string DefaultDCLdapPath(string DC)
|
|
||||||
{
|
|
||||||
return string.Format("LDAP://{0}/", DC);
|
|
||||||
}
|
|
||||||
internal static DirectoryEntry DefaultLdapRoot
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return new DirectoryEntry(string.Concat(ActiveDirectoryHelpers.DefaultLdapPath, ActiveDirectoryHelpers.DefaultDomainQualifiedName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
internal static DirectoryEntry DefaultDCLdapRoot(string DC)
|
|
||||||
{
|
|
||||||
return new DirectoryEntry(string.Concat(ActiveDirectoryHelpers.DefaultDCLdapPath(DC), ActiveDirectoryHelpers.DefaultDomainQualifiedName));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void DetermineDomainProperties()
|
|
||||||
{
|
|
||||||
if (!ActiveDirectoryHelpers._DetermineDomainProperties_Loaded)
|
|
||||||
{
|
|
||||||
lock (ActiveDirectoryHelpers._DetermineDomainProperties_Lock)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (!ActiveDirectoryHelpers._DetermineDomainProperties_Loaded)
|
|
||||||
{
|
|
||||||
using (Domain domain = Domain.GetDomain(new DirectoryContext(DirectoryContextType.Domain)))
|
|
||||||
{
|
|
||||||
ActiveDirectoryHelpers._DefaultDomainName = domain.Name;
|
|
||||||
ActiveDirectoryHelpers._DefaultDomainPDCName = domain.PdcRoleOwner.Name;
|
|
||||||
ActiveDirectoryHelpers._DefaultDomainDCNames = new System.Collections.Generic.List<string>(domain.DomainControllers.Count);
|
|
||||||
foreach (DomainController dc in domain.DomainControllers)
|
|
||||||
{
|
|
||||||
ActiveDirectoryHelpers._DefaultDomainDCNames.Add(dc.Name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ActiveDirectoryHelpers._DefaultDomainQualifiedName = string.Format("DC={0}", ActiveDirectoryHelpers._DefaultDomainName.Replace(".", ",DC="));
|
|
||||||
ActiveDirectoryHelpers._DefaultLdapPath = string.Format("LDAP://{0}/", ActiveDirectoryHelpers._DefaultDomainPDCName);
|
|
||||||
using (DirectoryEntry entry = new DirectoryEntry(string.Format("{0}CN=Partitions,CN=Configuration,{1}", ActiveDirectoryHelpers._DefaultLdapPath, ActiveDirectoryHelpers._DefaultDomainQualifiedName)))
|
|
||||||
{
|
|
||||||
using (DirectorySearcher searcher = new DirectorySearcher(entry, "(&(objectClass=crossRef)(nETBIOSName=*))", new string[] { "nETBIOSName" }))
|
|
||||||
{
|
|
||||||
SearchResult result = searcher.FindOne();
|
|
||||||
if (result != null)
|
|
||||||
{
|
|
||||||
ActiveDirectoryHelpers._DefaultDomainNetBiosName = result.Properties["nETBIOSName"][0].ToString();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ActiveDirectoryHelpers._DefaultDomainNetBiosName = ActiveDirectoryHelpers._DefaultDomainQualifiedName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ActiveDirectoryHelpers._DetermineDomainProperties_Loaded = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
internal static string ConvertBytesToSDDLString(byte[] SID)
|
|
||||||
{
|
|
||||||
SecurityIdentifier sID = new SecurityIdentifier(SID, 0);
|
|
||||||
|
|
||||||
return sID.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static byte[] ConvertSDDLStringToBytes(string SidSsdlString)
|
|
||||||
{
|
|
||||||
SecurityIdentifier sID = new SecurityIdentifier(SidSsdlString);
|
|
||||||
|
|
||||||
var sidBytes = new byte[sID.BinaryLength];
|
|
||||||
|
|
||||||
sID.GetBinaryForm(sidBytes, 0);
|
|
||||||
|
|
||||||
return sidBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static byte[] BuildPrimaryGroupSid(byte[] UserSID, int PrimaryGroupId)
|
|
||||||
{
|
|
||||||
var groupSid = (byte[])UserSID.Clone();
|
|
||||||
|
|
||||||
int ridOffset = groupSid.Length - 4;
|
|
||||||
int groupId = PrimaryGroupId;
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
groupSid[ridOffset + i] = (byte)(groupId & 0xFF);
|
|
||||||
groupId >>= 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
return groupSid;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string ConvertBytesToBinarySidString(byte[] SID)
|
|
||||||
{
|
|
||||||
StringBuilder escapedSid = new StringBuilder();
|
|
||||||
|
|
||||||
foreach (var sidByte in SID)
|
|
||||||
{
|
|
||||||
escapedSid.Append('\\');
|
|
||||||
escapedSid.Append(sidByte.ToString("x2"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return escapedSid.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string EscapeLdapQuery(string query)
|
|
||||||
{
|
|
||||||
return query.Replace("*", "\\2a").Replace("(", "\\28").Replace(")", "\\29").Replace("\\", "\\5c").Replace("NUL", "\\00").Replace("/", "\\2f");
|
|
||||||
}
|
|
||||||
internal static string FormatGuidForLdapQuery(System.Guid g)
|
|
||||||
{
|
|
||||||
checked
|
|
||||||
{
|
|
||||||
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
|
||||||
byte[] array = g.ToByteArray();
|
|
||||||
for (int i = 0; i < array.Length; i++)
|
|
||||||
{
|
|
||||||
byte b = array[i];
|
|
||||||
sb.Append("\\");
|
|
||||||
sb.Append(b.ToString("X2"));
|
|
||||||
}
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,301 +0,0 @@
|
|||||||
using Disco.Models.Interop.ActiveDirectory;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.DirectoryServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Net.NetworkInformation;
|
|
||||||
using System.Management;
|
|
||||||
|
|
||||||
namespace Disco.BI.Interop.ActiveDirectory
|
|
||||||
{
|
|
||||||
public static class ActiveDirectoryMachineAccountExtensions
|
|
||||||
{
|
|
||||||
public static void DeleteAccount(this ActiveDirectoryMachineAccount account)
|
|
||||||
{
|
|
||||||
if (account.IsCriticalSystemObject)
|
|
||||||
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
|
||||||
|
|
||||||
using (DirectoryEntry machineDE = new DirectoryEntry(account.Path))
|
|
||||||
{
|
|
||||||
DeleteAccountRecursive(machineDE);
|
|
||||||
|
|
||||||
using (var machineDEParent = machineDE.Parent)
|
|
||||||
{
|
|
||||||
machineDEParent.Children.Remove(machineDE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static void DeleteAccountRecursive(DirectoryEntry parent)
|
|
||||||
{
|
|
||||||
List<DirectoryEntry> children = new List<DirectoryEntry>();
|
|
||||||
foreach (DirectoryEntry child in parent.Children)
|
|
||||||
children.Add(child);
|
|
||||||
|
|
||||||
foreach (var child in children)
|
|
||||||
{
|
|
||||||
DeleteAccountRecursive(child);
|
|
||||||
parent.Children.Remove(child);
|
|
||||||
child.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static void SetNetbootGUID(this ActiveDirectoryMachineAccount account, System.Guid updatedNetbootGUID)
|
|
||||||
{
|
|
||||||
if (account.IsCriticalSystemObject)
|
|
||||||
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
|
||||||
|
|
||||||
using (DirectoryEntry machineDE = new DirectoryEntry(account.Path))
|
|
||||||
{
|
|
||||||
PropertyValueCollection netbootGUIDProp = machineDE.Properties["netbootGUID"];
|
|
||||||
bool flag = netbootGUIDProp.Count > 0;
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
netbootGUIDProp.Clear();
|
|
||||||
}
|
|
||||||
netbootGUIDProp.Add(updatedNetbootGUID.ToByteArray());
|
|
||||||
machineDE.CommitChanges();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static void SetDescription(this ActiveDirectoryMachineAccount account, string Description)
|
|
||||||
{
|
|
||||||
using (DirectoryEntry machineDE = new DirectoryEntry(account.Path))
|
|
||||||
{
|
|
||||||
PropertyValueCollection descriptionProp = machineDE.Properties["description"];
|
|
||||||
if (descriptionProp.Count > 0)
|
|
||||||
{
|
|
||||||
descriptionProp.Clear();
|
|
||||||
}
|
|
||||||
if (!string.IsNullOrEmpty(Description))
|
|
||||||
{
|
|
||||||
descriptionProp.Add(Description);
|
|
||||||
}
|
|
||||||
machineDE.CommitChanges();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static void SetDescription(this ActiveDirectoryMachineAccount account, Device Device)
|
|
||||||
{
|
|
||||||
System.Text.StringBuilder descriptionBuilder = new System.Text.StringBuilder();
|
|
||||||
|
|
||||||
if (Device.AssignedUserId != null)
|
|
||||||
{
|
|
||||||
descriptionBuilder.Append(Device.AssignedUser.Id).Append(" (").Append(Device.AssignedUser.DisplayName).Append("); ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Device.DeviceModelId.HasValue)
|
|
||||||
{
|
|
||||||
descriptionBuilder.Append(Device.DeviceModel.Description).Append("; ");
|
|
||||||
}
|
|
||||||
|
|
||||||
descriptionBuilder.Append(Device.DeviceProfile.Description).Append(";");
|
|
||||||
|
|
||||||
string description = descriptionBuilder.ToString().Trim();
|
|
||||||
if (description.Length > 1024)
|
|
||||||
{
|
|
||||||
description = description.Substring(0, 1024);
|
|
||||||
}
|
|
||||||
account.SetDescription(description);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void DisableAccount(this ActiveDirectoryMachineAccount account)
|
|
||||||
{
|
|
||||||
if (account.IsCriticalSystemObject)
|
|
||||||
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
|
||||||
|
|
||||||
using (DirectoryEntry machineDE = new DirectoryEntry(account.Path))
|
|
||||||
{
|
|
||||||
int accountControl = (int)machineDE.Properties["userAccountControl"][0];
|
|
||||||
int updatedAccountControl = (accountControl | 2);
|
|
||||||
if (accountControl != updatedAccountControl)
|
|
||||||
{
|
|
||||||
machineDE.Properties["userAccountControl"][0] = updatedAccountControl;
|
|
||||||
machineDE.CommitChanges();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static void EnableAccount(this ActiveDirectoryMachineAccount account)
|
|
||||||
{
|
|
||||||
if (account.IsCriticalSystemObject)
|
|
||||||
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
|
||||||
|
|
||||||
using (DirectoryEntry machineDE = new DirectoryEntry(account.Path))
|
|
||||||
{
|
|
||||||
int accountControl = (int)machineDE.Properties["userAccountControl"][0];
|
|
||||||
if ((accountControl & 2) == 2)
|
|
||||||
{
|
|
||||||
int updatedAccountControl = (accountControl ^ 2);
|
|
||||||
machineDE.Properties["userAccountControl"][0] = updatedAccountControl;
|
|
||||||
machineDE.CommitChanges();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool UpdateNetbootGUID(this ActiveDirectoryMachineAccount account, string UUID, string MACAddress)
|
|
||||||
{
|
|
||||||
if (account.IsCriticalSystemObject)
|
|
||||||
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
|
||||||
|
|
||||||
System.Guid netbootGUID = System.Guid.Empty;
|
|
||||||
bool flag = !string.IsNullOrWhiteSpace(UUID);
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
netbootGUID = ActiveDirectoryMachineAccountExtensions.NetbootGUIDFromUUID(UUID);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
flag = !string.IsNullOrWhiteSpace(MACAddress);
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
netbootGUID = ActiveDirectoryMachineAccountExtensions.NetbootGUIDFromMACAddress(MACAddress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
flag = (netbootGUID != System.Guid.Empty && netbootGUID != account.NetbootGUID);
|
|
||||||
bool UpdateNetbootGUID;
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
account.SetNetbootGUID(netbootGUID);
|
|
||||||
UpdateNetbootGUID = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateNetbootGUID = false;
|
|
||||||
}
|
|
||||||
return UpdateNetbootGUID;
|
|
||||||
}
|
|
||||||
internal static System.Guid NetbootGUIDFromMACAddress(string MACAddress)
|
|
||||||
{
|
|
||||||
string strippedMACAddress = MACAddress.Trim().Replace(":", string.Empty).Replace("-", string.Empty);
|
|
||||||
bool flag = strippedMACAddress.Length == 12;
|
|
||||||
System.Guid NetbootGUIDFromMACAddress;
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
System.Guid guid = new System.Guid(string.Format("00000000-0000-0000-0000-{0}", strippedMACAddress));
|
|
||||||
NetbootGUIDFromMACAddress = guid;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NetbootGUIDFromMACAddress = System.Guid.Empty;
|
|
||||||
}
|
|
||||||
return NetbootGUIDFromMACAddress;
|
|
||||||
}
|
|
||||||
internal static System.Guid NetbootGUIDFromUUID(string UUID)
|
|
||||||
{
|
|
||||||
System.Guid result = new System.Guid(UUID);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static object GetPropertyValue(this ActiveDirectoryMachineAccount account, string PropertyName, int Index = 0)
|
|
||||||
{
|
|
||||||
switch (PropertyName.ToLower())
|
|
||||||
{
|
|
||||||
case "name":
|
|
||||||
return account.Name;
|
|
||||||
case "samaccountname":
|
|
||||||
return account.SamAccountName;
|
|
||||||
case "distinguishedname":
|
|
||||||
return account.DistinguishedName;
|
|
||||||
case "objectsid":
|
|
||||||
return account.SecurityIdentifier;
|
|
||||||
case "netbootguid":
|
|
||||||
return account.NetbootGUID;
|
|
||||||
default:
|
|
||||||
object[] adProperty;
|
|
||||||
if (account.LoadedProperties.TryGetValue(PropertyName, out adProperty) && Index <= adProperty.Length)
|
|
||||||
return adProperty[Index];
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IPStatus PingComputer(this ActiveDirectoryMachineAccount account, int Timeout = 2000)
|
|
||||||
{
|
|
||||||
using (var p = new Ping())
|
|
||||||
{
|
|
||||||
PingReply reply = p.Send(account.DnsName, Timeout);
|
|
||||||
return reply.Status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Didn't Work - WMI Limitation?
|
|
||||||
// G# - 2012-06-18
|
|
||||||
//public static void OnlineRenameComputer(this ActiveDirectoryMachineAccount account, string NewComputerName)
|
|
||||||
//{
|
|
||||||
// if (account.IsCriticalSystemObject)
|
|
||||||
// throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
|
||||||
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// IPStatus pingResult = account.PingComputer();
|
|
||||||
// if (pingResult != IPStatus.Success)
|
|
||||||
// throw new Exception(string.Format("Ping Error Result: {0}", pingResult.ToString()));
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// throw new Exception(string.Format("Error trying to Ping the Device: {0}; {1}", account.DnsName, ex.Message), ex);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ConnectionOptions wmiConnectionOptions = new ConnectionOptions()
|
|
||||||
// {
|
|
||||||
// Authentication = AuthenticationLevel.PacketPrivacy,
|
|
||||||
// Impersonation = ImpersonationLevel.Impersonate,
|
|
||||||
// EnablePrivileges = true,
|
|
||||||
// Timeout = new TimeSpan(0, 0, 6)
|
|
||||||
// };
|
|
||||||
// ManagementPath wmiPath = new ManagementPath()
|
|
||||||
// {
|
|
||||||
// Server = account.DnsName,
|
|
||||||
// NamespacePath = @"root\cimv2",
|
|
||||||
// ClassName = "Win32_ComputerSystem"
|
|
||||||
// };
|
|
||||||
|
|
||||||
// ManagementScope wmiScope = new ManagementScope(wmiPath, wmiConnectionOptions);
|
|
||||||
|
|
||||||
// ObjectGetOptions wmiGetOptions = new ObjectGetOptions() { Timeout = new TimeSpan(0, 1, 0) };
|
|
||||||
|
|
||||||
// using (ManagementClass wmiClass = new ManagementClass(wmiScope, wmiPath, wmiGetOptions))
|
|
||||||
// {
|
|
||||||
// foreach (ManagementObject wmiWin32ComputerSystem in wmiClass.GetInstances())
|
|
||||||
// {
|
|
||||||
// UInt32 result = (UInt32)wmiWin32ComputerSystem.InvokeMethod("Rename", new object[] { NewComputerName });
|
|
||||||
// if (result != 0)
|
|
||||||
// throw new Exception(string.Format("Error Renaming Computer; WMI Remote Method 'Rename' returned: {0}", result));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
public static void MoveOrganisationUnit(this ActiveDirectoryMachineAccount account, string NewOrganisationUnit)
|
|
||||||
{
|
|
||||||
if (account.IsCriticalSystemObject)
|
|
||||||
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
|
|
||||||
|
|
||||||
var parentDistinguishedName = account.ParentDistinguishedName();
|
|
||||||
|
|
||||||
if (parentDistinguishedName != null && !parentDistinguishedName.Equals(NewOrganisationUnit, StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
{
|
|
||||||
string ouPath;
|
|
||||||
if (string.IsNullOrWhiteSpace(NewOrganisationUnit))
|
|
||||||
ouPath = string.Format("{0}CN=Computers,{1}", ActiveDirectoryHelpers.DefaultLdapPath, ActiveDirectoryHelpers.DefaultDomainQualifiedName);
|
|
||||||
else
|
|
||||||
ouPath = string.Format("{0}{1},{2}", ActiveDirectoryHelpers.DefaultLdapPath, NewOrganisationUnit, ActiveDirectoryHelpers.DefaultDomainQualifiedName);
|
|
||||||
|
|
||||||
using (DirectoryEntry ou = new DirectoryEntry(ouPath))
|
|
||||||
{
|
|
||||||
using (DirectoryEntry i = new DirectoryEntry(account.Path) { UsePropertyCache = false })
|
|
||||||
{
|
|
||||||
i.MoveTo(ou);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string ParentDistinguishedName(this ActiveDirectoryMachineAccount account)
|
|
||||||
{
|
|
||||||
// Determine Parent
|
|
||||||
if (!string.IsNullOrWhiteSpace(account.DistinguishedName))
|
|
||||||
return account.DistinguishedName.Substring(0, account.DistinguishedName.IndexOf(",DC=")).Substring(account.DistinguishedName.IndexOf(",") + 1);
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Disco.BI.Interop.ActiveDirectory
|
|
||||||
{
|
|
||||||
public class ActiveDirectoryOrganisationalUnit
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Path { get; set; }
|
|
||||||
public List<ActiveDirectoryOrganisationalUnit> Children { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,264 +0,0 @@
|
|||||||
using Disco.Data.Repository;
|
|
||||||
using Disco.Services.Logging;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
using Quartz;
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.DirectoryServices;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Net.NetworkInformation;
|
|
||||||
using System.Reflection;
|
|
||||||
using Disco.Services.Tasks;
|
|
||||||
namespace Disco.BI.Interop.ActiveDirectory
|
|
||||||
{
|
|
||||||
public class ActiveDirectoryUpdateLastNetworkLogonDateJob : ScheduledTask
|
|
||||||
{
|
|
||||||
|
|
||||||
public override string TaskName { get { return "Active Directory - Update Last Network Logon Dates Task"; } }
|
|
||||||
public override bool SingleInstanceTask { get { return true; } }
|
|
||||||
public override bool CancelInitiallySupported { get { return false; } }
|
|
||||||
|
|
||||||
public override void InitalizeScheduledTask(DiscoDataContext Database)
|
|
||||||
{
|
|
||||||
// ActiveDirectoryUpdateLastNetworkLogonDateJob @ 11:30pm
|
|
||||||
TriggerBuilder triggerBuilder = TriggerBuilder.Create().
|
|
||||||
WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(23, 30));
|
|
||||||
|
|
||||||
this.ScheduleTask(triggerBuilder);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void ExecuteTask()
|
|
||||||
{
|
|
||||||
int changeCount;
|
|
||||||
|
|
||||||
this.Status.UpdateStatus(1, "Starting", "Connecting to the Database and initializing the environment");
|
|
||||||
using (DiscoDataContext database = new DiscoDataContext())
|
|
||||||
{
|
|
||||||
UpdateLastNetworkLogonDates(database, this.Status);
|
|
||||||
this.Status.UpdateStatus(95, "Updating Database", "Writing last network logon dates to the Database");
|
|
||||||
changeCount = database.SaveChanges();
|
|
||||||
this.Status.Finished(string.Format("{0} Device last network logon dates updated", changeCount), "/Config/SystemConfig");
|
|
||||||
}
|
|
||||||
|
|
||||||
SystemLog.LogInformation(new string[]
|
|
||||||
{
|
|
||||||
"Updated LastNetworkLogon Device Property for Device/s",
|
|
||||||
changeCount.ToString()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ScheduledTaskStatus ScheduleImmediately()
|
|
||||||
{
|
|
||||||
var existingTask = ScheduledTasks.GetTaskStatuses(typeof(ActiveDirectoryUpdateLastNetworkLogonDateJob)).Where(s => s.IsRunning).FirstOrDefault();
|
|
||||||
if (existingTask != null)
|
|
||||||
return existingTask;
|
|
||||||
|
|
||||||
var instance = new ActiveDirectoryUpdateLastNetworkLogonDateJob();
|
|
||||||
return instance.ScheduleTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool UpdateLastNetworkLogonDate(Device Device)
|
|
||||||
{
|
|
||||||
System.DateTime? computerLastLogonDate = Device.LastNetworkLogonDate;
|
|
||||||
if (!string.IsNullOrEmpty(Device.ComputerName))
|
|
||||||
{
|
|
||||||
foreach (var dcName in ActiveDirectoryHelpers.DefaultDomainDCNames)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Ping p = new Ping();
|
|
||||||
PingReply pr;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
pr = p.Send(dcName, 500);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (p != null)
|
|
||||||
{
|
|
||||||
((System.IDisposable)p).Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pr.Status == IPStatus.Success)
|
|
||||||
{
|
|
||||||
using (DirectoryEntry dRootEntry = ActiveDirectoryHelpers.DefaultDCLdapRoot(dcName))
|
|
||||||
{
|
|
||||||
DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, string.Format("(&(objectCategory=Computer)(sAMAccountName={0}$))", ActiveDirectoryHelpers.EscapeLdapQuery(Device.ComputerName)), new string[]
|
|
||||||
{
|
|
||||||
"lastLogon"
|
|
||||||
}, SearchScope.Subtree);
|
|
||||||
SearchResult dResult = dSearcher.FindOne();
|
|
||||||
if (dResult != null)
|
|
||||||
{
|
|
||||||
ResultPropertyValueCollection dProp = dResult.Properties["lastLogon"];
|
|
||||||
if (dProp != null && dProp.Count > 0)
|
|
||||||
{
|
|
||||||
long lastLogonInt = (long)dProp[0];
|
|
||||||
if (lastLogonInt > 0L)
|
|
||||||
{
|
|
||||||
System.DateTime computerNameDate = System.DateTime.FromFileTime(lastLogonInt);
|
|
||||||
if (computerLastLogonDate.HasValue)
|
|
||||||
{
|
|
||||||
if (System.DateTime.Compare(computerLastLogonDate.Value, computerNameDate) < 0)
|
|
||||||
{
|
|
||||||
computerLastLogonDate = computerNameDate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
computerLastLogonDate = computerNameDate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SystemLog.LogError(new string[]
|
|
||||||
{
|
|
||||||
string.Format("Unable to ping Domain Controller: '{0}' (ref: Disco.BI.Interop.ActiveDirectory.ActiveDirectoryUpdateLastNetworkLogonDateJob.UpdateDeviceLastNetworkLogonDate)", dcName)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (System.Exception ex)
|
|
||||||
{
|
|
||||||
SystemLog.LogException("UpdateDeviceLastNetworkLogonDate", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool UpdateLastNetworkLogonDate;
|
|
||||||
if (computerLastLogonDate.HasValue)
|
|
||||||
{
|
|
||||||
if (!Device.LastNetworkLogonDate.HasValue)
|
|
||||||
{
|
|
||||||
Device.LastNetworkLogonDate = computerLastLogonDate;
|
|
||||||
UpdateLastNetworkLogonDate = true;
|
|
||||||
return UpdateLastNetworkLogonDate;
|
|
||||||
}
|
|
||||||
if (System.DateTime.Compare(computerLastLogonDate.Value, Device.LastNetworkLogonDate.Value) > 0)
|
|
||||||
{
|
|
||||||
Device.LastNetworkLogonDate = computerLastLogonDate;
|
|
||||||
UpdateLastNetworkLogonDate = true;
|
|
||||||
return UpdateLastNetworkLogonDate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UpdateLastNetworkLogonDate = false;
|
|
||||||
return UpdateLastNetworkLogonDate;
|
|
||||||
}
|
|
||||||
private static void UpdateLastNetworkLogonDates(DiscoDataContext Database, ScheduledTaskStatus status)
|
|
||||||
{
|
|
||||||
System.Collections.Generic.Dictionary<string, System.DateTime> computerLastLogonDates = new System.Collections.Generic.Dictionary<string, System.DateTime>();
|
|
||||||
|
|
||||||
int progressDCCountTotal = ActiveDirectoryHelpers.DefaultDomainDCNames.Count;
|
|
||||||
int progressDCCount = 0;
|
|
||||||
double progressDCProgress = 0;
|
|
||||||
if (progressDCCountTotal > 0)
|
|
||||||
progressDCProgress = 90 / progressDCCountTotal;
|
|
||||||
|
|
||||||
foreach (var dcName in ActiveDirectoryHelpers.DefaultDomainDCNames)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
PingReply pr;
|
|
||||||
using (Ping p = new Ping())
|
|
||||||
{
|
|
||||||
pr = p.Send(dcName, 2000);
|
|
||||||
}
|
|
||||||
if (pr.Status == IPStatus.Success)
|
|
||||||
{
|
|
||||||
using (DirectoryEntry dRootEntry = ActiveDirectoryHelpers.DefaultDCLdapRoot(dcName))
|
|
||||||
{
|
|
||||||
double progressDCStart = 5 + (progressDCCount * progressDCProgress);
|
|
||||||
status.UpdateStatus(progressDCStart, string.Format("Querying Domain Controller: {0}", dcName), "Searching...");
|
|
||||||
|
|
||||||
using (DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, "(objectCategory=Computer)", new string[] { "sAMAccountName", "lastLogon" }, SearchScope.Subtree))
|
|
||||||
{
|
|
||||||
using (SearchResultCollection dResults = dSearcher.FindAll())
|
|
||||||
{
|
|
||||||
|
|
||||||
int progressItemCount = 0;
|
|
||||||
double progressItemProgress = dResults.Count == 0 ? 0 : (progressDCProgress / dResults.Count);
|
|
||||||
|
|
||||||
foreach (SearchResult dResult in dResults)
|
|
||||||
{
|
|
||||||
ResultPropertyValueCollection dProp = dResult.Properties["sAMAccountName"];
|
|
||||||
if (dProp != null && dProp.Count > 0)
|
|
||||||
{
|
|
||||||
string computerName = ((string)dProp[0]).TrimEnd(new char[] { '$' }).ToUpper();
|
|
||||||
|
|
||||||
if (progressItemCount % 150 == 0) // Only Update Status every 150 devices
|
|
||||||
status.UpdateStatus(progressDCStart + (progressItemProgress * progressItemCount), string.Format("Analysing Device: {0}", computerName));
|
|
||||||
|
|
||||||
dProp = dResult.Properties["lastLogon"];
|
|
||||||
if (dProp != null && dProp.Count > 0)
|
|
||||||
{
|
|
||||||
long lastLogonInt = (long)dProp[0];
|
|
||||||
if (lastLogonInt > 0L)
|
|
||||||
{
|
|
||||||
System.DateTime computerNameDate = System.DateTime.FromFileTime(lastLogonInt);
|
|
||||||
System.DateTime existingDate;
|
|
||||||
if (computerLastLogonDates.TryGetValue(computerName, out existingDate))
|
|
||||||
{
|
|
||||||
if (System.DateTime.Compare(existingDate, computerNameDate) < 0)
|
|
||||||
{
|
|
||||||
computerLastLogonDates[computerName] = computerNameDate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
computerLastLogonDates[computerName] = computerNameDate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
progressItemCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SystemLog.LogError(new string[]
|
|
||||||
{
|
|
||||||
string.Format("Unable to ping Domain Controller: '{0}' (ref: Disco.BI.Interop.ActiveDirectory.ActiveDirectoryUpdateLastNetworkLogonDateJob.UpdateLastNetworkLogonDates)", dcName)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (System.Exception ex)
|
|
||||||
{
|
|
||||||
SystemLog.LogException("UpdateLastNetworkLogonDates", ex);
|
|
||||||
}
|
|
||||||
progressDCCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
foreach (Device d in Database.Devices.Where(device => device.ComputerName != null))
|
|
||||||
{
|
|
||||||
DateTime computerLastLogonDate;
|
|
||||||
if (computerLastLogonDates.TryGetValue(d.ComputerName.ToUpper(), out computerLastLogonDate))
|
|
||||||
{
|
|
||||||
if (d.LastNetworkLogonDate.HasValue)
|
|
||||||
{
|
|
||||||
// Change accuracy to the second
|
|
||||||
computerLastLogonDate = new DateTime((computerLastLogonDate.Ticks / 10000000L) * 10000000L);
|
|
||||||
|
|
||||||
if (System.DateTime.Compare(d.LastNetworkLogonDate.Value, computerLastLogonDate) < 0)
|
|
||||||
{
|
|
||||||
d.LastNetworkLogonDate = computerLastLogonDate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d.LastNetworkLogonDate = computerLastLogonDate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
using Disco.Models.Interop.ActiveDirectory;
|
|
||||||
using System;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
namespace Disco.BI.Interop.ActiveDirectory
|
|
||||||
{
|
|
||||||
internal static class ActiveDirectoryUserAccountExtensions
|
|
||||||
{
|
|
||||||
public static object GetPropertyValue(this ActiveDirectoryUserAccount account, string PropertyName, int Index = 0)
|
|
||||||
{
|
|
||||||
switch (PropertyName.ToLower())
|
|
||||||
{
|
|
||||||
case "name":
|
|
||||||
return account.Name;
|
|
||||||
case "samaccountname":
|
|
||||||
return account.SamAccountName;
|
|
||||||
case "distinguishedname":
|
|
||||||
return account.DistinguishedName;
|
|
||||||
case "objectsid":
|
|
||||||
return account.SecurityIdentifier;
|
|
||||||
case "sn":
|
|
||||||
return account.Surname;
|
|
||||||
case "givenname":
|
|
||||||
return account.GivenName;
|
|
||||||
case "mail":
|
|
||||||
return account.Email;
|
|
||||||
case "telephonenumber":
|
|
||||||
return account.Phone;
|
|
||||||
default:
|
|
||||||
object[] adProperty;
|
|
||||||
if (account.LoadedProperties.TryGetValue(PropertyName, out adProperty) && Index <= adProperty.Length)
|
|
||||||
return adProperty[Index];
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -29,15 +29,12 @@ namespace Disco.BI.Interop.Community
|
|||||||
return string.Format("{0}.{1}.{2:0000}.{3:0000}", v.Major, v.Minor, v.Build, v.Revision);
|
return string.Format("{0}.{1}.{2:0000}.{3:0000}", v.Major, v.Minor, v.Build, v.Revision);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UpdateResponse Check(DiscoDataContext Database, bool UseProxy, ScheduledTaskStatus status = null)
|
public static UpdateResponse Check(DiscoDataContext Database, bool UseProxy, IScheduledTaskStatus status)
|
||||||
{
|
{
|
||||||
if (status != null)
|
|
||||||
status.UpdateStatus(10, "Building Update Request");
|
status.UpdateStatus(10, "Building Update Request");
|
||||||
|
|
||||||
var request = BuildRequest(Database);
|
var request = BuildRequest(Database);
|
||||||
//var requestJson = JsonConvert.SerializeObject(request);
|
|
||||||
|
|
||||||
if (status != null)
|
|
||||||
status.UpdateStatus(40, "Sending Request");
|
status.UpdateStatus(40, "Sending Request");
|
||||||
|
|
||||||
var DiscoBIVersion = CurrentDiscoVersionFormatted();
|
var DiscoBIVersion = CurrentDiscoVersionFormatted();
|
||||||
@@ -61,13 +58,11 @@ namespace Disco.BI.Interop.Community
|
|||||||
XmlSerializer xml = new XmlSerializer(typeof(UpdateRequestV1));
|
XmlSerializer xml = new XmlSerializer(typeof(UpdateRequestV1));
|
||||||
xml.Serialize(wrStream, request);
|
xml.Serialize(wrStream, request);
|
||||||
}
|
}
|
||||||
if (status != null)
|
|
||||||
status.UpdateStatus(50, "Waiting for Response");
|
status.UpdateStatus(50, "Waiting for Response");
|
||||||
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
|
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
|
||||||
{
|
{
|
||||||
if (webResponse.StatusCode == HttpStatusCode.OK)
|
if (webResponse.StatusCode == HttpStatusCode.OK)
|
||||||
{
|
{
|
||||||
if (status != null)
|
|
||||||
status.UpdateStatus(90, "Reading Response");
|
status.UpdateStatus(90, "Reading Response");
|
||||||
UpdateResponse result;
|
UpdateResponse result;
|
||||||
using (var wResStream = webResponse.GetResponseStream())
|
using (var wResStream = webResponse.GetResponseStream())
|
||||||
@@ -75,7 +70,6 @@ namespace Disco.BI.Interop.Community
|
|||||||
XmlSerializer xml = new XmlSerializer(typeof(UpdateResponse));
|
XmlSerializer xml = new XmlSerializer(typeof(UpdateResponse));
|
||||||
result = (UpdateResponse)xml.Deserialize(wResStream);
|
result = (UpdateResponse)xml.Deserialize(wResStream);
|
||||||
}
|
}
|
||||||
//var result = JsonConvert.DeserializeObject<UpdateResponse>(responseContent);
|
|
||||||
Database.DiscoConfiguration.UpdateLastCheck = result;
|
Database.DiscoConfiguration.UpdateLastCheck = result;
|
||||||
Database.SaveChanges();
|
Database.SaveChanges();
|
||||||
|
|
||||||
@@ -85,7 +79,6 @@ namespace Disco.BI.Interop.Community
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (status != null)
|
|
||||||
status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
|
status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
using System;
|
using Disco.BI.Expressions;
|
||||||
using System.Collections.Generic;
|
using Disco.BI.Extensions;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
using Disco.Data.Repository;
|
using Disco.Data.Repository;
|
||||||
using Disco.Models.BI.DocumentTemplates;
|
using Disco.Models.BI.DocumentTemplates;
|
||||||
using System.IO;
|
|
||||||
using iTextSharp.text.pdf;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using Disco.BI.Expressions;
|
|
||||||
using System.Collections;
|
|
||||||
using Disco.BI.Extensions;
|
|
||||||
using Disco.Models.BI.Expressions;
|
using Disco.Models.BI.Expressions;
|
||||||
|
using Disco.Models.Repository;
|
||||||
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
using Disco.Services.Users;
|
using Disco.Services.Users;
|
||||||
|
using iTextSharp.text.pdf;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Disco.BI.Interop.Pdf
|
namespace Disco.BI.Interop.Pdf
|
||||||
{
|
{
|
||||||
@@ -65,9 +65,11 @@ namespace Disco.BI.Interop.Pdf
|
|||||||
DataObjects = new object[DataObjectsIds.Length];
|
DataObjects = new object[DataObjectsIds.Length];
|
||||||
for (int idIndex = 0; idIndex < DataObjectsIds.Length; idIndex++)
|
for (int idIndex = 0; idIndex < DataObjectsIds.Length; idIndex++)
|
||||||
{
|
{
|
||||||
DataObjects[idIndex] = UserService.GetUser(DataObjectsIds[idIndex], Database, true);
|
string dataObjectId = DataObjectsIds[idIndex];
|
||||||
|
|
||||||
|
DataObjects[idIndex] = UserService.GetUser(ActiveDirectory.ParseDomainAccountId(dataObjectId), Database, true);
|
||||||
if (DataObjects[idIndex] == null)
|
if (DataObjects[idIndex] == null)
|
||||||
throw new Exception(string.Format("Unknown Username specified: {0}", DataObjectsIds[idIndex]));
|
throw new Exception(string.Format("Unknown Username specified: {0}", dataObjectId));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -119,10 +121,10 @@ namespace Disco.BI.Interop.Pdf
|
|||||||
|
|
||||||
foreach (string pdfFieldKey in pdfStamper.AcroFields.Fields.Keys)
|
foreach (string pdfFieldKey in pdfStamper.AcroFields.Fields.Keys)
|
||||||
{
|
{
|
||||||
if (pdfFieldKey.Equals("DiscoAttachmentId", StringComparison.InvariantCultureIgnoreCase))
|
if (pdfFieldKey.Equals("DiscoAttachmentId", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
AcroFields.Item fields = pdfStamper.AcroFields.Fields[pdfFieldKey];
|
AcroFields.Item fields = pdfStamper.AcroFields.Fields[pdfFieldKey];
|
||||||
string fieldValue = dt.UniqueIdentifier(Data, CreatorUser.Id, TimeStamp);
|
string fieldValue = dt.UniqueIdentifier(Data, CreatorUser.UserId, TimeStamp);
|
||||||
if (FlattenFields)
|
if (FlattenFields)
|
||||||
pdfStamper.AcroFields.SetField(pdfFieldKey, String.Empty);
|
pdfStamper.AcroFields.SetField(pdfFieldKey, String.Empty);
|
||||||
else
|
else
|
||||||
@@ -132,7 +134,7 @@ namespace Disco.BI.Interop.Pdf
|
|||||||
for (int pdfFieldOrdinal = 0; pdfFieldOrdinal < fields.Size; pdfFieldOrdinal++)
|
for (int pdfFieldOrdinal = 0; pdfFieldOrdinal < fields.Size; pdfFieldOrdinal++)
|
||||||
{
|
{
|
||||||
AcroFields.FieldPosition pdfFieldPosition = pdfFieldPositions[pdfFieldOrdinal];
|
AcroFields.FieldPosition pdfFieldPosition = pdfFieldPositions[pdfFieldOrdinal];
|
||||||
string pdfBarcodeContent = dt.UniquePageIdentifier(Data, CreatorUser.Id, TimeStamp, pdfFieldPosition.page);
|
string pdfBarcodeContent = dt.UniquePageIdentifier(Data, CreatorUser.UserId, TimeStamp, pdfFieldPosition.page);
|
||||||
BarcodeQRCode pdfBarcode = new BarcodeQRCode(pdfBarcodeContent, (int)pdfFieldPosition.position.Width, (int)pdfFieldPosition.position.Height, null);
|
BarcodeQRCode pdfBarcode = new BarcodeQRCode(pdfBarcodeContent, (int)pdfFieldPosition.position.Width, (int)pdfFieldPosition.position.Height, null);
|
||||||
iTextSharp.text.Image pdfBarcodeImage = pdfBarcode.GetImage();
|
iTextSharp.text.Image pdfBarcodeImage = pdfBarcode.GetImage();
|
||||||
pdfBarcodeImage.SetAbsolutePosition(pdfFieldPosition.position.Left, pdfFieldPosition.position.Bottom);
|
pdfBarcodeImage.SetAbsolutePosition(pdfFieldPosition.position.Left, pdfFieldPosition.position.Bottom);
|
||||||
@@ -237,7 +239,7 @@ namespace Disco.BI.Interop.Pdf
|
|||||||
JobLog jl = new JobLog()
|
JobLog jl = new JobLog()
|
||||||
{
|
{
|
||||||
JobId = j.Id,
|
JobId = j.Id,
|
||||||
TechUserId = CreatorUser.Id,
|
TechUserId = CreatorUser.UserId,
|
||||||
Timestamp = DateTime.Now
|
Timestamp = DateTime.Now
|
||||||
};
|
};
|
||||||
jl.Comments = string.Format("Document Generated{0}{1} [{2}]", Environment.NewLine, dt.Description, dt.Id);
|
jl.Comments = string.Format("Document Generated{0}{1} [{2}]", Environment.NewLine, dt.Description, dt.Id);
|
||||||
|
|||||||
@@ -409,7 +409,7 @@ namespace Disco.BI.Interop.Pdf
|
|||||||
pdfPagesAssigned.Add(PageNumber, new Tuple<DocumentUniqueIdentifier, byte[]>(docId, pageResult.AttachmentThumbnailImage.ToArray()));
|
pdfPagesAssigned.Add(PageNumber, new Tuple<DocumentUniqueIdentifier, byte[]>(docId, pageResult.AttachmentThumbnailImage.ToArray()));
|
||||||
|
|
||||||
docId.LoadComponents(Database);
|
docId.LoadComponents(Database);
|
||||||
DocumentImporterLog.LogImportPageDetected(SessionId, PageNumber, docId.DocumentUniqueId, docId.DocumentTemplate.Description, docId.DocumentTemplate.Scope, docId.DataId, docId.DataDescription);
|
DocumentImporterLog.LogImportPageDetected(SessionId, PageNumber, docId.TemplateTypeId, docId.DocumentTemplate.Description, docId.DocumentTemplate.Scope, docId.DataId, docId.DataDescription);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
using Disco.Services.Users;
|
|
||||||
using Microsoft.AspNet.SignalR;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Disco.BI.Interop.SignalRHandlers
|
|
||||||
{
|
|
||||||
public class AuthorizedPersistentConnection : PersistentConnection
|
|
||||||
{
|
|
||||||
private string authorizedClaim = null;
|
|
||||||
|
|
||||||
protected virtual string AuthorizedClaim { get { return authorizedClaim; } }
|
|
||||||
|
|
||||||
protected override bool AuthorizeRequest(IRequest request)
|
|
||||||
{
|
|
||||||
if (!request.User.Identity.IsAuthenticated)
|
|
||||||
return false;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var authToken = UserService.CurrentAuthorization;
|
|
||||||
|
|
||||||
if (authToken == null)
|
|
||||||
return false; // No Current User
|
|
||||||
|
|
||||||
if (authorizedClaim == null)
|
|
||||||
return true; // Just Authenticate - no Authorization
|
|
||||||
else
|
|
||||||
return authToken.Has(authorizedClaim);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Microsoft.AspNet.SignalR;
|
|
||||||
using System.Reactive.Linq;
|
|
||||||
using Disco.Data.Repository.Monitor;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
|
|
||||||
namespace Disco.BI.Interop.SignalRHandlers
|
|
||||||
{
|
|
||||||
public class HeldDeviceNotifications : PersistentConnection
|
|
||||||
{
|
|
||||||
private static bool subscribed = false;
|
|
||||||
private static object subscribeLock = new object();
|
|
||||||
private static IPersistentConnectionContext notificationContext;
|
|
||||||
|
|
||||||
static HeldDeviceNotifications()
|
|
||||||
{
|
|
||||||
if (!subscribed)
|
|
||||||
lock (subscribeLock)
|
|
||||||
if (!subscribed)
|
|
||||||
{
|
|
||||||
notificationContext = GlobalHost.ConnectionManager.GetConnectionContext<HeldDeviceNotifications>();
|
|
||||||
|
|
||||||
Disco.Data.Repository.Monitor.RepositoryMonitor.StreamAfterCommit.Where(e => e.EntityType == typeof(Job)).Subscribe(JobUpdated);
|
|
||||||
|
|
||||||
Disco.Data.Repository.Monitor.RepositoryMonitor.StreamAfterCommit.Where(e =>
|
|
||||||
e.EntityType == typeof(Device) &&
|
|
||||||
(e.ModifiedProperties.Contains("Location") ||
|
|
||||||
e.ModifiedProperties.Contains("DeviceModelId") ||
|
|
||||||
e.ModifiedProperties.Contains("DeviceProfileId") ||
|
|
||||||
e.ModifiedProperties.Contains("DeviceBatchId") ||
|
|
||||||
e.ModifiedProperties.Contains("ComputerName") ||
|
|
||||||
e.ModifiedProperties.Contains("AssignedUserId"))
|
|
||||||
).Subscribe(DeviceUpdated);
|
|
||||||
|
|
||||||
Disco.Data.Repository.Monitor.RepositoryMonitor.StreamAfterCommit.Where(e =>
|
|
||||||
e.EntityType == typeof(User) &&
|
|
||||||
e.ModifiedProperties.Contains("DisplayName")
|
|
||||||
).Subscribe(UserUpdated);
|
|
||||||
|
|
||||||
subscribed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void JobUpdated(RepositoryMonitorEvent e)
|
|
||||||
{
|
|
||||||
Job j = (Job)e.Entity;
|
|
||||||
|
|
||||||
if (j.DeviceSerialNumber != null)
|
|
||||||
notificationContext.Connection.Broadcast(j.DeviceSerialNumber);
|
|
||||||
}
|
|
||||||
private static void DeviceUpdated(RepositoryMonitorEvent e)
|
|
||||||
{
|
|
||||||
Device d = (Device)e.Entity;
|
|
||||||
|
|
||||||
notificationContext.Connection.Broadcast(d.SerialNumber);
|
|
||||||
}
|
|
||||||
private static void UserUpdated(RepositoryMonitorEvent e)
|
|
||||||
{
|
|
||||||
User u = (User)e.Entity;
|
|
||||||
|
|
||||||
var userDevices = e.Database.Devices.Where(d => d.AssignedUserId == u.Id);
|
|
||||||
|
|
||||||
foreach (var userDevice in userDevices)
|
|
||||||
{
|
|
||||||
notificationContext.Connection.Broadcast(userDevice.SerialNumber);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
using Disco.Services.Authorization;
|
|
||||||
using Disco.Services.Logging;
|
|
||||||
using Disco.Services.Logging.Models;
|
|
||||||
using Microsoft.AspNet.SignalR;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Disco.BI.Interop.SignalRHandlers
|
|
||||||
{
|
|
||||||
public class LogNotifications : AuthorizedPersistentConnection
|
|
||||||
{
|
|
||||||
public static bool initialized = false;
|
|
||||||
|
|
||||||
protected override string AuthorizedClaim { get { return Claims.DiscoAdminAccount; } }
|
|
||||||
|
|
||||||
public LogNotifications()
|
|
||||||
{
|
|
||||||
if (!initialized)
|
|
||||||
{
|
|
||||||
initialized = true;
|
|
||||||
Disco.Services.Logging.Targets.LogLiveContext.LogBroadcast += Broadcast;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Task OnConnected(IRequest request, string connectionId)
|
|
||||||
{
|
|
||||||
string addToGroups = request.QueryString["addToGroups"];
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(addToGroups))
|
|
||||||
{
|
|
||||||
var groups = addToGroups.Split(',');
|
|
||||||
foreach (var g in groups)
|
|
||||||
{
|
|
||||||
this.Groups.Add(connectionId, g);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.OnConnected(request, connectionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override System.Threading.Tasks.Task OnReceived(IRequest request, string connectionId, string data)
|
|
||||||
{
|
|
||||||
// Add to Group
|
|
||||||
if (!string.IsNullOrWhiteSpace(data) && data.StartsWith("/addToGroups:") && data.Length > 13)
|
|
||||||
{
|
|
||||||
var groups = data.Substring(13).Split(',');
|
|
||||||
foreach (var g in groups)
|
|
||||||
{
|
|
||||||
this.Groups.Add(connectionId, g);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.OnReceived(request, connectionId, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void Broadcast(LogBase logModule, LogEventType eventType, DateTime Timestamp, params object[] Arguments)
|
|
||||||
{
|
|
||||||
var message = LogLiveEvent.Create(logModule, eventType, Timestamp, Arguments);
|
|
||||||
|
|
||||||
var connectionManager = GlobalHost.ConnectionManager;
|
|
||||||
var connectionContext = connectionManager.GetConnectionContext<LogNotifications>();
|
|
||||||
connectionContext.Groups.Send(_GroupNameAll, message);
|
|
||||||
connectionContext.Groups.Send(logModule.ModuleName, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
private const string _GroupNameAll = "__All";
|
|
||||||
|
|
||||||
public static string AllNotifications
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _GroupNameAll;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
using Disco.Data.Repository.Monitor;
|
|
||||||
using Disco.Services.Authorization;
|
|
||||||
using Microsoft.AspNet.SignalR;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Disco.BI.Interop.SignalRHandlers
|
|
||||||
{
|
|
||||||
public class RepositoryMonitorNotifications : AuthorizedPersistentConnection
|
|
||||||
{
|
|
||||||
protected override string AuthorizedClaim { get { return Claims.DiscoAdminAccount; } }
|
|
||||||
|
|
||||||
public static void Initialize()
|
|
||||||
{
|
|
||||||
RepositoryMonitor.StreamAfterCommit.Subscribe(AfterCommit);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Task OnConnected(IRequest request, string connectionId)
|
|
||||||
{
|
|
||||||
string addToGroups = request.QueryString["addToGroups"];
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(addToGroups))
|
|
||||||
{
|
|
||||||
var groups = addToGroups.Split(',');
|
|
||||||
foreach (var g in groups)
|
|
||||||
{
|
|
||||||
this.Groups.Add(connectionId, g);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.OnConnected(request, connectionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Task OnReceived(IRequest request, string connectionId, string data)
|
|
||||||
{
|
|
||||||
// Add to Group
|
|
||||||
if (!string.IsNullOrWhiteSpace(data) && data.StartsWith("/addToGroups:") && data.Length > 13)
|
|
||||||
{
|
|
||||||
var groups = data.Substring(13).Split(',');
|
|
||||||
foreach (var g in groups)
|
|
||||||
{
|
|
||||||
this.Groups.Add(connectionId, g);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.OnReceived(request, connectionId, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AfterCommit(RepositoryMonitorEvent e)
|
|
||||||
{
|
|
||||||
GlobalHost.ConnectionManager.GetConnectionContext<RepositoryMonitorNotifications>().Groups.Send(e.EntityType.Name, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
using Disco.Services.Authorization;
|
|
||||||
using Disco.Services.Tasks;
|
|
||||||
using Microsoft.AspNet.SignalR;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Disco.BI.Interop.SignalRHandlers
|
|
||||||
{
|
|
||||||
public class ScheduledTasksStatusNotifications : AuthorizedPersistentConnection
|
|
||||||
{
|
|
||||||
public static bool initialized = false;
|
|
||||||
|
|
||||||
protected override string AuthorizedClaim { get { return Claims.DiscoAdminAccount; } }
|
|
||||||
|
|
||||||
public ScheduledTasksStatusNotifications()
|
|
||||||
{
|
|
||||||
if (!initialized)
|
|
||||||
{
|
|
||||||
initialized = true;
|
|
||||||
Disco.Services.Tasks.ScheduledTaskStatus.UpdatedBroadcast += Broadcast;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Task OnConnected(IRequest request, string connectionId)
|
|
||||||
{
|
|
||||||
string addToGroups = request.QueryString["addToGroups"];
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(addToGroups))
|
|
||||||
{
|
|
||||||
var groups = addToGroups.Split(',');
|
|
||||||
foreach (var g in groups)
|
|
||||||
{
|
|
||||||
this.Groups.Add(connectionId, g);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.OnConnected(request, connectionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override System.Threading.Tasks.Task OnReceived(IRequest request, string connectionId, string data)
|
|
||||||
{
|
|
||||||
// Add to Group
|
|
||||||
if (!string.IsNullOrWhiteSpace(data) && data.StartsWith("/addToGroups:") && data.Length > 13)
|
|
||||||
{
|
|
||||||
var groups = data.Substring(13).Split(',');
|
|
||||||
foreach (var g in groups)
|
|
||||||
{
|
|
||||||
this.Groups.Add(connectionId, g);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return base.OnReceived(request, connectionId, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void Broadcast(ScheduledTaskStatusLive SessionStatus)
|
|
||||||
{
|
|
||||||
var connectionManager = GlobalHost.ConnectionManager;
|
|
||||||
var connectionContext = connectionManager.GetConnectionContext<ScheduledTasksStatusNotifications>();
|
|
||||||
connectionContext.Groups.Send(_GroupNameAll, SessionStatus);
|
|
||||||
connectionContext.Groups.Send(SessionStatus.SessionId, SessionStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
private const string _GroupNameAll = "__All";
|
|
||||||
|
|
||||||
public static string AllNotifications
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _GroupNameAll;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Web;
|
|
||||||
using System.Web.Routing;
|
|
||||||
using System.Web.Security;
|
|
||||||
using System.Web.SessionState;
|
|
||||||
using Microsoft.AspNet.SignalR;
|
|
||||||
using Owin;
|
|
||||||
using AppFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>;
|
|
||||||
|
|
||||||
namespace Disco.BI.Interop.SignalRHandlers
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Required for SignalR 1.1.0 NTLM support in Firefox & Safari
|
|
||||||
/// Returns 401 (Unauthorized) instead of 403 (Forbidden) when an unauthenticated request is processed
|
|
||||||
///
|
|
||||||
/// TODO: Remove this workaround when implementing SignalR 2.x
|
|
||||||
///
|
|
||||||
/// Thanks to David Fowler (@davidfowl)
|
|
||||||
/// </summary>
|
|
||||||
public static class SignalRAuthenticationWorkaround
|
|
||||||
{
|
|
||||||
public static void AddMiddleware(IAppBuilder app)
|
|
||||||
{
|
|
||||||
Func<AppFunc, AppFunc> convert403To401 = Convert403To401;
|
|
||||||
|
|
||||||
app.Use(convert403To401);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static AppFunc Convert403To401(AppFunc next)
|
|
||||||
{
|
|
||||||
return env =>
|
|
||||||
{
|
|
||||||
// Execute the SignalR pipeline
|
|
||||||
Task task = next(env);
|
|
||||||
|
|
||||||
// Get the status code
|
|
||||||
int statusCode = 0;
|
|
||||||
if (env.ContainsKey("owin.ResponseStatusCode"))
|
|
||||||
{
|
|
||||||
statusCode = (int)env["owin.ResponseStatusCode"];
|
|
||||||
}
|
|
||||||
|
|
||||||
// If its 403 then convert it to 401 (we shouldn't do
|
|
||||||
// this if it's a cross domain request since it doesn't make sense)
|
|
||||||
if (statusCode == 403)
|
|
||||||
{
|
|
||||||
env["owin.ResponseStatusCode"] = 401;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the original task
|
|
||||||
return task;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Microsoft.AspNet.SignalR;
|
|
||||||
using System.Reactive.Linq;
|
|
||||||
using Disco.Data.Repository.Monitor;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
|
|
||||||
namespace Disco.BI.Interop.SignalRHandlers
|
|
||||||
{
|
|
||||||
public class UserHeldDeviceNotifications : PersistentConnection
|
|
||||||
{
|
|
||||||
private static bool subscribed = false;
|
|
||||||
private static object subscribeLock = new object();
|
|
||||||
private static IPersistentConnectionContext notificationContext;
|
|
||||||
|
|
||||||
static UserHeldDeviceNotifications()
|
|
||||||
{
|
|
||||||
if (!subscribed)
|
|
||||||
lock (subscribeLock)
|
|
||||||
if (!subscribed)
|
|
||||||
{
|
|
||||||
notificationContext = GlobalHost.ConnectionManager.GetConnectionContext<UserHeldDeviceNotifications>();
|
|
||||||
|
|
||||||
Disco.Data.Repository.Monitor.RepositoryMonitor.StreamAfterCommit.Where(e => e.EntityType == typeof(Job)).Subscribe(JobUpdated);
|
|
||||||
|
|
||||||
Disco.Data.Repository.Monitor.RepositoryMonitor.StreamBeforeCommit.Where(e =>
|
|
||||||
e.EntityType == typeof(Device) &&
|
|
||||||
(e.ModifiedProperties.Contains("DeviceModelId") ||
|
|
||||||
e.ModifiedProperties.Contains("DeviceProfileId") ||
|
|
||||||
e.ModifiedProperties.Contains("DeviceBatchId") ||
|
|
||||||
e.ModifiedProperties.Contains("AssignedUserId"))
|
|
||||||
).Subscribe(DeviceUpdated);
|
|
||||||
|
|
||||||
Disco.Data.Repository.Monitor.RepositoryMonitor.StreamAfterCommit.Where(e =>
|
|
||||||
e.EntityType == typeof(User) &&
|
|
||||||
e.ModifiedProperties.Contains("DisplayName")
|
|
||||||
).Subscribe(UserUpdated);
|
|
||||||
|
|
||||||
subscribed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void JobUpdated(RepositoryMonitorEvent e)
|
|
||||||
{
|
|
||||||
Job j = (Job)e.Entity;
|
|
||||||
|
|
||||||
if (j.DeviceSerialNumber != null)
|
|
||||||
{
|
|
||||||
var jobDevice = e.Database.Devices.Where(d => d.SerialNumber == j.DeviceSerialNumber).FirstOrDefault();
|
|
||||||
|
|
||||||
if (jobDevice.AssignedUserId != null)
|
|
||||||
notificationContext.Connection.Broadcast(jobDevice.AssignedUserId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static void DeviceUpdated(RepositoryMonitorEvent e)
|
|
||||||
{
|
|
||||||
Device d = (Device)e.Entity;
|
|
||||||
|
|
||||||
string previouslyAssignedUserId = null;
|
|
||||||
|
|
||||||
if (e.ModifiedProperties.Contains("AssignedUserId"))
|
|
||||||
previouslyAssignedUserId = e.GetPreviousPropertyValue<string>("AssignedUserId");
|
|
||||||
|
|
||||||
e.ExecuteAfterCommit(me =>
|
|
||||||
{
|
|
||||||
if (previouslyAssignedUserId != null)
|
|
||||||
notificationContext.Connection.Broadcast(previouslyAssignedUserId);
|
|
||||||
|
|
||||||
if (d.AssignedUserId != null)
|
|
||||||
notificationContext.Connection.Broadcast(d.AssignedUserId);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
private static void UserUpdated(RepositoryMonitorEvent e)
|
|
||||||
{
|
|
||||||
User u = (User)e.Entity;
|
|
||||||
|
|
||||||
notificationContext.Connection.Broadcast(u.Id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
using Disco.Data.Repository;
|
|
||||||
using Disco.Data.Repository.Monitor;
|
|
||||||
using Disco.Models.BI.Job;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Disco.BI.Extensions;
|
|
||||||
using System.Reactive.Linq;
|
|
||||||
using Disco.Services.Users;
|
|
||||||
|
|
||||||
namespace Disco.BI.JobBI
|
|
||||||
{
|
|
||||||
using FilterFunc = Func<IQueryable<Job>, IQueryable<Job>>;
|
|
||||||
using SortFunc = Func<IEnumerable<Disco.Models.BI.Job.JobTableModel.JobTableItemModel>, IEnumerable<Disco.Models.BI.Job.JobTableModel.JobTableItemModel>>;
|
|
||||||
using Disco.Services.Logging;
|
|
||||||
|
|
||||||
public class ManagedJobList : JobTableModel, IDisposable
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public FilterFunc FilterFunction { get; set; }
|
|
||||||
public SortFunc SortFunction { get; set; }
|
|
||||||
private IDisposable unsubscribeToken;
|
|
||||||
private object updateLock = new object();
|
|
||||||
|
|
||||||
public override List<JobTableItemModel> Items
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return base.Items.PermissionsFiltered(UserService.CurrentAuthorization);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Items cannot be manually set in a Managed Job List");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ManagedJobList Initialize(DiscoDataContext Database)
|
|
||||||
{
|
|
||||||
// Can only Initialize once
|
|
||||||
if (base.Items != null)
|
|
||||||
return ReInitialize(Database);
|
|
||||||
|
|
||||||
lock (updateLock)
|
|
||||||
{
|
|
||||||
// Subscribe for Changes
|
|
||||||
// - Job (or Job Meta) Changes
|
|
||||||
// - Device Profile Address Changes (for multi-campus Schools)
|
|
||||||
// - Device Model Description Changes
|
|
||||||
// - Device's Profile or Model Changes
|
|
||||||
unsubscribeToken = RepositoryMonitor.StreamAfterCommit
|
|
||||||
.Where(n => n.EntityType == typeof(Job) ||
|
|
||||||
n.EntityType == typeof(JobMetaWarranty) ||
|
|
||||||
n.EntityType == typeof(JobMetaNonWarranty) ||
|
|
||||||
n.EntityType == typeof(JobMetaInsurance) ||
|
|
||||||
(n.EventType == RepositoryMonitorEventType.Modified && (
|
|
||||||
(n.EntityType == typeof(DeviceProfile) && n.ModifiedProperties.Contains("DefaultOrganisationAddress")) ||
|
|
||||||
(n.EntityType == typeof(DeviceModel) && n.ModifiedProperties.Contains("Description")) ||
|
|
||||||
(n.EntityType == typeof(Device) && n.ModifiedProperties.Contains("DeviceProfileId") || n.ModifiedProperties.Contains("DeviceModelId"))
|
|
||||||
)))
|
|
||||||
.Subscribe(JobNotification, NotificationError);
|
|
||||||
|
|
||||||
// Initially fill table
|
|
||||||
base.Items = this.SortFunction(this.DetermineItems(Database, this.FilterFunction(Database.Jobs))).ToList();
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ManagedJobList ReInitialize(DiscoDataContext Database)
|
|
||||||
{
|
|
||||||
return ReInitialize(Database, null, null);
|
|
||||||
}
|
|
||||||
public ManagedJobList ReInitialize(DiscoDataContext Database, FilterFunc FilterFunction)
|
|
||||||
{
|
|
||||||
return ReInitialize(Database, FilterFunction, null);
|
|
||||||
}
|
|
||||||
public ManagedJobList ReInitialize(DiscoDataContext Database, FilterFunc FilterFunction, SortFunc SortFunction)
|
|
||||||
{
|
|
||||||
if (Database == null)
|
|
||||||
throw new ArgumentNullException("Database");
|
|
||||||
|
|
||||||
lock (updateLock)
|
|
||||||
{
|
|
||||||
if (FilterFunction != null)
|
|
||||||
this.FilterFunction = FilterFunction;
|
|
||||||
if (SortFunction != null)
|
|
||||||
this.SortFunction = SortFunction;
|
|
||||||
|
|
||||||
base.Items = this.SortFunction(this.DetermineItems(Database, this.FilterFunction(Database.Jobs))).ToList();
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void NotificationError(Exception ex)
|
|
||||||
{
|
|
||||||
SystemLog.LogException(string.Format("Disco.BI.JobBI.ManagedJobList: [{0}]", this.Name), ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void JobNotification(RepositoryMonitorEvent e)
|
|
||||||
{
|
|
||||||
List<int> jobIds = null;
|
|
||||||
JobTableItemModel[] existingItems = null;
|
|
||||||
|
|
||||||
if (e.EntityType == typeof(Job))
|
|
||||||
jobIds = new List<int>() { ((Job)e.Entity).Id };
|
|
||||||
else
|
|
||||||
if (e.EntityType == typeof(JobMetaWarranty))
|
|
||||||
jobIds = new List<int>() { ((JobMetaWarranty)e.Entity).JobId };
|
|
||||||
else
|
|
||||||
if (e.EntityType == typeof(JobMetaNonWarranty))
|
|
||||||
jobIds = new List<int>() { ((JobMetaNonWarranty)e.Entity).JobId };
|
|
||||||
else
|
|
||||||
if (e.EntityType == typeof(JobMetaInsurance))
|
|
||||||
jobIds = new List<int>() { ((JobMetaInsurance)e.Entity).JobId };
|
|
||||||
else
|
|
||||||
if (e.EntityType == typeof(DeviceProfile))
|
|
||||||
{
|
|
||||||
int deviceProfileId = ((DeviceProfile)e.Entity).Id;
|
|
||||||
existingItems = base.Items.Where(i => i.DeviceProfileId == deviceProfileId).ToArray();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (e.EntityType == typeof(DeviceModel))
|
|
||||||
{
|
|
||||||
int deviceModelId = ((DeviceModel)e.Entity).Id;
|
|
||||||
existingItems = base.Items.Where(i => i.DeviceModelId == deviceModelId).ToArray();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (e.EntityType == typeof(Device))
|
|
||||||
{
|
|
||||||
string deviceSerialNumber = ((Device)e.Entity).SerialNumber;
|
|
||||||
existingItems = base.Items.Where(i => i.DeviceSerialNumber == deviceSerialNumber).ToArray();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return; // Subscription should never reach
|
|
||||||
|
|
||||||
if (jobIds == null)
|
|
||||||
{
|
|
||||||
if (existingItems == null)
|
|
||||||
throw new InvalidOperationException("Notification algorithm didn't indicate any Jobs for update");
|
|
||||||
else
|
|
||||||
jobIds = existingItems.Select(i => i.Id).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jobIds.Count == 0)
|
|
||||||
return;
|
|
||||||
else
|
|
||||||
UpdateJobs(e.Database, jobIds, existingItems);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateJobs(DiscoDataContext Database, List<int> jobIds, JobTableItemModel[] existingItems = null)
|
|
||||||
{
|
|
||||||
lock (updateLock)
|
|
||||||
{
|
|
||||||
// Check for existing items, if not handed them
|
|
||||||
if (existingItems == null)
|
|
||||||
existingItems = base.Items.Where(i => jobIds.Contains(i.Id)).ToArray();
|
|
||||||
|
|
||||||
var updatedItems = this.DetermineItems(Database, this.FilterFunction(Database.Jobs.Where(j => jobIds.Contains(j.Id))));
|
|
||||||
|
|
||||||
var refreshedList = base.Items.ToList();
|
|
||||||
|
|
||||||
// Remove Existing
|
|
||||||
if (existingItems.Length > 0)
|
|
||||||
foreach (var existingItem in existingItems)
|
|
||||||
refreshedList.Remove(existingItem);
|
|
||||||
|
|
||||||
// Add Updated Items
|
|
||||||
if (updatedItems.Count > 0)
|
|
||||||
foreach (var updatedItem in updatedItems)
|
|
||||||
refreshedList.Add(updatedItem);
|
|
||||||
|
|
||||||
// Reorder
|
|
||||||
base.Items = this.SortFunction(refreshedList).ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (unsubscribeToken != null)
|
|
||||||
{
|
|
||||||
unsubscribeToken.Dispose();
|
|
||||||
unsubscribeToken = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Disco.Models.BI.Job;
|
|
||||||
using Disco.Data.Repository;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
using Disco.BI.Extensions;
|
|
||||||
|
|
||||||
namespace Disco.BI.JobBI
|
|
||||||
{
|
|
||||||
public static class Searching
|
|
||||||
{
|
|
||||||
public static JobTableModel Search(DiscoDataContext Database, string Term, int? LimitCount = null, bool IncludeJobStatus = true, bool SearchDetails = false)
|
|
||||||
{
|
|
||||||
int termInt = default(int);
|
|
||||||
|
|
||||||
IQueryable<Job> query = default(IQueryable<Job>);
|
|
||||||
|
|
||||||
if (int.TryParse(Term, out termInt))
|
|
||||||
{
|
|
||||||
// Term is a Number (int)
|
|
||||||
if (SearchDetails)
|
|
||||||
{
|
|
||||||
query = BuildJobTableModel(Database).Where(j =>
|
|
||||||
j.Id == termInt ||
|
|
||||||
j.DeviceHeldLocation.Contains(Term) ||
|
|
||||||
j.Device.SerialNumber.Contains(Term) ||
|
|
||||||
j.Device.AssetNumber.Contains(Term) ||
|
|
||||||
j.User.Id == Term ||
|
|
||||||
j.User.Surname.Contains(Term) ||
|
|
||||||
j.User.GivenName.Contains(Term) ||
|
|
||||||
j.User.DisplayName.Contains(Term) ||
|
|
||||||
j.JobLogs.Any(jl => jl.Comments.Contains(Term)) ||
|
|
||||||
j.JobAttachments.Any(ja => ja.Comments.Contains(Term)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
query = BuildJobTableModel(Database).Where(j =>
|
|
||||||
j.Id == termInt ||
|
|
||||||
j.DeviceHeldLocation.Contains(Term) ||
|
|
||||||
j.Device.SerialNumber.Contains(Term) ||
|
|
||||||
j.Device.AssetNumber.Contains(Term) ||
|
|
||||||
j.User.Id == Term ||
|
|
||||||
j.User.Surname.Contains(Term) ||
|
|
||||||
j.User.GivenName.Contains(Term) ||
|
|
||||||
j.User.DisplayName.Contains(Term));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (SearchDetails)
|
|
||||||
{
|
|
||||||
query = BuildJobTableModel(Database).Where(j =>
|
|
||||||
j.DeviceHeldLocation.Contains(Term) ||
|
|
||||||
j.Device.SerialNumber.Contains(Term) ||
|
|
||||||
j.Device.AssetNumber.Contains(Term) ||
|
|
||||||
j.User.Id == Term ||
|
|
||||||
j.User.Surname.Contains(Term) ||
|
|
||||||
j.User.GivenName.Contains(Term) ||
|
|
||||||
j.User.DisplayName.Contains(Term) ||
|
|
||||||
j.JobLogs.Any(jl => jl.Comments.Contains(Term)) ||
|
|
||||||
j.JobAttachments.Any(ja => ja.Comments.Contains(Term)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
query = BuildJobTableModel(Database).Where(j =>
|
|
||||||
j.DeviceHeldLocation.Contains(Term) ||
|
|
||||||
j.Device.SerialNumber.Contains(Term) ||
|
|
||||||
j.Device.AssetNumber.Contains(Term) ||
|
|
||||||
j.User.Id == Term ||
|
|
||||||
j.User.Surname.Contains(Term) ||
|
|
||||||
j.User.GivenName.Contains(Term) ||
|
|
||||||
j.User.DisplayName.Contains(Term));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LimitCount.HasValue)
|
|
||||||
query = query.Take(LimitCount.Value);
|
|
||||||
|
|
||||||
JobTableModel model = new JobTableModel() { ShowStatus = IncludeJobStatus };
|
|
||||||
model.Fill(Database, query);
|
|
||||||
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IQueryable<Job> BuildJobTableModel(DiscoDataContext Database)
|
|
||||||
{
|
|
||||||
return Database.Jobs.Include("JobType").Include("Device").Include("User").Include("OpenedTechUser");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -24,6 +24,7 @@ namespace Disco.BI.JobBI.Statistics
|
|||||||
public override string TaskName { get { return "Job Statistics - Daily Opened/Closed Task"; } }
|
public override string TaskName { get { return "Job Statistics - Daily Opened/Closed Task"; } }
|
||||||
public override bool SingleInstanceTask { get { return true; } }
|
public override bool SingleInstanceTask { get { return true; } }
|
||||||
public override bool CancelInitiallySupported { get { return false; } }
|
public override bool CancelInitiallySupported { get { return false; } }
|
||||||
|
public override bool LogExceptionsOnly { get { return true; } }
|
||||||
|
|
||||||
public override void InitalizeScheduledTask(DiscoDataContext Database)
|
public override void InitalizeScheduledTask(DiscoDataContext Database)
|
||||||
{
|
{
|
||||||
@@ -100,7 +101,6 @@ namespace Disco.BI.JobBI.Statistics
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
DateTime? previousValue = e.GetPreviousPropertyValue<DateTime?>("ClosedDate");
|
DateTime? previousValue = e.GetPreviousPropertyValue<DateTime?>("ClosedDate");
|
||||||
DateTime? currentValue = e.GetCurrentPropertyValue<DateTime?>("ClosedDate");
|
|
||||||
|
|
||||||
if (previousValue.HasValue)
|
if (previousValue.HasValue)
|
||||||
{
|
{
|
||||||
@@ -116,6 +116,9 @@ namespace Disco.BI.JobBI.Statistics
|
|||||||
affectedStat.TotalJobs += 1;
|
affectedStat.TotalJobs += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime? currentValue = e.GetCurrentPropertyValue<DateTime?>("ClosedDate");
|
||||||
|
|
||||||
if (currentValue.HasValue)
|
if (currentValue.HasValue)
|
||||||
{
|
{
|
||||||
@@ -133,7 +136,6 @@ namespace Disco.BI.JobBI.Statistics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static DailyOpenedClosedItem Data(DiscoDataContext Database, DateTime ProcessDate)
|
private static DailyOpenedClosedItem Data(DiscoDataContext Database, DateTime ProcessDate)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,12 +10,12 @@ namespace Disco.BI.JobBI
|
|||||||
{
|
{
|
||||||
public static class Utilities
|
public static class Utilities
|
||||||
{
|
{
|
||||||
public static Job Create(DiscoDataContext Database, Device device, User user, JobType type, List<JobSubType> subTypes, User initialTech)
|
public static Job Create(DiscoDataContext Database, Device device, User user, JobType type, List<JobSubType> subTypes, User initialTech, bool addAutoQueues = true)
|
||||||
{
|
{
|
||||||
Job j = new Job()
|
Job j = new Job()
|
||||||
{
|
{
|
||||||
JobType = type,
|
JobType = type,
|
||||||
OpenedTechUserId = initialTech.Id,
|
OpenedTechUserId = initialTech.UserId,
|
||||||
OpenedTechUser = initialTech,
|
OpenedTechUser = initialTech,
|
||||||
OpenedDate = DateTime.Now
|
OpenedDate = DateTime.Now
|
||||||
};
|
};
|
||||||
@@ -31,7 +31,7 @@ namespace Disco.BI.JobBI
|
|||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
j.User = user;
|
j.User = user;
|
||||||
j.UserId = user.Id;
|
j.UserId = user.UserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sub Types
|
// Sub Types
|
||||||
@@ -40,6 +40,36 @@ namespace Disco.BI.JobBI
|
|||||||
|
|
||||||
Database.Jobs.Add(j);
|
Database.Jobs.Add(j);
|
||||||
|
|
||||||
|
// Job Queues
|
||||||
|
if (addAutoQueues)
|
||||||
|
{
|
||||||
|
var queues = from st in subTypes
|
||||||
|
from jq in st.JobQueues
|
||||||
|
group st by jq into g
|
||||||
|
select new { queue = g.Key, subTypes = g };
|
||||||
|
foreach (var queue in queues)
|
||||||
|
{
|
||||||
|
var commentBuilder = new StringBuilder("Automatically added by:").AppendLine();
|
||||||
|
foreach (var subType in queue.subTypes)
|
||||||
|
{
|
||||||
|
commentBuilder.AppendLine().Append("* ").Append(subType.Description);
|
||||||
|
}
|
||||||
|
|
||||||
|
var jqj = new JobQueueJob()
|
||||||
|
{
|
||||||
|
JobQueueId = queue.queue.Id,
|
||||||
|
Job = j,
|
||||||
|
AddedDate = DateTime.Now,
|
||||||
|
AddedUserId = initialTech.UserId,
|
||||||
|
AddedComment = commentBuilder.ToString(),
|
||||||
|
SLAExpiresDate = queue.queue.DefaultSLAExpiry.HasValue ? (DateTime?)DateTime.Now.AddMinutes(queue.queue.DefaultSLAExpiry.Value) : null,
|
||||||
|
Priority = JobQueuePriority.Normal
|
||||||
|
};
|
||||||
|
|
||||||
|
Database.JobQueueJobs.Add(jqj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (type.Id)
|
switch (type.Id)
|
||||||
{
|
{
|
||||||
case JobType.JobTypeIds.HWar:
|
case JobType.JobTypeIds.HWar:
|
||||||
@@ -79,7 +109,7 @@ namespace Disco.BI.JobBI
|
|||||||
Database.JobComponents.Add(new JobComponent()
|
Database.JobComponents.Add(new JobComponent()
|
||||||
{
|
{
|
||||||
Job = j,
|
Job = j,
|
||||||
TechUserId = initialTech.Id,
|
TechUserId = initialTech.UserId,
|
||||||
Cost = c.Cost,
|
Cost = c.Cost,
|
||||||
Description = c.Description
|
Description = c.Description
|
||||||
});
|
});
|
||||||
@@ -89,83 +119,5 @@ namespace Disco.BI.JobBI
|
|||||||
|
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string JobStatusDescription(string StatusId, Job j = null)
|
|
||||||
{
|
|
||||||
switch (StatusId)
|
|
||||||
{
|
|
||||||
case Job.JobStatusIds.Open:
|
|
||||||
return "Open";
|
|
||||||
case Job.JobStatusIds.Closed:
|
|
||||||
return "Closed";
|
|
||||||
case Job.JobStatusIds.AwaitingWarrantyRepair:
|
|
||||||
if (j == null)
|
|
||||||
return "Awaiting Warranty Repair";
|
|
||||||
else
|
|
||||||
if (j.DeviceHeld.HasValue)
|
|
||||||
return string.Format("Awaiting Warranty Repair ({0})", j.JobMetaWarranty.ExternalName);
|
|
||||||
else
|
|
||||||
return string.Format("Awaiting Warranty Repair - Not Held ({0})", j.JobMetaWarranty.ExternalName);
|
|
||||||
case Job.JobStatusIds.AwaitingRepairs:
|
|
||||||
if (j == null)
|
|
||||||
return "Awaiting Repairs";
|
|
||||||
else
|
|
||||||
if (j.DeviceHeld.HasValue)
|
|
||||||
return string.Format("Awaiting Repairs ({0})", j.JobMetaNonWarranty.RepairerName);
|
|
||||||
else
|
|
||||||
return string.Format("Awaiting Repairs - Not Held ({0})", j.JobMetaNonWarranty.RepairerName);
|
|
||||||
case Job.JobStatusIds.AwaitingDeviceReturn:
|
|
||||||
return "Awaiting Device Return";
|
|
||||||
case Job.JobStatusIds.AwaitingUserAction:
|
|
||||||
return "Awaiting User Action";
|
|
||||||
case Job.JobStatusIds.AwaitingAccountingPayment:
|
|
||||||
return "Awaiting Accounting Payment";
|
|
||||||
case Job.JobStatusIds.AwaitingAccountingCharge:
|
|
||||||
return "Awaiting Accounting Charge";
|
|
||||||
case Job.JobStatusIds.AwaitingInsuranceProcessing:
|
|
||||||
return "Awaiting Insurance Processing";
|
|
||||||
default:
|
|
||||||
return "Unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static string JobStatusDescription(string StatusId, JobTableModel.JobTableItemModelIncludeStatus j = null)
|
|
||||||
{
|
|
||||||
switch (StatusId)
|
|
||||||
{
|
|
||||||
case Job.JobStatusIds.Open:
|
|
||||||
return "Open";
|
|
||||||
case Job.JobStatusIds.Closed:
|
|
||||||
return "Closed";
|
|
||||||
case Job.JobStatusIds.AwaitingWarrantyRepair:
|
|
||||||
if (j == null)
|
|
||||||
return "Awaiting Warranty Repair";
|
|
||||||
else
|
|
||||||
if (j.DeviceHeld.HasValue)
|
|
||||||
return string.Format("Awaiting Warranty Repair ({0})", j.JobMetaWarranty_ExternalName);
|
|
||||||
else
|
|
||||||
return string.Format("Awaiting Warranty Repair - Not Held ({0})", j.JobMetaWarranty_ExternalName);
|
|
||||||
case Job.JobStatusIds.AwaitingRepairs:
|
|
||||||
if (j == null)
|
|
||||||
return "Awaiting Repairs";
|
|
||||||
else
|
|
||||||
if (j.DeviceHeld.HasValue)
|
|
||||||
return string.Format("Awaiting Repairs ({0})", j.JobMetaNonWarranty_RepairerName);
|
|
||||||
else
|
|
||||||
return string.Format("Awaiting Repairs - Not Held ({0})", j.JobMetaNonWarranty_RepairerName);
|
|
||||||
case Job.JobStatusIds.AwaitingDeviceReturn:
|
|
||||||
return "Awaiting Device Return";
|
|
||||||
case Job.JobStatusIds.AwaitingUserAction:
|
|
||||||
return "Awaiting User Action";
|
|
||||||
case Job.JobStatusIds.AwaitingAccountingPayment:
|
|
||||||
return "Awaiting Accounting Payment";
|
|
||||||
case Job.JobStatusIds.AwaitingAccountingCharge:
|
|
||||||
return "Awaiting Accounting Charge";
|
|
||||||
case Job.JobStatusIds.AwaitingInsuranceProcessing:
|
|
||||||
return "Awaiting Insurance Processing";
|
|
||||||
default:
|
|
||||||
return "Unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Disco.Models.BI.Search;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
using Disco.Data.Repository;
|
|
||||||
using Disco.Services.Users;
|
|
||||||
|
|
||||||
namespace Disco.BI.UserBI
|
|
||||||
{
|
|
||||||
public static class Searching
|
|
||||||
{
|
|
||||||
|
|
||||||
public static List<User> SearchUpstream(string Term)
|
|
||||||
{
|
|
||||||
return Interop.ActiveDirectory.ActiveDirectory.SearchUsers(Term).Select(adU => adU.ToRepositoryUser()).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<UserSearchResultItem> Search_SelectUserSearchResultItems(IQueryable<User> Query, int? LimitCount = null)
|
|
||||||
{
|
|
||||||
if (LimitCount.HasValue)
|
|
||||||
Query = Query.Take(LimitCount.Value);
|
|
||||||
|
|
||||||
return Query.Select(u => new UserSearchResultItem()
|
|
||||||
{
|
|
||||||
Id = u.Id,
|
|
||||||
Surname = u.Surname,
|
|
||||||
GivenName = u.GivenName,
|
|
||||||
DisplayName = u.DisplayName,
|
|
||||||
AssignedDevicesCount = u.DeviceUserAssignments.Where(dua => !dua.UnassignedDate.HasValue).Count(),
|
|
||||||
JobCount = u.Jobs.Count()
|
|
||||||
}).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<UserSearchResultItem> Search(DiscoDataContext Database, string Term, int? LimitCount = null)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(Term) || Term.Length < 2)
|
|
||||||
throw new ArgumentException("Search Term must contain at least two characters", "Term");
|
|
||||||
|
|
||||||
// Search Active Directory & Import Relevant Users
|
|
||||||
var adImportedUsers = Interop.ActiveDirectory.ActiveDirectory.SearchUsers(Term).Select(adU => adU.ToRepositoryUser());
|
|
||||||
foreach (var adU in adImportedUsers)
|
|
||||||
{
|
|
||||||
var existingUser = Database.Users.Find(adU.Id);
|
|
||||||
if (existingUser != null)
|
|
||||||
existingUser.UpdateSelf(adU);
|
|
||||||
else
|
|
||||||
Database.Users.Add(adU);
|
|
||||||
Database.SaveChanges();
|
|
||||||
UserService.InvalidateCachedUser(adU.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Search_SelectUserSearchResultItems(Database.Users.Where(u =>
|
|
||||||
u.Id.Contains(Term) ||
|
|
||||||
u.Surname.Contains(Term) ||
|
|
||||||
u.GivenName.Contains(Term) ||
|
|
||||||
u.DisplayName.Contains(Term)
|
|
||||||
), LimitCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
using Disco.BI.Wireless.eduSTAR;
|
|
||||||
using Disco.Data.Configuration;
|
|
||||||
using Disco.Data.Repository;
|
|
||||||
using Disco.BI.Extensions;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Threading;
|
|
||||||
namespace Disco.BI.Wireless
|
|
||||||
{
|
|
||||||
public abstract class BaseWirelessProvider
|
|
||||||
{
|
|
||||||
protected DiscoDataContext dbContext;
|
|
||||||
private static object _CertificateAllocateLock = System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(new object());
|
|
||||||
public static BaseWirelessProvider GetProvider(DiscoDataContext dbContext)
|
|
||||||
{
|
|
||||||
string provider = dbContext.DiscoConfiguration.Wireless.Provider;
|
|
||||||
if (provider == "eduSTAR")
|
|
||||||
{
|
|
||||||
return new eduSTARWirelessProvider(dbContext);
|
|
||||||
}
|
|
||||||
throw new System.NotSupportedException(string.Format("Wireless Provider Not Supported: '{0}'", dbContext.DiscoConfiguration.Wireless.Provider));
|
|
||||||
}
|
|
||||||
protected BaseWirelessProvider(DiscoDataContext dbContext)
|
|
||||||
{
|
|
||||||
this.dbContext = dbContext;
|
|
||||||
}
|
|
||||||
private DeviceCertificate CertificateAllocate(ref Device repoDevice)
|
|
||||||
{
|
|
||||||
lock (BaseWirelessProvider._CertificateAllocateLock)
|
|
||||||
{
|
|
||||||
this.FillCertificateAutoBuffer();
|
|
||||||
int timeout = 60;
|
|
||||||
int freeCertCount = this.dbContext.DeviceCertificates.Where(c => c.DeviceSerialNumber == null && c.Enabled).Count();
|
|
||||||
while (!(freeCertCount > 0 | timeout <= 0))
|
|
||||||
{
|
|
||||||
System.Threading.Thread.Sleep(500);
|
|
||||||
freeCertCount = this.dbContext.DeviceCertificates.Where(c => c.DeviceSerialNumber == null && c.Enabled).Count();
|
|
||||||
timeout--;
|
|
||||||
}
|
|
||||||
DeviceCertificate cert = this.dbContext.DeviceCertificates.Where(c => c.DeviceSerialNumber == null && c.Enabled).FirstOrDefault();
|
|
||||||
if (cert == null)
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog.LogAllocationFailed(repoDevice.SerialNumber);
|
|
||||||
throw new System.InvalidOperationException("Unable to Allocate a Wireless Certificate");
|
|
||||||
}
|
|
||||||
WirelessCertificatesLog.LogAllocated(cert.Name, repoDevice.SerialNumber);
|
|
||||||
cert.DeviceSerialNumber = repoDevice.SerialNumber;
|
|
||||||
cert.AllocatedDate = System.DateTime.Now;
|
|
||||||
this.dbContext.SaveChanges();
|
|
||||||
return cert;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public DeviceCertificate Enrol(Device repoDevice)
|
|
||||||
{
|
|
||||||
DeviceCertificate allocatedCert = this.dbContext.DeviceCertificates.Where(c => c.DeviceSerialNumber == repoDevice.SerialNumber && c.Enabled).FirstOrDefault();
|
|
||||||
if (allocatedCert != null)
|
|
||||||
{
|
|
||||||
return allocatedCert;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removed 2012-06-14 G# - Properties moved to DeviceProfile model & DB Migrated in DBv3.
|
|
||||||
//if (repoDevice.DeviceProfile.Configuration(this.dbContext).AllocateWirelessCertificate)
|
|
||||||
if (repoDevice.DeviceProfile.AllocateCertificate)
|
|
||||||
{
|
|
||||||
allocatedCert = this.CertificateAllocate(ref repoDevice);
|
|
||||||
return allocatedCert;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
protected abstract void FillCertificateAutoBuffer();
|
|
||||||
public abstract void FillCertificateBuffer(int Amount);
|
|
||||||
public abstract System.Collections.Generic.List<string> RemoveExistingCertificateNames();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,304 +0,0 @@
|
|||||||
using Disco.Logging;
|
|
||||||
using Disco.Logging.Models;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
namespace Disco.BI.Wireless
|
|
||||||
{
|
|
||||||
public class WirelessCertificatesLog : LogBase
|
|
||||||
{
|
|
||||||
public enum EventTypeIds
|
|
||||||
{
|
|
||||||
RetrievalStarting = 10,
|
|
||||||
RetrievalProgress,
|
|
||||||
RetrievalFinished,
|
|
||||||
RetrievalWarning = 15,
|
|
||||||
RetrievalError,
|
|
||||||
RetrievalCertificateStarting = 20,
|
|
||||||
RetrievalCertificateFinished = 22,
|
|
||||||
RetrievalCertificateWarning = 25,
|
|
||||||
RetrievalCertificateError,
|
|
||||||
Allocated = 40,
|
|
||||||
AllocationFailed = 50
|
|
||||||
}
|
|
||||||
private const int _ModuleId = 60;
|
|
||||||
private static bool _IsCertificateRetrievalProcessing;
|
|
||||||
private static string _CertificateRetrievalStatus;
|
|
||||||
private static int _CertificateRetrievalProgress;
|
|
||||||
public static WirelessCertificatesLog Current
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return (WirelessCertificatesLog)LogContext.LogModules[60];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static bool IsCertificateRetrievalProcessing
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return WirelessCertificatesLog._IsCertificateRetrievalProcessing;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override string ModuleDescription
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return "Wireless Certificates";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override int ModuleId
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return 60;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override string ModuleName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return "WirelessCertificates";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[System.Diagnostics.DebuggerNonUserCode]
|
|
||||||
public WirelessCertificatesLog()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
private static void Log(WirelessCertificatesLog.EventTypeIds EventTypeId, params object[] Args)
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog.Current.Log((int)EventTypeId, Args);
|
|
||||||
}
|
|
||||||
public static void LogRetrievalStarting(int CertificateCount, int CertificateIdFrom, int CertificateIdTo)
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.RetrievalStarting, new object[]
|
|
||||||
{
|
|
||||||
CertificateCount,
|
|
||||||
CertificateIdFrom,
|
|
||||||
CertificateIdTo
|
|
||||||
});
|
|
||||||
}
|
|
||||||
public static void LogRetrievalFinished()
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.RetrievalFinished, new object[0]);
|
|
||||||
}
|
|
||||||
public static void LogRetrievalWarning(string Message)
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.RetrievalWarning, new object[]
|
|
||||||
{
|
|
||||||
Message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
public static void LogRetrievalError(string Message)
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.RetrievalError, new object[]
|
|
||||||
{
|
|
||||||
Message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
public static void LogRetrievalCertificateStarting(string CertificateId)
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.RetrievalCertificateStarting, new object[]
|
|
||||||
{
|
|
||||||
CertificateId
|
|
||||||
});
|
|
||||||
}
|
|
||||||
public static void LogRetrievalCertificateFinished(string CertificateId)
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.RetrievalCertificateFinished, new object[]
|
|
||||||
{
|
|
||||||
CertificateId
|
|
||||||
});
|
|
||||||
}
|
|
||||||
public static void LogRetrievalCertificateWarning(string CertificateId, string Message)
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.RetrievalCertificateWarning, new object[]
|
|
||||||
{
|
|
||||||
CertificateId,
|
|
||||||
Message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
public static void LogRetrievalCertificateError(string CertificateId, string Message)
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.RetrievalCertificateError, new object[]
|
|
||||||
{
|
|
||||||
CertificateId,
|
|
||||||
Message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
public static void LogAllocated(string CertificateId, string DeviceSerialNumber)
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.Allocated, new object[]
|
|
||||||
{
|
|
||||||
CertificateId,
|
|
||||||
DeviceSerialNumber
|
|
||||||
});
|
|
||||||
}
|
|
||||||
public static void LogAllocationFailed(string DeviceSerialNumber)
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.AllocationFailed, new object[]
|
|
||||||
{
|
|
||||||
DeviceSerialNumber
|
|
||||||
});
|
|
||||||
}
|
|
||||||
public static void LogCertificateRetrievalProgress(bool? IsProcessing, int? Progress, string Status)
|
|
||||||
{
|
|
||||||
bool flag = IsProcessing.HasValue;
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog._IsCertificateRetrievalProcessing = IsProcessing.Value;
|
|
||||||
}
|
|
||||||
flag = WirelessCertificatesLog._IsCertificateRetrievalProcessing;
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
bool flag2 = Status != null;
|
|
||||||
if (flag2)
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog._CertificateRetrievalStatus = Status;
|
|
||||||
}
|
|
||||||
flag2 = Progress.HasValue;
|
|
||||||
if (flag2)
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog._CertificateRetrievalProgress = Progress.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog._CertificateRetrievalStatus = null;
|
|
||||||
WirelessCertificatesLog._CertificateRetrievalProgress = 0;
|
|
||||||
}
|
|
||||||
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.RetrievalProgress, new object[]
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog._IsCertificateRetrievalProcessing,
|
|
||||||
WirelessCertificatesLog._CertificateRetrievalProgress,
|
|
||||||
WirelessCertificatesLog._CertificateRetrievalStatus
|
|
||||||
});
|
|
||||||
}
|
|
||||||
protected override System.Collections.Generic.List<LogEventType> LoadEventTypes()
|
|
||||||
{
|
|
||||||
return new System.Collections.Generic.List<LogEventType>
|
|
||||||
{
|
|
||||||
new LogEventType
|
|
||||||
{
|
|
||||||
Id = 10,
|
|
||||||
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 = 11,
|
|
||||||
ModuleId = 60,
|
|
||||||
Name = "Retrieval Progress",
|
|
||||||
Format = "Processing: {0}; {1}% Complete; Status: {2}",
|
|
||||||
Severity = 0,
|
|
||||||
UseLive = true,
|
|
||||||
UsePersist = false,
|
|
||||||
UseDisplay = false
|
|
||||||
},
|
|
||||||
new LogEventType
|
|
||||||
{
|
|
||||||
Id = 12,
|
|
||||||
ModuleId = 60,
|
|
||||||
Name = "Retrieval Finished",
|
|
||||||
Format = "Retrieval of Certificates Complete",
|
|
||||||
Severity = 0,
|
|
||||||
UseLive = true,
|
|
||||||
UsePersist = true,
|
|
||||||
UseDisplay = true
|
|
||||||
},
|
|
||||||
new LogEventType
|
|
||||||
{
|
|
||||||
Id = 15,
|
|
||||||
ModuleId = 60,
|
|
||||||
Name = "Retrieval Warning",
|
|
||||||
Format = "Retrieval Warning: {0}",
|
|
||||||
Severity = 1,
|
|
||||||
UseLive = true,
|
|
||||||
UsePersist = true,
|
|
||||||
UseDisplay = true
|
|
||||||
},
|
|
||||||
new LogEventType
|
|
||||||
{
|
|
||||||
Id = 16,
|
|
||||||
ModuleId = 60,
|
|
||||||
Name = "Retrieval Error",
|
|
||||||
Format = "Retrieval Error: {0}",
|
|
||||||
Severity = 2,
|
|
||||||
UseLive = true,
|
|
||||||
UsePersist = true,
|
|
||||||
UseDisplay = true
|
|
||||||
},
|
|
||||||
new LogEventType
|
|
||||||
{
|
|
||||||
Id = 20,
|
|
||||||
ModuleId = 60,
|
|
||||||
Name = "Retrieval Certificate Starting",
|
|
||||||
Format = "Retrieving Certificate: {0}",
|
|
||||||
Severity = 0,
|
|
||||||
UseLive = true,
|
|
||||||
UsePersist = true,
|
|
||||||
UseDisplay = true
|
|
||||||
},
|
|
||||||
new LogEventType
|
|
||||||
{
|
|
||||||
Id = 22,
|
|
||||||
ModuleId = 60,
|
|
||||||
Name = "Retrieval Certificate Finished",
|
|
||||||
Format = "Certificate Retrieved: {0}",
|
|
||||||
Severity = 0,
|
|
||||||
UseLive = true,
|
|
||||||
UsePersist = true,
|
|
||||||
UseDisplay = true
|
|
||||||
},
|
|
||||||
new LogEventType
|
|
||||||
{
|
|
||||||
Id = 25,
|
|
||||||
ModuleId = 60,
|
|
||||||
Name = "Retrieval Certificate Warning",
|
|
||||||
Format = "{0} Certificate Warning: {1}",
|
|
||||||
Severity = 1,
|
|
||||||
UseLive = true,
|
|
||||||
UsePersist = true,
|
|
||||||
UseDisplay = true
|
|
||||||
},
|
|
||||||
new LogEventType
|
|
||||||
{
|
|
||||||
Id = 26,
|
|
||||||
ModuleId = 60,
|
|
||||||
Name = "Retrieval Certificate Error",
|
|
||||||
Format = "{0} Certificate Error: {1}",
|
|
||||||
Severity = 2,
|
|
||||||
UseLive = true,
|
|
||||||
UsePersist = true,
|
|
||||||
UseDisplay = true
|
|
||||||
},
|
|
||||||
new LogEventType
|
|
||||||
{
|
|
||||||
Id = 40,
|
|
||||||
ModuleId = 60,
|
|
||||||
Name = "Allocated",
|
|
||||||
Format = "Certificate {0} allocated to {1}",
|
|
||||||
Severity = 0,
|
|
||||||
UseLive = true,
|
|
||||||
UsePersist = true,
|
|
||||||
UseDisplay = true
|
|
||||||
},
|
|
||||||
new LogEventType
|
|
||||||
{
|
|
||||||
Id = 50,
|
|
||||||
ModuleId = 60,
|
|
||||||
Name = "Allocation Failed",
|
|
||||||
Format = "No certificates available for Device: {0}",
|
|
||||||
Severity = 2,
|
|
||||||
UseLive = true,
|
|
||||||
UsePersist = true,
|
|
||||||
UseDisplay = true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,283 +0,0 @@
|
|||||||
using Disco.BI.Wireless.eduSTAR.eduSTARWirelessCertService;
|
|
||||||
using Disco.Data.Repository;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
using Ionic.Zip;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Security.Cryptography.X509Certificates;
|
|
||||||
using System.ServiceModel;
|
|
||||||
using System.ServiceModel.Channels;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace Disco.BI.Wireless.eduSTAR
|
|
||||||
{
|
|
||||||
public class eduSTARWirelessProvider : BaseWirelessProvider
|
|
||||||
{
|
|
||||||
private class BulkLoadCertificatesContract
|
|
||||||
{
|
|
||||||
public int Start { get; set; }
|
|
||||||
public int Count { get; set; }
|
|
||||||
}
|
|
||||||
private static object _BulkLoadThreadLock = new object();
|
|
||||||
private static System.Threading.Thread _BulkLoadThread;
|
|
||||||
public eduSTARWirelessProvider(DiscoDataContext dbContext)
|
|
||||||
: base(dbContext)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
protected override void FillCertificateAutoBuffer()
|
|
||||||
{
|
|
||||||
int freeCertCount = this.dbContext.DeviceCertificates.Where(c => c.DeviceSerialNumber == null && c.Enabled).Count();
|
|
||||||
if (freeCertCount <= this.dbContext.DiscoConfiguration.Wireless.CertificateAutoBufferLow)
|
|
||||||
{
|
|
||||||
this.BulkLoadCertificates(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override void FillCertificateBuffer(int Amount)
|
|
||||||
{
|
|
||||||
this.BulkLoadCertificates(Amount);
|
|
||||||
}
|
|
||||||
public override System.Collections.Generic.List<string> RemoveExistingCertificateNames()
|
|
||||||
{
|
|
||||||
return new System.Collections.Generic.List<string>
|
|
||||||
{
|
|
||||||
"(eduPaSS)",
|
|
||||||
"(CN=Computers, ?DC=services, ?DC=education, ?DC=vic, ?DC=gov, ?DC=au)"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
private void BulkLoadCertificates(int Amount = 0)
|
|
||||||
{
|
|
||||||
if (eduSTARWirelessProvider._BulkLoadThread == null)
|
|
||||||
{
|
|
||||||
lock (eduSTARWirelessProvider._BulkLoadThreadLock)
|
|
||||||
{
|
|
||||||
if (eduSTARWirelessProvider._BulkLoadThread == null)
|
|
||||||
{
|
|
||||||
int start = 0;
|
|
||||||
if (this.dbContext.DeviceCertificates.Count() > 0)
|
|
||||||
{
|
|
||||||
start = this.dbContext.DeviceCertificates.Max(c => c.ProviderIndex) + 1;
|
|
||||||
}
|
|
||||||
int buffer = this.dbContext.DeviceCertificates.Count(c => c.DeviceSerialNumber == null && c.Enabled);
|
|
||||||
int count = this.dbContext.DiscoConfiguration.Wireless.CertificateAutoBufferMax - buffer;
|
|
||||||
if (Amount > 0)
|
|
||||||
{
|
|
||||||
count = Amount;
|
|
||||||
}
|
|
||||||
if (count > 0)
|
|
||||||
{
|
|
||||||
eduSTARWirelessProvider.BulkLoadCertificatesContract contract = new eduSTARWirelessProvider.BulkLoadCertificatesContract
|
|
||||||
{
|
|
||||||
Start = start,
|
|
||||||
Count = count
|
|
||||||
};
|
|
||||||
System.Threading.ParameterizedThreadStart threadStart = delegate(object a0)
|
|
||||||
{
|
|
||||||
this.BulkLoadCertificatesStart((eduSTARWirelessProvider.BulkLoadCertificatesContract)a0);
|
|
||||||
}
|
|
||||||
;
|
|
||||||
eduSTARWirelessProvider._BulkLoadThread = new System.Threading.Thread(threadStart);
|
|
||||||
eduSTARWirelessProvider._BulkLoadThread.Start(contract);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void BulkLoadCertificatesStart(eduSTARWirelessProvider.BulkLoadCertificatesContract contract)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog.LogRetrievalStarting(contract.Count, contract.Start, contract.Start + contract.Count - 1);
|
|
||||||
WirelessCertificatesLog.LogCertificateRetrievalProgress(true, 0, string.Format("Starting Bulk Retrieval (Loading {0} Certificate/s)", contract.Count));
|
|
||||||
DiscoDataContext dbLocalContext = new DiscoDataContext();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
WirelessCertServiceSoapClient proxy = this.GetProxy();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int num = contract.Start + contract.Count - 1;
|
|
||||||
int index = contract.Start;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
int num2 = num;
|
|
||||||
if (index > num2)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
WirelessCertificatesLog.LogCertificateRetrievalProgress(true, (int)System.Math.Round(unchecked(((double)checked(index - contract.Start) + 0.5) / (double)contract.Count * 100.0)), string.Format("Retrieving Certificate {0} of {1}", index - contract.Start + 1, contract.Count));
|
|
||||||
DeviceCertificate cert = this.LoadCertificate(index, proxy, dbLocalContext);
|
|
||||||
dbLocalContext.DeviceCertificates.Add(cert);
|
|
||||||
dbLocalContext.SaveChanges();
|
|
||||||
WirelessCertificatesLog.LogRetrievalCertificateFinished(cert.Name);
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
bool flag = proxy != null;
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
((System.IDisposable)proxy).Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
bool flag = dbLocalContext != null;
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
((System.IDisposable)dbLocalContext).Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (System.Exception ex)
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog.LogRetrievalError(string.Format("[{0}] {1}", ex.GetType().Name, ex.Message));
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
lock (eduSTARWirelessProvider._BulkLoadThreadLock)
|
|
||||||
{
|
|
||||||
eduSTARWirelessProvider._BulkLoadThread = null;
|
|
||||||
}
|
|
||||||
WirelessCertificatesLog.LogRetrievalFinished();
|
|
||||||
WirelessCertificatesLog.LogCertificateRetrievalProgress(false, null, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private DeviceCertificate LoadCertificate(int Index, DiscoDataContext dbContext)
|
|
||||||
{
|
|
||||||
DeviceCertificate LoadCertificate;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
WirelessCertServiceSoapClient proxy = this.GetProxy();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
LoadCertificate = this.LoadCertificate(Index, proxy, dbContext);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
bool flag = proxy != null;
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
((System.IDisposable)proxy).Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (System.Exception ex)
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog.LogRetrievalCertificateError(Index.ToString(), string.Format("[{0}] {1}", ex.GetType().Name, ex.Message));
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
return LoadCertificate;
|
|
||||||
}
|
|
||||||
private DeviceCertificate LoadCertificate(int Index, WirelessCertServiceSoapClient Proxy, DiscoDataContext dbContext)
|
|
||||||
{
|
|
||||||
bool flag = string.IsNullOrWhiteSpace(dbContext.DiscoConfiguration.Wireless.eduSTAR_ServiceAccountSchoolId);
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
throw new System.ArgumentException("Wireless Certificates: Invalid ServiceAccount SchoolId");
|
|
||||||
}
|
|
||||||
flag = string.IsNullOrWhiteSpace(dbContext.DiscoConfiguration.Wireless.eduSTAR_ServiceAccountUsername);
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
throw new System.ArgumentException("Wireless Certificates: Invalid ServiceAccount Username");
|
|
||||||
}
|
|
||||||
flag = string.IsNullOrWhiteSpace(dbContext.DiscoConfiguration.Wireless.eduSTAR_ServiceAccountPassword);
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
throw new System.ArgumentException("Wireless Certificates: Invalid ServiceAccount Password");
|
|
||||||
}
|
|
||||||
DeviceCertificate cert = new DeviceCertificate
|
|
||||||
{
|
|
||||||
ProviderIndex = Index,
|
|
||||||
Name = string.Format("{0}-{1}", dbContext.DiscoConfiguration.Wireless.eduSTAR_ServiceAccountSchoolId, Index.ToString("00000")),
|
|
||||||
Enabled = true
|
|
||||||
};
|
|
||||||
WirelessCertificatesLog.LogRetrievalCertificateStarting(cert.Name);
|
|
||||||
string response;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
response = Proxy.GetWirelessCert(dbContext.DiscoConfiguration.Wireless.eduSTAR_ServiceAccountSchoolId, cert.Name, "password", dbContext.DiscoConfiguration.Wireless.eduSTAR_ServiceAccountUsername, dbContext.DiscoConfiguration.Wireless.eduSTAR_ServiceAccountPassword);
|
|
||||||
}
|
|
||||||
catch (System.Exception ex)
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog.LogRetrievalCertificateError(cert.Name, ex.Message);
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
byte[] responseBytes = System.Convert.FromBase64String(response);
|
|
||||||
System.IO.MemoryStream responseByteStream = new System.IO.MemoryStream(responseBytes);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ZipFile responseZip = ZipFile.Read(responseByteStream);
|
|
||||||
ZipEntry certFile = responseZip.FirstOrDefault((ZipEntry ze) => ze.FileName.EndsWith(".pfx", System.StringComparison.InvariantCultureIgnoreCase));
|
|
||||||
System.IO.MemoryStream certByteStream = new System.IO.MemoryStream();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
certFile.Extract(certByteStream);
|
|
||||||
cert.Content = certByteStream.ToArray();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
flag = (certByteStream != null);
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
((System.IDisposable)certByteStream).Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
flag = (responseByteStream != null);
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
((System.IDisposable)responseByteStream).Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (System.Exception ex2)
|
|
||||||
{
|
|
||||||
if (response.Contains("Computer with this name already exists"))
|
|
||||||
{
|
|
||||||
WirelessCertificatesLog.LogRetrievalCertificateWarning(cert.Name, "Already exists on eduSTAR server, disabling and skipping.");
|
|
||||||
cert.ExpirationDate = System.DateTime.Now;
|
|
||||||
cert.Enabled = false;
|
|
||||||
cert.Content = null;
|
|
||||||
return cert;
|
|
||||||
}
|
|
||||||
throw new System.InvalidOperationException(string.Format("Unable to Uncompress (Server returned: {0})", response), ex2);
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
X509Certificate2 x509Cert = new X509Certificate2(cert.Content, "password");
|
|
||||||
cert.ExpirationDate = x509Cert.NotAfter;
|
|
||||||
}
|
|
||||||
catch (System.Exception ex3)
|
|
||||||
{
|
|
||||||
throw new System.InvalidOperationException("Invalid Certificate returned by Server", ex3);
|
|
||||||
}
|
|
||||||
return cert;
|
|
||||||
}
|
|
||||||
private WirelessCertServiceSoapClient GetProxy()
|
|
||||||
{
|
|
||||||
BasicHttpBinding binding = new BasicHttpBinding();
|
|
||||||
|
|
||||||
// Don't Use Proxy
|
|
||||||
binding.UseDefaultWebProxy = false;
|
|
||||||
binding.ProxyAddress = null;
|
|
||||||
|
|
||||||
binding.Security.Mode = BasicHttpSecurityMode.Transport;
|
|
||||||
binding.MaxReceivedMessageSize = 524288L;
|
|
||||||
binding.ReaderQuotas.MaxStringContentLength = 524288;
|
|
||||||
EndpointAddress endpointAddress = new EndpointAddress(new Uri("https://www.eduweb.vic.gov.au/edustar/WirelessCertWS/wirelesscertws.asmx"), new AddressHeader[0]);
|
|
||||||
return new WirelessCertServiceSoapClient(binding, endpointAddress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+15
-62
@@ -46,35 +46,6 @@
|
|||||||
<Reference Include="itextsharp">
|
<Reference Include="itextsharp">
|
||||||
<HintPath>..\Resources\Libraries\iTextSharp\itextsharp.dll</HintPath>
|
<HintPath>..\Resources\Libraries\iTextSharp\itextsharp.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="LumenWorks.Framework.IO">
|
|
||||||
<HintPath>..\..\..\Resources\Libraries\LumenWorks.Framework.IO\LumenWorks.Framework.IO.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.AspNet.SignalR.Core, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
<HintPath>..\packages\Microsoft.AspNet.SignalR.Core.1.1.2\lib\net40\Microsoft.AspNet.SignalR.Core.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.AspNet.SignalR.Owin, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
<HintPath>..\packages\Microsoft.AspNet.SignalR.Owin.1.1.2\lib\net45\Microsoft.AspNet.SignalR.Owin.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.AspNet.SignalR.SystemWeb, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
<HintPath>..\packages\Microsoft.AspNet.SignalR.SystemWeb.1.1.2\lib\net45\Microsoft.AspNet.SignalR.SystemWeb.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.Owin.Host.SystemWeb">
|
|
||||||
<HintPath>..\packages\Microsoft.Owin.Host.SystemWeb.1.0.1\lib\net45\Microsoft.Owin.Host.SystemWeb.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
|
||||||
<Private>True</Private>
|
|
||||||
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Owin">
|
|
||||||
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Quartz">
|
<Reference Include="Quartz">
|
||||||
<HintPath>..\Resources\Libraries\Quartz\Quartz.dll</HintPath>
|
<HintPath>..\Resources\Libraries\Quartz\Quartz.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
@@ -88,20 +59,21 @@
|
|||||||
<Reference Include="System.DirectoryServices" />
|
<Reference Include="System.DirectoryServices" />
|
||||||
<Reference Include="System.Drawing" />
|
<Reference Include="System.Drawing" />
|
||||||
<Reference Include="System.Management" />
|
<Reference Include="System.Management" />
|
||||||
<Reference Include="System.Reactive.Core, Version=2.1.30214.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
<Reference Include="System.Reactive.Core, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\Rx-Core.2.1.30214.0\lib\Net45\System.Reactive.Core.dll</HintPath>
|
<HintPath>..\packages\Rx-Core.2.2.4\lib\net45\System.Reactive.Core.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Reactive.Interfaces, Version=2.1.30214.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
<Reference Include="System.Reactive.Interfaces, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\Rx-Interfaces.2.1.30214.0\lib\Net45\System.Reactive.Interfaces.dll</HintPath>
|
<HintPath>..\packages\Rx-Interfaces.2.2.4\lib\net45\System.Reactive.Interfaces.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Reactive.Linq, Version=2.1.30214.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
<Reference Include="System.Reactive.Linq, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\Rx-Linq.2.1.30214.0\lib\Net45\System.Reactive.Linq.dll</HintPath>
|
<HintPath>..\packages\Rx-Linq.2.2.4\lib\net45\System.Reactive.Linq.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Reactive.PlatformServices">
|
<Reference Include="System.Reactive.PlatformServices, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Rx-PlatformServices.2.1.30214.0\lib\Net45\System.Reactive.PlatformServices.dll</HintPath>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\packages\Rx-PlatformServices.2.2.4\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Runtime.Serialization" />
|
<Reference Include="System.Runtime.Serialization" />
|
||||||
<Reference Include="System.ServiceModel" />
|
<Reference Include="System.ServiceModel" />
|
||||||
@@ -123,14 +95,12 @@
|
|||||||
<Compile Include="BI\AttachmentBI\Utilities.cs" />
|
<Compile Include="BI\AttachmentBI\Utilities.cs" />
|
||||||
<Compile Include="BI\DeviceBI\BatchUtilities.cs" />
|
<Compile Include="BI\DeviceBI\BatchUtilities.cs" />
|
||||||
<Compile Include="BI\DeviceBI\DeviceModelBI.cs" />
|
<Compile Include="BI\DeviceBI\DeviceModelBI.cs" />
|
||||||
<Compile Include="BI\DeviceBI\Importing\Export.cs" />
|
|
||||||
<Compile Include="BI\DeviceBI\Importing\Import.cs" />
|
|
||||||
<Compile Include="BI\DeviceBI\Importing\ImportParseTask.cs" />
|
|
||||||
<Compile Include="BI\DeviceBI\Importing\ImportProcessTask.cs" />
|
|
||||||
<Compile Include="BI\DeviceBI\Migration\LogMacAddressImporting.cs" />
|
<Compile Include="BI\DeviceBI\Migration\LogMacAddressImporting.cs" />
|
||||||
<Compile Include="BI\DeviceBI\Searching.cs" />
|
|
||||||
<Compile Include="BI\DisposableImageCollection.cs" />
|
<Compile Include="BI\DisposableImageCollection.cs" />
|
||||||
<Compile Include="BI\DocumentTemplateBI\DocumentTemplateQRCodeLocationCache.cs" />
|
<Compile Include="BI\DocumentTemplateBI\DocumentTemplateQRCodeLocationCache.cs" />
|
||||||
|
<Compile Include="BI\DocumentTemplateBI\ManagedGroups\DocumentTemplateUsersManagedGroup.cs" />
|
||||||
|
<Compile Include="BI\DocumentTemplateBI\ManagedGroups\DocumentTemplateDevicesManagedGroup.cs" />
|
||||||
|
<Compile Include="BI\DocumentTemplateBI\ManagedGroups\DocumentTemplateManagedGroups.cs" />
|
||||||
<Compile Include="BI\Expressions\EvaluateExpressionParseException.cs" />
|
<Compile Include="BI\Expressions\EvaluateExpressionParseException.cs" />
|
||||||
<Compile Include="BI\Expressions\ExpressionCachePreloadTask.cs" />
|
<Compile Include="BI\Expressions\ExpressionCachePreloadTask.cs" />
|
||||||
<Compile Include="BI\Expressions\Extensions\DataExt.cs" />
|
<Compile Include="BI\Expressions\Extensions\DataExt.cs" />
|
||||||
@@ -145,6 +115,7 @@
|
|||||||
<Compile Include="BI\Extensions\AttachmentExtensions.cs" />
|
<Compile Include="BI\Extensions\AttachmentExtensions.cs" />
|
||||||
<Compile Include="BI\Extensions\AuthorizationRoleExtensions.cs" />
|
<Compile Include="BI\Extensions\AuthorizationRoleExtensions.cs" />
|
||||||
<Compile Include="BI\Extensions\ClientServicesExtensions.cs" />
|
<Compile Include="BI\Extensions\ClientServicesExtensions.cs" />
|
||||||
|
<Compile Include="BI\Extensions\UserFlagActionExtensions.cs" />
|
||||||
<Compile Include="BI\Extensions\DeviceActionExtensions.cs" />
|
<Compile Include="BI\Extensions\DeviceActionExtensions.cs" />
|
||||||
<Compile Include="BI\Extensions\DeviceBatchExtensions.cs" />
|
<Compile Include="BI\Extensions\DeviceBatchExtensions.cs" />
|
||||||
<Compile Include="BI\Extensions\DeviceCertificateExtensions.cs" />
|
<Compile Include="BI\Extensions\DeviceCertificateExtensions.cs" />
|
||||||
@@ -154,7 +125,7 @@
|
|||||||
<Compile Include="BI\Extensions\JobActionExtensions.cs" />
|
<Compile Include="BI\Extensions\JobActionExtensions.cs" />
|
||||||
<Compile Include="BI\Extensions\JobExtensions.cs" />
|
<Compile Include="BI\Extensions\JobExtensions.cs" />
|
||||||
<Compile Include="BI\Extensions\JobFlagExtensions.cs" />
|
<Compile Include="BI\Extensions\JobFlagExtensions.cs" />
|
||||||
<Compile Include="BI\Extensions\JobTableExtensions.cs" />
|
<Compile Include="BI\Extensions\JobQueueActionExtensions.cs" />
|
||||||
<Compile Include="BI\Extensions\UserExtensions.cs" />
|
<Compile Include="BI\Extensions\UserExtensions.cs" />
|
||||||
<Compile Include="BI\Extensions\WirelessCertificateExtensions.cs" />
|
<Compile Include="BI\Extensions\WirelessCertificateExtensions.cs" />
|
||||||
<Compile Include="BI\Extensions\DeviceExtensions.cs" />
|
<Compile Include="BI\Extensions\DeviceExtensions.cs" />
|
||||||
@@ -174,32 +145,14 @@
|
|||||||
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterJob.cs" />
|
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterJob.cs" />
|
||||||
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterCleanCacheJob.cs" />
|
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterCleanCacheJob.cs" />
|
||||||
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterLog.cs" />
|
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterLog.cs" />
|
||||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectory.cs" />
|
|
||||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryCachedGroups.cs" />
|
|
||||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryGroupExtensions.cs" />
|
|
||||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryHelpers.cs" />
|
|
||||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryMachineAccountExtensions.cs" />
|
|
||||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryOrganisationalUnit.cs" />
|
|
||||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryUpdateLastNetworkLogonDateJob.cs" />
|
|
||||||
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryUserAccountExtensions.cs" />
|
|
||||||
<Compile Include="BI\Expressions\ExpressionCache.cs" />
|
<Compile Include="BI\Expressions\ExpressionCache.cs" />
|
||||||
<Compile Include="BI\Interop\Community\UpdateCheck.cs" />
|
<Compile Include="BI\Interop\Community\UpdateCheck.cs" />
|
||||||
<Compile Include="BI\Interop\Community\UpdateCheckTask.cs" />
|
<Compile Include="BI\Interop\Community\UpdateCheckTask.cs" />
|
||||||
<Compile Include="BI\Interop\MimeTypes.cs" />
|
<Compile Include="BI\Interop\MimeTypes.cs" />
|
||||||
<Compile Include="BI\Interop\Pdf\PdfGenerator.cs" />
|
<Compile Include="BI\Interop\Pdf\PdfGenerator.cs" />
|
||||||
<Compile Include="BI\Interop\Pdf\PdfImporter.cs" />
|
<Compile Include="BI\Interop\Pdf\PdfImporter.cs" />
|
||||||
<Compile Include="BI\Interop\SignalRHandlers\AuthorizedPersistentConnection.cs" />
|
|
||||||
<Compile Include="BI\Interop\SignalRHandlers\HeldDeviceNotifications.cs" />
|
|
||||||
<Compile Include="BI\Interop\SignalRHandlers\LogNotifications.cs" />
|
|
||||||
<Compile Include="BI\Interop\SignalRHandlers\RepositoryMonitorNotifications.cs" />
|
|
||||||
<Compile Include="BI\Interop\SignalRHandlers\ScheduledTasksStatusNotifications.cs" />
|
|
||||||
<Compile Include="BI\Interop\SignalRHandlers\SignalRAuthenticationWorkaround.cs" />
|
|
||||||
<Compile Include="BI\Interop\SignalRHandlers\UserHeldDeviceNotifications.cs" />
|
|
||||||
<Compile Include="BI\JobBI\ManagedJobList.cs" />
|
|
||||||
<Compile Include="BI\JobBI\Searching.cs" />
|
|
||||||
<Compile Include="BI\JobBI\Statistics\DailyOpenedClosed.cs" />
|
<Compile Include="BI\JobBI\Statistics\DailyOpenedClosed.cs" />
|
||||||
<Compile Include="BI\JobBI\Utilities.cs" />
|
<Compile Include="BI\JobBI\Utilities.cs" />
|
||||||
<Compile Include="BI\UserBI\Searching.cs" />
|
|
||||||
<Compile Include="BI\Extensions\UtilityExtensions.cs" />
|
<Compile Include="BI\Extensions\UtilityExtensions.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Properties\Resources.Designer.cs">
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
@@ -254,7 +207,7 @@
|
|||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<ProjectExtensions>
|
<ProjectExtensions>
|
||||||
<VisualStudio>
|
<VisualStudio>
|
||||||
<UserProperties BuildVersion_UpdateFileVersion="True" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_UseGlobalSettings="False" BuildVersion_DetectChanges="False" BuildVersion_BuildAction="Both" BuildVersion_StartDate="2011/7/1" />
|
<UserProperties BuildVersion_StartDate="2014/6/1" BuildVersion_BuildAction="Both" BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" />
|
||||||
</VisualStudio>
|
</VisualStudio>
|
||||||
</ProjectExtensions>
|
</ProjectExtensions>
|
||||||
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
|
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
|
||||||
|
|||||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
|||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("1.2.1001.1541")]
|
[assembly: AssemblyVersion("2.0.0626.0000")]
|
||||||
[assembly: AssemblyFileVersion("1.2.1001.1541")]
|
[assembly: AssemblyFileVersion("2.0.0626.0000")]
|
||||||
@@ -18,4 +18,28 @@
|
|||||||
<startup>
|
<startup>
|
||||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||||
</startup>
|
</startup>
|
||||||
|
<runtime>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Web.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
</runtime>
|
||||||
</configuration>
|
</configuration>
|
||||||
@@ -1,16 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="EntityFramework" version="5.0.0" targetFramework="net45" />
|
<package id="EntityFramework" version="5.0.0" targetFramework="net45" />
|
||||||
<package id="Microsoft.AspNet.SignalR.Core" version="1.1.2" targetFramework="net45" />
|
<package id="Rx-Core" version="2.2.4" targetFramework="net45" />
|
||||||
<package id="Microsoft.AspNet.SignalR.Owin" version="1.1.2" targetFramework="net45" />
|
<package id="Rx-Interfaces" version="2.2.4" targetFramework="net45" />
|
||||||
<package id="Microsoft.AspNet.SignalR.SystemWeb" version="1.1.2" targetFramework="net45" />
|
<package id="Rx-Linq" version="2.2.4" targetFramework="net45" />
|
||||||
<package id="Microsoft.Owin.Host.SystemWeb" version="1.0.1" targetFramework="net45" />
|
<package id="Rx-Main" version="2.2.4" targetFramework="net45" />
|
||||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" />
|
<package id="Rx-PlatformServices" version="2.2.4" targetFramework="net45" />
|
||||||
<package id="Newtonsoft.Json" version="5.0.8" targetFramework="net45" />
|
|
||||||
<package id="Owin" version="1.0" targetFramework="net45" />
|
|
||||||
<package id="Rx-Core" version="2.1.30214.0" targetFramework="net45" />
|
|
||||||
<package id="Rx-Interfaces" version="2.1.30214.0" targetFramework="net45" />
|
|
||||||
<package id="Rx-Linq" version="2.1.30214.0" targetFramework="net45" />
|
|
||||||
<package id="Rx-Main" version="2.1.30214.0" targetFramework="net45" />
|
|
||||||
<package id="Rx-PlatformServices" version="2.1.30214.0" targetFramework="net45" />
|
|
||||||
</packages>
|
</packages>
|
||||||
@@ -48,9 +48,8 @@
|
|||||||
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
|
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="Newtonsoft.Json">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<HintPath>..\packages\Newtonsoft.Json.6.0.3\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||||
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
|
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
@@ -122,7 +121,7 @@
|
|||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<ProjectExtensions>
|
<ProjectExtensions>
|
||||||
<VisualStudio>
|
<VisualStudio>
|
||||||
<UserProperties BuildVersion_UseGlobalSettings="False" BuildVersion_DetectChanges="False" BuildVersion_StartDate="2011/7/1" BuildVersion_BuildAction="Both" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" />
|
<UserProperties BuildVersion_UseGlobalSettings="False" BuildVersion_DetectChanges="False" BuildVersion_StartDate="2014/6/1" BuildVersion_BuildAction="Both" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" />
|
||||||
</VisualStudio>
|
</VisualStudio>
|
||||||
</ProjectExtensions>
|
</ProjectExtensions>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace Disco.Client.Extensions
|
|||||||
enrol.DeviceModelType = Interop.SystemAudit.DeviceType;
|
enrol.DeviceModelType = Interop.SystemAudit.DeviceType;
|
||||||
|
|
||||||
enrol.DeviceIsPartOfDomain = Interop.SystemAudit.DeviceIsPartOfDomain;
|
enrol.DeviceIsPartOfDomain = Interop.SystemAudit.DeviceIsPartOfDomain;
|
||||||
|
enrol.DeviceDNSDomainName = Interop.SystemAudit.DeviceDNSDomainName;
|
||||||
|
|
||||||
// LAN
|
// LAN
|
||||||
enrol.DeviceLanMacAddress = Interop.Network.PrimaryLanMacAddress;
|
enrol.DeviceLanMacAddress = Interop.Network.PrimaryLanMacAddress;
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 32 KiB |
@@ -22,8 +22,8 @@ namespace Disco.Client.Interop
|
|||||||
using (DirectoryEntry member = new DirectoryEntry(memberRef))
|
using (DirectoryEntry member = new DirectoryEntry(memberRef))
|
||||||
{
|
{
|
||||||
var memberPath = member.Path;
|
var memberPath = member.Path;
|
||||||
if (memberPath.Equals(string.Format("WinNT://{0}/{1}", UserDomain, Username), StringComparison.InvariantCultureIgnoreCase) ||
|
if (memberPath.Equals(string.Format("WinNT://{0}/{1}", UserDomain, Username), StringComparison.OrdinalIgnoreCase) ||
|
||||||
memberPath.Equals(string.Format("WinNT://{0}", UserSID), StringComparison.InvariantCultureIgnoreCase))
|
memberPath.Equals(string.Format("WinNT://{0}", UserSID), StringComparison.OrdinalIgnoreCase))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace Disco.Client.Interop
|
|||||||
// Determine Primary Adapters
|
// Determine Primary Adapters
|
||||||
|
|
||||||
// Lan
|
// Lan
|
||||||
PrimaryLanNetworkAdapter = NetworkAdapters.Where(n => !n.IsWLanAdapter && n.NetConnectionId.StartsWith("Local Area Connection", StringComparison.InvariantCultureIgnoreCase)).OrderByDescending(n => n.Speed).FirstOrDefault();
|
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.
|
// Might be too restrictive - remove name restriction just in case.
|
||||||
if (PrimaryLanNetworkAdapter == null)
|
if (PrimaryLanNetworkAdapter == null)
|
||||||
PrimaryLanNetworkAdapter = NetworkAdapters.Where(n => !n.IsWLanAdapter).OrderByDescending(n => n.Speed).FirstOrDefault();
|
PrimaryLanNetworkAdapter = NetworkAdapters.Where(n => !n.IsWLanAdapter).OrderByDescending(n => n.Speed).FirstOrDefault();
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ namespace Disco.Client.Interop
|
|||||||
public static string DeviceType { get; private set; }
|
public static string DeviceType { get; private set; }
|
||||||
public static string DeviceUUID { get; private set; }
|
public static string DeviceUUID { get; private set; }
|
||||||
public static bool DeviceIsPartOfDomain { get; private set; }
|
public static bool DeviceIsPartOfDomain { get; private set; }
|
||||||
|
public static string DeviceDNSDomainName { get; private set; }
|
||||||
|
|
||||||
public static void Initialize()
|
public static void Initialize()
|
||||||
{
|
{
|
||||||
@@ -56,7 +57,7 @@ namespace Disco.Client.Interop
|
|||||||
// Get System Information
|
// Get System Information
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT Manufacturer, Model, PartOfDomain, PCSystemType FROM Win32_ComputerSystem"))
|
using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT Manufacturer, Model, PartOfDomain, PCSystemType, Domain FROM Win32_ComputerSystem"))
|
||||||
{
|
{
|
||||||
using (ManagementObjectCollection mResults = mSearcher.Get())
|
using (ManagementObjectCollection mResults = mSearcher.Get())
|
||||||
{
|
{
|
||||||
@@ -74,6 +75,8 @@ namespace Disco.Client.Interop
|
|||||||
|
|
||||||
DeviceIsPartOfDomain = (bool)mItem.GetPropertyValue("PartOfDomain");
|
DeviceIsPartOfDomain = (bool)mItem.GetPropertyValue("PartOfDomain");
|
||||||
DeviceType = PCSystemTypeToString((UInt16)mItem.GetPropertyValue("PCSystemType"));
|
DeviceType = PCSystemTypeToString((UInt16)mItem.GetPropertyValue("PCSystemType"));
|
||||||
|
|
||||||
|
DeviceDNSDomainName = DeviceIsPartOfDomain ? mItem.GetPropertyValue("Domain") as string : null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -124,9 +127,9 @@ namespace Disco.Client.Interop
|
|||||||
// Added 2012-11-22 G# - Lenovo IdeaPad Serial SHIM
|
// 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
|
// http://www.discoict.com.au/forum/feature-requests/2012/11/serial-number-detection-on-ideapads.aspx
|
||||||
if (string.IsNullOrWhiteSpace(DeviceSerialNumber) ||
|
if (string.IsNullOrWhiteSpace(DeviceSerialNumber) ||
|
||||||
(DeviceManufacturer.Equals("LENOVO", StringComparison.InvariantCultureIgnoreCase) &&
|
(DeviceManufacturer.Equals("LENOVO", StringComparison.OrdinalIgnoreCase) &&
|
||||||
(DeviceModel.Equals("S10-3", StringComparison.InvariantCultureIgnoreCase) // S10-3
|
(DeviceModel.Equals("S10-3", StringComparison.OrdinalIgnoreCase) // S10-3
|
||||||
|| DeviceModel.Equals("2957", StringComparison.InvariantCultureIgnoreCase)))) // S10-2
|
|| DeviceModel.Equals("2957", StringComparison.OrdinalIgnoreCase)))) // S10-2
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
|||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("1.2.1001.1300")]
|
[assembly: AssemblyVersion("2.0.0626.0000")]
|
||||||
[assembly: AssemblyFileVersion("1.2.1001.1300")]
|
[assembly: AssemblyFileVersion("2.0.0626.0000")]
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Newtonsoft.Json" version="5.0.8" targetFramework="net40-Client" />
|
<package id="Newtonsoft.Json" version="6.0.3" targetFramework="net40-Client" />
|
||||||
</packages>
|
</packages>
|
||||||
@@ -149,7 +149,9 @@ namespace Disco.ClientBootstrapper
|
|||||||
// Unzip Client
|
// Unzip Client
|
||||||
statusUI.UpdateStatus(null, "Extracting", "Retrieving Preparation Client, Please wait...", true, -1);
|
statusUI.UpdateStatus(null, "Extracting", "Retrieving Preparation Client, Please wait...", true, -1);
|
||||||
string clientLocation = Path.Combine(tempWorkingDirectory, "PreparationClient");
|
string clientLocation = Path.Combine(tempWorkingDirectory, "PreparationClient");
|
||||||
if (!Directory.Exists(clientLocation))
|
if (Directory.Exists(clientLocation))
|
||||||
|
Directory.Delete(clientLocation, true);
|
||||||
|
|
||||||
Directory.CreateDirectory(clientLocation);
|
Directory.CreateDirectory(clientLocation);
|
||||||
using (var clientSource = Ionic.Zip.ZipFile.Read(clientSourceLocation))
|
using (var clientSource = Ionic.Zip.ZipFile.Read(clientSourceLocation))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -319,7 +319,7 @@
|
|||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<ProjectExtensions>
|
<ProjectExtensions>
|
||||||
<VisualStudio>
|
<VisualStudio>
|
||||||
<UserProperties BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_BuildAction="Both" BuildVersion_UseGlobalSettings="False" BuildVersion_UpdateFileVersion="True" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_DetectChanges="False" BuildVersion_StartDate="2011/7/1" />
|
<UserProperties BuildVersion_StartDate="2014/6/1" BuildVersion_DetectChanges="False" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildAction="Both" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" />
|
||||||
</VisualStudio>
|
</VisualStudio>
|
||||||
</ProjectExtensions>
|
</ProjectExtensions>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 32 KiB |
@@ -74,14 +74,14 @@ namespace Disco.ClientBootstrapper.Interop
|
|||||||
// Only Copy Certain Files
|
// Only Copy Certain Files
|
||||||
|
|
||||||
// Copy Wireless Certificates
|
// Copy Wireless Certificates
|
||||||
if (fileName.StartsWith("WLAN_Cert_Root_", StringComparison.InvariantCultureIgnoreCase) ||
|
if (fileName.StartsWith("WLAN_Cert_Root_", StringComparison.OrdinalIgnoreCase) ||
|
||||||
fileName.StartsWith("WLAN_Cert_Intermediate_", StringComparison.InvariantCultureIgnoreCase) ||
|
fileName.StartsWith("WLAN_Cert_Intermediate_", StringComparison.OrdinalIgnoreCase) ||
|
||||||
fileName.StartsWith("WLAN_Cert_Personal_", StringComparison.InvariantCultureIgnoreCase))
|
fileName.StartsWith("WLAN_Cert_Personal_", StringComparison.OrdinalIgnoreCase))
|
||||||
File.Copy(file, Path.Combine(InstallLocation, fileName));
|
File.Copy(file, Path.Combine(InstallLocation, fileName));
|
||||||
|
|
||||||
// Copy Wireless Profiles
|
// Copy Wireless Profiles
|
||||||
if (fileName.StartsWith("WLAN_Profile_", StringComparison.InvariantCultureIgnoreCase) &&
|
if (fileName.StartsWith("WLAN_Profile_", StringComparison.OrdinalIgnoreCase) &&
|
||||||
fileName.EndsWith(".xml", StringComparison.InvariantCultureIgnoreCase))
|
fileName.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
|
||||||
File.Copy(file, Path.Combine(InstallLocation, fileName));
|
File.Copy(file, Path.Combine(InstallLocation, fileName));
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -194,7 +194,7 @@ namespace Disco.ClientBootstrapper.Interop
|
|||||||
if (string.IsNullOrWhiteSpace(InstallLocation))
|
if (string.IsNullOrWhiteSpace(InstallLocation))
|
||||||
InstallLocation = Path.Combine(Path.GetPathRoot(Environment.SystemDirectory), "Disco");
|
InstallLocation = Path.Combine(Path.GetPathRoot(Environment.SystemDirectory), "Disco");
|
||||||
|
|
||||||
if (InstallLocation.EndsWith(".wim", StringComparison.InvariantCultureIgnoreCase))
|
if (InstallLocation.EndsWith(".wim", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
// Offline File System (WIM)
|
// Offline File System (WIM)
|
||||||
Program.Status.UpdateStatus("Installing Bootstrapper (Offline)", "Installing", string.Format("Install Location: {0}", InstallLocation));
|
Program.Status.UpdateStatus("Installing Bootstrapper (Offline)", "Installing", string.Format("Install Location: {0}", InstallLocation));
|
||||||
@@ -216,7 +216,7 @@ namespace Disco.ClientBootstrapper.Interop
|
|||||||
using (var wimImage = wim[i])
|
using (var wimImage = wim[i])
|
||||||
wimImageInfo.LoadXml(wimImage.ImageInformation);
|
wimImageInfo.LoadXml(wimImage.ImageInformation);
|
||||||
var wimImageInfoName = wimImageInfo.SelectSingleNode("//IMAGE/NAME");
|
var wimImageInfoName = wimImageInfo.SelectSingleNode("//IMAGE/NAME");
|
||||||
if (wimImageInfoName != null && wimImageInfoName.InnerText.Equals(WimImageId, StringComparison.InvariantCultureIgnoreCase))
|
if (wimImageInfoName != null && wimImageInfoName.InnerText.Equals(WimImageId, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
wimImageIndex = i + 1;
|
wimImageIndex = i + 1;
|
||||||
Program.Status.UpdateStatus(null, "Analysing WIM", string.Format("Found Image Id '{0}' at Index {1}", WimImageId, wimImageIndex));
|
Program.Status.UpdateStatus(null, "Analysing WIM", string.Format("Found Image Id '{0}' at Index {1}", WimImageId, wimImageIndex));
|
||||||
|
|||||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
|||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("1.2.1001.1300")]
|
[assembly: AssemblyVersion("2.0.0626.0000")]
|
||||||
[assembly: AssemblyFileVersion("1.2.1001.1300")]
|
[assembly: AssemblyFileVersion("2.0.0626.0000")]
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup>
|
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
|
||||||
<ProductVersion>
|
|
||||||
</ProductVersion>
|
|
||||||
<SchemaVersion>
|
|
||||||
</SchemaVersion>
|
|
||||||
<ProjectGuid>{CD7BB28C-B74D-4880-8B7E-4487AB5E6AFC}</ProjectGuid>
|
|
||||||
<OutputType>Library</OutputType>
|
|
||||||
<RootNamespace>Disco.Configuration</RootNamespace>
|
|
||||||
<AssemblyName>Disco.Configuration</AssemblyName>
|
|
||||||
<FileAlignment>512</FileAlignment>
|
|
||||||
<MyType>Windows</MyType>
|
|
||||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<DefineDebug>true</DefineDebug>
|
|
||||||
<DefineTrace>true</DefineTrace>
|
|
||||||
<OutputPath>bin\Debug\</OutputPath>
|
|
||||||
<DocumentationFile>Disco.Configuration.xml</DocumentationFile>
|
|
||||||
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<DefineDebug>false</DefineDebug>
|
|
||||||
<DefineTrace>true</DefineTrace>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<OutputPath>bin\Release\</OutputPath>
|
|
||||||
<DocumentationFile>Disco.Configuration.xml</DocumentationFile>
|
|
||||||
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup>
|
|
||||||
<OptionExplicit>On</OptionExplicit>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup>
|
|
||||||
<OptionCompare>Binary</OptionCompare>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup>
|
|
||||||
<OptionStrict>Off</OptionStrict>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup>
|
|
||||||
<OptionInfer>On</OptionInfer>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="System" />
|
|
||||||
<Reference Include="System.Data" />
|
|
||||||
<Reference Include="System.Xml" />
|
|
||||||
<Reference Include="System.Core" />
|
|
||||||
<Reference Include="System.Xml.Linq" />
|
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Import Include="Microsoft.VisualBasic" />
|
|
||||||
<Import Include="System" />
|
|
||||||
<Import Include="System.Collections" />
|
|
||||||
<Import Include="System.Collections.Generic" />
|
|
||||||
<Import Include="System.Data" />
|
|
||||||
<Import Include="System.Diagnostics" />
|
|
||||||
<Import Include="System.Linq" />
|
|
||||||
<Import Include="System.Xml.Linq" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="My Project\AssemblyInfo.vb" />
|
|
||||||
<Compile Include="My Project\Application.Designer.vb">
|
|
||||||
<AutoGen>True</AutoGen>
|
|
||||||
<DependentUpon>Application.myapp</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="My Project\Resources.Designer.vb">
|
|
||||||
<AutoGen>True</AutoGen>
|
|
||||||
<DesignTime>True</DesignTime>
|
|
||||||
<DependentUpon>Resources.resx</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="My Project\Settings.Designer.vb">
|
|
||||||
<AutoGen>True</AutoGen>
|
|
||||||
<DependentUpon>Settings.settings</DependentUpon>
|
|
||||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
|
||||||
</Compile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedResource Include="My Project\Resources.resx">
|
|
||||||
<Generator>VbMyResourcesResXFileCodeGenerator</Generator>
|
|
||||||
<LastGenOutput>Resources.Designer.vb</LastGenOutput>
|
|
||||||
<CustomToolNamespace>My.Resources</CustomToolNamespace>
|
|
||||||
<SubType>Designer</SubType>
|
|
||||||
</EmbeddedResource>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="My Project\Application.myapp">
|
|
||||||
<Generator>MyApplicationCodeGenerator</Generator>
|
|
||||||
<LastGenOutput>Application.Designer.vb</LastGenOutput>
|
|
||||||
</None>
|
|
||||||
<None Include="My Project\Settings.settings">
|
|
||||||
<Generator>SettingsSingleFileGenerator</Generator>
|
|
||||||
<CustomToolNamespace>My</CustomToolNamespace>
|
|
||||||
<LastGenOutput>Settings.Designer.vb</LastGenOutput>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Disco.Models\Disco.Models.vbproj">
|
|
||||||
<Project>{40F222A9-CC05-4035-AFF4-15A78250EF2B}</Project>
|
|
||||||
<Name>Disco.Models</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
|
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
|
||||||
<Target Name="BeforeBuild">
|
|
||||||
</Target>
|
|
||||||
<Target Name="AfterBuild">
|
|
||||||
</Target>
|
|
||||||
-->
|
|
||||||
</Project>
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
'------------------------------------------------------------------------------
|
|
||||||
' <auto-generated>
|
|
||||||
' This code was generated by a tool.
|
|
||||||
' Runtime Version:4.0.30319.235
|
|
||||||
'
|
|
||||||
' Changes to this file may cause incorrect behavior and will be lost if
|
|
||||||
' the code is regenerated.
|
|
||||||
' </auto-generated>
|
|
||||||
'------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Option Strict On
|
|
||||||
Option Explicit On
|
|
||||||
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
|
||||||
<MySubMain>false</MySubMain>
|
|
||||||
<SingleInstance>false</SingleInstance>
|
|
||||||
<ShutdownMode>0</ShutdownMode>
|
|
||||||
<EnableVisualStyles>true</EnableVisualStyles>
|
|
||||||
<AuthenticationMode>0</AuthenticationMode>
|
|
||||||
<ApplicationType>1</ApplicationType>
|
|
||||||
<SaveMySettingsOnExit>true</SaveMySettingsOnExit>
|
|
||||||
</MyApplicationData>
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
Imports System
|
|
||||||
Imports System.Reflection
|
|
||||||
Imports 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.
|
|
||||||
|
|
||||||
' Review the values of the assembly attributes
|
|
||||||
|
|
||||||
<Assembly: AssemblyTitle("Disco - Configuration")>
|
|
||||||
<Assembly: AssemblyDescription("")>
|
|
||||||
<Assembly: AssemblyCompany("")>
|
|
||||||
<Assembly: AssemblyProduct("Disco")>
|
|
||||||
<Assembly: AssemblyCopyright("")>
|
|
||||||
<Assembly: AssemblyTrademark("")>
|
|
||||||
|
|
||||||
<Assembly: ComVisible(False)>
|
|
||||||
|
|
||||||
'The following GUID is for the ID of the typelib if this project is exposed to COM
|
|
||||||
<Assembly: Guid("535f903b-6111-4adb-b200-9df78e49d13b")>
|
|
||||||
|
|
||||||
' 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("1.0.0.0")>
|
|
||||||
<Assembly: AssemblyFileVersion("1.0.0.0")>
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
'------------------------------------------------------------------------------
|
|
||||||
' <auto-generated>
|
|
||||||
' This code was generated by a tool.
|
|
||||||
' Runtime Version:4.0.30319.235
|
|
||||||
'
|
|
||||||
' Changes to this file may cause incorrect behavior and will be lost if
|
|
||||||
' the code is regenerated.
|
|
||||||
' </auto-generated>
|
|
||||||
'------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Option Strict On
|
|
||||||
Option Explicit On
|
|
||||||
|
|
||||||
|
|
||||||
Namespace My.Resources
|
|
||||||
|
|
||||||
'This class was auto-generated by the StronglyTypedResourceBuilder
|
|
||||||
'class via a tool like ResGen or Visual Studio.
|
|
||||||
'To add or remove a member, edit your .ResX file then rerun ResGen
|
|
||||||
'with the /str option, or rebuild your VS project.
|
|
||||||
'''<summary>
|
|
||||||
''' A strongly-typed resource class, for looking up localized strings, etc.
|
|
||||||
'''</summary>
|
|
||||||
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0"), _
|
|
||||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
|
||||||
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
|
||||||
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
|
|
||||||
Friend Module Resources
|
|
||||||
|
|
||||||
Private resourceMan As Global.System.Resources.ResourceManager
|
|
||||||
|
|
||||||
Private resourceCulture As Global.System.Globalization.CultureInfo
|
|
||||||
|
|
||||||
'''<summary>
|
|
||||||
''' Returns the cached ResourceManager instance used by this class.
|
|
||||||
'''</summary>
|
|
||||||
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
|
||||||
Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
|
|
||||||
Get
|
|
||||||
If Object.ReferenceEquals(resourceMan, Nothing) Then
|
|
||||||
Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("Disco.Configuration.Resources", GetType(Resources).Assembly)
|
|
||||||
resourceMan = temp
|
|
||||||
End If
|
|
||||||
Return resourceMan
|
|
||||||
End Get
|
|
||||||
End Property
|
|
||||||
|
|
||||||
'''<summary>
|
|
||||||
''' Overrides the current thread's CurrentUICulture property for all
|
|
||||||
''' resource lookups using this strongly typed resource class.
|
|
||||||
'''</summary>
|
|
||||||
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
|
||||||
Friend Property Culture() As Global.System.Globalization.CultureInfo
|
|
||||||
Get
|
|
||||||
Return resourceCulture
|
|
||||||
End Get
|
|
||||||
Set(ByVal value As Global.System.Globalization.CultureInfo)
|
|
||||||
resourceCulture = value
|
|
||||||
End Set
|
|
||||||
End Property
|
|
||||||
End Module
|
|
||||||
End Namespace
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<root>
|
|
||||||
<!--
|
|
||||||
Microsoft ResX Schema
|
|
||||||
|
|
||||||
Version 2.0
|
|
||||||
|
|
||||||
The primary goals of this format is to allow a simple XML format
|
|
||||||
that is mostly human readable. The generation and parsing of the
|
|
||||||
various data types are done through the TypeConverter classes
|
|
||||||
associated with the data types.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
... ado.net/XML headers & schema ...
|
|
||||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
|
||||||
<resheader name="version">2.0</resheader>
|
|
||||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
|
||||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
|
||||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
|
||||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
|
||||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
|
||||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
|
||||||
</data>
|
|
||||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
|
||||||
<comment>This is a comment</comment>
|
|
||||||
</data>
|
|
||||||
|
|
||||||
There are any number of "resheader" rows that contain simple
|
|
||||||
name/value pairs.
|
|
||||||
|
|
||||||
Each data row contains a name, and value. The row also contains a
|
|
||||||
type or mimetype. Type corresponds to a .NET class that support
|
|
||||||
text/value conversion through the TypeConverter architecture.
|
|
||||||
Classes that don't support this are serialized and stored with the
|
|
||||||
mimetype set.
|
|
||||||
|
|
||||||
The mimetype is used for serialized objects, and tells the
|
|
||||||
ResXResourceReader how to depersist the object. This is currently not
|
|
||||||
extensible. For a given mimetype the value must be set accordingly:
|
|
||||||
|
|
||||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
|
||||||
that the ResXResourceWriter will generate, however the reader can
|
|
||||||
read any of the formats listed below.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.binary.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.soap.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
|
||||||
value : The object must be serialized into a byte array
|
|
||||||
: using a System.ComponentModel.TypeConverter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
-->
|
|
||||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
|
||||||
<xsd:element name="root" msdata:IsDataSet="true">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:choice maxOccurs="unbounded">
|
|
||||||
<xsd:element name="metadata">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="assembly">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:attribute name="alias" type="xsd:string" />
|
|
||||||
<xsd:attribute name="name" type="xsd:string" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="data">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="resheader">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:choice>
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:schema>
|
|
||||||
<resheader name="resmimetype">
|
|
||||||
<value>text/microsoft-resx</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="version">
|
|
||||||
<value>2.0</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="reader">
|
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="writer">
|
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
</root>
|
|
||||||
-73
@@ -1,73 +0,0 @@
|
|||||||
'------------------------------------------------------------------------------
|
|
||||||
' <auto-generated>
|
|
||||||
' This code was generated by a tool.
|
|
||||||
' Runtime Version:4.0.30319.235
|
|
||||||
'
|
|
||||||
' Changes to this file may cause incorrect behavior and will be lost if
|
|
||||||
' the code is regenerated.
|
|
||||||
' </auto-generated>
|
|
||||||
'------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Option Strict On
|
|
||||||
Option Explicit On
|
|
||||||
|
|
||||||
|
|
||||||
Namespace My
|
|
||||||
|
|
||||||
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
|
||||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0"), _
|
|
||||||
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
|
||||||
Partial Friend NotInheritable Class MySettings
|
|
||||||
Inherits Global.System.Configuration.ApplicationSettingsBase
|
|
||||||
|
|
||||||
Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings)
|
|
||||||
|
|
||||||
#Region "My.Settings Auto-Save Functionality"
|
|
||||||
#If _MyType = "WindowsForms" Then
|
|
||||||
Private Shared addedHandler As Boolean
|
|
||||||
|
|
||||||
Private Shared addedHandlerLockObject As New Object
|
|
||||||
|
|
||||||
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
|
||||||
Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs)
|
|
||||||
If My.Application.SaveMySettingsOnExit Then
|
|
||||||
My.Settings.Save()
|
|
||||||
End If
|
|
||||||
End Sub
|
|
||||||
#End If
|
|
||||||
#End Region
|
|
||||||
|
|
||||||
Public Shared ReadOnly Property [Default]() As MySettings
|
|
||||||
Get
|
|
||||||
|
|
||||||
#If _MyType = "WindowsForms" Then
|
|
||||||
If Not addedHandler Then
|
|
||||||
SyncLock addedHandlerLockObject
|
|
||||||
If Not addedHandler Then
|
|
||||||
AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings
|
|
||||||
addedHandler = True
|
|
||||||
End If
|
|
||||||
End SyncLock
|
|
||||||
End If
|
|
||||||
#End If
|
|
||||||
Return defaultInstance
|
|
||||||
End Get
|
|
||||||
End Property
|
|
||||||
End Class
|
|
||||||
End Namespace
|
|
||||||
|
|
||||||
Namespace My
|
|
||||||
|
|
||||||
<Global.Microsoft.VisualBasic.HideModuleNameAttribute(), _
|
|
||||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
|
||||||
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute()> _
|
|
||||||
Friend Module MySettingsProperty
|
|
||||||
|
|
||||||
<Global.System.ComponentModel.Design.HelpKeywordAttribute("My.Settings")> _
|
|
||||||
Friend ReadOnly Property Settings() As Global.Disco.Configuration.My.MySettings
|
|
||||||
Get
|
|
||||||
Return Global.Disco.Configuration.My.MySettings.Default
|
|
||||||
End Get
|
|
||||||
End Property
|
|
||||||
End Module
|
|
||||||
End Namespace
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
|
||||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" UseMySettingsClassName="true">
|
|
||||||
<Profiles>
|
|
||||||
<Profile Name="(Default)" />
|
|
||||||
</Profiles>
|
|
||||||
<Settings />
|
|
||||||
</SettingsFile>
|
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Disco.Data.Configuration
|
namespace Disco.Data.Configuration
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
using Disco.Data.Repository;
|
using Disco.Data.Repository;
|
||||||
using Disco.Models.Repository;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Disco.Data.Configuration
|
namespace Disco.Data.Configuration
|
||||||
{
|
{
|
||||||
@@ -15,29 +11,37 @@ namespace Disco.Data.Configuration
|
|||||||
|
|
||||||
public abstract string Scope { get; }
|
public abstract string Scope { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a read-write configuration instance
|
||||||
|
/// </summary>
|
||||||
public ConfigurationBase(DiscoDataContext Database)
|
public ConfigurationBase(DiscoDataContext Database)
|
||||||
{
|
{
|
||||||
this.Database = Database;
|
this.Database = Database;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<ConfigurationItem> Items
|
/// <summary>
|
||||||
|
/// Creates a read-only configuration instance
|
||||||
|
/// </summary>
|
||||||
|
public ConfigurationBase() : this(null) { }
|
||||||
|
|
||||||
|
protected IEnumerable<string> ItemKeys
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ConfigurationCache.GetConfigurationItems(Database, this.Scope);
|
return ConfigurationCache.GetScopeKeys(Database, this.Scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetValue<ValueType>(string Key, ValueType Value)
|
private void SetValue<T>(string Key, T Value)
|
||||||
{
|
{
|
||||||
ConfigurationCache.SetConfigurationValue(Database, this.Scope, Key, Value);
|
ConfigurationCache.SetValue(Database, this.Scope, Key, Value);
|
||||||
}
|
}
|
||||||
private ValueType GetValue<ValueType>(string Key, ValueType Default)
|
private T GetValue<T>(string Key, T Default)
|
||||||
{
|
{
|
||||||
return ConfigurationCache.GetConfigurationValue(Database, this.Scope, Key, Default);
|
return ConfigurationCache.GetValue(Database, this.Scope, Key, Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void Set<ValueType>(ValueType Value, [CallerMemberName] string Key = null)
|
protected void Set<T>(T Value, [CallerMemberName] string Key = null)
|
||||||
{
|
{
|
||||||
if (Key == null)
|
if (Key == null)
|
||||||
throw new ArgumentNullException("Key");
|
throw new ArgumentNullException("Key");
|
||||||
@@ -45,7 +49,7 @@ namespace Disco.Data.Configuration
|
|||||||
this.SetValue(Key, Value);
|
this.SetValue(Key, Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ValueType Get<ValueType>(ValueType Default, [CallerMemberName] string Key = null)
|
protected T Get<T>(T Default, [CallerMemberName] string Key = null)
|
||||||
{
|
{
|
||||||
if (Key == null)
|
if (Key == null)
|
||||||
throw new ArgumentNullException("Key");
|
throw new ArgumentNullException("Key");
|
||||||
@@ -55,7 +59,7 @@ namespace Disco.Data.Configuration
|
|||||||
|
|
||||||
protected void SetObsfucated(string Value, [CallerMemberName] string Key = null)
|
protected void SetObsfucated(string Value, [CallerMemberName] string Key = null)
|
||||||
{
|
{
|
||||||
this.Set(ConfigurationCache.ObsfucateValue(Value), Key);
|
this.Set(Value.Obsfucate(), Key);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string GetDeobsfucated(string Default, [CallerMemberName] string Key = null)
|
protected string GetDeobsfucated(string Default, [CallerMemberName] string Key = null)
|
||||||
@@ -65,26 +69,40 @@ namespace Disco.Data.Configuration
|
|||||||
if (obsfucatedValue == null)
|
if (obsfucatedValue == null)
|
||||||
return Default;
|
return Default;
|
||||||
else
|
else
|
||||||
return ConfigurationCache.DeobsfucateValue(obsfucatedValue);
|
return obsfucatedValue.Deobsfucate();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void SetAsJson<ValueType>(ValueType Value, [CallerMemberName] string Key = null)
|
protected void RemoveScope()
|
||||||
{
|
{
|
||||||
if (Value == null)
|
ConfigurationCache.RemoveScope(Database, this.Scope);
|
||||||
this.Set<string>(null, Key);
|
|
||||||
else
|
|
||||||
this.Set(JsonConvert.SerializeObject(Value), Key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ValueType GetFromJson<ValueType>(ValueType Default, [CallerMemberName] string Key = null)
|
protected void RemoveItem(string Key)
|
||||||
{
|
{
|
||||||
var jsonValue = this.Get<string>(null, Key);
|
ConfigurationCache.RemoveScopeKey(Database, this.Scope, Key);
|
||||||
|
|
||||||
if (jsonValue == null)
|
|
||||||
return Default;
|
|
||||||
else
|
|
||||||
return JsonConvert.DeserializeObject<ValueType>(jsonValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete("Types are automatically serialized/deserialized if required, use Set<T>(T Value) instead.")]
|
||||||
|
protected void SetAsJson<T>(T Value, [CallerMemberName] string Key = null)
|
||||||
|
{
|
||||||
|
this.Set(Value, Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete("Types are automatically serialized/deserialized if required, use Get<T>(T Default) instead.")]
|
||||||
|
protected T GetFromJson<T>(T Default, [CallerMemberName] string Key = null)
|
||||||
|
{
|
||||||
|
return this.Get(Default, Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete("Types are automatically serialized/deserialized if required, use Set<T>(T Value) instead.")]
|
||||||
|
protected void SetAsEnum<T>(T Value, [CallerMemberName] string Key = null)
|
||||||
|
{
|
||||||
|
this.Set(Value, Key);
|
||||||
|
}
|
||||||
|
[Obsolete("Types are automatically serialized/deserialized if required, use Set<T>(T Value) instead.")]
|
||||||
|
protected T GetFromEnum<T>(T Default, [CallerMemberName] string Key = null)
|
||||||
|
{
|
||||||
|
return this.Get(Default, Key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,143 +1,384 @@
|
|||||||
using Disco.Data.Repository;
|
using Disco.Data.Repository;
|
||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Disco.Data.Configuration
|
namespace Disco.Data.Configuration
|
||||||
{
|
{
|
||||||
|
using ConfigurationCacheItemType = Tuple<ConfigurationItem, object>;
|
||||||
|
using ConfigurationCacheScopeType = ConcurrentDictionary<string, Tuple<ConfigurationItem, object>>;
|
||||||
|
using ConfigurationCacheType = ConcurrentDictionary<string, ConcurrentDictionary<string, Tuple<ConfigurationItem, object>>>;
|
||||||
|
|
||||||
internal static class ConfigurationCache
|
internal static class ConfigurationCache
|
||||||
{
|
{
|
||||||
#region Cache
|
#region Cache
|
||||||
|
|
||||||
private static Dictionary<String, Dictionary<String, ConfigurationItem>> configDictionary = new Dictionary<string, Dictionary<string, ConfigurationItem>>();
|
private static ConfigurationCacheType cacheStore = null;
|
||||||
private static List<ConfigurationItem> configurationItems = new List<ConfigurationItem>();
|
private static object configChangeLock = new object();
|
||||||
private static object configurationItemsLock = new object();
|
|
||||||
|
|
||||||
private static void LoadConfigurationItems(DiscoDataContext Database, string Scope, bool Reload)
|
private static ConfigurationCacheType Cache(DiscoDataContext Database)
|
||||||
{
|
{
|
||||||
if (Reload || !configDictionary.ContainsKey(Scope))
|
if (ConfigurationCache.cacheStore == null)
|
||||||
{
|
{
|
||||||
lock (configurationItemsLock)
|
lock (configChangeLock)
|
||||||
{
|
{
|
||||||
if (Reload || !configDictionary.ContainsKey(Scope))
|
if (ConfigurationCache.cacheStore == null)
|
||||||
{
|
{
|
||||||
if (Database == null)
|
if (Database == null)
|
||||||
throw new InvalidOperationException("Cache-miss where Configuration Item requested from Cache-Only Configuration Context");
|
throw new InvalidOperationException("The Configuration must be loaded at least once before a Cache-Only Configuration Context is used");
|
||||||
|
|
||||||
var newItems = Database.ConfigurationItems.Where(ci => ci.Scope == Scope).ToArray();
|
var configurationItems = Database.ConfigurationItems.ToArray();
|
||||||
|
|
||||||
if (configDictionary.ContainsKey(Scope))
|
var indexedItems = configurationItems
|
||||||
|
.GroupBy(ci => ci.Scope)
|
||||||
|
.Select(g =>
|
||||||
|
new KeyValuePair<string, ConfigurationCacheScopeType>(
|
||||||
|
g.Key,
|
||||||
|
new ConfigurationCacheScopeType(
|
||||||
|
g.Select(i => new KeyValuePair<string, ConfigurationCacheItemType>(i.Key, Tuple.Create(i, (object)null))))));
|
||||||
|
|
||||||
|
cacheStore = new ConfigurationCacheType(indexedItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ConfigurationCache.cacheStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ConfigurationCacheItemType CacheGetItem(DiscoDataContext Database, string Scope, string Key)
|
||||||
{
|
{
|
||||||
var existingItems = configDictionary[Scope];
|
var cache = Cache(Database);
|
||||||
foreach (var existingItem in existingItems.Values)
|
|
||||||
|
ConfigurationCacheScopeType scopeCache;
|
||||||
|
if (cache.TryGetValue(Scope, out scopeCache))
|
||||||
{
|
{
|
||||||
configurationItems.Remove(existingItem);
|
ConfigurationCacheItemType item = default(ConfigurationCacheItemType);
|
||||||
}
|
if (scopeCache.TryGetValue(Key, out item))
|
||||||
}
|
|
||||||
configurationItems.AddRange(newItems);
|
|
||||||
configDictionary[Scope] = newItems.ToDictionary(ci => ci.Key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static Dictionary<string, Dictionary<string, ConfigurationItem>> ConfigurationDictionary(DiscoDataContext Database, string IncludingScope)
|
|
||||||
{
|
|
||||||
LoadConfigurationItems(Database, IncludingScope, false);
|
|
||||||
return configDictionary;
|
|
||||||
}
|
|
||||||
private static ConfigurationItem ConfigurationItem(DiscoDataContext Database, string Scope, string Key)
|
|
||||||
{
|
|
||||||
Dictionary<string, ConfigurationItem> scopeDict = default(Dictionary<string, ConfigurationItem>);
|
|
||||||
if (ConfigurationDictionary(Database, Scope).TryGetValue(Scope, out scopeDict))
|
|
||||||
{
|
|
||||||
ConfigurationItem item = default(ConfigurationItem);
|
|
||||||
if (scopeDict.TryGetValue(Key, out item))
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
private static List<ConfigurationItem> ConfigurationItems(DiscoDataContext Database, string IncludingScope)
|
|
||||||
{
|
|
||||||
LoadConfigurationItems(Database, IncludingScope, false);
|
|
||||||
return configurationItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
private static ConfigurationCacheItemType CacheSetItem(DiscoDataContext Database, string Scope, string Key, string Value, object ObjectValue)
|
||||||
|
|
||||||
#region Public Helpers
|
|
||||||
internal static ValueType GetConfigurationValue<ValueType>(DiscoDataContext Database, string Scope, string Key, ValueType Default)
|
|
||||||
{
|
|
||||||
var ci = ConfigurationItem(Database, Scope, Key);
|
|
||||||
if (ci == null)
|
|
||||||
return Default;
|
|
||||||
else
|
|
||||||
return (ValueType)Convert.ChangeType(ci.Value, typeof(ValueType));
|
|
||||||
}
|
|
||||||
internal static void SetConfigurationValue<ValueType>(DiscoDataContext Database, string Scope, string Key, ValueType Value)
|
|
||||||
{
|
{
|
||||||
if (Database == null)
|
if (Database == null)
|
||||||
throw new InvalidOperationException("Cannot save changes with a CacheOnly Context");
|
throw new InvalidOperationException("Cannot save changes with a Cache-Only Configuration Context");
|
||||||
|
|
||||||
var ci = ConfigurationItem(Database, Scope, Key);
|
var item = CacheGetItem(Database, Scope, Key);
|
||||||
if (ci == null && Value != null)
|
|
||||||
|
if (item == null && Value == null)
|
||||||
{
|
{
|
||||||
lock (configurationItemsLock)
|
// No Change - already null
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else if (item == null)
|
||||||
{
|
{
|
||||||
ci = ConfigurationItem(Database, Scope, Key);
|
// New Configuration Item
|
||||||
if (ci == null)
|
lock (configChangeLock)
|
||||||
|
{
|
||||||
|
// Check again for thread safety
|
||||||
|
item = CacheGetItem(Database, Scope, Key);
|
||||||
|
if (item == null)
|
||||||
{
|
{
|
||||||
// Create Configuration Item
|
// Create Configuration Item
|
||||||
ci = new ConfigurationItem() { Scope = Scope, Key = Key, Value = Value.ToString() };
|
var configItem = new ConfigurationItem() { Scope = Scope, Key = Key, Value = Value };
|
||||||
// Add Item to DB & Internal Collections
|
item = new ConfigurationCacheItemType(configItem, ObjectValue);
|
||||||
Database.ConfigurationItems.Add(ci);
|
|
||||||
ConfigurationItems(Database, Scope).Add(ci);
|
// Add Item to DB
|
||||||
ConfigurationDictionary(Database, Scope)[Scope].Add(Key, ci);
|
Database.ConfigurationItems.Add(configItem);
|
||||||
ci = null;
|
|
||||||
}
|
// Add Item to Cache
|
||||||
}
|
ConfigurationCacheScopeType scopeCache;
|
||||||
}
|
if (!cacheStore.TryGetValue(Scope, out scopeCache))
|
||||||
if (ci != null)
|
|
||||||
{
|
{
|
||||||
lock (configurationItemsLock)
|
scopeCache = new ConfigurationCacheScopeType();
|
||||||
|
cacheStore.TryAdd(Scope, scopeCache);
|
||||||
|
}
|
||||||
|
scopeCache.TryAdd(Key, item);
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item != null)
|
||||||
{
|
{
|
||||||
var entityInfo = Database.Entry(ci);
|
// Existing Configuration Item
|
||||||
|
lock (configChangeLock)
|
||||||
|
{
|
||||||
|
var configItem = item.Item1;
|
||||||
|
|
||||||
|
// Compare Values
|
||||||
|
if (item.Item1.Value == Value)
|
||||||
|
{
|
||||||
|
// No Change - Update Cache Reference Only
|
||||||
|
return SetItemTypeValue(item, ObjectValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var entityInfo = Database.Entry(configItem);
|
||||||
if (entityInfo.State == System.Data.EntityState.Detached)
|
if (entityInfo.State == System.Data.EntityState.Detached)
|
||||||
{
|
{
|
||||||
// Reload Scope from DB
|
// Reload Item from DB
|
||||||
LoadConfigurationItems(Database, Scope, true);
|
configItem = Database.ConfigurationItems.Where(i => i.Scope == Scope && i.Key == Key).First();
|
||||||
ci = ConfigurationItem(Database, Scope, Key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Value == null)
|
if (Value == null)
|
||||||
{
|
{
|
||||||
Database.ConfigurationItems.Remove(ci);
|
// Remove item from Database
|
||||||
configurationItems.Remove(ci);
|
Database.ConfigurationItems.Remove(configItem);
|
||||||
configDictionary[Scope].Remove(Key);
|
|
||||||
|
// Remove item from Cache
|
||||||
|
ConfigurationCacheScopeType scopeCache;
|
||||||
|
if (cacheStore.TryGetValue(Scope, out scopeCache))
|
||||||
|
{
|
||||||
|
scopeCache.TryRemove(Key, out item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ci.Value = Value.ToString();
|
// Update Database
|
||||||
}
|
configItem.Value = Value;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static List<ConfigurationItem> GetConfigurationItems(DiscoDataContext Database, string Scope)
|
// Update Cache
|
||||||
|
ConfigurationCacheScopeType scopeCache;
|
||||||
|
if (cacheStore.TryGetValue(Scope, out scopeCache))
|
||||||
{
|
{
|
||||||
return ConfigurationDictionary(Database, Scope)[Scope].Values.ToList();
|
scopeCache.TryRemove(Key, out item);
|
||||||
|
item = new ConfigurationCacheItemType(configItem, ObjectValue);
|
||||||
|
scopeCache.TryAdd(Key, item);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string ObsfucateValue(string Value)
|
return null;
|
||||||
|
}
|
||||||
|
private static ConfigurationCacheItemType SetItemTypeValue(ConfigurationCacheItemType ExistingItem, object Value)
|
||||||
|
{
|
||||||
|
var cache = ConfigurationCache.cacheStore;
|
||||||
|
|
||||||
|
ConfigurationCacheScopeType scopeCache;
|
||||||
|
if (cache.TryGetValue(ExistingItem.Item1.Scope, out scopeCache))
|
||||||
|
{
|
||||||
|
ConfigurationCacheItemType newItem = new ConfigurationCacheItemType(ExistingItem.Item1, Value);
|
||||||
|
scopeCache.TryUpdate(ExistingItem.Item1.Key, newItem, ExistingItem);
|
||||||
|
return newItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Helpers
|
||||||
|
private static bool IsConvertableFromString(Type t)
|
||||||
|
{
|
||||||
|
if (t == typeof(Boolean) ||
|
||||||
|
t == typeof(Char) ||
|
||||||
|
t == typeof(SByte) ||
|
||||||
|
t == typeof(Byte) ||
|
||||||
|
t == typeof(Int16) || t == typeof(UInt16) ||
|
||||||
|
t == typeof(Int32) || t == typeof(UInt32) ||
|
||||||
|
t == typeof(Int64) || t == typeof(UInt64) ||
|
||||||
|
t == typeof(Single) ||
|
||||||
|
t == typeof(Double) ||
|
||||||
|
t == typeof(Decimal) ||
|
||||||
|
t == typeof(DateTime) ||
|
||||||
|
t == typeof(String))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Cache Getters/Setters
|
||||||
|
internal static T GetValue<T>(DiscoDataContext Database, string Scope, string Key, T Default)
|
||||||
|
{
|
||||||
|
var item = CacheGetItem(Database, Scope, Key);
|
||||||
|
|
||||||
|
if (item == null)
|
||||||
|
return Default;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (item.Item2 != null && item.Item2.GetType() == typeof(T))
|
||||||
|
{
|
||||||
|
// Return Cached Item
|
||||||
|
return (T)item.Item2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Convert Serialized Item
|
||||||
|
Type itemType = typeof(T);
|
||||||
|
object itemValue;
|
||||||
|
|
||||||
|
if (itemType == typeof(string))
|
||||||
|
{
|
||||||
|
// string
|
||||||
|
itemValue = item.Item1.Value;
|
||||||
|
}
|
||||||
|
else if (itemType == typeof(object))
|
||||||
|
{
|
||||||
|
// object
|
||||||
|
itemValue = item.Item1.Value;
|
||||||
|
}
|
||||||
|
else if (IsConvertableFromString(itemType))
|
||||||
|
{
|
||||||
|
// IConvertable
|
||||||
|
itemValue = Convert.ChangeType(item.Item1.Value, itemType);
|
||||||
|
}
|
||||||
|
else if (itemType.BaseType != null && itemType.BaseType == typeof(Enum))
|
||||||
|
{
|
||||||
|
// Enum
|
||||||
|
itemValue = Enum.Parse(typeof(T), item.Item1.Value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// JSON Deserialize
|
||||||
|
itemValue = JsonConvert.DeserializeObject<T>(item.Item1.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Item in Cache
|
||||||
|
SetItemTypeValue(item, itemValue);
|
||||||
|
|
||||||
|
return (T)itemValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal static void SetValue<T>(DiscoDataContext Database, string Scope, string Key, T Value)
|
||||||
|
{
|
||||||
|
Type valueType = typeof(T);
|
||||||
|
string stringValue;
|
||||||
|
|
||||||
|
if (Value == null)
|
||||||
|
{
|
||||||
|
stringValue = null;
|
||||||
|
}
|
||||||
|
else if (valueType == typeof(object))
|
||||||
|
{
|
||||||
|
throw new ArgumentException(string.Format("Cannot serialize the configuration item [{0}].[{1}] which defines a type of [System.Object]", Scope, Key), "Value");
|
||||||
|
}
|
||||||
|
else if (IsConvertableFromString(valueType))
|
||||||
|
{
|
||||||
|
// string or supports IConvertable
|
||||||
|
stringValue = Value.ToString();
|
||||||
|
}
|
||||||
|
else if (valueType.BaseType != null && valueType.BaseType == typeof(Enum))
|
||||||
|
{
|
||||||
|
// Enum
|
||||||
|
stringValue = Value.ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// JSON Serialize
|
||||||
|
stringValue = JsonConvert.SerializeObject(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
CacheSetItem(Database, Scope, Key, stringValue, Value);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Cache Helpers
|
||||||
|
|
||||||
|
internal static IEnumerable<string> GetScopeKeys(DiscoDataContext Database, string Scope)
|
||||||
|
{
|
||||||
|
var cache = Cache(Database);
|
||||||
|
|
||||||
|
ConfigurationCacheScopeType scopeCache;
|
||||||
|
if (cache.TryGetValue(Scope, out scopeCache))
|
||||||
|
{
|
||||||
|
return scopeCache.Keys.ToList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Enumerable.Empty<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void RemoveScope(DiscoDataContext Database, string Scope)
|
||||||
|
{
|
||||||
|
if (Database == null)
|
||||||
|
throw new InvalidOperationException("Cannot save changes with a Cache-Only Configuration Context");
|
||||||
|
|
||||||
|
lock (configChangeLock)
|
||||||
|
{
|
||||||
|
// Remove item from Database
|
||||||
|
var items = Database.ConfigurationItems.Where(i => i.Scope == Scope).ToList();
|
||||||
|
items.ForEach(i => Database.ConfigurationItems.Remove(i));
|
||||||
|
|
||||||
|
// Remove item from Cache
|
||||||
|
if (cacheStore != null)
|
||||||
|
{
|
||||||
|
ConfigurationCacheScopeType scopeCache;
|
||||||
|
cacheStore.TryRemove(Scope, out scopeCache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void RemoveScopeKey(DiscoDataContext Database, string Scope, string Key)
|
||||||
|
{
|
||||||
|
if (Database == null)
|
||||||
|
throw new InvalidOperationException("Cannot save changes with a Cache-Only Configuration Context");
|
||||||
|
|
||||||
|
lock (configChangeLock)
|
||||||
|
{
|
||||||
|
var cacheItem = CacheGetItem(Database, Scope, Key);
|
||||||
|
ConfigurationItem configItem = null;
|
||||||
|
|
||||||
|
// Remove item from Database
|
||||||
|
if (cacheItem != null)
|
||||||
|
{
|
||||||
|
configItem = cacheItem.Item1;
|
||||||
|
|
||||||
|
var entityInfo = Database.Entry(configItem);
|
||||||
|
if (entityInfo.State == System.Data.EntityState.Detached)
|
||||||
|
{
|
||||||
|
// Reload Item from DB
|
||||||
|
configItem = Database.ConfigurationItems.Where(i => i.Scope == Scope && i.Key == Key).FirstOrDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (configItem == null)
|
||||||
|
{
|
||||||
|
// Load Item from DB
|
||||||
|
configItem = Database.ConfigurationItems.Where(i => i.Scope == Scope && i.Key == Key).FirstOrDefault();
|
||||||
|
}
|
||||||
|
if (configItem != null)
|
||||||
|
{
|
||||||
|
Database.ConfigurationItems.Remove(configItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove item from Cache
|
||||||
|
if (cacheItem != null)
|
||||||
|
{
|
||||||
|
ConfigurationCacheScopeType scopeCache;
|
||||||
|
if (cacheStore.TryGetValue(Scope, out scopeCache))
|
||||||
|
{
|
||||||
|
scopeCache.TryRemove(Key, out cacheItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Obsfucation Helpers
|
||||||
|
internal static string Obsfucate(this string Value)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(Value))
|
if (string.IsNullOrEmpty(Value))
|
||||||
return Value;
|
return Value;
|
||||||
else
|
else
|
||||||
return Convert.ToBase64String(Encoding.Unicode.GetBytes(Value));
|
return Convert.ToBase64String(Encoding.Unicode.GetBytes(Value));
|
||||||
}
|
}
|
||||||
internal static string DeobsfucateValue(string ObsfucatedValue)
|
internal static string Deobsfucate(this string ObsfucatedValue)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(ObsfucatedValue))
|
if (string.IsNullOrEmpty(ObsfucatedValue))
|
||||||
return ObsfucatedValue;
|
return ObsfucatedValue;
|
||||||
@@ -145,6 +386,5 @@ namespace Disco.Data.Configuration
|
|||||||
return Encoding.Unicode.GetString(Convert.FromBase64String(ObsfucatedValue));
|
return Encoding.Unicode.GetString(Convert.FromBase64String(ObsfucatedValue));
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using Disco.Data.Repository;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Disco.Data.Configuration.Modules
|
||||||
|
{
|
||||||
|
public class ActiveDirectoryConfiguration : ConfigurationBase
|
||||||
|
{
|
||||||
|
public ActiveDirectoryConfiguration(DiscoDataContext Database) : base(Database) { }
|
||||||
|
|
||||||
|
public override string Scope
|
||||||
|
{
|
||||||
|
get { return "ActiveDirectory"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, List<string>> SearchContainers
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Get<Dictionary<string, List<string>>>(null);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Set(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool? SearchAllForestServers
|
||||||
|
{
|
||||||
|
get { return Get<bool?>(null); }
|
||||||
|
set { Set(value); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
using Disco.Data.Repository;
|
using Disco.Data.Repository;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Disco.Data.Configuration.Modules
|
namespace Disco.Data.Configuration.Modules
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
// Removed 2012-06-14 G# - Properties moved to DeviceProfile model & DB Migrated in DBv3.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//using System;
|
|
||||||
//using System.Collections.Generic;
|
|
||||||
//using System.Linq;
|
|
||||||
//using System.Text;
|
|
||||||
//using Disco.Models.Repository;
|
|
||||||
|
|
||||||
//namespace Disco.Data.Configuration.Modules
|
|
||||||
//{
|
|
||||||
// public class DeviceProfileConfiguration : ConfigurationBase
|
|
||||||
// {
|
|
||||||
// private DeviceProfilesConfiguration deviceProfilesConfig;
|
|
||||||
// private DeviceProfile deviceProfile;
|
|
||||||
|
|
||||||
// public DeviceProfileConfiguration(ConfigurationContext Context, DeviceProfile DeviceProfile)
|
|
||||||
// : base(Context)
|
|
||||||
// {
|
|
||||||
// this.deviceProfilesConfig = Context.DeviceProfiles;
|
|
||||||
// this.deviceProfile = DeviceProfile;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override string Scope
|
|
||||||
// {
|
|
||||||
// get
|
|
||||||
// {
|
|
||||||
// return string.Format("DeviceProfile:{0}", this.deviceProfile.Id);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public string ComputerNameTemplate
|
|
||||||
// {
|
|
||||||
// get
|
|
||||||
// {
|
|
||||||
// return this.GetValue("ComputerNameTemplate", "DeviceProfile.ShortName + '-' + SerialNumber");
|
|
||||||
// }
|
|
||||||
// set
|
|
||||||
// {
|
|
||||||
// this.SetValue("ComputerNameTemplate", value);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public enum DeviceProfileDistributionTypes : int
|
|
||||||
// {
|
|
||||||
// OneToMany = 0,
|
|
||||||
// OneToOne = 1
|
|
||||||
// }
|
|
||||||
// public DeviceProfileDistributionTypes DistributionType
|
|
||||||
// {
|
|
||||||
// get
|
|
||||||
// {
|
|
||||||
// return (DeviceProfileDistributionTypes)this.GetValue("DistributionType", (int)DeviceProfileDistributionTypes.OneToMany);
|
|
||||||
// }
|
|
||||||
// set
|
|
||||||
// {
|
|
||||||
// this.SetValue("DistributionType", (int)value);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// public string OrganisationalUnit
|
|
||||||
// {
|
|
||||||
// get
|
|
||||||
// {
|
|
||||||
// return this.GetValue<string>("OrganisationalUnit", null);
|
|
||||||
// }
|
|
||||||
// set
|
|
||||||
// {
|
|
||||||
// this.SetValue("OrganisationalUnit", value);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// public bool AllocateWirelessCertificate
|
|
||||||
// {
|
|
||||||
// get
|
|
||||||
// {
|
|
||||||
// return this.GetValue("AllocateWirelessCertificate", false);
|
|
||||||
// }
|
|
||||||
// set
|
|
||||||
// {
|
|
||||||
// this.SetValue("AllocateWirelessCertificate", value);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
@@ -1,9 +1,5 @@
|
|||||||
using System;
|
using Disco.Data.Repository;
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
using Disco.Data.Repository;
|
|
||||||
|
|
||||||
namespace Disco.Data.Configuration.Modules
|
namespace Disco.Data.Configuration.Modules
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using Disco.Data.Repository;
|
||||||
|
using Disco.Models.Services.Devices.Exporting;
|
||||||
|
|
||||||
|
namespace Disco.Data.Configuration.Modules
|
||||||
|
{
|
||||||
|
public class DevicesConfiguration : ConfigurationBase
|
||||||
|
{
|
||||||
|
public DevicesConfiguration(DiscoDataContext Database) : base(Database) { }
|
||||||
|
|
||||||
|
public override string Scope { get { return "Devices"; } }
|
||||||
|
|
||||||
|
public DeviceExportOptions LastExportOptions
|
||||||
|
{
|
||||||
|
get { return this.Get<DeviceExportOptions>(DeviceExportOptions.DefaultOptions()); }
|
||||||
|
set { this.Set(value); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
using Disco.Data.Repository;
|
using Disco.Data.Repository;
|
||||||
|
using Disco.Models.BI.Job;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Disco.Data.Configuration.Modules
|
namespace Disco.Data.Configuration.Modules
|
||||||
{
|
{
|
||||||
@@ -27,5 +25,32 @@ namespace Disco.Data.Configuration.Modules
|
|||||||
Set(value);
|
Set(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of minutes since the last recorded action is performed on a job before it is considered 'Stale'
|
||||||
|
/// </summary>
|
||||||
|
public int StaleJobMinutesThreshold
|
||||||
|
{
|
||||||
|
get { return Get<int>(60 * 24 * 2); } // Default to 48 Hours (2 days)
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
throw new ArgumentOutOfRangeException("value", "The Stale Job Minutes Threshold cannot be less than zero");
|
||||||
|
|
||||||
|
Set(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocationModes LocationMode
|
||||||
|
{
|
||||||
|
get { return Get<LocationModes>(LocationModes.Unrestricted); }
|
||||||
|
set { Set(value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<string> LocationList
|
||||||
|
{
|
||||||
|
get { return Get<List<string>>(new List<string>()); }
|
||||||
|
set { Set(value); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +1,22 @@
|
|||||||
using System;
|
using Disco.Data.Repository;
|
||||||
|
using Disco.Models.BI.Config;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using Disco.Models.BI.Config;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Disco.Data.Repository;
|
|
||||||
|
|
||||||
namespace Disco.Data.Configuration.Modules
|
namespace Disco.Data.Configuration.Modules
|
||||||
{
|
{
|
||||||
public class OrganisationAddressesConfiguration : ConfigurationBase
|
public class OrganisationAddressesConfiguration : ConfigurationBase
|
||||||
{
|
{
|
||||||
|
private const string scope = "OrganisationAddresses";
|
||||||
|
|
||||||
public OrganisationAddressesConfiguration(DiscoDataContext Database) : base(Database) { }
|
public OrganisationAddressesConfiguration(DiscoDataContext Database) : base(Database) { }
|
||||||
|
|
||||||
public override string Scope { get { return "OrganisationAddresses"; } }
|
public override string Scope { get { return scope; } }
|
||||||
|
|
||||||
public OrganisationAddress GetAddress(int Id)
|
public OrganisationAddress GetAddress(int Id)
|
||||||
{
|
{
|
||||||
var address = default(OrganisationAddress);
|
return this.Get<OrganisationAddress>(null, Id.ToString());
|
||||||
var addressString = this.Get<string>(null, Id.ToString());
|
|
||||||
if (addressString != null)
|
|
||||||
{
|
|
||||||
if (addressString.StartsWith("{"))
|
|
||||||
{
|
|
||||||
// Assume Json
|
|
||||||
address = JsonConvert.DeserializeObject<OrganisationAddress>(addressString);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Assume Old Storage Method
|
|
||||||
address = OrganisationAddress.FromConfigurationEntry(Id, addressString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return address;
|
|
||||||
}
|
}
|
||||||
public OrganisationAddress SetAddress(OrganisationAddress Address)
|
public OrganisationAddress SetAddress(OrganisationAddress Address)
|
||||||
{
|
{
|
||||||
@@ -41,25 +25,21 @@ namespace Disco.Data.Configuration.Modules
|
|||||||
Address.Id = NextOrganisationAddressId;
|
Address.Id = NextOrganisationAddressId;
|
||||||
}
|
}
|
||||||
|
|
||||||
string addressString = JsonConvert.SerializeObject(Address);
|
this.Set(Address, Address.Id.ToString());
|
||||||
|
|
||||||
this.Set(addressString, Address.Id.ToString()); //Address.ToConfigurationEntry());
|
|
||||||
return Address;
|
return Address;
|
||||||
}
|
}
|
||||||
public void RemoveAddress(int Id)
|
public void RemoveAddress(int Id)
|
||||||
{
|
{
|
||||||
// Set Config Item to null = Remove Configuration Item
|
// Remove Configuration Item
|
||||||
this.Set<string>(null, Id.ToString());
|
this.RemoveItem(Id.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<OrganisationAddress> Addresses
|
public List<OrganisationAddress> Addresses
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return this.Items.Select(ca => ca.Value.StartsWith("{") ?
|
return this.ItemKeys.Select(key => this.Get<OrganisationAddress>(null, key)).ToList();
|
||||||
JsonConvert.DeserializeObject<OrganisationAddress>(ca.Value) :
|
|
||||||
OrganisationAddress.FromConfigurationEntry(int.Parse(ca.Key), ca.Value)
|
|
||||||
).ToList();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,5 +58,19 @@ namespace Disco.Data.Configuration.Modules
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void MigrateDatabase(DiscoDataContext Database)
|
||||||
|
{
|
||||||
|
// Migrate all organisation addresses to JSON
|
||||||
|
if (Database.ConfigurationItems.Count(i => i.Scope == scope && !i.Value.StartsWith("{")) > 0)
|
||||||
|
{
|
||||||
|
var items = Database.ConfigurationItems.Where(i => i.Scope == scope && !i.Value.StartsWith("{")).ToList();
|
||||||
|
items.ForEach(i =>
|
||||||
|
{
|
||||||
|
i.Value = JsonConvert.SerializeObject(OrganisationAddress.FromConfigurationEntry(int.Parse(i.Key), i.Value));
|
||||||
|
});
|
||||||
|
Database.SaveChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,7 @@
|
|||||||
using System;
|
using Disco.Data.Repository;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Disco.Data.Repository;
|
|
||||||
using Disco.Models.Repository;
|
|
||||||
using System.IO;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using Disco.Models.BI.Interop.Community;
|
using Disco.Models.BI.Interop.Community;
|
||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace Disco.Data.Configuration
|
namespace Disco.Data.Configuration
|
||||||
{
|
{
|
||||||
@@ -21,6 +15,8 @@ namespace Disco.Data.Configuration
|
|||||||
this.moduleDeviceProfilesConfiguration = new Lazy<Modules.DeviceProfilesConfiguration>(() => new Modules.DeviceProfilesConfiguration(Database));
|
this.moduleDeviceProfilesConfiguration = new Lazy<Modules.DeviceProfilesConfiguration>(() => new Modules.DeviceProfilesConfiguration(Database));
|
||||||
this.moduleOrganisationAddressesConfiguration = new Lazy<Modules.OrganisationAddressesConfiguration>(() => new Modules.OrganisationAddressesConfiguration(Database));
|
this.moduleOrganisationAddressesConfiguration = new Lazy<Modules.OrganisationAddressesConfiguration>(() => new Modules.OrganisationAddressesConfiguration(Database));
|
||||||
this.moduleJobPreferencesConfiguration = new Lazy<Modules.JobPreferencesConfiguration>(() => new Modules.JobPreferencesConfiguration(Database));
|
this.moduleJobPreferencesConfiguration = new Lazy<Modules.JobPreferencesConfiguration>(() => new Modules.JobPreferencesConfiguration(Database));
|
||||||
|
this.moduleActiveDirectoryConfiguration = new Lazy<Modules.ActiveDirectoryConfiguration>(() => new Modules.ActiveDirectoryConfiguration(Database));
|
||||||
|
this.moduleDevicesConfiguration = new Lazy<Modules.DevicesConfiguration>(() => new Modules.DevicesConfiguration(Database));
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Configuration Modules
|
#region Configuration Modules
|
||||||
@@ -29,6 +25,8 @@ namespace Disco.Data.Configuration
|
|||||||
private Lazy<Modules.DeviceProfilesConfiguration> moduleDeviceProfilesConfiguration;
|
private Lazy<Modules.DeviceProfilesConfiguration> moduleDeviceProfilesConfiguration;
|
||||||
private Lazy<Modules.OrganisationAddressesConfiguration> moduleOrganisationAddressesConfiguration;
|
private Lazy<Modules.OrganisationAddressesConfiguration> moduleOrganisationAddressesConfiguration;
|
||||||
private Lazy<Modules.JobPreferencesConfiguration> moduleJobPreferencesConfiguration;
|
private Lazy<Modules.JobPreferencesConfiguration> moduleJobPreferencesConfiguration;
|
||||||
|
private Lazy<Modules.ActiveDirectoryConfiguration> moduleActiveDirectoryConfiguration;
|
||||||
|
private Lazy<Modules.DevicesConfiguration> moduleDevicesConfiguration;
|
||||||
|
|
||||||
public Modules.BootstrapperConfiguration Bootstrapper
|
public Modules.BootstrapperConfiguration Bootstrapper
|
||||||
{
|
{
|
||||||
@@ -58,6 +56,20 @@ namespace Disco.Data.Configuration
|
|||||||
return moduleJobPreferencesConfiguration.Value;
|
return moduleJobPreferencesConfiguration.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public Modules.ActiveDirectoryConfiguration ActiveDirectory
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return moduleActiveDirectoryConfiguration.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Modules.DevicesConfiguration Devices
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return moduleDevicesConfiguration.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -94,6 +106,18 @@ namespace Disco.Data.Configuration
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string Administrators
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.Get<string>("Domain Admins,Disco Admins");
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Set(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#region Plugin Locations
|
#region Plugin Locations
|
||||||
public string PluginsLocation
|
public string PluginsLocation
|
||||||
{
|
{
|
||||||
@@ -249,11 +273,11 @@ namespace Disco.Data.Configuration
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return this.GetFromJson<UpdateResponse>(null);
|
return this.Get<UpdateResponse>(null);
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
this.SetAsJson(value);
|
this.Set(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public bool UpdateBetaDeployment
|
public bool UpdateBetaDeployment
|
||||||
|
|||||||
@@ -40,26 +40,30 @@
|
|||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll</HintPath>
|
<HintPath>..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="Newtonsoft.Json">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<HintPath>..\packages\Newtonsoft.Json.6.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
|
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Data.Entity" />
|
<Reference Include="System.Data.Entity" />
|
||||||
|
<Reference Include="System.DirectoryServices" />
|
||||||
<Reference Include="System.Drawing" />
|
<Reference Include="System.Drawing" />
|
||||||
<Reference Include="System.Reactive.Core">
|
<Reference Include="System.Reactive.Core, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Rx-Core.2.1.30214.0\lib\Net45\System.Reactive.Core.dll</HintPath>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\packages\Rx-Core.2.2.4\lib\net45\System.Reactive.Core.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Reactive.Interfaces">
|
<Reference Include="System.Reactive.Interfaces, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Rx-Interfaces.2.1.30214.0\lib\Net45\System.Reactive.Interfaces.dll</HintPath>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\packages\Rx-Interfaces.2.2.4\lib\net45\System.Reactive.Interfaces.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Reactive.Linq">
|
<Reference Include="System.Reactive.Linq, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Rx-Linq.2.1.30214.0\lib\Net45\System.Reactive.Linq.dll</HintPath>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\packages\Rx-Linq.2.2.4\lib\net45\System.Reactive.Linq.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Reactive.PlatformServices">
|
<Reference Include="System.Reactive.PlatformServices, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Rx-PlatformServices.2.1.30214.0\lib\Net45\System.Reactive.PlatformServices.dll</HintPath>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\packages\Rx-PlatformServices.2.2.4\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Web" />
|
<Reference Include="System.Web" />
|
||||||
<Reference Include="System.Xml.Linq" />
|
<Reference Include="System.Xml.Linq" />
|
||||||
@@ -72,10 +76,11 @@
|
|||||||
<Compile Include="Configuration\CommunityHelpers.cs" />
|
<Compile Include="Configuration\CommunityHelpers.cs" />
|
||||||
<Compile Include="Configuration\ConfigurationBase.cs" />
|
<Compile Include="Configuration\ConfigurationBase.cs" />
|
||||||
<Compile Include="Configuration\ConfigurationCache.cs" />
|
<Compile Include="Configuration\ConfigurationCache.cs" />
|
||||||
|
<Compile Include="Configuration\Modules\ActiveDirectoryConfiguration.cs" />
|
||||||
|
<Compile Include="Configuration\Modules\DevicesConfiguration.cs" />
|
||||||
<Compile Include="Configuration\Modules\JobPreferencesConfiguration.cs" />
|
<Compile Include="Configuration\Modules\JobPreferencesConfiguration.cs" />
|
||||||
<Compile Include="Configuration\SystemConfiguration.cs" />
|
<Compile Include="Configuration\SystemConfiguration.cs" />
|
||||||
<Compile Include="Configuration\Modules\BootstrapperConfiguration.cs" />
|
<Compile Include="Configuration\Modules\BootstrapperConfiguration.cs" />
|
||||||
<Compile Include="Configuration\Modules\DeviceProfileConfiguration.cs" />
|
|
||||||
<Compile Include="Configuration\Modules\DeviceProfilesConfiguration.cs" />
|
<Compile Include="Configuration\Modules\DeviceProfilesConfiguration.cs" />
|
||||||
<Compile Include="Configuration\Modules\OrganisationAddressesConfiguration.cs" />
|
<Compile Include="Configuration\Modules\OrganisationAddressesConfiguration.cs" />
|
||||||
<Compile Include="Migrations\201204250418485_DBv0.cs" />
|
<Compile Include="Migrations\201204250418485_DBv0.cs" />
|
||||||
@@ -126,6 +131,18 @@
|
|||||||
<Compile Include="Migrations\201310282325491_DBv11.Designer.cs">
|
<Compile Include="Migrations\201310282325491_DBv11.Designer.cs">
|
||||||
<DependentUpon>201310282325491_DBv11.cs</DependentUpon>
|
<DependentUpon>201310282325491_DBv11.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Migrations\201402032322432_DBv12.cs" />
|
||||||
|
<Compile Include="Migrations\201402032322432_DBv12.Designer.cs">
|
||||||
|
<DependentUpon>201402032322432_DBv12.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Migrations\201404080227546_DBv13.cs" />
|
||||||
|
<Compile Include="Migrations\201404080227546_DBv13.Designer.cs">
|
||||||
|
<DependentUpon>201404080227546_DBv13.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Migrations\201406160912525_DBv14.cs" />
|
||||||
|
<Compile Include="Migrations\201406160912525_DBv14.Designer.cs">
|
||||||
|
<DependentUpon>201406160912525_DBv14.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Migrations\Configuration.cs" />
|
<Compile Include="Migrations\Configuration.cs" />
|
||||||
<Compile Include="Migrations\DiscoDataMigrator.cs" />
|
<Compile Include="Migrations\DiscoDataMigrator.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
@@ -174,6 +191,15 @@
|
|||||||
<EmbeddedResource Include="Migrations\201310282325491_DBv11.resx">
|
<EmbeddedResource Include="Migrations\201310282325491_DBv11.resx">
|
||||||
<DependentUpon>201310282325491_DBv11.cs</DependentUpon>
|
<DependentUpon>201310282325491_DBv11.cs</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Migrations\201402032322432_DBv12.resx">
|
||||||
|
<DependentUpon>201402032322432_DBv12.cs</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Migrations\201404080227546_DBv13.resx">
|
||||||
|
<DependentUpon>201404080227546_DBv13.cs</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Migrations\201406160912525_DBv14.resx">
|
||||||
|
<DependentUpon>201406160912525_DBv14.cs</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Include="Properties\Resources.resx">
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
<Generator>ResXFileCodeGenerator</Generator>
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
@@ -187,7 +213,7 @@
|
|||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<ProjectExtensions>
|
<ProjectExtensions>
|
||||||
<VisualStudio>
|
<VisualStudio>
|
||||||
<UserProperties BuildVersion_BuildAction="Both" BuildVersion_UseGlobalSettings="False" BuildVersion_DetectChanges="False" BuildVersion_StartDate="2011/7/1" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" />
|
<UserProperties BuildVersion_UpdateFileVersion="True" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_StartDate="2014/6/1" BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildAction="Both" />
|
||||||
</VisualStudio>
|
</VisualStudio>
|
||||||
</ProjectExtensions>
|
</ProjectExtensions>
|
||||||
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
|
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
namespace Disco.Data.Migrations
|
||||||
|
{
|
||||||
|
using System.Data.Entity.Migrations;
|
||||||
|
using System.Data.Entity.Migrations.Infrastructure;
|
||||||
|
using System.Resources;
|
||||||
|
|
||||||
|
public sealed partial class DBv12 : IMigrationMetadata
|
||||||
|
{
|
||||||
|
private readonly ResourceManager Resources = new ResourceManager(typeof(DBv12));
|
||||||
|
|
||||||
|
string IMigrationMetadata.Id
|
||||||
|
{
|
||||||
|
get { return "201402032322432_DBv12"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
string IMigrationMetadata.Source
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
string IMigrationMetadata.Target
|
||||||
|
{
|
||||||
|
get { return Resources.GetString("Target"); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
namespace Disco.Data.Migrations
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Data.Entity.Migrations;
|
||||||
|
|
||||||
|
public partial class DBv12 : DbMigration
|
||||||
|
{
|
||||||
|
public override void Up()
|
||||||
|
{
|
||||||
|
CreateTable(
|
||||||
|
"dbo.JobQueueJobs",
|
||||||
|
c => new
|
||||||
|
{
|
||||||
|
Id = c.Int(nullable: false, identity: true),
|
||||||
|
JobQueueId = c.Int(nullable: false),
|
||||||
|
JobId = c.Int(nullable: false),
|
||||||
|
AddedDate = c.DateTime(nullable: false),
|
||||||
|
AddedUserId = c.String(nullable: false, maxLength: 50),
|
||||||
|
AddedComment = c.String(),
|
||||||
|
RemovedDate = c.DateTime(),
|
||||||
|
RemovedUserId = c.String(maxLength: 50),
|
||||||
|
RemovedComment = c.String(),
|
||||||
|
SLAExpiresDate = c.DateTime(),
|
||||||
|
Priority = c.Byte(nullable: false),
|
||||||
|
})
|
||||||
|
.PrimaryKey(t => t.Id)
|
||||||
|
.ForeignKey("dbo.JobQueues", t => t.JobQueueId)
|
||||||
|
.ForeignKey("dbo.Jobs", t => t.JobId)
|
||||||
|
.ForeignKey("dbo.Users", t => t.AddedUserId)
|
||||||
|
.ForeignKey("dbo.Users", t => t.RemovedUserId)
|
||||||
|
.Index(t => t.JobQueueId)
|
||||||
|
.Index(t => t.JobId)
|
||||||
|
.Index(t => t.AddedUserId)
|
||||||
|
.Index(t => t.RemovedUserId);
|
||||||
|
|
||||||
|
CreateTable(
|
||||||
|
"dbo.JobQueues",
|
||||||
|
c => new
|
||||||
|
{
|
||||||
|
Id = c.Int(nullable: false, identity: true),
|
||||||
|
Name = c.String(nullable: false, maxLength: 100),
|
||||||
|
Description = c.String(maxLength: 500),
|
||||||
|
Icon = c.String(nullable: false, maxLength: 25),
|
||||||
|
IconColour = c.String(nullable: false, maxLength: 10),
|
||||||
|
DefaultSLAExpiry = c.Int(),
|
||||||
|
Priority = c.Byte(nullable: false),
|
||||||
|
SubjectIds = c.String(),
|
||||||
|
})
|
||||||
|
.PrimaryKey(t => t.Id);
|
||||||
|
|
||||||
|
CreateTable(
|
||||||
|
"dbo.JobQueues_JobSubTypes",
|
||||||
|
c => new
|
||||||
|
{
|
||||||
|
JobQueue_Id = c.Int(nullable: false),
|
||||||
|
JobSubType_Id = c.String(nullable: false, maxLength: 20),
|
||||||
|
JobSubType_JobTypeId = c.String(nullable: false, maxLength: 5),
|
||||||
|
})
|
||||||
|
.PrimaryKey(t => new { t.JobQueue_Id, t.JobSubType_Id, t.JobSubType_JobTypeId })
|
||||||
|
.ForeignKey("dbo.JobQueues", t => t.JobQueue_Id, cascadeDelete: true)
|
||||||
|
.ForeignKey("dbo.JobSubTypes", t => new { t.JobSubType_Id, t.JobSubType_JobTypeId }, cascadeDelete: true)
|
||||||
|
.Index(t => t.JobQueue_Id)
|
||||||
|
.Index(t => new { t.JobSubType_Id, t.JobSubType_JobTypeId });
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Down()
|
||||||
|
{
|
||||||
|
DropIndex("dbo.JobQueues_JobSubTypes", new[] { "JobSubType_Id", "JobSubType_JobTypeId" });
|
||||||
|
DropIndex("dbo.JobQueues_JobSubTypes", new[] { "JobQueue_Id" });
|
||||||
|
DropIndex("dbo.JobQueueJobs", new[] { "RemovedUserId" });
|
||||||
|
DropIndex("dbo.JobQueueJobs", new[] { "AddedUserId" });
|
||||||
|
DropIndex("dbo.JobQueueJobs", new[] { "JobId" });
|
||||||
|
DropIndex("dbo.JobQueueJobs", new[] { "JobQueueId" });
|
||||||
|
DropForeignKey("dbo.JobQueues_JobSubTypes", new[] { "JobSubType_Id", "JobSubType_JobTypeId" }, "dbo.JobSubTypes");
|
||||||
|
DropForeignKey("dbo.JobQueues_JobSubTypes", "JobQueue_Id", "dbo.JobQueues");
|
||||||
|
DropForeignKey("dbo.JobQueueJobs", "RemovedUserId", "dbo.Users");
|
||||||
|
DropForeignKey("dbo.JobQueueJobs", "AddedUserId", "dbo.Users");
|
||||||
|
DropForeignKey("dbo.JobQueueJobs", "JobId", "dbo.Jobs");
|
||||||
|
DropForeignKey("dbo.JobQueueJobs", "JobQueueId", "dbo.JobQueues");
|
||||||
|
DropTable("dbo.JobQueues_JobSubTypes");
|
||||||
|
DropTable("dbo.JobQueues");
|
||||||
|
DropTable("dbo.JobQueueJobs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,27 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
namespace Disco.Data.Migrations
|
||||||
|
{
|
||||||
|
using System.Data.Entity.Migrations;
|
||||||
|
using System.Data.Entity.Migrations.Infrastructure;
|
||||||
|
using System.Resources;
|
||||||
|
|
||||||
|
public sealed partial class DBv13 : IMigrationMetadata
|
||||||
|
{
|
||||||
|
private readonly ResourceManager Resources = new ResourceManager(typeof(DBv13));
|
||||||
|
|
||||||
|
string IMigrationMetadata.Id
|
||||||
|
{
|
||||||
|
get { return "201404080227546_DBv13"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
string IMigrationMetadata.Source
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
string IMigrationMetadata.Target
|
||||||
|
{
|
||||||
|
get { return Resources.GetString("Target"); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
namespace Disco.Data.Migrations
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Data.Entity.Migrations;
|
||||||
|
|
||||||
|
public partial class DBv13 : DbMigration
|
||||||
|
{
|
||||||
|
public override void Up()
|
||||||
|
{
|
||||||
|
AlterColumn("dbo.Devices", "ComputerName", c => c.String(maxLength: 50));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Down()
|
||||||
|
{
|
||||||
|
AlterColumn("dbo.Devices", "ComputerName", c => c.String(maxLength: 24));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user