基于角色限制用户可以执行的操作

本文关键字:用户 执行 操作 于角色 角色 | 更新日期: 2023-09-27 18:01:12

场景

我正在建立一个系统,每个项目都由两个不同的人进行审查。每当第一个审阅者保存项目审阅时,就轮到第二个审阅者完成他们的个人审阅。如果我提交了第一次审阅,然后再次打开该项目,则该项目将处于只读状态,因为您无法审阅自己的作品。此外,如果需要更多信息,第一个审阅者可以将项目置于挂起状态,而第二个审阅者则不能。每当每个用户从列表中选择一个项目时,他们都会得到一个特定的审阅者名单。

到目前为止我所拥有的

每次将一个项目加载到编辑器中时,该人员都会获得两个角色中的一个,即InitialReviewerSecondReviewer

public class Reviewer
{
    public void AddReview(string review) { }
}
public class InitialReviewer : Reviewer, ICanPutIntoPendingState
{
    public void PutIntoPendingState(string pendingState) { }
}
public class SecondReviewer : Reviewer
{
    // Just use base class to add review
}
public class ReviewerService
{
    private readonly Reviewer _reviewer;
    public void AddReview(string review)
    {
        _reviewer.AddReview(review);
    }
    public void PutIntoPendingState(string pendingState)
    {
        _reviewer.PutIntoPendingState(pendingState);
    }
}

我编辑的精简版。

public class Editor
{
    private readonly ReviewerService _reviewerService;
    public Editor(ReviewerService reviewerService)
    {
        _reviewerService = reviewerService;
    }
    public void SaveCommand()
    {
        if(user chose a pending state && _reviewerService.Reviewer is ICanPutIntoPendingState) // Pending state is a dropdown.
            _reviewerService.PutIntoPendingState("pending state");
        else // the user made a complete review
            _reviewerService.AddReview("user review");
    }
}

问题

我遇到的问题是,我似乎无法摆脱Save()中不属于Editor类的逻辑。

问题

如何从Editor类中去除Save()函数内部的逻辑?这似乎违反了SRP原则。我认为,检查当前审阅者对象是否属于ICanPutIntoPendingState类型是个大问题。

请注意,我已经放弃了所有的逻辑,因为有相当多的逻辑

基于角色限制用户可以执行的操作

给ReviewerService一个Save((方法是不够的,该方法内部调用抽象类Reviewer的一个Save((方法,该抽象类的具体实现是在InitialReviewer和SecondReviewer中实现的。因此,您可以将决策逻辑推送到具有具体实现的类中。希望这能有所帮助。

也许您应该考虑将业务逻辑从Reviewer类转移到ReviewerService。简单的实现是这样的:

    public abstract class Reviewer
{
    public abstract bool CanPutIntoPendingState { get; }
}
public class InitialReviewer : Reviewer
{
    public override bool CanPutIntoPendingState 
    {
        get
        {
            return true;
        }
    }
}
public class SecondReviewer : Reviewer
{
    public override bool CanPutIntoPendingState 
    {
        get
        {
            return false;
        }
    }
}
public class ReviewerService
{
    private readonly Reviewer _reviewer;
    public void AddReview(string review)
    {
        // do add review logic here
    }

    public void PutIntoPendingState(string pendingState) 
    { 
        if (_reviewer.CanPutIntoPendingState ) 
        {
            // do PutIntoPendingState logic here
        }
    }
}
public class Editor
{
    private readonly ReviewerService _reviewerService;
    public Editor(ReviewerService reviewerService)
    {
        _reviewerService = reviewerService;
    }
    public void SaveCommand()
    {
        if(user chose a pending state) // Pending state is a dropdown.
            _reviewerService.PutIntoPendingState("pending state");
        else // the user made a complete review
            _reviewerService.AddReview("user review");
    }
}

您还可以考虑在review服务上只公开一个函数,该函数接受输入模型。然后,服务负责验证输入并采取适当的操作。类似这样的东西:

public class ReviewerService
{
    private readonly Reviewer _reviewer;
    public void StoreReview(ReviewModel model)
    {
        // validate input here
        // do business logic here
        if (model.IsPendingState && _reviewer.CanPutIntoPendingState)
        {
            this.PutIntoPendingState("pending state");
        }
        else
        {
            this.AddReview(model.Review);
        }
    }
    private void AddReview(string review)
    {
        // do add review logic here
    }
    private void PutIntoPendingState(string pendingState)
    {
       // do PutIntoPendingState logic here
    }
}
public class ReviewModel
{
    public string Review { get; set; }
    public bool IsPendingState { get; set; }
}
public class Editor
{
    private readonly ReviewerService _reviewerService;
    public Editor(ReviewerService reviewerService)
    {
        _reviewerService = reviewerService;
    }
    public void SaveCommand()
    {
        ReviewModel model = new ReviewModel() {Review="user review",IsPendingState=user chose a pending state };
        _reviewerService.StoreReview(model);
    }
}