Merge pull request #121 from Moonlight-Panel/AddIpBan
Implemented ip ban
This commit is contained in:
@@ -45,6 +45,7 @@ public class DataContext : DbContext
|
|||||||
public DbSet<MySqlDatabase> Databases { get; set; }
|
public DbSet<MySqlDatabase> Databases { get; set; }
|
||||||
public DbSet<WebSpace> WebSpaces { get; set; }
|
public DbSet<WebSpace> WebSpaces { get; set; }
|
||||||
public DbSet<SupportChatMessage> SupportChatMessages { get; set; }
|
public DbSet<SupportChatMessage> SupportChatMessages { get; set; }
|
||||||
|
public DbSet<IpBan> IpBans { get; set; }
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
{
|
{
|
||||||
|
|||||||
8
Moonlight/App/Database/Entities/IpBan.cs
Normal file
8
Moonlight/App/Database/Entities/IpBan.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Moonlight.App.Database.Entities;
|
||||||
|
|
||||||
|
public class IpBan
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Ip { get; set; } = "";
|
||||||
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||||
|
}
|
||||||
1052
Moonlight/App/Database/Migrations/20230519125351_AddIpBanModel.Designer.cs
generated
Normal file
1052
Moonlight/App/Database/Migrations/20230519125351_AddIpBanModel.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Moonlight.App.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddIpBanModel : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "IpBans",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||||
|
Ip = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_IpBans", x => x.Id);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "IpBans");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -204,6 +204,24 @@ namespace Moonlight.App.Database.Migrations
|
|||||||
b.ToTable("ImageVariables");
|
b.ToTable("ImageVariables");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.IpBan", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Ip")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("IpBans");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Moonlight.App.Database.Entities.LoadingMessage", b =>
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LoadingMessage", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
|
|||||||
30
Moonlight/App/Services/Sessions/IpBanService.cs
Normal file
30
Moonlight/App/Services/Sessions/IpBanService.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using Moonlight.App.Database.Entities;
|
||||||
|
using Moonlight.App.Events;
|
||||||
|
using Moonlight.App.Repositories;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Services.Sessions;
|
||||||
|
|
||||||
|
public class IpBanService
|
||||||
|
{
|
||||||
|
private readonly IdentityService IdentityService;
|
||||||
|
private readonly Repository<IpBan> IpBanRepository;
|
||||||
|
|
||||||
|
public IpBanService(
|
||||||
|
IdentityService identityService,
|
||||||
|
Repository<IpBan> ipBanRepository)
|
||||||
|
{
|
||||||
|
IdentityService = identityService;
|
||||||
|
IpBanRepository = ipBanRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<bool> IsBanned()
|
||||||
|
{
|
||||||
|
var ip = IdentityService.GetIp();
|
||||||
|
|
||||||
|
return Task.FromResult(
|
||||||
|
IpBanRepository
|
||||||
|
.Get()
|
||||||
|
.Any(x => x.Ip == ip)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -118,6 +118,7 @@ namespace Moonlight
|
|||||||
builder.Services.AddSingleton<BucketService>();
|
builder.Services.AddSingleton<BucketService>();
|
||||||
builder.Services.AddScoped<RatingService>();
|
builder.Services.AddScoped<RatingService>();
|
||||||
builder.Services.AddScoped<ReCaptchaService>();
|
builder.Services.AddScoped<ReCaptchaService>();
|
||||||
|
builder.Services.AddScoped<IpBanService>();
|
||||||
|
|
||||||
builder.Services.AddScoped<GoogleOAuth2Service>();
|
builder.Services.AddScoped<GoogleOAuth2Service>();
|
||||||
builder.Services.AddScoped<DiscordOAuth2Service>();
|
builder.Services.AddScoped<DiscordOAuth2Service>();
|
||||||
|
|||||||
@@ -20,13 +20,8 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item mt-2">
|
<li class="nav-item mt-2">
|
||||||
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 3 ? "active" : "")" href="/admin/system/auditlog">
|
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 3 ? "active" : "")" href="/admin/system/security">
|
||||||
<TL>SecurityLog</TL>
|
<TL>Security</TL>
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item mt-2">
|
|
||||||
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 4 ? "active" : "")" href="/admin/system/auditlog">
|
|
||||||
<TL>ErrorLog</TL>
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item mt-2">
|
<li class="nav-item mt-2">
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
@inject EventSystem Event
|
@inject EventSystem Event
|
||||||
@inject ToastService ToastService
|
@inject ToastService ToastService
|
||||||
@inject SmartTranslateService SmartTranslateService
|
@inject SmartTranslateService SmartTranslateService
|
||||||
|
@inject IpBanService IpBanService
|
||||||
|
|
||||||
<GlobalErrorBoundary>
|
<GlobalErrorBoundary>
|
||||||
@{
|
@{
|
||||||
@@ -59,9 +60,11 @@
|
|||||||
<div id="kt_app_content_container" class="app-container container-fluid">
|
<div id="kt_app_content_container" class="app-container container-fluid">
|
||||||
<div class="mt-10">
|
<div class="mt-10">
|
||||||
<SoftErrorBoundary>
|
<SoftErrorBoundary>
|
||||||
@if (UserProcessed)
|
@if (!IsIpBanned)
|
||||||
{
|
{
|
||||||
@if (uri.LocalPath != "/login" &&
|
if (UserProcessed)
|
||||||
|
{
|
||||||
|
if (uri.LocalPath != "/login" &&
|
||||||
uri.LocalPath != "/passwordreset" &&
|
uri.LocalPath != "/passwordreset" &&
|
||||||
uri.LocalPath != "/register")
|
uri.LocalPath != "/register")
|
||||||
{
|
{
|
||||||
@@ -91,7 +94,7 @@
|
|||||||
{
|
{
|
||||||
@Body
|
@Body
|
||||||
|
|
||||||
<RatingPopup />
|
<RatingPopup/>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,6 +127,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="modal d-block">
|
||||||
|
<div class="modal-dialog modal-dialog-centered mw-900px">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="pt-2 modal-body py-lg-10 px-lg-10">
|
||||||
|
<h2>@(SmartTranslateService.Translate("Your ip has been banned"))</h2>
|
||||||
|
<p class="mt-3 fw-normal fs-6">@(SmartTranslateService.Translate("Your ip address has been banned by an admin"))</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</SoftErrorBoundary>
|
</SoftErrorBoundary>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -142,6 +159,8 @@
|
|||||||
private User? User;
|
private User? User;
|
||||||
private bool UserProcessed = false;
|
private bool UserProcessed = false;
|
||||||
|
|
||||||
|
private bool IsIpBanned = false;
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
AddBodyAttribute("data-kt-app-page-loading", "on");
|
AddBodyAttribute("data-kt-app-page-loading", "on");
|
||||||
@@ -170,6 +189,17 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
IsIpBanned = await IpBanService.IsBanned();
|
||||||
|
|
||||||
|
if(IsIpBanned)
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
|
||||||
|
await Event.On<Object>("ipBan.update", this, async o =>
|
||||||
|
{
|
||||||
|
IsIpBanned = await IpBanService.IsBanned();
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
});
|
||||||
|
|
||||||
User = await IdentityService.Get();
|
User = await IdentityService.Get();
|
||||||
UserProcessed = true;
|
UserProcessed = true;
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
|
|||||||
100
Moonlight/Shared/Views/Admin/Sys/Security.razor
Normal file
100
Moonlight/Shared/Views/Admin/Sys/Security.razor
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
@page "/admin/system/security"
|
||||||
|
|
||||||
|
@using Moonlight.Shared.Components.Navigations
|
||||||
|
@using BlazorTable
|
||||||
|
@using Moonlight.App.Database.Entities
|
||||||
|
@using Moonlight.App.Events
|
||||||
|
@using Moonlight.App.Repositories
|
||||||
|
@using Moonlight.App.Services
|
||||||
|
@using Moonlight.App.Services.Interop
|
||||||
|
|
||||||
|
@inject Repository<IpBan> IpBanRepository
|
||||||
|
@inject SmartTranslateService SmartTranslateService
|
||||||
|
@inject EventSystem Event
|
||||||
|
@inject ToastService ToastService
|
||||||
|
|
||||||
|
<OnlyAdmin>
|
||||||
|
<AdminSystemNavigation Index="3"/>
|
||||||
|
|
||||||
|
<div class="card mb-5">
|
||||||
|
<div class="card-header">
|
||||||
|
<div class="card-title">
|
||||||
|
<TL>Ip Bans</TL>
|
||||||
|
</div>
|
||||||
|
<div class="card-toolbar">
|
||||||
|
<table class="w-100">
|
||||||
|
<tr>
|
||||||
|
<td class="w-100">
|
||||||
|
<input @bind="Ip" type="text" class="form-control" placeholder="@(SmartTranslateService.Translate("Enter a ip"))"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<WButton OnClick="AddIpBan"
|
||||||
|
CssClasses="btn btn-primary ms-2"
|
||||||
|
Text="@(SmartTranslateService.Translate("Add"))"
|
||||||
|
WorkingText="@(SmartTranslateService.Translate("Adding"))">
|
||||||
|
</WButton>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<LazyLoader @ref="LazyLoader" Load="Load">
|
||||||
|
<Table TableItem="IpBan" Items="IpBans" PageSize="25" TableClass="table table-row-bordered table-row-gray-100 align-middle gs-0 gy-3" TableHeadClass="fw-bold text-muted">
|
||||||
|
<Column TableItem="IpBan" Title="@(SmartTranslateService.Translate("Ip"))" Field="@(x => x.Ip)" Filterable="true" Sortable="false"/>
|
||||||
|
<Column TableItem="IpBan" Title="" Field="@(x => x.Id)" Filterable="false" Sortable="false">
|
||||||
|
<Template>
|
||||||
|
<div class="text-end">
|
||||||
|
<DeleteButton Confirm="true" OnClick="() => DeleteIpBan(context)"></DeleteButton>
|
||||||
|
</div>
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
<Pager ShowPageNumber="true" ShowTotalCount="true"/>
|
||||||
|
</Table>
|
||||||
|
</LazyLoader>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</OnlyAdmin>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
private IpBan[] IpBans;
|
||||||
|
private string Ip;
|
||||||
|
|
||||||
|
private LazyLoader LazyLoader;
|
||||||
|
|
||||||
|
private Task Load(LazyLoader arg)
|
||||||
|
{
|
||||||
|
IpBans = IpBanRepository.Get().ToArray();
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ip Bans
|
||||||
|
|
||||||
|
private async Task AddIpBan()
|
||||||
|
{
|
||||||
|
var ipBan = IpBanRepository.Add(new()
|
||||||
|
{
|
||||||
|
Ip = Ip
|
||||||
|
});
|
||||||
|
|
||||||
|
await LazyLoader.Reload();
|
||||||
|
|
||||||
|
Ip = "";
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
|
||||||
|
await Event.Emit("ipBan.update");
|
||||||
|
|
||||||
|
await ToastService.Success(
|
||||||
|
SmartTranslateService.Translate($"Successfully banned {ipBan.Ip}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DeleteIpBan(IpBan ban)
|
||||||
|
{
|
||||||
|
IpBanRepository.Delete(ban);
|
||||||
|
|
||||||
|
await Event.Emit("ipBan.update");
|
||||||
|
await LazyLoader.Reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user