toni 0.0.1 → 0.0.2

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
  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