wallaby-core 0.1.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +60 -13
  3. data/app/controllers/wallaby/resources_controller.rb +15 -374
  4. data/app/security/ability.rb +1 -1
  5. data/config/locales/wallaby.en.yml +92 -128
  6. data/config/locales/wallaby_class.en.yml +2 -23
  7. data/lib/adaptors/wallaby/custom/default_provider.rb +1 -1
  8. data/lib/adaptors/wallaby/custom/model_decorator.rb +8 -7
  9. data/lib/adaptors/wallaby/custom/model_finder.rb +3 -2
  10. data/lib/adaptors/wallaby/custom/model_pagination_provider.rb +1 -1
  11. data/lib/adaptors/wallaby/custom/model_service_provider.rb +1 -40
  12. data/lib/authorizers/wallaby/cancancan_authorization_provider.rb +30 -24
  13. data/lib/authorizers/wallaby/default_authorization_provider.rb +6 -13
  14. data/lib/authorizers/wallaby/model_authorizer.rb +43 -67
  15. data/lib/authorizers/wallaby/pundit_authorization_provider.rb +21 -30
  16. data/lib/concerns/wallaby/application_concern.rb +110 -0
  17. data/lib/concerns/wallaby/authentication_concern.rb +162 -0
  18. data/lib/concerns/wallaby/authorizable.rb +8 -14
  19. data/lib/concerns/wallaby/baseable.rb +91 -10
  20. data/lib/concerns/wallaby/decoratable.rb +3 -3
  21. data/lib/concerns/wallaby/engineable.rb +1 -1
  22. data/lib/concerns/wallaby/fieldable.rb +4 -4
  23. data/lib/concerns/wallaby/paginatable.rb +3 -3
  24. data/lib/concerns/wallaby/prefixable.rb +21 -0
  25. data/lib/concerns/wallaby/resourcable.rb +4 -35
  26. data/lib/concerns/wallaby/resources_concern.rb +434 -0
  27. data/lib/concerns/wallaby/servicable.rb +4 -10
  28. data/lib/decorators/wallaby/resource_decorator.rb +53 -80
  29. data/lib/errors/wallaby/{cell_handling.rb → class_not_found.rb} +1 -1
  30. data/lib/errors/wallaby/model_not_found.rb +3 -1
  31. data/lib/errors/wallaby/resource_not_found.rb +1 -1
  32. data/lib/helpers/wallaby/application_helper.rb +6 -9
  33. data/lib/helpers/wallaby/form_helper.rb +2 -9
  34. data/lib/helpers/wallaby/index_helper.rb +2 -14
  35. data/lib/helpers/wallaby/links_helper.rb +5 -5
  36. data/lib/helpers/wallaby/resources_helper.rb +3 -7
  37. data/lib/helpers/wallaby/secure_helper.rb +3 -3
  38. data/lib/helpers/wallaby/styling_helper.rb +17 -3
  39. data/lib/interfaces/wallaby/mode.rb +5 -5
  40. data/lib/interfaces/wallaby/model_authorization_provider.rb +15 -13
  41. data/lib/interfaces/wallaby/model_decorator.rb +15 -3
  42. data/lib/paginators/wallaby/model_paginator.rb +14 -45
  43. data/lib/parsers/wallaby/parser.rb +49 -14
  44. data/lib/routes/wallaby/resources_router.rb +1 -1
  45. data/lib/servicers/wallaby/model_servicer.rb +32 -62
  46. data/lib/services/wallaby/map/mode_mapper.rb +14 -14
  47. data/lib/services/wallaby/map/model_class_collector.rb +2 -2
  48. data/lib/services/wallaby/map/model_class_mapper.rb +7 -26
  49. data/lib/services/wallaby/prefixes_builder.rb +15 -49
  50. data/lib/services/wallaby/type_renderer.rb +3 -13
  51. data/lib/utils/wallaby/locale.rb +53 -0
  52. data/lib/utils/wallaby/model_utils.rb +4 -3
  53. data/lib/utils/wallaby/module_utils.rb +1 -1
  54. data/lib/utils/wallaby/utils.rb +10 -15
  55. data/lib/wallaby/class_array.rb +75 -0
  56. data/lib/wallaby/class_hash.rb +94 -0
  57. data/lib/wallaby/classifier.rb +29 -0
  58. data/lib/wallaby/configuration/mapping.rb +33 -27
  59. data/lib/wallaby/configuration/metadata.rb +1 -1
  60. data/lib/wallaby/configuration/models.rb +5 -9
  61. data/lib/wallaby/configuration/security.rb +6 -3
  62. data/lib/wallaby/configuration/sorting.rb +1 -1
  63. data/lib/wallaby/configuration.rb +31 -2
  64. data/lib/wallaby/constants.rb +10 -8
  65. data/lib/wallaby/core/version.rb +1 -1
  66. data/lib/wallaby/core.rb +21 -16
  67. data/lib/wallaby/engine.rb +9 -20
  68. data/lib/wallaby/logger.rb +35 -0
  69. data/lib/wallaby/map.rb +20 -17
  70. data/lib/wallaby/preloader.rb +77 -0
  71. metadata +48 -22
  72. data/app/controllers/wallaby/application_controller.rb +0 -84
  73. data/app/controllers/wallaby/secure_controller.rb +0 -81
  74. data/lib/concerns/wallaby/rails_overridden_methods.rb +0 -42
  75. data/lib/concerns/wallaby/themeable.rb +0 -40
  76. data/lib/paginators/wallaby/resource_paginator.rb +0 -12
  77. data/lib/renderers/wallaby/cell.rb +0 -137
  78. data/lib/renderers/wallaby/cell_resolver.rb +0 -89
  79. data/lib/renderers/wallaby/custom_lookup_context.rb +0 -64
  80. data/lib/renderers/wallaby/custom_partial_renderer.rb +0 -33
  81. data/lib/renderers/wallaby/custom_renderer.rb +0 -16
  82. data/lib/utils/wallaby/cell_utils.rb +0 -34
  83. data/lib/utils/wallaby/preload_utils.rb +0 -44
