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.
Files changed (114) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +125 -0
  4. data/Rakefile +30 -0
  5. data/app/controllers/api_guardian/api_controller.rb +112 -0
  6. data/app/controllers/api_guardian/application_controller.rb +11 -0
  7. data/app/controllers/api_guardian/permissions_controller.rb +7 -0
  8. data/app/controllers/api_guardian/registration_controller.rb +38 -0
  9. data/app/controllers/api_guardian/roles_controller.rb +19 -0
  10. data/app/controllers/api_guardian/users_controller.rb +20 -0
  11. data/app/models/api_guardian/permission.rb +14 -0
  12. data/app/models/api_guardian/role.rb +97 -0
  13. data/app/models/api_guardian/role_permission.rb +8 -0
  14. data/app/models/api_guardian/user.rb +23 -0
  15. data/app/serializers/api_guardian/permission_serializer.rb +7 -0
  16. data/app/serializers/api_guardian/role_serializer.rb +7 -0
  17. data/app/serializers/api_guardian/user_serializer.rb +10 -0
  18. data/config/initializers/api_guardian.rb +10 -0
  19. data/config/initializers/doorkeeper.rb +143 -0
  20. data/config/routes.rb +20 -0
  21. data/db/migrate/20151117191338_api_guardian_enable_uuid_extension.rb +5 -0
  22. data/db/migrate/20151117191911_create_api_guardian_roles.rb +9 -0
  23. data/db/migrate/20151117195618_create_api_guardian_users.rb +25 -0
  24. data/db/migrate/20151117212826_create_api_guardian_permissions.rb +10 -0
  25. data/db/migrate/20151117213145_create_api_guardian_role_permissions.rb +11 -0
  26. data/db/migrate/20151117225238_create_doorkeeper_tables.rb +42 -0
  27. data/db/seeds.rb +32 -0
  28. data/lib/api_guardian.rb +80 -0
  29. data/lib/api_guardian/concerns/api_errors/handler.rb +145 -0
  30. data/lib/api_guardian/concerns/api_errors/renderer.rb +45 -0
  31. data/lib/api_guardian/concerns/api_request/validator.rb +66 -0
  32. data/lib/api_guardian/configuration.rb +171 -0
  33. data/lib/api_guardian/engine.rb +23 -0
  34. data/lib/api_guardian/errors/invalid_content_type_error.rb +6 -0
  35. data/lib/api_guardian/errors/invalid_permission_name_error.rb +6 -0
  36. data/lib/api_guardian/errors/invalid_request_body_error.rb +6 -0
  37. data/lib/api_guardian/errors/invalid_request_resource_id_error.rb +6 -0
  38. data/lib/api_guardian/errors/invalid_request_resource_type_error.rb +6 -0
  39. data/lib/api_guardian/errors/invalid_update_action_error.rb +6 -0
  40. data/lib/api_guardian/errors/reset_token_expired_error.rb +6 -0
  41. data/lib/api_guardian/errors/reset_token_user_mismatch_error.rb +6 -0
  42. data/lib/api_guardian/policies/application_policy.rb +65 -0
  43. data/lib/api_guardian/policies/permission_policy.rb +15 -0
  44. data/lib/api_guardian/policies/role_policy.rb +15 -0
  45. data/lib/api_guardian/policies/user_policy.rb +23 -0
  46. data/lib/api_guardian/stores/base.rb +53 -0
  47. data/lib/api_guardian/stores/permission_store.rb +6 -0
  48. data/lib/api_guardian/stores/role_store.rb +9 -0
  49. data/lib/api_guardian/stores/user_store.rb +86 -0
  50. data/lib/api_guardian/version.rb +3 -0
  51. data/lib/generators/api_guardian/install/USAGE +8 -0
  52. data/lib/generators/api_guardian/install/install_generator.rb +19 -0
  53. data/lib/generators/api_guardian/install/templates/README +1 -0
  54. data/lib/generators/api_guardian/install/templates/api_guardian.rb +5 -0
  55. data/lib/tasks/api_guardian_tasks.rake +4 -0
  56. data/spec/concerns/api_errors/handler_spec.rb +114 -0
  57. data/spec/concerns/api_request/validator_spec.rb +102 -0
  58. data/spec/dummy/README.rdoc +28 -0
  59. data/spec/dummy/Rakefile +6 -0
  60. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  61. data/spec/dummy/bin/bundle +3 -0
  62. data/spec/dummy/bin/rails +4 -0
  63. data/spec/dummy/bin/rake +4 -0
  64. data/spec/dummy/bin/setup +29 -0
  65. data/spec/dummy/config.ru +4 -0
  66. data/spec/dummy/config/application.rb +25 -0
  67. data/spec/dummy/config/boot.rb +5 -0
  68. data/spec/dummy/config/database.yml +13 -0
  69. data/spec/dummy/config/environment.rb +5 -0
  70. data/spec/dummy/config/environments/development.rb +41 -0
  71. data/spec/dummy/config/environments/production.rb +79 -0
  72. data/spec/dummy/config/environments/test.rb +42 -0
  73. data/spec/dummy/config/initializers/assets.rb +11 -0
  74. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  75. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  76. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  77. data/spec/dummy/config/initializers/inflections.rb +16 -0
  78. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  79. data/spec/dummy/config/initializers/session_store.rb +3 -0
  80. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  81. data/spec/dummy/config/locales/en.yml +23 -0
  82. data/spec/dummy/config/routes.rb +3 -0
  83. data/spec/dummy/config/secrets.yml +22 -0
  84. data/spec/dummy/db/schema.rb +104 -0
  85. data/spec/dummy/log/test.log +5031 -0
  86. data/spec/dummy/public/404.html +67 -0
  87. data/spec/dummy/public/422.html +67 -0
  88. data/spec/dummy/public/500.html +66 -0
  89. data/spec/dummy/public/favicon.ico +0 -0
  90. data/spec/factories/permissions.rb +6 -0
  91. data/spec/factories/role_permissions.rb +6 -0
  92. data/spec/factories/roles.rb +24 -0
  93. data/spec/factories/users.rb +11 -0
  94. data/spec/models/permission_spec.rb +28 -0
  95. data/spec/models/role_permission_spec.rb +27 -0
  96. data/spec/models/role_spec.rb +209 -0
  97. data/spec/models/user_spec.rb +44 -0
  98. data/spec/policies/application_policy_spec.rb +118 -0
  99. data/spec/policies/permission_policy_spec.rb +28 -0
  100. data/spec/policies/role_policy_spec.rb +28 -0
  101. data/spec/policies/user_policy_spec.rb +29 -0
  102. data/spec/requests/permissions_controller_spec.rb +19 -0
  103. data/spec/requests/registration_controller_spec.rb +151 -0
  104. data/spec/requests/roles_controller_spec.rb +75 -0
  105. data/spec/requests/users_controller_spec.rb +75 -0
  106. data/spec/spec_helper.rb +138 -0
  107. data/spec/stores/base_spec.rb +113 -0
  108. data/spec/stores/permission_store_spec.rb +2 -0
  109. data/spec/stores/role_store_spec.rb +12 -0
  110. data/spec/stores/user_store_spec.rb +144 -0
  111. data/spec/support/controller_concern_test_helpers.rb +21 -0
  112. data/spec/support/matchers.rb +37 -0
  113. data/spec/support/request_helpers.rb +111 -0
  114. metadata +508 -0
