mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 14:04:26 +01:00
Merge pull request #1408 from Kukks/api/api-key-uu-refactor
Refactor UI for Add APIKey/Authorize
This commit is contained in:
@@ -37,6 +37,11 @@ namespace BTCPayServer.Client
|
|||||||
{
|
{
|
||||||
return policy.StartsWith("btcpay.store", StringComparison.OrdinalIgnoreCase);
|
return policy.StartsWith("btcpay.store", StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool IsServerPolicy(string policy)
|
||||||
|
{
|
||||||
|
return policy.StartsWith("btcpay.server", StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public class Permission
|
public class Permission
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -86,9 +86,9 @@ namespace BTCPayServer.Tests
|
|||||||
Policies.CanModifyStoreSettings);
|
Policies.CanModifyStoreSettings);
|
||||||
|
|
||||||
s.Driver.FindElement(By.Id("AddApiKey")).Click();
|
s.Driver.FindElement(By.Id("AddApiKey")).Click();
|
||||||
s.Driver.FindElement(By.CssSelector("button[value=change-store-mode]")).Click();
|
s.Driver.FindElement(By.CssSelector("button[value='btcpay.store.canmodifystoresettings:change-store-mode']")).Click();
|
||||||
//there should be a store already by default in the dropdown
|
//there should be a store already by default in the dropdown
|
||||||
var dropdown = s.Driver.FindElement(By.Name("SpecificStores[0]"));
|
var dropdown = s.Driver.FindElement(By.Name("PermissionValues[2].SpecificStores[0]"));
|
||||||
var option = dropdown.FindElement(By.TagName("option"));
|
var option = dropdown.FindElement(By.TagName("option"));
|
||||||
var storeId = option.GetAttribute("value");
|
var storeId = option.GetAttribute("value");
|
||||||
option.Click();
|
option.Click();
|
||||||
|
|||||||
@@ -70,13 +70,11 @@ namespace BTCPayServer.Tests
|
|||||||
var x = Assert.IsType<RedirectToActionResult>(await manageController.AddApiKey(
|
var x = Assert.IsType<RedirectToActionResult>(await manageController.AddApiKey(
|
||||||
new ManageController.AddApiKeyViewModel()
|
new ManageController.AddApiKeyViewModel()
|
||||||
{
|
{
|
||||||
PermissionValues =
|
PermissionValues = permissions.Select(s => new ManageController.AddApiKeyViewModel.PermissionValueItem()
|
||||||
permissions.Select(s =>
|
{
|
||||||
new ManageController.AddApiKeyViewModel.PermissionValueItem()
|
Permission = s,
|
||||||
{
|
Value = true
|
||||||
Permission = s, Value = true
|
}).ToList()
|
||||||
}).ToList(),
|
|
||||||
StoreMode = ManageController.AddApiKeyViewModel.ApiKeyStoreMode.AllStores
|
|
||||||
}));
|
}));
|
||||||
var statusMessage = manageController.TempData.GetStatusMessageModel();
|
var statusMessage = manageController.TempData.GetStatusMessageModel();
|
||||||
Assert.NotNull(statusMessage);
|
Assert.NotNull(statusMessage);
|
||||||
|
|||||||
@@ -93,65 +93,93 @@ namespace BTCPayServer.Controllers
|
|||||||
});
|
});
|
||||||
return RedirectToAction("APIKeys");
|
return RedirectToAction("APIKeys");
|
||||||
}
|
}
|
||||||
|
|
||||||
permissions ??= Array.Empty<string>();
|
permissions ??= Array.Empty<string>();
|
||||||
|
|
||||||
var vm = await SetViewModelValues(new AuthorizeApiKeysViewModel(Permission.ToPermissions(permissions))
|
var parsedPermissions = Permission.ToPermissions(permissions).GroupBy(permission => permission.Policy);
|
||||||
|
var vm = await SetViewModelValues(new AuthorizeApiKeysViewModel()
|
||||||
{
|
{
|
||||||
Label = applicationName,
|
Label = applicationName,
|
||||||
ApplicationName = applicationName,
|
ApplicationName = applicationName,
|
||||||
SelectiveStores = selectiveStores,
|
SelectiveStores = selectiveStores,
|
||||||
Strict = strict,
|
Strict = strict,
|
||||||
|
Permissions = string.Join(';', parsedPermissions.SelectMany(grouping => grouping.Select(permission => permission.ToString())))
|
||||||
});
|
});
|
||||||
|
AdjustVMForAuthorization(vm);
|
||||||
|
|
||||||
return View(vm);
|
return View(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AdjustVMForAuthorization(AuthorizeApiKeysViewModel vm)
|
||||||
|
{
|
||||||
|
var parsedPermissions = Permission.ToPermissions(vm.Permissions.Split(';')).GroupBy(permission => permission.Policy);
|
||||||
|
|
||||||
|
for (var index = vm.PermissionValues.Count - 1; index >= 0; index--)
|
||||||
|
{
|
||||||
|
var permissionValue = vm.PermissionValues[index];
|
||||||
|
var wanted = parsedPermissions?.SingleOrDefault(permission =>
|
||||||
|
permission.Key.Equals(permissionValue.Permission,
|
||||||
|
StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
if (vm.Strict && !(wanted?.Any()??false))
|
||||||
|
{
|
||||||
|
vm.PermissionValues.RemoveAt(index);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (wanted?.Any()??false)
|
||||||
|
{
|
||||||
|
if (vm.SelectiveStores && Policies.IsStorePolicy(permissionValue.Permission) &&
|
||||||
|
wanted.Any(permission => !string.IsNullOrEmpty(permission.StoreId)))
|
||||||
|
{
|
||||||
|
permissionValue.StoreMode = AddApiKeyViewModel.ApiKeyStoreMode.Specific;
|
||||||
|
permissionValue.SpecificStores = wanted.Select(permission => permission.StoreId).ToList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
permissionValue.StoreMode = AddApiKeyViewModel.ApiKeyStoreMode.AllStores;
|
||||||
|
permissionValue.SpecificStores = new List<string>();
|
||||||
|
permissionValue.Value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPost("~/api-keys/authorize")]
|
[HttpPost("~/api-keys/authorize")]
|
||||||
public async Task<IActionResult> AuthorizeAPIKey([FromForm] AuthorizeApiKeysViewModel viewModel)
|
public async Task<IActionResult> AuthorizeAPIKey([FromForm] AuthorizeApiKeysViewModel viewModel)
|
||||||
{
|
{
|
||||||
await SetViewModelValues(viewModel);
|
await SetViewModelValues(viewModel);
|
||||||
|
|
||||||
|
AdjustVMForAuthorization(viewModel);
|
||||||
var ar = HandleCommands(viewModel);
|
var ar = HandleCommands(viewModel);
|
||||||
|
|
||||||
if (ar != null)
|
if (ar != null)
|
||||||
{
|
{
|
||||||
return ar;
|
return ar;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (viewModel.Strict)
|
for (int i = 0; i < viewModel.PermissionValues.Count; i++)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < viewModel.PermissionValues.Count; i++)
|
if (viewModel.PermissionValues[i].Forbidden && viewModel.Strict)
|
||||||
{
|
{
|
||||||
if (viewModel.PermissionValues[i].Forbidden)
|
viewModel.PermissionValues[i].Value = false;
|
||||||
{
|
ModelState.AddModelError($"{viewModel.PermissionValues}[{i}].Value",
|
||||||
ModelState.AddModelError($"{viewModel.PermissionValues}[{i}].Value",
|
$"The permission '{viewModel.PermissionValues[i].Title}' is required for this application.");
|
||||||
$"The permission '{viewModel.PermissionValues[i].Title}' is required for this application.");
|
}
|
||||||
}
|
|
||||||
|
if (viewModel.PermissionValues[i].StoreMode == AddApiKeyViewModel.ApiKeyStoreMode.Specific &&
|
||||||
|
!viewModel.SelectiveStores)
|
||||||
|
{
|
||||||
|
viewModel.PermissionValues[i].StoreMode = AddApiKeyViewModel.ApiKeyStoreMode.AllStores;
|
||||||
|
ModelState.AddModelError($"{viewModel.PermissionValues}[{i}].Value",
|
||||||
|
$"The permission '{viewModel.PermissionValues[i].Title}' cannot be store specific for this application.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var permissions = Permission.ToPermissions(viewModel.Permissions.Split(';')).ToHashSet();
|
|
||||||
if (permissions.Contains(Permission.Create(Policies.CanModifyStoreSettings)))
|
|
||||||
{
|
|
||||||
if (!viewModel.SelectiveStores &&
|
|
||||||
viewModel.StoreMode == AddApiKeyViewModel.ApiKeyStoreMode.Specific)
|
|
||||||
{
|
|
||||||
viewModel.StoreMode = AddApiKeyViewModel.ApiKeyStoreMode.AllStores;
|
|
||||||
ModelState.AddModelError(nameof(viewModel.StoreManagementPermission),
|
|
||||||
"This application does not allow selective store permissions.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!viewModel.StoreManagementPermission.Value && !viewModel.SpecificStores.Any() && viewModel.Strict)
|
|
||||||
{
|
|
||||||
ModelState.AddModelError(nameof(viewModel.StoreManagementPermission),
|
|
||||||
$"This permission '{viewModel.StoreManagementPermission.Title}' is required for this application.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ModelState.IsValid)
|
if (!ModelState.IsValid)
|
||||||
{
|
{
|
||||||
return View(viewModel);
|
return View(viewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (viewModel.Command.ToLowerInvariant())
|
switch (viewModel.Command.ToLowerInvariant())
|
||||||
{
|
{
|
||||||
case "no":
|
case "no":
|
||||||
@@ -197,35 +225,48 @@ namespace BTCPayServer.Controllers
|
|||||||
}
|
}
|
||||||
private IActionResult HandleCommands(AddApiKeyViewModel viewModel)
|
private IActionResult HandleCommands(AddApiKeyViewModel viewModel)
|
||||||
{
|
{
|
||||||
switch (viewModel.Command)
|
if (string.IsNullOrEmpty(viewModel.Command))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var parts = viewModel.Command.Split(':', StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
var permission = parts[0];
|
||||||
|
if (!Policies.IsStorePolicy(permission))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var permissionValueItem = viewModel.PermissionValues.Single(item => item.Permission == permission);
|
||||||
|
var command = parts[1];
|
||||||
|
var storeIndex = parts.Length == 3 ? parts[2] : null;
|
||||||
|
|
||||||
|
ModelState.Clear();
|
||||||
|
switch (command)
|
||||||
{
|
{
|
||||||
case "change-store-mode":
|
case "change-store-mode":
|
||||||
viewModel.StoreMode = viewModel.StoreMode == AddApiKeyViewModel.ApiKeyStoreMode.Specific
|
|
||||||
|
permissionValueItem.StoreMode = permissionValueItem.StoreMode == AddApiKeyViewModel.ApiKeyStoreMode.Specific
|
||||||
? AddApiKeyViewModel.ApiKeyStoreMode.AllStores
|
? AddApiKeyViewModel.ApiKeyStoreMode.AllStores
|
||||||
: AddApiKeyViewModel.ApiKeyStoreMode.Specific;
|
: AddApiKeyViewModel.ApiKeyStoreMode.Specific;
|
||||||
|
|
||||||
if (viewModel.StoreMode == AddApiKeyViewModel.ApiKeyStoreMode.Specific &&
|
if (permissionValueItem.StoreMode == AddApiKeyViewModel.ApiKeyStoreMode.Specific &&
|
||||||
!viewModel.SpecificStores.Any() && viewModel.Stores.Any())
|
!permissionValueItem.SpecificStores.Any() && viewModel.Stores.Any())
|
||||||
{
|
{
|
||||||
viewModel.SpecificStores.Add(null);
|
permissionValueItem.SpecificStores.Add(null);
|
||||||
}
|
}
|
||||||
return View(viewModel);
|
return View(viewModel);
|
||||||
case "add-store":
|
case "add-store":
|
||||||
viewModel.SpecificStores.Add(null);
|
permissionValueItem.SpecificStores.Add(null);
|
||||||
return View(viewModel);
|
return View(viewModel);
|
||||||
|
|
||||||
case string x when x.StartsWith("remove-store", StringComparison.InvariantCultureIgnoreCase):
|
case "remove-store":
|
||||||
{
|
{
|
||||||
ModelState.Clear();
|
if (storeIndex != null)
|
||||||
var index = int.Parse(
|
permissionValueItem.SpecificStores.RemoveAt(int.Parse(storeIndex,
|
||||||
viewModel.Command.Substring(
|
CultureInfo.InvariantCulture));
|
||||||
viewModel.Command.IndexOf(":", StringComparison.InvariantCultureIgnoreCase) + 1),
|
return View(viewModel);
|
||||||
CultureInfo.InvariantCulture);
|
}
|
||||||
viewModel.SpecificStores.RemoveAt(index);
|
|
||||||
return View(viewModel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,95 +290,56 @@ namespace BTCPayServer.Controllers
|
|||||||
private IEnumerable<Permission> GetPermissionsFromViewModel(AddApiKeyViewModel viewModel)
|
private IEnumerable<Permission> GetPermissionsFromViewModel(AddApiKeyViewModel viewModel)
|
||||||
{
|
{
|
||||||
List<Permission> permissions = new List<Permission>();
|
List<Permission> permissions = new List<Permission>();
|
||||||
foreach (var p in viewModel.PermissionValues.Where(tuple => tuple.Value && !tuple.Forbidden))
|
foreach (var p in viewModel.PermissionValues.Where(tuple => !tuple.Forbidden))
|
||||||
{
|
{
|
||||||
if (Permission.TryCreatePermission(p.Permission, null, out var pp))
|
if (Policies.IsStorePolicy(p.Permission))
|
||||||
|
{
|
||||||
|
if (p.StoreMode == AddApiKeyViewModel.ApiKeyStoreMode.AllStores && p.Value)
|
||||||
|
{
|
||||||
|
permissions.Add(Permission.Create(p.Permission));
|
||||||
|
}
|
||||||
|
else if (p.StoreMode == AddApiKeyViewModel.ApiKeyStoreMode.Specific)
|
||||||
|
{
|
||||||
|
permissions.AddRange(p.SpecificStores.Select(s => Permission.Create(p.Permission, s)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (p.Value && Permission.TryCreatePermission(p.Permission, null, out var pp))
|
||||||
permissions.Add(pp);
|
permissions.Add(pp);
|
||||||
}
|
}
|
||||||
if (viewModel.StoreMode == AddApiKeyViewModel.ApiKeyStoreMode.AllStores && viewModel.StoreManagementPermission.Value)
|
|
||||||
{
|
|
||||||
permissions.Add(Permission.Create(Policies.CanModifyStoreSettings));
|
|
||||||
}
|
|
||||||
else if (viewModel.StoreMode == AddApiKeyViewModel.ApiKeyStoreMode.Specific)
|
|
||||||
{
|
|
||||||
permissions.AddRange(viewModel.SpecificStores.Select(s => Permission.Create(Policies.CanModifyStoreSettings, s)));
|
|
||||||
}
|
|
||||||
return permissions.Distinct();
|
return permissions.Distinct();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<T> SetViewModelValues<T>(T viewModel) where T : AddApiKeyViewModel
|
private async Task<T> SetViewModelValues<T>(T viewModel) where T : AddApiKeyViewModel
|
||||||
{
|
{
|
||||||
viewModel.Stores = await _StoreRepository.GetStoresByUserId(_userManager.GetUserId(User));
|
viewModel.Stores = await _StoreRepository.GetStoresByUserId(_userManager.GetUserId(User));
|
||||||
var isAdmin = (await _authorizationService.AuthorizeAsync(User, Policies.CanModifyServerSettings)).Succeeded;
|
var isAdmin = (await _authorizationService.AuthorizeAsync(User, Policies.CanModifyServerSettings))
|
||||||
viewModel.PermissionValues ??= Policies.AllPolicies.Where(p => p != Policies.CanModifyStoreSettings)
|
.Succeeded;
|
||||||
.Select(s => new AddApiKeyViewModel.PermissionValueItem() { Permission = s, Value = false }).ToList();
|
viewModel.PermissionValues ??= Policies.AllPolicies
|
||||||
|
.Select(s => new AddApiKeyViewModel.PermissionValueItem()
|
||||||
|
{
|
||||||
|
Permission = s,
|
||||||
|
Value = false,
|
||||||
|
Forbidden = Policies.IsServerPolicy(s) && !isAdmin
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
|
||||||
if (!isAdmin)
|
if (!isAdmin)
|
||||||
{
|
{
|
||||||
foreach (var p in viewModel.PermissionValues)
|
foreach (var p in viewModel.PermissionValues.Where(item => Policies.IsServerPolicy(item.Permission)))
|
||||||
{
|
{
|
||||||
if (p.Permission == Policies.CanCreateUser ||
|
p.Forbidden = true;
|
||||||
p.Permission == Policies.CanModifyServerSettings)
|
|
||||||
{
|
|
||||||
p.Forbidden = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return viewModel;
|
return viewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AddApiKeyViewModel
|
public class AddApiKeyViewModel
|
||||||
{
|
{
|
||||||
public AddApiKeyViewModel()
|
|
||||||
{
|
|
||||||
StoreManagementPermission = new PermissionValueItem()
|
|
||||||
{
|
|
||||||
Permission = Policies.CanModifyStoreSettings,
|
|
||||||
Value = false
|
|
||||||
};
|
|
||||||
StoreManagementSelectivePermission = new PermissionValueItem()
|
|
||||||
{
|
|
||||||
Permission = $"{Policies.CanModifyStoreSettings}:",
|
|
||||||
Value = true
|
|
||||||
};
|
|
||||||
}
|
|
||||||
public AddApiKeyViewModel(IEnumerable<Permission> permissions):this()
|
|
||||||
{
|
|
||||||
StoreManagementPermission.Value = permissions.Any(p => p.Policy == Policies.CanModifyStoreSettings && p.StoreId == null);
|
|
||||||
PermissionValues = permissions.Where(p => p.Policy != Policies.CanModifyStoreSettings)
|
|
||||||
.Select(p => new PermissionValueItem() { Permission = p.ToString(), Value = true })
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<Permission> GetPermissions()
|
|
||||||
{
|
|
||||||
if (!(PermissionValues is null))
|
|
||||||
{
|
|
||||||
foreach (var p in PermissionValues.Where(o => o.Value))
|
|
||||||
{
|
|
||||||
if (Permission.TryCreatePermission(p.Permission, null, out var pp))
|
|
||||||
yield return pp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.StoreMode == ApiKeyStoreMode.AllStores)
|
|
||||||
{
|
|
||||||
if (StoreManagementPermission.Value)
|
|
||||||
yield return Permission.Create(Policies.CanModifyStoreSettings);
|
|
||||||
}
|
|
||||||
else if (this.StoreMode == ApiKeyStoreMode.Specific && SpecificStores is List<string>)
|
|
||||||
{
|
|
||||||
foreach (var p in SpecificStores)
|
|
||||||
{
|
|
||||||
if (Permission.TryCreatePermission(Policies.CanModifyStoreSettings, p, out var pp))
|
|
||||||
yield return pp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public string Label { get; set; }
|
public string Label { get; set; }
|
||||||
public StoreData[] Stores { get; set; }
|
public StoreData[] Stores { get; set; }
|
||||||
public ApiKeyStoreMode StoreMode { get; set; }
|
|
||||||
public List<string> SpecificStores { get; set; } = new List<string>();
|
|
||||||
public PermissionValueItem StoreManagementPermission { get; set; }
|
|
||||||
public PermissionValueItem StoreManagementSelectivePermission { get; set; }
|
|
||||||
public string Command { get; set; }
|
public string Command { get; set; }
|
||||||
public List<PermissionValueItem> PermissionValues { get; set; }
|
public List<PermissionValueItem> PermissionValues { get; set; }
|
||||||
|
|
||||||
@@ -354,43 +356,40 @@ namespace BTCPayServer.Controllers
|
|||||||
{BTCPayServer.Client.Policies.Unrestricted, ("Unrestricted access", "The app will have unrestricted access to your account.")},
|
{BTCPayServer.Client.Policies.Unrestricted, ("Unrestricted access", "The app will have unrestricted access to your account.")},
|
||||||
{BTCPayServer.Client.Policies.CanCreateUser, ("Create new users", "The app will be able to create new users on this server.")},
|
{BTCPayServer.Client.Policies.CanCreateUser, ("Create new users", "The app will be able to create new users on this server.")},
|
||||||
{BTCPayServer.Client.Policies.CanModifyStoreSettings, ("Modify your stores", "The app will be able to create, view and modify, delete and create new invoices on the all your stores.")},
|
{BTCPayServer.Client.Policies.CanModifyStoreSettings, ("Modify your stores", "The app will be able to create, view and modify, delete and create new invoices on the all your stores.")},
|
||||||
{BTCPayServer.Client.Policies.CanViewStoreSettings, ("View your stores", "The app will be able to view stores settings.")},
|
|
||||||
{$"{BTCPayServer.Client.Policies.CanModifyStoreSettings}:", ("Manage selected stores", "The app will be able to view, modify, delete and create new invoices on the selected stores.")},
|
{$"{BTCPayServer.Client.Policies.CanModifyStoreSettings}:", ("Manage selected stores", "The app will be able to view, modify, delete and create new invoices on the selected stores.")},
|
||||||
|
{BTCPayServer.Client.Policies.CanViewStoreSettings, ("View your stores", "The app will be able to view stores settings.")},
|
||||||
|
{$"{BTCPayServer.Client.Policies.CanViewStoreSettings}:", ("View your stores", "The app will be able to view the selected stores' settings.")},
|
||||||
{BTCPayServer.Client.Policies.CanModifyServerSettings, ("Manage your server", "The app will have total control on the server settings of your server")},
|
{BTCPayServer.Client.Policies.CanModifyServerSettings, ("Manage your server", "The app will have total control on the server settings of your server")},
|
||||||
{BTCPayServer.Client.Policies.CanViewProfile, ("View your profile", "The app will be able to view your user profile.")},
|
{BTCPayServer.Client.Policies.CanViewProfile, ("View your profile", "The app will be able to view your user profile.")},
|
||||||
{BTCPayServer.Client.Policies.CanModifyProfile, ("Manage your profile", "The app will be able to view and modify your user profile.")},
|
{BTCPayServer.Client.Policies.CanModifyProfile, ("Manage your profile", "The app will be able to view and modify your user profile.")},
|
||||||
{BTCPayServer.Client.Policies.CanCreateInvoice, ("Create an invoice", "The app will be able to create new invoice.")},
|
{BTCPayServer.Client.Policies.CanCreateInvoice, ("Create an invoice", "The app will be able to create new invoices.")},
|
||||||
|
{$"{BTCPayServer.Client.Policies.CanCreateInvoice}:", ("Create an invoice", "The app will be able to create new invoices on the selected stores.")},
|
||||||
};
|
};
|
||||||
public string Title
|
public string Title
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return PermissionDescriptions[Permission].Title;
|
return PermissionDescriptions[$"{Permission}{(StoreMode == ApiKeyStoreMode.Specific? ":": "")}"].Title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public string Description
|
public string Description
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return PermissionDescriptions[Permission].Description;
|
return PermissionDescriptions[$"{Permission}{(StoreMode == ApiKeyStoreMode.Specific? ":": "")}"].Description;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public string Permission { get; set; }
|
public string Permission { get; set; }
|
||||||
public bool Value { get; set; }
|
public bool Value { get; set; }
|
||||||
public bool Forbidden { get; set; }
|
public bool Forbidden { get; set; }
|
||||||
|
|
||||||
|
public ApiKeyStoreMode StoreMode { get; set; } = ApiKeyStoreMode.AllStores;
|
||||||
|
public List<string> SpecificStores { get; set; } = new List<string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AuthorizeApiKeysViewModel : AddApiKeyViewModel
|
public class AuthorizeApiKeysViewModel : AddApiKeyViewModel
|
||||||
{
|
{
|
||||||
public AuthorizeApiKeysViewModel()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
public AuthorizeApiKeysViewModel(IEnumerable<Permission> permissions) : base(permissions)
|
|
||||||
{
|
|
||||||
Permissions = string.Join(';', permissions.Select(p => p.ToString()).ToArray());
|
|
||||||
}
|
|
||||||
public string ApplicationName { get; set; }
|
public string ApplicationName { get; set; }
|
||||||
public bool Strict { get; set; }
|
public bool Strict { get; set; }
|
||||||
public bool SelectiveStores { get; set; }
|
public bool SelectiveStores { get; set; }
|
||||||
|
|||||||
@@ -8,102 +8,108 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
<h4>@ViewData["Title"]</h4>
|
<h4>@ViewData["Title"]</h4>
|
||||||
<partial name="_StatusMessage" />
|
<partial name="_StatusMessage"/>
|
||||||
<p>
|
<p>
|
||||||
Generate a new api key to use BTCPay through its API.
|
Generate a new api key to use BTCPay through its API.
|
||||||
</p>
|
</p>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<form method="post" asp-action="AddApiKey" class="list-group">
|
<form method="post" asp-action="AddApiKey" class="list-group">
|
||||||
|
|
||||||
<input type="hidden" asp-for="StoreMode" value="@Model.StoreMode" />
|
|
||||||
<div asp-validation-summary="All" class="text-danger"></div>
|
<div asp-validation-summary="All" class="text-danger"></div>
|
||||||
|
|
||||||
<div class="list-group-item ">
|
<div class="list-group-item ">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label asp-for="Label"></label>
|
<label asp-for="Label"></label>
|
||||||
<input asp-for="Label" class="form-control" />
|
<input asp-for="Label" class="form-control"/>
|
||||||
<span asp-validation-for="Label" class="text-danger"></span>
|
<span asp-validation-for="Label" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@for (int i = 0; i < Model.PermissionValues.Count; i++)
|
@for (int i = 0; i < Model.PermissionValues.Count; i++)
|
||||||
{
|
{
|
||||||
@if (!Model.PermissionValues[i].Forbidden)
|
@if (!Model.PermissionValues[i].Forbidden)
|
||||||
{
|
{
|
||||||
<div class="list-group-item form-group">
|
<input type="hidden" asp-for="PermissionValues[i].Permission"/>
|
||||||
<div class="form-check">
|
@if (Policies.IsStorePolicy(Model.PermissionValues[i].Permission))
|
||||||
<input type="hidden" asp-for="PermissionValues[i].Permission">
|
|
||||||
<input id="@Model.PermissionValues[i].Permission" type="checkbox" asp-for="PermissionValues[i].Value" class="form-check-input" />
|
|
||||||
<label for="@Model.PermissionValues[i].Permission" class="h5 form-check-label">@Model.PermissionValues[i].Title</label>
|
|
||||||
<span asp-validation-for="PermissionValues[i].Value" class="text-danger"></span>
|
|
||||||
<span class="form-text text-muted">@Model.PermissionValues[i].Description</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@if (Model.StoreMode == ManageController.AddApiKeyViewModel.ApiKeyStoreMode.AllStores)
|
|
||||||
{
|
|
||||||
<div class="list-group-item form-group">
|
|
||||||
<div class="form-check">
|
|
||||||
<input id="@Model.StoreManagementPermission.Permission" type="checkbox" asp-for="@Model.StoreManagementPermission.Value" class="form-check-input" />
|
|
||||||
<label for="@Model.StoreManagementPermission.Permission" class="h5 form-check-label">@Model.StoreManagementPermission.Title</label>
|
|
||||||
<button type="submit" class="btn btn-link" name="command" value="change-store-mode">select specific stores...</button>
|
|
||||||
<span asp-validation-for="StoreManagementPermission" class="text-danger"></span>
|
|
||||||
<span class="form-text text-muted"><span>@Model.StoreManagementPermission.Description</span></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
else if (Model.StoreMode == ManageController.AddApiKeyViewModel.ApiKeyStoreMode.Specific)
|
|
||||||
{
|
|
||||||
<div class="list-group-item ">
|
|
||||||
<h5 class="mb-1">@Model.StoreManagementSelectivePermission.Title</h5>
|
|
||||||
<span class="form-text text-muted">@Model.StoreManagementSelectivePermission.Description</span>
|
|
||||||
<button type="submit" class="btn btn-link" name="command" value="change-store-mode">Give permission to all stores instead</button>
|
|
||||||
</div>
|
|
||||||
@if (!Model.Stores.Any())
|
|
||||||
{
|
{
|
||||||
<div class="list-group-item alert-warning">
|
<input type="hidden" asp-for="PermissionValues[i].StoreMode" value="@Model.PermissionValues[i].StoreMode"/>
|
||||||
You currently have no stores configured.
|
@if (Model.PermissionValues[i].StoreMode == ManageController.AddApiKeyViewModel.ApiKeyStoreMode.AllStores)
|
||||||
</div>
|
{
|
||||||
}
|
<div class="list-group-item form-group">
|
||||||
@for (var index = 0; index < Model.SpecificStores.Count; index++)
|
<div class="form-check">
|
||||||
{
|
<input id="@Model.PermissionValues[i].Permission" type="checkbox" asp-for="PermissionValues[i].Value" class="form-check-input"/>
|
||||||
<div class="list-group-item transaction-output-form p-0 pl-lg-2">
|
<label for="@Model.PermissionValues[i].Permission" class="h5 form-check-label">@Model.PermissionValues[i].Title</label>
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-12 col-md-12 col-lg-10 py-2 ">
|
|
||||||
<div class="form-group my-0">
|
|
||||||
@if (Model.SpecificStores[index] == null)
|
|
||||||
{
|
|
||||||
<select asp-for="SpecificStores[index]" class="form-control" asp-items="@(new SelectList(Model.Stores.Where(data => !Model.SpecificStores.Contains(data.Id)), nameof(StoreData.Id), nameof(StoreData.StoreName)))"></select>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var store = Model.Stores.SingleOrDefault(data => data.Id == Model.SpecificStores[index]);
|
|
||||||
<select asp-for="SpecificStores[index]" class="form-control" asp-items="@(new SelectList(new[] {store}, nameof(StoreData.Id), nameof(StoreData.StoreName), store.Id))"></select>
|
|
||||||
}
|
|
||||||
|
|
||||||
<span asp-validation-for="SpecificStores[index]" class="text-danger"></span>
|
<button type="submit" class="btn btn-link" name="command" value="@($"{Model.PermissionValues[i].Permission}:change-store-mode")">select specific stores...</button>
|
||||||
</div>
|
<span asp-validation-for="PermissionValues[i].Value" class="text-danger"></span>
|
||||||
</div>
|
<span class="form-text text-muted">@Model.PermissionValues[i].Description</span>
|
||||||
<div class="col-sm-12 col-md-12 col-lg-2 pull-right">
|
</div>
|
||||||
<button type="submit" title="Remove Store Permission" name="command" value="@($"remove-store:{index}")"
|
</div>
|
||||||
class="d-block d-lg-none d-xl-none btn btn-danger mb-2 ml-2">
|
}
|
||||||
Remove
|
else
|
||||||
</button>
|
{
|
||||||
<button type="submit" title="Remove Store Permission" name="command" value="@($"remove-store:{index}")"
|
<div class="list-group-item ">
|
||||||
class="d-none d-lg-block remove-btn text-decoration-none h-100 align-middle btn text-danger btn-link fa fa-times rounded-0 pull-right">
|
<h5 class="mb-1">@Model.PermissionValues[i].Title</h5>
|
||||||
</button>
|
<span class="form-text text-muted">@Model.PermissionValues[i].Description</span>
|
||||||
</div>
|
<button type="submit" class="btn btn-link" name="command" value="@($"{Model.PermissionValues[i].Permission}:change-store-mode")">Give permission to all stores instead</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
@if (!Model.Stores.Any())
|
||||||
|
{
|
||||||
|
<div class="list-group-item alert-warning">
|
||||||
|
You currently have no stores configured.
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@for (var index = 0; index < Model.PermissionValues[i].SpecificStores.Count; index++)
|
||||||
|
{
|
||||||
|
<div class="list-group-item transaction-output-form p-0 pl-lg-2">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12 col-md-12 col-lg-10 py-2 ">
|
||||||
|
<div class="form-group my-0">
|
||||||
|
@if (Model.PermissionValues[i].SpecificStores[index] == null)
|
||||||
|
{
|
||||||
|
<select asp-for="PermissionValues[i].SpecificStores[index]" class="form-control" asp-items="@(new SelectList(Model.Stores.Where(data => !Model.PermissionValues[i].SpecificStores.Contains(data.Id)), nameof(StoreData.Id), nameof(StoreData.StoreName)))"></select>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var store = Model.Stores.SingleOrDefault(data => data.Id == Model.PermissionValues[i].SpecificStores[index]);
|
||||||
|
<select asp-for="PermissionValues[i].SpecificStores[index]" class="form-control" asp-items="@(new SelectList(new[] {store}, nameof(StoreData.Id), nameof(StoreData.StoreName), store.Id))"></select>
|
||||||
|
}
|
||||||
|
|
||||||
|
<span asp-validation-for="PermissionValues[i].SpecificStores[index]" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-12 col-md-12 col-lg-2 pull-right">
|
||||||
|
<button type="submit" title="Remove Store Permission" name="command" value="@($"{Model.PermissionValues[i].Permission}:remove-store:{index}")"
|
||||||
|
class="d-block d-lg-none d-xl-none btn btn-danger mb-2 ml-2">
|
||||||
|
Remove
|
||||||
|
</button>
|
||||||
|
<button type="submit" title="Remove Store Permission" name="command" value="@($"{Model.PermissionValues[i].Permission}:remove-store:{index}")"
|
||||||
|
class="d-none d-lg-block remove-btn text-decoration-none h-100 align-middle btn text-danger btn-link fa fa-times rounded-0 pull-right">
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (Model.PermissionValues[i].SpecificStores.Count < Model.Stores.Length)
|
||||||
|
{
|
||||||
|
<div class="list-group-item">
|
||||||
|
<button type="submit" name="command" value="@($"{Model.PermissionValues[i].Permission}:add-store")" class="ml-1 btn btn-secondary">Add another store </button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@if (Model.SpecificStores.Count < Model.Stores.Length)
|
else
|
||||||
{
|
{
|
||||||
<div class="list-group-item">
|
<div class="list-group-item form-group">
|
||||||
<button type="submit" name="command" value="add-store" class="ml-1 btn btn-secondary">Add another store </button>
|
<div class="form-check">
|
||||||
</div>
|
<input id="@Model.PermissionValues[i].Permission" type="checkbox" asp-for="PermissionValues[i].Value" class="form-check-input"/>
|
||||||
|
<label for="@Model.PermissionValues[i].Permission" class="h5 form-check-label">@Model.PermissionValues[i].Title</label>
|
||||||
|
<span asp-validation-for="PermissionValues[i].Value" class="text-danger"></span>
|
||||||
|
<span class="form-text text-muted">@Model.PermissionValues[i].Description</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
<button type="submit" class="btn btn-primary" id="Generate">Generate API Key</button>
|
<button type="submit" class="btn btn-primary" id="Generate">Generate API Key</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -6,17 +6,15 @@
|
|||||||
@{
|
@{
|
||||||
Layout = "_Layout";
|
Layout = "_Layout";
|
||||||
ViewData["Title"] = $"Authorize {(Model.ApplicationName ?? "Application")}";
|
ViewData["Title"] = $"Authorize {(Model.ApplicationName ?? "Application")}";
|
||||||
var permissions = Permission.ToPermissions(Model.Permissions.Split(';'));
|
var permissions = Permission.ToPermissions(Model.Permissions.Split(';')).GroupBy(permission => permission.Policy);
|
||||||
var hasStorePermission = permissions.Any(p => p.Policy == Policies.CanModifyStoreSettings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<partial name="_StatusMessage" />
|
<partial name="_StatusMessage"/>
|
||||||
<form method="post" asp-action="AuthorizeAPIKey">
|
<form method="post" asp-action="AuthorizeAPIKey">
|
||||||
<input type="hidden" asp-for="Permissions" value="@Model.Permissions" />
|
<input type="hidden" asp-for="Permissions" value="@Model.Permissions"/>
|
||||||
<input type="hidden" asp-for="Strict" value="@Model.Strict" />
|
<input type="hidden" asp-for="Strict" value="@Model.Strict"/>
|
||||||
<input type="hidden" asp-for="ApplicationName" value="@Model.ApplicationName" />
|
<input type="hidden" asp-for="ApplicationName" value="@Model.ApplicationName"/>
|
||||||
<input type="hidden" asp-for="SelectiveStores" value="@Model.SelectiveStores" />
|
<input type="hidden" asp-for="SelectiveStores" value="@Model.SelectiveStores"/>
|
||||||
<input type="hidden" asp-for="StoreMode" value="@Model.StoreMode" />
|
|
||||||
<section>
|
<section>
|
||||||
<div class="card container">
|
<div class="card container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -32,119 +30,138 @@
|
|||||||
<div class="list-group-item ">
|
<div class="list-group-item ">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label asp-for="Label"></label>
|
<label asp-for="Label"></label>
|
||||||
<input asp-for="Label" class="form-control" />
|
<input asp-for="Label" class="form-control"/>
|
||||||
<span asp-validation-for="Label" class="text-danger"></span>
|
<span asp-validation-for="Label" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@if (!permissions.Any())
|
@if (!permissions.Any())
|
||||||
{
|
{
|
||||||
<div class="list-group-item form-group">
|
<div class="list-group-item form-group">
|
||||||
<p>There are no associated permissions to the API key being requested here. The application cannot do anything with your BTCPay account other than validating your account exists.</p>
|
<p class="text-center">There are no associated permissions to the API key being requested by the application.<br/>The application cannot do anything with your BTCPay account other than validating your account exists.</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@for (int i = 0; i < Model.PermissionValues.Count; i++)
|
@for (int i = 0; i < Model.PermissionValues.Count; i++)
|
||||||
{
|
{
|
||||||
<div class="list-group-item form-group">
|
<input type="hidden" asp-for="PermissionValues[i].Forbidden"/>
|
||||||
<div class="form-check">
|
<input type="hidden" asp-for="PermissionValues[i].Permission"/>
|
||||||
<input type="hidden" asp-for="PermissionValues[i].Permission">
|
<input type="hidden" asp-for="PermissionValues[i].StoreMode" value="@Model.PermissionValues[i].StoreMode"/>
|
||||||
@if (Model.Strict)
|
@if (Model.PermissionValues[i].Forbidden && !Model.Strict)
|
||||||
{
|
|
||||||
<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" />
|
|
||||||
}
|
|
||||||
<label for="@Model.PermissionValues[i].Permission" class="h5 form-check-label">@Model.PermissionValues[i].Title</label>
|
|
||||||
@if (Model.PermissionValues[i].Forbidden)
|
|
||||||
{
|
|
||||||
<br />
|
|
||||||
<span class="text-danger">
|
|
||||||
This permission is not available for your account.
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
<span class="form-text text-muted">@Model.PermissionValues[i].Description</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (hasStorePermission)
|
|
||||||
{
|
|
||||||
@if (Model.StoreMode == ManageController.AddApiKeyViewModel.ApiKeyStoreMode.AllStores)
|
|
||||||
{
|
{
|
||||||
<div class="list-group-item form-group">
|
continue;
|
||||||
<div class="form-check">
|
}
|
||||||
@if (Model.Strict)
|
@if (Policies.IsStorePolicy(Model.PermissionValues[i].Permission))
|
||||||
{
|
|
||||||
<input id="@Model.StoreManagementPermission.Permission" type="hidden" asp-for="StoreManagementPermission.Value" />
|
|
||||||
<input type="checkbox" checked="@Model.StoreManagementPermission.Value" disabled class="form-check-input" />
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<input id="@Model.StoreManagementPermission.Permission" type="checkbox" asp-for="StoreManagementPermission.Value" class="form-check-input" />
|
|
||||||
}
|
|
||||||
<label for="@Model.StoreManagementPermission.Permission" class="h5 form-check-label">@Model.StoreManagementPermission.Title</label>
|
|
||||||
@if (Model.SelectiveStores)
|
|
||||||
{
|
|
||||||
<button type="submit" class="btn btn-link" name="command" value="change-store-mode">select specific stores...</button>
|
|
||||||
}
|
|
||||||
<br />
|
|
||||||
<span asp-validation-for="StoreManagementPermission" class="text-danger"></span>
|
|
||||||
<span class="form-text text-muted">@Model.StoreManagementPermission.Description</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
else if (Model.StoreMode == ManageController.AddApiKeyViewModel.ApiKeyStoreMode.Specific)
|
|
||||||
{
|
{
|
||||||
<div class="list-group-item">
|
@if (Model.PermissionValues[i].StoreMode == ManageController.AddApiKeyViewModel.ApiKeyStoreMode.AllStores)
|
||||||
<h5 class="mb-1">@Model.StoreManagementSelectivePermission.Title</h5>
|
{
|
||||||
<span class="form-text text-muted">@Model.StoreManagementSelectivePermission.Description</span>
|
<div class="list-group-item form-group">
|
||||||
<button type="submit" class="btn btn-link" name="command" value="change-store-mode">Give permission to all stores instead</button>
|
<div class="form-check">
|
||||||
</div>
|
@if (Model.Strict || Model.PermissionValues[i].Forbidden)
|
||||||
@if (!Model.Stores.Any())
|
{
|
||||||
|
<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"/>
|
||||||
|
}
|
||||||
|
<label for="@Model.PermissionValues[i].Permission" class="h5 form-check-label">@Model.PermissionValues[i].Title</label>
|
||||||
|
@if (Model.SelectiveStores)
|
||||||
|
{
|
||||||
|
<button type="submit" class="btn btn-link" name="command" value="@($"{Model.PermissionValues[i].Permission}:change-store-mode")">select specific stores...</button>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (Model.PermissionValues[i].Forbidden)
|
||||||
|
{
|
||||||
|
<br/>
|
||||||
|
<span class="text-danger">
|
||||||
|
This permission is not available for your account.
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
<span asp-validation-for="PermissionValues[i].Value" class="text-danger"></span>
|
||||||
|
<span class="form-text text-muted">@Model.PermissionValues[i].Description</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else if (Model.SelectiveStores)
|
||||||
|
{
|
||||||
|
<div class="list-group-item ">
|
||||||
|
<h5 class="mb-1">@Model.PermissionValues[i].Title</h5>
|
||||||
|
<span class="form-text text-muted">@Model.PermissionValues[i].Description</span>
|
||||||
|
<button type="submit" class="btn btn-link" name="command" value="@($"{Model.PermissionValues[i].Permission}:change-store-mode")">Give permission to all stores instead</button>
|
||||||
|
</div>
|
||||||
|
@if (!Model.Stores.Any())
|
||||||
{
|
{
|
||||||
<div class="list-group-item alert-warning">
|
<div class="list-group-item alert-warning">
|
||||||
You currently have no stores configured.
|
You currently have no stores configured.
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@for (var index = 0; index < Model.SpecificStores.Count; index++)
|
@for (var index = 0; index < Model.PermissionValues[i].SpecificStores.Count; index++)
|
||||||
{
|
{
|
||||||
<div class="list-group-item transaction-output-form p-0 pl-lg-2">
|
<div class="list-group-item transaction-output-form p-0 pl-lg-2">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12 col-md-12 col-lg-10 py-2 ">
|
<div class="col-sm-12 col-md-12 col-lg-10 py-2 ">
|
||||||
<div class="form-group my-0">
|
<div class="form-group my-0">
|
||||||
@if (Model.SpecificStores[index] == null)
|
@if (Model.PermissionValues[i].SpecificStores[index] == null)
|
||||||
{
|
{
|
||||||
<select asp-for="SpecificStores[index]" class="form-control" asp-items="@(new SelectList(Model.Stores.Where(data => !Model.SpecificStores.Contains(data.Id)), nameof(StoreData.Id), nameof(StoreData.StoreName)))"></select>
|
<select asp-for="PermissionValues[i].SpecificStores[index]" class="form-control" asp-items="@(new SelectList(Model.Stores.Where(data => !Model.PermissionValues[i].SpecificStores.Contains(data.Id)), nameof(StoreData.Id), nameof(StoreData.StoreName)))"></select>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var store = Model.Stores.SingleOrDefault(data => data.Id == Model.SpecificStores[index]);
|
var store = Model.Stores.SingleOrDefault(data => data.Id == Model.PermissionValues[i].SpecificStores[index]);
|
||||||
<select asp-for="SpecificStores[index]" class="form-control" asp-items="@(new SelectList(new[] {store}, nameof(StoreData.Id), nameof(StoreData.StoreName), store.Id))"></select>
|
<select asp-for="PermissionValues[i].SpecificStores[index]" class="form-control" asp-items="@(new SelectList(new[] {store}, nameof(StoreData.Id), nameof(StoreData.StoreName), store.Id))"></select>
|
||||||
}
|
}
|
||||||
|
|
||||||
<span asp-validation-for="SpecificStores[index]" class="text-danger"></span>
|
<span asp-validation-for="PermissionValues[i].SpecificStores[index]" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-12 col-md-12 col-lg-2 pull-right">
|
||||||
|
<button type="submit" title="Remove Store Permission" name="command" value="@($"{Model.PermissionValues[i].Permission}:remove-store:{index}")"
|
||||||
|
class="d-block d-lg-none d-xl-none btn btn-danger mb-2 ml-2">
|
||||||
|
Remove
|
||||||
|
</button>
|
||||||
|
<button type="submit" title="Remove Store Permission" name="command" value="@($"{Model.PermissionValues[i].Permission}:remove-store:{index}")"
|
||||||
|
class="d-none d-lg-block remove-btn text-decoration-none h-100 align-middle btn text-danger btn-link fa fa-times rounded-0 pull-right">
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (Model.PermissionValues[i].SpecificStores.Count < Model.Stores.Length)
|
||||||
|
{
|
||||||
|
<div class="list-group-item">
|
||||||
|
<button type="submit" name="command" value="@($"{Model.PermissionValues[i].Permission}:add-store")" class="ml-1 btn btn-secondary">Add another store </button>
|
||||||
|
</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"/>
|
||||||
|
}
|
||||||
|
<label for="@Model.PermissionValues[i].Permission" class="h5 form-check-label">@Model.PermissionValues[i].Title</label>
|
||||||
|
@if (Model.PermissionValues[i].Forbidden)
|
||||||
|
{
|
||||||
|
<br/>
|
||||||
|
<span class="text-danger">
|
||||||
|
This permission is not available for your account.
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
<span asp-validation-for="PermissionValues[i].Value" class="text-danger"></span>
|
||||||
|
<span class="form-text text-muted">@Model.PermissionValues[i].Description</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-12 col-md-12 col-lg-2 pull-right">
|
|
||||||
<button type="submit" title="Remove Store Permission" name="command" value="@($"remove-store:{index}")"
|
|
||||||
class="d-block d-lg-none d-xl-none btn btn-danger mb-2 ml-2">
|
|
||||||
Remove
|
|
||||||
</button>
|
|
||||||
<button type="submit" title="Remove Store Permission" name="command" value="@($"remove-store:{index}")"
|
|
||||||
class="d-none d-lg-block remove-btn text-decoration-none h-100 align-middle btn text-danger btn-link fa fa-times rounded-0 pull-right">
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (Model.SpecificStores.Count < Model.Stores.Length)
|
|
||||||
{
|
|
||||||
<div class="list-group-item">
|
|
||||||
<button type="submit" name="command" value="add-store" class="ml-1 btn btn-secondary">Add another store </button>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user