toni 0.0.1 → 0.0.2

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
  SHA1:
3
- metadata.gz: c0672f47c55346d477e4489c4cefcb1f0e000c9b
4
- data.tar.gz: 8cdca30ac45fd0d3674236da33729e9042938400
3
+ metadata.gz: 7ac2b196171e40bf0d69e5c191c4a9435ce3855a
4
+ data.tar.gz: 587bbdcb7dd9a86db28551388a8efe786b6ceaa6
5
5
  SHA512:
6
- metadata.gz: 162bce0becb671e9bf13c50ce2667a8b096cef24bf10e0358f1e4f06d33136458994ffea265134c595f8dc9b5adf8ef7da549a0a828a5eed73a6bf8f60c04388
7
- data.tar.gz: d20995225334b18c8ac4435ea7c3d2fdf952742679db715f44804d5f3ed1e666c56190ddc96422d0a0b4bfd2d47d5318aea306dab2cc8104ce1b42e3c175460d
6
+ metadata.gz: bdadf5d1db3e86f10963fda52f7b810d2f1ad87c071a0959d871f3f28a9bbac9dae2e28838eeaa7bfb3e4eb9f60ecf7fe88476cb2bff28e00de6415fd940b177
7
+ data.tar.gz: aa782e08c89471234beb82c2690f29c6ed0f8a10dc9e597e2ef8cd159784bf86d59278daf56e318301d43d6b83324d4c00e5fb6331618e64e2abca87c3752902
data/.travis.yml CHANGED
@@ -2,7 +2,8 @@ language: ruby
2
2
  rvm:
3
3
  - 2.1.0
4
4
  - 2.0.0
5
+ - jruby-19mode
5
6
  addons:
6
7
  code_climate:
7
- repo_token: 53df9a1d69568057bc007b09
8
+ repo_token: a08fee81d94a545de3cd98a06528c3428d7ec70cae31137730bdf10664eb0a61
8
9
  script: bundle exec rspec spec
data/Gemfile CHANGED
@@ -3,4 +3,7 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in toni.gemspec
4
4
  gemspec
5
5
 
