using System.Text; using API.Controllers.DTOs; using API.Controllers.Requests; using API.Schema.NotificationsContext; using Asp.Versioning; using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using static Microsoft.AspNetCore.Http.StatusCodes; // ReSharper disable InconsistentNaming namespace API.Controllers; [ApiVersion(2)] [ApiController] [Produces("application/json")] [Route("v{v:apiVersion}/[controller]")] public class NotificationConnectorController(NotificationsContext context) : Controller { /// /// Gets all configured /// /// /// Error during Database Operation [HttpGet] [ProducesResponseType>(Status200OK, "application/json")] [ProducesResponseType(Status500InternalServerError)] public async Task>, InternalServerError>> GetAllConnectors () { if(await context.NotificationConnectors.ToListAsync(HttpContext.RequestAborted) is not { } result) return TypedResults.InternalServerError(); List notificationConnectors = result.Select(n => new NotificationConnector(n.Name, n.Url, n.HttpMethod, n.Body, n.Headers)).ToList(); return TypedResults.Ok(notificationConnectors); } /// /// Returns with requested Name /// /// .Name /// /// with not found [HttpGet("{Name}")] [ProducesResponseType(Status200OK, "application/json")] [ProducesResponseType(Status404NotFound, "text/plain")] public async Task, NotFound>> GetConnector (string Name) { if (await context.NotificationConnectors.FirstOrDefaultAsync(c => c.Name == Name, HttpContext.RequestAborted) is not { } connector) return TypedResults.NotFound(nameof(Name)); NotificationConnector notificationConnector = new NotificationConnector(connector.Name, connector.Url, connector.HttpMethod, connector.Body, connector.Headers); return TypedResults.Ok(notificationConnector); } /// /// Creates a new /// /// Formatting placeholders: "%title" and "%text" can be placed in url, header-values and body and will be replaced when notifications are sent /// ID of the new /// Error during Database Operation [HttpPut] [ProducesResponseType(Status201Created, "text/plain")] [ProducesResponseType(Status500InternalServerError, "text/plain")] public async Task, InternalServerError>> CreateConnector ([FromBody]CreateNotificationConnectorRecord requestData) { // TODO validate data API.Schema.NotificationsContext.NotificationConnectors.NotificationConnector newConnector = new(requestData.Name, requestData.Url, requestData.Headers, requestData.HttpMethod, requestData.Body); context.NotificationConnectors.Add(newConnector); context.Notifications.Add(new ("Added new Notification Connector!", newConnector.Name, NotificationUrgency.High)); if(await context.Sync(HttpContext.RequestAborted) is { success: false } result) return TypedResults.InternalServerError(result.exceptionMessage); return TypedResults.Created(string.Empty, newConnector.Name); } /// /// Creates a new Gotify- /// /// Priority needs to be between 0 and 10 /// ID of the new /// Error during Database Operation [HttpPut("Gotify")] [ProducesResponseType(Status201Created, "text/plain")] [ProducesResponseType(Status500InternalServerError, "text/plain")] public async Task, InternalServerError>> CreateGotifyConnector ([FromBody]CreateGotifyConnectorRecord createGotifyConnectorData) { //TODO Validate Data CreateNotificationConnectorRecord gotifyConnector = new (createGotifyConnectorData.Name, createGotifyConnectorData.Url, "POST", $"{{\"message\": \"%text\", \"title\": \"%title\", \"Priority\": {createGotifyConnectorData.Priority}}}", new () { { "X-Gotify-Key", createGotifyConnectorData.AppToken } }); return await CreateConnector(gotifyConnector); } /// /// Creates a new Ntfy- /// /// Priority needs to be between 1 and 5 /// ID of the new /// Error during Database Operation [HttpPut("Ntfy")] [ProducesResponseType(Status201Created, "text/plain")] [ProducesResponseType(Status500InternalServerError, "text/plain")] public async Task, InternalServerError>> CreateNtfyConnector ([FromBody]CreateNtfyConnectorRecord createNtfyConnectorRecord) { //TODO Validate Data string authHeader = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{createNtfyConnectorRecord.Username}:{createNtfyConnectorRecord.Password}")); string auth = Convert.ToBase64String(Encoding.UTF8.GetBytes(authHeader)).Replace("=",""); CreateNotificationConnectorRecord ntfyConnector = new (createNtfyConnectorRecord.Name, $"{createNtfyConnectorRecord.Url}?auth={auth}", "POST", $"{{\"message\": \"%text\", \"title\": \"%title\", \"Priority\": {createNtfyConnectorRecord.Priority} \"Topic\": \"{createNtfyConnectorRecord.Topic}\"}}", new () {{"Authorization", auth}}); return await CreateConnector(ntfyConnector); } /// /// Creates a new Pushover- /// /// https://pushover.net/api /// ID of the new /// Error during Database Operation [HttpPut("Pushover")] [ProducesResponseType(Status201Created, "text/plain")] [ProducesResponseType(Status500InternalServerError, "text/plain")] public async Task, InternalServerError>> CreatePushoverConnector ([FromBody]CreatePushoverConnectorRecord createPushoverConnectorRecord) { //TODO Validate Data CreateNotificationConnectorRecord pushoverConnector = new (createPushoverConnectorRecord.Name, $"https://api.pushover.net/1/messages.json", "POST", $"{{\"token\": \"{createPushoverConnectorRecord.AppToken}\", \"user\": \"{createPushoverConnectorRecord.Username}\", \"message:\":\"%text\", \"%title\" }}", new ()); return await CreateConnector(pushoverConnector); } /// /// Deletes the with the requested Name /// /// .Name /// /// with Name not found /// Error during Database Operation [HttpDelete("{Name}")] [ProducesResponseType(Status200OK)] [ProducesResponseType(Status404NotFound, "text/plain")] [ProducesResponseType(Status500InternalServerError, "text/plain")] public async Task, InternalServerError>> DeleteConnector (string Name) { if (await context.NotificationConnectors.FirstOrDefaultAsync(c => c.Name == Name, HttpContext.RequestAborted) is not { } connector) return TypedResults.NotFound(nameof(Name)); context.NotificationConnectors.Remove(connector); if(await context.Sync(HttpContext.RequestAborted) is { success: false } result) return TypedResults.InternalServerError(result.exceptionMessage); return TypedResults.Ok(); } }