wallaby-core 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +31 -0
- data/app/controllers/wallaby/application_controller.rb +84 -0
- data/app/controllers/wallaby/resources_controller.rb +381 -0
- data/app/controllers/wallaby/secure_controller.rb +81 -0
- data/app/security/ability.rb +13 -0
- data/config/locales/wallaby.en.yml +140 -0
- data/config/locales/wallaby_class.en.yml +30 -0
- data/config/routes.rb +39 -0
- data/lib/adaptors/wallaby/custom.rb +7 -0
- data/lib/adaptors/wallaby/custom/default_provider.rb +9 -0
- data/lib/adaptors/wallaby/custom/model_decorator.rb +71 -0
- data/lib/adaptors/wallaby/custom/model_finder.rb +13 -0
- data/lib/adaptors/wallaby/custom/model_pagination_provider.rb +14 -0
- data/lib/adaptors/wallaby/custom/model_service_provider.rb +48 -0
- data/lib/authorizers/wallaby/cancancan_authorization_provider.rb +72 -0
- data/lib/authorizers/wallaby/default_authorization_provider.rb +58 -0
- data/lib/authorizers/wallaby/model_authorizer.rb +100 -0
- data/lib/authorizers/wallaby/pundit_authorization_provider.rb +89 -0
- data/lib/concerns/wallaby/authorizable.rb +103 -0
- data/lib/concerns/wallaby/baseable.rb +36 -0
- data/lib/concerns/wallaby/decoratable.rb +101 -0
- data/lib/concerns/wallaby/defaultable.rb +38 -0
- data/lib/concerns/wallaby/engineable.rb +61 -0
- data/lib/concerns/wallaby/fieldable.rb +78 -0
- data/lib/concerns/wallaby/paginatable.rb +72 -0
- data/lib/concerns/wallaby/rails_overridden_methods.rb +42 -0
- data/lib/concerns/wallaby/resourcable.rb +149 -0
- data/lib/concerns/wallaby/servicable.rb +68 -0
- data/lib/concerns/wallaby/shared_helpers.rb +22 -0
- data/lib/concerns/wallaby/themeable.rb +40 -0
- data/lib/decorators/wallaby/resource_decorator.rb +189 -0
- data/lib/errors/wallaby/cell_handling.rb +6 -0
- data/lib/errors/wallaby/forbidden.rb +6 -0
- data/lib/errors/wallaby/general_error.rb +6 -0
- data/lib/errors/wallaby/invalid_error.rb +6 -0
- data/lib/errors/wallaby/model_not_found.rb +11 -0
- data/lib/errors/wallaby/not_authenticated.rb +6 -0
- data/lib/errors/wallaby/not_found.rb +6 -0
- data/lib/errors/wallaby/not_implemented.rb +6 -0
- data/lib/errors/wallaby/resource_not_found.rb +11 -0
- data/lib/errors/wallaby/unprocessable_entity.rb +6 -0
- data/lib/forms/wallaby/form_builder.rb +60 -0
- data/lib/helpers/wallaby/application_helper.rb +79 -0
- data/lib/helpers/wallaby/base_helper.rb +65 -0
- data/lib/helpers/wallaby/configuration_helper.rb +18 -0
- data/lib/helpers/wallaby/form_helper.rb +62 -0
- data/lib/helpers/wallaby/index_helper.rb +84 -0
- data/lib/helpers/wallaby/links_helper.rb +213 -0
- data/lib/helpers/wallaby/resources_helper.rb +52 -0
- data/lib/helpers/wallaby/secure_helper.rb +54 -0
- data/lib/helpers/wallaby/styling_helper.rb +82 -0
- data/lib/interfaces/wallaby/mode.rb +72 -0
- data/lib/interfaces/wallaby/model_authorization_provider.rb +99 -0
- data/lib/interfaces/wallaby/model_decorator.rb +168 -0
- data/lib/interfaces/wallaby/model_finder.rb +12 -0
- data/lib/interfaces/wallaby/model_pagination_provider.rb +107 -0
- data/lib/interfaces/wallaby/model_service_provider.rb +84 -0
- data/lib/paginators/wallaby/model_paginator.rb +115 -0
- data/lib/paginators/wallaby/resource_paginator.rb +12 -0
- data/lib/parsers/wallaby/parser.rb +34 -0
- data/lib/renderers/wallaby/cell.rb +137 -0
- data/lib/renderers/wallaby/cell_resolver.rb +89 -0
- data/lib/renderers/wallaby/custom_lookup_context.rb +64 -0
- data/lib/renderers/wallaby/custom_partial_renderer.rb +33 -0
- data/lib/renderers/wallaby/custom_renderer.rb +16 -0
- data/lib/responders/wallaby/json_api_responder.rb +101 -0
- data/lib/responders/wallaby/resources_responder.rb +28 -0
- data/lib/routes/wallaby/resources_router.rb +72 -0
- data/lib/servicers/wallaby/model_servicer.rb +154 -0
- data/lib/services/wallaby/engine_name_finder.rb +22 -0
- data/lib/services/wallaby/engine_url_for.rb +46 -0
- data/lib/services/wallaby/link_options_normalizer.rb +19 -0
- data/lib/services/wallaby/map/mode_mapper.rb +27 -0
- data/lib/services/wallaby/map/model_class_collector.rb +49 -0
- data/lib/services/wallaby/map/model_class_mapper.rb +38 -0
- data/lib/services/wallaby/prefixes_builder.rb +66 -0
- data/lib/services/wallaby/sorting/hash_builder.rb +19 -0
- data/lib/services/wallaby/sorting/link_builder.rb +69 -0
- data/lib/services/wallaby/sorting/next_builder.rb +63 -0
- data/lib/services/wallaby/sorting/single_builder.rb +20 -0
- data/lib/services/wallaby/type_renderer.rb +50 -0
- data/lib/support/action_dispatch/routing/mapper.rb +75 -0
- data/lib/tree/wallaby/node.rb +25 -0
- data/lib/utils/wallaby/cell_utils.rb +34 -0
- data/lib/utils/wallaby/field_utils.rb +43 -0
- data/lib/utils/wallaby/filter_utils.rb +20 -0
- data/lib/utils/wallaby/model_utils.rb +51 -0
- data/lib/utils/wallaby/module_utils.rb +46 -0
- data/lib/utils/wallaby/params_utils.rb +14 -0
- data/lib/utils/wallaby/preload_utils.rb +44 -0
- data/lib/utils/wallaby/test_utils.rb +34 -0
- data/lib/utils/wallaby/utils.rb +27 -0
- data/lib/wallaby/configuration.rb +103 -0
- data/lib/wallaby/configuration/features.rb +24 -0
- data/lib/wallaby/configuration/mapping.rb +140 -0
- data/lib/wallaby/configuration/metadata.rb +23 -0
- data/lib/wallaby/configuration/models.rb +46 -0
- data/lib/wallaby/configuration/pagination.rb +30 -0
- data/lib/wallaby/configuration/security.rb +98 -0
- data/lib/wallaby/configuration/sorting.rb +28 -0
- data/lib/wallaby/constants.rb +45 -0
- data/lib/wallaby/core.rb +117 -0
- data/lib/wallaby/core/version.rb +7 -0
- data/lib/wallaby/engine.rb +43 -0
- data/lib/wallaby/map.rb +170 -0
- metadata +222 -0
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wallaby
|
4
|
+
# Cancancan base authorization provider
|
5
|
+
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.
|
10
|
+
def self.available?(context)
|
11
|
+
defined?(CanCanCan) && defined?(Ability) && context.respond_to?(:current_ability)
|
12
|
+
end
|
13
|
+
|
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
|
20
|
+
|
21
|
+
# @!attribute [r] ability
|
22
|
+
# @return [Ability]
|
23
|
+
attr_reader :ability
|
24
|
+
|
25
|
+
def initialize(ability:, user: nil)
|
26
|
+
@ability = ability
|
27
|
+
@user = user
|
28
|
+
end
|
29
|
+
|
30
|
+
# Check user's permission for an action on given subject.
|
31
|
+
# This method will be used in controller.
|
32
|
+
# @param action [Symbol, String]
|
33
|
+
# @param subject [Object, Class]
|
34
|
+
# @raise [Wallaby::Forbidden] when user is not authorized to perform the action.
|
35
|
+
def authorize(action, subject)
|
36
|
+
ability.authorize! action, subject
|
37
|
+
rescue ::CanCan::AccessDenied
|
38
|
+
Rails.logger.info I18n.t('errors.unauthorized', user: user, action: action, subject: subject)
|
39
|
+
raise Forbidden
|
40
|
+
end
|
41
|
+
|
42
|
+
# Check and see if user is allowed to perform an action on given subject.
|
43
|
+
# @param action [Symbol, String]
|
44
|
+
# @param subject [Object, Class]
|
45
|
+
# @return [Boolean]
|
46
|
+
def authorized?(action, subject)
|
47
|
+
ability.can? action, subject
|
48
|
+
end
|
49
|
+
|
50
|
+
# Restrict user to access certain scope.
|
51
|
+
# @param action [Symbol, String]
|
52
|
+
# @param scope [Object]
|
53
|
+
# @return [Object]
|
54
|
+
def accessible_for(action, scope)
|
55
|
+
ModuleUtils.try_to(scope, :accessible_by, ability, action) || scope
|
56
|
+
end
|
57
|
+
|
58
|
+
# Restrict user to assign certain values.
|
59
|
+
# @param action [Symbol, String]
|
60
|
+
# @param subject [Object]
|
61
|
+
# @return nil
|
62
|
+
delegate :attributes_for, to: :ability
|
63
|
+
|
64
|
+
# Just return nil
|
65
|
+
# @param action [Symbol, String]
|
66
|
+
# @param subject [Object]
|
67
|
+
# @return [nil]
|
68
|
+
def permit_params(action, subject)
|
69
|
+
# Do nothing
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wallaby
|
4
|
+
# Default authorization provider
|
5
|
+
class DefaultAuthorizationProvider < ModelAuthorizationProvider
|
6
|
+
# Always available.
|
7
|
+
# @param _context [ActionController::Base]
|
8
|
+
# @return [true]
|
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
|
+
{}
|
18
|
+
end
|
19
|
+
|
20
|
+
# Do nothing
|
21
|
+
# @param _action [Symbol, String]
|
22
|
+
# @param subject [Object, Class]
|
23
|
+
def authorize(_action, subject)
|
24
|
+
subject
|
25
|
+
end
|
26
|
+
|
27
|
+
# Always return true
|
28
|
+
# @param _action [Symbol, String]
|
29
|
+
# @param _subject [Object, Class]
|
30
|
+
# @return [true]
|
31
|
+
def authorized?(_action, _subject)
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
# Do nothing
|
36
|
+
# @param _action [Symbol, String]
|
37
|
+
# @param scope [Object]
|
38
|
+
def accessible_for(_action, scope)
|
39
|
+
scope
|
40
|
+
end
|
41
|
+
|
42
|
+
# Return empty attributes
|
43
|
+
# @param _action [Symbol, String]
|
44
|
+
# @param _subject [Object]
|
45
|
+
# @return [Hash] empty hash
|
46
|
+
def attributes_for(_action, _subject)
|
47
|
+
{}
|
48
|
+
end
|
49
|
+
|
50
|
+
# @note Please make sure to return nil when the authorization doesn't support this feature.
|
51
|
+
# @param _action [Symbol, String]
|
52
|
+
# @param _subject [Object]
|
53
|
+
# @return [nil]
|
54
|
+
def permit_params(_action, _subject)
|
55
|
+
# Do nothing
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wallaby
|
4
|
+
# Model Authorizer to provide authorization functions
|
5
|
+
# @since 5.2.0
|
6
|
+
class ModelAuthorizer
|
7
|
+
extend Baseable::ClassMethods
|
8
|
+
|
9
|
+
class << self
|
10
|
+
# @!attribute [w] model_class
|
11
|
+
attr_writer :model_class
|
12
|
+
|
13
|
+
# @!attribute [r] model_class
|
14
|
+
# Return associated model class, e.g. return **Product** for **ProductAuthorizer**.
|
15
|
+
#
|
16
|
+
# If Wallaby can't recognise the model class for Authorizer, it's required to be configured as below example:
|
17
|
+
# @example To configure model class
|
18
|
+
# class Admin::ProductAuthorizer < Admin::ApplicationAuthorizer
|
19
|
+
# self.model_class = Product
|
20
|
+
# end
|
21
|
+
# @example To configure model class for version below 5.2.0
|
22
|
+
# class Admin::ProductAuthorizer < Admin::ApplicationAuthorizer
|
23
|
+
# def self.model_class
|
24
|
+
# Product
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
# @return [Class] assoicated model class
|
28
|
+
# @return [nil] if current class is marked as base class
|
29
|
+
# @return [nil] if current class is the same as the value of {Wallaby::Configuration::Mapping#model_authorizer}
|
30
|
+
# @return [nil] if current class is {Wallaby::ModelAuthorizer}
|
31
|
+
# @return [nil] if assoicated model class is not found
|
32
|
+
def model_class
|
33
|
+
return unless self < ModelAuthorizer
|
34
|
+
return if base_class? || self == Wallaby.configuration.mapping.model_authorizer
|
35
|
+
|
36
|
+
@model_class ||= Map.model_class_map(name.gsub(/(^#{namespace}::)|(Authorizer$)/, EMPTY_STRING))
|
37
|
+
end
|
38
|
+
|
39
|
+
# @!attribute [w] provider_name
|
40
|
+
attr_writer :provider_name
|
41
|
+
|
42
|
+
# @!attribute [r] provider_name
|
43
|
+
# @return [String, Symbol] provider name of the authorization framework used
|
44
|
+
def provider_name
|
45
|
+
@provider_name ||= ModuleUtils.try_to superclass, :provider_name
|
46
|
+
end
|
47
|
+
|
48
|
+
# Factory method to create the model authorizer
|
49
|
+
# @param context [ActionController::Base]
|
50
|
+
# @param model_class [Class]
|
51
|
+
# @return [Wallaby::ModelAuthorizer]
|
52
|
+
def create(context, model_class)
|
53
|
+
model_class ||= self.model_class
|
54
|
+
provider_class = guess_provider_class context, model_class
|
55
|
+
new model_class, provider_class, provider_class.args_from(context)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
# @param context [ActionController::Base]
|
61
|
+
# @param model_class [Class]
|
62
|
+
# @return [Class] provider class
|
63
|
+
def guess_provider_class(context, model_class)
|
64
|
+
providers = Map.authorizer_provider_map model_class
|
65
|
+
providers[provider_name] || providers.values.find { |klass| klass.available? context }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
delegate(*ModelAuthorizationProvider.instance_methods(false), to: :@provider)
|
70
|
+
|
71
|
+
# @!attribute [r] model_class
|
72
|
+
# @return [Class]
|
73
|
+
attr_reader :model_class
|
74
|
+
|
75
|
+
# @!attribute [r] provider
|
76
|
+
# @return [Wallaby::ModelAuthorizationProvider]
|
77
|
+
# @since 5.2.0
|
78
|
+
attr_reader :provider
|
79
|
+
|
80
|
+
# @param model_class [Class]
|
81
|
+
# @param provider_name_or_class [String, Symbol, Class]
|
82
|
+
# @param options [Hash]
|
83
|
+
def initialize(model_class, provider_name_or_class, options = {})
|
84
|
+
@model_class = model_class || self.class.model_class
|
85
|
+
@provider = init_provider provider_name_or_class, options
|
86
|
+
end
|
87
|
+
|
88
|
+
protected
|
89
|
+
|
90
|
+
# Go through provider list and detect which provider is used.
|
91
|
+
# @param provider_name_or_class [String, Symbol, Class]
|
92
|
+
# @param options [Hash]
|
93
|
+
# @return [Wallaby::Authorizer]
|
94
|
+
def init_provider(provider_name_or_class, options)
|
95
|
+
providers = Map.authorizer_provider_map model_class
|
96
|
+
provider_class = provider_name_or_class.is_a?(Class) ? provider_name_or_class : providers[provider_name_or_class]
|
97
|
+
provider_class.new(**options)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wallaby
|
4
|
+
# Pundit base authorization provider
|
5
|
+
class PunditAuthorizationProvider < ModelAuthorizationProvider
|
6
|
+
# Detect and see if Pundit is in use.
|
7
|
+
# @param context [ActionController::Base]
|
8
|
+
# @return [true] if Pundit is in use.
|
9
|
+
# @return [false] if Pundit is not in use.
|
10
|
+
def self.available?(context)
|
11
|
+
defined?(Pundit) && context.respond_to?(:pundit_user)
|
12
|
+
end
|
13
|
+
|
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
|
+
{ user: context.pundit_user }
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param user [Object]
|
22
|
+
def initialize(user:)
|
23
|
+
@user = user
|
24
|
+
end
|
25
|
+
|
26
|
+
# Check user's permission for an action on given subject.
|
27
|
+
#
|
28
|
+
# This method will be used in controller.
|
29
|
+
# @param action [Symbol, String]
|
30
|
+
# @param subject [Object, Class]
|
31
|
+
# @raise [Wallaby::Forbidden] when user is not authorized to perform the action.
|
32
|
+
def authorize(action, subject)
|
33
|
+
Pundit.authorize(user, subject, normalize(action)) && subject
|
34
|
+
rescue ::Pundit::NotAuthorizedError
|
35
|
+
Rails.logger.info I18n.t('errors.unauthorized', user: user, action: action, subject: subject)
|
36
|
+
raise Forbidden
|
37
|
+
end
|
38
|
+
|
39
|
+
# Check and see if user is allowed to perform an action on given subject
|
40
|
+
# @param action [Symbol, String]
|
41
|
+
# @param subject [Object, Class]
|
42
|
+
# @return [Boolean]
|
43
|
+
def authorized?(action, subject)
|
44
|
+
policy = Pundit.policy! user, subject
|
45
|
+
ModuleUtils.try_to policy, normalize(action)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Restrict user to assign certain values.
|
49
|
+
#
|
50
|
+
# It will do a lookup in policy's methods and pick the first available method:
|
51
|
+
#
|
52
|
+
# - attributes\_for\_#\{ action \}
|
53
|
+
# - attributes\_for
|
54
|
+
# @param action [Symbol, String]
|
55
|
+
# @param subject [Object]
|
56
|
+
# @return [Hash] field value paired hash that user's allowed to assign
|
57
|
+
def attributes_for(action, subject)
|
58
|
+
policy = Pundit.policy! user, subject
|
59
|
+
value = ModuleUtils.try_to(policy, "attributes_for_#{action}") || ModuleUtils.try_to(policy, 'attributes_for')
|
60
|
+
Rails.logger.warn I18n.t('error.pundit.not_found.attributes_for', subject: subject) unless value
|
61
|
+
value || {}
|
62
|
+
end
|
63
|
+
|
64
|
+
# Restrict user for mass assignment.
|
65
|
+
#
|
66
|
+
# It will do a lookup in policy's methods and pick the first available method:
|
67
|
+
#
|
68
|
+
# - permitted\_attributes\_for\_#\{ action \}
|
69
|
+
# - permitted\_attributes
|
70
|
+
# @param action [Symbol, String]
|
71
|
+
# @param subject [Object]
|
72
|
+
# @return [Array] field list that user's allowed to change.
|
73
|
+
def permit_params(action, subject)
|
74
|
+
policy = Pundit.policy! user, subject
|
75
|
+
# @see https://github.com/varvet/pundit/blob/master/lib/pundit.rb#L258
|
76
|
+
ModuleUtils.try_to(policy, "permitted_attributes_for_#{action}") \
|
77
|
+
|| ModuleUtils.try_to(policy, 'permitted_attributes')
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
# Convert action to pundit method name
|
83
|
+
# @param action [Symbol, String]
|
84
|
+
# @return [String] e.g. `create?`
|
85
|
+
def normalize(action)
|
86
|
+
"#{action}?".tr('??', '?')
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wallaby
|
4
|
+
# Authorizer related attributes
|
5
|
+
module Authorizable
|
6
|
+
# Configurable attribute for authorizer related
|
7
|
+
module ClassMethods
|
8
|
+
# @!attribute [w] model_authorizer
|
9
|
+
def model_authorizer=(model_authorizer)
|
10
|
+
ModuleUtils.inheritance_check model_authorizer, application_authorizer
|
11
|
+
@model_authorizer = model_authorizer
|
12
|
+
end
|
13
|
+
|
14
|
+
# @!attribute [r] model_authorizer
|
15
|
+
# If Wallaby doesn't get it right, please specify the **model_authorizer**.
|
16
|
+
# @example To set model authorizer
|
17
|
+
# class Admin::ProductionsController < Admin::ApplicationController
|
18
|
+
# self.model_authorizer = ProductAuthorizer
|
19
|
+
# end
|
20
|
+
# @return [Class] model authorizer
|
21
|
+
# @raise [ArgumentError] when **model_authorizer** doesn't inherit from **application_authorizer**
|
22
|
+
# @see Wallaby::ModelAuthorizer
|
23
|
+
# @since 5.2.0
|
24
|
+
attr_reader :model_authorizer
|
25
|
+
|
26
|
+
# @!attribute [w] application_authorizer
|
27
|
+
def application_authorizer=(application_authorizer)
|
28
|
+
ModuleUtils.inheritance_check model_authorizer, application_authorizer
|
29
|
+
@application_authorizer = application_authorizer
|
30
|
+
end
|
31
|
+
|
32
|
+
# @!attribute [r] application_authorizer
|
33
|
+
# The **application_authorizer** is as the base class of {#model_authorizer}.
|
34
|
+
# @example To set application decorator:
|
35
|
+
# class Admin::ApplicationController < Wallaby::ResourcesController
|
36
|
+
# self.application_authorizer = AnotherApplicationAuthorizer
|
37
|
+
# end
|
38
|
+
# @return [Class] application decorator
|
39
|
+
# @raise [ArgumentError] when **model_authorizer** doesn't inherit from **application_authorizer**
|
40
|
+
# @see Wallaby::ModelAuthorizer
|
41
|
+
# @since 5.2.0
|
42
|
+
def application_authorizer
|
43
|
+
@application_authorizer ||= ModuleUtils.try_to superclass, :application_authorizer
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Model authorizer for current modal class.
|
48
|
+
#
|
49
|
+
# It can be configured in following class attributes:
|
50
|
+
#
|
51
|
+
# - controller configuration {Wallaby::Authorizable::ClassMethods#model_authorizer .model_authorizer}
|
52
|
+
# - a generic authorizer based on
|
53
|
+
# {Wallaby::Authorizable::ClassMethods#application_authorizer .application_authorizer}
|
54
|
+
# @return [Wallaby::ModelAuthorizer] model authorizer
|
55
|
+
# @since 5.2.0
|
56
|
+
def current_authorizer
|
57
|
+
@current_authorizer ||=
|
58
|
+
authorizer_of(current_model_class, controller_to_get(:model_authorizer)).tap do |authorizer|
|
59
|
+
Rails.logger.info %( - Current authorizer: #{authorizer.try(:class)})
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Check if user is allowed to perform action on given subject
|
64
|
+
# @param action [Symbol, String]
|
65
|
+
# @param subject [Object, Class]
|
66
|
+
# @return [true] if allowed
|
67
|
+
# @return [false] if not allowed
|
68
|
+
# @since 5.2.0
|
69
|
+
def authorized?(action, subject)
|
70
|
+
return false unless subject
|
71
|
+
|
72
|
+
klass = subject.is_a?(Class) ? subject : subject.class
|
73
|
+
authorizer_of(klass).authorized? action, subject
|
74
|
+
end
|
75
|
+
|
76
|
+
# Check if user is allowed to perform action on given subject
|
77
|
+
# @param action [Symbol, String]
|
78
|
+
# @param subject [Object, Class]
|
79
|
+
# @return [true] if not allowed
|
80
|
+
# @return [false] if allowed
|
81
|
+
# @since 5.2.0
|
82
|
+
def unauthorized?(action, subject)
|
83
|
+
!authorized? action, subject
|
84
|
+
end
|
85
|
+
|
86
|
+
# @deprecated Use {#current_authorizer} instead. It will be removed from 5.3.*
|
87
|
+
def authorizer
|
88
|
+
Utils.deprecate 'deprecation.authorizer', caller: caller
|
89
|
+
current_authorizer
|
90
|
+
end
|
91
|
+
|
92
|
+
protected
|
93
|
+
|
94
|
+
# @param model_class [Class]
|
95
|
+
# @param authorizer_class [Class, nil]
|
96
|
+
# @return [Wallaby::ModelAuthorizer] model authorizer for given model
|
97
|
+
# @since 5.2.0
|
98
|
+
def authorizer_of(model_class, authorizer_class = nil)
|
99
|
+
authorizer_class ||= Map.authorizer_map(model_class, controller_to_get(:application_authorizer))
|
100
|
+
authorizer_class.try :create, self, model_class
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wallaby
|
4
|
+
# Abstract related class methods
|
5
|
+
module Baseable
|
6
|
+
# Configurable attributes and class methods for marking a class the base class
|
7
|
+
# and skipping {Wallaby::Map Wallaby mapping}
|
8
|
+
module ClassMethods
|
9
|
+
# @return [true] if class is a base class
|
10
|
+
# @return [false] if class is not a base class
|
11
|
+
def base_class?
|
12
|
+
@base_class ||= false
|
13
|
+
end
|
14
|
+
|
15
|
+
# Mark class a base class
|
16
|
+
# @return [true]
|
17
|
+
def base_class!
|
18
|
+
@base_class = true
|
19
|
+
end
|
20
|
+
|
21
|
+
# @!attribute [w] namespace
|
22
|
+
# Used by `model_class`
|
23
|
+
# @since 5.2.0
|
24
|
+
attr_writer :namespace
|
25
|
+
|
26
|
+
# @!attribute [r] namespace
|
27
|
+
# @return [String] namespace
|
28
|
+
# @since 5.2.0
|
29
|
+
def namespace
|
30
|
+
@namespace ||=
|
31
|
+
ModuleUtils.try_to(superclass, :namespace) \
|
32
|
+
|| name.deconstantize.gsub(/Wallaby(::)?/, EMPTY_STRING).presence
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|