Skip to content
59 changes: 48 additions & 11 deletions Refresh.Database/GameDatabaseContext.Registration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public bool IsEmailTaken(string emailAddress)
{
return this.GameUsers.Any(u => u.EmailAddress == emailAddress) ||
this.QueuedRegistrations.Any(r => r.EmailAddress == emailAddress) ||
this.IsEmailDisallowed(emailAddress);
this.IsEmailAddressDisallowed(emailAddress);
}

public void AddRegistrationToQueue(string username, string emailAddress, string passwordBcrypt)
Expand Down Expand Up @@ -253,34 +253,71 @@ public bool IsUserDisallowed(string username)
return this.DisallowedUsers.FirstOrDefault(u => u.Username == username) != null;
}

public bool DisallowEmail(string email)
public bool DisallowEmailAddress(string emailAddress)
{
if (this.IsEmailDisallowed(email))
if (this.IsEmailAddressDisallowed(emailAddress))
return false;

this.DisallowedEmails.Add(new()
this.DisallowedEmailAddresses.Add(new()
{
Email = email,
Address = emailAddress,
});
this.SaveChanges();

return true;
}

public bool ReallowEmail(string email)
public bool ReallowEmailAddress(string emailAddress)
{
DisallowedEmail? disallowedEmail = this.DisallowedEmails.FirstOrDefault(u => u.Email == email);
if (disallowedEmail == null)
DisallowedEmailAddress? DisallowedEmailAddress = this.DisallowedEmailAddresses.FirstOrDefault(u => u.Address == emailAddress);
if (DisallowedEmailAddress == null)
return false;

this.DisallowedEmails.Remove(disallowedEmail);
this.DisallowedEmailAddresses.Remove(DisallowedEmailAddress);
this.SaveChanges();

return true;
}

public bool IsEmailDisallowed(string email)
public bool IsEmailAddressDisallowed(string emailAddress)
{
return this.DisallowedEmails.Any(u => u.Email == email);
return this.DisallowedEmailAddresses.Any(u => u.Address == emailAddress);
}

private string GetEmailDomainFromAddress(string emailAddress)
=> emailAddress.Split('@').Last();

public bool DisallowEmailDomain(string emailAddress)
{
string emailDomain = this.GetEmailDomainFromAddress(emailAddress);
if (this.IsEmailDomainDisallowed(emailDomain))
return false;

this.DisallowedEmailDomains.Add(new()
{
Domain = emailDomain,
});
this.SaveChanges();

return true;
}

public bool ReallowEmailDomain(string emailAddress)
{
string emailDomain = this.GetEmailDomainFromAddress(emailAddress);
DisallowedEmailDomain? disallowedDomain = this.DisallowedEmailDomains.FirstOrDefault(u => u.Domain == emailDomain);
if (disallowedDomain == null)
return false;

this.DisallowedEmailDomains.Remove(disallowedDomain);
this.SaveChanges();

return true;
}

public bool IsEmailDomainDisallowed(string emailAddress)
{
string emailDomain = this.GetEmailDomainFromAddress(emailAddress);
return this.DisallowedEmailDomains.Any(u => u.Domain == emailDomain);
}
}
3 changes: 2 additions & 1 deletion Refresh.Database/GameDatabaseContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ public partial class GameDatabaseContext : DbContext, IDatabaseContext
internal DbSet<AssetDependencyRelation> AssetDependencyRelations { get; set; }
internal DbSet<GameReview> GameReviews { get; set; }
internal DbSet<DisallowedUser> DisallowedUsers { get; set; }
internal DbSet<DisallowedEmail> DisallowedEmails { get; set; }
internal DbSet<DisallowedEmailAddress> DisallowedEmailAddresses { get; set; }
internal DbSet<DisallowedEmailDomain> DisallowedEmailDomains { get; set; }
internal DbSet<RateReviewRelation> RateReviewRelations { get; set; }
internal DbSet<TagLevelRelation> TagLevelRelations { get; set; }
internal DbSet<GamePlaylist> GamePlaylists { get; set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

namespace Refresh.Database.Migrations
{
/// <inheritdoc />
[DbContext(typeof(GameDatabaseContext))]
[Migration("20260331143640_AddAbilityToDisallowEmailDomains")]
public partial class AddAbilityToDisallowEmailDomains : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameTable(name: "DisallowedEmails", newName: "DisallowedEmailAddresses");
migrationBuilder.DropPrimaryKey(name: "PK_DisallowedEmails", table: "DisallowedEmailAddresses");
migrationBuilder.RenameColumn(name: "Email", table: "DisallowedEmailAddresses", newName: "Address");
migrationBuilder.AddPrimaryKey(name: "PK_DisallowedEmailAddresses", table: "DisallowedEmailAddresses", column: "Address");

migrationBuilder.CreateTable(
name: "DisallowedEmailDomains",
columns: table => new
{
Domain = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_DisallowedEmailDomains", x => x.Domain);
});
}

/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "DisallowedEmailDomains");

