From 54307d75827cdf54d44f7fcdc7ff8094e306038c Mon Sep 17 00:00:00 2001 From: AlanMoonbase Date: Wed, 26 Feb 2025 13:04:50 -0800 Subject: [PATCH 1/6] initial data model work --- src/Model/DBContext.cs | 9 +++++++++ src/Model/UserBan.cs | 19 +++++++++++++++++++ src/Model/Viking.cs | 1 + src/Schema/UserBanType.cs | 9 +++++++++ 4 files changed, 38 insertions(+) create mode 100644 src/Model/UserBan.cs create mode 100644 src/Schema/UserBanType.cs diff --git a/src/Model/DBContext.cs b/src/Model/DBContext.cs index 1832763..bc1a0c9 100644 --- a/src/Model/DBContext.cs +++ b/src/Model/DBContext.cs @@ -30,6 +30,7 @@ public class DBContext : DbContext { public DbSet RatingRanks { get; set; } = null!; public DbSet UserMissionData { get; set; } = null!; public DbSet UserBadgesCompleted { get; set; } = null!; + public DbSet Bans { get; set; } = null!; private readonly IOptions config; @@ -156,6 +157,9 @@ public class DBContext : DbContext { builder.Entity().HasMany(v => v.UserBadgesCompleted) .WithOne(r => r.Viking); + builder.Entity().HasMany(v => v.UserBans) + .WithOne(r => r.Viking); + // Dragons builder.Entity().HasOne(d => d.Viking) .WithMany(e => e.Dragons) @@ -301,5 +305,10 @@ public class DBContext : DbContext { builder.Entity().HasOne(r => r.Viking) .WithMany(v => v.UserBadgesCompleted) .HasForeignKey(r => r.VikingId); + + // Bans + builder.Entity().HasOne(r => r.Viking) + .WithMany(e => e.UserBans) + .HasForeignKey(e => e.VikingId); } } diff --git a/src/Model/UserBan.cs b/src/Model/UserBan.cs new file mode 100644 index 0000000..c7bcb0d --- /dev/null +++ b/src/Model/UserBan.cs @@ -0,0 +1,19 @@ +using System; +using System.ComponentModel.DataAnnotations; +using sodoff.Schema; + +namespace sodoff.Model; + +public class UserBan +{ + [Key] + public int Id { get; set; } + + public int VikingId { get; set; } + + public UserBanType UserBanType { get; set; } + public DateTime CreatedAt { get; set; } + public DateTime? ExpiresOn { get; set; } + + public virtual Viking? Viking { get; set; } +} diff --git a/src/Model/Viking.cs b/src/Model/Viking.cs index a787107..0578525 100644 --- a/src/Model/Viking.cs +++ b/src/Model/Viking.cs @@ -44,6 +44,7 @@ public class Viking { public virtual Dragon? SelectedDragon { get; set; } public virtual ICollection UserMissions { get; set; } = null!; public virtual ICollection UserBadgesCompleted { get; set; } = null!; + public virtual ICollection UserBans { get; set; } = null!; public DateTime? CreationDate { get; set; } public DateTime? BirthDate { get; set; } diff --git a/src/Schema/UserBanType.cs b/src/Schema/UserBanType.cs new file mode 100644 index 0000000..9a3a892 --- /dev/null +++ b/src/Schema/UserBanType.cs @@ -0,0 +1,9 @@ +namespace sodoff.Schema; + +public enum UserBanType +{ + IndefiniteOpenChatBan = 1, + TemporaryOpenChatBan = 2, + IndefiniteAccountBan = 3, + TemporaryAccountBan = 4 +} -- 2.47.2 From 3800fc49c800189477950d174ab8377e3b599d5b Mon Sep 17 00:00:00 2001 From: AlanMoonbase Date: Wed, 26 Feb 2025 14:00:27 -0800 Subject: [PATCH 2/6] implement ``ModerationService`` add type ``NotBanned`` to ``UserBanType`` enum --- src/Schema/UserBanType.cs | 1 + src/Services/ModerationService.cs | 84 +++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 src/Services/ModerationService.cs diff --git a/src/Schema/UserBanType.cs b/src/Schema/UserBanType.cs index 9a3a892..29c99a3 100644 --- a/src/Schema/UserBanType.cs +++ b/src/Schema/UserBanType.cs @@ -2,6 +2,7 @@ namespace sodoff.Schema; public enum UserBanType { + NotBanned = 0, IndefiniteOpenChatBan = 1, TemporaryOpenChatBan = 2, IndefiniteAccountBan = 3, diff --git a/src/Services/ModerationService.cs b/src/Services/ModerationService.cs new file mode 100644 index 0000000..e1bb61b --- /dev/null +++ b/src/Services/ModerationService.cs @@ -0,0 +1,84 @@ +using System; +using sodoff.Model; +using sodoff.Schema; + +namespace sodoff.Services; + +public class ModerationService +{ + public readonly DBContext ctx; + + public ModerationService(DBContext ctx) + { + this.ctx = ctx; + } + + public UserBan AddBanToViking(Viking viking, UserBanType userBanType, DateTime expirationDate = new DateTime()) + { + // get UTC time stamp of function execution + DateTime timestamp = DateTime.UtcNow; + + // construct user ban + UserBan userBan = new UserBan + { + UserBanType = userBanType, + ExpiresOn = expirationDate, + CreatedAt = timestamp + }; + + // add to viking userban list + viking.UserBans.Add(userBan); + ctx.SaveChanges(); + + // return ban + return userBan; + } + + public bool RemoveBanById(int id) + { + // find ban + UserBan? ban = ctx.Bans.FirstOrDefault(e => e.Id == id); + + // remove it + if (ban != null) { ctx.Bans.Remove(ban); ctx.SaveChanges(); return true; } + else return false; + } + + public bool RemoveBansFromVikingByType(Viking viking, UserBanType userBanType) + { + // get all bans of type + List userBans = viking.UserBans.Where(e => e.UserBanType == userBanType).ToList(); + + if (userBans.Count == 0) return false; + + // delete all + foreach(var ban in userBans) + viking.UserBans.Remove(ban); + + ctx.SaveChanges(); + + return true; + } + + public UserBanType IsVikingBanned(Viking viking) + { + // get UTC time stamp of function execution + DateTime timestamp = DateTime.UtcNow; + + // sort viking ban list by latest first + List bans = viking.UserBans.OrderByDescending(e => e.CreatedAt).ToList(); + + if (bans.Count == 0) return UserBanType.NotBanned; // no bans in list means viking is not banned + + if (bans.First().UserBanType == UserBanType.IndefiniteAccountBan) return UserBanType.IndefiniteAccountBan; + else if (bans.First().UserBanType == UserBanType.IndefiniteOpenChatBan) return UserBanType.IndefiniteOpenChatBan; + + if (DateTime.Compare(bans.First().ExpiresOn ?? new DateTime(9999, 99, 99), timestamp) > 0) return bans.First().UserBanType; + else + { + // ban should be removed + RemoveBanById(bans.First().Id); + return UserBanType.NotBanned; + } + } +} -- 2.47.2 From df4c7e4017a649f0ebedcb6f8bec911be8c8169d Mon Sep 17 00:00:00 2001 From: AlanMoonbase Date: Thu, 27 Feb 2025 14:50:46 -0800 Subject: [PATCH 3/6] introduce ``Internal`` namespace implement ``ModerationController`` --- .../Internal/ModerationController.cs | 91 +++++++++++++++++++ src/Services/ModerationService.cs | 3 +- 2 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 src/Controllers/Internal/ModerationController.cs diff --git a/src/Controllers/Internal/ModerationController.cs b/src/Controllers/Internal/ModerationController.cs new file mode 100644 index 0000000..640cc3f --- /dev/null +++ b/src/Controllers/Internal/ModerationController.cs @@ -0,0 +1,91 @@ +using System.Linq.Expressions; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using sodoff.Model; +using sodoff.Schema; +using sodoff.Services; + +namespace sodoff.Controllers.Internal +{ + [ApiController] + public class ModerationController : Controller + { + public readonly DBContext ctx; + public readonly ModerationService moderationService; + public ModerationController(DBContext ctx, ModerationService moderationService) + { + this.ctx = ctx; + this.moderationService = moderationService; + } + + [HttpPost] + [Route("Moderation/AddBanToVikingByGuid")] + public IActionResult AddBanToVikingByGuid([FromForm] Guid token, [FromForm] Guid userId, [FromForm] int banType, [FromForm] int days = 0) + { + var validationResult = ValidateSession(token); + + if(validationResult) + { + // get the viking + Viking? viking = ctx.Vikings.FirstOrDefault(e => e.Uid == userId); + + // get execution timestamp + DateTime timestamp = DateTime.UtcNow; + + DateTime expiration = new DateTime(); + + if (days == 0) expiration = new DateTime(9999, 99, 99); // a days value of 0 should mean indefinite ban (might change later) + else expiration = timestamp.AddDays(days); + + if (viking != null) return Ok(moderationService.AddBanToViking(viking, (UserBanType)banType, expiration)); + else return NotFound(); + } + + return Unauthorized("You Do Not Have Sufficient Permissions To Moderate Users"); + } + + [HttpDelete] + [Route("Moderation/RemoveBansFromVikingByGuidAndType")] + public IActionResult RemoveBanFromVikingByGuid([FromForm] Guid token, [FromForm] Guid userId, [FromForm] int banType) + { + var validationResult = ValidateSession(token); + + if (validationResult) + { + // get the viking + Viking? viking = ctx.Vikings.FirstOrDefault(e => e.Uid == userId); + + // remove all bans of type + if (viking != null) return Ok(moderationService.RemoveBansFromVikingByType(viking, (UserBanType)banType)); + else return NotFound(); + } + + return Unauthorized("You Do Not Have Sufficient Permissions To Moderate Users"); + } + + [HttpGet] + [Route("Moderation/CheckForVikingBan")] + public IActionResult CheckForVikingBan([FromForm] Guid token) + { + // get viking session + var session = ctx.Sessions.FirstOrDefault(e => e.ApiToken == token); + + if (session != null && session.Viking != null) return Ok(moderationService.IsVikingBanned(session.Viking)); + else return Ok(UserBanType.NotBanned); // invalid session, for now just return not banned + } + + private bool ValidateSession(Guid token) + { + // get active session + var session = ctx.Sessions.FirstOrDefault(e => e.ApiToken == token); + + if (session != null) + { + // most endpoints here should only be activated by a 'Moderator' or above + Role? vikingRole = session.Viking?.MMORoles.FirstOrDefault()?.Role; + if (vikingRole != null && (vikingRole == Role.Moderator || vikingRole == Role.Admin)) return true; + else return false; + } else return false; + } + } +} diff --git a/src/Services/ModerationService.cs b/src/Services/ModerationService.cs index e1bb61b..344cf97 100644 --- a/src/Services/ModerationService.cs +++ b/src/Services/ModerationService.cs @@ -52,8 +52,7 @@ public class ModerationService if (userBans.Count == 0) return false; // delete all - foreach(var ban in userBans) - viking.UserBans.Remove(ban); + foreach(var ban in userBans) { viking.UserBans.Remove(ban); } ctx.SaveChanges(); -- 2.47.2 From ff4e8c39cd372e99a0c67b75cfb842cf4155a165 Mon Sep 17 00:00:00 2001 From: AlanMoonbase Date: Thu, 27 Feb 2025 18:01:54 -0800 Subject: [PATCH 4/6] change to ``HttpPost`` --- src/Controllers/Internal/ModerationController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Controllers/Internal/ModerationController.cs b/src/Controllers/Internal/ModerationController.cs index 640cc3f..9b35e3c 100644 --- a/src/Controllers/Internal/ModerationController.cs +++ b/src/Controllers/Internal/ModerationController.cs @@ -44,7 +44,7 @@ namespace sodoff.Controllers.Internal return Unauthorized("You Do Not Have Sufficient Permissions To Moderate Users"); } - [HttpDelete] + [HttpPost] [Route("Moderation/RemoveBansFromVikingByGuidAndType")] public IActionResult RemoveBanFromVikingByGuid([FromForm] Guid token, [FromForm] Guid userId, [FromForm] int banType) { @@ -63,7 +63,7 @@ namespace sodoff.Controllers.Internal return Unauthorized("You Do Not Have Sufficient Permissions To Moderate Users"); } - [HttpGet] + [HttpPost] [Route("Moderation/CheckForVikingBan")] public IActionResult CheckForVikingBan([FromForm] Guid token) { -- 2.47.2 From 3ff5c729e7ca861afa6de7c0965d8a296cacf35a Mon Sep 17 00:00:00 2001 From: AlanMoonbase Date: Thu, 27 Feb 2025 18:56:48 -0800 Subject: [PATCH 5/6] add ``ModerationService`` to service list --- src/Program.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Program.cs b/src/Program.cs index 91cbbaa..1c1cbe9 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -40,6 +40,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); bool assetServer = builder.Configuration.GetSection("AssetServer").GetValue("Enabled"); string assetIP = builder.Configuration.GetSection("AssetServer").GetValue("ListenIP"); -- 2.47.2 From 3f408bbae6a6590de4a10ba93aeb122c60b9ea27 Mon Sep 17 00:00:00 2001 From: AlanMoonbase Date: Sun, 2 Mar 2025 15:58:42 -0800 Subject: [PATCH 6/6] change response in ``AddBanToViking`` --- src/Services/ModerationService.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Services/ModerationService.cs b/src/Services/ModerationService.cs index 344cf97..35686b9 100644 --- a/src/Services/ModerationService.cs +++ b/src/Services/ModerationService.cs @@ -13,7 +13,7 @@ public class ModerationService this.ctx = ctx; } - public UserBan AddBanToViking(Viking viking, UserBanType userBanType, DateTime expirationDate = new DateTime()) + public string AddBanToViking(Viking viking, UserBanType userBanType, DateTime expirationDate = new DateTime()) { // get UTC time stamp of function execution DateTime timestamp = DateTime.UtcNow; @@ -30,8 +30,8 @@ public class ModerationService viking.UserBans.Add(userBan); ctx.SaveChanges(); - // return ban - return userBan; + // return success message + return "Success"; } public bool RemoveBanById(int id) -- 2.47.2