ez-permissions 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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