migrationBuilder.RenameTable(name: "DisallowedEmailAddresses", newName: "DisallowedEmails");
migrationBuilder.DropPrimaryKey(name: "PK_DisallowedEmailAddresses", table: "DisallowedEmails");
migrationBuilder.RenameColumn(name: "Address", table: "DisallowedEmails", newName: "Email");
migrationBuilder.AddPrimaryKey(name: "PK_DisallowedEmails", table: "DisallowedEmails", column: "Email");
}
}
}
18 changes: 14 additions & 4 deletions Refresh.Database/Migrations/GameDatabaseContextModelSnapshot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1510,14 +1510,24 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("RequestStatistics");
});

modelBuilder.Entity("Refresh.Database.Models.Users.DisallowedEmail", b =>
modelBuilder.Entity("Refresh.Database.Models.Users.DisallowedEmailAddress", b =>
{
b.Property<string>("Email")
b.Property<string>("Address")
.HasColumnType("text");

b.HasKey("Email");
b.HasKey("Address");

b.ToTable("DisallowedEmails");
b.ToTable("DisallowedEmailAddresses");
});

modelBuilder.Entity("Refresh.Database.Models.Users.DisallowedEmailDomain", b =>
{
b.Property<string>("Domain")
.HasColumnType("text");

b.HasKey("Domain");

b.ToTable("DisallowedEmailDomains");
});

modelBuilder.Entity("Refresh.Database.Models.Users.DisallowedUser", b =>
Expand Down
9 changes: 0 additions & 9 deletions Refresh.Database/Models/Users/DisallowedEmail.cs

This file was deleted.

9 changes: 9 additions & 0 deletions Refresh.Database/Models/Users/DisallowedEmailAddress.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Refresh.Database.Models.Users;

#nullable disable

public partial class DisallowedEmailAddress
{
[Key]
public string Address { get; set; }
}
9 changes: 9 additions & 0 deletions Refresh.Database/Models/Users/DisallowedEmailDomain.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Refresh.Database.Models.Users;

#nullable disable

public partial class DisallowedEmailDomain
{
[Key]
public string Domain { get; set; }
}
40 changes: 32 additions & 8 deletions Refresh.GameServer/CommandLineManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,17 @@ private class Options
[Option("reallow-user", HelpText = "Re-allow a user to register. Username option is required if this is set.")]
public bool ReallowUser { get; set; }

[Option("disallow-email", HelpText = "Disallow the email from being used by anyone in the future. Email option is required if this is set.")]
public bool DisallowEmail { get; set; }
[Option("disallow-email", HelpText = "Disallow the email address from being used by anyone in the future. Email option is required if this is set.")]
public bool DisallowEmailAddress { get; set; }

[Option("reallow-email", HelpText = "Re-allow the email to be used by anyone. Email option is required if this is set")]
public bool ReallowEmail { get; set; }
[Option("reallow-email", HelpText = "Re-allow the email address to be used for account registration. Email option is required if this is set")]
public bool ReallowEmailAddress { get; set; }

[Option("disallow-email-domain", HelpText = "Disallow the email domain from being used by anyone in the future. Email option is required if this is set. If a whole Email address is given, only the substring after the last @ will be used.")]
public bool DisallowEmailDomain { get; set; }

[Option("reallow-email-domain", HelpText = "Re-allow the email domain to be used by anyone. Email option is required if this is set. If a whole Email address is given, only the substring after the last @ will be used.")]
public bool ReallowEmailDomain { get; set; }

[Option("rename-user", HelpText = "Changes a user's username. (old) username or Email option is required if this is set.")]
public string? RenameUser { get; set; }
Expand Down Expand Up @@ -194,24 +200,42 @@ private void StartWithOptions(Options options)
}
else Fail("No username was provided");
}
else if (options.DisallowEmail)
else if (options.DisallowEmailAddress)
{
if (options.EmailAddress != null)
{
if (!this._server.DisallowEmail(options.EmailAddress))
if (!this._server.DisallowEmailAddress(options.EmailAddress))
Fail("Email address is already disallowed");
}
else Fail("No email address was provided");
}
else if (options.ReallowEmail)
else if (options.ReallowEmailAddress)
{
if (options.EmailAddress != null)
{
if (!this._server.ReallowEmail(options.EmailAddress))
if (!this._server.ReallowEmailAddress(options.EmailAddress))
Fail("Email address is already allowed");
}
else Fail("No email address was provided");
}
else if (options.DisallowEmailDomain)
{
if (options.EmailAddress != null)
{
if (!this._server.DisallowEmailDomain(options.EmailAddress))
Fail("Email domain is already disallowed");
}
else Fail("No email domain was provided");
}
else if (options.ReallowEmailDomain)
{
if (options.EmailAddress != null)
{
if (!this._server.ReallowEmailDomain(options.EmailAddress))
Fail("Email domain is already allowed");
}
else Fail("No email domain was provided");
}
else if (options.RenameUser != null)
{
if(string.IsNullOrWhiteSpace(options.RenameUser))
Expand Down
26 changes: 20 additions & 6 deletions Refresh.GameServer/RefreshGameServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -285,18 +285,32 @@ public bool ReallowUser(string username)
return context.ReallowUser(username);
}

