Add remaining project files

This commit is contained in:
Marco Baldwin
2026-07-23 18:21:43 -07:00
parent c12d8ac35d
commit 6e15e89a9d
453 changed files with 64265 additions and 0 deletions
@@ -0,0 +1,48 @@
using DeluxeBackend.Models;
using DeluxeBackend.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace DeluxeBackend.Controllers.Accounts
{
[Route("Accounts/accountprivacysettings")]
[ApiController]
public class AccountPrivacySettingsController(ILiteDbService db, IJwtService jwt) : ControllerBase
{
[HttpGet("{accId}")]
public async Task<IActionResult> AccountPrivacySettings(long accId)
{
Account? account = db.Accounts.FindById(accId);
if (account == null)
{
return NotFound();
}
return Ok(new
{
accountId = accId,
isRecentHistoryVisible = account.IsRecentHistoryVisible
});
}
[HttpGet("recenthistoryvisibility")]
[Authorize(Roles = "gameClient")]
public async Task<IActionResult> RecentHistoryVisibility([FromForm] bool isRecentHistoryVisible)
{
LoginWithInfoResult? login = await jwt.GetLoginWithInfo(User);
if (login == null) return Unauthorized();
Account account = login.Account;
account.IsRecentHistoryVisible = isRecentHistoryVisible;
db.Accounts.Update(account);
return Ok(new
{
Success = true
});
}
}
}
+43
View File
@@ -0,0 +1,43 @@
using DeluxeBackend.Models;
using DeluxeBackend.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace DeluxeBackend.Controllers.Accounts
{
[Route("Accounts/account")]
[ApiController]
public class BruhController : ControllerBase
{
private readonly IJwtService jwt;
private readonly ILiteDbService db;
public BruhController(IJwtService _jwt, ILiteDbService _db)
{
jwt = _jwt;
db = _db;
}
[HttpGet("{accId}/bio")]
[Authorize(Roles = "gameClient")]
public async Task<IActionResult> Btio(long accId)
{
Account? account = db.Accounts.FindById(accId);
if (account == null)
{
return NotFound();
}
return Ok(new
{
accountId = accId,
bio = account.Bio
});
}
}
}
+54
View File
@@ -0,0 +1,54 @@
using DeluxeBackend.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using DeluxeBackend.Models;
namespace DeluxeBackend.Controllers.Accounts
{
[Route("Accounts/account/bulk")]
[ApiController]
public class BulkController : ControllerBase
{
private readonly ILiteDbService db;
private readonly bool setup = false;
public BulkController(ILiteDbService _db, IJwtService _jwtService)
{
db = _db;
if (!setup)
{
if (db.Accounts.FindById(1) == null)
{
Account account = new()
{
Username = "Coach",
DisplayName = "Coach",
Birthday = DateOnly.MinValue,
ImageName= "DefaultProfileImage"
};
db.Accounts.Insert(account);
}
}
}
[HttpGet]
public async Task<IActionResult> Bulk([FromQuery(Name ="id")] List<long> accountIds)
{
var accounts = db.Accounts.Find(x => accountIds.Contains(x.Id));
var accountDictionaries = accounts.Select(a => a.ToDictionary()).ToList();
return Ok(accountDictionaries);
}
[HttpGet("all_db")]
public async Task<IActionResult> all()
{
var accounts = db.Accounts.FindAll();
return Ok(accounts.ToList());
}
}
}
+244
View File
@@ -0,0 +1,244 @@
using DeluxeBackend.Models;
using DeluxeBackend.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;
using System.IO;
using static DeluxeBackend.Enums;
namespace DeluxeBackend.Controllers.Accounts
{
[Route("Accounts/account/me")]
[ApiController]
public partial class MeController : ControllerBase
{
private readonly ILiteDbService db;
private readonly IJwtService jwt;
private readonly IPasswordService passwordService;
private readonly INotificationService ws;
public MeController(ILiteDbService _db, IJwtService _jwtService, IPasswordService _passwordService, INotificationService _ws)
{
db = _db;
jwt = _jwtService;
passwordService = _passwordService;
ws = _ws;
}
[HttpGet]
[Authorize]
public async Task<IActionResult> Me()
{
Account? account = await jwt.GetLogin(User);
if (account == null) return Unauthorized();
return Ok(account.ToDictionaryMe());
}
[HttpPut("birthday")]
[Authorize]
public async Task<IActionResult> Birthday([FromForm] string birthday)
{
Account? account = await jwt.GetLogin(User);
if (account == null) return Unauthorized();
if (account.Birthday.HasValue)
{
return Conflict(new { Success = false, Error = "Account birthday has already been set." });
}
if (DateTime.TryParse(birthday, out DateTime parsedDateTime))
{
if (parsedDateTime > DateTime.UtcNow || parsedDateTime < DateTime.UtcNow.AddYears(-125))
{
return BadRequest(new { Success = false, Error = "Please provide a valid birth date." });
}
account.Birthday = DateOnly.FromDateTime(parsedDateTime);
db.Accounts.Update(account);
return Ok(new { Success = true });
}
return BadRequest(new { Success = false, Error = "Invalid date format received." });
}
[HttpPut("username")]
[Authorize]
public async Task<IActionResult> Username([FromForm] string username)
{
Account? account = await jwt.GetLogin(User);
if (account == null) return Unauthorized();
if (string.IsNullOrWhiteSpace(username))
{
return BadRequest(new { Success = false, Error = "Username cannot be empty." });
}
username = username.Trim();
if (username.Length < 3 || username.Length > 20)
{
return BadRequest(new { Success = false, Error = "Username must be between 3 and 20 characters." });
}
if (!UsernameRegex().IsMatch(username))
{
return BadRequest(new { Success = false, Error = "Username can only contain letters, numbers, and underscores." });
}
string[] reservedNames = { "admin", "administrator", "moderator", "system", "support", "staff", "deluxe" };
if (reservedNames.Contains(username.ToLowerInvariant()))
{
return BadRequest(new { Success = false, Error = "This username is reserved." });
}
bool isTaken = db.Accounts.Exists(a => a.Username.Equals(username, StringComparison.OrdinalIgnoreCase));
if (isTaken)
{
return Conflict(new { Success = false, Error = $"The username '{username}' is already taken." });
}
account.Username = username;
account.DisplayName = username;
db.Accounts.Update(account);
await ws.SendToPlayer(account.Id, "SelfAccountUpdate", account.ToDictionaryMe());
await ws.SendToPlayerSubs(account.Id, "AccountUpdate", account.ToDictionary());
return Ok(new { Success = true });
}
[HttpPost("/Auth/account/me/changepassword")]
[Authorize]
public async Task<IActionResult> Changepassword([FromForm] string newPassword, [FromForm] string oldPassword = "")
{
Account? account = await jwt.GetLogin(User);
if (account == null) return Unauthorized();
if (string.IsNullOrWhiteSpace(newPassword) || newPassword.Length < 6)
{
return BadRequest(new { Success = false, Error = "New password must be at least 6 characters long." });
}
if (!string.IsNullOrEmpty(account.PasswordHash))
{
if (string.IsNullOrEmpty(oldPassword))
{
return BadRequest(new { Success = false, Error = "Old password is required." });
}
var verificationResult = passwordService.VerifyPassword(account, oldPassword);
if (verificationResult == Microsoft.AspNetCore.Identity.PasswordVerificationResult.Failed)
{
return BadRequest(new { Success = false, Error = "Old password is incorrect." });
}
}
passwordService.setPassword(account, newPassword);
db.Accounts.Update(account);
return Ok(new { Success = true });
}
[HttpPost("/Auth/account/me/haspassword")]
[Authorize]
public async Task<IActionResult> HasPassword([FromForm] string newPassword, [FromForm] string oldPassword = "")
{
Account? account = await jwt.GetLogin(User);
if (account == null) return Unauthorized();
return Ok(!string.IsNullOrEmpty(account.PasswordHash));
}
[HttpGet("/Accounts/parentalcontrol/me")]
[Authorize]
public async Task<IActionResult> ParentalControl()
{
Account? account = await jwt.GetLogin(User);
if (account == null) return Unauthorized();
return Ok(new
{
accountId = account.Id,
disallowInAppPurchases = false
});
}
[HttpPut("personalpronouns")]
[Authorize]
public async Task<IActionResult> PersonalPronouns([FromForm] PronounsType pronounFlags)
{
Account? account = await jwt.GetLogin(User);
if (account == null) return Unauthorized();
account.Pronouns = pronounFlags;
db.Accounts.Update(account);
await ws.SendToPlayerSubs(account.Id, "AccountUpdate", account.ToDictionary());
return Ok(new { Success = true });
}
[HttpPut("identityflags")]
[Authorize]
public async Task<IActionResult> IdentityFlags([FromForm] IdentityFlagsType identityFlags)
{
Account? account = await jwt.GetLogin(User);
if (account == null) return Unauthorized();
account.IdentityFlags = identityFlags;
db.Accounts.Update(account);
await ws.SendToPlayerSubs(account.Id, "AccountUpdate", account.ToDictionary());
return Ok(new { Success = true });
}
[HttpPut("bio")]
[Authorize]
public async Task<IActionResult> Bio([FromForm] string bio)
{
Account? account = await jwt.GetLogin(User);
if (account == null) return Unauthorized();
if (bio != null && bio.Length > 250)
{
return BadRequest(new { Success = false, Error = "Bio cannot exceed 250 characters." });
}
account.Bio = bio ?? string.Empty;
db.Accounts.Update(account);
await ws.SendToPlayerSubs(account.Id, "AccountUpdate", account.ToDictionary());
return Ok(new { Success = true });
}
[HttpPut("profileimage")]
[Authorize]
public async Task<IActionResult> ProfileImage([FromForm(Name = "imageName"), Required] string ImageName)
{
Account? account = await jwt.GetLogin(User);
if (account == null) return Unauthorized();
string sanitizedPath = Path.GetFileName(ImageName);
if (string.IsNullOrWhiteSpace(sanitizedPath) || sanitizedPath != ImageName)
{
return BadRequest(new { Success = false, Error = "Invalid image file name format." });
}
account.ImageName = ImageName;
db.Accounts.Update(account);
await ws.SendToPlayerSubs(account.Id, "AccountUpdate", account.ToDictionary());
return Ok(new { Success = true });
}
[GeneratedRegex("^[a-zA-Z0-9_]+$")]
private static partial Regex UsernameRegex();
}
}