wallaby-core 0.2.11 → 0.3.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/wallaby/resources_controller.rb +20 -7
  3. data/app/security/ability.rb +1 -1
  4. data/config/routes.rb +21 -14
  5. data/lib/adaptors/wallaby/custom/default_provider.rb +1 -1
  6. data/lib/adaptors/wallaby/custom/model_decorator.rb +5 -17
  7. data/lib/adaptors/wallaby/custom/model_finder.rb +3 -3
  8. data/lib/adaptors/wallaby/custom/model_pagination_provider.rb +1 -1
  9. data/lib/adaptors/wallaby/custom/model_service_provider.rb +1 -1
  10. data/lib/authorizers/wallaby/cancancan_authorization_provider.rb +12 -5
  11. data/lib/authorizers/wallaby/default_authorization_provider.rb +10 -1
  12. data/lib/authorizers/wallaby/model_authorizer.rb +41 -16
  13. data/lib/authorizers/wallaby/pundit_authorization_provider.rb +22 -8
  14. data/lib/concerns/wallaby/application_concern.rb +41 -71
  15. data/lib/concerns/wallaby/authentication_concern.rb +29 -127
  16. data/lib/concerns/wallaby/authorizable.rb +14 -57
  17. data/lib/concerns/wallaby/baseable.rb +24 -57
  18. data/lib/concerns/wallaby/configurable.rb +416 -0
  19. data/lib/concerns/wallaby/decoratable.rb +24 -60
  20. data/lib/concerns/wallaby/engineable.rb +29 -46
  21. data/lib/concerns/wallaby/fieldable.rb +45 -56
  22. data/lib/concerns/wallaby/paginatable.rb +20 -51
  23. data/lib/concerns/wallaby/prefixable.rb +24 -4
  24. data/lib/concerns/wallaby/resourcable.rb +130 -72
  25. data/lib/concerns/wallaby/resources_concern.rb +205 -305
  26. data/lib/concerns/wallaby/servicable.rb +8 -48
  27. data/lib/concerns/wallaby/urlable.rb +69 -0
  28. data/lib/decorators/wallaby/resource_decorator.rb +72 -34
  29. data/lib/errors/wallaby/class_not_found.rb +1 -2
  30. data/lib/errors/wallaby/forbidden.rb +1 -2
  31. data/lib/errors/wallaby/general_error.rb +1 -1
  32. data/lib/errors/wallaby/invalid_error.rb +1 -2
  33. data/lib/errors/wallaby/method_removed.rb +5 -0
  34. data/lib/errors/wallaby/model_not_found.rb +1 -2
  35. data/lib/errors/wallaby/not_authenticated.rb +1 -2
  36. data/lib/errors/wallaby/not_found.rb +1 -2
  37. data/lib/errors/wallaby/not_implemented.rb +1 -2
  38. data/lib/errors/wallaby/resource_not_found.rb +1 -2
  39. data/lib/errors/wallaby/unprocessable_entity.rb +1 -2
  40. data/lib/fields/wallaby/all_fields.rb +63 -0
  41. data/lib/forms/wallaby/form_builder.rb +2 -2
  42. data/lib/generators/wallaby/engine/application_generator.rb +33 -0
  43. data/lib/generators/wallaby/engine/authorizer/USAGE +20 -0
  44. data/lib/generators/wallaby/engine/authorizer/authorizer_generator.rb +19 -0
  45. data/lib/generators/wallaby/engine/authorizer/templates/authorizer.rb.erb +35 -0
  46. data/lib/generators/wallaby/engine/controller/USAGE +20 -0
  47. data/lib/generators/wallaby/engine/controller/controller_generator.rb +23 -0
  48. data/lib/generators/wallaby/engine/controller/templates/controller.rb.erb +130 -0
  49. data/lib/generators/wallaby/engine/decorator/USAGE +20 -0
  50. data/lib/generators/wallaby/engine/decorator/decorator_generator.rb +19 -0
  51. data/lib/generators/wallaby/engine/decorator/templates/decorator.rb.erb +5 -0
  52. data/lib/generators/wallaby/engine/install/USAGE +19 -0
  53. data/lib/generators/wallaby/engine/install/install_generator.rb +91 -0
  54. data/lib/generators/wallaby/engine/install/templates/application_authorizer.rb.erb +37 -0
  55. data/lib/generators/wallaby/engine/install/templates/application_controller.rb.erb +173 -0
  56. data/lib/generators/wallaby/engine/install/templates/application_decorator.rb.erb +7 -0
  57. data/lib/generators/wallaby/engine/install/templates/application_paginator.rb.erb +27 -0
  58. data/lib/generators/wallaby/engine/install/templates/application_servicer.rb.erb +47 -0
  59. data/lib/generators/wallaby/engine/install/templates/initializer.rb.erb +16 -0
  60. data/lib/generators/wallaby/engine/paginator/USAGE +20 -0
  61. data/lib/generators/wallaby/engine/paginator/paginator_generator.rb +19 -0
  62. data/lib/generators/wallaby/engine/paginator/templates/paginator.rb.erb +25 -0
  63. data/lib/generators/wallaby/engine/servicer/USAGE +20 -0
  64. data/lib/generators/wallaby/engine/servicer/servicer_generator.rb +19 -0
  65. data/lib/generators/wallaby/engine/servicer/templates/servicer.rb.erb +45 -0
  66. data/lib/helpers/wallaby/application_helper.rb +10 -59
  67. data/lib/helpers/wallaby/base_helper.rb +11 -11
  68. data/lib/helpers/wallaby/configuration_helper.rb +36 -4
  69. data/lib/helpers/wallaby/form_helper.rb +1 -1
  70. data/lib/helpers/wallaby/index_helper.rb +19 -9
  71. data/lib/helpers/wallaby/links_helper.rb +13 -80
  72. data/lib/helpers/wallaby/resources_helper.rb +39 -7
  73. data/lib/helpers/wallaby/secure_helper.rb +20 -19
  74. data/lib/interfaces/wallaby/mode.rb +8 -8
  75. data/lib/interfaces/wallaby/model_authorization_provider.rb +23 -22
  76. data/lib/interfaces/wallaby/model_decorator.rb +36 -48
  77. data/lib/interfaces/wallaby/model_finder.rb +3 -3
  78. data/lib/interfaces/wallaby/model_pagination_provider.rb +2 -6
  79. data/lib/interfaces/wallaby/model_service_provider.rb +4 -4
  80. data/lib/paginators/wallaby/model_paginator.rb +1 -1
  81. data/lib/responders/wallaby/json_api_responder.rb +10 -5
  82. data/lib/responders/wallaby/resources_responder.rb +7 -2
  83. data/lib/routes/wallaby/engines/base_route.rb +78 -0
  84. data/lib/routes/wallaby/engines/custom_app_route.rb +92 -0
  85. data/lib/routes/wallaby/engines/engine_route.rb +77 -0
  86. data/lib/routes/wallaby/resources_router.rb +100 -45
  87. data/lib/servicers/wallaby/model_servicer.rb +13 -13
  88. data/lib/services/wallaby/authorizer_finder.rb +23 -0
  89. data/lib/services/wallaby/class_finder.rb +42 -0
  90. data/lib/services/wallaby/controller_finder.rb +29 -0
  91. data/lib/services/wallaby/decorator_finder.rb +34 -0
  92. data/lib/services/wallaby/default_models_excluder.rb +45 -0
  93. data/lib/services/wallaby/engine_name_finder.rb +14 -11
  94. data/lib/services/wallaby/engine_url_for.rb +82 -37
  95. data/lib/services/wallaby/fields_regulator.rb +34 -0
  96. data/lib/services/wallaby/map/mode_mapper.rb +4 -4
  97. data/lib/services/wallaby/map/model_class_mapper.rb +1 -1
  98. data/lib/services/wallaby/model_class_filter.rb +29 -0
  99. data/lib/services/wallaby/paginator_finder.rb +24 -0
  100. data/lib/services/wallaby/prefixes_builder.rb +49 -8
  101. data/lib/services/wallaby/servicer_finder.rb +31 -0
  102. data/lib/services/wallaby/sorting/hash_builder.rb +9 -0
  103. data/lib/services/wallaby/sorting/link_builder.rb +7 -10
  104. data/lib/services/wallaby/sorting/next_builder.rb +1 -12
  105. data/lib/services/wallaby/sorting/single_builder.rb +1 -1
  106. data/lib/support/action_dispatch/routing/mapper.rb +29 -4
  107. data/lib/utils/wallaby/field_utils.rb +9 -8
  108. data/lib/utils/wallaby/inflector.rb +94 -0
  109. data/lib/utils/wallaby/locale.rb +2 -2
  110. data/lib/utils/wallaby/module_utils.rb +3 -10
  111. data/lib/utils/wallaby/utils.rb +21 -14
  112. data/lib/wallaby/class_array.rb +18 -13
  113. data/lib/wallaby/class_hash.rb +16 -14
  114. data/lib/wallaby/classifier.rb +4 -2
  115. data/lib/wallaby/configuration/features.rb +8 -2
  116. data/lib/wallaby/configuration/mapping.rb +66 -112
  117. data/lib/wallaby/configuration/metadata.rb +15 -12
  118. data/lib/wallaby/configuration/models.rb +27 -25
  119. data/lib/wallaby/configuration/pagination.rb +15 -19
  120. data/lib/wallaby/configuration/security.rb +88 -80
  121. data/lib/wallaby/configuration/sorting.rb +15 -17
  122. data/lib/wallaby/configuration.rb +58 -23
  123. data/lib/wallaby/constants.rb +21 -13
  124. data/lib/wallaby/core/version.rb +1 -1
  125. data/lib/wallaby/core.rb +34 -10
  126. data/lib/wallaby/deprecator.rb +81 -0
  127. data/lib/wallaby/engine.rb +2 -19
  128. data/lib/wallaby/guesser.rb +45 -0
  129. data/lib/wallaby/logger.rb +35 -13
  130. data/lib/wallaby/map.rb +11 -88
  131. data/lib/wallaby/preloader.rb +9 -31
  132. metadata +120 -15
  133. data/config/locales/wallaby_class.en.yml +0 -9
  134. data/lib/concerns/wallaby/defaultable.rb +0 -38
  135. data/lib/concerns/wallaby/shared_helpers.rb +0 -22
  136. data/lib/services/wallaby/map/model_class_collector.rb +0 -49
  137. data/lib/services/wallaby/type_renderer.rb +0 -40
  138. data/lib/utils/wallaby/model_utils.rb +0 -52
  139. data/lib/utils/wallaby/test_utils.rb +0 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0f1ac3bd8eff66540e6b9f6c6c7b1f569bffe58177134b70fde36bd5b9e3df82
