cerebris / jsonapi-resources

A resource-focused Rails library for developing JSON:API compliant servers.

Home Page:http://jsonapi-resources.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Authorization

Samsinite opened this issue · comments

Hey guys,

This gem/library looks great! What about directly supporting an option to easily hook up authorization instead of requiring the resource controller index/show/create/update/destroy methods to be overridden?

Something like a simple interface that filters for index/read_list, returns true/false for show/create/update/destroy, and if in the future updating lists or destroying lists are supported, the interface could be updated to support filtering those as well. Than it would be straight forward for whoever to override it to support their preferred method of authorization, such as pundit or cancancan. I wouldn't mind implementing this if you guys are interested.

I have been thinking about different ways to handle authorization. I stripped out my first attempt (a set of callbacks of the resource) since I wasn't sure it was quite right.

One concern I have about overriding the controller to handle authorization is that once we get patch support implemented it will be possible to have a single request create multiple operations. Authorization will need to be checked for each of these operations. I don't know how well Pundit or cancancan can be adapted to this criteria.

One method I have been playing with (in my project using this gem) has been to create a custom OperationsProcessor, derived from the ActiveRecordOperationsProcessor. In before_operation I call a custom method on each resource which I have named approve_operation. This allows each resource to have it's own authorization scheme. I'm not totally happy with this approach since the approve_operation method isn't as clean as I think it should be (due to needing to pull the details out of the Operation object).

I would certainly appreciate any work you wish to put into this problem. I just want to make sure any solution we adopt will support multiple operations, is flexible to support different authorization packages, and is resource centric (if possible).

lgebhardt,

I'll put together an example showing the gist of what I was thinking, and see what you think.

I'm thinking an interface that can be specified in the controller -- similar to how context is specified -- so nothing on the controller has to be overridden. I don't see this getting in the way for a patch single request that handles multiple operations, as whatever handles the type of patch operation that occurs can know the appropriate type of authorization that it needs to do. I currently think authorization should occur in the controller and not in the resource -- thus why I think a callback on a resource is a bad idea.

@Samsinite, thanks, I look forward to seeing your proposal.

From the http://jsonapi.org/format/#patch-urls

