mirror of
https://github.com/CannedNet/CannedNet.git
synced 2026-10-25 23:18:54 -07:00
Few more migrations
This commit is contained in:
+101
-38
@@ -1,48 +1,111 @@
|
|||||||
using CannedNet;
|
using CannedNet.Data;
|
||||||
|
using CannedNet.Hubs;
|
||||||
using CannedNet.Services;
|
using CannedNet.Services;
|
||||||
using CannedNet.Services.Infrastructure;
|
using CannedNet.Services.Infrastructure;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
var apps = new List<(WebApplication App, ServiceRegistry Service)>();
|
namespace CannedNet;
|
||||||
|
|
||||||
foreach (var service in Services.All)
|
public static class Program
|
||||||
{
|
{
|
||||||
var builder = WebApplication.CreateBuilder();
|
public static async Task Main(string[] args) {
|
||||||
|
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
builder.Services.AddLogging(logging =>
|
//builder.Services.AddLogging(logging => {
|
||||||
{
|
// logging.AddConsole();
|
||||||
logging.AddConsole();
|
// logging.SetMinimumLevel(LogLevel.Debug);
|
||||||
logging.SetMinimumLevel(LogLevel.Debug);
|
//});
|
||||||
});
|
|
||||||
|
|
||||||
service.ConfigureBuilder(builder);
|
string connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? "Host=localhost;Port=5432;Database=cannednet;Username=postgres;Password=postgres";
|
||||||
builder.WebHost.UseUrls($"http://*:{service.Port}");
|
|
||||||
builder.Configuration.AddJsonFile($"AppConfigs/appsettings.{service.Name}.json", optional: true, reloadOnChange: true);
|
|
||||||
|
|
||||||
apps.Add((builder.Build(), service));
|
builder.Services.AddControllers();
|
||||||
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
builder.Services.AddSwaggerGen();
|
||||||
|
|
||||||
|
builder.Services.ConfigureHttpJsonOptions(options => options.SerializerOptions.PropertyNamingPolicy = null);
|
||||||
|
builder.Services.AddDbContext<AppDbContext>(options => options.UseNpgsql(connectionString));
|
||||||
|
builder.Services.AddSingleton<NotificationService>();
|
||||||
|
builder.Services.AddScoped<StorefrontFillService>();
|
||||||
|
builder.Services.AddScoped<JwtTokenService>();
|
||||||
|
builder.Services.AddSignalR();
|
||||||
|
|
||||||
|
WebApplication app = builder.Build();
|
||||||
|
|
||||||
|
app.MapHub<NotificationsHub>("/hub/v1");
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
//app.UseRequestLogging();
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
IHubContext<NotificationsHub> hubContext = app.Services.GetRequiredService<IHubContext<NotificationsHub>>();
|
||||||
|
NotificationService.SetHubContext(hubContext);
|
||||||
|
|
||||||
|
//if (app.Environment.IsDevelopment()) {
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI(options => {
|
||||||
|
options.SwaggerEndpoint("/swagger/v1/swagger.json", "CannedNet v1");
|
||||||
|
options.RoutePrefix = "swagger/ui/";
|
||||||
|
});
|
||||||
|
//}
|
||||||
|
|
||||||
|
using IServiceScope scope = app.Services.CreateScope();
|
||||||
|
AppDbContext db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
|
||||||
|
StorefrontFillService seedingService = scope.ServiceProvider.GetRequiredService<StorefrontFillService>();
|
||||||
|
await seedingService.FillStorefrontsAsync();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await db.Database.MigrateAsync();
|
||||||
|
} catch {
|
||||||
|
await db.Database.EnsureCreatedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
await app.RunAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
//public static async Task T() {
|
||||||
|
// List<(WebApplication App, ServiceRegistry Service)> apps = new();
|
||||||
|
//
|
||||||
|
// foreach (var service in Services.Infrastructure.Services.All)
|
||||||
|
// {
|
||||||
|
// var builder = WebApplication.CreateBuilder();
|
||||||
|
//
|
||||||
|
// builder.Services.AddLogging(logging =>
|
||||||
|
// {
|
||||||
|
// logging.AddConsole();
|
||||||
|
// logging.SetMinimumLevel(LogLevel.Debug);
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// service.ConfigureBuilder(builder);
|
||||||
|
// builder.WebHost.UseUrls($"http://*:{service.Port}");
|
||||||
|
// builder.Configuration.AddJsonFile($"AppConfigs/appsettings.{service.Name}.json", optional: true, reloadOnChange: true);
|
||||||
|
//
|
||||||
|
// apps.Add((builder.Build(), service));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// using var scope = apps[0].App.Services.CreateScope();
|
||||||
|
// var dbContext = scope.ServiceProvider.GetRequiredService<CannedNet.Data.AppDbContext>();
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// dbContext.Database.Migrate();
|
||||||
|
// }
|
||||||
|
// catch (Exception ex)
|
||||||
|
// {
|
||||||
|
// dbContext.Database.EnsureCreated();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // automatically fill out storefronts tables from the JSON's
|
||||||
|
// var seedingService = scope.ServiceProvider.GetRequiredService<StorefrontFillService>();
|
||||||
|
// await seedingService.FillStorefrontsAsync();
|
||||||
|
//
|
||||||
|
// var jwtService = scope.ServiceProvider.GetRequiredService<JwtTokenService>();
|
||||||
|
//
|
||||||
|
// foreach (var (app, service) in apps)
|
||||||
|
// {
|
||||||
|
// service.MapEndpoints(app, jwtService);
|
||||||
|
// app.UseRequestLogging();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// await Task.WhenAll(apps.Select(t => t.App.RunAsync()));
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
using var scope = apps[0].App.Services.CreateScope();
|
|
||||||
var dbContext = scope.ServiceProvider.GetRequiredService<CannedNet.Data.AppDbContext>();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
dbContext.Database.Migrate();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
dbContext.Database.EnsureCreated();
|
|
||||||
}
|
|
||||||
|
|
||||||
// automatically fill out storefronts tables from the JSON's
|
|
||||||
var seedingService = scope.ServiceProvider.GetRequiredService<StorefrontFillService>();
|
|
||||||
await seedingService.FillStorefrontsAsync();
|
|
||||||
|
|
||||||
var jwtService = scope.ServiceProvider.GetRequiredService<JwtTokenService>();
|
|
||||||
|
|
||||||
foreach (var (app, service) in apps)
|
|
||||||
{
|
|
||||||
service.MapEndpoints(app, jwtService);
|
|
||||||
app.UseRequestLogging();
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.WhenAll(apps.Select(t => t.App.RunAsync()));
|
|
||||||
|
|||||||
@@ -1,512 +1,458 @@
|
|||||||
using CannedNet.Data;
|
using CannedNet.Data;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using CannedNet.Services;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using CannedNet.Services.Infrastructure;
|
using Microsoft.Extensions.Primitives;
|
||||||
|
|
||||||
namespace CannedNet.Services.Controllers;
|
namespace CannedNet.Services.Controllers;
|
||||||
|
|
||||||
public class AccountsController
|
//TODO: remove duplicate code(most of it is checking if the user is authenticated, ASP.NET has stuff for this)
|
||||||
|
[ApiController, Route("account")]
|
||||||
|
public class AccountsController : ControllerBase
|
||||||
{
|
{
|
||||||
public WebApplicationBuilder Initialize(string[]? args = null) => ServiceExtensions.CreateRecNetBuilder(args);
|
//[HttpGet]
|
||||||
|
//public Task<IResult> Root() {
|
||||||
|
// return Task.FromResult(Results.Ok("FUCKL MYSJDIOJD"));
|
||||||
|
//}
|
||||||
|
|
||||||
public void MapEndpoints(WebApplication app, JwtTokenService jwtService)
|
[HttpGet("me")]
|
||||||
{
|
public async Task<IResult> Me(HttpRequest request, AppDbContext db, JwtTokenService jwtService) {
|
||||||
app.MapGet("/", (HttpRequest request) =>
|
string authHeader = request.Headers.Authorization.ToString();
|
||||||
{
|
|
||||||
return Results.Ok("FUCKL MYSJDIOJD");
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapGet("/account/me", async (HttpRequest request, AppDbContext db) =>
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
return Results.Unauthorized();
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
string token = authHeader.Substring("Bearer ".Length);
|
||||||
return Results.Unauthorized();
|
string? accountId = jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out int id))
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
return Results.Unauthorized();
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
Account? account = await db.Accounts.FindAsync(id);
|
||||||
return Results.Unauthorized();
|
if (account == null)
|
||||||
|
return Results.NotFound();
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
SelfAccount selfAccount = new SelfAccount {
|
||||||
return Results.Unauthorized();
|
AccountId = id,
|
||||||
|
ProfileImage = account.ProfileImage ?? "hdqeamlcmatc6qzoi2ybgf0ddijjcf.jpg",
|
||||||
|
IsJunior = account.IsJunior,
|
||||||
|
Platforms = account.Platforms ?? 0,
|
||||||
|
PersonalPronouns = account.PersonalPronouns ?? 0,
|
||||||
|
IdentityFlags = account.IdentityFlags ?? 0,
|
||||||
|
Username = account.Username ?? $"Player{id}",
|
||||||
|
DisplayName = account.DisplayName ?? $"Player{id}",
|
||||||
|
CreatedAt = account.CreatedAt,
|
||||||
|
Email = null,
|
||||||
|
Phone = null,
|
||||||
|
JuniorState = null,
|
||||||
|
Birthday = null,
|
||||||
|
ParentAccountId = null,
|
||||||
|
AvailableUsernameChanges = 1
|
||||||
|
};
|
||||||
|
|
||||||
var account = await db.Accounts.FindAsync(id);
|
return Results.Ok(selfAccount);
|
||||||
if (account == null)
|
}
|
||||||
return Results.NotFound();
|
|
||||||
|
|
||||||
var selfAccount = new SelfAccount
|
[HttpGet("bulk")]
|
||||||
{
|
public async Task<IResult> Bulk(HttpRequest request, AppDbContext db) {
|
||||||
AccountId = id,
|
StringValues ids = request.Query["id"];
|
||||||
ProfileImage = account.ProfileImage ?? "hdqeamlcmatc6qzoi2ybgf0ddijjcf.jpg",
|
List<int> accountIds = [];
|
||||||
IsJunior = account.IsJunior,
|
|
||||||
Platforms = account.Platforms ?? 0,
|
|
||||||
PersonalPronouns = account.PersonalPronouns ?? 0,
|
|
||||||
IdentityFlags = account.IdentityFlags ?? 0,
|
|
||||||
Username = account.Username ?? $"Player{id}",
|
|
||||||
DisplayName = account.DisplayName ?? $"Player{id}",
|
|
||||||
CreatedAt = account.CreatedAt,
|
|
||||||
Email = null,
|
|
||||||
Phone = null,
|
|
||||||
JuniorState = null,
|
|
||||||
Birthday = null,
|
|
||||||
ParentAccountId = null,
|
|
||||||
AvailableUsernameChanges = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
return Results.Ok(selfAccount);
|
foreach (string? id in ids) {
|
||||||
});
|
if (int.TryParse(id, out int accountId)) {
|
||||||
|
accountIds.Add(accountId);
|
||||||
app.MapGet("/account/bulk", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var ids = request.Query["id"];
|
|
||||||
var accountIds = new List<int>();
|
|
||||||
|
|
||||||
foreach (var id in ids)
|
|
||||||
{
|
|
||||||
if (int.TryParse(id, out var accountId))
|
|
||||||
{
|
|
||||||
accountIds.Add(accountId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var 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();
|
||||||
|
|
||||||
var 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,
|
Platforms = a.Platforms ?? 0,
|
||||||
Platforms = a.Platforms ?? 0,
|
PersonalPronouns = a.PersonalPronouns ?? 0,
|
||||||
PersonalPronouns = a.PersonalPronouns ?? 0,
|
IdentityFlags = a.IdentityFlags ?? 0,
|
||||||
IdentityFlags = a.IdentityFlags ?? 0,
|
Username = a.Username ?? $"Player{a.AccountId}",
|
||||||
Username = a.Username ?? $"Player{a.AccountId}",
|
DisplayName = a.DisplayName ?? $"Player{a.AccountId}",
|
||||||
DisplayName = a.DisplayName ?? $"Player{a.AccountId}",
|
CreatedAt = a.CreatedAt
|
||||||
CreatedAt = a.CreatedAt
|
}).ToList();
|
||||||
}).ToList();
|
|
||||||
|
|
||||||
return Results.Json(result);
|
return Results.Json(result);
|
||||||
});
|
}
|
||||||
|
|
||||||
app.MapGet("/account/{id}", async (HttpRequest request, string id, AppDbContext db) =>
|
[HttpGet("{id}")]
|
||||||
{
|
public async Task<IResult> Id(HttpRequest request, string id, AppDbContext db) {
|
||||||
if (!int.TryParse(id, out var accountId))
|
if (!int.TryParse(id, out int accountId))
|
||||||
return Results.BadRequest();
|
return Results.BadRequest();
|
||||||
|
|
||||||
var account = await db.Accounts.FindAsync(accountId);
|
Account? account = await db.Accounts.FindAsync(accountId);
|
||||||
if (account == null)
|
if (account == null)
|
||||||
return Results.NotFound();
|
return Results.NotFound();
|
||||||
|
|
||||||
var result = new Account
|
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,
|
Platforms = account.Platforms ?? 0,
|
||||||
Platforms = account.Platforms ?? 0,
|
PersonalPronouns = account.PersonalPronouns ?? 0,
|
||||||
PersonalPronouns = account.PersonalPronouns ?? 0,
|
IdentityFlags = account.IdentityFlags ?? 0,
|
||||||
IdentityFlags = account.IdentityFlags ?? 0,
|
Username = account.Username ?? $"Player{account.AccountId}",
|
||||||
Username = account.Username ?? $"Player{account.AccountId}",
|
DisplayName = account.DisplayName ?? $"Player{account.AccountId}",
|
||||||
DisplayName = account.DisplayName ?? $"Player{account.AccountId}",
|
CreatedAt = account.CreatedAt
|
||||||
CreatedAt = account.CreatedAt
|
};
|
||||||
};
|
|
||||||
|
|
||||||
return Results.Json(result);
|
return Results.Json(result);
|
||||||
});
|
}
|
||||||
|
|
||||||
app.MapPost("/account/create", async (HttpRequest httpRequest, AppDbContext db) =>
|
[HttpPost("cerate")]
|
||||||
{
|
public async Task<IResult> Create(HttpRequest httpRequest, AppDbContext db) {
|
||||||
int platform = 0;
|
int platform = 0;
|
||||||
string platformId = "";
|
string platformId = "";
|
||||||
|
|
||||||
if (httpRequest.ContentLength.HasValue && httpRequest.ContentLength > 0)
|
if (httpRequest.ContentLength is > 0) {
|
||||||
{
|
try {
|
||||||
try
|
string contentType = httpRequest.ContentType ?? "";
|
||||||
{
|
httpRequest.EnableBuffering();
|
||||||
var contentType = httpRequest.ContentType ?? "";
|
|
||||||
httpRequest.EnableBuffering();
|
|
||||||
|
|
||||||
using var reader = new StreamReader(httpRequest.Body, leaveOpen: true);
|
using StreamReader reader = new(httpRequest.Body, leaveOpen: true);
|
||||||
var 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 (var pair in body.Split('&'))
|
string[] keyValue = pair.Split('=');
|
||||||
{
|
if (keyValue.Length != 2) continue;
|
||||||
var keyValue = pair.Split('=');
|
string key = Uri.UnescapeDataString(keyValue[0]);
|
||||||
if (keyValue.Length == 2)
|
string value = Uri.UnescapeDataString(keyValue[1]);
|
||||||
{
|
|
||||||
var key = Uri.UnescapeDataString(keyValue[0]);
|
|
||||||
var value = Uri.UnescapeDataString(keyValue[1]);
|
|
||||||
|
|
||||||
if (key == "platform" && int.TryParse(value, out var parsedPlatform))
|
switch (key) {
|
||||||
platform = parsedPlatform;
|
case "platform" when int.TryParse(value, out var parsedPlatform):
|
||||||
else if (key == "platformId")
|
platform = parsedPlatform;
|
||||||
platformId = value;
|
break;
|
||||||
}
|
case "platformId":
|
||||||
|
platformId = value;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
httpRequest.Body.Position = 0;
|
|
||||||
}
|
}
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
var accountId = new Random().Next(10000, 99999);
|
httpRequest.Body.Position = 0;
|
||||||
var account = new Account
|
}
|
||||||
{
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
int accountId = new Random().Next(10000, 99999);
|
||||||
|
Account account = new() {
|
||||||
|
AccountId = accountId,
|
||||||
|
ProfileImage = "DefaultProfileImage.jpg",
|
||||||
|
IsJunior = false,
|
||||||
|
Platforms = 0,
|
||||||
|
PersonalPronouns = 0,
|
||||||
|
IdentityFlags = 0,
|
||||||
|
Username = $"Player{accountId}",
|
||||||
|
DisplayName = $"Player{accountId}",
|
||||||
|
CreatedAt = DateTime.UtcNow
|
||||||
|
};
|
||||||
|
|
||||||
|
db.Accounts.Add(account);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(platformId)) {
|
||||||
|
db.CachedLogins.Add(new CachedLogin {
|
||||||
AccountId = accountId,
|
AccountId = accountId,
|
||||||
ProfileImage = "DefaultProfileImage.jpg",
|
Platform = (PlatformType)platform,
|
||||||
IsJunior = false,
|
PlatformID = platformId,
|
||||||
Platforms = 0,
|
LastLoginTime = DateTime.UtcNow,
|
||||||
PersonalPronouns = 0,
|
RequirePassword = false
|
||||||
IdentityFlags = 0,
|
});
|
||||||
Username = $"Player{accountId}",
|
}
|
||||||
DisplayName = $"Player{accountId}",
|
|
||||||
CreatedAt = DateTime.UtcNow
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
// create players dorm room
|
||||||
|
int maxRoomId = await db.Rooms.MaxAsync(r => (int?)r.RoomId) ?? 0;
|
||||||
|
int maxId = await db.Rooms.MaxAsync(r => (int?)r.Id) ?? 0;
|
||||||
|
int dormRoomId = maxRoomId + 1;
|
||||||
|
//int dormId = maxId + 1;
|
||||||
|
Room dormRoom = new Room {
|
||||||
|
Id = maxId + 1,
|
||||||
|
RoomId = dormRoomId,
|
||||||
|
Name = "DormRoom",
|
||||||
|
Description = "Your personal room",
|
||||||
|
CreatorAccountId = accountId,
|
||||||
|
ImageName = "",
|
||||||
|
State = 0,
|
||||||
|
Accessibility = 0,
|
||||||
|
SupportsLevelVoting = false,
|
||||||
|
IsRRO = false,
|
||||||
|
IsDorm = true,
|
||||||
|
CloningAllowed = false,
|
||||||
|
SupportsVRLow = true,
|
||||||
|
SupportsQuest2 = true,
|
||||||
|
SupportsMobile = true,
|
||||||
|
SupportsScreens = true,
|
||||||
|
SupportsWalkVR = true,
|
||||||
|
SupportsTeleportVR = true,
|
||||||
|
SupportsJuniors = true,
|
||||||
|
MinLevel = 0,
|
||||||
|
WarningMask = 0,
|
||||||
|
CustomWarning = null,
|
||||||
|
DisableMicAutoMute = false,
|
||||||
|
DisableRoomComments = false,
|
||||||
|
EncryptVoiceChat = false,
|
||||||
|
CreatedAt = DateTime.UtcNow,
|
||||||
|
Tags = "[]"
|
||||||
|
};
|
||||||
|
db.Rooms.Add(dormRoom);
|
||||||
|
|
||||||
|
// Create a sub room for the dorm
|
||||||
|
SubRoom dormSubRoom = new SubRoom {
|
||||||
|
RoomId = dormRoomId,
|
||||||
|
SubRoomId = 1,
|
||||||
|
Name = "DormRoom",
|
||||||
|
DataBlob = "",
|
||||||
|
IsSandbox = false,
|
||||||
|
MaxPlayers = 4,
|
||||||
|
Accessibility = 0,
|
||||||
|
UnitySceneId = "76d98498-60a1-430c-ab76-b54a29b7a163", // Dorm scene ID
|
||||||
|
DataSavedAt = DateTime.UtcNow
|
||||||
|
};
|
||||||
|
db.SubRooms.Add(dormSubRoom);
|
||||||
|
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
return Results.Ok(RecNetResult.Ok(account));
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("me/displayname")]
|
||||||
|
public async Task<IResult> PutMeDisplayName(HttpRequest request, AppDbContext db, JwtTokenService jwtService) {
|
||||||
|
string authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) || !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 var id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
|
string newDisplayName = "";
|
||||||
|
|
||||||
|
if (request.ContentLength is > 0) {
|
||||||
|
try {
|
||||||
|
request.EnableBuffering();
|
||||||
|
using StreamReader reader = new(request.Body, leaveOpen: true);
|
||||||
|
string body = await reader.ReadToEndAsync();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(body)) {
|
||||||
|
foreach (string pair in body.Split('&')) {
|
||||||
|
string[] keyValue = pair.Split('=');
|
||||||
|
if (keyValue.Length != 2) continue;
|
||||||
|
string key = Uri.UnescapeDataString(keyValue[0]);
|
||||||
|
string value = Uri.UnescapeDataString(keyValue[1]);
|
||||||
|
|
||||||
|
if (key == "displayName")
|
||||||
|
newDisplayName = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request.Body.Position = 0;
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
Account? account = await db.Accounts.FindAsync(id);
|
||||||
|
if (account == null)
|
||||||
|
return Results.NotFound();
|
||||||
|
|
||||||
|
account.DisplayName = newDisplayName;
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
return Results.Ok(RecNetResult.Ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("me/username")]
|
||||||
|
public async Task<IResult> PutMeUsername(HttpRequest request, AppDbContext db, JwtTokenService jwtService) {
|
||||||
|
string authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) ||
|
||||||
|
!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();
|
||||||
|
|
||||||
|
string newAccountName = "";
|
||||||
|
|
||||||
|
if (request.ContentLength is > 0) {
|
||||||
|
try {
|
||||||
|
request.EnableBuffering();
|
||||||
|
using StreamReader reader = new(request.Body, leaveOpen: true);
|
||||||
|
string body = await reader.ReadToEndAsync();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(body)) {
|
||||||
|
foreach (string pair in body.Split('&')) {
|
||||||
|
string[] keyValue = pair.Split('=');
|
||||||
|
if (keyValue.Length != 2) continue;
|
||||||
|
string key = Uri.UnescapeDataString(keyValue[0]);
|
||||||
|
string value = Uri.UnescapeDataString(keyValue[1]);
|
||||||
|
|
||||||
|
if (key == "username")
|
||||||
|
newAccountName = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request.Body.Position = 0;
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
Account? account = await db.Accounts.FindAsync(id);
|
||||||
|
if (account == null)
|
||||||
|
return Results.NotFound();
|
||||||
|
|
||||||
|
account.Username = newAccountName;
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
return Results.Ok(RecNetResult.Ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("{id}/bio")]
|
||||||
|
public async Task<IResult> GetBio(string id, AppDbContext db) {
|
||||||
|
if (!int.TryParse(id, out int accountId))
|
||||||
|
return Results.BadRequest();
|
||||||
|
|
||||||
|
PlayerBio? bio = await db.PlayerBios.FirstOrDefaultAsync(b => b.accountId == accountId);
|
||||||
|
|
||||||
|
return Results.Json(bio == null
|
||||||
|
? new { accountId = accountId, bio = "" }
|
||||||
|
: new { accountId = bio.accountId, bio = bio.bio });
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("me/bio")]
|
||||||
|
public async Task<IResult> PutMeBio(HttpRequest request, AppDbContext db, JwtTokenService jwtService) {
|
||||||
|
string authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(authHeader) ||
|
||||||
|
!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();
|
||||||
|
|
||||||
|
string newBio = "";
|
||||||
|
|
||||||
|
if (request.ContentLength is > 0) {
|
||||||
|
try {
|
||||||
|
request.EnableBuffering();
|
||||||
|
using StreamReader reader = new StreamReader(request.Body, leaveOpen: true);
|
||||||
|
string body = await reader.ReadToEndAsync();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(body)) {
|
||||||
|
foreach (string pair in body.Split('&')) {
|
||||||
|
string[] keyValue = pair.Split('=');
|
||||||
|
if (keyValue.Length != 2) continue;
|
||||||
|
string key = Uri.UnescapeDataString(keyValue[0]);
|
||||||
|
string value = Uri.UnescapeDataString(keyValue[1]);
|
||||||
|
|
||||||
|
if (key == "bio")
|
||||||
|
newBio = Uri.UnescapeDataString(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request.Body.Position = 0;
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerBio? bio = await db.PlayerBios.FirstOrDefaultAsync(b => b.accountId == id);
|
||||||
|
|
||||||
|
if (bio == null) {
|
||||||
|
bio = new PlayerBio {
|
||||||
|
accountId = id,
|
||||||
|
bio = newBio
|
||||||
};
|
};
|
||||||
|
db.PlayerBios.Add(bio);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bio.bio = newBio;
|
||||||
|
db.PlayerBios.Update(bio);
|
||||||
|
}
|
||||||
|
|
||||||
db.Accounts.Add(account);
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(platformId))
|
return Results.Json(new { success = true });
|
||||||
{
|
}
|
||||||
db.CachedLogins.Add(new CachedLogin
|
|
||||||
{
|
|
||||||
AccountId = accountId,
|
|
||||||
Platform = (PlatformType)platform,
|
|
||||||
PlatformID = platformId,
|
|
||||||
LastLoginTime = DateTime.UtcNow,
|
|
||||||
RequirePassword = false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
[HttpPut("me/profileimage")]
|
||||||
|
public async Task<IResult> PutMeProfileImage(HttpRequest request, AppDbContext db, JwtTokenService jwtService) {
|
||||||
|
string authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
// create players dorm room
|
if (string.IsNullOrEmpty(authHeader) ||
|
||||||
var maxRoomId = await db.Rooms.MaxAsync(r => (int?)r.RoomId) ?? 0;
|
!authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
var maxId = await db.Rooms.MaxAsync(r => (int?)r.Id) ?? 0;
|
return Results.Unauthorized();
|
||||||
var dormRoomId = maxRoomId + 1;
|
|
||||||
var dormId = maxId + 1;
|
|
||||||
var dormRoom = new Room
|
|
||||||
{
|
|
||||||
Id = maxId + 1,
|
|
||||||
RoomId = dormRoomId,
|
|
||||||
Name = "DormRoom",
|
|
||||||
Description = "Your personal room",
|
|
||||||
CreatorAccountId = accountId,
|
|
||||||
ImageName = "",
|
|
||||||
State = 0,
|
|
||||||
Accessibility = 0,
|
|
||||||
SupportsLevelVoting = false,
|
|
||||||
IsRRO = false,
|
|
||||||
IsDorm = true,
|
|
||||||
CloningAllowed = false,
|
|
||||||
SupportsVRLow = true,
|
|
||||||
SupportsQuest2 = true,
|
|
||||||
SupportsMobile = true,
|
|
||||||
SupportsScreens = true,
|
|
||||||
SupportsWalkVR = true,
|
|
||||||
SupportsTeleportVR = true,
|
|
||||||
SupportsJuniors = true,
|
|
||||||
MinLevel = 0,
|
|
||||||
WarningMask = 0,
|
|
||||||
CustomWarning = null,
|
|
||||||
DisableMicAutoMute = false,
|
|
||||||
DisableRoomComments = false,
|
|
||||||
EncryptVoiceChat = false,
|
|
||||||
CreatedAt = DateTime.UtcNow,
|
|
||||||
Tags = "[]"
|
|
||||||
};
|
|
||||||
db.Rooms.Add(dormRoom);
|
|
||||||
|
|
||||||
// Create a sub room for the dorm
|
string token = authHeader.Substring("Bearer ".Length);
|
||||||
var dormSubRoom = new SubRoom
|
string? accountId = jwtService.ValidateAndGetAccountId(token);
|
||||||
{
|
|
||||||
RoomId = dormRoomId,
|
|
||||||
SubRoomId = 1,
|
|
||||||
Name = "DormRoom",
|
|
||||||
DataBlob = "",
|
|
||||||
IsSandbox = false,
|
|
||||||
MaxPlayers = 4,
|
|
||||||
Accessibility = 0,
|
|
||||||
UnitySceneId = "76d98498-60a1-430c-ab76-b54a29b7a163", // Dorm scene ID
|
|
||||||
DataSavedAt = DateTime.UtcNow
|
|
||||||
};
|
|
||||||
db.SubRooms.Add(dormSubRoom);
|
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out int id))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
return Results.Ok(RecNetResultWithValue<Account>.Ok(account));
|
string newProfileImage = "";
|
||||||
});
|
|
||||||
app.MapGet("/parentalcontrol/me", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
if (request.ContentLength is > 0) {
|
||||||
return Results.Unauthorized();
|
try {
|
||||||
|
request.EnableBuffering();
|
||||||
|
using StreamReader reader = new(request.Body, leaveOpen: true);
|
||||||
|
string body = await reader.ReadToEndAsync();
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
if (!string.IsNullOrWhiteSpace(body)) {
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
foreach (var pair in body.Split('&')) {
|
||||||
|
string[] keyValue = pair.Split('=');
|
||||||
|
if (keyValue.Length != 2) continue;
|
||||||
|
string key = Uri.UnescapeDataString(keyValue[0]);
|
||||||
|
string value = Uri.UnescapeDataString(keyValue[1]);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
if (key == "imageName")
|
||||||
return Results.Unauthorized();
|
newProfileImage = value;
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
return Results.Content($"{{\"accountId\":{accountId},\"disallowInAppPurchases\":false}}", "application/json");
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapPut("/account/me/displayname", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
string newDisplayName = "";
|
|
||||||
|
|
||||||
if (request.ContentLength.HasValue && request.ContentLength > 0)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
request.EnableBuffering();
|
|
||||||
using var reader = new StreamReader(request.Body, leaveOpen: true);
|
|
||||||
var body = await reader.ReadToEndAsync();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(body))
|
|
||||||
{
|
|
||||||
foreach (var pair in body.Split('&'))
|
|
||||||
{
|
|
||||||
var keyValue = pair.Split('=');
|
|
||||||
if (keyValue.Length == 2)
|
|
||||||
{
|
|
||||||
var key = Uri.UnescapeDataString(keyValue[0]);
|
|
||||||
var value = Uri.UnescapeDataString(keyValue[1]);
|
|
||||||
|
|
||||||
if (key == "displayName")
|
|
||||||
newDisplayName = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
request.Body.Position = 0;
|
|
||||||
}
|
}
|
||||||
catch { }
|
|
||||||
|
request.Body.Position = 0;
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
var account = await db.Accounts.FindAsync(id);
|
Account? account = await db.Accounts.FindAsync(id);
|
||||||
if (account == null)
|
if (account == null)
|
||||||
return Results.NotFound();
|
return Results.NotFound();
|
||||||
|
|
||||||
account.DisplayName = newDisplayName;
|
account.ProfileImage = newProfileImage;
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
return Results.Ok(RecNetResult.Ok());
|
return Results.Ok(RecNetResult.Ok());
|
||||||
});
|
}
|
||||||
|
|
||||||
app.MapPut("/account/me/username", async (HttpRequest request, AppDbContext db) =>
|
[HttpGet("parentalcontrol/me")]
|
||||||
{
|
public async Task<IResult> ParentalControl(HttpRequest request, JwtTokenService jwtService) {
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
string authHeader = request.Headers.Authorization.ToString();
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
if (string.IsNullOrEmpty(authHeader) ||
|
||||||
return Results.Unauthorized();
|
!authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Results.Unauthorized();
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
string token = authHeader.Substring("Bearer ".Length);
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
string? accountId = jwtService.ValidateAndGetAccountId(token);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
if (string.IsNullOrEmpty(accountId) || !int.TryParse(accountId.AsSpan(), out _))
|
||||||
return Results.Unauthorized();
|
return Results.Unauthorized();
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
return Results.Content($"{{\"accountId\":{accountId},\"disallowInAppPurchases\":false}}", "application/json");
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
string newAccountName = "";
|
|
||||||
|
|
||||||
if (request.ContentLength.HasValue && request.ContentLength > 0)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
request.EnableBuffering();
|
|
||||||
using var reader = new StreamReader(request.Body, leaveOpen: true);
|
|
||||||
var body = await reader.ReadToEndAsync();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(body))
|
|
||||||
{
|
|
||||||
foreach (var pair in body.Split('&'))
|
|
||||||
{
|
|
||||||
var keyValue = pair.Split('=');
|
|
||||||
if (keyValue.Length == 2)
|
|
||||||
{
|
|
||||||
var key = Uri.UnescapeDataString(keyValue[0]);
|
|
||||||
var value = Uri.UnescapeDataString(keyValue[1]);
|
|
||||||
|
|
||||||
if (key == "username")
|
|
||||||
newAccountName = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
request.Body.Position = 0;
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
var account = await db.Accounts.FindAsync(id);
|
|
||||||
if (account == null)
|
|
||||||
return Results.NotFound();
|
|
||||||
|
|
||||||
account.Username = newAccountName;
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
|
|
||||||
return Results.Ok(RecNetResult.Ok());
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapGet("/account/{id}/bio", async (HttpRequest request, string id, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
if (!int.TryParse(id, out var accountId))
|
|
||||||
return Results.BadRequest();
|
|
||||||
|
|
||||||
var bio = await db.PlayerBios.FirstOrDefaultAsync(b => b.accountId == accountId);
|
|
||||||
|
|
||||||
if (bio == null)
|
|
||||||
{
|
|
||||||
return Results.Json(new { accountId = accountId, bio = "" });
|
|
||||||
}
|
|
||||||
|
|
||||||
return Results.Json(new { accountId = bio.accountId, bio = bio.bio });
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapPut("/account/me/bio", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
string newBio = "";
|
|
||||||
|
|
||||||
if (request.ContentLength.HasValue && request.ContentLength > 0)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
request.EnableBuffering();
|
|
||||||
using var reader = new StreamReader(request.Body, leaveOpen: true);
|
|
||||||
var body = await reader.ReadToEndAsync();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(body))
|
|
||||||
{
|
|
||||||
foreach (var pair in body.Split('&'))
|
|
||||||
{
|
|
||||||
var keyValue = pair.Split('=');
|
|
||||||
if (keyValue.Length == 2)
|
|
||||||
{
|
|
||||||
var key = Uri.UnescapeDataString(keyValue[0]);
|
|
||||||
var value = Uri.UnescapeDataString(keyValue[1]);
|
|
||||||
|
|
||||||
if (key == "bio")
|
|
||||||
newBio = Uri.UnescapeDataString(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
request.Body.Position = 0;
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
var bio = await db.PlayerBios.FirstOrDefaultAsync(b => b.accountId == id);
|
|
||||||
|
|
||||||
if (bio == null)
|
|
||||||
{
|
|
||||||
bio = new PlayerBio
|
|
||||||
{
|
|
||||||
accountId = id,
|
|
||||||
bio = newBio
|
|
||||||
};
|
|
||||||
db.PlayerBios.Add(bio);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bio.bio = newBio;
|
|
||||||
db.PlayerBios.Update(bio);
|
|
||||||
}
|
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
|
|
||||||
return Results.Json(new { success = true });
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapPut("/account/me/profileimage", async (HttpRequest request, AppDbContext db) =>
|
|
||||||
{
|
|
||||||
var authHeader = request.Headers.Authorization.ToString();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
var token = authHeader.Substring("Bearer ".Length);
|
|
||||||
var accountId = jwtService.ValidateAndGetAccountId(token);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountId))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
if (!int.TryParse(accountId.AsSpan(), out var id))
|
|
||||||
return Results.Unauthorized();
|
|
||||||
|
|
||||||
string newProfileImage = "";
|
|
||||||
|
|
||||||
if (request.ContentLength.HasValue && request.ContentLength > 0)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
request.EnableBuffering();
|
|
||||||
using var reader = new StreamReader(request.Body, leaveOpen: true);
|
|
||||||
var body = await reader.ReadToEndAsync();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(body))
|
|
||||||
{
|
|
||||||
foreach (var pair in body.Split('&'))
|
|
||||||
{
|
|
||||||
var keyValue = pair.Split('=');
|
|
||||||
if (keyValue.Length == 2)
|
|
||||||
{
|
|
||||||
var key = Uri.UnescapeDataString(keyValue[0]);
|
|
||||||
var value = Uri.UnescapeDataString(keyValue[1]);
|
|
||||||
|
|
||||||
if (key == "imageName")
|
|
||||||
newProfileImage = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
request.Body.Position = 0;
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
var account = await db.Accounts.FindAsync(id);
|
|
||||||
if (account == null)
|
|
||||||
return Results.NotFound();
|
|
||||||
|
|
||||||
account.ProfileImage = newProfileImage;
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
|
|
||||||
return Results.Ok(RecNetResult.Ok());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
using CannedNet.Services.Infrastructure;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace CannedNet.Services.Controllers;
|
namespace CannedNet.Services.Controllers;
|
||||||
|
|
||||||
public class ChatController
|
[ApiController]
|
||||||
|
public class ChatController : ControllerBase
|
||||||
{
|
{
|
||||||
public WebApplicationBuilder Initialize(string[]? args = null) => ServiceExtensions.CreateRecNetBuilder(args);
|
[HttpGet("thread")]
|
||||||
|
public async Task<IResult> Get() {
|
||||||
|
return Results.Content("[]", "application/json");
|
||||||
|
|
||||||
public void MapEndpoints(WebApplication app)
|
|
||||||
{
|
|
||||||
app.MapGet("/thread", () => Results.Content("[]", "application/json"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using System.Net.Mime;
|
using CannedNet.Services.Infrastructure;
|
||||||
using CannedNet.Services.Infrastructure;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using SixLabors.ImageSharp;
|
using SixLabors.ImageSharp;
|
||||||
using SixLabors.ImageSharp.Formats.Jpeg;
|
using SixLabors.ImageSharp.Formats.Jpeg;
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
@@ -7,104 +7,91 @@ using SixLabors.ImageSharp.Processing;
|
|||||||
|
|
||||||
namespace CannedNet.Services.Controllers;
|
namespace CannedNet.Services.Controllers;
|
||||||
|
|
||||||
public class ImageController
|
[ApiController, Route("")]
|
||||||
|
public class ImageController : ControllerBase
|
||||||
{
|
{
|
||||||
private static readonly byte[] PlaceholderJpeg;
|
private static readonly byte[] PlaceholderJpeg;
|
||||||
|
|
||||||
static ImageController()
|
static ImageController() {
|
||||||
{
|
|
||||||
Signatures.Init();
|
Signatures.Init();
|
||||||
|
|
||||||
using var image = new Image<Rgba32>(64, 64);
|
using Image<Rgba32> image = new(64, 64);
|
||||||
image.Mutate(x => x.BackgroundColor(Color.FromRgb(32, 32, 32)));
|
image.Mutate(x => x.BackgroundColor(Color.FromRgb(32, 32, 32)));
|
||||||
using var ms = new MemoryStream();
|
using MemoryStream ms = new();
|
||||||
image.SaveAsJpeg(ms, new JpegEncoder { Quality = 50 });
|
image.SaveAsJpeg(ms, new JpegEncoder { Quality = 50 });
|
||||||
PlaceholderJpeg = ms.ToArray();
|
PlaceholderJpeg = ms.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebApplicationBuilder Initialize(string[]? args = null)
|
public WebApplicationBuilder Initialize(string[]? args = null) => ServiceExtensions.CreateRecNetBuilder(args);
|
||||||
=> ServiceExtensions.CreateRecNetBuilder(args);
|
|
||||||
|
|
||||||
public void MapEndpoints(WebApplication app)
|
[HttpGet("{imageName}")]
|
||||||
{
|
public async Task<IResult> GetImage(HttpContext context, string imageName) {
|
||||||
var imagesDir = Path.Combine("Images");
|
string imagesDir = Path.Combine("Images");
|
||||||
Directory.CreateDirectory(imagesDir);
|
Directory.CreateDirectory(imagesDir);
|
||||||
|
string filePath = Path.Combine(imagesDir, imageName);
|
||||||
|
|
||||||
app.MapGet("/{imageName}", async (HttpContext context, string imageName) =>
|
byte[] imageBytes;
|
||||||
{
|
string contentType;
|
||||||
var filePath = Path.Combine(imagesDir, imageName);
|
|
||||||
|
|
||||||
byte[] imageBytes;
|
if (System.IO.File.Exists(filePath)) {
|
||||||
string contentType;
|
imageBytes = await System.IO.File.ReadAllBytesAsync(filePath);
|
||||||
|
string ext = Path.GetExtension(imageName).ToLowerInvariant();
|
||||||
|
contentType = ext switch {
|
||||||
|
".jpg" or ".jpeg" => "image/jpeg",
|
||||||
|
".gif" => "image/gif",
|
||||||
|
".webp" => "image/webp",
|
||||||
|
".bmp" => "image/bmp",
|
||||||
|
_ => "image/png"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
imageBytes = PlaceholderJpeg;
|
||||||
|
contentType = "image/jpeg";
|
||||||
|
}
|
||||||
|
|
||||||
if (File.Exists(filePath))
|
string? cropSquare = context.Request.Query["cropSquare"].FirstOrDefault();
|
||||||
{
|
string? widthStr = context.Request.Query["width"].FirstOrDefault();
|
||||||
imageBytes = await File.ReadAllBytesAsync(filePath);
|
string? heightStr = context.Request.Query["height"].FirstOrDefault();
|
||||||
var ext = Path.GetExtension(imageName).ToLowerInvariant();
|
|
||||||
contentType = ext switch
|
|
||||||
{
|
|
||||||
".jpg" or ".jpeg" => "image/jpeg",
|
|
||||||
".gif" => "image/gif",
|
|
||||||
".webp" => "image/webp",
|
|
||||||
".bmp" => "image/bmp",
|
|
||||||
_ => "image/png"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
imageBytes = PlaceholderJpeg;
|
|
||||||
contentType = "image/jpeg";
|
|
||||||
}
|
|
||||||
|
|
||||||
var cropSquare = context.Request.Query["cropSquare"].FirstOrDefault();
|
if (string.IsNullOrEmpty(widthStr) && string.IsNullOrEmpty(heightStr) && string.IsNullOrEmpty(cropSquare)) {
|
||||||
var widthStr = context.Request.Query["width"].FirstOrDefault();
|
|
||||||
var heightStr = context.Request.Query["height"].FirstOrDefault();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(widthStr) && string.IsNullOrEmpty(heightStr) && string.IsNullOrEmpty(cropSquare))
|
|
||||||
{
|
|
||||||
SignImageResponse(context, ref imageBytes);
|
|
||||||
return Results.File(imageBytes, contentType);
|
|
||||||
}
|
|
||||||
|
|
||||||
using var image = Image.Load(imageBytes);
|
|
||||||
|
|
||||||
var resizeWidth = 0;
|
|
||||||
var resizeHeight = 0;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(cropSquare) && cropSquare != "0" && cropSquare != "false")
|
|
||||||
{
|
|
||||||
var size = Math.Min(image.Width, image.Height);
|
|
||||||
var x = (image.Width - size) / 2;
|
|
||||||
var y = (image.Height - size) / 2;
|
|
||||||
image.Mutate(img => img.Crop(new Rectangle(x, y, size, size)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (int.TryParse(widthStr, out var w))
|
|
||||||
resizeWidth = w;
|
|
||||||
|
|
||||||
if (int.TryParse(heightStr, out var h))
|
|
||||||
resizeHeight = h;
|
|
||||||
|
|
||||||
if (resizeWidth > 0 || resizeHeight > 0)
|
|
||||||
{
|
|
||||||
image.Mutate(x => x.Resize(resizeWidth, resizeHeight));
|
|
||||||
}
|
|
||||||
|
|
||||||
using var output = new MemoryStream();
|
|
||||||
await image.SaveAsJpegAsync(output, new JpegEncoder { Quality = 85 });
|
|
||||||
imageBytes = output.ToArray();
|
|
||||||
SignImageResponse(context, ref imageBytes);
|
SignImageResponse(context, ref imageBytes);
|
||||||
return Results.File(imageBytes, "image/jpeg");
|
return Results.File(imageBytes, contentType);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
using Image image = Image.Load(imageBytes);
|
||||||
|
|
||||||
|
int resizeWidth = 0;
|
||||||
|
int resizeHeight = 0;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(cropSquare) && cropSquare != "0" && cropSquare != "false") {
|
||||||
|
int size = Math.Min(image.Width, image.Height);
|
||||||
|
int x = (image.Width - size) / 2;
|
||||||
|
int y = (image.Height - size) / 2;
|
||||||
|
image.Mutate(img => img.Crop(new Rectangle(x, y, size, size)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (int.TryParse(widthStr, out int w))
|
||||||
|
resizeWidth = w;
|
||||||
|
|
||||||
|
if (int.TryParse(heightStr, out int h))
|
||||||
|
resizeHeight = h;
|
||||||
|
|
||||||
|
if (resizeWidth > 0 || resizeHeight > 0) {
|
||||||
|
image.Mutate(x => x.Resize(resizeWidth, resizeHeight));
|
||||||
|
}
|
||||||
|
|
||||||
|
using MemoryStream output = new();
|
||||||
|
await image.SaveAsJpegAsync(output, new JpegEncoder { Quality = 85 });
|
||||||
|
imageBytes = output.ToArray();
|
||||||
|
SignImageResponse(context, ref imageBytes);
|
||||||
|
return Results.File(imageBytes, "image/jpeg");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SignImageResponse(HttpContext context, ref byte[] imageBytes)
|
private static void SignImageResponse(HttpContext context, ref byte[] imageBytes) {
|
||||||
{
|
|
||||||
if (context.Request.Query["sig"] != "p1") return;
|
if (context.Request.Query["sig"] != "p1") return;
|
||||||
|
|
||||||
var signature = Signatures.Sign(imageBytes);
|
string? signature = Signatures.Sign(imageBytes);
|
||||||
if (signature != null)
|
if (signature != null) {
|
||||||
{
|
|
||||||
context.Response.Headers["Content-Signature"] = $"key-id=KEY:RSA:p1.rec.net; data={signature}";
|
context.Response.Headers["Content-Signature"] = $"key-id=KEY:RSA:p1.rec.net; data={signature}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,14 @@
|
|||||||
using CannedNet.Services.Infrastructure;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace CannedNet.Services.Controllers;
|
namespace CannedNet.Services.Controllers;
|
||||||
|
|
||||||
public class NSController
|
//TODO: proper NameServer configs
|
||||||
|
[ApiController, Route("")]
|
||||||
|
public class NSController : ControllerBase
|
||||||
{
|
{
|
||||||
public WebApplicationBuilder Initialize(string[]? args = null) => ServiceExtensions.CreateRecNetBuilder(args);
|
[HttpGet]
|
||||||
|
public async Task<IResult> Get() {
|
||||||
public void MapEndpoints(WebApplication app)
|
string json = await System.IO.File.ReadAllTextAsync("JSON/endpoints.json");
|
||||||
{
|
return Results.Content(json, "application/json");
|
||||||
// Rec Room automatically calls this and sets the endpoints that correspond to services in the JSON file. These will be moved to the main server config once I get there.
|
|
||||||
app.MapGet("/", () =>
|
|
||||||
{
|
|
||||||
var json = File.ReadAllText("JSON/endpoints.json");
|
|
||||||
return Results.Content(json, "application/json");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CannedNet.Hubs;
|
/*using CannedNet.Hubs;
|
||||||
using CannedNet.Services.Infrastructure;
|
using CannedNet.Services.Infrastructure;
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
|
||||||
@@ -16,3 +16,4 @@ public class NotifyController
|
|||||||
NotificationService.SetHubContext(hubContext);
|
NotificationService.SetHubContext(hubContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
using System.Net.Mime;
|
|
||||||
using CannedNet.Services.Controllers;
|
using CannedNet.Services.Controllers;
|
||||||
|
|
||||||
namespace CannedNet.Services.Infrastructure;
|
namespace CannedNet.Services.Infrastructure;
|
||||||
@@ -16,15 +15,15 @@ public static class Services
|
|||||||
{
|
{
|
||||||
public static readonly List<ServiceRegistry> All =
|
public static readonly List<ServiceRegistry> All =
|
||||||
[
|
[
|
||||||
new() { Name = "NS", Port = 5001, ServiceType = typeof(NSController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new NSController().MapEndpoints(app) },
|
//new() { Name = "NS", Port = 5001, ServiceType = typeof(NSController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new NSController().MapEndpoints(app) },
|
||||||
new() { Name = "API", Port = 5000, ServiceType = typeof(APIController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new APIController().MapEndpoints(app) },
|
new() { Name = "API", Port = 5000, ServiceType = typeof(APIController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new APIController().MapEndpoints(app) },
|
||||||
new() { Name = "Auth", Port = 5002, ServiceType = typeof(AuthController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, jwt) => new AuthController().MapEndpoints(app) },
|
//new() { Name = "Auth", Port = 5002, ServiceType = typeof(AuthController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, jwt) => new AuthController().MapEndpoints(app) },
|
||||||
new() { Name = "Chat", Port = 5003, ServiceType = typeof(ChatController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new ChatController().MapEndpoints(app) },
|
//new() { Name = "Chat", Port = 5003, ServiceType = typeof(ChatController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new ChatController().MapEndpoints(app) },
|
||||||
new() { Name = "Match", Port = 5004, ServiceType = typeof(MatchmakingController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new MatchmakingController().MapEndpoints(app) },
|
new() { Name = "Match", Port = 5004, ServiceType = typeof(MatchmakingController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new MatchmakingController().MapEndpoints(app) },
|
||||||
new() { Name = "Accounts", Port = 5005, ServiceType = typeof(AccountsController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, jwt) => new AccountsController().MapEndpoints(app, jwt) },
|
//new() { Name = "Accounts", Port = 5005, ServiceType = typeof(AccountsController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, jwt) => new AccountsController().MapEndpoints(app, jwt) },
|
||||||
new() { Name = "Notify", Port = 5006, ServiceType = typeof(NotifyController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new NotifyController().MapEndpoints(app) },
|
//new() { Name = "Notify", Port = 5006, ServiceType = typeof(NotifyController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new NotifyController().MapEndpoints(app) },
|
||||||
new() { Name = "CDN", Port = 5007, ServiceType = typeof(CDNController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new CDNController().MapEndpoints(app) },
|
new() { Name = "CDN", Port = 5007, ServiceType = typeof(CDNController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new CDNController().MapEndpoints(app) },
|
||||||
new() { Name = "Image", Port = 5008, ServiceType = typeof(ImageController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new ImageController().MapEndpoints(app) },
|
//new() { Name = "Image", Port = 5008, ServiceType = typeof(ImageController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new ImageController().MapEndpoints(app) },
|
||||||
new() { Name = "Clubs", Port = 5009, ServiceType = typeof(ClubsController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new ClubsController().MapEndpoints(app) },
|
new() { Name = "Clubs", Port = 5009, ServiceType = typeof(ClubsController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new ClubsController().MapEndpoints(app) },
|
||||||
new() { Name = "Commerce", Port = 5010, ServiceType = typeof(CommerceController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new CommerceController().MapEndpoints(app) },
|
new() { Name = "Commerce", Port = 5010, ServiceType = typeof(CommerceController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new CommerceController().MapEndpoints(app) },
|
||||||
new() { Name = "Econ", Port = 5011, ServiceType = typeof(EconController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new EconController().MapEndpoints(app) },
|
new() { Name = "Econ", Port = 5011, ServiceType = typeof(EconController), ConfigureBuilder = b => b.ConfigureRecNetServices(), MapEndpoints = (app, _) => new EconController().MapEndpoints(app) },
|
||||||
|
|||||||
Reference in New Issue
Block a user