using FluentValidation;
using FluentValidation.Results;
using Raven.Client.Documents;
using Raven.Client.Documents.Linq;
namespace zero.Configuration;
public class IntegrationStore : IIntegrationStore
{
protected IStoreOperations Operations { get; private set; }
protected IIntegrationTypeService IntegrationTypes { get; private set; }
public IntegrationStore(IStoreOperationsWithInactive operations, IIntegrationTypeService integrationTypes)
{
IntegrationTypes = integrationTypes;
Operations = operations;
}
///
public virtual async Task Empty(string alias)
{
return await Operations.Empty(alias);
}
///
public virtual async Task Load(string alias)
{
Paged result = await Operations.Load(1, 1, q => q.Where(x => x.Flavor == alias));
return result.Items.FirstOrDefault();
}
///
public async Task> LoadByTag(string tag)
{
IEnumerable types = IntegrationTypes.GetByTag(tag);
if (!types.Any())
{
return new List();
}
string[] aliases = types.Select(x => x.Alias).ToArray();
return await Operations.Session.Query().Where(x => x.Flavor.In(aliases)).ToListAsync();
}
///
public async Task Any(string tag)
{
IEnumerable types = IntegrationTypes.GetByTag(tag);
if (!types.Any())
{
return false;
}
string[] aliases = types.Select(x => x.Alias).ToArray();
return await Operations.Session.Query().AnyAsync(x => x.Flavor.In(aliases) && x.IsActive);
}
///
public virtual string GetChangeToken(Integration model) => Operations.GetChangeToken(model);
///
public virtual async Task> Create(Integration model) => await Save(model, true);
///
public virtual async Task> Update(Integration model) => await Save(model, false);
///
public virtual async Task> Activate(string alias)
{
Integration model = await Load(alias);
if (model != null)
{
model.IsActive = true;
}
return await Update(model);
}
///
public virtual async Task> Deactivate(string alias)
{
Integration model = await Load(alias);
if (model != null)
{
model.IsActive = false;
}
return await Update(model);
}
///
public async Task> Delete(string alias)
{
Integration integration = await Load(alias);
return await Operations.Delete(integration);
}
//
protected virtual async Task Validate(Integration model, bool create = false)
{
ValidationResult result = new();
if (model == null)
{
result.Errors.Add(new ValidationFailure("__nofield", "@integration.errors.notfound"));
}
else
{
IntegrationType type = IntegrationTypes.GetByAlias(model.Flavor);
if (type == null)
{
result.Errors.Add(new ValidationFailure("__nofield", "@integration.errors.typenotfound"));
}
if (create && await Operations.Any(q => q.Where(x => x.Flavor == model.Flavor)))
{
result.Errors.Add(new ValidationFailure("__nofield", "@integration.errors.multiplenotallowed"));
}
if (!create && await Operations.Any(q => q.Where(x => x.Flavor == model.Flavor && x.Id != model.Id)))
{
result.Errors.Add(new ValidationFailure("__nofield", "@integration.errors.alreadycreated"));
}
if (type != null && type.Validator != null)
{
ValidationResult innerResult = await type.Validator.ValidateAsync(new ValidationContext(model));
result.Errors.AddRange(innerResult.Errors);
}
}
return result;
}
///
protected virtual async Task> Save(Integration model, bool create = false)
{
return await Operations.Create(model, async (x, ctx) => await Validate(x, create));
}
}
public interface IIntegrationStore
{
///
/// Get new instance of an integration by integration alias
///
Task Empty(string alias);
///
/// Get an integration by integration alias
///
Task Load(string alias);
///
/// Get all integrations by a certain tag
///
Task> LoadByTag(string tag);
///
/// Check if there are any activated integrations for a certain tag
///
Task Any(string tag);
///
/// Get the change vector for a model (Proxy to IAsyncDocumentSession.GetChangeVectorFor<>)
///
string GetChangeToken(Integration model);
///
/// Creates a new integration
///
Task> Create(Integration model);
///
/// Updates an integration
///
Task> Update(Integration model);
///
/// Activates a configured integration
///
Task> Activate(string alias);
///
/// Disables a configured integration
///
Task> Deactivate(string alias);
///
/// Deletes configuration of an integration and disables it
///
Task> Delete(string alias);
}