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

@ -103,7 +103,7 @@ public partial class SessionStatusViewModel : ViewModelBase
if (profile is null)
throw new InvalidOperationException("Le serveur a renvoyé un profil vide.");
if (version == _accessVersion)
IsAdministrator = profile.Roles.Contains(Yavsc.Constants.AdminGroupName, StringComparer.Ordinal);
IsAdministrator = profile.Roles.Contains(Yavsc.Constants.AdminName, StringComparer.Ordinal);
}
catch (Exception ex)
{

View file

@ -14,6 +14,7 @@ namespace Yavsc
public const string CirclePath = "circle";
public const string CommentsPath = "blogcomments";
public const string ChatHubPath = "chathub";
public const string Administration = "administration";
public static readonly Scope[] SiteScopes = {
new Scope { Id = "profile", Description = "Your profile informations" },
@ -52,7 +53,7 @@ namespace Yavsc
public const string DefaultFactor = "Default";
public const string MobileAppFactor = "Mobile Application";
public const string SMSFactor = "SMS";
public const string AdminGroupName = "Administrator";
public const string AdminName = "Administrator";
public const string PerformerGroupName = "Performer";
public const string StarGroupName = "Star";
public const string StarHunterGroupName = "StarHunter";

View file

@ -24,7 +24,7 @@ public sealed class NotificationsApiController : Controller
public async Task<ActionResult<List<Notification>>> GetCurrentUserNotifications()
{
var currentUserId = User.GetUserId();
var isAdmin = User.IsInRole(Constants.AdminGroupName);
var isAdmin = User.IsInRole(Constants.AdminName);
var dismissedIds = string.IsNullOrWhiteSpace(currentUserId)
? new HashSet<long>()

View file

@ -78,7 +78,7 @@ public sealed class ResourceUsageApiController : Controller
[HttpGet(Constants.ResourceUsageAdminRoute)]
public async Task<ActionResult<List<ResourceUsageSummary>>> GetAdminOverview()
{
if (!User.IsInRole(Constants.AdminGroupName))
if (!User.IsInRole(Constants.AdminName))
{
return Forbid();
}

View file

@ -7,7 +7,7 @@ using Yavsc.Api.Services;
namespace Yavsc.ApiControllers.Administration;
[ApiController]
[ApiExplorerSettings(GroupName = "administration")]
[ApiExplorerSettings(GroupName = Constants.Administration)]
[Authorize("AdministratorOnly")]
[Route(Constants.APIPrefix + "/administration")]
[Produces("application/json")]

View file

@ -107,7 +107,7 @@ namespace Yavsc.ApiControllers
logger.LogWarning("Got bill ack:"+bill.GetIsAcquitted().ToString());
if (bill is not NominativeServiceCommand { InvoiceEstimateId: not null } invoice)
return Conflict(new { Error = "Create the invoice from a signed estimate first." });
if (User.GetUserId() != invoice.InvoicePerformerId && !User.IsInRole(Constants.AdminGroupName))
if (User.GetUserId() != invoice.InvoicePerformerId && !User.IsInRole(Constants.AdminName))
return Forbid();
return ViewComponent("Bill",new object[] { billingCode, bill, OutputFormat.Pdf, true } );
}

View file

@ -24,12 +24,12 @@ namespace Yavsc.Controllers
}
bool UserIsAdminOrThis(string uid)
{
if (User.IsInRole(Constants.AdminGroupName)) return true;
if (User.IsInRole(Constants.AdminName)) return true;
return uid == User.GetUserId();
}
bool UserIsAdminOrInThese(string oid, string uid)
{
if (User.IsInRole(Constants.AdminGroupName)) return true;
if (User.IsInRole(Constants.AdminName)) return true;
var cuid = User.GetUserId();
return cuid == uid || cuid == oid;
}
@ -79,7 +79,7 @@ namespace Yavsc.Controllers
return BadRequest();
}
var uid = User.GetUserId();
if (!User.IsInRole(Constants.AdminGroupName))
if (!User.IsInRole(Constants.AdminName))
{
if (uid != estimate.OwnerId)
{
@ -115,7 +115,7 @@ namespace Yavsc.Controllers
var uid = User.GetUserId();
if (estimate.OwnerId == null) estimate.OwnerId = uid;
if (!User.IsInRole(Constants.AdminGroupName))
if (!User.IsInRole(Constants.AdminName))
{
if (uid != estimate.OwnerId)
{
@ -185,7 +185,7 @@ namespace Yavsc.Controllers
return NotFound();
}
var uid = User.GetUserId();
if (!User.IsInRole(Constants.AdminGroupName))
if (!User.IsInRole(Constants.AdminName))
{
if (uid != estimate.OwnerId)
{
@ -285,7 +285,7 @@ namespace Yavsc.Controllers
if (estimate == null) return NotFound();
var uid = User.GetUserId();
if (!User.IsInRole(Constants.AdminGroupName) && uid != estimate.OwnerId)
if (!User.IsInRole(Constants.AdminName) && uid != estimate.OwnerId)
return new StatusCodeResult(StatusCodes.Status403Forbidden);
if (body == null || body.FileId <= 0)
@ -319,7 +319,7 @@ namespace Yavsc.Controllers
if (estimate == null) return NotFound();
var uid = User.GetUserId();
if (!User.IsInRole(Constants.AdminGroupName) && uid != estimate.OwnerId)
if (!User.IsInRole(Constants.AdminName) && uid != estimate.OwnerId)
return new StatusCodeResult(StatusCodes.Status403Forbidden);
var link = _context.EstimateAttachedFiles

View file

@ -63,7 +63,7 @@ namespace Yavsc.Controllers
}
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (estimateTemplate.OwnerId!=uid)
if (!User.IsInRole(Constants.AdminGroupName))
if (!User.IsInRole(Constants.AdminName))
return new StatusCodeResult(StatusCodes.Status403Forbidden);
_context.Entry(estimateTemplate).State = EntityState.Modified;
@ -133,7 +133,7 @@ namespace Yavsc.Controllers
}
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (estimateTemplate.OwnerId!=uid)
if (!User.IsInRole(Constants.AdminGroupName))
if (!User.IsInRole(Constants.AdminName))
return new StatusCodeResult(StatusCodes.Status403Forbidden);
_context.EstimateTemplates.Remove(estimateTemplate);

View file

@ -86,7 +86,7 @@ namespace Yavsc.ApiControllers
if (estimate is null) return NotFound(new { Error = "no estimate linked to this query" });
var uid = User.GetUserId();
if (!User.IsInRole(Constants.AdminGroupName)
if (!User.IsInRole(Constants.AdminName)
&& uid != estimate.ClientId && uid != estimate.OwnerId)
return Forbid();
@ -117,7 +117,7 @@ namespace Yavsc.ApiControllers
if (estimate is null) return NotFound(new { Error = "no estimate linked to this query" });
var uid = User.GetUserId();
if (!User.IsInRole(Constants.AdminGroupName)
if (!User.IsInRole(Constants.AdminName)
&& uid != estimate.ClientId && uid != estimate.OwnerId)
return Forbid();
@ -403,7 +403,7 @@ namespace Yavsc.ApiControllers
if (isProvider) return (query, ActorRole.Provider, null);
if (isClient) return (query, ActorRole.Client, null);
if (User.IsInRole(Constants.AdminGroupName))
if (User.IsInRole(Constants.AdminName))
return (query, ActorRole.Admin, null);
return (null, ActorRole.None, Forbid());
@ -453,7 +453,7 @@ namespace Yavsc.ApiControllers
if (error is not null) return error;
if (query is null) return BadRequest(new { Error = "query not found" });
if (role != ActorRole.Client && !User.IsInRole(Constants.AdminGroupName))
if (role != ActorRole.Client && !User.IsInRole(Constants.AdminName))
return new StatusCodeResult(StatusCodes.Status403Forbidden);
if (body == null || body.FileId <= 0)
@ -463,7 +463,7 @@ namespace Yavsc.ApiControllers
var file = await dbContext.UploadedFiles
.FirstOrDefaultAsync(f => f.Id == body.FileId, token);
if (file == null) return BadRequest(new { error = "file not found" });
if (file.OwnerId != uid && !User.IsInRole(Constants.AdminGroupName))
if (file.OwnerId != uid && !User.IsInRole(Constants.AdminName))
return new StatusCodeResult(StatusCodes.Status403Forbidden);
var existing = await dbContext.QueryAttachedFiles
@ -490,7 +490,7 @@ namespace Yavsc.ApiControllers
if (error is not null) return error;
if (query is null) return BadRequest(new { Error = "query not found" });
if (role != ActorRole.Client && !User.IsInRole(Constants.AdminGroupName))
if (role != ActorRole.Client && !User.IsInRole(Constants.AdminName))
return new StatusCodeResult(StatusCodes.Status403Forbidden);
var link = await dbContext.QueryAttachedFiles

View file

@ -70,7 +70,7 @@ public class HairCutQueryApiController : Controller
return NotFound();
}
if (query.ClientId != uid && query.PerformerId != uid && !User.IsInRole(Constants.AdminGroupName))
if (query.ClientId != uid && query.PerformerId != uid && !User.IsInRole(Constants.AdminName))
{
return Forbid();
}
@ -141,7 +141,7 @@ public class HairCutQueryApiController : Controller
}
var uid = User.GetUserId();
if (existing.ClientId != uid && !User.IsInRole(Constants.AdminGroupName))
if (existing.ClientId != uid && !User.IsInRole(Constants.AdminName))
{
return Forbid();
}
@ -185,7 +185,7 @@ public class HairCutQueryApiController : Controller
return NotFound();
}
if (query.ClientId != uid && !User.IsInRole(Constants.AdminGroupName))
if (query.ClientId != uid && !User.IsInRole(Constants.AdminName))
{
return Forbid();
}
@ -234,4 +234,4 @@ public class HairCutQueryApiController : Controller
Details = prestation.GetDisplayDetails(),
};
}
}
}