4
- data.tar.gz: ec78aac3194fe1dd051160d9f77695247213565260b1035d1aebd7acd84ea1a6
3
+ metadata.gz: ac0d0b6d6922e91c8efb73f107bd9565911f7484b56f4cf3790d156e2de64ff9
4
+ data.tar.gz: 1217566eccf96b6d26d4bc52e0a44674d8bf3681f0b5d8a3ca8def1f57377743
5
5
  SHA512:
6
- metadata.gz: d5b70441c58655aa2bd9aa49175f137e8680a78619c9a5236e560a912dc86995dba8597a60f54ad90ac3a80a074a4ddb8bfca346c8a73fa772edae8e63aa2fc9
7
- data.tar.gz: 459f70f2d01dba201f7873b5a7fa61c33ea3cf8ff8824ea7d33f450878ddbb01242bf71887a3200229cfe44b3c0c70190e76ea165872fe43238e424ed5a0254e
6
+ metadata.gz: 652027a296d62af1e939591fa866e2fc6fa1a37fc2717e192cf893a02a7ca51ccd862985624fb5d1bedbbc48cfd5e53a9accf491e16b30ea7b09aa2ba2ac1588
7
+ data.tar.gz: 3457d4933495eb845198f869cd74c32c6deba85c500bb5d0e07bd8159004fda5bbbc0972f008facf5d04c44136f86b2e5ae09c2daec44934c22ba385316515fc
@@ -1,16 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Wallaby
4
+ # define {ResourcesController}'s parent
4
5
  ResourcesController = Class.new configuration.base_controller
