Files
2026-07-23 18:21:43 -07:00

244 lines
8.7 KiB
C#

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();
}
}