omniperm 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 04bdb832b5cfc5b526a541dad64aa588f44c71342a94940d9bdc9620c7589429
4
- data.tar.gz: a574b750fa0d74c9c654e6d10af2a755be2f4dbde911286a5cfa744b3a3db7f8
3
+ metadata.gz: 9a95c6e48a800f14e564fc1739f3de6c7523f6da0df3a74a7551cf1bfb1112ae
4
+ data.tar.gz: d0cfb2fa102d4364af689f12aa261f03400c340d0f03579463da58625221c252
5
5
  SHA512:
6
- metadata.gz: ac9b1b1dae8f9c57f869dcc85f7bd61b019303615c07aec0bee8ccbfd46e13435dfd18857eabe4b596d5b810df563c1087b6a8b67977882afa66384671e0f6db
7
- data.tar.gz: 2194424c41ef5f61797145cb4c34f55db07050c636c45d7ce79eaa1430f0cc399ef9fc5c95e6814dcb7ae7ec1316d706e5c77ba81c96a8724e7a529db22a69b5
6
+ metadata.gz: fc51b8f2f0f9e59d60d74dfa8955f5a26017eff84ded89abd0e39498a731bea21a4c1eb692baec1e89c6fc9e215dc81e33d3a3dfd9adc7b60d84efe8dead6acd
7
+ data.tar.gz: 4a9b02818fd4a898918c67ff1c423290bcbbf60bbbbdf8fedc5eed741a53760314fc815aa36ce27fd27ecb1cc0555040b031b14f527a13e907edbbcff9e5244f
@@ -0,0 +1,21 @@
1
+ version: 2.1
2
+ orbs:
3
+ ruby: circleci/ruby@0.1.2
4
+
5
+ jobs:
6
+ build:
7
+ docker:
8
+ - image: circleci/ruby:2.6.3-stretch-node
9
+ executor: ruby/default
10
+ steps:
11
+ - checkout
12
+ - run:
13
+ name: Install bundler
14
+ command: gem install bundler:2.1.4
15
+ - run:
16
+ name: Which bundler?
17
+ command: bundle -v
18
+ - ruby/bundle-install
19
+ - run:
20
+ name: Run tests
21
+ command: rake
@@ -0,0 +1,32 @@
1
+ # General
2
+ .DS_Store
3
+ .AppleDouble
4
+ .LSOverride
5
+
6
+ # Icon must end with two \r
7
+ Icon
8
+
9
+ # Thumbnails
10
+ ._*
11
+
12
+ # Files that might appear in the root of a volume
13
+ .DocumentRevisions-V100
14
+ .fseventsd
15
+ .Spotlight-V100
16
+ .TemporaryItems
17
+ .Trashes
18
+ .VolumeIcon.icns
19
+ .com.apple.timemachine.donotpresent
20
+
21
+ # Directories potentially created on remote AFP share
22
+ .AppleDB
23
+ .AppleDesktop
24
+ Network Trash Folder
25
+ Temporary Items
26
+ .apdisk
27
+
28
+ .ruby-gemset
29
+ .ruby-version
30
+
31
+ tmp/
32
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in context_authorization.gemspec
6
+ gemspec
@@ -0,0 +1,146 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ omniperm (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ actioncable (6.0.3.2)
10
+ actionpack (= 6.0.3.2)
11
+ nio4r (~> 2.0)
12
+ websocket-driver (>= 0.6.1)
13
+ actionmailbox (6.0.3.2)
14
+ actionpack (= 6.0.3.2)
15
+ activejob (= 6.0.3.2)
16
+ activerecord (= 6.0.3.2)
17
+ activestorage (= 6.0.3.2)
18
+ activesupport (= 6.0.3.2)
19
+ mail (>= 2.7.1)
20
+ actionmailer (6.0.3.2)
21
+ actionpack (= 6.0.3.2)
22
+ actionview (= 6.0.3.2)
23
+ activejob (= 6.0.3.2)
24
+ mail (~> 2.5, >= 2.5.4)
25
+ rails-dom-testing (~> 2.0)
26
+ actionpack (6.0.3.2)
27
+ actionview (= 6.0.3.2)
28
+ activesupport (= 6.0.3.2)
29
+ rack (~> 2.0, >= 2.0.8)
30
+ rack-test (>= 0.6.3)
31
+ rails-dom-testing (~> 2.0)
32
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
33
+ actiontext (6.0.3.2)
34
+ actionpack (= 6.0.3.2)
35
+ activerecord (= 6.0.3.2)
36
+ activestorage (= 6.0.3.2)
37
+ activesupport (= 6.0.3.2)
38
+ nokogiri (>= 1.8.5)
39
+ actionview (6.0.3.2)
40
+ activesupport (= 6.0.3.2)
41
+ builder (~> 3.1)
42
+ erubi (~> 1.4)
43
+ rails-dom-testing (~> 2.0)
44
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
45
+ activejob (6.0.3.2)
46
+ activesupport (= 6.0.3.2)
47
+ globalid (>= 0.3.6)
48
+ activemodel (6.0.3.2)
49
+ activesupport (= 6.0.3.2)
50
+ activerecord (6.0.3.2)
51
+ activemodel (= 6.0.3.2)
52
+ activesupport (= 6.0.3.2)
53
+ activestorage (6.0.3.2)
54
+ actionpack (= 6.0.3.2)
55
+ activejob (= 6.0.3.2)
56
+ activerecord (= 6.0.3.2)
57
+ marcel (~> 0.3.1)
58
+ activesupport (6.0.3.2)
59
+ concurrent-ruby (~> 1.0, >= 1.0.2)
60
+ i18n (>= 0.7, < 2)
61
+ minitest (~> 5.1)
62
+ tzinfo (~> 1.1)
63
+ zeitwerk (~> 2.2, >= 2.2.2)
64
+ builder (3.2.4)
65
+ concurrent-ruby (1.1.6)
66
+ crass (1.0.6)
67
+ erubi (1.9.0)
68
+ globalid (0.4.2)
69
+ activesupport (>= 4.2.0)
70
+ i18n (1.8.5)
71
+ concurrent-ruby (~> 1.0)
72
+ loofah (2.6.0)
73
+ crass (~> 1.0.2)
74
+ nokogiri (>= 1.5.9)
75
+ mail (2.7.1)
76
+ mini_mime (>= 0.1.1)
77
+ marcel (0.3.3)
78
+ mimemagic (~> 0.3.2)
79
+ method_source (1.0.0)
80
+ mimemagic (0.3.5)
81
+ mini_mime (1.0.2)
82
+ mini_portile2 (2.4.0)
83
+ minitest (5.11.3)
84
+ minitest-sprint (1.2.1)
85
+ path_expander (~> 1.1)
86
+ nio4r (2.5.2)
87
+ nokogiri (1.10.10)
88
+ mini_portile2 (~> 2.4.0)
89
+ path_expander (1.1.0)
90
+ rack (2.2.3)
91
+ rack-test (1.1.0)
92
+ rack (>= 1.0, < 3)
93
+ rails (6.0.3.2)
94
+ actioncable (= 6.0.3.2)
95
+ actionmailbox (= 6.0.3.2)
96
+ actionmailer (= 6.0.3.2)
97
+ actionpack (= 6.0.3.2)
98
+ actiontext (= 6.0.3.2)
99
+ actionview (= 6.0.3.2)
100
+ activejob (= 6.0.3.2)
101
+ activemodel (= 6.0.3.2)
102
+ activerecord (= 6.0.3.2)
103
+ activestorage (= 6.0.3.2)
104
+ activesupport (= 6.0.3.2)
105
+ bundler (>= 1.3.0)
106
+ railties (= 6.0.3.2)
107
+ sprockets-rails (>= 2.0.0)
108
+ rails-dom-testing (2.0.3)
109
+ activesupport (>= 4.2.0)
110
+ nokogiri (>= 1.6)
111
+ rails-html-sanitizer (1.3.0)
112
+ loofah (~> 2.3)
113
+ railties (6.0.3.2)
114
+ actionpack (= 6.0.3.2)
115
+ activesupport (= 6.0.3.2)
116
+ method_source
117
+ rake (>= 0.8.7)
118
+ thor (>= 0.20.3, < 2.0)
119
+ rake (13.0.1)
120
+ sprockets (4.0.2)
121
+ concurrent-ruby (~> 1.0)
122
+ rack (> 1, < 3)
123
+ sprockets-rails (3.2.1)
124
+ actionpack (>= 4.0)
125
+ activesupport (>= 4.0)
126
+ sprockets (>= 3.0.0)
127
+ thor (1.0.1)
128
+ thread_safe (0.3.6)
129
+ tzinfo (1.2.7)
130
+ thread_safe (~> 0.1)
131
+ websocket-driver (0.7.3)
132
+ websocket-extensions (>= 0.1.0)
133
+ websocket-extensions (0.1.5)
134
+ zeitwerk (2.4.0)
135
+
136
+ PLATFORMS
137
+ ruby
138
+
139
+ DEPENDENCIES
140
+ minitest (~> 5.0)
141
+ minitest-sprint
142
+ omniperm!
143
+ rails
144
+
145
+ BUNDLED WITH
146
+ 2.1.4
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2020 Samuel BOHN
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.
@@ -0,0 +1,47 @@
1
+ [![Circle CI](https://circleci.com/gh/3pns/omniperm.svg?style=svg)](https://circleci.com/gh/3pns/omniperm)
2
+
3
+ # OmniPerm
4
+
5
+ ## About
6
+
7
+ With Omniperm you can centralize your authorization strategies in a YAML file against a configurable context
8
+
9
+ ## Install
10
+
11
+ Install for Ruby on Rails applications
12
+
13
+ ```
14
+ rails g omniperm:install
15
+ ```
16
+
17
+ ## How to use
18
+
19
+ Manually authorize a method
20
+
21
+ ```
22
+ def my_method
23
+ service_authorized?
24
+ end
25
+ ```
26
+
27
+ Authorize all methods of a class and its children
28
+
29
+ ```
30
+ class MyService < Omniperm::AuthorizationRequired
31
+
32
+ def do_something
33
+ end
34
+
35
+ def do_another_thing
36
+ end
37
+ end
38
+
39
+ class MySubService < MyService
40
+
41
+ def do_something
42
+ end
43
+
44
+ def do_another_thing
45
+ end
46
+ end
47
+ ```
@@ -0,0 +1,19 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/gem_tasks"
5
+ require "rake/testtask"
6
+
7
+ desc "Run all the tests"
8
+ task default: :test
9
+
10
+ desc 'Run unit tests.'
11
+ Rake::TestTask.new(:test) do |t|
12
+ puts "running tests"
13
+ #t.libs << 'lib'
14
+ t.libs << 'test'
15
+ # t.pattern = 'test/**/*_test.rb'
16
+ t.test_files = FileList["test/**/*_test.rb", "test/**/spec_*.rb", "test/gemloader.rb"]
17
+ t.verbose = true
18
+ t.warning = false
19
+ end
@@ -0,0 +1,19 @@
1
+ require 'rails/generators'
2
+
3
+ module Omniperm
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path('templates', __dir__)
7
+
8
+ desc "Creates Omniperm initializer and copy a template authorizations.yml to your application."
9
+
10
+ def copy_initializer
11
+ copy_file "omniperm.rb", "config/initializers/omniperm.rb"
12
+ end
13
+
14
+ def copy_authorizations
15
+ copy_file "omniperm.yml", "config/omniperm.yml"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,18 @@
1
+ # Configure Omniperm to tailor fit your application
2
+ Omniperm.configure do |config|
3
+ config.config_file = 'config/omniperm.yml'
4
+
5
+ # Strategies not allowed will be unauthorized
6
+ # Example of common types of strategies :
7
+ # Use roles : admin/staff/user/superuser
8
+ # Third party services : nanosoft/pears/amazonia
9
+ config.whitelisted_strategies = ["nanosoft", "pears", "amazonia"]
10
+
11
+ # determine_strategy shall return the strategy of a given object
12
+ config.determine_strategy = -> (obj, instance_variables){
13
+ return obj if obj.class == String
14
+ return @role unless @role.nil?
15
+ return obj.role if obj.respond_to?("role")
16
+ return obj.owner.role if obj.respond_to?("item")
17
+ }
18
+ end
@@ -0,0 +1,18 @@
1
+ #############################
2
+ ######### Omniperm ##########
3
+ #############################
4
+ # Describe your authorization strategy in this file
5
+
6
+ # ExampleClass:
7
+ # default: false
8
+ # pear: true
9
+ # amazonia: false
10
+ # ExampleModule:
11
+ # pear: true
12
+ # nanosoft: false
13
+ # NestedClass: true
14
+ # TestClass: true
15
+ # default: true
16
+ # Nested:
17
+ # nested_method: false
18
+ # another_nested_method: true
@@ -0,0 +1,52 @@
1
+ require 'yaml' if not Object.const_defined?("YAML")
2
+
3
+ module Omniperm
4
+ # Configures global settings for Omniperm
5
+ # Omniperm.configure do |config|
6
+ # config.config_file = 'config/service_authorizations.yml'
7
+ # end
8
+ class << self
9
+ def configure
10
+ yield config
11
+ end
12
+
13
+ def config
14
+ @_config ||= Config.new
15
+ end
16
+ end
17
+
18
+ class Config
19
+ attr_accessor :config_file, :whitelisted_strategies, :rules, :determine_strategy
20
+ attr_reader :rules
21
+
22
+ def initialize
23
+ @authorizable_name = 'service'
24
+ # @config_file = "config/#{@authorizable_name}_authorizations.yml" # for multi contexts
25
+ @config_file = 'config/omniperm.yml'
26
+ @whitelisted_strategies = []
27
+ begin
28
+ @rules = YAML.load_file(@config_file)
29
+ rescue
30
+ @rules = {}
31
+ end
32
+ @determine_strategy = -> (obj){
33
+ return "default"
34
+ }
35
+ end
36
+
37
+ def config_file=(config_file)
38
+ @config_file = config_file
39
+ @rules = YAML.load_file(@config_file)
40
+ end
41
+
42
+ def determine_strategy=(new_strategy)
43
+ @determine_strategy = new_strategy
44
+ Object.class_eval do
45
+ def __omniperm_determine_strategy(obj)
46
+ self.instance_exec(obj, &Omniperm.config.determine_strategy)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+
@@ -0,0 +1,30 @@
1
+ module Omniperm
2
+ module Core
3
+ def self.authorize(returnable, authorization)
4
+ return authorization if returnable.to_s == "boolean"
5
+ raise Exception.new "Omniperm: Unauthorized" if returnable.to_s == "raise" and authorization == false
6
+ end
7
+
8
+ def self.authorize_service(context, returnable: "boolean", hierarchy: "", strategy: "default")
9
+ method_name = caller_locations(2,1)[0].label
10
+ whitelisted_strategies = Omniperm.config.whitelisted_strategies
11
+ rules = Omniperm.config.rules
12
+
13
+ return self.authorize(returnable, false) unless whitelisted_strategies.include?(strategy)
14
+ stack = [] + hierarchy.split("::") + [method_name] + [""]
15
+ while stack.slice!(-1) != nil do
16
+ rule = rules
17
+ stack.each do |key|
18
+ next if key.nil?
19
+ rule = rule[key] unless rule.nil?
20
+ return self.authorize(returnable, rule) if [true, false].include?(rule)
21
+ end
22
+ next if rule.nil?
23
+ return self.authorize(returnable, rule[strategy]) if rule.is_a? Hash and rule.keys.include?(strategy)
24
+ return self.authorize(returnable, rule["default"]) if rule.is_a? Hash and rule.keys.include?("default")
25
+ return self.authorize(returnable, rule) if [true, false].include?(rule)
26
+ end
27
+ return self.authorize(returnable, false)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,112 @@
1
+ module Omniperm
2
+ module CallbackDecorators
3
+
4
+ module MethodsDecorator
5
+
6
+ def __before_method
7
+ end
8
+
9
+ def __after_method
10
+ end
11
+
12
+ def decorate_methods_with_before_and_after
13
+ target_methods = singleton_methods(false) + instance_methods(false)
14
+ target_methods.reject{|value| [:inject_before_to_methods, :__before_method, :__after_method].include?(value) }.each { |m|
15
+ # Rename original method
16
+ target = nil
17
+ target = self if instance_methods(false).include?(m.to_sym)
18
+ target = self.singleton_class if singleton_methods(false).include?(m.to_sym)
19
+ if target
20
+ target.send(:alias_method, "__#{m}_original", m)
21
+ target.define_method m do |*args, **kwargs|
22
+ before_method = Proc.new {
23
+ if respond_to?("__before_method")
24
+ return_value = __before_method
25
+ else
26
+ return_value = target.__before_method
27
+ end
28
+
29
+ return return_value unless return_value.nil?
30
+ };
31
+ before_method.call
32
+
33
+ if kwargs.empty?
34
+ return self.send "__#{m}_original", *args
35
+ else
36
+ return self.send "__#{m}_original", *args, **kwargs
37
+ end
38
+ # after_method = Proc.new {
39
+ # return_value = __after_method
40
+ # return return_value unless return_value.nil?
41
+ # };
42
+ # after_method.call
43
+ end
44
+ end
45
+ }
46
+ end
47
+ end
48
+
49
+ class ClassDecorator
50
+ extend CallbackDecorators::MethodsDecorator
51
+
52
+ def self.inherited(subclass)
53
+ TracePoint.trace(:end) do |t|
54
+ if subclass == t.self
55
+ subclass.decorate_methods_with_before_and_after
56
+ t.disable
57
+ end
58
+ end
59
+ super
60
+ end
61
+ end
62
+
63
+ module MixinDecorator
64
+ def self.included base
65
+ base.extend CallbackDecorators::MethodsDecorator
66
+ TracePoint.trace(:end) do |t|
67
+ if base == t.self
68
+ base.decorate_methods_with_before_and_after
69
+ t.disable
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ # is working
77
+ class AuthorizationRequired < CallbackDecorators::ClassDecorator
78
+
79
+ def self.__before_method
80
+ # Warning: method name will be dected as __before_method
81
+ unless service_authorized?
82
+ return false # stop execution
83
+ end
84
+ return # allow execution to continue
85
+ end
86
+
87
+ def __before_method
88
+ # Warning: method name will be dected as __before_method
89
+ unless service_authorized?
90
+ return false # stop execution
91
+ end
92
+ return # allow execution to continue
93
+ end
94
+
95
+ end
96
+
97
+ # is broken / dont work anymore
98
+ module Authorizable
99
+ include CallbackDecorators::MixinDecorator
100
+
101
+ def __before_method
102
+ unless service_authorized?
103
+ return false # stop execution
104
+ end
105
+ return
106
+ end
107
+
108
+ def __after_method
109
+ end
110
+
111
+ end
112
+ end
@@ -0,0 +1,24 @@
1
+ require_relative 'core.rb'
2
+
3
+ module Omniperm
4
+ module Helpers
5
+ private
6
+ def hierarchy
7
+ if [Class, Module].include?(self.class)
8
+ name
9
+ else
10
+ self.class.to_s
11
+ end
12
+ end
13
+
14
+ def service_authorized?(obj = nil)
15
+ strategy = __omniperm_determine_strategy(obj)
16
+ Core.authorize_service(obj, returnable: "boolean", hierarchy: hierarchy, strategy: strategy)
17
+ end
18
+
19
+ def service_authorized!(obj = nil)
20
+ strategy = __omniperm_determine_strategy(obj)
21
+ Core.authorize_service(obj, returnable: "raise", hierarchy: hierarchy, strategy: strategy)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ module Omniperm
2
+ VERSION = '0.0.3'
3
+ end
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'omniperm/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{omniperm}
8
+ s.version = Omniperm::VERSION
9
+ s.authors = ['Samuel Bohn']
10
+ s.email = %w(samuel@hydrodigit.com)
11
+ s.date = %q{2020-07-21}
12
+ s.description = %q{With Omniperm you can centralize your authorization strategies in a YAML file against a configurable context }
13
+ s.summary = 'Flexible Authorization for Ruby or Rails'
14
+ s.homepage = 'https://github.com/3pns/omniperm'
15
+ s.license = 'MIT'
16
+ s.files = `git ls-files`.split($/)
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_development_dependency 'minitest', "~> 5.0"
20
+ s.add_development_dependency 'minitest-sprint'
21
+ s.add_development_dependency 'rails'
22
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ describe Omniperm::Core do
6
+ before do
7
+ @user = User.new(:pear)
8
+ @user_googol = User.new(:googol)
9
+ @service_class_decorated_allowed = Services::ExternalServiceClassDecorated.new(@user)
10
+ @service_class_decorated_nanosoft_allowed = Services::ExternalServiceClassDecorated.new(@user_googol)
11
+ end
12
+
13
+ it 'should perform authorization' do
14
+ skip("todo: fix method name not properly detected using inheritance")
15
+ assert_equal 42, @service_class_decorated_allowed.load_data
16
+ end
17
+
18
+ it 'should perform authorization' do
19
+ skip("todo: fix method name not properly detected using inheritance")
20
+ assert_equal 42, @service_class_decorated_allowed.buy
21
+ end
22
+
23
+ it 'should perform authorization' do
24
+ assert_equal false, @service_class_decorated_allowed.bucket
25
+ end
26
+
27
+ it 'should perform authorization' do
28
+ assert_equal false, @service_class_decorated_allowed.n42
29
+ end
30
+
31
+ it 'should perform authorization' do
32
+ assert_equal 42, @service_class_decorated_nanosoft_allowed.load_data
33
+ end
34
+
35
+ it 'should perform authorization' do
36
+ assert_equal 42, @service_class_decorated_nanosoft_allowed.buy
37
+ end
38
+
39
+ it 'should perform authorization' do
40
+ assert_equal 42, @service_class_decorated_nanosoft_allowed.bucket
41
+ end
42
+
43
+ it 'should perform authorization' do
44
+ assert_equal 42, @service_class_decorated_nanosoft_allowed.n42
45
+ end
46
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubygems'
4
+ project = 'omniperm'
5
+ gemspec = File.expand_path("#{project}.gemspec", Dir.pwd)
6
+ Gem::Specification.load(gemspec).dependencies.each do |dep|
7
+ begin
8
+ gem dep.name, *dep.requirement.as_list
9
+ rescue Gem::LoadError
10
+ warn "Cannot load #{dep.name} #{dep.requirement.to_s}"
11
+ end
12
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ ENV["RAILS_ENV"] = "test"
4
+ require_relative '../lib/omniperm'
5
+ require_relative 'models/user'
6
+ require_relative 'services/class_service'
7
+ require_relative 'services/module_service'
8
+ require_relative 'services/external_service'
9
+ require_relative 'services/internal_service'
10
+ require_relative 'services/external_service_class_decorated'
11
+ require 'minitest/spec'
12
+ require 'minitest/autorun'
13
+ Dir["models/services/*.rb"].each {|file| require file }
14
+
15
+ # configure Omniperm
16
+ Omniperm.configure do |config|
17
+ config.config_file = 'test/test_config.yml'
18
+ config.whitelisted_strategies = ["nanosoft", "pear", "googol"]
19
+ config.determine_strategy = -> (obj){
20
+ return obj if obj.class == String
21
+ return @user.adaptor_type if @user
22
+ return obj.adaptor_type if obj.class == User
23
+ return "default"
24
+ }
25
+ end
@@ -0,0 +1,7 @@
1
+ class User
2
+ attr_reader :adaptor_type
3
+
4
+ def initialize(adaptor_type)
5
+ @adaptor_type = adaptor_type.to_s
6
+ end
7
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ describe Omniperm::Core do
6
+ before do
7
+ @user = User.new(:pear)
8
+ @service = Services::ExternalService.new(@user)
9
+ @internal_service = Services::InternalService.new(@user)
10
+ @secret_service = Services::InternalService::SecretService.new(@user)
11
+ end
12
+
13
+ it 'should properly detect hierarchy and method_name from a module method' do
14
+ assert_equal 42, Services::ModuleService.compute(@user)
15
+ end
16
+
17
+ it 'should properly detect hierarchy and method_name from a class method' do
18
+ assert_equal 42, Services::ClassService.compute(@user)
19
+ end
20
+
21
+ it 'should deny if element has default to true' do
22
+ assert_equal false, @internal_service.save_data
23
+ end
24
+
25
+ it 'should priorize elements higher in the hierarchy' do
26
+ assert_equal 42, @secret_service.save_data
27
+ end
28
+
29
+ it 'should find element without passing any arg' do
30
+ assert_equal false, @internal_service.authorize_with_no_args
31
+ assert_equal 42, @secret_service.authorize_with_no_args
32
+ end
33
+
34
+ it 'should authorize if element in hierarchy is true' do
35
+ assert_equal 42, @service.load_data
36
+ end
37
+
38
+ it 'should authorize if method is true' do
39
+ assert_equal 42, @service.buy
40
+ end
41
+
42
+ it 'should deny if method exist but has no rule for strategy' do
43
+ assert_equal false, @service.bucket
44
+ end
45
+
46
+ it 'should not authorize if no rule in the hierarchy' do
47
+ assert_equal false, @service.n42
48
+ end
49
+
50
+ end
@@ -0,0 +1,8 @@
1
+ module Services
2
+ class ClassService
3
+ def self.compute(user)
4
+ return false unless service_authorized?(user)
5
+ return 42
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,28 @@
1
+ module Services
2
+ class ExternalService
3
+
4
+ def initialize(user)
5
+ @user = user
6
+ end
7
+
8
+ def load_data
9
+ return false unless service_authorized?(@user)
10
+ return 42
11
+ end
12
+
13
+ def buy
14
+ return false unless service_authorized?(@user)
15
+ return 42
16
+ end
17
+
18
+ def bucket
19
+ return false unless service_authorized?(@user)
20
+ return 42
21
+ end
22
+
23
+ def n42
24
+ return false unless service_authorized?(@user)
25
+ return 42
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ module Services
2
+ class ExternalServiceClassDecorated < Omniperm::AuthorizationRequired
3
+
4
+ def initialize(user)
5
+ @user = user
6
+ end
7
+
8
+ def load_data
9
+ return 42
10
+ end
11
+
12
+ def buy
13
+ return 42
14
+ end
15
+
16
+ def bucket
17
+ return 42
18
+ end
19
+
20
+ def n42
21
+ return 42
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,34 @@
1
+ module Services
2
+ class InternalService
3
+
4
+ def initialize(user)
5
+ @user = user
6
+ end
7
+
8
+ def authorize_with_no_args
9
+ return false unless service_authorized?
10
+ return 42
11
+ end
12
+
13
+ def save_data
14
+ return false unless service_authorized?(@user)
15
+ return 42
16
+ end
17
+
18
+ class SecretService
19
+ def initialize(user)
20
+ @user = user
21
+ end
22
+
23
+ def authorize_with_no_args
24
+ return false unless service_authorized?
25
+ return 42
26
+ end
27
+
28
+ def save_data
29
+ return false unless service_authorized?(@user)
30
+ return 42
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,8 @@
1
+ module Services
2
+ module ModuleService
3
+ def self.compute(user)
4
+ return false unless service_authorized?(user)
5
+ return 42
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,27 @@
1
+ Services:
2
+ InternalService:
3
+ default: false
4
+ SecretService: true
5
+ ExternalService:
6
+ load_data: true
7
+ buy:
8
+ nanosoft: true
9
+ pear: true
10
+ bucket:
11
+ googol: true
12
+ nanosoft: true
13
+ ModuleService:
14
+ compute:
15
+ pear: true
16
+ ClassService:
17
+ compute:
18
+ pear: true
19
+ ExternalServiceClassDecorated:
20
+ googol: true # all true for googol
21
+ load_data: true
22
+ buy:
23
+ nanosoft: true
24
+ pear: true
25
+ bucket:
26
+ googol: true
27
+ nanosoft: true
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniperm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Bohn
@@ -60,7 +60,34 @@ executables: []
60
60
  extensions: []
61
61
  extra_rdoc_files: []
62
62
  files:
63
+ - ".circleci/config.yml"
64
+ - ".gitignore"
65
+ - Gemfile
66
+ - Gemfile.lock
67
+ - MIT-LICENSE
68
+ - README.md
69
+ - Rakefile
70
+ - lib/generators/omniperm/install_generator.rb
71
+ - lib/generators/omniperm/templates/omniperm.rb
72
+ - lib/generators/omniperm/templates/omniperm.yml
63
73
  - lib/omniperm.rb
74
+ - lib/omniperm/config.rb
75
+ - lib/omniperm/core.rb
76
+ - lib/omniperm/decorators.rb
77
+ - lib/omniperm/helpers.rb
78
+ - lib/omniperm/version.rb
79
+ - omniperm.gemspec
80
+ - test/decorators_test.rb
81
+ - test/gemloader.rb
82
+ - test/helper.rb
83
+ - test/models/user.rb
84
+ - test/omniperm_test.rb
85
+ - test/services/class_service.rb
86
+ - test/services/external_service.rb
87
+ - test/services/external_service_class_decorated.rb
88
+ - test/services/internal_service.rb
89
+ - test/services/module_service.rb
90
+ - test/test_config.yml
64
91
  homepage: https://github.com/3pns/omniperm
65
92
  licenses:
66
93
  - MIT