Skip to content

Commit

Permalink
Use Pundit for authorization + let there always be a model (#180)
Browse files Browse the repository at this point in the history
  • Loading branch information
jensljungblad authored Dec 12, 2017
1 parent b06229c commit f16c720
Show file tree
Hide file tree
Showing 12 changed files with 43 additions and 125 deletions.
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ gemspec

# The dummy app loads whatever is specified in this gemfile, therefore
# we add the admin engine used by the dummy app here
gem "admin", path: "test/dummy/admin", group: [:test, :development]
gem "admin", path: "test/dummy/admin", group: %i[test development]
19 changes: 15 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,15 @@ It inserts a `navbar_item` in the `app/views/shared/_navigation.html.erb` partia
<%= navbar_item Article %>
```

If Godmin was installed inside an engine, it creates a model class:

```ruby
module Admin
class Article < ::Article
end
end
```

It creates a controller:

```ruby
Expand Down Expand Up @@ -742,7 +751,7 @@ The admin section is now authenticated using Devise.

## Authorization

In order to enable authorization, authentication must first be enabled. See the previous section. The Godmin authorization system is heavily inspired by [Pundit](https://github.com/elabs/pundit) and implements the same interface.
In order to enable authorization, authentication must first be enabled. See the previous section. The Godmin authorization system uses [Pundit](https://github.com/elabs/pundit).

Add the authorization module to the application controller:

Expand Down Expand Up @@ -802,8 +811,8 @@ end
That is, everyone can list and view articles, only editors can create them, and only unpublished articles can be updated and destroyed.

### Handle unauthorized access
When a user is not authorized to access a resource, a `NotAuthorizedError` is raised. By default this error is rescued by Godmin and turned into a status code `403 Forbidden` response.
If you want to change this behaviour you can rescue the error yourself in the appropriate `ApplicationController`:

When a user is not authorized to access a resource, a `Pundit::NotAuthorizedError` is raised. By default this error is rescued by Godmin and turned into a status code `403 Forbidden` response. If you want to change this behaviour you can rescue the error yourself in the appropriate `ApplicationController`:

```ruby
class ApplicationController < ActionController::Base
Expand All @@ -812,13 +821,14 @@ class ApplicationController < ActionController::Base
include Godmin::Authorization

# Renders 404 page and returns status code 404.
rescue_from NotAuthorizedError do
rescue_from Pundit::NotAuthorizedError do
render file: "#{Rails.root}/public/404.html", status: 404, layout: false
end
end
```

### Override policy object

If you wish to specify what policy to use manually, override the following method in your model. It does not have to be an ActiveRecord object, but any object will do.

```ruby
Expand All @@ -830,6 +840,7 @@ end
```

### Batch action authorization

Batch actions must be authorized in your policy if you are using Godmin's built in authorization functionality. The policy method is called with the relation containing all records to be processed.

```ruby
Expand Down
1 change: 1 addition & 0 deletions godmin.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Gem::Specification.new do |gem|
gem.add_dependency "csv_builder", "~> 2.1"
gem.add_dependency "jquery-rails", [">= 3.0", "< 5.0"]
gem.add_dependency "momentjs-rails", "~> 2.8"
gem.add_dependency "pundit", [">= 1.1", "< 2.0"]
gem.add_dependency "rails", [">= 4.2.0", "< 6.0"]
gem.add_dependency "sass-rails", [">= 4.0", "< 6.0"]
gem.add_dependency "selectize-rails", "~> 0.12"
Expand Down
8 changes: 7 additions & 1 deletion lib/generators/godmin/resource/resource_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class Godmin::ResourceGenerator < Godmin::Generators::NamedBase
argument :attributes, type: :array, default: [], banner: "attribute attribute"

def add_route
route "resources :#{file_name.pluralize}"
invoke "resource_route"
end

def add_navigation
Expand All @@ -15,6 +15,12 @@ def add_navigation
end
end

def create_model
if namespaced?
template "resource_model.rb", File.join("app/models", class_path, "#{file_name}.rb")
end
end

def create_controller
template "resource_controller.rb", File.join("app/controllers", class_path, "#{file_name.pluralize}_controller.rb")
end
Expand Down
4 changes: 4 additions & 0 deletions lib/generators/godmin/resource/templates/resource_model.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<% module_namespacing do -%>
class <%= class_name %> < ::<%= class_name %>
end
<% end -%>
26 changes: 6 additions & 20 deletions lib/godmin/authorization.rb
Original file line number Diff line number Diff line change
@@ -1,34 +1,20 @@
require "pundit"
require "godmin/authorization/policy"
require "godmin/authorization/policy_finder"

module Godmin
module Authorization
extend ActiveSupport::Concern

included do
helper_method :policy
include Pundit

rescue_from NotAuthorizedError do
included do
rescue_from Pundit::NotAuthorizedError do
render plain: "You are not authorized to do this", status: 403, layout: "godmin/login"
end
end

def authorize(record, query = nil)
policy = policy(record)

unless policy.public_send(query || action_name + "?")
fail NotAuthorizedError
end
def pundit_user
admin_user
end

def policy(record)
policies[record] ||= PolicyFinder.find(record, engine_wrapper.namespace).new(admin_user, record)
end

def policies
@_policies ||= {}
end

class NotAuthorizedError < StandardError; end
end
end
31 changes: 0 additions & 31 deletions lib/godmin/authorization/policy_finder.rb

This file was deleted.

8 changes: 4 additions & 4 deletions lib/godmin/generators/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ module Godmin
module Generators
class Base < Rails::Generators::Base
def self.source_paths
%w(authentication install policy resource).map do |path|
%w[authentication install policy resource].map do |path|
File.expand_path("../../../generators/godmin/#{path}/templates", __FILE__)
end
end

private

def namespace
@namespace ||= Rails::Generators.namespace
@_namespace ||= Rails::Generators.namespace
end

def namespaced?
@namespaced ||= namespace.present?
@_namespaced ||= namespace.present?
end

def namespaced_path
@namespaced_path ||= begin
@_namespaced_path ||= begin
if namespaced?
namespace.name.split("::").map(&:underscore)
else
Expand Down
8 changes: 4 additions & 4 deletions lib/godmin/generators/named_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@ class NamedBase < Base
private

def full_class_name
if namespace
if namespaced?
"#{namespace}::#{class_name}"
else
class_name
end
end

def class_name
@class_name ||= name.classify
@_class_name ||= name.classify
end

def class_path
@class_path ||= namespaced_path + name.classify.deconstantize.split("::").map(&:underscore)
@_class_path ||= namespaced_path + name.classify.deconstantize.split("::").map(&:underscore)
end

def file_name
@file_name ||= class_name.demodulize.underscore
@_file_name ||= class_name.demodulize.underscore
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/godmin/resources/resource_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def resource_class
end

def resource_class_name
self.class.name.demodulize.chomp("Service")
self.class.name.chomp("Service")
end

def resources_relation
Expand Down
4 changes: 0 additions & 4 deletions test/fakes/article_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ def initialize(*)
@called_methods = { scopes: {}, filters: {}, batch_actions: {}, ordering: {} }
end

def resource_class
Fakes::Article
end

def resources_relation
[:foo, :bar, :baz]
end
Expand Down
55 changes: 0 additions & 55 deletions test/lib/godmin/policy_finder_test.rb

This file was deleted.

0 comments on commit f16c720

Please sign in to comment.