mirror of
https://github.com/MAKS-IT-COM/maksit-certs-ui.git
synced 2025-12-30 19:50:07 +01:00
(refactor): webapi cache controller refactoring
This commit is contained in:
parent
bd67ad6a6b
commit
4000026b7a
2
src/ClientApp/.vscode/settings.json
vendored
2
src/ClientApp/.vscode/settings.json
vendored
@ -1,7 +1,7 @@
|
||||
{
|
||||
"editor.tabSize": 2,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
"source.fixAll.eslint": "explicit"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
enum ApiRoutes {
|
||||
CACHE_ACCOUNTS = 'api/cache/accounts',
|
||||
CACHE_ACCOUNT = 'api/cache/account/{accountId}',
|
||||
CACHE_ACCOUNT_CONTACTS = 'api/cache/account/{accountId}/contacts',
|
||||
CACHE_ACCOUNT_CONTACT = 'api/cache/account/{accountId}/contact/{index}',
|
||||
CACHE_ACCOUNT_HOSTNAMES = 'api/cache/account/{accountId}/hostnames'
|
||||
ACCOUNTS = 'api/accounts',
|
||||
ACCOUNT = 'api/account/{accountId}',
|
||||
ACCOUNT_CONTACTS = 'api/account/{accountId}/contacts',
|
||||
ACCOUNT_CONTACT = 'api/account/{accountId}/contact/{index}',
|
||||
ACCOUNT_HOSTNAMES = 'api/account/{accountId}/hostnames'
|
||||
|
||||
// CERTS_FLOW_CONFIGURE_CLIENT = `api/CertsFlow/ConfigureClient`,
|
||||
// CERTS_FLOW_TERMS_OF_SERVICE = `api/CertsFlow/TermsOfService/{sessionId}`,
|
||||
|
||||
@ -10,7 +10,7 @@ import {
|
||||
} from '@/hooks/useValidation'
|
||||
import { CustomButton, CustomInput } from '@/controls'
|
||||
import { TrashIcon, PlusIcon } from '@heroicons/react/24/solid'
|
||||
import { GetAccountResponse } from '@/models/letsEncryptServer/cache/responses/GetAccountResponse'
|
||||
import { GetAccountResponse } from '@/models/letsEncryptServer/account/responses/GetAccountResponse'
|
||||
import { deepCopy } from './functions'
|
||||
import { CacheAccount } from '@/entities/CacheAccount'
|
||||
|
||||
@ -50,18 +50,21 @@ export default function Page() {
|
||||
const fetchAccounts = async () => {
|
||||
const newAccounts: CacheAccount[] = []
|
||||
const accounts = await httpService.get<GetAccountResponse[]>(
|
||||
GetApiRoute(ApiRoutes.CACHE_ACCOUNTS)
|
||||
GetApiRoute(ApiRoutes.ACCOUNTS)
|
||||
)
|
||||
|
||||
accounts?.forEach((account) => {
|
||||
newAccounts.push({
|
||||
accountId: account.accountId,
|
||||
description: account.description,
|
||||
contacts: account.contacts,
|
||||
hostnames: account.hostnames.map((h) => ({
|
||||
hostname: h.hostname,
|
||||
expires: new Date(h.expires),
|
||||
isUpcomingExpire: h.isUpcomingExpire
|
||||
})),
|
||||
challengeType: account.challengeType,
|
||||
hostnames:
|
||||
account.hostnames?.map((h) => ({
|
||||
hostname: h.hostname,
|
||||
expires: new Date(h.expires),
|
||||
isUpcomingExpire: h.isUpcomingExpire
|
||||
})) ?? [],
|
||||
isEditMode: false
|
||||
})
|
||||
})
|
||||
@ -97,7 +100,7 @@ export default function Page() {
|
||||
|
||||
// TODO: Remove from cache
|
||||
httpService.delete(
|
||||
GetApiRoute(ApiRoutes.CACHE_ACCOUNT_CONTACT, accountId, contact)
|
||||
GetApiRoute(ApiRoutes.ACCOUNT_CONTACT, accountId, contact)
|
||||
)
|
||||
|
||||
setAccounts(
|
||||
@ -387,7 +390,9 @@ export default function Page() {
|
||||
) : (
|
||||
<>
|
||||
<div className="mb-4">
|
||||
<h3 className="text-xl font-medium mb-2">Description:</h3>
|
||||
<h3 className="text-xl font-medium mb-2">
|
||||
Description: {account.description}
|
||||
</h3>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<h3 className="text-xl font-medium mb-2">Contacts:</h3>
|
||||
@ -399,6 +404,11 @@ export default function Page() {
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<h3 className="text-xl font-medium mb-2">
|
||||
Challenge type: {account.challengeType}
|
||||
</h3>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-medium mb-2">Hostnames:</h3>
|
||||
<ul className="list-disc list-inside pl-4 mb-2">
|
||||
|
||||
@ -4,6 +4,7 @@ export interface CacheAccount {
|
||||
accountId: string
|
||||
description?: string
|
||||
contacts: string[]
|
||||
challengeType?: string
|
||||
hostnames: CacheAccountHostname[]
|
||||
isEditMode: boolean
|
||||
}
|
||||
|
||||
@ -2,6 +2,8 @@ import { HostnameResponse } from './HostnameResponse'
|
||||
|
||||
export interface GetAccountResponse {
|
||||
accountId: string
|
||||
description?: string
|
||||
contacts: string[]
|
||||
hostnames: HostnameResponse[]
|
||||
challengeType?: string
|
||||
hostnames?: HostnameResponse[]
|
||||
}
|
||||
@ -29,9 +29,10 @@ public class RegistrationCache {
|
||||
/// <summary>
|
||||
/// Field used to identify cache by account id
|
||||
/// </summary>
|
||||
public Guid AccountId { get; set; }
|
||||
public required Guid AccountId { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string[]? Contacts { get; set; }
|
||||
public required string[] Contacts { get; set; }
|
||||
public string? ChallengeType { get; set; }
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
@ -1,8 +1,13 @@
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using DomainResults.Common;
|
||||
|
||||
using MaksIT.LetsEncrypt.Entities;
|
||||
using MaksIT.LetsEncrypt.Exceptions;
|
||||
using MaksIT.Core.Extensions;
|
||||
@ -10,9 +15,6 @@ using MaksIT.LetsEncrypt.Models.Responses;
|
||||
using MaksIT.LetsEncrypt.Models.Interfaces;
|
||||
using MaksIT.LetsEncrypt.Models.Requests;
|
||||
using MaksIT.LetsEncrypt.Entities.Jws;
|
||||
using DomainResults.Common;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Security.Principal;
|
||||
|
||||
namespace MaksIT.LetsEncrypt.Services;
|
||||
|
||||
@ -230,6 +232,7 @@ public class LetsEncryptService : ILetsEncryptService {
|
||||
|
||||
var challenge = challengeResponse.Result.Challenges.First(x => x.Type == challengeType);
|
||||
state.Challenges.Add(challenge);
|
||||
state.Cache.ChallengeType = challengeType;
|
||||
|
||||
var keyToken = state.JwsService.GetKeyAuthorization(challenge.Token);
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ namespace MaksIT.LetsEncryptServer.BackgroundServices {
|
||||
|
||||
private readonly IOptions<Configuration> _appSettings;
|
||||
private readonly ILogger<AutoRenewal> _logger;
|
||||
private readonly ICacheInternalService _cacheService;
|
||||
private readonly ICacheService _cacheService;
|
||||
private readonly ICertsInternalService _certsFlowService;
|
||||
|
||||
public AutoRenewal(
|
||||
@ -61,7 +61,7 @@ namespace MaksIT.LetsEncryptServer.BackgroundServices {
|
||||
return IDomainResult.Success();
|
||||
}
|
||||
|
||||
var renewResult = await RenewCertificatesForHostnames(cache.AccountId, cache.Description, cache.Contacts, hostnames);
|
||||
var renewResult = await RenewCertificatesForHostnames(cache.AccountId, cache.Description, cache.Contacts, hostnames, cache.ChallengeType);
|
||||
if (!renewResult.IsSuccess)
|
||||
return renewResult;
|
||||
|
||||
@ -70,7 +70,7 @@ namespace MaksIT.LetsEncryptServer.BackgroundServices {
|
||||
return IDomainResult.Success();
|
||||
}
|
||||
|
||||
private async Task<IDomainResult> RenewCertificatesForHostnames(Guid accountId, string description, string[] contacts, string[] hostnames) {
|
||||
private async Task<IDomainResult> RenewCertificatesForHostnames(Guid accountId, string description, string[] contacts, string[] hostnames, string challengeType) {
|
||||
var (sessionId, configureClientResult) = await _certsFlowService.ConfigureClientAsync();
|
||||
if (!configureClientResult.IsSuccess || sessionId == null) {
|
||||
LogErrors(configureClientResult.Errors);
|
||||
@ -85,7 +85,7 @@ namespace MaksIT.LetsEncryptServer.BackgroundServices {
|
||||
return initResult;
|
||||
}
|
||||
|
||||
var (_, newOrderResult) = await _certsFlowService.NewOrderAsync(sessionIdValue, hostnames, "http-01");
|
||||
var (_, newOrderResult) = await _certsFlowService.NewOrderAsync(sessionIdValue, hostnames, challengeType);
|
||||
if (!newOrderResult.IsSuccess) {
|
||||
LogErrors(newOrderResult.Errors);
|
||||
return newOrderResult;
|
||||
|
||||
@ -3,89 +3,128 @@
|
||||
using DomainResults.Mvc;
|
||||
|
||||
using MaksIT.LetsEncryptServer.Services;
|
||||
using MaksIT.Models.LetsEncryptServer.Cache.Requests;
|
||||
using MaksIT.Models.LetsEncryptServer.Account.Requests;
|
||||
|
||||
namespace MaksIT.LetsEncryptServer.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/account")]
|
||||
[Route("api")]
|
||||
public class AccountController : ControllerBase {
|
||||
private readonly ICacheRestService _cacheService;
|
||||
private readonly ICertsFlowService _certsFlowService;
|
||||
private readonly IAccountRestService _accountService;
|
||||
|
||||
public AccountController(
|
||||
ICacheService cacheService,
|
||||
ICertsFlowService certsFlowService
|
||||
IAccountService accountService
|
||||
) {
|
||||
_cacheService = cacheService;
|
||||
_certsFlowService = certsFlowService;
|
||||
_accountService = accountService;
|
||||
}
|
||||
|
||||
#region Accounts
|
||||
|
||||
[HttpPost]
|
||||
[HttpGet("accounts")]
|
||||
public async Task<IActionResult> GetAccounts() {
|
||||
var result = await _accountService.GetAccountsAsync();
|
||||
return result.ToActionResult();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Account
|
||||
|
||||
[HttpPost("account")]
|
||||
public async Task<IActionResult> PostAccount([FromBody] PostAccountRequest requestData) {
|
||||
//var result = await _cacheService.PostAccountAsync(requestData);
|
||||
var result = await _accountService.PostAccountAsync(requestData);
|
||||
return result.ToActionResult();
|
||||
}
|
||||
|
||||
[HttpPut("account/{accountId:guid}")]
|
||||
public async Task<IActionResult> PutAccount(Guid accountId, [FromBody] PutAccountRequest requestData) {
|
||||
var result = await _accountService.PutAccountAsync(accountId, requestData);
|
||||
return result.ToActionResult();
|
||||
}
|
||||
|
||||
[HttpPatch("account/{accountId:guid}")]
|
||||
public async Task<IActionResult> PatchAccount(Guid accountId, [FromBody] PatchAccountRequest requestData) {
|
||||
var result = await _accountService.PatchAccountAsync(accountId, requestData);
|
||||
return result.ToActionResult();
|
||||
}
|
||||
|
||||
[HttpDelete("account/{accountd:guid}")]
|
||||
public async Task<IActionResult> DeleteAccount(Guid accountId) {
|
||||
var result = await _accountService.DeleteAccountAsync(accountId);
|
||||
return result.ToActionResult();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Account Contacts
|
||||
|
||||
[HttpGet("account/{accountId:guid}/contacts")]
|
||||
public async Task<IActionResult> GetContacts(Guid accountId) {
|
||||
var result = await _accountService.GetContactsAsync(accountId);
|
||||
return result.ToActionResult();
|
||||
}
|
||||
|
||||
[HttpPost("account/{accountId:guid}/contacts")]
|
||||
public async Task<IActionResult> PostContacts(Guid accountId, [FromBody] PostContactsRequest requestData) {
|
||||
//var result = await _accountService.PostContactsAsync(accountId, requestData);
|
||||
//return result.ToActionResult();
|
||||
|
||||
return BadRequest("Not implemented");
|
||||
}
|
||||
|
||||
[HttpPut("{accountId:guid}")]
|
||||
public async Task<IActionResult> PutAccount(Guid accountId, [FromBody] PutAccountRequest requestData) {
|
||||
var result = await _cacheService.PutAccountAsync(accountId, requestData);
|
||||
return result.ToActionResult();
|
||||
}
|
||||
|
||||
[HttpPatch("{accountId:guid}")]
|
||||
public async Task<IActionResult> PatchAccount(Guid accountId, [FromBody] PatchAccountRequest requestData) {
|
||||
var result = await _cacheService.PatchAccountAsync(accountId, requestData);
|
||||
return result.ToActionResult();
|
||||
}
|
||||
|
||||
[HttpDelete("{accountd:guid}")]
|
||||
public async Task<IActionResult> DeleteAccount(Guid accountId) {
|
||||
var result = await _cacheService.DeleteAccountAsync(accountId);
|
||||
return result.ToActionResult();
|
||||
}
|
||||
|
||||
#region Contacts
|
||||
|
||||
[HttpGet("{accountId:guid}/contacts")]
|
||||
public async Task<IActionResult> GetContacts(Guid accountId) {
|
||||
var result = await _cacheService.GetContactsAsync(accountId);
|
||||
return result.ToActionResult();
|
||||
}
|
||||
|
||||
[HttpPut("{accountId:guid}/contacts")]
|
||||
[HttpPut("account/{accountId:guid}/contacts")]
|
||||
public async Task<IActionResult> PutContacts(Guid accountId, [FromBody] PutContactsRequest requestData) {
|
||||
var result = await _cacheService.PutContactsAsync(accountId, requestData);
|
||||
var result = await _accountService.PutContactsAsync(accountId, requestData);
|
||||
return result.ToActionResult();
|
||||
}
|
||||
|
||||
[HttpPatch("{accountId:guid}/contacts")]
|
||||
[HttpPatch("account/{accountId:guid}/contacts")]
|
||||
public async Task<IActionResult> PatchContacts(Guid accountId, [FromBody] PatchContactsRequest requestData) {
|
||||
var result = await _cacheService.PatchContactsAsync(accountId, requestData);
|
||||
var result = await _accountService.PatchContactsAsync(accountId, requestData);
|
||||
return result.ToActionResult();
|
||||
}
|
||||
|
||||
[HttpDelete("{accountId:guid}/contact/{index:int}")]
|
||||
[HttpDelete("account/{accountId:guid}/contact/{index:int}")]
|
||||
public async Task<IActionResult> DeleteContact(Guid accountId, int index) {
|
||||
var result = await _cacheService.DeleteContactAsync(accountId, index);
|
||||
var result = await _accountService.DeleteContactAsync(accountId, index);
|
||||
return result.ToActionResult();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Hostnames
|
||||
#region Account Hostnames
|
||||
|
||||
[HttpGet("{accountId:guid}/hostnames")]
|
||||
public async Task<IActionResult> GetHostnames(Guid accountId) {
|
||||
var result = await _cacheService.GetHostnames(accountId);
|
||||
var result = await _accountService.GetHostnames(accountId);
|
||||
return result.ToActionResult();
|
||||
}
|
||||
|
||||
[HttpPost("{accountId:guid}")]
|
||||
[HttpPost("account/{accountId:guid}/hostnames")]
|
||||
public async Task<IActionResult> PostHostname(Guid accountId, [FromBody] PostHostnamesRequest requestData) {
|
||||
//var result = await _cacheService.PostHostnameAsync(accountId, requestData);
|
||||
//return result.ToActionResult();
|
||||
|
||||
[HttpDelete("{accountId:guid}/hostname/{index:int}")]
|
||||
return BadRequest("Not implemented");
|
||||
}
|
||||
|
||||
[HttpPut("account/{accountId:guid}/hostnames")]
|
||||
public async Task<IActionResult> PutHostname(Guid accountId, [FromBody] PutHostnamesRequest requestData) {
|
||||
//var result = await _cacheService.PutHostnameAsync(accountId, requestData);
|
||||
//return result.ToActionResult();
|
||||
|
||||
return BadRequest("Not implemented");
|
||||
}
|
||||
|
||||
[HttpPatch("account/{accountId:guid}/hostnames")]
|
||||
public async Task<IActionResult> PatchHostname(Guid accountId, [FromBody] PatchHostnamesRequest requestData) {
|
||||
//var result = await _cacheService.PatchHostnameAsync(accountId, requestData);
|
||||
//return result.ToActionResult();
|
||||
|
||||
return BadRequest("Not implemented");
|
||||
}
|
||||
|
||||
|
||||
[HttpDelete("account/{accountId:guid}/hostname/{index:int}")]
|
||||
public async Task<IActionResult> DeleteHostname(Guid accountId, int index) {
|
||||
//var result = await _cacheService.DeleteHostnameAsync(accountId, index);
|
||||
//return result.ToActionResult();
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
using DomainResults.Mvc;
|
||||
|
||||
using MaksIT.LetsEncryptServer.Services;
|
||||
using MaksIT.Models.LetsEncryptServer.Cache.Requests;
|
||||
|
||||
namespace MaksIT.LetsEncryptServer.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/accounts")]
|
||||
public class AccountsController : ControllerBase {
|
||||
private readonly ICacheRestService _cacheService;
|
||||
private readonly ICertsFlowService _certsFlowService;
|
||||
|
||||
public AccountsController(
|
||||
ICacheService cacheService,
|
||||
ICertsFlowService certsFlowService
|
||||
) {
|
||||
_cacheService = cacheService;
|
||||
_certsFlowService = certsFlowService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetAccounts() {
|
||||
var result = await _cacheService.GetAccountsAsync();
|
||||
return result.ToActionResult();
|
||||
}
|
||||
}
|
||||
@ -29,8 +29,9 @@ builder.Services.AddCors();
|
||||
builder.Services.AddMemoryCache();
|
||||
|
||||
builder.Services.AddHttpClient<ILetsEncryptService, LetsEncryptService>();
|
||||
builder.Services.AddSingleton<ICertsFlowService, CertsFlowService>();
|
||||
builder.Services.AddSingleton<ICacheService, CacheService>();
|
||||
builder.Services.AddSingleton<ICertsFlowService, CertsFlowService>();
|
||||
builder.Services.AddSingleton<IAccountService, AccountService>();
|
||||
builder.Services.AddHttpClient<IAgentService, AgentService>();
|
||||
builder.Services.AddHostedService<AutoRenewal>();
|
||||
|
||||
|
||||
337
src/LetsEncryptServer/Services/AccoutService.cs
Normal file
337
src/LetsEncryptServer/Services/AccoutService.cs
Normal file
@ -0,0 +1,337 @@
|
||||
using System.Text.Json;
|
||||
|
||||
using DomainResults.Common;
|
||||
|
||||
using MaksIT.Core.Extensions;
|
||||
using MaksIT.LetsEncrypt.Entities;
|
||||
using MaksIT.LetsEncrypt.Models.Responses;
|
||||
using MaksIT.Models;
|
||||
using MaksIT.Models.LetsEncryptServer.Account.Requests;
|
||||
using MaksIT.Models.LetsEncryptServer.Account.Responses;
|
||||
|
||||
namespace MaksIT.LetsEncryptServer.Services;
|
||||
|
||||
|
||||
public interface IAccountInternalService {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public interface IAccountRestService {
|
||||
Task<(GetAccountResponse[]?, IDomainResult)> GetAccountsAsync();
|
||||
Task<(GetAccountResponse?, IDomainResult)> GetAccountAsync(Guid accountId);
|
||||
Task<(GetAccountResponse?, IDomainResult)> PostAccountAsync(PostAccountRequest requestData);
|
||||
Task<(GetAccountResponse?, IDomainResult)> PutAccountAsync(Guid accountId, PutAccountRequest requestData);
|
||||
Task<(GetAccountResponse?, IDomainResult)> PatchAccountAsync(Guid accountId, PatchAccountRequest requestData);
|
||||
Task<IDomainResult> DeleteAccountAsync(Guid accountId);
|
||||
Task<(GetContactsResponse?, IDomainResult)> GetContactsAsync(Guid accountId);
|
||||
Task<(GetContactsResponse?, IDomainResult)> PostContactsAsync(Guid accountId, PostContactsRequest requestData);
|
||||
Task<(GetAccountResponse?, IDomainResult)> PutContactsAsync(Guid accountId, PutContactsRequest requestData);
|
||||
Task<(GetAccountResponse?, IDomainResult)> PatchContactsAsync(Guid accountId, PatchContactsRequest requestData);
|
||||
Task<IDomainResult> DeleteContactAsync(Guid accountId, int index);
|
||||
Task<(GetHostnamesResponse?, IDomainResult)> GetHostnames(Guid accountId);
|
||||
}
|
||||
|
||||
public interface IAccountService : IAccountInternalService, IAccountRestService { }
|
||||
|
||||
public class AccountService : IAccountService {
|
||||
|
||||
private readonly ILogger<CacheService> _logger;
|
||||
private readonly ICacheService _cacheService;
|
||||
private readonly ICertsInternalService _certsFlowService;
|
||||
|
||||
public AccountService(
|
||||
ILogger<CacheService> logger,
|
||||
ICacheService cacheService,
|
||||
ICertsFlowService certsFlowService
|
||||
) {
|
||||
_logger = logger;
|
||||
_cacheService = cacheService;
|
||||
_certsFlowService = certsFlowService;
|
||||
}
|
||||
|
||||
#region Accounts
|
||||
|
||||
public async Task<(GetAccountResponse[]?, IDomainResult)> GetAccountsAsync() {
|
||||
|
||||
var (caches, result) = await _cacheService.LoadAccountsFromCacheAsync();
|
||||
if (!result.IsSuccess || caches == null) {
|
||||
return (null, result);
|
||||
}
|
||||
|
||||
var accounts = caches.Select(cache => new GetAccountResponse {
|
||||
AccountId = cache.AccountId,
|
||||
Description = cache.Description,
|
||||
Contacts = cache.Contacts,
|
||||
ChallengeType = cache.ChallengeType,
|
||||
Hostnames = GetHostnamesFromCache(cache).ToArray()
|
||||
});
|
||||
|
||||
return IDomainResult.Success(accounts.ToArray());
|
||||
}
|
||||
|
||||
public async Task<(GetAccountResponse?, IDomainResult)> GetAccountAsync(Guid accountId) {
|
||||
var (cache, result) = await _cacheService.LoadAccountFromCacheAsync(accountId);
|
||||
if (!result.IsSuccess || cache == null) {
|
||||
return (null, result);
|
||||
}
|
||||
|
||||
var response = new GetAccountResponse {
|
||||
AccountId = accountId,
|
||||
Description = cache.Description,
|
||||
Contacts = cache.Contacts,
|
||||
Hostnames = GetHostnamesFromCache(cache).ToArray()
|
||||
};
|
||||
|
||||
return IDomainResult.Success(response);
|
||||
}
|
||||
|
||||
public async Task<(GetAccountResponse?, IDomainResult)> PostAccountAsync(PostAccountRequest requestData) {
|
||||
var (sessionId, configureClientResult) = await _certsFlowService.ConfigureClientAsync();
|
||||
if (!configureClientResult.IsSuccess || sessionId == null) {
|
||||
//LogErrors(configureClientResult.Errors);
|
||||
return (null, configureClientResult);
|
||||
}
|
||||
var sessionIdValue = sessionId.Value;
|
||||
|
||||
var (_, initResult) = await _certsFlowService.InitAsync(sessionIdValue, null, requestData.Description, requestData.Contacts);
|
||||
if (!initResult.IsSuccess) {
|
||||
//LogErrors(initResult.Errors);
|
||||
return (null, initResult);
|
||||
}
|
||||
|
||||
var (_, newOrderResult) = await _certsFlowService.NewOrderAsync(sessionIdValue, requestData.Hostnames, requestData.ChallengeType);
|
||||
if (!newOrderResult.IsSuccess) {
|
||||
//LogErrors(newOrderResult.Errors);
|
||||
return (null, newOrderResult);
|
||||
}
|
||||
|
||||
var challengeResult = await _certsFlowService.CompleteChallengesAsync(sessionIdValue);
|
||||
if (!challengeResult.IsSuccess) {
|
||||
//LogErrors(challengeResult.Errors);
|
||||
return (null, challengeResult);
|
||||
}
|
||||
|
||||
var getOrderResult = await _certsFlowService.GetOrderAsync(sessionIdValue, requestData.Hostnames);
|
||||
if (!getOrderResult.IsSuccess) {
|
||||
//LogErrors(getOrderResult.Errors);
|
||||
return (null, getOrderResult);
|
||||
}
|
||||
|
||||
var certs = await _certsFlowService.GetCertificatesAsync(sessionIdValue, requestData.Hostnames);
|
||||
if (!certs.IsSuccess) {
|
||||
//LogErrors(certs.Errors);
|
||||
return (null, certs);
|
||||
}
|
||||
|
||||
var (_, applyCertsResult) = await _certsFlowService.ApplyCertificatesAsync(sessionIdValue, requestData.Hostnames);
|
||||
if (!applyCertsResult.IsSuccess) {
|
||||
//LogErrors(applyCertsResult.Errors);
|
||||
return (null, applyCertsResult);
|
||||
}
|
||||
|
||||
return IDomainResult.Success<GetAccountResponse?>(null);
|
||||
}
|
||||
|
||||
public async Task<(GetAccountResponse?, IDomainResult)> PutAccountAsync(Guid accountId, PutAccountRequest requestData) {
|
||||
var (cache, loadResult) = await _cacheService.LoadAccountFromCacheAsync(accountId);
|
||||
if (!loadResult.IsSuccess || cache == null) {
|
||||
return (null, loadResult);
|
||||
}
|
||||
|
||||
cache.Description = requestData.Description;
|
||||
cache.Contacts = requestData.Contacts;
|
||||
|
||||
var saveResult = await _cacheService.SaveToCacheAsync(accountId, cache);
|
||||
if (!saveResult.IsSuccess) {
|
||||
return (null, saveResult);
|
||||
}
|
||||
|
||||
return CreateGetAccountResponse(accountId, cache);
|
||||
}
|
||||
|
||||
public async Task<(GetAccountResponse?, IDomainResult)> PatchAccountAsync(Guid accountId, PatchAccountRequest requestData) {
|
||||
var (cache, loadResult) = await _cacheService.LoadAccountFromCacheAsync(accountId);
|
||||
if (!loadResult.IsSuccess || cache == null) {
|
||||
return (null, loadResult);
|
||||
}
|
||||
|
||||
if (requestData.Description != null) {
|
||||
switch (requestData.Description.Op) {
|
||||
case PatchOperation.Replace:
|
||||
cache.Description = requestData.Description.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (requestData.Contacts != null && requestData.Contacts.Any()) {
|
||||
var contacts = cache.Contacts?.ToList() ?? new List<string>();
|
||||
foreach (var action in requestData.Contacts) {
|
||||
switch (action.Op)
|
||||
{
|
||||
case PatchOperation.Add:
|
||||
if (action.Value != null) contacts.Add(action.Value);
|
||||
break;
|
||||
case PatchOperation.Replace:
|
||||
if (action.Index != null && action.Index >= 0 && action.Index < contacts.Count)
|
||||
contacts[action.Index.Value] = action.Value;
|
||||
break;
|
||||
case PatchOperation.Remove:
|
||||
if (action.Index != null && action.Index >= 0 && action.Index < contacts.Count)
|
||||
contacts.RemoveAt(action.Index.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
cache.Contacts = contacts.ToArray();
|
||||
}
|
||||
|
||||
var saveResult = await _cacheService.SaveToCacheAsync(accountId, cache);
|
||||
if (!saveResult.IsSuccess) {
|
||||
return (null, saveResult);
|
||||
}
|
||||
|
||||
return CreateGetAccountResponse(accountId, cache);
|
||||
}
|
||||
|
||||
public async Task<IDomainResult> DeleteAccountAsync(Guid accountId) {
|
||||
return await _cacheService.DeleteFromCacheAsync(accountId);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Contacts Operations
|
||||
|
||||
public async Task<(GetContactsResponse?, IDomainResult)> GetContactsAsync(Guid accountId) {
|
||||
var (cache, loadResult) = await _cacheService.LoadAccountFromCacheAsync(accountId);
|
||||
if (!loadResult.IsSuccess || cache == null) {
|
||||
return (null, loadResult);
|
||||
}
|
||||
|
||||
return IDomainResult.Success(new GetContactsResponse {
|
||||
Contacts = cache.Contacts ?? Array.Empty<string>()
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<(GetContactsResponse?, IDomainResult)> PostContactsAsync(Guid accountId, PostContactsRequest requestData) {
|
||||
return IDomainResult.Failed<GetContactsResponse?>("Not implemented");
|
||||
}
|
||||
|
||||
public async Task<(GetAccountResponse?, IDomainResult)> PutContactsAsync(Guid accountId, PutContactsRequest requestData) {
|
||||
var (cache, loadResult) = await _cacheService.LoadAccountFromCacheAsync(accountId);
|
||||
if (!loadResult.IsSuccess || cache == null) {
|
||||
return (null, loadResult);
|
||||
}
|
||||
|
||||
cache.Contacts = requestData.Contacts;
|
||||
var saveResult = await _cacheService.SaveToCacheAsync(accountId, cache);
|
||||
if (!saveResult.IsSuccess) {
|
||||
return (null, saveResult);
|
||||
}
|
||||
|
||||
return CreateGetAccountResponse(accountId, cache);
|
||||
}
|
||||
|
||||
public async Task<(GetAccountResponse?, IDomainResult)> PatchContactsAsync(Guid accountId, PatchContactsRequest requestData) {
|
||||
var (cache, loadResult) = await _cacheService.LoadAccountFromCacheAsync(accountId);
|
||||
if (!loadResult.IsSuccess || cache == null) {
|
||||
return (null, loadResult);
|
||||
}
|
||||
|
||||
var contacts = cache.Contacts?.ToList() ?? new List<string>();
|
||||
|
||||
foreach (var contact in requestData.Contacts) {
|
||||
switch (contact.Op) {
|
||||
case PatchOperation.Add:
|
||||
if (contact.Value != null) {
|
||||
contacts.Add(contact.Value);
|
||||
}
|
||||
break;
|
||||
case PatchOperation.Replace:
|
||||
if (contact.Index.HasValue && contact.Index.Value >= 0 && contact.Index.Value < contacts.Count && contact.Value != null) {
|
||||
contacts[contact.Index.Value] = contact.Value;
|
||||
}
|
||||
break;
|
||||
case PatchOperation.Remove:
|
||||
if (contact.Index.HasValue && contact.Index.Value >= 0 && contact.Index.Value < contacts.Count) {
|
||||
contacts.RemoveAt(contact.Index.Value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return (null, IDomainResult.Failed("Invalid patch operation."));
|
||||
}
|
||||
}
|
||||
|
||||
cache.Contacts = contacts.ToArray();
|
||||
var saveResult = await _cacheService.SaveToCacheAsync(accountId, cache);
|
||||
if (!saveResult.IsSuccess) {
|
||||
return (null, saveResult);
|
||||
}
|
||||
|
||||
return CreateGetAccountResponse(accountId, cache);
|
||||
}
|
||||
|
||||
public async Task<IDomainResult> DeleteContactAsync(Guid accountId, int index) {
|
||||
var (cache, loadResult) = await _cacheService.LoadAccountFromCacheAsync(accountId);
|
||||
if (!loadResult.IsSuccess || cache == null) {
|
||||
return loadResult;
|
||||
}
|
||||
|
||||
var contacts = cache.Contacts?.ToList() ?? new List<string>();
|
||||
|
||||
if (index >= 0 && index < contacts.Count) {
|
||||
contacts.RemoveAt(index);
|
||||
}
|
||||
|
||||
cache.Contacts = contacts.ToArray();
|
||||
var saveResult = await _cacheService.SaveToCacheAsync(accountId, cache);
|
||||
if (!saveResult.IsSuccess) {
|
||||
return saveResult;
|
||||
}
|
||||
|
||||
return IDomainResult.Success();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Hostnames Operations
|
||||
|
||||
public async Task<(GetHostnamesResponse?, IDomainResult)> GetHostnames(Guid accountId) {
|
||||
var (cache, loadResult) = await _cacheService.LoadAccountFromCacheAsync(accountId);
|
||||
if (!loadResult.IsSuccess || cache?.CachedCerts == null) {
|
||||
return (null, loadResult);
|
||||
}
|
||||
|
||||
var hostnames = GetHostnamesFromCache(cache);
|
||||
|
||||
return IDomainResult.Success(new GetHostnamesResponse {
|
||||
Hostnames = hostnames
|
||||
});
|
||||
}
|
||||
|
||||
private List<HostnameResponse> GetHostnamesFromCache(RegistrationCache cache) {
|
||||
var hosts = cache.GetHosts().Select(x => new HostnameResponse {
|
||||
Hostname = x.Hostname,
|
||||
Expires = x.Expires,
|
||||
IsUpcomingExpire = x.IsUpcomingExpire
|
||||
}).ToList();
|
||||
|
||||
return hosts;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
private (GetAccountResponse?, IDomainResult) CreateGetAccountResponse(Guid accountId, RegistrationCache cache) {
|
||||
var hostnames = GetHostnamesFromCache(cache) ?? new List<HostnameResponse>();
|
||||
|
||||
return (new GetAccountResponse {
|
||||
AccountId = accountId,
|
||||
Description = cache.Description,
|
||||
Contacts = cache.Contacts,
|
||||
Hostnames = hostnames.ToArray()
|
||||
}, IDomainResult.Success());
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -5,33 +5,16 @@ using DomainResults.Common;
|
||||
using MaksIT.Core.Extensions;
|
||||
using MaksIT.LetsEncrypt.Entities;
|
||||
using MaksIT.Models;
|
||||
using MaksIT.Models.LetsEncryptServer.Cache.Requests;
|
||||
using MaksIT.Models.LetsEncryptServer.Cache.Responses;
|
||||
|
||||
namespace MaksIT.LetsEncryptServer.Services;
|
||||
|
||||
public interface ICacheInternalService {
|
||||
public interface ICacheService {
|
||||
Task<(RegistrationCache[]?, IDomainResult)> LoadAccountsFromCacheAsync();
|
||||
Task<(RegistrationCache?, IDomainResult)> LoadAccountFromCacheAsync(Guid accountId);
|
||||
Task<IDomainResult> SaveToCacheAsync(Guid accountId, RegistrationCache cache);
|
||||
Task<IDomainResult> DeleteFromCacheAsync(Guid accountId);
|
||||
}
|
||||
|
||||
public interface ICacheRestService {
|
||||
Task<(GetAccountResponse[]?, IDomainResult)> GetAccountsAsync();
|
||||
Task<(GetAccountResponse?, IDomainResult)> GetAccountAsync(Guid accountId);
|
||||
Task<(GetAccountResponse?, IDomainResult)> PutAccountAsync(Guid accountId, PutAccountRequest requestData);
|
||||
Task<(GetAccountResponse?, IDomainResult)> PatchAccountAsync(Guid accountId, PatchAccountRequest requestData);
|
||||
Task<IDomainResult> DeleteAccountAsync(Guid accountId);
|
||||
Task<(GetContactsResponse?, IDomainResult)> GetContactsAsync(Guid accountId);
|
||||
Task<(GetAccountResponse?, IDomainResult)> PutContactsAsync(Guid accountId, PutContactsRequest requestData);
|
||||
Task<(GetAccountResponse?, IDomainResult)> PatchContactsAsync(Guid accountId, PatchContactsRequest requestData);
|
||||
Task<IDomainResult> DeleteContactAsync(Guid accountId, int index);
|
||||
Task<(GetHostnamesResponse?, IDomainResult)> GetHostnames(Guid accountId);
|
||||
}
|
||||
|
||||
public interface ICacheService : ICacheInternalService, ICacheRestService {}
|
||||
|
||||
public class CacheService : ICacheService, IDisposable {
|
||||
private readonly ILogger<CacheService> _logger;
|
||||
private readonly string _cacheDirectory;
|
||||
@ -86,9 +69,7 @@ public class CacheService : ICacheService, IDisposable {
|
||||
}
|
||||
|
||||
|
||||
public Task<(RegistrationCache?, IDomainResult)> LoadAccountFromCacheAsync(Guid accountId) {
|
||||
return _lockManager.ExecuteWithLockAsync(() => LoadFromCacheInternalAsync(accountId));
|
||||
}
|
||||
|
||||
|
||||
private async Task<(RegistrationCache?, IDomainResult)> LoadFromCacheInternalAsync(Guid accountId) {
|
||||
var cacheFilePath = GetCacheFilePath(accountId);
|
||||
@ -110,9 +91,7 @@ public class CacheService : ICacheService, IDisposable {
|
||||
return IDomainResult.Success(cache);
|
||||
}
|
||||
|
||||
public Task<IDomainResult> SaveToCacheAsync(Guid accountId, RegistrationCache cache) {
|
||||
return _lockManager.ExecuteWithLockAsync(() => SaveToCacheInternalAsync(accountId, cache));
|
||||
}
|
||||
|
||||
|
||||
private async Task<IDomainResult> SaveToCacheInternalAsync(Guid accountId, RegistrationCache cache) {
|
||||
var cacheFilePath = GetCacheFilePath(accountId);
|
||||
@ -122,9 +101,7 @@ public class CacheService : ICacheService, IDisposable {
|
||||
return DomainResult.Success();
|
||||
}
|
||||
|
||||
public Task<IDomainResult> DeleteFromCacheAsync(Guid accountId) {
|
||||
return _lockManager.ExecuteWithLockAsync(() => DeleteFromCacheInternal(accountId));
|
||||
}
|
||||
|
||||
|
||||
private IDomainResult DeleteFromCacheInternal(Guid accountId) {
|
||||
var cacheFilePath = GetCacheFilePath(accountId);
|
||||
@ -137,245 +114,23 @@ public class CacheService : ICacheService, IDisposable {
|
||||
}
|
||||
return DomainResult.Success();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Account Operations
|
||||
|
||||
public async Task<(GetAccountResponse[]?, IDomainResult)> GetAccountsAsync() {
|
||||
return await _lockManager.ExecuteWithLockAsync(async () => {
|
||||
|
||||
var accountIds = GetCachedAccounts();
|
||||
var accounts = new List<GetAccountResponse>();
|
||||
|
||||
foreach (var accountId in accountIds) {
|
||||
var (account, result) = await GetAccountAsync(accountId);
|
||||
if (!result.IsSuccess || account == null) {
|
||||
return (null, result);
|
||||
}
|
||||
accounts.Add(account);
|
||||
}
|
||||
|
||||
return IDomainResult.Success(accounts.ToArray());
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<(GetAccountResponse?, IDomainResult)> GetAccountAsync(Guid accountId) {
|
||||
return await _lockManager.ExecuteWithLockAsync(async () => {
|
||||
var (cache, result) = await LoadAccountFromCacheAsync(accountId);
|
||||
if (!result.IsSuccess || cache == null) {
|
||||
return (null, result);
|
||||
}
|
||||
|
||||
var response = new GetAccountResponse {
|
||||
AccountId = accountId,
|
||||
Description = cache.Description,
|
||||
Contacts = cache.Contacts,
|
||||
Hostnames = GetHostnamesFromCache(cache).ToArray()
|
||||
};
|
||||
|
||||
return IDomainResult.Success(response);
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<(GetAccountResponse?, IDomainResult)> PutAccountAsync(Guid accountId, PutAccountRequest requestData) {
|
||||
var (cache, loadResult) = await LoadAccountFromCacheAsync(accountId);
|
||||
if (!loadResult.IsSuccess || cache == null) {
|
||||
return (null, loadResult);
|
||||
}
|
||||
|
||||
cache.Description = requestData.Description;
|
||||
cache.Contacts = requestData.Contacts;
|
||||
|
||||
var saveResult = await SaveToCacheAsync(accountId, cache);
|
||||
if (!saveResult.IsSuccess) {
|
||||
return (null, saveResult);
|
||||
}
|
||||
|
||||
return CreateGetAccountResponse(accountId, cache);
|
||||
}
|
||||
|
||||
public async Task<(GetAccountResponse?, IDomainResult)> PatchAccountAsync(Guid accountId, PatchAccountRequest requestData) {
|
||||
var (cache, loadResult) = await LoadAccountFromCacheAsync(accountId);
|
||||
if (!loadResult.IsSuccess || cache == null) {
|
||||
return (null, loadResult);
|
||||
}
|
||||
|
||||
if (requestData.Description != null) {
|
||||
switch (requestData.Description.Op) {
|
||||
case PatchOperation.Replace:
|
||||
cache.Description = requestData.Description.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (requestData.Contacts != null && requestData.Contacts.Any()) {
|
||||
var contacts = cache.Contacts?.ToList() ?? new List<string>();
|
||||
foreach (var action in requestData.Contacts) {
|
||||
switch (action.Op)
|
||||
{
|
||||
case PatchOperation.Add:
|
||||
if (action.Value != null) contacts.Add(action.Value);
|
||||
break;
|
||||
case PatchOperation.Replace:
|
||||
if (action.Index != null && action.Index >= 0 && action.Index < contacts.Count)
|
||||
contacts[action.Index.Value] = action.Value;
|
||||
break;
|
||||
case PatchOperation.Remove:
|
||||
if (action.Index != null && action.Index >= 0 && action.Index < contacts.Count)
|
||||
contacts.RemoveAt(action.Index.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
cache.Contacts = contacts.ToArray();
|
||||
}
|
||||
|
||||
var saveResult = await SaveToCacheAsync(accountId, cache);
|
||||
if (!saveResult.IsSuccess) {
|
||||
return (null, saveResult);
|
||||
}
|
||||
|
||||
return CreateGetAccountResponse(accountId, cache);
|
||||
}
|
||||
|
||||
public async Task<IDomainResult> DeleteAccountAsync(Guid accountId) {
|
||||
return await DeleteFromCacheAsync(accountId);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Contacts Operations
|
||||
|
||||
public async Task<(GetContactsResponse?, IDomainResult)> GetContactsAsync(Guid accountId) {
|
||||
var (cache, loadResult) = await LoadAccountFromCacheAsync(accountId);
|
||||
if (!loadResult.IsSuccess || cache == null) {
|
||||
return (null, loadResult);
|
||||
}
|
||||
|
||||
return IDomainResult.Success(new GetContactsResponse {
|
||||
Contacts = cache.Contacts ?? Array.Empty<string>()
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<(GetAccountResponse?, IDomainResult)> PutContactsAsync(Guid accountId, PutContactsRequest requestData) {
|
||||
var (cache, loadResult) = await LoadAccountFromCacheAsync(accountId);
|
||||
if (!loadResult.IsSuccess || cache == null) {
|
||||
return (null, loadResult);
|
||||
}
|
||||
|
||||
cache.Contacts = requestData.Contacts;
|
||||
var saveResult = await SaveToCacheAsync(accountId, cache);
|
||||
if (!saveResult.IsSuccess) {
|
||||
return (null, saveResult);
|
||||
}
|
||||
|
||||
return CreateGetAccountResponse(accountId, cache);
|
||||
}
|
||||
|
||||
public async Task<(GetAccountResponse?, IDomainResult)> PatchContactsAsync(Guid accountId, PatchContactsRequest requestData) {
|
||||
var (cache, loadResult) = await LoadAccountFromCacheAsync(accountId);
|
||||
if (!loadResult.IsSuccess || cache == null) {
|
||||
return (null, loadResult);
|
||||
}
|
||||
|
||||
var contacts = cache.Contacts?.ToList() ?? new List<string>();
|
||||
|
||||
foreach (var contact in requestData.Contacts) {
|
||||
switch (contact.Op) {
|
||||
case PatchOperation.Add:
|
||||
if (contact.Value != null) {
|
||||
contacts.Add(contact.Value);
|
||||
}
|
||||
break;
|
||||
case PatchOperation.Replace:
|
||||
if (contact.Index.HasValue && contact.Index.Value >= 0 && contact.Index.Value < contacts.Count && contact.Value != null) {
|
||||
contacts[contact.Index.Value] = contact.Value;
|
||||
}
|
||||
break;
|
||||
case PatchOperation.Remove:
|
||||
if (contact.Index.HasValue && contact.Index.Value >= 0 && contact.Index.Value < contacts.Count) {
|
||||
contacts.RemoveAt(contact.Index.Value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return (null, IDomainResult.Failed("Invalid patch operation."));
|
||||
}
|
||||
}
|
||||
|
||||
cache.Contacts = contacts.ToArray();
|
||||
var saveResult = await SaveToCacheAsync(accountId, cache);
|
||||
if (!saveResult.IsSuccess) {
|
||||
return (null, saveResult);
|
||||
}
|
||||
|
||||
return CreateGetAccountResponse(accountId, cache);
|
||||
}
|
||||
|
||||
public async Task<IDomainResult> DeleteContactAsync(Guid accountId, int index) {
|
||||
var (cache, loadResult) = await LoadAccountFromCacheAsync(accountId);
|
||||
if (!loadResult.IsSuccess || cache == null) {
|
||||
return loadResult;
|
||||
}
|
||||
|
||||
var contacts = cache.Contacts?.ToList() ?? new List<string>();
|
||||
|
||||
if (index >= 0 && index < contacts.Count) {
|
||||
contacts.RemoveAt(index);
|
||||
}
|
||||
|
||||
cache.Contacts = contacts.ToArray();
|
||||
var saveResult = await SaveToCacheAsync(accountId, cache);
|
||||
if (!saveResult.IsSuccess) {
|
||||
return saveResult;
|
||||
}
|
||||
|
||||
return IDomainResult.Success();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Hostnames Operations
|
||||
|
||||
public async Task<(GetHostnamesResponse?, IDomainResult)> GetHostnames(Guid accountId) {
|
||||
var (cache, loadResult) = await LoadAccountFromCacheAsync(accountId);
|
||||
if (!loadResult.IsSuccess || cache?.CachedCerts == null) {
|
||||
return (null, loadResult);
|
||||
}
|
||||
|
||||
var hostnames = GetHostnamesFromCache(cache);
|
||||
|
||||
return IDomainResult.Success(new GetHostnamesResponse {
|
||||
Hostnames = hostnames
|
||||
});
|
||||
public Task<(RegistrationCache?, IDomainResult)> LoadAccountFromCacheAsync(Guid accountId) {
|
||||
return _lockManager.ExecuteWithLockAsync(() => LoadFromCacheInternalAsync(accountId));
|
||||
}
|
||||
|
||||
private List<HostnameResponse> GetHostnamesFromCache(RegistrationCache cache) {
|
||||
var hosts = cache.GetHosts().Select(x => new HostnameResponse {
|
||||
Hostname = x.Hostname,
|
||||
Expires = x.Expires,
|
||||
IsUpcomingExpire = x.IsUpcomingExpire
|
||||
}).ToList();
|
||||
|
||||
return hosts;
|
||||
public Task<IDomainResult> SaveToCacheAsync(Guid accountId, RegistrationCache cache) {
|
||||
return _lockManager.ExecuteWithLockAsync(() => SaveToCacheInternalAsync(accountId, cache));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
private (GetAccountResponse?, IDomainResult) CreateGetAccountResponse(Guid accountId, RegistrationCache cache) {
|
||||
var hostnames = GetHostnamesFromCache(cache) ?? new List<HostnameResponse>();
|
||||
|
||||
return (new GetAccountResponse {
|
||||
AccountId = accountId,
|
||||
Description = cache.Description,
|
||||
Contacts = cache.Contacts,
|
||||
Hostnames = hostnames.ToArray()
|
||||
}, IDomainResult.Success());
|
||||
public Task<IDomainResult> DeleteFromCacheAsync(Guid accountId) {
|
||||
return _lockManager.ExecuteWithLockAsync(() => DeleteFromCacheInternal(accountId));
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
_lockManager?.Dispose();
|
||||
_lockManager.Dispose();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MaksIT.Models.LetsEncryptServer.Cache.Requests {
|
||||
namespace MaksIT.Models.LetsEncryptServer.Account.Requests {
|
||||
public class PatchAccountRequest {
|
||||
|
||||
public PatchAction<string>? Description { get; set; }
|
||||
@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MaksIT.Models.LetsEncryptServer.Cache.Requests {
|
||||
namespace MaksIT.Models.LetsEncryptServer.Account.Requests {
|
||||
|
||||
public class PatchContactsRequest {
|
||||
public List<PatchAction<string>> Contacts { get; set; }
|
||||
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MaksIT.Models.LetsEncryptServer.Account.Requests {
|
||||
|
||||
public class PatchHostnamesRequest {
|
||||
public List<PatchAction<string>> Hostnames { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,13 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace MaksIT.Models.LetsEncryptServer.Cache.Requests {
|
||||
namespace MaksIT.Models.LetsEncryptServer.Account.Requests {
|
||||
public class PostAccountRequest : IValidatableObject {
|
||||
public required string Description { get; set; }
|
||||
public required string[] Contacts { get; set; }
|
||||
public required string[] Hostnames { get; set; }
|
||||
|
||||
public required string ChallengeType { get; set; }
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
|
||||
if (string.IsNullOrWhiteSpace(Description))
|
||||
yield return new ValidationResult("Description is required", new[] { nameof(Description) });
|
||||
@ -15,6 +17,9 @@ namespace MaksIT.Models.LetsEncryptServer.Cache.Requests {
|
||||
|
||||
if (Hostnames == null || Hostnames.Length == 0)
|
||||
yield return new ValidationResult("Hostnames is required", new[] { nameof(Hostnames) });
|
||||
|
||||
if (string.IsNullOrWhiteSpace(ChallengeType) && ChallengeType != "http-01")
|
||||
yield return new ValidationResult("ChallengeType is required", new[] { nameof(ChallengeType) });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MaksIT.Models.LetsEncryptServer.Cache.Requests {
|
||||
namespace MaksIT.Models.LetsEncryptServer.Account.Requests {
|
||||
public class PostContactsRequest : IValidatableObject {
|
||||
|
||||
public required string[] Contacts { get; set; }
|
||||
@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MaksIT.Models.LetsEncryptServer.Account.Requests {
|
||||
public class PostHostnamesRequest : IValidatableObject {
|
||||
public required string[] Hostnames { get; set; }
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
|
||||
if (Hostnames == null || Hostnames.Length == 0)
|
||||
yield return new ValidationResult("Hostnames is required", new[] { nameof(Hostnames) });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MaksIT.Models.LetsEncryptServer.Cache.Requests {
|
||||
namespace MaksIT.Models.LetsEncryptServer.Account.Requests {
|
||||
public class PutAccountRequest : IValidatableObject {
|
||||
public required string Description { get; set; }
|
||||
public required string[] Contacts { get; set; }
|
||||
@ -1,7 +1,7 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
|
||||
namespace MaksIT.Models.LetsEncryptServer.Cache.Requests {
|
||||
namespace MaksIT.Models.LetsEncryptServer.Account.Requests {
|
||||
public class PutContactsRequest : IValidatableObject {
|
||||
|
||||
public required string[] Contacts { get; set; }
|
||||
@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MaksIT.Models.LetsEncryptServer.Account.Requests {
|
||||
public class PutHostnamesRequest : IValidatableObject {
|
||||
public string[] Hostnames { get; set; }
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
|
||||
if (Hostnames == null || Hostnames.Length == 0)
|
||||
yield return new ValidationResult("Hostnames is required", new[] { nameof(Hostnames) });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,13 +4,15 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MaksIT.Models.LetsEncryptServer.Cache.Responses {
|
||||
namespace MaksIT.Models.LetsEncryptServer.Account.Responses {
|
||||
public class GetAccountResponse {
|
||||
public Guid AccountId { get; set; }
|
||||
|
||||
public string? Description { get; set; }
|
||||
|
||||
public string []? Contacts { get; set; }
|
||||
public required string [] Contacts { get; set; }
|
||||
|
||||
public string? ChallengeType { get; set; }
|
||||
|
||||
public HostnameResponse[]? Hostnames { get; set; }
|
||||
}
|
||||
@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MaksIT.Models.LetsEncryptServer.Cache.Responses {
|
||||
namespace MaksIT.Models.LetsEncryptServer.Account.Responses {
|
||||
public class GetContactsResponse {
|
||||
public string[] Contacts { get; set; }
|
||||
}
|
||||
@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MaksIT.Models.LetsEncryptServer.Cache.Responses {
|
||||
namespace MaksIT.Models.LetsEncryptServer.Account.Responses {
|
||||
|
||||
public class GetHostnamesResponse {
|
||||
public List<HostnameResponse> Hostnames { get; set; }
|
||||
@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MaksIT.Models.LetsEncryptServer.Cache.Responses {
|
||||
namespace MaksIT.Models.LetsEncryptServer.Account.Responses {
|
||||
public class HostnameResponse {
|
||||
public string Hostname { get; set; }
|
||||
public DateTime Expires { get; set; }
|
||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user