mirror of
https://github.com/SoPat712/allstarr.git
synced 2026-02-10 07:58:39 -05:00
Release 1.0.0 - Production ready
- Fixed AdminController export/import .env endpoints (moved from ConfigUpdateRequest class) - Added ArtistId and AlbumId to integration test fixtures - All 225 tests passing - Version set to 1.0.0 (semantic versioning) - MusicBrainz service ready for future ISRC-based matching (1.1.0) - Import/export handles full .env configuration with timestamped backups
This commit is contained in:
@@ -28,6 +28,7 @@ public class AdminController : ControllerBase
|
||||
private readonly DeezerSettings _deezerSettings;
|
||||
private readonly QobuzSettings _qobuzSettings;
|
||||
private readonly SquidWTFSettings _squidWtfSettings;
|
||||
private readonly MusicBrainzSettings _musicBrainzSettings;
|
||||
private readonly SpotifyApiClient _spotifyClient;
|
||||
private readonly SpotifyPlaylistFetcher _playlistFetcher;
|
||||
private readonly SpotifyTrackMatchingService? _matchingService;
|
||||
@@ -47,6 +48,7 @@ public class AdminController : ControllerBase
|
||||
IOptions<DeezerSettings> deezerSettings,
|
||||
IOptions<QobuzSettings> qobuzSettings,
|
||||
IOptions<SquidWTFSettings> squidWtfSettings,
|
||||
IOptions<MusicBrainzSettings> musicBrainzSettings,
|
||||
SpotifyApiClient spotifyClient,
|
||||
SpotifyPlaylistFetcher playlistFetcher,
|
||||
RedisCacheService cache,
|
||||
@@ -62,6 +64,7 @@ public class AdminController : ControllerBase
|
||||
_deezerSettings = deezerSettings.Value;
|
||||
_qobuzSettings = qobuzSettings.Value;
|
||||
_squidWtfSettings = squidWtfSettings.Value;
|
||||
_musicBrainzSettings = musicBrainzSettings.Value;
|
||||
_spotifyClient = spotifyClient;
|
||||
_playlistFetcher = playlistFetcher;
|
||||
_matchingService = matchingService;
|
||||
@@ -721,6 +724,14 @@ public class AdminController : ControllerBase
|
||||
squidWtf = new
|
||||
{
|
||||
quality = _squidWtfSettings.Quality ?? "LOSSLESS"
|
||||
},
|
||||
musicBrainz = new
|
||||
{
|
||||
enabled = _musicBrainzSettings.Enabled,
|
||||
username = _musicBrainzSettings.Username ?? "(not set)",
|
||||
password = MaskValue(_musicBrainzSettings.Password),
|
||||
baseUrl = _musicBrainzSettings.BaseUrl,
|
||||
rateLimitMs = _musicBrainzSettings.RateLimitMs
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1551,6 +1562,85 @@ public class AdminController : ControllerBase
|
||||
// Only allow alphanumeric, underscore, and must start with letter/underscore
|
||||
return Regex.IsMatch(key, @"^[A-Z_][A-Z0-9_]*$", RegexOptions.IgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export .env file for backup/transfer
|
||||
/// </summary>
|
||||
[HttpGet("export-env")]
|
||||
public IActionResult ExportEnv()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!System.IO.File.Exists(_envFilePath))
|
||||
{
|
||||
return NotFound(new { error = ".env file not found" });
|
||||
}
|
||||
|
||||
var envContent = System.IO.File.ReadAllText(_envFilePath);
|
||||
var bytes = System.Text.Encoding.UTF8.GetBytes(envContent);
|
||||
|
||||
return File(bytes, "text/plain", ".env");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to export .env file");
|
||||
return StatusCode(500, new { error = "Failed to export .env file", details = ex.Message });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Import .env file from upload
|
||||
/// </summary>
|
||||
[HttpPost("import-env")]
|
||||
public async Task<IActionResult> ImportEnv([FromForm] IFormFile file)
|
||||
{
|
||||
if (file == null || file.Length == 0)
|
||||
{
|
||||
return BadRequest(new { error = "No file provided" });
|
||||
}
|
||||
|
||||
if (!file.FileName.EndsWith(".env"))
|
||||
{
|
||||
return BadRequest(new { error = "File must be a .env file" });
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Read uploaded file
|
||||
using var reader = new StreamReader(file.OpenReadStream());
|
||||
var content = await reader.ReadToEndAsync();
|
||||
|
||||
// Validate it's a valid .env file (basic check)
|
||||
if (string.IsNullOrWhiteSpace(content))
|
||||
{
|
||||
return BadRequest(new { error = ".env file is empty" });
|
||||
}
|
||||
|
||||
// Backup existing .env
|
||||
if (System.IO.File.Exists(_envFilePath))
|
||||
{
|
||||
var backupPath = $"{_envFilePath}.backup.{DateTime.UtcNow:yyyyMMddHHmmss}";
|
||||
System.IO.File.Copy(_envFilePath, backupPath, true);
|
||||
_logger.LogInformation("Backed up existing .env to {BackupPath}", backupPath);
|
||||
}
|
||||
|
||||
// Write new .env file
|
||||
await System.IO.File.WriteAllTextAsync(_envFilePath, content);
|
||||
|
||||
_logger.LogInformation(".env file imported successfully");
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
success = true,
|
||||
message = ".env file imported successfully. Restart the application for changes to take effect."
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to import .env file");
|
||||
return StatusCode(500, new { error = "Failed to import .env file", details = ex.Message });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ConfigUpdateRequest
|
||||
|
||||
Reference in New Issue
Block a user