ez-permissions 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 63fcfa633d299ba98948f0139ad49873bbdd3098f45a6e714d2fb5da27f28b18
4
+ data.tar.gz: c392ff7f90575129d0c7c7a99d873c7552acf88d59b82460e766a3c42dac4461
5
+ SHA512:
6
+ metadata.gz: e6bb7cfe77c7b5f3c51d38d5e4f9349d2e59c7d8e47de0f9c728c66190453013fef6ce348cfef4bfcba40cda3d58296d1b7a047a0001c1358a1274b01cbc152b
7
+ data.tar.gz: 37c0fe0b3dd8f727b20f8a4820cdd56c95e29dd413b0317c8f0cee204fe9e152129805a96f4a402e90255571b1b9ce9c0d8610af5057d07a31eb635d9806bd52
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2019 Volodymyr Sveredyuk
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,210 @@
1
+ # Ez::Permissions
2
+
3
+ [![Build Status](https://travis-ci.org/ez-engines/ez-permissions.svg?branch=master)](https://travis-ci.org/ez-engines/ez-permissions)
4
+
5
+ **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.
6
+
7
+ - Most advanced RBAC model:
8
+ - Flexible tool with simple DSL and confguration
9
+ - All in one solution
10
+ - Convetion over configuration principles.
11
+ - Depends on [ez-core](https://github.com/ez-engines/ez-core)
12
+
13
+ ## Installation
14
+ Add this line to your application's Gemfile:
15
+ ```ruby
16
+ gem 'ez-permissions'
17
+ ```
18
+
19
+ ## Generators
20
+
21
+ Generate configuration file:
22
+ ```bash
23
+ rails generate ez:permissions:install
24
+ ```
25
+
26
+ ### Configuration
27
+
28
+ Configuration interface allows you to change default behavior
29
+ ```ruby
30
+ Ez::Permissions.configure do |config|
31
+ # If in generated migrations you changed table names, please configure them here:
32
+ config.permission_table_name = 'my_permissions'
33
+ config.roles_table_name = 'my_roles'
34
+ config.models_roles_table_name = 'my_model_roles'
35
+ config.permissions_roles_table_name = 'my_permissions_roles'
36
+
37
+ # Define your custom callbacks
38
+ config.handle_no_permission_model = lambda { |context|
39
+ raise 'User not exist'
40
+ }
41
+
42
+ config.handle_not_authorized = lambda { |context|
43
+ raise 'Not authorized'
44
+ }
45
+ end
46
+
47
+ ```
48
+ ### ActiveRecord migrations:
49
+
50
+ **If you need change table names, please change configuration first**
51
+
52
+ And run
53
+ ```bash
54
+ rails generate ez:permissions:migrations
55
+ ```
56
+
57
+ ## DSL
58
+
59
+ Simple DSL for difinition of permission relationships
60
+ ```ruby
61
+ Ez::Permissions::DSL.define do |setup|
62
+ # You need add all resources of your application and possible actions
63
+ setup.add :roles, actions: %i[create read]
64
+
65
+ # Use `crud` for adding default `create`, `read`, `update` and `delete` actions
66
+ # And any your custom action
67
+ setup.add :permissions, actions: %i[crud my_custom_action]
68
+
69
+ # Actions option are not required. In such case you add all crud actions by default
70
+ setup.add :users
71
+ setup.add :projects
72
+ end
73
+ ```
74
+
75
+ ## Permission model
76
+
77
+ In your application, you usually have `User` model.
78
+ ```ruby
79
+ class User < ActiveRecord::Base
80
+ include Ez::Permissions::Model
81
+ end
82
+
83
+ user = User.first
84
+
85
+ # User model become permission model
86
+ user.roles #=> [application level roles]
87
+ user.assigned_roles #=> [user owned roles, gloabal and scoped]
88
+ user.permissions #=> [user available permissions through assigned_roles]
89
+ ```
90
+
91
+ ## API
92
+
93
+ **Please, do not use direct rails code like:** `Ez::Permissions::Permission.create(name: 'admin')`
94
+
95
+ Instead you should use public api. You can extend you custom module with `API` mixin
96
+ ```ruby
97
+ # Use engine facade methods
98
+ Ez::Permissions::API
99
+
100
+ # or extend your own module and keep your code clean
101
+ module Permissions
102
+ extend Ez::Permissions::API::Roles
103
+ extend Ez::Permissions::API::Permissions
104
+ extend Ez::Permissions::API::Models
105
+ extend Ez::Permissions::API::Authorize
106
+ end
107
+ ```
108
+
109
+ ### Roles
110
+ ```ruby
111
+ # Create regular role
112
+ Permissions.create_role(:user)
113
+ Permissions.create_role(:admin)
114
+
115
+ # Get role object by name
116
+ Permissions.get_role(:user)
117
+
118
+ # Update role attributes
119
+ Permissions.update_role(:user, name: 'super_user')
120
+
121
+ # Delete role
122
+ Permissions.delete_role(:user)
123
+
124
+ # Assign role to the user
125
+ user = User.first
126
+ Permissions.assign_role(user, :admin)
127
+
128
+ # Assign role to the user in scope of any resource
129
+ project = Project.first
130
+ Permissions.assign_role(user, :admin, scoped: project)
131
+
132
+ # Reject user role in global scope, but project admin role will stay
133
+ Permissions.reject_role(user, :admin)
134
+ ```
135
+
136
+ ### Permissions
137
+ ```ruby
138
+ # Create a role
139
+ Permissions.create_role(:user)
140
+
141
+ # Grant role's possibility to have action per resource
142
+ Permissions.grant_permission(:user, :read, :projects)
143
+
144
+ # Grant all defined actions per resource
145
+ Permissions.grant_permission(:user, :all, :projects)
146
+
147
+ # Revoke particular permission
148
+ Permissions.revoke_permission(:user, :create, :projects)
149
+ ```
150
+
151
+ ### Authorize access
152
+ ```ruby
153
+ user = User.first
154
+ project = Project.first
155
+
156
+ Permissions.create_role(:admin)
157
+ Permissions.grant_permission(:admin, :all, :users)
158
+ Permissions.assign_role(user, :admin, scoped: project)
159
+
160
+ Permissions.authorize!(user, :create, :users, scoped: project) do
161
+ # code here would be executed if user has permissions
162
+ # for user creation in particular project
163
+ end
164
+
165
+ # otherwise catch exception
166
+ Ez::Permissions::API::Authrozation::NotAuthorized
167
+
168
+ # if you don't want raise exception, just use
169
+ Permissions.authorize(user, :create, :users) { puts 'Yeahh!' } #=> false
170
+ # Because user has scoped role in the project and don't has global role.
171
+ ```
172
+
173
+ ### Kepp it excplicit!
174
+ You can wonder, why we just not add authorization methods to user instance, like:
175
+ ```ruby
176
+ user.can?(:something)
177
+ ```
178
+ Because ez-permissions engine don't want pollute your application and keep implementation isolated in external modules.
179
+ Of course, you can use them as mixins, but it's up to you.
180
+
181
+ ## Understanding scoped roles
182
+ - System have many roles
183
+ - User has many assigned roles
184
+ - User can has role in scope of some resource (Project, Company, Business, etc.)
185
+ - User can has role in global scope (without scope)
186
+ - If user want access data in scope of resource - user must has assigned role scoped for this resource
187
+ - If user want access data in global scope - user must has assigned role wihtout any scoped resorce (global role)
188
+ - User with global role - can't access scoped resources.
189
+ - User with scoped role - can't access global resources.
190
+
191
+ ## TODO
192
+ - [x] Add README
193
+ - [x] Add Role model
194
+ - [x] Add Permissions model
195
+ - [x] Add PermissionsRole model
196
+ - [x] Add rails generators for migrations
197
+ - [x] Add rails generators for configuration
198
+ - [x] Add configuration DSL
199
+ - [x] Add Permissions API for managing relationships
200
+ - [x] User can has multiple roles
201
+ - [x] Better errors for non-existing records
202
+ - [x] Add permissions helpers `authorize` and `authorize!`
203
+ - [x] Move all erros under `Ez::Permissions::API` namespace and add `Error` suffix
204
+ - [ ] Add helper methods for seed grant permissions
205
+
206
+ ## Contributing
207
+ Contribution directions go here.
208
+
209
+ ## License
210
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError
6
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ require 'rdoc/task'
10
+
11
+ RDoc::Task.new(:rdoc) do |rdoc|
12
+ rdoc.rdoc_dir = 'rdoc'
13
+ rdoc.title = 'Ez::Permissions'
14
+ rdoc.options << '--line-numbers'
15
+ rdoc.rdoc_files.include('README.md')
16
+ rdoc.rdoc_files.include('lib/**/*.rb')
17
+ end
18
+
19
+ APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
20
+ load 'rails/tasks/engine.rake'
21
+
22
+ load 'rails/tasks/statistics.rake'
23
+
24
+ require 'bundler/gem_tasks'
25
+
26
+ require 'rspec/core/rake_task'
27
+
28
+ RSpec::Core::RakeTask.new(:spec)
29
+
30
+ task default: :spec
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # TODO: Use this for potential UI or API features
4
+ # module Ez
5
+ # module Permissions
6
+ # class ApplicationController < ActionController::Base
7
+ # protect_from_forgery with: :exception
8
+ # end
9
+ # end
10
+ # end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ez
4
+ module Permissions
5
+ class ApplicationRecord < ActiveRecord::Base
6
+ self.abstract_class = true
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ez
4
+ module Permissions
5
+ module Model
6
+ # rubocop:disable Metrics/MethodLength
7
+ def self.included(base)
8
+ base.has_many :assigned_roles,
9
+ class_name: 'Ez::Permissions::ModelRole',
10
+ as: :model
11
+
12
+ base.has_many :roles,
13
+ -> { distinct },
14
+ through: :assigned_roles,
15
+ class_name: 'Ez::Permissions::Role'
16
+
17
+ base.has_many :permissions,
18
+ -> { distinct },
19
+ through: :roles,
20
+ class_name: 'Ez::Permissions::Permission'
21
+ end
22
+ # rubocop:enable Metrics/MethodLength
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ez
4
+ module Permissions
5
+ class ModelRole < ApplicationRecord
6
+ self.table_name = Ez::Permissions.config.models_roles_table_name
7
+
8
+ belongs_to :model, polymorphic: true
9
+ belongs_to :scoped, polymorphic: true, optional: true
10
+ belongs_to :role
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ez
4
+ module Permissions
5
+ class Permission < ApplicationRecord
6
+ self.table_name = Ez::Permissions.config.permissions_table_name
7
+
8
+ validates :resource, presence: true
9
+ validates :action, presence: true
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ez
4
+ module Permissions
5
+ class PermissionRole < ApplicationRecord
6
+ self.table_name = Ez::Permissions.config.permissions_roles_table_name
7
+
8
+ belongs_to :permission, class_name: 'Ez::Permissions::Permission'
9
+ belongs_to :role, class_name: 'Ez::Permissions::Role'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ez
4
+ module Permissions
5
+ class Role < ApplicationRecord
6
+ self.table_name = Ez::Permissions.config.roles_table_name
7
+
8
+ has_and_belongs_to_many :permissions
9
+
10
+ validates :name, presence: true
11
+ validates :name, uniqueness: true
12
+ end
13
+ end
14
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # TODO: Use this for potential UI or API features
4
+ # Ez::Permissions::Engine.routes.draw do
5
+ # end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ez
4
+ module Permissions
5
+ module API
6
+ module Authorize
7
+ NotAuthorized = Class.new(StandardError)
8
+
9
+ def authorize!(model, *actions, resource, scoped: nil, &block)
10
+ authorize(model, *actions, resource, scoped: scoped, raise_exception: true, &block)
11
+ end
12
+
13
+ def authorize(model, *actions, resource, scoped: nil, raise_exception: false)
14
+ return handle_no_permission_model_callback.call(self) if handle_no_permission_model_callback && !model
15
+
16
+ return yield if permissions(model, *actions, resource, scoped: scoped).any?
17
+
18
+ return handle_not_authorized_callback.call(self) if handle_not_authorized_callback
19
+
20
+ raise NotAuthorized, not_authorized_msg(model, actions, resource, scoped) if raise_exception
21
+
22
+ false
23
+ end
24
+
25
+ private
26
+
27
+ def permissions(model, *actions, resource, scoped: nil)
28
+ # 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)
31
+
32
+ Ez::Permissions::Permission.where(
33
+ id: permission_ids,
34
+ resource: resource,
35
+ action: actions.map(&:to_s)
36
+ )
37
+ end
38
+
39
+ def not_authorized_msg(model, actions, resource, scoped = nil)
40
+ msg = "#{model.class}##{model.id} is not authorized to [#{actions.join(', ')} -> #{resource}]"
41
+ msg = "#{msg} for #{scoped.class}##{scoped.id}" if scoped
42
+
43
+ msg
44
+ end
45
+
46
+ def handle_no_permission_model_callback
47
+ Ez::Permissions.config.handle_no_permission_model
48
+ end
49
+
50
+ def handle_not_authorized_callback
51
+ Ez::Permissions.config.handle_not_authorized
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ez
4
+ module Permissions
5
+ module API
6
+ module Models
7
+ def assign_role(model, role_name, scoped: nil)
8
+ role = Ez::Permissions::API.get_role!(role_name)
9
+
10
+ Ez::Permissions::ModelRole.find_or_create_by!(
11
+ role: role,
12
+ model: model,
13
+ scoped: scoped
14
+ )
15
+ end
16
+
17
+ def reject_role(model, role_name, scoped: nil)
18
+ role = Ez::Permissions::API.get_role!(role_name)
19
+
20
+ Ez::Permissions::ModelRole.find_by(
21
+ role: role,
22
+ model: model,
23
+ scoped: scoped
24
+ )&.delete
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ez
4
+ module Permissions
5
+ module API
6
+ module Permissions
7
+ PermissionNotFound = Class.new(StandardError)
8
+
9
+ def get_permission!(action, resource)
10
+ Ez::Permissions::Permission.find_by!(resource: resource, action: action)
11
+ rescue ActiveRecord::RecordNotFound
12
+ raise PermissionNotFound, "Permission [#{action} -> #{resource}] not found"
13
+ end
14
+
15
+ def grant_permission(role_name, action, resource)
16
+ role = Ez::Permissions::API.get_role!(role_name)
17
+
18
+ if action == :all
19
+ grant_all_permissions(role, resource)
20
+ else
21
+ permission = get_permission!(action, resource)
22
+ grant_single_permission(role, permission)
23
+ end
24
+ end
25
+
26
+ def revoke_permission(role_name, action, resource)
27
+ role = Ez::Permissions::API.get_role!(role_name)
28
+ permission = get_permission!(action, resource)
29
+
30
+ Ez::Permissions::PermissionRole.find_by(
31
+ role: role,
32
+ permission: permission
33
+ )&.delete
34
+ end
35
+
36
+ private
37
+
38
+ def grant_single_permission(role, permission)
39
+ Ez::Permissions::PermissionRole.find_or_create_by!(
40
+ role: role,
41
+ permission: permission
42
+ )
43
+ end
44
+
45
+ def grant_all_permissions(role, resource)
46
+ Ez::Permissions::DSL.resource(resource).actions.each do |action|
47
+ permission = get_permission!(action, resource)
48
+ grant_single_permission(role, permission)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ez
4
+ module Permissions
5
+ module API
6
+ module Roles
7
+ RoleNotFound = Class.new(StandardError)
8
+
9
+ def create_role(name)
10
+ Role.create(name: name)
11
+ end
12
+
13
+ def get_role(name)
14
+ Role.find_by(name: name)
15
+ end
16
+
17
+ def get_role!(name)
18
+ Role.find_by!(name: name)
19
+ rescue ActiveRecord::RecordNotFound
20
+ raise RoleNotFound, "Role #{name} not found"
21
+ end
22
+
23
+ def update_role(role_name, name:)
24
+ role = get_role!(role_name)
25
+
26
+ role.update(name: name)
27
+ end
28
+
29
+ def delete_role(name)
30
+ role = get_role!(name)
31
+
32
+ role.delete
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'api/roles'
4
+ require_relative 'api/permissions'
5
+ require_relative 'api/models'
6
+ require_relative 'api/authorize'
7
+
8
+ module Ez
9
+ module Permissions
10
+ module API
11
+ extend Ez::Permissions::API::Roles
12
+ extend Ez::Permissions::API::Permissions
13
+ extend Ez::Permissions::API::Models
14
+ extend Ez::Permissions::API::Authorize
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'resource'
4
+
5
+ module Ez
6
+ module Permissions
7
+ class DSL
8
+ include Singleton
9
+
10
+ def self.define
11
+ yield DSL.instance
12
+ end
13
+
14
+ def self.resources
15
+ DSL.instance.resources
16
+ end
17
+
18
+ def self.resource(name)
19
+ DSL.instance.resources.find { |r| r.name.to_sym == name.to_sym }
20
+ end
21
+
22
+ attr_reader :resources
23
+
24
+ def initialize
25
+ @resources = []
26
+ end
27
+
28
+ def add(name, options = {})
29
+ if self.class.resource(name)
30
+ return message("[WARN] Ez::Permissions resource [#{name}] has been already defined!")
31
+ end
32
+
33
+ resource = Ez::Permissions::Resource.new(name, options)
34
+
35
+ message(
36
+ "[SUCCESS] Ez::Permissions resource [#{name}] has been successfully registred with actions: \
37
+ [#{resource.actions.join(', ')}]"
38
+ )
39
+
40
+ @resources << resource
41
+ seed_to_db resource
42
+ end
43
+
44
+ private
45
+
46
+ def message(txt)
47
+ STDOUT.puts(txt)
48
+ end
49
+
50
+ def seed_to_db(resource)
51
+ try_db_connection
52
+
53
+ return unless ActiveRecord::Base.connection.data_source_exists?(Ez::Permissions.config.permissions_table_name)
54
+
55
+ return unless resource.actions
56
+
57
+ resource.actions.each do |action|
58
+ Ez::Permissions::Permission.where(
59
+ resource: resource.name,
60
+ action: action
61
+ ).first_or_create!
62
+ end
63
+ end
64
+
65
+ def try_db_connection
66
+ ActiveRecord::Base.connection
67
+ rescue ActiveRecord::NoDatabaseError
68
+ STDOUT.puts 'Database does not exist'
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ez
4
+ module Permissions
5
+ class Engine < ::Rails::Engine
6
+ isolate_namespace Ez::Permissions
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # TODO: Use this for potential UI or API features
4
+ # module Ez
5
+ # module Permissions
6
+ # class Railtie < ::Rails::Railtie
7
+ # end
8
+ # end
9
+ # end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ez
4
+ module Permissions
5
+ class Resource
6
+ ACTIONS = %i[create read update delete].freeze
7
+
8
+ attr_reader :name, :model, :actions
9
+
10
+ def initialize(name, options = {})
11
+ @name = name
12
+ @model = options.fetch(:model, nil)
13
+ @actions = process_actions(options.fetch(:actions, nil))
14
+ end
15
+
16
+ def <=>(other)
17
+ name <=> other.name
18
+ end
19
+
20
+ private
21
+
22
+ def process_actions(actions)
23
+ return ACTIONS unless actions
24
+
25
+ actions.map { |action| action == :crud ? ACTIONS : action }.flatten
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ez
4
+ module Permissions
5
+ VERSION = '0.1.0'
6
+ end
7
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ez/permissions/engine'
4
+ require 'ez/permissions/dsl'
5
+ require 'ez/permissions/api'
6
+ require 'ez/configurator'
7
+
8
+ module Ez
9
+ module Permissions
10
+ include Ez::Configurator
11
+
12
+ configure do |config|
13
+ config.permissions_table_name = 'ez_permissions_permissions'
14
+ config.roles_table_name = 'ez_permissions_roles'
15
+ config.models_roles_table_name = 'ez_permissions_model_roles'
16
+ config.permissions_roles_table_name = 'ez_permissions_permissions_roles'
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ez
4
+ module Permissions
5
+ class InstallGenerator < Rails::Generators::Base
6
+ def create_migration
7
+ create_file 'config/initializers/ez_permissions.rb',
8
+ "# frozen_string_literal: true
9
+
10
+ Ez::Permissions.configure do |config|
11
+ # config.permission_table_name = 'ez_permissions_permissions'
12
+ # config.roles_table_name = 'ez_permissions_roles'
13
+ # config.models_roles_table_name = 'ez_permissions_model_roles'
14
+ # config.permissions_roles_table_name = 'ez_permissions_permissions_roles'
15
+
16
+ # config.handle_no_permission_model = lambda { |context|
17
+ # here you can define your custom callback
18
+ # in case when permission model (user) is nil
19
+ # }
20
+
21
+ # config.handle_not_authorized = lambda { |context|
22
+ # here you can define your custom callback
23
+ # in case when model (user) is not authorized
24
+ # }
25
+ end
26
+ "
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable all
4
+ module Ez
5
+ module Permissions
6
+ class MigrationsGenerator < Rails::Generators::Base
7
+ def config
8
+ Ez::Permissions.config
9
+ end
10
+
11
+ def create_migration
12
+ create_file "db/migrate/#{Time.current.strftime('%Y%m%d%H%M%S')}_create_ez_permissions_roles.rb",
13
+ "# frozen_string_literal: true
14
+
15
+ class CreateEzPermissionsRoles < ActiveRecord::Migration[5.0]
16
+ def change
17
+ create_table :#{config.roles_table_name} do |t|
18
+ t.string :name, null: false
19
+ t.timestamps null: false
20
+ end
21
+ end
22
+ end
23
+ "
24
+ create_file "db/migrate/#{(Time.current + 1).strftime('%Y%m%d%H%M%S')}_create_ez_permissions_permissions.rb",
25
+ "# frozen_string_literal: true
26
+
27
+ class CreateEzPermissionsPermissions < ActiveRecord::Migration[5.0]
28
+ def change
29
+ create_table :#{config.permissions_table_name} do |t|
30
+ t.string :resource, index: true, null: false
31
+ t.string :action, index: true, null: false
32
+ t.timestamps null: false
33
+ end
34
+ end
35
+ end
36
+ "
37
+ create_file "db/migrate/#{(Time.current + 2).strftime('%Y%m%d%H%M%S')}_create_ez_permissions_model_roles.rb",
38
+ "# frozen_string_literal: true
39
+
40
+ class CreateEzPermissionsModelRoles < ActiveRecord::Migration[5.0]
41
+ def change
42
+ create_table :#{config.models_roles_table_name} do |t|
43
+ t.integer :model_id, index: true, null: false
44
+ t.string :model_type, index: true, null: false
45
+
46
+ t.integer :scoped_id, index: true
47
+ t.string :scoped_type, index: true
48
+
49
+ t.integer :role_id, index: true, null: false
50
+
51
+ t.timestamps null: false
52
+ end
53
+ end
54
+ end
55
+ "
56
+
57
+ create_file "db/migrate/#{(Time.current + 3).strftime('%Y%m%d%H%M%S')}_create_ez_permissions_permissions_roles.rb",
58
+ "# frozen_string_literal: true
59
+
60
+ class CreateEzPermissionsPermissionsRoles < ActiveRecord::Migration[5.0]
61
+ def change
62
+ create_table :#{config.permissions_roles_table_name} do |t|
63
+ t.integer :permission_id, index: true, null: false
64
+ t.integer :role_id, index: true
65
+ end
66
+ end
67
+ end
68
+ "
69
+ end
70
+ end
71
+ end
72
+ end
73
+ # rubocop: enable all
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # desc "Explaining what the task does"
4
+ # task :ez_permissions do
5
+ # # Task goes here
6
+ # end
metadata ADDED
@@ -0,0 +1,210 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ez-permissions
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Volodya Sveredyuk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-02-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ez-core
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '5.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '5.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: faker
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard-rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry-rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec-rails
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: sqlite3
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 1.3.6
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: 1.3.6
153
+ description: Easy permissions engine for Rails app.
154
+ email:
155
+ - sveredyuk@gmail.com
156
+ executables: []
157
+ extensions: []
158
+ extra_rdoc_files: []
159
+ files:
160
+ - MIT-LICENSE
161
+ - README.md
162
+ - Rakefile
163
+ - app/controllers/ez/permissions/application_controller.rb
164
+ - app/models/ez/permissions/application_record.rb
165
+ - app/models/ez/permissions/model.rb
166
+ - app/models/ez/permissions/model_role.rb
167
+ - app/models/ez/permissions/permission.rb
168
+ - app/models/ez/permissions/permission_role.rb
169
+ - app/models/ez/permissions/role.rb
170
+ - config/routes.rb
171
+ - lib/ez/permissions.rb
172
+ - lib/ez/permissions/api.rb
173
+ - lib/ez/permissions/api/authorize.rb
174
+ - lib/ez/permissions/api/models.rb
175
+ - lib/ez/permissions/api/permissions.rb
176
+ - lib/ez/permissions/api/roles.rb
177
+ - lib/ez/permissions/dsl.rb
178
+ - lib/ez/permissions/engine.rb
179
+ - lib/ez/permissions/railtie.rb
180
+ - lib/ez/permissions/resource.rb
181
+ - lib/ez/permissions/version.rb
182
+ - lib/generators/ez/permissions/install_generator.rb
183
+ - lib/generators/ez/permissions/migrations_generator.rb
184
+ - lib/tasks/ez/permissions_tasks.rake
185
+ homepage: https://github.com/ez-permissions
186
+ licenses:
187
+ - MIT
188
+ metadata:
189
+ allowed_push_host: https://rubygems.org
190
+ post_install_message:
191
+ rdoc_options: []
192
+ require_paths:
193
+ - lib
194
+ required_ruby_version: !ruby/object:Gem::Requirement
195
+ requirements:
196
+ - - ">="
197
+ - !ruby/object:Gem::Version
198
+ version: '0'
199
+ required_rubygems_version: !ruby/object:Gem::Requirement
200
+ requirements:
201
+ - - ">="
202
+ - !ruby/object:Gem::Version
203
+ version: '0'
204
+ requirements: []
205
+ rubyforge_project:
206
+ rubygems_version: 2.7.6
207
+ signing_key:
208
+ specification_version: 4
209
+ summary: Easy permissions engine for Rails app.
210
+ test_files: []