fix crashes and logging in

This commit is contained in:
Lapis
2026-06-07 17:06:34 -04:00
parent 289e9a906e
commit 26d85d0748
10 changed files with 219 additions and 216 deletions
+35 -35
View File
@@ -1,38 +1,38 @@
{ {
"Accounts": "https://cannednet.lapis.codes/accounts", "Accounts": "https://cannednet.lapis.codes",
"AI": "https://cannednet.lapis.codes/ai", "AI": "https://cannednet.lapis.codes",
"API": "https://cannednet.lapis.codes/api", "API": "https://cannednet.lapis.codes",
"Auth": "https://cannednet.lapis.codes/auth", "Auth": "https://cannednet.lapis.codes",
"BugReporting": "https://cannednet.lapis.codes/bugreporting", "BugReporting": "https://cannednet.lapis.codes",
"Cards": "https://cannednet.lapis.codes/cards", "Cards": "https://cannednet.lapis.codes",
"CDN": "https://cannednet.lapis.codes/cdn", "CDN": "https://cannednet.lapis.codes",
"Chat": "https://cannednet.lapis.codes/chat", "Chat": "https://cannednet.lapis.codes",
"Clubs": "https://cannednet.lapis.codes/clubs", "Clubs": "https://cannednet.lapis.codes",
"CMS": "https://cannednet.lapis.codes/cms", "CMS": "https://cannednet.lapis.codes",
"Commerce": "https://cannednet.lapis.codes/commerce", "Commerce": "https://cannednet.lapis.codes",
"Data": "https://cannednet.lapis.codes/data", "Data": "https://cannednet.lapis.codes",
"DataCollection": "https://cannednet.lapis.codes/datacollection", "DataCollection": "https://cannednet.lapis.codes",
"Discovery": "https://cannednet.lapis.codes/discovery", "Discovery": "https://cannednet.lapis.codes",
"Econ": "https://cannednet.lapis.codes/econ", "Econ": "https://cannednet.lapis.codes",
"GameLogs": "https://cannednet.lapis.codes/gamelogs", "GameLogs": "https://cannednet.lapis.codes",
"Geo": "https://cannednet.lapis.codes/geo", "Geo": "https://cannednet.lapis.codes",
"Images": "https://cannednet.lapis.codes/img", "Images": "https://cannednet.lapis.codes",
"Leaderboard": "https://cannednet.lapis.codes/leaderboard", "Leaderboard": "https://cannednet.lapis.codes",
"Link": "https://cannednet.lapis.codes/link", "Link": "https://cannednet.lapis.codes",
"Lists": "https://cannednet.lapis.codes/lists", "Lists": "https://cannednet.lapis.codes",
"Matchmaking": "https://cannednet.lapis.codes/match", "Matchmaking": "https://cannednet.lapis.codes",
"Moderation": "https://cannednet.lapis.codes/moderation", "Moderation": "https://cannednet.lapis.codes",
"Notifications": "https://cannednet.lapis.codes/notify", "Notifications": "https://cannednet.lapis.codes",
"PlatformNotifications": "https://cannednet.lapis.codes/platformnotifications", "PlatformNotifications": "https://cannednet.lapis.codes",
"PlayerSettings": "https://cannednet.lapis.codes/playersettings", "PlayerSettings": "https://cannednet.lapis.codes",
"RoomComments": "https://cannednet.lapis.codes/roomcomments", "RoomComments": "https://cannednet.lapis.codes",
"RoomieIntegrations": "https://cannednet.lapis.codes/roomieintegrations", "RoomieIntegrations": "https://cannednet.lapis.codes",
"Rooms": "https://cannednet.lapis.codes/rooms", "Rooms": "https://cannednet.lapis.codes",
"Storage": "https://cannednet.lapis.codes/storage", "Storage": "https://cannednet.lapis.codes",
"Strings": "https://cannednet.lapis.codes/strings", "Strings": "https://cannednet.lapis.codes",
"StringsCDN": "https://cannednet.lapis.codes/stringscdn", "StringsCDN": "https://cannednet.lapis.codes",
"Studio": "https://cannednet.lapis.codes/studio", "Studio": "https://cannednet.lapis.codes",
"Thorn": "https://cannednet.lapis.codes/thorn", "Thorn": "https://cannednet.lapis.codes",
"Videos": "https://cannednet.lapis.codes/videos", "Videos": "https://cannednet.lapis.codes",
"WWW": "https://cannednet.lapis.codes" "WWW": "https://cannednet.lapis.codes"
} }
+15 -7
View File
@@ -1,3 +1,4 @@
using System.Security.Claims;
using CannedNet.Data; using CannedNet.Data;
using CannedNet.Hubs; using CannedNet.Hubs;
using CannedNet.Services; using CannedNet.Services;
@@ -47,29 +48,36 @@ public static class Program
{ {
ValidateIssuerSigningKey = true, ValidateIssuerSigningKey = true,
IssuerSigningKey = securityKey, IssuerSigningKey = securityKey,
ValidateIssuer = true,
ValidateIssuer = false,
ValidIssuer = "https://lapis.codes", ValidIssuer = "https://lapis.codes",
ValidateAudience = true,
ValidAudience = "https://lapis.codes/resources", ValidateAudience = false,
ValidAudiences = new[]
{
"https://lapis.codes",
"https://lapis.codes/resources"
},
ValidateLifetime = true, ValidateLifetime = true,
ClockSkew = TimeSpan.Zero, ClockSkew = TimeSpan.Zero,
// sub is account id NameClaimType = ClaimTypes.NameIdentifier,
NameClaimType = "sub",
RoleClaimType = "role" RoleClaimType = "role"
}; };
}); });
builder.Services.AddAuthorization(); builder.Services.AddAuthorization();
WebApplication app = builder.Build(); WebApplication app = builder.Build();
app.MapHub<NotificationsHub>("/hub/v1"); app.MapHub<NotificationsHub>("/hub/v1");
app.UseHttpsRedirection(); app.UseHttpsRedirection();
//app.UseRequestLogging(); app.UseRequestLogging();
app.MapControllers();
app.UseAuthentication(); app.UseAuthentication();
app.UseAuthorization(); app.UseAuthorization();
app.MapControllers();
IHubContext<NotificationsHub> hubContext = app.Services.GetRequiredService<IHubContext<NotificationsHub>>(); IHubContext<NotificationsHub> hubContext = app.Services.GetRequiredService<IHubContext<NotificationsHub>>();
NotificationService.SetHubContext(hubContext); NotificationService.SetHubContext(hubContext);
+10 -10
View File
@@ -56,7 +56,7 @@ public class APIController : ControllerBase
public async Task<IResult> GetPlayersV1Progression(string id) => Results.Content($"{{\"PlayerId\":{id},\"Level\":1,\"XP\":0}}", "application/json"); public async Task<IResult> GetPlayersV1Progression(string id) => Results.Content($"{{\"PlayerId\":{id},\"Level\":1,\"XP\":0}}", "application/json");
[HttpPost("playerReputation/v2/bulk")] [HttpPost("playerReputation/v2/bulk")]
public async Task<IResult> PostPlayerReputationV2Bulk(HttpRequest httpRequest, AppDbContext db) { public async Task<IResult> PostPlayerReputationV2Bulk(AppDbContext db) {
/*var ids = await ParseFormIds(httpRequest); /*var ids = await ParseFormIds(httpRequest);
if (!ids.Any()) if (!ids.Any())
@@ -83,8 +83,8 @@ public class APIController : ControllerBase
} }
[HttpPost("players/v2/progression/bulk")] [HttpPost("players/v2/progression/bulk")]
public async Task<IResult> PostProgressionBulkV2(HttpRequest httpRequest, AppDbContext db) { public async Task<IResult> PostProgressionBulkV2(AppDbContext db) {
List<int> ids = await ParseFormIds(httpRequest); List<int> ids = await ParseFormIds(HttpContext.Request);
if (!ids.Any()) if (!ids.Any())
return Results.Json(new List<PlayerProgressionBulkResponse>()); return Results.Json(new List<PlayerProgressionBulkResponse>());
@@ -98,8 +98,8 @@ public class APIController : ControllerBase
} }
[HttpPost("v1/progression/bulk")] [HttpPost("v1/progression/bulk")]
public async Task<IResult> PostProgressionBulkV1(HttpRequest httpRequest, AppDbContext db) { public async Task<IResult> PostProgressionBulkV1(AppDbContext db) {
List<int> ids = await ParseFormIds(httpRequest); List<int> ids = await ParseFormIds(HttpContext.Request);
if (!ids.Any()) if (!ids.Any())
return Results.Json(new List<PlayerProgressionBulkResponse>()); return Results.Json(new List<PlayerProgressionBulkResponse>());
@@ -116,11 +116,11 @@ public class APIController : ControllerBase
[HttpPost("avatar/v2/set")] [HttpPost("avatar/v2/set")]
[Authorize] [Authorize]
public async Task<IResult> SetAvatarV2(HttpRequest request, AppDbContext db, JwtTokenService jwtService) public async Task<IResult> SetAvatarV2(AppDbContext db, JwtTokenService jwtService)
{ {
int id = User.Identity.Name != null && int.TryParse(User.Identity.Name, out var parsedId) ? parsedId : -1; int id = User.Identity.Name != null && int.TryParse(User.Identity.Name, out var parsedId) ? parsedId : -1;
request.EnableBuffering(); HttpContext.Request.EnableBuffering();
var avatarUpdate = await System.Text.Json.JsonSerializer.DeserializeAsync<PlayerAvatar>(request.Body); var avatarUpdate = await System.Text.Json.JsonSerializer.DeserializeAsync<PlayerAvatar>(HttpContext.Request.Body);
if (avatarUpdate == null) if (avatarUpdate == null)
return Results.BadRequest(); return Results.BadRequest();
@@ -158,7 +158,7 @@ public class APIController : ControllerBase
[HttpGet("settings/v2")] [HttpGet("settings/v2")]
[Authorize] [Authorize]
public async Task<IResult> GetSettings(HttpRequest request, AppDbContext db, JwtTokenService jwtService) public async Task<IResult> GetSettings(AppDbContext db, JwtTokenService jwtService)
{ {
int id = User.Identity.Name != null && int.TryParse(User.Identity.Name, out var parsedId) ? parsedId : -1; int id = User.Identity.Name != null && int.TryParse(User.Identity.Name, out var parsedId) ? parsedId : -1;
@@ -212,7 +212,7 @@ public class APIController : ControllerBase
[HttpGet("accounts/v1/getBio")] [HttpGet("accounts/v1/getBio")]
[Authorize] [Authorize]
public async Task<IResult> GetAccountBio(HttpRequest request, AppDbContext db) public async Task<IResult> GetAccountBio(AppDbContext db)
{ {
int accountId = User.Identity.Name != null && int.TryParse(User.Identity.Name, out var parsedId) ? parsedId : -1; int accountId = User.Identity.Name != null && int.TryParse(User.Identity.Name, out var parsedId) ? parsedId : -1;
@@ -1,25 +1,19 @@
using CannedNet.Data; using CannedNet.Data;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
namespace CannedNet.Services.Controllers; namespace CannedNet.Services.Controllers;
//TODO: remove duplicate code(most of it is checking if the user is authenticated, ASP.NET has stuff for this)
[ApiController, Route("account")] [ApiController, Route("account")]
public class AccountsController : ControllerBase public class AccountsController : ControllerBase
{ {
[HttpGet("me")] [HttpGet("me")]
public async Task<IResult> Me(HttpRequest request, AppDbContext db, JwtTokenService jwtService) { [Authorize]
string authHeader = request.Headers.Authorization.ToString(); public async Task<IResult> Me(AppDbContext db)
{
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) if (!int.TryParse(User.Identity?.Name, out var id))
return Results.Unauthorized();
string token = authHeader.Substring("Bearer ".Length);
string? accountId = jwtService.ValidateAndGetAccountId(token);
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out int id))
return Results.Unauthorized(); return Results.Unauthorized();
Account? account = await db.Accounts.FindAsync(id); Account? account = await db.Accounts.FindAsync(id);
@@ -48,21 +42,23 @@ public class AccountsController : ControllerBase
} }
[HttpGet("bulk")] [HttpGet("bulk")]
public async Task<IResult> Bulk(HttpRequest request, AppDbContext db) { public async Task<IResult> Bulk(AppDbContext db)
StringValues ids = request.Query["id"]; {
StringValues ids = HttpContext.Request.Query["id"];
List<int> accountIds = []; List<int> accountIds = [];
foreach (string? id in ids) { foreach (string? id in ids)
if (int.TryParse(id, out int accountId)) { {
if (int.TryParse(id, out int accountId))
accountIds.Add(accountId); accountIds.Add(accountId);
} }
}
List<Account> accounts = await db.Accounts List<Account> accounts = await db.Accounts
.Where(a => accountIds.Contains(a.AccountId.Value)) .Where(a => accountIds.Contains(a.AccountId.Value))
.ToListAsync(); .ToListAsync();
List<Account> result = accounts.Select(a => new Account { List<Account> result = accounts.Select(a => new Account
{
AccountId = a.AccountId, AccountId = a.AccountId,
ProfileImage = a.ProfileImage ?? "DefaultProfileImage.jpg", ProfileImage = a.ProfileImage ?? "DefaultProfileImage.jpg",
IsJunior = a.IsJunior, IsJunior = a.IsJunior,
@@ -78,7 +74,8 @@ public class AccountsController : ControllerBase
} }
[HttpGet("{id}")] [HttpGet("{id}")]
public async Task<IResult> Id(HttpRequest request, string id, AppDbContext db) { public async Task<IResult> Id(string id, AppDbContext db)
{
if (!int.TryParse(id, out int accountId)) if (!int.TryParse(id, out int accountId))
return Results.BadRequest(); return Results.BadRequest();
@@ -86,7 +83,8 @@ public class AccountsController : ControllerBase
if (account == null) if (account == null)
return Results.NotFound(); return Results.NotFound();
Account result = new() { Account result = new()
{
AccountId = account.AccountId, AccountId = account.AccountId,
ProfileImage = account.ProfileImage ?? "DefaultProfileImage.jpg", ProfileImage = account.ProfileImage ?? "DefaultProfileImage.jpg",
IsJunior = account.IsJunior, IsJunior = account.IsJunior,
@@ -102,26 +100,33 @@ public class AccountsController : ControllerBase
} }
[HttpPost("create")] [HttpPost("create")]
public async Task<IResult> Create(HttpRequest httpRequest, AppDbContext db) { public async Task<IResult> Create(AppDbContext db)
{
var request = HttpContext.Request;
int platform = 0; int platform = 0;
string platformId = ""; string platformId = "";
if (httpRequest.ContentLength is > 0) { if (request.ContentLength is > 0)
try { {
string contentType = httpRequest.ContentType ?? ""; try
httpRequest.EnableBuffering(); {
string contentType = request.ContentType ?? "";
request.EnableBuffering();
using StreamReader reader = new(httpRequest.Body, leaveOpen: true); using StreamReader reader = new(request.Body, leaveOpen: true);
string body = await reader.ReadToEndAsync(); string body = await reader.ReadToEndAsync();
if (!string.IsNullOrWhiteSpace(body) && contentType.Contains("application/x-www-form-urlencoded")) { if (!string.IsNullOrWhiteSpace(body) && contentType.Contains("application/x-www-form-urlencoded"))
foreach (string pair in body.Split('&')) { {
foreach (string pair in body.Split('&'))
{
string[] keyValue = pair.Split('='); string[] keyValue = pair.Split('=');
if (keyValue.Length != 2) continue; if (keyValue.Length != 2) continue;
string key = Uri.UnescapeDataString(keyValue[0]); string key = Uri.UnescapeDataString(keyValue[0]);
string value = Uri.UnescapeDataString(keyValue[1]); string value = Uri.UnescapeDataString(keyValue[1]);
switch (key) { switch (key)
{
case "platform" when int.TryParse(value, out var parsedPlatform): case "platform" when int.TryParse(value, out var parsedPlatform):
platform = parsedPlatform; platform = parsedPlatform;
break; break;
@@ -132,13 +137,14 @@ public class AccountsController : ControllerBase
} }
} }
httpRequest.Body.Position = 0; request.Body.Position = 0;
} }
catch { } catch { }
} }
int accountId = new Random().Next(10000, 99999); int accountId = new Random().Next(10000, 99999);
Account account = new() { Account account = new()
{
AccountId = accountId, AccountId = accountId,
ProfileImage = "DefaultProfileImage.jpg", ProfileImage = "DefaultProfileImage.jpg",
IsJunior = false, IsJunior = false,
@@ -152,8 +158,10 @@ public class AccountsController : ControllerBase
db.Accounts.Add(account); db.Accounts.Add(account);
if (!string.IsNullOrEmpty(platformId)) { if (!string.IsNullOrEmpty(platformId))
db.CachedLogins.Add(new CachedLogin { {
db.CachedLogins.Add(new CachedLogin
{
AccountId = accountId, AccountId = accountId,
Platform = (PlatformType)platform, Platform = (PlatformType)platform,
PlatformID = platformId, PlatformID = platformId,
@@ -164,12 +172,11 @@ public class AccountsController : ControllerBase
await db.SaveChangesAsync(); await db.SaveChangesAsync();
// create players dorm room
int maxRoomId = await db.Rooms.MaxAsync(r => (int?)r.RoomId) ?? 0; int maxRoomId = await db.Rooms.MaxAsync(r => (int?)r.RoomId) ?? 0;
int maxId = await db.Rooms.MaxAsync(r => (int?)r.Id) ?? 0; int maxId = await db.Rooms.MaxAsync(r => (int?)r.Id) ?? 0;
int dormRoomId = maxRoomId + 1; int dormRoomId = maxRoomId + 1;
//int dormId = maxId + 1; Room dormRoom = new Room
Room dormRoom = new Room { {
Id = maxId + 1, Id = maxId + 1,
RoomId = dormRoomId, RoomId = dormRoomId,
Name = "DormRoom", Name = "DormRoom",
@@ -200,8 +207,8 @@ public class AccountsController : ControllerBase
}; };
db.Rooms.Add(dormRoom); db.Rooms.Add(dormRoom);
// Create a sub room for the dorm SubRoom dormSubRoom = new SubRoom
SubRoom dormSubRoom = new SubRoom { {
RoomId = dormRoomId, RoomId = dormRoomId,
SubRoomId = 1, SubRoomId = 1,
Name = "DormRoom", Name = "DormRoom",
@@ -209,7 +216,7 @@ public class AccountsController : ControllerBase
IsSandbox = false, IsSandbox = false,
MaxPlayers = 4, MaxPlayers = 4,
Accessibility = 0, Accessibility = 0,
UnitySceneId = "76d98498-60a1-430c-ab76-b54a29b7a163", // Dorm scene ID UnitySceneId = "76d98498-60a1-430c-ab76-b54a29b7a163",
DataSavedAt = DateTime.UtcNow DataSavedAt = DateTime.UtcNow
}; };
db.SubRooms.Add(dormSubRoom); db.SubRooms.Add(dormSubRoom);
@@ -219,28 +226,27 @@ public class AccountsController : ControllerBase
} }
[HttpPut("me/displayname")] [HttpPut("me/displayname")]
public async Task<IResult> PutMeDisplayName(HttpRequest request, AppDbContext db, JwtTokenService jwtService) { [Authorize]
string authHeader = request.Headers.Authorization.ToString(); public async Task<IResult> PutMeDisplayName(AppDbContext db)
{
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) if (!int.TryParse(User.Identity?.Name, out var id))
return Results.Unauthorized();
string token = authHeader.Substring("Bearer ".Length);
string? accountId = jwtService.ValidateAndGetAccountId(token);
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out var id))
return Results.Unauthorized(); return Results.Unauthorized();
var request = HttpContext.Request;
string newDisplayName = ""; string newDisplayName = "";
if (request.ContentLength is > 0) { if (request.ContentLength is > 0)
try { {
try
{
request.EnableBuffering(); request.EnableBuffering();
using StreamReader reader = new(request.Body, leaveOpen: true); using StreamReader reader = new(request.Body, leaveOpen: true);
string body = await reader.ReadToEndAsync(); string body = await reader.ReadToEndAsync();
if (!string.IsNullOrWhiteSpace(body)) { if (!string.IsNullOrWhiteSpace(body))
foreach (string pair in body.Split('&')) { {
foreach (string pair in body.Split('&'))
{
string[] keyValue = pair.Split('='); string[] keyValue = pair.Split('=');
if (keyValue.Length != 2) continue; if (keyValue.Length != 2) continue;
string key = Uri.UnescapeDataString(keyValue[0]); string key = Uri.UnescapeDataString(keyValue[0]);
@@ -267,29 +273,27 @@ public class AccountsController : ControllerBase
} }
[HttpPut("me/username")] [HttpPut("me/username")]
public async Task<IResult> PutMeUsername(HttpRequest request, AppDbContext db, JwtTokenService jwtService) { [Authorize]
string authHeader = request.Headers.Authorization.ToString(); public async Task<IResult> PutMeUsername(AppDbContext db)
{
if (string.IsNullOrEmpty(authHeader) || if (!int.TryParse(User.Identity?.Name, out var id))
!authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
return Results.Unauthorized();
string token = authHeader.Substring("Bearer ".Length);
string? accountId = jwtService.ValidateAndGetAccountId(token);
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out int id))
return Results.Unauthorized(); return Results.Unauthorized();
var request = HttpContext.Request;
string newAccountName = ""; string newAccountName = "";
if (request.ContentLength is > 0) { if (request.ContentLength is > 0)
try { {
try
{
request.EnableBuffering(); request.EnableBuffering();
using StreamReader reader = new(request.Body, leaveOpen: true); using StreamReader reader = new(request.Body, leaveOpen: true);
string body = await reader.ReadToEndAsync(); string body = await reader.ReadToEndAsync();
if (!string.IsNullOrWhiteSpace(body)) { if (!string.IsNullOrWhiteSpace(body))
foreach (string pair in body.Split('&')) { {
foreach (string pair in body.Split('&'))
{
string[] keyValue = pair.Split('='); string[] keyValue = pair.Split('=');
if (keyValue.Length != 2) continue; if (keyValue.Length != 2) continue;
string key = Uri.UnescapeDataString(keyValue[0]); string key = Uri.UnescapeDataString(keyValue[0]);
@@ -316,7 +320,8 @@ public class AccountsController : ControllerBase
} }
[HttpGet("{id}/bio")] [HttpGet("{id}/bio")]
public async Task<IResult> GetBio(string id, AppDbContext db) { public async Task<IResult> GetBio(string id, AppDbContext db)
{
if (!int.TryParse(id, out int accountId)) if (!int.TryParse(id, out int accountId))
return Results.BadRequest(); return Results.BadRequest();
@@ -328,29 +333,27 @@ public class AccountsController : ControllerBase
} }
[HttpPut("me/bio")] [HttpPut("me/bio")]
public async Task<IResult> PutMeBio(HttpRequest request, AppDbContext db, JwtTokenService jwtService) { [Authorize]
string authHeader = request.Headers.Authorization.ToString(); public async Task<IResult> PutMeBio(AppDbContext db)
{
if (string.IsNullOrEmpty(authHeader) || if (!int.TryParse(User.Identity?.Name, out var id))
!authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
return Results.Unauthorized();
string token = authHeader.Substring("Bearer ".Length);
string? accountId = jwtService.ValidateAndGetAccountId(token);
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out int id))
return Results.Unauthorized(); return Results.Unauthorized();
var request = HttpContext.Request;
string newBio = ""; string newBio = "";
if (request.ContentLength is > 0) { if (request.ContentLength is > 0)
try { {
try
{
request.EnableBuffering(); request.EnableBuffering();
using StreamReader reader = new StreamReader(request.Body, leaveOpen: true); using StreamReader reader = new StreamReader(request.Body, leaveOpen: true);
string body = await reader.ReadToEndAsync(); string body = await reader.ReadToEndAsync();
if (!string.IsNullOrWhiteSpace(body)) { if (!string.IsNullOrWhiteSpace(body))
foreach (string pair in body.Split('&')) { {
foreach (string pair in body.Split('&'))
{
string[] keyValue = pair.Split('='); string[] keyValue = pair.Split('=');
if (keyValue.Length != 2) continue; if (keyValue.Length != 2) continue;
string key = Uri.UnescapeDataString(keyValue[0]); string key = Uri.UnescapeDataString(keyValue[0]);
@@ -368,14 +371,17 @@ public class AccountsController : ControllerBase
PlayerBio? bio = await db.PlayerBios.FirstOrDefaultAsync(b => b.accountId == id); PlayerBio? bio = await db.PlayerBios.FirstOrDefaultAsync(b => b.accountId == id);
if (bio == null) { if (bio == null)
bio = new PlayerBio { {
bio = new PlayerBio
{
accountId = id, accountId = id,
bio = newBio bio = newBio
}; };
db.PlayerBios.Add(bio); db.PlayerBios.Add(bio);
} }
else { else
{
bio.bio = newBio; bio.bio = newBio;
db.PlayerBios.Update(bio); db.PlayerBios.Update(bio);
} }
@@ -386,29 +392,27 @@ public class AccountsController : ControllerBase
} }
[HttpPut("me/profileimage")] [HttpPut("me/profileimage")]
public async Task<IResult> PutMeProfileImage(HttpRequest request, AppDbContext db, JwtTokenService jwtService) { [Authorize]
string authHeader = request.Headers.Authorization.ToString(); public async Task<IResult> PutMeProfileImage(AppDbContext db)
{
if (string.IsNullOrEmpty(authHeader) || if (!int.TryParse(User.Identity?.Name, out var id))
!authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
return Results.Unauthorized();
string token = authHeader.Substring("Bearer ".Length);
string? accountId = jwtService.ValidateAndGetAccountId(token);
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out int id))
return Results.Unauthorized(); return Results.Unauthorized();
var request = HttpContext.Request;
string newProfileImage = ""; string newProfileImage = "";
if (request.ContentLength is > 0) { if (request.ContentLength is > 0)
try { {
try
{
request.EnableBuffering(); request.EnableBuffering();
using StreamReader reader = new(request.Body, leaveOpen: true); using StreamReader reader = new(request.Body, leaveOpen: true);
string body = await reader.ReadToEndAsync(); string body = await reader.ReadToEndAsync();
if (!string.IsNullOrWhiteSpace(body)) { if (!string.IsNullOrWhiteSpace(body))
foreach (var pair in body.Split('&')) { {
foreach (var pair in body.Split('&'))
{
string[] keyValue = pair.Split('='); string[] keyValue = pair.Split('=');
if (keyValue.Length != 2) continue; if (keyValue.Length != 2) continue;
string key = Uri.UnescapeDataString(keyValue[0]); string key = Uri.UnescapeDataString(keyValue[0]);
@@ -435,19 +439,12 @@ public class AccountsController : ControllerBase
} }
[HttpGet("parentalcontrol/me")] [HttpGet("parentalcontrol/me")]
public async Task<IResult> ParentalControl(HttpRequest request, JwtTokenService jwtService) { [Authorize]
string authHeader = request.Headers.Authorization.ToString(); public async Task<IResult> ParentalControl()
{
if (string.IsNullOrEmpty(authHeader) || if (!int.TryParse(User.Identity?.Name, out var id))
!authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
return Results.Unauthorized(); return Results.Unauthorized();
string token = authHeader.Substring("Bearer ".Length); return Results.Content($"{{\"accountId\":{id},\"disallowInAppPurchases\":false}}", "application/json");
string? accountId = jwtService.ValidateAndGetAccountId(token);
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out _))
return Results.Unauthorized();
return Results.Content($"{{\"accountId\":{accountId},\"disallowInAppPurchases\":false}}", "application/json");
} }
} }
@@ -24,17 +24,17 @@ public class AuthController : ControllerBase
} }
[HttpPost("connect/token")] [HttpPost("connect/token")]
public async Task<IResult> ConnectToken(HttpRequest httpRequest, AppDbContext db, JwtTokenService jwtService) { public async Task<IResult> ConnectToken(AppDbContext db, JwtTokenService jwtService) {
string accountId = ""; string accountId = "";
string platformId = ""; string platformId = "";
string platform = ""; string platform = "";
if (httpRequest.ContentLength is > 0) if (HttpContext.Request.ContentLength is > 0)
{ {
try try
{ {
httpRequest.EnableBuffering(); HttpContext.Request.EnableBuffering();
using StreamReader reader = new (httpRequest.Body, leaveOpen: true); using StreamReader reader = new (HttpContext.Request.Body, leaveOpen: true);
string body = await reader.ReadToEndAsync(); string body = await reader.ReadToEndAsync();
if (!string.IsNullOrWhiteSpace(body)) if (!string.IsNullOrWhiteSpace(body))
@@ -56,7 +56,7 @@ public class AuthController : ControllerBase
} }
} }
} }
httpRequest.Body.Position = 0; HttpContext.Request.Body.Position = 0;
} }
catch { } catch { }
} }
@@ -85,11 +85,11 @@ public class AuthController : ControllerBase
} }
[HttpPost("api/accounts/v1/forplatformids")] [HttpPost("api/accounts/v1/forplatformids")]
public async Task<IResult> AccountsForPlatformIds(HttpRequest request, AppDbContext db) { public async Task<IResult> AccountsForPlatformIds(AppDbContext db) {
request.EnableBuffering(); HttpContext.Request.EnableBuffering();
request.Body.Position = 0; HttpContext.Request.Body.Position = 0;
using var reader = new StreamReader(request.Body); using var reader = new StreamReader(HttpContext.Request.Body);
string body = await reader.ReadToEndAsync(); string body = await reader.ReadToEndAsync();
List<string> ids = []; List<string> ids = [];
@@ -238,14 +238,14 @@ public class EconController : ControllerBase
[HttpPost("api/settings/v2/set")] [HttpPost("api/settings/v2/set")]
[Authorize] [Authorize]
public async Task<IResult> SetSettings(HttpRequest request, AppDbContext db) public async Task<IResult> SetSettings(AppDbContext db)
{ {
if (!int.TryParse(User.Identity?.Name, out var id)) if (!int.TryParse(User.Identity?.Name, out var id))
return Results.Unauthorized(); return Results.Unauthorized();
request.EnableBuffering(); HttpContext.Request.EnableBuffering();
request.Body.Position = 0; HttpContext.Request.Body.Position = 0;
using var reader = new StreamReader(request.Body); using var reader = new StreamReader(HttpContext.Request.Body);
var body = await reader.ReadToEndAsync(); var body = await reader.ReadToEndAsync();
Console.WriteLine($"Settings request body: {body}"); Console.WriteLine($"Settings request body: {body}");
@@ -383,13 +383,11 @@ public class EconController : ControllerBase
[HttpGet("api/avatar/v3/saved")] [HttpGet("api/avatar/v3/saved")]
[Authorize] [Authorize]
public async Task<IResult> GetSavedAvatars(HttpRequest request, AppDbContext db) public async Task<IResult> GetSavedAvatars(AppDbContext db)
{ {
if (!int.TryParse(User.Identity?.Name, out var id)) if (!int.TryParse(User.Identity?.Name, out var id))
return Results.Unauthorized(); return Results.Unauthorized();
request.EnableBuffering();
var items = await db.SavedOutfits var items = await db.SavedOutfits
.Where(i => i.OwnerAccountId == id) .Where(i => i.OwnerAccountId == id)
.ToListAsync(); .ToListAsync();
@@ -23,9 +23,9 @@ public class MatchmakingController : ControllerBase
} }
[HttpGet("player")] [HttpGet("player")]
public async Task<IResult> GetPlayer(HttpRequest request, AppDbContext db) public async Task<IResult> GetPlayer(AppDbContext db)
{ {
var id = request.Query["id"].FirstOrDefault(); var id = HttpContext.Request.Query["id"].FirstOrDefault();
if (string.IsNullOrEmpty(id) || !int.TryParse(id, out var accountId)) if (string.IsNullOrEmpty(id) || !int.TryParse(id, out var accountId))
{ {
var json = System.IO.File.ReadAllText("JSON/getplayer.json"); var json = System.IO.File.ReadAllText("JSON/getplayer.json");
@@ -83,20 +83,20 @@ public class MatchmakingController : ControllerBase
[HttpPost("goto/room/{room}")] [HttpPost("goto/room/{room}")]
[Authorize] [Authorize]
public async Task<IResult> GotoRoom(HttpRequest request, string room, AppDbContext db) public async Task<IResult> GotoRoom(string room, AppDbContext db)
{ {
if (!int.TryParse(User.Identity?.Name, out var id)) if (!int.TryParse(User.Identity?.Name, out var id))
return Results.Unauthorized(); return Results.Unauthorized();
request.EnableBuffering(); HttpContext.Request.EnableBuffering();
request.Body.Position = 0; HttpContext.Request.Body.Position = 0;
var form = await request.ReadFormAsync(); var form = await HttpContext.Request.ReadFormAsync();
int joinMode = 0; int joinMode = 0;
if (int.TryParse(form["JoinMode"].ToString(), out var mode)) if (int.TryParse(form["JoinMode"].ToString(), out var mode))
{ {
joinMode = mode; joinMode = mode;
} }
request.Body.Position = 0; HttpContext.Request.Body.Position = 0;
Room? roomData = null; Room? roomData = null;
var roomLower = room.ToLower(); var roomLower = room.ToLower();
@@ -223,20 +223,20 @@ public class MatchmakingController : ControllerBase
[HttpPost("matchmake/{room}")] [HttpPost("matchmake/{room}")]
[Authorize] [Authorize]
public async Task<IResult> MatchmakeRoom(HttpRequest request, string room, AppDbContext db) public async Task<IResult> MatchmakeRoom(string room, AppDbContext db)
{ {
if (!int.TryParse(User.Identity?.Name, out var id)) if (!int.TryParse(User.Identity?.Name, out var id))
return Results.Unauthorized(); return Results.Unauthorized();
request.EnableBuffering(); HttpContext.Request.EnableBuffering();
request.Body.Position = 0; HttpContext.Request.Body.Position = 0;
var form = await request.ReadFormAsync(); var form = await HttpContext.Request.ReadFormAsync();
int joinMode = 0; int joinMode = 0;
if (int.TryParse(form["JoinMode"].ToString(), out var mode)) if (int.TryParse(form["JoinMode"].ToString(), out var mode))
{ {
joinMode = mode; joinMode = mode;
} }
request.Body.Position = 0; HttpContext.Request.Body.Position = 0;
Room? roomData = null; Room? roomData = null;
var roomLower = room.ToLower(); var roomLower = room.ToLower();
@@ -391,18 +391,18 @@ public class MatchmakingController : ControllerBase
[HttpPost("player/heartbeat")] [HttpPost("player/heartbeat")]
[Authorize] [Authorize]
public async Task<IResult> PlayerHeartbeat(HttpRequest request, AppDbContext db) public async Task<IResult> PlayerHeartbeat(AppDbContext db)
{ {
if (!int.TryParse(User.Identity?.Name, out var id)) if (!int.TryParse(User.Identity?.Name, out var id))
return Results.Unauthorized(); return Results.Unauthorized();
request.EnableBuffering(); HttpContext.Request.EnableBuffering();
request.Body.Position = 0; HttpContext.Request.Body.Position = 0;
using var reader = new StreamReader(request.Body); using var reader = new StreamReader(HttpContext.Request.Body);
var body = await reader.ReadToEndAsync(); var body = await reader.ReadToEndAsync();
request.Body.Position = 0; HttpContext.Request.Body.Position = 0;
var form = await request.ReadFormAsync(); var form = await HttpContext.Request.ReadFormAsync();
var loginLock = form["LoginLock"].ToString(); var loginLock = form["LoginLock"].ToString();
HeartbeatRequest? heartbeat = null; HeartbeatRequest? heartbeat = null;
@@ -8,7 +8,7 @@ namespace CannedNet.Services.Controllers;
[ApiController, Route("playersettings")] [ApiController, Route("playersettings")]
public class PlayerSettingsController : ControllerBase public class PlayerSettingsController : ControllerBase
{ {
[HttpGet("playersettings")] [HttpGet("/playersettings")]
[Authorize] [Authorize]
public async Task<IResult> GetPlayerSettings(AppDbContext db) public async Task<IResult> GetPlayerSettings(AppDbContext db)
{ {
@@ -63,18 +63,18 @@ public class PlayerSettingsController : ControllerBase
return Results.Json(settings); return Results.Json(settings);
} }
[HttpPut("playersettings")] [HttpPut("/playersettings")]
[Authorize] [Authorize]
public async Task<IResult> PutPlayerSettings(HttpRequest request, AppDbContext db) public async Task<IResult> PutPlayerSettings(AppDbContext db)
{ {
if (!int.TryParse(User.Identity?.Name, out var id)) if (!int.TryParse(User.Identity?.Name, out var id))
return Results.Unauthorized(); return Results.Unauthorized();
var settings = new List<PlayerSetting>(); var settings = new List<PlayerSetting>();
if (request.ContentType?.Contains("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase) == true) if (HttpContext.Request.ContentType?.Contains("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase) == true)
{ {
var form = await request.ReadFormAsync(); var form = await HttpContext.Request.ReadFormAsync();
var key = form["key"].FirstOrDefault(); var key = form["key"].FirstOrDefault();
var value = form["value"].FirstOrDefault(); var value = form["value"].FirstOrDefault();
if (!string.IsNullOrEmpty(key)) if (!string.IsNullOrEmpty(key))
@@ -82,11 +82,11 @@ public class PlayerSettingsController : ControllerBase
} }
else else
{ {
request.EnableBuffering(); HttpContext.Request.EnableBuffering();
request.Body.Position = 0; HttpContext.Request.Body.Position = 0;
using var reader = new StreamReader(request.Body, leaveOpen: true); using var reader = new StreamReader(HttpContext.Request.Body, leaveOpen: true);
var body = await reader.ReadToEndAsync(); var body = await reader.ReadToEndAsync();
request.Body.Position = 0; HttpContext.Request.Body.Position = 0;
Console.WriteLine($"Settings request body: {body}"); Console.WriteLine($"Settings request body: {body}");
@@ -8,10 +8,10 @@ namespace CannedNet.Services.Controllers;
public class RoomsController : ControllerBase public class RoomsController : ControllerBase
{ {
[HttpGet("rooms")] [HttpGet("rooms")]
public async Task<IResult> GetRooms(HttpRequest request, AppDbContext db) public async Task<IResult> GetRooms(AppDbContext db)
{ {
var idParam = request.Query["id"].FirstOrDefault(); var idParam = HttpContext.Request.Query["id"].FirstOrDefault();
var nameParam = request.Query["name"].FirstOrDefault(); var nameParam = HttpContext.Request.Query["name"].FirstOrDefault();
if (string.IsNullOrEmpty(idParam) && string.IsNullOrEmpty(nameParam)) if (string.IsNullOrEmpty(idParam) && string.IsNullOrEmpty(nameParam))
return Results.BadRequest("Either 'id' or 'name' query parameter is required"); return Results.BadRequest("Either 'id' or 'name' query parameter is required");
+2 -2
View File
@@ -33,11 +33,11 @@ public class JwtTokenService
var claims = new List<Claim> var claims = new List<Claim>
{ {
new Claim("iss", "https://api.lapis.codes"), new Claim("iss", "https://lapis.codes"),
new Claim("nbf", ((DateTimeOffset)now).ToUnixTimeSeconds().ToString()), new Claim("nbf", ((DateTimeOffset)now).ToUnixTimeSeconds().ToString()),
new Claim("iat", ((DateTimeOffset)now).ToUnixTimeSeconds().ToString()), new Claim("iat", ((DateTimeOffset)now).ToUnixTimeSeconds().ToString()),
new Claim("exp", ((DateTimeOffset)exp).ToUnixTimeSeconds().ToString()), new Claim("exp", ((DateTimeOffset)exp).ToUnixTimeSeconds().ToString()),
new Claim("aud", "https://api.lapis.codes/resources"), new Claim("aud", "https://lapis.codes/resources"),
new Claim("amr", "cached_login"), new Claim("amr", "cached_login"),
new Claim("client_id", "recroom"), new Claim("client_id", "recroom"),
new Claim("sub", accountId), new Claim("sub", accountId),