Files
OTSSignsOrchestrator/OTSSignsOrchestrator.Core/Services/XiboApiService.cs

539 lines
25 KiB
C#
Raw Normal View History

using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using OTSSignsOrchestrator.Core.Configuration;
namespace OTSSignsOrchestrator.Core.Services;
/// <summary>
/// Provides connectivity testing and administrative operations against deployed Xibo CMS instances.
///
/// Bootstrap flow:
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
/// 1. After a new instance is deployed, <see cref="PostInstanceInitService"/> calls
/// <see cref="LoginAsync"/> with the default Xibo admin credentials to obtain a session cookie.
/// 2. Subsequent operations (create user, register OAuth2 app, set theme) authenticate
/// using that session cookie — no pre-existing OAuth2 application is required.
/// </summary>
public class XiboApiService
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly XiboOptions _options;
private readonly ILogger<XiboApiService> _logger;
public XiboApiService(
IHttpClientFactory httpClientFactory,
IOptions<XiboOptions> options,
ILogger<XiboApiService> logger)
{
_httpClientFactory = httpClientFactory;
_options = options.Value;
_logger = logger;
}
// ─────────────────────────────────────────────────────────────────────────
// Connection test
// ─────────────────────────────────────────────────────────────────────────
public async Task<XiboTestResult> TestConnectionAsync(string instanceUrl, string clientId, string clientSecret)
{
_logger.LogInformation("Testing Xibo connection to {InstanceUrl}", instanceUrl);
var client = _httpClientFactory.CreateClient("XiboApi");
client.Timeout = TimeSpan.FromSeconds(_options.TestConnectionTimeoutSeconds);
try
{
var token = await GetTokenAsync(instanceUrl, clientId, clientSecret, client);
_logger.LogInformation("Xibo connection test succeeded for {InstanceUrl}", instanceUrl);
return new XiboTestResult
{
IsValid = true,
Message = "Connected successfully.",
HttpStatus = 200
};
}
catch (XiboAuthException ex)
{
return new XiboTestResult
{
IsValid = false,
Message = ex.Message,
HttpStatus = ex.HttpStatus
};
}
catch (TaskCanceledException)
{
return new XiboTestResult { IsValid = false, Message = "Connection timed out." };
}
catch (HttpRequestException ex)
{
return new XiboTestResult { IsValid = false, Message = $"Cannot reach Xibo instance: {ex.Message}" };
}
}
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
// ─────────────────────────────────────────────────────────────────────────
// Session login
// ─────────────────────────────────────────────────────────────────────────
/// <summary>
/// Obtains a Bearer access token using the OAuth2 <c>client_credentials</c> grant.
/// The caller must have previously created an OAuth2 application in the Xibo CMS
/// admin UI and provide the resulting <paramref name="clientId"/> and
/// <paramref name="clientSecret"/>.
/// </summary>
public async Task<string> LoginAsync(string instanceUrl, string clientId, string clientSecret)
{
var baseUrl = instanceUrl.TrimEnd('/');
var tokenUrl = $"{baseUrl}/api/authorize/access_token";
var client = _httpClientFactory.CreateClient("XiboApi");
client.Timeout = TimeSpan.FromSeconds(30);
var form = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "client_credentials"),
new KeyValuePair<string, string>("client_id", clientId),
new KeyValuePair<string, string>("client_secret", clientSecret),
});
var response = await client.PostAsync(tokenUrl, form);
if (!response.IsSuccessStatusCode)
{
var body = await response.Content.ReadAsStringAsync();
throw new XiboAuthException(
$"Xibo client_credentials login failed for client '{clientId}': HTTP {(int)response.StatusCode} — {body}",
(int)response.StatusCode);
}
using var doc = await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync());
var accessToken = doc.RootElement.GetProperty("access_token").GetString()
?? throw new InvalidOperationException("access_token missing in Xibo token response.");
_logger.LogInformation("Xibo access token obtained for client '{ClientId}' at {Url}", clientId, baseUrl);
return accessToken;
}
// ─────────────────────────────────────────────────────────────────────────
// Health / readiness
// ─────────────────────────────────────────────────────────────────────────
/// <summary>
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
/// Polls <paramref name="instanceUrl"/> until Xibo is genuinely online by calling
/// the public <c>/about</c> page (no auth required) and confirming the response body
/// contains the word "Xibo". <paramref name="instanceUrl"/> must already include the
/// instance sub-path (e.g. <c>https://ots.ots-signs.com/ots</c>).
/// The JSON <c>/api/about</c> and <c>/api/clock</c> endpoints both require auth, so
/// the HTML about page is the only reliable unauthenticated Xibo-specific probe.
/// A plain 200 from a proxy is not sufficient — the body must contain "Xibo".
/// </summary>
public async Task<bool> WaitForReadyAsync(
string instanceUrl,
TimeSpan timeout,
CancellationToken ct = default)
{
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
var deadline = DateTime.UtcNow + timeout;
var baseUrl = instanceUrl.TrimEnd('/');
var client = _httpClientFactory.CreateClient("XiboHealth");
client.Timeout = TimeSpan.FromSeconds(10);
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
var healthUrl = $"{baseUrl}/about";
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
_logger.LogInformation("Waiting for Xibo instance to become ready: {Url}", healthUrl);
while (DateTime.UtcNow < deadline && !ct.IsCancellationRequested)
{
try
{
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
var response = await client.GetAsync(healthUrl, ct);
if (response.IsSuccessStatusCode)
{
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
// The public /about page always contains the word "Xibo" in its HTML
// when Xibo itself is serving responses. A proxy 200 page will not.
var body = await response.Content.ReadAsStringAsync(ct);
if (body.Contains("Xibo", StringComparison.OrdinalIgnoreCase))
{
_logger.LogInformation("Xibo is ready: {Url}", healthUrl);
return true;
}
_logger.LogDebug("About page returned 200 but body lacks 'Xibo' — proxy may be up but Xibo not yet ready");
}
}
catch { /* not yet available */ }
await Task.Delay(TimeSpan.FromSeconds(10), ct);
}
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
_logger.LogWarning("Xibo did not become ready within {Timeout}: {Url}", timeout, healthUrl);
return false;
}
// ─────────────────────────────────────────────────────────────────────────
// Admin user
// ─────────────────────────────────────────────────────────────────────────
/// <summary>
/// Creates a new super-admin user in the Xibo instance and returns its numeric ID.
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
/// Authenticates using the supplied <paramref name="accessToken"/> (Bearer token
/// obtained from <see cref="LoginAsync"/>).
/// </summary>
public async Task<int> CreateAdminUserAsync(
string instanceUrl,
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
string accessToken,
string newUsername,
string newPassword,
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
string email,
int groupId)
{
var client = _httpClientFactory.CreateClient("XiboApi");
var baseUrl = instanceUrl.TrimEnd('/');
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
SetBearer(client, accessToken);
var form = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("userName", newUsername),
new KeyValuePair<string, string>("email", email),
new KeyValuePair<string, string>("userTypeId", "1"), // Super Admin
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
new KeyValuePair<string, string>("homePageId", "icondashboard.view"),
new KeyValuePair<string, string>("libraryQuota", "0"),
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
new KeyValuePair<string, string>("groupId", groupId.ToString()),
new KeyValuePair<string, string>("password", newPassword),
new KeyValuePair<string, string>("newUserWizard", "0"),
new KeyValuePair<string, string>("hideNavigation", "0"),
new KeyValuePair<string, string>("isPasswordChangeRequired", "0"),
});
var response = await client.PostAsync($"{baseUrl}/api/user", form);
await EnsureSuccessAsync(response, "create Xibo admin user");
using var doc = await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync());
var userId = doc.RootElement.GetProperty("userId").GetInt32();
_logger.LogInformation("Xibo admin user created: username={Username}, userId={UserId}", newUsername, userId);
return userId;
}
/// <summary>
/// Changes the password of an existing Xibo user.
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
/// Authenticates using the supplied <paramref name="accessToken"/> (Bearer token
/// obtained from <see cref="LoginAsync"/>).
/// </summary>
public async Task RotateUserPasswordAsync(
string instanceUrl,
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
string accessToken,
int userId,
string newPassword)
{
var client = _httpClientFactory.CreateClient("XiboApi");
var baseUrl = instanceUrl.TrimEnd('/');
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
SetBearer(client, accessToken);
var form = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("newUserPassword", newPassword),
new KeyValuePair<string, string>("retypeNewUserPassword", newPassword),
});
var response = await client.PutAsync($"{baseUrl}/api/user/{userId}", form);
await EnsureSuccessAsync(response, "rotate Xibo user password");
_logger.LogInformation("Xibo user password rotated: userId={UserId}", userId);
}
// ─────────────────────────────────────────────────────────────────────────
// OAuth2 application
// ─────────────────────────────────────────────────────────────────────────
/// <summary>
/// Registers a new client_credentials OAuth2 application in Xibo and returns
/// the generated client_id and client_secret.
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
/// Authenticates using the supplied <paramref name="accessToken"/> (Bearer token
/// obtained from <see cref="LoginAsync"/>).
/// </summary>
public async Task<(string ClientId, string ClientSecret)> RegisterOAuthClientAsync(
string instanceUrl,
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
string accessToken,
string appName)
{
var client = _httpClientFactory.CreateClient("XiboApi");
var baseUrl = instanceUrl.TrimEnd('/');
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
SetBearer(client, accessToken);
var form = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("name", appName),
new KeyValuePair<string, string>("clientId", Guid.NewGuid().ToString("N")),
new KeyValuePair<string, string>("confidential", "1"),
new KeyValuePair<string, string>("authCode", "0"),
new KeyValuePair<string, string>("clientCredentials", "1"),
});
var response = await client.PostAsync($"{baseUrl}/api/application", form);
await EnsureSuccessAsync(response, "register Xibo OAuth2 application");
using var doc = await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync());
var root = doc.RootElement;
var cid = root.GetProperty("key").GetString()
?? throw new InvalidOperationException("Xibo application 'key' missing in response.");
var secret = root.GetProperty("secret").GetString()
?? throw new InvalidOperationException("Xibo application 'secret' missing in response.");
_logger.LogInformation("Xibo OAuth2 application registered: name={Name}, clientId={ClientId}", appName, cid);
return (cid, secret);
}
// ─────────────────────────────────────────────────────────────────────────
// Theme
// ─────────────────────────────────────────────────────────────────────────
/// <summary>
/// Sets the active CMS theme by writing the THEME_FOLDER setting.
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
/// Authenticates using the supplied <paramref name="accessToken"/> (Bearer token
/// obtained from <see cref="LoginAsync"/>).
/// </summary>
public async Task SetThemeAsync(
string instanceUrl,
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
string accessToken,
string themeFolderName = "otssigns")
{
var client = _httpClientFactory.CreateClient("XiboApi");
var baseUrl = instanceUrl.TrimEnd('/');
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
SetBearer(client, accessToken);
// Xibo stores settings as an array: settings[THEME_FOLDER]=otssigns
var form = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("settings[THEME_FOLDER]", themeFolderName),
});
var response = await client.PostAsync($"{baseUrl}/api/admin/setting", form);
await EnsureSuccessAsync(response, "set Xibo theme");
_logger.LogInformation("Xibo theme set to: {Theme}", themeFolderName);
}
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
// ─────────────────────────────────────────────────────────────────────────
// User groups
// ─────────────────────────────────────────────────────────────────────────
/// <summary>
/// Creates a new user group and returns its numeric group ID.
/// </summary>
public async Task<int> CreateUserGroupAsync(
string instanceUrl,
string accessToken,
string groupName)
{
var client = _httpClientFactory.CreateClient("XiboApi");
var baseUrl = instanceUrl.TrimEnd('/');
SetBearer(client, accessToken);
var form = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("group", groupName),
new KeyValuePair<string, string>("libraryQuota", "0"),
});
var response = await client.PostAsync($"{baseUrl}/api/group", form);
await EnsureSuccessAsync(response, "create Xibo user group");
// The response is an array containing the created group
using var doc = await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync());
var root = doc.RootElement;
// Response may be an array or a single object depending on Xibo version
var groupEl = root.ValueKind == JsonValueKind.Array ? root[0] : root;
var gid = groupEl.GetProperty("groupId").GetInt32();
_logger.LogInformation("Xibo user group created: name={Name}, groupId={GroupId}", groupName, gid);
return gid;
}
/// <summary>
/// Assigns a user to a Xibo user group.
/// </summary>
public async Task AssignUserToGroupAsync(
string instanceUrl,
string accessToken,
int groupId,
int userId)
{
var client = _httpClientFactory.CreateClient("XiboApi");
var baseUrl = instanceUrl.TrimEnd('/');
SetBearer(client, accessToken);
var form = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("userId[]", userId.ToString()),
});
var response = await client.PostAsync($"{baseUrl}/api/group/members/assign/{groupId}", form);
await EnsureSuccessAsync(response, $"assign user {userId} to group {groupId}");
_logger.LogInformation("User {UserId} assigned to group {GroupId}", userId, groupId);
}
// ─────────────────────────────────────────────────────────────────────────
// User lookup / update / deletion
// ─────────────────────────────────────────────────────────────────────────
/// <summary>
/// Updates an existing Xibo user's username, password, and email.
/// Authenticates using the supplied <paramref name="accessToken"/>.
/// </summary>
public async Task UpdateUserAsync(
string instanceUrl,
string accessToken,
int userId,
string newUsername,
string newPassword,
string email)
{
var client = _httpClientFactory.CreateClient("XiboApi");
var baseUrl = instanceUrl.TrimEnd('/');
SetBearer(client, accessToken);
var form = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("userName", newUsername),
new KeyValuePair<string, string>("email", email),
new KeyValuePair<string, string>("userTypeId", "1"),
new KeyValuePair<string, string>("homePageId", "icondashboard.view"),
new KeyValuePair<string, string>("libraryQuota", "0"),
new KeyValuePair<string, string>("newPassword", newPassword),
new KeyValuePair<string, string>("retypeNewPassword", newPassword),
new KeyValuePair<string, string>("newUserWizard", "0"),
new KeyValuePair<string, string>("hideNavigation", "0"),
new KeyValuePair<string, string>("isPasswordChangeRequired", "0"),
});
var response = await client.PutAsync($"{baseUrl}/api/user/{userId}", form);
await EnsureSuccessAsync(response, $"update Xibo user {userId}");
_logger.LogInformation("Xibo user updated: userId={UserId}, newUsername={Username}", userId, newUsername);
}
/// <summary>
/// Finds a Xibo user by username and returns their numeric user ID.
/// Authenticates using the supplied <paramref name="accessToken"/>.
/// </summary>
public async Task<int> GetUserIdByNameAsync(string instanceUrl, string accessToken, string username)
{
var client = _httpClientFactory.CreateClient("XiboApi");
var baseUrl = instanceUrl.TrimEnd('/');
SetBearer(client, accessToken);
var response = await client.GetAsync($"{baseUrl}/api/user?userName={Uri.EscapeDataString(username)}");
await EnsureSuccessAsync(response, "look up Xibo user by name");
using var doc = await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync());
foreach (var user in doc.RootElement.EnumerateArray())
{
var name = user.GetProperty("userName").GetString();
if (string.Equals(name, username, StringComparison.OrdinalIgnoreCase))
return user.GetProperty("userId").GetInt32();
}
throw new InvalidOperationException(
$"Xibo user '{username}' not found.");
}
/// <summary>
/// Deletes a Xibo user by their numeric user ID.
/// Authenticates using the supplied <paramref name="accessToken"/>.
/// </summary>
public async Task DeleteUserAsync(string instanceUrl, string accessToken, int userId)
{
var client = _httpClientFactory.CreateClient("XiboApi");
var baseUrl = instanceUrl.TrimEnd('/');
SetBearer(client, accessToken);
var response = await client.DeleteAsync($"{baseUrl}/api/user/{userId}");
await EnsureSuccessAsync(response, $"delete Xibo user {userId}");
_logger.LogInformation("Xibo user deleted: userId={UserId}", userId);
}
// ─────────────────────────────────────────────────────────────────────────
// Helpers
// ─────────────────────────────────────────────────────────────────────────
private async Task<string> GetTokenAsync(
string baseUrl,
string clientId,
string clientSecret,
HttpClient client)
{
var tokenUrl = $"{baseUrl}/api/authorize/access_token";
var form = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "client_credentials"),
new KeyValuePair<string, string>("client_id", clientId),
new KeyValuePair<string, string>("client_secret", clientSecret),
});
var response = await client.PostAsync(tokenUrl, form);
if (!response.IsSuccessStatusCode)
{
throw new XiboAuthException(
response.StatusCode switch
{
System.Net.HttpStatusCode.Unauthorized => "Invalid Xibo credentials.",
System.Net.HttpStatusCode.Forbidden => "User lacks API permissions.",
System.Net.HttpStatusCode.ServiceUnavailable => "Xibo instance not ready.",
_ => $"Unexpected response: {(int)response.StatusCode}"
},
(int)response.StatusCode);
}
using var doc = await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync());
var aToken = doc.RootElement.GetProperty("access_token").GetString()
?? throw new InvalidOperationException("access_token missing in Xibo token response.");
return aToken;
}
private static void SetBearer(HttpClient client, string token)
=> client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
feat: Implement container logs functionality in InstancesViewModel - Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
2026-02-25 17:39:17 -05:00
private static async Task EnsureSuccessAsync(HttpResponseMessage response, string operation)
{
if (!response.IsSuccessStatusCode)
{
var body = await response.Content.ReadAsStringAsync();
throw new InvalidOperationException(
$"Xibo API call '{operation}' failed: {(int)response.StatusCode} — {body}");
}
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Result / exception types
// ─────────────────────────────────────────────────────────────────────────────
public class XiboTestResult
{
public bool IsValid { get; set; }
public string Message { get; set; } = string.Empty;
public int HttpStatus { get; set; }
}
public class XiboAuthException : Exception
{
public int HttpStatus { get; }
public XiboAuthException(string message, int httpStatus) : base(message)
=> HttpStatus = httpStatus;
}