Add ability to grant a user additional slots (#262)

* Add ability to grant a user additional slots

Closes #232

* Apply suggestions from code review

Co-authored-by: Josh <josh@slendy.pw>

* Move set granted slots form to partial

Reduces duplicate code.

* Apply suggestions from code review

Co-authored-by: Josh <josh@slendy.pw>

Co-authored-by: Josh <josh@slendy.pw>
This commit is contained in:
jvyden 2022-04-02 19:51:38 -04:00 committed by GitHub
commit ffae9a5ce6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 128 additions and 12 deletions

View file

@ -0,0 +1,30 @@
using LBPUnion.ProjectLighthouse;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ProjectLighthouse.Migrations
{
[DbContext(typeof(Database))]
[Migration("20220402212909_AddAdminGrantedSlotsToUser")]
public partial class AddAdminGrantedSlotsToUser : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "AdminGrantedSlots",
table: "Users",
type: "int",
nullable: false,
defaultValue: 0);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "AdminGrantedSlots",
table: "Users");
}
}
}

View file

@ -15,7 +15,7 @@ namespace ProjectLighthouse.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.2")
.HasAnnotation("ProductVersion", "6.0.3")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.AuthenticationAttempt", b =>
@ -695,6 +695,9 @@ namespace ProjectLighthouse.Migrations
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("AdminGrantedSlots")
.HasColumnType("int");
b.Property<bool>("Banned")
.HasColumnType("tinyint(1)");

View file

@ -0,0 +1,9 @@
@page "/admin/user/{id:int}/setGrantedSlots"
@model LBPUnion.ProjectLighthouse.Pages.Admin.AdminSetGrantedSlotsPage
@{
Layout = "Layouts/BaseLayout";
Model.Title = "Set granted slots for " + Model.TargetedUser!.Username;
}
@await Html.PartialAsync("Partials/AdminSetGrantedSlotsFormPartial", Model.TargetedUser)

View file

@ -0,0 +1,41 @@
#nullable enable
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Pages.Layouts;
using LBPUnion.ProjectLighthouse.Types;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Pages.Admin;
public class AdminSetGrantedSlotsPage : BaseLayout
{
public AdminSetGrantedSlotsPage(Database database) : base(database)
{}
public User? TargetedUser;
public async Task<IActionResult> OnGet([FromRoute] int id)
{
User? user = this.Database.UserFromWebRequest(this.Request);
if (user == null || !user.IsAdmin) return this.NotFound();
this.TargetedUser = await this.Database.Users.FirstOrDefaultAsync(u => u.UserId == id);
if (this.TargetedUser == null) return this.NotFound();
return this.Page();
}
public async Task<IActionResult> OnPost([FromRoute] int id, int grantedSlotCount)
{
User? user = this.Database.UserFromWebRequest(this.Request);
if (user == null || !user.IsAdmin) return this.NotFound();
this.TargetedUser = await this.Database.Users.FirstOrDefaultAsync(u => u.UserId == id);
if (this.TargetedUser == null) return this.NotFound();
this.TargetedUser.AdminGrantedSlots = grantedSlotCount;
await this.Database.SaveChangesAsync();
return this.Redirect($"/user/{this.TargetedUser.UserId}");
}
}

View file

@ -0,0 +1,12 @@
@model LBPUnion.ProjectLighthouse.Types.User
<form method="post" action="/admin/user/@Model.UserId/setGrantedSlots">
@Html.AntiForgeryToken()
<div class="ui left action input">
<button type="submit" class="ui blue button">
<i class="pencil icon"></i>
<span>Set Granted Slots</span>
</button>
<input type="text" name="grantedSlotCount" placeholder="Granted Slots" value="@Model.AdminGrantedSlots">
</div>
</form>

View file

@ -72,13 +72,6 @@
<span>Reset Password</span>
</a>
}
@if (Model.User != null && Model.User.IsAdmin && !Model.ProfileUser.Banned)
{
<a class="ui red button" href="/admin/user/@Model.ProfileUser.UserId/ban">
<i class="ban icon"></i>
<span>Ban User</span>
</a>
}
</div>
<div class="eight wide column">
<div class="ui blue segment">
@ -118,4 +111,23 @@
</div>
}
@await Html.PartialAsync("Partials/CommentsPartial")
@await Html.PartialAsync("Partials/CommentsPartial")
@if (Model.User != null && Model.User.IsAdmin)
{
<div class="ui yellow segment">
<h2>Admin Options</h2>
@if (!Model.ProfileUser.Banned)
{
<a class="ui red button" href="/admin/user/@Model.ProfileUser.UserId/ban">
<i class="ban icon"></i>
<span>Ban User</span>
</a>
<br><br>
}
@await Html.PartialAsync("Partials/AdminSetGrantedSlotsFormPartial", Model.ProfileUser)
</div>
}

View file

@ -2,6 +2,7 @@ using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text.Json.Serialization;
using System.Xml.Serialization;
using LBPUnion.ProjectLighthouse.Serialization;
using LBPUnion.ProjectLighthouse.Types.Profiles;
using LBPUnion.ProjectLighthouse.Types.Settings;
@ -199,11 +200,19 @@ public class User
}
#nullable disable
[JsonIgnore]
[XmlIgnore]
public int EntitledSlots => ServerSettings.Instance.EntitledSlots + this.AdminGrantedSlots;
/// <summary>
/// The number of slots remaining on the earth
/// </summary>
[JsonIgnore]
public int FreeSlots => ServerSettings.Instance.EntitledSlots - this.UsedSlots;
public int FreeSlots => this.EntitledSlots - this.UsedSlots;
[JsonIgnore]
[XmlIgnore]
public int AdminGrantedSlots { get; set; }
private static readonly string[] slotTypes =
{
@ -232,12 +241,12 @@ public class User
slotTypesLocal = slotTypes;
}
slots += LbpSerializer.StringElement("entitledSlots", ServerSettings.Instance.EntitledSlots);
slots += LbpSerializer.StringElement("entitledSlots", this.EntitledSlots);
slots += LbpSerializer.StringElement("freeSlots", this.FreeSlots);
foreach (string slotType in slotTypesLocal)
{
slots += LbpSerializer.StringElement(slotType + "EntitledSlots", ServerSettings.Instance.EntitledSlots);
slots += LbpSerializer.StringElement(slotType + "EntitledSlots", this.EntitledSlots);
// ReSharper disable once StringLiteralTypo
slots += LbpSerializer.StringElement(slotType + slotType == "crossControl" ? "PurchsedSlots" : "PurchasedSlots", 0);
slots += LbpSerializer.StringElement(slotType + "FreeSlots", this.FreeSlots);