activeadmin 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activeadmin might be problematic. Click here for more details.
- data/.travis.yml +8 -5
- data/CHANGELOG.md +151 -0
- data/Gemfile +16 -16
- data/LICENSE +1 -1
- data/activeadmin.gemspec +1 -0
- data/app/assets/images/active_admin/index_list_icons/block_icon.svg +10 -0
- data/app/assets/images/active_admin/index_list_icons/blog_icon.svg +4 -0
- data/app/assets/images/active_admin/index_list_icons/grid_icon.svg +13 -0
- data/app/assets/images/active_admin/index_list_icons/table_icon.svg +3 -0
- data/app/assets/javascripts/active_admin/components/jquery.aa.checkbox-toggler.js.coffee +17 -44
- data/app/assets/javascripts/active_admin/components/jquery.aa.dropdown-menu.js.coffee +2 -4
- data/app/assets/javascripts/active_admin/components/jquery.aa.popover.js.coffee +0 -3
- data/app/assets/javascripts/active_admin/components/jquery.aa.table-checkbox-toggler.js.coffee +10 -12
- data/app/assets/javascripts/active_admin/pages/application.js.coffee +13 -10
- data/app/assets/javascripts/active_admin/pages/batch_actions.js.coffee +3 -3
- data/app/assets/stylesheets/active_admin/_base.css.scss +1 -0
- data/app/assets/stylesheets/active_admin/_header.css.scss +5 -2
- data/app/assets/stylesheets/active_admin/components/_dropdown_menu.scss +2 -2
- data/app/assets/stylesheets/active_admin/components/_index_list.scss +12 -0
- data/app/assets/stylesheets/active_admin/components/_popovers.css.scss +2 -2
- data/app/assets/stylesheets/active_admin/components/_table_tools.css.scss +2 -2
- data/app/assets/stylesheets/active_admin/mixins/_buttons.css.scss +4 -4
- data/app/assets/stylesheets/active_admin/mixins/_gradients.css.scss +5 -4
- data/app/assets/stylesheets/active_admin/mixins/_sections.css.scss +1 -1
- data/app/assets/stylesheets/active_admin/pages/_logged_out.scss +1 -1
- data/app/assets/stylesheets/active_admin/print.css.scss +2 -2
- data/app/assets/stylesheets/active_admin/structure/_title_bar.scss +1 -1
- data/app/views/active_admin/devise/unlocks/new.html.erb +14 -12
- data/docs/1-general-configuration.md +13 -0
- data/docs/10-custom-pages.md +40 -28
- data/docs/11-decorators.md +6 -4
- data/docs/12-arbre-components.md +1 -1
- data/docs/13-authorization-adapter.md +206 -0
- data/docs/2-resource-customization.md +129 -14
- data/docs/3-index-pages.md +65 -0
- data/docs/3-index-pages/create-an-index.md +29 -0
- data/docs/3-index-pages/index-as-table.md +35 -11
- data/docs/5-forms.md +2 -2
- data/features/authorization.feature +64 -0
- data/features/authorization_cancan.feature +52 -0
- data/features/belongs_to.feature +41 -5
- data/features/index/batch_actions.feature +27 -3
- data/features/index/formats.feature +27 -0
- data/features/index/index_as_table.feature +74 -2
- data/features/index/index_parameters.feature +69 -0
- data/features/index/index_scopes.feature +7 -11
- data/features/index/page_title.feature +18 -0
- data/features/index/switch_index_view.feature +73 -0
- data/features/menu.feature +27 -0
- data/features/registering_pages.feature +21 -0
- data/features/step_definitions/additional_web_steps.rb +4 -0
- data/features/step_definitions/batch_action_steps.rb +16 -6
- data/features/step_definitions/index_scope_steps.rb +3 -3
- data/features/step_definitions/index_views_steps.rb +3 -0
- data/features/step_definitions/menu_steps.rb +4 -0
- data/features/support/env.rb +4 -0
- data/features/support/paths.rb +3 -0
- data/lib/active_admin.rb +4 -0
- data/lib/active_admin/application.rb +43 -76
- data/lib/active_admin/authorization_adapter.rb +128 -0
- data/lib/active_admin/base_controller.rb +18 -1
- data/lib/active_admin/base_controller/authorization.rb +153 -0
- data/lib/active_admin/base_controller/menu.rb +8 -3
- data/lib/active_admin/batch_actions/resource_extension.rb +8 -7
- data/lib/active_admin/batch_actions/views/batch_action_form.rb +1 -1
- data/lib/active_admin/cancan_adapter.rb +40 -0
- data/lib/active_admin/dashboards.rb +4 -5
- data/lib/active_admin/dashboards/dashboard_controller.rb +1 -1
- data/lib/active_admin/devise.rb +22 -7
- data/lib/active_admin/dsl.rb +18 -5
- data/lib/active_admin/engine.rb +1 -1
- data/lib/active_admin/filters/dsl.rb +1 -1
- data/lib/active_admin/filters/forms.rb +9 -7
- data/lib/active_admin/filters/resource_extension.rb +20 -15
- data/lib/active_admin/form_builder.rb +44 -49
- data/lib/active_admin/helpers/optional_display.rb +4 -8
- data/lib/active_admin/inputs/filter_boolean_input.rb +1 -1
- data/lib/active_admin/inputs/filter_string_input.rb +5 -1
- data/lib/active_admin/locales/bg.yml +1 -1
- data/lib/active_admin/locales/ca.yml +1 -1
- data/lib/active_admin/locales/cs.yml +26 -25
- data/lib/active_admin/locales/da.yml +1 -1
- data/lib/active_admin/locales/de.yml +1 -1
- data/lib/active_admin/locales/en.yml +11 -1
- data/lib/active_admin/locales/es.yml +16 -16
- data/lib/active_admin/locales/fr.yml +1 -1
- data/lib/active_admin/locales/he.yml +1 -1
- data/lib/active_admin/locales/hr.yml +1 -1
- data/lib/active_admin/locales/hu.yml +1 -1
- data/lib/active_admin/locales/it.yml +1 -1
- data/lib/active_admin/locales/ja.yml +4 -1
- data/lib/active_admin/locales/ko.yml +1 -1
- data/lib/active_admin/locales/lt.yml +1 -1
- data/lib/active_admin/locales/lv.yml +12 -1
- data/lib/active_admin/locales/nl.yml +2 -2
- data/lib/active_admin/locales/no-NB.yml +22 -1
- data/lib/active_admin/locales/pl.yml +1 -1
- data/lib/active_admin/locales/pt-BR.yml +1 -1
- data/lib/active_admin/locales/pt-PT.yml +81 -0
- data/lib/active_admin/locales/ro.yml +1 -1
- data/lib/active_admin/locales/ru.yml +1 -1
- data/lib/active_admin/locales/sv-SE.yml +1 -1
- data/lib/active_admin/locales/tr.yml +1 -1
- data/lib/active_admin/locales/vi.yml +1 -1
- data/lib/active_admin/locales/zh-CN.yml +1 -1
- data/lib/active_admin/locales/zh-TW.yml +1 -1
- data/lib/active_admin/menu.rb +76 -38
- data/lib/active_admin/menu_collection.rb +96 -0
- data/lib/active_admin/menu_item.rb +61 -71
- data/lib/active_admin/namespace.rb +67 -5
- data/lib/active_admin/page.rb +6 -0
- data/lib/active_admin/page_controller.rb +13 -3
- data/lib/active_admin/resource.rb +11 -20
- data/lib/active_admin/resource/action_items.rb +3 -3
- data/lib/active_admin/resource/controllers.rb +0 -17
- data/lib/active_admin/resource/menu.rb +52 -24
- data/lib/active_admin/resource/naming.rb +6 -10
- data/lib/active_admin/resource/page_presenters.rb +57 -3
- data/lib/active_admin/resource/routes.rb +46 -0
- data/lib/active_admin/resource_controller.rb +2 -17
- data/lib/active_admin/resource_controller/data_access.rb +299 -0
- data/lib/active_admin/resource_controller/decorators.rb +2 -1
- data/lib/active_admin/resource_dsl.rb +12 -14
- data/lib/active_admin/router.rb +61 -56
- data/lib/active_admin/scope.rb +28 -18
- data/lib/active_admin/version.rb +1 -1
- data/lib/active_admin/view_factory.rb +0 -1
- data/lib/active_admin/view_helpers/breadcrumb_helper.rb +13 -19
- data/lib/active_admin/view_helpers/fields_for.rb +2 -0
- data/lib/active_admin/view_helpers/form_helper.rb +1 -1
- data/lib/active_admin/view_helpers/method_or_proc_helper.rb +66 -11
- data/lib/active_admin/views/components/attributes_table.rb +7 -4
- data/lib/active_admin/views/components/index_list.rb +68 -0
- data/lib/active_admin/views/components/paginated_collection.rb +13 -9
- data/lib/active_admin/views/components/scopes.rb +2 -8
- data/lib/active_admin/views/components/table_for.rb +1 -1
- data/lib/active_admin/views/footer.rb +1 -1
- data/lib/active_admin/views/header.rb +3 -2
- data/lib/active_admin/views/index_as_block.rb +4 -0
- data/lib/active_admin/views/index_as_blog.rb +4 -0
- data/lib/active_admin/views/index_as_grid.rb +4 -0
- data/lib/active_admin/views/index_as_table.rb +49 -7
- data/lib/active_admin/views/pages/index.rb +19 -4
- data/lib/active_admin/views/tabbed_navigation.rb +10 -54
- data/lib/generators/active_admin/install/install_generator.rb +5 -1
- data/lib/generators/active_admin/install/templates/active_admin.rb.erb +58 -0
- data/spec/integration/{default_namespace.rb → default_namespace_spec.rb} +0 -16
- data/spec/spec_helper.rb +3 -0
- data/spec/support/detect_rails_version.rb +10 -3
- data/spec/support/rails_template.rb +1 -1
- data/spec/support/templates/post_decorator.rb +6 -6
- data/spec/unit/application_spec.rb +5 -5
- data/spec/unit/authorization/authorization_adapter_spec.rb +61 -0
- data/spec/unit/authorization/controller_authorization_spec.rb +47 -0
- data/spec/unit/base_controller_spec.rb +0 -2
- data/spec/unit/batch_actions/resource_spec.rb +1 -1
- data/spec/unit/breadcrumbs_spec.rb +3 -3
- data/spec/unit/cancan_adapter_spec.rb +35 -0
- data/spec/unit/config_shared_examples.rb +9 -30
- data/spec/unit/devise_spec.rb +29 -0
- data/spec/unit/dsl_spec.rb +61 -0
- data/spec/unit/filters/filter_form_builder_spec.rb +58 -4
- data/spec/unit/filters/resource_spec.rb +17 -5
- data/spec/unit/form_builder_spec.rb +15 -0
- data/spec/unit/menu_collection_spec.rb +62 -0
- data/spec/unit/menu_item_spec.rb +51 -37
- data/spec/unit/menu_spec.rb +33 -29
- data/spec/unit/namespace/authorization_spec.rb +31 -0
- data/spec/unit/namespace/register_page_spec.rb +6 -28
- data/spec/unit/namespace/register_resource_spec.rb +11 -34
- data/spec/unit/namespace_spec.rb +63 -2
- data/spec/unit/page_controller_spec.rb +0 -3
- data/spec/unit/reloader_spec.rb +5 -5
- data/spec/unit/resource/menu_spec.rb +1 -13
- data/spec/unit/resource/naming_spec.rb +20 -2
- data/spec/unit/resource/page_presenters_spec.rb +14 -2
- data/spec/unit/resource_controller/{collection_spec.rb → data_access_spec.rb} +31 -13
- data/spec/unit/resource_controller_spec.rb +4 -5
- data/spec/unit/resource_spec.rb +33 -11
- data/spec/unit/routing_spec.rb +43 -0
- data/spec/unit/scope_spec.rb +13 -0
- data/spec/unit/view_factory_spec.rb +0 -1
- data/spec/unit/view_helpers/fields_for_spec.rb +4 -0
- data/spec/unit/view_helpers/form_helper_spec.rb +6 -2
- data/spec/unit/view_helpers/method_or_proc_helper_spec.rb +97 -0
- data/spec/unit/views/components/attributes_table_spec.rb +11 -0
- data/spec/unit/views/components/index_list_spec.rb +32 -0
- data/spec/unit/views/tabbed_navigation_spec.rb +42 -40
- data/tasks/test.rake +1 -1
- metadata +127 -40
- data/lib/active_admin/menu_builder.rb +0 -65
- data/lib/active_admin/resource_controller/callbacks.rb +0 -59
- data/lib/active_admin/resource_controller/collection.rb +0 -158
- data/lib/active_admin/views/utility_nav.rb +0 -41
- data/spec/unit/base_controller_shared_examples.rb +0 -25
- data/spec/unit/dsl_include_spec.rb +0 -20
@@ -0,0 +1,128 @@
|
|
1
|
+
module ActiveAdmin
|
2
|
+
|
3
|
+
# Default Authorization permissions for Active Admin
|
4
|
+
module Authorization
|
5
|
+
READ = :read
|
6
|
+
CREATE = :create
|
7
|
+
UPDATE = :update
|
8
|
+
DESTROY = :destroy
|
9
|
+
end
|
10
|
+
|
11
|
+
Auth = Authorization
|
12
|
+
|
13
|
+
|
14
|
+
# Active Admin's default authorization adapter. This adapter returns true
|
15
|
+
# for all requests to `#authorized?`. It should be the starting point for
|
16
|
+
# implementing your own authorization adapter.
|
17
|
+
#
|
18
|
+
# To view an example subclass, check out `ActiveAdmin::CanCanAdapter`
|
19
|
+
class AuthorizationAdapter
|
20
|
+
attr_reader :resource, :user
|
21
|
+
|
22
|
+
|
23
|
+
# Initialize a new authorization adapter. This happens on each and
|
24
|
+
# every request to a controller.
|
25
|
+
#
|
26
|
+
# @param [ActiveAdmin::Resource, ActiveAdmin::Page] resource The resource
|
27
|
+
# that the user is currently on. Note, we may be authorizing access
|
28
|
+
# to a different subject, so don't rely on this other than to
|
29
|
+
# pull configuration information from.
|
30
|
+
#
|
31
|
+
# @param [any] user The current user. The user is set to whatever is returned
|
32
|
+
# from `#current_active_admin_user` in the controller.
|
33
|
+
#
|
34
|
+
def initialize(resource, user)
|
35
|
+
@resource = resource
|
36
|
+
@user = user
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns true of false depending on if the user is authorized to perform
|
40
|
+
# the action on the subject.
|
41
|
+
#
|
42
|
+
# @param [Symbol] action The name of the action to perform. Usually this will be
|
43
|
+
# one of the `ActiveAdmin::Auth::*` symbols.
|
44
|
+
#
|
45
|
+
# @param [any] subject The subject the action is being performed on usually this
|
46
|
+
# is a model object. Note, that this is NOT always in instance, it can be
|
47
|
+
# the class of the subject also. For example, Active Admin uses the class
|
48
|
+
# of the resource to decide if the resource should be displayed in the
|
49
|
+
# global navigation. To deal with this nicely in a case statement, take
|
50
|
+
# a look at `#normalized(klasss)`
|
51
|
+
#
|
52
|
+
# @returns [Boolean]
|
53
|
+
def authorized?(action, subject = nil)
|
54
|
+
true
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
# A hook method for authorization libraries to scope the collection. By
|
59
|
+
# default, we just return the same collection. The returned scope is used
|
60
|
+
# as the starting point for all queries to the db in the controller.
|
61
|
+
#
|
62
|
+
# @param [ActiveRecord::Relation] collection The collection the user is
|
63
|
+
# attempting to view.
|
64
|
+
#
|
65
|
+
# @returns [ActiveRecord::Relation] A new collection, scoped to the
|
66
|
+
# objects that the current user has access to.
|
67
|
+
def scope_collection(collection)
|
68
|
+
collection
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
# The `#authorized?` method's subject can be set to both instances as well
|
74
|
+
# as classes of objects. This can make it much difficult to create simple
|
75
|
+
# case statements for authorization since you have to handle both the
|
76
|
+
# class level match and the instance level match.
|
77
|
+
#
|
78
|
+
# For example:
|
79
|
+
#
|
80
|
+
# class MyAuthAdapter < ActiveAdmin::AuthorizationAdapter
|
81
|
+
#
|
82
|
+
# def authorized?(action, subject = nil)
|
83
|
+
# case subject
|
84
|
+
# when Post
|
85
|
+
# true
|
86
|
+
# when Class
|
87
|
+
# if subject == Post
|
88
|
+
# true
|
89
|
+
# end
|
90
|
+
# end
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
# To handle this, the normalized method takes care of returning a object
|
96
|
+
# which implements `===` to be matched in a case statement.
|
97
|
+
#
|
98
|
+
# The above now becomes:
|
99
|
+
#
|
100
|
+
# class MyAuthAdapter < ActiveAdmin::AuthorizationAdapter
|
101
|
+
#
|
102
|
+
# def authorized?(action, subject = nil)
|
103
|
+
# case subject
|
104
|
+
# when normalized(Post)
|
105
|
+
# true
|
106
|
+
# end
|
107
|
+
# end
|
108
|
+
#
|
109
|
+
# end
|
110
|
+
def normalized(klass)
|
111
|
+
NormalizedMatcher.new(klass)
|
112
|
+
end
|
113
|
+
|
114
|
+
class NormalizedMatcher
|
115
|
+
|
116
|
+
def initialize(klass)
|
117
|
+
@klass = klass
|
118
|
+
end
|
119
|
+
|
120
|
+
def ===(other)
|
121
|
+
@klass == other || other.is_a?(@klass)
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'inherited_resources'
|
2
|
+
|
3
|
+
require 'active_admin/base_controller/authorization'
|
2
4
|
require 'active_admin/base_controller/menu'
|
3
5
|
|
4
6
|
module ActiveAdmin
|
@@ -7,7 +9,7 @@ module ActiveAdmin
|
|
7
9
|
class BaseController < ::InheritedResources::Base
|
8
10
|
helper ::ActiveAdmin::ViewHelpers
|
9
11
|
|
10
|
-
layout
|
12
|
+
layout :determine_active_admin_layout
|
11
13
|
|
12
14
|
before_filter :only_render_implemented_actions
|
13
15
|
before_filter :authenticate_active_admin_user
|
@@ -29,6 +31,7 @@ module ActiveAdmin
|
|
29
31
|
end
|
30
32
|
|
31
33
|
include Menu
|
34
|
+
include Authorization
|
32
35
|
|
33
36
|
private
|
34
37
|
|
@@ -57,5 +60,19 @@ module ActiveAdmin
|
|
57
60
|
end
|
58
61
|
helper_method :active_admin_namespace
|
59
62
|
|
63
|
+
|
64
|
+
ACTIVE_ADMIN_ACTIONS = [:index, :show, :new, :create, :edit, :update, :destroy]
|
65
|
+
|
66
|
+
# Determine which layout to use.
|
67
|
+
#
|
68
|
+
# 1. If we're rendering a standard Active Admin action, we want layout(false)
|
69
|
+
# because these actions are subclasses of the Base page (which implements
|
70
|
+
# all the required layout code)
|
71
|
+
# 2. If we're rendering a custom action, we'll use the active_admin layout so
|
72
|
+
# that users can render any template inside Active Admin.
|
73
|
+
def determine_active_admin_layout
|
74
|
+
ACTIVE_ADMIN_ACTIONS.include?(params[:action].to_sym) ? false : 'active_admin'
|
75
|
+
end
|
76
|
+
|
60
77
|
end
|
61
78
|
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
module ActiveAdmin
|
2
|
+
|
3
|
+
# Exception class to raise when there is an authorized access
|
4
|
+
# exception thrown. The exception has a few goodies that may
|
5
|
+
# be useful for capturing / recognizing security issues.
|
6
|
+
class AccessDenied < StandardError
|
7
|
+
attr_reader :user, :action, :subject
|
8
|
+
|
9
|
+
def initialize(user, action, subject)
|
10
|
+
@user, @action, @subject = user, action, subject
|
11
|
+
|
12
|
+
super()
|
13
|
+
end
|
14
|
+
|
15
|
+
def message
|
16
|
+
I18n.t("active_admin.access_denied.message")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
class BaseController < ::InheritedResources::Base
|
22
|
+
module Authorization
|
23
|
+
include MethodOrProcHelper
|
24
|
+
extend ActiveSupport::Concern
|
25
|
+
|
26
|
+
ACTIONS_DICTIONARY = {
|
27
|
+
:index => ActiveAdmin::Authorization::READ,
|
28
|
+
:show => ActiveAdmin::Authorization::READ,
|
29
|
+
:new => ActiveAdmin::Authorization::CREATE,
|
30
|
+
:create => ActiveAdmin::Authorization::CREATE,
|
31
|
+
:edit => ActiveAdmin::Authorization::UPDATE,
|
32
|
+
:update => ActiveAdmin::Authorization::UPDATE,
|
33
|
+
:destroy => ActiveAdmin::Authorization::DESTROY
|
34
|
+
}
|
35
|
+
|
36
|
+
included do
|
37
|
+
rescue_from ActiveAdmin::AccessDenied, :with => :dispatch_active_admin_access_denied
|
38
|
+
|
39
|
+
helper_method :authorized?
|
40
|
+
helper_method :authorize!
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
# Authorize the action and subject. Available in the controller
|
46
|
+
# as well as all the views.
|
47
|
+
#
|
48
|
+
# @param [Symbol] action The action to check if the user has permission
|
49
|
+
# to perform on the subject.
|
50
|
+
#
|
51
|
+
# @param [any] subject The subject that the user is trying to perform
|
52
|
+
# the action on.
|
53
|
+
#
|
54
|
+
# @returns [Boolean]
|
55
|
+
#
|
56
|
+
def authorized?(action, subject = nil)
|
57
|
+
active_admin_authorization.authorized?(action, subject)
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
# Authorize the action and subject. Available in the controller
|
62
|
+
# as well as all the views. If the action is not allowd, it raises
|
63
|
+
# an ActiveAdmin::AccessDenied exception.
|
64
|
+
#
|
65
|
+
# @param [Symbol] action The action to check if the user has permission
|
66
|
+
# to perform on the subject.
|
67
|
+
#
|
68
|
+
# @param [any] subject The subject that the user is trying to perform
|
69
|
+
# the action on.
|
70
|
+
#
|
71
|
+
# @returns [Boolean] True if authorized, otherwise raises
|
72
|
+
# an ActiveAdmin::AccessDenied.
|
73
|
+
def authorize!(action, subject = nil)
|
74
|
+
unless authorized? action, subject
|
75
|
+
raise ActiveAdmin::AccessDenied.new(current_active_admin_user,
|
76
|
+
action,
|
77
|
+
subject)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Performs authorization on the resource using the current controller
|
82
|
+
# action as the permission action.
|
83
|
+
#
|
84
|
+
def authorize_resource!(resource)
|
85
|
+
permission = action_to_permission(params[:action])
|
86
|
+
authorize! permission, resource
|
87
|
+
end
|
88
|
+
|
89
|
+
# Retrieve or instantiate the authorization instance for this resource
|
90
|
+
#
|
91
|
+
# @returns [ActiveAdmin::AuthorizationAdapter]
|
92
|
+
def active_admin_authorization
|
93
|
+
@active_admin_authorization ||= active_admin_authorization_adapter.new(active_admin_config, current_active_admin_user)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Returns the class to be used as the authorization adapter
|
97
|
+
#
|
98
|
+
# @returns [Class]
|
99
|
+
def active_admin_authorization_adapter
|
100
|
+
if active_admin_namespace.authorization_adapter.is_a?(String)
|
101
|
+
ActiveSupport::Dependencies.constantize(active_admin_namespace.authorization_adapter)
|
102
|
+
else
|
103
|
+
active_admin_namespace.authorization_adapter
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Converts a controller action into one of the correct Active Admin
|
108
|
+
# authorization names. Uses the ACTIONS_DICTIONARY to convert the
|
109
|
+
# action name to permission.
|
110
|
+
#
|
111
|
+
# @param [String, Symbol] action The controller action name.
|
112
|
+
#
|
113
|
+
# @returns [Symbol] The permission name to use.
|
114
|
+
def action_to_permission(action)
|
115
|
+
return nil unless action
|
116
|
+
|
117
|
+
action = action.to_sym
|
118
|
+
|
119
|
+
if Authorization::ACTIONS_DICTIONARY.has_key?(action)
|
120
|
+
Authorization::ACTIONS_DICTIONARY[action]
|
121
|
+
else
|
122
|
+
action
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def dispatch_active_admin_access_denied(exception)
|
127
|
+
call_method_or_exec_proc active_admin_namespace.on_unauthorized_access, exception
|
128
|
+
end
|
129
|
+
|
130
|
+
def rescue_active_admin_access_denied(exception)
|
131
|
+
error_message = exception.message
|
132
|
+
|
133
|
+
respond_to do |format|
|
134
|
+
format.html do
|
135
|
+
flash[:error] = error_message
|
136
|
+
|
137
|
+
if request.headers.keys.include?("HTTP_REFERER")
|
138
|
+
redirect_to :back
|
139
|
+
else
|
140
|
+
controller, action = active_admin_namespace.root_to.split("#")
|
141
|
+
redirect_to :controller => controller, :action => action
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
format.csv { render :text => error_message, :status => :unauthorized}
|
146
|
+
format.json { render :json => { :error => error_message }, :status => :unauthorized}
|
147
|
+
format.xml { render :xml => "<error>#{error_message}</error>", :status => :unauthorized}
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -11,14 +11,19 @@ module ActiveAdmin
|
|
11
11
|
protected
|
12
12
|
|
13
13
|
def current_menu
|
14
|
-
active_admin_config.
|
14
|
+
active_admin_config.navigation_menu
|
15
15
|
end
|
16
16
|
|
17
17
|
# Set's @current_tab to be name of the tab to mark as current
|
18
18
|
# Get's called through a before filter
|
19
19
|
def set_current_tab
|
20
|
-
@current_tab = if active_admin_config.belongs_to? && parent?
|
21
|
-
active_admin_config.belongs_to_config.target.menu_item
|
20
|
+
@current_tab = if current_menu && active_admin_config.belongs_to? && parent?
|
21
|
+
parent_item = active_admin_config.belongs_to_config.target.menu_item
|
22
|
+
if current_menu.include? parent_item
|
23
|
+
parent_item
|
24
|
+
else
|
25
|
+
active_admin_config.menu_item
|
26
|
+
end
|
22
27
|
else
|
23
28
|
active_admin_config.menu_item
|
24
29
|
end
|
@@ -51,8 +51,8 @@ module ActiveAdmin
|
|
51
51
|
end
|
52
52
|
|
53
53
|
# Path to the batch action itself
|
54
|
-
def batch_action_path
|
55
|
-
|
54
|
+
def batch_action_path(params = {})
|
55
|
+
[route_collection_path(params), "batch_action"].join("/")
|
56
56
|
end
|
57
57
|
|
58
58
|
private
|
@@ -62,16 +62,17 @@ module ActiveAdmin
|
|
62
62
|
destroy_options = {
|
63
63
|
:priority => 100,
|
64
64
|
:confirm => proc { I18n.t('active_admin.batch_actions.delete_confirmation', :plural_model => active_admin_config.plural_resource_label.downcase) },
|
65
|
-
:if => proc{ controller.action_methods.include?('destroy') }
|
65
|
+
:if => proc{ controller.action_methods.include?('destroy') && authorized?(ActiveAdmin::Auth::DESTROY, active_admin_config.resource_class) }
|
66
66
|
}
|
67
67
|
|
68
68
|
add_batch_action :destroy, proc { I18n.t('active_admin.delete') }, destroy_options do |selected_ids|
|
69
69
|
active_admin_config.resource_class.find(selected_ids).each { |r| r.destroy }
|
70
70
|
|
71
|
-
redirect_to
|
72
|
-
|
73
|
-
|
74
|
-
|
71
|
+
redirect_to active_admin_config.route_collection_path(params),
|
72
|
+
:notice => I18n.t("active_admin.batch_actions.succesfully_destroyed",
|
73
|
+
:count => selected_ids.count,
|
74
|
+
:model => active_admin_config.resource_label.downcase,
|
75
|
+
:plural_model => active_admin_config.plural_resource_label.downcase)
|
75
76
|
end
|
76
77
|
end
|
77
78
|
|
@@ -13,7 +13,7 @@ module ActiveAdmin
|
|
13
13
|
options[:id] ||= "collection_selection"
|
14
14
|
|
15
15
|
# Open a form
|
16
|
-
text_node form_tag(
|
16
|
+
text_node form_tag(active_admin_config.batch_action_path(params), :id => options[:id])
|
17
17
|
input(:name => :batch_action, :id => :batch_action, :type => :hidden)
|
18
18
|
|
19
19
|
super(options)
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'cancan'
|
2
|
+
|
3
|
+
# Add a setting to the application to configure the ability
|
4
|
+
ActiveAdmin::Application.inheritable_setting :cancan_ability_class, "Ability"
|
5
|
+
|
6
|
+
module ActiveAdmin
|
7
|
+
|
8
|
+
class CanCanAdapter < AuthorizationAdapter
|
9
|
+
|
10
|
+
def authorized?(action, subject = nil)
|
11
|
+
cancan_ability.can?(action, subject)
|
12
|
+
end
|
13
|
+
|
14
|
+
def cancan_ability
|
15
|
+
@cancan_ability ||= initialize_cancan_ability
|
16
|
+
end
|
17
|
+
|
18
|
+
def scope_collection(collection)
|
19
|
+
collection.accessible_by(cancan_ability)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
# The setting allows the class to be stored as a string
|
25
|
+
# to enable reloading in development.
|
26
|
+
def initialize_cancan_ability
|
27
|
+
ability_class_name = resource.namespace.cancan_ability_class
|
28
|
+
|
29
|
+
if ability_class_name.is_a?(String)
|
30
|
+
ability_class = ActiveSupport::Dependencies.constantize(ability_class_name)
|
31
|
+
else
|
32
|
+
ability_class = ability_class_name
|
33
|
+
end
|
34
|
+
|
35
|
+
ability_class.new(user)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -58,11 +58,10 @@ module ActiveAdmin
|
|
58
58
|
|
59
59
|
dashboard_path = namespace.root? ? :dashboard_path : "#{namespace.name}_dashboard_path".to_sym
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
menu.add item
|
61
|
+
menu.add :id => "dashboard",
|
62
|
+
:label => proc{ I18n.t("active_admin.dashboard") },
|
63
|
+
:url => dashboard_path,
|
64
|
+
:priority => 1
|
66
65
|
end
|
67
66
|
end
|
68
67
|
end
|