Improve views; fix tests

This commit is contained in:
Dennis Reimann 2022-06-20 15:43:24 +02:00 committed by Andrew Camilleri
parent 2f1df3be7d
commit 27c5b16957
4 changed files with 72 additions and 71 deletions

View file

@ -12,6 +12,7 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OpenQA.Selenium;
using OpenQA.Selenium.Support.Extensions;
using OpenQA.Selenium.Support.UI;
using Xunit;
using Xunit.Abstractions;
using StoreData = BTCPayServer.Data.StoreData;
@ -57,6 +58,7 @@ namespace BTCPayServer.Tests
s.GoToProfile(ManageNavPages.APIKeys);
s.Driver.FindElement(By.Id("AddApiKey")).Click();
Assert.Contains("btcpay.server.canmodifyserversettings", s.Driver.PageSource);
//server management should show now
s.Driver.SetCheckbox(By.Id("btcpay.server.canmodifyserversettings"), true);
s.Driver.SetCheckbox(By.Id("btcpay.store.canmodifystoresettings"), true);
@ -136,10 +138,26 @@ namespace BTCPayServer.Tests
var appidentifier = "testapp";
var callbackUrl = s.ServerUri + "postredirect-callback-test";
var authUrl = BTCPayServerClient.GenerateAuthorizeUri(s.ServerUri,
new[] { Policies.CanModifyServerSettings }, applicationDetails: (appidentifier, new Uri(callbackUrl))).ToString();
// No upfront store selection with only server settings
TestLogs.LogInformation($"Going to auth URL {authUrl}");
s.GoToUrl(authUrl);
Assert.Contains(appidentifier, s.Driver.PageSource);
Assert.False(s.Driver.FindElement(By.Id("SpecificStores")).Displayed);
// Now with store settings
authUrl = BTCPayServerClient.GenerateAuthorizeUri(s.ServerUri,
new[] { Policies.CanModifyStoreSettings, Policies.CanModifyServerSettings }, applicationDetails: (appidentifier, new Uri(callbackUrl))).ToString();
TestLogs.LogInformation($"Going to auth URL {authUrl}");
s.GoToUrl(authUrl);
Assert.Contains(appidentifier, s.Driver.PageSource);
// Select a store
var select = new SelectElement(s.Driver.FindElement(By.Id("SpecificStores")));
select.SelectByIndex(0);
s.Driver.FindElement(By.Id("continue")).Click();
Assert.Equal("hidden", s.Driver.FindElement(By.Id("btcpay.store.canmodifystoresettings")).GetAttribute("type").ToLowerInvariant());
Assert.Equal("true", s.Driver.FindElement(By.Id("btcpay.store.canmodifystoresettings")).GetAttribute("value").ToLowerInvariant());
Assert.Equal("hidden", s.Driver.FindElement(By.Id("btcpay.server.canmodifyserversettings")).GetAttribute("type").ToLowerInvariant());
@ -168,13 +186,17 @@ namespace BTCPayServer.Tests
TestLogs.LogInformation("On auth URL 2");
Assert.DoesNotContain("kukksappname", s.Driver.PageSource);
// Select a store
select = new SelectElement(s.Driver.FindElement(By.Id("SpecificStores")));
select.SelectByIndex(0);
s.Driver.FindElement(By.Id("continue")).Click();
Assert.Equal("checkbox", s.Driver.FindElement(By.Id("btcpay.store.canmodifystoresettings")).GetAttribute("type").ToLowerInvariant());
Assert.Equal("true", s.Driver.FindElement(By.Id("btcpay.store.canmodifystoresettings")).GetAttribute("value").ToLowerInvariant());
Assert.Equal("checkbox", s.Driver.FindElement(By.Id("btcpay.server.canmodifyserversettings")).GetAttribute("type").ToLowerInvariant());
Assert.Equal("true", s.Driver.FindElement(By.Id("btcpay.server.canmodifyserversettings")).GetAttribute("value").ToLowerInvariant());
s.Driver.SetCheckbox(By.Id("btcpay.server.canmodifyserversettings"), false);
Assert.Contains("change-store-mode", s.Driver.PageSource);
TestLogs.LogInformation("Going to callback URL 2");
s.Driver.WaitForAndClick(By.Id("consent-yes"));

View file

@ -362,6 +362,10 @@ namespace BTCPayServer.Tests
public void Logout()
{
if (!Driver.PageSource.Contains("id=\"Nav-Logout\""))
{
Driver.Navigate().GoToUrl(ServerUri);
}
Driver.FindElement(By.Id("Nav-Account")).Click();
Driver.FindElement(By.Id("Nav-Logout")).Click();
}

View file