@@ -1,140 +1,104 @@
1
- # Files in the config/locales directory are used for internationalization
2
- # and are automatically loaded by Rails. If you want to use locales other
3
- # than English, add the necessary files in this directory.
4
- #
5
- # To use the locales, use `I18n.t`:
6
- #
7
- # I18n.t 'hello'
8
- #
9
- # In views, this is aliased to just `t`:
10
- #
11
- # <%= t('hello') %>
12
- #
13
- # To use a different locale, set it with `I18n.locale`:
14
- #
15
- # I18n.locale = :es
16
- #
17
- # This would use the information in config/locales/es.yml.
18
- #
19
- # To learn more, please read the Rails Internationalization guide
20
- # available at http://guides.rubyonrails.org/i18n.html.
21
-
22
1
  en:
23
- labels:
24
- count: 'Count: '
25
- auto_select_hint: 'Type to select...'
26
- upload: 'Upload'
27
- empty: 'null'
28
- na: 'n/a'
29
- edit: 'Edit # %{id}'
30
- create: 'Create a %{model}'
2
+ wallaby:
3
+ labels:
4
+ count: 'Count: '
5
+ auto_select_hint: 'Type to select...'
6
+ upload: 'Upload'
7
+ empty: 'null'
8
+ na: 'n/a'
9
+ edit: 'Edit # %{id}'
10
+ create: 'Create a %{model}'
31
11
 
32
- buttons:
33
- save: 'Save'
12
+ buttons:
13
+ save: 'Save'
34
14
 
35
- links:
36
- new: 'Create %{model}'
37
- show: 'Show'
38
- edit: 'Edit'
39
- delete: 'Delete'
40
- cancel: 'Cancel'
41
- confirm:
42
- delete: 'Please confirm to delete'
43
- export: 'Export as %{ext}'
15
+ links:
16
+ new: 'Create %{model}'
17
+ show: 'Show'
18
+ edit: 'Edit'
19
+ delete: 'Delete'
20
+ cancel: 'Cancel'
21
+ confirm:
22
+ delete: 'Please confirm to delete'
23
+ export: 'Export as %{ext}'
44
24
 