public bool DisallowEmail(string email)
public bool DisallowEmailAddress(string address)
{
using GameDatabaseContext context = this.GetContext();
return context.DisallowEmail(email);

return context.DisallowEmailAddress(address);
}

public bool ReallowEmail(string email)
public bool ReallowEmailAddress(string address)
{
using GameDatabaseContext context = this.GetContext();

return context.ReallowEmail(email);

return context.ReallowEmailAddress(address);
}

public bool DisallowEmailDomain(string domain)
{
using GameDatabaseContext context = this.GetContext();

return context.DisallowEmailDomain(domain);
}

public bool ReallowEmailDomain(string domain)
{
using GameDatabaseContext context = this.GetContext();

return context.ReallowEmailDomain(domain);
}

public void RenameUser(GameUser user, string newUsername, bool force = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ public ApiResponse<IApiAuthenticationResponse> Register(RequestContext context,
if (!smtpService.CheckEmailDomainValidity(body.EmailAddress))
return ApiValidationError.EmailDoesNotActuallyExistError;

if (database.IsUserDisallowed(body.Username) || database.IsEmailDisallowed(body.EmailAddress))
if (database.IsUserDisallowed(body.Username) || database.IsEmailAddressDisallowed(body.EmailAddress) || database.IsEmailDomainDisallowed(body.EmailAddress))
return new ApiAuthenticationError("You aren't allowed to play on this instance.");

if (!database.IsUsernameValid(body.Username))
Expand Down
Loading
Loading