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
@@ -1,5 +1,4 @@
using Disco.Models.Repository;
using Disco.Services;
using Disco.Services;
using Disco.Services.Web;
using System;
using System.Data.Entity;
@@ -10,34 +9,25 @@ namespace Disco.Web.Areas.API.Controllers
{
public partial class DeviceFlagAssignmentController : AuthorizedDatabaseController
{
const string pComments = "comments";
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult Update(int id, string key, string value = null, bool? redirect = null)
public virtual ActionResult Edit(int id, string comments, DateTime? removeDate, bool? redirect = null)
{
try
{
if (id < 0)
throw new ArgumentOutOfRangeException(nameof(id));
if (string.IsNullOrEmpty(key))
throw new ArgumentNullException(nameof(key));
var assignment = Database.DeviceFlagAssignments
.Include(a => a.DeviceFlag)
.FirstOrDefault(a => a.Id == id);
if (assignment != null)
{
switch (key.ToLower())
{
case pComments:
UpdateComments(assignment, value);
break;
default:
throw new Exception("Invalid Update Key");
}
}
else
{
throw new Exception("Invalid Device Flag Assignment Id");
}
.FirstOrDefault(a => a.Id == id)
?? throw new Exception("Invalid Device Flag Assignment Id");
if (!assignment.CanEdit())
throw new InvalidOperationException("Editing comments for device flags is denied");
assignment.OnEdit(comments, removeDate);
Database.SaveChanges();
if (redirect.HasValue && redirect.Value)
return Redirect($"{Url.Action(MVC.Device.Show(assignment.DeviceSerialNumber))}#DeviceDetailTab-Flags");
else
@@ -52,43 +42,30 @@ namespace Disco.Web.Areas.API.Controllers
}
}
#region Update Shortcut Methods
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult UpdateComments(int id, string Comments = null, bool? redirect = null)
{
return Update(id, pComments, Comments, redirect);
}
#endregion
#region Update Properties
private void UpdateComments(DeviceFlagAssignment assignment, string comments)
{
if (!assignment.CanEdit())
throw new InvalidOperationException("Editing comments for device flags is denied");
assignment.OnEdit(comments);
Database.SaveChanges();
}
#endregion
#region Actions
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult AddDevice(int id, string deviceSerialNumber, string comments)
public virtual ActionResult AddDevice(int id, string deviceSerialNumber, string comments, DateTime? removeDate)
{
Database.Configuration.LazyLoadingEnabled = true;
var flag = Database.DeviceFlags.Find(id);
if (flag == null)
throw new ArgumentException("Invalid Device Flag Id", nameof(id));
var flag = Database.DeviceFlags.Find(id)
?? throw new ArgumentException("Invalid Device Flag Id", nameof(id));
var device = Database.Devices.Include(u => u.DeviceFlagAssignments).FirstOrDefault(d => d.SerialNumber == deviceSerialNumber);
if (device == null)
throw new ArgumentException("Invalid Device Serial Number", nameof(deviceSerialNumber));
var device = Database.Devices
.Include(u => u.DeviceFlagAssignments)
.FirstOrDefault(d => d.SerialNumber == deviceSerialNumber)
?? throw new ArgumentException("Invalid Device Serial Number", nameof(deviceSerialNumber));
if (!device.CanAddDeviceFlag(flag))
return Unauthorized("Adding device flag is denied");
var assignment = device.OnAddDeviceFlag(Database, flag, comments);
if (removeDate.HasValue && removeDate.Value < DateTime.Today.AddDays(1))
removeDate = null;
if (device.CanRemoveDeviceFlag(flag))
device.OnAddDeviceFlag(Database, flag, comments, removeDate);
else
device.OnAddDeviceFlag(Database, flag, comments);
Database.SaveChanges();
@@ -102,9 +79,8 @@ namespace Disco.Web.Areas.API.Controllers
var assignment = Database.DeviceFlagAssignments
.Include(a => a.DeviceFlag)
.FirstOrDefault(a => a.Id == id);
if (assignment == null)
throw new ArgumentException("Invalid Device Flag Assignment Id", nameof(id));
.FirstOrDefault(a => a.Id == id)
?? throw new ArgumentException("Invalid Device Flag Assignment Id", nameof(id));
if (!assignment.CanRemove())
return Unauthorized("Removing device flag assignment is denied");
@@ -10,6 +10,7 @@ using Disco.Web.Areas.API.Models.Shared;
using Disco.Web.Areas.Config.Models.DeviceFlag;
using Disco.Web.Extensions;
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web.Mvc;
@@ -17,12 +18,13 @@ namespace Disco.Web.Areas.API.Controllers
{
public partial class DeviceFlagController : AuthorizedDatabaseController
{
const string pName = "name";
const string pDescription = "description";
const string pIcon = "icon";
const string pIconColour = "iconcolour";
const string pOnAssignmentExpression = "onassignmentexpression";
const string pOnUnassignmentExpression = "onunassignmentexpression";
private const string pName = "name";
private const string pDescription = "description";
private const string pIcon = "icon";
private const string pIconColour = "iconcolour";
private const string pDefaultRemoveDays = "defaultremovedays";
private const string pOnAssignmentExpression = "onassignmentexpression";
private const string pOnUnassignmentExpression = "onunassignmentexpression";
[DiscoAuthorize(Claims.Config.DeviceFlag.Configure)]
[HttpPost, ValidateAntiForgeryToken]
@@ -53,6 +55,9 @@ namespace Disco.Web.Areas.API.Controllers
case pIconColour:
UpdateIconColour(flag, value);
break;
case pDefaultRemoveDays:
UpdateDefaultRemoveDays(flag, value);
break;
case pOnAssignmentExpression:
UpdateOnAssignmentExpression(flag, value);
break;
@@ -143,6 +148,12 @@ namespace Disco.Web.Areas.API.Controllers
}
[DiscoAuthorize(Claims.Config.DeviceFlag.Configure)]
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult UpdateDefaultRemoveDays(int id, [Range(1, int.MaxValue)] int? defaultRemoveDays = null, bool? redirect = null)
{
return Update(id, pDefaultRemoveDays, defaultRemoveDays?.ToString(), redirect);
}
[DiscoAuthorize(Claims.Config.DeviceFlag.Configure)]
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult UpdateOnAssignmentExpression(int id, string OnAssignmentExpression = null, bool redirect = false)
{
return Update(id, pOnAssignmentExpression, OnAssignmentExpression, redirect);
@@ -280,6 +291,23 @@ namespace Disco.Web.Areas.API.Controllers
}
}
private void UpdateDefaultRemoveDays(DeviceFlag deviceFlag, string defaultRemoveDays)
{
if (string.IsNullOrWhiteSpace(defaultRemoveDays))
{
deviceFlag.DefaultRemoveDays = null;
}
else
{
if (!int.TryParse(defaultRemoveDays, out var days) || days < 1)
throw new ArgumentOutOfRangeException(nameof(defaultRemoveDays), "Unable to parse days");
deviceFlag.DefaultRemoveDays = days;
}
DeviceFlagService.Update(Database, deviceFlag);
}
private void UpdateOnAssignmentExpression(DeviceFlag deviceFlag, string onAssignmentExpression)
{
if (string.IsNullOrWhiteSpace(onAssignmentExpression))
@@ -1,5 +1,4 @@
using Disco.Models.Repository;
using Disco.Services;
using Disco.Services;
using Disco.Services.Web;
using System;
using System.Data.Entity;
@@ -10,34 +9,25 @@ namespace Disco.Web.Areas.API.Controllers
{
public partial class UserFlagAssignmentController : AuthorizedDatabaseController
{
const string pComments = "comments";
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult Update(int id, string key, string value = null, bool? redirect = null)
public virtual ActionResult Edit(int id, string comments, DateTime? removeDate, bool? redirect = null)
{
try
{
if (id < 0)
throw new ArgumentOutOfRangeException(nameof(id));
if (string.IsNullOrEmpty(key))
throw new ArgumentNullException(nameof(key));
var userFlagAssignment = Database.UserFlagAssignments
.Include(a => a.UserFlag)
.FirstOrDefault(a => a.Id == id);
if (userFlagAssignment != null)
{
switch (key.ToLower())
{
case pComments:
UpdateComments(userFlagAssignment, value);
break;
default:
throw new Exception("Invalid Update Key");
}
}
else
{
throw new Exception("Invalid User Flag Assignment Id");
}
.FirstOrDefault(a => a.Id == id)
?? throw new Exception("Invalid User Flag Assignment Id");
if (!userFlagAssignment.CanEdit())
throw new InvalidOperationException("Editing comments for user flags is denied");
userFlagAssignment.OnEdit(comments, removeDate);
Database.SaveChanges();
if (redirect.HasValue && redirect.Value)
return Redirect($"{Url.Action(MVC.User.Show(userFlagAssignment.UserId))}#UserDetailTab-Flags");
else
@@ -52,44 +42,31 @@ namespace Disco.Web.Areas.API.Controllers
}
}
#region Update Shortcut Methods
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult UpdateComments(int id, string Comments = null, bool? redirect = null)
{
return Update(id, pComments, Comments, redirect);
}
#endregion
#region Update Properties
private void UpdateComments(UserFlagAssignment userFlagAssignment, string comments)
{
if (!userFlagAssignment.CanEdit())
throw new InvalidOperationException("Editing comments for user flags is denied");
userFlagAssignment.OnEdit(comments);
Database.SaveChanges();
}
#endregion
#region Actions
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult AddUser(int id, string UserId, string Comments)
public virtual ActionResult AddUser(int id, string UserId, string Comments, DateTime? RemoveDate)
{
Database.Configuration.LazyLoadingEnabled = true;
var userFlag = Database.UserFlags.Find(id);
if (userFlag == null)
throw new ArgumentException("Invalid User Flag Id", nameof(id));
var userFlag = Database.UserFlags.Find(id)
?? throw new ArgumentException("Invalid User Flag Id", nameof(id));
var user = Database.Users.Include(u => u.UserFlagAssignments).FirstOrDefault(u => u.UserId == UserId);
if (user == null)
throw new ArgumentException("Invalid User Id", nameof(UserId));
var user = Database.Users
.Include(u => u.UserFlagAssignments)
.FirstOrDefault(u => u.UserId == UserId)
?? throw new ArgumentException("Invalid User Id", nameof(UserId));
if (!user.CanAddUserFlag(userFlag))
return Unauthorized("Adding user flag is denied");
var userFlagAssignment = user.OnAddUserFlag(Database, userFlag, Comments);
if (RemoveDate.HasValue && RemoveDate.Value < DateTime.Today.AddDays(1))
RemoveDate = null;
if (user.CanRemoveUserFlag(userFlag))
user.OnAddUserFlag(Database, userFlag, Comments, RemoveDate);
else
user.OnAddUserFlag(Database, userFlag, Comments);
Database.SaveChanges();
@@ -103,9 +80,8 @@ namespace Disco.Web.Areas.API.Controllers
var userFlagAssignment = Database.UserFlagAssignments
.Include(a => a.UserFlag)
.FirstOrDefault(a => a.Id == id);
if (userFlagAssignment == null)
throw new ArgumentException("Invalid User Flag Assignment Id", nameof(id));
.FirstOrDefault(a => a.Id == id)
?? throw new ArgumentException("Invalid User Flag Assignment Id", nameof(id));
if (!userFlagAssignment.CanRemove())
return Unauthorized("Removing user flag assignment is denied");
@@ -10,6 +10,7 @@ using Disco.Web.Areas.API.Models.Shared;
using Disco.Web.Areas.Config.Models.UserFlag;
using Disco.Web.Extensions;
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web.Mvc;
@@ -17,12 +18,13 @@ namespace Disco.Web.Areas.API.Controllers
{
public partial class UserFlagController : AuthorizedDatabaseController
{
const string pName = "name";
const string pDescription = "description";
const string pIcon = "icon";
const string pIconColour = "iconcolour";
const string pOnAssignmentExpression = "onassignmentexpression";
const string pOnUnassignmentExpression = "onunassignmentexpression";
private const string pName = "name";
private const string pDescription = "description";
private const string pIcon = "icon";
private const string pIconColour = "iconcolour";
private const string pDefaultRemoveDays = "defaultremovedays";
private const string pOnAssignmentExpression = "onassignmentexpression";
private const string pOnUnassignmentExpression = "onunassignmentexpression";
[DiscoAuthorize(Claims.Config.UserFlag.Configure)]
[HttpPost, ValidateAntiForgeryToken]
@@ -53,6 +55,9 @@ namespace Disco.Web.Areas.API.Controllers
case pIconColour:
UpdateIconColour(flag, value);
break;
case pDefaultRemoveDays:
UpdateDefaultRemoveDays(flag, value);
break;
case pOnAssignmentExpression:
UpdateOnAssignmentExpression(flag, value);
break;
@@ -143,6 +148,12 @@ namespace Disco.Web.Areas.API.Controllers
}
[DiscoAuthorize(Claims.Config.UserFlag.Configure)]
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult UpdateDefaultRemoveDays(int id, [Range(1, int.MaxValue)] int? defaultRemoveDays = null, bool? redirect = null)
{
return Update(id, pDefaultRemoveDays, defaultRemoveDays?.ToString(), redirect);
}
[DiscoAuthorize(Claims.Config.UserFlag.Configure)]
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult UpdateOnAssignmentExpression(int id, string OnAssignmentExpression = null, bool redirect = false)
{
return Update(id, pOnAssignmentExpression, OnAssignmentExpression, redirect);
@@ -280,6 +291,23 @@ namespace Disco.Web.Areas.API.Controllers
}
}
private void UpdateDefaultRemoveDays(UserFlag userFlag, string defaultRemoveDays)
{
if (string.IsNullOrWhiteSpace(defaultRemoveDays))
{
userFlag.DefaultRemoveDays = null;
}
else
{
if (!int.TryParse(defaultRemoveDays, out var days) || days < 1)
throw new ArgumentOutOfRangeException(nameof(defaultRemoveDays), "Unable to parse days");
userFlag.DefaultRemoveDays = days;
}
UserFlagService.Update(Database, userFlag);
}
private void UpdateOnAssignmentExpression(UserFlag UserFlag, string OnAssignmentExpression)
{
if (string.IsNullOrWhiteSpace(OnAssignmentExpression))