Certificate/wireless plugins; major refactoring
Migrate much of BI to Services. Added Wireless Profile Provider plugin feature. Added Certificate Authority Provider plugin feature. Modified Certificate Provider plugin feature. Database migration v17, for Device Profiles. Enrolment Client Updated to support CA Certificates, Wireless Profiles and Hardware Info. New Client Enrolment Protocol to support new features. Plugin Manifest Generator added to main solution. Improved AD search performance.
This commit is contained in:
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Data.Repository;
|
||||
|
||||
namespace Disco.BI.DeviceBI
|
||||
{
|
||||
public static class BatchUtilities
|
||||
{
|
||||
public static DeviceBatch DefaultNewDeviceBatch(DiscoDataContext Database)
|
||||
{
|
||||
return new DeviceBatch()
|
||||
{
|
||||
PurchaseDate = DateTime.Today
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Entity;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
|
||||
namespace Disco.BI
|
||||
{
|
||||
public static class DeviceModelBI
|
||||
{
|
||||
|
||||
// Added: 2013-02-07 G#
|
||||
// Ensure Duplicate Device Models are not created by creating only one Device Model at a time
|
||||
// http://www.discoict.com.au/forum/support/2013/2/duplicate-device-models.aspx
|
||||
// Thanks to Michael Vorster for reporting this problem.
|
||||
private static object _CreateDeviceModelLock = new object();
|
||||
public static Tuple<DeviceModel, bool> GetOrCreateDeviceModel(this DbSet<DeviceModel> DeviceModelsSet, string Manufacturer, string Model, string ModelType)
|
||||
{
|
||||
// Already Exists?
|
||||
var deviceModel = DeviceModelsSet.FirstOrDefault(dm => dm.Manufacturer == Manufacturer && dm.Model == Model);
|
||||
if (deviceModel == null)
|
||||
{
|
||||
// Ensure only one thread/request at a time
|
||||
lock (_CreateDeviceModelLock)
|
||||
{
|
||||
// Check again now that lock is enforced
|
||||
deviceModel = DeviceModelsSet.FirstOrDefault(dm => dm.Manufacturer == Manufacturer && dm.Model == Model);
|
||||
|
||||
if (deviceModel == null)
|
||||
{
|
||||
// Create the Device Model in a different DataContext so we don't have to commit unrelated changes
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
var addDeviceModel = new DeviceModel
|
||||
{
|
||||
Manufacturer = Manufacturer,
|
||||
Model = Model,
|
||||
ModelType = ModelType,
|
||||
Description = string.Format("{0} {1}", Manufacturer, Model)
|
||||
};
|
||||
database.DeviceModels.Add(addDeviceModel);
|
||||
database.SaveChanges();
|
||||
}
|
||||
|
||||
// Obtain the Device Model with the in-scope DataContext
|
||||
// - Overhead acknowledged, but reasonable given the infrequency of occurrence
|
||||
deviceModel = DeviceModelsSet.FirstOrDefault(dm => dm.Manufacturer == Manufacturer && dm.Model == Model);
|
||||
return new Tuple<DeviceModel, bool>(deviceModel, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (deviceModel.ModelType != ModelType)
|
||||
deviceModel.ModelType = ModelType;
|
||||
}
|
||||
|
||||
return new Tuple<DeviceModel,bool>(deviceModel, false);
|
||||
}
|
||||
// Added: 2013-02-07 G#
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,820 +0,0 @@
|
||||
using Disco.BI.Extensions;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.ClientServices;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Users;
|
||||
using Exceptionless;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Renci.SshNet;
|
||||
using PList;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Disco.BI.DeviceBI
|
||||
{
|
||||
public class DeviceEnrol
|
||||
{
|
||||
public enum EnrolmentTypes
|
||||
{
|
||||
Normal,
|
||||
Mac = 5,
|
||||
MacSecure,
|
||||
Register = 30
|
||||
}
|
||||
|
||||
public static MacSecureEnrolResponse MacSecureEnrol(DiscoDataContext Database, string Host)
|
||||
{
|
||||
MacEnrol trustedRequest = new MacEnrol();
|
||||
string sessionId = System.Guid.NewGuid().ToString("B");
|
||||
MacSecureEnrolResponse MacSecureEnrol;
|
||||
try
|
||||
{
|
||||
EnrolmentLog.LogSessionStarting(sessionId, Host, EnrolmentTypes.MacSecure);
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 0, $"Connecting to '{Host}' as '{Database.DiscoConfiguration.Bootstrapper.MacSshUsername}'");
|
||||
|
||||
var sshConnectionInfo = new KeyboardInteractiveConnectionInfo(Host, Database.DiscoConfiguration.Bootstrapper.MacSshUsername);
|
||||
sshConnectionInfo.AuthenticationPrompt += (sender, e) =>
|
||||
{
|
||||
foreach (var prompt in e.Prompts)
|
||||
{
|
||||
if (prompt.Request.StartsWith("Password", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 10, $"Authenticating at '{Host}' as '{Database.DiscoConfiguration.Bootstrapper.MacSshUsername}'");
|
||||
prompt.Response = Database.DiscoConfiguration.Bootstrapper.MacSshPassword;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using (var sshClient = new SshClient(sshConnectionInfo))
|
||||
{
|
||||
sshClient.Connect();
|
||||
|
||||
try
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 30, "Retrieving System Profile Information");
|
||||
var sshResult = sshClient.RunCommand("system_profiler -xml SPHardwareDataType SPNetworkDataType SPSoftwareDataType");
|
||||
PListRoot profilerData;
|
||||
using (var reader = new StringReader(sshResult.Result))
|
||||
{
|
||||
using (var xmlReader = XmlReader.Create(reader, new XmlReaderSettings() { DtdProcessing = DtdProcessing.Ignore }))
|
||||
{
|
||||
XmlSerializer serializer = new XmlSerializer(typeof(PListRoot));
|
||||
profilerData = (PListRoot)serializer.Deserialize(xmlReader);
|
||||
}
|
||||
}
|
||||
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 90, "Processing System Profile Information");
|
||||
|
||||
PListDict profilerDataHardware = null;
|
||||
PListArray profilerDataNetwork = null;
|
||||
PListDict profilerDataSoftware = null;
|
||||
|
||||
foreach (PListDict node in (profilerData.Root as PListArray))
|
||||
{
|
||||
var nodeItems = ((PListArray)node["_items"]);
|
||||
|
||||
switch (((PListString)node["_dataType"]).Value)
|
||||
{
|
||||
case "SPHardwareDataType":
|
||||
profilerDataHardware = (PListDict)nodeItems[0];
|
||||
break;
|
||||
case "SPNetworkDataType":
|
||||
profilerDataNetwork = nodeItems;
|
||||
break;
|
||||
case "SPSoftwareDataType":
|
||||
profilerDataSoftware = (PListDict)nodeItems[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (profilerDataHardware == null || profilerDataNetwork == null || profilerDataSoftware == null)
|
||||
throw new InvalidOperationException("System Profiler didn't return information for a requested data type");
|
||||
|
||||
trustedRequest.DeviceSerialNumber = (profilerDataHardware["serial_number"] as PListString).Value;
|
||||
trustedRequest.DeviceUUID = (profilerDataHardware["platform_UUID"] as PListString).Value;
|
||||
trustedRequest.DeviceComputerName = (profilerDataSoftware["local_host_name"] as PListString).Value;
|
||||
|
||||
var profilerDataNetworkEthernet = profilerDataNetwork.Cast<PListDict>().FirstOrDefault(e => ((PListString)e["_name"]).Value == "Ethernet");
|
||||
if (profilerDataNetworkEthernet != null)
|
||||
{
|
||||
trustedRequest.DeviceLanMacAddress = ((PListString)(profilerDataNetworkEthernet["Ethernet"] as PListDict)["MAC Address"]).Value;
|
||||
}
|
||||
|
||||
var profilerDataNetworkWiFi = profilerDataNetwork.Cast<PListDict>().FirstOrDefault(e => ((PListString)e["_name"]).Value == "Wi-Fi");
|
||||
if (profilerDataNetworkWiFi != null)
|
||||
{
|
||||
trustedRequest.DeviceWlanMacAddress = ((PListString)(profilerDataNetworkWiFi["Ethernet"] as PListDict)["MAC Address"]).Value;
|
||||
}
|
||||
|
||||
trustedRequest.DeviceManufacturer = "Apple Inc.";
|
||||
trustedRequest.DeviceModel = (profilerDataHardware["machine_model"] as PListString).Value;
|
||||
|
||||
trustedRequest.DeviceModelType = ParseMacModelType((profilerDataHardware["machine_name"] as PListString).Value);
|
||||
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 99, "Disconnecting");
|
||||
|
||||
sshClient.Disconnect();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (sshClient != null)
|
||||
{
|
||||
bool connected = sshClient.IsConnected;
|
||||
if (connected)
|
||||
{
|
||||
sshClient.Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 100, "Disconnected, Starting Disco Enrolment");
|
||||
MacSecureEnrolResponse response = MacSecureEnrolResponse.FromMacEnrolResponse(MacEnrol(Database, trustedRequest, true, sessionId));
|
||||
EnrolmentLog.LogSessionFinished(sessionId);
|
||||
MacSecureEnrol = response;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
ex.ToExceptionless().Submit();
|
||||
EnrolmentLog.LogSessionError(sessionId, ex);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
return MacSecureEnrol;
|
||||
}
|
||||
|
||||
#region "Mac Enrol Helpers"
|
||||
|
||||
private static string ParseMacModelType(string ModelName)
|
||||
{
|
||||
string ParseMacModelType;
|
||||
if (!string.IsNullOrWhiteSpace(ModelName))
|
||||
{
|
||||
string mn = ModelName.ToLower();
|
||||
if (mn.Contains("imac") || mn.Contains("mini"))
|
||||
{
|
||||
ParseMacModelType = "Desktop";
|
||||
return ParseMacModelType;
|
||||
}
|
||||
if (mn.Contains("macbook"))
|
||||
{
|
||||
ParseMacModelType = "Mobile";
|
||||
return ParseMacModelType;
|
||||
}
|
||||
if (mn.Contains("xserve"))
|
||||
{
|
||||
ParseMacModelType = "Server";
|
||||
return ParseMacModelType;
|
||||
}
|
||||
}
|
||||
ParseMacModelType = "Unknown";
|
||||
return ParseMacModelType;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static MacEnrolResponse MacEnrol(DiscoDataContext Database, MacEnrol Request, bool Trusted, string OpenSessionId = null)
|
||||
{
|
||||
string sessionId;
|
||||
if (OpenSessionId == null)
|
||||
{
|
||||
sessionId = System.Guid.NewGuid().ToString("B");
|
||||
EnrolmentLog.LogSessionStarting(sessionId, Request.DeviceSerialNumber, EnrolmentTypes.Mac);
|
||||
}
|
||||
else
|
||||
{
|
||||
sessionId = OpenSessionId;
|
||||
}
|
||||
EnrolmentLog.LogSessionDeviceInfo(sessionId, Request);
|
||||
MacEnrolResponse response = new MacEnrolResponse();
|
||||
try
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 10, "Querying Database");
|
||||
Device RepoDevice = Database.Devices.Include("AssignedUser").Include("DeviceProfile").Include("DeviceProfile").Where(d => d.SerialNumber == Request.DeviceSerialNumber).FirstOrDefault();
|
||||
if (!Trusted)
|
||||
{
|
||||
if (RepoDevice == null)
|
||||
throw new EnrolSafeException(string.Format("Unknown Device Serial Number (SN: '{0}')", Request.DeviceSerialNumber));
|
||||
if (!RepoDevice.AllowUnauthenticatedEnrol)
|
||||
throw new EnrolSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.DeviceSerialNumber));
|
||||
}
|
||||
if (RepoDevice == null)
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 50, "New Device, Building Disco Instance");
|
||||
EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.DeviceSerialNumber);
|
||||
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
|
||||
|
||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
|
||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||
if (deviceModelResult.Item2)
|
||||
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
||||
else
|
||||
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id);
|
||||
|
||||
RepoDevice = new Device
|
||||
{
|
||||
SerialNumber = Request.DeviceSerialNumber,
|
||||
DeviceDomainId = Request.DeviceComputerName,
|
||||
DeviceProfile = deviceProfile,
|
||||
DeviceModel = deviceModel,
|
||||
AllowUnauthenticatedEnrol = false,
|
||||
CreatedDate = DateTime.Now,
|
||||
EnrolledDate = DateTime.Now
|
||||
};
|
||||
Database.Devices.Add(RepoDevice);
|
||||
}
|
||||
else
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 50, "Existing Device, Updating Disco Instance");
|
||||
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
|
||||
|
||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
|
||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||
if (deviceModelResult.Item2)
|
||||
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
||||
else
|
||||
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id);
|
||||
|
||||
RepoDevice.DeviceModel = deviceModel;
|
||||
|
||||
RepoDevice.DeviceDomainId = Request.DeviceComputerName;
|
||||
if (!RepoDevice.EnrolledDate.HasValue)
|
||||
{
|
||||
RepoDevice.EnrolledDate = DateTime.Now;
|
||||
}
|
||||
}
|
||||
RepoDevice.LastEnrolDate = DateTime.Now;
|
||||
RepoDevice.AllowUnauthenticatedEnrol = false;
|
||||
// Removed 2012-06-14 G# - Properties moved to DeviceProfile model & DB Migrated in DBv3.
|
||||
//DeviceProfileConfiguration RepoDeviceProfileContext = RepoDevice.DeviceProfile.Configuration(Context);
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 90, "Building Response");
|
||||
//if (RepoDeviceProfileContext.DistributionType == DeviceProfileConfiguration.DeviceProfileDistributionTypes.OneToOne && RepoDevice.AssignedUser != null)
|
||||
if (RepoDevice.DeviceProfile.DistributionType == DeviceProfile.DistributionTypes.OneToOne && RepoDevice.AssignedUser != null)
|
||||
{
|
||||
ADUserAccount AssignedUserInfo = ActiveDirectory.RetrieveADUserAccount(RepoDevice.AssignedUser.UserId);
|
||||
EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.SamAccountName, AssignedUserInfo.Domain.NetBiosName, AssignedUserInfo.SecurityIdentifier.ToString());
|
||||
response.DeviceAssignedUserUsername = AssignedUserInfo.SamAccountName;
|
||||
response.DeviceAssignedUserDomain = AssignedUserInfo.Domain.NetBiosName;
|
||||
response.DeviceAssignedUserName = AssignedUserInfo.DisplayName;
|
||||
response.DeviceAssignedUserSID = AssignedUserInfo.SecurityIdentifier.ToString();
|
||||
}
|
||||
response.DeviceComputerName = RepoDevice.DeviceDomainId;
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 100, "Completed Successfully");
|
||||
}
|
||||
catch (EnrolSafeException ex)
|
||||
{
|
||||
EnrolmentLog.LogSessionError(sessionId, ex);
|
||||
return new MacEnrolResponse { ErrorMessage = ex.Message };
|
||||
}
|
||||
catch (System.Exception ex2)
|
||||
{
|
||||
ex2.ToExceptionless().Submit();
|
||||
EnrolmentLog.LogSessionError(sessionId, ex2);
|
||||
throw ex2;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (OpenSessionId == null)
|
||||
EnrolmentLog.LogSessionFinished(sessionId);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
public static EnrolResponse Enrol(DiscoDataContext Database, string Username, Models.ClientServices.Enrol Request)
|
||||
{
|
||||
ADMachineAccount adMachineAccount = null;
|
||||
|
||||
EnrolResponse response = new EnrolResponse();
|
||||
|
||||
AuthorizationToken authenticatedToken = null;
|
||||
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");
|
||||
response.SessionId = sessionId;
|
||||
|
||||
EnrolmentLog.LogSessionStarting(sessionId, Request.DeviceSerialNumber, EnrolmentTypes.Normal);
|
||||
EnrolmentLog.LogSessionDeviceInfo(sessionId, Request);
|
||||
|
||||
try
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 10, "Loading User Data");
|
||||
if (!string.IsNullOrWhiteSpace(Username))
|
||||
{
|
||||
authenticatedToken = UserService.GetAuthorization(Username, Database);
|
||||
isAuthenticated = (authenticatedToken != null);
|
||||
}
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 13, "Loading Device Data");
|
||||
|
||||
Device RepoDevice = Database.Devices.Include("AssignedUser").Include("DeviceModel").Include("DeviceProfile").Where(d => d.SerialNumber == Request.DeviceSerialNumber).FirstOrDefault();
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 15, "Discovering User/Device Disco Permissions");
|
||||
if (isAuthenticated)
|
||||
{
|
||||
if (!authenticatedToken.Has(Claims.Device.Actions.EnrolDevices))
|
||||
{
|
||||
if (!authenticatedToken.Has(Claims.ComputerAccount))
|
||||
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.UserId));
|
||||
|
||||
if (domain == null)
|
||||
domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName);
|
||||
|
||||
if (!authenticatedToken.User.UserId.Equals(string.Format(@"{0}\{1}$", domain.NetBiosName, Request.DeviceComputerName), System.StringComparison.OrdinalIgnoreCase))
|
||||
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.UserId));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (RepoDevice == null)
|
||||
{
|
||||
throw new EnrolSafeException(string.Format("Unknown Device Serial Number (SN: '{0}')", Request.DeviceSerialNumber));
|
||||
}
|
||||
if (!RepoDevice.AllowUnauthenticatedEnrol)
|
||||
{
|
||||
if (RepoDevice.DeviceProfile.AllowUntrustedReimageJobEnrolment)
|
||||
{
|
||||
if (Database.Jobs.Count(j => j.DeviceSerialNumber == RepoDevice.SerialNumber && j.JobTypeId == JobType.JobTypeIds.SImg && !j.ClosedDate.HasValue) == 0)
|
||||
{
|
||||
throw new EnrolSafeException(string.Format("Device has no open 'Software - Reimage' job (SN: '{0}')", Request.DeviceSerialNumber));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new EnrolSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.DeviceSerialNumber));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Request.DeviceIsPartOfDomain && !string.IsNullOrWhiteSpace(Request.DeviceComputerName))
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 20, "Loading Active Directory Computer Account");
|
||||
System.Guid? uuidGuid = null;
|
||||
System.Guid? macAddressGuid = null;
|
||||
if (!string.IsNullOrEmpty(Request.DeviceUUID))
|
||||
uuidGuid = ADMachineAccount.NetbootGUIDFromUUID(Request.DeviceUUID);
|
||||
if (!string.IsNullOrEmpty(Request.DeviceLanMacAddress))
|
||||
macAddressGuid = ADMachineAccount.NetbootGUIDFromMACAddress(Request.DeviceLanMacAddress);
|
||||
|
||||
if (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)
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 30, "New Device, Creating Disco Instance");
|
||||
EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.DeviceSerialNumber);
|
||||
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
|
||||
|
||||
|
||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
|
||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||
if (deviceModelResult.Item2)
|
||||
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
||||
else
|
||||
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id);
|
||||
|
||||
if (domain == null)
|
||||
domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName);
|
||||
|
||||
RepoDevice = new Device
|
||||
{
|
||||
SerialNumber = Request.DeviceSerialNumber,
|
||||
DeviceDomainId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.DeviceComputerName),
|
||||
DeviceProfile = deviceProfile,
|
||||
DeviceModel = deviceModel,
|
||||
AllowUnauthenticatedEnrol = false,
|
||||
CreatedDate = DateTime.Now,
|
||||
EnrolledDate = DateTime.Now,
|
||||
LastEnrolDate = DateTime.Now,
|
||||
DeviceDetails = new List<DeviceDetail>()
|
||||
};
|
||||
Database.Devices.Add(RepoDevice);
|
||||
|
||||
if (!string.IsNullOrEmpty(Request.DeviceLanMacAddress))
|
||||
RepoDevice.DeviceDetails.LanMacAddress(RepoDevice, Request.DeviceLanMacAddress);
|
||||
if (!string.IsNullOrEmpty(Request.DeviceWlanMacAddress))
|
||||
RepoDevice.DeviceDetails.WLanMacAddress(RepoDevice, Request.DeviceWlanMacAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 30, "Existing Device, Updating Disco Instance");
|
||||
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
|
||||
|
||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
|
||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||
if (deviceModelResult.Item2)
|
||||
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
||||
else
|
||||
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id);
|
||||
|
||||
RepoDevice.DeviceModel = deviceModel;
|
||||
|
||||
if (!string.IsNullOrEmpty(Request.DeviceLanMacAddress))
|
||||
RepoDevice.DeviceDetails.LanMacAddress(RepoDevice, Request.DeviceLanMacAddress);
|
||||
if (!string.IsNullOrEmpty(Request.DeviceWlanMacAddress))
|
||||
RepoDevice.DeviceDetails.WLanMacAddress(RepoDevice, Request.DeviceWlanMacAddress);
|
||||
|
||||
if (!RepoDevice.EnrolledDate.HasValue)
|
||||
RepoDevice.EnrolledDate = DateTime.Now;
|
||||
RepoDevice.LastEnrolDate = DateTime.Now;
|
||||
}
|
||||
|
||||
if (adMachineAccount == null)
|
||||
{
|
||||
if (RepoDevice.DeviceProfile.ProvisionADAccount)
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 50, "Provisioning an Active Directory Computer Account");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(RepoDevice.DeviceProfile.OrganisationalUnit))
|
||||
throw new InvalidOperationException("No Organisational Unit has been set in the device profile");
|
||||
if (domain == null)
|
||||
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;
|
||||
}
|
||||
if (adMachineAccount != null)
|
||||
{
|
||||
response.DeviceComputerName = adMachineAccount.Name;
|
||||
response.DeviceDomainName = adMachineAccount.Domain.NetBiosName;
|
||||
}
|
||||
else if (ActiveDirectory.IsValidDomainAccountId(RepoDevice.DeviceDomainId))
|
||||
{
|
||||
string accountUsername;
|
||||
ADDomain accountDomain;
|
||||
ActiveDirectory.ParseDomainAccountId(RepoDevice.DeviceDomainId, out accountUsername, out accountDomain);
|
||||
|
||||
response.DeviceDomainName = accountDomain == null ? null : accountDomain.NetBiosName;
|
||||
response.DeviceComputerName = accountUsername;
|
||||
}
|
||||
else
|
||||
{
|
||||
response.DeviceDomainName = Request.DeviceDNSDomainName;
|
||||
response.DeviceComputerName = Request.DeviceComputerName;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RepoDevice.DeviceDomainId = adMachineAccount.Id.Trim('$');
|
||||
response.DeviceComputerName = adMachineAccount.Name;
|
||||
response.DeviceDomainName = adMachineAccount.Domain.NetBiosName;
|
||||
|
||||
// Enforce Computer Name Convention
|
||||
if (!adMachineAccount.IsCriticalSystemObject && RepoDevice.DeviceProfile.EnforceComputerNameConvention)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(RepoDevice.DeviceProfile.OrganisationalUnit))
|
||||
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.LogSessionTaskRenamingDevice(sessionId, Request.DeviceComputerName, calculatedComputerName);
|
||||
|
||||
RepoDevice.DeviceDomainId = calculatedComputerName;
|
||||
response.DeviceDomainName = domain.NetBiosName;
|
||||
response.DeviceComputerName = calculatedAccountUsername;
|
||||
|
||||
// Create New Account
|
||||
string offlineProvisionDiagnosicInfo;
|
||||
|
||||
response.OfflineDomainJoin = domainController.Value.OfflineDomainJoinProvision(RepoDevice.DeviceDomainId, RepoDevice.DeviceProfile.OrganisationalUnit, ref adMachineAccount, out offlineProvisionDiagnosicInfo);
|
||||
|
||||
EnrolmentLog.LogSessionDiagnosticInformation(sessionId, offlineProvisionDiagnosicInfo);
|
||||
|
||||
response.RequireReboot = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Enforce Organisational Unit
|
||||
if (!adMachineAccount.IsCriticalSystemObject && response.OfflineDomainJoin == null && RepoDevice.DeviceProfile.EnforceOrganisationalUnit)
|
||||
{
|
||||
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 (!parentDistinguishedName.Equals(RepoDevice.DeviceProfile.OrganisationalUnit, StringComparison.OrdinalIgnoreCase)) // Custom OU
|
||||
{
|
||||
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 Organisational Unit: {0} -> {1}", parentDistinguishedName, RepoDevice.DeviceProfile.OrganisationalUnit));
|
||||
EnrolmentLog.LogSessionTaskMovingDeviceOrganisationUnit(sessionId, parentDistinguishedName, RepoDevice.DeviceProfile.OrganisationalUnit);
|
||||
adMachineAccount.MoveOrganisationalUnit(domainController.Value, RepoDevice.DeviceProfile.OrganisationalUnit);
|
||||
response.RequireReboot = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (adMachineAccount != null && !adMachineAccount.IsCriticalSystemObject)
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 75, "Updating Active Directory Computer Account Properties");
|
||||
adMachineAccount.UpdateNetbootGUID(Request.DeviceUUID, Request.DeviceLanMacAddress);
|
||||
if (RepoDevice.AssignedUser != null)
|
||||
adMachineAccount.SetDescription(RepoDevice);
|
||||
}
|
||||
if (RepoDevice.DeviceProfile.DistributionType == DeviceProfile.DistributionTypes.OneToOne)
|
||||
{
|
||||
if (RepoDevice.AssignedUser == null)
|
||||
{
|
||||
response.AllowBootstrapperUninstall = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 80, "Retrieving Active Directory Assigned User Account");
|
||||
ADUserAccount AssignedUserInfo = ActiveDirectory.RetrieveADUserAccount(RepoDevice.AssignedUser.UserId);
|
||||
EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.SamAccountName, AssignedUserInfo.Domain.NetBiosName, AssignedUserInfo.SecurityIdentifier.ToString());
|
||||
response.AllowBootstrapperUninstall = true;
|
||||
response.DeviceAssignedUserIsLocalAdmin = RepoDevice.DeviceProfile.AssignedUserLocalAdmin;
|
||||
response.DeviceAssignedUserUsername = AssignedUserInfo.SamAccountName;
|
||||
response.DeviceAssignedUserDomain = AssignedUserInfo.Domain.NetBiosName;
|
||||
response.DeviceAssignedUserName = AssignedUserInfo.DisplayName;
|
||||
response.DeviceAssignedUserSID = AssignedUserInfo.SecurityIdentifier.ToString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response.AllowBootstrapperUninstall = true;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(Request.DeviceWlanMacAddress) && !string.IsNullOrEmpty(RepoDevice.DeviceProfile.CertificateProviderId))
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 90, "Provisioning a Wireless Certificate");
|
||||
|
||||
var allocationResult = RepoDevice.AllocateCertificate(Database);
|
||||
var deviceCertificate = allocationResult.Item1;
|
||||
if (deviceCertificate != null)
|
||||
{
|
||||
bool certAlreadyInstalled = false;
|
||||
if (Request.DeviceCertificates != null && Request.DeviceCertificates.Count > 0)
|
||||
{
|
||||
foreach (string existingCertName in Request.DeviceCertificates)
|
||||
{
|
||||
if (existingCertName.Contains(deviceCertificate.Name))
|
||||
{
|
||||
certAlreadyInstalled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!certAlreadyInstalled)
|
||||
{
|
||||
EnrolmentLog.LogSessionTaskProvisioningWirelessCertificate(sessionId, RepoDevice.SerialNumber, deviceCertificate.Name);
|
||||
response.DeviceCertificate = System.Convert.ToBase64String(deviceCertificate.Content);
|
||||
}
|
||||
}
|
||||
response.DeviceCertificateRemoveExisting = allocationResult.Item2;
|
||||
}
|
||||
|
||||
// Reset 'AllowUnauthenticatedEnrol'
|
||||
if (RepoDevice.AllowUnauthenticatedEnrol)
|
||||
RepoDevice.AllowUnauthenticatedEnrol = false;
|
||||
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 100, "Completed Successfully");
|
||||
}
|
||||
catch (EnrolSafeException ex)
|
||||
{
|
||||
EnrolmentLog.LogSessionError(sessionId, ex);
|
||||
return new EnrolResponse
|
||||
{
|
||||
SessionId = sessionId,
|
||||
ErrorMessage = ex.Message
|
||||
};
|
||||
}
|
||||
catch (System.Exception ex2)
|
||||
{
|
||||
ex2.ToExceptionless().Submit();
|
||||
EnrolmentLog.LogSessionError(sessionId, ex2);
|
||||
throw ex2;
|
||||
}
|
||||
finally
|
||||
{
|
||||
EnrolmentLog.LogSessionFinished(sessionId);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
public static RegisterResponse Register(DiscoDataContext Database, string Username, Register Request)
|
||||
{
|
||||
RegisterResponse response = new RegisterResponse();
|
||||
ADMachineAccount adMachineAccount = null;
|
||||
AuthorizationToken authenticatedToken = null;
|
||||
|
||||
ADDomain domain = null;
|
||||
Lazy<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");
|
||||
response.SessionId = sessionId;
|
||||
|
||||
EnrolmentLog.LogSessionStarting(sessionId, Request.DeviceSerialNumber, EnrolmentTypes.Register);
|
||||
EnrolmentLog.LogSessionDeviceInfo(sessionId, Request);
|
||||
|
||||
try
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 10, "Loading User Data");
|
||||
if (!string.IsNullOrWhiteSpace(Username))
|
||||
{
|
||||
authenticatedToken = UserService.GetAuthorization(Username, Database);
|
||||
}
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 13, "Loading Device Data");
|
||||
|
||||
Device RepoDevice = Database.Devices.Include("AssignedUser").Include("DeviceModel").Include("DeviceProfile").Where(d => d.SerialNumber == Request.DeviceSerialNumber).FirstOrDefault();
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 15, "Discovering User/Device Disco Permissions");
|
||||
if (authenticatedToken != null)
|
||||
{
|
||||
if (!authenticatedToken.Has(Claims.Device.Actions.EnrolDevices))
|
||||
{
|
||||
if (!authenticatedToken.Has(Claims.ComputerAccount))
|
||||
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.UserId));
|
||||
|
||||
if (domain == null)
|
||||
domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName);
|
||||
|
||||
if (!authenticatedToken.User.UserId.Equals(string.Format(@"{0}\{1}$", domain.NetBiosName, Request.DeviceComputerName), System.StringComparison.OrdinalIgnoreCase))
|
||||
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.UserId));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (RepoDevice == null)
|
||||
{
|
||||
throw new EnrolSafeException(string.Format("Unknown Device Serial Number (SN: '{0}')", Request.DeviceSerialNumber));
|
||||
}
|
||||
if (!RepoDevice.AllowUnauthenticatedEnrol)
|
||||
{
|
||||
if (RepoDevice.DeviceProfile.AllowUntrustedReimageJobEnrolment)
|
||||
{
|
||||
if (Database.Jobs.Count(j => j.DeviceSerialNumber == RepoDevice.SerialNumber && j.JobTypeId == JobType.JobTypeIds.SImg && !j.ClosedDate.HasValue) == 0)
|
||||
{
|
||||
throw new EnrolSafeException(string.Format("Device has no open 'Software - Reimage' job (SN: '{0}')", Request.DeviceSerialNumber));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new EnrolSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.DeviceSerialNumber));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Request.DeviceIsPartOfDomain && !string.IsNullOrWhiteSpace(Request.DeviceComputerName))
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 20, "Loading Active Directory Computer Account");
|
||||
System.Guid? uuidGuid = null;
|
||||
if (!string.IsNullOrEmpty(Request.DeviceUUID))
|
||||
uuidGuid = ADMachineAccount.NetbootGUIDFromUUID(Request.DeviceUUID);
|
||||
|
||||
if (domain == null)
|
||||
domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName);
|
||||
|
||||
var requestDeviceId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.DeviceComputerName);
|
||||
|
||||
adMachineAccount = domainController.Value.RetrieveADMachineAccount(requestDeviceId, uuidGuid);
|
||||
}
|
||||
if (RepoDevice == null)
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 30, "New Device, Creating Disco Instance");
|
||||
EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.DeviceSerialNumber);
|
||||
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
|
||||
|
||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
|
||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||
if (deviceModelResult.Item2)
|
||||
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
||||
else
|
||||
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id);
|
||||
|
||||
if (domain == null)
|
||||
domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName);
|
||||
|
||||
RepoDevice = new Device
|
||||
{
|
||||
SerialNumber = Request.DeviceSerialNumber,
|
||||
DeviceDomainId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.DeviceComputerName),
|
||||
DeviceProfile = deviceProfile,
|
||||
DeviceModel = deviceModel,
|
||||
AllowUnauthenticatedEnrol = false,
|
||||
CreatedDate = DateTime.Now,
|
||||
EnrolledDate = DateTime.Now,
|
||||
LastEnrolDate = DateTime.Now,
|
||||
DeviceDetails = new List<DeviceDetail>()
|
||||
};
|
||||
Database.Devices.Add(RepoDevice);
|
||||
}
|
||||
else
|
||||
{
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 30, "Existing Device, Updating Disco Instance");
|
||||
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
|
||||
|
||||
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
|
||||
DeviceModel deviceModel = deviceModelResult.Item1;
|
||||
if (deviceModelResult.Item2)
|
||||
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
|
||||
else
|
||||
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id);
|
||||
|
||||
RepoDevice.DeviceModel = deviceModel;
|
||||
|
||||
if (!RepoDevice.EnrolledDate.HasValue)
|
||||
RepoDevice.EnrolledDate = DateTime.Now;
|
||||
RepoDevice.LastEnrolDate = DateTime.Now;
|
||||
}
|
||||
|
||||
if (adMachineAccount == null)
|
||||
{
|
||||
if (adMachineAccount != null)
|
||||
{
|
||||
response.DeviceComputerName = adMachineAccount.Name;
|
||||
response.DeviceDomainName = adMachineAccount.Domain.NetBiosName;
|
||||
}
|
||||
else if (ActiveDirectory.IsValidDomainAccountId(RepoDevice.DeviceDomainId))
|
||||
{
|
||||
string accountUsername;
|
||||
ADDomain accountDomain;
|
||||
ActiveDirectory.ParseDomainAccountId(RepoDevice.DeviceDomainId, out accountUsername, out accountDomain);
|
||||
|
||||
response.DeviceDomainName = accountDomain == null ? null : accountDomain.NetBiosName;
|
||||
response.DeviceComputerName = accountUsername;
|
||||
}
|
||||
else
|
||||
{
|
||||
response.DeviceDomainName = Request.DeviceDNSDomainName;
|
||||
response.DeviceComputerName = Request.DeviceComputerName;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RepoDevice.DeviceDomainId = adMachineAccount.Id.Trim('$');
|
||||
response.DeviceComputerName = adMachineAccount.Name;
|
||||
response.DeviceDomainName = adMachineAccount.Domain.NetBiosName;
|
||||
}
|
||||
|
||||
// Reset 'AllowUnauthenticatedEnrol'
|
||||
if (RepoDevice.AllowUnauthenticatedEnrol)
|
||||
RepoDevice.AllowUnauthenticatedEnrol = false;
|
||||
|
||||
EnrolmentLog.LogSessionProgress(sessionId, 100, "Completed Successfully");
|
||||
}
|
||||
catch (EnrolSafeException ex)
|
||||
{
|
||||
EnrolmentLog.LogSessionError(sessionId, ex);
|
||||
return new RegisterResponse
|
||||
{
|
||||
SessionId = sessionId,
|
||||
ErrorMessage = ex.Message
|
||||
};
|
||||
}
|
||||
catch (System.Exception ex2)
|
||||
{
|
||||
ex2.ToExceptionless().Submit();
|
||||
EnrolmentLog.LogSessionError(sessionId, ex2);
|
||||
throw ex2;
|
||||
}
|
||||
finally
|
||||
{
|
||||
EnrolmentLog.LogSessionFinished(sessionId);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
namespace Disco.BI
|
||||
{
|
||||
public class EnrolSafeException : System.Exception
|
||||
{
|
||||
public EnrolSafeException(string Message) : base(Message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,486 +0,0 @@
|
||||
using Disco.Services.Logging;
|
||||
using Disco.Services.Logging.Models;
|
||||
using Disco.Models.ClientServices;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
namespace Disco.BI.DeviceBI
|
||||
{
|
||||
public class EnrolmentLog : LogBase
|
||||
{
|
||||
public enum EventTypeIds
|
||||
{
|
||||
SessionStarting = 10,
|
||||
SessionProgress,
|
||||
SessionDevice,
|
||||
SessionDeviceInfo,
|
||||
SessionFinished = 20,
|
||||
SessionDiagnosticInformation,
|
||||
SessionWarning,
|
||||
SessionError,
|
||||
SessionErrorWithInner,
|
||||
SessionClientError,
|
||||
SessionTaskAddedDevice = 50,
|
||||
SessionTaskUpdatingDevice,
|
||||
SessionTaskCreatedDeviceModel = 56,
|
||||
SessionTaskProvisioningADAccount = 58,
|
||||
SessionTaskAssigningUser = 60,
|
||||
SessionTaskProvisioningWirelessCertificate = 62,
|
||||
SessionTaskRenamingDevice = 64,
|
||||
SessionTaskMovingDeviceOrganisationUnit = 66,
|
||||
ClientError = 400
|
||||
}
|
||||
private const int _ModuleId = 50;
|
||||
public static EnrolmentLog Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return (EnrolmentLog)LogContext.LogModules[50];
|
||||
}
|
||||
}
|
||||
public override string ModuleDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Device Enrolment";
|
||||
}
|
||||
}
|
||||
public override int ModuleId
|
||||
{
|
||||
get
|
||||
{
|
||||
return 50;
|
||||
}
|
||||
}
|
||||
public override string ModuleName
|
||||
{
|
||||
get
|
||||
{
|
||||
return "DeviceEnrolment";
|
||||
}
|
||||
}
|
||||
[System.Diagnostics.DebuggerNonUserCode]
|
||||
public EnrolmentLog()
|
||||
{
|
||||
}
|
||||
private static void Log(EnrolmentLog.EventTypeIds EventTypeId, params object[] Args)
|
||||
{
|
||||
EnrolmentLog.Current.Log((int)EventTypeId, Args);
|
||||
}
|
||||
public static void LogSessionStarting(string SessionId, string HostId, DeviceEnrol.EnrolmentTypes EnrolmentType)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionStarting, new object[]
|
||||
{
|
||||
SessionId,
|
||||
HostId,
|
||||
System.Enum.GetName(EnrolmentType.GetType(), EnrolmentType)
|
||||
});
|
||||
}
|
||||
public static void LogSessionDevice(string SessionId, string DeviceSerialNumber, int? DeviceModelId)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionDevice, new object[]
|
||||
{
|
||||
SessionId,
|
||||
DeviceSerialNumber,
|
||||
DeviceModelId
|
||||
});
|
||||
}
|
||||
public static void LogSessionDeviceInfo(string SessionId, string SerialNumber, string UUID, string ComputerName, string LanMacAddress, string WlanMacAddress, string Manufacturer, string Model, string ModelType)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionDeviceInfo, new object[]
|
||||
{
|
||||
SessionId,
|
||||
SerialNumber,
|
||||
UUID,
|
||||
ComputerName,
|
||||
LanMacAddress,
|
||||
WlanMacAddress,
|
||||
Manufacturer,
|
||||
Model,
|
||||
ModelType
|
||||
});
|
||||
}
|
||||
public static void LogSessionDeviceInfo(string SessionId, MacEnrol Request)
|
||||
{
|
||||
EnrolmentLog.LogSessionDeviceInfo(SessionId, Request.DeviceSerialNumber, Request.DeviceUUID, Request.DeviceComputerName, Request.DeviceLanMacAddress, Request.DeviceWlanMacAddress, Request.DeviceManufacturer, Request.DeviceModel, Request.DeviceModelType);
|
||||
}
|
||||
public static void LogSessionDeviceInfo(string SessionId, Models.ClientServices.Enrol Request)
|
||||
{
|
||||
EnrolmentLog.LogSessionDeviceInfo(SessionId, Request.DeviceSerialNumber, Request.DeviceUUID, Request.DeviceComputerName, Request.DeviceLanMacAddress, Request.DeviceWlanMacAddress, Request.DeviceManufacturer, Request.DeviceModel, Request.DeviceModelType);
|
||||
}
|
||||
public static void LogSessionDeviceInfo(string SessionId, Models.ClientServices.Register Request)
|
||||
{
|
||||
EnrolmentLog.LogSessionDeviceInfo(SessionId, Request.DeviceSerialNumber, Request.DeviceUUID, Request.DeviceComputerName, null, null, Request.DeviceManufacturer, Request.DeviceModel, Request.DeviceModelType);
|
||||
}
|
||||
public static void LogSessionProgress(string SessionId, int Progress, string Status)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionProgress, new object[]
|
||||
{
|
||||
SessionId,
|
||||
Progress,
|
||||
Status
|
||||
});
|
||||
}
|
||||
public static void LogSessionFinished(string SessionId)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionFinished, new object[]
|
||||
{
|
||||
SessionId
|
||||
});
|
||||
}
|
||||
public static void LogSessionDiagnosticInformation(string SessionId, string Message)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionDiagnosticInformation, new object[]
|
||||
{
|
||||
SessionId,
|
||||
Message
|
||||
});
|
||||
}
|
||||
public static void LogSessionWarning(string SessionId, string Message)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionWarning, new object[]
|
||||
{
|
||||
SessionId,
|
||||
Message
|
||||
});
|
||||
}
|
||||
public static void LogSessionError(string SessionId, System.Exception Ex)
|
||||
{
|
||||
if (Ex.InnerException == null)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionError, new object[]
|
||||
{
|
||||
SessionId,
|
||||
Ex.GetType().Name,
|
||||
Ex.Message,
|
||||
Ex.StackTrace
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionErrorWithInner, new object[]
|
||||
{
|
||||
SessionId,
|
||||
Ex.GetType().Name,
|
||||
Ex.Message,
|
||||
Ex.InnerException.GetType().Name,
|
||||
Ex.InnerException.Message,
|
||||
Ex.StackTrace,
|
||||
Ex.InnerException.StackTrace
|
||||
});
|
||||
}
|
||||
}
|
||||
public static void LogSessionClientError(string SessionId, string ClientIP, string ClientIdentifier, string ClientVersion, string Error, string RawError)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionClientError, new object[]
|
||||
{
|
||||
SessionId,
|
||||
ClientIP,
|
||||
ClientIdentifier,
|
||||
ClientVersion,
|
||||
Error,
|
||||
RawError
|
||||
});
|
||||
}
|
||||
public static void LogSessionTaskAddedDevice(string SessionId, string DeviceSerialNumber)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskAddedDevice, new object[]
|
||||
{
|
||||
SessionId,
|
||||
DeviceSerialNumber
|
||||
});
|
||||
}
|
||||
public static void LogSessionTaskUpdatingDevice(string SessionId, string DeviceSerialNumber)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskUpdatingDevice, new object[]
|
||||
{
|
||||
SessionId,
|
||||
DeviceSerialNumber
|
||||
});
|
||||
}
|
||||
public static void LogSessionTaskCreatedDeviceModel(string SessionId, string DeviceSerialNumber, string Manufacturer, string Model)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskCreatedDeviceModel, new object[]
|
||||
{
|
||||
SessionId,
|
||||
DeviceSerialNumber,
|
||||
Manufacturer,
|
||||
Model
|
||||
});
|
||||
}
|
||||
public static void LogSessionTaskProvisioningADAccount(string SessionId, string DeviceSerialNumber, string ADAccountName)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskProvisioningADAccount, new object[]
|
||||
{
|
||||
SessionId,
|
||||
DeviceSerialNumber,
|
||||
ADAccountName
|
||||
});
|
||||
}
|
||||
public static void LogSessionTaskAssigningUser(string SessionId, string DeviceSerialNumber, string UserDisplayName, string UserUsername, string UserDomain, string UserSID)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskAssigningUser, new object[]
|
||||
{
|
||||
SessionId,
|
||||
DeviceSerialNumber,
|
||||
UserDisplayName,
|
||||
UserUsername,
|
||||
UserDomain,
|
||||
UserSID
|
||||
});
|
||||
}
|
||||
public static void LogSessionTaskProvisioningWirelessCertificate(string SessionId, string DeviceSerialNumber, string CertificateName)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskProvisioningWirelessCertificate, new object[]
|
||||
{
|
||||
SessionId,
|
||||
DeviceSerialNumber,
|
||||
CertificateName
|
||||
});
|
||||
}
|
||||
public static void LogSessionTaskRenamingDevice(string SessionId, string OldComputerName, string NewComputerName)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskRenamingDevice, new object[]
|
||||
{
|
||||
SessionId,
|
||||
OldComputerName,
|
||||
NewComputerName
|
||||
});
|
||||
}
|
||||
public static void LogSessionTaskMovingDeviceOrganisationUnit(string SessionId, string OldOrganisationUnit, string NewOrganisationUnit)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.SessionTaskMovingDeviceOrganisationUnit, new object[]
|
||||
{
|
||||
SessionId,
|
||||
OldOrganisationUnit,
|
||||
NewOrganisationUnit
|
||||
});
|
||||
}
|
||||
public static void LogClientError(string ClientIP, string ClientIdentifier, string ClientVersion, string Error, string RawError)
|
||||
{
|
||||
EnrolmentLog.Log(EnrolmentLog.EventTypeIds.ClientError, new object[]
|
||||
{
|
||||
ClientIP,
|
||||
ClientIdentifier,
|
||||
ClientVersion,
|
||||
Error,
|
||||
RawError
|
||||
});
|
||||
}
|
||||
protected override System.Collections.Generic.List<LogEventType> LoadEventTypes()
|
||||
{
|
||||
return new System.Collections.Generic.List<LogEventType>
|
||||
{
|
||||
new LogEventType
|
||||
{
|
||||
Id = 10,
|
||||
ModuleId = 50,
|
||||
Name = "Session Starting",
|
||||
Format = "Starting '{2}' Enrolment for {1} (Session# {0})",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 12,
|
||||
ModuleId = 50,
|
||||
Name = "Session Device",
|
||||
Format = null,
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = false
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 11,
|
||||
ModuleId = 50,
|
||||
Name = "Session Progress",
|
||||
Format = "Processing Session# {0}; {1}% Complete; Status: {2}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = false,
|
||||
UseDisplay = false
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 13,
|
||||
ModuleId = 50,
|
||||
Name = "Session Device Info",
|
||||
Format = null,
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 20,
|
||||
ModuleId = 50,
|
||||
Name = "Session Finished",
|
||||
Format = "Finished Session# {0}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 21,
|
||||
ModuleId = 50,
|
||||
Name = "Session Diagnostic Information",
|
||||
Format = null,
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = false,
|
||||
UseDisplay = false
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 22,
|
||||
ModuleId = 50,
|
||||
Name = "Session Warning",
|
||||
Format = null,
|
||||
Severity = 1,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 23,
|
||||
ModuleId = 50,
|
||||
Name = "Session Error",
|
||||
Format = "An Error Occurred: [{1}] {2}",
|
||||
Severity = 2,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 24,
|
||||
ModuleId = 50,
|
||||
Name = "Session Error with Internal",
|
||||
Format = "An Error Occurred: [{1}] {2}; Internal Error: [{3}] {4}",
|
||||
Severity = 2,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.SessionClientError,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Client Error",
|
||||
Format = "IP: {1}; Device ID: {2}; Version: {3} Error: {4}; Session# {0}",
|
||||
Severity = (int)LogEventType.Severities.Error,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 50,
|
||||
ModuleId = 50,
|
||||
Name = "Task - Added Device",
|
||||
Format = "Creating Disco Device {1}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 51,
|
||||
ModuleId = 50,
|
||||
Name = "Task - Updating Device",
|
||||
Format = "Updating Disco Device {1}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 56,
|
||||
ModuleId = 50,
|
||||
Name = "Task - Creating Device Model",
|
||||
Format = "Creating Device Model '{2} {3}' for Device {1}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 58,
|
||||
ModuleId = 50,
|
||||
Name = "Task - Provisioning Active Directory Account",
|
||||
Format = "Provisioning Active Directory Account '{2}' for Device {1}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 60,
|
||||
ModuleId = 50,
|
||||
Name = "Task - Assigning User",
|
||||
Format = "Assigning User '{2}' ({4}\\{3} {{{5}}}) for Device {1}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 62,
|
||||
ModuleId = 50,
|
||||
Name = "Task - Provisioning Wireless Certificate",
|
||||
Format = "Provisioning Wireless Certificate '{2}' for Device {1}",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 64,
|
||||
ModuleId = 50,
|
||||
Name = "Task - Renaming Device",
|
||||
Format = "Renaming Device '{1}' to '{2}'",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = 66,
|
||||
ModuleId = 50,
|
||||
Name = "Task - Moving Device Organisation Unit",
|
||||
Format = "Moving Device Organisation Unit '{1}' to '{2}'",
|
||||
Severity = 0,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
},
|
||||
new LogEventType
|
||||
{
|
||||
Id = (int)EventTypeIds.ClientError,
|
||||
ModuleId = _ModuleId,
|
||||
Name = "Client Error",
|
||||
Format = "IP: {0}; Device ID: {1}; Version: {2} Error: {3}",
|
||||
Severity = (int)LogEventType.Severities.Error,
|
||||
UseLive = true,
|
||||
UsePersist = true,
|
||||
UseDisplay = true
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
using Disco.BI.Extensions;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Services.Logging;
|
||||
using Disco.Services.Tasks;
|
||||
using Quartz;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Disco.BI.DeviceBI.Migration
|
||||
{
|
||||
public class LogMacAddressImporting : ScheduledTask
|
||||
{
|
||||
public override string TaskName { get { return "Migration: Logs to Device Mac Address Details"; } }
|
||||
|
||||
public override bool SingleInstanceTask { get { return true; } }
|
||||
public override bool CancelInitiallySupported { get { return false; } }
|
||||
|
||||
#region Required Helpers
|
||||
private static string RequiredFilePath(DiscoDataContext Database)
|
||||
{
|
||||
if (Database.DiscoConfiguration.DataStoreLocation != null)
|
||||
return System.IO.Path.Combine(Database.DiscoConfiguration.DataStoreLocation, "_LogMacAddressImportingRequired.txt");
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool IsRequired(DiscoDataContext Database)
|
||||
{
|
||||
var requiredFilePath = RequiredFilePath(Database);
|
||||
|
||||
if (requiredFilePath == null)
|
||||
return false;
|
||||
else
|
||||
return System.IO.File.Exists(requiredFilePath);
|
||||
}
|
||||
public static void SetRequired(DiscoDataContext Database)
|
||||
{
|
||||
var requiredFilePath = RequiredFilePath(Database);
|
||||
|
||||
if (requiredFilePath != null)
|
||||
{
|
||||
System.IO.File.WriteAllText(requiredFilePath, "This file exists to indicate an Importing of Mac Address from the Disco Logs is required. It will automatically be deleted when the import completes.");
|
||||
System.IO.File.SetAttributes(requiredFilePath, System.IO.FileAttributes.Hidden);
|
||||
}
|
||||
// ELSE: Could never be required if no DataStoreLocation is set (no logs to process)
|
||||
}
|
||||
#endregion
|
||||
|
||||
public override void InitalizeScheduledTask(DiscoDataContext Database)
|
||||
{
|
||||
if (IsRequired(Database))
|
||||
{
|
||||
// Schedule in 15mins
|
||||
var trigger = TriggerBuilder.Create()
|
||||
.StartAt(DateTimeOffset.Now.AddMinutes(5));
|
||||
|
||||
this.ScheduleTask(trigger);
|
||||
}
|
||||
}
|
||||
|
||||
public static ScheduledTaskStatus ScheduleImmediately()
|
||||
{
|
||||
var existingTask = ScheduledTasks.GetTaskStatuses(typeof(LogMacAddressImporting)).Where(s => s.IsRunning).FirstOrDefault();
|
||||
if (existingTask != null)
|
||||
return existingTask;
|
||||
|
||||
var instance = new LogMacAddressImporting();
|
||||
return instance.ScheduleTask();
|
||||
}
|
||||
|
||||
protected override void ExecuteTask()
|
||||
{
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
Status.UpdateStatus(0, "Importing MAC Addresses", "Querying Logs for Details");
|
||||
// Load Logs
|
||||
var logRetriever = new ReadLogContext()
|
||||
{
|
||||
Module = DeviceBI.EnrolmentLog.Current.ModuleId,
|
||||
EventTypes = new List<int>() { (int)DeviceBI.EnrolmentLog.EventTypeIds.SessionDeviceInfo }
|
||||
};
|
||||
var results = logRetriever.Query(database);
|
||||
|
||||
Status.UpdateStatus(50, string.Format("Passing {0} logs", results.Count));
|
||||
|
||||
Dictionary<string, Tuple<string, string>> addresses = new Dictionary<string, Tuple<string, string>>();
|
||||
|
||||
foreach (var result in results.OrderBy(r => r.Timestamp))
|
||||
addresses[((string)result.Arguments[1]).ToLower()] = new Tuple<string, string>((string)result.Arguments[4], (string)result.Arguments[5]);
|
||||
|
||||
Status.UpdateStatus(75, string.Format("Importing {0} details", addresses.Count));
|
||||
|
||||
var devices = database.Devices.Include("DeviceDetails").ToList();
|
||||
|
||||
Tuple<string, string> addressResult;
|
||||
foreach (var device in devices)
|
||||
{
|
||||
if (addresses.TryGetValue(device.SerialNumber.ToLower(), out addressResult))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(addressResult.Item1))
|
||||
device.DeviceDetails.LanMacAddress(device, addressResult.Item1);
|
||||
if (!string.IsNullOrEmpty(addressResult.Item2))
|
||||
device.DeviceDetails.WLanMacAddress(device, addressResult.Item2);
|
||||
}
|
||||
}
|
||||
|
||||
Status.UpdateStatus(90, "Saving to Database");
|
||||
|
||||
database.SaveChanges();
|
||||
|
||||
// Finished - Remove Placeholder File
|
||||
var requiredFilePath = RequiredFilePath(database);
|
||||
if (System.IO.File.Exists(requiredFilePath))
|
||||
System.IO.File.Delete(requiredFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Disco.BI
|
||||
{
|
||||
public class DisposableImageCollection : List<Bitmap>, IDisposable
|
||||
{
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (Image i in this)
|
||||
{
|
||||
if (i != null)
|
||||
i.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,486 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,365 +0,0 @@
|
||||
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,96 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Services.Users;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.BI.DocumentTemplateBI.ManagedGroups;
|
||||
using Disco.Services;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class AttachmentActionExtensions
|
||||
{
|
||||
|
||||
#region Delete
|
||||
public static bool CanDelete(this DeviceAttachment da)
|
||||
{
|
||||
if (UserService.CurrentAuthorization.Has(Claims.Device.Actions.RemoveAnyAttachments))
|
||||
return true;
|
||||
|
||||
if (UserService.CurrentAuthorization.Has(Claims.Device.Actions.RemoveOwnAttachments)
|
||||
&& da.TechUserId.Equals(UserService.CurrentUserId, StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
public static void OnDelete(this DeviceAttachment da, DiscoDataContext Database)
|
||||
{
|
||||
if (!da.CanDelete())
|
||||
throw new InvalidOperationException("Deletion of Attachment is Denied");
|
||||
|
||||
var attachmentId = da.Id;
|
||||
var documentTemplateId = da.DocumentTemplateId;
|
||||
var deviceSerialNumber = da.DeviceSerialNumber;
|
||||
|
||||
da.RepositoryDelete(Database);
|
||||
Database.DeviceAttachments.Remove(da);
|
||||
|
||||
DocumentTemplateManagedGroups.TriggerDeviceAttachmentDeleted(Database, attachmentId, documentTemplateId, deviceSerialNumber);
|
||||
}
|
||||
public static bool CanDelete(this JobAttachment ja)
|
||||
{
|
||||
if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.RemoveAnyAttachments))
|
||||
return true;
|
||||
|
||||
if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.RemoveOwnAttachments)
|
||||
&& ja.TechUserId.Equals(UserService.CurrentUserId, StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
public static void OnDelete(this JobAttachment ja, DiscoDataContext Database)
|
||||
{
|
||||
if (!ja.CanDelete())
|
||||
throw new InvalidOperationException("Deletion of Attachment is Denied");
|
||||
|
||||
var attachmentId = ja.Id;
|
||||
var documentTemplateId = ja.DocumentTemplateId;
|
||||
var jobId = ja.JobId;
|
||||
|
||||
ja.RepositoryDelete(Database);
|
||||
Database.JobAttachments.Remove(ja);
|
||||
|
||||
DocumentTemplateManagedGroups.TriggerJobAttachmentDeleted(Database, attachmentId, documentTemplateId, jobId);
|
||||
}
|
||||
public static bool CanDelete(this UserAttachment ua)
|
||||
{
|
||||
if (UserService.CurrentAuthorization.Has(Claims.User.Actions.RemoveAnyAttachments))
|
||||
return true;
|
||||
|
||||
if (UserService.CurrentAuthorization.Has(Claims.User.Actions.RemoveOwnAttachments)
|
||||
&& ua.TechUserId.Equals(UserService.CurrentUserId, StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
public static void OnDelete(this UserAttachment ua, DiscoDataContext Database)
|
||||
{
|
||||
if (!ua.CanDelete())
|
||||
throw new InvalidOperationException("Deletion of Attachment is Denied");
|
||||
|
||||
var attachmentId = ua.Id;
|
||||
var documentTemplateId = ua.DocumentTemplateId;
|
||||
var userId = ua.UserId;
|
||||
|
||||
ua.RepositoryDelete(Database);
|
||||
Database.UserAttachments.Remove(ua);
|
||||
|
||||
DocumentTemplateManagedGroups.TriggerUserAttachmentDeleted(Database, attachmentId, documentTemplateId, userId);
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Services.Authorization;
|
||||
using Disco.Models.Repository;
|
||||
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 AuthorizationRoleExtensions
|
||||
{
|
||||
|
||||
public static void Delete(this IRoleToken roleToken, DiscoDataContext Database)
|
||||
{
|
||||
var role = Database.AuthorizationRoles.Find(roleToken.Role.Id);
|
||||
UserService.DeleteAuthorizationRole(Database, roleToken.Role);
|
||||
}
|
||||
|
||||
public static void Delete(this AuthorizationRole role, DiscoDataContext Database)
|
||||
{
|
||||
UserService.DeleteAuthorizationRole(Database, role);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.ClientServices;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Users;
|
||||
using System;
|
||||
using System.Web;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class ClientServicesExtensions
|
||||
{
|
||||
public static EnrolResponse BuildResponse(this Enrol request)
|
||||
{
|
||||
if (HttpContext.Current == null)
|
||||
throw new PlatformNotSupportedException("This function can only be accessed from within ASP.NET");
|
||||
|
||||
string username = null;
|
||||
if (HttpContext.Current.Request.IsAuthenticated)
|
||||
username = HttpContext.Current.User.Identity.Name;
|
||||
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
EnrolResponse response = DeviceBI.DeviceEnrol.Enrol(database, username, request);
|
||||
database.SaveChanges();
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
public static WhoAmIResponse BuildResponse(this WhoAmI request)
|
||||
{
|
||||
if (HttpContext.Current == null)
|
||||
throw new PlatformNotSupportedException("This function can only be accessed from within ASP.NET");
|
||||
|
||||
string username = null;
|
||||
if (HttpContext.Current.Request.IsAuthenticated)
|
||||
username = HttpContext.Current.User.Identity.Name;
|
||||
|
||||
if (username == null)
|
||||
throw new InvalidOperationException("Unauthenticated Http Context");
|
||||
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
AuthorizationToken token = UserService.GetAuthorization(username, database, true);
|
||||
|
||||
WhoAmIResponse response = new WhoAmIResponse()
|
||||
{
|
||||
Username = token.User.UserId,
|
||||
DisplayName = token.User.DisplayName,
|
||||
Type = token.Has(Claims.ComputerAccount) ? "Computer Account" : "User Account"
|
||||
};
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
public static MacEnrolResponse BuildResponse(this MacEnrol request)
|
||||
{
|
||||
if (HttpContext.Current == null)
|
||||
throw new PlatformNotSupportedException("This function can only be accessed from within ASP.NET");
|
||||
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
MacEnrolResponse response = DeviceBI.DeviceEnrol.MacEnrol(database, request, false);
|
||||
database.SaveChanges();
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
public static RegisterResponse BuildResponse(this Register request)
|
||||
{
|
||||
if (HttpContext.Current == null)
|
||||
throw new PlatformNotSupportedException("This function can only be accessed from within ASP.NET");
|
||||
|
||||
string username = null;
|
||||
if (HttpContext.Current.Request.IsAuthenticated)
|
||||
username = HttpContext.Current.User.Identity.Name;
|
||||
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
RegisterResponse response = DeviceBI.DeviceEnrol.Register(database, username, request);
|
||||
database.SaveChanges();
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Users;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class DeviceActionExtensions
|
||||
{
|
||||
public static bool IsDecommissioned(this Device d)
|
||||
{
|
||||
return d.DecommissionedDate.HasValue;
|
||||
}
|
||||
|
||||
public static bool CanCreateJob(this Device d)
|
||||
{
|
||||
if (!JobActionExtensions.CanCreate())
|
||||
return false;
|
||||
|
||||
return !d.IsDecommissioned();
|
||||
}
|
||||
|
||||
public static bool CanUpdateAssignment(this Device d)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Device.Actions.AssignUser))
|
||||
return false;
|
||||
|
||||
return !d.IsDecommissioned();
|
||||
}
|
||||
|
||||
public static bool CanUpdateDeviceProfile(this Device d)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Device.Properties.DeviceProfile))
|
||||
return false;
|
||||
|
||||
return !d.IsDecommissioned();
|
||||
}
|
||||
|
||||
public static bool CanUpdateDeviceBatch(this Device d)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Device.Properties.DeviceBatch))
|
||||
return false;
|
||||
|
||||
return !d.IsDecommissioned();
|
||||
}
|
||||
|
||||
public static bool CanUpdateTrustEnrol(this Device d)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Device.Actions.AllowUnauthenticatedEnrol))
|
||||
return false;
|
||||
|
||||
return !d.IsDecommissioned() && !d.AllowUnauthenticatedEnrol;
|
||||
}
|
||||
public static bool CanUpdateUntrustEnrol(this Device d)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Device.Actions.AllowUnauthenticatedEnrol))
|
||||
return false;
|
||||
|
||||
return !d.IsDecommissioned() && d.AllowUnauthenticatedEnrol;
|
||||
}
|
||||
|
||||
#region Decommission
|
||||
public static bool CanDecommission(this Device d)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Device.Actions.Decommission))
|
||||
return false;
|
||||
|
||||
if (d.DecommissionedDate.HasValue)
|
||||
return false; // Already Decommissioned
|
||||
|
||||
if (d.AssignedUserId != null)
|
||||
return false; // User Assigned to Device
|
||||
|
||||
if (d.Jobs.Count(j => !j.ClosedDate.HasValue) > 0)
|
||||
return false; // Device linked to > 0 Open Jobs
|
||||
|
||||
return true;
|
||||
}
|
||||
public static void OnDecommission(this Device d, Disco.Models.Repository.DecommissionReasons Reason)
|
||||
{
|
||||
if (!d.CanDecommission())
|
||||
throw new InvalidOperationException("Decommission of Device is Denied");
|
||||
|
||||
d.DecommissionedDate = DateTime.Now;
|
||||
d.DecommissionReason = Reason;
|
||||
|
||||
// Disable AD Account
|
||||
if (ActiveDirectory.IsValidDomainAccountId(d.DeviceDomainId))
|
||||
{
|
||||
var adAccount = d.ActiveDirectoryAccount();
|
||||
if (adAccount != null && !adAccount.IsCriticalSystemObject)
|
||||
{
|
||||
adAccount.DisableAccount();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region Recommission
|
||||
public static bool CanRecommission(this Device d)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Device.Actions.Recommission))
|
||||
return false;
|
||||
|
||||
return d.DecommissionedDate.HasValue;
|
||||
}
|
||||
public static void OnRecommission(this Device d)
|
||||
{
|
||||
if (!d.CanRecommission())
|
||||
throw new InvalidOperationException("Recommission of Device is Denied");
|
||||
|
||||
d.DecommissionedDate = null;
|
||||
d.DecommissionReason = null;
|
||||
|
||||
// Enable AD Account
|
||||
if (ActiveDirectory.IsValidDomainAccountId(d.DeviceDomainId))
|
||||
{
|
||||
var adAccount = d.ActiveDirectoryAccount();
|
||||
if (adAccount != null && !adAccount.IsCriticalSystemObject)
|
||||
{
|
||||
adAccount.EnableAccount();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Delete
|
||||
public static bool CanDelete(this Device d)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Device.Actions.Delete))
|
||||
return false;
|
||||
|
||||
return d.DecommissionedDate.HasValue;
|
||||
}
|
||||
public static void OnDelete(this Device d, DiscoDataContext Database)
|
||||
{
|
||||
// Delete Jobs
|
||||
foreach (Job j in Database.Jobs.Where(i => i.DeviceSerialNumber == d.SerialNumber))
|
||||
{
|
||||
if (j.UserId == null)
|
||||
{ // No User associated, thus must Delete whole Job
|
||||
if (j.CanDelete())
|
||||
j.OnDelete(Database);
|
||||
else
|
||||
throw new InvalidOperationException(string.Format("Deletion of Device is Denied (See Job# {0})", j.Id));
|
||||
}
|
||||
else
|
||||
{
|
||||
// User associated to Job, thus just remove Devices' association
|
||||
j.DeviceSerialNumber = null;
|
||||
|
||||
// Write Job Log
|
||||
JobLog jobLog = new JobLog()
|
||||
{
|
||||
JobId = j.Id,
|
||||
TechUserId = UserService.CurrentUser.UserId,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = string.Format("# Device Deleted\r\n\r\nSerial Number: **{0}**\r\nComputer Name: **{1}**\r\nModel: **{2}**\r\nProfile: **{3}**",
|
||||
d.SerialNumber, d.DeviceDomainId, d.DeviceModel, d.DeviceProfile)
|
||||
};
|
||||
Database.JobLogs.Add(jobLog);
|
||||
}
|
||||
}
|
||||
|
||||
// Disable Wireless Certificates
|
||||
foreach (var wc in Database.DeviceCertificates.Where(i => i.DeviceSerialNumber == d.SerialNumber))
|
||||
{
|
||||
wc.DeviceSerialNumber = null;
|
||||
wc.Enabled = false;
|
||||
}
|
||||
// Delete Device Details
|
||||
foreach (var dd in Database.DeviceDetails.Where(i => i.DeviceSerialNumber == d.SerialNumber))
|
||||
Database.DeviceDetails.Remove(dd);
|
||||
// Delete Device Attachments
|
||||
foreach (var da in Database.DeviceAttachments.Where(i => i.DeviceSerialNumber == d.SerialNumber))
|
||||
{
|
||||
da.RepositoryDelete(Database);
|
||||
Database.DeviceAttachments.Remove(da);
|
||||
}
|
||||
// Delete Device User Assignments
|
||||
foreach (var dua in Database.DeviceUserAssignments.Where(i => i.DeviceSerialNumber == d.SerialNumber))
|
||||
Database.DeviceUserAssignments.Remove(dua);
|
||||
|
||||
Database.Devices.Remove(d);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Devices.ManagedGroups;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Users;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class DeviceBatchExtensions
|
||||
{
|
||||
public static bool CanDelete(this DeviceBatch db, DiscoDataContext Database)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Config.DeviceBatch.Delete))
|
||||
return false;
|
||||
|
||||
// Can't Delete if Contains Devices
|
||||
var deviceCount = Database.Devices.Count(d => d.DeviceBatchId == db.Id);
|
||||
if (deviceCount > 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Delete(this DeviceBatch db, DiscoDataContext Database)
|
||||
{
|
||||
if (!db.CanDelete(Database))
|
||||
throw new InvalidOperationException("The state of this Device Batch doesn't allow it to be deleted");
|
||||
|
||||
// Remove Linked Group
|
||||
ActiveDirectory.Context.ManagedGroups.Remove(DeviceBatchDevicesManagedGroup.GetKey(db));
|
||||
ActiveDirectory.Context.ManagedGroups.Remove(DeviceBatchAssignedUsersManagedGroup.GetKey(db));
|
||||
|
||||
// Delete Batch
|
||||
Database.DeviceBatches.Remove(db);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
using System.Linq;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Plugins;
|
||||
using Disco.Services.Plugins.Features.CertificateProvider;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class DeviceCertificateExtensions
|
||||
{
|
||||
|
||||
public static Tuple<DeviceCertificate, List<string>> AllocateCertificate(this Device device, DiscoDataContext Database)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(device.DeviceProfile.CertificateProviderId))
|
||||
{
|
||||
// Load Plugin
|
||||
PluginFeatureManifest featureManifest = Plugins.GetPluginFeature(device.DeviceProfile.CertificateProviderId, typeof(CertificateProviderFeature));
|
||||
|
||||
using (CertificateProviderFeature providerFeature = featureManifest.CreateInstance<CertificateProviderFeature>())
|
||||
{
|
||||
// REMOVED 2012-07-18 G# - Plugin is responsible for checking
|
||||
// Already Allocated Certificate
|
||||
//if (deviceCertificates.Count > 0)
|
||||
// return new Tuple<DeviceCertificate, List<string>>(deviceCertificates[0], providerPlugin.RemoveExistingCertificateNames());
|
||||
//else
|
||||
|
||||
return providerFeature.AllocateCertificate(Database, device);
|
||||
}
|
||||
}
|
||||
|
||||
// Device Profile does not allow certificate allocation
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
using Disco.Models.Repository;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class DeviceDetailExtensions
|
||||
{
|
||||
#region Helpers
|
||||
private static string GetDetail(this IEnumerable<DeviceDetail> details, string Scope, string Key)
|
||||
{
|
||||
if (details == null)
|
||||
throw new ArgumentNullException("details");
|
||||
if (string.IsNullOrEmpty(Scope))
|
||||
throw new ArgumentNullException("Scope");
|
||||
if (string.IsNullOrEmpty(Key))
|
||||
throw new ArgumentNullException("Key");
|
||||
|
||||
var detail = details.Where(d => d.Key == Key).FirstOrDefault();
|
||||
|
||||
if (detail == null)
|
||||
return null;
|
||||
else
|
||||
return detail.Value;
|
||||
}
|
||||
|
||||
private static void SetDetail(this Device device, string Scope, string Key, string Value)
|
||||
{
|
||||
if (device == null)
|
||||
throw new ArgumentNullException("device");
|
||||
if (string.IsNullOrEmpty(Scope))
|
||||
throw new ArgumentNullException("Scope");
|
||||
if (string.IsNullOrEmpty(Key))
|
||||
throw new ArgumentNullException("Key");
|
||||
|
||||
var detail = device.DeviceDetails.Where(d => d.Scope == Scope && d.Key == Key).FirstOrDefault();
|
||||
|
||||
// No Detail Stored & Set to Null
|
||||
if (detail == null && Value == null)
|
||||
return;
|
||||
|
||||
if (detail == null)
|
||||
{
|
||||
detail = new DeviceDetail()
|
||||
{
|
||||
DeviceSerialNumber = device.SerialNumber,
|
||||
Scope = Scope,
|
||||
Key = Key,
|
||||
Value = Value
|
||||
};
|
||||
device.DeviceDetails.Add(detail);
|
||||
}
|
||||
|
||||
if (detail.Value != Value)
|
||||
{
|
||||
if (Value == null)
|
||||
{
|
||||
device.DeviceDetails.Remove(detail);
|
||||
}
|
||||
else
|
||||
{
|
||||
detail.Value = Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region LanMacAddress
|
||||
/// <summary>
|
||||
/// Gets the LanMacAddress Device Detail Value
|
||||
/// </summary>
|
||||
/// <returns>The LanMacAddress or null</returns>
|
||||
public static string LanMacAddress(this IEnumerable<DeviceDetail> details)
|
||||
{
|
||||
return details.GetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyLanMacAddress);
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the LanMacAddress Device Detail Value
|
||||
/// </summary>
|
||||
public static void LanMacAddress(this IEnumerable<DeviceDetail> details, Device device, string LanMacAddress)
|
||||
{
|
||||
device.SetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyLanMacAddress, LanMacAddress);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region WLanMacAddress
|
||||
/// <summary>
|
||||
/// Gets the WLanMacAddress Device Detail Value
|
||||
/// </summary>
|
||||
/// <returns>The WLanMacAddress or null</returns>
|
||||
public static string WLanMacAddress(this IEnumerable<DeviceDetail> details)
|
||||
{
|
||||
return details.GetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyWLanMacAddress);
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the WLanMacAddress Device Detail Value
|
||||
/// </summary>
|
||||
public static void WLanMacAddress(this IEnumerable<DeviceDetail> details, Device device, string WLanMacAddress)
|
||||
{
|
||||
device.SetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyWLanMacAddress, WLanMacAddress);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ACAdapter
|
||||
/// <summary>
|
||||
/// Gets the ACAdapter Device Detail Value
|
||||
/// </summary>
|
||||
/// <returns>The ACAdapter or null</returns>
|
||||
public static string ACAdapter(this IEnumerable<DeviceDetail> details)
|
||||
{
|
||||
return details.GetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyACAdapter);
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the ACAdapter Device Detail Value
|
||||
/// </summary>
|
||||
public static void ACAdapter(this IEnumerable<DeviceDetail> details, Device device, string ACAdapter)
|
||||
{
|
||||
device.SetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyACAdapter, ACAdapter);
|
||||
}
|
||||
#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,215 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Documents;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Expressions;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Users;
|
||||
using Exceptionless;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class DeviceExtensions
|
||||
{
|
||||
|
||||
public static string ComputerNameRender(this Device device, DiscoDataContext Database, ADDomain Domain)
|
||||
{
|
||||
if (Domain == null)
|
||||
throw new ArgumentNullException("Domain");
|
||||
|
||||
var deviceProfile = device.DeviceProfile;
|
||||
Expression computerNameTemplateExpression = null;
|
||||
computerNameTemplateExpression = ExpressionCache.GetValue(DeviceProfileExtensions.ComputerNameExpressionCacheModule, deviceProfile.Id.ToString(), () =>
|
||||
{
|
||||
// Removed 2012-06-14 G# - Properties moved to DeviceProfile model & DB Migrated in DBv3.
|
||||
//return Expressions.Expression.TokenizeSingleDynamic(null, deviceProfile.Configuration(context).ComputerNameTemplate, 0);
|
||||
return Expression.TokenizeSingleDynamic(null, deviceProfile.ComputerNameTemplate, 0);
|
||||
});
|
||||
var evaluatorVariables = Expression.StandardVariables(null, Database, UserService.CurrentUser, DateTime.Now, null);
|
||||
string rendered;
|
||||
try
|
||||
{
|
||||
rendered = computerNameTemplateExpression.EvaluateFirst<string>(device, evaluatorVariables);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.ToExceptionless().AddObject(deviceProfile.ComputerNameTemplate, "ComputerNameTemplate").Submit();
|
||||
throw new InvalidOperationException(string.Format("An error occurred rendering the computer name: [{0}] {1}", ex.GetType().Name, ex.Message), ex.InnerException);
|
||||
}
|
||||
if (rendered == null || rendered.Length > 24)
|
||||
{
|
||||
throw new InvalidOperationException("The rendered computer name would be invalid or longer than 24 characters");
|
||||
}
|
||||
|
||||
return string.Format(@"{0}\{1}", Domain.NetBiosName, rendered);
|
||||
}
|
||||
public static List<DocumentTemplate> AvailableDocumentTemplates(this Device d, DiscoDataContext Database, User User, DateTime TimeStamp)
|
||||
{
|
||||
List<DocumentTemplate> ats = Database.DocumentTemplates
|
||||
.Where(at => at.Scope == DocumentTemplate.DocumentTemplateScopes.Device).ToList();
|
||||
|
||||
return ats.Where(at => at.FilterExpressionMatches(d, Database, User, TimeStamp, DocumentState.DefaultState())).ToList();
|
||||
}
|
||||
|
||||
public static bool UpdateLastNetworkLogonDate(this Device Device)
|
||||
{
|
||||
return ADNetworkLogonDatesUpdateTask.UpdateLastNetworkLogonDate(Device);
|
||||
}
|
||||
|
||||
public static Device AddOffline(this Device d, DiscoDataContext Database)
|
||||
{
|
||||
// Just Include:
|
||||
// - Serial Number
|
||||
// - Asset Number
|
||||
// - Profile Id
|
||||
// - Assigned User Id
|
||||
// - Batch
|
||||
|
||||
// Enforce Authorization
|
||||
var auth = UserService.CurrentAuthorization;
|
||||
if (!auth.Has(Claims.Device.Properties.AssetNumber))
|
||||
d.AssetNumber = null;
|
||||
if (!auth.Has(Claims.Device.Properties.Location))
|
||||
d.Location = null;
|
||||
if (!auth.Has(Claims.Device.Properties.DeviceBatch))
|
||||
d.DeviceBatchId = null;
|
||||
if (!auth.Has(Claims.Device.Properties.DeviceProfile))
|
||||
d.DeviceProfileId = Database.DiscoConfiguration.DeviceProfiles.DefaultAddDeviceOfflineDeviceProfileId;
|
||||
if (!auth.Has(Claims.Device.Actions.AssignUser))
|
||||
d.AssignedUserId = null;
|
||||
|
||||
|
||||
// Batch
|
||||
DeviceBatch db = default(DeviceBatch);
|
||||
if (d.DeviceBatchId.HasValue)
|
||||
db = Database.DeviceBatches.Find(d.DeviceBatchId.Value);
|
||||
|
||||
// Default Device Model
|
||||
DeviceModel dm = default(DeviceModel);
|
||||
if (db != null && db.DefaultDeviceModelId.HasValue)
|
||||
dm = Database.DeviceModels.Find(db.DefaultDeviceModelId); // From Batch
|
||||
else
|
||||
dm = Database.DeviceModels.Find(1); // Default
|
||||
|
||||
Device d2 = new Device()
|
||||
{
|
||||
SerialNumber = d.SerialNumber.ToUpper(),
|
||||
AssetNumber = d.AssetNumber,
|
||||
Location = d.Location,
|
||||
CreatedDate = DateTime.Now,
|
||||
DeviceProfileId = d.DeviceProfileId,
|
||||
DeviceProfile = Database.DeviceProfiles.Find(d.DeviceProfileId),
|
||||
AllowUnauthenticatedEnrol = true,
|
||||
DeviceModelId = dm.Id,
|
||||
DeviceModel = dm,
|
||||
DeviceBatchId = d.DeviceBatchId,
|
||||
DeviceBatch = db
|
||||
};
|
||||
|
||||
Database.Devices.Add(d2);
|
||||
if (!string.IsNullOrEmpty(d.AssignedUserId))
|
||||
{
|
||||
User u = UserService.GetUser(ActiveDirectory.ParseDomainAccountId(d.AssignedUserId), Database, true);
|
||||
d2.AssignDevice(Database, u);
|
||||
}
|
||||
|
||||
return d2;
|
||||
}
|
||||
|
||||
public static DeviceUserAssignment AssignDevice(this Device d, DiscoDataContext Database, User u)
|
||||
{
|
||||
DeviceUserAssignment newDua = default(DeviceUserAssignment);
|
||||
|
||||
// Mark existing assignments as Unassigned
|
||||
foreach (var dua in Database.DeviceUserAssignments.Where(m => m.DeviceSerialNumber == d.SerialNumber && !m.UnassignedDate.HasValue))
|
||||
dua.UnassignedDate = DateTime.Now;
|
||||
|
||||
if (u != null)
|
||||
{
|
||||
// Add new Assignment
|
||||
newDua = new DeviceUserAssignment()
|
||||
{
|
||||
DeviceSerialNumber = d.SerialNumber,
|
||||
AssignedUserId = u.UserId,
|
||||
AssignedDate = DateTime.Now
|
||||
};
|
||||
Database.DeviceUserAssignments.Add(newDua);
|
||||
|
||||
d.AssignedUserId = u.UserId;
|
||||
d.AssignedUser = u;
|
||||
}
|
||||
else
|
||||
{
|
||||
d.AssignedUserId = null;
|
||||
}
|
||||
|
||||
// Update AD Account
|
||||
if (ActiveDirectory.IsValidDomainAccountId(d.DeviceDomainId))
|
||||
{
|
||||
var adMachineAccount = ActiveDirectory.RetrieveADMachineAccount(d.DeviceDomainId);
|
||||
if (adMachineAccount != null)
|
||||
adMachineAccount.SetDescription(d);
|
||||
}
|
||||
|
||||
return newDua;
|
||||
}
|
||||
|
||||
public static string ReasonMessage(this DecommissionReasons r)
|
||||
{
|
||||
switch (r)
|
||||
{
|
||||
case DecommissionReasons.EndOfLife:
|
||||
return "End of Life";
|
||||
case DecommissionReasons.Sold:
|
||||
return "Sold";
|
||||
case DecommissionReasons.Stolen:
|
||||
return "Stolen";
|
||||
case DecommissionReasons.Lost:
|
||||
return "Lost";
|
||||
case DecommissionReasons.Damaged:
|
||||
return "Damaged";
|
||||
case DecommissionReasons.Donated:
|
||||
return "Donated";
|
||||
case DecommissionReasons.Returned:
|
||||
return "Returned";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
public static string ReasonMessage(this DecommissionReasons? r)
|
||||
{
|
||||
if (!r.HasValue)
|
||||
return "Not Decommissioned";
|
||||
|
||||
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)
|
||||
{
|
||||
if (Device.DecommissionedDate.HasValue)
|
||||
return string.Format("Decommissioned ({0})", Device.DecommissionReason.ReasonMessage());
|
||||
|
||||
if (!Device.EnrolledDate.HasValue)
|
||||
return "Not Enrolled";
|
||||
|
||||
return "Active";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Users;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class DeviceModelExtensions
|
||||
{
|
||||
#region Actions
|
||||
public static bool CanDelete(this DeviceModel dm, DiscoDataContext Database)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Config.DeviceModel.Delete))
|
||||
return false;
|
||||
|
||||
// Can't Delete Default Model (Id: 1)
|
||||
if (dm.Id == 1)
|
||||
return false;
|
||||
|
||||
// Can't Delete if Contains Devices
|
||||
if (Database.Devices.Count(d => d.DeviceModelId == dm.Id) > 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
public static void Delete(this DeviceModel dm, DiscoDataContext Database)
|
||||
{
|
||||
if (!dm.CanDelete(Database))
|
||||
throw new InvalidOperationException("The state of this Device Model doesn't allow it to be deleted");
|
||||
|
||||
// Delete Image
|
||||
var deviceModelImagePath = dm.ImageFilePath();
|
||||
if (File.Exists(deviceModelImagePath))
|
||||
File.Delete(deviceModelImagePath);
|
||||
|
||||
// Delete any Device Model Components
|
||||
foreach (var deviceModelComponent in Database.DeviceComponents.Where(dc => dc.DeviceModelId == dm.Id).ToList())
|
||||
{
|
||||
Database.DeviceComponents.Remove(deviceModelComponent);
|
||||
}
|
||||
|
||||
// Delete Model
|
||||
Database.DeviceModels.Remove(dm);
|
||||
}
|
||||
// End Added 2012-11-26 G#
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.BI.Config;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Devices.ManagedGroups;
|
||||
using Disco.Services.Expressions;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Users;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class DeviceProfileExtensions
|
||||
{
|
||||
public const string ComputerNameExpressionCacheModule = "ComputerNameTemplate";
|
||||
|
||||
public static void ComputerNameInvalidateCache(this DeviceProfile deviceProfile)
|
||||
{
|
||||
ExpressionCache.InvalidateKey(ComputerNameExpressionCacheModule, deviceProfile.Id.ToString());
|
||||
}
|
||||
|
||||
public static OrganisationAddress DefaultOrganisationAddressDetails(this DeviceProfile deviceProfile, DiscoDataContext Database)
|
||||
{
|
||||
if (deviceProfile.DefaultOrganisationAddress.HasValue)
|
||||
{
|
||||
return Database.DiscoConfiguration.OrganisationAddresses.GetAddress(deviceProfile.DefaultOrganisationAddress.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CanDelete(this DeviceProfile dp, DiscoDataContext Database)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Config.DeviceProfile.Delete))
|
||||
return false;
|
||||
|
||||
// Can't Delete Default Profile (Id: 1)
|
||||
if (dp.Id == 1)
|
||||
return false;
|
||||
|
||||
// Can't Delete if Contains Devices
|
||||
if (Database.Devices.Count(d => d.DeviceProfileId == dp.Id) > 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
public static void Delete(this DeviceProfile dp, DiscoDataContext Database)
|
||||
{
|
||||
if (!dp.CanDelete(Database))
|
||||
throw new InvalidOperationException("The state of this Device Profile doesn't allow it to be deleted");
|
||||
|
||||
// Update Defaults
|
||||
if (Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId == dp.Id)
|
||||
Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId = 1;
|
||||
if (Database.DiscoConfiguration.DeviceProfiles.DefaultAddDeviceOfflineDeviceProfileId == dp.Id)
|
||||
Database.DiscoConfiguration.DeviceProfiles.DefaultAddDeviceOfflineDeviceProfileId = 1;
|
||||
|
||||
// Remove Linked Group
|
||||
ActiveDirectory.Context.ManagedGroups.Remove(DeviceProfileDevicesManagedGroup.GetKey(dp));
|
||||
ActiveDirectory.Context.ManagedGroups.Remove(DeviceProfileAssignedUsersManagedGroup.GetKey(dp));
|
||||
|
||||
// Delete Profile
|
||||
Database.DeviceProfiles.Remove(dp);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
using Disco.BI.DocumentTemplateBI.ManagedGroups;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Documents;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Documents;
|
||||
using Disco.Services.Documents.ManagedGroups;
|
||||
using Disco.Services.Expressions;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using iTextSharp.text.pdf;
|
||||
|
||||
@@ -1,725 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Exceptionless;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.BI.Config;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Plugins;
|
||||
using Disco.Services.Plugins.Features.WarrantyProvider;
|
||||
using Disco.Services.Users;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Plugins.Features.RepairProvider;
|
||||
|
||||
using PublishJobResult = Disco.Models.Services.Interop.DiscoServices.PublishJobResult;
|
||||
using DiscoServicesJobs = Disco.Services.Interop.DiscoServices.Jobs;
|
||||
using Disco.Services;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
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
|
||||
public static bool CanDeviceHeld(this Job j)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.DeviceHeld))
|
||||
return false;
|
||||
|
||||
return (!j.ClosedDate.HasValue) && (j.DeviceSerialNumber != null) &&
|
||||
(!j.DeviceHeld.HasValue || j.DeviceReturnedDate.HasValue);
|
||||
}
|
||||
public static void OnDeviceHeld(this Job j, User Technician)
|
||||
{
|
||||
if (!j.CanDeviceHeld())
|
||||
throw new InvalidOperationException("Holding Device was Denied");
|
||||
|
||||
j.DeviceHeld = DateTime.Now;
|
||||
j.DeviceHeldTechUserId = Technician.UserId;
|
||||
j.DeviceReadyForReturn = null;
|
||||
j.DeviceReadyForReturnTechUserId = null;
|
||||
j.DeviceReturnedDate = null;
|
||||
j.DeviceReturnedTechUserId = null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Device Ready for Return
|
||||
public static bool CanDeviceReadyForReturn(this Job j)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.DeviceReadyForReturn))
|
||||
return false;
|
||||
|
||||
return (!j.ClosedDate.HasValue) && j.DeviceHeld.HasValue &&
|
||||
!j.DeviceReadyForReturn.HasValue && !j.DeviceReturnedDate.HasValue;
|
||||
}
|
||||
public static void OnDeviceReadyForReturn(this Job j, User Technician)
|
||||
{
|
||||
if (!j.CanDeviceReadyForReturn())
|
||||
throw new InvalidOperationException("Device Ready for Return was Denied");
|
||||
|
||||
j.DeviceReadyForReturn = DateTime.Now;
|
||||
j.DeviceReadyForReturnTechUserId = Technician.UserId;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Device Returned
|
||||
public static bool CanDeviceReturned(this Job j)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.DeviceReturned))
|
||||
return false;
|
||||
|
||||
return (!j.ClosedDate.HasValue) && j.DeviceHeld.HasValue &&
|
||||
!j.DeviceReturnedDate.HasValue;
|
||||
}
|
||||
public static void OnDeviceReturned(this Job j, User Technician)
|
||||
{
|
||||
if (!j.CanDeviceReturned())
|
||||
throw new InvalidOperationException("Device Return was Denied");
|
||||
|
||||
j.DeviceReturnedDate = DateTime.Now;
|
||||
j.DeviceReturnedTechUserId = Technician.UserId;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Waiting For User Action
|
||||
public static bool CanWaitingForUserAction(this Job j)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.WaitingForUserAction))
|
||||
return false;
|
||||
|
||||
return !j.ClosedDate.HasValue && (j.UserId != null) && !j.WaitingForUserAction.HasValue;
|
||||
}
|
||||
public static void OnWaitingForUserAction(this Job j, DiscoDataContext Database, User Technician, string Reason)
|
||||
{
|
||||
if (!j.CanWaitingForUserAction())
|
||||
throw new InvalidOperationException("Waiting for User Action was Denied");
|
||||
|
||||
j.WaitingForUserAction = DateTime.Now;
|
||||
|
||||
// Write Log
|
||||
JobLog jobLog = new JobLog()
|
||||
{
|
||||
JobId = j.Id,
|
||||
TechUserId = Technician.UserId,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = string.Format("# Waiting on User Action\r\n{0}", string.IsNullOrWhiteSpace(Reason) ? "<no reason provided>" : Reason)
|
||||
};
|
||||
Database.JobLogs.Add(jobLog);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Not Waiting For User Action
|
||||
public static bool CanNotWaitingForUserAction(this Job j)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.NotWaitingForUserAction))
|
||||
return false;
|
||||
|
||||
return j.WaitingForUserAction.HasValue;
|
||||
}
|
||||
public static void OnNotWaitingForUserAction(this Job j, DiscoDataContext Database, User Technician, string Resolution)
|
||||
{
|
||||
if (!j.CanNotWaitingForUserAction())
|
||||
throw new InvalidOperationException("Not Waiting for User Action was Denied");
|
||||
|
||||
j.WaitingForUserAction = null;
|
||||
|
||||
// Write Log
|
||||
JobLog jobLog = new JobLog()
|
||||
{
|
||||
JobId = j.Id,
|
||||
TechUserId = Technician.UserId,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = string.Format("# User Action Resolved\r\n{0}", string.IsNullOrWhiteSpace(Resolution) ? "<no comment provided>" : Resolution)
|
||||
};
|
||||
Database.JobLogs.Add(jobLog);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Log Warranty
|
||||
public static bool CanLogWarranty(this Job j)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.LogWarranty))
|
||||
return false;
|
||||
|
||||
return !j.ClosedDate.HasValue &&
|
||||
(j.DeviceSerialNumber != null) &&
|
||||
j.JobTypeId == JobType.JobTypeIds.HWar &&
|
||||
!j.JobMetaWarranty.ExternalLoggedDate.HasValue;
|
||||
}
|
||||
public static void OnLogWarranty(this Job j, DiscoDataContext Database, string FaultDescription, List<JobAttachment> SendAttachments, PluginFeatureManifest WarrantyProviderDefinition, OrganisationAddress Address, User TechUser, Dictionary<string, string> WarrantyProviderProperties)
|
||||
{
|
||||
if (!j.CanLogWarranty())
|
||||
throw new InvalidOperationException("Log Warranty was Denied");
|
||||
|
||||
PublishJobResult publishJobResult = null;
|
||||
|
||||
using (WarrantyProviderFeature WarrantyProvider = WarrantyProviderDefinition.CreateInstance<WarrantyProviderFeature>())
|
||||
{
|
||||
if (SendAttachments != null && SendAttachments.Count > 0)
|
||||
{
|
||||
publishJobResult = DiscoServicesJobs.Publish(
|
||||
Database,
|
||||
j,
|
||||
TechUser,
|
||||
WarrantyProvider.WarrantyProviderId,
|
||||
null,
|
||||
FaultDescription,
|
||||
SendAttachments,
|
||||
AttachmentDataStoreExtensions.RepositoryFilename);
|
||||
|
||||
if (!publishJobResult.Success)
|
||||
throw new Exception(string.Format("Disco ICT Online Services failed with the following message: ", publishJobResult.ErrorMessage));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(FaultDescription))
|
||||
FaultDescription = publishJobResult.PublishMessage;
|
||||
else
|
||||
FaultDescription = string.Concat(FaultDescription, Environment.NewLine, "___", Environment.NewLine, publishJobResult.PublishMessage);
|
||||
}
|
||||
|
||||
string submitDescription;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(FaultDescription))
|
||||
submitDescription = j.GenerateFaultDescriptionFooter(Database, WarrantyProviderDefinition);
|
||||
else
|
||||
submitDescription = string.Concat(FaultDescription, Environment.NewLine, Environment.NewLine, j.GenerateFaultDescriptionFooter(Database, WarrantyProviderDefinition));
|
||||
|
||||
string providerRef = WarrantyProvider.SubmitJob(Database, j, Address, TechUser, submitDescription, WarrantyProviderProperties);
|
||||
|
||||
j.JobMetaWarranty.ExternalLoggedDate = DateTime.Now;
|
||||
j.JobMetaWarranty.ExternalName = WarrantyProvider.WarrantyProviderId;
|
||||
|
||||
if (providerRef != null && providerRef.Length > 100)
|
||||
j.JobMetaWarranty.ExternalReference = providerRef.Substring(0, 100);
|
||||
else
|
||||
j.JobMetaWarranty.ExternalReference = providerRef;
|
||||
|
||||
// Write Log
|
||||
JobLog jobLog = new JobLog()
|
||||
{
|
||||
JobId = j.Id,
|
||||
TechUserId = TechUser.UserId,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = string.Format("# Warranty Claim Submitted\r\nProvider: **{0}**\r\nAddress: **{1}**\r\nReference: **{2}**\r\n___\r\n```{3}```", WarrantyProvider.Manifest.Name, Address.Name, providerRef, FaultDescription)
|
||||
};
|
||||
Database.JobLogs.Add(jobLog);
|
||||
|
||||
if (publishJobResult != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
DiscoServicesJobs.UpdateRecipientReference(Database, j, publishJobResult.Id, publishJobResult.Secret, j.JobMetaWarranty.ExternalReference);
|
||||
}
|
||||
catch (Exception ex) { ex.ToExceptionless().Submit(); } // Ignore Errors as this is not completely necessary
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void OnLogWarranty(this Job j, DiscoDataContext Database, string FaultDescription, string ManualProviderName, string ManualProviderReference, OrganisationAddress Address, User TechUser)
|
||||
{
|
||||
if (!j.CanLogWarranty())
|
||||
throw new InvalidOperationException("Log Warranty was Denied");
|
||||
|
||||
j.JobMetaWarranty.ExternalLoggedDate = DateTime.Now;
|
||||
j.JobMetaWarranty.ExternalName = ManualProviderName;
|
||||
|
||||
if (ManualProviderReference != null && ManualProviderReference.Length > 100)
|
||||
j.JobMetaWarranty.ExternalReference = ManualProviderReference.Substring(0, 100);
|
||||
else
|
||||
j.JobMetaWarranty.ExternalReference = ManualProviderReference;
|
||||
|
||||
// Write Log
|
||||
JobLog jobLog = new JobLog()
|
||||
{
|
||||
JobId = j.Id,
|
||||
TechUserId = TechUser.UserId,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = string.Format("# Manual Warranty Claim Submitted\r\nProvider: **{0}**\r\nAddress: **{1}**\r\nReference: **{2}**\r\n___\r\n```{3}```", ManualProviderName, Address.Name, ManualProviderReference ?? "<none>", FaultDescription)
|
||||
};
|
||||
Database.JobLogs.Add(jobLog);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Convert HWar to HNWar
|
||||
public static bool CanConvertHWarToHNWar(this Job j)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.ConvertHWarToHNWar))
|
||||
return false;
|
||||
|
||||
return !j.ClosedDate.HasValue && (j.DeviceSerialNumber != null) &&
|
||||
j.JobTypeId == JobType.JobTypeIds.HWar && string.IsNullOrEmpty(j.JobMetaWarranty.ExternalReference);
|
||||
}
|
||||
public static void OnConvertHWarToHNWar(this Job j, DiscoDataContext Database)
|
||||
{
|
||||
if (!j.CanConvertHWarToHNWar())
|
||||
throw new InvalidOperationException("Convert HWar to HNWar was Denied");
|
||||
|
||||
var techUser = UserService.CurrentUser;
|
||||
|
||||
// Remove JobMetaWarranty
|
||||
if (j.JobMetaWarranty != null)
|
||||
Database.JobMetaWarranties.Remove(j.JobMetaWarranty);
|
||||
|
||||
// Add JobMetaNonWarranty
|
||||
var metaHNWar = new JobMetaNonWarranty() { Job = j };
|
||||
Database.JobMetaNonWarranties.Add(metaHNWar);
|
||||
|
||||
// Swap Job Sub Types
|
||||
List<string> jobSubTypes = j.JobSubTypes.Select(jst => jst.Id).ToList();
|
||||
j.JobSubTypes.Clear();
|
||||
foreach (var jst in Database.JobSubTypes.Where(i => i.JobTypeId == JobType.JobTypeIds.HNWar && jobSubTypes.Contains(i.Id)))
|
||||
j.JobSubTypes.Add(jst);
|
||||
|
||||
// Add Components
|
||||
var components = Database.DeviceComponents.Include("JobSubTypes").Where(c => !c.DeviceModelId.HasValue || c.DeviceModelId == j.Device.DeviceModelId);
|
||||
var jobComponents = new List<DeviceComponent>();
|
||||
foreach (var component in components)
|
||||
{
|
||||
if (component.JobSubTypes.Count == 0)
|
||||
{
|
||||
jobComponents.Add(component);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var st in component.JobSubTypes)
|
||||
{
|
||||
foreach (var jst in j.JobSubTypes)
|
||||
{
|
||||
if (st.JobTypeId == jst.JobTypeId && st.Id == jst.Id)
|
||||
{
|
||||
jobComponents.Add(component);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (jobComponents.Contains(component))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (var component in jobComponents)
|
||||
{
|
||||
Database.JobComponents.Add(new JobComponent()
|
||||
{
|
||||
Job = j,
|
||||
TechUserId = techUser.UserId,
|
||||
Cost = component.Cost,
|
||||
Description = component.Description
|
||||
});
|
||||
}
|
||||
|
||||
// Write Log
|
||||
JobLog jobLog = new JobLog()
|
||||
{
|
||||
JobId = j.Id,
|
||||
TechUserId = techUser.UserId,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = string.Format("# Job Type Converted\r\nFrom: **{0}**\r\nTo: **{1}**", Database.JobTypes.Find(JobType.JobTypeIds.HWar), Database.JobTypes.Find(JobType.JobTypeIds.HNWar))
|
||||
};
|
||||
Database.JobLogs.Add(jobLog);
|
||||
|
||||
j.JobTypeId = JobType.JobTypeIds.HNWar;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Warranty Completed
|
||||
public static bool CanWarrantyCompleted(this Job j)
|
||||
{
|
||||
return (j.JobTypeId == JobType.JobTypeIds.HWar) &&
|
||||
j.JobMetaWarranty.ExternalLoggedDate.HasValue &&
|
||||
!j.JobMetaWarranty.ExternalCompletedDate.HasValue;
|
||||
}
|
||||
public static void OnWarrantyCompleted(this Job j)
|
||||
{
|
||||
if (!j.CanWarrantyCompleted())
|
||||
throw new InvalidOperationException("Warranty Completed was Denied");
|
||||
|
||||
j.JobMetaWarranty.ExternalCompletedDate = DateTime.Now;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Insurance Claim Form Sent
|
||||
public static bool CanInsuranceClaimFormSent(this Job j)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.NonWarrantyProperties.InsuranceClaimFormSent))
|
||||
return false;
|
||||
|
||||
return (j.JobTypeId == JobType.JobTypeIds.HNWar) &&
|
||||
j.JobMetaNonWarranty.IsInsuranceClaim &&
|
||||
!j.JobMetaInsurance.ClaimFormSentDate.HasValue;
|
||||
}
|
||||
public static void OnInsuranceClaimFormSent(this Job j)
|
||||
{
|
||||
if (!j.CanInsuranceClaimFormSent())
|
||||
throw new InvalidOperationException("Insurance Claim Form Sent was Denied");
|
||||
|
||||
var techUser = UserService.CurrentUser;
|
||||
|
||||
j.JobMetaInsurance.ClaimFormSentDate = DateTime.Now;
|
||||
j.JobMetaInsurance.ClaimFormSentUserId = techUser.UserId;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Log Repair
|
||||
public static bool CanLogRepair(this Job j)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.LogRepair))
|
||||
return false;
|
||||
|
||||
return (j.JobTypeId == JobType.JobTypeIds.HNWar) &&
|
||||
(j.DeviceSerialNumber != null) &&
|
||||
!j.JobMetaNonWarranty.RepairerLoggedDate.HasValue &&
|
||||
!j.JobMetaNonWarranty.RepairerCompletedDate.HasValue;
|
||||
}
|
||||
public static void OnLogRepair(this Job j, DiscoDataContext Database, string RepairDescription, List<JobAttachment> SendAttachments, PluginFeatureManifest RepairProviderDefinition, OrganisationAddress Address, User TechUser, Dictionary<string, string> RepairProviderProperties)
|
||||
{
|
||||
if (!j.CanLogRepair())
|
||||
throw new InvalidOperationException("Log Repair was Denied");
|
||||
|
||||
PublishJobResult publishJobResult = null;
|
||||
|
||||
using (RepairProviderFeature RepairProvider = RepairProviderDefinition.CreateInstance<RepairProviderFeature>())
|
||||
{
|
||||
if (SendAttachments != null && SendAttachments.Count > 0)
|
||||
{
|
||||
publishJobResult = DiscoServicesJobs.Publish(
|
||||
Database,
|
||||
j,
|
||||
TechUser,
|
||||
RepairProvider.ProviderId,
|
||||
null,
|
||||
RepairDescription,
|
||||
SendAttachments,
|
||||
AttachmentDataStoreExtensions.RepositoryFilename);
|
||||
|
||||
if (!publishJobResult.Success)
|
||||
throw new Exception(string.Format("Disco ICT Online Services failed with the following message: ", publishJobResult.ErrorMessage));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(RepairDescription))
|
||||
RepairDescription = publishJobResult.PublishMessage;
|
||||
else
|
||||
RepairDescription = string.Concat(RepairDescription, Environment.NewLine, "___", Environment.NewLine, publishJobResult.PublishMessage);
|
||||
}
|
||||
|
||||
string submitDescription;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(RepairDescription))
|
||||
submitDescription = j.GenerateFaultDescriptionFooter(Database, RepairProviderDefinition);
|
||||
else
|
||||
submitDescription = string.Concat(RepairDescription, Environment.NewLine, Environment.NewLine, j.GenerateFaultDescriptionFooter(Database, RepairProviderDefinition));
|
||||
|
||||
string providerRef = RepairProvider.SubmitJob(Database, j, Address, TechUser, submitDescription, RepairProviderProperties);
|
||||
|
||||
j.JobMetaNonWarranty.RepairerLoggedDate = DateTime.Now;
|
||||
j.JobMetaNonWarranty.RepairerName = RepairProvider.ProviderId;
|
||||
|
||||
if (providerRef != null && providerRef.Length > 100)
|
||||
j.JobMetaNonWarranty.RepairerReference = providerRef.Substring(0, 100);
|
||||
else
|
||||
j.JobMetaNonWarranty.RepairerReference = providerRef;
|
||||
|
||||
// Write Log
|
||||
JobLog jobLog = new JobLog()
|
||||
{
|
||||
JobId = j.Id,
|
||||
TechUserId = TechUser.UserId,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = string.Format("# Repair Request Submitted\r\nProvider: **{0}**\r\nAddress: **{1}**\r\nReference: **{2}**\r\n___\r\n```{3}```", RepairProvider.Manifest.Name, Address.Name, providerRef, RepairDescription)
|
||||
};
|
||||
Database.JobLogs.Add(jobLog);
|
||||
|
||||
if (publishJobResult != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
DiscoServicesJobs.UpdateRecipientReference(Database, j, publishJobResult.Id, publishJobResult.Secret, j.JobMetaNonWarranty.RepairerReference);
|
||||
}
|
||||
catch (Exception ex) { ex.ToExceptionless().Submit(); } // Ignore Errors as this is not completely necessary
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void OnLogRepair(this Job j, DiscoDataContext Database, string FaultDescription, string ManualProviderName, string ManualProviderReference, OrganisationAddress Address, User TechUser)
|
||||
{
|
||||
if (!j.CanLogRepair())
|
||||
throw new InvalidOperationException("Log Repair was Denied");
|
||||
|
||||
j.JobMetaNonWarranty.RepairerLoggedDate = DateTime.Now;
|
||||
j.JobMetaNonWarranty.RepairerName = ManualProviderName;
|
||||
|
||||
if (ManualProviderReference != null && ManualProviderReference.Length > 100)
|
||||
j.JobMetaNonWarranty.RepairerReference = ManualProviderReference.Substring(0, 100);
|
||||
else
|
||||
j.JobMetaNonWarranty.RepairerReference = ManualProviderReference;
|
||||
|
||||
// Write Log
|
||||
JobLog jobLog = new JobLog()
|
||||
{
|
||||
JobId = j.Id,
|
||||
TechUserId = TechUser.UserId,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = string.Format("# Manual Repair Request Submitted\r\nProvider: **{0}**\r\nAddress: **{1}**\r\nReference: **{2}**\r\n___\r\n```{3}```", ManualProviderName, Address.Name, ManualProviderReference ?? "<none>", FaultDescription)
|
||||
};
|
||||
Database.JobLogs.Add(jobLog);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Repair Complete
|
||||
public static bool CanRepairComplete(this Job j)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.NonWarrantyProperties.RepairerCompletedDate))
|
||||
return false;
|
||||
|
||||
return (j.JobTypeId == JobType.JobTypeIds.HNWar) &&
|
||||
j.JobMetaNonWarranty.RepairerLoggedDate.HasValue &&
|
||||
!j.JobMetaNonWarranty.RepairerCompletedDate.HasValue;
|
||||
}
|
||||
public static void OnRepairComplete(this Job j)
|
||||
{
|
||||
if (!j.CanRepairComplete())
|
||||
throw new InvalidOperationException("Repair Complete was Denied");
|
||||
|
||||
j.JobMetaNonWarranty.RepairerCompletedDate = DateTime.Now;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Close
|
||||
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))
|
||||
return true;
|
||||
|
||||
if (j.ClosedDate.HasValue)
|
||||
return true; // Job already Closed
|
||||
|
||||
if (j.DeviceHeld.HasValue && !j.DeviceReturnedDate.HasValue)
|
||||
return true; // Device not returned to User
|
||||
|
||||
if (j.WaitingForUserAction.HasValue)
|
||||
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)
|
||||
{
|
||||
case JobType.JobTypeIds.HWar:
|
||||
|
||||
if (!string.IsNullOrEmpty(j.JobMetaWarranty.ExternalReference) && !j.JobMetaWarranty.ExternalCompletedDate.HasValue)
|
||||
return false; // Job Logged (Warranty) but not completed
|
||||
|
||||
break;
|
||||
case JobType.JobTypeIds.HNWar:
|
||||
|
||||
if (j.JobMetaNonWarranty.RepairerLoggedDate.HasValue && !j.JobMetaNonWarranty.RepairerCompletedDate.HasValue)
|
||||
return false; // Job Logged (Repair) but not completed
|
||||
|
||||
if (j.JobMetaNonWarranty.AccountingChargeRequiredDate.HasValue && !j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue)
|
||||
return false; // Accounting Charge Required, but not added
|
||||
|
||||
if ((j.JobMetaNonWarranty.AccountingChargeRequiredDate.HasValue || j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue) && !j.JobMetaNonWarranty.AccountingChargePaidDate.HasValue)
|
||||
return false; // Accounting Charge Required or Added, but not paid
|
||||
|
||||
if (j.JobMetaNonWarranty.IsInsuranceClaim && !j.JobMetaInsurance.ClaimFormSentDate.HasValue)
|
||||
return false; // Is Insurance Claim, but claim form not sent
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool CanCloseJobNormallyAfterRemoved(this JobQueueJob jqj)
|
||||
{
|
||||
if (jqj.Job.CanCloseNever(jqj))
|
||||
return false;
|
||||
|
||||
return jqj.Job.CanCloseNormallyInternal();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Force Close
|
||||
public static bool CanCloseForced(this Job j)
|
||||
{
|
||||
List<string> reasons;
|
||||
|
||||
return CanCloseForced(j, out reasons);
|
||||
}
|
||||
public static bool CanCloseForced(this Job j, out List<string> Reasons)
|
||||
{
|
||||
Reasons = null;
|
||||
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.ForceClose))
|
||||
return false;
|
||||
|
||||
if (j.CanCloseNever())
|
||||
return false;
|
||||
|
||||
if (j.CanCloseNormally())
|
||||
return false;
|
||||
|
||||
Reasons = new List<string>();
|
||||
|
||||
switch (j.JobTypeId)
|
||||
{
|
||||
case JobType.JobTypeIds.HWar:
|
||||
if (!string.IsNullOrEmpty(j.JobMetaWarranty.ExternalReference) && !j.JobMetaWarranty.ExternalCompletedDate.HasValue)
|
||||
Reasons.Add("Warranty Job Not Completed"); // Job Logged (Warranty) but not completed
|
||||
break;
|
||||
case JobType.JobTypeIds.HNWar:
|
||||
|
||||
if (j.JobMetaNonWarranty.RepairerLoggedDate.HasValue && !j.JobMetaNonWarranty.RepairerCompletedDate.HasValue)
|
||||
Reasons.Add("Repair Job Not Completed"); // Job Logged (Repair) but not completed
|
||||
|
||||
if (j.JobMetaNonWarranty.AccountingChargeRequiredDate.HasValue && (!j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue && !j.JobMetaNonWarranty.AccountingChargePaidDate.HasValue))
|
||||
Reasons.Add("Accounting Charge Required But Not Added Or Paid"); // Accounting Charge Required, but not added or paid
|
||||
else if (j.JobMetaNonWarranty.AccountingChargeRequiredDate.HasValue && !j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue)
|
||||
Reasons.Add("Accounting Charge Required But Not Added"); // Accounting Charge Required, but not added
|
||||
else if (j.JobMetaNonWarranty.AccountingChargeAddedDate.HasValue && !j.JobMetaNonWarranty.AccountingChargePaidDate.HasValue)
|
||||
Reasons.Add("Accounting Charge Added But Not Paid"); // Accounting Charge Added, but not paid
|
||||
else if (j.JobMetaNonWarranty.AccountingChargeRequiredDate.HasValue && !j.JobMetaNonWarranty.AccountingChargePaidDate.HasValue)
|
||||
Reasons.Add("Accounting Charge Required But Not Paid"); // Accounting Charge Required, but not paid
|
||||
|
||||
if (j.JobMetaNonWarranty.IsInsuranceClaim && !j.JobMetaInsurance.ClaimFormSentDate.HasValue)
|
||||
Reasons.Add("Insurance Claim Form Not Sent"); // Is Insurance Claim, but claim form not sent
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return (Reasons.Count > 0);
|
||||
}
|
||||
public static void OnCloseForced(this Job j, DiscoDataContext Database, User Technician, string Reason)
|
||||
{
|
||||
if (!j.CanCloseForced())
|
||||
throw new InvalidOperationException("Force Close was Denied");
|
||||
|
||||
// Write Log
|
||||
JobLog jobLog = new JobLog()
|
||||
{
|
||||
JobId = j.Id,
|
||||
TechUserId = Technician.UserId,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = string.Format("# Job Forcibly Closed\r\n{0}", string.IsNullOrWhiteSpace(Reason) ? "<no reason provided>" : Reason)
|
||||
};
|
||||
Database.JobLogs.Add(jobLog);
|
||||
|
||||
j.ClosedDate = DateTime.Now;
|
||||
j.ClosedTechUserId = Technician.UserId;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Reopen
|
||||
public static bool CanReopen(this Job j)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.Reopen))
|
||||
return false;
|
||||
|
||||
return j.ClosedDate.HasValue;
|
||||
}
|
||||
public static void OnReopen(this Job j)
|
||||
{
|
||||
if (!j.CanReopen())
|
||||
throw new InvalidOperationException("Reopen was Denied");
|
||||
|
||||
j.ClosedDate = null;
|
||||
j.ClosedTechUserId = null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Delete
|
||||
public static bool CanDelete(this Job j)
|
||||
{
|
||||
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.Delete))
|
||||
return false;
|
||||
|
||||
return j.ClosedDate.HasValue;
|
||||
}
|
||||
public static void OnDelete(this Job j, DiscoDataContext Database)
|
||||
{
|
||||
// Job Sub Types
|
||||
j.JobSubTypes.Clear();
|
||||
|
||||
// Job Attachments
|
||||
foreach (var ja in j.JobAttachments.ToArray())
|
||||
ja.OnDelete(Database);
|
||||
j.JobAttachments.Clear();
|
||||
|
||||
// Job Components
|
||||
foreach (var jc in j.JobComponents.ToArray())
|
||||
Database.JobComponents.Remove(jc);
|
||||
j.JobComponents.Clear();
|
||||
|
||||
// Job Queue Jobs
|
||||
foreach (var jqj in j.JobQueues.ToArray())
|
||||
Database.JobQueueJobs.Remove(jqj);
|
||||
j.JobQueues.Clear();
|
||||
|
||||
// Job Logs
|
||||
foreach (var jl in j.JobLogs.ToArray())
|
||||
Database.JobLogs.Remove(jl);
|
||||
j.JobLogs.Clear();
|
||||
|
||||
// Job Meta
|
||||
if (j.JobMetaInsurance != null)
|
||||
{
|
||||
Database.JobMetaInsurances.Remove(j.JobMetaInsurance);
|
||||
j.JobMetaInsurance = null;
|
||||
}
|
||||
if (j.JobMetaNonWarranty != null)
|
||||
{
|
||||
Database.JobMetaNonWarranties.Remove(j.JobMetaNonWarranty);
|
||||
j.JobMetaNonWarranty = null;
|
||||
}
|
||||
if (j.JobMetaWarranty != null)
|
||||
{
|
||||
Database.JobMetaWarranties.Remove(j.JobMetaWarranty);
|
||||
j.JobMetaWarranty = null;
|
||||
}
|
||||
|
||||
// Job
|
||||
Database.Jobs.Remove(j);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Documents;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Plugins;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class JobExtensions
|
||||
{
|
||||
public static List<DocumentTemplate> AvailableDocumentTemplates(this Job j, DiscoDataContext Database, User User, DateTime TimeStamp)
|
||||
{
|
||||
var dts = Database.DocumentTemplates.Include("JobSubTypes")
|
||||
.Where(dt => dt.Scope == DocumentTemplate.DocumentTemplateScopes.Job)
|
||||
.ToList();
|
||||
|
||||
foreach (var dt in dts.ToArray())
|
||||
{
|
||||
if (dt.JobSubTypes.Count != 0)
|
||||
{ // Filter Applied
|
||||
bool match = false;
|
||||
foreach (var st in j.JobSubTypes)
|
||||
{
|
||||
if (dt.JobSubTypes.Contains(st))
|
||||
{
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match)
|
||||
dts.Remove(dt);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate Filters
|
||||
dts = dts.Where(dt => dt.FilterExpressionMatches(j, Database, User, TimeStamp, DocumentState.DefaultState())).ToList();
|
||||
|
||||
return dts;
|
||||
}
|
||||
|
||||
public static DateTime ValidateDateAfterOpened(this Job j, DateTime d)
|
||||
{
|
||||
if (d < j.OpenedDate)
|
||||
{
|
||||
if (d > j.OpenedDate.AddMinutes(-1))
|
||||
return j.OpenedDate;
|
||||
else
|
||||
throw new ArgumentException("The Date must be >= the Open Date.", "d");
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
public static string GenerateFaultDescription(this Job j, DiscoDataContext Database)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("Faulty Components:");
|
||||
foreach (var jst in j.JobSubTypes)
|
||||
sb.Append("- ").AppendLine(jst.Description).AppendLine(" - ");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string GenerateFaultDescriptionFooter(this Job j, DiscoDataContext Database, PluginFeatureManifest WarrantyProviderDefinition)
|
||||
{
|
||||
var versionDisco = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
|
||||
return string.Format("Automation by Disco v{0}.{1}.{2:0000}.{3:0000} (Provider: {4} v{5})",
|
||||
versionDisco.Major, versionDisco.Minor, versionDisco.Build, versionDisco.Revision, WarrantyProviderDefinition.Id, WarrantyProviderDefinition.PluginManifest.Version.ToString(4));
|
||||
}
|
||||
|
||||
public static void UpdateSubTypes(this Job j, DiscoDataContext Database, List<JobSubType> SubTypes, bool AddComponents, User TechUser)
|
||||
{
|
||||
if (SubTypes == null || SubTypes.Count == 0)
|
||||
throw new ArgumentException("The Job must contain at least one Sub Type");
|
||||
|
||||
List<JobSubType> addedSubTypes = new List<JobSubType>();
|
||||
List<JobSubType> removedSubTypes = new List<JobSubType>();
|
||||
|
||||
// Removed Sub Types
|
||||
foreach (var t in j.JobSubTypes.ToArray())
|
||||
if (!SubTypes.Contains(t))
|
||||
{
|
||||
removedSubTypes.Add(t);
|
||||
j.JobSubTypes.Remove(t);
|
||||
}
|
||||
// Added Sub Types
|
||||
foreach (var t in SubTypes)
|
||||
if (!j.JobSubTypes.Contains(t))
|
||||
{
|
||||
addedSubTypes.Add(t);
|
||||
j.JobSubTypes.Add(t);
|
||||
}
|
||||
|
||||
// Write Log
|
||||
if (addedSubTypes.Count > 0 || removedSubTypes.Count > 0)
|
||||
{
|
||||
StringBuilder logBuilder = new StringBuilder();
|
||||
logBuilder.AppendLine("# Updated Job Sub Types");
|
||||
if (removedSubTypes.Count > 0)
|
||||
{
|
||||
logBuilder.AppendLine().AppendLine("Removed:");
|
||||
foreach (var t in removedSubTypes)
|
||||
logBuilder.Append("- **").Append(t.ToString()).AppendLine("**");
|
||||
}
|
||||
if (addedSubTypes.Count > 0)
|
||||
{
|
||||
logBuilder.AppendLine().AppendLine("Added:");
|
||||
foreach (var t in addedSubTypes)
|
||||
logBuilder.Append("- **").Append(t.ToString()).AppendLine("**");
|
||||
}
|
||||
Database.JobLogs.Add(new JobLog()
|
||||
{
|
||||
JobId = j.Id,
|
||||
TechUserId = TechUser.UserId,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = logBuilder.ToString()
|
||||
});
|
||||
}
|
||||
|
||||
// Add Components
|
||||
if (AddComponents && addedSubTypes.Count > 0 && j.DeviceSerialNumber != null)
|
||||
{
|
||||
var components = Database.DeviceComponents.Include("JobSubTypes").Where(c => !c.DeviceModelId.HasValue || c.DeviceModelId == j.Device.DeviceModelId);
|
||||
var addedComponents = new List<DeviceComponent>();
|
||||
foreach (var c in components)
|
||||
{
|
||||
foreach (var st in c.JobSubTypes)
|
||||
{
|
||||
foreach (var jst in addedSubTypes)
|
||||
{
|
||||
if (st.JobTypeId == jst.JobTypeId && st.Id == jst.Id)
|
||||
{
|
||||
addedComponents.Add(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (addedComponents.Contains(c))
|
||||
break;
|
||||
}
|
||||
}
|
||||
foreach (var c in addedComponents)
|
||||
{
|
||||
if (!j.JobComponents.Any(jc => jc.Description.Equals(c.Description, StringComparison.OrdinalIgnoreCase)))
|
||||
{ // Job Component with matching Description doesn't exist.
|
||||
Database.JobComponents.Add(new JobComponent()
|
||||
{
|
||||
Job = j,
|
||||
TechUserId = TechUser.UserId,
|
||||
Cost = c.Cost,
|
||||
Description = c.Description
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.Repository;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class JobFlagExtensions
|
||||
{
|
||||
|
||||
private static Dictionary<string, Dictionary<long, string>> allFlags;
|
||||
private static void CacheAllFlags()
|
||||
{
|
||||
if (allFlags == null)
|
||||
{
|
||||
var fType = typeof(Job.UserManagementFlags);
|
||||
var fMembers = fType.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
|
||||
|
||||
var flags = new Dictionary<string, Dictionary<long, string>>();
|
||||
foreach (var f in fMembers)
|
||||
{
|
||||
DisplayAttribute display = (DisplayAttribute)(f.GetCustomAttributes(typeof(DisplayAttribute), false)[0]);
|
||||
string gn = display.GroupName;
|
||||
Dictionary<long, string> g;
|
||||
if (!flags.TryGetValue(gn, out g))
|
||||
{
|
||||
g = new Dictionary<long, string>();
|
||||
flags.Add(gn, g);
|
||||
}
|
||||
g[(long)f.GetRawConstantValue()] = display.Name;
|
||||
}
|
||||
allFlags = flags;
|
||||
}
|
||||
}
|
||||
|
||||
public static Dictionary<string, List<Tuple<long, string, bool>>> ValidFlagsGrouped(this Job j)
|
||||
{
|
||||
Dictionary<string, List<Tuple<long, string, bool>>> validFlags = new Dictionary<string, List<Tuple<long, string, bool>>>();
|
||||
|
||||
CacheAllFlags();
|
||||
|
||||
var currentFlags = (long)(j.Flags ?? 0);
|
||||
|
||||
foreach (var jt in j.JobSubTypes)
|
||||
{
|
||||
Dictionary<long, string> g;
|
||||
if (allFlags.TryGetValue(jt.Id, out g))
|
||||
{
|
||||
validFlags[jt.Id] = g.Select(f => new Tuple<long, string, bool>(f.Key, f.Value, ((currentFlags & f.Key) == f.Key))).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
validFlags[jt.Id] = null;
|
||||
}
|
||||
}
|
||||
return validFlags;
|
||||
}
|
||||
public static Dictionary<long, Tuple<string, bool>> ValidFlags(this Job j)
|
||||
{
|
||||
Dictionary<long, Tuple<string, bool>> validFlags = new Dictionary<long, Tuple<string, bool>>();
|
||||
|
||||
CacheAllFlags();
|
||||
|
||||
var currentFlags = (long)(j.Flags ?? 0);
|
||||
|
||||
foreach (var jt in j.JobSubTypes)
|
||||
{
|
||||
Dictionary<long, string> g;
|
||||
if (allFlags.TryGetValue(jt.Id, out g))
|
||||
{
|
||||
foreach (var f in g)
|
||||
validFlags[f.Key] = new Tuple<string, bool>(string.Format("{0}: {1}", jt.Description, f.Value), ((currentFlags & f.Key) == f.Key));
|
||||
}
|
||||
}
|
||||
return validFlags;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
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,36 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Documents;
|
||||
using Disco.Services;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class UserExtensions
|
||||
{
|
||||
public static List<DocumentTemplate> AvailableDocumentTemplates(this User u, DiscoDataContext Database, User User, DateTime TimeStamp)
|
||||
{
|
||||
var dts = Database.DocumentTemplates.Include("JobSubTypes")
|
||||
.Where(dt => dt.Scope == DocumentTemplate.DocumentTemplateScopes.User)
|
||||
.ToArray()
|
||||
.Where(dt => dt.FilterExpressionMatches(u, Database, User, TimeStamp, DocumentState.DefaultState())).ToList();
|
||||
|
||||
return dts;
|
||||
}
|
||||
|
||||
public static List<DeviceUserAssignment> CurrentDeviceUserAssignments(this User u)
|
||||
{
|
||||
return u.DeviceUserAssignments.Where(dua => !dua.UnassignedDate.HasValue).ToList();
|
||||
}
|
||||
|
||||
public static bool CanCreateJob(this User u)
|
||||
{
|
||||
if (!JobActionExtensions.CanCreate())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
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
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.IO;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class UtilityExtensions
|
||||
{
|
||||
|
||||
public static string StreamToString(this System.IO.Stream stream)
|
||||
{
|
||||
if (stream.Position != 0 && stream.CanSeek)
|
||||
{
|
||||
stream.Position = 0;
|
||||
}
|
||||
using (System.IO.StreamReader sr = new System.IO.StreamReader(stream))
|
||||
{
|
||||
return sr.ReadToEnd();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using Disco.Models.Repository;
|
||||
using System;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class WirelessCertificateExtensions
|
||||
{
|
||||
public static System.DateTime? CertificateExpirationDate(this DeviceCertificate wc)
|
||||
{
|
||||
if (wc.Content == null || wc.Content.Length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
X509Certificate2 c = new X509Certificate2(wc.Content, "password");
|
||||
return c.NotAfter;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ namespace Disco.BI.Interop.Pdf
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream bulkPdf = DocumentTemplateBI.Utilities.JoinPdfs(generatedPdfs.ToArray());
|
||||
Stream bulkPdf = Utilities.JoinPdfs(generatedPdfs.ToArray());
|
||||
foreach (Stream singlePdf in generatedPdfs)
|
||||
singlePdf.Dispose();
|
||||
return bulkPdf;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using iTextSharp.text;
|
||||
using iTextSharp.text.pdf;
|
||||
|
||||
namespace Disco.BI.DocumentTemplateBI
|
||||
namespace Disco.BI.Interop.Pdf
|
||||
{
|
||||
public static class Utilities
|
||||
{
|
||||
@@ -1,173 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Quartz;
|
||||
using Disco.Models.BI.Job.Statistics;
|
||||
using Disco.Data.Repository;
|
||||
using Quartz.Impl;
|
||||
using Disco.Services.Tasks;
|
||||
using System.Reactive.Linq;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Data.Repository.Monitor;
|
||||
|
||||
namespace Disco.BI.JobBI.Statistics
|
||||
{
|
||||
public class DailyOpenedClosed : ScheduledTask
|
||||
{
|
||||
|
||||
private static List<DailyOpenedClosedItem> _data;
|
||||
private static object _dataLock = new object();
|
||||
private static IDisposable _streamSubscription;
|
||||
|
||||
|
||||
public override string TaskName { get { return "Job Statistics - Daily Opened/Closed Task"; } }
|
||||
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)
|
||||
{
|
||||
// Trigger Daily @ 12:29am
|
||||
TriggerBuilder triggerBuilder = TriggerBuilder.Create().WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(0, 29));
|
||||
|
||||
this.ScheduleTask(triggerBuilder);
|
||||
}
|
||||
protected override void ExecuteTask()
|
||||
{
|
||||
using (var database = new DiscoDataContext())
|
||||
{
|
||||
UpdateDataHistory(database, true);
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateDataHistory(DiscoDataContext Database, bool Refresh = false)
|
||||
{
|
||||
DateTime historyEnd = DateTime.Now.Date;
|
||||
|
||||
if (Refresh || _data == null || _data.Count == 0 || _data.Last().Timestamp < historyEnd)
|
||||
{
|
||||
lock (_dataLock)
|
||||
{
|
||||
if (Refresh || _data == null || _data.Count == 0 || _data.Last().Timestamp < historyEnd)
|
||||
{
|
||||
DateTime historyStart = DateTime.Now.AddDays(-28).Date;
|
||||
|
||||
// Initialize Memory Store
|
||||
List<DailyOpenedClosedItem> resultData;
|
||||
if (Refresh || _data == null)
|
||||
resultData = new List<DailyOpenedClosedItem>();
|
||||
else
|
||||
resultData = _data;
|
||||
|
||||
// Remove Old Data
|
||||
while (resultData.Count > 0 && resultData[0].Timestamp < historyStart)
|
||||
resultData.RemoveAt(0);
|
||||
|
||||
// Calculate Update Scope
|
||||
DateTime processDate = historyStart;
|
||||
if (resultData.Count > 0)
|
||||
processDate = resultData.Last().Timestamp.AddDays(-1);
|
||||
|
||||
// Cache Data
|
||||
while (processDate <= historyEnd)
|
||||
{
|
||||
resultData.Add(Data(Database, processDate));
|
||||
processDate = processDate.AddDays(1);
|
||||
}
|
||||
_data = resultData;
|
||||
|
||||
// Subscribe to Live Repository Events
|
||||
if (_streamSubscription != null)
|
||||
_streamSubscription.Dispose();
|
||||
_streamSubscription = Disco.Data.Repository.Monitor.RepositoryMonitor.StreamBeforeCommit.Where(
|
||||
e => e.EntityType == typeof(Job) &&
|
||||
(e.EventType == RepositoryMonitorEventType.Added || (e.EventType == RepositoryMonitorEventType.Modified && e.ModifiedProperties.Contains("ClosedDate")))).Subscribe(RepositoryEvent_JobChange);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void RepositoryEvent_JobChange(RepositoryMonitorEvent e)
|
||||
{
|
||||
|
||||
if (e.EventType == RepositoryMonitorEventType.Added)
|
||||
{
|
||||
// New Job
|
||||
var todaysStats = _data.Last();
|
||||
todaysStats.OpenedJobs += 1;
|
||||
todaysStats.TotalJobs += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DateTime? previousValue = e.GetPreviousPropertyValue<DateTime?>("ClosedDate");
|
||||
|
||||
if (previousValue.HasValue)
|
||||
{
|
||||
// Remove Statistics
|
||||
var statItem = _data.FirstOrDefault(i => i.Timestamp == previousValue.Value.Date);
|
||||
if (statItem != null)
|
||||
{
|
||||
statItem.ClosedJobs -= 1;
|
||||
statItem.TotalJobs += 1;
|
||||
}
|
||||
foreach (var affectedStat in _data.Where(i => i.Timestamp > previousValue))
|
||||
{
|
||||
affectedStat.TotalJobs += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DateTime? currentValue = e.GetCurrentPropertyValue<DateTime?>("ClosedDate");
|
||||
|
||||
if (currentValue.HasValue)
|
||||
{
|
||||
// Add Statistics
|
||||
// Remove Statistics
|
||||
var statItem = _data.FirstOrDefault(i => i.Timestamp == currentValue.Value.Date);
|
||||
if (statItem != null)
|
||||
{
|
||||
statItem.ClosedJobs += 1;
|
||||
statItem.TotalJobs -= 1;
|
||||
}
|
||||
foreach (var affectedStat in _data.Where(i => i.Timestamp > currentValue))
|
||||
{
|
||||
affectedStat.TotalJobs -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static DailyOpenedClosedItem Data(DiscoDataContext Database, DateTime ProcessDate)
|
||||
{
|
||||
DateTime processDateStart = ProcessDate;
|
||||
DateTime processDateEnd = ProcessDate.AddDays(1);
|
||||
|
||||
int totalJobs = Database.Jobs.Where(j => j.OpenedDate < processDateEnd && (!j.ClosedDate.HasValue || j.ClosedDate > processDateEnd)).Count();
|
||||
int openedJobs = Database.Jobs.Where(j => j.OpenedDate > processDateStart && j.OpenedDate < processDateEnd).Count();
|
||||
int closedJobs = Database.Jobs.Where(j => j.ClosedDate > processDateStart && j.ClosedDate < processDateEnd).Count();
|
||||
|
||||
return new DailyOpenedClosedItem()
|
||||
{
|
||||
Timestamp = ProcessDate,
|
||||
TotalJobs = totalJobs,
|
||||
OpenedJobs = openedJobs,
|
||||
ClosedJobs = closedJobs
|
||||
};
|
||||
}
|
||||
|
||||
public static List<DailyOpenedClosedItem> Data(DiscoDataContext Database, bool FilterUnimportantWeekends = false)
|
||||
{
|
||||
List<DailyOpenedClosedItem> resultData;
|
||||
|
||||
UpdateDataHistory(Database);
|
||||
|
||||
if (FilterUnimportantWeekends)
|
||||
resultData = _data.Where(i => (i.Timestamp.DayOfWeek != DayOfWeek.Saturday && i.Timestamp.DayOfWeek != DayOfWeek.Sunday) ||
|
||||
(i.OpenedJobs > 0 || i.ClosedJobs > 0)).ToList();
|
||||
else
|
||||
resultData = _data.ToList();
|
||||
|
||||
return resultData;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.BI.Job;
|
||||
|
||||
namespace Disco.BI.JobBI
|
||||
{
|
||||
public static class Utilities
|
||||
{
|
||||
public static Job Create(DiscoDataContext Database, Device device, User user, JobType type, List<JobSubType> subTypes, User initialTech, bool addAutoQueues = true)
|
||||
{
|
||||
Job j = new Job()
|
||||
{
|
||||
JobType = type,
|
||||
OpenedTechUserId = initialTech.UserId,
|
||||
OpenedTechUser = initialTech,
|
||||
OpenedDate = DateTime.Now
|
||||
};
|
||||
|
||||
// Device
|
||||
if (device != null)
|
||||
{
|
||||
j.Device = device;
|
||||
j.DeviceSerialNumber = device.SerialNumber;
|
||||
}
|
||||
|
||||
// User
|
||||
if (user != null)
|
||||
{
|
||||
j.User = user;
|
||||
j.UserId = user.UserId;
|
||||
}
|
||||
|
||||
// Sub Types
|
||||
List<JobSubType> jobSubTypes = subTypes.ToList();
|
||||
j.JobSubTypes = jobSubTypes;
|
||||
|
||||
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)
|
||||
{
|
||||
case JobType.JobTypeIds.HWar:
|
||||
Database.JobMetaWarranties.Add(new JobMetaWarranty() { Job = j });
|
||||
break;
|
||||
case JobType.JobTypeIds.HNWar:
|
||||
Database.JobMetaNonWarranties.Add(new JobMetaNonWarranty() { Job = j });
|
||||
if (device != null)
|
||||
{
|
||||
// Add Job Components
|
||||
var components = Database.DeviceComponents.Include("JobSubTypes").Where(c => !c.DeviceModelId.HasValue || c.DeviceModelId == j.Device.DeviceModelId);
|
||||
var addedComponents = new List<DeviceComponent>();
|
||||
foreach (var c in components)
|
||||
{
|
||||
if (c.JobSubTypes.Count == 0)
|
||||
{ // No Filter
|
||||
addedComponents.Add(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var st in c.JobSubTypes)
|
||||
{
|
||||
foreach (var jst in jobSubTypes)
|
||||
{
|
||||
if (st.JobTypeId == jst.JobTypeId && st.Id == jst.Id)
|
||||
{
|
||||
addedComponents.Add(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (addedComponents.Contains(c))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (var c in addedComponents)
|
||||
Database.JobComponents.Add(new JobComponent()
|
||||
{
|
||||
Job = j,
|
||||
TechUserId = initialTech.UserId,
|
||||
Cost = c.Cost,
|
||||
Description = c.Description
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
<TargetFrameworkProfile />
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
<AssemblyVersion>2.2.16272.1003</AssemblyVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -37,33 +38,15 @@
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="BitMiracle.LibTiff.NET">
|
||||
<HintPath>..\Resources\Libraries\LibTiff.NET\BitMiracle.LibTiff.NET.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="EntityFramework">
|
||||
<HintPath>..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Exceptionless, Version=1.5.2092.0, Culture=neutral, PublicKeyToken=fc181f0a46f65747, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Exceptionless.1.5.2092\lib\net45\Exceptionless.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Exceptionless.Models, Version=1.5.2092.0, Culture=neutral, PublicKeyToken=fc181f0a46f65747, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Exceptionless.1.5.2092\lib\net45\Exceptionless.Models.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="itextsharp">
|
||||
<HintPath>..\Resources\Libraries\iTextSharp\itextsharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PList, Version=0.1.4109.38751, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\plist.net.1.0\lib\Net35\PList.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Quartz">
|
||||
<HintPath>..\Resources\Libraries\Quartz\Quartz.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Renci.SshNet">
|
||||
<HintPath>..\..\..\Resources\Libraries\SshNet\Renci.SshNet.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Core" />
|
||||
@@ -72,29 +55,15 @@
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Management" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Net.Http.Extensions">
|
||||
<Reference Include="System.Net.Http.Extensions, Version=2.2.22.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Net.Http.2.2.22\lib\net45\System.Net.Http.Extensions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.Primitives">
|
||||
<Reference Include="System.Net.Http.Primitives, Version=4.2.22.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Net.Http.2.2.22\lib\net45\System.Net.Http.Primitives.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.WebRequest" />
|
||||
<Reference Include="System.Reactive.Core, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Reactive.Interfaces, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Reactive.Linq, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Reactive.PlatformServices, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Web" />
|
||||
@@ -105,39 +74,9 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BI\DeviceBI\BatchUtilities.cs" />
|
||||
<Compile Include="BI\DeviceBI\DeviceModelBI.cs" />
|
||||
<Compile Include="BI\DeviceBI\Migration\LogMacAddressImporting.cs" />
|
||||
<Compile Include="BI\DisposableImageCollection.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\Extensions\AttachmentActionExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\AuthorizationRoleExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\ClientServicesExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\UserFlagActionExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceActionExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceBatchExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceCertificateExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceDetailExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceModelExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceProfileExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\JobActionExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\JobExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\JobFlagExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\JobQueueActionExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\UserExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\WirelessCertificateExtensions.cs" />
|
||||
<Compile Include="BI\Extensions\DeviceExtensions.cs" />
|
||||
<Compile Include="BI\DeviceBI\EnrolSafeException.cs" />
|
||||
<Compile Include="BI\DeviceBI\Enrol.cs" />
|
||||
<Compile Include="BI\DeviceBI\EnrolmentLog.cs" />
|
||||
<Compile Include="BI\Extensions\DocumentTemplateExtensions.cs" />
|
||||
<Compile Include="BI\DocumentTemplateBI\Utilities.cs" />
|
||||
<Compile Include="BI\Interop\Pdf\Utilities.cs" />
|
||||
<Compile Include="BI\Interop\Pdf\PdfGenerator.cs" />
|
||||
<Compile Include="BI\JobBI\Statistics\DailyOpenedClosed.cs" />
|
||||
<Compile Include="BI\JobBI\Utilities.cs" />
|
||||
<Compile Include="BI\Extensions\UtilityExtensions.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
@@ -170,24 +109,6 @@
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-img16.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-pdf16.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\EmptyLogo.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-doc48.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-pdf48.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\MimeType-unknown48.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
|
||||
|
||||
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("2.1.0.0")]
|
||||
[assembly: AssemblyFileVersion("2.1.0.0")]
|
||||
[assembly: AssemblyVersion("2.2.16272.1003")]
|
||||
[assembly: AssemblyFileVersion("2.2.16272.1003")]
|
||||
+1
-51
@@ -1,7 +1,7 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.17929
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
@@ -59,55 +59,5 @@ namespace Disco.Properties {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap MimeType_doc48 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("MimeType_doc48", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap MimeType_img16 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("MimeType_img16", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap MimeType_pdf16 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("MimeType_pdf16", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap MimeType_pdf48 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("MimeType_pdf48", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap MimeType_unknown48 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("MimeType_unknown48", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,20 +117,4 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="MimeType_doc48" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MimeType-doc48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="MimeType_img16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MimeType-img16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="MimeType_pdf16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MimeType-pdf16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="MimeType_pdf48" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MimeType-pdf48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="MimeType_unknown48" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MimeType-unknown48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 30 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,14 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="EntityFramework" version="5.0.0" targetFramework="net45" />
|
||||
<package id="Exceptionless" version="1.5.2092" targetFramework="net45" />
|
||||
<package id="Microsoft.Bcl" version="1.1.9" targetFramework="net45" />
|
||||
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net45" />
|
||||
<package id="Microsoft.Net.Http" version="2.2.22" targetFramework="net45" />
|
||||
<package id="plist.net" version="1.0" targetFramework="net45" />
|
||||
<package id="Rx-Core" version="2.2.5" targetFramework="net45" />
|
||||
<package id="Rx-Interfaces" version="2.2.5" targetFramework="net45" />
|
||||
<package id="Rx-Linq" version="2.2.5" targetFramework="net45" />
|
||||
<package id="Rx-Main" version="2.2.5" targetFramework="net45" />
|
||||
<package id="Rx-PlatformServices" version="2.2.5" targetFramework="net45" />
|
||||
</packages>
|
||||
Reference in New Issue
Block a user