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,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
|