View file

@ -77,7 +77,7 @@ public class HairMultiCutQueryApiController : Controller
return NotFound();
}
if (query.ClientId != uid && query.PerformerId != uid && !User.IsInRole(Constants.AdminGroupName))
if (query.ClientId != uid && query.PerformerId != uid && !User.IsInRole(Constants.AdminName))
{
return Forbid();
}
@ -152,7 +152,7 @@ public class HairMultiCutQueryApiController : Controller
}
var uid = User.GetUserId();
if (existing.ClientId != uid && !User.IsInRole(Constants.AdminGroupName))
if (existing.ClientId != uid && !User.IsInRole(Constants.AdminName))
{
return Forbid();
}
@ -200,7 +200,7 @@ public class HairMultiCutQueryApiController : Controller
return NotFound();
}
if (query.ClientId != uid && !User.IsInRole(Constants.AdminGroupName))
if (query.ClientId != uid && !User.IsInRole(Constants.AdminName))
{
return Forbid();
}
@ -285,4 +285,4 @@ public class HairMultiCutQueryApiController : Controller
return query;
}
}
}

View file

@ -39,7 +39,7 @@ public sealed class InvoicesController(IInvoicingService invoices, ILogger<Invoi
public Task<ActionResult<InvoiceResponse>> VerifyPayPal(long commandId, VerifyInvoicePayPalRequest request, CancellationToken ct)
=> ExecuteAsync(() => invoices.VerifyPayPalAsync(commandId, request.TransactionId, User.GetUserId(), IsAdmin, ct));
private bool IsAdmin => User.IsInRole(Constants.AdminGroupName);
private bool IsAdmin => User.IsInRole(Constants.AdminName);
private async Task<ActionResult<InvoiceResponse>> ExecuteAsync(Func<Task<InvoiceResponse>> action, bool created = false)
{

View file

@ -62,7 +62,7 @@ public class RdvQueryApiController : Controller
return NotFound();
}
if (query.ClientId != uid && query.PerformerId != uid && !User.IsInRole(Constants.AdminGroupName))
if (query.ClientId != uid && query.PerformerId != uid && !User.IsInRole(Constants.AdminName))
{
return Forbid();
}
@ -157,7 +157,7 @@ public class RdvQueryApiController : Controller
return NotFound();
}
if (existing.ClientId != uid && !User.IsInRole(Constants.AdminGroupName))
if (existing.ClientId != uid && !User.IsInRole(Constants.AdminName))
{
return Forbid();
}
@ -222,7 +222,7 @@ public class RdvQueryApiController : Controller
return NotFound();
}
if (query.ClientId != uid && !User.IsInRole(Constants.AdminGroupName))
if (query.ClientId != uid && !User.IsInRole(Constants.AdminName))
{
return Forbid();
}