45
- http_errors:
46
- report_error_html: 'And report the error <a href="https://github.com/reinteractive/wallaby/issues/new" target="_blank">here</a>.'
47
- not_implemented: 'Not implemented.'
48
- internal_server_error: 'Hope you feel better.'
49
- bad_request: 'Your request is not supported.'
50
- not_found: 'Not found.'
51
- unprocessable_entity: 'Your request cannot be processed.'
52
- unauthorized: 'You need to sign in to access this page.'
53
- forbidden: 'You need permission to access this page.'
25
+ http_errors:
26
+ report_error_html: 'And report the error <a href="https://github.com/reinteractive/wallaby/issues/new" target="_blank">here</a>.'
27
+ not_implemented: 'Not implemented.'
28
+ internal_server_error: 'Hope you feel better.'
29
+ bad_request: 'Your request is not supported.'
30
+ not_found: 'Not found.'
31
+ unprocessable_entity: 'Your request cannot be processed.'
32
+ unauthorized: 'You need to sign in to access this page.'
33
+ forbidden: 'You need permission to access this page.'
54
34
 
55
- json_errors:
56
- not_implemented: 'Not implemented.'
57
- internal_server_error: 'Internal server error.'
58
- bad_request: 'Your request is not supported.'
59
- not_found: 'Not found.'
60
- unprocessable_entity: 'Your request cannot be processed.'
61
- unauthorized: 'You need to sign in to access this page.'
62
- forbidden: 'You need permission to access this page.'
35
+ json_errors:
36
+ not_implemented: 'Not implemented.'
37
+ internal_server_error: 'Internal server error.'
38
+ bad_request: 'Your request is not supported.'
39
+ not_found: 'Not found.'
40
+ unprocessable_entity: 'Your request cannot be processed.'
41
+ unauthorized: 'You need to sign in to access this page.'
42
+ forbidden: 'You need permission to access this page.'
63
43
 
64
- errors:
65
- invalid:
66
- models: '%{models} are invalid models.'
67
- inheritance: '%{klass} does not inherit from %{parent}.'
68
- type_required: 'Type is required for %{field_name}.'
69
- not_found:
70
- collection: 'Records cannot be found. Click + button to add one.'
71
- model: 'Model %{model} cannot be found.'
72
- resource: 'Record %{resource} cannot be found.'
73
- unprocessable_entity:
74
- keyword_search: 'Unable to perform keyword search when no text fields can be used.'
75
- field_colon_search: 'Unable to perform field colon search for %{invalid_fields}.'
76
- model: 'Unable to handle model %{model}.'
77
- unauthorized: 'User %{user} is trying to perform %{action} on %{subject}'
78
- pundit:
44
+ errors:
45
+ invalid:
46
+ models: '%{models} are invalid models.'
47
+ inheritance: '%{klass} does not inherit from %{parent}.'
48
+ type_required: 'Type is required for %{field_name}.'
79
49
  not_found:
80
- scope_policy: 'Cannot find scope policy for %{scope}.'
81
- attributes_for: 'Cannot find attributes for %{subject}.'
82
- activerecord:
83
- paginatable: '%{collection} is not paginatable.'
84
- required: '%{subject} is required.'
85
- not_implemented:
86
- model_servicer: 'Custom model servicer method `%{method_name}` is not implemented'
87
-
88
- pagination:
89
- prev: 'Prev'
90
- next: 'Next'
91
- from_to: '%{from} to %{to}'
92
- of: ' of '
93
- total_count: '%{total}'
94
- pers: 'Page Size'
95
- pages: 'Page Number'
50
+ collection: 'Records cannot be found. Click + button to add one.'
51
+ model: 'Model %{model} cannot be found.'
52
+ resource: 'Record %{resource} cannot be found.'
53
+ unprocessable_entity:
54
+ keyword_search: 'Unable to perform keyword search when no text fields can be used.'
55
+ field_colon_search: 'Unable to perform field colon search for %{invalid_fields}.'
56
+ model: 'Unable to handle model %{model}.'
57
+ unauthorized: 'User %{user} is trying to perform %{action} on %{subject}'
58
+ pundit:
59
+ not_found:
60
+ scope_policy: 'Cannot find scope policy for %{scope}.'
61
+ attributes_for: 'Cannot find attributes for %{subject}.'
62
+ required: '%{subject} is required.'
63
+ not_implemented:
64
+ model_servicer: 'Custom model servicer method `%{method_name}` is not implemented'
96
65
 
