permissions 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +21 -0
- data/LICENSE +21 -0
- data/README.md +70 -0
- data/Rakefile +9 -0
- data/lib/permissions.rb +37 -0
- data/permissions.gemspec +14 -0
- data/test/permissions_test.rb +131 -0
- metadata +67 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9bfba6131fb8f4d043ee8d5583def68e610231d8
|
4
|
+
data.tar.gz: 5eb1358ab58b09ee5517b437d5c8d1904bafd4b2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 36d2667cd3358117d81dea70dd07c7815d7bc7f4f26f70eb34fd0c9cbea75ac6d21000903362fa4f1870daa82a207414a34795e4b926179ea870e0a9765c0f45
|
7
|
+
data.tar.gz: 945e45848d83d5fdb589d23227dfb3bd99f3f0baaad31129bc55df45aeebe3c8edc119c0ebdfbd8e8b8803aee2d2ecd14d79ea9001264635b5b6b22a50e4d9f7
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
.gs/
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Steven Weiss
|
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
|
13
|
+
all 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
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# Permissions
|
2
|
+
|
3
|
+
A small library for adding permissions to an application for authorization.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
`gem install permissions`
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
### API
|
12
|
+
|
13
|
+
`for(*keys, &block)`: Creates a permission with the given block for each key.
|
14
|
+
|
15
|
+
`authorize?(key, *args)`: Runs permission block for key with args.
|
16
|
+
|
17
|
+
`deep_dup`: Copies permissions to a new object.
|
18
|
+
|
19
|
+
#### Authorizable
|
20
|
+
|
21
|
+
`permissions`: Must be implemented by your application.
|
22
|
+
|
23
|
+
`authorize_for?(key, *args)` Based off the implemented permissions, calls block with args for the given key.
|
24
|
+
|
25
|
+
### Example
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
require 'permissions'
|
29
|
+
|
30
|
+
class User
|
31
|
+
include Permissions::Authorizable
|
32
|
+
|
33
|
+
def initialize(permissions)
|
34
|
+
@permissions = permissions
|
35
|
+
end
|
36
|
+
|
37
|
+
# Authorizables must provide their own implementation of "permissions".
|
38
|
+
# An attr_reader would do.
|
39
|
+
def permissions
|
40
|
+
@permissions
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Command
|
45
|
+
attr_reader :user
|
46
|
+
|
47
|
+
def initialize(user)
|
48
|
+
@user = user
|
49
|
+
end
|
50
|
+
|
51
|
+
# Not provided by the library. An advanced example
|
52
|
+
# on how to authorize things like: "Does an object
|
53
|
+
# belong to a particular user?"
|
54
|
+
def authorize?(other)
|
55
|
+
other.authorize_for?(self.class, self)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
permissions = Permissions.new
|
60
|
+
|
61
|
+
permissions.for(Command) { |user, command| user == command.user }
|
62
|
+
|
63
|
+
user = User.new(permissions)
|
64
|
+
|
65
|
+
command = Command.new(user)
|
66
|
+
|
67
|
+
command.authorize?(user) # true
|
68
|
+
```
|
69
|
+
|
70
|
+
More examples can be found by in the tests.
|
data/Rakefile
ADDED
data/lib/permissions.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
class Permissions
|
2
|
+
VERSION = '0.1.0'
|
3
|
+
|
4
|
+
module Authorizable
|
5
|
+
def permissions
|
6
|
+
raise NotImplementedError
|
7
|
+
end
|
8
|
+
|
9
|
+
def authorize_for?(key, *args)
|
10
|
+
permissions.authorize?(key, self, *args)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :permissions, :default
|
15
|
+
|
16
|
+
def initialize(permissions = {}, &default)
|
17
|
+
@permissions = permissions
|
18
|
+
|
19
|
+
if block_given?
|
20
|
+
@default = default
|
21
|
+
else
|
22
|
+
@default = lambda { false }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def for(*keys, &block)
|
27
|
+
keys.each { |key| permissions[key] = block }
|
28
|
+
end
|
29
|
+
|
30
|
+
def authorize?(key, *args)
|
31
|
+
permissions.fetch(key, default).call(*args)
|
32
|
+
end
|
33
|
+
|
34
|
+
def deep_dup
|
35
|
+
Permissions.new({}.merge(permissions)) { default }
|
36
|
+
end
|
37
|
+
end
|
data/permissions.gemspec
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative "./lib/permissions"
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "permissions"
|
5
|
+
s.summary = "Permissions"
|
6
|
+
s.version = Permissions::VERSION
|
7
|
+
s.authors = ["Steve Weiss"]
|
8
|
+
s.email = ["weissst@mail.gvsu.edu"]
|
9
|
+
s.homepage = "https://github.com/sirscriptalot/permissions"
|
10
|
+
s.license = "MIT"
|
11
|
+
s.files = `git ls-files`.split("\n")
|
12
|
+
|
13
|
+
s.add_development_dependency "cutest"
|
14
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require_relative '../lib/permissions'
|
2
|
+
|
3
|
+
class User
|
4
|
+
include Permissions::Authorizable
|
5
|
+
|
6
|
+
def initialize(permissions)
|
7
|
+
@permissions = permissions
|
8
|
+
end
|
9
|
+
|
10
|
+
# Authorizables must provide their own implementation of "permissions".
|
11
|
+
# An attr_reader would do.
|
12
|
+
def permissions
|
13
|
+
@permissions
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Command
|
18
|
+
attr_reader :user
|
19
|
+
|
20
|
+
def initialize(user)
|
21
|
+
@user = user
|
22
|
+
end
|
23
|
+
|
24
|
+
# Not provided by the library. An advanced example
|
25
|
+
# on how to authorize things like: "Does an object
|
26
|
+
# belong to a particular user?"
|
27
|
+
def authorize?(other)
|
28
|
+
other.authorize_for?(self.class, self)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Create < Command
|
33
|
+
def execute
|
34
|
+
'Create something...'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Update < Command
|
39
|
+
def execute
|
40
|
+
'Update something...'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Delete < Command
|
45
|
+
def execute
|
46
|
+
'Delete something...'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def assert_authorize_for(user, subject)
|
51
|
+
assert user.authorize_for?(subject), "#{user} is not authorized for #{subject}, it should be"
|
52
|
+
end
|
53
|
+
|
54
|
+
def refute_authorize_for(user, subject)
|
55
|
+
assert !user.authorize_for?(subject), "#{user} is authorized for #{subject}, it should not be"
|
56
|
+
end
|
57
|
+
|
58
|
+
def assert_authorize(subject, user)
|
59
|
+
assert subject.authorize?(user), "#{subject} does not authorize #{user}, it should"
|
60
|
+
end
|
61
|
+
|
62
|
+
def refute_authorize(subject, user)
|
63
|
+
assert !subject.authorize?(user), "#{subject} does authorize #{user}, it should not"
|
64
|
+
end
|
65
|
+
|
66
|
+
# Create a Permissions object.
|
67
|
+
guest_permissions = Permissions.new
|
68
|
+
|
69
|
+
# Create permissions, guests are allowed to execute Create.
|
70
|
+
guest_permissions.for(Create) { true }
|
71
|
+
|
72
|
+
# Guests cannot Update or Delete, this is also the default permission.
|
73
|
+
guest_permissions.for(Update, Delete) { false }
|
74
|
+
|
75
|
+
# As a convenience, deep_dup lets you copy existing permissions.
|
76
|
+
member_permissions = guest_permissions.deep_dup
|
77
|
+
|
78
|
+
# Users are allowed to update if they "own" the subject.
|
79
|
+
member_permissions.for(Update, Delete) { |user, command| user == command.user }
|
80
|
+
|
81
|
+
# Specify a custom default permissions to allow admins to do everything.
|
82
|
+
admin_permissions = Permissions.new { true }
|
83
|
+
|
84
|
+
guest = User.new(guest_permissions)
|
85
|
+
|
86
|
+
member = User.new(member_permissions)
|
87
|
+
|
88
|
+
admin = User.new(admin_permissions)
|
89
|
+
|
90
|
+
member_update = Update.new(member) # Commands with "ownership".
|
91
|
+
|
92
|
+
member_delete = Delete.new(member)
|
93
|
+
|
94
|
+
admin_update = Update.new(admin)
|
95
|
+
|
96
|
+
admin_delete = Delete.new(admin)
|
97
|
+
|
98
|
+
test '#authorize_for?' do
|
99
|
+
# Guest
|
100
|
+
assert_authorize_for guest, Create
|
101
|
+
refute_authorize_for guest, Update
|
102
|
+
refute_authorize_for guest, Delete
|
103
|
+
|
104
|
+
# Member
|
105
|
+
assert_authorize_for member, Create
|
106
|
+
assert_authorize_for admin, Create
|
107
|
+
|
108
|
+
# Admin
|
109
|
+
assert_authorize_for admin, Update
|
110
|
+
assert_authorize_for admin, Delete
|
111
|
+
end
|
112
|
+
|
113
|
+
test '#authorize?' do
|
114
|
+
# Guest
|
115
|
+
refute_authorize member_update, guest
|
116
|
+
refute_authorize member_delete, guest
|
117
|
+
refute_authorize admin_update, guest
|
118
|
+
refute_authorize admin_delete, guest
|
119
|
+
|
120
|
+
# Member
|
121
|
+
assert_authorize member_update, member
|
122
|
+
assert_authorize member_delete, member
|
123
|
+
refute_authorize admin_update, member
|
124
|
+
refute_authorize admin_delete, member
|
125
|
+
|
126
|
+
# Admin
|
127
|
+
assert_authorize member_update, admin
|
128
|
+
assert_authorize member_delete, admin
|
129
|
+
assert_authorize admin_update, admin
|
130
|
+
assert_authorize admin_delete, admin
|
131
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: permissions
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Steve Weiss
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-08-11 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: cutest
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description:
|
28
|
+
email:
|
29
|
+
- weissst@mail.gvsu.edu
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- ".gitignore"
|
35
|
+
- Gemfile
|
36
|
+
- Gemfile.lock
|
37
|
+
- LICENSE
|
38
|
+
- README.md
|
39
|
+
- Rakefile
|
40
|
+
- lib/permissions.rb
|
41
|
+
- permissions.gemspec
|
42
|
+
- test/permissions_test.rb
|
43
|
+
homepage: https://github.com/sirscriptalot/permissions
|
44
|
+
licenses:
|
45
|
+
- MIT
|
46
|
+
metadata: {}
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 2.6.11
|
64
|
+
signing_key:
|
65
|
+
specification_version: 4
|
66
|
+
summary: Permissions
|
67
|
+
test_files: []
|