Improved ArticleEditor submit permission validation

This commit is contained in:
Mia Rose Winter 2024-01-18 22:19:50 +01:00
parent 5e5dee0c0c
commit ce0ffbe711
Signed by: miawinter
GPG key ID: 4B6F6A83178F595E

View file

@ -3,12 +3,10 @@
@using Wave.Data
@using Microsoft.EntityFrameworkCore
@using System.ComponentModel.DataAnnotations
@using Markdig
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Identity
@using Wave.Utilities
@attribute [Authorize(Policy = "ArticleEditPermissions")]
@attribute [Authorize(Policy = "ArticleEditOrReviewPermissions")]
@inject IDbContextFactory<ApplicationDbContext> ContextFactory
@inject NavigationManager Navigation
@inject UserManager<ApplicationUser> UserManager
@ -106,6 +104,8 @@
var user = await UserManager.GetUserAsync(state.User);
User = user ?? throw new ApplicationException("???2");
IsAdmin = await UserManager.IsInRoleAsync(User, "Admin");
// TODO properly check if user can edit this article (see HandleRoles)
}
private async Task OnValidSubmit() {
@ -130,12 +130,8 @@
}
if (Model.PublishDate is not null) article.PublishDate = Model.PublishDate.Value;
if (User.Id != article.Author.Id && !IsAdmin)
throw new ApplicationException("You do not have permissions to edit this article");
if (User.Id != article.Author.Id) {
article.Reviewer = User; // If an admin edits this article, add them as reviewer
}
article.LastModified = DateTimeOffset.UtcNow;
HandleRoles(article, User);
article.BodyHtml = MarkdownUtilities.Parse(article.Body);
@ -147,6 +143,27 @@
}
}
private async Task HandleRoles(Article article, ApplicationUser me) {
// it's our draft
if (article.Status is ArticleStatus.Draft && article.Author.Id == me.Id) return;
var roles = await UserManager.GetRolesAsync(me);
// reviewers and admins can review articles
if (article.Status is ArticleStatus.InReview && roles.Any(r => r is "Admin" or "Reviewer")) {
article.Reviewer = me;
return;
}
// published articles may only be edited my admins or moderators
if (article.Status is ArticleStatus.Published && roles.Any(r => r is "Admin" or "Reviewer")) {
article.Reviewer = me; // TODO replace with editor or something?
return;
}
throw new ApplicationException("You do not have permissions to edit this article");
}
private sealed class InputModel {
public Guid? Id { get; set; }
[Required(AllowEmptyStrings = false), MaxLength(256)]