sinatra-authorize 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ pkg/*
2
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format=nested
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :gemcutter
2
+
3
+ # Specify your gem's dependencies in sinatra-authorize.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,37 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ sinatra-authorize (0.0.0)
5
+ sinatra (>= 1.2)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.1.2)
11
+ rack (1.2.2)
12
+ rack-test (0.5.7)
13
+ rack (>= 1.0)
14
+ rake (0.8.7)
15
+ rspec (2.5.0)
16
+ rspec-core (~> 2.5.0)
17
+ rspec-expectations (~> 2.5.0)
18
+ rspec-mocks (~> 2.5.0)
19
+ rspec-core (2.5.1)
20
+ rspec-expectations (2.5.0)
21
+ diff-lcs (~> 1.1.2)
22
+ rspec-mocks (2.5.0)
23
+ sinatra (1.2.2)
24
+ rack (~> 1.1)
25
+ tilt (>= 1.2.2, < 2.0)
26
+ tilt (1.2.2)
27
+
28
+ PLATFORMS
29
+ ruby
30
+
31
+ DEPENDENCIES
32
+ bundler (>= 1.0.0.rc.5)
33
+ rack-test (>= 0.5.7)
34
+ rake (>= 0.8)
35
+ rspec (>= 2.4)
36
+ sinatra (>= 1.2)
37
+ sinatra-authorize!
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
@@ -0,0 +1,77 @@
1
+ require 'sinatra/base'
2
+
3
+ module Sinatra
4
+ module Authorize
5
+ class Condition < Proc; end
6
+
7
+ def authorize(opts = {}, &block)
8
+ opts = {opts => []} if opts.is_a?(Symbol)
9
+
10
+ if opts[:deny]
11
+ args = *(opts[:deny])
12
+ set(:authorize_default, Proc.new {
13
+ authorize_condition(:deny, args)
14
+ })
15
+ else
16
+ args = *(opts[:allow] || [])
17
+ set(:authorize_default, Proc.new {
18
+ authorize_condition(:allow, args)
19
+ })
20
+ end
21
+
22
+ if block_given?
23
+ define_method(:authorize_do_block, block)
24
+ authorize_do = instance_method(:authorize_do_block)
25
+ remove_method(:authorize_do_block)
26
+
27
+ set :authorize_do, Proc.new { authorize_do }
28
+ end
29
+ end
30
+
31
+ def allow(*args)
32
+ condition &(authorize_condition(:allow, args))
33
+ end
34
+
35
+ def deny(*args)
36
+ condition &(authorize_condition(:deny, args))
37
+ end
38
+
39
+ def authorize_condition(rule, args)
40
+ Condition.new { settings.authorize_do.bind(self).call(rule, args) }
41
+ end
42
+
43
+ class << self
44
+ def registered(app)
45
+ app.authorize do |rule, args|
46
+ raise "No authorize block is specified."
47
+ end
48
+
49
+ app.class_eval do
50
+ alias :old_process_route :process_route
51
+
52
+ def process_route(pattern, keys, conditions, &block)
53
+ authorize_conditions = conditions.select do |cond|
54
+ cond.is_a?(Authorize::Condition)
55
+ end
56
+
57
+ regular_conditions = conditions - authorize_conditions
58
+
59
+ old_process_route(pattern, keys, regular_conditions) do
60
+ throw :halt, 403 if authorize_route(authorize_conditions) == false
61
+ yield
62
+ end
63
+ end
64
+
65
+ def authorize_route(conditions)
66
+ conditions = conditions.dup
67
+ conditions.unshift(settings.authorize_default)
68
+ conditions = conditions.collect { |cond| instance_eval(&cond) }
69
+ conditions.select { |allow| allow == true || allow == false }.last
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ register Authorize
77
+ end
@@ -0,0 +1,5 @@
1
+ module Sinatra
2
+ module Authorize
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
data/readme.md ADDED
@@ -0,0 +1,108 @@
1
+ # sinatra-authorize
2
+
3
+ ### Authentication-agnostic rule-based authorization extension for Sinatra
4
+
5
+ Provides a flexible rule-based authorization framework:
6
+
7
+ * Define `authorize` block for evaluating rules
8
+ * Set default rule for all routes
9
+ * Override default rule per route
10
+
11
+ Choice of authentication approach is entirely up to the application.
12
+
13
+ ### Installation
14
+
15
+ gem install sinatra-authorize
16
+
17
+ ### Usage
18
+
19
+ Define `authorize` block for evaluating rules, and optionally set the default rule:
20
+
21
+ authorize :deny => :all do |rule, args|
22
+ # evaluate rule
23
+ end
24
+
25
+ Omitting a default rule when defining the `authorize` block makes
26
+ `:allow => []` the default rule.
27
+
28
+ Override default rule per route:
29
+
30
+ get '/', :allow => :all do
31
+ # :allow => :all rule overrides default :deny => :all rule
32
+ end
33
+
34
+ Authorization is performed just before the route is evaluated, after the
35
+ pattern has been matched and any other conditions have been evaluated.
36
+
37
+ #### Usage scenario
38
+
39
+ Simple scenario with default `:allow` rule, which is overriden for protected
40
+ routes:
41
+
42
+ require 'sinatra'
43
+ require 'sinatra/authorize'
44
+
45
+ enable :sessions
46
+
47
+ authorize do |rule, args|
48
+ if args == [:user]
49
+ session[:user] != nil
50
+ elsif args == [:admin]
51
+ session[:admin] != nil
52
+ end
53
+ end
54
+
55
+ # Availabe to all, as default rule is :allow => []
56
+ get '/' do
57
+ end
58
+
59
+ # Availabe to all, as default rule is :allow => []
60
+ post '/authenticate' do
61
+ if params[:username] == 'username' && params[:password] == 'password'
62
+ session[:user] = params[:username]
63
+
64
+ if session[:user] == 'admin'
65
+ session[:admin] = true
66
+ end
67
+ end
68
+ end
69
+
70
+ # Only run for authorized user requests, because of override rule
71
+ get '/content/:id' :allow => :user do
72
+ end
73
+
74
+ # Only run for authorized admin requests, because of override rule
75
+ get '/admin/content/:id', :allow => :admin do
76
+ end
77
+
78
+ The `authorize` block only needs to handle the `:allow` rules present in the
79
+ scenario. Also, only the rule arguments used, `:user` and `:admin`, are
80
+ accounted for. No default rule is set when defining the `authorize` block,
81
+ thus making `:allow => []` the default rule. The routes `/` and `/authenticate`
82
+ is evaluated using the default `:allow` rule, whereas the `/content/:id` and
83
+ `/admin/content:id` routes override the default rule.
84
+
85
+ ### License
86
+
87
+ (The MIT License)
88
+
89
+ Copyright (c) 2011 Ole Petter Bang &lt;olepbang@gmail.com&gt;
90
+
91
+ Permission is hereby granted, free of charge, to any person obtaining
92
+ a copy of this software and associated documentation files (the
93
+ 'Software'), to deal in the Software without restriction, including
94
+ without limitation the rights to use, copy, modify, merge, publish,
95
+ distribute, sublicense, and/or sell copies of the Software, and to
96
+ permit persons to whom the Software is furnished to do so, subject to
97
+ the following conditions:
98
+
99
+ The above copyright notice and this permission notice shall be
100
+ included in all copies or substantial portions of the Software.
101
+
102
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
103
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
104
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
105
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
106
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
107
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
108
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
3
+ require 'sinatra-authorize/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "sinatra-authorize"
7
+ s.version = Sinatra::Authorize::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Ole Petter Bang"]
10
+ s.email = ["olepbang@gmail.com"]
11
+ s.homepage = "https://github.com/gnab/sinatra-authorize"
12
+ s.summary = "Smooth authentication-agnostic rule-based authorization " +
13
+ "extension for Sinatra"
14
+ s.description = s.summary
15
+
16
+ s.required_rubygems_version = ">= 1.3.6"
17
+ s.rubyforge_project = "sinatra-authorize"
18
+
19
+ s.add_development_dependency "bundler", ">= 1.0.0.rc.5"
20
+ s.add_development_dependency "rake", ">= 0.8"
21
+ s.add_development_dependency "rack-test", ">= 0.5.7"
22
+ s.add_development_dependency "rspec", ">= 2.4"
23
+
24
+ s.add_runtime_dependency "sinatra", ">= 1.2"
25
+
26
+ s.files = `git ls-files`.split("\n")
27
+ s.executables = `git ls-files`.split("\n").select{|f| f =~ /^bin/}
28
+ s.require_path = 'lib'
29
+ end
@@ -0,0 +1,148 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ shared_examples_for "when no default authorization is set" do
4
+ it 'should allow route with allow all rule' do
5
+ app.get('/', :allow => :all) {}
6
+ get '/'
7
+ last_response.status.should == 200
8
+ end
9
+
10
+ it 'should allow route with deny none rule' do
11
+ app.get('/', :deny => :none) {}
12
+ get '/'
13
+ last_response.status.should == 200
14
+ end
15
+
16
+ it 'should deny route with deny all rule' do
17
+ app.get('/', :deny => :all) {}
18
+ get '/'
19
+ last_response.status.should == 403
20
+ end
21
+
22
+ it 'should deny route with allow none rule' do
23
+ app.get('/', :allow => :none) {}
24
+ get '/'
25
+ last_response.status.should == 403
26
+ end
27
+ end
28
+
29
+ describe Sinatra::Authorize do
30
+
31
+ before :all do
32
+ app.authorize do |rule, args|
33
+ allow_default = lambda do |args|
34
+ if args == [] || args == [:all]
35
+ true
36
+ elsif args == [:none]
37
+ false
38
+ else
39
+ raise "Unknown authorization rule argument: #{args}."
40
+ end
41
+ end
42
+
43
+ if rule == :allow
44
+ allow_default.call(args)
45
+ elsif rule == :deny
46
+ !allow_default.call(args)
47
+ else
48
+ raise "Unknown authorization rule: #{rule}."
49
+ end
50
+ end
51
+ end
52
+
53
+ before do
54
+ app.reset!
55
+ end
56
+
57
+ it 'should allow routes by default' do
58
+ app.get('/') {}
59
+ get '/'
60
+ last_response.status.should == 200
61
+ end
62
+
63
+ it_behaves_like "when no default authorization is set"
64
+
65
+ context "#authorize :allow" do
66
+ before do
67
+ app.authorize :allow
68
+ end
69
+
70
+ it 'should allow routes by default' do
71
+ app.get('/') {}
72
+ get '/'
73
+ last_response.status.should == 200
74
+ end
75
+
76
+ it_behaves_like "when no default authorization is set"
77
+
78
+ context ' => :all' do
79
+ before do
80
+ app.authorize :allow => :all
81
+ end
82
+
83
+ it 'should allow routes by default' do
84
+ app.get('/') {}
85
+ get '/'
86
+ last_response.status.should == 200
87
+ end
88
+
89
+ it_behaves_like "when no default authorization is set"
90
+ end
91
+
92
+ context ' => :none' do
93
+ before do
94
+ app.authorize :allow => :none
95
+ end
96
+
97
+ it 'should deny routes by default' do
98
+ app.get('/') {}
99
+ get '/'
100
+ last_response.status.should == 403
101
+ end
102
+
103
+ it_behaves_like "when no default authorization is set"
104
+ end
105
+ end
106
+
107
+ context '#authorize :deny' do
108
+ before do
109
+ app.authorize :deny
110
+ end
111
+
112
+ it 'should deny routes by default' do
113
+ app.get('/') {}
114
+ get '/'
115
+ last_response.status.should == 403
116
+ end
117
+
118
+ it_behaves_like "when no default authorization is set"
119
+
120
+ context ' => :all' do
121
+ before do
122
+ app.authorize :deny => :all
123
+ end
124
+
125
+ it 'should deny routes by default' do
126
+ app.get('/') {}
127
+ get '/'
128
+ last_response.status.should == 403
129
+ end
130
+
131
+ it_behaves_like "when no default authorization is set"
132
+ end
133
+
134
+ context ' => :none' do
135
+ before do
136
+ app.authorize :deny => :none
137
+ end
138
+
139
+ it 'should allow routes by default' do
140
+ app.get('/') {}
141
+ get '/'
142
+ last_response.status.should == 200
143
+ end
144
+
145
+ it_behaves_like "when no default authorization is set"
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,19 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+
3
+ ENV['RACK_ENV'] = 'test'
4
+
5
+ require 'rspec'
6
+ require 'rack/test'
7
+ require 'sinatra/base'
8
+ require 'sinatra/authorize'
9
+
10
+ module SpecHelper
11
+ def app
12
+ @app ||= Sinatra::Application
13
+ end
14
+ end
15
+
16
+ RSpec.configure do |config|
17
+ config.include Rack::Test::Methods
18
+ config.include SpecHelper
19
+ end
metadata ADDED
@@ -0,0 +1,150 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sinatra-authorize
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Ole Petter Bang
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-04-16 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: bundler
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 0
31
+ - 0
32
+ - rc
33
+ - 5
34
+ version: 1.0.0.rc.5
35
+ type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: rake
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ segments:
46
+ - 0
47
+ - 8
48
+ version: "0.8"
49
+ type: :development
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: rack-test
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ segments:
60
+ - 0
61
+ - 5
62
+ - 7
63
+ version: 0.5.7
64
+ type: :development
65
+ version_requirements: *id003
66
+ - !ruby/object:Gem::Dependency
67
+ name: rspec
68
+ prerelease: false
69
+ requirement: &id004 !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ segments:
75
+ - 2
76
+ - 4
77
+ version: "2.4"
78
+ type: :development
79
+ version_requirements: *id004
80
+ - !ruby/object:Gem::Dependency
81
+ name: sinatra
82
+ prerelease: false
83
+ requirement: &id005 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ segments:
89
+ - 1
90
+ - 2
91
+ version: "1.2"
92
+ type: :runtime
93
+ version_requirements: *id005
94
+ description: Smooth authentication-agnostic rule-based authorization extension for Sinatra
95
+ email:
96
+ - olepbang@gmail.com
97
+ executables: []
98
+
99
+ extensions: []
100
+
101
+ extra_rdoc_files: []
102
+
103
+ files:
104
+ - .gitignore
105
+ - .rspec
106
+ - Gemfile
107
+ - Gemfile.lock
108
+ - Rakefile
109
+ - lib/sinatra-authorize/version.rb
110
+ - lib/sinatra/authorize.rb
111
+ - readme.md
112
+ - sinatra-authorize.gemspec
113
+ - spec/sinatra/authorize_spec.rb
114
+ - spec/spec_helper.rb
115
+ has_rdoc: true
116
+ homepage: https://github.com/gnab/sinatra-authorize
117
+ licenses: []
118
+
119
+ post_install_message:
120
+ rdoc_options: []
121
+
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ segments:
130
+ - 0
131
+ version: "0"
132
+ required_rubygems_version: !ruby/object:Gem::Requirement
133
+ none: false
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ segments:
138
+ - 1
139
+ - 3
140
+ - 6
141
+ version: 1.3.6
142
+ requirements: []
143
+
144
+ rubyforge_project: sinatra-authorize
145
+ rubygems_version: 1.3.7
146
+ signing_key:
147
+ specification_version: 3
148
+ summary: Smooth authentication-agnostic rule-based authorization extension for Sinatra
149
+ test_files: []
150
+