SpinaCMS / Spina

Spina CMS
http://www.spinacms.com
Other
2.19k stars 403 forks source link

Fine-grained control over who can edit/publish pages #1298

Closed Bramjetten closed 6 months ago

Bramjetten commented 1 year ago

Role-based authorization of page editing/publishing. Preferably like we do authentication so the implementation can be swapped.

Things we'd like to have:

Bramjetten commented 1 year ago

This is probably a pro feature, but will require some hooks in Spina's open source code base.

stale[bot] commented 10 months ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

sedubois commented 10 months ago

@Bramjetten this feature is important, I don't understand how one would expect to use Spina in a team without it. Isn't there any short term plan to add basic support?

Bramjetten commented 10 months ago

@sedubois We personally haven’t needed it in the teams where we deploy Spina, that’s why it’s not included yet. We like the idea though, that’s why it’s on our radar. The challenge is finding the right balance between flexibility and ease of use and finding the right abstraction level.

Open to suggestions and feedback!

sedubois commented 10 months ago

As an example, I need as a system administrator to have access to everything, but collaborators should have different access levels for different types of resources (not at all, read-only, modify only some attributes, or modify all attributes). For example a content writer could create new articles, but not publish them. Someone in charge of user support could view user data or create testimonials. Someone in charge of social media marketing could view but not modify testimonials. Etc. And they should have restricted or no access to other resources. It is important to have fine-grained access for security reasons, and to limit the risk that non-experts break or delete some content by mistake. In my experience having fine-grained authorization is needed even in a small company, precisely because there are few resources available and so there are part-time collaborators who are external to the company and who should therefore be granted limited administrative access.

The only tool I have experience with is Administrate, this is what I want to migrate away from and I also want to avoid for new projects, because it has accumulated too much legacy. Administrate however does integrate with Pundit which is what we use. It seems that the main authorization gems to consider are Pundit, ActionPolicy, CanCanCan, Consul. By having a thin abstraction layer, it should hopefully be possible to support any of them.

Essentially, similar to Administrate, in controllers Spina could call a method authorize with the concerned user, resource, and action, which will delegate to the application's authorization logic (such as pundit). If it returns true then the action can proceed. And in views, the same principle can be applied to decide which info and buttons should be shown.

See in Administrate: https://github.com/thoughtbot/administrate/blob/21c52889445d56d409fe30d1081b651252390baa/app/controllers/administrate/application_controller.rb#L248-L260

    # Whether the current user is authorized to perform the named action on the
    # resource.
    #
    # @param _resource [ActiveRecord::Base, Class, String, Symbol] The
    #   temptative target of the action, or the name of its class.
    # @param _action_name [String, Symbol] The name of an action that might be
    #   possible to perform on a resource or resource class.
    # @return [Boolean] `true` if the current user is authorized to perform the
    #   action on the resource. `false` otherwise.
    def authorized_action?(_resource, _action_name)
      true
    end
    helper_method :authorized_action?

We override this in our own ApplicationController to call Pundit as follows:

module Admin
  class ApplicationController < Administrate::ApplicationController
    include Admin::Punditize
    # ...
  end
end

module Admin
  module Punditize
    include Pundit::Authorization
    # ...
    def authorized_action?(resource, action_name)
      policy(resource).send("#{action_name}?".to_sym)
    end

    def pundit_user
      current_administrator
    end
  end
end

There is also some logic to configure the policy scope.

In a nutshell, I would aim to add the simplest abstract authorization API possible, which returns true all the time, and then let this be customized in the application as needed.

stale[bot] commented 8 months ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

sedubois commented 8 months ago

Isn't there any plan to work on this? This is really blocking us from using Spina.

Bramjetten commented 8 months ago

Yes, we do plan on building this for Spina. Cannot give you a timeline though, so if you really want to have it now you'll have to extend Spina's functionality using overrides.

stale[bot] commented 6 months ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.