5
6
 
6
- # Resources controller, superclass for all customization controllers.
7
- # It contains CRUD template action methods
8
- # ({Wallaby::ResourcesConcern#index #index} / {Wallaby::ResourcesConcern#new #new}
9
- # / {Wallaby::ResourcesConcern#create #create} / {Wallaby::ResourcesConcern#edit #edit}
10
- # / {Wallaby::ResourcesConcern#update #update} / {Wallaby::ResourcesConcern#destroy #destroy})
11
- # that allow subclasses to override.
7
+ # Resources controller is the superclass for all customization controllers.
8
+ # It can be used for both Admin Interface and general purpose.
12
9
  #
13
- # For better practice, please create an application controller class (see example)
10
+ # It contains typical resourceful action template methods
11
+ # that can be overridden by subclasses when customizing:
12
+ #
13
+ # - {ResourcesConcern#index #index}
14
+ # - {ResourcesConcern#new #new}
15
+ # - {ResourcesConcern#create #create}
16
+ # - {ResourcesConcern#edit #edit}
17
+ # - {ResourcesConcern#update #update}
18
+ # - {ResourcesConcern#destroy #destroy}
19
+ #
20
+ # And it also contains resource related helper methods, e.g.:
21
+ #
22
+ # - {Resourcable#collection #collection}
23
+ # - {Resourcable#resource #resource}
24
+ # - {Resourcable#resource_params #resource_params}
25
+ #
26
+ # For better practice, please create an application controller class (see example)
14
27
  # to better control the functions shared between different resource controllers.
15
28
  # @example Create an application class for Admin Interface usage
16
29
  # class Admin::ApplicationController < Wallaby::ResourcesController
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # @!visibility private
4
- # Defualt ability for wallaby
4
+ # Defualt ability for {Wallaby}
5
5
  # If main app has defined `ability.rb`, this file will not be loaded/used.
6
6
  class Ability
7
7
  include ::CanCan::Ability if defined?(::CanCan)
data/config/routes.rb CHANGED
@@ -2,37 +2,44 @@
2
2
 
3
3
  Wallaby::Engine.routes.draw do
4
4
  # NOTE: For health check if needed
5
- # @see Wallaby::ApplicationController#healthy
5
+ # @see Wallaby::ApplicationConcern#healthy
6
6
  get 'status', to: 'wallaby/resources#healthy'
7
7
 
8
8
  with_options to: Wallaby::ResourcesRouter.new do |route|
9
- # @see `home` action for more
9
+ # @see Wallaby::ResourcesConcern#home
10
10
  route.root defaults: { action: 'home' }
11
11
 
12
- # To generate error pages for all supported HTTP status
12
+ # Error pages for all supported HTTP status in {Wallaby::ERRORS}
13
13
  Wallaby::ERRORS.each do |status|
14
14
  code = Rack::Utils::SYMBOL_TO_STATUS_CODE[status]
15
- route.get status, defaults: { action: status }
16
- route.get code.to_s, defaults: { action: status }
15
+ route.get status, defaults: { action: status.to_s }
16
+ route.get code.to_s, defaults: { action: status.to_s }
17
17
  end
18
18
 
19
- # To generate general CRUD resourceful routes
19
+ # resourceful routes.
20
+ #
21
+ # `:resources` param here will be converted to the model class in the controller.
22
+ # For instance, `"order::items"` will become `Order::Item` later,
23
+ # and `Order::Item` will be used by servicer/authorizer/paginator through out the whole request process.
24
+ #
25
+ # Using colons in the `:resources` param e.g. `"order::items"` instead of `"order/items"` is
26
+ # to make nested namespace possible to be handled by these dynamic routes.
20
27
  # @see Wallaby::ResourcesRouter
21
28
  scope path: ':resources' do
22
- # @see Wallaby::ResourcesController#index
29
+ # @see Wallaby::ResourcesConcern#index
23
30
  route.get '', defaults: { action: 'index' }, as: :resources
24
- # @see Wallaby::ResourcesController#new
31
+ # @see Wallaby::ResourcesConcern#new
25
32
  route.get 'new', defaults: { action: 'new' }, as: :new_resource
26
- # @see Wallaby::ResourcesController#edit
33
+ # @see Wallaby::ResourcesConcern#edit
27
34
  route.get ':id/edit', defaults: { action: 'edit' }, as: :edit_resource
28
- # @see Wallaby::ResourcesController#show
35
+ # @see Wallaby::ResourcesConcern#show
29
36
  route.get ':id', defaults: { action: 'show' }, as: :resource
30
37
 
31
- # @see Wallaby::ResourcesController#create
38
+ # @see Wallaby::ResourcesConcern#create
32
39
  route.post '', defaults: { action: 'create' }
33
- # @see Wallaby::ResourcesController#update
34
- route.match ':id', via: %i(patch put), defaults: { action: 'update' }
35
- # @see Wallaby::ResourcesController#destroy
40
+ # @see Wallaby::ResourcesConcern#update
41
+ route.match ':id', via: %i[patch put], defaults: { action: 'update' }
42
+ # @see Wallaby::ResourcesConcern#destroy
36
43
  route.delete ':id', defaults: { action: 'destroy' }
37
44
  end
38
45
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Wallaby
4
4
  class Custom
5
- # Default authorization provider for {Wallaby::Custom} mode that whitelists everything.
5
+ # Default authorization provider for {Custom} mode that allowlists everything.
6
6
  class DefaultProvider < DefaultAuthorizationProvider
7
7
  end
8
8
  end
@@ -2,9 +2,9 @@
2
2
 
3
3
  module Wallaby
4
4
  class Custom
