Files
rr3-server/RR3CommunityServer/Controllers/AuthController.cs
Daniel Elliott a6bab92282 Add user authentication and account management system
Features:
- User registration with username, email, password
- Login with JWT token authentication
- Password hashing with BCrypt
- Account settings & management
- Device linking to accounts
- Change password & password reset
- Account-User relationship (1-to-1 with game data)

Database entities:
- Account: User accounts with credentials
- DeviceAccount: Link devices to accounts (many-to-many)

API endpoints:
- POST /api/auth/register
- POST /api/auth/login
- POST /api/auth/change-password
- POST /api/auth/forgot-password
- POST /api/auth/reset-password
- GET /api/auth/me
- POST /api/auth/link-device
- DELETE /api/auth/unlink-device/{deviceId}

Starting resources for new accounts:
- 100,000 Gold
- 500,000 Cash
- Level 1

Ready for VPS deployment with HTTPS.
2026-02-19 15:00:16 -08:00

129 lines
4.2 KiB
C#

using Microsoft.AspNetCore.Mvc;
using RR3CommunityServer.Models;
using RR3CommunityServer.Services;
namespace RR3CommunityServer.Controllers;
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
private readonly IAuthService _authService;
private readonly ILogger<AuthController> _logger;
public AuthController(IAuthService authService, ILogger<AuthController> logger)
{
_authService = authService;
_logger = logger;
}
[HttpPost("register")]
public async Task<ActionResult> Register([FromBody] RegisterRequest request)
{
var (success, token, error) = await _authService.RegisterAsync(request);
if (!success)
return BadRequest(new { message = error });
return Ok(new { message = "Account created successfully", token });
}
[HttpPost("login")]
public async Task<ActionResult> Login([FromBody] LoginRequest request)
{
var (success, response, error) = await _authService.LoginAsync(request);
if (!success)
return Unauthorized(new { message = error });
return Ok(response);
}
[HttpPost("change-password")]
public async Task<ActionResult> ChangePassword([FromBody] ChangePasswordRequest request)
{
var token = Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
var account = await _authService.ValidateTokenAsync(token);
if (account == null)
return Unauthorized(new { message = "Invalid or expired token" });
var (success, error) = await _authService.ChangePasswordAsync(account.Id, request);
if (!success)
return BadRequest(new { message = error });
return Ok(new { message = "Password changed successfully" });
}
[HttpPost("forgot-password")]
public async Task<ActionResult> ForgotPassword([FromBody] ForgotPasswordRequest request)
{
var (success, error) = await _authService.ForgotPasswordAsync(request);
if (!success)
return BadRequest(new { message = error });
return Ok(new { message = "Password reset instructions sent to your email" });
}
[HttpPost("reset-password")]
public async Task<ActionResult> ResetPassword([FromBody] ResetPasswordRequest request)
{
var (success, error) = await _authService.ResetPasswordAsync(request);
if (!success)
return BadRequest(new { message = error });
return Ok(new { message = "Password reset successfully" });
}
[HttpGet("me")]
public async Task<ActionResult> GetCurrentUser()
{
var token = Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
var account = await _authService.ValidateTokenAsync(token);
if (account == null)
return Unauthorized(new { message = "Invalid or expired token" });
var settings = await _authService.GetAccountSettingsAsync(account.Id);
return Ok(settings);
}
[HttpPost("link-device")]
public async Task<ActionResult> LinkDevice([FromBody] LinkDeviceRequest request)
{
var token = Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
var account = await _authService.ValidateTokenAsync(token);
if (account == null)
return Unauthorized(new { message = "Invalid or expired token" });
var (success, error) = await _authService.LinkDeviceAsync(account.Id, request);
if (!success)
return BadRequest(new { message = error });
return Ok(new { message = "Device linked successfully" });
}
[HttpDelete("unlink-device/{deviceId}")]
public async Task<ActionResult> UnlinkDevice(string deviceId)
{
var token = Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
var account = await _authService.ValidateTokenAsync(token);
if (account == null)
return Unauthorized(new { message = "Invalid or expired token" });
var (success, error) = await _authService.UnlinkDeviceAsync(account.Id, deviceId);
if (!success)
return BadRequest(new { message = error });
return Ok(new { message = "Device unlinked successfully" });
}
}