feat random bullshit GO!

This commit is contained in:
elar1s
2025-09-29 21:46:30 +03:00
parent 02934b1fd9
commit 63c89c48d5
71 changed files with 1976 additions and 1196 deletions

View File

@@ -0,0 +1,83 @@
using System.Security.Claims;
using LctMonolith.Domain.Entities;
using LctMonolith.Services;
using LctMonolith.Services.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
namespace LctMonolith.Controllers;
/// <summary>
/// Authentication endpoints (mocked local identity + JWT issuing).
/// </summary>
[ApiController]
[Route("api/auth")]
public class AuthController : ControllerBase
{
private readonly UserManager<AppUser> _userManager;
private readonly SignInManager<AppUser> _signInManager;
private readonly ITokenService _tokenService;
public AuthController(UserManager<AppUser> userManager, SignInManager<AppUser> signInManager, ITokenService tokenService)
{
_userManager = userManager;
_signInManager = signInManager;
_tokenService = tokenService;
}
/// <summary>Registers a new user (simplified).</summary>
[HttpPost("register")]
[AllowAnonymous]
public async Task<ActionResult<TokenPair>> Register(AuthRequest req, CancellationToken ct)
{
var existing = await _userManager.FindByEmailAsync(req.Email);
if (existing != null) return Conflict("Email already registered");
var user = new AppUser { UserName = req.Email, Email = req.Email, FirstName = req.FirstName, LastName = req.LastName };
var result = await _userManager.CreateAsync(user, req.Password);
if (!result.Succeeded) return BadRequest(result.Errors);
var tokens = await _tokenService.IssueAsync(user, ct);
return Ok(tokens);
}
/// <summary>Login with email + password.</summary>
[HttpPost("login")]
[AllowAnonymous]
public async Task<ActionResult<TokenPair>> Login(AuthRequest req, CancellationToken ct)
{
var user = await _userManager.FindByEmailAsync(req.Email);
if (user == null) return Unauthorized();
var passOk = await _signInManager.CheckPasswordSignInAsync(user, req.Password, lockoutOnFailure: false);
if (!passOk.Succeeded) return Unauthorized();
var tokens = await _tokenService.IssueAsync(user, ct);
return Ok(tokens);
}
/// <summary>Refresh access token by refresh token.</summary>
[HttpPost("refresh")]
[AllowAnonymous]
public async Task<ActionResult<TokenPair>> Refresh(RefreshRequest req, CancellationToken ct)
{
var pair = await _tokenService.RefreshAsync(req.RefreshToken, ct);
return Ok(pair);
}
/// <summary>Revoke refresh token (logout).</summary>
[HttpPost("revoke")]
[Authorize]
public async Task<IActionResult> Revoke(RevokeRequest req, CancellationToken ct)
{
await _tokenService.RevokeAsync(req.RefreshToken, ct);
return NoContent();
}
/// <summary>Returns current user id (debug).</summary>
[HttpGet("me")]
[Authorize]
public ActionResult<object> Me()
{
var id = User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.FindFirstValue(ClaimTypes.Name);
return Ok(new { userId = id });
}
}

View File

@@ -0,0 +1,33 @@
using System.Security.Claims;
using LctMonolith.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace LctMonolith.Controllers;
/// <summary>
/// Endpoints exposing gamification progress information.
/// </summary>
[ApiController]
[Route("api/gamification")]
[Authorize]
public class GamificationController : ControllerBase
{
private readonly IGamificationService _gamificationService;
public GamificationController(IGamificationService gamificationService)
{
_gamificationService = gamificationService;
}
private Guid GetUserId() => Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!);
/// <summary>Returns current user progress snapshot (rank, xp, outstanding requirements).</summary>
[HttpGet("progress")]
public async Task<IActionResult> GetProgress(CancellationToken ct)
{
var snapshot = await _gamificationService.GetProgressAsync(GetUserId(), ct);
return Ok(snapshot);
}
}

View File

