Move API key and mailbox management to their own pages
This commit is contained in:
parent
f274b113e2
commit
8933c6a372
9 changed files with 166 additions and 128 deletions
|
@ -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"};
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
69
src/Website/Controllers/Admin.cs
Normal file
69
src/Website/Controllers/Admin.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
30
src/Website/Views/Admin/ApiKeys.cshtml
Normal file
30
src/Website/Views/Admin/ApiKeys.cshtml
Normal 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>
|
12
src/Website/Views/Admin/Index.cshtml
Normal file
12
src/Website/Views/Admin/Index.cshtml
Normal 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>
|
29
src/Website/Views/Admin/Mailboxes.cshtml
Normal file
29
src/Website/Views/Admin/Mailboxes.cshtml
Normal 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>
|
|
@ -258,6 +258,16 @@ table.actions {
|
|||
}
|
||||
}
|
||||
|
||||
.block {
|
||||
display: block;
|
||||
}
|
||||
|
||||
label{
|
||||
&.block{
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
@import "blog.scss";
|
||||
@import "home.scss";
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue