wallaby-core 0.2.0 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +42 -1
- data/app/controllers/wallaby/resources_controller.rb +15 -375
- data/app/security/ability.rb +1 -1
- data/config/locales/wallaby.en.yml +92 -128
- data/config/locales/wallaby_class.en.yml +2 -23
- data/lib/adaptors/wallaby/custom/default_provider.rb +1 -1
- data/lib/adaptors/wallaby/custom/model_decorator.rb +8 -7
- data/lib/adaptors/wallaby/custom/model_finder.rb +3 -2
- data/lib/adaptors/wallaby/custom/model_pagination_provider.rb +1 -1
- data/lib/adaptors/wallaby/custom/model_service_provider.rb +1 -40
- data/lib/authorizers/wallaby/cancancan_authorization_provider.rb +30 -24
- data/lib/authorizers/wallaby/default_authorization_provider.rb +6 -13
- data/lib/authorizers/wallaby/model_authorizer.rb +43 -67
- data/lib/authorizers/wallaby/pundit_authorization_provider.rb +21 -30
- data/lib/concerns/wallaby/application_concern.rb +110 -0
- data/lib/concerns/wallaby/authentication_concern.rb +162 -0
- data/lib/concerns/wallaby/authorizable.rb +8 -8
- data/lib/concerns/wallaby/baseable.rb +91 -10
- data/lib/concerns/wallaby/decoratable.rb +3 -3
- data/lib/concerns/wallaby/engineable.rb +1 -1
- data/lib/concerns/wallaby/fieldable.rb +4 -4
- data/lib/concerns/wallaby/paginatable.rb +3 -3
- data/lib/concerns/wallaby/resourcable.rb +4 -35
- data/lib/concerns/wallaby/resources_concern.rb +434 -0
- data/lib/concerns/wallaby/servicable.rb +4 -4
- data/lib/decorators/wallaby/resource_decorator.rb +53 -80
- data/lib/errors/wallaby/class_not_found.rb +6 -0
- data/lib/errors/wallaby/model_not_found.rb +3 -1
- data/lib/errors/wallaby/resource_not_found.rb +1 -1
- data/lib/helpers/wallaby/application_helper.rb +6 -0
- data/lib/helpers/wallaby/form_helper.rb +2 -3
- data/lib/helpers/wallaby/index_helper.rb +2 -2
- data/lib/helpers/wallaby/links_helper.rb +5 -5
- data/lib/helpers/wallaby/resources_helper.rb +3 -0
- data/lib/helpers/wallaby/secure_helper.rb +3 -3
- data/lib/helpers/wallaby/styling_helper.rb +17 -3
- data/lib/interfaces/wallaby/mode.rb +5 -5
- data/lib/interfaces/wallaby/model_authorization_provider.rb +15 -13
- data/lib/interfaces/wallaby/model_decorator.rb +15 -3
- data/lib/paginators/wallaby/model_paginator.rb +14 -45
- data/lib/routes/wallaby/resources_router.rb +1 -1
- data/lib/servicers/wallaby/model_servicer.rb +32 -62
- data/lib/services/wallaby/map/mode_mapper.rb +14 -14
- data/lib/services/wallaby/map/model_class_collector.rb +2 -2
- data/lib/services/wallaby/map/model_class_mapper.rb +7 -26
- data/lib/services/wallaby/type_renderer.rb +2 -12
- data/lib/utils/wallaby/locale.rb +53 -0
- data/lib/utils/wallaby/model_utils.rb +4 -3
- data/lib/utils/wallaby/module_utils.rb +1 -1
- data/lib/utils/wallaby/utils.rb +23 -9
- data/lib/wallaby/class_array.rb +75 -0
- data/lib/wallaby/class_hash.rb +94 -0
- data/lib/wallaby/classifier.rb +29 -0
- data/lib/wallaby/configuration/mapping.rb +33 -21
- data/lib/wallaby/configuration/metadata.rb +1 -1
- data/lib/wallaby/configuration/models.rb +5 -9
- data/lib/wallaby/configuration/security.rb +6 -3
- data/lib/wallaby/configuration/sorting.rb +1 -1
- data/lib/wallaby/configuration.rb +31 -2
- data/lib/wallaby/core/version.rb +1 -1
- data/lib/wallaby/core.rb +18 -6
- data/lib/wallaby/engine.rb +9 -20
- data/lib/wallaby/logger.rb +35 -0
- data/lib/wallaby/map.rb +20 -17
- data/lib/wallaby/preloader.rb +77 -0
- metadata +16 -9
- data/app/controllers/wallaby/application_controller.rb +0 -84
- data/app/controllers/wallaby/secure_controller.rb +0 -81
- 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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
33
|
-
|
12
|
+
buttons:
|
13
|
+
save: 'Save'
|
34
14
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
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
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
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
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
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
|
-
|
98
|
-
|
99
|
-
|
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
|
-
|
102
|
-
|
75
|
+
filters:
|
76
|
+
title: 'Filters'
|
77
|
+
all: 'All'
|
103
78
|
|
104
|
-
|
105
|
-
|
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
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
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
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
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: "
|
4
|
+
missing_mode_for_model_class: "Don't know how to handle this model %{model}."
|
26
5
|
model_class_mapper:
|
27
|
-
missing_model_class: "
|
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
|
-
# Custom
|
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]
|
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
|
-
|
67
|
-
|
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 [
|
8
|
+
# @return [Wallaby::ClashArray] a list of classes
|
8
9
|
def all
|
9
10
|
Wallaby.configuration.custom_models.presence
|
10
11
|
end
|
@@ -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
|
-
#
|
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
|
7
|
-
# @param context [ActionController::Base]
|
8
|
-
# @return [true] if
|
9
|
-
# @return [false]
|
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) &&
|
14
|
+
defined?(CanCanCan) && context.respond_to?(:current_ability)
|
12
15
|
end
|
13
16
|
|
14
|
-
#
|
15
|
-
|
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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
@
|
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
|
-
#
|
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
|
-
|
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 [
|
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
|
-
|
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
|
-
#
|
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
|
-
#
|
7
|
-
# @param _context [ActionController::Base]
|
8
|
-
# @return [
|
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
|
-
|
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]
|