PATCH operations MAY be allowed at the root URL of an API. In this case, every "path" within a PATCH operation MUST include the full resource URL. This allows for general "fire hose" updates to any resource represented by an API. As stated above, a server MAY limit the type, order and count of bulk operations.`

I want any authorization system we come up with to allow jsonapi-resources to support PATCH operations on the root URL.

Authorizations are also important on the UI side for the client that will use the data. I was thinking about sending along with the object, the operation the user can perform on it.

For a post the author can create, read, update, delete, but a viewer can only read. Based on that meta information, the client can change the UI to reflect it.

This does not remove the need to block actions on the server based on the user's authorization, but it would provide a much more complete approach.

It might help others to see how I'm handing authorization. I'm pretty happy with the approach.

I'm using the pundit gem in combination with the new callbacks that are available in v0.1.0 of jsonapi-resources.

This is what my BaseResource class looks like.

module V1
  class BaseResource < JSONAPI::Resource
    [:create, :update, :remove].each do |action|
      set_callback action, :before, :authorize
    end

    # Authorize the model for the permission required by the controller
    # action. Also, mark the controller as having been policy authorized.
    def authorize
      controller = context.fetch(:controller)
      permission = controller.action_name + "?"

      controller.policy_authorized!
      policy = Pundit.policy!(context.fetch(:current_user), model)
      unless policy.public_send(permission)
        error = Pundit::NotAuthorizedError.new("not allowed to #{permission} this #{model}")
        error.query, error.record, error.policy = permission, model, policy
        raise error
      end
    end

    class << self
      # Override the records method to policy scope the records
      # used by JSONAPI::Resource find methods. Also, mark the controller
      # as having been policy scoped.
      def records(options = {})
        options.fetch(:context).fetch(:controller).policy_scoped!
        relation = Pundit.policy_scope!(options.fetch(:context).fetch(:current_user), _model_class)
        authorize(options.fetch(:context), relation)
        relation
      end

      private

      def authorize(context, relation)
        case context.fetch(:controller).action_name
        when "show"
          resource_for(
            context.fetch(:controller).params.fetch(:controller)
          ).new(relation.first, context).authorize
        end
      end
    end
  end
end

@barelyknown what are you using for authentication? My only experience with authentication in Rails so far is Devise, but that does not appear to be a good fit here.

@wzowee Devise could work fine. I've used that or just rolled my own using has_secure_password. In either case, I use the OAuth2 password flow and then ember-simple-auth.

@barelyknown I think you're on to something, I've been also thinking it'd be nice to use a pundit-like solution. Only I'm wondering if it'd be possible to have separate Policy objects with methods for each of the operations, and this object would be passed around to both resources (for GET requests / show operations) and controllers (for POST and PATCH / create and update operations). I'm still grokking the source to be able to offer a concrete solution, though

@wzowee we're also using ember-simple-auth + rolling our own token oauth, but this setup assumes you have an ember front-end, a single trusted client. Is that your scenario? It might be different for, say, services, or a public API.

I've evolved my approach a bit (but it's still the same basic idea). Here's some sample code. It might be helpful.

module V1
  class BaseResource < JSONAPI::Resource
    include ResourcePolicyAuthorization
    // ...
  end
end
module ResourcePolicyAuthorization
  extend ActiveSupport::Concern

  included do
    [:save, :remove].each do |action|
      set_callback action, :before, :authorize
    end
  end

  delegate :authorize_policy, to: :class

  def authorize
    authorize_policy(context[:current_user], model, context[:controller])
  end

  def records_for(association_name, options={})
    records = model.public_send(association_name)

    return records if context.nil?

    if records
      authorize_policy(context[:current_user], records, context[:controller])
    end
    records
  end

  class_methods do
    def records(options = {})
      authorized_records(
        options[:context][:current_user],
        options[:records_base] || _model_class,
        options[:context][:controller]
      )
    end

    def authorized_records(user, records, controller)
      records = Pundit.policy_scope!(user, records)
      controller.policy_scoped!

      authorize_policy(user, records, controller)

      records
    end

    def authorize_policy(user, records, controller)
      controller.policy_authorized!

      case records
      when ActiveRecord::Relation
        return if records.count == 0
      end

      policy = Pundit.policy!(user, policy_record_for(records))
      permission = permission_for(controller, policy)

      if !_authorized?(policy, permission)
        raise Pundit::NotAuthorizedError.new(
          query: permission_for(controller, policy),
          record: policy_record_for(records)
        )
      end
    end

    private

    def policy_record_for(records)
      case records
      when ActiveRecord::Base then records
      when ActiveRecord::Relation then records.first || records.model
      end
    end

    def permission_for(controller, policy)
      case controller.model_class == policy.model_class
      when true then controller.action_name.to_s + "?"
      when false then "show?"
      end
    end

    def _authorized?(policy, permission)
      policy.public_send(permission)
    end

  end
end

@oliverbarnes yeah - that's pretty much my scenario at present - have gone with ember-simple-auth and devise for now (see http://johnmosesman.com/ember-simple-auth-tutorial-and-common-problems/), mainly due to time constraints and not wanting to re-implement what comes for free with devise (account locking, password reset emails etc)

@barelyknown thanks for the update on how your authorisation is evolving.

@barelyknown I'm having a hard time seeing where the authorization rules are, or would go, there

The authorization rules are all in Pundit policies. https://github.com/elabs/pundit

Sure. Here's an ApplicationPolicy for an app. Ever resource has a matching policy (like PostPolicy or CommentPolicy), and they all (or at least most) inherit from the ApplicationPolicy. pundit policies authorize requests and provide scopes (which are relations that represent all of the records that a given user is authorized to see). Let me know if you'd like anything explained.

class ApplicationPolicy
  attr_reader :user, :record

  def initialize(user, record)
    @user = user
    @record = record
  end

  def index?
    true
  end

  def show?
    scope.where(:id => record.id).exists?
  end

  def get_related_resource?
    show?
  end

  def get_related_resources?
    index?
  end

  def create?
    false
  end

  def update?
    false
  end

  def destroy?
    false
  end

  def scope
    self.class::Scope.new(user, record.class).resolve
  end

  def model_class
    self.class.to_s[/.+(?=Policy)/].constantize
  end

  class Scope
    attr_reader :user, :scope

    def initialize(user, scope)
      @user = user
      @scope = scope
    end

    def resolve
      scope.none
    end
  end
end

Thanks. I guess my question is how would a pundit policy handle authorization that needs to be done before hitting the model. Checking the user id requested to patch a user resource against the current user's id, for example

It would first find the user that is the subject of the action. Then it would check if the current_user has permission to perform the action on that user (see #authorize_policy).

Right, that's what I mean - how do we do that based only on the user id param, without actually fetching the user from the database? Maybe this is out of JR's concern in the end... there's a reason why there's separate specs for authorization (like OAuth2) and resources. Just learning this myself

Why wouldn't you want to fetch the user with the user_id param?

Why fetch a record or even touch the database at all when you already know it’s off-limits? Best to respond with 403 as quickly as possible, IMHO

On June 5, 2015 at 3:09:18 PM, Sean Devine (notifications@github.com) wrote:

Why wouldn't you want to fetch the user with the user_id param?


Reply to this email directly or view it on GitHub.

How would you know?

@barelyknown i like the approach. I'll give it a shot and provide feedback.

The client would send it? Assuming the relationship with the owner is always present in the requests

On June 7, 2015 at 7:28:12 PM, Sean Devine (notifications@github.com) wrote:

How would you know?


Reply to this email directly or view it on GitHub.

That doesn't sound right (at least not for the standard case). You can authenticate who the request came from based on info in the request, but you need for the server to authorize that that user can perform whatever action they're trying to perform, and that will require looking up the some info in the DB (or wherever).

Would it be possible to authorize before show/index with the method barelyknown uses? As far as I can tell there are no callbacks for these methods. We need to restrict access to listing for some resources and displaying certain records in others in our API.

The approach that I use works for all actions including show/index. Are you running across a situation that doesn't seem like a fit?

We figured it out - I was confused by the split between using callbacks for save and remove, and fetching being implemented by overriding class methods, but my colleague helped clarify it for me.

@barelyknown this seems worth extracting to a gem so we have a common approach to JR auth with pundit.

I tried out the example code on a new API and so far options[:context][:controller], controller.policy_scoped! and controller.policy_authorized! are not available. I'm guessing these are manually defined on the controller?

First, I agree that extracting a common approach would be good, and I'm pretty sure that the method that I'm using is close to being right. I haven't honestly thought much about how to extract it, but it's one of the most frequently asked questions about jsonapi-resources so it's a great candidate for standardization.

Those methods are defined in this module:

# This module acts like Pundit but provides
# methods to make verification easier when authorization
# is done within a JSONAPI::Resource.
module PolicyAuthorization
  extend ActiveSupport::Concern

  included do
    class PolicyAuthorizationNotPerformedError < StandardError; end
    class PolicyScopingNotPerformedError < PolicyAuthorizationNotPerformedError; end

    after_action :verify_policy_authorized, except: [:index]
    after_action :verify_policy_scoped, only: [:index]

    rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized

    hide_action(
      :policy_authorized!,
      :policy_scoped!,
      :policy_authorized?,
      :policy_scoped?,
    )
  end

  # Indicate that a policy has been authorized on this controller.
  def policy_authorized!
    @policy_authorized = true
  end

  # Indicate that a policy scope has been used in this controller.
  def policy_scoped!
    @policy_scoped = true
  end

  def policy_authorized?
    !!@policy_authorized
  end

  def policy_scoped?
    !!@policy_scoped
  end

private
  # How to respond when the user is not authorized
  # to perform the action. Override in a subclass if
  # when you'd like different behavior.
  def user_not_authorized
    head :forbidden
  end

  def verify_policy_authorized
    raise PolicyAuthorizationNotPerformedError unless policy_authorized?
  end

  def verify_policy_scoped
    raise PolicyScopingNotPerformedError unless policy_scoped?
  end
end

@barelyknown This is really helpful, thanks a bunch! We've come across a little snag though, which we were hoping you might have a pointer for.

This method, from your earlier example:

def policy_record_for(records)
  case records
  when ActiveRecord::Base then records
  when ActiveRecord::Relation then records.first || records.model
  end
end

In our code, records is neither a ActiveRecord::Base nor an ActiveRecord::Relation here, so the method returns nil and causes errors elsewhere (unable to find policy of nil). records seems to come from the _model_class method, and we're not quite sure what it is exactly. (#class just returns Class).

Sidestepping the case statement and returning records in an else does seem to make it work again, but I'm curious as to why it might be different on our end. Changes in JAR?

Thanks again! (Love your podcast 😉)

I'm not exactly sure why records would be nil for you sometimes. I checked the application that I extracted that example out of and I haven't made any changes to ResourcePolicyAuthorization since and it still works great (on the master branch of JR). Without digging in too deeply, it doesn't sound right to me that records would ever be nil since the Resource should have a _model_class. Take a look into that and see what you find.

For what it's worth, you can add an else to the end of a case statement.

We know that authorization can be the trickiest bit for users of JR (especially in more complex situations), and we're thinking through how to make it less tricky. Any input is much appreciated.

And thanks for the nice words about the podcast :)

Ah, sorry, I wasn't completely clear - records is never nil, but records does not match ActiveRecord::Base or ActiveRecord::Relation in the case statement, which makes the method return nil.

Being completely new to both rails and ruby, I'm not sure how to find out what records is if it's not either of those, but like I said above, adding an else and returning records does seem to work.

Although it would be nice to find out what's actually going on here, I am helped with this solution.


Just as a side note to anyone stumbling upon this - we got an error about the controller not having implemented the model_class method, so we implemented that:

def model_class
  controller_name.classify.constantize
end

There are various ways that you could inspect records - either puts records.inspect and watch the logs or call byebug (if you have it installed) and it'll give you a debugger or raise records.inspect. But if you can figure out what type of object that is you could figure out how to handle it in a graceful way.

I know this is not a support forum, but to not leave people following along hanging with regards to the issue discussed above, the solution was to change the code to this:

def policy_record_for(records)
  case records
  when ActiveRecord::Relation then records.first || records.model
  else records
  end
end

The reason for this is that records can some times be the actual model class (not an instance). This is still a bit weird to me, but we'll get through it ;)

Thanks again to @barelyknown for helping out a bit more yesterday :)

Interesting problems keeps coming up regarding auth for us (I'm working with @kimroen). I'm trying to think of generic solutions as well as our particular problems.

What we hit yesterday was when trying to implement a policy where you can only update records that you "own" (record.user == current_user). What happened with our (tweaked) version of the solution @barelyknown provided is that the record sent into Pundit is a random one - because of this line:

when ActiveRecord::Relation then records.first || records.model

So Pundit is served records.first, which does not match the record that the update operation will find. This is because the update operation calls records.where(id: id) internally, which triggers authorized_records, and so on.

It seems to me that the intention of the implementation is that update and destroy operations shouldn't get authorized here at all, but later in the before_action callback defined at the top of the ResourcePolicyAuthorization concern.

My current ugly workaround is this:

def records(options = {})
  controller = options[:context][:controller]
  action = controller.action_name
  return super(options) if %w(update destroy).include? action
  # […]

I have a hunch that options[:records_base] from @barelyknown's implementation may have something to do with how it's supposed to work, as I haven't been able to figure out where that is supposed to come from or what it should do.

Generic solution

I've been thinking while working with this that it seems like a good idea generally to do the authorization in the resource.

In general I think one or more methods to override specifically for authorization in the resource would be nice to have. One difficult point is that some authorizations, like allowing or disallowing index, can probably be done without consulting the database, while others, like update and show, might require the record to be loaded, because you might want to check one or more properties on it (like object ownership) as a part of the authorization check.

It's kind of possible with overriding records today, like we're doing now, but it's very cumbersome especially because of the lack of distinction between the different kind of actions. And since you don't know if the caller will load all records or one particular record after going through records, it can't cover cases like the update case described above.

Hi everyone!

Me and @valscion also tried to incorporate authorization into our use of jsonapi-resources, and the discussion here has been of great help. Especially the code samples by @barelyknown provided a good starting point.

We decided to take a stab at extracting it into a gem of it's own: https://github.com/venuu/jsonapi-authorization. Please take it for a spin, have a look at the code, and see if it feels like something you'd like to contribute to.

We first tried to hook some of the authorization calls to the resource itself, but soon realised that not enough information about the current operation is available at that level. I agree with @thomassnielsen that it would be a pleasant place to work from, but currently it didn't seem possible.

Instead, we went with a custom OperationsProcessor, the way @lgebhardt was talking about above. It makes it possible to have very granular authorization if your app requires it, much more than just update? on the main record. Also, even if multiple operations were batched at once, it should be possible to authorize them one by one.

We can definitely second the claim that the Operation API could be cleaner. We currently reach very deep into the private parts of each @operation, through slightly differently named methods, to get the particular information needed (i.e. the affected models). Those models are then passed forward to a much simpler "authorizer" which ties together with Pundit. It works, but is brittle to upstream changes. Maybe our code can provide some pointers on how we could make the callbacks more authorization-friendly.

I hope you like it! We'd very much appreciate it if other, more seasoned users of jsonapi-resources are interested in helping with improving and maintaining the gem. ;)

I'm trying jsonapi-resources for the first time, and when using @barelyknown's solution with Pundit, some resource endpoints are returning 404 Not found instead of 403 Forbidden. It looks like this is because the policy scope is applied first before checking the show? permission. So instead checking the permission on the record and then raising NotAuthorizedError, it uses the scope and the record is never even included.

The scope is useful for index actions, but for show actions what's a good way to get the desired behavior of a 403 response? Or is it recommended to keep sending 404 for resources that couldn't be found because they are not authorized to be found?

@xtagon,

is it recommended to keep sending 404 for resources that couldn't be
found because they are not authorized to be found?

I would say yes, 404 is appropriate. You don't want to expose whether or
not the forbidden resource exists.

@vrybas Ah, that makes sense. Thanks.

@barelyknown I tried your Pundit solution with a few slight modifications to get it working on Rails 4. Everything seems to work OK, but I was running into trouble catching the Pundit::NotAuthorizedError in the resource controller. I made sure to whitelist it via:

JSONAPI.configure do |config|
  config.exception_class_whitelist = [Pundit::NotAuthorizedError]
end

But it ignores the rescue_from and simply falls back to returning the default 500 status code. If I modify the resource to simply throw an Exception with a "Not Authorized" message and handle that in my controller it seems to work fine. Doesn't seem to play well with StandardError though.

Seems to be a bug. If I downgrade to 0.6.2 everything seems to work. Supposedly #573 fixes this issue but it doesn't seem to work for me or something else is breaking it.

@nozpheratu The problem is probably related to this commit ace49ff. It removed some of the modules that provide the rescuable functionality.

You can add them back you your controller class. For example, I added something like the following:

class ApplicationController < JSONAPI::ResourceController
  include ActionController::Rescue
  include ActionController::Head

  rescue_from Pundit::NotAuthorizedError do |exception|
    head :forbidden
  end
end

I recently started a project with JSONAPI::Resources, and I'm now trying to implement authorization with Pundit. I stumbled across this and have read the entire thread multiple times over, but I have to admit I'm completely lost.

I'm fairly new to Rails, and this is my first time working with JSONAPI in any capacity. Does anyone have a working demo of the techniques discussed here, or perhaps a simple explanation of what's going on for someone with a bit less Rails experience? I've tried using some of the code snippets from above, but I just get a bunch of errors for each one.

Any help would be greatly appreciated.

The code worked for me on earlier versions of the gem. From:notifications@github.comSent:April 23, 2016 3:15 PMTo:jsonapi-resources@noreply.github.comReply-to:reply@reply.github.comCc:cylehunter33@gmail.com; mention@noreply.github.comSubject:Re: [cerebris/jsonapi-resources] Authorization (#16) I recently started a project with JSONAPI::Resources, and I'm now trying to implement authorization with Pundit. I stumbled across this and have read the entire thread multiple times over, but I have to admit I'm completely lost.

I'm fairly new to Rails, and this is my first time working with JSONAPI in any capacity. Does anyone have a working demo of the techniques discussed here, or perhaps a simple explanation of what's going on for someone with a bit less Rails experience? I've tried using some of the code snippets from above, but I just get a bunch of errors for each one.

Any help would be greatly appreciated.

—You are receiving this because you were mentioned.Reply to this email directly or view it on GitHub

@GRardB, give our gem a try: https://github.com/venuu/jsonapi-authorization — it should help you get started. Even though it's an alpha version and most likely still contains some bugs, it should have proper authorization hooks in place for all actions to be checked. If not, then that's a bug and we'd like to address it :)

@valscion I should document+test this better, but I have a 60-line module which hooks JR to Pundit for hummingbird.me. I'd love to compare notes and see if we can combine efforts. I know one problem with mine is that in certain cases a create is handled as an update, due to the way is_new? works.

@NuckChorris that looks like a nice approach, but I'm afraid you might not get enough protection by just applying hooks to resource classes. You might need to get all the way to the operations processor level to get all the necessary information out for authorization purposes, and that's indeed what we're doing with our gem. I'm not sure your approach protects against relationship actions.

We've got extensive request specs to test authorization. Check out e.g. POST /articles/:id/relationships/comments spec and think whether your approach would give the same level of authorization as ours. I'm not 100% sure but I think that resource level hooks are not enough in these cases

Years go by. Nothing done on authorisation. Wasted a day digging into the useless gem.

@ulitiy I can understand that you're disappointed, but there's no need to be rude. This gem works nicely for what it does, and authorization can be handled like we've done with our gem. You can't always get something for free and ready out-of-the-box, you might have to take your time to write the missing pieces yourself.

@ulitiy Authorization can be done in many ways. If there's a particular package that you are trying to use and it's conflicting with this gem please write up an issue specific to that problem. Gems like this intentionally do not try to solve every problem and it is a decision we have made to not advocate for one particular authorization solution.

Gems like this intentionally do not try to solve every problem and it is a decision we have made to not advocate for one particular authorization solution.

That's actually a great stance. Maybe it could be written up somewhere, and closing this issue as it's highly unlikely this will ever be "resolved" per se? Perhaps a wiki page, or something?

I haven't announced this gem yet (need to add tests for Rails 4.2), but https://github.com/togglepro/pundit-resources will be a drop in solution for using Pundit with jsonapi-resources for authorization. I've used the technique for a long time now on multiple projects, and it works great.

@valscion We definitely should add a section on authorization to the README. We could list the common options and maybe document it further in the Wiki. I haven't checked out @barelyknown's https://github.com/togglepro/pundit-resources yet, but if it's "drop in" (and good, as I assume) we might just recommend that as the safe and simple solution.

I'll leave this issue open until we address this in the README.

@barelyknown that seems like a nice approach. I'd be curious to know how it compares to https://github.com/venuu/jsonapi-authorization which handles ties authorization to Pundit, too.

Our gem just does it via operations processors as we thought that resource level callbacks weren't enough for everything. Operations processor also allows for more fine-grained permission handling.

If your gem happens to cover the same use cases as our gem with much less complexity, that's a huge win 😄.

@valscion I didn't even know that jsonapi-authorization existed! I hadn't looked because I've been using the code that is becoming pundit-resources for a long time and just hadn't extracted it. I'd be interested in any examples that would require the operations processor approach. It feels like they'd exist BUT I haven't come across one.

@barelyknown I'm using operations processors to protect show and index actions.

eg after_show_operation checks :show? and before_find_operation checks :index?

Just found this thread while trying to add punding to our JR project.
It seems that jsonapi-authorization and pundit-resources take different approaches to integrate JR and pundit.
Could anyone explain the difference between those 2 approaches?
Thanks!

Could anyone explain the difference between those 2 approaches?

Disclaimer: I know much more about jsonapi-authorization than pundit-resources, as I've co-authored it. I try to be objective when comparing these approaches but I might naturally have a bias towards the gem I've helped develop.

From the way I see it, pundit-resources relies on resource-level callbacks to tie into Pundit and call the matching Pundit policy methods when those resource-level callbacks are called. I haven't looked at what specific operations call each callback.

Now, how that compares to jsonapi-authorization?

I might still have missing details on pundit-resources, but I am very interested in seeing their gem progressing. If pundit-resources manages to handle all the authorization properly on resource level, it will be huge as writing operations processor callbacks currently is quite nasty. I hope for all the best for them, and seek to try out their gem once it has covered all JR operations somehow :)

Please correct me if I'm wrong on some aspects @barelyknown 😄

P.S.
If you want to try out jsonapi-authorization, please do so, but we encourage you to write some level of authorization tests on your own API anyway. I don't know much how our jsonapi-authorization is used in production yet as we've only protected some quite simple, non-critical internal APIs with it as of now. We intend to keep on developing this approach further as we create more APIs, but I don't know when that will be relevant.

I suppose @thibaudgg has a large-ish API using jsonapi-authorization, so he might be able to chime in on how to test for API authorization internally, too?

@aaronbhansen might also have some insight into how these two gems could possibly compare given my points.

I assume @arcreative could also tell a bit about using jsonapi-authorization, as he seems to have struggled with some issues at least?

EDIT:
Redacted the comment about relationship operations as corrected by @alyssais.

Wow thanks for this detailed answer :)
I'm still at the early stages of implementing authorization but that'll definitely be handy!

@valscion pundit-resources should be able to handle relationships, and they can be tested, I just haven't implemented the tests yet. The process for creating this gem was taking some code that we knew to work and extracting it to a gem, meaning we needed new tests, some of which just haven't been implemented yet (but I'm on it).

Thanks, @alyssais! I'll edit my comment accordingly :)

No problem @valscion. Everything else you've written about pundit-resources looks good. 👍

@valscion I'm not sure if you have seen the recent changes we have made to JR regarding processors. So far these are only in the master branch, though I hope to move them into a beta release this week. I bring this up because it's a breaking change for projects that use custom OperationsProcessors.

More details on the new Processors can be found in the Operation Processors section of the README.

I just became aware of JSONAPI::Authorization in this thread, so I'm sorry for the short notice on these changes. I'm hoping the changes will be relatively minor, and if there's anything I can do to help out please let me know.

@valscion I'm not sure if you have seen the recent changes we have made to JR regarding processors.

We've seen them 😉 venuu/jsonapi-authorization#22. We did anticipate that there might be changes like this, as we were fiddling with some private-ish APIs. I hope we can somehow make the approach backwards-compatible in jsonapi-authorization without having to write lots of clunky code, though 😕 .

I just became aware of JSONAPI::Authorization in this thread, so I'm sorry for the short notice on these changes.

No worries, the new approach to processors makes a lot of sense.

I'm hoping the changes will be relatively minor, and if there's anything I can do to help out please let me know.

I haven't yet figured how much trouble we're in if we want to retain backwards compatibility with JR 0.7.0 and the upcoming version. If you have any ideas, please let me know 😅 . We can discuss this in venuu/jsonapi-authorization#22 to avoid pinging all the people subscribed in this thread.

By the way, was this issue now resolved when #769 was merged? 🎉

@lgebhardt: #16 (comment)

I'll leave this issue open until we address this in the README.

@valscion It's a bit circular as #769 references this. But I'll close this since the pertinent details can now be reached from the readme.