mirror of
https://github.com/Jetsparrow/jetherald.git
synced 2026-01-21 07:56:09 +03:00
users touchups, example admin panel for invites
This commit is contained in:
parent
31c6ced153
commit
290b98c798
@ -61,6 +61,7 @@ public class UserInvite
|
|||||||
public uint PlanId { get; set; }
|
public uint PlanId { get; set; }
|
||||||
public uint RoleId { get; set; }
|
public uint RoleId { get; set; }
|
||||||
public uint RedeemedBy { get; set; }
|
public uint RedeemedBy { get; set; }
|
||||||
|
public string? RedeemedByLogin { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UserSession
|
public class UserSession
|
||||||
|
|||||||
13
JetHerald/Controllers/Ui/AdminController.cs
Normal file
13
JetHerald/Controllers/Ui/AdminController.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using JetHerald.Authorization;
|
||||||
|
|
||||||
|
namespace JetHerald.Controllers.Ui;
|
||||||
|
[Permission("admin")]
|
||||||
|
[Route("ui/admin")]
|
||||||
|
public class AdminController : Controller
|
||||||
|
{
|
||||||
|
public AdminController() { }
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult Index() => View();
|
||||||
|
}
|
||||||
@ -1,41 +1,35 @@
|
|||||||
using JetHerald.Authorization;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using JetHerald.Contracts;
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
|
using JetHerald.Authorization;
|
||||||
using JetHerald.Options;
|
using JetHerald.Options;
|
||||||
using JetHerald.Services;
|
using JetHerald.Services;
|
||||||
|
using JetHerald.Contracts;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
|
||||||
|
|
||||||
namespace JetHerald.Controllers.Ui;
|
namespace JetHerald.Controllers.Ui;
|
||||||
[Permission("admintools")]
|
|
||||||
public class AdminToolsController : Controller
|
[Permission("admin.invites")]
|
||||||
|
[Route("ui/admin/invites")]
|
||||||
|
public class AdminInvitesController : Controller
|
||||||
{
|
{
|
||||||
Db Db { get; }
|
Db Db { get; }
|
||||||
ILogger Log { get; }
|
|
||||||
AuthConfig AuthCfg { get; }
|
AuthConfig AuthCfg { get; }
|
||||||
public AdminToolsController(
|
public AdminInvitesController(
|
||||||
ILogger<AdminToolsController> log,
|
|
||||||
Db db,
|
Db db,
|
||||||
IOptionsSnapshot<AuthConfig> authCfg
|
IOptionsSnapshot<AuthConfig> authCfg
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Db = db;
|
Db = db;
|
||||||
Log = log;
|
|
||||||
AuthCfg = authCfg.Value;
|
AuthCfg = authCfg.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet, Route("ui/admintools/")]
|
[HttpGet]
|
||||||
public IActionResult Index() => View();
|
public async Task<IActionResult> Index()
|
||||||
|
|
||||||
|
|
||||||
[HttpGet, Route("ui/admintools/invites")]
|
|
||||||
public async Task<IActionResult> ViewInvites()
|
|
||||||
{
|
{
|
||||||
using var ctx = await Db.GetContext();
|
using var ctx = await Db.GetContext();
|
||||||
var invites = await ctx.GetInvites();
|
var invites = await ctx.GetInvites();
|
||||||
var plans = await ctx.GetPlans();
|
var plans = await ctx.GetPlans();
|
||||||
var roles = await ctx.GetRoles();
|
var roles = await ctx.GetRoles();
|
||||||
return View(new ViewInvitesModel
|
return View(new AdminInvitesModel
|
||||||
{
|
{
|
||||||
Invites = invites.ToArray(),
|
Invites = invites.ToArray(),
|
||||||
Plans = plans.ToDictionary(p => p.PlanId),
|
Plans = plans.ToDictionary(p => p.PlanId),
|
||||||
@ -50,17 +44,35 @@ public class AdminToolsController : Controller
|
|||||||
[BindProperty(Name = "roleId"), BindRequired]
|
[BindProperty(Name = "roleId"), BindRequired]
|
||||||
public uint RoleId { get; set; }
|
public uint RoleId { get; set; }
|
||||||
}
|
}
|
||||||
[HttpPost, Route("ui/admintools/invites/create")]
|
|
||||||
|
[Permission("admin.invites.create")]
|
||||||
|
[HttpPost, Route("create")]
|
||||||
public async Task<IActionResult> CreateInvite(CreateInviteRequest req)
|
public async Task<IActionResult> CreateInvite(CreateInviteRequest req)
|
||||||
{
|
{
|
||||||
using var ctx = await Db.GetContext();
|
using var ctx = await Db.GetContext();
|
||||||
await ctx.CreateUserInvite(req.PlanId, req.RoleId, TokenHelper.GetToken(AuthCfg.InviteCodeLength));
|
await ctx.CreateUserInvite(req.PlanId, req.RoleId, TokenHelper.GetToken(AuthCfg.InviteCodeLength));
|
||||||
ctx.Commit();
|
ctx.Commit();
|
||||||
return RedirectToAction(nameof(ViewInvites));
|
return RedirectToAction(nameof(Index));
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DeleteInviteRequest
|
||||||
|
{
|
||||||
|
[BindProperty(Name = "inviteId"), BindRequired]
|
||||||
|
public uint UserInviteId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Permission("admin.invites.delete")]
|
||||||
|
[HttpPost, Route("delete")]
|
||||||
|
public async Task<IActionResult> DeleteInvite(DeleteInviteRequest req)
|
||||||
|
{
|
||||||
|
using var ctx = await Db.GetContext();
|
||||||
|
await ctx.DeleteUserInvite(req.UserInviteId);
|
||||||
|
ctx.Commit();
|
||||||
|
return RedirectToAction(nameof(Index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ViewInvitesModel
|
public class AdminInvitesModel
|
||||||
{
|
{
|
||||||
public UserInvite[] Invites { get; set; }
|
public UserInvite[] Invites { get; set; }
|
||||||
public Dictionary<uint, Plan> Plans { get; set; }
|
public Dictionary<uint, Plan> Plans { get; set; }
|
||||||
@ -56,7 +56,10 @@ public class DbContext : IDisposable
|
|||||||
public Task<IEnumerable<Role>> GetRoles()
|
public Task<IEnumerable<Role>> GetRoles()
|
||||||
=> Tran.QueryAsync<Role>("SELECT * FROM role");
|
=> Tran.QueryAsync<Role>("SELECT * FROM role");
|
||||||
public Task<IEnumerable<UserInvite>> GetInvites()
|
public Task<IEnumerable<UserInvite>> GetInvites()
|
||||||
=> Tran.QueryAsync<UserInvite>("SELECT * FROM userinvite");
|
=> Tran.QueryAsync<UserInvite>(@"
|
||||||
|
SELECT ui.*, u.Login as RedeemedByLogin
|
||||||
|
FROM userinvite ui
|
||||||
|
LEFT JOIN user u ON ui.RedeemedBy = u.UserId");
|
||||||
|
|
||||||
public Task<IEnumerable<Heart>> GetHeartsForUser(uint userId)
|
public Task<IEnumerable<Heart>> GetHeartsForUser(uint userId)
|
||||||
=> Tran.QueryAsync<Heart>(
|
=> Tran.QueryAsync<Heart>(
|
||||||
@ -71,6 +74,11 @@ public class DbContext : IDisposable
|
|||||||
(@planId, @roleId, @inviteCode)",
|
(@planId, @roleId, @inviteCode)",
|
||||||
new { planId, roleId, inviteCode });
|
new { planId, roleId, inviteCode });
|
||||||
|
|
||||||
|
public Task DeleteUserInvite(uint inviteId)
|
||||||
|
=> Tran.ExecuteAsync(@" DELETE FROM userinvite WHERE UserInviteId = @intiteId",
|
||||||
|
new { inviteId });
|
||||||
|
|
||||||
|
|
||||||
public Task<Topic> GetTopic(string name)
|
public Task<Topic> GetTopic(string name)
|
||||||
=> Tran.QuerySingleOrDefaultAsync<Topic>(
|
=> Tran.QuerySingleOrDefaultAsync<Topic>(
|
||||||
"SELECT * FROM topic WHERE Name = @name",
|
"SELECT * FROM topic WHERE Name = @name",
|
||||||
|
|||||||
6
JetHerald/Views/Admin/Index.cshtml
Normal file
6
JetHerald/Views/Admin/Index.cshtml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<ul class="issues-list">
|
||||||
|
<li><a asp-controller="AdminInvites">Invites</a></li>
|
||||||
|
<li><a asp-controller="AdminUsers">Users</a></li>
|
||||||
|
<li><a asp-controller="AdminRoles">Roles</a></li>
|
||||||
|
<li><a asp-controller="AdminPlans">Plans</a></li>
|
||||||
|
</ul>
|
||||||
@ -1,6 +1,6 @@
|
|||||||
@model ViewInvitesModel
|
@model AdminInvitesModel
|
||||||
|
|
||||||
<form asp-controller="AdminTools" asp-action="CreateInvite" method="POST" enctype="application/x-www-form-urlencoded">
|
<form asp-controller="AdminInvites" asp-action="CreateInvite" method="POST" enctype="application/x-www-form-urlencoded">
|
||||||
<label for="roleselector">Role:</label>
|
<label for="roleselector">Role:</label>
|
||||||
<select name="roleId" required id="roleselector">
|
<select name="roleId" required id="roleselector">
|
||||||
@foreach (var role in Model.Roles.Values)
|
@foreach (var role in Model.Roles.Values)
|
||||||
@ -25,11 +25,23 @@
|
|||||||
@foreach (var invite in Model.Invites)
|
@foreach (var invite in Model.Invites)
|
||||||
{
|
{
|
||||||
<li>
|
<li>
|
||||||
<span style="font-family:monospace">@invite.InviteCode.Substring(0, 8)... r:(@Model.Roles[invite.RoleId].Name) p:(@Model.Plans[invite.PlanId].Name)</span>
|
<span style="font-family:monospace">@invite.InviteCode.Substring(0, 12)... r:(@Model.Roles[invite.RoleId].Name) p:(@Model.Plans[invite.PlanId].Name)</span>
|
||||||
<form asp-controller="Admin" asp-action="DeleteInvite" asp-route-inviteId="@invite.UserInviteId" method="POST" style="display:inline">
|
<form asp-controller="Admin" asp-action="DeleteInvite" asp-route-inviteId="@invite.UserInviteId" method="POST" style="display:inline">
|
||||||
<input type="submit" value="❌" style="display:inline; color:red;" class="buttonlink">
|
<input type="submit" value="❌" style="display:inline; color:red;" class="buttonlink">
|
||||||
</form>
|
</form>
|
||||||
<a asp-controller="Registration" asp-action="Register" asp-route-invite="@invite.InviteCode" class="copier" style="display:inline; color:blue">📤</a>
|
@if (invite.RedeemedBy == default)
|
||||||
|
{
|
||||||
|
<a class="copier" style="display:inline; color:blue"
|
||||||
|
asp-controller="Registration" asp-action="Register" asp-route-invite="@invite.InviteCode">
|
||||||
|
📤
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span>
|
||||||
|
@invite.RedeemedBy:@(invite.RedeemedByLogin ?? "deleted user")
|
||||||
|
</span>
|
||||||
|
}
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
@ -1,6 +0,0 @@
|
|||||||
<ul class="issues-list">
|
|
||||||
<li><a asp-action="ViewUsers">View all registered users</a></li>
|
|
||||||
<!-- <li><a asp-action="ViewInvites">View unredeemed invites</a></li>
|
|
||||||
<li><a asp-action="ViewRoles">View all roles</a></li>
|
|
||||||
-->
|
|
||||||
</ul>
|
|
||||||
@ -21,9 +21,9 @@
|
|||||||
{
|
{
|
||||||
<a asp-action="Index" asp-controller="Dashboard">Dashboard</a>
|
<a asp-action="Index" asp-controller="Dashboard">Dashboard</a>
|
||||||
}
|
}
|
||||||
@if (Context.UserCan("admintools"))
|
@if (Context.UserCan("admin"))
|
||||||
{
|
{
|
||||||
<a asp-action="Index" asp-controller="AdminTools">Admin tools</a>
|
<a asp-action="Index" asp-controller="Admin">Admin tools</a>
|
||||||
}
|
}
|
||||||
@if (User.IsAnonymous())
|
@if (User.IsAnonymous())
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user