padrino-auth 0.0.12
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 +7 -0
- data/.gitignore +34 -0
- data/EXAMPLES.md +249 -0
- data/Gemfile +2 -0
- data/LICENSE +21 -0
- data/README.md +118 -0
- data/Rakefile +12 -0
- data/lib/padrino-auth.rb +2 -0
- data/lib/padrino-auth/access.rb +148 -0
- data/lib/padrino-auth/login.rb +138 -0
- data/lib/padrino-auth/login/controller.rb +20 -0
- data/lib/padrino-auth/login/layouts/layout.slim +10 -0
- data/lib/padrino-auth/login/new.slim +35 -0
- data/lib/padrino-auth/permissions.rb +180 -0
- data/lib/padrino-auth/version.rb +5 -0
- data/padrino-auth.gemspec +29 -0
- data/test/helper.rb +68 -0
- data/test/test_padrino_access.rb +124 -0
- data/test/test_padrino_auth.rb +38 -0
- data/test/test_padrino_login.rb +81 -0
- metadata +154 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env gem build
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require File.expand_path("../lib/padrino-auth/version.rb", __FILE__)
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "padrino-auth"
|
8
|
+
s.rubyforge_project = "padrino-auth"
|
9
|
+
s.authors = ["Igor Bochkariov"]
|
10
|
+
s.email = "ujifgc@gmail.com"
|
11
|
+
s.summary = "Authentication and authorization modules for Padrino"
|
12
|
+
s.homepage = "https://github.com/ujifgc/padrino-auth"
|
13
|
+
s.description = "Lean authorization and authentication modules for Padrino framework"
|
14
|
+
s.required_rubygems_version = ">= 1.3.6"
|
15
|
+
s.version = Padrino::Auth.version
|
16
|
+
s.date = Time.now.strftime("%Y-%m-%d")
|
17
|
+
s.license = "MIT"
|
18
|
+
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
22
|
+
|
23
|
+
s.add_development_dependency('rake', '~> 10')
|
24
|
+
s.add_development_dependency('rack', '~> 1')
|
25
|
+
s.add_development_dependency('rack-test', '~> 0', '>= 0.5')
|
26
|
+
s.add_development_dependency('slim', '~> 2')
|
27
|
+
s.add_development_dependency('padrino-helpers', '~> 0.12')
|
28
|
+
s.add_development_dependency('padrino-core', '~> 0.12')
|
29
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
ENV['RACK_ENV'] = 'test'
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'rack/test'
|
5
|
+
require 'rack'
|
6
|
+
require 'padrino-core'
|
7
|
+
require 'padrino-auth'
|
8
|
+
|
9
|
+
# Helper methods for testing Padrino::Access
|
10
|
+
class MiniTest::Spec
|
11
|
+
include Rack::Test::Methods
|
12
|
+
|
13
|
+
def mock_app(base=Padrino::Application, &block)
|
14
|
+
@app = Sinatra.new(base, &block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def app
|
18
|
+
Rack::Lint.new(@app)
|
19
|
+
end
|
20
|
+
|
21
|
+
def status; last_response.status; end
|
22
|
+
def body; last_response.body; end
|
23
|
+
alias response last_response
|
24
|
+
|
25
|
+
def set_access(*args)
|
26
|
+
@app.set_access(*args)
|
27
|
+
end
|
28
|
+
|
29
|
+
def allow(subject = nil, path = '/')
|
30
|
+
@app.fake_session[:visitor] = nil
|
31
|
+
get "/login/#{subject.id}" if subject
|
32
|
+
get path
|
33
|
+
assert_equal 200, status, caller.first.to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
def deny(subject = nil, path = '/')
|
37
|
+
@app.fake_session[:visitor] = nil
|
38
|
+
get "/login/#{subject.id}" if subject
|
39
|
+
get path
|
40
|
+
assert_equal 403, status, caller.first.to_s
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
module Character
|
45
|
+
extend self
|
46
|
+
|
47
|
+
def authenticate(credentials)
|
48
|
+
case
|
49
|
+
when credentials[:email] && credentials[:password]
|
50
|
+
target = all.find{ |resource| resource.id.to_s == credentials[:email] }
|
51
|
+
target.name.gsub(/[^A-Z]/,'') == credentials[:password] ? target : nil
|
52
|
+
when credentials.has_key?(:id)
|
53
|
+
all.find{ |resource| resource.id == credentials[:id] }
|
54
|
+
else
|
55
|
+
false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def all
|
60
|
+
@all = [
|
61
|
+
OpenStruct.new(:id => :bender, :name => 'Bender Bending Rodriguez', :role => :robots ),
|
62
|
+
OpenStruct.new(:id => :leela, :name => 'Turanga Leela', :role => :mutants ),
|
63
|
+
OpenStruct.new(:id => :fry, :name => 'Philip J. Fry', :role => :humans ),
|
64
|
+
OpenStruct.new(:id => :ami, :name => 'Amy Wong', :role => :humans ),
|
65
|
+
OpenStruct.new(:id => :zoidberg, :name => 'Dr. John A. Zoidberg', :role => :lobsters),
|
66
|
+
]
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require File.expand_path('../helper', __FILE__)
|
2
|
+
|
3
|
+
describe "Padrino::Access" do
|
4
|
+
before do
|
5
|
+
mock_app do
|
6
|
+
set :credentials_reader, :visitor
|
7
|
+
register Padrino::Access
|
8
|
+
set_access :*, :allow => :login
|
9
|
+
set :users, Character.all
|
10
|
+
get(:login, :with => :id) do
|
11
|
+
user = settings.users.find{ |user| user.id.to_s == params[:id] }
|
12
|
+
self.send(:"#{settings.credentials_reader}=", user)
|
13
|
+
end
|
14
|
+
get(:index){ 'foo' }
|
15
|
+
get(:bend){ 'bend' }
|
16
|
+
get(:drink){ 'bend' }
|
17
|
+
get(:subject){ self.send(settings.credentials_reader).inspect }
|
18
|
+
get(:stop_partying){ 'stop partying' }
|
19
|
+
controller :surface do
|
20
|
+
get(:live) { 'live on the surface' }
|
21
|
+
end
|
22
|
+
controller :sewers do
|
23
|
+
get(:live) { 'live in the sewers' }
|
24
|
+
get(:visit) { 'visit the sewers' }
|
25
|
+
end
|
26
|
+
set :fake_session, {}
|
27
|
+
helpers do
|
28
|
+
def visitor
|
29
|
+
settings.fake_session[:visitor]
|
30
|
+
end
|
31
|
+
def visitor=(user)
|
32
|
+
settings.fake_session[:visitor] = user
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
Character.all.each do |user|
|
37
|
+
instance_variable_set :"@#{user.id}", user
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should register with authorization module' do
|
42
|
+
assert @app.respond_to? :set_access
|
43
|
+
assert_kind_of Padrino::Permissions, @app.permissions
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should properly detect access subject' do
|
47
|
+
set_access :*
|
48
|
+
get '/login/ami'
|
49
|
+
get '/subject'
|
50
|
+
assert_equal @ami.inspect, body
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should reset access properly' do
|
54
|
+
set_access :*
|
55
|
+
allow
|
56
|
+
@app.reset_access!
|
57
|
+
deny
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should set group access' do
|
61
|
+
# only humans should be allowed on TV
|
62
|
+
set_access :humans
|
63
|
+
allow @fry
|
64
|
+
deny @bender
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should set individual access' do
|
68
|
+
# only Fry should be allowed to romance Leela
|
69
|
+
set_access @fry
|
70
|
+
allow @fry
|
71
|
+
deny @ami
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should set mixed individual and group access' do
|
75
|
+
# only humans and Leela should be allowed on the surface
|
76
|
+
set_access :humans
|
77
|
+
set_access @leela
|
78
|
+
allow @fry
|
79
|
+
allow @leela
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should set action-specific access' do
|
83
|
+
# bender should be allowed to bend, and he's denied to stop partying
|
84
|
+
set_access @bender, :allow => :bend
|
85
|
+
set_access @fry, :allow => :stop_partying
|
86
|
+
allow @bender, '/bend'
|
87
|
+
deny @bender, '/stop_partying'
|
88
|
+
allow @fry, '/stop_partying'
|
89
|
+
deny @fry, '/bend'
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should set multiple action' do
|
93
|
+
# bender should be allowed to bend and drink
|
94
|
+
set_access @bender, :allow => [:drink, :bend]
|
95
|
+
allow @bender, '/drink'
|
96
|
+
allow @bender, '/bend'
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should set object-specific access' do
|
100
|
+
# only humans and Leela should be allowed to live on the surface
|
101
|
+
# only mutants should be allowed to live in the sewers though humans can visit
|
102
|
+
set_access :humans, :allow => :live, :with => :surface
|
103
|
+
set_access :mutants, :allow => :live, :with => :sewers
|
104
|
+
set_access @leela, :allow => :live, :with => :surface
|
105
|
+
set_access :humans, :allow => :visit, :with => :sewers
|
106
|
+
allow @fry, '/surface/live'
|
107
|
+
deny @fry, '/sewers/live'
|
108
|
+
allow @fry, '/sewers/visit'
|
109
|
+
allow @leela, '/surface/live'
|
110
|
+
allow @leela, '/sewers/live'
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should detect object when setting access from controller' do
|
114
|
+
# only humans and lobsters should have binocular vision
|
115
|
+
@app.controller :binocular do
|
116
|
+
set_access :humans, :lobsters
|
117
|
+
get(:vision) { 'binocular vision' }
|
118
|
+
end
|
119
|
+
deny @fry, '/'
|
120
|
+
allow @fry, '/binocular/vision'
|
121
|
+
allow @zoidberg, '/binocular/vision'
|
122
|
+
deny @leela, '/binocular/vision'
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.expand_path('../helper', __FILE__)
|
2
|
+
|
3
|
+
Account = Character
|
4
|
+
|
5
|
+
describe "Padrino::Auth" do
|
6
|
+
before do
|
7
|
+
mock_app do
|
8
|
+
enable :sessions
|
9
|
+
register Padrino::Login
|
10
|
+
register Padrino::Access
|
11
|
+
get(:robot_area){ 'robot_area' }
|
12
|
+
set_access :robots, :allow => :robot_area
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should login and access play nicely together' do
|
17
|
+
get '/robot_area'
|
18
|
+
assert_equal 302, status
|
19
|
+
|
20
|
+
post '/login', :email => :bender, :password => 'BBR'
|
21
|
+
get '/robot_area'
|
22
|
+
assert_equal 200, status
|
23
|
+
|
24
|
+
post '/login', :email => :leela, :password => 'TL'
|
25
|
+
get '/robot_area'
|
26
|
+
assert_equal 403, status
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should fail if the order is wrong' do
|
30
|
+
whine = capture_io do
|
31
|
+
mock_app do
|
32
|
+
register Padrino::Access
|
33
|
+
register Padrino::Login
|
34
|
+
end
|
35
|
+
end
|
36
|
+
assert_match /must be registered before/, whine.to_s
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require File.expand_path('../helper', __FILE__)
|
2
|
+
require 'padrino-helpers'
|
3
|
+
|
4
|
+
describe "Padrino::Access" do
|
5
|
+
before do
|
6
|
+
mock_app do
|
7
|
+
set :credentials_accessor, :visitor
|
8
|
+
set :login_model, :character
|
9
|
+
register Padrino::Rendering
|
10
|
+
enable :sessions
|
11
|
+
register Padrino::Login
|
12
|
+
get(:index){ 'index' }
|
13
|
+
get(:restricted){ 'secret' }
|
14
|
+
helpers Padrino::Helpers::AssetTagHelpers
|
15
|
+
helpers Padrino::Helpers::OutputHelpers
|
16
|
+
helpers Padrino::Helpers::TagHelpers
|
17
|
+
helpers Padrino::Helpers::FormHelpers
|
18
|
+
helpers do
|
19
|
+
def authorized?
|
20
|
+
return !['/restricted'].include?(request.env['PATH_INFO']) unless visitor
|
21
|
+
case
|
22
|
+
when visitor.id == :bender
|
23
|
+
true
|
24
|
+
else
|
25
|
+
false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
Character.all.each do |user|
|
31
|
+
instance_variable_set :"@#{user.id}", user
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should pass unrestricted area' do
|
36
|
+
get '/'
|
37
|
+
assert_equal 200, status
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should be redirected from restricted area to login page' do
|
41
|
+
get '/restricted'
|
42
|
+
assert_equal 302, status
|
43
|
+
get response.location
|
44
|
+
assert_equal 200, status
|
45
|
+
assert_match /<form .*<input .*/, body
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should not be able to authenticate with wrong password' do
|
49
|
+
post '/login', :email => :bender, :password => '123'
|
50
|
+
assert_equal 200, status
|
51
|
+
assert_match 'Wrong password', body
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should be able to authenticate with email and password' do
|
55
|
+
post '/login', :email => :bender, :password => 'BBR'
|
56
|
+
assert_equal 302, status
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should be redirected back' do
|
60
|
+
get '/restricted'
|
61
|
+
post response.location, :email => :bender, :password => 'BBR'
|
62
|
+
assert_match /\/restricted$/, response.location
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should be redirected to root if no location was saved' do
|
66
|
+
post '/login', :email => :bender, :password => 'BBR'
|
67
|
+
assert_match /\/$/, response.location
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should be allowed in restricted area after logging in' do
|
71
|
+
post '/login', :email => :bender, :password => 'BBR'
|
72
|
+
get '/restricted'
|
73
|
+
assert_equal 'secret', body
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should not be allowed in restricted area after logging in an account lacking privileges' do
|
77
|
+
post '/login', :email => :leela, :password => 'TL'
|
78
|
+
get '/restricted'
|
79
|
+
assert_equal 403, status
|
80
|
+
end
|
81
|
+
end
|
metadata
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: padrino-auth
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.12
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Igor Bochkariov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-04-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '10'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rack
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rack-test
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0.5'
|
51
|
+
type: :development
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - "~>"
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0.5'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: slim
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '2'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '2'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: padrino-helpers
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0.12'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0.12'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: padrino-core
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0.12'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0.12'
|
103
|
+
description: Lean authorization and authentication modules for Padrino framework
|
104
|
+
email: ujifgc@gmail.com
|
105
|
+
executables: []
|
106
|
+
extensions: []
|
107
|
+
extra_rdoc_files: []
|
108
|
+
files:
|
109
|
+
- ".gitignore"
|
110
|
+
- EXAMPLES.md
|
111
|
+
- Gemfile
|
112
|
+
- LICENSE
|
113
|
+
- README.md
|
114
|
+
- Rakefile
|
115
|
+
- lib/padrino-auth.rb
|
116
|
+
- lib/padrino-auth/access.rb
|
117
|
+
- lib/padrino-auth/login.rb
|
118
|
+
- lib/padrino-auth/login/controller.rb
|
119
|
+
- lib/padrino-auth/login/layouts/layout.slim
|
120
|
+
- lib/padrino-auth/login/new.slim
|
121
|
+
- lib/padrino-auth/permissions.rb
|
122
|
+
- lib/padrino-auth/version.rb
|
123
|
+
- padrino-auth.gemspec
|
124
|
+
- test/helper.rb
|
125
|
+
- test/test_padrino_access.rb
|
126
|
+
- test/test_padrino_auth.rb
|
127
|
+
- test/test_padrino_login.rb
|
128
|
+
homepage: https://github.com/ujifgc/padrino-auth
|
129
|
+
licenses:
|
130
|
+
- MIT
|
131
|
+
metadata: {}
|
132
|
+
post_install_message:
|
133
|
+
rdoc_options:
|
134
|
+
- "--charset=UTF-8"
|
135
|
+
require_paths:
|
136
|
+
- lib
|
137
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: 1.3.6
|
147
|
+
requirements: []
|
148
|
+
rubyforge_project: padrino-auth
|
149
|
+
rubygems_version: 2.2.2
|
150
|
+
signing_key:
|
151
|
+
specification_version: 4
|
152
|
+
summary: Authentication and authorization modules for Padrino
|
153
|
+
test_files: []
|
154
|
+
has_rdoc:
|