mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-06-08 07:37:12 -04:00
Add IP block tables (#2131)
This commit is contained in:
committed by
Leendert de Borst
parent
a60d0966e6
commit
f0db97f4c2
@@ -142,6 +142,11 @@ public class AliasServerDbContext : WorkerStatusDbContext, IDataProtectionKeyCon
|
||||
/// </summary>
|
||||
public DbSet<MobileLoginRequest> MobileLoginRequests { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the BlockedIpRanges DbSet.
|
||||
/// </summary>
|
||||
public DbSet<BlockedIpRange> BlockedIpRanges { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets up the connection string if it is not already configured.
|
||||
/// </summary>
|
||||
|
||||
@@ -36,6 +36,11 @@ public class AliasVaultUser : IdentityUser
|
||||
/// </summary>
|
||||
public bool Blocked { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the user is marked as shadow-blocked.
|
||||
/// </summary>
|
||||
public bool ShadowBlocked { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets updated timestamp.
|
||||
/// </summary>
|
||||
|
||||
@@ -57,6 +57,11 @@ public enum AuthFailureReason
|
||||
/// </summary>
|
||||
RegistrationRateLimitExceeded = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the attempt was blocked because the originating IP address is on the blocklist.
|
||||
/// </summary>
|
||||
IpBlocked = 9,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the failure reason was unknown.
|
||||
/// </summary>
|
||||
|
||||
80
apps/server/Databases/AliasServerDb/BlockedIpRange.cs
Normal file
80
apps/server/Databases/AliasServerDb/BlockedIpRange.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// <copyright file="BlockedIpRange.cs" company="aliasvault">
|
||||
// Copyright (c) aliasvault. All rights reserved.
|
||||
// Licensed under the AGPLv3 license. See LICENSE.md file in the project root for full license information.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace AliasServerDb;
|
||||
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a blocked IP address range. Ranges are stored in CIDR notation (e.g. "1.2.3.4/32",
|
||||
/// "1.2.3.0/24", "1.2.0.0/16", "1.0.0.0/8") and are matched against the raw IP address
|
||||
/// of an incoming request.
|
||||
/// </summary>
|
||||
[Index(nameof(IpRange), Name = "IX_BlockedIpRange_IpRange", IsUnique = true)]
|
||||
[Index(nameof(Enabled), Name = "IX_BlockedIpRange_Enabled")]
|
||||
public class BlockedIpRange
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the unique identifier for the blocked IP range entry.
|
||||
/// </summary>
|
||||
[Key]
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the IP range in normalized CIDR notation (e.g. "1.2.3.0/24"). A single address is
|
||||
/// stored with a full prefix length (/32 for IPv4, /128 for IPv6).
|
||||
/// </summary>
|
||||
[Required]
|
||||
[MaxLength(50)]
|
||||
public string IpRange { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether requests from this range are blocked from registering new accounts.
|
||||
/// </summary>
|
||||
public bool BlockRegistration { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether requests from this range are blocked from logging in / general access.
|
||||
/// </summary>
|
||||
public bool BlockLogin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether requests from this range are shadow blocked. A shadow blocked user
|
||||
/// will be limited in certain ways, such as not being able to retrieve emails.
|
||||
/// </summary>
|
||||
public bool BlockShadow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an optional free-text reason / note describing why the range was blocked.
|
||||
/// </summary>
|
||||
[MaxLength(500)]
|
||||
public string? Reason { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this blocklist entry is currently active. Disabled entries are
|
||||
/// retained for auditing but are not enforced.
|
||||
/// </summary>
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an optional identifier of who created the entry (e.g. admin username or "system").
|
||||
/// </summary>
|
||||
[MaxLength(255)]
|
||||
public string? CreatedBy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the creation date of the blocklist entry.
|
||||
/// </summary>
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the last update date of the blocklist entry.
|
||||
/// </summary>
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
}
|
||||
1041
apps/server/Databases/AliasServerDb/Migrations/20260604174903_AddIpBlocklistAndShadowBlock.Designer.cs
generated
Normal file
1041
apps/server/Databases/AliasServerDb/Migrations/20260604174903_AddIpBlocklistAndShadowBlock.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace AliasServerDb.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddIpBlocklistAndShadowBlock : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "ShadowBlocked",
|
||||
table: "AliasVaultUsers",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "BlockedIpRanges",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
IpRange = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
BlockRegistration = table.Column<bool>(type: "boolean", nullable: false),
|
||||
BlockLogin = table.Column<bool>(type: "boolean", nullable: false),
|
||||
BlockShadow = table.Column<bool>(type: "boolean", nullable: false),
|
||||
Reason = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: true),
|
||||
Enabled = table.Column<bool>(type: "boolean", nullable: false),
|
||||
CreatedBy = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true),
|
||||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_BlockedIpRanges", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_BlockedIpRange_Enabled",
|
||||
table: "BlockedIpRanges",
|
||||
column: "Enabled");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_BlockedIpRange_IpRange",
|
||||
table: "BlockedIpRanges",
|
||||
column: "IpRange",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "BlockedIpRanges");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ShadowBlocked",
|
||||
table: "AliasVaultUsers");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -180,6 +180,9 @@ namespace AliasServerDb.Migrations
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("ShadowBlocked")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("SrpIdentity")
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("character varying(255)");
|
||||
@@ -317,6 +320,55 @@ namespace AliasServerDb.Migrations
|
||||
b.ToTable("AuthLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AliasServerDb.BlockedIpRange", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<bool>("BlockLogin")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("BlockRegistration")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("BlockShadow")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("CreatedBy")
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("character varying(255)");
|
||||
|
||||
b.Property<bool>("Enabled")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("IpRange")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<string>("Reason")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("character varying(500)");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex(new[] { "Enabled" }, "IX_BlockedIpRange_Enabled");
|
||||
|
||||
b.HasIndex(new[] { "IpRange" }, "IX_BlockedIpRange_IpRange")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("BlockedIpRanges");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AliasServerDb.Email", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
||||
Reference in New Issue
Block a user