5
- # {Wallaby::Custom} mode decorator that only pulls out all the attributes from setter/getter methods.
5
+ # {Custom} mode decorator that only pulls out all the attributes from setter/getter pair methods.
6
6
  class ModelDecorator < ::Wallaby::ModelDecorator
7
- # Assume that attributes come from the setter/getter, e.g. `name=`/`name`
7
+ # Retrieve the attributes from the setter/getter pair methods, e.g. `name=` and `name`
8
8
  # @return [ActiveSupport::HashWithIndifferentAccess] metadata
9
9
  def fields
10
10
  @fields ||=
@@ -34,21 +34,9 @@ module Wallaby
34
34
  @form_fields ||= Utils.clone fields
35
35
  end
36
36
 
37
- # @return [Array<String>] a list of field names for index page
38
- def index_field_names
39
- @index_field_names ||= reposition index_fields.keys, primary_key
40
- end
41
-
42
- # @return [Array<String>] a list of field names for show page
43
- def show_field_names
44
- @show_field_names ||= reposition show_fields.keys, primary_key
45
- end
46
-
47
- # @return [Array<String>] a list of field names for form (new/edit) page
48
- def form_field_names
49
- @form_field_names ||= form_fields.keys - [primary_key.to_s]
50
- end
51
-
37
+ # It returns an ActiveModel::Errors instance. However, this instance does not contain any errors.
38
+ # You might want to override this method in the custom resource decorator
39
+ # and get the errors out from the given **resource**.
52
40
  # @param resource [Object]
53
41
  # @return [ActiveModel::Errors]
54
42
  def form_active_errors(resource)
@@ -2,12 +2,12 @@
2
2
 
3
3
  module Wallaby
4
4
  class Custom
5
- # Model finder for {Wallaby::Custom} mode that returns the list of model set by
5
+ # Model finder for {Custom} mode that returns the list of model set by
6
6
  # {Wallaby::Configuration#custom_models}
7
7
  class ModelFinder < ::Wallaby::ModelFinder
8
- # @return [Wallaby::ClashArray] a list of classes
8
+ # @return [ClashArray] a list of classes
9
9
  def all
10
- Wallaby.configuration.custom_models.presence
10
+ Wallaby.configuration.custom_models
11
11
  end
12
12
  end
13
13
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Wallaby
4
4
  class Custom
5
- # Model pagination provider for {Wallaby::Custom} mode
5
+ # Model pagination provider for {Custom} mode
6
6
  class ModelPaginationProvider < ::Wallaby::ModelPaginationProvider
7
7
  # By default, it doesn't support pagination
8
8
  # @return [false]
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Wallaby
4
4
  class Custom
5
- # Model service provider for {Wallaby::Custom} mode
5
+ # Model service provider for {Custom} mode
6
6
  class ModelServiceProvider < ::Wallaby::ModelServiceProvider
7
7
  end
8
8
  end
@@ -14,18 +14,25 @@ module Wallaby
14
14
  defined?(CanCanCan) && context.respond_to?(:current_ability)
15
15
  end
16
16
 
17
+ # Get the information from context for {ModelAuthorizationProvider#initialize}
18
+ # @param context [ActionController::Base, ActionView::Base]
19
+ # @return [Hash] options
20
+ def self.options_from(context)
21
+ {
22
+ ability: context.try(:current_ability),
23
+ user: context.try(:wallaby_user)
24
+ }
25
+ end
26
+
17
27
  # @!attribute [w] ability
18
28
  attr_writer :ability
19
29
 
20
30
  # @!attribute [r] ability
21
- # @return [Ability] the Ability instance for {#user #user} (which is a
22
- # {Wallaby::AuthenticationConcern#wallaby_user #wallaby_user})
31
+ # @return [Ability] the Ability instance for {#user #user} or from the {#options}[:ability]
23
32
  def ability
24
33
  # NOTE: use current_ability's class to create the ability instance.
25
34
  # just in case that developer uses a different Ability class (e.g. UserAbility)
26
35
  @ability ||= options[:ability] || Ability.new(user)
27
- rescue ArgumentError, NameError
28
- context.current_ability
29
36
  end
30
37
 
31
38
  # Check user's permission for an action on given subject.
@@ -33,7 +40,7 @@ module Wallaby
33
40
  # This method will be mostly used in controller.
34
41
  # @param action [Symbol, String]
35
42
  # @param subject [Object, Class]
36
- # @raise [Wallaby::Forbidden] when user is not authorized to perform the action.
43
+ # @raise [Forbidden] when user is not authorized to perform the action.
37
44
  def authorize(action, subject)
