u-authorization 1.0.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 +7 -0
- data/authorization.rb +164 -0
- data/u-authorization.rb +3 -0
- metadata +45 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1a8a0a045b9fdd6b4f30c7c6b376635b2665b2609450226a329a2f4ad93e8747
|
4
|
+
data.tar.gz: 3f52e3df4e835319ca288750b7cedc85cd83189d4ec91054f1559a9f30ceb1cd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a8a2e6243af66478cf723b9df7662eeeaa8c31bc53b487a90e7ba8b501c4546b55b1fcfec416bb917f7bf05a6fb1291216475fec952590c88ec11515a6cc7125
|
7
|
+
data.tar.gz: 104a3e02d545745efdfd0ed189725a04caaf2dd1c0c9a2abff44ef0cd8f1c11ad76e02f3886b6fa3f24c970616f24da187da3185794b495c5287d096c45baf03
|
data/authorization.rb
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Authorization
|
4
|
+
VERSION = '1.0.0'
|
5
|
+
|
6
|
+
MapValuesAsDowncasedStrings = -> (values) do
|
7
|
+
Array(values).map { |value| String(value).downcase }
|
8
|
+
end
|
9
|
+
|
10
|
+
module CheckRolePermission
|
11
|
+
extend self
|
12
|
+
|
13
|
+
def call(context, role_permissions, required_features)
|
14
|
+
required_features
|
15
|
+
.all? { |feature| has_permission?(context, role_permissions[feature]) }
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def has_permission?(context, role_permission)
|
21
|
+
return false if role_permission.nil?
|
22
|
+
|
23
|
+
if !(any = role_permission['any']).nil?
|
24
|
+
any
|
25
|
+
elsif only = role_permission['only']
|
26
|
+
check_feature_permission(only) { |perm| context.include?(perm) }
|
27
|
+
elsif except = role_permission['except']
|
28
|
+
check_feature_permission(except) { |perm| !context.include?(perm) }
|
29
|
+
else
|
30
|
+
raise NotImplementedError
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def check_feature_permission(context_values)
|
35
|
+
MapValuesAsDowncasedStrings.(context_values).any? do |context_value|
|
36
|
+
Array(context_value.split('.')).all? { |permission| yield(permission) }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Permissions
|
42
|
+
attr_reader :role, :context
|
43
|
+
|
44
|
+
def self.[](instance)
|
45
|
+
return instance if instance.is_a?(Permissions)
|
46
|
+
|
47
|
+
raise ArgumentError, "#{instance.inspect} must be a #{self.name}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def initialize(role_permissions, context: [])
|
51
|
+
@role = role_permissions.dup.freeze
|
52
|
+
@context = MapValuesAsDowncasedStrings.(context).freeze
|
53
|
+
|
54
|
+
@cache = {}
|
55
|
+
end
|
56
|
+
|
57
|
+
def to?(features = nil)
|
58
|
+
required_features = MapValuesAsDowncasedStrings.(features)
|
59
|
+
|
60
|
+
cache_key = required_features.inspect
|
61
|
+
|
62
|
+
return @cache[cache_key] unless @cache[cache_key].nil?
|
63
|
+
|
64
|
+
@cache[cache_key] = CheckRolePermission.call(
|
65
|
+
@context, @role, required_features
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_not?(features = nil)
|
70
|
+
!to?(features)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class Policy
|
75
|
+
def self.type(klass)
|
76
|
+
return klass if klass < self
|
77
|
+
|
78
|
+
raise ArgumentError, "policy must be a #{self.name}"
|
79
|
+
end
|
80
|
+
|
81
|
+
def initialize(user, subject = nil, permissions: nil)
|
82
|
+
@user = user
|
83
|
+
@subject = subject
|
84
|
+
@permissions = permissions
|
85
|
+
end
|
86
|
+
|
87
|
+
def method_missing(method, *args, **keyargs, &block)
|
88
|
+
return false if method =~ /\?\z/
|
89
|
+
super(method)
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def user; @user; end
|
95
|
+
def subject; @subject; end
|
96
|
+
def permissions; @permissions; end
|
97
|
+
end
|
98
|
+
|
99
|
+
class Model
|
100
|
+
attr_reader :user, :permissions
|
101
|
+
|
102
|
+
def self.build(user, role, context: [], policies: {})
|
103
|
+
permissions = Permissions.new(role, context: context)
|
104
|
+
|
105
|
+
self.new(user, permissions: permissions, policies: policies)
|
106
|
+
end
|
107
|
+
|
108
|
+
def initialize(user, permissions:, policies: {})
|
109
|
+
@user = user
|
110
|
+
@policies = {}
|
111
|
+
@policies_cache = {}
|
112
|
+
@permissions = Permissions[permissions]
|
113
|
+
|
114
|
+
add_policies(policies)
|
115
|
+
end
|
116
|
+
|
117
|
+
def map(context: nil, policies: nil)
|
118
|
+
if context.nil? && policies.nil?
|
119
|
+
raise ArgumentError, 'context or policies keywords args must be defined'
|
120
|
+
end
|
121
|
+
|
122
|
+
new_permissions =
|
123
|
+
Permissions.new(permissions.role, context: context || @context)
|
124
|
+
|
125
|
+
self.class.new(
|
126
|
+
user, permissions: new_permissions, policies: policies || @policies
|
127
|
+
)
|
128
|
+
end
|
129
|
+
|
130
|
+
def add_policy(key, policy_klass)
|
131
|
+
raise ArgumentError, 'key must be a Symbol' unless key.is_a?(Symbol)
|
132
|
+
|
133
|
+
@policies[key] ||= Policy.type(policy_klass)
|
134
|
+
|
135
|
+
self
|
136
|
+
end
|
137
|
+
|
138
|
+
def add_policies(new_policies)
|
139
|
+
unless new_policies.is_a?(Hash)
|
140
|
+
raise ArgumentError, "policies must be a Hash (key => #{Policy.name})"
|
141
|
+
end
|
142
|
+
|
143
|
+
new_policies.each &method(:add_policy)
|
144
|
+
|
145
|
+
self
|
146
|
+
end
|
147
|
+
|
148
|
+
def to(policy_key, subject: nil)
|
149
|
+
policy_klass = @policies.fetch(policy_key, Policy)
|
150
|
+
|
151
|
+
return policy_klass.new(user, subject, permissions: permissions) if subject
|
152
|
+
|
153
|
+
return @policies_cache[policy_key] if @policies_cache[policy_key]
|
154
|
+
|
155
|
+
policy_klass.new(user, permissions: permissions).tap do |instance|
|
156
|
+
@policies_cache[policy_key] = instance if policy_klass != Policy
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def policy(key = :default, subject: nil)
|
161
|
+
to(key, subject: subject)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
data/u-authorization.rb
ADDED
metadata
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: u-authorization
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rodrigo Serradura
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-10-18 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Simple authorization library and role managment for Ruby.
|
14
|
+
email: rodrigo.serradura@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- authorization.rb
|
20
|
+
- u-authorization.rb
|
21
|
+
homepage: https://gist.github.com/serradura/7d51b979b90609d8601d0f416a9aa373
|
22
|
+
licenses:
|
23
|
+
- MIT
|
24
|
+
metadata: {}
|
25
|
+
post_install_message:
|
26
|
+
rdoc_options: []
|
27
|
+
require_paths:
|
28
|
+
- "."
|
29
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.2.2
|
34
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ">="
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
requirements: []
|
40
|
+
rubyforge_project:
|
41
|
+
rubygems_version: 2.7.7
|
42
|
+
signing_key:
|
43
|
+
specification_version: 4
|
44
|
+
summary: Authorization library and role managment
|
45
|
+
test_files: []
|