Fixed most buttons @onclick -> form
This commit is contained in:
@@ -14,10 +14,10 @@
|
|||||||
<h2 class="h5 card-title">Guest access</h2>
|
<h2 class="h5 card-title">Guest access</h2>
|
||||||
<p class="text-secondary">Change the code guests use to view the list.</p>
|
<p class="text-secondary">Change the code guests use to view the list.</p>
|
||||||
|
|
||||||
<form @onsubmit="UpdateGuestAccessCode" @onsubmit:preventDefault="true">
|
<form method="post" action="/admin/guest-access-code">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="guest-access-code">New guest access code</label>
|
<label class="form-label" for="guest-access-code">New guest access code</label>
|
||||||
<input id="guest-access-code" class="form-control" @bind="NewGuestAccessCode" />
|
<input id="guest-access-code" class="form-control" name="guestAccessCode" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary">
|
<button type="submit" class="btn btn-primary">
|
||||||
@@ -37,20 +37,20 @@
|
|||||||
<h2 class="h5 card-title">Create maintainer</h2>
|
<h2 class="h5 card-title">Create maintainer</h2>
|
||||||
<p class="text-secondary">Maintainers can add, edit and delete guests.</p>
|
<p class="text-secondary">Maintainers can add, edit and delete guests.</p>
|
||||||
|
|
||||||
<form @onsubmit="CreateMaintainer" @onsubmit:preventDefault="true">
|
<form method="post" action="/admin/maintainers/create">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="maintainer-username">Username</label>
|
<label class="form-label" for="maintainer-username">Username</label>
|
||||||
<input id="maintainer-username" class="form-control" @bind="MaintainerUsername" />
|
<input id="maintainer-username" class="form-control" name="username" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="maintainer-name">Name</label>
|
<label class="form-label" for="maintainer-name">Name</label>
|
||||||
<input id="maintainer-name" class="form-control" @bind="MaintainerDisplayName" />
|
<input id="maintainer-name" class="form-control" name="displayName" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="maintainer-password">Password</label>
|
<label class="form-label" for="maintainer-password">Password</label>
|
||||||
<input id="maintainer-password" class="form-control" type="password" @bind="MaintainerPassword" />
|
<input id="maintainer-password" class="form-control" type="password" name="password" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary">
|
<button type="submit" class="btn btn-primary">
|
||||||
@@ -87,9 +87,12 @@
|
|||||||
<div class="fw-semibold">@maintainer.DisplayName</div>
|
<div class="fw-semibold">@maintainer.DisplayName</div>
|
||||||
<div class="small text-secondary">@maintainer.Username</div>
|
<div class="small text-secondary">@maintainer.Username</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn btn-outline-danger btn-sm" @onclick="() => DeleteMaintainer(maintainer.Id)">
|
<form method="post" action="/admin/maintainers/delete">
|
||||||
Delete
|
<input type="hidden" name="id" value="@maintainer.Id" />
|
||||||
</button>
|
<button type="submit" class="btn btn-outline-danger btn-sm">
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@@ -102,9 +105,11 @@
|
|||||||
<h2 class="h5 card-title">Setup recovery</h2>
|
<h2 class="h5 card-title">Setup recovery</h2>
|
||||||
<p class="text-secondary">Use this after a partial setup if admin access exists but setup is incomplete.</p>
|
<p class="text-secondary">Use this after a partial setup if admin access exists but setup is incomplete.</p>
|
||||||
|
|
||||||
<button type="button" class="btn btn-outline-primary" @onclick="CompleteSetupRecovery">
|
<form method="post" action="/admin/setup-recovery">
|
||||||
Complete setup recovery
|
<button type="submit" class="btn btn-outline-primary">
|
||||||
</button>
|
Complete setup recovery
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
@if (!string.IsNullOrWhiteSpace(RecoveryMessage))
|
@if (!string.IsNullOrWhiteSpace(RecoveryMessage))
|
||||||
{
|
{
|
||||||
@@ -118,9 +123,11 @@
|
|||||||
<h2 class="h5 card-title">Reset setup</h2>
|
<h2 class="h5 card-title">Reset setup</h2>
|
||||||
<p class="text-secondary">Move existing users to backup and mark setup as incomplete.</p>
|
<p class="text-secondary">Move existing users to backup and mark setup as incomplete.</p>
|
||||||
|
|
||||||
<button type="button" class="btn btn-outline-danger" @onclick="ResetSetup">
|
<form method="post" action="/admin/reset-setup">
|
||||||
Reset setup
|
<button type="submit" class="btn btn-outline-danger">
|
||||||
</button>
|
Reset setup
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
@if (!string.IsNullOrWhiteSpace(Message))
|
@if (!string.IsNullOrWhiteSpace(Message))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,8 +25,25 @@ public partial class Admin
|
|||||||
protected string MaintainerMessage { get; set; } = "";
|
protected string MaintainerMessage { get; set; } = "";
|
||||||
protected List<UserDocument>? Maintainers { get; set; }
|
protected List<UserDocument>? Maintainers { get; set; }
|
||||||
|
|
||||||
|
[SupplyParameterFromQuery(Name = "message")]
|
||||||
|
public string? IncomingMessage { get; set; }
|
||||||
|
|
||||||
|
[SupplyParameterFromQuery(Name = "accessCodeMessage")]
|
||||||
|
public string? IncomingAccessCodeMessage { get; set; }
|
||||||
|
|
||||||
|
[SupplyParameterFromQuery(Name = "maintainerMessage")]
|
||||||
|
public string? IncomingMaintainerMessage { get; set; }
|
||||||
|
|
||||||
|
[SupplyParameterFromQuery(Name = "recoveryMessage")]
|
||||||
|
public string? IncomingRecoveryMessage { get; set; }
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
|
Message = IncomingMessage ?? "";
|
||||||
|
AccessCodeMessage = IncomingAccessCodeMessage ?? "";
|
||||||
|
MaintainerMessage = IncomingMaintainerMessage ?? "";
|
||||||
|
RecoveryMessage = IncomingRecoveryMessage ?? "";
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Maintainers = await UserService.GetMaintainersAsync();
|
Maintainers = await UserService.GetMaintainersAsync();
|
||||||
|
|||||||
@@ -9,10 +9,19 @@
|
|||||||
<p class="text-secondary mb-0">Add, edit, delete and filter guest entries.</p>
|
<p class="text-secondary mb-0">Add, edit, delete and filter guest entries.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-100 w-md-auto">
|
<form method="get" action="/guests" class="w-100 w-md-auto">
|
||||||
<label class="form-label" for="guest-search">Search</label>
|
<label class="form-label" for="guest-search">Search</label>
|
||||||
<input id="guest-search" class="form-control" @bind="SearchTerm" @bind:event="oninput" placeholder="Name, note or user" />
|
<div class="d-flex gap-2">
|
||||||
</div>
|
<input id="guest-search" class="form-control" name="search" value="@SearchTerm" placeholder="Name, note or user" />
|
||||||
|
<button type="submit" class="btn btn-outline-primary">
|
||||||
|
Search
|
||||||
|
</button>
|
||||||
|
@if (!string.IsNullOrWhiteSpace(SearchTerm))
|
||||||
|
{
|
||||||
|
<a class="btn btn-outline-secondary" href="/guests">Clear</a>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (!string.IsNullOrWhiteSpace(ErrorMessage))
|
@if (!string.IsNullOrWhiteSpace(ErrorMessage))
|
||||||
@@ -24,15 +33,15 @@
|
|||||||
<article class="card shadow-sm">
|
<article class="card shadow-sm">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h2 class="h5 card-title">Add guest</h2>
|
<h2 class="h5 card-title">Add guest</h2>
|
||||||
<form @onsubmit="AddGuest" @onsubmit:preventDefault="true">
|
<form method="post" action="/guests/add">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="new-guest-name">Name</label>
|
<label class="form-label" for="new-guest-name">Name</label>
|
||||||
<input id="new-guest-name" class="form-control" @bind="NewGuestName" />
|
<input id="new-guest-name" class="form-control" name="name" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="new-guest-notes">Notes</label>
|
<label class="form-label" for="new-guest-notes">Notes</label>
|
||||||
<textarea id="new-guest-notes" class="form-control" rows="3" @bind="NewGuestNotes"></textarea>
|
<textarea id="new-guest-notes" class="form-control" rows="3" name="notes"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary w-100">
|
<button type="submit" class="btn btn-primary w-100">
|
||||||
@@ -76,15 +85,17 @@
|
|||||||
{
|
{
|
||||||
<h2 class="h5 card-title">Edit guest</h2>
|
<h2 class="h5 card-title">Edit guest</h2>
|
||||||
|
|
||||||
<form class="d-flex flex-column flex-grow-1" @onsubmit="SaveEdit" @onsubmit:preventDefault="true">
|
<form class="d-flex flex-column flex-grow-1" method="post" action="/guests/update">
|
||||||
|
<input type="hidden" name="id" value="@guest.Id" />
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label">Name</label>
|
<label class="form-label">Name</label>
|
||||||
<input class="form-control" @bind="EditGuestName" />
|
<input class="form-control" name="name" value="@guest.Name" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label">Notes</label>
|
<label class="form-label">Notes</label>
|
||||||
<textarea class="form-control" rows="3" @bind="EditGuestNotes"></textarea>
|
<textarea class="form-control" rows="3" name="notes">@guest.Notes</textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="d-flex gap-2 mt-auto">
|
<div class="d-flex gap-2 mt-auto">
|
||||||
@@ -92,9 +103,9 @@
|
|||||||
Save
|
Save
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button type="button" class="btn btn-outline-secondary" @onclick="CancelEdit">
|
<a class="btn btn-outline-secondary" href="/guests">
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
}
|
}
|
||||||
@@ -117,13 +128,16 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="d-flex gap-2">
|
<div class="d-flex gap-2">
|
||||||
<button type="button" class="btn btn-outline-primary btn-sm" @onclick="() => StartEdit(guest)">
|
<a class="btn btn-outline-primary btn-sm" href="/guests?edit=@guest.Id">
|
||||||
Edit
|
Edit
|
||||||
</button>
|
</a>
|
||||||
|
|
||||||
<button type="button" class="btn btn-outline-danger btn-sm" @onclick="() => DeleteGuest(guest.Id)">
|
<form method="post" action="/guests/delete">
|
||||||
Delete
|
<input type="hidden" name="id" value="@guest.Id" />
|
||||||
</button>
|
<button type="submit" class="btn btn-outline-danger btn-sm">
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -23,6 +23,15 @@ public partial class Guests : ComponentBase
|
|||||||
|
|
||||||
protected List<GuestEntryDocument>? GuestEntries { get; set; }
|
protected List<GuestEntryDocument>? GuestEntries { get; set; }
|
||||||
|
|
||||||
|
[SupplyParameterFromQuery(Name = "error")]
|
||||||
|
public string? IncomingError { get; set; }
|
||||||
|
|
||||||
|
[SupplyParameterFromQuery(Name = "search")]
|
||||||
|
public string? IncomingSearchTerm { get; set; }
|
||||||
|
|
||||||
|
[SupplyParameterFromQuery(Name = "edit")]
|
||||||
|
public string? IncomingEditingGuestId { get; set; }
|
||||||
|
|
||||||
protected IEnumerable<GuestEntryDocument> FilteredGuestEntries
|
protected IEnumerable<GuestEntryDocument> FilteredGuestEntries
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -48,6 +57,17 @@ public partial class Guests : ComponentBase
|
|||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
|
SearchTerm = IncomingSearchTerm ?? "";
|
||||||
|
EditingGuestId = IncomingEditingGuestId;
|
||||||
|
|
||||||
|
ErrorMessage = IncomingError switch
|
||||||
|
{
|
||||||
|
"duplicate" => "A guest with this name and note already exists. Use a distinct note if this is a different person.",
|
||||||
|
"add-failed" => "Guest could not be added.",
|
||||||
|
null or "" => "",
|
||||||
|
_ => IncomingError
|
||||||
|
};
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
GuestEntries = await GuestEntryService.GetAllAsync();
|
GuestEntries = await GuestEntryService.GetAllAsync();
|
||||||
|
|||||||
@@ -40,24 +40,24 @@ else if (HasAnyUsers == true)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<form class="admin-panel-grid" @onsubmit="CompleteSetup" @onsubmit:preventDefault="true">
|
<form class="admin-panel-grid" method="post" action="/setup/complete">
|
||||||
<section class="card shadow-sm">
|
<section class="card shadow-sm">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h2 class="h5 card-title">First admin</h2>
|
<h2 class="h5 card-title">First admin</h2>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="setup-username">Username</label>
|
<label class="form-label" for="setup-username">Username</label>
|
||||||
<input id="setup-username" class="form-control" @bind="Username" />
|
<input id="setup-username" class="form-control" name="username" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="setup-name">Name</label>
|
<label class="form-label" for="setup-name">Name</label>
|
||||||
<input id="setup-name" class="form-control" @bind="DisplayName" />
|
<input id="setup-name" class="form-control" name="displayName" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="setup-password">Password</label>
|
<label class="form-label" for="setup-password">Password</label>
|
||||||
<input id="setup-password" class="form-control" type="password" @bind="Password" />
|
<input id="setup-password" class="form-control" type="password" name="password" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -69,7 +69,7 @@ else
|
|||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="setup-access-code">Guest access code</label>
|
<label class="form-label" for="setup-access-code">Guest access code</label>
|
||||||
<input id="setup-access-code" class="form-control" @bind="GuestAccessCode" />
|
<input id="setup-access-code" class="form-control" name="guestAccessCode" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary">
|
<button type="submit" class="btn btn-primary">
|
||||||
|
|||||||
@@ -25,8 +25,21 @@ public partial class Setup : ComponentBase
|
|||||||
|
|
||||||
protected bool? IsSetupComplete { get; set; }
|
protected bool? IsSetupComplete { get; set; }
|
||||||
|
|
||||||
|
[SupplyParameterFromQuery(Name = "error")]
|
||||||
|
public string? SetupError { get; set; }
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(SetupError))
|
||||||
|
{
|
||||||
|
ErrorMessage = SetupError switch
|
||||||
|
{
|
||||||
|
"existing-user" => "Setup cannot create another initial admin user.",
|
||||||
|
"setup-failed" => "Setup could not be completed. No partial admin user was kept.",
|
||||||
|
_ => SetupError
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IsSetupComplete = await SetupStatusService.IsSetupCompleteAsync();
|
IsSetupComplete = await SetupStatusService.IsSetupCompleteAsync();
|
||||||
|
|||||||
+272
-1
@@ -35,7 +35,11 @@ builder.Services
|
|||||||
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
|
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.Services.AddAuthorization();
|
builder.Services.AddAuthorization(options =>
|
||||||
|
{
|
||||||
|
options.AddPolicy("StaffOnly", policy => policy.RequireRole(UserRoles.Admin, UserRoles.Maintainer));
|
||||||
|
options.AddPolicy("AdminOnly", policy => policy.RequireRole(UserRoles.Admin));
|
||||||
|
});
|
||||||
|
|
||||||
builder.Services.AddHttpClient();
|
builder.Services.AddHttpClient();
|
||||||
builder.Services.AddHttpContextAccessor();
|
builder.Services.AddHttpContextAccessor();
|
||||||
@@ -173,6 +177,272 @@ app.MapPost("/guest/logout", (HttpContext httpContext) =>
|
|||||||
return Results.Redirect("/guest");
|
return Results.Redirect("/guest");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.MapPost("/setup/complete", async (
|
||||||
|
HttpContext httpContext,
|
||||||
|
UserService userService,
|
||||||
|
AccessCodeService accessCodeService,
|
||||||
|
SetupStatusService setupStatusService) =>
|
||||||
|
{
|
||||||
|
var form = await httpContext.Request.ReadFormAsync();
|
||||||
|
|
||||||
|
var username = form["username"].ToString();
|
||||||
|
var displayName = form["displayName"].ToString();
|
||||||
|
var password = form["password"].ToString();
|
||||||
|
var guestAccessCode = form["guestAccessCode"].ToString();
|
||||||
|
|
||||||
|
if (await userService.HasAnyUsersAsync())
|
||||||
|
{
|
||||||
|
return Results.Redirect("/setup?error=existing-user");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(displayName))
|
||||||
|
{
|
||||||
|
displayName = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
var adminCreated = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await userService.CreateAdminAsync(displayName, username, password);
|
||||||
|
adminCreated = true;
|
||||||
|
|
||||||
|
await accessCodeService.SetGuestAccessCodeAsync(guestAccessCode);
|
||||||
|
await setupStatusService.MarkSetupCompleteAsync();
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException exception)
|
||||||
|
{
|
||||||
|
if (adminCreated)
|
||||||
|
{
|
||||||
|
await userService.DeleteUserByUsernameAsync(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
var error = Uri.EscapeDataString(exception.Message);
|
||||||
|
return Results.Redirect($"/setup?error={error}");
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
if (adminCreated)
|
||||||
|
{
|
||||||
|
await userService.DeleteUserByUsernameAsync(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Results.Redirect("/setup?error=setup-failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Results.Redirect("/login");
|
||||||
|
});
|
||||||
|
|
||||||
|
app.MapPost("/guests/add", async (
|
||||||
|
HttpContext httpContext,
|
||||||
|
GuestEntryService guestEntryService) =>
|
||||||
|
{
|
||||||
|
var form = await httpContext.Request.ReadFormAsync();
|
||||||
|
var name = form["name"].ToString();
|
||||||
|
var notes = form["notes"].ToString();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (await guestEntryService.NameAndNotesExistAsync(name, notes))
|
||||||
|
{
|
||||||
|
return Results.Redirect("/guests?error=duplicate");
|
||||||
|
}
|
||||||
|
|
||||||
|
var userId = httpContext.User.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? "";
|
||||||
|
var username = httpContext.User.Identity?.Name ?? "unknown";
|
||||||
|
|
||||||
|
await guestEntryService.AddAsync(name, notes, userId, username);
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException exception)
|
||||||
|
{
|
||||||
|
var error = Uri.EscapeDataString(exception.Message);
|
||||||
|
return Results.Redirect($"/guests?error={error}");
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Results.Redirect("/guests?error=add-failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Results.Redirect("/guests");
|
||||||
|
}).RequireAuthorization("StaffOnly");
|
||||||
|
|
||||||
|
app.MapPost("/guests/delete", async (
|
||||||
|
HttpContext httpContext,
|
||||||
|
GuestEntryService guestEntryService) =>
|
||||||
|
{
|
||||||
|
var form = await httpContext.Request.ReadFormAsync();
|
||||||
|
var id = form["id"].ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(id))
|
||||||
|
{
|
||||||
|
return Results.Redirect("/guests?error=Guest entry is missing an id.");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await guestEntryService.DeleteAsync(id);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Results.Redirect("/guests?error=Guest could not be deleted.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Results.Redirect("/guests");
|
||||||
|
}).RequireAuthorization("StaffOnly");
|
||||||
|
|
||||||
|
app.MapPost("/guests/update", async (
|
||||||
|
HttpContext httpContext,
|
||||||
|
GuestEntryService guestEntryService) =>
|
||||||
|
{
|
||||||
|
var form = await httpContext.Request.ReadFormAsync();
|
||||||
|
var id = form["id"].ToString();
|
||||||
|
var name = form["name"].ToString();
|
||||||
|
var notes = form["notes"].ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(id))
|
||||||
|
{
|
||||||
|
return Results.Redirect("/guests?error=No guest entry is selected for editing.");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (await guestEntryService.NameAndNotesExistAsync(name, notes, id))
|
||||||
|
{
|
||||||
|
return Results.Redirect($"/guests?edit={Uri.EscapeDataString(id)}&error=duplicate");
|
||||||
|
}
|
||||||
|
|
||||||
|
await guestEntryService.UpdateAsync(id, name, notes);
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException exception)
|
||||||
|
{
|
||||||
|
var error = Uri.EscapeDataString(exception.Message);
|
||||||
|
return Results.Redirect($"/guests?edit={Uri.EscapeDataString(id)}&error={error}");
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Results.Redirect($"/guests?edit={Uri.EscapeDataString(id)}&error=Guest could not be updated.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Results.Redirect("/guests");
|
||||||
|
}).RequireAuthorization("StaffOnly");
|
||||||
|
|
||||||
|
app.MapPost("/admin/guest-access-code", async (
|
||||||
|
HttpContext httpContext,
|
||||||
|
AccessCodeService accessCodeService) =>
|
||||||
|
{
|
||||||
|
var form = await httpContext.Request.ReadFormAsync();
|
||||||
|
var accessCode = form["guestAccessCode"].ToString();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await accessCodeService.SetGuestAccessCodeAsync(accessCode);
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException exception)
|
||||||
|
{
|
||||||
|
var error = Uri.EscapeDataString(exception.Message);
|
||||||
|
return Results.Redirect($"/admin?accessCodeMessage={error}");
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Results.Redirect("/admin?accessCodeMessage=Guest access code could not be updated.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Results.Redirect("/admin?accessCodeMessage=Guest access code has been updated.");
|
||||||
|
}).RequireAuthorization("AdminOnly");
|
||||||
|
|
||||||
|
app.MapPost("/admin/maintainers/create", async (
|
||||||
|
HttpContext httpContext,
|
||||||
|
UserService userService) =>
|
||||||
|
{
|
||||||
|
var form = await httpContext.Request.ReadFormAsync();
|
||||||
|
var username = form["username"].ToString();
|
||||||
|
var displayName = form["displayName"].ToString();
|
||||||
|
var password = form["password"].ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(displayName))
|
||||||
|
{
|
||||||
|
displayName = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await userService.CreateMaintainerAsync(displayName, username, password);
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException exception)
|
||||||
|
{
|
||||||
|
var error = Uri.EscapeDataString(exception.Message);
|
||||||
|
return Results.Redirect($"/admin?maintainerMessage={error}");
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Results.Redirect("/admin?maintainerMessage=Maintainer could not be created.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Results.Redirect("/admin?maintainerMessage=Maintainer has been created.");
|
||||||
|
}).RequireAuthorization("AdminOnly");
|
||||||
|
|
||||||
|
app.MapPost("/admin/maintainers/delete", async (
|
||||||
|
HttpContext httpContext,
|
||||||
|
UserService userService) =>
|
||||||
|
{
|
||||||
|
var form = await httpContext.Request.ReadFormAsync();
|
||||||
|
var id = form["id"].ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(id))
|
||||||
|
{
|
||||||
|
return Results.Redirect("/admin?maintainerMessage=Maintainer is missing an id.");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await userService.DeleteMaintainerAsync(id);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Results.Redirect("/admin?maintainerMessage=Maintainer could not be deleted.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Results.Redirect("/admin?maintainerMessage=Maintainer has been deleted.");
|
||||||
|
}).RequireAuthorization("AdminOnly");
|
||||||
|
|
||||||
|
app.MapPost("/admin/reset-setup", async (
|
||||||
|
UserService userService,
|
||||||
|
SetupStatusService setupStatusService) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await userService.BackupAndClearUsersAsync("Setup reset from admin panel");
|
||||||
|
await setupStatusService.ResetSetupAsync();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Results.Redirect("/admin?message=Setup could not be reset.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Results.Redirect("/admin?message=Setup has been reset. Existing users were moved to backup.");
|
||||||
|
}).RequireAuthorization("AdminOnly");
|
||||||
|
|
||||||
|
app.MapPost("/admin/setup-recovery", async (
|
||||||
|
AccessCodeService accessCodeService,
|
||||||
|
SetupStatusService setupStatusService) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!await accessCodeService.HasGuestAccessCodeAsync())
|
||||||
|
{
|
||||||
|
return Results.Redirect("/admin?recoveryMessage=Set a guest access code before completing recovery.");
|
||||||
|
}
|
||||||
|
|
||||||
|
await setupStatusService.MarkSetupCompleteAsync();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Results.Redirect("/admin?recoveryMessage=Setup recovery could not be completed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Results.Redirect("/admin?recoveryMessage=Setup recovery has been completed.");
|
||||||
|
}).RequireAuthorization("AdminOnly");
|
||||||
|
|
||||||
using (var scope = app.Services.CreateScope())
|
using (var scope = app.Services.CreateScope())
|
||||||
{
|
{
|
||||||
var userService = scope.ServiceProvider.GetRequiredService<UserService>();
|
var userService = scope.ServiceProvider.GetRequiredService<UserService>();
|
||||||
@@ -209,6 +479,7 @@ app.Use(async (context, next) =>
|
|||||||
var allowedPaths =
|
var allowedPaths =
|
||||||
isStaticFile ||
|
isStaticFile ||
|
||||||
path.StartsWithSegments("/setup") ||
|
path.StartsWithSegments("/setup") ||
|
||||||
|
path.StartsWithSegments("/setup/complete") ||
|
||||||
path.StartsWithSegments("/auth/logout") ||
|
path.StartsWithSegments("/auth/logout") ||
|
||||||
path.StartsWithSegments("/guest/logout") ||
|
path.StartsWithSegments("/guest/logout") ||
|
||||||
path.StartsWithSegments("/_framework") ||
|
path.StartsWithSegments("/_framework") ||
|
||||||
|
|||||||
Reference in New Issue
Block a user