97
- filters:
98
- title: 'Filters'
99
- all: 'All'
66
+ pagination:
67
+ prev: 'Prev'
68
+ next: 'Next'
69
+ from_to: '%{from} to %{to}'
70
+ of: ' of '
71
+ total_count: '%{total}'
72
+ pers: 'Page Size'
73
+ pages: 'Page Number'
100
74
 
101
- search:
102
- hint: 'Press enter to search.'
75
+ filters:
76
+ title: 'Filters'
77
+ all: 'All'
103
78
 
104
- hints:
105
- box_html: 'Format: <code>(x1, y1), (x2, y2)</code> where <i>(x1,y1)</i> and <i>(x2,y2)</i> are any two opposite corners of the box.'
106
- cidr_html: 'Example: <code>192.168.1.1/24</code> which holds an IPv4 or IPv6 network specification.'
107
- circle_html: 'Format: <code><(x, y), r></code> where <i>(x,y)</i> is the center point and <i>r</i> is the radius of the circle.'
108
- hstore_html: 'Format: <code>"Key1" => "Value1", "Key2" => "Value2"</code> is used for input and output, includes zero or more <i>key => value</i> pairs separated by commas.'
109
- inet_html: 'Example: <code>192.168.1.1/24</code> which holds an IPv4 or IPv6 network specification.'
110
- line_html: 'Format: <code>{ A, B, C }</code> which are represented by the linear equation <i>Ax + By + C = 0</i>.'
111
- lseg_html: 'Format: <code>[(x1, y1), (x2, y2)]</code> where <i>(x1,y1)</i> and <i>(x2,y2)</i> are the end points of the line segment.'
112
- ltree_html: 'Example: <code>Top.Countries.Europe.Russia</code> which is a sequence of zero or more labels separated by dots.'
113
- macaddr_html: 'Example: <code>08:00:2b:01:02:03</code> which stores MAC addresses.'
114
- path_html: 'Format: <code>((x1, y1) , ... , (xn, yn))</code> where the points are the end points of the line segments comprising the path.'
115
- polygon_html: 'Format: <code>((x1, y1) , ... , (xn, yn))</code> where the points are the end points of the line segments comprising the boundary of the polygon.'
79
+ search:
80
+ hint: 'Press enter to search.'
116
81
 
