Add device settings management and web panel sync API
Features:
- New DeviceSettings admin page at /devicesettings
- Manage device server configurations (URL, mode, deviceId)
- 3 new API endpoints for APK sync functionality
- UserSettings database model with SQLite storage
Implementation:
- ServerSettingsController.cs with getUserSettings, updateUserSettings, getAllUserSettings
- DeviceSettings.cshtml Razor page with add/edit/delete UI
- DeviceSettings.cshtml.cs page model with CRUD operations
- UserSettings model added to ApiModels.cs
- UserSettings DbSet added to RR3DbContext
- EF Core migration: 20260219180936_AddUserSettings
- Link added to Admin dashboard
API Endpoints:
- GET /api/settings/getUserSettings?deviceId={id} - APK sync endpoint
- POST /api/settings/updateUserSettings - Web panel update
- GET /api/settings/getAllUserSettings - Admin list view
Database Schema:
- UserSettings table (Id, DeviceId, ServerUrl, Mode, LastUpdated)
- SQLite storage with EF Core migrations
Integration:
- Works with APK SettingsActivity sync button
- Real-time configuration updates
- Emoji logging for all operations
- Device-specific server URL management
Usage:
1. Admin configures device settings at /devicesettings
2. User opens RR3 APK and taps Sync from Web Panel
3. APK downloads settings via API
4. Settings saved to SharedPreferences
5. Game restart applies configuration
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
174
RR3CommunityServer/Controllers/ServerSettingsController.cs
Normal file
174
RR3CommunityServer/Controllers/ServerSettingsController.cs
Normal file
@@ -0,0 +1,174 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using RR3CommunityServer.Data;
|
||||
using RR3CommunityServer.Models;
|
||||
|
||||
namespace RR3CommunityServer.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/settings")]
|
||||
public class ServerSettingsController : ControllerBase
|
||||
{
|
||||
private readonly RR3DbContext _context;
|
||||
private readonly ILogger<ServerSettingsController> _logger;
|
||||
|
||||
public ServerSettingsController(RR3DbContext context, ILogger<ServerSettingsController> logger)
|
||||
{
|
||||
_context = context;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get user settings (called by APK sync button)
|
||||
/// GET /api/settings/getUserSettings?deviceId=xxx
|
||||
/// </summary>
|
||||
[HttpGet("getUserSettings")]
|
||||
public async Task<ActionResult<UserSettingsResponse>> GetUserSettings([FromQuery] string? deviceId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(deviceId))
|
||||
{
|
||||
_logger.LogWarning("GetUserSettings: No deviceId provided");
|
||||
return BadRequest(new { error = "deviceId is required" });
|
||||
}
|
||||
|
||||
_logger.LogInformation($"🔄 GetUserSettings: deviceId={deviceId}");
|
||||
|
||||
var settings = await _context.UserSettings
|
||||
.Where(s => s.DeviceId == deviceId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (settings == null)
|
||||
{
|
||||
_logger.LogInformation($"⚠️ No settings found for deviceId={deviceId}, returning defaults");
|
||||
return Ok(new UserSettingsResponse
|
||||
{
|
||||
mode = "offline",
|
||||
serverUrl = "",
|
||||
message = "No settings found, using defaults"
|
||||
});
|
||||
}
|
||||
|
||||
_logger.LogInformation($"✅ Found settings: mode={settings.Mode}, url={settings.ServerUrl}");
|
||||
return Ok(new UserSettingsResponse
|
||||
{
|
||||
mode = settings.Mode,
|
||||
serverUrl = settings.ServerUrl,
|
||||
message = "Settings retrieved successfully"
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "❌ Error in GetUserSettings");
|
||||
return StatusCode(500, new { error = "Internal server error" });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update user settings (called by web panel)
|
||||
/// POST /api/settings/updateUserSettings
|
||||
/// Body: { "deviceId": "xxx", "mode": "online", "serverUrl": "https://example.com:8443" }
|
||||
/// </summary>
|
||||
[HttpPost("updateUserSettings")]
|
||||
public async Task<ActionResult<UpdateSettingsResponse>> UpdateUserSettings([FromBody] UpdateUserSettingsRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(request.deviceId))
|
||||
{
|
||||
return BadRequest(new { error = "deviceId is required" });
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(request.mode))
|
||||
{
|
||||
return BadRequest(new { error = "mode is required" });
|
||||
}
|
||||
|
||||
_logger.LogInformation($"🔄 UpdateUserSettings: deviceId={request.deviceId}, mode={request.mode}, url={request.serverUrl}");
|
||||
|
||||
var settings = await _context.UserSettings
|
||||
.Where(s => s.DeviceId == request.deviceId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (settings == null)
|
||||
{
|
||||
// Create new settings
|
||||
settings = new UserSettings
|
||||
{
|
||||
DeviceId = request.deviceId,
|
||||
Mode = request.mode,
|
||||
ServerUrl = request.serverUrl ?? "",
|
||||
LastUpdated = DateTime.UtcNow
|
||||
};
|
||||
_context.UserSettings.Add(settings);
|
||||
_logger.LogInformation($"➕ Created new settings for deviceId={request.deviceId}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update existing settings
|
||||
settings.Mode = request.mode;
|
||||
settings.ServerUrl = request.serverUrl ?? "";
|
||||
settings.LastUpdated = DateTime.UtcNow;
|
||||
_logger.LogInformation($"✏️ Updated existing settings for deviceId={request.deviceId}");
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
return Ok(new UpdateSettingsResponse
|
||||
{
|
||||
success = true,
|
||||
message = "Settings updated successfully"
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "❌ Error in UpdateUserSettings");
|
||||
return StatusCode(500, new { error = "Internal server error" });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all user settings (for admin panel)
|
||||
/// GET /api/settings/getAllUserSettings
|
||||
/// </summary>
|
||||
[HttpGet("getAllUserSettings")]
|
||||
public async Task<ActionResult<List<UserSettings>>> GetAllUserSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
var allSettings = await _context.UserSettings
|
||||
.OrderByDescending(s => s.LastUpdated)
|
||||
.ToListAsync();
|
||||
|
||||
_logger.LogInformation($"📋 Retrieved {allSettings.Count} user settings");
|
||||
return Ok(allSettings);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "❌ Error in GetAllUserSettings");
|
||||
return StatusCode(500, new { error = "Internal server error" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Response models
|
||||
public class UserSettingsResponse
|
||||
{
|
||||
public string mode { get; set; } = "offline";
|
||||
public string serverUrl { get; set; } = "";
|
||||
public string? message { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateUserSettingsRequest
|
||||
{
|
||||
public string deviceId { get; set; } = string.Empty;
|
||||
public string mode { get; set; } = "offline";
|
||||
public string? serverUrl { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateSettingsResponse
|
||||
{
|
||||
public bool success { get; set; }
|
||||
public string? message { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user