pasaporte 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +2 -0
- data/Manifest.txt +41 -0
- data/README.txt +72 -0
- data/Rakefile +111 -0
- data/TODO.txt +2 -0
- data/bin/pasaporte-fcgi.rb +17 -0
- data/lib/pasaporte/.DS_Store +0 -0
- data/lib/pasaporte/assets/.DS_Store +0 -0
- data/lib/pasaporte/assets/bgbar.png +0 -0
- data/lib/pasaporte/assets/lock.png +0 -0
- data/lib/pasaporte/assets/mainbg_green.gif +0 -0
- data/lib/pasaporte/assets/mainbg_red.gif +0 -0
- data/lib/pasaporte/assets/openid.png +0 -0
- data/lib/pasaporte/assets/pasaporte.css +192 -0
- data/lib/pasaporte/assets/pasaporte.js +10 -0
- data/lib/pasaporte/assets/user.png +0 -0
- data/lib/pasaporte/auth/cascade.rb +16 -0
- data/lib/pasaporte/auth/remote_web_workplace.rb +61 -0
- data/lib/pasaporte/auth/yaml_digest_table.rb +23 -0
- data/lib/pasaporte/auth/yaml_table.rb +43 -0
- data/lib/pasaporte/faster_openid.rb +39 -0
- data/lib/pasaporte/iso_countries.yml +247 -0
- data/lib/pasaporte/julik_state.rb +42 -0
- data/lib/pasaporte/markaby_ext.rb +8 -0
- data/lib/pasaporte/pasaporte_store.rb +60 -0
- data/lib/pasaporte/timezones.yml +797 -0
- data/lib/pasaporte.rb +1214 -0
- data/test/fixtures/pasaporte_approvals.yml +12 -0
- data/test/fixtures/pasaporte_profiles.yml +45 -0
- data/test/fixtures/pasaporte_throttles.yml +4 -0
- data/test/helper.rb +66 -0
- data/test/mosquito.rb +596 -0
- data/test/test_approval.rb +33 -0
- data/test/test_auth_backends.rb +59 -0
- data/test/test_openid.rb +363 -0
- data/test/test_pasaporte.rb +326 -0
- data/test/test_profile.rb +165 -0
- data/test/test_settings.rb +27 -0
- data/test/test_throttle.rb +70 -0
- data/test/testable_openid_fetcher.rb +82 -0
- metadata +151 -0
@@ -0,0 +1,165 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
class TestProfile < Camping::ModelTest
|
4
|
+
DOMAIN = 'my-pasaporte.com'
|
5
|
+
fixtures :pasaporte_profiles
|
6
|
+
|
7
|
+
def test_aa_fixtures_loaded
|
8
|
+
assert_equal 4, Profile.count
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_assumes_localhost_as_default_domain
|
12
|
+
@profile = Profile.new
|
13
|
+
assert_equal 'localhost', @profile.domain_name
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_requires_nickname_and_domain
|
17
|
+
@profile = Profile.new
|
18
|
+
|
19
|
+
deny @profile.valid?, "The profile without a nickname and a domain name is invalid"
|
20
|
+
@profile.nickname = 'xxx'
|
21
|
+
@profile.domain_name = ''
|
22
|
+
|
23
|
+
deny @profile.valid?, "The profile without a domain name is invalid"
|
24
|
+
|
25
|
+
@profile.domain_name = 'somedomain'
|
26
|
+
assert @profile.valid?
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_domain_name_and_nickname_are_protected
|
30
|
+
@profile = Profile.new
|
31
|
+
@profile.attributes = {:nickname => 'xyz', :domain_name => 'google'}
|
32
|
+
|
33
|
+
assert_not_equal @profile.nickname, 'xyz'
|
34
|
+
assert_not_equal @profile.domain_name, 'google'
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_find_or_create_by_domain_and_nickname_exempted_from_attribute_protection
|
38
|
+
prof = create("julik", "julik.nl")
|
39
|
+
assert prof.valid?
|
40
|
+
deny prof.new_record?
|
41
|
+
assert_equal 'julik.nl', prof.domain_name
|
42
|
+
assert_equal 'julik', prof.nickname
|
43
|
+
prof = create("julik", "julik.nl")
|
44
|
+
assert prof.valid?
|
45
|
+
deny prof.new_record?
|
46
|
+
assert_equal 'julik.nl', prof.domain_name
|
47
|
+
assert_equal 'julik', prof.nickname
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_secret_integer_generated
|
51
|
+
secrets = %w( foo bar baz daz daing ).map do | word |
|
52
|
+
prof = Profile.find_or_create_by_nickname_and_domain_name(word, word)
|
53
|
+
deny prof.new_record?
|
54
|
+
prof.secret_salt
|
55
|
+
end
|
56
|
+
assert_equal secrets.length, secrets.uniq.length,
|
57
|
+
"All generated secrets should be autogenerated and unique"
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_enforces_unique_nickname_and_domain
|
61
|
+
prof1 = create("MisterZed", "google.com")
|
62
|
+
prof2 = Profile.new do | p |
|
63
|
+
p.nickname = "MisterZed"
|
64
|
+
p.domain_name = "google.com"
|
65
|
+
end
|
66
|
+
|
67
|
+
assert prof1.valid?, "The first created should be valid"
|
68
|
+
deny prof2.valid?, "The second one clashes"
|
69
|
+
|
70
|
+
prof2.domain_name = "yahoo.com"
|
71
|
+
assert prof2.valid?, "The second one is valid too because there are no clashes anymore"
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_validates_both_delegate_urls
|
75
|
+
p = create("strained", "test.host")
|
76
|
+
assert p.valid?, "The newly created profile should be valid"
|
77
|
+
|
78
|
+
p.openid_server = "watatoe.com/openid"
|
79
|
+
deny p.valid?, "The profile cannot be valid with only the server URL"
|
80
|
+
assert_not_nil p.errors[:openid_delegate], "Should require delegate URL"
|
81
|
+
|
82
|
+
p.openid_delegate = "watatoe.com/openid/backend"
|
83
|
+
assert p.valid?, "As two URLs are present the profile becomes valid"
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_delegate_urls_removed_when_delegate_set_to_false
|
87
|
+
p = create('julik', DOMAIN,
|
88
|
+
:openid_server => 'xxx.com', :openid_delegate => 'xyz.org/x')
|
89
|
+
assert p.delegates_openid?, "This profile delegates"
|
90
|
+
p.delegates_openid = false
|
91
|
+
p.save!
|
92
|
+
|
93
|
+
assert p.openid_server.blank?, "The openid server should have been removed"
|
94
|
+
assert p.openid_delegate.blank?, "The openid delegate should have been removed"
|
95
|
+
deny p.delegates_openid?, "Delegation is now turned off because we sent a bool switch of false"
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_normalizes_both_delegate_urls
|
99
|
+
p = create('julik', DOMAIN,
|
100
|
+
:openid_server => 'xxx.com', :openid_delegate => 'xyz.org/x')
|
101
|
+
assert_equal 'http://xxx.com/', p.openid_server,
|
102
|
+
"The URL should be normalized with HTTP scheme and trailing slash"
|
103
|
+
assert_equal 'http://xyz.org/x', p.openid_delegate,
|
104
|
+
"The URL should be normalized with HTTP scheme"
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_to_sreg_fields_by_default
|
108
|
+
p = create('julik', DOMAIN,
|
109
|
+
:email => 'foo@var.com', :dob => Date.parse("10.15.1983"))
|
110
|
+
all_fields = p.to_sreg_fields
|
111
|
+
r = {"dob"=>"1983-10-15", "nickname"=>"julik", "email"=>"foo@var.com"}
|
112
|
+
assert_equal r, all_fields
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_to_sreg_fields_with_requested_fields
|
116
|
+
p = create('julik', DOMAIN,
|
117
|
+
:email => 'foo@var.com', :dob => Date.parse("10.15.1983"))
|
118
|
+
partial_fields = p.to_sreg_fields([:dob, :gender, :country])
|
119
|
+
r = {"dob"=>"1983-10-15"}
|
120
|
+
assert_equal r, partial_fields
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_to_sreg_fields_with_lotso_data
|
124
|
+
mh = Profile.find(1)
|
125
|
+
ref = {"dob"=>"1953-01-12", "postcode"=>"1234",
|
126
|
+
"nickname"=>"monsieur-hulot",
|
127
|
+
"country"=>"fr", "fullname"=>"Monsieur Hulot", "gender"=>"m"}
|
128
|
+
assert_equal ref, mh.to_sreg_fields
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_openid_requestor
|
132
|
+
begin
|
133
|
+
o = Pasaporte::ALLOW_DELEGATION
|
134
|
+
silence_warnings { Pasaporte.const_set(:ALLOW_DELEGATION, true) }
|
135
|
+
|
136
|
+
mh = Profile.find(1)
|
137
|
+
deny mh.delegates_openid?
|
138
|
+
assert mh.update_attributes(
|
139
|
+
:openid_server => 'http://tativille.fr/oid',
|
140
|
+
:openid_delegate => 'http://tativille.fr/oid/proc'
|
141
|
+
)
|
142
|
+
|
143
|
+
assert mh.delegates_openid?, "delegates_openid? should be true"
|
144
|
+
assert mh.update_attributes(:openid_server => '', :openid_delegate => '')
|
145
|
+
deny mh.delegates_openid?, "There are no URLS - no delegation happens"
|
146
|
+
|
147
|
+
assert mh.update_attributes(
|
148
|
+
:openid_server => 'http://tativille.fr/oid',
|
149
|
+
:openid_delegate => 'http://tativille.fr/oid/proc'
|
150
|
+
)
|
151
|
+
silence_warnings { Pasaporte.const_set(:ALLOW_DELEGATION, false) }
|
152
|
+
deny mh.delegates_openid?, "Delegation is turned off - "+
|
153
|
+
"no delegation happens"
|
154
|
+
ensure
|
155
|
+
silence_warnings { Pasaporte.const_set(:ALLOW_DELEGATION, o) }
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
def create(nick, domain, extras = {})
|
161
|
+
p = Profile.find_or_create_by_nickname_and_domain_name(nick, domain)
|
162
|
+
p.update_attributes(extras) if extras.any?
|
163
|
+
p
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
class TestSettings < Camping::Test
|
4
|
+
CONFIG = File.dirname(Pasaporte::PATH) + '/pasaporte/config.yml'
|
5
|
+
|
6
|
+
def test_application
|
7
|
+
emit :throttle_for => 45.minutes
|
8
|
+
assert_nothing_raised { Pasaporte.apply_config! }
|
9
|
+
assert_equal 45.minutes, Pasaporte::THROTTLE_FOR, "The setting should have " +
|
10
|
+
"been applied"
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_bail_on_unknowns
|
14
|
+
emit :achtung => "shtoink"
|
15
|
+
e = assert_raise(NameError) { Pasaporte.apply_config! }
|
16
|
+
assert_match /ACHTUNG/i, e.message
|
17
|
+
end
|
18
|
+
|
19
|
+
def teardown
|
20
|
+
begin; File.unlink(CONFIG); rescue Errno::ENOENT; end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def emit(hash = {})
|
25
|
+
File.open(CONFIG, 'w') { | f | f << hash.to_yaml }
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
class TestThrottle < Camping::ModelTest
|
4
|
+
DOMAIN = 'my-pasaporte.com'
|
5
|
+
HEADERS = Mosquito::MockRequest::DEFAULT_HEADERS.merge('REMOTE_ADDR' => '120.171.0.1')
|
6
|
+
|
7
|
+
def setup
|
8
|
+
silence_warnings { Pasaporte.const_set(:THROTTLE_FOR, 2.minutes) }
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_throttle_set
|
13
|
+
deny Throttle.throttled?(HEADERS)
|
14
|
+
|
15
|
+
t = Throttle.set!(HEADERS)
|
16
|
+
assert_kind_of Throttle, t
|
17
|
+
deny t.new_record?
|
18
|
+
assert Throttle.throttled?(HEADERS)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_throttle_response_depends_on_cutoff
|
22
|
+
Throttle.set!(HEADERS)
|
23
|
+
flexmock(Throttle).should_receive(:cutoff).at_least.once.and_return(Time.now + 10)
|
24
|
+
deny Throttle.throttled?(HEADERS)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_cutoff_depends_on_app_setting
|
28
|
+
assert_time_matches (Time.now - Pasaporte::THROTTLE_FOR), Throttle.send(:cutoff)
|
29
|
+
silence_warnings{ Pasaporte.const_set(:THROTTLE_FOR, 14) }
|
30
|
+
assert_time_matches Time.now - 14, Throttle.send(:cutoff)
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_throttle_response_depends_on_env_params
|
34
|
+
envs = [
|
35
|
+
{'HTTP_USER_AGENT' => 'KitchenSink, NOT like IE',
|
36
|
+
'REMOTE_ADDR' => '164.10.10.1'},
|
37
|
+
{'HTTP_USER_AGENT' => 'WebKit (like Gecko)',
|
38
|
+
'REMOTE_ADDR' => '164.10.10.1'},
|
39
|
+
{'HTTP_USER_AGENT' => 'KitchenSink, NOT like IE',
|
40
|
+
'REMOTE_ADDR' => '164.10.10.1'},
|
41
|
+
]
|
42
|
+
|
43
|
+
Throttle.set!(envs[0])
|
44
|
+
assert Throttle.throttled?(envs[0])
|
45
|
+
assert Throttle.throttled?(envs[2])
|
46
|
+
deny Throttle.throttled?(envs[1]), "This environment is not throttled"
|
47
|
+
end
|
48
|
+
|
49
|
+
def teardown
|
50
|
+
Throttle.delete_all
|
51
|
+
super
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_throttle_autoexpiry_on_check
|
55
|
+
Throttle.set!(HEADERS)
|
56
|
+
assert_equal 1, Throttle.count
|
57
|
+
flexmock(Throttle).should_receive(:cutoff).at_least.once.and_return(Time.now + 10)
|
58
|
+
|
59
|
+
deny Throttle.throttled?(HEADERS)
|
60
|
+
assert_equal 0, Throttle.count
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def assert_time_matches(ref, actual)
|
65
|
+
assert_kind_of Time, ref, "The reference value should be Time"
|
66
|
+
assert_kind_of Time, actual, "The actual value should be Time"
|
67
|
+
assert_in_delta(ref.to_i, actual.to_i, 2,
|
68
|
+
"The times passed should be within 2s")
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# Implements OpenID::Fetcher. Will run the request through the mosquito test case instead of calling
|
2
|
+
# out via HTTP
|
3
|
+
class TestableOpenidFetcher
|
4
|
+
# Will be raised when the fetcher tries to get a URL which is
|
5
|
+
# not within the application being tested
|
6
|
+
class ExternalResource < RuntimeError; end
|
7
|
+
|
8
|
+
# We need a separate Mosquito tester class for things that will
|
9
|
+
# happen via POST, because this is a different flow -
|
10
|
+
# the requests of the server instead of the browser.
|
11
|
+
# If you post directly from the same test case you are wiring yourself into the
|
12
|
+
# session ID that has been gotten by the simulated browser, that's why we use that.
|
13
|
+
class OpenidPoster < Pasaporte::WebTest
|
14
|
+
attr_reader :request, :response
|
15
|
+
def test_foo; assert true; end
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(test_case)
|
19
|
+
@browser_getter = test_case
|
20
|
+
@browser_getter.request.headers['HTTP_HOST'] = 'test.host'
|
21
|
+
@server_poster = OpenidPoster.new("test_foo")
|
22
|
+
@server_poster.setup # manually yes
|
23
|
+
end
|
24
|
+
|
25
|
+
# This is used by OpenID lib 2
|
26
|
+
def fetch(url, body=nil, headers=nil, redirect_limit=10)
|
27
|
+
url, url_stringified = URI::parse(url), url.dup
|
28
|
+
|
29
|
+
h = headers || {}
|
30
|
+
|
31
|
+
raise_on_external url, @browser_getter
|
32
|
+
|
33
|
+
camping_controller_with_response = (body.blank? ? get(url.request_uri, h) : post(url.request_uri, h, body))
|
34
|
+
::OpenID::HTTPResponse._from_net_response(FakeResponse.new(camping_controller_with_response), url_stringified)
|
35
|
+
end
|
36
|
+
|
37
|
+
# An adapter to make a Mosquito response (Camping controller) behave like Net::HTTPResponse
|
38
|
+
class FakeResponse < ::Net::HTTPResponse
|
39
|
+
def initialize(mosquito_response)
|
40
|
+
@the = mosquito_response
|
41
|
+
super('1.0', @the.status.to_s, 'Found') # http version, resp code and message
|
42
|
+
flat_headers = @the.headers.inject({}) { |n, k| n.merge k[0] => k[1].to_s } rescue {}
|
43
|
+
initialize_http_header(flat_headers)
|
44
|
+
end
|
45
|
+
|
46
|
+
def body
|
47
|
+
@the.body
|
48
|
+
end
|
49
|
+
|
50
|
+
def code
|
51
|
+
@the.status.to_s
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def get(uri, headers = {})
|
57
|
+
Pasaporte::LOGGER.debug "OpenID requested GET on #{uri}"
|
58
|
+
@browser_getter.get relativized(uri) # this fails somehow
|
59
|
+
@browser_getter.response
|
60
|
+
end
|
61
|
+
|
62
|
+
def post(uri, headers = {}, body = '')
|
63
|
+
Pasaporte::LOGGER.debug "OpenID requested POST on #{uri}"
|
64
|
+
@server_poster.post relativized(uri), body
|
65
|
+
@server_poster.response
|
66
|
+
end
|
67
|
+
|
68
|
+
def relativized(uri)
|
69
|
+
# Here we need to replace the mount point URL otherwise
|
70
|
+
# OpenID gets confused and actually posts into it
|
71
|
+
# - Mosquito does not like that
|
72
|
+
u = URI.parse(uri)
|
73
|
+
u.path.gsub(/^\/pasaporte/, '')
|
74
|
+
end
|
75
|
+
|
76
|
+
# Check if we are calling to the outside world
|
77
|
+
def raise_on_external(uri, testcase)
|
78
|
+
unless ((uri.host == testcase.request.http_host) || uri.host.blank?)
|
79
|
+
raise ExternalResource, "Called out to external resource: OpenID consumer wants to have #{uri}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
metadata
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pasaporte
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Julik Tarkhanov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-11-03 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activerecord
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: camping
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: ruby-openid
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 2.1.0
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: flexmock
|
47
|
+
type: :runtime
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: hoe
|
57
|
+
type: :development
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 1.8.2
|
64
|
+
version:
|
65
|
+
description: An OpenID server with a colored bar on top
|
66
|
+
email: me@julik.nl
|
67
|
+
executables:
|
68
|
+
- pasaporte-fcgi.rb
|
69
|
+
extensions: []
|
70
|
+
|
71
|
+
extra_rdoc_files:
|
72
|
+
- History.txt
|
73
|
+
- Manifest.txt
|
74
|
+
- README.txt
|
75
|
+
- TODO.txt
|
76
|
+
files:
|
77
|
+
- History.txt
|
78
|
+
- Manifest.txt
|
79
|
+
- README.txt
|
80
|
+
- Rakefile
|
81
|
+
- TODO.txt
|
82
|
+
- bin/pasaporte-fcgi.rb
|
83
|
+
- lib/pasaporte.rb
|
84
|
+
- lib/pasaporte/.DS_Store
|
85
|
+
- lib/pasaporte/assets/.DS_Store
|
86
|
+
- lib/pasaporte/assets/bgbar.png
|
87
|
+
- lib/pasaporte/assets/lock.png
|
88
|
+
- lib/pasaporte/assets/mainbg_green.gif
|
89
|
+
- lib/pasaporte/assets/mainbg_red.gif
|
90
|
+
- lib/pasaporte/assets/openid.png
|
91
|
+
- lib/pasaporte/assets/pasaporte.css
|
92
|
+
- lib/pasaporte/assets/pasaporte.js
|
93
|
+
- lib/pasaporte/assets/user.png
|
94
|
+
- lib/pasaporte/auth/cascade.rb
|
95
|
+
- lib/pasaporte/auth/remote_web_workplace.rb
|
96
|
+
- lib/pasaporte/auth/yaml_digest_table.rb
|
97
|
+
- lib/pasaporte/auth/yaml_table.rb
|
98
|
+
- lib/pasaporte/faster_openid.rb
|
99
|
+
- lib/pasaporte/iso_countries.yml
|
100
|
+
- lib/pasaporte/julik_state.rb
|
101
|
+
- lib/pasaporte/markaby_ext.rb
|
102
|
+
- lib/pasaporte/pasaporte_store.rb
|
103
|
+
- lib/pasaporte/timezones.yml
|
104
|
+
- test/fixtures/pasaporte_approvals.yml
|
105
|
+
- test/fixtures/pasaporte_profiles.yml
|
106
|
+
- test/fixtures/pasaporte_throttles.yml
|
107
|
+
- test/helper.rb
|
108
|
+
- test/mosquito.rb
|
109
|
+
- test/test_throttle.rb
|
110
|
+
- test/testable_openid_fetcher.rb
|
111
|
+
- test/test_approval.rb
|
112
|
+
- test/test_auth_backends.rb
|
113
|
+
- test/test_openid.rb
|
114
|
+
- test/test_pasaporte.rb
|
115
|
+
- test/test_profile.rb
|
116
|
+
- test/test_settings.rb
|
117
|
+
has_rdoc: true
|
118
|
+
homepage: http://pasaporte.rubyforge.org
|
119
|
+
post_install_message:
|
120
|
+
rdoc_options:
|
121
|
+
- --main
|
122
|
+
- README.txt
|
123
|
+
require_paths:
|
124
|
+
- lib
|
125
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ">="
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: "0"
|
130
|
+
version:
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - ">="
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: "0"
|
136
|
+
version:
|
137
|
+
requirements: []
|
138
|
+
|
139
|
+
rubyforge_project: pasaporte
|
140
|
+
rubygems_version: 1.2.0
|
141
|
+
signing_key:
|
142
|
+
specification_version: 2
|
143
|
+
summary: Downgrades the OpenID providing business to the usual login-password stupidity.
|
144
|
+
test_files:
|
145
|
+
- test/test_approval.rb
|
146
|
+
- test/test_auth_backends.rb
|
147
|
+
- test/test_openid.rb
|
148
|
+
- test/test_pasaporte.rb
|
149
|
+
- test/test_profile.rb
|
150
|
+
- test/test_settings.rb
|
151
|
+
- test/test_throttle.rb
|