117
- deprecation:
118
- authorizer: "[DEPRECATION] `authorizer` will be removed from 5.3.*. Please use `current_authorizer` instead.\n(called from %{from})"
119
- current_model_service: "[DEPRECATION] `current_model_service` will be removed from 5.3.*. Please use `current_servicer` instead.\n(called from %{from})"
120
- find_filter_name: "[DEPRECATION] `Wallaby::Utils.find_filter_name` will be removed from 5.3.*. Please use `Wallaby::FilterUtils.filter_name_by` instead.\n(called from %{from})"
121
- form_type_partial_render: "[DEPRECATION] `form_type_partial_render` will be removed from 5.3.*. Please use `type_render` instead.\n(called from %{from})"
122
- index_params: "[DEPRECATION] `index_params` will be removed from 5.3.*.\n(called from %{from})"
123
- paginator_of: "[DEPRECATION] `paginator_of` will be removed from 5.3.*. Please use `current_paginator` instead.\n(called from %{from})"
124
- resource_paginator_inheirtance: "[DEPRECATION] `Wallaby::ResourcePaginator` will be removed from 5.3.*. Please inherit from `Wallaby::ModelPaginator` instead.\n(called from %{from})"
125
- resource_paginator=: "[DEPRECATION] `resource_paginator=` will be removed from 5.3.*. Please use `model_paginator=` instead.\n(called from %{from})"
126
- type_partial_render: "[DEPRECATION] `type_partial_render` will be removed from 5.3.*. Please use `type_render` instead.\n(called from %{from})"
82
+ hints:
83
+ box_html: 'Format: <code>(x1, y1), (x2, y2)</code> where <i>(x1,y1)</i> and <i>(x2,y2)</i> are any two opposite corners of the box.'
84
+ cidr_html: 'Example: <code>192.168.1.1/24</code> which holds an IPv4 or IPv6 network specification.'
85
+ circle_html: 'Format: <code><(x, y), r></code> where <i>(x,y)</i> is the center point and <i>r</i> is the radius of the circle.'
86
+ hstore_html: 'Format: <code>"Key1" => "Value1", "Key2" => "Value2"</code> is used for input and output, includes zero or more <i>key => value</i> pairs separated by commas.'
87
+ inet_html: 'Example: <code>192.168.1.1/24</code> which holds an IPv4 or IPv6 network specification.'
88
+ line_html: 'Format: <code>{ A, B, C }</code> which are represented by the linear equation <i>Ax + By + C = 0</i>.'
89
+ lseg_html: 'Format: <code>[(x1, y1), (x2, y2)]</code> where <i>(x1,y1)</i> and <i>(x2,y2)</i> are the end points of the line segment.'
90
+ ltree_html: 'Example: <code>Top.Countries.Europe.Russia</code> which is a sequence of zero or more labels separated by dots.'
91
+ macaddr_html: 'Example: <code>08:00:2b:01:02:03</code> which stores MAC addresses.'
92
+ path_html: 'Format: <code>((x1, y1) , ... , (xn, yn))</code> where the points are the end points of the line segments comprising the path.'
93
+ polygon_html: 'Format: <code>((x1, y1) , ... , (xn, yn))</code> where the points are the end points of the line segments comprising the boundary of the polygon.'
127
94
 
128
- fa:
129
- # map fa 5's icon name to version 4
130
- # @see this fa migration document https://fontawesome.com/how-to-use/on-the-web/setup/upgrading-from-version-4
131
- v4:
132
- clock: 'clock-o'
133
- bars: 'navicon'
134
- calendar: 'calendar-o'
135
- check-square: 'check-square-o'
136
- square: 'square-o'
137
- link: 'chain'
138
- user: 'user-o'
139
- v5:
140
- no-need: 'no-need'
95
+ deprecation:
96
+ authorizer: "[DEPRECATION] `authorizer` will be removed from 5.3.*. Please use `current_authorizer` instead.\n(called from %{from})"
97
+ current_model_service: "[DEPRECATION] `current_model_service` will be removed from 5.3.*. Please use `current_servicer` instead.\n(called from %{from})"
98
+ find_filter_name: "[DEPRECATION] `Wallaby::Utils.find_filter_name` will be removed from 5.3.*. Please use `Wallaby::FilterUtils.filter_name_by` instead.\n(called from %{from})"
99
+ form_type_partial_render: "[DEPRECATION] `form_type_partial_render` will be removed from 5.3.*. Please use `type_render` instead.\n(called from %{from})"
100
+ index_params: "[DEPRECATION] `index_params` will be removed from 5.3.*.\n(called from %{from})"
101
+ paginator_of: "[DEPRECATION] `paginator_of` will be removed from 5.3.*. Please use `current_paginator` instead.\n(called from %{from})"
102
+ resource_paginator_inheirtance: "[DEPRECATION] `Wallaby::ResourcePaginator` will be removed from 5.3.*. Please inherit from `Wallaby::ModelPaginator` instead.\n(called from %{from})"
103
+ resource_paginator=: "[DEPRECATION] `resource_paginator=` will be removed from 5.3.*. Please use `model_paginator=` instead.\n(called from %{from})"
104
+ type_partial_render: "[DEPRECATION] `type_partial_render` will be removed from 5.3.*. Please use `type_render` instead.\n(called from %{from})"
@@ -1,30 +1,9 @@
1
- # Files in the config/locales directory are used for internationalization
2
- # and are automatically loaded by Rails. If you want to use locales other
3
- # than English, add the necessary files in this directory.
4
- #
5
- # To use the locales, use `I18n.t`:
6
- #
7
- # I18n.t 'hello'
8
- #
9
- # In views, this is aliased to just `t`:
10
- #
11
- # <%= t('hello') %>
12
- #
13
- # To use a different locale, set it with `I18n.locale`:
14
- #
15
- # I18n.locale = :es
16
- #
17
- # This would use the information in config/locales/es.yml.
18
- #
19
- # To learn more, please read the Rails Internationalization guide
20
- # available at http://guides.rubyonrails.org/i18n.html.
21
-
22
1
  en:
23
2
  wallaby:
24
3
  map:
25
- missing_mode_for_model_class: "[WALLABY] Don't know how to handle this model %{model}."
4
+ missing_mode_for_model_class: "Don't know how to handle this model %{model}."
26
5
  model_class_mapper:
27
- missing_model_class: "[WALLABY] Please define self.model_class for %{model} or set it as global.\n @see Wallaby.configuration.mapping"
6
+ missing_model_class: "Please define self.model_class for %{model} or set it as global.\n @see Wallaby.configuration.mapping"
28
7
 
29
8
  mode:
30
9
  inherit_required: '%{klass} must inherit from %{parent}.'
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Wallaby
4
4
  class Custom
5
- # Default provider for custom mode
5
+ # Default authorization provider for {Wallaby::Custom} mode that whitelists everything.
6
6
  class DefaultProvider < DefaultAuthorizationProvider
7
7
  end
8
8
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Wallaby
4
4
  class Custom
5
- # Custom modal decorator
5
+ # {Wallaby::Custom} mode decorator that only pulls out all the attributes from setter/getter methods.
6
6
  class ModelDecorator < ::Wallaby::ModelDecorator
7
7
  # Assume that attributes come from the setter/getter, e.g. `name=`/`name`
8
8
  # @return [ActiveSupport::HashWithIndifferentAccess] metadata
@@ -11,8 +11,7 @@ module Wallaby
11
11
  ::ActiveSupport::HashWithIndifferentAccess.new.tap do |hash|
12
12
  methods = model_class.public_instance_methods(false).map(&:to_s)
13
13
  methods
14
- .grep(/[^=]$/)
15
- .select { |method_id| methods.include? "#{method_id}=" }
14
+ .grep(/[^=]$/).select { |method_id| methods.include? "#{method_id}=" }
16
15
  .each { |attribute| hash[attribute] = { label: attribute.humanize, type: 'string' } }
17
16
  end.freeze
18
17
  end
@@ -50,21 +49,23 @@ module Wallaby
50
49
  @form_field_names ||= form_fields.keys - [primary_key.to_s]
51
50
  end
52
51
 
52
+ # @param resource [Object]
53
53
  # @return [ActiveModel::Errors]
54
54
  def form_active_errors(resource)
55
55
  @form_active_errors ||= ActiveModel::Errors.new resource
56
56
  end
57
57
 
58
- # @return [String, Symbole] primary key name
58
+ # @return [String, Symbole] default to `:id`
59
59
  def primary_key
60
60
  @primary_key ||= :id
61
61
  end
62
62
 
63
63
  # @param resource [Object]
64
- # @return [String]
64
+ # @return [String, nil]
65
65
  def guess_title(resource)
66
- field_name = FieldUtils.first_field_by({ name: /name|title|subject/ }, fields)
67
- ModuleUtils.try_to resource, field_name
66
+ FieldUtils
67
+ .first_field_by({ name: /name|title|subject/ }, fields)
68
+ .try { |field_name| resource.try field_name }
68
69
  end
69
70
  end
70
71
  end
@@ -2,9 +2,10 @@
2
2
 
3
3
  module Wallaby
4
4
  class Custom
5
- # Model finder
5
+ # Model finder for {Wallaby::Custom} mode that returns the list of model set by
6
+ # {Wallaby::Configuration#custom_models}
6
7
  class ModelFinder < ::Wallaby::ModelFinder