@@ -0,0 +1,44 @@
1
+ RSpec.describe ApiGuardian::User, type: :model do
2
+ subject { create(:user) }
3
+
4
+ # Relations
5
+ context 'relations' do
6
+ it { should belong_to(:role) }
7
+ end
8
+
9
+ # Validations
10
+ context 'validations' do
11
+ it { should validate_presence_of :email }
12
+ it { should validate_uniqueness_of :email }
13
+ it { should validate_length_of :password }
14
+ end
15
+
16
+ # Delegates
17
+ describe 'delegates' do
18
+ it { should delegate_method(:can?).to(:role) }
19
+ it { should delegate_method(:cannot?).to(:role) }
20
+ end
21
+
22
+ # Scopes
23
+ describe 'scopes' do
24
+ end
25
+
26
+ # Methods
27
+ context 'methods' do
28
+ describe '#reset_password_token_valid?' do
29
+ let!(:user) { create(:user) }
30
+
31
+ it 'is invalid if token was sent more than 24 hours ago' do
32
+ expect(user.reset_password_token_valid?).to be false
33
+
34
+ user.reset_password_sent_at = 30.hours.ago
35
+
36
+ expect(user.reset_password_token_valid?).to be false
37
+
38
+ user.reset_password_sent_at = 8.hours.ago
39
+
40
+ expect(user.reset_password_token_valid?).to be true
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,118 @@
1
+ describe ApiGuardian::Policies::ApplicationPolicy do
2
+ before(:each) do
3
+ FactoryGirl.create(:permission, name: 'user:create')
4
+ FactoryGirl.create(:permission, name: 'user:read')
5
+ FactoryGirl.create(:permission, name: 'user:update')
6
+ FactoryGirl.create(:permission, name: 'user:delete')
7
+ FactoryGirl.create(:permission, name: 'user:manage')
8
+ end
9
+
10
+ let(:current_user) { FactoryGirl.create(:user) }
11
+
12
+ subject { described_class }
13
+
14
+ context 'defaults to disallowing' do
15
+ let(:record) { FactoryGirl.create(:user) }
16
+
17
+ permissions :index? do
18
+ it { is_expected.not_to permit(current_user, record) }
19
+ end
20
+ end
21
+
22
+ context 'current_user has no permissions during' do
23
+ let(:record) { FactoryGirl.create(:user) }
24
+
25
+ permissions :show?, :create?, :new?, :update?, :edit?, :destroy? do
26
+ it { is_expected.not_to permit(current_user, record) }
27
+ end
28
+ end
29
+
30
+ context 'current_user has read permissions during' do
31
+ let(:record) { FactoryGirl.create(:user) }
32
+
33
+ permissions :show? do
34
+ it { is_expected.not_to permit(current_user, record) }
35
+ end
36
+
37
+ permissions :show? do
38
+ let(:current_user) do
39
+ user = FactoryGirl.create(:user)
40
+ user.role.add_permission('user:read')
41
+ user
42
+ end
43
+ it { is_expected.to permit(current_user, record) }
44
+ end
45
+ end
46
+
47
+ context 'current_user has create permissions during' do
48
+ let(:record) { FactoryGirl.create(:user) }
49
+
50
+ permissions :create? do
51
+ it { is_expected.not_to permit(current_user, record) }
52
+ end
53
+
54
+ permissions :create? do
55
+ let(:current_user) do
56
+ user = FactoryGirl.create(:user)
57
+ user.role.add_permission('user:create')
58
+ user
59
+ end
60
+ it { is_expected.to permit(current_user, record) }
61
+ end
62
+ end
63
+
64
+ context 'current_user has update permissions during' do
65
+ let(:record) { FactoryGirl.create(:user) }
66
+
67
+ permissions :update? do
68
+ it { is_expected.not_to permit(current_user, record) }
69
+ end
70
+
71
+ permissions :update? do
72
+ let(:current_user) do
73
+ user = FactoryGirl.create(:user)
74
+ user.role.add_permission('user:update')
75
+ user
76
+ end
77
+ it { is_expected.to permit(current_user, record) }
78
+ end
79
+ end
80
+
81
+ context 'current_user has delete permissions during' do
82
+ let(:record) { FactoryGirl.create(:user) }
83
+
84
+ permissions :destroy? do
85
+ it { is_expected.not_to permit(current_user, record) }
86
+ end
87
+
88
+ permissions :destroy? do
89
+ let(:current_user) do
90
+ user = FactoryGirl.create(:user)
91
+ user.role.add_permission('user:delete')
92
+ user
93
+ end
94
+ it { is_expected.to permit(current_user, record) }
95
+ end
96
+ end
97
+
98
+ context 'current_user has manage permissions during' do
99
+ let(:record) { FactoryGirl.create(:user) }
100
+
101
+ permissions :show? do
102
+ it { is_expected.not_to permit(current_user, record) }
103
+ end
104
+
105
+ permissions :show?, :create?, :new?, :update?, :edit?, :destroy? do
106
+ let(:current_user) do
107
+ user = FactoryGirl.create(:user)
108
+ user.role.add_permission('user:manage')
109
+ user
110
+ end
111
+ it { is_expected.to permit(current_user, record) }
112
+ end
113
+ end
114
+
115
+ # permissions '.scope' do
116
+ # pending 'add some examples to (or delete) #{__FILE__}'
117
+ # end
118
+ end
@@ -0,0 +1,28 @@
1
+ # require 'spec_helper'
2
+ #
3
+ # describe PermissionPolicy do
4
+ #
5
+ # let(:user) { User.new }
6
+ #
7
+ # subject { described_class }
8
+ #
9
+ # permissions ".scope" do
10
+ # pending "add some examples to (or delete) #{__FILE__}"
11
+ # end
12
+ #
13
+ # permissions :show? do
14
+ # pending "add some examples to (or delete) #{__FILE__}"
15
+ # end
16
+ #
17
+ # permissions :create? do
18
+ # pending "add some examples to (or delete) #{__FILE__}"
19
+ # end
20
+ #
21
+ # permissions :update? do
22
+ # pending "add some examples to (or delete) #{__FILE__}"
23
+ # end
24
+ #
25
+ # permissions :destroy? do
26
+ # pending "add some examples to (or delete) #{__FILE__}"
27
+ # end
28
+ # end
@@ -0,0 +1,28 @@
1
+ # require 'spec_helper'
2
+ #
3
+ # describe RolePolicy do
4
+ #
5
+ # let(:user) { User.new }
6
+ #
7
+ # subject { described_class }
8
+ #
9
+ # permissions ".scope" do
10
+ # pending "add some examples to (or delete) #{__FILE__}"
11
+ # end
12
+ #
13
+ # permissions :show? do
14
+ # pending "add some examples to (or delete) #{__FILE__}"
15
+ # end
16
+ #
17
+ # permissions :create? do
18
+ # pending "add some examples to (or delete) #{__FILE__}"
19
+ # end
20
+ #
21
+ # permissions :update? do
22
+ # pending "add some examples to (or delete) #{__FILE__}"
23
+ # end
24
+ #
25
+ # permissions :destroy? do
26
+ # pending "add some examples to (or delete) #{__FILE__}"
27
+ # end
28
+ # end
@@ -0,0 +1,29 @@
1
+ describe ApiGuardian::Policies::UserPolicy do
2
+ before(:each) do
3
+ FactoryGirl.create(:permission, name: 'user:create')
4
+ FactoryGirl.create(:permission, name: 'user:read')
5
+ FactoryGirl.create(:permission, name: 'user:update')
6
+ FactoryGirl.create(:permission, name: 'user:delete')
7
+ FactoryGirl.create(:permission, name: 'user:manage')
8
+ end
9
+
10
+ let(:current_user) { FactoryGirl.create(:user) }
11
+
12
+ subject { described_class }
13
+
14
+ context 'when current_user and user match for' do
15
+ permissions :show?, :update?, :edit? do
16
+ let(:record) { current_user }
17
+ it { is_expected.to permit(current_user, record) }
18
+ end
19
+
20
+ permissions :create?, :new?, :destroy? do
21
+ let(:record) { current_user }
22
+ it { is_expected.not_to permit(current_user, record) }
23
+ end
24
+ end
25
+
26
+ # permissions '.scope' do
27
+ # pending 'add some examples to (or delete) #{__FILE__}'
28
+ # end
29
+ end
@@ -0,0 +1,19 @@
1
+ describe 'ApiGuardian::PermissionsController' do
2
+ # Authentication and permissions are tested elsewhere
3
+ before(:each) { @routes = ApiGuardian::Engine.routes }
4
+ before(:each) { seed_permissions('permission') }
5
+ before(:each) { auth_user }
6
+ after(:each) { destroy_user }
7
+
8
+ describe 'RESOURCE /permissions' do
9
+ describe 'GET /' do
10
+ it 'returns a list of permissions' do
11
+ add_user_permission('permission:read')
12
+
13
+ get '/permissions', {}, get_headers
14
+
15
+ expect(response).to have_http_status(:ok)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,151 @@
1
+ describe 'Registration' do
2
+ before(:each) do
3
+ create(:default_role)
4
+ end
5
+
6
+ let(:headers) { { 'Accept' => 'application/json', 'Content-Type' => 'application/json' } }
7
+
8
+ describe 'POST /register' do
9
+ it 'registers a user' do
10
+ expect(ApiGuardian::Stores::UserStore).to receive(:register).and_return(true)
11
+
12
+ post '/register', {}, headers
13
+
14
+ expect(response).to have_http_status(:created)
15
+ # TODO: Validate JSON output
16
+ end
17
+
18
+ # it 'fails on invalid email' do
19
+ # data = {password: 'password', password_confirmation: 'password' }
20
+ #
21
+ # post '/register', data.to_json, headers
22
+ #
23
+ # validate_unprocessable_entity(
24
+ # [{field: 'email', detail: 'can\'t be blank' }]
25
+ # )
26
+ # end
27
+ #
28
+ # it 'fails on duplicate email' do
29
+ # email = Faker::Internet.email
30
+ # create(:user, email: email)
31
+ # data = { email: email, password: 'password', password_confirmation: 'password' }
32
+ #
33
+ # post '/register', data.to_json, headers
34
+ #
35
+ # validate_unprocessable_entity(
36
+ # [{field: 'email', detail: 'has already been taken' }]
37
+ # )
38
+ # end
39
+ #
40
+ # it 'fails on password mismatch' do
41
+ # data = { email: Faker::Internet.email, password: 'password', password_confirmation: 'password1' }
42
+ #
43
+ # post '/register', data.to_json, headers
44
+ #
45
+ # validate_unprocessable_entity(
46
+ # [{field: 'password_confirmation', detail: 'doesn\'t match Password' }]
47
+ # )
48
+ # end
49
+ #
50
+ # it 'fails on password length error' do
51
+ # data = { email: Faker::Internet.email, password: 'pass', password_confirmation: 'pass' }
52
+ #
53
+ # post '/register', data.to_json, headers
54
+ #
55
+ # validate_unprocessable_entity(
56
+ # [{field: 'password', detail: 'is too short (minimum is 8 characters)' }]
57
+ # )
58
+ # end
59
+ end
60
+
61
+ describe 'POST /reset-password' do
62
+ it 'resets a users password' do
63
+ # TODO: don't skip params
64
+ allow_any_instance_of(ActionController::Parameters).to receive(:fetch).and_return({})
65
+ expect(ApiGuardian::Stores::UserStore).to receive(:reset_password).and_return(true)
66
+
67
+ post '/reset-password', {}, headers
68
+
69
+ expect(response).to have_http_status(:no_content)
70
+ end
71
+
72
+ it 'renders not found when user is missing' do
73
+ # TODO: don't skip params
74
+ allow_any_instance_of(ActionController::Parameters).to receive(:fetch).and_return({})
75
+ expect(ApiGuardian::Stores::UserStore).to receive(:reset_password).and_return(false)
76
+
77
+ post '/reset-password', {}, headers
78
+
79
+ validate_not_found '/reset-password'
80
+ end
81
+ end
82
+
83
+ describe 'POST /complete-reset-password' do
84
+ it 'completes the password reset process' do
85
+ expect(ApiGuardian::Stores::UserStore).to receive(:complete_reset_password).and_return(true)
86
+
87
+ post '/complete-reset-password', {}, headers
88
+
89
+ expect(response).to have_http_status(:no_content)
90
+ end
91
+
92
+ it 'renders not found when user is missing' do
93
+ expect(ApiGuardian::Stores::UserStore).to receive(:complete_reset_password).and_return(false)
94
+
95
+ post '/complete-reset-password', {}, headers
96
+
97
+ validate_not_found '/complete-reset-password'
98
+ end
99
+
100
+ # it 'fails when token mismatches user' do
101
+ # user = create(:user, email: Faker::Internet.email)
102
+ # user.reset_password_token = SecureRandom.hex(64)
103
+ # user.reset_password_sent_at = DateTime.now.utc
104
+ # user.save
105
+ #
106
+ # data = { email: Faker::Internet.email, token: user.reset_password_token, password: 'password', password_confirmatin: 'password' }
107
+ #
108
+ # post '/complete-reset-password', data.to_json, headers
109
+ #
110
+ # validate_api_error(
111
+ # status: 403,
112
+ # code: 'reset_token_mismatch',
113
+ # title: 'Reset Token Mismatch',
114
+ # detail: 'Reset token is not valid for the supplied email address.'
115
+ # )
116
+ # end
117
+
118
+ # it 'fails when token is expired' do
119
+ # user = create(:user, email: Faker::Internet.email)
120
+ # user.reset_password_token = SecureRandom.hex(64)
121
+ # user.reset_password_sent_at = 36.hours.ago.utc
122
+ # user.save
123
+ #
124
+ # data = { email: user.email, token: user.reset_password_token, password: 'password', password_confirmatin: 'password' }
125
+ #
126
+ # post '/complete-reset-password', data.to_json, headers
127
+ #
128
+ # validate_api_error(
129
+ # status: 403,
130
+ # code: 'reset_token_expired',
131
+ # title: 'Reset Token Expired',
132
+ # detail: 'This reset token has expired. Tokens are valid for 24 hours.'
133
+ # )
134
+ # end
135
+ #
136
+ # it 'fails when the password is blank' do
137
+ # user = create(:user, email: Faker::Internet.email)
138
+ # user.reset_password_token = SecureRandom.hex(64)
139
+ # user.reset_password_sent_at = DateTime.now.utc
140
+ # user.save
141
+ #
142
+ # data = { email: user.email, token: user.reset_password_token}
143
+ #
144
+ # post '/complete-reset-password', data.to_json, headers
145
+ #
146
+ # validate_unprocessable_entity(
147
+ # [{field: 'password', detail: 'can\'t be blank'}]
148
+ # )
149
+ # end
150
+ end
151
+ end
@@ -0,0 +1,75 @@
1
+ describe 'ApiGuardian::RolesController' do
2
+ # Authentication and permissions are tested elsewhere
3
+ before(:each) { @routes = ApiGuardian::Engine.routes }
4
+ before(:each) { seed_permissions('role') }
5
+ before(:each) { auth_user }
6
+ after(:each) { destroy_user }
7
+
8
+ describe 'RESOURCE /roles' do
9
+ describe 'GET /' do
10
+ it 'returns a list of roles' do
11
+ add_user_permission('role:read')
12
+
13
+ get '/roles', {}, 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 role' do
21
+ add_user_permission('role:create')
22
+ role = create(:role)
23
+
24
+ allow_any_instance_of(ApiGuardian::Stores::RoleStore).to receive(:create).and_return(role)
25
+
26
+ data = { data: { type: 'roles', attributes: { name: '', default: false, permissions: [] } } }
27
+
28
+ post '/roles', data.to_json, get_headers
29
+
30
+ expect(response).to have_http_status(:created)
31
+ end
32
+ end
33
+
34
+ describe 'GET /{:role_id}' do
35
+ it 'gets a role by id' do
36
+ add_user_permission('role:read')
37
+ role = create(:role)
38
+
39
+ allow_any_instance_of(ApiGuardian::Stores::RoleStore).to receive(:find).and_return(role)
40
+
41
+ get "/roles/#{role.id}", {}, get_headers
42
+
43
+ expect(response).to have_http_status(:ok)
44
+ end
45
+ end
46
+
47
+ describe 'PATCH /{:role_id}' do
48
+ it 'updates a role by id' do
49
+ add_user_permission('role:update')
50
+ role = create(:role)
51
+
52
+ allow_any_instance_of(ApiGuardian::Stores::RoleStore).to receive(:update).and_return(role)
53
+
54
+ data = { data: { type: 'roles', id: "#{role.id}", attributes: { name: Faker::Lorem.word, default: false } } }
55
+
56
+ patch "/roles/#{role.id}", data.to_json, get_headers
57
+
58
+ expect(response).to have_http_status(:ok)
59
+ end
60
+ end
61
+
62
+ describe 'DELETE /{:role_id}' do
63
+ it 'deletes a role by id' do
64
+ add_user_permission('role:delete')
65
+ role = create(:role)
66
+
67
+ allow_any_instance_of(ApiGuardian::Stores::RoleStore).to receive(:destroy).and_return(role)
68
+
69
+ delete "/roles/#{role.id}", {}, get_headers
70
+
71
+ expect(response).to have_http_status(:no_content)
72
+ end
73
+ end
74
+ end
75
+ end