shield 0.0.0

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/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2009 Michel Martens, Damian Janowski and Cyril David
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.
@@ -0,0 +1,5 @@
1
+ # Shield
2
+
3
+ See the [one file tutorial][tut] for info on getting started.
4
+
5
+ [tut]: http://cyx.github.com/shield
@@ -0,0 +1,73 @@
1
+ ## Shield
2
+
3
+ # A simple authentication framework for use with a basic Rack application.
4
+ # It doesn't try to be generic and instead has the following assertions:
5
+
6
+ # 1. You use [Ohm][ohm] for your persistence layer.
7
+ # 2. That your app has some form of a Helper plugin system.
8
+
9
+ ## Usage
10
+
11
+ # The fastest way to get started with `Shield` is to use it as a [Sinatra][sin]
12
+ # extension on top of your main application.
13
+
14
+ # We simply have to require sinatra, shield, and [Ohm][ohm].
15
+ require "sinatra/base"
16
+ require "shield"
17
+ require "ohm"
18
+
19
+ # We then define a `User` class on the top-level namespace:
20
+ class User < Shield::User
21
+ end
22
+
23
+ # Our sinatra application can be a classic style, but for this example,
24
+ # we'll use the more modular style extending from `Sinatra::Base`.
25
+ class App < Sinatra::Base
26
+ # One very very important detail to remember is that you need to
27
+ # have session support for all of Shield to work.
28
+ enable :sessions
29
+
30
+ # Now for the main highlight: This line simply does two things:
31
+ #
32
+ # 1. It adds `Shield::Helpers` to your Sinatra app's helpers.
33
+ # 2. It adds `Shield::Login` as a middleware for your application.
34
+ #
35
+ register Shield
36
+
37
+ # This is a normal Sinatra route. No authentication is needed here.
38
+ get "/public" do
39
+ "Public"
40
+ end
41
+
42
+ # This is a private Sinatra route, which we enforce using
43
+ # `ensure_authenticated`. This method comes from `Shield::Helpers` along
44
+ # with some other helper methods:
45
+ #
46
+ # 1. `current_user` - ain't this the standard nowadays?
47
+ # 2. `logged_in?` - simple sugar to verify if the user is logged in.
48
+ # 3. `ensure_authenticated` - as shown here.
49
+ # 4. `redirect_to_stored` - redirects to the previous url the user was
50
+ # trying to access prior to authenticating.
51
+ get "/private" do
52
+ ensure_authenticated
53
+
54
+ "Private"
55
+ end
56
+ end
57
+
58
+ # If this file was run directly i.e. ruby README.rb.
59
+ if __FILE__ == $0
60
+ # For the purposes of this quick script, let's create a User. You'll use that
61
+ # to quickly verify that you can indeed login to the application.
62
+ if User.all.size == 0
63
+ User.create(:email => "quentin@test.com",
64
+ :password => "password",
65
+ :password_confirmation => "password")
66
+ end
67
+
68
+ # Let Sinatra take the stage.
69
+ App.run!
70
+ end
71
+
72
+ # [ohm]: http://ohm.keyvalue.org
73
+ # [sin]: http://sinatrarb.com
@@ -0,0 +1,6 @@
1
+ desc "Run all tests using cutest."
2
+ task :test do
3
+ system("cutest -r ./test/helper ./test/*_test.rb")
4
+ end
5
+
6
+ task :default => :test
@@ -0,0 +1,18 @@
1
+ module Shield
2
+ VERSION = "0.0.0"
3
+
4
+ autoload :BasicUser, "shield/template/basic_user"
5
+ autoload :User, "shield/template/user"
6
+ autoload :FlexiUser, "shield/template/flexi_user"
7
+ autoload :Password, "shield/password"
8
+ autoload :Login, "shield/login"
9
+ autoload :Helpers, "shield/helpers"
10
+
11
+ def self.registered(app)
12
+ app.helpers Helpers
13
+
14
+ app.use Login do |m|
15
+ m.settings.set :views, app.views if app.views
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ module Shield
2
+ module Helpers
3
+ def ensure_authenticated
4
+ return if logged_in?
5
+
6
+ session[:return_to] = request.fullpath
7
+ redirect "/login"
8
+ end
9
+
10
+ def logged_in?
11
+ !! current_user
12
+ end
13
+
14
+ def current_user
15
+ @_current_user ||= ::User[session[:user]]
16
+ end
17
+
18
+ def redirect_to_stored(default = "/")
19
+ redirect(session.delete(:return_to) || default)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,38 @@
1
+ require "sinatra/base"
2
+
3
+ module Shield
4
+ class Login < Sinatra::Base
5
+ enable :sessions
6
+ helpers Helpers
7
+
8
+ set :views, File.join(File.dirname(__FILE__), "..", "..", "views")
9
+
10
+ set :auth_success_message, "You have successfully logged in."
11
+ set :auth_failure_message, "Wrong Username and/or Password combination."
12
+
13
+ get "/login/?" do
14
+ haml :login
15
+ end
16
+
17
+ post "/login/?" do
18
+ user = ::User.authenticate(params[:login], params[:password])
19
+
20
+ if user
21
+ session[:success] = settings.auth_success_message
22
+ session[:user] = user.id
23
+
24
+ redirect_to_stored
25
+ else
26
+ session[:error] = settings.auth_failure_message
27
+ redirect "/login"
28
+ end
29
+ end
30
+
31
+ get "/logout/?" do
32
+ session.delete(:user)
33
+ session.delete(:return_to)
34
+
35
+ redirect "/"
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,24 @@
1
+ require "digest/sha2"
2
+
3
+ module Shield
4
+ module Password
5
+ def self.encrypt(password, salt = generate_salt)
6
+ digest(password, salt) + salt
7
+ end
8
+
9
+ def self.check(password, encrypted)
10
+ sha512, salt = encrypted.to_s[0..127], encrypted.to_s[128..-1]
11
+
12
+ digest(password, salt) == sha512
13
+ end
14
+
15
+ private
16
+ def self.digest(password, salt)
17
+ Digest::SHA512.hexdigest("#{ password }#{ salt }")
18
+ end
19
+
20
+ def self.generate_salt
21
+ Digest::SHA512.hexdigest(Time.now.to_f.to_s)[0, 64]
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,37 @@
1
+ module Shield
2
+ class BasicUser < Ohm::Model
3
+ Unimplemented = Class.new(StandardError)
4
+
5
+ def self.inherited(model)
6
+ model.attribute :crypted_password
7
+ end
8
+
9
+ # TODO : change this if Ohm decides on implementing subclassing.
10
+ def self._copy_attributes_indices_counters(model)
11
+ attributes.each { |att| model.attribute(att) }
12
+ indices.each { |att| model.index(att) }
13
+ counters.each { |att| model.counter(att) }
14
+ end
15
+
16
+ attr_reader :password, :password_confirmation
17
+ attr_writer :password_confirmation
18
+
19
+ def self.authenticate(login, password)
20
+ user = find_by_login(login)
21
+
22
+ if user && Shield::Password.check(password, user.crypted_password)
23
+ return user
24
+ end
25
+ end
26
+
27
+ def self.find_by_login(login)
28
+ raise Unimplemented
29
+ end
30
+
31
+ def password=(password)
32
+ write_local :crypted_password, Shield::Password.encrypt(password)
33
+
34
+ @password = password
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,22 @@
1
+ module Shield
2
+ class FlexiUser < User
3
+ def self.inherited(model)
4
+ model.attribute :username
5
+ model.index :username
6
+
7
+ _copy_attributes_indices_counters(model)
8
+ end
9
+
10
+ def self.find_by_login(login)
11
+ super or find(:username => login).first
12
+ end
13
+
14
+ def validate
15
+ super
16
+
17
+ assert_present(:username) &&
18
+ assert_format(:username, /\A[a-z][a-z0-9\-\_\.]{2,}\z/) &&
19
+ assert_unique(:username)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,32 @@
1
+ require "ohm/contrib"
2
+
3
+ module Shield
4
+ class User < BasicUser
5
+ include Ohm::WebValidations
6
+
7
+ def self.inherited(model)
8
+ model.attribute :email
9
+ model.index :email
10
+
11
+ _copy_attributes_indices_counters(model)
12
+ end
13
+
14
+ def self.find_by_login(login)
15
+ find(:email => login).first
16
+ end
17
+
18
+ def validate
19
+ super
20
+
21
+ assert_present(:email) && assert_email(:email) && assert_unique(:email)
22
+
23
+ if new?
24
+ assert_present :password
25
+ end
26
+
27
+ unless password.to_s.empty?
28
+ assert password == password_confirmation, [:password, :not_confirmed]
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,37 @@
1
+ require File.expand_path("helper", File.dirname(__FILE__))
2
+
3
+ class BasicUser < Shield::BasicUser
4
+ end
5
+
6
+ setup do
7
+ BasicUser.create(:password => "password")
8
+ end
9
+
10
+ test "allows password checks at the minimum" do |u|
11
+ assert Shield::Password.check("password", u.crypted_password)
12
+ end
13
+
14
+ test "no find_by_login" do
15
+ assert_raise Shield::BasicUser::Unimplemented do
16
+ BasicUser.authenticate("quentin", "password")
17
+ end
18
+
19
+ assert_raise Shield::BasicUser::Unimplemented do
20
+ BasicUser.find_by_login("quentin")
21
+ end
22
+ end
23
+
24
+ test "has password confirmation accesors" do |u|
25
+ u.password_confirmation = "pass"
26
+
27
+ assert "pass" == u.password_confirmation
28
+ end
29
+
30
+ test "writes the new crypted password on set" do
31
+ u = BasicUser.new(:password => "mypass")
32
+ assert Shield::Password.check("mypass", u.crypted_password)
33
+
34
+ u.save
35
+ u = BasicUser[u.id]
36
+ assert Shield::Password.check("mypass", u.crypted_password)
37
+ end
@@ -0,0 +1,40 @@
1
+ require File.expand_path("helper", File.dirname(__FILE__))
2
+
3
+ class FlexiUser < Shield::FlexiUser
4
+ end
5
+
6
+ setup do
7
+ FlexiUser.create(:email => "quentin@test.com",
8
+ :username => "quentin",
9
+ :password => "password",
10
+ :password_confirmation => "password")
11
+ end
12
+
13
+ test "find_by_login" do |u|
14
+ assert u == FlexiUser.find_by_login("quentin@test.com")
15
+ assert u == FlexiUser.find_by_login("quentin")
16
+ end
17
+
18
+ test "authenticate" do |u|
19
+ assert u == FlexiUser.authenticate("quentin", "password")
20
+ assert u == FlexiUser.authenticate("quentin@test.com", "password")
21
+ end
22
+
23
+ test "username validation" do |u|
24
+ u.username = nil
25
+ assert ! u.valid?
26
+ assert u.errors.include?([:username, :not_present])
27
+
28
+ ["1foo", "fo", "foo^", "foo&", "foo#"].each do |username|
29
+ u.username = username
30
+ assert ! u.valid?
31
+ assert u.errors.include?([:username, :format])
32
+ end
33
+
34
+ u.username = "foo"
35
+ assert u.valid?
36
+
37
+ newuser = FlexiUser.new(:username => "quentin")
38
+ assert ! newuser.valid?
39
+ assert newuser.errors.include?([:username, :not_unique])
40
+ end
@@ -0,0 +1,25 @@
1
+ $:.unshift(File.expand_path("../lib", File.dirname(__FILE__)))
2
+
3
+ require "shield"
4
+ require "cutest"
5
+ require "rack/test"
6
+ require "sinatra/base"
7
+ require "nokogiri"
8
+ require "haml"
9
+ require "ohm"
10
+ require "ohm/contrib"
11
+
12
+ prepare { Ohm.flush }
13
+
14
+ class Cutest::Scope
15
+ include Rack::Test::Methods
16
+
17
+ def assert_redirected_to(path)
18
+ assert 302 == last_response.status
19
+ assert path == last_response.headers["Location"]
20
+ end
21
+
22
+ def session
23
+ last_request.env["rack.session"]
24
+ end
25
+ end
@@ -0,0 +1,59 @@
1
+ require File.expand_path("helper", File.dirname(__FILE__))
2
+
3
+ class User < Shield::User
4
+ end
5
+
6
+ class Main < Sinatra::Base
7
+ enable :sessions
8
+ helpers Shield::Helpers
9
+
10
+ get "/public" do
11
+ "Public"
12
+ end
13
+
14
+ get "/private" do
15
+ ensure_authenticated
16
+
17
+ "Private"
18
+ end
19
+
20
+ use Shield::Login do |login|
21
+ login.settings.auth_success_message = "Booya!"
22
+ login.settings.auth_failure_message = "BOOM!"
23
+ end
24
+ end
25
+
26
+ scope do
27
+ def app
28
+ Main.new
29
+ end
30
+
31
+ setup do
32
+ clear_cookies
33
+
34
+ User.create(:email => "quentin@test.com",
35
+ :password => "password",
36
+ :password_confirmation => "password")
37
+ end
38
+
39
+ test "public" do
40
+ get "/public"
41
+ assert "Public" == last_response.body
42
+ end
43
+
44
+ test "logging in" do
45
+ post "/login", :login => "quentin@test.com", :password => "password"
46
+
47
+ get "/private"
48
+ assert "Private" == last_response.body
49
+ assert "Booya!" == session[:success]
50
+ end
51
+
52
+ test "login, logout, login failure" do
53
+ post "/login", :login => "quentin@test.com", :password => "password"
54
+ get "/logout"
55
+
56
+ post "/login"
57
+ assert "BOOM!" == session[:error]
58
+ end
59
+ end
@@ -0,0 +1,63 @@
1
+ require File.expand_path("helper", File.dirname(__FILE__))
2
+
3
+ class User < Shield::User
4
+ end
5
+
6
+ class Main < Sinatra::Base
7
+ enable :sessions
8
+ helpers Shield::Helpers
9
+
10
+ get "/public" do
11
+ "Public"
12
+ end
13
+
14
+ get "/private" do
15
+ ensure_authenticated
16
+
17
+ "Private"
18
+ end
19
+ end
20
+
21
+ $app = Rack::Builder.app {
22
+ use Shield::Login
23
+
24
+ map "/" do
25
+ run Main
26
+ end
27
+ }
28
+
29
+ scope do
30
+ def app
31
+ $app
32
+ end
33
+
34
+ setup do
35
+ clear_cookies
36
+
37
+ User.create(:email => "quentin@test.com",
38
+ :password => "password",
39
+ :password_confirmation => "password")
40
+ end
41
+
42
+ test "public" do
43
+ get "/public"
44
+
45
+ assert "Public" == last_response.body
46
+ end
47
+
48
+ test "logging in" do
49
+ post "/login", :login => "quentin@test.com",
50
+ :password => "password"
51
+
52
+ get "/private"
53
+ assert "Private" == last_response.body
54
+ end
55
+
56
+ test "being redirected and then logging in" do
57
+ get "/private"
58
+ assert_redirected_to "/login"
59
+
60
+ post "/login", :login => "quentin@test.com", :password => "password"
61
+ assert_redirected_to "/private"
62
+ end
63
+ end
@@ -0,0 +1,96 @@
1
+ require File.expand_path("helper", File.dirname(__FILE__))
2
+
3
+ class User < Shield::User
4
+ end
5
+
6
+ class App < Sinatra::Base
7
+ enable :sessions
8
+
9
+ helpers Shield::Helpers
10
+ end
11
+
12
+ class Main < App
13
+ get "/public" do
14
+ "Public"
15
+ end
16
+
17
+ get "/private" do
18
+ ensure_authenticated
19
+
20
+ "Private"
21
+ end
22
+ end
23
+
24
+ class Admin < App
25
+ before do
26
+ ensure_authenticated unless request.fullpath == "/admin/login"
27
+ end
28
+
29
+ get "/events" do
30
+ "Events"
31
+ end
32
+
33
+ get "/sponsors" do
34
+ "Sponsors"
35
+ end
36
+
37
+ post "/login" do
38
+ user = User.authenticate(params[:login], params[:password])
39
+
40
+ if user
41
+ session[:success] = "Success"
42
+ session[:user] = user.id
43
+
44
+ redirect_to_stored
45
+ else
46
+ session[:error] = "Failure"
47
+ redirect "/login"
48
+ end
49
+ end
50
+ end
51
+
52
+ $app = Rack::Builder.app {
53
+ map "/" do
54
+ run Main
55
+ end
56
+
57
+ map "/admin" do
58
+ run Admin
59
+ end
60
+ }
61
+
62
+ scope do
63
+ def app
64
+ $app
65
+ end
66
+
67
+ setup do
68
+ User.create(:email => "quentin@test.com",
69
+ :password => "password",
70
+ :password_confirmation => "password")
71
+ end
72
+
73
+ test "public" do
74
+ get "/public"
75
+
76
+ assert "Public" == last_response.body
77
+ end
78
+
79
+ test "all admin routes" do
80
+ get "/admin/events"
81
+ assert_redirected_to "/login"
82
+ assert "/admin/events" == session[:return_to]
83
+
84
+ get "/admin/sponsors"
85
+ assert_redirected_to "/login"
86
+ assert "/admin/sponsors" == session[:return_to]
87
+ end
88
+
89
+ test "single sign on" do
90
+ post "/admin/login", :login => "quentin@test.com",
91
+ :password => "password"
92
+
93
+ get "/private"
94
+ assert "Private" == last_response.body
95
+ end
96
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path("helper", File.dirname(__FILE__))
2
+
3
+ test "encrypt" do
4
+ encrypted = Shield::Password.encrypt("password")
5
+ assert Shield::Password.check("password", encrypted)
6
+ end
7
+
8
+ test "with custom 64 character salt" do
9
+ encrypted = Shield::Password.encrypt("password", "A" * 64)
10
+ assert Shield::Password.check("password", encrypted)
11
+ end
12
+
13
+ test "nil password doesn't raise" do
14
+ ex = nil
15
+
16
+ begin
17
+ encrypted = Shield::Password.encrypt(nil)
18
+ rescue Exception => e
19
+ ex = e
20
+ end
21
+
22
+ assert nil == ex
23
+ end
@@ -0,0 +1 @@
1
+ require File.expand_path("helper", File.dirname(__FILE__))
@@ -0,0 +1,73 @@
1
+ require File.expand_path("helper", File.dirname(__FILE__))
2
+
3
+ class User < Shield::User
4
+ end
5
+
6
+ class SinatraApp < Sinatra::Base
7
+ enable :sessions
8
+ register Shield
9
+
10
+ get "/public" do
11
+ "Public"
12
+ end
13
+
14
+ get "/private" do
15
+ ensure_authenticated
16
+
17
+ "Private"
18
+ end
19
+ end
20
+
21
+ scope do
22
+ def app
23
+ SinatraApp.new
24
+ end
25
+
26
+ setup do
27
+ User.create(:email => "quentin@test.com",
28
+ :password => "password",
29
+ :password_confirmation => "password")
30
+ end
31
+
32
+ test "public" do
33
+ get "/public"
34
+ assert "Public" == last_response.body
35
+ end
36
+
37
+ test "private" do
38
+ get "/private"
39
+ assert_redirected_to "/login"
40
+ assert "/private" == session[:return_to]
41
+
42
+ post "/login", :login => "quentin@test.com", :password => "password"
43
+ assert_redirected_to "/private"
44
+ end
45
+
46
+ test "GET /login response" do
47
+ get "/login"
48
+
49
+ doc = Nokogiri(%{<div>#{last_response.body}</div>})
50
+
51
+ assert 2 == doc.search("form > fieldset > label > input").size
52
+ assert 1 == doc.search("form > fieldset > button").size
53
+ end
54
+ end
55
+
56
+ class LoginCustomized < Sinatra::Base
57
+ enable :sessions
58
+ set :views, File.join(File.dirname(__FILE__), "fixtures", "views")
59
+
60
+ register Shield
61
+ end
62
+
63
+ scope do
64
+ def app
65
+ LoginCustomized.new
66
+ end
67
+
68
+ test "login response" do
69
+ get "/login"
70
+
71
+ assert "<h1>Login</h1>" == last_response.body.strip
72
+ end
73
+ end
@@ -0,0 +1,33 @@
1
+ require File.expand_path("helper", File.dirname(__FILE__))
2
+
3
+ class User < Shield::User
4
+ end
5
+
6
+ setup do
7
+ User.create(:email => "quentin@email.com", :password => "password",
8
+ :password_confirmation => "password")
9
+ end
10
+
11
+ test "authentication default" do |u|
12
+ assert u == User.authenticate("quentin@email.com", "password")
13
+
14
+ assert nil == User.authenticate("quentin@email.com", "pass")
15
+ assert nil == User.authenticate("quentin@email.co.uk", "password")
16
+ end
17
+
18
+ test "email validation" do |u|
19
+ u.email = nil
20
+ assert ! u.valid?
21
+ assert u.errors.include?([:email, :not_present])
22
+
23
+ u.email = "foobar"
24
+ assert ! u.valid?
25
+ assert u.errors.include?([:email, :not_email])
26
+
27
+ u.email = "foo@bar.com"
28
+ u.save
29
+
30
+ foo = User.new(:email => "foo@bar.com")
31
+ assert ! foo.valid?
32
+ assert foo.errors.include?([:email, :not_unique])
33
+ end
metadata ADDED
@@ -0,0 +1,179 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shield
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 0
9
+ version: 0.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Michel Martens
13
+ - Damian Janowski
14
+ - Cyril David
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-10-15 00:00:00 +08:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: cutest
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: sinatra
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ segments:
44
+ - 0
45
+ version: "0"
46
+ type: :development
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: haml
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 0
58
+ version: "0"
59
+ type: :development
60
+ version_requirements: *id003
61
+ - !ruby/object:Gem::Dependency
62
+ name: rack-test
63
+ prerelease: false
64
+ requirement: &id004 !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ type: :development
73
+ version_requirements: *id004
74
+ - !ruby/object:Gem::Dependency
75
+ name: ohm
76
+ prerelease: false
77
+ requirement: &id005 !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ segments:
83
+ - 0
84
+ version: "0"
85
+ type: :development
86
+ version_requirements: *id005
87
+ - !ruby/object:Gem::Dependency
88
+ name: ohm-contrib
89
+ prerelease: false
90
+ requirement: &id006 !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ segments:
96
+ - 0
97
+ version: "0"
98
+ type: :development
99
+ version_requirements: *id006
100
+ - !ruby/object:Gem::Dependency
101
+ name: nokogiri
102
+ prerelease: false
103
+ requirement: &id007 !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ segments:
109
+ - 0
110
+ version: "0"
111
+ type: :development
112
+ version_requirements: *id007
113
+ description: "\n Gets you 80-90% of the way regarding your authentication\n requirements. Provides convenience helper functions which you can\n use with your favorite web framework of choice.\n "
114
+ email:
115
+ - michel@soveran.com
116
+ - djanowski@dimaion.com
117
+ - cyx@pipetodevnull.com
118
+ executables: []
119
+
120
+ extensions: []
121
+
122
+ extra_rdoc_files: []
123
+
124
+ files:
125
+ - lib/shield/helpers.rb
126
+ - lib/shield/login.rb
127
+ - lib/shield/password.rb
128
+ - lib/shield/template/basic_user.rb
129
+ - lib/shield/template/flexi_user.rb
130
+ - lib/shield/template/user.rb
131
+ - lib/shield.rb
132
+ - README.markdown
133
+ - README.rb
134
+ - LICENSE
135
+ - Rakefile
136
+ - test/basic_user_test.rb
137
+ - test/flexi_user_test.rb
138
+ - test/helper.rb
139
+ - test/login_middleware_test.rb
140
+ - test/login_rack_mounting_test.rb
141
+ - test/mounted_middleware_test.rb
142
+ - test/password_hash_test.rb
143
+ - test/shield_test.rb
144
+ - test/sinatra_test.rb
145
+ - test/user_test.rb
146
+ has_rdoc: true
147
+ homepage: http://github.com/cyx/shield
148
+ licenses: []
149
+
150
+ post_install_message:
151
+ rdoc_options: []
152
+
153
+ require_paths:
154
+ - lib
155
+ required_ruby_version: !ruby/object:Gem::Requirement
156
+ none: false
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ segments:
161
+ - 0
162
+ version: "0"
163
+ required_rubygems_version: !ruby/object:Gem::Requirement
164
+ none: false
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ segments:
169
+ - 0
170
+ version: "0"
171
+ requirements: []
172
+
173
+ rubyforge_project: shield
174
+ rubygems_version: 1.3.7
175
+ signing_key:
176
+ specification_version: 3
177
+ summary: Ohm specific authentication solution.
178
+ test_files: []
179
+