7
- # @return [Array<Class>] a list of classes
8
+ # @return [Wallaby::ClashArray] a list of classes
8
9
  def all
9
10
  Wallaby.configuration.custom_models.presence
10
11
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Wallaby
4
4
  class Custom
5
- # Model pagination provider
5
+ # Model pagination provider for {Wallaby::Custom} mode
6
6
  class ModelPaginationProvider < ::Wallaby::ModelPaginationProvider
7
7
  # By default, it doesn't support pagination
8
8
  # @return [false]
@@ -2,47 +2,8 @@
2
2
 
3
3
  module Wallaby
4
4
  class Custom
5
- # Model service provider
5
+ # Model service provider for {Wallaby::Custom} mode
6
6
  class ModelServiceProvider < ::Wallaby::ModelServiceProvider
7
- # @raise [Wallaby::NotImplemented]
8
- def permit(*)
9
- raise Wallaby::NotImplemented, I18n.t('errors.not_implemented.model_servicer', method_name: __callee__)
10
- end
11
-
12
- # @raise [Wallaby::NotImplemented]
13
- def collection(*)
14
- raise Wallaby::NotImplemented, I18n.t('errors.not_implemented.model_servicer', method_name: __callee__)
15
- end
16
-
17
- # @raise [Wallaby::NotImplemented]
18
- def paginate(*)
19
- raise Wallaby::NotImplemented, I18n.t('errors.not_implemented.model_servicer', method_name: __callee__)
20
- end
21
-
22
- # @raise [Wallaby::NotImplemented]
23
- def new(*)
24
- raise Wallaby::NotImplemented, I18n.t('errors.not_implemented.model_servicer', method_name: __callee__)
25
- end
26
-
27
- # @raise [Wallaby::NotImplemented]
28
- def find(*)
29
- raise Wallaby::NotImplemented, I18n.t('errors.not_implemented.model_servicer', method_name: __callee__)
30
- end
31
-
32
- # @raise [Wallaby::NotImplemented]
33
- def create(*)
34
- raise Wallaby::NotImplemented, I18n.t('errors.not_implemented.model_servicer', method_name: __callee__)
35
- end
36
-
37
- # @raise [Wallaby::NotImplemented]
38
- def update(*)
39
- raise Wallaby::NotImplemented, I18n.t('errors.not_implemented.model_servicer', method_name: __callee__)
40
- end
41
-
42
- # @raise [Wallaby::NotImplemented]
43
- def destroy(*)
44
- raise Wallaby::NotImplemented, I18n.t('errors.not_implemented.model_servicer', method_name: __callee__)
45
- end
46
7
  end
47
8
  end
48
9
  end
@@ -1,67 +1,73 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Wallaby
4
- # Cancancan base authorization provider
4
+ # @note This authorization provider DOES NOT use the existing
5
+ # {https://www.rubydoc.info/github/CanCanCommunity/cancancan/CanCan%2FControllerAdditions:current_ability
6
+ # current_ability} helper. It has its own version of {#ability} instance.
7
+ # {https://github.com/CanCanCommunity/cancancan CanCanCan} base authorization provider.
5
8
  class CancancanAuthorizationProvider < ModelAuthorizationProvider
6
- # Detect and see if Cancancan is in use.
7
- # @param context [ActionController::Base]
8
- # @return [true] if Cancancan is in use.
9
- # @return [false] if Cancancan is not in use.
9
+ # Detect and see if CanCanCan is in use.
10
+ # @param context [ActionController::Base, ActionView::Base]
11
+ # @return [true] if CanCanCan is in use
12
+ # @return [false] otherwise.
10
13
  def self.available?(context)
11
- defined?(CanCanCan) && defined?(Ability) && context.respond_to?(:current_ability)
14
+ defined?(CanCanCan) && context.respond_to?(:current_ability)
12
15
  end
13
16
 
14
- # This will pull out the args required for contruction from context
15
- # @param context [ActionController::Base]
16
- # @return [Hash] args for initialize
17
- def self.args_from(context)
18
- { ability: context.current_ability, user: ModuleUtils.try_to(context, :current_user) }
19
- end
17
+ # @!attribute [w] ability
18
+ attr_writer :ability
20
19
 
