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,75 @@
|
|
|
1
|
+
describe 'ApiGuardian::UsersController' do
|
|
2
|
+
# Authentication and permissions are tested elsewhere
|
|
3
|
+
before(:each) { @routes = ApiGuardian::Engine.routes }
|
|
4
|
+
before(:each) { seed_permissions('user') }
|
|
5
|
+
before(:each) { auth_user }
|
|
6
|
+
after(:each) { destroy_user }
|
|
7
|
+
|
|
8
|
+
describe 'RESOURCE /users' do
|
|
9
|
+
describe 'GET /' do
|
|
10
|
+
it 'returns a list of users' do
|
|
11
|
+
add_user_permission('user:read')
|
|
12
|
+
|
|
13
|
+
get '/users', {}, get_headers
|
|
14
|
+
|
|
15
|
+
expect(response).to have_http_status(:ok)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe 'POST /' do
|
|
20
|
+
it 'creates a new user' do
|
|
21
|
+
add_user_permission('user:create')
|
|
22
|
+
user = create(:user)
|
|
23
|
+
|
|
24
|
+
allow_any_instance_of(ApiGuardian::Stores::UserStore).to receive(:create).and_return(user)
|
|
25
|
+
|
|
26
|
+
data = { data: { type: 'users', attributes: { name: '', default: false, permissions: [] } } }
|
|
27
|
+
|
|
28
|
+
post '/users', data.to_json, get_headers
|
|
29
|
+
|
|
30
|
+
expect(response).to have_http_status(:created)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe 'GET /{:permission_id}' do
|
|
35
|
+
it 'gets a user by id' do
|
|
36
|
+
add_user_permission('user:read')
|
|
37
|
+
user = create(:user)
|
|
38
|
+
|
|
39
|
+
allow_any_instance_of(ApiGuardian::Stores::UserStore).to receive(:find).and_return(user)
|
|
40
|
+
|
|
41
|
+
get "/users/#{user.id}", {}, get_headers
|
|
42
|
+
|
|
43
|
+
expect(response).to have_http_status(:ok)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe 'PATCH /{:permission_id}' do
|
|
48
|
+
it 'updates a user by id' do
|
|
49
|
+
add_user_permission('user:update')
|
|
50
|
+
user = create(:user)
|
|
51
|
+
|
|
52
|
+
allow_any_instance_of(ApiGuardian::Stores::UserStore).to receive(:update).and_return(user)
|
|
53
|
+
|
|
54
|
+
data = { data: { type: 'users', id: "#{user.id}", attributes: { name: Faker::Lorem.word, default: false } } }
|
|
55
|
+
|
|
56
|
+
patch "/users/#{user.id}", data.to_json, get_headers
|
|
57
|
+
|
|
58
|
+
expect(response).to have_http_status(:ok)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe 'DELETE /{:permission_id}' do
|
|
63
|
+
it 'deletes a user by id' do
|
|
64
|
+
add_user_permission('user:delete')
|
|
65
|
+
user = create(:user)
|
|
66
|
+
|
|
67
|
+
allow_any_instance_of(ApiGuardian::Stores::UserStore).to receive(:destroy).and_return(user)
|
|
68
|
+
|
|
69
|
+
delete "/users/#{user.id}", {}, get_headers
|
|
70
|
+
|
|
71
|
+
expect(response).to have_http_status(:no_content)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Configure Rails Environment
|
|
2
|
+
ENV["RAILS_ENV"] = "test"
|
|
3
|
+
|
|
4
|
+
require File.expand_path("../dummy/config/environment.rb", __FILE__)
|
|
5
|
+
require 'capybara/rspec'
|
|
6
|
+
require 'pundit/rspec'
|
|
7
|
+
require 'rspec/rails'
|
|
8
|
+
require 'factory_girl_rails'
|
|
9
|
+
require 'simplecov'
|
|
10
|
+
require 'coveralls'
|
|
11
|
+
require 'faker'
|
|
12
|
+
require 'database_cleaner'
|
|
13
|
+
require "shoulda/matchers"
|
|
14
|
+
require 'support/matchers'
|
|
15
|
+
require 'support/request_helpers'
|
|
16
|
+
require 'rspec-activemodel-mocks'
|
|
17
|
+
|
|
18
|
+
Rails.backtrace_cleaner.remove_silencers!
|
|
19
|
+
ActiveRecord::Migration.maintain_test_schema!
|
|
20
|
+
|
|
21
|
+
if ENV['IS_CODESHIP']
|
|
22
|
+
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
|
23
|
+
Coveralls.wear!('rails')
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
SimpleCov.start do
|
|
27
|
+
add_group 'Controllers', 'app/controllers'
|
|
28
|
+
add_group 'Models', 'app/models'
|
|
29
|
+
add_group 'Serializers', 'app/serializers'
|
|
30
|
+
add_group 'Engine::Concerns', 'lib/api_guardian/concerns'
|
|
31
|
+
add_group 'Engine::Policies', 'lib/api_guardian/policies'
|
|
32
|
+
add_group 'Engine::Errors', 'lib/api_guardian/errors'
|
|
33
|
+
add_group 'Engine::Stores', 'lib/api_guardian/stores'
|
|
34
|
+
add_filter 'db'
|
|
35
|
+
add_filter 'spec'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Eager load for code coverages purposes
|
|
39
|
+
Dir[Rails.root.parent.parent.join('app/controllers/**/*.rb')].each { |f| require f }
|
|
40
|
+
Dir[Rails.root.parent.parent.join('app/models/**/*.rb')].each { |f| require f }
|
|
41
|
+
Dir[Rails.root.parent.parent.join('app/serializers/**/*.rb')].each { |f| require f }
|
|
42
|
+
Dir[Rails.root.parent.parent.join('lib/**/*.rb')].each { |f| require f }
|
|
43
|
+
|
|
44
|
+
# Load support files
|
|
45
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
|
46
|
+
|
|
47
|
+
RSpec.configure do |config|
|
|
48
|
+
config.include Rails.application.routes.url_helpers
|
|
49
|
+
|
|
50
|
+
# If you're not using ActiveRecord, or you'd prefer not to run each of your
|
|
51
|
+
# examples within a transaction, remove the following line or assign false
|
|
52
|
+
# instead of true.
|
|
53
|
+
config.use_transactional_fixtures = false
|
|
54
|
+
|
|
55
|
+
# RSpec Rails can automatically mix in different behaviours to your tests
|
|
56
|
+
# based on their file location, for example enabling you to call `get` and
|
|
57
|
+
# `post` in specs under `spec/controllers`.
|
|
58
|
+
#
|
|
59
|
+
# You can disable this behaviour by removing the line below, and instead
|
|
60
|
+
# explicitly tag your specs with their type, e.g.:
|
|
61
|
+
#
|
|
62
|
+
# RSpec.describe UsersController, :type => :controller do
|
|
63
|
+
# # ...
|
|
64
|
+
# end
|
|
65
|
+
#
|
|
66
|
+
# The different available types are documented in the features, such as in
|
|
67
|
+
# https://relishapp.com/rspec/rspec-rails/docs
|
|
68
|
+
config.infer_spec_type_from_file_location!
|
|
69
|
+
|
|
70
|
+
# rspec-expectations config goes here. You can use an alternate
|
|
71
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
|
72
|
+
# assertions if you prefer.
|
|
73
|
+
config.expect_with :rspec do |expectations|
|
|
74
|
+
# This option will default to `true` in RSpec 4. It makes the `description`
|
|
75
|
+
# and `failure_message` of custom matchers include text for helper methods
|
|
76
|
+
# defined using `chain`, e.g.:
|
|
77
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
|
78
|
+
# # => "be bigger than 2 and smaller than 4"
|
|
79
|
+
# ...rather than:
|
|
80
|
+
# # => "be bigger than 2"
|
|
81
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
|
85
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
|
86
|
+
config.mock_with :rspec do |mocks|
|
|
87
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
|
88
|
+
# a real object. This is generally recommended, and will default to
|
|
89
|
+
# `true` in RSpec 4.
|
|
90
|
+
mocks.verify_partial_doubles = true
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Use color in STDOUT
|
|
94
|
+
config.color = true
|
|
95
|
+
|
|
96
|
+
# Use color not only in STDOUT but also in pagers and files
|
|
97
|
+
config.tty = true
|
|
98
|
+
|
|
99
|
+
# Use the specified formatter
|
|
100
|
+
config.formatter = 'Fuubar' # :progress, :html, :textmate
|
|
101
|
+
|
|
102
|
+
config.order = "random"
|
|
103
|
+
|
|
104
|
+
config.before(:suite) do
|
|
105
|
+
DatabaseCleaner.clean_with(:truncation)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
config.before(:each) do
|
|
109
|
+
DatabaseCleaner.strategy = :transaction
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
config.before(:each, js: true) do
|
|
113
|
+
DatabaseCleaner.strategy = :truncation
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
config.before(:each) do
|
|
117
|
+
DatabaseCleaner.start
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
config.after(:each) do
|
|
121
|
+
DatabaseCleaner.clean
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
config.include FactoryGirl::Syntax::Methods
|
|
125
|
+
config.include Requests::JsonHelpers, type: :request
|
|
126
|
+
config.include Requests::AuthHelpers, type: :request
|
|
127
|
+
config.include Requests::ErrorHelpers, type: :request
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
Shoulda::Matchers.configure do |config|
|
|
131
|
+
config.integrate do |with|
|
|
132
|
+
# Choose a test framework:
|
|
133
|
+
with.test_framework :rspec
|
|
134
|
+
|
|
135
|
+
# Choose one or more libraries:
|
|
136
|
+
with.library :rails
|
|
137
|
+
end
|
|
138
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
describe ApiGuardian::Stores::Base do
|
|
2
|
+
subject { ApiGuardian::Stores::Base.new(scope) }
|
|
3
|
+
|
|
4
|
+
let(:scope) { double(ApiGuardian::Policies::ApplicationPolicy::Scope) }
|
|
5
|
+
|
|
6
|
+
# Delegates
|
|
7
|
+
describe 'delegates' do
|
|
8
|
+
it { should delegate_method(:new).to(:resource_class) }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Methods
|
|
12
|
+
describe 'methods' do
|
|
13
|
+
# using the user model to test the base store
|
|
14
|
+
let(:user) { double(ApiGuardian::User) }
|
|
15
|
+
|
|
16
|
+
before(:each) do
|
|
17
|
+
allow_any_instance_of(ApiGuardian::Stores::Base).to receive(:resource_class).and_return(user)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe '#all' do
|
|
21
|
+
it 'returns objects via scope' do
|
|
22
|
+
expect(scope).to receive(:all)
|
|
23
|
+
subject.all
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe '#paginate' do
|
|
28
|
+
context 'returns objects via scope with pagination' do
|
|
29
|
+
it 'without arguments' do
|
|
30
|
+
expect(scope).to receive(:page).with(1).and_return(scope)
|
|
31
|
+
expect(scope).to receive(:per).with(25)
|
|
32
|
+
|
|
33
|
+
subject.paginate
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'with arguments' do
|
|
37
|
+
expect(scope).to receive(:page).with(10).and_return(scope)
|
|
38
|
+
expect(scope).to receive(:per).with(50)
|
|
39
|
+
|
|
40
|
+
subject.paginate(10, 50)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe '#find' do
|
|
46
|
+
it 'errors on missing record' do
|
|
47
|
+
expect(user).to receive(:find).and_return(nil)
|
|
48
|
+
|
|
49
|
+
expect { subject.find(1) }.to raise_error ActiveRecord::RecordNotFound
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'returns record if found' do
|
|
53
|
+
a_user = double(ApiGuardian::User)
|
|
54
|
+
expect(user).to receive(:find).and_return(a_user)
|
|
55
|
+
|
|
56
|
+
result = subject.find(1)
|
|
57
|
+
|
|
58
|
+
expect(result).to eq a_user
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe '#save' do
|
|
63
|
+
it 'saves a record' do
|
|
64
|
+
a_user = instance_double(ApiGuardian::User)
|
|
65
|
+
expect(a_user).to receive(:save!)
|
|
66
|
+
|
|
67
|
+
subject.save(a_user)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe '#create' do
|
|
72
|
+
it 'errors on invalid record' do
|
|
73
|
+
attributes = {}
|
|
74
|
+
new_user = mock_model(ApiGuardian::User)
|
|
75
|
+
expect(new_user).to receive(:valid?).and_return(false)
|
|
76
|
+
expect(user).to receive(:new).with(attributes).and_return(new_user)
|
|
77
|
+
|
|
78
|
+
expect { subject.create(attributes) }.to raise_error ActiveRecord::RecordInvalid
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it 'creates a record' do
|
|
82
|
+
attributes = {}
|
|
83
|
+
new_user = mock_model(ApiGuardian::User)
|
|
84
|
+
expect(new_user).to receive(:valid?).and_return(true)
|
|
85
|
+
expect(user).to receive(:new).with(attributes).and_return(new_user)
|
|
86
|
+
expect(subject).to receive(:save).with(new_user)
|
|
87
|
+
|
|
88
|
+
result = subject.create(attributes)
|
|
89
|
+
|
|
90
|
+
expect(result).to eq new_user
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
describe '#update' do
|
|
95
|
+
it 'updates a record' do
|
|
96
|
+
attributes = {}
|
|
97
|
+
a_user = instance_double(ApiGuardian::User)
|
|
98
|
+
expect(a_user).to receive(:update_attributes!).with(attributes)
|
|
99
|
+
|
|
100
|
+
subject.update(a_user, attributes)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
describe '#destroy' do
|
|
105
|
+
it 'destroys a record' do
|
|
106
|
+
a_user = instance_double(ApiGuardian::User)
|
|
107
|
+
expect(a_user).to receive(:destroy!)
|
|
108
|
+
|
|
109
|
+
subject.destroy(a_user)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
describe ApiGuardian::Stores::RoleStore do
|
|
2
|
+
# Methods
|
|
3
|
+
describe 'methods' do
|
|
4
|
+
describe '.default_role' do
|
|
5
|
+
it 'should return the default role' do
|
|
6
|
+
expect(ApiGuardian::Role).to receive(:default_role)
|
|
7
|
+
|
|
8
|
+
ApiGuardian::Stores::RoleStore.default_role
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
describe ApiGuardian::Stores::UserStore do
|
|
2
|
+
# Methods
|
|
3
|
+
describe 'methods' do
|
|
4
|
+
describe '#find_by_email' do
|
|
5
|
+
it 'should find user by email' do
|
|
6
|
+
expect(ApiGuardian::User).to receive(:find_by_email).with('test')
|
|
7
|
+
|
|
8
|
+
subject.find_by_email('test')
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe '#find_by_reset_password_token' do
|
|
13
|
+
it 'should find user by reset password token' do
|
|
14
|
+
expect(ApiGuardian::User).to receive(:find_by_reset_password_token).with('test')
|
|
15
|
+
|
|
16
|
+
subject.find_by_reset_password_token('test')
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe '#create' do
|
|
21
|
+
it 'should set default attributes before saving' do
|
|
22
|
+
attributes = {}
|
|
23
|
+
role = mock_model(ApiGuardian::Role)
|
|
24
|
+
expect(role).to receive(:id).and_return(1)
|
|
25
|
+
expect(ApiGuardian::Stores::RoleStore).to receive(:default_role).and_return(role)
|
|
26
|
+
expect_any_instance_of(ApiGuardian::User).to receive(:valid?).and_return(true)
|
|
27
|
+
expect_any_instance_of(ApiGuardian::User).to receive(:save!).and_return(true)
|
|
28
|
+
|
|
29
|
+
subject.create(attributes)
|
|
30
|
+
|
|
31
|
+
expect(attributes[:role_id]).to eq 1
|
|
32
|
+
expect(attributes[:email_confirmed_at]).to be_a(DateTime)
|
|
33
|
+
expect(attributes[:active]).to eq true
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe '.register' do
|
|
38
|
+
it 'fails on invalid attributes' do
|
|
39
|
+
role = mock_model(ApiGuardian::Role)
|
|
40
|
+
expect(role).to receive(:id).and_return(1)
|
|
41
|
+
expect(ApiGuardian::Stores::RoleStore).to receive(:default_role).and_return(role)
|
|
42
|
+
allow_any_instance_of(ApiGuardian::User).to receive(:valid?).and_return(false)
|
|
43
|
+
|
|
44
|
+
expect { ApiGuardian::Stores::UserStore.register({}) }.to raise_error ActiveRecord::RecordInvalid
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'creates inactive user with unconfirmed email and default role' do
|
|
48
|
+
role = mock_model(ApiGuardian::Role)
|
|
49
|
+
user = create(:user)
|
|
50
|
+
expect(role).to receive(:id).and_return(1)
|
|
51
|
+
expect(ApiGuardian::Stores::RoleStore).to receive(:default_role).and_return(role)
|
|
52
|
+
expect(ApiGuardian::User).to receive(:new).and_return(user)
|
|
53
|
+
expect_any_instance_of(ApiGuardian::User).to receive(:valid?).and_return(true)
|
|
54
|
+
expect_any_instance_of(ApiGuardian::User).to receive(:save!).and_return(true)
|
|
55
|
+
|
|
56
|
+
result = ApiGuardian::Stores::UserStore.register({})
|
|
57
|
+
|
|
58
|
+
expect(result.role_id).to eq user.role_id
|
|
59
|
+
expect(result.active).to be false
|
|
60
|
+
expect(result.email_confirmed_at).to be nil
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
describe '.reset_password' do
|
|
65
|
+
it 'resets on valid email' do
|
|
66
|
+
user = mock_model(ApiGuardian::User)
|
|
67
|
+
expect(user).to receive(:reset_password_token=)
|
|
68
|
+
expect(user).to receive(:reset_password_sent_at=)
|
|
69
|
+
expect(user).to receive(:save)
|
|
70
|
+
|
|
71
|
+
allow_any_instance_of(ApiGuardian::Stores::UserStore).to receive(:find_by_email).and_return(user)
|
|
72
|
+
|
|
73
|
+
result = ApiGuardian::Stores::UserStore.reset_password('email')
|
|
74
|
+
|
|
75
|
+
expect(result).to be true
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it 'fails on invalid email' do
|
|
79
|
+
allow_any_instance_of(ApiGuardian::Stores::UserStore).to receive(:find_by_email).and_return(nil)
|
|
80
|
+
|
|
81
|
+
result = ApiGuardian::Stores::UserStore.reset_password('email')
|
|
82
|
+
|
|
83
|
+
expect(result).to be false
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
describe '.complete_reset_password' do
|
|
88
|
+
it 'fails on missing user' do
|
|
89
|
+
allow_any_instance_of(ApiGuardian::Stores::UserStore).to receive(:find_by_reset_password_token).and_return(nil)
|
|
90
|
+
expect(ApiGuardian::Stores::UserStore.complete_reset_password({})).to be false
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it 'fails if token doesn\'t match user email' do
|
|
94
|
+
user = mock_model(ApiGuardian::User)
|
|
95
|
+
expect(user).to receive(:email).and_return('bar')
|
|
96
|
+
allow_any_instance_of(ApiGuardian::Stores::UserStore).to receive(:find_by_reset_password_token).and_return(user)
|
|
97
|
+
|
|
98
|
+
expect { ApiGuardian::Stores::UserStore.complete_reset_password(email: 'foo') }.to raise_error ApiGuardian::Errors::ResetTokenUserMismatchError
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it 'fails if token is expired' do
|
|
102
|
+
user = mock_model(ApiGuardian::User)
|
|
103
|
+
expect(user).to receive(:email).and_return('bar')
|
|
104
|
+
expect(user).to receive(:reset_password_token_valid?).and_return(false)
|
|
105
|
+
allow_any_instance_of(ApiGuardian::Stores::UserStore).to receive(:find_by_reset_password_token).and_return(user)
|
|
106
|
+
|
|
107
|
+
expect { ApiGuardian::Stores::UserStore.complete_reset_password(email: 'bar') }.to raise_error ApiGuardian::Errors::ResetTokenExpiredError
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it 'fails if the new password is missing' do
|
|
111
|
+
user = mock_model(ApiGuardian::User)
|
|
112
|
+
allow_any_instance_of(ApiGuardian::Stores::UserStore).to receive(:find_by_reset_password_token).and_return(user)
|
|
113
|
+
expect(user).to receive(:email).and_return('foo')
|
|
114
|
+
expect(user).to receive(:reset_password_token_valid?).and_return(true)
|
|
115
|
+
expect(user).to receive(:password)
|
|
116
|
+
expect_any_instance_of(ActionController::Parameters).to receive(:fetch).with(:password, nil).and_return(nil)
|
|
117
|
+
expect { ApiGuardian::Stores::UserStore.complete_reset_password(ActionController::Parameters.new(email: 'foo')) }.to raise_error ActiveRecord::RecordInvalid
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it 'resets on valid attributes' do
|
|
121
|
+
user = mock_model(ApiGuardian::User)
|
|
122
|
+
allow_any_instance_of(ApiGuardian::Stores::UserStore).to receive(:find_by_reset_password_token).and_return(user)
|
|
123
|
+
expect(user).to receive(:email).and_return('foo')
|
|
124
|
+
expect(user).to receive(:reset_password_token_valid?).and_return(true)
|
|
125
|
+
expect_any_instance_of(ActionController::Parameters).to receive(:fetch).with(:password, nil).and_return('password')
|
|
126
|
+
expect(user).to receive(:assign_attributes)
|
|
127
|
+
expect(user).to receive(:save!)
|
|
128
|
+
expect(user).to receive(:reset_password_token=)
|
|
129
|
+
expect(user).to receive(:reset_password_sent_at=)
|
|
130
|
+
expect(user).to receive(:save)
|
|
131
|
+
|
|
132
|
+
attributes = ActionController::Parameters.new(
|
|
133
|
+
email: 'foo',
|
|
134
|
+
password: 'password',
|
|
135
|
+
password_confirmation: 'password'
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
expect(ApiGuardian::Stores::UserStore.complete_reset_password(attributes)).to be true
|
|
139
|
+
expect(user.reset_password_token).to be nil
|
|
140
|
+
expect(user.reset_password_sent_at).to be nil
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|