feature: scheduled flag removal

This commit is contained in:
Gary Sharp
2025-09-19 12:18:45 +10:00
parent 356762c811
commit 7603cac01a
34 changed files with 2210 additions and 1055 deletions
@@ -14,19 +14,26 @@ namespace Disco.Services
public static class DeviceFlagExtensions
{
#region Edit Comments
#region Edit
public static bool CanEdit(this DeviceFlagAssignment fa)
{
var (_, permission) = DeviceFlagService.GetDeviceFlag(fa.DeviceFlagId);
return permission.CanEdit();
}
public static void OnEdit(this DeviceFlagAssignment fa, string comments)
public static void OnEdit(this DeviceFlagAssignment fa, string comments, DateTime? removeDate)
{
if (!fa.CanEdit())
throw new InvalidOperationException("Editing comments for device flags is denied");
fa.Comments = string.IsNullOrWhiteSpace(comments) ? null : comments.Trim();
if (fa.CanRemove() && removeDate != fa.RemoveDate &&
(!removeDate.HasValue || removeDate.Value >= DateTime.Today))
{
fa.RemoveDate = removeDate?.Date;
fa.RemoveUserId = UserService.CurrentUser.UserId;
}
}
#endregion
@@ -49,6 +56,11 @@ namespace Disco.Services
}
public static void OnRemoveUnsafe(this DeviceFlagAssignment fa, DiscoDataContext database, User removingUser)
{
OnRemoveUnsafe(fa, database, removingUser, isScheduled: false);
}
internal static void OnRemoveUnsafe(this DeviceFlagAssignment fa, DiscoDataContext database, User removingUser, bool isScheduled)
{
fa = database.DeviceFlagAssignments
.Include(a => a.DeviceFlag)
@@ -58,6 +70,13 @@ namespace Disco.Services
fa.RemovedDate = DateTime.Now;
fa.RemovedUserId = removingUser.UserId;
if (!isScheduled)
{
fa.RemoveDate = null;
fa.RemoveUser = null;
fa.RemoveUserId = null;
}
if (!string.IsNullOrWhiteSpace(fa.DeviceFlag.OnUnassignmentExpression))
{
try
@@ -89,15 +108,45 @@ namespace Disco.Services
return permission.CanAssign();
}
public static bool CanRemoveDeviceFlag(this Device d, DeviceFlag flag)
{
var (_, permission) = DeviceFlagService.GetDeviceFlag(flag.Id);
return permission.CanRemove();
}
public static DeviceFlagAssignment OnAddDeviceFlag(this Device d, DiscoDataContext database, DeviceFlag flag, string comments)
{
if (!d.CanAddDeviceFlag(flag))
throw new InvalidOperationException("Adding device flag is denied");
return d.OnAddDeviceFlagUnsafe(database, flag, UserService.CurrentUser, comments);
var removeDate = (DateTime?)null;
if (flag.DefaultRemoveDays.HasValue)
removeDate = DateTime.Today.AddDays(flag.DefaultRemoveDays.Value);
return OnAddDeviceFlag(d, database, flag, comments, removeDate);
}
public static DeviceFlagAssignment OnAddDeviceFlag(this Device d, DiscoDataContext database, DeviceFlag flag, string comments, DateTime? removeDate)
{
if (!d.CanAddDeviceFlag(flag))
throw new InvalidOperationException("Adding device flag is denied");
if (d.CanRemoveDeviceFlag(flag))
return d.OnAddDeviceFlagUnsafe(database, flag, UserService.CurrentUser, comments, removeDate);
else
return d.OnAddDeviceFlagUnsafe(database, flag, UserService.CurrentUser, comments);
}
public static DeviceFlagAssignment OnAddDeviceFlagUnsafe(this Device d, DiscoDataContext database, DeviceFlag flag, User addingUser, string comments)
{
var removeDate = (DateTime?)null;
if (flag.DefaultRemoveDays.HasValue)
removeDate = DateTime.Today.AddDays(flag.DefaultRemoveDays.Value);
return OnAddDeviceFlagUnsafe(d, database, flag, addingUser, comments, removeDate);
}
public static DeviceFlagAssignment OnAddDeviceFlagUnsafe(this Device d, DiscoDataContext database, DeviceFlag flag, User addingUser, string comments, DateTime? removeDate)
{
flag = database.DeviceFlags.First(f => f.Id == flag.Id);
d = database.Devices.First(de => de.SerialNumber == d.SerialNumber);
@@ -113,6 +162,13 @@ namespace Disco.Services
Comments = string.IsNullOrWhiteSpace(comments) ? null : comments.Trim()
};
if (removeDate.HasValue)
{
fa.RemoveDate = removeDate.Value.Date;
fa.RemoveUser = addingUser;
fa.RemoveUserId = addingUser.UserId;
}
database.DeviceFlagAssignments.Add(fa);
if (!string.IsNullOrWhiteSpace(flag.OnAssignmentExpression))
@@ -0,0 +1,65 @@
using Disco.Data.Repository;
using Disco.Services.Tasks;
using Quartz;
using System;
using System.Data.Entity;
using System.Linq;
namespace Disco.Services.Devices.DeviceFlags
{
public class FlagRemovalTask : ScheduledTask
{
public override string TaskName { get; } = "Flags - Scheduled Removal";
public override bool SingleInstanceTask { get; } = false;
public override bool CancelInitiallySupported { get; } = false;
public override bool LogExceptionsOnly { get; } = true;
public override void InitalizeScheduledTask(DiscoDataContext Database)
{
// Schedule in 1mins
var trigger = TriggerBuilder.Create()
.StartAt(DateTimeOffset.Now.AddMinutes(1));
ScheduleTask(trigger);
// Schedule every day at midnight
trigger = TriggerBuilder.Create()
.WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(0, 0));
ScheduleTask(trigger);
}
protected override void ExecuteTask()
{
using (DiscoDataContext database = new DiscoDataContext())
{
var assignments = database.DeviceFlagAssignments
.Include(a => a.RemoveUser)
.Include(a => a.AddedUser)
.Where(a => a.RemovedDate == null && a.RemoveDate <= DateTime.Today)
.ToList();
foreach (var assignment in assignments)
{
assignment.OnRemoveUnsafe(database, assignment.RemoveUser ?? assignment.AddedUser, isScheduled: true);
}
database.SaveChanges();
}
using (DiscoDataContext database = new DiscoDataContext())
{
var assignments = database.UserFlagAssignments
.Include(a => a.RemoveUser)
.Include(a => a.AddedUser)
.Where(a => a.RemovedDate == null && a.RemoveDate <= DateTime.Today)
.ToList();
foreach (var assignment in assignments)
{
assignment.OnRemoveUnsafe(database, assignment.RemoveUser ?? assignment.AddedUser, isScheduled: true);
}
database.SaveChanges();
}
}
}
}