omniperm 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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