api_guardian 0.1.0.pre
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +125 -0
- data/Rakefile +30 -0
- data/app/controllers/api_guardian/api_controller.rb +112 -0
- data/app/controllers/api_guardian/application_controller.rb +11 -0
- data/app/controllers/api_guardian/permissions_controller.rb +7 -0
- data/app/controllers/api_guardian/registration_controller.rb +38 -0
- data/app/controllers/api_guardian/roles_controller.rb +19 -0
- data/app/controllers/api_guardian/users_controller.rb +20 -0
- data/app/models/api_guardian/permission.rb +14 -0
- data/app/models/api_guardian/role.rb +97 -0
- data/app/models/api_guardian/role_permission.rb +8 -0
- data/app/models/api_guardian/user.rb +23 -0
- data/app/serializers/api_guardian/permission_serializer.rb +7 -0
- data/app/serializers/api_guardian/role_serializer.rb +7 -0
- data/app/serializers/api_guardian/user_serializer.rb +10 -0
- data/config/initializers/api_guardian.rb +10 -0
- data/config/initializers/doorkeeper.rb +143 -0
- data/config/routes.rb +20 -0
- data/db/migrate/20151117191338_api_guardian_enable_uuid_extension.rb +5 -0
- data/db/migrate/20151117191911_create_api_guardian_roles.rb +9 -0
- data/db/migrate/20151117195618_create_api_guardian_users.rb +25 -0
- data/db/migrate/20151117212826_create_api_guardian_permissions.rb +10 -0
- data/db/migrate/20151117213145_create_api_guardian_role_permissions.rb +11 -0
- data/db/migrate/20151117225238_create_doorkeeper_tables.rb +42 -0
- data/db/seeds.rb +32 -0
- data/lib/api_guardian.rb +80 -0
- data/lib/api_guardian/concerns/api_errors/handler.rb +145 -0
- data/lib/api_guardian/concerns/api_errors/renderer.rb +45 -0
- data/lib/api_guardian/concerns/api_request/validator.rb +66 -0
- data/lib/api_guardian/configuration.rb +171 -0
- data/lib/api_guardian/engine.rb +23 -0
- data/lib/api_guardian/errors/invalid_content_type_error.rb +6 -0
- data/lib/api_guardian/errors/invalid_permission_name_error.rb +6 -0
- data/lib/api_guardian/errors/invalid_request_body_error.rb +6 -0
- data/lib/api_guardian/errors/invalid_request_resource_id_error.rb +6 -0
- data/lib/api_guardian/errors/invalid_request_resource_type_error.rb +6 -0
- data/lib/api_guardian/errors/invalid_update_action_error.rb +6 -0
- data/lib/api_guardian/errors/reset_token_expired_error.rb +6 -0
- data/lib/api_guardian/errors/reset_token_user_mismatch_error.rb +6 -0
- data/lib/api_guardian/policies/application_policy.rb +65 -0
- data/lib/api_guardian/policies/permission_policy.rb +15 -0
- data/lib/api_guardian/policies/role_policy.rb +15 -0
- data/lib/api_guardian/policies/user_policy.rb +23 -0
- data/lib/api_guardian/stores/base.rb +53 -0
- data/lib/api_guardian/stores/permission_store.rb +6 -0
- data/lib/api_guardian/stores/role_store.rb +9 -0
- data/lib/api_guardian/stores/user_store.rb +86 -0
- data/lib/api_guardian/version.rb +3 -0
- data/lib/generators/api_guardian/install/USAGE +8 -0
- data/lib/generators/api_guardian/install/install_generator.rb +19 -0
- data/lib/generators/api_guardian/install/templates/README +1 -0
- data/lib/generators/api_guardian/install/templates/api_guardian.rb +5 -0
- data/lib/tasks/api_guardian_tasks.rake +4 -0
- data/spec/concerns/api_errors/handler_spec.rb +114 -0
- data/spec/concerns/api_request/validator_spec.rb +102 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +25 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +13 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +41 -0
- data/spec/dummy/config/environments/production.rb +79 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/schema.rb +104 -0
- data/spec/dummy/log/test.log +5031 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/factories/permissions.rb +6 -0
- data/spec/factories/role_permissions.rb +6 -0
- data/spec/factories/roles.rb +24 -0
- data/spec/factories/users.rb +11 -0
- data/spec/models/permission_spec.rb +28 -0
- data/spec/models/role_permission_spec.rb +27 -0
- data/spec/models/role_spec.rb +209 -0
- data/spec/models/user_spec.rb +44 -0
- data/spec/policies/application_policy_spec.rb +118 -0
- data/spec/policies/permission_policy_spec.rb +28 -0
- data/spec/policies/role_policy_spec.rb +28 -0
- data/spec/policies/user_policy_spec.rb +29 -0
- data/spec/requests/permissions_controller_spec.rb +19 -0
- data/spec/requests/registration_controller_spec.rb +151 -0
- data/spec/requests/roles_controller_spec.rb +75 -0
- data/spec/requests/users_controller_spec.rb +75 -0
- data/spec/spec_helper.rb +138 -0
- data/spec/stores/base_spec.rb +113 -0
- data/spec/stores/permission_store_spec.rb +2 -0
- data/spec/stores/role_store_spec.rb +12 -0
- data/spec/stores/user_store_spec.rb +144 -0
- data/spec/support/controller_concern_test_helpers.rb +21 -0
- data/spec/support/matchers.rb +37 -0
- data/spec/support/request_helpers.rb +111 -0
- metadata +508 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module ApiGuardian
|
|
2
|
+
module Policies
|
|
3
|
+
class ApplicationPolicy
|
|
4
|
+
attr_reader :user, :record
|
|
5
|
+
|
|
6
|
+
def initialize(user, record)
|
|
7
|
+
@user = user
|
|
8
|
+
@record = record
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def index?
|
|
12
|
+
false
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def show?
|
|
16
|
+
user.can?(["#{resource_name}:read", "#{resource_name}:manage"])
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def create?
|
|
20
|
+
user.can?(["#{resource_name}:create", "#{resource_name}:manage"])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def new?
|
|
24
|
+
create?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def update?
|
|
28
|
+
user.can?(["#{resource_name}:update", "#{resource_name}:manage"])
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def edit?
|
|
32
|
+
update?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def destroy?
|
|
36
|
+
user.can?(["#{resource_name}:delete", "#{resource_name}:manage"])
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def scope
|
|
40
|
+
Pundit.policy_scope!(user, record.class)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class Scope
|
|
44
|
+
attr_reader :user, :scope
|
|
45
|
+
|
|
46
|
+
def initialize(user, scope)
|
|
47
|
+
@user = user
|
|
48
|
+
@scope = scope
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def resolve
|
|
52
|
+
scope
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
protected
|
|
57
|
+
|
|
58
|
+
def resource_name
|
|
59
|
+
return record.new.class.name.demodulize.downcase if record.respond_to? :new
|
|
60
|
+
|
|
61
|
+
record.class.name.demodulize.downcase
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module ApiGuardian
|
|
2
|
+
module Policies
|
|
3
|
+
class PermissionPolicy < ApplicationPolicy
|
|
4
|
+
class Scope < Scope
|
|
5
|
+
def resolve
|
|
6
|
+
if user.can?(['permission:read', 'permission:manage'])
|
|
7
|
+
scope
|
|
8
|
+
else
|
|
9
|
+
fail Pundit::NotAuthorizedError
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module ApiGuardian
|
|
2
|
+
module Policies
|
|
3
|
+
class UserPolicy < ApplicationPolicy
|
|
4
|
+
class Scope < Scope
|
|
5
|
+
def resolve
|
|
6
|
+
if user.can?(['user:read', 'user:manage'])
|
|
7
|
+
scope.includes(role: [role_permissions: [:permission]])
|
|
8
|
+
else
|
|
9
|
+
fail Pundit::NotAuthorizedError
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def show?
|
|
15
|
+
user.can?(['user:read', 'user:manage']) || record.id == user.id
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def update?
|
|
19
|
+
user.can?(['user:update', 'user:manage']) || record.id == user.id
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module ApiGuardian
|
|
2
|
+
module Stores
|
|
3
|
+
class Base
|
|
4
|
+
@@instance = nil
|
|
5
|
+
|
|
6
|
+
delegate :new, to: :resource_class
|
|
7
|
+
|
|
8
|
+
def initialize(scope = nil)
|
|
9
|
+
@scope = scope
|
|
10
|
+
@@instance = self
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def all
|
|
14
|
+
@scope.all
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def paginate(page = 1, per_page = 25)
|
|
18
|
+
@scope.page(page).per(per_page)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def find(id)
|
|
22
|
+
record = resource_class.find(id)
|
|
23
|
+
fail ActiveRecord::RecordNotFound unless record
|
|
24
|
+
record
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def save(resource)
|
|
28
|
+
resource.save!
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def create(attributes)
|
|
32
|
+
resource = resource_class.new(attributes)
|
|
33
|
+
fail ActiveRecord::RecordInvalid.new(resource), '' unless resource.valid?
|
|
34
|
+
save(resource)
|
|
35
|
+
resource
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def update(resource, attributes)
|
|
39
|
+
resource.update_attributes!(attributes)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def destroy(resource)
|
|
43
|
+
resource.destroy!
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
protected
|
|
47
|
+
|
|
48
|
+
def resource_class
|
|
49
|
+
@resource_class ||= self.class.name.gsub('Stores::', '').gsub('Store', '').classify.constantize
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# TODO: How can we remove dependency on .new?
|
|
2
|
+
module ApiGuardian
|
|
3
|
+
module Stores
|
|
4
|
+
class UserStore < Base
|
|
5
|
+
def find_by_email(email)
|
|
6
|
+
User.find_by_email(email)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def find_by_reset_password_token(token)
|
|
10
|
+
User.find_by_reset_password_token(token)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def create(attributes)
|
|
14
|
+
attributes[:role_id] = ApiGuardian::Stores::RoleStore.default_role.id
|
|
15
|
+
attributes[:email_confirmed_at] = DateTime.now.utc
|
|
16
|
+
attributes[:active] = true
|
|
17
|
+
super attributes
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.register(attributes)
|
|
21
|
+
instance = new(nil)
|
|
22
|
+
|
|
23
|
+
attributes[:role_id] = ApiGuardian::Stores::RoleStore.default_role.id
|
|
24
|
+
attributes[:active] = false
|
|
25
|
+
|
|
26
|
+
# create user
|
|
27
|
+
user = instance.new(attributes)
|
|
28
|
+
fail ActiveRecord::RecordInvalid.new(user), '' unless user.valid?
|
|
29
|
+
instance.save(user)
|
|
30
|
+
|
|
31
|
+
# TODO: put user created event onto queue
|
|
32
|
+
|
|
33
|
+
user
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.reset_password(email)
|
|
37
|
+
instance = new(nil)
|
|
38
|
+
|
|
39
|
+
user = instance.find_by_email(email)
|
|
40
|
+
|
|
41
|
+
if user
|
|
42
|
+
user.reset_password_token = SecureRandom.hex(64)
|
|
43
|
+
user.reset_password_sent_at = DateTime.now.utc
|
|
44
|
+
user.save
|
|
45
|
+
|
|
46
|
+
# TODO: email password reset
|
|
47
|
+
return true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
false
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def self.complete_reset_password(attributes)
|
|
54
|
+
instance = new(nil)
|
|
55
|
+
# Find user by token
|
|
56
|
+
user = instance.find_by_reset_password_token(attributes[:token])
|
|
57
|
+
|
|
58
|
+
if user
|
|
59
|
+
# Validate submitted email matches token
|
|
60
|
+
fail ApiGuardian::Errors::ResetTokenUserMismatchError, attributes[:email] unless user.email == attributes[:email]
|
|
61
|
+
|
|
62
|
+
# Check that it hasn't expired
|
|
63
|
+
fail ApiGuardian::Errors::ResetTokenExpiredError, '' unless user.reset_password_token_valid?
|
|
64
|
+
|
|
65
|
+
# Validate password
|
|
66
|
+
if attributes.fetch(:password, nil).blank?
|
|
67
|
+
user.errors.add(:password, :blank)
|
|
68
|
+
fail ActiveRecord::RecordInvalid.new(user), ''
|
|
69
|
+
end
|
|
70
|
+
user.assign_attributes(attributes.slice(:password, :password_confirmation))
|
|
71
|
+
user.save! # This will fail if it is invalid
|
|
72
|
+
|
|
73
|
+
# Done
|
|
74
|
+
user.reset_password_token = nil
|
|
75
|
+
user.reset_password_sent_at = nil
|
|
76
|
+
user.save
|
|
77
|
+
|
|
78
|
+
# TODO: send password changed confirmation email
|
|
79
|
+
|
|
80
|
+
return true
|
|
81
|
+
end
|
|
82
|
+
false
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module ApiGuardian
|
|
2
|
+
class InstallGenerator < Rails::Generators::Base
|
|
3
|
+
source_root File.expand_path('../templates', __FILE__)
|
|
4
|
+
|
|
5
|
+
desc 'Creates an ApiGuardian initializer and copy locale files to your application.'
|
|
6
|
+
|
|
7
|
+
def copy_initializer
|
|
8
|
+
template 'api_guardian.rb', 'config/initializers/api_guardian.rb'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def add_routes
|
|
12
|
+
route 'mount ApiGuardian::Engine => \'/auth\''
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def show_readme
|
|
16
|
+
readme 'README' if behavior == :invoke
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Do stuff with ApiGuardian
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
module Test
|
|
2
|
+
class Dummy
|
|
3
|
+
include ControllerConcernTestHelpers
|
|
4
|
+
include ApiGuardian::Concerns::ApiErrors::Handler
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe ApiGuardian::Concerns::ApiErrors::Handler, type: :request do
|
|
9
|
+
let(:dummy_class) { Test::Dummy.new }
|
|
10
|
+
|
|
11
|
+
# Methods
|
|
12
|
+
describe 'methods' do
|
|
13
|
+
describe '#doorkeeper_unauthorized_render_options' do
|
|
14
|
+
it 'returns an error hash' do
|
|
15
|
+
expect_any_instance_of(Test::Dummy).to receive(:construct_error).with(
|
|
16
|
+
401, 'not_authenticated', 'Not Authenticated', 'You must be logged in.'
|
|
17
|
+
).and_return('foo')
|
|
18
|
+
result = dummy_class.doorkeeper_unauthorized_render_options ''
|
|
19
|
+
|
|
20
|
+
expect(result).to eq(json: { errors: ['foo'] })
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe '#api_error_handler' do
|
|
25
|
+
it 'handles Pundit::NotAuthorizedError' do
|
|
26
|
+
expect_any_instance_of(Test::Dummy).to receive(:render_error).with(
|
|
27
|
+
403, 'not_authorized', 'Not Authorized', 'You are not authorized to perform this action.'
|
|
28
|
+
)
|
|
29
|
+
expect { dummy_class.api_error_handler(Pundit::NotAuthorizedError.new) }.not_to raise_error
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'handles ActionController::ParameterMissing' do
|
|
33
|
+
expect_any_instance_of(Test::Dummy).to receive(:render_error).with(
|
|
34
|
+
400, 'malformed_request', 'Malformed Request', 'param is missing or the value is empty: test'
|
|
35
|
+
)
|
|
36
|
+
expect { dummy_class.api_error_handler(ActionController::ParameterMissing.new('test')) }.not_to raise_error
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'handles ActiveRecord::RecordInvalid' do
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'handles ActiveRecord::RecordNotFound' do
|
|
43
|
+
allow_any_instance_of(ActionDispatch::Request).to receive(:original_url).and_return('test.com')
|
|
44
|
+
expect_any_instance_of(Test::Dummy).to receive(:render_error).with(
|
|
45
|
+
404, 'not_found', 'Not Found', 'Resource or endpoint missing: test.com'
|
|
46
|
+
)
|
|
47
|
+
expect { dummy_class.api_error_handler(ActiveRecord::RecordNotFound.new('test')) }.not_to raise_error
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it 'handles InvalidContentTypeError' do
|
|
51
|
+
expect_any_instance_of(Test::Dummy).to receive(:render_error).with(
|
|
52
|
+
415, 'invalid_content_type', 'Invalid Content Type', 'Supported content types are: application/vnd.api+json'
|
|
53
|
+
)
|
|
54
|
+
expect { dummy_class.api_error_handler(ApiGuardian::Errors::InvalidContentTypeError.new('')) }.not_to raise_error
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'handles InvalidRequestBodyError' do
|
|
58
|
+
expect_any_instance_of(Test::Dummy).to receive(:render_error).with(
|
|
59
|
+
400, 'invalid_request_body', 'Invalid Request Body', 'The \'test\' property is required.'
|
|
60
|
+
)
|
|
61
|
+
expect { dummy_class.api_error_handler(ApiGuardian::Errors::InvalidRequestBodyError.new('test')) }.not_to raise_error
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'handles InvalidRequestResourceTypeError' do
|
|
65
|
+
expect_any_instance_of(Test::Dummy).to receive(:render_error).with(
|
|
66
|
+
400, 'invalid_request_resource_type', 'Invalid Request Resource Type',
|
|
67
|
+
'Expected \'type\' property to be \'test\' for this resource.'
|
|
68
|
+
)
|
|
69
|
+
expect { dummy_class.api_error_handler(ApiGuardian::Errors::InvalidRequestResourceTypeError.new('test')) }.not_to raise_error
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'handles InvalidRequestResourceIdError' do
|
|
73
|
+
allow_any_instance_of(ActionController::Parameters).to receive(:fetch).with(:id, nil).and_return('test')
|
|
74
|
+
expect_any_instance_of(Test::Dummy).to receive(:render_error).with(
|
|
75
|
+
400, 'invalid_request_resource_id', 'Invalid Request Resource ID',
|
|
76
|
+
'Request \'id\' property does not match \'id\' of URI. Provided: value, Expected: test'
|
|
77
|
+
)
|
|
78
|
+
expect { dummy_class.api_error_handler(ApiGuardian::Errors::InvalidRequestResourceIdError.new('value')) }.not_to raise_error
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it 'handles InvalidUpdateActionError' do
|
|
82
|
+
expect_any_instance_of(Test::Dummy).to receive(:render_error).with(
|
|
83
|
+
405, 'method_not_allowed', 'Method Not Allowed',
|
|
84
|
+
'Resource update action expects PATCH method.'
|
|
85
|
+
)
|
|
86
|
+
expect { dummy_class.api_error_handler(ApiGuardian::Errors::InvalidUpdateActionError.new('')) }.not_to raise_error
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'handles ResetTokenUserMismatchError' do
|
|
90
|
+
expect_any_instance_of(Test::Dummy).to receive(:render_error).with(
|
|
91
|
+
403, 'reset_token_mismatch', 'Reset Token Mismatch',
|
|
92
|
+
'Reset token is not valid for the supplied email address.'
|
|
93
|
+
)
|
|
94
|
+
expect { dummy_class.api_error_handler(ApiGuardian::Errors::ResetTokenUserMismatchError.new('')) }.not_to raise_error
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it 'handles ResetTokenExpiredError' do
|
|
98
|
+
expect_any_instance_of(Test::Dummy).to receive(:render_error).with(
|
|
99
|
+
403, 'reset_token_expired', 'Reset Token Expired',
|
|
100
|
+
'This reset token has expired. Tokens are valid for 24 hours.'
|
|
101
|
+
)
|
|
102
|
+
expect { dummy_class.api_error_handler(ApiGuardian::Errors::ResetTokenExpiredError.new('')) }.not_to raise_error
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it 'handles generic errors' do
|
|
106
|
+
exception = StandardError.new('')
|
|
107
|
+
expect_any_instance_of(Test::Dummy).to receive(:render_error).with(
|
|
108
|
+
500, nil, nil, nil, exception
|
|
109
|
+
)
|
|
110
|
+
expect { dummy_class.api_error_handler(exception) }.not_to raise_error
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|