Move API key and mailbox management to their own pages

This commit is contained in:
Robert Marshall 2021-05-31 08:24:49 +01:00
parent f274b113e2
commit 8933c6a372
9 changed files with 166 additions and 128 deletions

View file

@ -19,9 +19,7 @@ namespace Website.Tests.Controllers {
[Fact]
public void Login_WithReturnUrl_ReturnsViewThatHasModelWithReturnUrlAndFalseFailedAttempt() {
var authenticationProvider = Substitute.For<IAuthenticationProvider>();
var apiKeyManager = Substitute.For<IApiKeyManager>();
var mailboxesApi = Substitute.For<IMailboxesApi>();
var controller = new AccountController(authenticationProvider, apiKeyManager, mailboxesApi);
var controller = new AccountController(authenticationProvider);
var expected = new LoginViewModel {
ReturnUrl = "returnUrl",
@ -36,9 +34,7 @@ namespace Website.Tests.Controllers {
[Fact]
public void Login_WithReturnUrlAndFailedAttempt_ReturnsViewThatHasModelWithReturnUrlAndTrueFailedAttempt() {
var authenticationProvider = Substitute.For<IAuthenticationProvider>();
var apiKeyManager = Substitute.For<IApiKeyManager>();
var mailboxesApi = Substitute.For<IMailboxesApi>();
var controller = new AccountController(authenticationProvider, apiKeyManager, mailboxesApi);
var controller = new AccountController(authenticationProvider);
var expected = new LoginViewModel {
ReturnUrl = "returnUrl",
@ -53,9 +49,7 @@ namespace Website.Tests.Controllers {
[Fact]
public async Task Login_WithLoginRequest_WhenAuthenticationIsUnsuccessful_ReturnsViewThatHasModelWithReturnUrlAndTrueFailedAttempt() {
var authenticationProvider = Substitute.For<IAuthenticationProvider>();
var apiKeyManager = Substitute.For<IApiKeyManager>();
var mailboxesApi = Substitute.For<IMailboxesApi>();
var controller = new AccountController(authenticationProvider, apiKeyManager, mailboxesApi);
var controller = new AccountController(authenticationProvider);
var request = new LoginRequest {
Username = "username",
@ -82,9 +76,7 @@ namespace Website.Tests.Controllers {
serviceProvider.GetService(typeof(IAuthenticationService)).Returns(authenticationService);
var authenticationProvider = Substitute.For<IAuthenticationProvider>();
var apiKeyManager = Substitute.For<IApiKeyManager>();
var mailboxesApi = Substitute.For<IMailboxesApi>();
var controller = new AccountController(authenticationProvider, apiKeyManager, mailboxesApi) {
var controller = new AccountController(authenticationProvider) {
ControllerContext = new ControllerContext {
HttpContext = new DefaultHttpContext {
RequestServices = serviceProvider
@ -119,9 +111,7 @@ namespace Website.Tests.Controllers {
serviceProvider.GetService(typeof(IUrlHelperFactory)).Returns(urlHelperFactory);
var authenticationProvider = Substitute.For<IAuthenticationProvider>();
var apiKeyManager = Substitute.For<IApiKeyManager>();
var mailboxesApi = Substitute.For<IMailboxesApi>();
var controller = new AccountController(authenticationProvider, apiKeyManager, mailboxesApi) {
var controller = new AccountController(authenticationProvider) {
ControllerContext = new ControllerContext {
HttpContext = new DefaultHttpContext {
RequestServices = serviceProvider
@ -144,9 +134,7 @@ namespace Website.Tests.Controllers {
[Fact]
public async Task Login_WithLoginRequest_WhenAuthenticationServiceFails_ReturnsViewThatHasModelWithReturnUrlAndTrueFailedAttempt() {
var authenticationProvider = Substitute.For<IAuthenticationProvider>();
var apiKeyManager = Substitute.For<IApiKeyManager>();
var mailboxesApi = Substitute.For<IMailboxesApi>();
var controller = new AccountController(authenticationProvider, apiKeyManager, mailboxesApi);
var controller = new AccountController(authenticationProvider);
var request = new LoginRequest {Username = "username", Password = "password", ReturnUrl = "returnUrl"};

View file

@ -6,26 +6,19 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Website.Data;
using Website.Models.Auth;
using Website.Models.Mailboxes;
using Website.ViewModels;
namespace Website.Controllers {
public class AccountController:Controller {
private readonly IAuthenticationProvider _authenticationProvider;
private readonly IApiKeyManager _apiKeyManager;
private readonly IMailboxesApi _mailboxesApi;
public AccountController(IAuthenticationProvider authenticationProvider, IApiKeyManager apiKeyManager, IMailboxesApi mailboxesApi) {
public AccountController(IAuthenticationProvider authenticationProvider) {
_authenticationProvider = authenticationProvider;
_apiKeyManager = apiKeyManager;
_mailboxesApi = mailboxesApi;
}
[Authorize]
public async Task<IActionResult> Index() {
var keys = await _apiKeyManager.List();
var aliases = await _mailboxesApi.ListAliases();
var model = new AccountViewModel(keys, aliases);
public IActionResult Index() {
var model = new AccountViewModel();
return View(model);
}
@ -60,49 +53,8 @@ namespace Website.Controllers {
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
return string.IsNullOrEmpty(returnUrl)
? (IActionResult) RedirectToAction(nameof(Index))
? RedirectToAction(nameof(Index))
: Redirect(returnUrl);
}
public async Task<IActionResult> CreateApiKey(string name) {
await _apiKeyManager.Create(name);
return RedirectToAction(nameof(Index));
}
public async Task<IActionResult> EnableApiKey(string key) {
await _apiKeyManager.Enable(key);
return RedirectToAction(nameof(Index));
}
public async Task<IActionResult> DisableApiKey(string key) {
await _apiKeyManager.Disable(key);
return RedirectToAction(nameof(Index));
}
public async Task<IActionResult> DeleteApiKey(string key) {
await _apiKeyManager.Delete(key);
return RedirectToAction(nameof(Index));
}
public async Task<IActionResult> EnableAlias(int id) {
await _mailboxesApi.EnableAlias(id);
return RedirectToAction(nameof(Index));
}
public async Task<IActionResult> DisableAlias(int id) {
await _mailboxesApi.DisableAlias(id);
return RedirectToAction(nameof(Index));
}
public async Task<IActionResult> DeleteAlias(int id) {
await _mailboxesApi.DeleteAlias(id);
return RedirectToAction(nameof(Index));
}
public async Task<IActionResult> CreateAlias(string source, string destination, bool active) {
var alias = new NewAlias {Source = source, Destination = destination, Active = active};
await _mailboxesApi.CreateAlias(alias);
return RedirectToAction(nameof(Index));
}
}
}

View file

@ -0,0 +1,69 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Website.Data;
using Website.Models.Mailboxes;
namespace Website.Controllers {
[Authorize]
public class Admin : Controller {
private readonly IApiKeyManager _apiKeyManager;
private readonly IMailboxesApi _mailboxesApi;
public Admin(IApiKeyManager apiKeyManager, IMailboxesApi mailboxesApi) {
_apiKeyManager = apiKeyManager;
_mailboxesApi = mailboxesApi;
}
public async Task<IActionResult> ApiKeys() {
var keys = await _apiKeyManager.List();
return View(keys);
}
public async Task<IActionResult> Mailboxes() {
var aliases = await _mailboxesApi.ListAliases();
return View(aliases);
}
public async Task<IActionResult> CreateApiKey(string name) {
await _apiKeyManager.Create(name);
return RedirectToAction(nameof(ApiKeys));
}
public async Task<IActionResult> EnableApiKey(string key) {
await _apiKeyManager.Enable(key);
return RedirectToAction(nameof(ApiKeys));
}
public async Task<IActionResult> DisableApiKey(string key) {
await _apiKeyManager.Disable(key);
return RedirectToAction(nameof(ApiKeys));
}
public async Task<IActionResult> DeleteApiKey(string key) {
await _apiKeyManager.Delete(key);
return RedirectToAction(nameof(ApiKeys));
}
public async Task<IActionResult> EnableAlias(int id) {
await _mailboxesApi.EnableAlias(id);
return RedirectToAction(nameof(Mailboxes));
}
public async Task<IActionResult> DisableAlias(int id) {
await _mailboxesApi.DisableAlias(id);
return RedirectToAction(nameof(Mailboxes));
}
public async Task<IActionResult> DeleteAlias(int id) {
await _mailboxesApi.DeleteAlias(id);
return RedirectToAction(nameof(Mailboxes));
}
public async Task<IActionResult> CreateAlias(string source, string destination, bool active) {
var alias = new NewAlias {Source = source, Destination = destination, Active = active};
await _mailboxesApi.CreateAlias(alias);
return RedirectToAction(nameof(Mailboxes));
}
}
}

View file

@ -1,15 +1,4 @@
using System.Collections.Generic;
using Website.Models.ApiKey;
using Website.Models.Mailboxes;
namespace Website.ViewModels {
public class AccountViewModel {
public IEnumerable<ApiKey> ApiKeys { get; }
public IEnumerable<Alias> Aliases { get; }
public AccountViewModel(IEnumerable<ApiKey> apiKeys, IEnumerable<Alias> aliases) {
ApiKeys = apiKeys;
Aliases = aliases;
}
}
}

View file

@ -5,51 +5,10 @@
Layout = "_Layout";
}
<h2>Manage API Keys</h2>
<h3>Existing Keys</h3>
<div class="table-scroll-container">
<table class="actions">
@foreach (var apiKey in Model.ApiKeys)
{
<tr>
<td>@apiKey.Name</td>
<td class="stretch"><pre>@apiKey.Key</pre></td>
<td><img src="/images/copy.svg" alt="Copy" title="Copy" onclick="navigator.clipboard.writeText('@apiKey.Key')" /></td>
<td>@(apiKey.Enabled?"Enabled":"Disabled")</td>
<td><a asp-action="EnableApiKey" asp-route-key="@apiKey.Key"><img src="/images/enable.svg" alt="Enable" title="Enable" onclick="return confirm('Are you sure?')"/></a></td>
<td><a asp-action="DisableApiKey" asp-route-key="@apiKey.Key"><img src="/images/disable.svg" alt="Disable" title="Disable" onclick="return confirm('Are you sure?')"/></a></td>
<td><a asp-action="DeleteApiKey" asp-route-key="@apiKey.Key"><img src="/images/delete.svg" alt="Delete" title="Delete" onclick="return confirm('Are you sure?')"/></a></td>
</tr>
}
</table>
<h2>Admin Panel</h2>
<div>
<a asp-controller="Admin" asp-action="ApiKeys">Manage API Keys</a>
</div>
<h3>Create New Key</h3>
<form asp-action="CreateApiKey">
<label for="new-key-name">Name: </label><input type="text" name="name" id="new-key-name" />
<button type="submit">Create</button>
</form>
<h2>Manage Mailboxes</h2>
<h3>Aliases</h3>
<div class="table-scroll-container">
<table class="actions">
@foreach (var alias in Model.Aliases)
{
<tr>
<td>@alias.Source</td>
<td class="stretch">@alias.Destination</td>
<td>@(alias.Active?"Enabled":"Disabled")</td>
<td><a asp-action="EnableAlias" asp-route-id="@alias.Id"><img src="/images/enable.svg" alt="Enable" title="Enable" onclick="return confirm('Are you sure?')"/></a></td>
<td><a asp-action="DisableAlias" asp-route-id="@alias.Id"><img src="/images/disable.svg" alt="Disable" title="Disable" onclick="return confirm('Are you sure?')"/></a></td>
<td><a asp-action="DeleteAlias" asp-route-id="@alias.Id"><img src="/images/delete.svg" alt="Delete" title="Delete" onclick="return confirm('Are you sure?')"/></a></td>
</tr>
}
</table>
</div>
<h3>Create New Alias</h3>
<form asp-action="CreateAlias">
<label>Source: <input type="text" name="source" /></label>
<label>Destination: <input type="text" name="destination" /></label>
<label>@Html.CheckBox("active") Active</label>
<button type="submit">Create</button>
</form>
<div>
<a asp-controller="Admin" asp-action="Mailboxes">Manage Mailboxes</a>
</div>

View file

@ -0,0 +1,30 @@
@model IEnumerable<Website.Models.ApiKey.ApiKey>
@{
ViewBag.Title = "Manage Api Keys";
Layout = "_Layout";
}
<h2>Manage Api Keys</h2>
<h3>Existing Keys</h3>
<div class="table-scroll-container">
<table class="actions">
@foreach (var apiKey in Model)
{
<tr>
<td>@apiKey.Name</td>
<td class="stretch"><pre>@apiKey.Key</pre></td>
<td><img src="/images/copy.svg" alt="Copy" title="Copy" onclick="navigator.clipboard.writeText('@apiKey.Key')" /></td>
<td>@(apiKey.Enabled?"Enabled":"Disabled")</td>
<td><a asp-action="EnableApiKey" asp-route-key="@apiKey.Key"><img src="/images/enable.svg" alt="Enable" title="Enable" onclick="return confirm('Are you sure?')"/></a></td>
<td><a asp-action="DisableApiKey" asp-route-key="@apiKey.Key"><img src="/images/disable.svg" alt="Disable" title="Disable" onclick="return confirm('Are you sure?')"/></a></td>
<td><a asp-action="DeleteApiKey" asp-route-key="@apiKey.Key"><img src="/images/delete.svg" alt="Delete" title="Delete" onclick="return confirm('Are you sure?')"/></a></td>
</tr>
}
</table>
</div>
<h3>Create New Key</h3>
<form asp-action="CreateApiKey">
<label class="block">Name: <input type="text" name="name" /> </label>
<button type="submit">Create</button>
</form>

View file

@ -0,0 +1,12 @@
@{
ViewBag.Title = "Admin Panel";
Layout = "_Layout";
}
<h2>Admin Panel</h2>
<div>
<a asp-controller="Admin" asp-action="ApiKeys">Manage API Keys</a>
</div>
<div>
<a asp-controller="Admin" asp-action="Mailboxes">Manage Mailboxes</a>
</div>

View file

@ -0,0 +1,29 @@
@model IEnumerable<Website.Models.Mailboxes.Alias>
@{
ViewBag.Title = "Manage Mailboxes";
Layout = "_Layout";
}
<h2>Aliases</h2>
<div class="table-scroll-container">
<table class="actions">
@foreach (var alias in Model)
{
<tr>
<td>@alias.Source</td>
<td class="stretch">@alias.Destination</td>
<td>@(alias.Active?"Enabled":"Disabled")</td>
<td><a asp-action="EnableAlias" asp-route-id="@alias.Id"><img src="/images/enable.svg" alt="Enable" title="Enable" onclick="return confirm('Are you sure?')"/></a></td>
<td><a asp-action="DisableAlias" asp-route-id="@alias.Id"><img src="/images/disable.svg" alt="Disable" title="Disable" onclick="return confirm('Are you sure?')"/></a></td>
<td><a asp-action="DeleteAlias" asp-route-id="@alias.Id"><img src="/images/delete.svg" alt="Delete" title="Delete" onclick="return confirm('Are you sure?')"/></a></td>
</tr>
}
</table>
</div>
<h3>Create New Alias</h3>
<form asp-action="CreateAlias">
<label class="block">Source: <input type="text" name="source" /></label>
<label class="block">Destination: <input type="text" name="destination" /></label>
<label class="block">@Html.CheckBox("active") Active</label>
<button type="submit">Create</button>
</form>

View file

@ -258,6 +258,16 @@ table.actions {
}
}
.block {
display: block;
}
label{
&.block{
margin-bottom: 5px;
}
}
@import "blog.scss";
@import "home.scss";