Files
Disco/Disco.Services/Devices/DeviceModelExtensions.cs
T
2025-07-20 15:58:42 +10:00

130 lines
5.0 KiB
C#

using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Services.Authorization;
using Disco.Services.Users;
using System;
using System.Data.Entity;
using System.IO;
using System.Linq;
namespace Disco.Services
{
public static class DeviceModelExtensions
{
private static object _CreateDeviceModelLock = new object();
public static bool CanDelete(this DeviceModel dm, DiscoDataContext Database)
{
if (!UserService.CurrentAuthorization.Has(Claims.Config.DeviceModel.Delete))
return false;
// Can't Delete Default Model (Id: 1)
if (dm.Id == 1)
return false;
// Can't Delete if Contains Devices
if (Database.Devices.Count(d => d.DeviceModelId == dm.Id) > 0)
return false;
return true;
}
public static void Delete(this DeviceModel dm, DiscoDataContext Database)
{
if (!dm.CanDelete(Database))
throw new InvalidOperationException("The state of this Device Model doesn't allow it to be deleted");
// Delete Image
var deviceModelImagePath = dm.ImageFilePath();
if (File.Exists(deviceModelImagePath))
File.Delete(deviceModelImagePath);
// Delete any Device Model Components
foreach (var deviceModelComponent in Database.DeviceComponents.Where(dc => dc.DeviceModelId == dm.Id).ToList())
{
Database.DeviceComponents.Remove(deviceModelComponent);
}
// Delete Model
Database.DeviceModels.Remove(dm);
}
public static bool CanDecommission(this DeviceModel dm, DiscoDataContext database)
{
if (!UserService.CurrentAuthorization.Has(Claims.Device.Actions.Import))
return false;
if (!database.Devices.Any(d => d.DeviceModelId == dm.Id && d.DecommissionedDate == null))
return false;
return true;
}
public static Tuple<DeviceModel, bool> GetOrCreateDeviceModel(this DbSet<DeviceModel> DeviceModelsSet, string Manufacturer, string Model, string ModelType)
{
if (string.IsNullOrWhiteSpace(Manufacturer))
Manufacturer = "Unknown";
else
Manufacturer = Manufacturer.Trim();
if (string.IsNullOrWhiteSpace(Model))
Model = "Unknown";
else
Model = Model.Trim();
if (string.IsNullOrWhiteSpace(ModelType))
ModelType = null;
else
ModelType = ModelType.Trim();
// Already Exists?
var deviceModel = DeviceModelsSet.Where(dm => dm.ModelType != DeviceModel.CustomModelType).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.Where(dm => dm.ModelType != DeviceModel.CustomModelType).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 description = $"{Manufacturer} {Model}";
if (Model.Equals("Unknown", StringComparison.OrdinalIgnoreCase))
{
description = $"Unknown {Manufacturer} Model";
}
var addDeviceModel = new DeviceModel
{
Manufacturer = Manufacturer,
Model = Model,
ModelType = ModelType,
Description = description
};
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 Tuple.Create(deviceModel, true);
}
}
}
else
{
if (deviceModel.ModelType != ModelType)
deviceModel.ModelType = ModelType;
}
return Tuple.Create(deviceModel, false);
}
}
}