Rename Permissions.Can.. to Policies.Can..

This commit is contained in:
nicolas.dorier
2020-03-20 13:41:47 +09:00
parent 44b3bb34a4
commit 318d826694
13 changed files with 70 additions and 68 deletions

View File

@@ -5,7 +5,7 @@ using System.Text.Json.Serialization;
namespace BTCPayServer.Client
{
public class Permission
public class Policies
{
public const string CanModifyServerSettings = "btcpay.server.canmodifyserversettings";
public const string CanModifyStoreSettings = "btcpay.store.canmodifystoresettings";
@@ -15,7 +15,6 @@ namespace BTCPayServer.Client
public const string CanViewProfile = "btcpay.user.canviewprofile";
public const string CanCreateUser = "btcpay.server.cancreateuser";
public const string Unrestricted = "unrestricted";
public static IEnumerable<string> AllPolicies
{
get
@@ -30,7 +29,18 @@ namespace BTCPayServer.Client
yield return Unrestricted;
}
}
public static bool IsValidPolicy(string policy)
{
return AllPolicies.Any(p => p.Equals(policy, StringComparison.OrdinalIgnoreCase));
}
public static bool IsStorePolicy(string policy)
{
return policy.StartsWith("btcpay.store", StringComparison.OrdinalIgnoreCase);
}
}
public class Permission
{
public static Permission Create(string policy, string storeId = null)
{
if (TryCreatePermission(policy, storeId, out var r))
@@ -44,9 +54,9 @@ namespace BTCPayServer.Client
if (policy == null)
throw new ArgumentNullException(nameof(policy));
policy = policy.Trim().ToLowerInvariant();
if (!IsValidPolicy(policy))
if (!Policies.IsValidPolicy(policy))
return false;
if (storeId != null && !IsStorePolicy(policy))
if (storeId != null && !Policies.IsStorePolicy(policy))
return false;
permission = new Permission(policy, storeId);
return true;
@@ -62,7 +72,7 @@ namespace BTCPayServer.Client
if (separator == -1)
{
str = str.ToLowerInvariant();
if (!IsValidPolicy(str))
if (!Policies.IsValidPolicy(str))
return false;
permission = new Permission(str, null);
return true;
@@ -70,9 +80,9 @@ namespace BTCPayServer.Client
else
{
var policy = str.Substring(0, separator).ToLowerInvariant();
if (!IsValidPolicy(policy))
if (!Policies.IsValidPolicy(policy))
return false;
if (!IsStorePolicy(policy))
if (!Policies.IsStorePolicy(policy))
return false;
var storeId = str.Substring(separator + 1);
if (storeId.Length == 0)
@@ -82,15 +92,7 @@ namespace BTCPayServer.Client
}
}
private static bool IsValidPolicy(string policy)
{
return AllPolicies.Any(p => p.Equals(policy, StringComparison.OrdinalIgnoreCase));
}
private static bool IsStorePolicy(string policy)
{
return policy.StartsWith("btcpay.store", StringComparison.OrdinalIgnoreCase);
}
internal Permission(string policy, string storeId)
{
@@ -107,7 +109,7 @@ namespace BTCPayServer.Client
{
return false;
}
if (!IsStorePolicy(subpermission.Policy))
if (!Policies.IsStorePolicy(subpermission.Policy))
return true;
return StoreId == null || subpermission.StoreId == this.StoreId;
}
@@ -133,15 +135,15 @@ namespace BTCPayServer.Client
private bool ContainsPolicy(string subpolicy)
{
if (this.Policy == Unrestricted)
if (this.Policy == Policies.Unrestricted)
return true;
if (this.Policy == subpolicy)
return true;
if (subpolicy == CanViewStoreSettings && this.Policy == CanModifyStoreSettings)
if (subpolicy == Policies.CanViewStoreSettings && this.Policy == Policies.CanModifyStoreSettings)
return true;
if (subpolicy == CanCreateInvoice && this.Policy == CanModifyStoreSettings)
if (subpolicy == Policies.CanCreateInvoice && this.Policy == Policies.CanModifyStoreSettings)
return true;
if (subpolicy == CanViewProfile && this.Policy == CanModifyProfile)
if (subpolicy == Policies.CanViewProfile && this.Policy == Policies.CanModifyProfile)
return true;
return false;
}

View File

@@ -67,7 +67,7 @@ namespace BTCPayServer.Tests
var superApiKey = s.AssertHappyMessage().FindElement(By.TagName("code")).Text;
//this api key has access to everything
await TestApiAgainstAccessToken(superApiKey, tester, user, $"{Permission.CanModifyServerSettings};{Permission.CanModifyStoreSettings};{Permission.CanViewProfile}");
await TestApiAgainstAccessToken(superApiKey, tester, user, $"{Policies.CanModifyServerSettings};{Policies.CanModifyStoreSettings};{Policies.CanViewProfile}");
s.Driver.FindElement(By.Id("AddApiKey")).Click();
@@ -75,7 +75,7 @@ namespace BTCPayServer.Tests
s.Driver.FindElement(By.Id("Generate")).Click();
var serverOnlyApiKey = s.AssertHappyMessage().FindElement(By.TagName("code")).Text;
await TestApiAgainstAccessToken(serverOnlyApiKey, tester, user,
Permission.CanModifyServerSettings);
Policies.CanModifyServerSettings);
s.Driver.FindElement(By.Id("AddApiKey")).Click();
@@ -83,7 +83,7 @@ namespace BTCPayServer.Tests
s.Driver.FindElement(By.Id("Generate")).Click();
var allStoreOnlyApiKey = s.AssertHappyMessage().FindElement(By.TagName("code")).Text;
await TestApiAgainstAccessToken(allStoreOnlyApiKey, tester, user,
Permission.CanModifyStoreSettings);
Policies.CanModifyStoreSettings);
s.Driver.FindElement(By.Id("AddApiKey")).Click();
s.Driver.FindElement(By.CssSelector("button[value=change-store-mode]")).Click();
@@ -95,7 +95,7 @@ namespace BTCPayServer.Tests
s.Driver.FindElement(By.Id("Generate")).Click();
var selectiveStoreApiKey = s.AssertHappyMessage().FindElement(By.TagName("code")).Text;
await TestApiAgainstAccessToken(selectiveStoreApiKey, tester, user,
Permission.Create(Permission.CanModifyStoreSettings, storeId).ToString());
Permission.Create(Policies.CanModifyStoreSettings, storeId).ToString());
s.Driver.FindElement(By.Id("AddApiKey")).Click();
s.Driver.FindElement(By.Id("Generate")).Click();
@@ -117,7 +117,7 @@ namespace BTCPayServer.Tests
//strict
//selectiveStores
var authUrl = BTCPayServerClient.GenerateAuthorizeUri(tester.PayTester.ServerUri,
new[] { Permission.CanModifyStoreSettings, Permission.CanModifyServerSettings }).ToString();
new[] { Policies.CanModifyStoreSettings, Policies.CanModifyServerSettings }).ToString();
s.Driver.Navigate().GoToUrl(authUrl);
s.Driver.PageSource.Contains("kukksappname");
Assert.Equal("hidden", s.Driver.FindElement(By.Id("btcpay.store.canmodifystoresettings")).GetAttribute("type").ToLowerInvariant());
@@ -136,7 +136,7 @@ namespace BTCPayServer.Tests
(await apiKeyRepo.GetKey(results.Single(pair => pair.Key == "key").Value)).Permissions);
authUrl = BTCPayServerClient.GenerateAuthorizeUri(tester.PayTester.ServerUri,
new[] { Permission.CanModifyStoreSettings, Permission.CanModifyServerSettings }, false, true).ToString();
new[] { Policies.CanModifyStoreSettings, Policies.CanModifyServerSettings }, false, true).ToString();
s.Driver.Navigate().GoToUrl(authUrl);
Assert.DoesNotContain("kukksappname", s.Driver.PageSource);
@@ -172,7 +172,7 @@ namespace BTCPayServer.Tests
Assert.True(permissions.Any(p => p == expectPermission), $"Missing expected permission {expectPermission}");
}
if (permissions.Contains(Permission.Create(Permission.CanViewProfile)))
if (permissions.Contains(Permission.Create(Policies.CanViewProfile)))
{
var resultUser = await TestApiAgainstAccessToken<string>(accessToken, $"{TestApiPath}/me/id", tester.PayTester.HttpClient);
Assert.Equal(testAccount.UserId, resultUser);
@@ -188,10 +188,10 @@ namespace BTCPayServer.Tests
var secondUser = tester.NewAccount();
secondUser.GrantAccess();
var canModifyAllStores = Permission.Create(Permission.CanModifyStoreSettings, null);
var canModifyServer = Permission.Create(Permission.CanModifyServerSettings, null);
var unrestricted = Permission.Create(Permission.Unrestricted, null);
var selectiveStorePermissions = permissions.Where(p => p.StoreId != null && p.Policy == Permission.CanModifyStoreSettings);
var canModifyAllStores = Permission.Create(Policies.CanModifyStoreSettings, null);
var canModifyServer = Permission.Create(Policies.CanModifyServerSettings, null);
var unrestricted = Permission.Create(Policies.Unrestricted, null);
var selectiveStorePermissions = permissions.Where(p => p.StoreId != null && p.Policy == Policies.CanModifyStoreSettings);
if (permissions.Contains(canModifyAllStores) || selectiveStorePermissions.Any())
{
var resultStores =
@@ -209,7 +209,7 @@ namespace BTCPayServer.Tests
}
bool shouldBeAuthorized = false;
if (permissions.Contains(canModifyAllStores) || selectiveStorePermissions.Contains(Permission.Create(Permission.CanViewStoreSettings, testAccount.StoreId)))
if (permissions.Contains(canModifyAllStores) || selectiveStorePermissions.Contains(Permission.Create(Policies.CanViewStoreSettings, testAccount.StoreId)))
{
Assert.True(await TestApiAgainstAccessToken<bool>(accessToken,
$"{TestApiPath}/me/stores/{testAccount.StoreId}/can-view",
@@ -218,7 +218,7 @@ namespace BTCPayServer.Tests
data => data.Id.Equals(testAccount.StoreId, StringComparison.InvariantCultureIgnoreCase));
shouldBeAuthorized = true;
}
if (permissions.Contains(canModifyAllStores) || selectiveStorePermissions.Contains(Permission.Create(Permission.CanModifyStoreSettings, testAccount.StoreId)))
if (permissions.Contains(canModifyAllStores) || selectiveStorePermissions.Contains(Permission.Create(Policies.CanModifyStoreSettings, testAccount.StoreId)))
{
Assert.True(await TestApiAgainstAccessToken<bool>(accessToken,
$"{TestApiPath}/me/stores/{testAccount.StoreId}/can-view",

View File

@@ -38,7 +38,7 @@ namespace BTCPayServer.Tests
var user = tester.NewAccount();
user.GrantAccess();
await user.MakeAdmin();
var client = await user.CreateClient(Permission.CanModifyServerSettings, Permission.CanModifyStoreSettings);
var client = await user.CreateClient(Policies.CanModifyServerSettings, Policies.CanModifyStoreSettings);
//Get current api key
var apiKeyData = await client.GetCurrentAPIKeyInfo();
Assert.NotNull(apiKeyData);
@@ -97,14 +97,14 @@ namespace BTCPayServer.Tests
var adminAcc = tester.NewAccount();
adminAcc.UserId = admin.Id;
adminAcc.IsAdmin = true;
var adminClient = await adminAcc.CreateClient(Permission.CanModifyProfile);
var adminClient = await adminAcc.CreateClient(Policies.CanModifyProfile);
// We should be forbidden to create a new user without proper admin permissions
await AssertHttpError(403, async () => await adminClient.CreateUser(new CreateApplicationUserRequest() { Email = "test4@gmail.com", Password = "afewfoiewiou" }));
await AssertHttpError(403, async () => await adminClient.CreateUser(new CreateApplicationUserRequest() { Email = "test4@gmail.com", Password = "afewfoiewiou", IsAdministrator = true }));
// However, should be ok with the server management permissions
adminClient = await adminAcc.CreateClient(Permission.CanModifyServerSettings);
adminClient = await adminAcc.CreateClient(Policies.CanModifyServerSettings);
await adminClient.CreateUser(new CreateApplicationUserRequest() { Email = "test4@gmail.com", Password = "afewfoiewiou" });
// Even creating new admin should be ok
await adminClient.CreateUser(new CreateApplicationUserRequest() { Email = "admin4@gmail.com", Password = "afewfoiewiou", IsAdministrator = true });
@@ -112,7 +112,7 @@ namespace BTCPayServer.Tests
var user1Acc = tester.NewAccount();
user1Acc.UserId = user1.Id;
user1Acc.IsAdmin = false;
var user1Client = await user1Acc.CreateClient(Permission.CanModifyServerSettings);
var user1Client = await user1Acc.CreateClient(Policies.CanModifyServerSettings);
// User1 trying to get server management would still fail to create user
await AssertHttpError(403, async () => await user1Client.CreateUser(new CreateApplicationUserRequest() { Email = "test8@gmail.com", Password = "afewfoiewiou" }));
@@ -141,9 +141,9 @@ namespace BTCPayServer.Tests
var user = tester.NewAccount();
user.GrantAccess();
await user.MakeAdmin();
var clientProfile = await user.CreateClient(Permission.CanModifyProfile);
var clientServer = await user.CreateClient(Permission.CanModifyServerSettings, Permission.CanViewProfile);
var clientInsufficient = await user.CreateClient(Permission.CanModifyStoreSettings);
var clientProfile = await user.CreateClient(Policies.CanModifyProfile);
var clientServer = await user.CreateClient(Policies.CanModifyServerSettings, Policies.CanViewProfile);
var clientInsufficient = await user.CreateClient(Policies.CanModifyStoreSettings);
var apiKeyProfileUserData = await clientProfile.GetCurrentUser();

View File

@@ -3005,16 +3005,16 @@ noninventoryitem:
[Trait("Fast", "Fast")]
public void CanUsePermission()
{
Assert.True(Permission.Create(Permission.CanModifyServerSettings).Contains(Permission.Create(Permission.CanModifyServerSettings)));
Assert.True(Permission.Create(Permission.CanModifyProfile).Contains(Permission.Create(Permission.CanViewProfile)));
Assert.True(Permission.Create(Permission.CanModifyStoreSettings).Contains(Permission.Create(Permission.CanViewStoreSettings)));
Assert.False(Permission.Create(Permission.CanViewStoreSettings).Contains(Permission.Create(Permission.CanModifyStoreSettings)));
Assert.False(Permission.Create(Permission.CanModifyServerSettings).Contains(Permission.Create(Permission.CanModifyStoreSettings)));
Assert.True(Permission.Create(Permission.Unrestricted).Contains(Permission.Create(Permission.CanModifyStoreSettings)));
Assert.True(Permission.Create(Permission.Unrestricted).Contains(Permission.Create(Permission.CanModifyStoreSettings, "abc")));
Assert.True(Permission.Create(Policies.CanModifyServerSettings).Contains(Permission.Create(Policies.CanModifyServerSettings)));
Assert.True(Permission.Create(Policies.CanModifyProfile).Contains(Permission.Create(Policies.CanViewProfile)));
Assert.True(Permission.Create(Policies.CanModifyStoreSettings).Contains(Permission.Create(Policies.CanViewStoreSettings)));
Assert.False(Permission.Create(Policies.CanViewStoreSettings).Contains(Permission.Create(Policies.CanModifyStoreSettings)));
Assert.False(Permission.Create(Policies.CanModifyServerSettings).Contains(Permission.Create(Policies.CanModifyStoreSettings)));
Assert.True(Permission.Create(Policies.Unrestricted).Contains(Permission.Create(Policies.CanModifyStoreSettings)));
Assert.True(Permission.Create(Policies.Unrestricted).Contains(Permission.Create(Policies.CanModifyStoreSettings, "abc")));
Assert.True(Permission.Create(Permission.CanViewStoreSettings).Contains(Permission.Create(Permission.CanViewStoreSettings, "abcd")));
Assert.False(Permission.Create(Permission.CanModifyStoreSettings, "abcd").Contains(Permission.Create(Permission.CanModifyStoreSettings)));
Assert.True(Permission.Create(Policies.CanViewStoreSettings).Contains(Permission.Create(Policies.CanViewStoreSettings, "abcd")));
Assert.False(Permission.Create(Policies.CanModifyStoreSettings, "abcd").Contains(Permission.Create(Policies.CanModifyStoreSettings)));
}
[Fact(Timeout = TestTimeout)]

View File

@@ -13,7 +13,7 @@ using Microsoft.AspNetCore.Mvc;
namespace BTCPayServer.Controllers
{
[BitpayAPIConstraint]
[Authorize(Permission.CanCreateInvoice, AuthenticationSchemes = AuthenticationSchemes.Bitpay)]
[Authorize(Policies.CanCreateInvoice, AuthenticationSchemes = AuthenticationSchemes.Bitpay)]
public class InvoiceControllerAPI : Controller
{
private InvoiceController _InvoiceController;

View File

@@ -511,7 +511,7 @@ namespace BTCPayServer.Controllers
[HttpPost]
[Route("invoices/create")]
[Authorize(Policy = Permission.CanCreateInvoice, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[Authorize(Policy = Policies.CanCreateInvoice, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[BitpayAPIConstraint(false)]
public async Task<IActionResult> CreateInvoice(CreateInvoiceModel model, CancellationToken cancellationToken)
{

View File

@@ -28,35 +28,35 @@ namespace BTCPayServer.Controllers.RestApi
}
[HttpGet("me/id")]
[Authorize(Policy = Permission.CanViewProfile, AuthenticationSchemes = AuthenticationSchemes.ApiKey)]
[Authorize(Policy = Policies.CanViewProfile, AuthenticationSchemes = AuthenticationSchemes.ApiKey)]
public string GetCurrentUserId()
{
return _userManager.GetUserId(User);
}
[HttpGet("me")]
[Authorize(Policy = Permission.CanViewProfile, AuthenticationSchemes = AuthenticationSchemes.ApiKey)]
[Authorize(Policy = Policies.CanViewProfile, AuthenticationSchemes = AuthenticationSchemes.ApiKey)]
public async Task<ApplicationUser> GetCurrentUser()
{
return await _userManager.GetUserAsync(User);
}
[HttpGet("me/is-admin")]
[Authorize(Policy = Permission.CanModifyServerSettings, AuthenticationSchemes = AuthenticationSchemes.ApiKey)]
[Authorize(Policy = Policies.CanModifyServerSettings, AuthenticationSchemes = AuthenticationSchemes.ApiKey)]
public bool AmIAnAdmin()
{
return true;
}
[HttpGet("me/stores")]
[Authorize(Policy = Permission.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.ApiKey)]
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.ApiKey)]
public StoreData[] GetCurrentUserStores()
{
return this.HttpContext.GetStoresData();
}
[HttpGet("me/stores/{storeId}/can-view")]
[Authorize(Policy = Permission.CanViewStoreSettings,
[Authorize(Policy = Policies.CanViewStoreSettings,
AuthenticationSchemes = AuthenticationSchemes.ApiKey)]
public bool CanViewStore(string storeId)
{
@@ -64,7 +64,7 @@ namespace BTCPayServer.Controllers.RestApi
}
[HttpGet("me/stores/{storeId}/can-edit")]
[Authorize(Policy = Permission.CanModifyStoreSettings,
[Authorize(Policy = Policies.CanModifyStoreSettings,
AuthenticationSchemes = AuthenticationSchemes.ApiKey)]
public bool CanEditStore(string storeId)
{

View File

@@ -55,7 +55,7 @@ namespace BTCPayServer.Controllers.RestApi.Users
_authorizationService = authorizationService;
}
[Authorize(Policy = Permission.CanViewProfile, AuthenticationSchemes = AuthenticationSchemes.ApiKey)]
[Authorize(Policy = Policies.CanViewProfile, AuthenticationSchemes = AuthenticationSchemes.ApiKey)]
[HttpGet("~/api/v1/users/me")]
public async Task<ActionResult<ApplicationUserData>> GetCurrentUser()
{

View File

@@ -39,7 +39,7 @@ using BTCPayServer.Client;
namespace BTCPayServer.Controllers
{
[Authorize(Policy = Permission.CanModifyServerSettings,
[Authorize(Policy = Policies.CanModifyServerSettings,
AuthenticationSchemes = BTCPayServer.Security.AuthenticationSchemes.Cookie)]
public partial class ServerController : Controller
{

View File

@@ -34,7 +34,7 @@ namespace BTCPayServer.Controllers
{
[Route("stores")]
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[Authorize(Policy = Permission.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[AutoValidateAntiforgeryToken]
public partial class StoresController : Controller
{

View File

@@ -31,7 +31,7 @@ using Newtonsoft.Json;
namespace BTCPayServer.Controllers
{
[Route("wallets")]
[Authorize(Policy = Permission.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[AutoValidateAntiforgeryToken]
public partial class WalletsController : Controller
{
@@ -840,7 +840,7 @@ namespace BTCPayServer.Controllers
var vm = new RescanWalletModel();
vm.IsFullySync = _dashboard.IsFullySynched(walletId.CryptoCode, out var unused);
vm.IsServerAdmin = (await _authorizationService.AuthorizeAsync(User, Permission.CanModifyServerSettings)).Succeeded;
vm.IsServerAdmin = (await _authorizationService.AuthorizeAsync(User, Policies.CanModifyServerSettings)).Succeeded;
vm.IsSupportedByCurrency = _dashboard.Get(walletId.CryptoCode)?.Status?.BitcoinStatus?.Capabilities?.CanScanTxoutSet == true;
var explorer = ExplorerClientProvider.GetExplorerClient(walletId.CryptoCode);
var scanProgress = await explorer.GetScanUTXOSetInformationAsync(paymentMethod.AccountDerivation);
@@ -870,7 +870,7 @@ namespace BTCPayServer.Controllers
[HttpPost]
[Route("{walletId}/rescan")]
[Authorize(Policy = Permission.CanModifyServerSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[Authorize(Policy = Policies.CanModifyServerSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
public async Task<IActionResult> WalletRescan(
[ModelBinder(typeof(WalletIdModelBinder))]
WalletId walletId, RescanWalletModel vm)

View File

@@ -3,11 +3,11 @@ using Microsoft.AspNetCore.Authorization;
namespace BTCPayServer.Security
{
public static class Policies
public static class ServerPolicies
{
public static AuthorizationOptions AddBTCPayPolicies(this AuthorizationOptions options)
{
foreach (var p in Permission.AllPolicies)
foreach (var p in Policies.AllPolicies)
{
options.AddPolicy(p);
}

View File

@@ -27,8 +27,8 @@ namespace BTCPayServer.Services.Altcoins.Monero.UI
[Route("stores/{storeId}/monerolike")]
[OnlyIfSupportAttribute("XMR")]
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[Authorize(Policy = Permission.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[Authorize(Policy = Permission.CanModifyServerSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[Authorize(Policy = Policies.CanModifyServerSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
public class MoneroLikeStoreController : Controller
{
private readonly MoneroLikeConfiguration _MoneroLikeConfiguration;