6
- gem "codeclimate-test-reporter", group: :test, require: nil
6
+ gem "codeclimate-test-reporter", group: :test, require: nil
7
+ gem "sqlite3", group: :test, platform: :ruby
8
+ gem "jdbc-sqlite3", group: :test, platform: :jruby
9
+ gem "activerecord-jdbcsqlite3-adapter", group: :test, platform: :jruby
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # Toni
2
- [![Build Status](https://travis-ci.org/jalyna/toni.svg?branch=master)](https://travis-ci.org/jalyna/toni) [![Code Climate](https://codeclimate.com/github/jalyna/toni/badges/gpa.svg)](https://codeclimate.com/github/jalyna/toni) [![Inline docs](http://inch-ci.org/github/jalyna/toni.png?branch=master)](http://inch-ci.org/github/jalyna/toni)
2
+ [![Gem Version](https://badge.fury.io/rb/toni.svg)](http://badge.fury.io/rb/toni) [![Build Status](https://travis-ci.org/jalyna/toni.svg?branch=master)](https://travis-ci.org/jalyna/toni) [![Code Climate](https://codeclimate.com/github/jalyna/toni/badges/gpa.svg)](https://codeclimate.com/github/jalyna/toni) [![Test Coverage](https://codeclimate.com/github/jalyna/toni/badges/coverage.svg)](https://codeclimate.com/github/jalyna/toni) [![Inline docs](http://inch-ci.org/github/jalyna/toni.png?branch=master)](http://inch-ci.org/github/jalyna/toni)
3
3
 
4
4
  Toni enables you to create a centralized authorization rules configuration with a readable DSL,
5
5
  similar to [declarative authorization](https://github.com/stffn/declarative_authorization), but not required to use with Ruby on Rails.
6
- Internally the Gem is using RSpec Matchers. You can use Toni with **Sinatra** and **Ruby on Rails**.
6
+ Internally the Gem is using RSpec Matchers. You can use Toni with **[Sinatra](#sinatra)** and **[Ruby on Rails](#ruby-on-rails)**.
7
7
 
8
8
  ## Installation
9
9
 
@@ -23,14 +23,113 @@ Or install it yourself as:
23
23
 
24
24
  ### Setup Authorization Rules
25
25
 
26
- TODO: Write usage instructions here
26
+ To setup the rules that your toni uses you have to create a `authorization_rules.rb` file e.g. in your config folder:
27
27
 
28
- ### Ruby on Rails
28
+ ```ruby
29
+ # Guest role gets automatically assigned if you don't have a current_user
30
+ role :guest do
31
+ has_permission_on :books, to: :read
32
+ end
29
33
 
30
- TODO: Write usage instructions here
34
+ role :author do
35
+ has_permission_on :books, to: [:create, :read, :update, :delete] do
36
+ expect_attribute :author_id { eq(current_user.id) }
37
+ end
38
+ end
39
+
40
+ role :admin do
41
+ has_permission_on :books, to: [:create, :read, :update, :delete]
42
+ has_permission_on :users, to: :delete do
43
+ expect_attribute :id { not.eq(current_user.id) }
44
+ end
45
+ end
46
+ ```
47
+
48
+ ### Assign Roles
49
+
50
+ To provide roles it is necessary to pass a `current_user` that provides a `role_symbols` method.
51
+
52
+ ```ruby
53
+ class User
54
+ def role_symbols
55
+ [:user, :admin]
56
+ end
57
+ end
58
+
59
+ Toni.current_user = User.new
60
+ ```
61
+
62
+ What logic this method contains is up to you.
31
63
 
32
64
  ### Sinatra
33
65
 
66
+ The Toni Sinatra Module provides some usefule helpers and an error handling which can be useful
67
+ if you want to map not authorized errors. And there is a `permitted_to` method where you can pass a block that gets executed when the current user has the demanded permissions.
68
+
69
+ ```ruby
70
+ require "toni/sinatra"
71
+
72
+ class AuthorizationApp < Sinatra::Base
73
+ # Register Toni Sinatra
74
+ register Toni::Sinatra
75
+
76
+ before do
77
+ # Set user after authentication
78
+ Toni.current_user = User.new
79
+ end
80
+
81
+ not_authorized do |e|
82
+ # Map NotAuthorizedError to 403
83
+ halt 403
84
+ end
85
+
86
+ set :show_exceptions, false
87
+
88
+ get '/' do
89
+ # This won't throw an exception, remove bang: false if you
90
+ # want that the not_authorized error handler is called
91
+ permitted_to(:read, :books, bang: false) do
92
+ "You can read books!"
93
+ end
94
+ end
95
+
96
+ get '/another_page' do
97
+ without_authorization do
98
+ "Hello world"
99
+ end
100
+ end
101
+ end
102
+ ```
103
+
104
+ A more detailed example can be found in [examples/sinatra](examples/sinatra).
105
+
106
+ ### Testing with RSpec
107
+
108
+ To setup Toni's RspecHelper you have to change `spec_helper.rb`:
109
+ ```ruby
110
+ require "toni/rspec_helper"
111
+ RSpec.configure { |c| c.include Toni::RSpecHelper }
112
+ ```
113
+
114
+ Then you are able to test permissions with following matcher:
115
+ ```ruby
116
+ expect(user).to have_permission_on :books, to: :read
117
+ expect(user).to_not have_permission_on :books, to: :create
118
+ ```
119
+
120
+ By default your specs are running with authorization. If you want to exclude parts or execute with a specific user you can use:
121
+ ```ruby
122
+ without_authorization do
123
+ book.create
124
+ end
125
+
126
+ with_user(user) do
127
+ book.save
128
+ end
129
+ ```
130
+
131
+ ### Ruby on Rails
132
+
34
133
  TODO: Write usage instructions here
35
134
 
36
135
  ## Contributing
@@ -0,0 +1,9 @@
1
+ # Toni in Sinatra
2
+
3
+ ## Installation
4
+ $ bundle
5
+ $ rackup
6
+
7
+ ## Further notes
8
+
9
+ To setup sinatra with active record please have a look at the rails example (TODO).
@@ -0,0 +1,33 @@
1
+ require 'toni'
2
+ require 'toni/sinatra'
3
+ require 'sinatra'
4
+ require 'CGI'
5
+ require './user'
6
+
7
+ class AuthorizationApp < Sinatra::Base
8
+ register Toni::Sinatra
9
+
10
+ before do
11
+ # Set user after authentication
12
+ Toni.current_user = User.new
13
+ end
14
+
15
+ not_authorized do |e|
16
+ # Map NotAuthorizedError to 403
17
+ halt 403, CGI.escapeHTML(e.message)
18
+ end
19
+
20
+ set :show_exceptions, false
21
+
22
+ get '/' do
23
+ permitted_to(:read, :books, bang: false) do
24
+ "You can read books!"
25
+ end
26
+ end
27
+
28
+ get '/create' do
29
+ permitted_to(:create, :books) do
30
+ "You can create books"
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,7 @@
1
+ role :user do
2
+ has_permission_on :books, to: :read
3
+ end
4
+
5
+ role :admin do
6
+ has_permission_on :books, to: :create
7
+ end
@@ -0,0 +1,2 @@
1
+ require './app'
2
+ run AuthorizationApp
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+
3
+ describe "Authorization Rules" do
4
+ describe "user" do
5
+ it "is permitted to read books" do
6
+ user = double("user", role_symbols: [:user])
7
+ expect(user).to have_permission_on :books, to: :read
8
+ end
9
+ it "is not permitted to create books" do
10
+ user = double("user", role_symbols: [:user])
11
+ expect(user).to_not have_permission_on :books, to: :create
12
+ end
13
+ end
14
+ describe "admin" do
15
+ it "is permitted to create books" do
16
+ user = double("user", role_symbols: [:admin])
17
+ expect(user).to have_permission_on :books, to: :create
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,10 @@
1
+ require "rspec"
2
+ require "toni/rspec_helper"
3
+
4
+ require 'rack/test'
5
+
6
+ require File.expand_path '../../app.rb', __FILE__
7
+
8
+ ENV['RACK_ENV'] = 'test'
9
+
10
+ RSpec.configure { |c| c.include Toni::RSpecHelper }
@@ -0,0 +1,7 @@
1
+ class User
2
+
3
+ def role_symbols
4
+ [:user]
5
+ end
6
+
7
+ end
@@ -1,4 +1,4 @@
1
- class Toni
1
+ module Toni
2
2
  class AnonymousUser
3
3
  def role_symbols
4
4
  [:guest]
data/lib/toni/builder.rb CHANGED
@@ -2,7 +2,7 @@ require "toni/role"
2
2
  require "toni/permission"
3
3
  require "rspec/matchers"
4
4
 
5
- class Toni
5
+ module Toni
6
6
  class Builder
7
7
 
8
8
  attr_reader :roles
@@ -46,8 +46,7 @@ class Toni
46
46
  attr_reader :permission
47
47
 
48
48
  def initialize(resource_name, options={}, &block)
49
- options[:to] ||= [:manage]
50
- @permission = Permission.new(resource_name, options[:to])
49
+ @permission = Permission.new(resource_name, [*options[:to]])
51
50
  if block_given?
52
51
  instance_eval &block
53
52
  end
@@ -84,6 +83,14 @@ class Toni
84
83
  Toni.current_user
85
84
  end
86
85
 
86
+ def not
87
+ Toni::PermissionMatcher::NotMatcher.new
88
+ end
89
+
90
+ def permitted_to(activity)
91
+ Toni::PermissionMatcher::PermittedToMatcher.new(activity)
92
+ end
93
+
87
94
  end
88
95
 
89
96
  end
@@ -1,14 +1,14 @@
1
1
  require "toni/permission_matcher"
2
2
 
3
- class Toni
3
+ module Toni
4
4
  class Permission
5
5
 
6
6
  attr_reader :resource_name, :matchers, :activities
7
7
 
8
8
  def initialize(resource_name, activities = [])
9
- @resource_name = resource_name
10
- @matchers = []
11
- @activities = activities
9
+ @resource_name = resource_name
10
+ @matchers = []
11
+ @activities = activities
12
12
  end
13
13
 
14
14
  def add_matcher(method_name, matcher, is_attr = false)
@@ -1,12 +1,12 @@
1
- class Toni
1
+ module Toni
2
2
  class PermissionMatcher
3
3
 
4
4
  attr_reader :method_name, :matcher, :is_attr
5
5
 
6
6
  def initialize(method_name, matcher, is_attr = false)
7
- @method_name = method_name
8
- @matcher = matcher
9
- @is_attr = is_attr
7
+ @method_name = method_name
8
+ @matcher = matcher
9
+ @is_attr = is_attr
10
10
  end
11
11
 
12
12
  def matches?(object)
@@ -16,5 +16,39 @@ class Toni
16
16
  matcher.matches?(object.send(method_name))
17
17
  end
18
18
 
19
+ class NotMatcher
20
+ attr_reader :matcher
21
+
22
+ def initialize
23
+ @matcher = nil
24
+ end
25
+
26
+ def method_missing(method_name, *args)
27
+ builder = Toni::Builder::ExpectationBuilder.new
28
+ if builder.respond_to?(method_name)
29
+ @matcher = builder.send(method_name, *args)
30
+ else
31
+ super
32
+ end
33
+ end
34
+
35
+ def matches?(object)
36
+ raise Toni::MissingMatcherError if @matcher.nil?
37
+ !@matcher.matches?(object)
38
+ end
39
+ end
40
+
41
+ class PermittedToMatcher
42
+
43
+ def initialize(activity)
44
+ @activity = activity
45
+ end
46
+
47
+ def matches?(object)
48
+ Toni.permitted_to?(@activity, object)
49
+ end
50
+
51
+ end
52
+
19
53
  end
20
54
  end
data/lib/toni/role.rb CHANGED
@@ -1,12 +1,12 @@
1
- class Toni
1
+ module Toni
2
2
  class Role
3
3
 
4
4
  attr_reader :role_symbol, :ancestors, :permissions
5
5
 
6
6
  def initialize(role_symbol)
7
- @role_symbol = role_symbol
8
- @ancestors = []
9
- @permissions = []
7
+ @role_symbol = role_symbol
8
+ @ancestors = []
9
+ @permissions = []
10
10
  end
11
11
 
12
12
  def add_ancestor(role_symbol)
@@ -0,0 +1,27 @@
1
+ require 'rspec/expectations'
2
+ require 'toni'
3
+
4
+ module Toni
5
+ module RSpecHelper
6
+ extend RSpec::Matchers::DSL
7
+
8
+ def with_user(user, &block)
9
+ Toni.current_user = user
10
+ result = yield
11
+ Toni.current_user = nil
12
+ result
13
+ end
14
+
15
+ def without_authorization(&block)
16
+ Toni.without_authorization(&block)
17
+ end
18
+
19
+ matcher :have_permission_on do |resource_or_name, options = {}|
20
+ match do |user|
21
+ with_user(user) do
22
+ [*options[:to]].all? { |a| Toni.permitted_to?(a, resource_or_name) }
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ require 'sinatra/base'
2
+
3
+ module Toni
4
+ module Sinatra
5
+ module AuthorizationHelper
6
+ def permitted_to(activity, resource_or_name, options={}, &block)
7
+ options[:bang] = true unless options.key?(:bang)
8
+ if Toni.permitted_to?(activity, resource_or_name, options)
9
+ block.call if block_given?
10
+ end
11
+ end
12
+
13
+ def without_authorization(&block)
14
+ Toni.without_authorization(&block)
15
+ end
16
+ end
17
+
18
+ module AuthorizationErrorHandler
19
+ def not_authorized(&block)
20
+ error do
21
+ if env['sinatra.error'].instance_of? Toni::NotAuthorizedError
22
+ instance_exec env['sinatra.error'], &block if block_given?
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def self.registered(app)
29
+ app.helpers AuthorizationHelper
30
+ app.register AuthorizationErrorHandler
31
+ end
32
+ end
33
+ end
data/lib/toni/version.rb CHANGED
@@ -1,3 +1,3 @@
1
- class Toni
2
- VERSION = "0.0.1"
1
+ module Toni
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/toni.rb CHANGED
@@ -2,36 +2,35 @@ require "toni/version"
2
2
  require "toni/anonymous_user"
3
3
  require "toni/builder"
4
4
 
5
- class Toni
6
- AUTH_FILE = File.dirname(__FILE__) + "/authorization_rules.rb"
5
+ module Toni
6
+ AUTH_FILE = "config/authorization_rules.rb"
7
7
 
8
8
  class InvalidCurrentUserError < StandardError; end
9
9
  class NoAuthorizationContextProvidedError < StandardError; end
10
10
  class NoMethodForMatcherError < StandardError; end
11
11
  class NotAuthorizedError < StandardError; end
12
+ class MissingMatcherError < StandardError; end
12
13
 
13
14
  class << self
14
- @@without_authorization = false
15
-
16
15
  def current_user
17
- @@curent_user ||= nil
18
- @@curent_user || anonymous_user
16
+ @curent_user ||= nil
17
+ @curent_user || anonymous_user
19
18
  end
20
19
 
21
20
  def current_user=(user)
22
21
  raise InvalidCurrentUserError if !user.nil? && !user.respond_to?(:role_symbols)
23
- @@curent_user = user
22
+ @curent_user = user
24
23
  end
25
24
 
26
25
  def roles
27
- @@roles ||= build
26
+ @roles ||= build
28
27
  end
29
28
 
30
29
  def permitted_to?(activity, resource_or_name, options={})
31
- return true if @@without_authorization
30
+ return true if @without_authorization
32
31
  permitted = current_roles.any?{ |r| r.permitted_to?(activity, resource_or_name, options) }
33
32
  if options[:bang] && !permitted
34
- raise NotAuthorizedError.new("#{current_user.inspect} is not allowed to #{activity} on #{resource_or_name.inspect}")
33
+ raise NotAuthorizedError.new("#{current_user.to_s} with #{current_user.role_symbols.inspect} is not allowed to #{activity} on #{resource_or_name.inspect}")
35
34
  end
36
35
 
37
36
  permitted
@@ -42,9 +41,10 @@ class Toni
42
41
  end
43
42
 
44
43
  def without_authorization(&block)
45
- @@without_authorization = true
46
- yield if block_given?
47
- @@without_authorization = false
44
+ @without_authorization = true
45
+ result = block_given? ? yield : nil
46
+ @without_authorization = false
47
+ result
48
48
  end
49
49
 
50
50
  private
@@ -58,7 +58,7 @@ class Toni
58
58
  end
59
59
 
60
60
  def anonymous_user
61
- @@anonymous_user ||= AnonymousUser.new
61
+ @anonymous_user ||= AnonymousUser.new
62
62
  end
63
63
  end
64
- end
64
+ end
data/spec/spec_helper.rb CHANGED
@@ -3,7 +3,12 @@ CodeClimate::TestReporter.start
3
3
 
4
4
  require "active_record"
5
5
 
6
- ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
6
+ if ENV["RUBY_VERSION"].include?("jruby")
7
+ ActiveRecord::Base.establish_connection(:adapter => "jdbcsqlite3", :database => ":memory:")
8
+ else
9
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
10
+ end
11
+
7
12
  ActiveRecord::Schema.define do
8
13
  self.verbose = false
9
14
 
@@ -1,3 +1,4 @@
1
+ require "spec_helper"
1
2
  require "toni/anonymous_user"
2
3
 
3
4
  describe Toni::AnonymousUser do
@@ -1,3 +1,4 @@
1
+ require "spec_helper"
1
2
  require "toni/builder"
2
3
 
3
4
  describe Toni::Builder do
@@ -31,15 +32,15 @@ describe Toni::Builder::RoleBuilder do
31
32
 
32
33
  describe :includes do
33
34
  it "calls add_ancestor for the given role_symbol" do
35
+ expect(builder.role).to receive(:add_ancestor).with(:parent_user)
34
36
  builder.includes(:parent_user)
35
- allow(builder.role).to receive(:add_ancestor).with(:parent_user)
36
37
  end
37
38
  end
38
39
 
39
40
  describe :has_permission_on do
40
41
  it "calls add_permission on role" do
42
+ expect(builder.role).to receive(:add_permission)
41
43
  builder.has_permission_on(:my_resource)
42
- allow(builder.role).to receive(:add_permission)
43
44
  end
44
45
  end
45
46
 
@@ -49,6 +50,17 @@ describe Toni::Builder::PermissionBuilder do
49
50
 
50
51
  let(:builder) { Toni::Builder::PermissionBuilder.new(:resource_name) }
51
52
 
53
+ describe :initialize do
54
+ it "sets the activtities" do
55
+ builder = Toni::Builder::PermissionBuilder.new(:resource_name, to: [:create, :read])
56
+ expect(builder.permission.activities).to eq([:create, :read])
57
+ end
58
+ it "sets single activtities" do
59
+ builder = Toni::Builder::PermissionBuilder.new(:resource_name, to: :read)
60
+ expect(builder.permission.activities).to eq([:read])
61
+ end
62
+ end
63
+
52
64
  describe :permission do
53
65
  it "is a Permission" do
54
66
  expect(builder.permission).to be_instance_of(Toni::Permission)
@@ -57,17 +69,17 @@ describe Toni::Builder::PermissionBuilder do
57
69
 
58
70
  describe :expect_attribute do
59
71
  it "calls expect_method with is_attribute true" do
72
+ expect(builder).to receive(:expect_method).with(nil, true)
60
73
  builder.expect_attribute(nil)
61
- allow(builder).to receive(:expect_method).with(nil, true)
62
74
  end
63
75
  end
64
76
 
65
77
  describe :expect_method do
66
78
  it "calls add_matcher on permission per method_name" do
79
+ expect(builder.permission).to receive(:add_matcher).with(:foo, anything, false)
80
+ expect(builder.permission).to receive(:add_matcher).with(:bar, anything, false)
67
81
  builder.expect_method(:foo) { nil }
68
82
  builder.expect_method(:bar) { nil }
69
- allow(builder.permission).to receive(:add_matcher).with(:foo, anything)
70
- allow(builder.permission).to receive(:add_matcher).with(:bar, anything)
71
83
  end
72
84
  end
73
85
 
@@ -78,7 +90,7 @@ describe Toni::Builder::ExpectationBuilder do
78
90
  let(:builder) { Toni::Builder::ExpectationBuilder.new }
79
91
 
80
92
  describe :execute do
81
- it "calls block eagerly" do
93
+ it "calls block lazely" do
82
94
  double = double()
83
95
  builder = Toni::Builder::ExpectationBuilder.new do
84
96
  double.call
@@ -90,8 +102,8 @@ describe Toni::Builder::ExpectationBuilder do
90
102
 
91
103
  describe "uses rspec matchers" do
92
104
  it "calls rspec matcher methods" do
93
- builder.be_nil
94
105
  allow(RSpec::Matchers).to receive(:be_nil)
106
+ builder.be_nil
95
107
  end
96
108
 
97
109
  it "sets the called matcher" do
@@ -102,4 +114,23 @@ describe Toni::Builder::ExpectationBuilder do
102
114
  end
103
115
  end
104
116
 
117
+ describe :not do
118
+ it "should create a NotMatcher" do
119
+ expect(builder.not).to be_instance_of(Toni::PermissionMatcher::NotMatcher)
120
+ end
121
+ end
122
+
123
+ describe :permitted_to do
124
+ it "should create a PermittedToMatcher" do
125
+ expect(builder.permitted_to(:read)).to be_instance_of(Toni::PermissionMatcher::PermittedToMatcher)
126
+ end
127
+ end
128
+
129
+ describe :current_user do
130
+ it "gets the toni user" do
131
+ expect(Toni).to receive(:current_user)
132
+ builder.current_user
133
+ end
134
+ end
135
+
105
136
  end
@@ -1,3 +1,4 @@
1
+ require "spec_helper"
1
2
  require "toni/permission_matcher"
2
3
  require "toni"
3
4
  require "ostruct"
@@ -77,4 +78,43 @@ describe Toni::PermissionMatcher do
77
78
  end
78
79
  end
79
80
 
81
+ end
82
+
83
+ describe Toni::PermissionMatcher::NotMatcher do
84
+
85
+ let(:not_matcher) { Toni::PermissionMatcher::NotMatcher.new }
86
+
87
+ describe :method_missing do
88
+ it "looks up method in ExpectationBuilder" do
89
+ expect { not_matcher.be_truthy }.to_not raise_error
90
+ end
91
+ it "throws error when method does not exist" do
92
+ expect { not_matcher.that_does_not_exist }.to raise_error
93
+ end
94
+ end
95
+
96
+ describe :matches? do
97
+ it "raises error when matcher is nil" do
98
+ expect { not_matcher.matches?(nil) }.to raise_error(Toni::MissingMatcherError)
99
+ end
100
+ it "uses matches method of matcher and flips the boolean" do
101
+ not_matcher.eq(nil)
102
+ expect(not_matcher.matches?(nil)).to eq(false)
103
+ end
104
+ end
105
+
106
+ end
107
+
108
+ describe Toni::PermissionMatcher::PermittedToMatcher do
109
+
110
+ let(:permitted_to_matcher) { Toni::PermissionMatcher::PermittedToMatcher.new(:read) }
111
+
112
+ describe :matches? do
113
+ it "calls Toni.permitted_to? for given attribute" do
114
+ double = double
115
+ expect(Toni).to receive(:permitted_to?).with(:read, double)
116
+ permitted_to_matcher.matches?(double)
117
+ end
118
+ end
119
+
80
120
  end
@@ -1,3 +1,4 @@
1
+ require "spec_helper"
1
2
  require "toni/permission"
2
3
  require "ostruct"
3
4
 
@@ -1,3 +1,4 @@
1
+ require "spec_helper"
1
2
  require "toni/role"
2
3
  require "toni/permission"
3
4
  require "ostruct"
@@ -0,0 +1,37 @@
1
+ require "spec_helper"
2
+ require "toni/rspec_helper"
3
+
4
+ describe Toni::RSpecHelper do
5
+ include Toni::RSpecHelper
6
+
7
+ describe :without_authorization do
8
+ it "calls Toni without_authorization" do
9
+ expect(Toni).to receive(:without_authorization)
10
+ without_authorization
11
+ end
12
+ end
13
+
14
+ describe :with_user do
15
+ it "calls block with given user and return the result of the block" do
16
+ user = double("user")
17
+ expect(Toni).to receive(:current_user=).with(user)
18
+ expect(Toni).to receive(:current_user=).with(nil)
19
+ expect(with_user(user) { 1 }).to eq(1)
20
+ end
21
+ end
22
+
23
+ describe "have_permission_on matcher" do
24
+ it "returns true if all permissions are true for the given activities" do
25
+ user = double("user", role_symbols: [])
26
+ expect(Toni).to receive(:permitted_to?).with(:create, :books) { true }
27
+ expect(Toni).to receive(:permitted_to?).with(:read, :books) { true }
28
+ expect(user).to have_permission_on(:books, to: [:create, :read])
29
+ end
30
+ it "returns false if one permissions is not true for the given activities" do
31
+ user = double("user", role_symbols: [])
32
+ expect(Toni).to receive(:permitted_to?).with(:create, :books) { true }
33
+ expect(Toni).to receive(:permitted_to?).with(:read, :books) { false }
34
+ expect(user).not_to have_permission_on(:books, to: [:create, :read])
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,78 @@
1
+ require "spec_helper"
2
+ require "toni/sinatra"
3
+ require "rack/test"
4
+
5
+ describe Toni::Sinatra::AuthorizationHelper do
6
+ let(:helper) {
7
+ Class.new do
8
+ include Toni::Sinatra::AuthorizationHelper
9
+ end.new
10
+ }
11
+
12
+ describe :permitted_to do
13
+ it "calls permitted_to? of toni, sets bang to true and calls the given block" do
14
+ double = double("block")
15
+ expect(Toni).to receive(:permitted_to?).with(:read, :books, bang: true) { true }
16
+ expect(double).to receive(:call)
17
+ helper.permitted_to(:read, :books) do
18
+ double.call
19
+ end
20
+ end
21
+
22
+ it "does not call the block if it is not permitted to" do
23
+ double = double("block")
24
+ expect(Toni).to receive(:permitted_to?).with(:read, :books, bang: false) { false }
25
+ expect(double).to_not receive(:call)
26
+ helper.permitted_to(:read, :books, bang: false) do
27
+ double.call
28
+ end
29
+ end
30
+ end
31
+
32
+ describe :without_authorization do
33
+ it "calls toni without_authorization" do
34
+ expect(Toni).to receive(:without_authorization)
35
+ helper.without_authorization
36
+ end
37
+ end
38
+ end
39
+
40
+ describe Toni::Sinatra::AuthorizationErrorHandler do
41
+ include Rack::Test::Methods
42
+
43
+ let(:app) {
44
+ Class.new(Sinatra::Base) do
45
+ register Toni::Sinatra
46
+
47
+ set :show_exceptions, false
48
+ set :raise_errors, false
49
+
50
+ not_authorized do |e|
51
+ halt 403, e.message
52
+ end
53
+
54
+ get '/' do
55
+ permitted_to(:read, :books) do
56
+ "permitted"
57
+ end
58
+ end
59
+ end
60
+ }
61
+
62
+ describe :not_authorized do
63
+ it "does not call error handler when permitted to" do
64
+ allow(Toni).to receive(:permitted_to?).with(:read, :books, anything) { true }
65
+ get '/'
66
+ expect(last_response.body).to eq("permitted")
67
+ end
68
+
69
+ it "calls error handler when permitted to" do
70
+ allow(Toni).to receive(:permitted_to?).with(:read, :books, anything) do
71
+ raise Toni::NotAuthorizedError.new("not authorized")
72
+ end
73
+ get '/'
74
+ expect(last_response.status).to eq(403)
75
+ expect(last_response.body).to eq("not authorized")
76
+ end
77
+ end
78
+ end
data/spec/toni_spec.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require "spec_helper"
1
2
  require "toni"
2
3
  require "ostruct"
3
4
 
@@ -6,6 +7,19 @@ describe Toni do
6
7
  let(:role_symbols) { [] }
7
8
  let(:current_user) { OpenStruct.new(role_symbols: role_symbols) }
8
9
 
10
+ before do
11
+ allow(File).to receive(:read).with(Toni::AUTH_FILE) do
12
+ <<-eos
13
+ role :guest do
14
+ has_permission_on :x, to: [:read, :delete]
15
+ end
16
+ role :user do
17
+ has_permission_on :test, to: [:read, :create]
18
+ end
19
+ eos
20
+ end
21
+ end
22
+
9
23
  describe ".current_user" do
10
24
  it "has a anonymous user as default" do
11
25
  expect(Toni.current_user).to be_instance_of(Toni::AnonymousUser)
@@ -29,15 +43,30 @@ describe Toni do
29
43
  end
30
44
 
31
45
  describe ".roles" do
32
- pending
46
+ it "reads roles from auth_file" do
47
+ expect(Toni.roles.keys).to eq([:guest, :user])
48
+ end
33
49
  end
34
50
 
35
51
  describe ".current_roles" do
36
- pending
52
+ let(:role_symbols) { [:user] }
53
+ it "gets the roles that are in the role_symbols methods" do
54
+ Toni.current_user = current_user
55
+ expect(Toni.current_roles).to eq([Toni.roles[:user]])
56
+ end
37
57
  end
38
58
 
39
59
  describe ".without_authorization" do
40
- pending
60
+ it "executes block without authorization and returns result of the given block" do
61
+ with_authorization = Toni.permitted_to?(:something, :test)
62
+ without_authorization = false
63
+ expect(Toni.without_authorization do
64
+ without_authorization = Toni.permitted_to?(:something, :test)
65
+ 3
66
+ end).to eq(3)
67
+ expect(with_authorization).to eq(false)
68
+ expect(without_authorization).to eq(true)
69
+ end
41
70
  end
42
71
 
43
72
  describe ".permitted_to?" do
data/toni.gemspec CHANGED
@@ -27,5 +27,5 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency "rspec"
28
28
  spec.add_development_dependency "activerecord", "~> 4.1"
29
29
  spec.add_development_dependency "rails", "~> 4.1"
30
- spec.add_development_dependency "sqlite3"
30
+ spec.add_development_dependency "sinatra"
31
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toni
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jalyna
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-04 00:00:00.000000000 Z
11
+ date: 2014-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec-expectations
@@ -95,7 +95,7 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '4.1'
97
97
  - !ruby/object:Gem::Dependency
98
- name: sqlite3
98
+ name: sinatra
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - '>='
@@ -121,12 +121,21 @@ files:
121
121
  - LICENSE.txt
122
122
  - README.md
123
123
  - Rakefile
124
+ - examples/sinatra/README.md
125
+ - examples/sinatra/app.rb
126
+ - examples/sinatra/config.ru
127
+ - examples/sinatra/config/authorization_rules.rb
128
+ - examples/sinatra/spec/authorization_rules_spec.rb
129
+ - examples/sinatra/spec/spec_helper.rb
130
+ - examples/sinatra/user.rb
124
131
  - lib/toni.rb
125
132
  - lib/toni/anonymous_user.rb
126
133
  - lib/toni/builder.rb
127
134
  - lib/toni/permission.rb
128
135
  - lib/toni/permission_matcher.rb
129
136
  - lib/toni/role.rb
137
+ - lib/toni/rspec_helper.rb
138
+ - lib/toni/sinatra.rb
130
139
  - lib/toni/version.rb
131
140
  - spec/spec_helper.rb
132
141
  - spec/toni/anonymous_user_spec.rb
@@ -134,6 +143,8 @@ files:
134
143
  - spec/toni/permission_matcher_spec.rb
135
144
  - spec/toni/permission_spec.rb
136
145
  - spec/toni/role_spec.rb
146
+ - spec/toni/rspec_helper_spec.rb
147
+ - spec/toni/sinatra_spec.rb
137
148
  - spec/toni_spec.rb
138
149
  - toni.gemspec
139
150
  homepage: https://github.com/jalyna/toni
@@ -169,4 +180,6 @@ test_files:
169
180
  - spec/toni/permission_matcher_spec.rb
170
181
  - spec/toni/permission_spec.rb
171
182
  - spec/toni/role_spec.rb
183
+ - spec/toni/rspec_helper_spec.rb
184
+ - spec/toni/sinatra_spec.rb
172
185
  - spec/toni_spec.rb