2017-09-15 18:15:17 +02:00
|
|
|
|
using BTCPayServer.Models;
|
|
|
|
|
using BTCPayServer.Models.ServerViewModels;
|
2017-09-27 07:18:09 +02:00
|
|
|
|
using BTCPayServer.Services;
|
|
|
|
|
using BTCPayServer.Services.Mails;
|
2018-04-14 15:35:52 +02:00
|
|
|
|
using BTCPayServer.Services.Rates;
|
2017-09-27 07:18:09 +02:00
|
|
|
|
using BTCPayServer.Validations;
|
2017-09-15 18:20:57 +02:00
|
|
|
|
using Microsoft.AspNetCore.Authorization;
|
2017-09-15 18:15:17 +02:00
|
|
|
|
using Microsoft.AspNetCore.Identity;
|
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2017-09-27 07:18:09 +02:00
|
|
|
|
using System.ComponentModel.DataAnnotations;
|
2017-09-15 18:15:17 +02:00
|
|
|
|
using System.Linq;
|
2017-09-27 07:18:09 +02:00
|
|
|
|
using System.Net;
|
2018-04-14 15:35:52 +02:00
|
|
|
|
using System.Net.Http;
|
2017-09-27 07:18:09 +02:00
|
|
|
|
using System.Net.Mail;
|
2017-09-15 18:15:17 +02:00
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
namespace BTCPayServer.Controllers
|
|
|
|
|
{
|
2017-10-27 10:53:04 +02:00
|
|
|
|
[Authorize(Roles = Roles.ServerAdmin)]
|
|
|
|
|
public class ServerController : Controller
|
|
|
|
|
{
|
|
|
|
|
private UserManager<ApplicationUser> _UserManager;
|
|
|
|
|
SettingsRepository _SettingsRepository;
|
2017-09-15 18:15:17 +02:00
|
|
|
|
|
2018-04-14 15:35:52 +02:00
|
|
|
|
public ServerController(UserManager<ApplicationUser> userManager,
|
|
|
|
|
IRateProviderFactory rateProviderFactory,
|
|
|
|
|
SettingsRepository settingsRepository)
|
2017-10-27 10:53:04 +02:00
|
|
|
|
{
|
|
|
|
|
_UserManager = userManager;
|
|
|
|
|
_SettingsRepository = settingsRepository;
|
2018-04-14 15:35:52 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Route("server/rates")]
|
|
|
|
|
public async Task<IActionResult> Rates()
|
|
|
|
|
{
|
|
|
|
|
var rates = (await _SettingsRepository.GetSettingAsync<RatesSetting>()) ?? new RatesSetting();
|
|
|
|
|
return View(new RatesViewModel()
|
|
|
|
|
{
|
|
|
|
|
CacheMinutes = rates.CacheInMinutes,
|
|
|
|
|
PrivateKey = rates.PrivateKey,
|
|
|
|
|
PublicKey = rates.PublicKey
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Route("server/rates")]
|
|
|
|
|
[HttpPost]
|
|
|
|
|
public async Task<IActionResult> Rates(RatesViewModel vm)
|
|
|
|
|
{
|
|
|
|
|
var rates = (await _SettingsRepository.GetSettingAsync<RatesSetting>()) ?? new RatesSetting();
|
|
|
|
|
rates.PrivateKey = vm.PrivateKey;
|
|
|
|
|
rates.PublicKey = vm.PublicKey;
|
|
|
|
|
rates.CacheInMinutes = vm.CacheMinutes;
|
|
|
|
|
try
|
|
|
|
|
{
|
2018-04-18 09:07:16 +02:00
|
|
|
|
var settings = new CoinAverageSettings()
|
|
|
|
|
{
|
|
|
|
|
KeyPair = (vm.PublicKey, vm.PrivateKey)
|
|
|
|
|
};
|
|
|
|
|
if (settings.GetCoinAverageSignature() != null)
|
2018-04-14 15:35:52 +02:00
|
|
|
|
{
|
|
|
|
|
await new CoinAverageRateProvider("BTC")
|
2018-04-18 09:07:16 +02:00
|
|
|
|
{ Authenticator = settings }.TestAuthAsync();
|
2018-04-14 15:35:52 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
ModelState.AddModelError(nameof(vm.PrivateKey), "Invalid API key pair");
|
|
|
|
|
}
|
|
|
|
|
if (!ModelState.IsValid)
|
|
|
|
|
return View(vm);
|
|
|
|
|
await _SettingsRepository.UpdateSetting(rates);
|
|
|
|
|
StatusMessage = "Rate settings successfully updated";
|
|
|
|
|
return RedirectToAction(nameof(Rates));
|
2017-10-27 10:53:04 +02:00
|
|
|
|
}
|
2017-09-15 18:15:17 +02:00
|
|
|
|
|
2017-10-27 10:53:04 +02:00
|
|
|
|
[Route("server/users")]
|
|
|
|
|
public IActionResult ListUsers()
|
|
|
|
|
{
|
|
|
|
|
var users = new UsersViewModel();
|
2017-12-04 06:39:02 +01:00
|
|
|
|
users.StatusMessage = StatusMessage;
|
2017-10-27 10:53:04 +02:00
|
|
|
|
users.Users
|
|
|
|
|
= _UserManager.Users.Select(u => new UsersViewModel.UserViewModel()
|
|
|
|
|
{
|
|
|
|
|
Name = u.UserName,
|
2017-12-04 06:39:02 +01:00
|
|
|
|
Email = u.Email,
|
|
|
|
|
Id = u.Id
|
2017-10-27 10:53:04 +02:00
|
|
|
|
}).ToList();
|
|
|
|
|
return View(users);
|
|
|
|
|
}
|
2017-09-27 07:18:09 +02:00
|
|
|
|
|
2018-03-22 11:55:14 +01:00
|
|
|
|
[Route("server/users/{userId}")]
|
|
|
|
|
public new async Task<IActionResult> User(string userId)
|
|
|
|
|
{
|
|
|
|
|
var user = await _UserManager.FindByIdAsync(userId);
|
|
|
|
|
if (user == null)
|
|
|
|
|
return NotFound();
|
|
|
|
|
var roles = await _UserManager.GetRolesAsync(user);
|
|
|
|
|
var userVM = new UserViewModel();
|
|
|
|
|
userVM.Id = user.Id;
|
|
|
|
|
userVM.IsAdmin = IsAdmin(roles);
|
|
|
|
|
return View(userVM);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static bool IsAdmin(IList<string> roles)
|
|
|
|
|
{
|
|
|
|
|
return roles.Contains(Roles.ServerAdmin, StringComparer.Ordinal);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Route("server/users/{userId}")]
|
|
|
|
|
[HttpPost]
|
|
|
|
|
public new async Task<IActionResult> User(string userId, UserViewModel viewModel)
|
|
|
|
|
{
|
|
|
|
|
var user = await _UserManager.FindByIdAsync(userId);
|
|
|
|
|
if (user == null)
|
|
|
|
|
return NotFound();
|
|
|
|
|
var roles = await _UserManager.GetRolesAsync(user);
|
|
|
|
|
var isAdmin = IsAdmin(roles);
|
|
|
|
|
bool updated = false;
|
|
|
|
|
|
2018-04-14 15:35:52 +02:00
|
|
|
|
if (isAdmin != viewModel.IsAdmin)
|
2018-03-22 11:55:14 +01:00
|
|
|
|
{
|
|
|
|
|
if (viewModel.IsAdmin)
|
|
|
|
|
await _UserManager.AddToRoleAsync(user, Roles.ServerAdmin);
|
|
|
|
|
else
|
|
|
|
|
await _UserManager.RemoveFromRoleAsync(user, Roles.ServerAdmin);
|
|
|
|
|
updated = true;
|
|
|
|
|
}
|
2018-04-14 15:35:52 +02:00
|
|
|
|
if (updated)
|
2018-03-22 11:55:14 +01:00
|
|
|
|
{
|
|
|
|
|
viewModel.StatusMessage = "User successfully updated";
|
|
|
|
|
}
|
|
|
|
|
return View(viewModel);
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-04 06:39:02 +01:00
|
|
|
|
|
|
|
|
|
[Route("server/users/{userId}/delete")]
|
|
|
|
|
public async Task<IActionResult> DeleteUser(string userId)
|
|
|
|
|
{
|
|
|
|
|
var user = userId == null ? null : await _UserManager.FindByIdAsync(userId);
|
|
|
|
|
if (user == null)
|
|
|
|
|
return NotFound();
|
|
|
|
|
return View("Confirm", new ConfirmModel()
|
|
|
|
|
{
|
|
|
|
|
Title = "Delete user " + user.Email,
|
|
|
|
|
Description = "This user will be permanently deleted",
|
|
|
|
|
Action = "Delete"
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Route("server/users/{userId}/delete")]
|
|
|
|
|
[HttpPost]
|
|
|
|
|
public async Task<IActionResult> DeleteUserPost(string userId)
|
|
|
|
|
{
|
|
|
|
|
var user = userId == null ? null : await _UserManager.FindByIdAsync(userId);
|
|
|
|
|
if (user == null)
|
|
|
|
|
return NotFound();
|
|
|
|
|
await _UserManager.DeleteAsync(user);
|
|
|
|
|
StatusMessage = "User deleted";
|
|
|
|
|
return RedirectToAction(nameof(ListUsers));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[TempData]
|
|
|
|
|
public string StatusMessage
|
|
|
|
|
{
|
|
|
|
|
get; set;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-27 10:53:04 +02:00
|
|
|
|
[Route("server/emails")]
|
|
|
|
|
public async Task<IActionResult> Emails()
|
|
|
|
|
{
|
|
|
|
|
var data = (await _SettingsRepository.GetSettingAsync<EmailSettings>()) ?? new EmailSettings();
|
|
|
|
|
return View(new EmailsViewModel() { Settings = data });
|
|
|
|
|
}
|
2017-09-27 07:18:09 +02:00
|
|
|
|
|
2017-10-27 10:53:04 +02:00
|
|
|
|
[Route("server/policies")]
|
|
|
|
|
public async Task<IActionResult> Policies()
|
|
|
|
|
{
|
|
|
|
|
var data = (await _SettingsRepository.GetSettingAsync<PoliciesSettings>()) ?? new PoliciesSettings();
|
|
|
|
|
return View(data);
|
|
|
|
|
}
|
|
|
|
|
[Route("server/policies")]
|
|
|
|
|
[HttpPost]
|
|
|
|
|
public async Task<IActionResult> Policies(PoliciesSettings settings)
|
|
|
|
|
{
|
|
|
|
|
await _SettingsRepository.UpdateSetting(settings);
|
|
|
|
|
TempData["StatusMessage"] = "Policies upadated successfully";
|
|
|
|
|
return View(settings);
|
|
|
|
|
}
|
2017-09-27 07:18:09 +02:00
|
|
|
|
|
2017-10-27 10:53:04 +02:00
|
|
|
|
[Route("server/emails")]
|
|
|
|
|
[HttpPost]
|
|
|
|
|
public async Task<IActionResult> Emails(EmailsViewModel model, string command)
|
|
|
|
|
{
|
|
|
|
|
if (command == "Test")
|
|
|
|
|
{
|
|
|
|
|
if (!ModelState.IsValid)
|
|
|
|
|
return View(model);
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var client = model.Settings.CreateSmtpClient();
|
|
|
|
|
await client.SendMailAsync(model.Settings.From, model.TestEmail, "BTCPay test", "BTCPay test");
|
|
|
|
|
model.StatusMessage = "Email sent to " + model.TestEmail + ", please, verify you received it";
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
model.StatusMessage = "Error: " + ex.Message;
|
|
|
|
|
}
|
|
|
|
|
return View(model);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ModelState.Remove(nameof(model.TestEmail));
|
|
|
|
|
if (!ModelState.IsValid)
|
|
|
|
|
return View(model);
|
|
|
|
|
await _SettingsRepository.UpdateSetting(model.Settings);
|
|
|
|
|
model.StatusMessage = "Email settings saved";
|
|
|
|
|
return View(model);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-09-15 18:15:17 +02:00
|
|
|
|
}
|