Bug fix - notifications audience

* Performers had their notifications publicaly published.
* refacto admin group name
This commit is contained in:
Paul Schneider 2026-10-23 13:32:42 +01:00
commit d476c08046
Signed by: notazof
GPG key ID: AD4B9B545FBD7D12
36 changed files with 421 additions and 74 deletions

View file

@ -90,7 +90,7 @@ public sealed class ApiWebServerFixture : WebHostFixture
options.AddPolicy("AdministratorOnly", policy =>
{
policy.RequireAuthenticatedUser();
policy.RequireClaim(Yavsc.Constants.RoleClaimType, Yavsc.Constants.AdminGroupName);
policy.RequireClaim(Yavsc.Constants.RoleClaimType, Yavsc.Constants.AdminName);
});
});

View file

@ -6,8 +6,10 @@ using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Yavsc.Abstract.Models.Messaging;
using Yavsc.Api.Test.Fixtures;
using Yavsc.Controllers;
using Yavsc.Models;
using Yavsc.Models.Workflow;
namespace Yavsc.Api.Test;
@ -57,6 +59,106 @@ public sealed class HomeControllerTests : IClassFixture<ApiWebServerFixture>
Assert.DoesNotContain(model, a => a.Code == "ghost");
}
[Fact]
public async Task Index_does_not_show_performer_notification_to_anonymous_visitors()
{
_fixture.ResetAndSeedActivityGraph();
using var scope = _fixture.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<Yavsc.Models.ApplicationDbContext>();
db.Notification.AddRange(
Note("Rendez-vous professionnel", "user/alice"),
Note("Annonce publique", "pub/all"));
await db.SaveChangesAsync();
var controller = CreateHomeController(db, new ClaimsPrincipal(new ClaimsIdentity()));
controller.ControllerContext.HttpContext.Session = new TestSession();
await controller.Index(id: null);
object notifyValue = controller.ViewBag.Notify;
var notifications = Assert.IsAssignableFrom<IEnumerable<Notification>>(notifyValue);
Assert.Equal("Annonce publique", Assert.Single(notifications).title);
}
[Fact]
public async Task Index_shows_performer_notification_only_to_its_target_user()
{
_fixture.ResetAndSeedActivityGraph();
using var scope = _fixture.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<Yavsc.Models.ApplicationDbContext>();
db.Notification.AddRange(
Note("Rendez-vous professionnel", "user/alice"),
Note("Autre rendez-vous", "user/bob"),
Note("Annonce publique", "pub/all"));
await db.SaveChangesAsync();
var controller = CreateHomeController(db, UserPrincipal("bob"));
await controller.Index(id: null);
object notifyValue = controller.ViewBag.Notify;
var notifications = Assert.IsAssignableFrom<IEnumerable<Notification>>(notifyValue);
Assert.Equal(new[] { "Autre rendez-vous", "Annonce publique" },
notifications.Select(notification => notification.title));
var performerController = CreateHomeController(db, UserPrincipal("alice"));
await performerController.Index(id: null);
object performerNotifyValue = performerController.ViewBag.Notify;
var performerNotifications = Assert.IsAssignableFrom<IEnumerable<Notification>>(performerNotifyValue);
Assert.Equal(new[] { "Rendez-vous professionnel", "Annonce publique" },
performerNotifications.Select(notification => notification.title));
}
private static HomeController CreateHomeController(
Yavsc.Models.ApplicationDbContext db,
ClaimsPrincipal user)
{
var controller = new HomeController(
NullLogger<HomeController>.Instance,
localizer: null!,
context: db,
settingsOptions: Options.Create(new SiteSettings()),
env: new TestEnvironment());
controller.ControllerContext = new ControllerContext
{
HttpContext = new DefaultHttpContext { User = user }
};
return controller;
}
private static ClaimsPrincipal UserPrincipal(string userId)
=> new(new ClaimsIdentity(new[]
{
new Claim("sub", userId),
new Claim(ClaimTypes.NameIdentifier, userId)
}, "Bearer"));
private static Notification Note(string title, string target)
=> new()
{
title = title,
body = "Corps",
click_action = "Fermer",
Target = target
};
private sealed class TestSession : ISession
{
private readonly Dictionary<string, byte[]> _values = new();
public bool IsAvailable => true;
public string Id => "home-controller-test-session";
public IEnumerable<string> Keys => _values.Keys;
public void Clear() => _values.Clear();
public Task CommitAsync(CancellationToken cancellationToken = default) => Task.CompletedTask;
public Task LoadAsync(CancellationToken cancellationToken = default) => Task.CompletedTask;
public void Remove(string key) => _values.Remove(key);
public void Set(string key, byte[] value) => _values[key] = value;
public bool TryGetValue(string key, out byte[] value) => _values.TryGetValue(key, out value!);
}
private sealed class TestEnvironment : IWebHostEnvironment
{
public string ApplicationName { get; set; } = "Yavsc.Api.Test";

View file

@ -414,7 +414,7 @@ public sealed class InvoiceApiTests(ApiWebServerFixture fixture) : IClassFixture
using var admin = Client();
admin.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",
TestTokenIssuer.Issue("alice", "api", extraClaims:
[new System.Security.Claims.Claim(Constants.RoleClaimType, Constants.AdminGroupName)]));
[new System.Security.Claims.Claim(Constants.RoleClaimType, Constants.AdminName)]));
var response = await admin.GetAsync("/openapi/invoicing.json", Ct);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var json = await response.Content.ReadAsStringAsync(Ct);

View file

@ -89,7 +89,7 @@ public sealed class PodcastControllerTests(ApiWebServerFixture fixture) : IClass
using var admin = Client("podcast-admin");
admin.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",
TestTokenIssuer.Issue("podcast-admin", "api",
extraClaims: new[] { new Claim(Constants.RoleClaimType, Constants.AdminGroupName) }));
extraClaims: new[] { new Claim(Constants.RoleClaimType, Constants.AdminName) }));
using var response = await admin.GetAsync("/openapi/podcasts.json", _ct);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
using var document = JsonDocument.Parse(await response.Content.ReadAsStringAsync(_ct));

View file

@ -143,7 +143,7 @@ public sealed class ResourceUsageApiControllerTests : IClassFixture<ApiWebServer
title = "Admin",
body = "Restricted to administrators",
click_action = "/admin",
Target = "administration",
Target = Constants.Administration,
});
await db.SaveChangesAsync();
@ -172,7 +172,7 @@ public sealed class ResourceUsageApiControllerTests : IClassFixture<ApiWebServer
"api",
new[]
{
new Claim(Yavsc.Constants.RoleClaimType, Yavsc.Constants.AdminGroupName)
new Claim(Yavsc.Constants.RoleClaimType, Yavsc.Constants.AdminName)
});
var response = await adminHttp.GetAsync("/api/v1/resource-usage/admin", TestContext.Current.CancellationToken);