@@ -0,0 +1,53 @@
using System.Security.Claims;
using LctMonolith.Domain.Entities;
using LctMonolith.Services;
using LctMonolith.Services.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace LctMonolith.Controllers;
/// <summary>
/// Endpoints for listing and managing missions.
/// </summary>
[ApiController]
[Route("api/missions")]
[Authorize]
public class MissionsController : ControllerBase
{
private readonly IMissionService _missionService;
public MissionsController(IMissionService missionService)
{
_missionService = missionService;
}
private Guid GetUserId() => Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!);
/// <summary>Returns missions currently available to the authenticated user.</summary>
[HttpGet]
public async Task<ActionResult<IEnumerable<Mission>>> GetAvailable(CancellationToken ct)
{
var userId = GetUserId();
var list = await _missionService.GetAvailableMissionsAsync(userId, ct);
return Ok(list);
}
/// <summary>Create a mission (HR functionality for now any authenticated user).</summary>
[HttpPost]
public async Task<ActionResult<Mission>> Create(CreateMissionModel model, CancellationToken ct)
{
var mission = await _missionService.CreateMissionAsync(model, ct);
return CreatedAtAction(nameof(GetAvailable), new { id = mission.Id }, mission);
}
/// <summary>Update mission status for current user (submit/complete/etc.).</summary>
[HttpPatch("{missionId:guid}/status")]
public async Task<ActionResult> UpdateStatus(Guid missionId, UpdateMissionStatusRequest req, CancellationToken ct)
{
var userId = GetUserId();
var result = await _missionService.UpdateStatusAsync(userId, missionId, req.Status, req.SubmissionData, ct);
return Ok(new { result.MissionId, result.Status, result.UpdatedAt });
}
}

View File

@@ -0,0 +1,57 @@
using System.Security.Claims;
using LctMonolith.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace LctMonolith.Controllers;
/// <summary>
/// In-app user notifications API.
/// </summary>
[ApiController]
[Route("api/notifications")]
[Authorize]
public class NotificationsController : ControllerBase
{
private readonly INotificationService _notifications;
public NotificationsController(INotificationService notifications)
{
_notifications = notifications;
}
private Guid GetUserId() => Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!);
/// <summary>Get up to 100 unread notifications.</summary>
[HttpGet("unread")]
public async Task<IActionResult> GetUnread(CancellationToken ct)
{
var list = await _notifications.GetUnreadAsync(GetUserId(), ct);
return Ok(list);
}
/// <summary>Get recent notifications (paged by take).</summary>
[HttpGet]
public async Task<IActionResult> GetAll([FromQuery] int take = 100, CancellationToken ct = default)
{
var list = await _notifications.GetAllAsync(GetUserId(), take, ct);
return Ok(list);
}
/// <summary>Mark a notification as read.</summary>
[HttpPost("mark/{id:guid}")]
public async Task<IActionResult> MarkRead(Guid id, CancellationToken ct)
{
await _notifications.MarkReadAsync(GetUserId(), id, ct);
return NoContent();
}
/// <summary>Mark all notifications as read.</summary>
[HttpPost("mark-all")]
public async Task<IActionResult> MarkAll(CancellationToken ct)
{
var cnt = await _notifications.MarkAllReadAsync(GetUserId(), ct);
return Ok(new { updated = cnt });
}
}

View File

@@ -0,0 +1,42 @@
using System.Security.Claims;
using LctMonolith.Services;
using LctMonolith.Services.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace LctMonolith.Controllers;
/// <summary>
/// Store endpoints for listing items and purchasing.
/// </summary>
[ApiController]
[Route("api/store")]
[Authorize]
public class StoreController : ControllerBase
{
private readonly IStoreService _storeService;
public StoreController(IStoreService storeService)
{
_storeService = storeService;
}
private Guid GetUserId() => Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!);
/// <summary>List active store items.</summary>
[HttpGet("items")]
public async Task<IActionResult> GetItems(CancellationToken ct)
{
var items = await _storeService.GetActiveItemsAsync(ct);
return Ok(items);
}
/// <summary>Purchase an item for the authenticated user.</summary>
[HttpPost("purchase")]
public async Task<IActionResult> Purchase(PurchaseRequest req, CancellationToken ct)
{
var inv = await _storeService.PurchaseAsync(GetUserId(), req.ItemId, req.Quantity, ct);
return Ok(new { inv.StoreItemId, inv.Quantity, inv.AcquiredAt });
}
}