ez-permissions 0.1.2 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d61f8b0da7075fce3bcda936552795798409466554085d9204356871375e0bb9
4
- data.tar.gz: a978748b29533101823a8c42c3f723f17879777eac05be362d19d3cc3a603bc8
3
+ metadata.gz: e17eb8ad5fd168be1fc8a40908d613466f05df2cf724ad2989e8eb0ea98068b0
4
+ data.tar.gz: 42ab1e2a10d6c279139e034ecefbdc1b60e36ed8de464904d4f0fb067650c971
5
5
  SHA512:
6
- metadata.gz: 10d393a8297ec27fd7bcf478d7e47d5c62fbfa8a1268428fb588933a967a98a919b75037746a82a93fa10b329ee495b559e2880b3ce5f37c214ed26c7976f0b5
7
- data.tar.gz: a7c3a76e50a9d380ed43f393fc1901db3ff3eb26e8321d0fb1fb2915f96542a4c34bfcd422029a35fa864740f7ed144648e325b59d3be84a6a12c3847eb88164
6
+ metadata.gz: 7b8b712c799ce127b6ec8e2d3a5f95e8b2d79a36c693f846263dc18f0faf256cadc0c92a792dee8e15b054a1beb77c49f8d62ec3438187f1b82efbed9507b784
7
+ data.tar.gz: 901a12fb2c742deb2f17d3dab4082e8bdeab288101d34a1434ad68dc16d860e456c325567345374494a6f2930a022d7c1c58ec7c9771fe29b313eaaa1d701621
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Ez::Permissions
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/ez-permissions.svg)](https://badge.fury.io/rb/ez-permissions)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
5
  [![Build Status](https://travis-ci.org/ez-engines/ez-permissions.svg?branch=master)](https://travis-ci.org/ez-engines/ez-permissions)
5
6
 
6
7
  **Ez Permissions** (read as "easy permissions") - one of the [ez-engines](https://github.com/ez-engines) collection that helps easily add permissions interface to your [Rails](http://rubyonrails.org/) application.
@@ -132,6 +133,13 @@ Permissions.assign_role(user, :admin, scoped: project)
132
133
 
133
134
  # Reject user role in global scope, but project admin role will stay
134
135
  Permissions.reject_role(user, :admin)
136
+
137
+ # Check if user includes global role
138
+ Permissions.includes_role?(user, :admin)
139
+
140
+ # Check if user includes scoped role
141
+ project = Project.first
142
+ Permissions.includes_role?(user, :manager, scoped: project)
135
143
  ```
136
144
 
137
145
  ### Permissions
@@ -169,6 +177,45 @@ Ez::Permissions::API::Authrozation::NotAuthorized
169
177
  # if you don't want raise exception, just use
170
178
  Permissions.authorize(user, :create, :users) { puts 'Yeahh!' } #=> false
171
179
  # Because user has scoped role in the project and don't has global role.
180
+
181
+ # and for simple cases you can always ask if user can something
182
+ Permissions.can?(user, :create, :users) => # true
183
+ Permissions.can?(user, :create, :users, scoped: project) => # false
184
+ ```
185
+
186
+ ### Testing
187
+ EzPermissions ships with bunch of RSpec helper methods that helps mock permission.
188
+ For large test suite (more than 5000 specs) it saves up to 30% of test runs time.
189
+
190
+ Add test helpers tou your rspec config
191
+ ```ruby
192
+ require 'ez/permissions/rspec_helpers'
193
+
194
+ RSpec.configure do |config|
195
+ config.include Ez::Permissions::RSpecHelpers
196
+ end
197
+
198
+ ```
199
+
200
+ Examples:
201
+ ```ruby
202
+ user = User.first
203
+ project = Project.first
204
+
205
+ # Mock role, model role, all permissions and user assigned role. DB will not be touched.
206
+ assume_user_permissions(user, :admin, :all)
207
+
208
+ # In case when you need real records data to be stored in DB, use
209
+ seed_user_permissions(user, :admin, :create, :update, :users, scoped: project)
210
+
211
+ # Mock role and who possible could has or not this role
212
+ mock_role(:manager, has: [user], has_not: [User.second], scoped: project)
213
+
214
+ # Mock model (user) role assignment
215
+ mock_model_role(:worker, user)
216
+
217
+ # Mock permissions for resources/action
218
+ mock_permission(:users, :create)
172
219
  ```
173
220
 
174
221
  ### Kepp it excplicit!
@@ -13,7 +13,7 @@ module Ez
13
13
  def authorize(model, *actions, resource, scoped: nil, raise_exception: false)
14
14
  return handle_no_permission_model_callback.call(self) if handle_no_permission_model_callback && !model
15
15
 
16
- return yield if permissions(model, *actions, resource, scoped: scoped).any?
16
+ return yield if can?(model, *actions, resource, scoped: scoped)
17
17
 
18
18
  return handle_not_authorized_callback.call(self) if handle_not_authorized_callback
19
19
 
@@ -22,12 +22,16 @@ module Ez
22
22
  false
23
23
  end
24
24
 
25
+ def can?(model, *actions, resource, scoped: nil)
26
+ permissions(model, *actions, resource, scoped: scoped).any?
27
+ end
28
+
25
29
  private
26
30
 
27
31
  def permissions(model, *actions, resource, scoped: nil)
28
32
  # TODO: Refactor to 1 query with joins
29
- roles_ids = model.assigned_roles.where(scoped: scoped).pluck(:role_id)
30
- permission_ids = Ez::Permissions::PermissionRole.where(role_id: roles_ids).pluck(:permission_id)
33
+ role_ids = model.assigned_roles.where(scoped: scoped).pluck(:role_id)
34
+ permission_ids = Ez::Permissions::PermissionRole.where(role_id: role_ids).pluck(:permission_id)
31
35
 
32
36
  Ez::Permissions::Permission.where(
33
37
  id: permission_ids,
@@ -17,11 +17,23 @@ module Ez
17
17
  def reject_role(model, role_name, scoped: nil)
18
18
  role = Ez::Permissions::API.get_role!(role_name)
19
19
 
20
+ model_role(role, model, scoped)&.delete
21
+ end
22
+
23
+ def includes_role?(model, role_name, scoped: nil)
24
+ role = Ez::Permissions::API.get_role!(role_name)
25
+
26
+ model_role(role, model, scoped) ? true : false
27
+ end
28
+
29
+ private
30
+
31
+ def model_role(role, model, scoped)
20
32
  Ez::Permissions::ModelRole.find_by(
21
33
  role: role,
22
34
  model: model,
23
35
  scoped: scoped
24
- )&.delete
36
+ )
25
37
  end
26
38
  end
27
39
  end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable all
4
+ module Ez
5
+ module Permissions
6
+ module RSpecHelpers
7
+ def seed_user_permissions(user, role, *actions, resource, scoped: nil)
8
+ Ez::Permissions::API.create_role(role)
9
+
10
+ actions.each do |action|
11
+ Ez::Permissions::API.grant_permission(role, action, resource)
12
+ end
13
+
14
+ Ez::Permissions::API.assign_role(user, role, scoped: scoped)
15
+ end
16
+
17
+ def assume_user_permissions(model, role, *actions, resource, scoped: nil)
18
+ # ROLE
19
+ mocked_role = mock_role(role) # ROLE
20
+
21
+ # MODEL ROLE
22
+ allow(Ez::Permissions::ModelRole).to receive(:find_by).with(
23
+ role: mocked_role,
24
+ model: model,
25
+ scoped: scoped
26
+ ).and_return(mock_model_role(mocked_role, model, scoped: scoped))
27
+
28
+ # PERMISSIONS
29
+ mocked_permissions = actions.map { |action| mock_permission(resource, action) }
30
+
31
+ # USER ROLES
32
+ mocked_assiges_roles = double(:mocked_assiges_roles, where: [], size: 1, first: mocked_role)
33
+ mocked_roles = double(:mocked_roles, pluck: [])
34
+
35
+ # USER PERMISSION MODEL
36
+ allow(model).to receive(:assigned_roles).and_return(mocked_assiges_roles)
37
+ allow(mocked_assiges_roles).to receive(:where).with(scoped: scoped).and_return(mocked_roles)
38
+ allow(mocked_roles).to receive(:pluck).with(:role_id).and_return [mocked_role.id]
39
+
40
+ mocked_permission_role = double(:mocked_permission_role, pluck: [])
41
+ allow(Ez::Permissions::PermissionRole).to receive(:where).with(role_id: [mocked_role.id]).and_return(mocked_permission_role)
42
+ allow(mocked_permission_role).to receive(:pluck).with(:permission_id).and_return(mocked_permissions.map(&:id))
43
+
44
+ # USER PERMISSION MODEL for scoped access
45
+ mocked_empty_permission_role = double(:mocked_permission_role, pluck: [])
46
+ allow(Ez::Permissions::PermissionRole).to receive(:where).with(role_id: []).and_return(mocked_empty_permission_role)
47
+ allow(mocked_empty_permission_role).to receive(:pluck).with(:permission_id).and_return([])
48
+
49
+ # PERMISSIONS
50
+ allow(Ez::Permissions::Permission).to receive(:where).with(
51
+ id: mocked_permissions.map(&:id),
52
+ resource: resource,
53
+ action: actions.map(&:to_s)
54
+ ).and_return(mocked_permissions)
55
+
56
+ # PERMISSIONS missing for all other actions
57
+ other_resource_actions = Ez::Permissions::DSL.resource(resource).actions.reject { |a| actions.include?(a) }.map(&:to_s)
58
+
59
+ allow(Ez::Permissions::Permission).to receive(:where).with(
60
+ id: mocked_permissions.map(&:id),
61
+ resource: resource,
62
+ action: other_resource_actions
63
+ ).and_return([])
64
+
65
+ # PERMISSIONS missing for scoped access
66
+ allow(Ez::Permissions::Permission).to receive(:where).with(
67
+ id: [],
68
+ resource: resource,
69
+ action: actions.map(&:to_s)
70
+ ).and_return([])
71
+ end
72
+
73
+ def mock_role(name, has: [], has_not: [], scoped: nil)
74
+ mocked_role = double(:role, id: rand(1..99_999), name: name.to_s)
75
+
76
+ allow(Ez::Permissions::Role).to receive(:find_by).with(name: name).and_return(mocked_role)
77
+ allow(Ez::Permissions::Role).to receive(:find_by!).with(name: name).and_return(mocked_role)
78
+
79
+ has.each do |model|
80
+ mock_model_role(mocked_role, model, scoped: scoped)
81
+ end
82
+
83
+ has_not.each do |model|
84
+ allow(Ez::Permissions::ModelRole).to receive(:find_by).with(
85
+ role: mocked_role,
86
+ model: model,
87
+ scoped: scoped
88
+ ).and_return(nil)
89
+ end
90
+
91
+ # Allow any model to assign the role
92
+ allow(Ez::Permissions::ModelRole).to receive(:find_or_create_by!).with(
93
+ role: mocked_role,
94
+ model: anything,
95
+ scoped: scoped
96
+ ).and_return(double(:mocked_model_role))
97
+
98
+ mocked_role
99
+ end
100
+
101
+ def mock_model_role(role, model, scoped: nil)
102
+ mocked_model_role = double(:mocked_model_role, role: role, model: model, scoped: scoped)
103
+
104
+ allow(Ez::Permissions::ModelRole).to receive(:find_by).with(
105
+ role: role,
106
+ model: model,
107
+ scoped: scoped
108
+ ).and_return(mocked_model_role)
109
+
110
+ allow(Ez::Permissions::ModelRole).to receive(:find_or_create_by!).with(
111
+ role: role,
112
+ model: model,
113
+ scoped: scoped
114
+ ).and_return(mocked_model_role)
115
+ end
116
+
117
+ def mock_permission(resource, action)
118
+ mocked_permission = double(:permission, id: rand(1..99_999), resource: resource.to_s, action: action.to_s)
119
+
120
+ allow(Ez::Permissions::Permission)
121
+ .to receive(:find_by!)
122
+ .with(resource: resource, action: action)
123
+ .and_return(mocked_permission)
124
+
125
+ mocked_permission
126
+ end
127
+ end
128
+ end
129
+ end
130
+ # rubocop:enable all
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ez
4
4
  module Permissions
5
- VERSION = '0.1.2'
5
+ VERSION = '0.2.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ez-permissions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Volodya Sveredyuk
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-24 00:00:00.000000000 Z
11
+ date: 2019-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ez-core
@@ -178,6 +178,7 @@ files:
178
178
  - lib/ez/permissions/engine.rb
179
179
  - lib/ez/permissions/railtie.rb
180
180
  - lib/ez/permissions/resource.rb
181
+ - lib/ez/permissions/rspec_helpers.rb
181
182
  - lib/ez/permissions/version.rb
182
183
  - lib/generators/ez/permissions/install_generator.rb
183
184
  - lib/generators/ez/permissions/migrations_generator.rb