38
45
  ability.authorize! action, subject
39
46
  rescue ::CanCan::AccessDenied
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Wallaby
4
- # Default authorization provider that whitelists everything.
4
+ # Default authorization provider that allowlists everything.
5
5
  class DefaultAuthorizationProvider < ModelAuthorizationProvider
6
6
  # It returns false so that it can be used as the last resort.
7
7
  # @param _context [ActionController::Base, ActionView::Base]
@@ -10,6 +10,15 @@ module Wallaby
10
10
  false
11
11
  end
12
12
 
13
+ # It returns empty hash.
14
+ # @param context [ActionController::Base, ActionView::Base]
15
+ # @return [Hash]
16
+ def self.options_from(context)
17
+ {
18
+ user: context.try(:wallaby_user)
19
+ }
20
+ end
21
+
13
22
  # Do nothing
14
23
  # @param _action [Symbol, String]
15
24
  # @param subject [Object, Class]
@@ -23,7 +23,7 @@ module Wallaby
23
23
  # It will be inherited from its parent classes if there isn't one for current class.
24
24
  # @return [String, Symbol]
25
25
  def provider_name
26
- @provider_name ||= superclass.try :provider_name
26
+ @provider_name || superclass.try(:provider_name)
27
27
  end
28
28
  end
29
29
 
@@ -34,12 +34,12 @@ module Wallaby
34
34
  attr_reader :model_class
35
35
 
36
36
  # @!attribute [r] provider
37
- # @return [Wallaby::ModelAuthorizationProvider] the instance that does the job
37
+ # @return [ModelAuthorizationProvider] the instance that does the job
38
38
  # @since wallaby-5.2.0
39
39
  attr_reader :provider
40
40
 
41
41
  # @!attribute [r] context
42
- # @return [ActionController::Base, ActionView::Base]
42
+ # @return [ActionController::Base, ActionView::Base, nil]
43
43
  # @since 0.2.2
44
44
  attr_reader :context
45
45
 
@@ -48,29 +48,54 @@ module Wallaby
48
48
  # @since 0.2.2
49
49
  attr_reader :options
50
50
 
51
+ # @note use this method instead of {#initialize} to create authorizer instance
52
+ # Factory method to determine which provider and what options to use.
51
53
  # @param model_class [Class]
52
54
  # @param context [ActionController::Base, ActionView::Base]
53
- # @param options [Symbol, String, nil]
54
- def initialize(model_class, context, **options)
55
+ def self.create(model_class, context)
56
+ model_class ||= self.model_class
57
+ provider_class = guess_and_set_provider_from(model_class, context)
58
+ options = provider_class.options_from(context)
59
+ new(model_class, provider: provider_class.new(options), context: context)
60
+ end
61
+
62
+ # Shortcut of {Map.authorizer_provider_map}
63
+ def self.providers_of(model_class)
64
+ Map.authorizer_provider_map(model_class)
65
+ end
66
+
67
+ # @param model_class [Class]
68
+ # @param provider_name [String]
69
+ # @param provider [Wallaby::ModelAuthorizationProvider]
70
+ # @param context [ActionController::Base, ActionView::Base]
71
+ # @param options [Hash]
72
+ def initialize(
73
+ model_class,
74
+ provider_name: nil,
75
+ provider: nil,
76
+ context: nil,
77
+ options: {}
78
+ )
55
79
  @model_class = model_class || self.class.model_class
56
- @context = context
57
80
  @options = options
58
- @provider = guess_provider_from(context)
81
+ @context = context
82
+ @provider = provider \
83
+ || self.class.providers_of(@model_class)[provider_name].new(options)
59
84
  end
60
85
 
61
- protected
62
-
63
86
  # Go through the provider list and find out the one is
64
87
  # {Wallaby::ModelAuthorizationProvider.available? .available?}
88
+ # @param model_class [Class]
65
89
  # @param context [ActionController::Base, ActionView::Base]
66
- def guess_provider_from(context)
90
+ # @return [Class] provider class
91
+ def self.guess_and_set_provider_from(model_class, context)
92
+ providers = providers_of(model_class)
67
93
  provider_class =
68
- Map.authorizer_provider_map(model_class).try do |providers|
69
- providers[options[:provider_name] || self.class.provider_name] \
70
- || providers.values.find { |klass| klass.available? context } \
71
- || providers[:default] # fallback to default
72
- end
73
- provider_class.new context, **options
94
+ providers[provider_name] \
95
+ || providers.values.find { |klass| klass.available? context } \
96
+ || providers[:default] # fallback to default
97
+ self.provider_name ||= provider_class.provider_name
98
+ provider_class
74
99
  end