@ -191,6 +191,7 @@ namespace BTCPayServer.Controllers
private void AdjustVMForAuthorization(AuthorizeApiKeysViewModel vm)
{
var storeIds = vm.SpecificStores.ToArray();
var permissions = vm.Permissions?.Split(';') ?? Array.Empty<string>();
var permissionsWithStoreIDs = new List<string>();
@ -198,20 +199,18 @@ namespace BTCPayServer.Controllers
// Go over each permission and associated store IDs and join them
// so that permission for a specific store is parsed correctly
for (var i = 0; i < permissions.Length; i++)
foreach (var permission in permissions)
{
var currPerm = permissions[i];
var storeIds = vm.SpecificStores.ToArray();
if (storeIds.Length > 0)
if (!Policies.IsStorePolicy(permission) || storeIds.Length == 0)
{
for (var x = 0; x < storeIds.Length; x++)
{
permissionsWithStoreIDs.Add($"{currPerm}:{storeIds[x]}");
}
permissionsWithStoreIDs.Add(permission);
}
else
{
permissionsWithStoreIDs.Add(currPerm);
foreach (var t in storeIds)
{
permissionsWithStoreIDs.Add($"{permission}:{t}");
}
}
}
@ -220,7 +219,7 @@ namespace BTCPayServer.Controllers
for (var index = vm.PermissionValues.Count - 1; index >= 0; index--)
{
var permissionValue = vm.PermissionValues[index];
var wanted = parsedPermissions?.SingleOrDefault(permission =>
var wanted = parsedPermissions.SingleOrDefault(permission =>
permission.Key.Equals(permissionValue.Permission,
StringComparison.InvariantCultureIgnoreCase));
if (vm.Strict && !(wanted?.Any() ?? false))
@ -240,6 +239,9 @@ namespace BTCPayServer.Controllers
continue;
}
// Set the value to true and adjust the other fields based on the policy type
permissionValue.Value = true;
if (vm.SelectiveStores && Policies.IsStorePolicy(permissionValue.Permission) &&
wanted.Any(permission => !string.IsNullOrEmpty(permission.Scope)))
{
@ -250,7 +252,6 @@ namespace BTCPayServer.Controllers
{
permissionValue.StoreMode = AddApiKeyViewModel.ApiKeyStoreMode.AllStores;
permissionValue.SpecificStores = new List<string>();
permissionValue.Value = true;
}
}
}

View file

@ -83,6 +83,17 @@
<span asp-validation-for="Label" class="text-danger"></span>
</div>
@if (Model.NeedsStorePermission && Model.SpecificStores.Any())
{
<h2 class="h5 fw-semibold mt-4">Stores</h2>
<ul>
@foreach (var storeId in Model.SpecificStores)
{
<li>@Model.Stores.First(s => s.Id == storeId).StoreName</li>
}
</ul>
}
<h2 class="h5 fw-semibold mt-4">Permissions</h2>
@if (!permissions.Any())
{
@ -94,7 +105,7 @@
else
{
<div class="list-group list-group-flush mt-3">
@for (int i = 0; i < Model.PermissionValues.Count; i++)
@for (var i = 0; i < Model.PermissionValues.Count; i++)
{
<input type="hidden" asp-for="PermissionValues[i].Forbidden"/>
<input type="hidden" asp-for="PermissionValues[i].Permission"/>
@ -102,67 +113,30 @@
@if (Model.PermissionValues[i].Forbidden && !Model.Strict)
{
continue;
}
@if (Policies.IsStorePolicy(Model.PermissionValues[i].Permission))
{
<div class="list-group-item form-group">
<div class="form-check">
@if (Model.Strict || Model.PermissionValues[i].Forbidden)
{
<input id="@Model.PermissionValues[i].Permission" type="hidden" asp-for="PermissionValues[i].Value"/>
<input id="@Model.PermissionValues[i].Permission" type="checkbox" asp-for="PermissionValues[i].Value" class="form-check-input" disabled />
}
else
{
<input id="@Model.PermissionValues[i].Permission" type="checkbox" asp-for="PermissionValues[i].Value" class="form-check-input"/>
}
@* Wrapper div prevents the label to be muted in case of disabled checkbox (strict mode) *@
<div>
<label for="@Model.PermissionValues[i].Permission" class="form-check-label">@Model.PermissionValues[i].Title</label>
</div>
<div class="form-text text-muted">@Model.PermissionValues[i].Description</div>
<span asp-validation-for="PermissionValues[i].Value" class="text-danger"></span>
@if (Model.PermissionValues[i].Forbidden)
{
<br/>
<span class="text-danger">
This permission is not available for your account.
</span>
}
</div>
</div>
}
else
{
<div class="list-group-item form-group">
<div class="form-check">
@if (Model.Strict || Model.PermissionValues[i].Forbidden)
{
<input id="@Model.PermissionValues[i].Permission" type="hidden" asp-for="PermissionValues[i].Value"/>
<input type="checkbox" checked="@Model.PermissionValues[i].Value" disabled class="form-check-input"/>
}
else
{
<input id="@Model.PermissionValues[i].Permission" type="checkbox" asp-for="PermissionValues[i].Value" class="form-check-input"/>
}
@* Wrapper div prevents the label to be muted in case of disabled checkbox (strict mode) *@
<div>
<label for="@Model.PermissionValues[i].Permission" class="form-check-label">@Model.PermissionValues[i].Title</label>
</div>
<div class="form-text text-muted">@Model.PermissionValues[i].Description</div>
<span asp-validation-for="PermissionValues[i].Value" class="text-danger"></span>
@if (Model.PermissionValues[i].Forbidden)
{
<br/>
<span class="text-danger">
This permission is not available for your account.
</span>
}
<div class="list-group-item form-group">
<div class="form-check">
@if (Model.Strict || Model.PermissionValues[i].Forbidden)
{
<input id="@Model.PermissionValues[i].Permission" type="hidden" asp-for="PermissionValues[i].Value"/>
<input id="@Model.PermissionValues[i].Permission" type="checkbox" checked="@Model.PermissionValues[i].Value" class="form-check-input" disabled />
}
else
{
<input id="@Model.PermissionValues[i].Permission" type="checkbox" asp-for="PermissionValues[i].Value" class="form-check-input"/>
}
@* Wrapper div prevents the label to be muted in case of disabled checkbox (strict mode) *@
<div>
<label for="@Model.PermissionValues[i].Permission" class="form-check-label">@Model.PermissionValues[i].Title</label>
</div>
<div class="form-text text-muted">@Model.PermissionValues[i].Description</div>
<span asp-validation-for="PermissionValues[i].Value" class="text-danger"></span>
@if (Model.PermissionValues[i].Forbidden)
{
<div class="text-danger">This permission is not available for your account.</div>
}
</div>
}
</div>
}
</div>
}