Add developer application page with form submission that creates tickets in SilverDESK. Includes provisioning service scaffolding for Mattermost, Mailcow, and Gitea account creation. Fixes API key header casing (X-API-Key) and ticket payload to match SilverDESK's CreateTicketDto contract. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
157 lines
6.2 KiB
C#
157 lines
6.2 KiB
C#
using System.Text;
|
|
using System.Text.Json;
|
|
|
|
namespace SilverLabs.Website.Services;
|
|
|
|
public class ProvisioningService
|
|
{
|
|
private readonly IHttpClientFactory _httpClientFactory;
|
|
private readonly ILogger<ProvisioningService> _logger;
|
|
|
|
public ProvisioningService(IHttpClientFactory httpClientFactory, ILogger<ProvisioningService> logger)
|
|
{
|
|
_httpClientFactory = httpClientFactory;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<(bool Success, string Message)> ApproveApplicationAsync(
|
|
int ticketId, string username, string email, string fullName)
|
|
{
|
|
var results = new List<string>();
|
|
var allSuccess = true;
|
|
|
|
// 1. Create SilverDESK user
|
|
var (deskOk, deskMsg) = await CreateSilverDeskUserAsync(username, email, fullName);
|
|
results.Add($"SilverDESK: {deskMsg}");
|
|
if (!deskOk) allSuccess = false;
|
|
|
|
// 2. Create Mattermost user
|
|
var (mmOk, mmMsg) = await CreateMattermostUserAsync(username, email, fullName);
|
|
results.Add($"Mattermost: {mmMsg}");
|
|
if (!mmOk) allSuccess = false;
|
|
|
|
// 3. Create Mailcow mailbox
|
|
var (mailOk, mailMsg) = await CreateMailcowMailboxAsync(username, fullName);
|
|
results.Add($"Mailcow: {mailMsg}");
|
|
if (!mailOk) allSuccess = false;
|
|
|
|
// 4. Update SilverDESK ticket
|
|
if (allSuccess)
|
|
{
|
|
await UpdateTicketStatusAsync(ticketId, "approved", string.Join("\n", results));
|
|
}
|
|
|
|
var summary = string.Join("; ", results);
|
|
_logger.LogInformation("Provisioning for {Username}: {Summary}", username, summary);
|
|
|
|
return (allSuccess, summary);
|
|
}
|
|
|
|
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, name = fullName, role = "user" };
|
|
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 payload = new
|
|
{
|
|
local_part = username,
|
|
domain = "silverlabs.uk",
|
|
name = fullName,
|
|
password = Guid.NewGuid().ToString("N")[..16] + "!A1", // Temporary password
|
|
password2 = "",
|
|
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}");
|
|
}
|
|
}
|
|
|
|
private async Task UpdateTicketStatusAsync(int ticketId, string status, string note)
|
|
{
|
|
try
|
|
{
|
|
var client = _httpClientFactory.CreateClient("SilverDesk");
|
|
var payload = new { status, note = $"Application approved. Provisioning results:\n{note}" };
|
|
var json = JsonSerializer.Serialize(payload);
|
|
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
|
|
|
await client.PutAsync($"/api/tickets/{ticketId}", content);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Failed to update ticket {TicketId} status", ticketId);
|
|
}
|
|
}
|
|
}
|