Skip to content

Commit

Permalink
Allow upload of direct yml files via api token (#63)
Browse files Browse the repository at this point in the history
  • Loading branch information
Simyon264 authored Oct 22, 2024
1 parent 35d9c61 commit c97e6fa
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 2 deletions.
46 changes: 46 additions & 0 deletions ReplayBrowser/Controllers/ReplayController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -220,4 +220,50 @@ public async Task<IActionResult> FavoriteReplay(int replayId)

return Ok(!isFavorited);
}

[HttpPost("replay/upload")]
[AllowAnonymous]
[IgnoreAntiforgeryToken]
public async Task<IActionResult> UploadReplay(
IFormCollection form
)
{
if (!CheckAuthenticationTokenServerApi())
{
return Unauthorized("No valid token provided.");
}

var file = form.Files.FirstOrDefault();
if (file == null)
{
return BadRequest("No file provided.");
}

var reader = new StreamReader(file.OpenReadStream());
Replay? replay = null;
try
{
replay = _replayParserService.FinalizeReplayParse(reader, null);
}
catch (Exception e)
{
return BadRequest(e.Message);
}
await _dbContext.Replays.AddAsync(replay);
await _dbContext.SaveChangesAsync();
return Ok();
}

private bool CheckAuthenticationTokenServerApi()
{
var token = Request.Headers.Authorization;
if (token.Count == 0)
{
return false;
}

var tokenString = token.ToString().Split(" ")[1];

return _dbContext.ServerTokens.Any(t => t.Token == tokenString);
}
}
12 changes: 12 additions & 0 deletions ReplayBrowser/Data/Migrations/ReplayDbContextModelSnapshot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,18 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("ReplayParticipants");
});

modelBuilder.Entity("ReplayBrowser.Data.Models.ServerToken", b =>
{
b.Property<string>("Token")
.HasColumnType("text");

b.HasKey("Token");

b.HasIndex("Token");

b.ToTable("ServerTokens");
});

modelBuilder.Entity("ReplayBrowser.Data.Models.Account.Account", b =>
{
b.HasOne("ReplayBrowser.Data.Models.Account.AccountSettings", "Settings")
Expand Down
4 changes: 3 additions & 1 deletion ReplayBrowser/Data/Models/Replay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public ReplayResult ToResult()
};
}

public static Replay FromYaml(YamlReplay replay, string link)
public static Replay FromYaml(YamlReplay replay, string? link)
{
var participants = replay.RoundEndPlayers?
.GroupBy(p => p.PlayerGuid)
Expand All @@ -97,6 +97,8 @@ public static Replay FromYaml(YamlReplay replay, string link)
})
.ToList();

link ??= replay.Link ?? throw new ArgumentException("Link is required.");

return new Replay {
Link = link,
ServerId = replay.ServerId,
Expand Down
18 changes: 18 additions & 0 deletions ReplayBrowser/Data/Models/ServerToken.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace ReplayBrowser.Data.Models;

/// <summary>
/// Represents a token that is used to authenticate with the API for ingesting replays.
/// </summary>
public class ServerToken : IEntityTypeConfiguration<ServerToken>
{
public required string Token { get; set; }

public void Configure(EntityTypeBuilder<ServerToken> builder)
{
builder.HasKey(t => t.Token);
builder.HasIndex(t => t.Token);
}
}
2 changes: 2 additions & 0 deletions ReplayBrowser/Data/ReplayDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
public DbSet<JobDepartment> JobDepartments { get; set; }

public DbSet<ReplayParticipant> ReplayParticipants { get; set; }

public DbSet<ServerToken> ServerTokens { get; set; }
}
5 changes: 5 additions & 0 deletions ReplayBrowser/Models/Ingested/YamlReplay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ namespace ReplayBrowser.Models.Ingested;
public class YamlReplay {
public int? RoundId { get; set; }

/// <summary>
/// Fallback link to the replay.
/// </summary>
public string? Link { get; set; }

[YamlMember(Alias = "server_id", ApplyNamingConventions = false)]
public required string ServerId { get; set; }
[YamlMember(Alias = "server_name", ApplyNamingConventions = false)]
Expand Down
8 changes: 8 additions & 0 deletions ReplayBrowser/Pages/Shared/ReplayDetails.razor
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@
@if(Replay != null)
{
<h2>@NameFormatted</h2>
@if(Replay.Duration == "00:00:00.0000000")
{
// Replay is a legacy replay, show a warning
<div class="alert alert-warning" role="alert">
This replay is a legacy replay and is missing a lot of information. You may not be able to run this replay in a normal client.
</div>
}

@if (Replay.Map == null)
{
<p>Maps: @string.Join(", ", Replay.Maps!)</p>
Expand Down
2 changes: 1 addition & 1 deletion ReplayBrowser/Services/ReplayParser/ReplayParserService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ private Replay ParseReplay(Stream stream, string replayLink)
return FinalizeReplayParse(reader, replayLink);
}

private Replay FinalizeReplayParse(StreamReader stream, string replayLink)
public Replay FinalizeReplayParse(TextReader stream, string? replayLink)
{
var deserializer = new DeserializerBuilder()
.IgnoreUnmatchedProperties()
Expand Down
8 changes: 8 additions & 0 deletions ReplayBrowser/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
},
"AllowedHosts": "*",
"ReplayUrls": [
{
"url": "https://cdn.replay.unstablefoundation.de/",
"provider": "dummy",
"fallBackServerName": "wizards",
"fallBackServerId": "wizards",
"replayRegex": "[a-zA-Z0-9-]+-(\\d{4}_\\d{2}_\\d{2}-\\d{2}_\\d{2})-round_\\d+\\.zip$",
"serverNameRegex": "([a-zA-Z0-9-]+)-\\d{4}_\\d{2}_\\d{2}-\\d{2}_\\d{2}-round_\\d+\\.zip$"
},
{
"url": "https://cdn.networkgamez.com/replays/hullrot/",
"provider": "nginx",
Expand Down

0 comments on commit c97e6fa

Please sign in to comment.