LANCommander/LANCommander.Server/Controllers/Api/SavesController.cs
2024-11-16 12:21:08 -06:00

181 lines
6 KiB
C#

using AutoMapper;
using LANCommander.Server.Data;
using LANCommander.Server.Data.Models;
using LANCommander.Server.Extensions;
using LANCommander.Server.Models;
using LANCommander.Server.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Runtime.Intrinsics.X86;
namespace LANCommander.Server.Controllers.Api
{
[Authorize(AuthenticationSchemes = "Bearer")]
[Route("api/[controller]")]
[ApiController]
public class SavesController : BaseApiController
{
private readonly IMapper Mapper;
private readonly GameService GameService;
private readonly GameSaveService GameSaveService;
private readonly UserService UserService;
public SavesController(
ILogger<SavesController> logger,
IMapper mapper,
GameService gameService,
GameSaveService gameSaveService,
UserService userService) : base(logger)
{
Mapper = mapper;
GameService = gameService;
GameSaveService = gameSaveService;
UserService = userService;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<SDK.Models.GameSave>>> GetAsync()
{
return Ok(Mapper.Map<IEnumerable<SDK.Models.GameSave>>(await GameSaveService.GetAsync()));
}
[HttpGet("{id}")]
public async Task<ActionResult<SDK.Models.GameSave>> GetAsync(Guid id)
{
var gameSave = await GameSaveService.GetAsync(id);
if (gameSave == null)
return NotFound();
return Ok(Mapper.Map<SDK.Models.GameSave>(gameSave));
}
[HttpGet("Game/{gameId}")]
public async Task<ActionResult<IEnumerable<SDK.Models.GameSave>>> GetGameSavesAsync(Guid gameId)
{
var user = await UserService.GetAsync(User?.Identity?.Name);
if (user == null)
return Unauthorized();
var userSaves = await GameSaveService.GetAsync(gs => gs.UserId == user.Id && gs.GameId == gameId);
return Ok(Mapper.Map<IEnumerable<SDK.Models.GameSave>>(userSaves));
}
[HttpGet("Latest/{gameId}")]
public async Task<ActionResult<SDK.Models.GameSave>> LatestAsync(Guid gameId)
{
var user = await UserService.GetAsync(User?.Identity?.Name);
if (user == null)
return Unauthorized();
var latestSave = await GameSaveService.FirstOrDefaultAsync(gs => gs.UserId == user.Id && gs.GameId == gameId, gs => gs.CreatedOn);
// Should probably return 404 if no latest save exists
// Not sure if this will affect launcher stability
return Ok(Mapper.Map<SDK.Models.GameSave>(latestSave));
}
[HttpGet("DownloadLatest/{gameId}")]
public async Task<IActionResult> DownloadLatestAsync(Guid gameId)
{
var user = await UserService.GetAsync(User?.Identity?.Name);
if (user == null)
return NotFound();
var save = await GameSaveService
.FirstOrDefaultAsync(gs => gs.GameId == gameId && gs.UserId == user.Id, gs => gs.CreatedOn);
if (save == null)
return NotFound();
var filename = save.GetUploadPath();
if (!System.IO.File.Exists(filename))
return NotFound();
return File(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read), "application/octet-stream", $"{save.Id.ToString().SanitizeFilename()}.zip");
}
[HttpGet("Download/{id}")]
public async Task<IActionResult> DownloadAsync(Guid id)
{
var save = await GameSaveService.GetAsync(id);
if (save == null)
return NotFound();
var filename = save.GetUploadPath();
if (!System.IO.File.Exists(filename))
return NotFound();
return File(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read), "application/octet-stream", $"{save.Id.ToString().SanitizeFilename()}.zip");
}
[HttpPost("Upload/{id}")]
public async Task<IActionResult> UploadAsync(Guid id)
{
var file = Request.Form.Files.First();
var user = await UserService.GetAsync(User?.Identity?.Name);
var game = await GameService.GetAsync(id);
if (game == null)
return NotFound();
var save = new GameSave()
{
GameId = id,
UserId = user.Id,
Size = file.Length,
};
save = await GameSaveService.AddAsync(save);
var saveUploadPath = Path.GetDirectoryName(save.GetUploadPath());
if (!Directory.Exists(saveUploadPath))
Directory.CreateDirectory(saveUploadPath);
using (var stream = System.IO.File.Create(save.GetUploadPath()))
{
await file.CopyToAsync(stream);
}
if (Settings.UserSaves.MaxSaves > 0)
{
var saves = (await GameSaveService.GetAsync(gs => gs.UserId == user.Id && gs.GameId == game.Id)).OrderByDescending(gs => gs.CreatedOn).Skip(Settings.UserSaves.MaxSaves).ToList();
foreach (var extraSave in saves)
await GameSaveService.DeleteAsync(extraSave);
}
return Ok(Mapper.Map<SDK.Models.GameSave>(save));
}
[HttpDelete("Delete/{id}")]
public async Task<IActionResult> DeleteAsync(Guid id)
{
try
{
var save = await GameSaveService.GetAsync(id);
await GameSaveService.DeleteAsync(save);
return Ok();
}
catch (Exception ex)
{
Logger.LogError(ex, "An unknown error occurred while trying to delete a game save with the ID {GameSaveId}", id);
return BadRequest();
}
}
}
}