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.

Files changed (196) hide show
  1. data/.travis.yml +8 -5
  2. data/CHANGELOG.md +151 -0
  3. data/Gemfile +16 -16
  4. data/LICENSE +1 -1
  5. data/activeadmin.gemspec +1 -0
  6. data/app/assets/images/active_admin/index_list_icons/block_icon.svg +10 -0
  7. data/app/assets/images/active_admin/index_list_icons/blog_icon.svg +4 -0
  8. data/app/assets/images/active_admin/index_list_icons/grid_icon.svg +13 -0
  9. data/app/assets/images/active_admin/index_list_icons/table_icon.svg +3 -0
  10. data/app/assets/javascripts/active_admin/components/jquery.aa.checkbox-toggler.js.coffee +17 -44
  11. data/app/assets/javascripts/active_admin/components/jquery.aa.dropdown-menu.js.coffee +2 -4
  12. data/app/assets/javascripts/active_admin/components/jquery.aa.popover.js.coffee +0 -3
  13. data/app/assets/javascripts/active_admin/components/jquery.aa.table-checkbox-toggler.js.coffee +10 -12
  14. data/app/assets/javascripts/active_admin/pages/application.js.coffee +13 -10
  15. data/app/assets/javascripts/active_admin/pages/batch_actions.js.coffee +3 -3
  16. data/app/assets/stylesheets/active_admin/_base.css.scss +1 -0
  17. data/app/assets/stylesheets/active_admin/_header.css.scss +5 -2
  18. data/app/assets/stylesheets/active_admin/components/_dropdown_menu.scss +2 -2
  19. data/app/assets/stylesheets/active_admin/components/_index_list.scss +12 -0
  20. data/app/assets/stylesheets/active_admin/components/_popovers.css.scss +2 -2
  21. data/app/assets/stylesheets/active_admin/components/_table_tools.css.scss +2 -2
  22. data/app/assets/stylesheets/active_admin/mixins/_buttons.css.scss +4 -4
  23. data/app/assets/stylesheets/active_admin/mixins/_gradients.css.scss +5 -4
  24. data/app/assets/stylesheets/active_admin/mixins/_sections.css.scss +1 -1
  25. data/app/assets/stylesheets/active_admin/pages/_logged_out.scss +1 -1
  26. data/app/assets/stylesheets/active_admin/print.css.scss +2 -2
  27. data/app/assets/stylesheets/active_admin/structure/_title_bar.scss +1 -1
  28. data/app/views/active_admin/devise/unlocks/new.html.erb +14 -12
  29. data/docs/1-general-configuration.md +13 -0
  30. data/docs/10-custom-pages.md +40 -28
  31. data/docs/11-decorators.md +6 -4
  32. data/docs/12-arbre-components.md +1 -1
  33. data/docs/13-authorization-adapter.md +206 -0
  34. data/docs/2-resource-customization.md +129 -14
  35. data/docs/3-index-pages.md +65 -0
  36. data/docs/3-index-pages/create-an-index.md +29 -0
  37. data/docs/3-index-pages/index-as-table.md +35 -11
  38. data/docs/5-forms.md +2 -2
  39. data/features/authorization.feature +64 -0
  40. data/features/authorization_cancan.feature +52 -0
  41. data/features/belongs_to.feature +41 -5
  42. data/features/index/batch_actions.feature +27 -3
  43. data/features/index/formats.feature +27 -0
  44. data/features/index/index_as_table.feature +74 -2
  45. data/features/index/index_parameters.feature +69 -0
  46. data/features/index/index_scopes.feature +7 -11
  47. data/features/index/page_title.feature +18 -0
  48. data/features/index/switch_index_view.feature +73 -0
  49. data/features/menu.feature +27 -0
  50. data/features/registering_pages.feature +21 -0
  51. data/features/step_definitions/additional_web_steps.rb +4 -0
  52. data/features/step_definitions/batch_action_steps.rb +16 -6
  53. data/features/step_definitions/index_scope_steps.rb +3 -3
  54. data/features/step_definitions/index_views_steps.rb +3 -0
  55. data/features/step_definitions/menu_steps.rb +4 -0
  56. data/features/support/env.rb +4 -0
  57. data/features/support/paths.rb +3 -0
  58. data/lib/active_admin.rb +4 -0
  59. data/lib/active_admin/application.rb +43 -76
  60. data/lib/active_admin/authorization_adapter.rb +128 -0
  61. data/lib/active_admin/base_controller.rb +18 -1
  62. data/lib/active_admin/base_controller/authorization.rb +153 -0
  63. data/lib/active_admin/base_controller/menu.rb +8 -3
  64. data/lib/active_admin/batch_actions/resource_extension.rb +8 -7
  65. data/lib/active_admin/batch_actions/views/batch_action_form.rb +1 -1
  66. data/lib/active_admin/cancan_adapter.rb +40 -0
  67. data/lib/active_admin/dashboards.rb +4 -5
  68. data/lib/active_admin/dashboards/dashboard_controller.rb +1 -1
  69. data/lib/active_admin/devise.rb +22 -7
  70. data/lib/active_admin/dsl.rb +18 -5
  71. data/lib/active_admin/engine.rb +1 -1
  72. data/lib/active_admin/filters/dsl.rb +1 -1
  73. data/lib/active_admin/filters/forms.rb +9 -7
  74. data/lib/active_admin/filters/resource_extension.rb +20 -15
  75. data/lib/active_admin/form_builder.rb +44 -49
  76. data/lib/active_admin/helpers/optional_display.rb +4 -8
  77. data/lib/active_admin/inputs/filter_boolean_input.rb +1 -1
  78. data/lib/active_admin/inputs/filter_string_input.rb +5 -1
  79. data/lib/active_admin/locales/bg.yml +1 -1
  80. data/lib/active_admin/locales/ca.yml +1 -1
  81. data/lib/active_admin/locales/cs.yml +26 -25
  82. data/lib/active_admin/locales/da.yml +1 -1
  83. data/lib/active_admin/locales/de.yml +1 -1
  84. data/lib/active_admin/locales/en.yml +11 -1
  85. data/lib/active_admin/locales/es.yml +16 -16
  86. data/lib/active_admin/locales/fr.yml +1 -1
  87. data/lib/active_admin/locales/he.yml +1 -1
  88. data/lib/active_admin/locales/hr.yml +1 -1
  89. data/lib/active_admin/locales/hu.yml +1 -1
  90. data/lib/active_admin/locales/it.yml +1 -1
  91. data/lib/active_admin/locales/ja.yml +4 -1
  92. data/lib/active_admin/locales/ko.yml +1 -1
  93. data/lib/active_admin/locales/lt.yml +1 -1
  94. data/lib/active_admin/locales/lv.yml +12 -1
  95. data/lib/active_admin/locales/nl.yml +2 -2
  96. data/lib/active_admin/locales/no-NB.yml +22 -1
  97. data/lib/active_admin/locales/pl.yml +1 -1
  98. data/lib/active_admin/locales/pt-BR.yml +1 -1
  99. data/lib/active_admin/locales/pt-PT.yml +81 -0
  100. data/lib/active_admin/locales/ro.yml +1 -1
  101. data/lib/active_admin/locales/ru.yml +1 -1
  102. data/lib/active_admin/locales/sv-SE.yml +1 -1
  103. data/lib/active_admin/locales/tr.yml +1 -1
  104. data/lib/active_admin/locales/vi.yml +1 -1
  105. data/lib/active_admin/locales/zh-CN.yml +1 -1
  106. data/lib/active_admin/locales/zh-TW.yml +1 -1
  107. data/lib/active_admin/menu.rb +76 -38
  108. data/lib/active_admin/menu_collection.rb +96 -0
  109. data/lib/active_admin/menu_item.rb +61 -71
  110. data/lib/active_admin/namespace.rb +67 -5
  111. data/lib/active_admin/page.rb +6 -0
  112. data/lib/active_admin/page_controller.rb +13 -3
  113. data/lib/active_admin/resource.rb +11 -20
  114. data/lib/active_admin/resource/action_items.rb +3 -3
  115. data/lib/active_admin/resource/controllers.rb +0 -17
  116. data/lib/active_admin/resource/menu.rb +52 -24
  117. data/lib/active_admin/resource/naming.rb +6 -10
  118. data/lib/active_admin/resource/page_presenters.rb +57 -3
  119. data/lib/active_admin/resource/routes.rb +46 -0
  120. data/lib/active_admin/resource_controller.rb +2 -17
  121. data/lib/active_admin/resource_controller/data_access.rb +299 -0
  122. data/lib/active_admin/resource_controller/decorators.rb +2 -1
  123. data/lib/active_admin/resource_dsl.rb +12 -14
  124. data/lib/active_admin/router.rb +61 -56
  125. data/lib/active_admin/scope.rb +28 -18
  126. data/lib/active_admin/version.rb +1 -1
  127. data/lib/active_admin/view_factory.rb +0 -1
  128. data/lib/active_admin/view_helpers/breadcrumb_helper.rb +13 -19
  129. data/lib/active_admin/view_helpers/fields_for.rb +2 -0
  130. data/lib/active_admin/view_helpers/form_helper.rb +1 -1
  131. data/lib/active_admin/view_helpers/method_or_proc_helper.rb +66 -11
  132. data/lib/active_admin/views/components/attributes_table.rb +7 -4
  133. data/lib/active_admin/views/components/index_list.rb +68 -0
  134. data/lib/active_admin/views/components/paginated_collection.rb +13 -9
  135. data/lib/active_admin/views/components/scopes.rb +2 -8
  136. data/lib/active_admin/views/components/table_for.rb +1 -1
  137. data/lib/active_admin/views/footer.rb +1 -1
  138. data/lib/active_admin/views/header.rb +3 -2
  139. data/lib/active_admin/views/index_as_block.rb +4 -0
  140. data/lib/active_admin/views/index_as_blog.rb +4 -0
  141. data/lib/active_admin/views/index_as_grid.rb +4 -0
  142. data/lib/active_admin/views/index_as_table.rb +49 -7
  143. data/lib/active_admin/views/pages/index.rb +19 -4
  144. data/lib/active_admin/views/tabbed_navigation.rb +10 -54
  145. data/lib/generators/active_admin/install/install_generator.rb +5 -1
  146. data/lib/generators/active_admin/install/templates/active_admin.rb.erb +58 -0
  147. data/spec/integration/{default_namespace.rb → default_namespace_spec.rb} +0 -16
  148. data/spec/spec_helper.rb +3 -0
  149. data/spec/support/detect_rails_version.rb +10 -3
  150. data/spec/support/rails_template.rb +1 -1
  151. data/spec/support/templates/post_decorator.rb +6 -6
  152. data/spec/unit/application_spec.rb +5 -5
  153. data/spec/unit/authorization/authorization_adapter_spec.rb +61 -0
  154. data/spec/unit/authorization/controller_authorization_spec.rb +47 -0
  155. data/spec/unit/base_controller_spec.rb +0 -2
  156. data/spec/unit/batch_actions/resource_spec.rb +1 -1
  157. data/spec/unit/breadcrumbs_spec.rb +3 -3
  158. data/spec/unit/cancan_adapter_spec.rb +35 -0
  159. data/spec/unit/config_shared_examples.rb +9 -30
  160. data/spec/unit/devise_spec.rb +29 -0
  161. data/spec/unit/dsl_spec.rb +61 -0
  162. data/spec/unit/filters/filter_form_builder_spec.rb +58 -4
  163. data/spec/unit/filters/resource_spec.rb +17 -5
  164. data/spec/unit/form_builder_spec.rb +15 -0
  165. data/spec/unit/menu_collection_spec.rb +62 -0
  166. data/spec/unit/menu_item_spec.rb +51 -37
  167. data/spec/unit/menu_spec.rb +33 -29
  168. data/spec/unit/namespace/authorization_spec.rb +31 -0
  169. data/spec/unit/namespace/register_page_spec.rb +6 -28
  170. data/spec/unit/namespace/register_resource_spec.rb +11 -34
  171. data/spec/unit/namespace_spec.rb +63 -2
  172. data/spec/unit/page_controller_spec.rb +0 -3
  173. data/spec/unit/reloader_spec.rb +5 -5
  174. data/spec/unit/resource/menu_spec.rb +1 -13
  175. data/spec/unit/resource/naming_spec.rb +20 -2
  176. data/spec/unit/resource/page_presenters_spec.rb +14 -2
  177. data/spec/unit/resource_controller/{collection_spec.rb → data_access_spec.rb} +31 -13
  178. data/spec/unit/resource_controller_spec.rb +4 -5
  179. data/spec/unit/resource_spec.rb +33 -11
  180. data/spec/unit/routing_spec.rb +43 -0
  181. data/spec/unit/scope_spec.rb +13 -0
  182. data/spec/unit/view_factory_spec.rb +0 -1
  183. data/spec/unit/view_helpers/fields_for_spec.rb +4 -0
  184. data/spec/unit/view_helpers/form_helper_spec.rb +6 -2
  185. data/spec/unit/view_helpers/method_or_proc_helper_spec.rb +97 -0
  186. data/spec/unit/views/components/attributes_table_spec.rb +11 -0
  187. data/spec/unit/views/components/index_list_spec.rb +32 -0
  188. data/spec/unit/views/tabbed_navigation_spec.rb +42 -40
  189. data/tasks/test.rake +1 -1
  190. metadata +127 -40
  191. data/lib/active_admin/menu_builder.rb +0 -65
  192. data/lib/active_admin/resource_controller/callbacks.rb +0 -59
  193. data/lib/active_admin/resource_controller/collection.rb +0 -158
  194. data/lib/active_admin/views/utility_nav.rb +0 -41
  195. data/spec/unit/base_controller_shared_examples.rb +0 -25
  196. 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 'active_admin'
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.namespace.menu
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
- "batch_action_#{route_collection_path}".to_sym
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 collection_path, :notice => I18n.t("active_admin.batch_actions.succesfully_destroyed",
72
- :count => selected_ids.count,
73
- :model => active_admin_config.resource_label.downcase,
74
- :plural_model => active_admin_config.plural_resource_label.downcase)
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(send(active_admin_config.batch_action_path), :id => options[:id])
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
- item = MenuItem.new :id => "dashboard",
62
- :label => proc{ I18n.t("active_admin.dashboard") },
63
- :url => dashboard_path,
64
- :priority => 1
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