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,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/404.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The page you were looking for doesn't exist.</h1>
62
+ <p>You may have mistyped the address or the page may have moved.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/422.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The change you wanted was rejected.</h1>
62
+ <p>Maybe you tried to change something you didn't have access to.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,66 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/500.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>We're sorry, but something went wrong.</h1>
62
+ </div>
63
+ <p>If you are the application owner check the logs for more information.</p>
64
+ </div>
65
+ </body>
66
+ </html>
File without changes
@@ -0,0 +1,6 @@
1
+ FactoryGirl.define do
2
+ factory :permission, class: ApiGuardian::Permission do |f|
3
+ f.sequence(:name) { |n| "#{Faker::Lorem.word} #{n}" }
4
+ f.sequence(:desc) { |n| "#{Faker::Lorem.sentence} #{n}" }
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ FactoryGirl.define do
2
+ factory :role_permission, class: ApiGuardian::RolePermission do
3
+ association :role, factory: :role
4
+ association :permission, factory: :permission
5
+ end
6
+ end
@@ -0,0 +1,24 @@
1
+ FactoryGirl.define do
2
+ factory :role, class: ApiGuardian::Role do
3
+ name { Faker::Lorem.word }
4
+ default false
5
+
6
+ factory :default_role do
7
+ default true
8
+ end
9
+
10
+ factory :role_with_permissions do
11
+ transient do
12
+ permission_count 5
13
+ end
14
+
15
+ after(:create) do |role, evaluator|
16
+ evaluator.permission_count.times do |n|
17
+ permission = create(:permission)
18
+ granted = n.even? ? true : false
19
+ create(:role_permission, role: role, permission: permission, granted: granted)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,11 @@
1
+ FactoryGirl.define do
2
+ factory :user, class: ApiGuardian::User do |f|
3
+ f.first_name { Faker::Name.first_name }
4
+ f.last_name { Faker::Name.last_name }
5
+ f.sequence(:email) { |n| "what#{n}@someplace.com" }
6
+ f.phone_number { Faker::PhoneNumber.phone_number }
7
+ f.password 'password'
8
+ f.password_confirmation 'password'
9
+ f.association :role, factory: :role_with_permissions
10
+ end
11
+ end
@@ -0,0 +1,28 @@
1
+ RSpec.describe ApiGuardian::Permission, type: :model do
2
+ subject { create(:permission) }
3
+
4
+ # Relations
5
+ context 'relations' do
6
+ it { should have_many(:role_permissions) }
7
+ it { should have_many(:roles) }
8
+ end
9
+
10
+ # Validations
11
+ context 'validations' do
12
+ it { should validate_presence_of :name }
13
+ it { should validate_presence_of :desc }
14
+ it { should validate_uniqueness_of :name }
15
+ end
16
+
17
+ # Delegates
18
+ describe 'delegates' do
19
+ end
20
+
21
+ # Scopes
22
+ describe 'scopes' do
23
+ end
24
+
25
+ # Methods
26
+ context 'methods' do
27
+ end
28
+ end
@@ -0,0 +1,27 @@
1
+ RSpec.describe ApiGuardian::RolePermission, type: :model do
2
+ subject { create(:role_permission) }
3
+
4
+ # Relations
5
+ context 'relations' do
6
+ it { should belong_to(:role) }
7
+ it { should belong_to(:permission) }
8
+ end
9
+
10
+ # Validations
11
+ context 'validations' do
12
+ # TODO: This has a weird test error
13
+ # it { should validate_uniqueness_of(:role_id).scoped_to(:permission_id).with_message('Permission combination already exists!') }
14
+ end
15
+
16
+ # Delegates
17
+ describe 'delegates' do
18
+ end
19
+
20
+ # Scopes
21
+ describe 'scopes' do
22
+ end
23
+
24
+ # Methods
25
+ context 'methods' do
26
+ end
27
+ end
@@ -0,0 +1,209 @@
1
+ RSpec.describe ApiGuardian::Role, type: :model do
2
+ # Relations
3
+ context 'relations' do
4
+ it { should have_many(:users) }
5
+ it { should have_many(:role_permissions) }
6
+ end
7
+
8
+ # Validations
9
+ context 'validations' do
10
+ it { should validate_presence_of :name }
11
+ it { should validate_uniqueness_of :name }
12
+
13
+ # TODO: Fix this
14
+ # context 'default should be unique' do
15
+ # context 'if true' do
16
+ # before { subject.default = true }
17
+ # it { should validate_uniqueness_of :default }
18
+ # end
19
+ #
20
+ # context 'unless false' do
21
+ # before { subject.default = false }
22
+ # it { should_not validate_uniqueness_of :default }
23
+ # end
24
+ # end
25
+ end
26
+
27
+ # Delegates
28
+ describe 'delegates' do
29
+ end
30
+
31
+ # Scopes
32
+ describe 'scopes' do
33
+ let!(:default_role) { create(:role, default: true) }
34
+ let!(:non_default_role) { create(:role) }
35
+
36
+ it '.default' do
37
+ expect(ApiGuardian::Role.default.all).to eq [default_role]
38
+ end
39
+ end
40
+
41
+ # Methods
42
+ context 'methods' do
43
+ describe '.default_role' do
44
+ let!(:default_role) { create(:role, default: true) }
45
+ let!(:non_default_role) { create(:role) }
46
+
47
+ it 'should return default role' do
48
+ expect(ApiGuardian::Role.default_role).to eq default_role
49
+ end
50
+ end
51
+
52
+ describe '#can? and #cannot?' do
53
+ let!(:role) { create(:role_with_permissions) }
54
+
55
+ it 'errors on invalid permisson' do
56
+ expect { role.can? 'invalid' }.to raise_error ApiGuardian::Errors::InvalidPermissionNameError
57
+ expect { role.cannot? 'invalid' }.to raise_error ApiGuardian::Errors::InvalidPermissionNameError
58
+ end
59
+
60
+ context 'with array of permissions' do
61
+ it 'is true if at least one permission is granted' do
62
+ granted_perm1 = role.role_permissions.where(granted: true).first.permission
63
+ granted_perm2 = role.role_permissions.where(granted: true).last.permission
64
+ nongranted_perm1 = role.role_permissions.where(granted: false).first.permission
65
+ nongranted_perm2 = role.role_permissions.where(granted: false).last.permission
66
+
67
+ # multiple granted permissions
68
+ expect(role.can?([granted_perm1.name, granted_perm2.name])).to be true
69
+ expect(role.cannot?([granted_perm1.name, granted_perm2.name])).to be false
70
+
71
+ # single granted permission
72
+ expect(role.can?([granted_perm1.name, nongranted_perm1.name])).to be true
73
+ expect(role.cannot?([granted_perm1.name, nongranted_perm1.name])).to be false
74
+
75
+ # no granted permissions
76
+ expect(role.can?([nongranted_perm1.name, nongranted_perm2.name])).to be false
77
+ expect(role.cannot?([nongranted_perm1.name, nongranted_perm2.name])).to be true
78
+ end
79
+ end
80
+
81
+ context 'with single permission' do
82
+ it 'is true if permission is granted' do
83
+ granted_perm = role.role_permissions.where(granted: true).first.permission
84
+ nongranted_perm = role.role_permissions.where(granted: false).first.permission
85
+
86
+ expect(role.can? granted_perm.name).to be true
87
+ expect(role.cannot? granted_perm.name).to be false
88
+ expect(role.can? nongranted_perm.name).to be false
89
+ expect(role.cannot? nongranted_perm.name).to be true
90
+ end
91
+ end
92
+ end
93
+
94
+ describe '#permissions' do
95
+ let!(:role) { create(:role_with_permissions) }
96
+
97
+ it 'returns an array of granted permission names' do
98
+ result = role.permissions
99
+
100
+ perms = []
101
+ role.role_permissions.each do |rp|
102
+ perms.push rp.permission.name if rp.granted
103
+ end
104
+
105
+ expect(result).to eq perms
106
+ end
107
+
108
+ it 'returns only manage permission if it exists' do
109
+ perm_read = create(:permission, name: 'user:read')
110
+ perm_create = create(:permission, name: 'user:create')
111
+ perm_manage = create(:permission, name: 'user:manage')
112
+
113
+ role.role_permissions.create!(permission: perm_read, granted: true)
114
+ role.role_permissions.create!(permission: perm_create, granted: true)
115
+ role.role_permissions.create!(permission: perm_manage, granted: true)
116
+
117
+ result = role.permissions
118
+
119
+ expect(result).not_to include('user:read')
120
+ expect(result).not_to include('user:create')
121
+ expect(result).to include('user:manage')
122
+ end
123
+ end
124
+
125
+ describe '#create_default_permissions' do
126
+ let!(:role) { create(:role_with_permissions) }
127
+
128
+ it 'should associate permissions that are not yet associated' do
129
+ expect(role.role_permissions.count).to eq 5 # default from factory
130
+
131
+ # When granted
132
+ perm1 = create(:permission)
133
+
134
+ role.create_default_permissions true
135
+
136
+ expect(role.role_permissions.count).to eq 6
137
+ expect(role.permissions).to include(perm1.name)
138
+
139
+ # When not granted
140
+ perm2 = create(:permission)
141
+
142
+ role.create_default_permissions false
143
+
144
+ expect(role.role_permissions.count).to eq 7
145
+ expect(role.permissions).not_to include(perm2.name)
146
+ end
147
+ end
148
+
149
+ describe '#add_permission' do
150
+ let!(:role) { create(:role_with_permissions) }
151
+
152
+ it 'errors on invalid permission' do
153
+ expect { role.add_permission 'invalid' }.to raise_error ApiGuardian::Errors::InvalidPermissionNameError
154
+ end
155
+
156
+ it 'allows permission to be added by name' do
157
+ expect(role.permissions.count).to eq 3
158
+
159
+ create(:permission, name: 'user:read')
160
+ role.add_permission('user:read')
161
+
162
+ expect(role.permissions.count).to eq 4
163
+ expect(role.permissions).to include('user:read')
164
+ end
165
+
166
+ it 'grants already added permission' do
167
+ expect(role.permissions.count).to eq 3
168
+ expect(role.role_permissions.count).to eq 5
169
+
170
+ perm = create(:permission, name: 'user:read')
171
+ role.role_permissions.create(permission: perm, granted: false)
172
+
173
+ expect(role.permissions.count).to eq 3
174
+ expect(role.role_permissions.count).to eq 6
175
+
176
+ role.add_permission('user:read')
177
+
178
+ expect(role.permissions.count).to eq 4
179
+ expect(role.role_permissions.count).to eq 6
180
+ end
181
+ end
182
+
183
+ describe '#remove_permission' do
184
+ let!(:role) { create(:role_with_permissions) }
185
+
186
+ it 'sets permission grant to false' do
187
+ perm_name = role.permissions.first
188
+ expect(role.permissions.count).to eq 3
189
+ expect(role.role_permissions.count).to eq 5
190
+
191
+ role.remove_permission(perm_name)
192
+
193
+ expect(role.permissions.count).to eq 2
194
+ expect(role.role_permissions.count).to eq 5
195
+ end
196
+
197
+ it 'can destroy permission altogether' do
198
+ perm_name = role.permissions.first
199
+ expect(role.permissions.count).to eq 3
200
+ expect(role.role_permissions.count).to eq 5
201
+
202
+ role.remove_permission(perm_name, true)
203
+
204
+ expect(role.permissions.count).to eq 2
205
+ expect(role.role_permissions.count).to eq 4
206
+ end
207
+ end
208
+ end
209
+ end