using System.Net.Http.Json; using System.Text; using System.Text.Json; namespace SilverLabs.Website.Services; public class ProvisioningService { private readonly IHttpClientFactory _httpClientFactory; private readonly ILogger _logger; public ProvisioningService(IHttpClientFactory httpClientFactory, ILogger logger) { _httpClientFactory = httpClientFactory; _logger = logger; } public async Task<(bool Success, string Message)> ApproveApplicationAsync( string ticketId, string username, string email, string fullName) { var results = new List(); var allSuccess = true; // SilverDESK user already exists (created at application time) // Only provision external services // 1. Create Mattermost user var (mmOk, mmMsg) = await CreateMattermostUserAsync(username, email, fullName); results.Add($"Mattermost: {mmMsg}"); if (!mmOk) allSuccess = false; // 2. Create Mailcow mailbox var (mailOk, mailMsg) = await CreateMailcowMailboxAsync(username, fullName); results.Add($"Mailcow: {mailMsg}"); if (!mailOk) allSuccess = false; // 3. Update the DeveloperApplication record in SilverDESK var (updateOk, updateMsg) = await UpdateApplicationStatusAsync(ticketId, mmOk, mailOk); results.Add($"Application record: {updateMsg}"); if (!updateOk) allSuccess = false; var summary = string.Join("; ", results); _logger.LogInformation("Provisioning for {Username} (ticket {TicketId}): {Summary}", username, ticketId, summary); return (allSuccess, summary); } private async Task<(bool Success, string Message)> UpdateApplicationStatusAsync( string ticketId, bool mattermostProvisioned, bool mailcowProvisioned) { try { var client = _httpClientFactory.CreateClient("SilverDesk"); // Look up the application by ticketId var lookupResponse = await client.GetAsync($"/api/developer-program/applications?ticketId={ticketId}"); if (!lookupResponse.IsSuccessStatusCode) { var body = await lookupResponse.Content.ReadAsStringAsync(); _logger.LogWarning("Failed to look up application by ticket {TicketId}: {Status} {Body}", ticketId, lookupResponse.StatusCode, body); return (false, $"Lookup failed ({lookupResponse.StatusCode})"); } var apps = await lookupResponse.Content.ReadFromJsonAsync(); if (apps.GetArrayLength() == 0) { _logger.LogWarning("No application found for ticket {TicketId}", ticketId); return (false, "No application found for ticket"); } var appId = apps[0].GetProperty("id").GetString(); // Update the application status to Approved with provisioning flags var updatePayload = new { status = 1, // ApplicationStatus.Approved mattermostProvisioned, mailcowProvisioned }; var updateResponse = await client.PutAsJsonAsync($"/api/developer-program/applications/{appId}", updatePayload); if (updateResponse.IsSuccessStatusCode) { _logger.LogInformation("Application {AppId} updated to Approved for ticket {TicketId}", appId, ticketId); return (true, "Updated to Approved"); } var updateBody = await updateResponse.Content.ReadAsStringAsync(); _logger.LogWarning("Failed to update application {AppId}: {Status} {Body}", appId, updateResponse.StatusCode, updateBody); return (false, $"Update failed ({updateResponse.StatusCode})"); } catch (Exception ex) { _logger.LogError(ex, "Error updating application status for ticket {TicketId}", ticketId); return (false, $"Error: {ex.Message}"); } } public async Task<(bool Success, string Message)> CreateSilverDeskUserAsync(string username, string email, string fullName) { try { var client = _httpClientFactory.CreateClient("SilverDesk"); var payload = new { username, email, fullName, password = Guid.NewGuid().ToString("N")[..16] + "!A1" }; var json = JsonSerializer.Serialize(payload); var content = new StringContent(json, Encoding.UTF8, "application/json"); var response = await client.PostAsync("/api/users", content); if (response.IsSuccessStatusCode) return (true, "User created"); var body = await response.Content.ReadAsStringAsync(); _logger.LogError("SilverDESK user creation failed: {Status} {Body}", response.StatusCode, body); return (false, $"Failed ({response.StatusCode})"); } catch (Exception ex) { _logger.LogError(ex, "SilverDESK user creation error for {Username}", username); return (false, $"Error: {ex.Message}"); } } public async Task<(bool Success, string Message)> CreateMattermostUserAsync(string username, string email, string fullName) { try { var client = _httpClientFactory.CreateClient("Mattermost"); var nameParts = fullName.Split(' ', 2); var payload = new { email, username, first_name = nameParts[0], last_name = nameParts.Length > 1 ? nameParts[1] : "", password = Guid.NewGuid().ToString("N")[..16] + "!A1" // Temporary password }; var json = JsonSerializer.Serialize(payload); var content = new StringContent(json, Encoding.UTF8, "application/json"); var response = await client.PostAsync("/api/v4/users", content); if (response.IsSuccessStatusCode) return (true, "User created"); var body = await response.Content.ReadAsStringAsync(); _logger.LogError("Mattermost user creation failed: {Status} {Body}", response.StatusCode, body); return (false, $"Failed ({response.StatusCode})"); } catch (Exception ex) { _logger.LogError(ex, "Mattermost user creation error for {Username}", username); return (false, $"Error: {ex.Message}"); } } public async Task<(bool Success, string Message)> CreateMailcowMailboxAsync(string username, string fullName) { try { var client = _httpClientFactory.CreateClient("Mailcow"); var tempPassword = Guid.NewGuid().ToString("N")[..16] + "!A1"; var payload = new { local_part = username, domain = "silverlabs.uk", name = fullName, password = tempPassword, password2 = tempPassword, quota = 1024, // 1GB active = 1, force_pw_update = 1 }; var json = JsonSerializer.Serialize(payload); var content = new StringContent(json, Encoding.UTF8, "application/json"); var response = await client.PostAsync("/api/v1/add/mailbox", content); if (response.IsSuccessStatusCode) return (true, "Mailbox created"); var body = await response.Content.ReadAsStringAsync(); _logger.LogError("Mailcow mailbox creation failed: {Status} {Body}", response.StatusCode, body); return (false, $"Failed ({response.StatusCode})"); } catch (Exception ex) { _logger.LogError(ex, "Mailcow mailbox creation error for {Username}", username); return (false, $"Error: {ex.Message}"); } } }