View file

@ -35,7 +35,7 @@ namespace Yavsc.Controllers
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (blogpost.AuthorId!=uid)
if (!User.IsInRole(Constants.AdminGroupName))
if (!User.IsInRole(Constants.AdminName))
return BadRequest();
_context.SaveChanges(User.GetUserId());

View file

@ -49,7 +49,7 @@ namespace Yavsc.Controllers
{
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (uid != blackListed.OwnerId)
if (!User.IsInRole(Constants.AdminGroupName))
if (!User.IsInRole(Constants.AdminName))
if (!User.IsInRole(Constants.FrontOfficeGroupName))
return false;
return true;

View file

@ -46,7 +46,7 @@ namespace Yavsc.Controllers
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (uid != chatRoomAccess.UserId && uid != chatRoomAccess.Room.OwnerId
&& ! User.IsInMsRole(Constants.AdminGroupName))
&& ! User.IsInMsRole(Constants.AdminName))
{
ModelState.AddModelError("UserId","get refused");
@ -72,7 +72,7 @@ namespace Yavsc.Controllers
}
var room = _context.ChatRoom.First(channel => channel.Name == chatRoomAccess.ChannelName );
if (uid != room.OwnerId && ! User.IsInMsRole(Constants.AdminGroupName))
if (uid != room.OwnerId && ! User.IsInMsRole(Constants.AdminName))
{
ModelState.AddModelError("ChannelName", "access put refused");
return BadRequest(ModelState);
@ -110,7 +110,7 @@ namespace Yavsc.Controllers
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
var room = _context.ChatRoom.First(channel => channel.Name == chatRoomAccess.ChannelName );
if (room == null || (uid != room.OwnerId && ! User.IsInMsRole(Constants.AdminGroupName)))
if (room == null || (uid != room.OwnerId && ! User.IsInMsRole(Constants.AdminName)))
{
ModelState.AddModelError("ChannelName", "access post refused");
return BadRequest(ModelState);
@ -154,7 +154,7 @@ namespace Yavsc.Controllers
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
var room = _context.ChatRoom.First(channel => channel.Name == chatRoomAccess.ChannelName );
if (room == null || (uid != room.OwnerId && chatRoomAccess.UserId != uid && ! User.IsInMsRole(Constants.AdminGroupName)))
if (room == null || (uid != room.OwnerId && chatRoomAccess.UserId != uid && ! User.IsInMsRole(Constants.AdminName)))
{
ModelState.AddModelError("UserId", "access drop refused");
return BadRequest(ModelState);

View file

@ -136,7 +136,7 @@ namespace Yavsc.Controllers
if (User.GetUserId() != chatRoom.OwnerId )
{
if (!User.IsInMsRole(Constants.AdminGroupName))
if (!User.IsInMsRole(Constants.AdminName))
return BadRequest(new {error = "OwnerId"});
}

View file

@ -63,7 +63,7 @@ internal class Program
{
policy
.RequireAuthenticatedUser()
.RequireClaim(Constants.RoleClaimType, Constants.AdminGroupName);
.RequireClaim(Constants.RoleClaimType, Constants.AdminName);
});
})
.AddYavscCors(builder.Configuration)

