Adding Admin API

This commit is contained in:
2026-04-08 14:25:10 -07:00
parent 0ba076b650
commit b9a04df861
67 changed files with 3316 additions and 74 deletions

View File

@@ -0,0 +1,14 @@
using FluentValidation;
namespace MicCheck.Api.Webhooks;
public record CreateWebhookRequest(string Url, string? Secret, bool Enabled);
public class CreateWebhookRequestValidator : AbstractValidator<CreateWebhookRequest>
{
public CreateWebhookRequestValidator()
{
RuleFor(x => x.Url).NotEmpty().MaximumLength(500).Must(u => Uri.TryCreate(u, UriKind.Absolute, out _))
.WithMessage("Url must be a valid absolute URL.");
}
}

View File

@@ -0,0 +1,23 @@
namespace MicCheck.Api.Webhooks;
public record WebhookResponse(
int Id,
string Url,
string? Secret,
string Scope,
bool Enabled,
int? EnvironmentId,
int? OrganizationId,
DateTimeOffset CreatedAt
)
{
public static WebhookResponse From(Webhook webhook) => new(
webhook.Id,
webhook.Url,
webhook.Secret,
webhook.Scope.ToString(),
webhook.Enabled,
webhook.EnvironmentId,
webhook.OrganizationId,
webhook.CreatedAt);
}

View File

@@ -0,0 +1,56 @@
using MicCheck.Api.Data;
using Microsoft.EntityFrameworkCore;
namespace MicCheck.Api.Webhooks;
public class WebhookService(MicCheckDbContext db)
{
public async Task<IReadOnlyList<Webhook>> ListByEnvironmentAsync(int environmentId, CancellationToken ct = default)
{
return await db.Webhooks
.Where(w => w.EnvironmentId == environmentId)
.ToListAsync(ct);
}
public async Task<Webhook?> FindByIdAsync(int id, CancellationToken ct = default)
{
return await db.Webhooks.FirstOrDefaultAsync(w => w.Id == id, ct);
}
public async Task<Webhook> CreateAsync(int environmentId, string url, string? secret, bool enabled, CancellationToken ct = default)
{
var webhook = new Webhook
{
Url = url,
Secret = secret,
Scope = WebhookScope.Environment,
EnvironmentId = environmentId,
Enabled = enabled,
CreatedAt = DateTimeOffset.UtcNow
};
db.Webhooks.Add(webhook);
await db.SaveChangesAsync(ct);
return webhook;
}
public async Task<Webhook> UpdateAsync(int id, string url, string? secret, bool enabled, CancellationToken ct = default)
{
var webhook = await db.Webhooks.FirstOrDefaultAsync(w => w.Id == id, ct)
?? throw new KeyNotFoundException($"Webhook {id} not found.");
webhook.Url = url;
webhook.Secret = secret;
webhook.Enabled = enabled;
await db.SaveChangesAsync(ct);
return webhook;
}
public async Task DeleteAsync(int id, CancellationToken ct = default)
{
var webhook = await db.Webhooks.FirstOrDefaultAsync(w => w.Id == id, ct);
if (webhook is null) return;
db.Webhooks.Remove(webhook);
await db.SaveChangesAsync(ct);
}
}