75
100
  end
76
101
  end
@@ -1,9 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Wallaby
4
- # @note This authorization provider DOES NOT use the
5
- # {https://github.com/varvet/pundit#customize-pundit-user pundit_user} helper.
6
- # It uses the one from {Wallaby::AuthenticationConcern#wallaby_user #wallaby_user} instead.
7
4
  # {https://github.com/varvet/pundit Pundit} base authorization provider.
8
5
  class PunditAuthorizationProvider < ModelAuthorizationProvider
9
6
  # Detect and see if Pundit is in use.
@@ -14,12 +11,21 @@ module Wallaby
14
11
  defined?(Pundit) && context.respond_to?(:pundit_user)
15
12
  end
16
13
 
14
+ # Get the information from context for {ModelAuthorizationProvider#initialize}
15
+ # @param context [ActionController::Base, ActionView::Base]
16
+ # @return [Hash] options
17
+ def self.options_from(context)
18
+ {
19
+ user: context.try(:pundit_user) || context.try(:wallaby_user)
20
+ }
21
+ end
22
+
17
23
  # Check user's permission for an action on given subject.
18
24
  #
19
- # This method will be mostly used in controller.
25
+ # This method is mostly used in controller.
20
26
  # @param action [Symbol, String]
21
27
  # @param subject [Object, Class]
22
- # @raise [Wallaby::Forbidden] when user is not authorized to perform the action.
28
+ # @raise [Forbidden] when user is not authorized to perform the action.
23
29
  def authorize(action, subject)
24
30
  Pundit.authorize(user, subject, normalize(action)) && subject
25
31
  rescue ::Pundit::NotAuthorizedError
@@ -35,10 +41,18 @@ module Wallaby
35
41
  # @return [true] if user is allowed to perform the action
36
42
  # @return [false] otherwise
37
43
  def authorized?(action, subject)
38
- policy = Pundit.policy! user, subject
44
+ policy = Pundit.policy!(user, subject)
39
45
  policy.try normalize(action)
40
46
  end
41
47
 
48
+ # Restrict user to access certain scope/query.
49
+ # @param _action [Symbol, String]
50
+ # @param scope [Object]
51
+ # @return [Object]
52
+ def accessible_for(_action, scope)
53
+ Pundit.policy_scope!(user, scope)
54
+ end
55
+
42
56
  # Restrict user to assign certain values.
43
57
  #
44
58
  # It will do a lookup in policy's methods and pick the first available method:
@@ -49,7 +63,7 @@ module Wallaby
49
63
  # @param subject [Object]
50
64
  # @return [Hash] field value paired hash that user's allowed to assign
51
65
  def attributes_for(action, subject)
52
- policy = Pundit.policy! user, subject
66
+ policy = Pundit.policy!(user, subject)
53
67
  policy.try("attributes_for_#{action}") || policy.try('attributes_for') || {}
54
68
  end
55
69
 
@@ -63,7 +77,7 @@ module Wallaby
63
77
  # @param subject [Object]
64
78
  # @return [Array] field list that user's allowed to change.
65
79
  def permit_params(action, subject)
66
- policy = Pundit.policy! user, subject
80
+ policy = Pundit.policy!(user, subject)
67
81
  # @see https://github.com/varvet/pundit/blob/master/lib/pundit.rb#L258
68
82
  policy.try("permitted_attributes_for_#{action}") || policy.try('permitted_attributes')
69
83
  end
@@ -6,105 +6,75 @@ module Wallaby
6
6
  module ApplicationConcern
7
7
  extend ActiveSupport::Concern
8
8
 
9
- # @!parse
10
- # extend Engineable::ClassMethods
11
- # include Engineable
12
- # include SharedHelpers
9
+ include Engineable
10
+ include Urlable
11
+
12
+ included do
13
+ rescue_from NotFound, with: :not_found
14
+ rescue_from ::ActionController::ParameterMissing, with: :bad_request
15
+ rescue_from ::ActiveRecord::StatementInvalid, with: :unprocessable_entity
16
+ rescue_from NotImplemented, with: :not_implemented
17
+ rescue_from UnprocessableEntity, with: :unprocessable_entity
18
+
19
+ delegate(:configuration, to: Wallaby)
20
+ end
13
21
 
14
- # @!method healthy
15
22
  # Health check page
23
+ def healthy
24
+ render plain: 'healthy'
25
+ end
16
26
 
