authorizable 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +33 -0
- data/.travis.yml +14 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +178 -0
- data/LICENSE +22 -0
- data/README.md +80 -0
- data/Rakefile +1 -0
- data/authorizable.gemspec +40 -0
- data/config/locales/en.yml +6 -0
- data/lib/authorizable.rb +31 -0
- data/lib/authorizable/controller.rb +156 -0
- data/lib/authorizable/model.rb +162 -0
- data/lib/authorizable/permission_utilities.rb +89 -0
- data/lib/authorizable/permissions.rb +112 -0
- data/lib/authorizable/version.rb +5 -0
- data/spec/integration/controller_spec.rb +127 -0
- data/spec/integration/model_spec.rb +169 -0
- data/spec/rails_helper.rb +14 -0
- data/spec/spec_helper.rb +48 -0
- data/spec/support/definitions.rb +16 -0
- data/spec/support/factories.rb +17 -0
- data/spec/support/factory_girl.rb +7 -0
- data/spec/support/rails_app/Rakefile +6 -0
- data/spec/support/rails_app/app/assets/images/.keep +0 -0
- data/spec/support/rails_app/app/assets/javascripts/application.js +16 -0
- data/spec/support/rails_app/app/assets/javascripts/some_resources.js +2 -0
- data/spec/support/rails_app/app/assets/javascripts/users.js +2 -0
- data/spec/support/rails_app/app/assets/stylesheets/application.css +15 -0
- data/spec/support/rails_app/app/assets/stylesheets/scaffold.css +56 -0
- data/spec/support/rails_app/app/assets/stylesheets/some_resources.css +4 -0
- data/spec/support/rails_app/app/assets/stylesheets/users.css +4 -0
- data/spec/support/rails_app/app/controllers/application_controller.rb +14 -0
- data/spec/support/rails_app/app/controllers/events_controller.rb +58 -0
- data/spec/support/rails_app/app/controllers/users_controller.rb +58 -0
- data/spec/support/rails_app/app/helpers/application_helper.rb +2 -0
- data/spec/support/rails_app/app/helpers/events_helper.rb +2 -0
- data/spec/support/rails_app/app/helpers/users_helper.rb +2 -0
- data/spec/support/rails_app/app/mailers/.keep +0 -0
- data/spec/support/rails_app/app/models/collaboration.rb +16 -0
- data/spec/support/rails_app/app/models/concerns/.keep +0 -0
- data/spec/support/rails_app/app/models/discount.rb +3 -0
- data/spec/support/rails_app/app/models/event.rb +5 -0
- data/spec/support/rails_app/app/models/user.rb +9 -0
- data/spec/support/rails_app/app/views/events/_form.html.erb +17 -0
- data/spec/support/rails_app/app/views/events/edit.html.erb +6 -0
- data/spec/support/rails_app/app/views/events/index.html.erb +25 -0
- data/spec/support/rails_app/app/views/events/new.html.erb +5 -0
- data/spec/support/rails_app/app/views/events/show.html.erb +4 -0
- data/spec/support/rails_app/app/views/layouts/application.html.erb +14 -0
- data/spec/support/rails_app/app/views/users/_form.html.erb +17 -0
- data/spec/support/rails_app/app/views/users/edit.html.erb +6 -0
- data/spec/support/rails_app/app/views/users/index.html.erb +25 -0
- data/spec/support/rails_app/app/views/users/new.html.erb +5 -0
- data/spec/support/rails_app/app/views/users/show.html.erb +4 -0
- data/spec/support/rails_app/bin/bundle +3 -0
- data/spec/support/rails_app/bin/rails +8 -0
- data/spec/support/rails_app/bin/rake +4 -0
- data/spec/support/rails_app/config.ru +0 -0
- data/spec/support/rails_app/config/application.rb +29 -0
- data/spec/support/rails_app/config/boot.rb +3 -0
- data/spec/support/rails_app/config/database.yml +25 -0
- data/spec/support/rails_app/config/environment.rb +5 -0
- data/spec/support/rails_app/config/environments/development.rb +41 -0
- data/spec/support/rails_app/config/environments/production.rb +79 -0
- data/spec/support/rails_app/config/environments/test.rb +42 -0
- data/spec/support/rails_app/config/initializers/assets.rb +11 -0
- data/spec/support/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/support/rails_app/config/initializers/cookies_serializer.rb +3 -0
- data/spec/support/rails_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/support/rails_app/config/initializers/inflections.rb +16 -0
- data/spec/support/rails_app/config/initializers/mime_types.rb +4 -0
- data/spec/support/rails_app/config/initializers/session_store.rb +3 -0
- data/spec/support/rails_app/config/initializers/wrap_parameters.rb +14 -0
- data/spec/support/rails_app/config/locales/en.yml +23 -0
- data/spec/support/rails_app/config/routes.rb +60 -0
- data/spec/support/rails_app/config/secrets.yml +22 -0
- data/spec/support/rails_app/db/development.sqlite3 +0 -0
- data/spec/support/rails_app/db/migrate/20141231134904_create_users.rb +8 -0
- data/spec/support/rails_app/db/migrate/20150102221633_create_collaborations.rb +13 -0
- data/spec/support/rails_app/db/migrate/20150102225507_create_events.rb +9 -0
- data/spec/support/rails_app/db/migrate/20150104171110_create_discounts.rb +11 -0
- data/spec/support/rails_app/db/schema.rb +45 -0
- data/spec/support/rails_app/db/seeds.rb +7 -0
- data/spec/support/rails_app/db/test.sqlite3 +0 -0
- data/spec/support/rails_app/log/development.log +26296 -0
- data/spec/support/rails_app/public/404.html +67 -0
- data/spec/support/rails_app/public/422.html +67 -0
- data/spec/support/rails_app/public/500.html +66 -0
- data/spec/support/rails_app/public/favicon.ico +0 -0
- data/spec/support/rails_app/public/robots.txt +5 -0
- data/spec/unit/permission_utilities_spec.rb +157 -0
- data/spec/unit/permissions_spec.rb +65 -0
- metadata +352 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 77b3ab727e51ec220be5820eed631d12c66e9bc9
|
4
|
+
data.tar.gz: e613cfad5041f4419977489325edbe0054aca213
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c28114098c0412fe8238865421378c5c97a1f82b8a1499bfe6264658d71e0541410ed1eacaa26ff1623b6d6883733c0092f054fd31da8bd4f051597bf55a3ba7
|
7
|
+
data.tar.gz: 3ae8cd4b03c111c7e826b9bd102fa58b68c228818f3354fb538a604946389f2821edee2ddd74958e830a7f2a6829b0fa71fb10a9c65c0efa65fb01e117606bf3
|
data/.gitignore
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
*.rbc
|
2
|
+
capybara-*.html
|
3
|
+
.rspec
|
4
|
+
/log
|
5
|
+
/spec/rails_app/log
|
6
|
+
/tmp
|
7
|
+
/spec/rails_app/tmp
|
8
|
+
/db/*.sqlite3
|
9
|
+
/public/system
|
10
|
+
/coverage/
|
11
|
+
/spec/tmp
|
12
|
+
**.orig
|
13
|
+
rerun.txt
|
14
|
+
pickle-email-*.html
|
15
|
+
|
16
|
+
# TODO Comment out these rules if you are OK with secrets being uploaded to the repo
|
17
|
+
config/initializers/secret_token.rb
|
18
|
+
config/secrets.yml
|
19
|
+
|
20
|
+
## Environment normalisation:
|
21
|
+
/.bundle
|
22
|
+
/vendor/bundle
|
23
|
+
|
24
|
+
# these should all be checked in to normalise the environment:
|
25
|
+
# Gemfile.lock, .ruby-version, .ruby-gemset
|
26
|
+
|
27
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
28
|
+
.rvmrc
|
29
|
+
|
30
|
+
# if using bower-rails ignore default bower_components path bower.json files
|
31
|
+
/vendor/assets/bower_components
|
32
|
+
*.bowerrc
|
33
|
+
bower.json
|
data/.travis.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
language: ruby
|
2
|
+
bundler_args: --without guard
|
3
|
+
rvm:
|
4
|
+
- "2.0"
|
5
|
+
- "2.1"
|
6
|
+
- ruby-head
|
7
|
+
script: "bundle exec rspec"
|
8
|
+
addons:
|
9
|
+
code_climate:
|
10
|
+
repo_token: 68f28e1d037ca7b58d24f943b59d82cd649e1f9b9f79437d4a5d864140dd4eb0
|
11
|
+
branches:
|
12
|
+
only: master
|
13
|
+
notifications:
|
14
|
+
email: false
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
GIT
|
2
|
+
remote: https://github.com/codeclimate/ruby-test-reporter.git
|
3
|
+
revision: 7eeff8c596b1b540cb7ff004b93053265e4d8be5
|
4
|
+
branch: check_git_dir
|
5
|
+
specs:
|
6
|
+
codeclimate-test-reporter (0.4.4)
|
7
|
+
simplecov (>= 0.7.1, < 1.0.0)
|
8
|
+
|
9
|
+
PATH
|
10
|
+
remote: .
|
11
|
+
specs:
|
12
|
+
authorizable (0.9.0)
|
13
|
+
activesupport (>= 3.0.0)
|
14
|
+
i18n
|
15
|
+
|
16
|
+
GEM
|
17
|
+
remote: https://rubygems.org/
|
18
|
+
specs:
|
19
|
+
actionmailer (4.2.0)
|
20
|
+
actionpack (= 4.2.0)
|
21
|
+
actionview (= 4.2.0)
|
22
|
+
activejob (= 4.2.0)
|
23
|
+
mail (~> 2.5, >= 2.5.4)
|
24
|
+
rails-dom-testing (~> 1.0, >= 1.0.5)
|
25
|
+
actionpack (4.2.0)
|
26
|
+
actionview (= 4.2.0)
|
27
|
+
activesupport (= 4.2.0)
|
28
|
+
rack (~> 1.6.0)
|
29
|
+
rack-test (~> 0.6.2)
|
30
|
+
rails-dom-testing (~> 1.0, >= 1.0.5)
|
31
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.1)
|
32
|
+
actionview (4.2.0)
|
33
|
+
activesupport (= 4.2.0)
|
34
|
+
builder (~> 3.1)
|
35
|
+
erubis (~> 2.7.0)
|
36
|
+
rails-dom-testing (~> 1.0, >= 1.0.5)
|
37
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.1)
|
38
|
+
activejob (4.2.0)
|
39
|
+
activesupport (= 4.2.0)
|
40
|
+
globalid (>= 0.3.0)
|
41
|
+
activemodel (4.2.0)
|
42
|
+
activesupport (= 4.2.0)
|
43
|
+
builder (~> 3.1)
|
44
|
+
activerecord (4.2.0)
|
45
|
+
activemodel (= 4.2.0)
|
46
|
+
activesupport (= 4.2.0)
|
47
|
+
arel (~> 6.0)
|
48
|
+
activesupport (4.2.0)
|
49
|
+
i18n (~> 0.7)
|
50
|
+
json (~> 1.7, >= 1.7.7)
|
51
|
+
minitest (~> 5.1)
|
52
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
53
|
+
tzinfo (~> 1.1)
|
54
|
+
arel (6.0.0)
|
55
|
+
awesome_print (1.6.1)
|
56
|
+
builder (3.2.2)
|
57
|
+
byebug (3.5.1)
|
58
|
+
columnize (~> 0.8)
|
59
|
+
debugger-linecache (~> 1.2)
|
60
|
+
slop (~> 3.6)
|
61
|
+
coderay (1.1.0)
|
62
|
+
columnize (0.9.0)
|
63
|
+
debugger-linecache (1.2.0)
|
64
|
+
diff-lcs (1.2.5)
|
65
|
+
docile (1.1.5)
|
66
|
+
erubis (2.7.0)
|
67
|
+
factory_girl (4.5.0)
|
68
|
+
activesupport (>= 3.0.0)
|
69
|
+
factory_girl_rails (4.5.0)
|
70
|
+
factory_girl (~> 4.5.0)
|
71
|
+
railties (>= 3.0.0)
|
72
|
+
globalid (0.3.0)
|
73
|
+
activesupport (>= 4.1.0)
|
74
|
+
hike (1.2.3)
|
75
|
+
i18n (0.7.0)
|
76
|
+
json (1.8.1)
|
77
|
+
loofah (2.0.1)
|
78
|
+
nokogiri (>= 1.5.9)
|
79
|
+
mail (2.6.3)
|
80
|
+
mime-types (>= 1.16, < 3)
|
81
|
+
method_source (0.8.2)
|
82
|
+
mime-types (2.4.3)
|
83
|
+
mini_portile (0.6.2)
|
84
|
+
minitest (5.5.0)
|
85
|
+
multi_json (1.10.1)
|
86
|
+
nokogiri (1.6.5)
|
87
|
+
mini_portile (~> 0.6.0)
|
88
|
+
pry (0.10.1)
|
89
|
+
coderay (~> 1.1.0)
|
90
|
+
method_source (~> 0.8.1)
|
91
|
+
slop (~> 3.4)
|
92
|
+
pry-byebug (2.0.0)
|
93
|
+
byebug (~> 3.4)
|
94
|
+
pry (~> 0.10)
|
95
|
+
rack (1.6.0)
|
96
|
+
rack-test (0.6.2)
|
97
|
+
rack (>= 1.0)
|
98
|
+
rails (4.2.0)
|
99
|
+
actionmailer (= 4.2.0)
|
100
|
+
actionpack (= 4.2.0)
|
101
|
+
actionview (= 4.2.0)
|
102
|
+
activejob (= 4.2.0)
|
103
|
+
activemodel (= 4.2.0)
|
104
|
+
activerecord (= 4.2.0)
|
105
|
+
activesupport (= 4.2.0)
|
106
|
+
bundler (>= 1.3.0, < 2.0)
|
107
|
+
railties (= 4.2.0)
|
108
|
+
sprockets-rails
|
109
|
+
rails-deprecated_sanitizer (1.0.3)
|
110
|
+
activesupport (>= 4.2.0.alpha)
|
111
|
+
rails-dom-testing (1.0.5)
|
112
|
+
activesupport (>= 4.2.0.beta, < 5.0)
|
113
|
+
nokogiri (~> 1.6.0)
|
114
|
+
rails-deprecated_sanitizer (>= 1.0.1)
|
115
|
+
rails-html-sanitizer (1.0.1)
|
116
|
+
loofah (~> 2.0)
|
117
|
+
railties (4.2.0)
|
118
|
+
actionpack (= 4.2.0)
|
119
|
+
activesupport (= 4.2.0)
|
120
|
+
rake (>= 0.8.7)
|
121
|
+
thor (>= 0.18.1, < 2.0)
|
122
|
+
rake (10.4.2)
|
123
|
+
rspec (3.1.0)
|
124
|
+
rspec-core (~> 3.1.0)
|
125
|
+
rspec-expectations (~> 3.1.0)
|
126
|
+
rspec-mocks (~> 3.1.0)
|
127
|
+
rspec-core (3.1.7)
|
128
|
+
rspec-support (~> 3.1.0)
|
129
|
+
rspec-expectations (3.1.2)
|
130
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
131
|
+
rspec-support (~> 3.1.0)
|
132
|
+
rspec-mocks (3.1.3)
|
133
|
+
rspec-support (~> 3.1.0)
|
134
|
+
rspec-rails (3.1.0)
|
135
|
+
actionpack (>= 3.0)
|
136
|
+
activesupport (>= 3.0)
|
137
|
+
railties (>= 3.0)
|
138
|
+
rspec-core (~> 3.1.0)
|
139
|
+
rspec-expectations (~> 3.1.0)
|
140
|
+
rspec-mocks (~> 3.1.0)
|
141
|
+
rspec-support (~> 3.1.0)
|
142
|
+
rspec-support (3.1.2)
|
143
|
+
simplecov (0.9.1)
|
144
|
+
docile (~> 1.1.0)
|
145
|
+
multi_json (~> 1.0)
|
146
|
+
simplecov-html (~> 0.8.0)
|
147
|
+
simplecov-html (0.8.0)
|
148
|
+
slop (3.6.0)
|
149
|
+
sprockets (2.12.3)
|
150
|
+
hike (~> 1.2)
|
151
|
+
multi_json (~> 1.0)
|
152
|
+
rack (~> 1.0)
|
153
|
+
tilt (~> 1.1, != 1.3.0)
|
154
|
+
sprockets-rails (2.2.2)
|
155
|
+
actionpack (>= 3.0)
|
156
|
+
activesupport (>= 3.0)
|
157
|
+
sprockets (>= 2.8, < 4.0)
|
158
|
+
sqlite3 (1.3.10)
|
159
|
+
thor (0.19.1)
|
160
|
+
thread_safe (0.3.4)
|
161
|
+
tilt (1.4.1)
|
162
|
+
tzinfo (1.2.2)
|
163
|
+
thread_safe (~> 0.1)
|
164
|
+
|
165
|
+
PLATFORMS
|
166
|
+
ruby
|
167
|
+
|
168
|
+
DEPENDENCIES
|
169
|
+
authorizable!
|
170
|
+
awesome_print
|
171
|
+
bundler
|
172
|
+
codeclimate-test-reporter!
|
173
|
+
factory_girl_rails (~> 4.4)
|
174
|
+
pry-byebug
|
175
|
+
rails (>= 4)
|
176
|
+
rspec
|
177
|
+
rspec-rails
|
178
|
+
sqlite3
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 L. Preston Sego III
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
authorizable
|
2
|
+
============
|
3
|
+
|
4
|
+
A gem for rails giving vast flexibility in authorization management.
|
5
|
+
|
6
|
+
[![docs](https://img.shields.io/badge/docs-yardoc-blue.svg?style=flat-square)](http://www.rubydoc.info/github/NullVoxPopuli/authorizable)
|
7
|
+
[![Build Status](http://img.shields.io/travis/NullVoxPopuli/authorizable.svg?style=flat-square)](https://travis-ci.org/NullVoxPopuli/authorizable)
|
8
|
+
[![Code Climate](http://img.shields.io/codeclimate/github/NullVoxPopuli/authorizable.svg?style=flat-square)](https://codeclimate.com/github/NullVoxPopuli/authorizable)
|
9
|
+
[![Test Coverage](http://img.shields.io/codeclimate/coverage/github/NullVoxPopuli/authorizable.svg?style=flat-square)](https://codeclimate.com/github/NullVoxPopuli/authorizable)
|
10
|
+
|
11
|
+
|
12
|
+
## Features
|
13
|
+
|
14
|
+
- Customizable Permissions
|
15
|
+
- Permissions are all defined in one place
|
16
|
+
- Role-Based
|
17
|
+
- Easy UI Generation
|
18
|
+
- Categorization for Organizing Permission in the UI
|
19
|
+
- Easily Extensible (e.g.: adding support for permission groups )
|
20
|
+
- Automatic controller response upon unauthorized status
|
21
|
+
- Controller response is customizable
|
22
|
+
- Controller behavior defined in one place (optionally in the controller)
|
23
|
+
|
24
|
+
## Installation
|
25
|
+
|
26
|
+
Gemfile
|
27
|
+
|
28
|
+
gem "authorizable", github: "NullVoxPopuli/authorizable"
|
29
|
+
|
30
|
+
## Configuration
|
31
|
+
### Defining permissions
|
32
|
+
|
33
|
+
There are a couple ways that permissions can be defined.
|
34
|
+
|
35
|
+
If you like calling methods for configuration:
|
36
|
+
|
37
|
+
module Authorizable
|
38
|
+
class Permissions
|
39
|
+
can :delete_event
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
will create a permission definition called `delete_event` which can be accessed by calling
|
44
|
+
`user.can_delete_event?(@event)`
|
45
|
+
|
46
|
+
module Authorizable
|
47
|
+
class Permissions
|
48
|
+
can :edit_event, true, "Edit an Event", nil, ->(e, user){ e.user == user }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
will create a permission definition called `edit_event` with an additional condition allowing editing only if the user owns the event
|
53
|
+
|
54
|
+
Authorizable::Permissions.set(
|
55
|
+
edit_organization: [Authorizable::OBJECT, true],
|
56
|
+
delete_organization: [Authorizable::OBJECT, [true, false], nil, ->(e, user){ e.user == user }, ->(e, user){ e.owner == user }]
|
57
|
+
)
|
58
|
+
|
59
|
+
This is how Authorizable references the permission definitions internally, just as raw permission: definition sets. Note that `Authorizable::Permissions.set` overrides the definitions list each time.
|
60
|
+
|
61
|
+
### Customizing roles
|
62
|
+
|
63
|
+
coming soon...
|
64
|
+
|
65
|
+
### Supporting group-based permissions
|
66
|
+
|
67
|
+
coming soon...
|
68
|
+
|
69
|
+
## Why not CanCan?
|
70
|
+
|
71
|
+
Initially, I wanted something more customizable and that could aid in the generation of a UI where users
|
72
|
+
can customize permissions for various groups or organizations. My goal is to at least support everything CanCan has, but with the mindset and intention of customizing behavior and remaining DRY.
|
73
|
+
|
74
|
+
## Contributing
|
75
|
+
|
76
|
+
1. Fork the project
|
77
|
+
2. Create a new, descriptively named branch
|
78
|
+
3. Add Test(s)!
|
79
|
+
4. Commit your proposed changes
|
80
|
+
5. Submit a pull request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require "authorizable/version"
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "authorizable"
|
9
|
+
s.version = Authorizable::VERSION
|
10
|
+
s.platform = Gem::Platform::RUBY
|
11
|
+
s.license = "MIT"
|
12
|
+
s.authors = ["L. Preston Sego III"]
|
13
|
+
s.email = "LPSego3+dev@gmail.com"
|
14
|
+
s.homepage = "https://github.com/NullVoxPopuli/authorizable"
|
15
|
+
s.summary = "Authorizable-#{Authorizable::VERSION}"
|
16
|
+
s.description = "A gem for rails giving vast flexibility in authorization management."
|
17
|
+
|
18
|
+
|
19
|
+
s.files = `git ls-files`.split($/)
|
20
|
+
s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
21
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
|
24
|
+
|
25
|
+
s.add_runtime_dependency "activesupport", ">= 3.0.0"
|
26
|
+
s.add_runtime_dependency "i18n"
|
27
|
+
|
28
|
+
# for testing a gem with a rails app (controller specs)
|
29
|
+
# https://codingdaily.wordpress.com/2011/01/14/test-a-gem-with-the-rails-3-stack/
|
30
|
+
s.add_development_dependency "bundler"
|
31
|
+
s.add_development_dependency "rails", ">= 4"
|
32
|
+
s.add_development_dependency "factory_girl_rails", "~> 4.4"
|
33
|
+
s.add_development_dependency "awesome_print"
|
34
|
+
s.add_development_dependency "rspec"
|
35
|
+
s.add_development_dependency "rspec-rails"
|
36
|
+
s.add_development_dependency "sqlite3"
|
37
|
+
s.add_development_dependency "pry-byebug"
|
38
|
+
# s.add_development_dependency "codeclimate-test-reporter", "0.4.3"
|
39
|
+
|
40
|
+
end
|
data/lib/authorizable.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'active_support'
|
3
|
+
require 'action_controller'
|
4
|
+
|
5
|
+
require 'authorizable/permission_utilities'
|
6
|
+
require 'authorizable/permissions'
|
7
|
+
require 'authorizable/controller'
|
8
|
+
require 'authorizable/model'
|
9
|
+
require 'authorizable/version'
|
10
|
+
|
11
|
+
module Authorizable
|
12
|
+
OBJECT = PermissionUtilities::OBJECT
|
13
|
+
ACCESS = PermissionUtilities::ACCESS
|
14
|
+
|
15
|
+
def self.definitions
|
16
|
+
Authorizable::Permissions.definitions || {}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# add authorizable method to ActionController
|
21
|
+
ActionController::Base.send(:include, Authorizable::Controller)
|
22
|
+
# class ActionController::Base
|
23
|
+
# include Authorizable::Controller
|
24
|
+
|
25
|
+
# def self.authorizable
|
26
|
+
# ap 'wat'
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
|
30
|
+
# add authorizable method to ActiveModel
|
31
|
+
# ActiveRecord::Base.send( :extend, Authorizable::Model )
|
@@ -0,0 +1,156 @@
|
|
1
|
+
module Authorizable
|
2
|
+
module Controller
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
|
7
|
+
# where the config for this controller is stored
|
8
|
+
# after validation
|
9
|
+
class_attribute :authorizable_config
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
# sets up a before filter that will redirect if the permission
|
14
|
+
# condition fails
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# authorizable(
|
18
|
+
# edit: { # implies current_user.can_edit?(@event)
|
19
|
+
# target: :event,
|
20
|
+
# redirect_path: Proc.new{ hosted_event_path(@event) }
|
21
|
+
# }
|
22
|
+
# )
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# authorizable(
|
26
|
+
# create: {
|
27
|
+
# permission: :can_create_event?,
|
28
|
+
# redirect_path: Proc.new{ hosted_events_path }
|
29
|
+
# },
|
30
|
+
# destroy: { # implies current_user.can_delete?(@event)
|
31
|
+
# target: :event,
|
32
|
+
# redirect_path: Proc.new{ hosted_event_path(@event) }
|
33
|
+
# }
|
34
|
+
# )
|
35
|
+
#
|
36
|
+
# @param [Hash] config the list of options to configure actions to be authorizable
|
37
|
+
# @option config [Symbol] action the action to authorize with
|
38
|
+
# @option action [ActiveRecord::Base] :user (current_user) object to run the condition on
|
39
|
+
# @option action [Symbol] :permission (can_{action}?(target)) the condition to run on the :user
|
40
|
+
# @option action [Symbol] :target ("@#{target}") the name of the object passed to the :permission
|
41
|
+
# if no target is provided :permission becomes a required option
|
42
|
+
# @option action [Proc] :redirect_path where to go upon unauthorized
|
43
|
+
# @option action [String] :message (I18n.t('authorizable.not_authorized'))
|
44
|
+
# message to display as a flash message upon an unauthorized attempt
|
45
|
+
# @option action [Symbol] :flash_type (:alert) what flash type to use for displaying the :message
|
46
|
+
def authorizable(config = {})
|
47
|
+
Authorizable::Controller.parameters_are_valid?(config)
|
48
|
+
|
49
|
+
self.authorizable_config = config
|
50
|
+
|
51
|
+
self.send(:before_filter, :authorizable_authorized?)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def authorizable_authorized?
|
58
|
+
result = false
|
59
|
+
action = params[:action].to_sym
|
60
|
+
|
61
|
+
if !self.class.authorizable_config[action]
|
62
|
+
action = Authorizable::Controller.alias_action(action)
|
63
|
+
end
|
64
|
+
|
65
|
+
settings_for_action = self.class.authorizable_config[action]
|
66
|
+
|
67
|
+
return true unless settings_for_action.present?
|
68
|
+
|
69
|
+
defaults = {
|
70
|
+
user: current_user,
|
71
|
+
permission: "can_#{action.to_s}?",
|
72
|
+
message: I18n.t('authorizable.not_authorized'),
|
73
|
+
flash_type: :alert
|
74
|
+
}
|
75
|
+
|
76
|
+
options = defaults.merge(settings_for_action)
|
77
|
+
|
78
|
+
# run permission
|
79
|
+
if options[:target]
|
80
|
+
object = instance_variable_get("@#{options[:target]}")
|
81
|
+
result = options[:user].send(options[:permission], object)
|
82
|
+
else
|
83
|
+
result = options[:user].send(options[:permission])
|
84
|
+
end
|
85
|
+
|
86
|
+
# redirect
|
87
|
+
unless result
|
88
|
+
authorizable_respond_with(
|
89
|
+
options[:flash_type],
|
90
|
+
options[:message],
|
91
|
+
options[:redirect_path]
|
92
|
+
)
|
93
|
+
|
94
|
+
# halt
|
95
|
+
return false
|
96
|
+
end
|
97
|
+
|
98
|
+
# proceed with execution
|
99
|
+
true
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
def authorizable_respond_with(flash_type, message, path)
|
104
|
+
flash[flash_type] = message
|
105
|
+
|
106
|
+
respond_to do |format|
|
107
|
+
format.html{
|
108
|
+
path = self.instance_eval(&path)
|
109
|
+
redirect_to path
|
110
|
+
}
|
111
|
+
format.json{
|
112
|
+
render json: {}, status: 401
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.alias_action(action)
|
119
|
+
if action == :update
|
120
|
+
action = :edit
|
121
|
+
elsif action == :edit
|
122
|
+
action = :update
|
123
|
+
elsif action == :create
|
124
|
+
action = :new
|
125
|
+
elsif action == :new
|
126
|
+
action = :create
|
127
|
+
end
|
128
|
+
|
129
|
+
action
|
130
|
+
end
|
131
|
+
|
132
|
+
# @see @authorizable for options
|
133
|
+
# @return [Boolean]
|
134
|
+
def self.parameters_are_valid?(config)
|
135
|
+
config.each do |action, settings|
|
136
|
+
if !settings[:target]
|
137
|
+
# permission is required
|
138
|
+
if !settings[:permission]
|
139
|
+
raise ArgumentError.new(I18n.t('authorizable.permission_required'))
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# redirect_path is always required
|
144
|
+
redirect_path = settings[:redirect_path]
|
145
|
+
if !redirect_path
|
146
|
+
raise ArgumentError.new(I18n.t('authorizable.redirect_path_required'))
|
147
|
+
else
|
148
|
+
if !redirect_path.is_a?(Proc)
|
149
|
+
raise ArgumentError.new(I18n.t("authorizable.redirect_path_must_be_proc"))
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
end
|