Skip to content

Commit

Permalink
Minor fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
NixFey committed Feb 28, 2024
1 parent 2413698 commit 5172108
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 54 deletions.
5 changes: 3 additions & 2 deletions Auth/AuthTokenAuthSchemeHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Text.Encodings.Web;
using fim_queueing_admin.Data;
using Microsoft.AspNetCore.Authentication;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;

namespace fim_queueing_admin.Auth;
Expand All @@ -19,7 +20,7 @@ public class AuthTokenAuthSchemeHandler(
FimDbContext dbContext)
: AuthenticationHandler<AuthTokenAuthSchemeOptions>(options, logger, encoder)
{
protected async override Task<AuthenticateResult> HandleAuthenticateAsync()
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
// Read the token from request headers/cookies
// Check that it's a valid session, depending on your implementation
Expand All @@ -37,7 +38,7 @@ protected async override Task<AuthenticateResult> HandleAuthenticateAsync()
return AuthenticateResult.Fail("Failed to retrieve token");
}

var cart = dbContext.Carts.SingleOrDefault(c => c.AuthToken == token.ToString());
var cart = await dbContext.Carts.SingleOrDefaultAsync(c => c.AuthToken == token.ToString());

if (cart is null)
{
Expand Down
37 changes: 14 additions & 23 deletions Controllers/TwitchController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Globalization;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
Expand All @@ -11,21 +10,11 @@

namespace fim_queueing_admin.Controllers;

public class TwitchController : Controller
public class TwitchController(ILogger<TwitchController> logger, IConfiguration config) : Controller
{
private readonly ILogger<TwitchController> _logger;
private readonly IConfiguration _config;

public TwitchController(ILogger<TwitchController> logger, IConfiguration config)
{
_logger = logger;
_config = config;
}

/// <summary>
/// The main endpoint that handles all of our Twitch webhooks.
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<ActionResult> Webhook([FromServices] IServiceProvider services)
{
Expand All @@ -41,21 +30,21 @@ public async Task<ActionResult> Webhook([FromServices] IServiceProvider services
// When we set up a new webhook we need to verify with Twitch
case "webhook_callback_verification":
{
_logger.LogInformation("Verifying a webhook from Twitch");
logger.LogInformation("Verifying a webhook from Twitch");

if (!messageBody.TryGetProperty("challenge", out var challenge))
{
return BadRequest("No challenge");
}
_logger.LogInformation("Challenge {}", challenge.GetString());
logger.LogInformation("Challenge {}", challenge.GetString());
Response.StatusCode = StatusCodes.Status200OK;
return Ok(challenge.GetString()!);
}
case "revocation":
_logger.LogWarning("Revoked webhook {}", JsonSerializer.Serialize(messageBody));
logger.LogWarning("Revoked webhook {}", JsonSerializer.Serialize(messageBody));
return Ok();
case "notification":
_logger.LogInformation("Notification webhook {}", JsonSerializer.Serialize(messageBody));
logger.LogInformation("Notification webhook {}", JsonSerializer.Serialize(messageBody));
if (messageBody.TryGetProperty("subscription", out var subscription) &&
subscription.TryGetProperty("type", out var type) &&
(type.GetString() == "stream.online" || type.GetString() == "stream.offline"))
Expand All @@ -64,7 +53,7 @@ public async Task<ActionResult> Webhook([FromServices] IServiceProvider services
if (!messageBody.TryGetProperty("event", out var evt) ||
!evt.TryGetProperty("broadcaster_user_login", out var login))
{
_logger.LogWarning("Could not get broadcaster_user_login from message");
logger.LogWarning("Could not get broadcaster_user_login from message");
return BadRequest();
}
var slackMessage = type.GetString() switch
Expand All @@ -77,12 +66,12 @@ public async Task<ActionResult> Webhook([FromServices] IServiceProvider services
var slack = services.GetService<ISlackApiClient>();
if (slack is null)
{
_logger.LogWarning("Cannot send Slack messages without slack being configured");
logger.LogWarning("Cannot send Slack messages without slack being configured");
return Ok("Could not send slack message, ignoring");
}
await slack.Chat.PostMessage(new Message()
{
Channel = _config["Slack:NotificationChannel"],
Channel = config["Slack:NotificationChannel"],
Text = slackMessage
});

Expand All @@ -96,23 +85,25 @@ await slack.Chat.PostMessage(new Message()

private async Task<bool> VerifyMessage(HttpRequest request)
{
// Todo this needs to be tested

// Make sure we can read the body more than once
if (!request.Body.CanSeek)
{
request.EnableBuffering();
}

var webhookSecret = config["Twitch:WebhookSecret"];
if (string.IsNullOrEmpty(webhookSecret)) throw new ApplicationException("No Twitch Webhook secret set");

request.Body.Position = 0;
var body = await (new StreamReader(request.Body, Encoding.UTF8)).ReadToEndAsync();
var body = await new StreamReader(request.Body, Encoding.UTF8).ReadToEndAsync();
request.Body.Position = 0;

// Build up the HMAC and compare against what we were given
var msgToVerify = new StringBuilder();
msgToVerify.Append(request.Headers["Twitch-Eventsub-Message-Id"].First());
msgToVerify.Append(request.Headers["Twitch-Eventsub-Message-Timestamp"].First());
msgToVerify.Append(body);
var computedHmac = HMACSHA256.HashData(Encoding.UTF8.GetBytes(_config["Twitch:WebhookSecret"]),
var computedHmac = HMACSHA256.HashData(Encoding.UTF8.GetBytes(webhookSecret),
Encoding.UTF8.GetBytes(msgToVerify.ToString()));
return string.Equals(request.Headers["Twitch-Eventsub-Message-Signature"].First(),
"sha256=" + Convert.ToHexString(computedHmac), StringComparison.OrdinalIgnoreCase);
Expand Down
2 changes: 1 addition & 1 deletion Models/DbEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ public class DbEvent
public int? currentMatchNumber { get; set; }
public string? playoffMatchNumber { get; set; }
public int? numQualMatches { get; set; }
public string dataSource { get; set; }
public string? dataSource { get; set; }
}
17 changes: 12 additions & 5 deletions Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ async Task<string> GetAccessToken()
opt.ExpireTimeSpan = TimeSpan.FromDays(31);
}).AddScheme<AuthTokenAuthSchemeOptions, AuthTokenAuthSchemeHandler>(AuthTokenScheme.AuthenticationScheme, _ => { });

var isBehindProxy = bool.TryParse(builder.Configuration["EnableForwardedHeaders"], out var res) && res;

builder.Services.AddAuthorization(opt =>
{
opt.DefaultPolicy = new AuthorizationPolicyBuilder(CookieAuthenticationDefaults.AuthenticationScheme)
Expand Down Expand Up @@ -95,8 +93,10 @@ async Task<string> GetAccessToken()
client.BaseAddress = new Uri("https://frc-api.firstinspires.org/v3.0/");
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(Encoding.UTF8.GetBytes(builder.Configuration["FRCAPIToken"])));
Convert.ToBase64String(Encoding.UTF8.GetBytes(builder.Configuration["FRCAPIToken"]!)));
});
if (string.IsNullOrWhiteSpace(builder.Configuration["TBAAPIToken"]))
throw new ApplicationException("TBA API Token is required to start up");
builder.Services.AddHttpClient("TBA", client =>
{
client.BaseAddress = new Uri("https://www.thebluealliance.com/api/v3/");
Expand Down Expand Up @@ -145,13 +145,20 @@ async Task<string> GetAccessToken()
});
}

if (bool.TryParse(builder.Configuration["EnableForwardedHeaders"], out var builderProxy) && builderProxy)
var isBehindProxy = bool.TryParse(builder.Configuration["EnableForwardedHeaders"], out var res) && res;

if (isBehindProxy)
{
var proxyIpAddress = builder.Configuration["ProxyIPAddress"];
if (proxyIpAddress is null)
throw new ApplicationException("Forwarded headers were enabled but no proxy IP was defined");
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
options.KnownProxies.Add(IPAddress.Parse(builder.Configuration["ProxyIPAddress"]));
options.KnownProxies.Add(IPAddress.Parse(proxyIpAddress));
});
}

builder.Services.AddHostedService<DatabaseKeepAliveService>();

Expand Down
6 changes: 3 additions & 3 deletions Services/CreateEventsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -280,11 +280,11 @@ public class CreatedEvent

public class EventInfo
{
public string EventCode { get; set; }
public string Name { get; set; }
public required string EventCode { get; set; }
public required string Name { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public string Timezone { get; set; }
public required string Timezone { get; set; }
public string? TwitchChannel { get; set; }
}

Expand Down
42 changes: 22 additions & 20 deletions Views/Event/Manage.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
<div class="accordion-collapse collapse" id="welcomeCollapse">
<div class="accordion-body">
<div>
Field number: @(carts.FirstOrDefault(c => c.Value == eventData?.cartId.ToString())?.Text ?? "Unknown")
Field number: @(carts.FirstOrDefault(c => c.Value == eventData.cartId.ToString())?.Text ?? "Unknown")
</div>
<div id="welcome">@Html.Raw(welcome)</div>
</div>
Expand All @@ -58,7 +58,7 @@
<div class="card-body">
<form method="post" asp-action="UpdateState" asp-route-id="@(ViewData["id"])">
<div class="form-group mb-2">
<label for="state">New State</label>
<label for="eventState">New State</label>
@{
var currentState = eventData.state?.ToString();
var eventStateList = Enum.GetNames<EventState>().Select(n =>
Expand All @@ -81,7 +81,9 @@
var currentLink = eventData.streamEmbedLink;
}
<input id="link" name="link" class="form-control" value="@currentLink" type="url" />
<div class="form-text">Ex: https://player.twitch.tv/?channel=firstinspires31&parent=fim-queueing.web.app&autoplay=true&muted=false</div>
<div class="form-text">
Ex: https://player.twitch.tv/?channel=firstinspires31&amp;parent=fim-queueing.web.app&amp;autoplay=true&amp;muted=false
</div>
</div>
<button class="btn btn-primary">Update</button>
</form>
Expand Down Expand Up @@ -125,23 +127,23 @@
</div>
</div>

<div class="card mt-3">
<h5 class="card-header">Manage Admins</h5>
<div class="card-body">
<div class="form-group mb-2">
<label for="link">Start</label>
<input id="start" name="start" class="form-control" value="@eventData.start!.Value.ToString("s")" type="datetime-local"/>
</div>
<div class="form-group mb-2">
<label for="link">End</label>
<input id="end" name="end" class="form-control" value="@eventData.end!.Value.ToString("s")" type="datetime-local"/>
</div>
<div class="form-group mb-2">
<label for="link">Timezone Offset</label>
<input id="offset" name="offset" class="form-control" value="@eventData.start!.Value.Offset" type="text"/>
</div>
</div>
</div>
@* <div class="card mt-3"> *@
@* <h5 class="card-header">Manage Admins</h5> *@
@* <div class="card-body"> *@
@* <div class="form-group mb-2"> *@
@* <label for="link">Start</label> *@
@* <input id="start" name="start" class="form-control" value="@eventData.start!.Value.ToString("s")" type="datetime-local"/> *@
@* </div> *@
@* <div class="form-group mb-2"> *@
@* <label for="link">End</label> *@
@* <input id="end" name="end" class="form-control" value="@eventData.end!.Value.ToString("s")" type="datetime-local"/> *@
@* </div> *@
@* <div class="form-group mb-2"> *@
@* <label for="link">Timezone Offset</label> *@
@* <input id="offset" name="offset" class="form-control" value="@eventData.start!.Value.Offset" type="text"/> *@
@* </div> *@
@* </div> *@
@* </div> *@
</div>

@section Scripts
Expand Down

0 comments on commit 5172108

Please sign in to comment.