forked from SoDOff-Project/sodoff
Basic Moderation System #1
91
src/Controllers/Internal/ModerationController.cs
Normal file
91
src/Controllers/Internal/ModerationController.cs
Normal file
@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[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");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -30,6 +30,7 @@ public class DBContext : DbContext {
|
|||||||
public DbSet<RatingRank> RatingRanks { get; set; } = null!;
|
public DbSet<RatingRank> RatingRanks { get; set; } = null!;
|
||||||
public DbSet<UserMissionData> UserMissionData { get; set; } = null!;
|
public DbSet<UserMissionData> UserMissionData { get; set; } = null!;
|
||||||
public DbSet<UserBadgeCompleteData> UserBadgesCompleted { get; set; } = null!;
|
public DbSet<UserBadgeCompleteData> UserBadgesCompleted { get; set; } = null!;
|
||||||
|
public DbSet<UserBan> Bans { get; set; } = null!;
|
||||||
|
|
||||||
private readonly IOptions<ApiServerConfig> config;
|
private readonly IOptions<ApiServerConfig> config;
|
||||||
|
|
||||||
@ -156,6 +157,9 @@ public class DBContext : DbContext {
|
|||||||
builder.Entity<Viking>().HasMany(v => v.UserBadgesCompleted)
|
builder.Entity<Viking>().HasMany(v => v.UserBadgesCompleted)
|
||||||
.WithOne(r => r.Viking);
|
.WithOne(r => r.Viking);
|
||||||
|
|
||||||
|
builder.Entity<Viking>().HasMany(v => v.UserBans)
|
||||||
|
.WithOne(r => r.Viking);
|
||||||
|
|
||||||
// Dragons
|
// Dragons
|
||||||
builder.Entity<Dragon>().HasOne(d => d.Viking)
|
builder.Entity<Dragon>().HasOne(d => d.Viking)
|
||||||
.WithMany(e => e.Dragons)
|
.WithMany(e => e.Dragons)
|
||||||
@ -301,5 +305,10 @@ public class DBContext : DbContext {
|
|||||||
builder.Entity<UserBadgeCompleteData>().HasOne(r => r.Viking)
|
builder.Entity<UserBadgeCompleteData>().HasOne(r => r.Viking)
|
||||||
.WithMany(v => v.UserBadgesCompleted)
|
.WithMany(v => v.UserBadgesCompleted)
|
||||||
.HasForeignKey(r => r.VikingId);
|
.HasForeignKey(r => r.VikingId);
|
||||||
|
|
||||||
|
// Bans
|
||||||
|
builder.Entity<UserBan>().HasOne(r => r.Viking)
|
||||||
|
.WithMany(e => e.UserBans)
|
||||||
|
.HasForeignKey(e => e.VikingId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19
src/Model/UserBan.cs
Normal file
19
src/Model/UserBan.cs
Normal file
@ -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; }
|
||||||
|
}
|
@ -44,6 +44,7 @@ public class Viking {
|
|||||||
public virtual Dragon? SelectedDragon { get; set; }
|
public virtual Dragon? SelectedDragon { get; set; }
|
||||||
public virtual ICollection<UserMissionData> UserMissions { get; set; } = null!;
|
public virtual ICollection<UserMissionData> UserMissions { get; set; } = null!;
|
||||||
public virtual ICollection<UserBadgeCompleteData> UserBadgesCompleted { get; set; } = null!;
|
public virtual ICollection<UserBadgeCompleteData> UserBadgesCompleted { get; set; } = null!;
|
||||||
|
public virtual ICollection<UserBan> UserBans { get; set; } = null!;
|
||||||
|
|
||||||
public DateTime? CreationDate { get; set; }
|
public DateTime? CreationDate { get; set; }
|
||||||
public DateTime? BirthDate { get; set; }
|
public DateTime? BirthDate { get; set; }
|
||||||
|
@ -40,6 +40,7 @@ builder.Services.AddScoped<AchievementService>();
|
|||||||
builder.Services.AddScoped<GameDataService>();
|
builder.Services.AddScoped<GameDataService>();
|
||||||
builder.Services.AddScoped<ProfileService>();
|
builder.Services.AddScoped<ProfileService>();
|
||||||
builder.Services.AddScoped<NeighborhoodService>();
|
builder.Services.AddScoped<NeighborhoodService>();
|
||||||
|
builder.Services.AddScoped<ModerationService>();
|
||||||
|
|
||||||
bool assetServer = builder.Configuration.GetSection("AssetServer").GetValue<bool>("Enabled");
|
bool assetServer = builder.Configuration.GetSection("AssetServer").GetValue<bool>("Enabled");
|
||||||
string assetIP = builder.Configuration.GetSection("AssetServer").GetValue<string>("ListenIP");
|
string assetIP = builder.Configuration.GetSection("AssetServer").GetValue<string>("ListenIP");
|
||||||
|
10
src/Schema/UserBanType.cs
Normal file
10
src/Schema/UserBanType.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
public enum UserBanType
|
||||||
|
{
|
||||||
|
NotBanned = 0,
|
||||||
|
IndefiniteOpenChatBan = 1,
|
||||||
|
TemporaryOpenChatBan = 2,
|
||||||
|
IndefiniteAccountBan = 3,
|
||||||
|
TemporaryAccountBan = 4
|
||||||
|
}
|
83
src/Services/ModerationService.cs
Normal file
83
src/Services/ModerationService.cs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
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 string 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 success message
|
||||||
|
return "Success";
|
||||||
|
}
|
||||||
|
|
||||||
|
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<UserBan> 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<UserBan> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user