View file

@ -32,7 +32,7 @@ public sealed partial class AdministrationService(
public async Task<AdministrationSummary> GetSummaryAsync(CancellationToken ct)
=> new(await db.Users.CountAsync(ct),
(await users.GetUsersInRoleAsync(Constants.AdminGroupName)).Count,
(await users.GetUsersInRoleAsync(Constants.AdminName)).Count,
typeof(AdministrationService).Assembly.GetName().ToString(), System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription);
public async Task<IReadOnlyList<AdministrationRole>> GetRolesAsync(CancellationToken ct)
@ -46,7 +46,7 @@ public sealed partial class AdministrationService(
public async Task EnsureRolesAsync(CancellationToken ct)
{
foreach (var name in new[] { Constants.AdminGroupName, Constants.StarGroupName, Constants.PerformerGroupName,
foreach (var name in new[] { Constants.AdminName, Constants.StarGroupName, Constants.PerformerGroupName,
Constants.FrontOfficeGroupName, Constants.StarHunterGroupName, Constants.BlogModeratorGroupName })
{
ct.ThrowIfCancellationRequested();
@ -73,7 +73,7 @@ public sealed partial class AdministrationService(
CheckIdentity(await users.AddToRoleAsync(user, role.Name!));
else if (!member && alreadyMember)
{
if (role.Name == Constants.AdminGroupName &&
if (role.Name == Constants.AdminName &&
(await users.GetUsersInRoleAsync(role.Name)).Count <= 1)
throw Conflict("Impossible de retirer le dernier administrateur.");
CheckIdentity(await users.RemoveFromRoleAsync(user, role.Name!));

View file

@ -9,8 +9,8 @@ public static class AdministrationServiceCollectionExtensions
services.AddHttpContextAccessor();
services.AddScoped<IAdministrationService, AdministrationService>();
services.AddScoped<AdministrationExceptionFilter>();
services.AddOpenApi("administration", options =>
options.ShouldInclude = description => description.GroupName == "administration");
services.AddOpenApi(Constants.Administration, options =>
options.ShouldInclude = description => description.GroupName == Constants.Administration);
return services;
}
}

View file

@ -216,7 +216,7 @@ namespace Yavsc.Blogs.Controllers
// autorisés comme pour le reste du workflow.
bool CanReadFile(UploadedFile file, string uid)
{
if (User.IsInRole(Constants.AdminGroupName)) return true;
if (User.IsInRole(Constants.AdminName)) return true;
if (file.OwnerId == uid) return true;
if (dbContext.EstimateAttachedFiles.Any(a =>

View file

@ -56,7 +56,7 @@ namespace Yavsc.Controllers
{
// ensure all roles existence
foreach (string roleName in new string[] {
Constants.AdminGroupName,
Constants.AdminName,
Constants.StarGroupName,
Constants.PerformerGroupName,
Constants.FrontOfficeGroupName,
@ -86,13 +86,12 @@ namespace Yavsc.Controllers
public async Task<IActionResult> Take()
{
// If some amdin already exists, make this method disapear
var admins = await _userManager.GetUsersInRoleAsync(Constants.AdminGroupName);
var admins = await _userManager.GetUsersInRoleAsync(Constants.AdminName);
if (admins != null && admins.Count > 0)
{
// All is ok, nothing to do here.
if (User.IsInMsRole(Constants.AdminGroupName))
if (User.IsInMsRole(Constants.AdminName))
{
return Ok(new { message = "you already got it." });
}
return NotFound();
@ -116,7 +115,7 @@ namespace Yavsc.Controllers
return new BadRequestObjectResult(ModelState);
}
var addToRoleResult = await _userManager.AddToRoleAsync(user, Constants.AdminGroupName);
var addToRoleResult = await _userManager.AddToRoleAsync(user, Constants.AdminName);
if (!addToRoleResult.Succeeded)
{
AddErrors(addToRoleResult);
@ -130,11 +129,11 @@ namespace Yavsc.Controllers
public async Task<IActionResult> Index()
{
var adminCount = await _userManager.GetUsersInRoleAsync(
Constants.AdminGroupName);
Constants.AdminName);
var userCount = await _dbContext.Users.CountAsync();
var youAreAdmin = await _userManager.IsInRoleAsync(
await _userManager.FindByIdAsync(User.GetUserId()),
Constants.AdminGroupName);
Constants.AdminName);
var roles = await _roleManager.Roles.Select(x => new RoleInfo
{

View file

@ -57,7 +57,7 @@ namespace Yavsc.Controllers
}
private async Task SetupView(Announce announce)
{
ViewBag.IsAdmin = User.IsInMsRole(Constants.AdminGroupName);
ViewBag.IsAdmin = User.IsInMsRole(Constants.AdminName);
ViewBag.IsPerformer = User.IsInMsRole(Constants.PerformerGroupName);
ViewBag.AllowEdit = announce==null || announce.Id<=0 || !_authorizationService.AuthorizeAsync(User,announce,new EditPermission()).IsFaulted;
List<SelectListItem> dl = new List<SelectListItem>();
@ -80,7 +80,7 @@ namespace Yavsc.Controllers
if (ModelState.IsValid)
{
// Only allow admin to create corporate annonces
if (announce.For == Reason.Corporate && ! User.IsInMsRole(Constants.AdminGroupName))
if (announce.For == Reason.Corporate && ! User.IsInMsRole(Constants.AdminName))
{
ModelState.AddModelError("For", _localizer["YourNotAdmin"]);
return View(announce);

View file

@ -50,9 +50,14 @@ namespace Yavsc.Controllers
if (clicked == null) clicked = new long[0];
}
else clicked = _dbContext.DismissClicked.Where(d => d.UserId == uid).Select(d => d.NotificationId).ToArray();
var isAdmin = User.IsInRole(Constants.AdminName);
var notes = _dbContext.Notification.Where(
n => !clicked.Contains(n.Id)
);
).Where(n =>
string.IsNullOrWhiteSpace(n.Target)
|| (n.Target != null && n.Target.StartsWith("pub/"))
|| (!string.IsNullOrWhiteSpace(uid) && n.Target == $"user/{uid}")
|| (isAdmin && n.Target == Constants.Administration));
if (notes.Any()) this.Notify(notes);
var toShow = _dbContext.Activities

View file

@ -63,7 +63,7 @@ namespace Yavsc.Controllers
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (ModelState.IsValid)
{
if (model.UserId != uid) if (!User.IsInMsRole(Constants.AdminGroupName))
if (model.UserId != uid) if (!User.IsInMsRole(Constants.AdminName))
return new ChallengeResult();
_context.Instrumentation.Add(model);
@ -81,7 +81,7 @@ namespace Yavsc.Controllers
{
return NotFound();
}
if (id != uid) if (!User.IsInMsRole(Constants.AdminGroupName))
if (id != uid) if (!User.IsInMsRole(Constants.AdminName))
return new ChallengeResult();
Instrumentation musicianSettings = await _context.Instrumentation.SingleAsync(m => m.UserId == id);
if (musicianSettings == null)
@ -97,7 +97,7 @@ namespace Yavsc.Controllers
public async Task<IActionResult> Edit(Instrumentation musicianSettings)
{
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (musicianSettings.UserId != uid) if (!User.IsInMsRole(Constants.AdminGroupName))
if (musicianSettings.UserId != uid) if (!User.IsInMsRole(Constants.AdminName))
return new ChallengeResult();
if (ModelState.IsValid)
{
@ -123,7 +123,7 @@ namespace Yavsc.Controllers
return NotFound();
}
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (musicianSettings.UserId != uid) if (!User.IsInMsRole(Constants.AdminGroupName))
if (musicianSettings.UserId != uid) if (!User.IsInMsRole(Constants.AdminName))
return new ChallengeResult();
return View(musicianSettings);
}
@ -136,7 +136,7 @@ namespace Yavsc.Controllers
Instrumentation musicianSettings = await _context.Instrumentation.SingleAsync(m => m.UserId == id);
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (musicianSettings.UserId != uid) if (!User.IsInMsRole(Constants.AdminGroupName))
if (musicianSettings.UserId != uid) if (!User.IsInMsRole(Constants.AdminName))
return new ChallengeResult();

View file

@ -263,14 +263,14 @@ public static class HostingExtensions
policy
.RequireAuthenticatedUser()
.RequireClaim(Constants.RoleClaimType,
new string[] { Constants.PerformerGroupName, Constants.AdminGroupName })
new string[] { Constants.PerformerGroupName, Constants.AdminName })
;
});
options.AddPolicy("AdministratorOnly", policy =>
{
_ = policy
.RequireAuthenticatedUser()
.RequireClaim(Constants.RoleClaimType, Constants.AdminGroupName);
.RequireClaim(Constants.RoleClaimType, Constants.AdminName);
});
options.AddPolicy("FrontOffice", policy => policy.RequireRole(Constants.FrontOfficeGroupName));

View file

@ -16,7 +16,7 @@
<li><a class="dropdown-item @PageHelpers.ActivePage(ViewContext, "Feature")" asp-controller="Feature" asp-action="Index">Features</a></li>
</ul>
</li>
@if (User.IsInMsRole(Constants.AdminGroupName)) {
@if (User.IsInMsRole(Constants.AdminName)) {
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle @PageHelpers.ActivePageAny(ViewContext, administrationControllers)" href="#" id="dropdown05" data-bs-toggle="dropdown" aria-expanded="false">
Administration

View file

@ -80,7 +80,7 @@ namespace Yavsc.Server.Hubs
var userId = _dbContext.Users.First(u => u.UserName == userName).Id;
await Clients.Group(ChatHubConstants.HubGroupFollowingPrefix + userId).SendAsync("notifyUser", NotificationTypes.Connected, userName, null);
isCop = Context.User.IsInMsRole(Constants.AdminGroupName);
isCop = Context.User.IsInMsRole(Constants.AdminName);
if (isCop)
{
await Groups.AddToGroupAsync(Context.ConnectionId, ChatHubConstants.HubGroupCops);
@ -232,7 +232,7 @@ namespace Yavsc.Server.Hubs
throw new NotImplementedException();
}
[Authorize(Constants.AdminGroupName)]
[Authorize(Constants.AdminName)]
public void GLine(string userName, string reason)
{
if (!InputValidator.ValidateUserName(userName)) return;
@ -330,7 +330,7 @@ namespace Yavsc.Server.Hubs
var identityUserName = Context.User.GetUserName();
if (userName[0] != '?' && Context.User != null)
if (!Context.User.IsInMsRole(Constants.AdminGroupName))
if (!Context.User.IsInMsRole(Constants.AdminName))
{
var bl = _dbContext.BlackListed

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);