mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2024-11-19 01:43:50 +01:00
Greenfield: Admins can create/delete API keys of any user (#4680)
* Greenfield: Admins can create/delete API keys of any user * Greenfield: Improve doc for scoped apikey (Close #4673) * Fix permissions hierarchy * Update BTCPayServer.Client/Permissions.cs * Fix tests --------- Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
This commit is contained in:
parent
d14dafc871
commit
4ae05272c3
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@ -22,6 +23,15 @@ namespace BTCPayServer.Client
|
||||
return await HandleResponse<ApiKeyData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<ApiKeyData> CreateAPIKey(string userId, CreateApiKeyRequest request, CancellationToken token = default)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/{userId}/api-keys",
|
||||
bodyPayload: request, method: HttpMethod.Post), token);
|
||||
return await HandleResponse<ApiKeyData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task RevokeCurrentAPIKeyInfo(CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest("api/v1/api-keys/current", null, HttpMethod.Delete), token);
|
||||
@ -35,5 +45,14 @@ namespace BTCPayServer.Client
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/api-keys/{apikey}", null, HttpMethod.Delete), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
public virtual async Task RevokeAPIKey(string userId, string apikey, CancellationToken token = default)
|
||||
{
|
||||
if (apikey == null)
|
||||
throw new ArgumentNullException(nameof(apikey));
|
||||
if (userId is null)
|
||||
throw new ArgumentNullException(nameof(userId));
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/{userId}/api-keys/{apikey}", null, HttpMethod.Delete), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ namespace BTCPayServer.Client
|
||||
public const string CanViewNotificationsForUser = "btcpay.user.canviewnotificationsforuser";
|
||||
public const string CanViewUsers = "btcpay.server.canviewusers";
|
||||
public const string CanCreateUser = "btcpay.server.cancreateuser";
|
||||
public const string CanManageUsers = "btcpay.server.canmanageusers";
|
||||
public const string CanDeleteUser = "btcpay.user.candeleteuser";
|
||||
public const string CanManagePullPayments = "btcpay.store.canmanagepullpayments";
|
||||
public const string CanCreatePullPayments = "btcpay.store.cancreatepullpayments";
|
||||
@ -73,6 +74,7 @@ namespace BTCPayServer.Client
|
||||
yield return CanDepositToCustodianAccounts;
|
||||
yield return CanWithdrawFromCustodianAccounts;
|
||||
yield return CanTradeCustodianAccount;
|
||||
yield return CanManageUsers;
|
||||
}
|
||||
}
|
||||
public static bool IsValidPolicy(string policy)
|
||||
@ -206,15 +208,23 @@ namespace BTCPayServer.Client
|
||||
private static void Init()
|
||||
{
|
||||
PolicyHasChild(Policies.CanModifyStoreSettings,
|
||||
Policies.CanManageCustodianAccounts, Policies.CanManagePullPayments, Policies.CanModifyInvoices, Policies.CanViewStoreSettings, Policies.CanModifyStoreWebhooks, Policies.CanModifyPaymentRequests );
|
||||
|
||||
Policies.CanManageCustodianAccounts,
|
||||
Policies.CanManagePullPayments,
|
||||
Policies.CanModifyInvoices,
|
||||
Policies.CanViewStoreSettings,
|
||||
Policies.CanModifyStoreWebhooks,
|
||||
Policies.CanModifyPaymentRequests);
|
||||
|
||||
PolicyHasChild(Policies.CanManageUsers, Policies.CanCreateUser);
|
||||
PolicyHasChild(Policies.CanManagePullPayments, Policies.CanCreatePullPayments );
|
||||
PolicyHasChild(Policies.CanCreatePullPayments, Policies.CanCreateNonApprovedPullPayments );
|
||||
PolicyHasChild(Policies.CanModifyPaymentRequests, Policies.CanViewPaymentRequests );
|
||||
PolicyHasChild(Policies.CanModifyProfile, Policies.CanViewProfile );
|
||||
PolicyHasChild(Policies.CanUseLightningNodeInStore, Policies.CanViewLightningInvoiceInStore, Policies.CanCreateLightningInvoiceInStore );
|
||||
PolicyHasChild(Policies.CanManageNotificationsForUser, Policies.CanViewNotificationsForUser );
|
||||
PolicyHasChild(Policies.CanModifyServerSettings, Policies.CanUseInternalLightningNode );
|
||||
PolicyHasChild(Policies.CanModifyServerSettings,
|
||||
Policies.CanUseInternalLightningNode,
|
||||
Policies.CanManageUsers);
|
||||
PolicyHasChild(Policies.CanUseInternalLightningNode, Policies.CanCreateLightningInvoiceInternalNode,Policies.CanViewLightningInvoiceInternalNode );
|
||||
PolicyHasChild(Policies.CanManageCustodianAccounts, Policies.CanViewCustodianAccounts );
|
||||
PolicyHasChild(Policies.CanModifyInvoices, Policies.CanViewInvoices, Policies.CanCreateInvoice );
|
||||
|
@ -190,6 +190,41 @@ namespace BTCPayServer.Tests
|
||||
|
||||
await unrestricted.RevokeAPIKey(apiKey.ApiKey);
|
||||
await AssertAPIError("apikey-not-found", () => unrestricted.RevokeAPIKey(apiKey.ApiKey));
|
||||
|
||||
|
||||
// Admin create API key to new user
|
||||
acc = tester.NewAccount();
|
||||
await acc.GrantAccessAsync(isAdmin: true);
|
||||
unrestricted = await acc.CreateClient();
|
||||
var newUser = await unrestricted.CreateUser(new CreateApplicationUserRequest() { Email = Utils.GenerateEmail(), Password = "Kitten0@" });
|
||||
var newUserAPIKey = await unrestricted.CreateAPIKey(newUser.Id, new CreateApiKeyRequest()
|
||||
{
|
||||
Label = "Hello world",
|
||||
Permissions = new Permission[] { Permission.Create(Policies.CanViewProfile) }
|
||||
});
|
||||
var newUserClient = acc.CreateClientFromAPIKey(newUserAPIKey.ApiKey);
|
||||
Assert.Equal(newUser.Id, (await newUserClient.GetCurrentUser()).Id);
|
||||
// Admin delete it
|
||||
await unrestricted.RevokeAPIKey(newUser.Id, newUserAPIKey.ApiKey);
|
||||
await Assert.ThrowsAsync<GreenfieldAPIException>(() => newUserClient.GetCurrentUser());
|
||||
|
||||
// Admin create store
|
||||
var store = await unrestricted.CreateStore(new CreateStoreRequest() { Name = "Pouet lol" });
|
||||
|
||||
// Grant right to another user
|
||||
newUserAPIKey = await unrestricted.CreateAPIKey(newUser.Id, new CreateApiKeyRequest()
|
||||
{
|
||||
Label = "Hello world",
|
||||
Permissions = new Permission[] { Permission.Create(Policies.CanViewInvoices, store.Id) },
|
||||
});
|
||||
|
||||
// Despite the grant, the user shouldn't be able to get the invoices!
|
||||
newUserClient = acc.CreateClientFromAPIKey(newUserAPIKey.ApiKey);
|
||||
await Assert.ThrowsAsync<GreenfieldAPIException>(() => newUserClient.GetInvoices(store.Id));
|
||||
|
||||
// if user is a guest or owner, then it should be ok
|
||||
await unrestricted.AddStoreUser(store.Id, new StoreUserData() { UserId = newUser.Id, Role = "Guest" });
|
||||
await newUserClient.GetInvoices(store.Id);
|
||||
}
|
||||
|
||||
[Fact(Timeout = TestTimeout)]
|
||||
|
@ -219,7 +219,7 @@ namespace BTCPayServer.Tests
|
||||
var account = parent.PayTester.GetController<UIAccountController>();
|
||||
RegisterDetails = new RegisterViewModel()
|
||||
{
|
||||
Email = Guid.NewGuid() + "@toto.com",
|
||||
Email = Utils.GenerateEmail(),
|
||||
ConfirmPassword = "Kitten0@",
|
||||
Password = "Kitten0@",
|
||||
IsAdmin = isAdmin
|
||||
|
@ -160,25 +160,7 @@ namespace BTCPayServer.Tests
|
||||
await tester.StartAsync();
|
||||
var acc = tester.NewAccount();
|
||||
|
||||
var description =
|
||||
"BTCPay Server supports authenticating and authorizing users through an API Key that is generated by them. Send the API Key as a header value to Authorization with the format: `token {token}`. For a smoother experience, you can generate a url that redirects users to an API key creation screen.\n\n The following permissions are available to the context of the user creating the API Key:\n\n#OTHERPERMISSIONS#\n\nThe following permissions are available if the user is an administrator:\n\n#SERVERPERMISSIONS#\n\nThe following permissions applies to all stores of the user, you can limit to a specific store with the following format: `btcpay.store.cancreateinvoice:6HSHAEU4iYWtjxtyRs9KyPjM9GAQp8kw2T9VWbGG1FnZ`:\n\n#STOREPERMISSIONS#\n\nNote that API Keys only limits permission of a user and can never expand it. If an API Key has the permission `btcpay.server.canmodifyserversettings` but that the user account creating this API Key is not administrator, the API Key will not be able to modify the server settings.\nSome permissions may include other permissions, see [this operation](#operation/permissionsMetadata).\n";
|
||||
|
||||
var storePolicies =
|
||||
UIManageController.AddApiKeyViewModel.PermissionValueItem.PermissionDescriptions.Where(pair =>
|
||||
Policies.IsStorePolicy(pair.Key) && !pair.Key.EndsWith(":", StringComparison.InvariantCulture));
|
||||
var serverPolicies =
|
||||
UIManageController.AddApiKeyViewModel.PermissionValueItem.PermissionDescriptions.Where(pair =>
|
||||
Policies.IsServerPolicy(pair.Key));
|
||||
var otherPolicies =
|
||||
UIManageController.AddApiKeyViewModel.PermissionValueItem.PermissionDescriptions.Where(pair =>
|
||||
!Policies.IsStorePolicy(pair.Key) && !Policies.IsServerPolicy(pair.Key));
|
||||
|
||||
description = description.Replace("#OTHERPERMISSIONS#",
|
||||
string.Join("\n", otherPolicies.Select(pair => $"* `{pair.Key}`: {pair.Value.Title}")))
|
||||
.Replace("#SERVERPERMISSIONS#",
|
||||
string.Join("\n", serverPolicies.Select(pair => $"* `{pair.Key}`: {pair.Value.Title}")))
|
||||
.Replace("#STOREPERMISSIONS#",
|
||||
string.Join("\n", storePolicies.Select(pair => $"* `{pair.Key}`: {pair.Value.Title}")));
|
||||
var description = UtilitiesTests.GetSecuritySchemeDescription();
|
||||
TestLogs.LogInformation(description);
|
||||
|
||||
var sresp = Assert
|
||||
@ -187,7 +169,11 @@ namespace BTCPayServer.Tests
|
||||
|
||||
JObject json = JObject.Parse(sresp);
|
||||
|
||||
Assert.Equal(description, json["components"]["securitySchemes"]["API_Key"]["description"].Value<string>());
|
||||
// If this test fail, run `UpdateSwagger` once.
|
||||
if (description != json["components"]["securitySchemes"]["API_Key"]["description"].Value<string>())
|
||||
{
|
||||
Assert.False(true, "Please run manually the test `UpdateSwagger` once");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -1,15 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Amazon.Runtime.Internal;
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.WindowsAzure.Storage.RetryPolicies;
|
||||
using NBitcoin.DataEncoders;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Controllers;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Xunit;
|
||||
|
||||
@ -20,6 +16,39 @@ namespace BTCPayServer.Tests
|
||||
/// </summary>
|
||||
public class UtilitiesTests
|
||||
{
|
||||
internal static string GetSecuritySchemeDescription()
|
||||
{
|
||||
var description =
|
||||
"BTCPay Server supports authenticating and authorizing users through an API Key that is generated by them. Send the API Key as a header value to Authorization with the format: `token {token}`. For a smoother experience, you can generate a url that redirects users to an API key creation screen.\n\n The following permissions are available to the context of the user creating the API Key:\n\n#OTHERPERMISSIONS#\n\nThe following permissions are available if the user is an administrator:\n\n#SERVERPERMISSIONS#\n\nThe following permissions applies to all stores of the user, you can limit to a specific store with the following format: `btcpay.store.cancreateinvoice:6HSHAEU4iYWtjxtyRs9KyPjM9GAQp8kw2T9VWbGG1FnZ`:\n\n#STOREPERMISSIONS#\n\nNote that API Keys only limits permission of a user and can never expand it. If an API Key has the permission `btcpay.server.canmodifyserversettings` but that the user account creating this API Key is not administrator, the API Key will not be able to modify the server settings.\nSome permissions may include other permissions, see [this operation](#operation/permissionsMetadata).\n";
|
||||
|
||||
var storePolicies =
|
||||
UIManageController.AddApiKeyViewModel.PermissionValueItem.PermissionDescriptions.Where(pair =>
|
||||
Policies.IsStorePolicy(pair.Key) && !pair.Key.EndsWith(":", StringComparison.InvariantCulture));
|
||||
var serverPolicies =
|
||||
UIManageController.AddApiKeyViewModel.PermissionValueItem.PermissionDescriptions.Where(pair =>
|
||||
Policies.IsServerPolicy(pair.Key));
|
||||
var otherPolicies =
|
||||
UIManageController.AddApiKeyViewModel.PermissionValueItem.PermissionDescriptions.Where(pair =>
|
||||
!Policies.IsStorePolicy(pair.Key) && !Policies.IsServerPolicy(pair.Key));
|
||||
|
||||
description = description.Replace("#OTHERPERMISSIONS#",
|
||||
string.Join("\n", otherPolicies.Select(pair => $"* `{pair.Key}`: {pair.Value.Title}")))
|
||||
.Replace("#SERVERPERMISSIONS#",
|
||||
string.Join("\n", serverPolicies.Select(pair => $"* `{pair.Key}`: {pair.Value.Title}")))
|
||||
.Replace("#STOREPERMISSIONS#",
|
||||
string.Join("\n", storePolicies.Select(pair => $"* `{pair.Key}`: {pair.Value.Title}")));
|
||||
return description;
|
||||
}
|
||||
[Trait("Utilities", "Utilities")]
|
||||
[Fact]
|
||||
public void UpdateSwagger()
|
||||
{
|
||||
var filePath = Path.Combine(TestUtils.TryGetSolutionDirectoryInfo().FullName, "BTCPayServer", "wwwroot", "swagger", "v1", "swagger.template.json");
|
||||
var o = JObject.Parse(File.ReadAllText(filePath));
|
||||
o["components"]["securitySchemes"]["API_Key"]["description"] = GetSecuritySchemeDescription();
|
||||
File.WriteAllText(filePath, o.ToString(Newtonsoft.Json.Formatting.Indented));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download transifex transactions and put them in BTCPayServer\wwwroot\locales
|
||||
/// </summary>
|
||||
|
@ -77,5 +77,10 @@ namespace BTCPayServer.Tests
|
||||
}
|
||||
// depending on your use case, consider throwing an exception here
|
||||
}
|
||||
|
||||
public static string GenerateEmail()
|
||||
{
|
||||
return Guid.NewGuid() + "@toto.com";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,14 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
|
||||
[HttpPost("~/api/v1/api-keys")]
|
||||
[Authorize(Policy = Policies.Unrestricted, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
public async Task<IActionResult> CreateKey(CreateApiKeyRequest request)
|
||||
public Task<IActionResult> CreateAPIKey(CreateApiKeyRequest request)
|
||||
{
|
||||
return CreateUserAPIKey(_userManager.GetUserId(User), request);
|
||||
}
|
||||
|
||||
[HttpPost("~/api/v1/users/{userId}/api-keys")]
|
||||
[Authorize(Policy = Policies.CanManageUsers, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
public async Task<IActionResult> CreateUserAPIKey(string userId, CreateApiKeyRequest request)
|
||||
{
|
||||
request ??= new CreateApiKeyRequest();
|
||||
request.Permissions ??= System.Array.Empty<Permission>();
|
||||
@ -52,7 +59,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
{
|
||||
Id = Encoders.Hex.EncodeData(RandomUtils.GetBytes(20)),
|
||||
Type = APIKeyType.Permanent,
|
||||
UserId = _userManager.GetUserId(User),
|
||||
UserId = userId,
|
||||
Label = request.Label
|
||||
};
|
||||
key.SetBlob(new APIKeyBlob()
|
||||
@ -72,19 +79,27 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
// Should be impossible (we force apikey auth)
|
||||
return Task.FromResult<IActionResult>(BadRequest());
|
||||
}
|
||||
return RevokeKey(apiKey);
|
||||
return RevokeAPIKey(apiKey);
|
||||
}
|
||||
[HttpDelete("~/api/v1/api-keys/{apikey}", Order = 1)]
|
||||
[Authorize(Policy = Policies.Unrestricted, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
public async Task<IActionResult> RevokeKey(string apikey)
|
||||
public Task<IActionResult> RevokeAPIKey(string apikey)
|
||||
{
|
||||
return RevokeAPIKey(_userManager.GetUserId(User), apikey);
|
||||
}
|
||||
|
||||
[HttpDelete("~/api/v1/users/{userId}/api-keys/{apikey}", Order = 1)]
|
||||
[Authorize(Policy = Policies.CanManageUsers, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
public async Task<IActionResult> RevokeAPIKey(string userId, string apikey)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(apikey) &&
|
||||
await _apiKeyRepository.Remove(apikey, _userManager.GetUserId(User)))
|
||||
await _apiKeyRepository.Remove(apikey, userId))
|
||||
return Ok();
|
||||
else
|
||||
return this.CreateAPIError("apikey-not-found", "This apikey does not exists");
|
||||
}
|
||||
|
||||
|
||||
private static ApiKeyData FromModel(APIKeyData data)
|
||||
{
|
||||
return new ApiKeyData()
|
||||
|
@ -670,7 +670,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
public override async Task<ApiKeyData> CreateAPIKey(CreateApiKeyRequest request,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
return GetFromActionResult<ApiKeyData>(await GetController<GreenfieldApiKeysController>().CreateKey(request));
|
||||
return GetFromActionResult<ApiKeyData>(await GetController<GreenfieldApiKeysController>().CreateAPIKey(request));
|
||||
}
|
||||
|
||||
public override async Task RevokeCurrentAPIKeyInfo(CancellationToken token = default)
|
||||
@ -680,7 +680,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
|
||||
public override async Task RevokeAPIKey(string apikey, CancellationToken token = default)
|
||||
{
|
||||
HandleActionResult(await GetController<GreenfieldApiKeysController>().RevokeKey(apikey));
|
||||
HandleActionResult(await GetController<GreenfieldApiKeysController>().RevokeAPIKey(apikey));
|
||||
}
|
||||
|
||||
public override async Task<IEnumerable<NotificationData>> GetNotifications(bool? seen = null,
|
||||
|
@ -509,6 +509,7 @@ namespace BTCPayServer.Controllers
|
||||
{Policies.Unrestricted, ("Unrestricted access", "The app will have unrestricted access to your account.")},
|
||||
{Policies.CanViewUsers, ("View users", "The app will be able to see all users on this server.")},
|
||||
{Policies.CanCreateUser, ("Create new users", "The app will be able to create new users on this server.")},
|
||||
{Policies.CanManageUsers, ("Manage users", "The app will be able to create/delete API keys for users.")},
|
||||
{Policies.CanDeleteUser, ("Delete user", "The app will be able to delete the user to whom it is assigned. Admin users can delete any user without this permission.")},
|
||||
{Policies.CanModifyStoreSettings, ("Modify your stores", "The app will be able to manage invoices on all your stores and modify their settings.")},
|
||||
{$"{Policies.CanModifyStoreSettings}:", ("Manage selected stores", "The app will be able to manage invoices on the selected stores and modify their settings.")},
|
||||
|
@ -47,7 +47,6 @@ namespace BTCPayServer.Security.Greenfield
|
||||
{
|
||||
throw new InvalidOperationException("cannot save a bitpay legacy api key with this repository");
|
||||
}
|
||||
|
||||
using var context = _applicationDbContextFactory.CreateContext();
|
||||
await context.ApiKeys.AddAsync(key);
|
||||
await context.SaveChangesAsync();
|
||||
|
@ -27,7 +27,47 @@
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"API_Key": ["unrestricted"],
|
||||
"API_Key": [ "unrestricted" ],
|
||||
"Basic": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/users/{userId}/api-keys/{apikey}": {
|
||||
"delete": {
|
||||
"operationId": "ApiKeys_DeleteUserApiKey",
|
||||
"tags": [
|
||||
"API Keys"
|
||||
],
|
||||
"summary": "Revoke an API Key of target user",
|
||||
"description": "Revoke the API key of a target user so that it cannot be used anymore",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "userId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "The target user",
|
||||
"schema": { "type": "string" }
|
||||
},
|
||||
{
|
||||
"name": "apikey",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "The API Key to revoke",
|
||||
"schema": { "type": "string" }
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The key has been deleted"
|
||||
},
|
||||
"404": {
|
||||
"description": "The key is not found for this user"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"API_Key": [ "unrestricted" ],
|
||||
"Basic": []
|
||||
}
|
||||
]
|
||||
@ -65,7 +105,8 @@
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"API_Key": []
|
||||
"API_Key": [ "btcpay.server.canmanageusers" ],
|
||||
"Basic": []
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -178,6 +219,89 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/users/{userId}/api-keys": {
|
||||
"post": {
|
||||
"operationId": "ApiKeys_CreateUserApiKey",
|
||||
"tags": [
|
||||
"API Keys"
|
||||
],
|
||||
"summary": "Create a new API Key for a user",
|
||||
"description": "Create a new API Key for a user",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "userId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "The target user",
|
||||
"schema": { "type": "string" }
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Information about the new api key",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiKeyData"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing authorization",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Unexpected error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"requestBody": {
|
||||
"x-name": "request",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"label": {
|
||||
"type": "string",
|
||||
"description": "The label of the new API Key",
|
||||
"nullable": true
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"description": "The permissions granted to this API Key (See API Key Authentication)",
|
||||
"nullable": true,
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"API_Key": [ "btcpay.server.canmanageusers" ],
|
||||
"Basic": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
@ -198,11 +322,12 @@
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"description": "The permissions associated to this API Key",
|
||||
"description": "The permissions associated to this API Key (can be scoped to a specific store)",
|
||||
"nullable": false,
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"example": [ "btcpay.server.canmanageusers", "btcpay.server.canmanageusers:2KxSpc9V5zDWfUbvgYiZuAfka4wUhGF96F75Ao8y4zHP" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,132 +1,140 @@
|
||||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"title": "BTCPay Greenfield API",
|
||||
"version": "v1",
|
||||
"description": "A full API to use your BTCPay Server",
|
||||
"contact": {
|
||||
"name": "BTCPay Server",
|
||||
"url": "https://btcpayserver.org"
|
||||
},
|
||||
"license": {
|
||||
"name": "MIT",
|
||||
"url": "https://github.com/btcpayserver/btcpayserver/blob/master/LICENSE"
|
||||
}
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"title": "BTCPay Greenfield API",
|
||||
"version": "v1",
|
||||
"description": "A full API to use your BTCPay Server",
|
||||
"contact": {
|
||||
"name": "BTCPay Server",
|
||||
"url": "https://btcpayserver.org"
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "/",
|
||||
"description": "BTCPay Server Greenfield API"
|
||||
}
|
||||
],
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationProblemDetails": {
|
||||
"type": "array",
|
||||
"description": "An array of validation errors of the request",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "A specific validation error on a json property",
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string",
|
||||
"nullable": false,
|
||||
"description": "The json path of the property which failed validation"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"nullable": false,
|
||||
"description": "User friendly error message about the validation"
|
||||
}
|
||||
}
|
||||
}
|
||||
"license": {
|
||||
"name": "MIT",
|
||||
"url": "https://github.com/btcpayserver/btcpayserver/blob/master/LICENSE"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "/",
|
||||
"description": "BTCPay Server Greenfield API"
|
||||
}
|
||||
],
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ValidationProblemDetails": {
|
||||
"type": "array",
|
||||
"description": "An array of validation errors of the request",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "A specific validation error on a json property",
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string",
|
||||
"nullable": false,
|
||||
"description": "The json path of the property which failed validation"
|
||||
},
|
||||
"ProblemDetails": {
|
||||
"type": "object",
|
||||
"description": "Description of an error happening during processing of the request",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "string",
|
||||
"nullable": false,
|
||||
"description": "An error code describing the error"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"nullable": false,
|
||||
"description": "User friendly error message about the error"
|
||||
}
|
||||
}
|
||||
},
|
||||
"UnixTimestamp": {
|
||||
"type": "number",
|
||||
"format": "int32",
|
||||
"example": 1592312018,
|
||||
"description": "A unix timestamp in seconds"
|
||||
},
|
||||
"SpeedPolicy": {
|
||||
"type": "string",
|
||||
"description": "`\"HighSpeed\"`: 0 confirmations (1 confirmation if RBF enabled in transaction) \n`\"MediumSpeed\"`: 1 confirmation \n`\"LowMediumSpeed\"`: 2 confirmations \n`\"LowSpeed\"`: 6 confirmations\n",
|
||||
"x-enumNames": [
|
||||
"HighSpeed",
|
||||
"MediumSpeed",
|
||||
"LowSpeed",
|
||||
"LowMediumSpeed"
|
||||
],
|
||||
"enum": [
|
||||
"HighSpeed",
|
||||
"MediumSpeed",
|
||||
"LowSpeed",
|
||||
"LowMediumSpeed"
|
||||
]
|
||||
},
|
||||
"CheckoutType": {
|
||||
"type": "string",
|
||||
"description": "`\"V1\"`: The original checkout form \n`\"V2\"`: The new experimental checkout form",
|
||||
"nullable": true,
|
||||
"default": "V1",
|
||||
"x-enumNames": [
|
||||
"V1",
|
||||
"V2"
|
||||
],
|
||||
"enum": [
|
||||
"V1",
|
||||
"V2"
|
||||
]
|
||||
},
|
||||
"TimeSpan": {
|
||||
"type": "number",
|
||||
"format": "int32",
|
||||
"example": 90
|
||||
},
|
||||
"TimeSpanSeconds": {
|
||||
"allOf": [ { "$ref": "#/components/schemas/TimeSpan" } ],
|
||||
"format": "seconds",
|
||||
"description": "A span of times in seconds"
|
||||
},
|
||||
"TimeSpanMinutes": {
|
||||
"allOf": [ { "$ref": "#/components/schemas/TimeSpan" } ],
|
||||
"format": "minutes",
|
||||
"description": "A span of times in minutes"
|
||||
}
|
||||
},
|
||||
"securitySchemes": {
|
||||
"API_Key": {
|
||||
"type": "apiKey",
|
||||
"description": "BTCPay Server supports authenticating and authorizing users through an API Key that is generated by them. Send the API Key as a header value to Authorization with the format: `token {token}`. For a smoother experience, you can generate a url that redirects users to an API key creation screen.\n\n The following permissions are available to the context of the user creating the API Key:\n\n* `unrestricted`: Unrestricted access\n* `btcpay.user.candeleteuser`: Delete user\n* `btcpay.user.canviewprofile`: View your profile\n* `btcpay.user.canmodifyprofile`: Manage your profile\n* `btcpay.user.canmanagenotificationsforuser`: Manage your notifications\n* `btcpay.user.canviewnotificationsforuser`: View your notifications\n\nThe following permissions are available if the user is an administrator:\n\n* `btcpay.server.canviewusers`: View users\n* `btcpay.server.cancreateuser`: Create new users\n* `btcpay.server.canmodifyserversettings`: Manage your server\n* `btcpay.server.canuseinternallightningnode`: Use the internal lightning node\n* `btcpay.server.canviewlightninginvoiceinternalnode`: View invoices from internal lightning node\n* `btcpay.server.cancreatelightninginvoiceinternalnode`: Create invoices with internal lightning node\n\nThe following permissions applies to all stores of the user, you can limit to a specific store with the following format: `btcpay.store.cancreateinvoice:6HSHAEU4iYWtjxtyRs9KyPjM9GAQp8kw2T9VWbGG1FnZ`:\n\n* `btcpay.store.canmodifystoresettings`: Modify your stores\n* `btcpay.store.canviewcustodianaccounts`: View exchange accounts linked to your stores\n* `btcpay.store.canmanagecustodianaccounts`: Manage exchange accounts linked to your stores\n* `btcpay.store.candeposittocustodianaccount`: Deposit funds to exchange accounts linked to your stores\n* `btcpay.store.canwithdrawfromcustodianaccount`: Withdraw funds from exchange accounts to your store\n* `btcpay.store.cantradecustodianaccount`: Trade funds on your store's exchange accounts\n* `btcpay.store.webhooks.canmodifywebhooks`: Modify stores webhooks\n* `btcpay.store.canviewstoresettings`: View your stores\n* `btcpay.store.cancreateinvoice`: Create an invoice\n* `btcpay.store.canviewinvoices`: View invoices\n* `btcpay.store.canmodifyinvoices`: Modify invoices\n* `btcpay.store.canmodifypaymentrequests`: Modify your payment requests\n* `btcpay.store.canviewpaymentrequests`: View your payment requests\n* `btcpay.store.canmanagepullpayments`: Manage your pull payments\n* `btcpay.store.cancreatepullpayments`: Create pull payments\n* `btcpay.store.cancreatenonapprovedpullpayments`: Create non-approved pull payments\n* `btcpay.store.canuselightningnode`: Use the lightning nodes associated with your stores\n* `btcpay.store.canviewlightninginvoice`: View the lightning invoices associated with your stores\n* `btcpay.store.cancreatelightninginvoice`: Create invoices from the lightning nodes associated with your stores\n\nNote that API Keys only limits permission of a user and can never expand it. If an API Key has the permission `btcpay.server.canmodifyserversettings` but that the user account creating this API Key is not administrator, the API Key will not be able to modify the server settings.\nSome permissions may include other permissions, see [this operation](#operation/permissionsMetadata).\n",
|
||||
"name": "Authorization",
|
||||
"in": "header"
|
||||
},
|
||||
"Basic": {
|
||||
"type": "http",
|
||||
"description": "BTCPay Server supports authenticating and authorizing users through the Basic HTTP authentication scheme. Send the user and password encoded in base64 with the format `Basic {base64(username:password)}`. Using this authentication method implicitly provides you with the `unrestricted` permission",
|
||||
"scheme": "Basic"
|
||||
"message": {
|
||||
"type": "string",
|
||||
"nullable": false,
|
||||
"description": "User friendly error message about the validation"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ProblemDetails": {
|
||||
"type": "object",
|
||||
"description": "Description of an error happening during processing of the request",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "string",
|
||||
"nullable": false,
|
||||
"description": "An error code describing the error"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"nullable": false,
|
||||
"description": "User friendly error message about the error"
|
||||
}
|
||||
}
|
||||
},
|
||||
"UnixTimestamp": {
|
||||
"type": "number",
|
||||
"format": "int32",
|
||||
"example": 1592312018,
|
||||
"description": "A unix timestamp in seconds"
|
||||
},
|
||||
"SpeedPolicy": {
|
||||
"type": "string",
|
||||
"description": "`\"HighSpeed\"`: 0 confirmations (1 confirmation if RBF enabled in transaction) \n`\"MediumSpeed\"`: 1 confirmation \n`\"LowMediumSpeed\"`: 2 confirmations \n`\"LowSpeed\"`: 6 confirmations\n",
|
||||
"x-enumNames": [
|
||||
"HighSpeed",
|
||||
"MediumSpeed",
|
||||
"LowSpeed",
|
||||
"LowMediumSpeed"
|
||||
],
|
||||
"enum": [
|
||||
"HighSpeed",
|
||||
"MediumSpeed",
|
||||
"LowSpeed",
|
||||
"LowMediumSpeed"
|
||||
]
|
||||
},
|
||||
"CheckoutType": {
|
||||
"type": "string",
|
||||
"description": "`\"V1\"`: The original checkout form \n`\"V2\"`: The new experimental checkout form",
|
||||
"nullable": true,
|
||||
"default": "V1",
|
||||
"x-enumNames": [
|
||||
"V1",
|
||||
"V2"
|
||||
],
|
||||
"enum": [
|
||||
"V1",
|
||||
"V2"
|
||||
]
|
||||
},
|
||||
"TimeSpan": {
|
||||
"type": "number",
|
||||
"format": "int32",
|
||||
"example": 90
|
||||
},
|
||||
"TimeSpanSeconds": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/TimeSpan"
|
||||
}
|
||||
],
|
||||
"format": "seconds",
|
||||
"description": "A span of times in seconds"
|
||||
},
|
||||
"TimeSpanMinutes": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/TimeSpan"
|
||||
}
|
||||
],
|
||||
"format": "minutes",
|
||||
"description": "A span of times in minutes"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"API_Key": [],
|
||||
"Basic": []
|
||||
}
|
||||
]
|
||||
}
|
||||
"securitySchemes": {
|
||||
"API_Key": {
|
||||
"type": "apiKey",
|
||||
"description": "BTCPay Server supports authenticating and authorizing users through an API Key that is generated by them. Send the API Key as a header value to Authorization with the format: `token {token}`. For a smoother experience, you can generate a url that redirects users to an API key creation screen.\n\n The following permissions are available to the context of the user creating the API Key:\n\n* `unrestricted`: Unrestricted access\n* `btcpay.user.candeleteuser`: Delete user\n* `btcpay.user.canviewprofile`: View your profile\n* `btcpay.user.canmodifyprofile`: Manage your profile\n* `btcpay.user.canmanagenotificationsforuser`: Manage your notifications\n* `btcpay.user.canviewnotificationsforuser`: View your notifications\n\nThe following permissions are available if the user is an administrator:\n\n* `btcpay.server.canviewusers`: View users\n* `btcpay.server.cancreateuser`: Create new users\n* `btcpay.server.canmanageusers`: Manage users\n* `btcpay.server.canmodifyserversettings`: Manage your server\n* `btcpay.server.canuseinternallightningnode`: Use the internal lightning node\n* `btcpay.server.canviewlightninginvoiceinternalnode`: View invoices from internal lightning node\n* `btcpay.server.cancreatelightninginvoiceinternalnode`: Create invoices with internal lightning node\n\nThe following permissions applies to all stores of the user, you can limit to a specific store with the following format: `btcpay.store.cancreateinvoice:6HSHAEU4iYWtjxtyRs9KyPjM9GAQp8kw2T9VWbGG1FnZ`:\n\n* `btcpay.store.canmodifystoresettings`: Modify your stores\n* `btcpay.store.canviewcustodianaccounts`: View exchange accounts linked to your stores\n* `btcpay.store.canmanagecustodianaccounts`: Manage exchange accounts linked to your stores\n* `btcpay.store.candeposittocustodianaccount`: Deposit funds to exchange accounts linked to your stores\n* `btcpay.store.canwithdrawfromcustodianaccount`: Withdraw funds from exchange accounts to your store\n* `btcpay.store.cantradecustodianaccount`: Trade funds on your store's exchange accounts\n* `btcpay.store.webhooks.canmodifywebhooks`: Modify stores webhooks\n* `btcpay.store.canviewstoresettings`: View your stores\n* `btcpay.store.cancreateinvoice`: Create an invoice\n* `btcpay.store.canviewinvoices`: View invoices\n* `btcpay.store.canmodifyinvoices`: Modify invoices\n* `btcpay.store.canmodifypaymentrequests`: Modify your payment requests\n* `btcpay.store.canviewpaymentrequests`: View your payment requests\n* `btcpay.store.canmanagepullpayments`: Manage your pull payments\n* `btcpay.store.cancreatepullpayments`: Create pull payments\n* `btcpay.store.cancreatenonapprovedpullpayments`: Create non-approved pull payments\n* `btcpay.store.canuselightningnode`: Use the lightning nodes associated with your stores\n* `btcpay.store.canviewlightninginvoice`: View the lightning invoices associated with your stores\n* `btcpay.store.cancreatelightninginvoice`: Create invoices from the lightning nodes associated with your stores\n\nNote that API Keys only limits permission of a user and can never expand it. If an API Key has the permission `btcpay.server.canmodifyserversettings` but that the user account creating this API Key is not administrator, the API Key will not be able to modify the server settings.\nSome permissions may include other permissions, see [this operation](#operation/permissionsMetadata).\n",
|
||||
"name": "Authorization",
|
||||
"in": "header"
|
||||
},
|
||||
"Basic": {
|
||||
"type": "http",
|
||||
"description": "BTCPay Server supports authenticating and authorizing users through the Basic HTTP authentication scheme. Send the user and password encoded in base64 with the format `Basic {base64(username:password)}`. Using this authentication method implicitly provides you with the `unrestricted` permission",
|
||||
"scheme": "Basic"
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"API_Key": [],
|
||||
"Basic": []
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user