diff --git a/BTCPayServer.Client/BTCPayServerClient.cs b/BTCPayServer.Client/BTCPayServerClient.cs index d934976cf..d410fdf5c 100644 --- a/BTCPayServer.Client/BTCPayServerClient.cs +++ b/BTCPayServer.Client/BTCPayServerClient.cs @@ -103,7 +103,7 @@ namespace BTCPayServer.Client return request; } - private static void AppendPayloadToQuery(UriBuilder uri, KeyValuePair keyValuePair) + public static void AppendPayloadToQuery(UriBuilder uri, KeyValuePair keyValuePair) { if (uri.Query.Length > 1) uri.Query += "&"; @@ -126,7 +126,7 @@ namespace BTCPayServer.Client uri.Query = uri.Query.Trim('&'); } - private static void AppendPayloadToQuery(UriBuilder uri, Dictionary payload) + public static void AppendPayloadToQuery(UriBuilder uri, Dictionary payload) { if (uri.Query.Length > 1) uri.Query += "&"; diff --git a/BTCPayServer/Controllers/ManageController.APIKeys.cs b/BTCPayServer/Controllers/ManageController.APIKeys.cs index ac8a1ca75..d08f220c0 100644 --- a/BTCPayServer/Controllers/ManageController.APIKeys.cs +++ b/BTCPayServer/Controllers/ManageController.APIKeys.cs @@ -104,69 +104,73 @@ namespace BTCPayServer.Controllers { UserId = new[] {_userManager.GetUserId(User)} }); - if (keys.Any()) + foreach (var key in keys) { - foreach (var key in keys) + var blob = key.GetBlob(); + + if (blob.ApplicationIdentifier != applicationIdentifier || + blob.ApplicationAuthority != redirect.Authority) { - var blob = key.GetBlob(); - - if (blob.ApplicationIdentifier != applicationIdentifier || - blob.ApplicationAuthority != redirect.Authority) + continue; + } + + //matched the identifier and authority, but we need to check if what the app is requesting in terms of permissions is enough + var alreadyPresentPermissions = Permission.ToPermissions(blob.Permissions) + .GroupBy(permission => permission.Policy); + var fail = false; + foreach (var permission in requestPermissions.GroupBy(permission => permission.Policy)) + { + var presentPermission = + alreadyPresentPermissions.SingleOrDefault(grouping => permission.Key == grouping.Key); + if (strict && presentPermission == null) { - continue; + fail = true; + break; } - //matched the identifier and authority, but we need to check if what the app is requesting in terms of permissions is enough - var alreadyPresentPermissions = Permission.ToPermissions(blob.Permissions).GroupBy(permission => permission.Policy); - var fail = false; - foreach (var permission in requestPermissions.GroupBy(permission => permission.Policy)) + + if (Policies.IsStorePolicy(permission.Key)) { - var presentPermission = - alreadyPresentPermissions.SingleOrDefault(grouping => permission.Key == grouping.Key); - if (strict && presentPermission == null) + if (!selectiveStores && + permission.Any(permission1 => !string.IsNullOrEmpty(permission1.Scope))) + { + + TempData.SetStatusMessageModel(new StatusMessageModel() + { + Severity = StatusMessageModel.StatusSeverity.Error, + Message = + "Cannot request specific store permission when selectiveStores is not enable" + }); + return RedirectToAction("APIKeys"); + } + else if (!selectiveStores && presentPermission.Any(permission1 => + !string.IsNullOrEmpty(permission1.Scope))) { fail = true; break; } - - if(Policies.IsStorePolicy(permission.Key)) - { - if (!selectiveStores && permission.Any(permission1 => !string.IsNullOrEmpty(permission1.Scope))) - { - - TempData.SetStatusMessageModel(new StatusMessageModel() - { - Severity = StatusMessageModel.StatusSeverity.Error, - Message = "Cannot request specific store permission when selectiveStores is not enable" - }); - return RedirectToAction("APIKeys"); - }else if (!selectiveStores && presentPermission.Any(permission1 => - !string.IsNullOrEmpty(permission1.Scope))) - { - fail = true; - break; - } - } } - - if (fail) - { - continue; - } - - //we have a key that is sufficient, redirect to a page to confirm that it's ok to provide this key to the app. - return View("Confirm", - new ConfirmModel() - { - Title = $"Are you sure about exposing your API Key to {applicationName??applicationIdentifier}?", - Description = $"You've previously generated this API Key ({key.Id}) specifically for {applicationName??applicationIdentifier} with the url {redirect}. ", - ActionUrl = GetRedirectToApplicationUrl(redirect, key), - ButtonClass = "btn-secondary", - Action = "Confirm" - }); } + + if (fail) + { + continue; + } + + //we have a key that is sufficient, redirect to a page to confirm that it's ok to provide this key to the app. + return View("Confirm", + new ConfirmModel() + { + Title = + $"Are you sure about exposing your API Key to {applicationName ?? applicationIdentifier}?", + Description = + $"You've previously generated this API Key ({key.Id}) specifically for {applicationName ?? applicationIdentifier} with the url {redirect}. ", + ActionUrl = GetRedirectToApplicationUrl(redirect, key), + ButtonClass = "btn-secondary", + Action = "Confirm" + }); } } - + var vm = await SetViewModelValues(new AuthorizeApiKeysViewModel() { RedirectUrl = redirect, @@ -256,8 +260,8 @@ namespace BTCPayServer.Controllers case "no": return RedirectToAction("APIKeys"); case "yes": - var key = await CreateKey(viewModel, (viewModel.ApplicationIdentifier, viewModel.RedirectUrl.Authority)); - + var key = await CreateKey(viewModel, (viewModel.ApplicationIdentifier, viewModel.RedirectUrl?.Authority)); + if (viewModel.RedirectUrl != null) { return Redirect(GetRedirectToApplicationUrl(viewModel.RedirectUrl, key)); @@ -278,15 +282,10 @@ namespace BTCPayServer.Controllers { var uri = new UriBuilder(redirect); var permissions = key.GetBlob().Permissions; - uri.AppendPayloadToQuery(new Dictionary() - { - {"key", key.Id}, {"permissions",permissions}, {"user", key.UserId} - }); - //uri builder has bug around string[] params - return uri.Uri.ToStringInvariant().Replace("permissions=System.String%5B%5D", - string.Join("&", permissions.Select(s1 => $"permissions={s1}")), StringComparison.InvariantCulture); + BTCPayServerClient.AppendPayloadToQuery(uri, + new Dictionary() {{"key", key.Id}, {"permissions", permissions}, {"user", key.UserId}}); + return uri.Uri.AbsoluteUri; } - [HttpPost] public async Task AddApiKey(AddApiKeyViewModel viewModel)