Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/Api/Controllers/DashboardController.cs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
using Application.Common.Models;
using Application.Identity;
using Infrastructure.Identity.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Api.Controllers;

public class DashboardController : ApiControllerBase
{
[RequiresRole(IdentityData.Roles.Admin)]
[HttpGet("online-users")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<ActionResult<int>> GetOnlineUsers()
{
return Ok(Result<int>.Succeed(RequiresRoleAttribute.OnlineUsers.Count));
}
}
15 changes: 14 additions & 1 deletion src/Api/Services/BackgroundWorkers.cs
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
using Application.Common.Interfaces;
using Domain.Statuses;
using Infrastructure.Identity.Authorization;
using Microsoft.EntityFrameworkCore;
using NodaTime;

Expand All@@ -22,7 +23,8 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
DisposeExpiredEntries(TimeSpan.FromSeconds(10), stoppingToken),
DisposeExpiredPermissions(TimeSpan.FromSeconds(10), stoppingToken),
HandleOverdueRequest(TimeSpan.FromMinutes(2),stoppingToken),
HandleOverdueRequest(TimeSpan.FromMinutes(2), stoppingToken),
HandleOnlineUsers(TimeSpan.FromSeconds(10), stoppingToken),
};

await Task.WhenAll(workers.ToArray());
Expand DownExpand Up@@ -74,4 +76,15 @@ private async Task HandleOverdueRequest(TimeSpan delay, CancellationToken stoppi
await context.SaveChangesAsync(stoppingToken);
await Task.Delay(delay, stoppingToken);
}

private async Task HandleOnlineUsers(TimeSpan delay, CancellationToken stoppingToken)
{
var onlineUsers = RequiresRoleAttribute.OnlineUsers;
foreach (var id in onlineUsers.Keys
.Where(id => DateTime.Now - onlineUsers[id] < delay))
{
RequiresRoleAttribute.OnlineUsers.Remove(id);
}
await Task.Delay(delay, stoppingToken);
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -64,7 +64,7 @@ public async Task<DocumentDto> Handle(Command request, CancellationToken cancell
_context.Files.Remove(document.File);
}

if (document.Status is DocumentStatus.Issued or DocumentStatus.Lost )
if (document.Status is DocumentStatus.Lost )
{
throw new ConflictException("This document cannot be uploaded to.");
}
Expand Down
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
using System.Collections.Immutable;
using System.IdentityModel.Tokens.Jwt;
using Application.Identity;
using Infrastructure.Persistence;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
Expand All@@ -11,6 +11,7 @@ namespace Infrastructure.Identity.Authorization;
public class RequiresRoleAttribute : Attribute, IAuthorizationFilter
{
private readonly string[] _claimValues;
public static Dictionary<Guid, DateTime> OnlineUsers { get; } = new();

public RequiresRoleAttribute(params string[] claimValues)
{
Expand All@@ -25,12 +26,16 @@ public void OnAuthorization(AuthorizationFilterContext context)

var user = dbContext.Users.FirstOrDefault(x => x.Email!.Equals(email));

foreach (var claimValue in _claimValues)
if (user is null)
{
if (user!.Role.Equals(claimValue))
{
return;
}
context.Result = new ForbidResult();
return;
}

if (_claimValues.Any(claimValue => user!.Role.Equals(claimValue)))
{
OnlineUsers[user.Id] = DateTime.Now;
return;
}

context.Result = new ForbidResult();
Expand Down