21
20
  # @!attribute [r] ability
22
- # @return [Ability]
23
- attr_reader :ability
24
-
25
- def initialize(ability:, user: nil)
26
- @ability = ability
27
- @user = user
21
+ # @return [Ability] the Ability instance for {#user #user} (which is a
22
+ # {Wallaby::AuthenticationConcern#wallaby_user #wallaby_user})
23
+ def ability
24
+ # NOTE: use current_ability's class to create the ability instance.
25
+ # just in case that developer uses a different Ability class (e.g. UserAbility)
26
+ @ability ||= options[:ability] || Ability.new(user)
27
+ rescue ArgumentError, NameError
28
+ context.current_ability
28
29
  end
29
30
 
30
31
  # Check user's permission for an action on given subject.
31
- # This method will be used in controller.
32
+ #
33
+ # This method will be mostly used in controller.
32
34
  # @param action [Symbol, String]
33
35
  # @param subject [Object, Class]
34
36
  # @raise [Wallaby::Forbidden] when user is not authorized to perform the action.
35
37
  def authorize(action, subject)
36
38
  ability.authorize! action, subject
37
39
  rescue ::CanCan::AccessDenied
38
- Rails.logger.info I18n.t('errors.unauthorized', user: user, action: action, subject: subject)
40
+ Logger.error <<~MESSAGE
41
+ #{Utils.inspect user} is forbidden to perform #{action} on #{Utils.inspect subject}
42
+ MESSAGE
39
43
  raise Forbidden
40
44
  end
41
45
 
42
46
  # Check and see if user is allowed to perform an action on given subject.
43
47
  # @param action [Symbol, String]
44
48
  # @param subject [Object, Class]
45
- # @return [Boolean]
49
+ # @return [true] if user is allowed to perform the action
50
+ # @return [false] otherwise
46
51
  def authorized?(action, subject)
47
52
  ability.can? action, subject
48
53
  end
49
54
 
50
- # Restrict user to access certain scope.
55
+ # Restrict user to access certain scope/query.
51
56
  # @param action [Symbol, String]
52
57
  # @param scope [Object]
53
58
  # @return [Object]
54
59
  def accessible_for(action, scope)
55
- ModuleUtils.try_to(scope, :accessible_by, ability, action) || scope
60
+ scope.try(:accessible_by, ability, action) || scope
56
61
  end
57
62
 
63
+ # @!method attributes_for(action, subject)
58
64
  # Restrict user to assign certain values.
59
65
  # @param action [Symbol, String]
60
66
  # @param subject [Object]
61
67
  # @return nil
62
68
  delegate :attributes_for, to: :ability
63
69
 
64
- # Just return nil
70
+ # Simply return nil as CanCanCan doesn't provide such a feature.
65
71
  # @param action [Symbol, String]
66
72
  # @param subject [Object]
67
73
  # @return [nil]
@@ -1,20 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Wallaby
4
- # Default authorization provider
4
+ # Default authorization provider that whitelists everything.
5
5
  class DefaultAuthorizationProvider < ModelAuthorizationProvider
6
- # Always available.
7
- # @param _context [ActionController::Base]
8
- # @return [true]
6
+ # It returns false so that it can be used as the last resort.
7
+ # @param _context [ActionController::Base, ActionView::Base]
8
+ # @return [false]
9
9
  def self.available?(_context)
10
- true
11
- end
12
-
13
- # This will pull out the args required for contruction from context
14
- # @param _context [ActionController::Base]
15
- # @return [Hash] args for initialize
16
- def self.args_from(_context)
17
- {}
10
+ false
18
11
  end
19
12
 
20
13
  # Do nothing
@@ -47,7 +40,7 @@ module Wallaby
47
40
  {}
48
41
  end
49
42
 
50
- # @note Please make sure to return nil when the authorization doesn't support this feature.
43
+ # @note Please make sure to return nil when the authorization provider doesn't support this feature.
51
44
  # @param _action [Symbol, String]
52
45
  # @param _subject [Object]
53
46
  # @return [nil]