17
- # @!method not_found(exception = nil)
18
27
  # Not found page
19
28
  # @param exception [Exception] comes from **rescue_from**
29
+ def not_found(exception = nil)
30
+ render_error exception, __callee__
31
+ end
20
32
 
21
- # @!method bad_request(exception = nil)
22
33
  # Bad request page
23
34
  # @param exception [Exception] comes from **rescue_from**
35
+ def bad_request(exception = nil)
36
+ render_error exception, __callee__
37
+ end
24
38
 
25
- # @!method unprocessable_entity(exception = nil)
26
39
  # Unprocessable entity page
27
40
  # @param exception [Exception] comes from **rescue_from**
41
+ def unprocessable_entity(exception = nil)
42
+ render_error exception, __callee__
43
+ end
28
44
 
29
- # @!method internal_server_error(exception = nil)
30
45
  # Internal server error page
31
46
  # @param exception [Exception] comes from **rescue_from**
47
+ def internal_server_error(exception = nil)
48
+ render_error exception, __callee__
49
+ end
32
50
 
33
- # @!method not_implemented(exception = nil)
34
51
  # Not implemented
35
52
  # @param exception [Exception] comes from **rescue_from**
53
+ def not_implemented(exception = nil)
54
+ render_error exception, __callee__
55
+ end
36
56
 
37
- # @!method helpers
38
57
  # {https://api.rubyonrails.org/classes/ActionController/Helpers.html#method-i-helpers helpers}
39
58
  # exists since Rails 5.0, need to mimic this to support Rails 4.2.
40
59
  # @see https://api.rubyonrails.org/classes/ActionController/Helpers.html#method-i-helpers
41
60
  # ActionController::Helpers#helpers
42
61
  # @see https://github.com/rails/rails/blob/5-0-stable/actionpack/lib/action_controller/metal/helpers.rb#L118
62
+ def helpers
63
+ @helpers ||= defined?(super) ? super : try(:view_context)
64
+ end
65
+
66
+ protected
43
67
 
44
- # @!method render_error(exception, symbol)
45
68
  # Capture exceptions and display the error using error template.
46
69
  # @param exception [Exception]
47
70
  # @param symbol [Symbol] http status symbol
71
+ def render_error(exception, symbol)
72
+ Logger.error exception
48
73
 
49
- included do # rubocop:disable Metrics/BlockLength
50
- extend Engineable::ClassMethods
51
- include Engineable
52
- include SharedHelpers
53
-
54
- rescue_from NotFound, with: :not_found
55
- rescue_from ::ActionController::ParameterMissing, with: :bad_request
56
- rescue_from ::ActiveRecord::StatementInvalid, with: :unprocessable_entity
57
- rescue_from NotImplemented, with: :not_implemented
58
- rescue_from UnprocessableEntity, with: :unprocessable_entity
59
-
60
- delegate(*ConfigurationHelper.instance_methods(false), :url_for, to: :helpers)
61
-
62
- # (see #healthy)
63
- def healthy
64
- render plain: 'healthy'
65
- end
66
-
67
- # (see #not_found)
68
- def not_found(exception = nil)
69
- render_error exception, __callee__
70
- end
71
-
72
- # (see #bad_request)
73
- def bad_request(exception = nil)
74
- render_error exception, __callee__
75
- end
76
-
77
- # (see #unprocessable_entity)
78
- def unprocessable_entity(exception = nil)
79
- render_error exception, __callee__
80
- end
81
-
82
- # (see #internal_server_error)
83
- def internal_server_error(exception = nil)
84
- render_error exception, __callee__
85
- end
86
-
87
- # (see #not_implemented)
88
- def not_implemented(exception = nil)
89
- render_error exception, __callee__
90
- end
91
-
92
- # (see #helpers)
93
- def helpers
94
- @helpers ||= defined?(super) ? super : view_context
95
- end
96
-
97
- protected
98
-
99
- # (see #render_error)
100
- def render_error(exception, symbol)
101
- Logger.error exception
102
-
103
- @exception = exception
104
- @symbol = symbol
105
- @code = Rack::Utils::SYMBOL_TO_STATUS_CODE[symbol].to_i
106
- respond_with @exception, status: @code, template: ERROR_PATH, prefixes: _prefixes
107
- end
74
+ @exception = exception
75
+ @symbol = symbol
76
+ @code = Rack::Utils::SYMBOL_TO_STATUS_CODE[symbol].to_i
77
+ respond_with @exception, status: @code, template: ERROR_PATH, prefixes: _prefixes
108
78
  end
109
79
  end
110
80
  end