wallaby-core 0.2.0 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,68 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Wallaby
|
4
|
-
#
|
5
|
-
#
|
4
|
+
# This is the base authorizer class to provider authorization for given/associated model.
|
5
|
+
#
|
6
|
+
# For best practice, please create an application authorizer class (see example)
|
7
|
+
# to better control the functions shared between different model authorizers.
|
8
|
+
# @example Create an application class for Admin Interface usage
|
9
|
+
# class Admin::ApplicationAuthorizer < Wallaby::ModelAuthorizer
|
10
|
+
# base_class!
|
11
|
+
# end
|
12
|
+
# @since wallaby-5.2.0
|
6
13
|
class ModelAuthorizer
|
7
14
|
extend Baseable::ClassMethods
|
15
|
+
base_class!
|
8
16
|
|
9
17
|
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
18
|
# @!attribute [w] provider_name
|
40
19
|
attr_writer :provider_name
|
41
20
|
|
42
21
|
# @!attribute [r] provider_name
|
43
|
-
#
|
22
|
+
# Provider name of the authorization framework used.
|
23
|
+
# It will be inherited from its parent classes if there isn't one for current class.
|
24
|
+
# @return [String, Symbol]
|
44
25
|
def provider_name
|
45
|
-
@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 }
|
26
|
+
@provider_name ||= superclass.try :provider_name
|
66
27
|
end
|
67
28
|
end
|
68
29
|
|
@@ -73,28 +34,43 @@ module Wallaby
|
|
73
34
|
attr_reader :model_class
|
74
35
|
|
75
36
|
# @!attribute [r] provider
|
76
|
-
# @return [Wallaby::ModelAuthorizationProvider]
|
77
|
-
# @since 5.2.0
|
37
|
+
# @return [Wallaby::ModelAuthorizationProvider] the instance that does the job
|
38
|
+
# @since wallaby-5.2.0
|
78
39
|
attr_reader :provider
|
79
40
|
|
41
|
+
# @!attribute [r] context
|
42
|
+
# @return [ActionController::Base, ActionView::Base]
|
43
|
+
# @since 0.2.2
|
44
|
+
attr_reader :context
|
45
|
+
|
46
|
+
# @!attribute [r] options
|
47
|
+
# @return [Hash]
|
48
|
+
# @since 0.2.2
|
49
|
+
attr_reader :options
|
50
|
+
|
80
51
|
# @param model_class [Class]
|
81
|
-
# @param
|
82
|
-
# @param options [
|
83
|
-
def initialize(model_class,
|
52
|
+
# @param context [ActionController::Base, ActionView::Base]
|
53
|
+
# @param options [Symbol, String, nil]
|
54
|
+
def initialize(model_class, context, **options)
|
84
55
|
@model_class = model_class || self.class.model_class
|
85
|
-
@
|
56
|
+
@context = context
|
57
|
+
@options = options
|
58
|
+
@provider = guess_provider_from(context)
|
86
59
|
end
|
87
60
|
|
88
61
|
protected
|
89
62
|
|
90
|
-
# Go through provider list and
|
91
|
-
#
|
92
|
-
# @param
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
63
|
+
# Go through the provider list and find out the one is
|
64
|
+
# {Wallaby::ModelAuthorizationProvider.available? .available?}
|
65
|
+
# @param context [ActionController::Base, ActionView::Base]
|
66
|
+
def guess_provider_from(context)
|
67
|
+
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
|
98
74
|
end
|
99
75
|
end
|
100
76
|
end
|
@@ -1,83 +1,74 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Wallaby
|
4
|
-
#
|
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
|
+
# {https://github.com/varvet/pundit Pundit} base authorization provider.
|
5
8
|
class PunditAuthorizationProvider < ModelAuthorizationProvider
|
6
9
|
# Detect and see if Pundit is in use.
|
7
|
-
# @param context [ActionController::Base]
|
8
|
-
# @return [true] if Pundit is in use
|
9
|
-
# @return [false]
|
10
|
+
# @param context [ActionController::Base, ActionView::Base]
|
11
|
+
# @return [true] if Pundit is in use
|
12
|
+
# @return [false] otherwise
|
10
13
|
def self.available?(context)
|
11
14
|
defined?(Pundit) && context.respond_to?(:pundit_user)
|
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
|
-
{ user: context.pundit_user }
|
19
|
-
end
|
20
|
-
|
21
|
-
# @param user [Object]
|
22
|
-
def initialize(user:)
|
23
|
-
@user = user
|
24
|
-
end
|
25
|
-
|
26
17
|
# Check user's permission for an action on given subject.
|
27
18
|
#
|
28
|
-
# This method will be used in controller.
|
19
|
+
# This method will be mostly used in controller.
|
29
20
|
# @param action [Symbol, String]
|
30
21
|
# @param subject [Object, Class]
|
31
22
|
# @raise [Wallaby::Forbidden] when user is not authorized to perform the action.
|
32
23
|
def authorize(action, subject)
|
33
24
|
Pundit.authorize(user, subject, normalize(action)) && subject
|
34
25
|
rescue ::Pundit::NotAuthorizedError
|
35
|
-
|
26
|
+
Logger.error <<~MESSAGE
|
27
|
+
#{Utils.inspect user} is forbidden to perform #{action} on #{Utils.inspect subject}
|
28
|
+
MESSAGE
|
36
29
|
raise Forbidden
|
37
30
|
end
|
38
31
|
|
39
32
|
# Check and see if user is allowed to perform an action on given subject
|
40
33
|
# @param action [Symbol, String]
|
41
34
|
# @param subject [Object, Class]
|
42
|
-
# @return [
|
35
|
+
# @return [true] if user is allowed to perform the action
|
36
|
+
# @return [false] otherwise
|
43
37
|
def authorized?(action, subject)
|
44
38
|
policy = Pundit.policy! user, subject
|
45
|
-
|
39
|
+
policy.try normalize(action)
|
46
40
|
end
|
47
41
|
|
48
42
|
# Restrict user to assign certain values.
|
49
43
|
#
|
50
44
|
# It will do a lookup in policy's methods and pick the first available method:
|
51
45
|
#
|
52
|
-
# -
|
53
|
-
# -
|
46
|
+
# - `attributes_for_#{action}`
|
47
|
+
# - `attributes_for`
|
54
48
|
# @param action [Symbol, String]
|
55
49
|
# @param subject [Object]
|
56
50
|
# @return [Hash] field value paired hash that user's allowed to assign
|
57
51
|
def attributes_for(action, subject)
|
58
52
|
policy = Pundit.policy! user, subject
|
59
|
-
|
60
|
-
Rails.logger.warn I18n.t('error.pundit.not_found.attributes_for', subject: subject) unless value
|
61
|
-
value || {}
|
53
|
+
policy.try("attributes_for_#{action}") || policy.try('attributes_for') || {}
|
62
54
|
end
|
63
55
|
|
64
56
|
# Restrict user for mass assignment.
|
65
57
|
#
|
66
58
|
# It will do a lookup in policy's methods and pick the first available method:
|
67
59
|
#
|
68
|
-
# -
|
69
|
-
# -
|
60
|
+
# - `permitted_attributes_for_#{ action }`
|
61
|
+
# - `permitted_attributes`
|
70
62
|
# @param action [Symbol, String]
|
71
63
|
# @param subject [Object]
|
72
64
|
# @return [Array] field list that user's allowed to change.
|
73
65
|
def permit_params(action, subject)
|
74
66
|
policy = Pundit.policy! user, subject
|
75
67
|
# @see https://github.com/varvet/pundit/blob/master/lib/pundit.rb#L258
|
76
|
-
|
77
|
-
|| ModuleUtils.try_to(policy, 'permitted_attributes')
|
68
|
+
policy.try("permitted_attributes_for_#{action}") || policy.try('permitted_attributes')
|
78
69
|
end
|
79
70
|
|
80
|
-
|
71
|
+
protected
|
81
72
|
|
82
73
|
# Convert action to pundit method name
|
83
74
|
# @param action [Symbol, String]
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wallaby
|
4
|
+
# Here, it provides the most basic functions e.g. error handling for common 4xx HTTP status, helpers method,
|
5
|
+
# and URL handling.
|
6
|
+
module ApplicationConcern
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
# @!parse
|
10
|
+
# extend Engineable::ClassMethods
|
11
|
+
# include Engineable
|
12
|
+
# include SharedHelpers
|
13
|
+
|
14
|
+
# @!method healthy
|
15
|
+
# Health check page
|
16
|
+
|
17
|
+
# @!method not_found(exception = nil)
|
18
|
+
# Not found page
|
19
|
+
# @param exception [Exception] comes from **rescue_from**
|
20
|
+
|
21
|
+
# @!method bad_request(exception = nil)
|
22
|
+
# Bad request page
|
23
|
+
# @param exception [Exception] comes from **rescue_from**
|
24
|
+
|
25
|
+
# @!method unprocessable_entity(exception = nil)
|
26
|
+
# Unprocessable entity page
|
27
|
+
# @param exception [Exception] comes from **rescue_from**
|
28
|
+
|
29
|
+
# @!method internal_server_error(exception = nil)
|
30
|
+
# Internal server error page
|
31
|
+
# @param exception [Exception] comes from **rescue_from**
|
32
|
+
|
33
|
+
# @!method not_implemented(exception = nil)
|
34
|
+
# Not implemented
|
35
|
+
# @param exception [Exception] comes from **rescue_from**
|
36
|
+
|
37
|
+
# @!method helpers
|
38
|
+
# {https://api.rubyonrails.org/classes/ActionController/Helpers.html#method-i-helpers helpers}
|
39
|
+
# exists since Rails 5.0, need to mimic this to support Rails 4.2.
|
40
|
+
# @see https://api.rubyonrails.org/classes/ActionController/Helpers.html#method-i-helpers
|
41
|
+
# ActionController::Helpers#helpers
|
42
|
+
# @see https://github.com/rails/rails/blob/5-0-stable/actionpack/lib/action_controller/metal/helpers.rb#L118
|
43
|
+
|
44
|
+
# @!method render_error(exception, symbol)
|
45
|
+
# Capture exceptions and display the error using error template.
|
46
|
+
# @param exception [Exception]
|
47
|
+
# @param symbol [Symbol] http status symbol
|
48
|
+
|
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
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wallaby
|
4
|
+
# Authentication related functions
|
5
|
+
module AuthenticationConcern
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
# @deprecated Use {#wallaby_user} instead
|
9
|
+
# @!method current_user
|
10
|
+
# @note This is a template method that can be overridden by subclasses
|
11
|
+
# This {current_user} method will try to looking up the actual implementation from the following
|
12
|
+
# places from high precedence to low:
|
13
|
+
#
|
14
|
+
# - {Wallaby::Configuration::Security#current_user}
|
15
|
+
# - `super`
|
16
|
+
# - do nothing
|
17
|
+
#
|
18
|
+
# It can be replaced completely in subclasses:
|
19
|
+
#
|
20
|
+
# def current_user
|
21
|
+
# # NOTE: please ensure `@current_user` is assigned, for instance:
|
22
|
+
# @current_user ||= User.new params.slice(:email)
|
23
|
+
# end
|
24
|
+
# @return [Object] a user object
|
25
|
+
|
26
|
+
# @deprecated Use {#authenticate_wallaby_user!} instead
|
27
|
+
# @!method authenticate_user!
|
28
|
+
# @note This is a template method that can be overridden by subclasses
|
29
|
+
# This {authenticate_user!} method will try to looking up the actual implementation from the following
|
30
|
+
# places from high precedence to low:
|
31
|
+
#
|
32
|
+
# - {Wallaby::Configuration::Security#authenticate}
|
33
|
+
# - `super`
|
34
|
+
# - do nothing
|
35
|
+
#
|
36
|
+
# It can be replaced completely in subclasses:
|
37
|
+
#
|
38
|
+
# def authenticate_user!
|
39
|
+
# authenticate_or_request_with_http_basic do |username, password|
|
40
|
+
# username == 'too_simple' && password == 'too_naive'
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
# @return [true] when user is authenticated successfully
|
44
|
+
# @raise [Wallaby::NotAuthenticated] when user fails to authenticate
|
45
|
+
|
46
|
+
# @!method wallaby_user
|
47
|
+
# @note This is a template method that can be overridden by subclasses
|
48
|
+
# This method will try to call {#current_user} from superclass.
|
49
|
+
# @example It can be overridden in subclasses:
|
50
|
+
# def wallaby_user
|
51
|
+
# # NOTE: better to assign user to `@wallaby_user` for better performance:
|
52
|
+
# @wallaby_user ||= User.new params.slice(:email)
|
53
|
+
# end
|
54
|
+
# @return [Object] a user object
|
55
|
+
|
56
|
+
# @!method pundit_user
|
57
|
+
# @note This is a template method that can be overridden by subclasses
|
58
|
+
# This overridden method of {#original_pundit_user} will try to call {#wallaby_user} instead of {#current_user}.
|
59
|
+
# @example It can be overridden in subclasses:
|
60
|
+
# def pundit_user
|
61
|
+
# @pundit_user ||= User.new params.slice(:email)
|
62
|
+
# end
|
63
|
+
# @return [Object] a user object
|
64
|
+
|
65
|
+
# @!parse alias :override_pundit_user :pundit_user
|
66
|
+
|
67
|
+
# @!method original_pundit_user
|
68
|
+
# This method is the original version of {#pundit_user} which calls the {#current_user}.
|
69
|
+
# @return [Object] a user object
|
70
|
+
|
71
|
+
# @!method authenticate_wallaby_user!
|
72
|
+
# @note This is a template method that can be overridden by subclasses
|
73
|
+
# This method will try to call {#authenticate_user!} from superclass.
|
74
|
+
# And it will be run as the first callback before an action.
|
75
|
+
# @example It can be overridden in subclasses:
|
76
|
+
# def authenticate_wallaby_user!
|
77
|
+
# authenticate_or_request_with_http_basic do |username, password|
|
78
|
+
# username == 'too_simple' && password == 'too_naive'
|
79
|
+
# end
|
80
|
+
# end
|
81
|
+
# @return [true] when user is authenticated successfully
|
82
|
+
# @raise [Wallaby::NotAuthenticated] when user fails to authenticate
|
83
|
+
|
84
|
+
# @!method unauthorized(exception = nil)
|
85
|
+
# Unauthorized page.
|
86
|
+
# @param exception [Exception] comes from **rescue_from**
|
87
|
+
|
88
|
+
# @!method forbidden(exception = nil)
|
89
|
+
# Forbidden page.
|
90
|
+
# @param exception [Exception] comes from **rescue_from**
|
91
|
+
|
92
|
+
included do # rubocop:disable Metrics/BlockLength
|
93
|
+
helper_method :wallaby_user
|
94
|
+
|
95
|
+
rescue_from NotAuthenticated, with: :unauthorized
|
96
|
+
rescue_from Forbidden, with: :forbidden
|
97
|
+
|
98
|
+
# (see #current_user)
|
99
|
+
# TODO: remove this from 6.2
|
100
|
+
def current_user
|
101
|
+
@current_user ||=
|
102
|
+
if security.current_user? || !defined? super
|
103
|
+
instance_exec(&security.current_user)
|
104
|
+
else
|
105
|
+
Logger.deprecated 'Wallaby will use `wallaby_user` instead of `current_user` from 6.2.'
|
106
|
+
super
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# (see #authenticate_user!)
|
111
|
+
# TODO: remove this from 6.2
|
112
|
+
def authenticate_user!
|
113
|
+
authenticated =
|
114
|
+
if security.authenticate? || !defined? super
|
115
|
+
instance_exec(&security.authenticate)
|
116
|
+
else
|
117
|
+
Logger.deprecated 'Wallaby will use `authenticate_wallaby_user!`' \
|
118
|
+
'instead of `authenticate_user!` from 6.2.'
|
119
|
+
super
|
120
|
+
end
|
121
|
+
raise NotAuthenticated if authenticated == false
|
122
|
+
|
123
|
+
true
|
124
|
+
end
|
125
|
+
|
126
|
+
# (see #wallaby_user)
|
127
|
+
def wallaby_user
|
128
|
+
@wallaby_user ||= try :current_user
|
129
|
+
end
|
130
|
+
|
131
|
+
if defined?(::Pundit) && instance_methods.include?(:pundit_user)
|
132
|
+
# (see #override_pundit_user)
|
133
|
+
def override_pundit_user
|
134
|
+
wallaby_user
|
135
|
+
end
|
136
|
+
|
137
|
+
# (see #original_pundit_user)
|
138
|
+
alias_method :original_pundit_user, :pundit_user
|
139
|
+
# (see #pundit_user)
|
140
|
+
alias_method :pundit_user, :override_pundit_user
|
141
|
+
end
|
142
|
+
|
143
|
+
# (see #authenticate_wallaby_user!)
|
144
|
+
def authenticate_wallaby_user!
|
145
|
+
authenticated = try :authenticate_user!
|
146
|
+
raise NotAuthenticated if authenticated == false
|
147
|
+
|
148
|
+
true
|
149
|
+
end
|
150
|
+
|
151
|
+
# (see #unauthorized)
|
152
|
+
def unauthorized(exception = nil)
|
153
|
+
render_error exception, __callee__
|
154
|
+
end
|
155
|
+
|
156
|
+
# (see #forbidden)
|
157
|
+
def forbidden(exception = nil)
|
158
|
+
render_error exception, __callee__
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -20,7 +20,7 @@ module Wallaby
|
|
20
20
|
# @return [Class] model authorizer
|
21
21
|
# @raise [ArgumentError] when **model_authorizer** doesn't inherit from **application_authorizer**
|
22
22
|
# @see Wallaby::ModelAuthorizer
|
23
|
-
# @since 5.2.0
|
23
|
+
# @since wallaby-5.2.0
|
24
24
|
attr_reader :model_authorizer
|
25
25
|
|
26
26
|
# @!attribute [w] application_authorizer
|
@@ -38,7 +38,7 @@ module Wallaby
|
|
38
38
|
# @return [Class] application decorator
|
39
39
|
# @raise [ArgumentError] when **model_authorizer** doesn't inherit from **application_authorizer**
|
40
40
|
# @see Wallaby::ModelAuthorizer
|
41
|
-
# @since 5.2.0
|
41
|
+
# @since wallaby-5.2.0
|
42
42
|
def application_authorizer
|
43
43
|
@application_authorizer ||= ModuleUtils.try_to superclass, :application_authorizer
|
44
44
|
end
|
@@ -52,11 +52,11 @@ module Wallaby
|
|
52
52
|
# - a generic authorizer based on
|
53
53
|
# {Wallaby::Authorizable::ClassMethods#application_authorizer .application_authorizer}
|
54
54
|
# @return [Wallaby::ModelAuthorizer] model authorizer
|
55
|
-
# @since 5.2.0
|
55
|
+
# @since wallaby-5.2.0
|
56
56
|
def current_authorizer
|
57
57
|
@current_authorizer ||=
|
58
58
|
authorizer_of(current_model_class, controller_to_get(:model_authorizer)).tap do |authorizer|
|
59
|
-
|
59
|
+
Logger.debug %(Current authorizer: #{authorizer.try(:class)}), sourcing: false
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
@@ -65,7 +65,7 @@ module Wallaby
|
|
65
65
|
# @param subject [Object, Class]
|
66
66
|
# @return [true] if allowed
|
67
67
|
# @return [false] if not allowed
|
68
|
-
# @since 5.2.0
|
68
|
+
# @since wallaby-5.2.0
|
69
69
|
def authorized?(action, subject)
|
70
70
|
return false unless subject
|
71
71
|
|
@@ -78,7 +78,7 @@ module Wallaby
|
|
78
78
|
# @param subject [Object, Class]
|
79
79
|
# @return [true] if not allowed
|
80
80
|
# @return [false] if allowed
|
81
|
-
# @since 5.2.0
|
81
|
+
# @since wallaby-5.2.0
|
82
82
|
def unauthorized?(action, subject)
|
83
83
|
!authorized? action, subject
|
84
84
|
end
|
@@ -88,10 +88,10 @@ module Wallaby
|
|
88
88
|
# @param model_class [Class]
|
89
89
|
# @param authorizer_class [Class, nil]
|
90
90
|
# @return [Wallaby::ModelAuthorizer] model authorizer for given model
|
91
|
-
# @since 5.2.0
|
91
|
+
# @since wallaby-5.2.0
|
92
92
|
def authorizer_of(model_class, authorizer_class = nil)
|
93
93
|
authorizer_class ||= Map.authorizer_map(model_class, controller_to_get(:application_authorizer))
|
94
|
-
authorizer_class.
|
94
|
+
authorizer_class.new model_class, self
|
95
95
|
end
|
96
96
|
end
|
97
97
|
end
|