varvet / pundit

Minimal authorization through OO design and pure Ruby classes
MIT License
8.21k stars 624 forks source link

First pass of Pundit::Context #797

Closed Burgestrand closed 2 months ago

Burgestrand commented 4 months ago

This should be backwards-compatible, so let me know if this breaks anything.

See https://github.com/varvet/pundit/discussions/774 initial draft/rationale.

Caution

Hopefully this allows us to:

Burgestrand commented 4 months ago

Right now this change is backwards-compatible, possibly with the exception of our new pundit method. We could probably try this out in the wild, and then expand on the Pundit::Context API surface to introduce namespacing.

Burgestrand commented 4 months ago

Unless it's far too controversial I'd like to be able to remove the singleton methods on Pundit class in the future, and instead call them through a Pundit::Context. This is only if you're using Pundit outside of Rails.

For those who uses Pundit::Authorization (i.e. Rails), I'm thinking not much would change.

Burgestrand commented 3 months ago

@mattzollinhofer I've added some more commits to kinda hint at where I'm going at.

A change I haven't gotten to is passing more information to policy_cache.fetch, at least the user and maybe the passed-in policy_class. Once that's done it would be up to the cache strategy to turn those three into a cache key.

We would achieve backwards-compatibility by having a LegacyCache as default cache, and that cache simply ignores the user and policy_class passed. It would then work just as before.

By then implementing a new cache strategy that's opt-in we can get caching behaviour when passing policy_class. How that looks then later in the view I'm not sure. Maybe we would require passing the overridden policy from the view too, so that the cache key remains the same - otherwise it would be impossible to mix explicit policy_class with pundit-found policy.

Burgestrand commented 3 months ago

Another idea I had for this is some shortcuts to how one could override the default behavior in specific controllers, e.g:

class AdminControllerBase < ApplicationController
  def pundit
    @pundit ||= super.with_namespace(Admin)
  end
end
Burgestrand commented 2 months ago

Had a few people at RailsConf try this out in their apps, and nothing broke! Thank you all :)