rack-cerberus 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ pkg
2
+
data/MIT_LICENCE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010 Mickael Riga
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,41 @@
1
+ "For over a thousand generations the Jedi Knights were the guardians of peace and justice in the Old Republic. Before the dark times, before the Empire." -- Obi-Wan Kenoby
2
+
3
+ = Cerberus
4
+
5
+ Cerberus is a Rack middleware for form-based authentication. Its purpose is only
6
+ to offer a nicer (or more actual) replacement for Basic HTTP authentication.
7
+ You can use it almost the same way you use <tt>Rack::Auth::Basic</tt>:
8
+
9
+ use Rack::Session::Cookie
10
+ use Cerberus do |login, pass|
11
+ pass=='secret'
12
+ end
13
+
14
+ Like in that example, make sure you have a session, because Cerberus use it for
15
+ persistent login.
16
+
17
+ There is an optional hash you can add for personalizing it. Options are:
18
+
19
+ * <tt>:company_name</tt>
20
+ * <tt>:fg_color</tt> (foreground color)
21
+ * <tt>:bg_color</tt> (background color)
22
+ * <tt>:icon_url</tt> (for a company logo or any icon)
23
+
24
+ Which is used that way:
25
+
26
+ use Cerberus, {:company_name => 'Nintendo'} do |login, pass|
27
+ pass=='secret'
28
+ end
29
+
30
+ Just like <tt>Rack::Auth::Basic</tt>, Cerberus yields login and pass, and delegate authentication
31
+ to the block you send it which should return a boolean.
32
+
33
+ If you want to see a concrete example, go into the Cerberus directory and run:
34
+
35
+ # rackup example.ru
36
+
37
+ It's gonna start the example at http://localhost:9292
38
+
39
+ === Copyright
40
+
41
+ (c) 2010 Mickael Riga - see MIT_LICENCE for details
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+
data/cerberus.gemspec ADDED
@@ -0,0 +1,13 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'rack-cerberus'
3
+ s.version = "0.0.1"
4
+ s.platform = Gem::Platform::RUBY
5
+ s.summary = "A Rack middleware for form-based authentication"
6
+ s.description = "A Rack middleware for form-based authentication"
7
+ s.files = `git ls-files`.split("\n").sort
8
+ s.test_files = ['spec.rb']
9
+ s.require_path = '.'
10
+ s.author = "Mickael Riga"
11
+ s.email = "mig@mypeplum.com"
12
+ s.homepage = "http://github.com/mig-hub/cerberus"
13
+ end
data/cerberus.rb ADDED
@@ -0,0 +1,83 @@
1
+ class Cerberus
2
+
3
+ AUTH_PAGE = <<-PAGE
4
+ <html><head>
5
+ <title>%s Authentication</title>
6
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
7
+ <style type='text/css'>
8
+ body { background-color: %s; font-family: sans-serif; }
9
+ h1, p { color: %s; }
10
+ .err {
11
+ padding: 5px;
12
+ border-radius: 5px;
13
+ -moz-border-radius: 5px;
14
+ -webkit-border-radius: 5px;
15
+ color: white;
16
+ background-color: red;
17
+ }
18
+ div {
19
+ width: 400px;
20
+ margin: 0px auto;
21
+ padding: 10px;
22
+ border-radius: 5px;
23
+ -moz-border-radius: 5px;
24
+ -webkit-border-radius: 5px;
25
+ background-color: %s; }
26
+ input { width: 400px; font-size: 20px; }
27
+ </style>
28
+ </head><body>
29
+ <div>
30
+ <h1>%s</h1>
31
+ %s
32
+ %s
33
+ <p>Please authenticate yourself</p>
34
+ <form action="%s" method="post" accept-charset="utf-8">
35
+ <input type="text" name="cerberus_login" value="login" id='login'><br />
36
+ <input type="password" name="cerberus_pass" value="pass" id='pass'>
37
+ <p><input type="submit" value="Log me &rarr;"></p>
38
+ </form>
39
+ <script type="text/javascript" charset="utf-8">
40
+ var login = document.getElementById('login');
41
+ var pass = document.getElementById('pass');
42
+ focus = function() {
43
+ if (this.value==this.id) this.value = '';
44
+ }
45
+ blur = function() {
46
+ if (this.value=='') this.value = this.id;
47
+ }
48
+ login.onfocus = focus;
49
+ pass.onfocus = focus;
50
+ login.onblur = blur;
51
+ pass.onblur = blur;
52
+ </script>
53
+ </div>
54
+ </body></html>
55
+ PAGE
56
+
57
+ def initialize(app, options={}, &block)
58
+ @app = app
59
+ defaults = { :company_name => 'Cerberus', :bg_color => '#333', :fg_color => '#555', :icon_url => nil}
60
+ @options = defaults.merge(options)
61
+ @block = block
62
+ end
63
+
64
+ def call(env)
65
+ dup._call(env)
66
+ end
67
+
68
+ def _call(env)
69
+ req = Rack::Request.new(env)
70
+ login = req['cerberus_login']
71
+ pass = req['cerberus_pass']
72
+ err = req.post? ? "<p class='err'>Wrong login or password</p>" : ''
73
+ if ((env['rack.session']['cerberus_user']!=nil && env['PATH_INFO']!='/logout') || (req.post? && @block.call(login, pass)))
74
+ env['rack.session']['cerberus_user'] ||= login
75
+ @app.call(env)
76
+ else
77
+ env['rack.session'].delete('cerberus_user')
78
+ icon = @options[:icon_url].nil? ? '' : "<img src='#{@options[:icon_url]}' /><br />"
79
+ [401, {'Content-Type' => 'text/html'}, AUTH_PAGE % [@options[:company_name], @options[:bg_color], @options[:bg_color], @options[:fg_color], @options[:company_name], icon, err, env['REQUEST_URI']]]
80
+ end
81
+ end
82
+
83
+ end
data/example.ru ADDED
@@ -0,0 +1,18 @@
1
+ require ::File.dirname(__FILE__) + '/cerberus'
2
+ use Rack::Session::Cookie
3
+
4
+ map '/' do
5
+ run lambda {|env|
6
+ body = "<html><head><title>Cerberus</title></head><body>This page is public, so you can see it. But what happens if you want to see a <a href='/secret'>Secret Page</a>? Nevertheless, I can give you access:<br /><br />Login: <b>mario</b><br />Pass: <b>bros</b></body></html>"
7
+ [200, {'Content-Type' => 'text/html'}, body]
8
+ }
9
+ end
10
+
11
+ map '/secret' do
12
+ use Cerberus, {:company_name => 'Nintendo'} do |login,pass|
13
+ [login,pass]==['mario','bros']
14
+ end
15
+ run lambda {|env|
16
+ [200, {'Content-Type' => 'text/plain'}, 'Welcome back Mario. Your Credit Card number is: 9292']
17
+ }
18
+ end
data/spec.rb ADDED
@@ -0,0 +1,45 @@
1
+ require 'rubygems'
2
+ require 'bacon'
3
+ require 'rack'
4
+
5
+ require ::File.dirname(__FILE__) + '/cerberus'
6
+
7
+ Bacon.summary_on_exit
8
+
9
+ describe 'cerberus' do
10
+
11
+ secret_app = lambda {|env| [200, {'Content-Type'=>'text/plain'}, env['rack.session'].inspect] }
12
+ app = Rack::Session::Cookie.new(Cerberus.new(secret_app, {}) {|login,pass| [login,pass]==['mario','bros']})
13
+ req = Rack::MockRequest.new(app)
14
+ cookie = ''
15
+
16
+ should 'Stop request if you are not already logged in or currently successfully logging' do
17
+ res = req.get('/')
18
+ res.status.should==401
19
+ res = req.post('/', :params => {'cerberus_login' => 'fake', 'cerberus_pass' => 'fake'})
20
+ res.status.should==401
21
+ end
22
+
23
+ should 'Give access with the appropriate login and pass' do
24
+ res = req.post('/', :params => {'cerberus_login' => 'mario', 'cerberus_pass' => 'bros'})
25
+ cookie = res["Set-Cookie"]
26
+ res.status.should==200
27
+ end
28
+
29
+ should 'Use session for persistent login' do
30
+ res = req.get('/', "HTTP_COOKIE" => cookie)
31
+ res.status.should==200
32
+ res.body.should=='{"cerberus_user"=>"mario"}'
33
+ cookie = res["Set-Cookie"]
34
+ req.get('/', "HTTP_COOKIE" => cookie).status.should==200
35
+ end
36
+
37
+ should 'Logout via /logout path' do
38
+ res = req.get('/logout', "HTTP_COOKIE" => cookie)
39
+ res.status.should==401
40
+ cookie = res["Set-Cookie"]
41
+ res = req.get('/', "HTTP_COOKIE" => cookie)
42
+ res.status.should==401
43
+ end
44
+
45
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-cerberus
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Mickael Riga
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-06-02 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: A Rack middleware for form-based authentication
23
+ email: mig@mypeplum.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - .gitignore
32
+ - MIT_LICENCE
33
+ - README.rdoc
34
+ - Rakefile
35
+ - cerberus.gemspec
36
+ - cerberus.rb
37
+ - example.ru
38
+ - spec.rb
39
+ has_rdoc: true
40
+ homepage: http://github.com/mig-hub/cerberus
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options: []
45
+
46
+ require_paths:
47
+ - .
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ hash: 3
54
+ segments:
55
+ - 0
56
+ version: "0"
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 3
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.3.7
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: A Rack middleware for form-based authentication
73
+ test_files:
74
+ - spec.rb