using Govor.Application.Interfaces.Friends; using Govor.Application.Interfaces.Infrastructure.Extensions; using Govor.Application.Interfaces.UserSession; using Govor.Application.Interfaces.UserSession.Crypto; using Govor.Contracts.Requests; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace Govor.API.Controllers.Authentication; [RequireHttps] [ApiController] [Route("api/session")] [Authorize(Roles = "Admin, User")] public class SessionKeysController : Controller { private readonly ILogger _logger; private readonly IFriendshipService _friendshipService; private readonly ICurrentUserSessionService _currentSession; private readonly ISessionKeyAttacher _sessionKeyAttacher; private readonly ISessionKeysReader _sessionKeysReader; private readonly IOneTimePreKeysRotator _oneTimePreKeysRotator; private readonly ICurrentUserService _currentUser; public SessionKeysController( ILogger logger, IFriendshipService friendshipService, ICurrentUserSessionService currentSession, ISessionKeyAttacher sessionKeyAttacher, ISessionKeysReader sessionKeysReader, ICurrentUserService currentUser) { _logger = logger; _friendshipService = friendshipService; _currentSession = currentSession; _sessionKeyAttacher = sessionKeyAttacher; _sessionKeysReader = sessionKeysReader; _currentUser = currentUser; } [HttpPost("keys")] public async Task UploadSessionKeys([FromBody] UploadKeysRequest request) { if (!ModelState.IsValid) return BadRequest(ModelState); if(request.OneTimePreKeys.Count > 100) return BadRequest("Too many one time pre keys"); var sessionId = _currentSession.GetUserSessionId(); await _sessionKeyAttacher.AttachKeysAsync(sessionId, request.IdentityKey, request.SignedPreKey, request.SignedPreKeySignature, request.OneTimePreKeys); return Ok(); } [HttpGet("users/{userId}/keys")] public async Task GetUserPublicKeys(Guid userId) { var requesterId = _currentUser.GetCurrentUserId(); if (!(await _friendshipService.GetFriendsAsync(userId)).Select(u => u.Id).Contains(requesterId)) return Forbid("You can only access keys of your friends"); var keys = await _sessionKeysReader.GetAllActiveKeysAsync(userId); return Ok(keys); } [HttpPost("keys/rotate")] public async Task RotateOneTimePreKeys([FromBody] RotateOneTimePreKeysRequest request) { if (!ModelState.IsValid) return BadRequest(ModelState); if (request.NewOneTimePreKeys.Count > 100) return BadRequest("Too many new one time pre keys"); var sessionId = _currentSession.GetUserSessionId(); await _oneTimePreKeysRotator.RotateOneTimePreKeysAsync(sessionId, request.NewOneTimePreKeys); return Ok("One-Time PreKeys rotated successfully."); } [HttpGet("keys/remaining")] public async Task GetRemainingOneTimePreKeysCount() { var sessionId = _currentSession.GetUserSessionId(); var count = await _sessionKeysReader.GetRemainingOneTimePreKeysCountAsync(sessionId); return Ok(new { remaining = count }); } [HttpPost("keys/{preKeyId}/used")] public async Task MarkOneTimePreKeyAsUsed([FromRoute] Guid preKeyId) { var sessionId = _currentSession.GetUserSessionId(); await _oneTimePreKeysRotator.MarkOneTimePreKeyAsUsedAsync(sessionId, preKeyId); return Ok("Marked as used."); } }