Refactor authorizations

This commit is contained in:
nicolas.dorier
2019-10-12 20:35:30 +09:00
parent bd94b5f84e
commit 281a2461ad
55 changed files with 732 additions and 646 deletions

View File

@@ -39,8 +39,8 @@ using IWebHostEnvironment = Microsoft.AspNetCore.Hosting.IHostingEnvironment;
namespace BTCPayServer.Controllers
{
[Route("stores")]
[Authorize(AuthenticationSchemes = Policies.CookieAuthentication)]
[Authorize(Policy = Policies.CanModifyStoreSettings.Key, AuthenticationSchemes = Policies.CookieAuthentication)]
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[Authorize(Policy = Policies.CanModifyStoreSettings.Key, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[AutoValidateAntiforgeryToken]
public partial class StoresController : Controller
{
@@ -124,8 +124,8 @@ namespace BTCPayServer.Controllers
private async Task FillUsers(StoreUsersViewModel vm)
{
var users = await _Repo.GetStoreUsers(StoreData.Id);
vm.StoreId = StoreData.Id;
var users = await _Repo.GetStoreUsers(CurrentStore.Id);
vm.StoreId = CurrentStore.Id;
vm.Users = users.Select(u => new StoreUsersViewModel.StoreUserViewModel()
{
Email = u.Email,
@@ -134,7 +134,7 @@ namespace BTCPayServer.Controllers
}).ToList();
}
public StoreData StoreData
public StoreData CurrentStore
{
get
{
@@ -163,7 +163,7 @@ namespace BTCPayServer.Controllers
ModelState.AddModelError(nameof(vm.Role), "Invalid role");
return View(vm);
}
if (!await _Repo.AddStoreUser(StoreData.Id, user.Id, vm.Role))
if (!await _Repo.AddStoreUser(CurrentStore.Id, user.Id, vm.Role))
{
ModelState.AddModelError(nameof(vm.Email), "The user already has access to this store");
return View(vm);
@@ -199,13 +199,13 @@ namespace BTCPayServer.Controllers
[HttpGet]
[Route("{storeId}/rates")]
public IActionResult Rates(string storeId)
public IActionResult Rates()
{
var storeBlob = StoreData.GetStoreBlob();
var storeBlob = CurrentStore.GetStoreBlob();
var vm = new RatesViewModel();
vm.SetExchangeRates(GetSupportedExchanges(), storeBlob.PreferredExchange ?? CoinAverageRateProvider.CoinAverageName);
vm.Spread = (double)(storeBlob.Spread * 100m);
vm.StoreId = storeId;
vm.StoreId = CurrentStore.Id;
vm.Script = storeBlob.GetRateRules(_NetworkProvider).ToString();
vm.DefaultScript = storeBlob.GetDefaultRateRules(_NetworkProvider).ToString();
vm.AvailableExchanges = GetSupportedExchanges();
@@ -239,7 +239,7 @@ namespace BTCPayServer.Controllers
if (model.PreferredExchange != null)
model.PreferredExchange = model.PreferredExchange.Trim().ToLowerInvariant();
var blob = StoreData.GetStoreBlob();
var blob = CurrentStore.GetStoreBlob();
model.DefaultScript = blob.GetDefaultRateRules(_NetworkProvider).ToString();
model.AvailableExchanges = GetSupportedExchanges();
@@ -311,14 +311,14 @@ namespace BTCPayServer.Controllers
}
else // command == Save
{
if (StoreData.SetStoreBlob(blob))
if (CurrentStore.SetStoreBlob(blob))
{
await _Repo.UpdateStore(StoreData);
await _Repo.UpdateStore(CurrentStore);
StatusMessage = "Rate settings updated";
}
return RedirectToAction(nameof(Rates), new
{
storeId = StoreData.Id
storeId = CurrentStore.Id
});
}
}
@@ -342,22 +342,22 @@ namespace BTCPayServer.Controllers
[Route("{storeId}/rates/confirm")]
public async Task<IActionResult> ShowRateRulesPost(bool scripting)
{
var blob = StoreData.GetStoreBlob();
var blob = CurrentStore.GetStoreBlob();
blob.RateScripting = scripting;
blob.RateScript = blob.GetDefaultRateRules(_NetworkProvider).ToString();
StoreData.SetStoreBlob(blob);
await _Repo.UpdateStore(StoreData);
CurrentStore.SetStoreBlob(blob);
await _Repo.UpdateStore(CurrentStore);
StatusMessage = "Rate rules scripting activated";
return RedirectToAction(nameof(Rates), new { storeId = StoreData.Id });
return RedirectToAction(nameof(Rates), new { storeId = CurrentStore.Id });
}
[HttpGet]
[Route("{storeId}/checkout")]
public IActionResult CheckoutExperience()
{
var storeBlob = StoreData.GetStoreBlob();
var storeBlob = CurrentStore.GetStoreBlob();
var vm = new CheckoutExperienceViewModel();
SetCryptoCurrencies(vm, StoreData);
SetCryptoCurrencies(vm, CurrentStore);
vm.CustomCSS = storeBlob.CustomCSS?.AbsoluteUri;
vm.CustomLogo = storeBlob.CustomLogo?.AbsoluteUri;
vm.HtmlTitle = storeBlob.HtmlTitle;
@@ -402,14 +402,14 @@ namespace BTCPayServer.Controllers
}
}
bool needUpdate = false;
var blob = StoreData.GetStoreBlob();
var blob = CurrentStore.GetStoreBlob();
var defaultPaymentMethodId = model.DefaultPaymentMethod == null ? null : PaymentMethodId.Parse(model.DefaultPaymentMethod);
if (StoreData.GetDefaultPaymentId(_NetworkProvider) != defaultPaymentMethodId)
if (CurrentStore.GetDefaultPaymentId(_NetworkProvider) != defaultPaymentMethodId)
{
needUpdate = true;
StoreData.SetDefaultPaymentId(defaultPaymentMethodId);
CurrentStore.SetDefaultPaymentId(defaultPaymentMethodId);
}
SetCryptoCurrencies(model, StoreData);
SetCryptoCurrencies(model, CurrentStore);
model.SetLanguages(_LangService, model.DefaultLang);
if (!ModelState.IsValid)
@@ -425,19 +425,19 @@ namespace BTCPayServer.Controllers
blob.LightningMaxValue = lightningMaxValue;
blob.LightningAmountInSatoshi = model.LightningAmountInSatoshi;
blob.RedirectAutomatically = model.RedirectAutomatically;
if (StoreData.SetStoreBlob(blob))
if (CurrentStore.SetStoreBlob(blob))
{
needUpdate = true;
}
if (needUpdate)
{
await _Repo.UpdateStore(StoreData);
await _Repo.UpdateStore(CurrentStore);
StatusMessage = "Store successfully updated";
}
return RedirectToAction(nameof(CheckoutExperience), new
{
storeId = StoreData.Id
storeId = CurrentStore.Id
});
}
@@ -529,23 +529,23 @@ namespace BTCPayServer.Controllers
public async Task<IActionResult> UpdateStore(StoreViewModel model, string command = null)
{
bool needUpdate = false;
if (StoreData.SpeedPolicy != model.SpeedPolicy)
if (CurrentStore.SpeedPolicy != model.SpeedPolicy)
{
needUpdate = true;
StoreData.SpeedPolicy = model.SpeedPolicy;
CurrentStore.SpeedPolicy = model.SpeedPolicy;
}
if (StoreData.StoreName != model.StoreName)
if (CurrentStore.StoreName != model.StoreName)
{
needUpdate = true;
StoreData.StoreName = model.StoreName;
CurrentStore.StoreName = model.StoreName;
}
if (StoreData.StoreWebsite != model.StoreWebsite)
if (CurrentStore.StoreWebsite != model.StoreWebsite)
{
needUpdate = true;
StoreData.StoreWebsite = model.StoreWebsite;
CurrentStore.StoreWebsite = model.StoreWebsite;
}
var blob = StoreData.GetStoreBlob();
var blob = CurrentStore.GetStoreBlob();
blob.AnyoneCanInvoice = model.AnyoneCanCreateInvoice;
blob.NetworkFeeMode = model.NetworkFeeMode;
blob.MonitoringExpiration = model.MonitoringExpiration;
@@ -553,20 +553,20 @@ namespace BTCPayServer.Controllers
blob.LightningDescriptionTemplate = model.LightningDescriptionTemplate ?? string.Empty;
blob.PaymentTolerance = model.PaymentTolerance;
if (StoreData.SetStoreBlob(blob))
if (CurrentStore.SetStoreBlob(blob))
{
needUpdate = true;
}
if (needUpdate)
{
await _Repo.UpdateStore(StoreData);
await _Repo.UpdateStore(CurrentStore);
StatusMessage = "Store successfully updated";
}
return RedirectToAction(nameof(UpdateStore), new
{
storeId = StoreData.Id
storeId = CurrentStore.Id
});
}
@@ -588,7 +588,7 @@ namespace BTCPayServer.Controllers
[Route("{storeId}/delete")]
public async Task<IActionResult> DeleteStorePost(string storeId)
{
await _Repo.DeleteStore(StoreData.Id);
await _Repo.DeleteStore(CurrentStore.Id);
StatusMessage = "Success: Store successfully deleted";
return RedirectToAction(nameof(UserStoresController.ListStores), "UserStores");
}
@@ -614,7 +614,7 @@ namespace BTCPayServer.Controllers
public async Task<IActionResult> ListTokens()
{
var model = new TokensViewModel();
var tokens = await _TokenRepository.GetTokensByStoreIdAsync(StoreData.Id);
var tokens = await _TokenRepository.GetTokensByStoreIdAsync(CurrentStore.Id);
model.StatusMessage = StatusMessage;
model.StoreNotConfigured = StoreNotConfigured;
model.Tokens = tokens.Select(t => new TokenViewModel()
@@ -624,7 +624,7 @@ namespace BTCPayServer.Controllers
Id = t.Value
}).ToArray();
model.ApiKey = (await _TokenRepository.GetLegacyAPIKeys(StoreData.Id)).FirstOrDefault();
model.ApiKey = (await _TokenRepository.GetLegacyAPIKeys(CurrentStore.Id)).FirstOrDefault();
if (model.ApiKey == null)
model.EncodedApiKey = "*API Key*";
else
@@ -637,7 +637,7 @@ namespace BTCPayServer.Controllers
public async Task<IActionResult> RevokeToken(string tokenId)
{
var token = await _TokenRepository.GetToken(tokenId);
if (token == null || token.StoreId != StoreData.Id)
if (token == null || token.StoreId != CurrentStore.Id)
return NotFound();
return View("Confirm", new ConfirmModel()
{
@@ -653,7 +653,7 @@ namespace BTCPayServer.Controllers
{
var token = await _TokenRepository.GetToken(tokenId);
if (token == null ||
token.StoreId != StoreData.Id ||
token.StoreId != CurrentStore.Id ||
!await _TokenRepository.DeleteToken(tokenId))
StatusMessage = "Failure to revoke this token";
else
@@ -666,7 +666,7 @@ namespace BTCPayServer.Controllers
public async Task<IActionResult> ShowToken(string tokenId)
{
var token = await _TokenRepository.GetToken(tokenId);
if (token == null || token.StoreId != StoreData.Id)
if (token == null || token.StoreId != CurrentStore.Id)
return NotFound();
return View(token);
}
@@ -674,7 +674,6 @@ namespace BTCPayServer.Controllers
[HttpPost]
[Route("/api-tokens")]
[Route("{storeId}/Tokens/Create")]
[AllowAnonymous]
public async Task<IActionResult> CreateToken(CreateTokenViewModel model)
{
if (!ModelState.IsValid)
@@ -684,23 +683,17 @@ namespace BTCPayServer.Controllers
model.Label = model.Label ?? String.Empty;
var userId = GetUserId();
if (userId == null)
return Challenge(Policies.CookieAuthentication);
return Challenge(AuthenticationSchemes.Cookie);
var store = StoreData;
var storeId = StoreData?.Id;
var store = CurrentStore;
var storeId = CurrentStore?.Id;
if (storeId == null)
{
storeId = model.StoreId;
store = await _Repo.FindStore(storeId, userId);
if (store == null)
return Challenge(Policies.CookieAuthentication);
return Challenge(AuthenticationSchemes.Cookie);
}
if (!store.HasClaim(Policies.CanModifyStoreSettings.Key))
{
return Challenge(Policies.CookieAuthentication);
}
var tokenRequest = new TokenRequest()
{
Label = model.Label,
@@ -737,20 +730,12 @@ namespace BTCPayServer.Controllers
[HttpGet]
[Route("/api-tokens")]
[Route("{storeId}/Tokens/Create")]
[AllowAnonymous]
public async Task<IActionResult> CreateToken()
{
var userId = GetUserId();
if (string.IsNullOrWhiteSpace(userId))
return Challenge(Policies.CookieAuthentication);
var storeId = StoreData?.Id;
if (StoreData != null)
{
if (!StoreData.HasClaim(Policies.CanModifyStoreSettings.Key))
{
return Challenge(Policies.CookieAuthentication);
}
}
return Challenge(AuthenticationSchemes.Cookie);
var storeId = CurrentStore?.Id;
var model = new CreateTokenViewModel();
ViewBag.HidePublicKey = storeId == null;
ViewBag.ShowStores = storeId == null;
@@ -759,7 +744,7 @@ namespace BTCPayServer.Controllers
if (storeId == null)
{
var stores = await _Repo.GetStoresByUserId(userId);
model.Stores = new SelectList(stores.Where(s => s.HasClaim(Policies.CanModifyStoreSettings.Key)), nameof(StoreData.Id), nameof(StoreData.StoreName), storeId);
model.Stores = new SelectList(stores.Where(s => s.Role == StoreRoles.Owner), nameof(CurrentStore.Id), nameof(CurrentStore.StoreName), storeId);
if (model.Stores.Count() == 0)
{
StatusMessage = "Error: You need to be owner of at least one store before pairing";
@@ -776,7 +761,7 @@ namespace BTCPayServer.Controllers
var store = HttpContext.GetStoreData();
if (store == null)
return NotFound();
await _TokenRepository.GenerateLegacyAPIKey(StoreData.Id);
await _TokenRepository.GenerateLegacyAPIKey(CurrentStore.Id);
StatusMessage = "API Key re-generated";
return RedirectToAction(nameof(ListTokens));
}
@@ -788,7 +773,7 @@ namespace BTCPayServer.Controllers
{
var userId = GetUserId();
if (userId == null)
return Challenge(Policies.CookieAuthentication);
return Challenge(AuthenticationSchemes.Cookie);
if (pairingCode == null)
return NotFound();
var pairing = await _TokenRepository.GetPairingAsync(pairingCode);
@@ -805,8 +790,8 @@ namespace BTCPayServer.Controllers
Id = pairing.Id,
Label = pairing.Label,
SIN = pairing.SIN ?? "Server-Initiated Pairing",
SelectedStore = selectedStore ?? stores.FirstOrDefault()?.Id,
Stores = stores.Where(u => u.HasClaim(Policies.CanModifyStoreSettings.Key)).Select(s => new PairingModel.StoreViewModel()
StoreId = selectedStore ?? stores.FirstOrDefault()?.Id,
Stores = stores.Where(u => u.Role == StoreRoles.Owner).Select(s => new PairingModel.StoreViewModel()
{
Id = s.Id,
Name = string.IsNullOrEmpty(s.StoreName) ? s.Id : s.StoreName
@@ -817,24 +802,15 @@ namespace BTCPayServer.Controllers
[HttpPost]
[Route("/api-access-request")]
[AllowAnonymous]
public async Task<IActionResult> Pair(string pairingCode, string selectedStore)
public async Task<IActionResult> Pair(string pairingCode, string storeId)
{
if (pairingCode == null)
return NotFound();
var userId = GetUserId();
if (userId == null)
return Challenge(Policies.CookieAuthentication);
var store = await _Repo.FindStore(selectedStore, userId);
var store = CurrentStore;
var pairing = await _TokenRepository.GetPairingAsync(pairingCode);
if (store == null || pairing == null)
return NotFound();
if (!store.HasClaim(Policies.CanModifyStoreSettings.Key))
{
return Challenge(Policies.CookieAuthentication);
}
var pairingResult = await _TokenRepository.PairWithStoreAsync(pairingCode, store.Id);
if (pairingResult == PairingResult.Complete || pairingResult == PairingResult.Partial)
{
@@ -863,7 +839,7 @@ namespace BTCPayServer.Controllers
private string GetUserId()
{
if (User.Identity.AuthenticationType != Policies.CookieAuthentication)
if (User.Identity.AuthenticationType != AuthenticationSchemes.Cookie)
return null;
return _UserManager.GetUserId(User);
}
@@ -877,7 +853,7 @@ namespace BTCPayServer.Controllers
[Route("{storeId}/paybutton")]
public IActionResult PayButton()
{
var store = StoreData;
var store = CurrentStore;
var storeBlob = store.GetStoreBlob();
if (!storeBlob.AnyoneCanInvoice)
@@ -906,17 +882,17 @@ namespace BTCPayServer.Controllers
[Route("{storeId}/paybutton")]
public async Task<IActionResult> PayButton(bool enableStore)
{
var blob = StoreData.GetStoreBlob();
var blob = CurrentStore.GetStoreBlob();
blob.AnyoneCanInvoice = enableStore;
if (StoreData.SetStoreBlob(blob))
if (CurrentStore.SetStoreBlob(blob))
{
await _Repo.UpdateStore(StoreData);
await _Repo.UpdateStore(CurrentStore);
StatusMessage = "Store successfully updated";
}
return RedirectToAction(nameof(PayButton), new
{
storeId = StoreData.Id
storeId = CurrentStore.Id
});
}