openid-store-sequel 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.travis.yml +14 -0
- data/Gemfile +3 -0
- data/Makefile +26 -0
- data/README.md +42 -0
- data/Rakefile +11 -0
- data/cat-attack.gif +0 -0
- data/lib/openid/store/sequel/association.rb +11 -0
- data/lib/openid/store/sequel/nonce.rb +8 -0
- data/lib/openid/store/sequel/version.rb +7 -0
- data/lib/openid/store/sequel.rb +77 -0
- data/openid-store-sequel.gemspec +24 -0
- data/test/helper.rb +20 -0
- data/test/openid/store/sequel_test.rb +219 -0
- metadata +141 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
before_script:
|
2
|
+
- psql -c 'create database openid_store_sequel_test;' -U postgres
|
3
|
+
|
4
|
+
env: DATABASE_URL=postgres://postgres:@localhost/openid_store_sequel_test
|
5
|
+
|
6
|
+
language: ruby
|
7
|
+
|
8
|
+
rvm:
|
9
|
+
- 1.9.2
|
10
|
+
- 1.9.3
|
11
|
+
- jruby-19mode
|
12
|
+
- rbx-19mode
|
13
|
+
|
14
|
+
script: bundle exec rake test --trace
|
data/Gemfile
ADDED
data/Makefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
VERSION=$(shell ruby -r./lib/openid/store/sequel/version -e "puts OpenID::Store::Sequel::VERSION")
|
2
|
+
|
3
|
+
# default the projcet name to the directory name
|
4
|
+
PROJECT?=$(notdir $(PWD))
|
5
|
+
GEM=$(PROJECT)-$(VERSION).gem
|
6
|
+
|
7
|
+
.PHONY: test
|
8
|
+
test:
|
9
|
+
bundle exec rake test
|
10
|
+
|
11
|
+
.PHONY: package
|
12
|
+
package: $(GEM)
|
13
|
+
|
14
|
+
# Always build the gem
|
15
|
+
.PHONY: $(GEM)
|
16
|
+
$(GEM):
|
17
|
+
gem build $(PROJECT).gemspec
|
18
|
+
|
19
|
+
.PHONY: install
|
20
|
+
install: $(GEM)
|
21
|
+
gem install $<
|
22
|
+
|
23
|
+
# Publish to gemgate
|
24
|
+
.PHONY: publish
|
25
|
+
publish: $(GEM)
|
26
|
+
gem push $(GEM)
|
data/README.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# OpenID Store Sequel
|
2
|
+
|
3
|
+
![](https://github.com/dylanegan/openid-store-sequel/raw/master/cat-attack.gif)
|
4
|
+
|
5
|
+
Storing your OpenIDs in your Sequels.
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
require 'openid/store/sequel'
|
11
|
+
|
12
|
+
DB = Sequel.connect(ENV['DATABASE_URL'] || "postgres://localhost/openid_store_sequel")
|
13
|
+
|
14
|
+
DB.create_table! :open_id_associations do
|
15
|
+
primary_key :id
|
16
|
+
File :server_url, :null => false
|
17
|
+
String :handle, :null => false
|
18
|
+
File :secret, :null => false
|
19
|
+
Integer :issued, :null => false
|
20
|
+
Integer :lifetime, :null => false
|
21
|
+
String :assoc_type, :null => false
|
22
|
+
end
|
23
|
+
|
24
|
+
DB.create_table! :open_id_nonces do
|
25
|
+
primary_key :id
|
26
|
+
String :server_url, :null => false
|
27
|
+
DateTime :timestamp, :null => false
|
28
|
+
String :salt, :null => false
|
29
|
+
end
|
30
|
+
|
31
|
+
server = OpenID::Server::Server.new(OpenID::Store::Sequel.new, ...)
|
32
|
+
```
|
33
|
+
|
34
|
+
## License (MIT)
|
35
|
+
|
36
|
+
Copyright © 2012 [Merman](http://dylanegan.com/)
|
37
|
+
|
38
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
39
|
+
|
40
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
41
|
+
|
42
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
data/cat-attack.gif
ADDED
Binary file
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require "base64"
|
2
|
+
require "sequel"
|
3
|
+
|
4
|
+
require 'openid/util'
|
5
|
+
require 'openid/store/nonce'
|
6
|
+
require 'openid/association'
|
7
|
+
|
8
|
+
module OpenID
|
9
|
+
module Store
|
10
|
+
class Sequel
|
11
|
+
autoload :Association, "openid/store/sequel/association"
|
12
|
+
autoload :Nonce, "openid/store/sequel/nonce"
|
13
|
+
|
14
|
+
def store_association(server_url, assoc)
|
15
|
+
remove_association(server_url, assoc.handle)
|
16
|
+
OpenID::Store::Sequel::Association.create(
|
17
|
+
server_url: server_url,
|
18
|
+
handle: assoc.handle,
|
19
|
+
secret: Base64.encode64(assoc.secret),
|
20
|
+
issued: assoc.issued,
|
21
|
+
lifetime: assoc.lifetime,
|
22
|
+
assoc_type: assoc.assoc_type
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_association(server_url, handle=nil)
|
27
|
+
assocs = if handle.nil? || handle.empty?
|
28
|
+
OpenID::Store::Sequel::Association.where(server_url: server_url)
|
29
|
+
else
|
30
|
+
OpenID::Store::Sequel::Association.where(server_url: server_url, handle: handle)
|
31
|
+
end
|
32
|
+
|
33
|
+
assocs.to_a.reverse.each do |assoc|
|
34
|
+
a = assoc.from_record
|
35
|
+
if a.expires_in == 0
|
36
|
+
assoc.destroy
|
37
|
+
else
|
38
|
+
return a
|
39
|
+
end
|
40
|
+
end if assocs.any?
|
41
|
+
|
42
|
+
return nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def remove_association(server_url, handle)
|
46
|
+
OpenID::Store::Sequel::Association.dataset.filter(server_url: server_url, handle: handle).delete > 0 ? true : false
|
47
|
+
end
|
48
|
+
|
49
|
+
def use_nonce(server_url, timestamp, salt)
|
50
|
+
return false if OpenID::Store::Sequel::Nonce.first(server_url: server_url, timestamp: Time.at(timestamp), salt: salt) || (timestamp - Time.now.to_i).abs > OpenID::Nonce.skew
|
51
|
+
OpenID::Store::Sequel::Nonce.create(server_url: server_url, timestamp: Time.at(timestamp), salt: salt)
|
52
|
+
return true
|
53
|
+
end
|
54
|
+
|
55
|
+
def cleanup_nonces
|
56
|
+
now = Time.now.to_i
|
57
|
+
count = 0
|
58
|
+
OpenID::Store::Sequel::Nonce.where("timestamp > '#{Time.at(now + OpenID::Nonce.skew)}' OR timestamp < '#{Time.at(now - OpenID::Nonce.skew)}'").each do |nonce|
|
59
|
+
nonce.destroy
|
60
|
+
count += 1
|
61
|
+
end
|
62
|
+
count
|
63
|
+
end
|
64
|
+
|
65
|
+
def cleanup_associations
|
66
|
+
count = 0
|
67
|
+
OpenID::Store::Sequel::Association.where('issued > 0').each do |association|
|
68
|
+
if association.lifetime + association.issued > Time.now.to_i
|
69
|
+
association.destroy
|
70
|
+
count += 1
|
71
|
+
end
|
72
|
+
end
|
73
|
+
count
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/openid/store/sequel/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Dylan Egan"]
|
6
|
+
gem.email = ["dylanegan@gmail.com"]
|
7
|
+
gem.description = %q{Storing your OpenIDs in your Sequels.}
|
8
|
+
gem.summary = %q{Storing OpenIDs in Sequels.}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
12
|
+
gem.files = `git ls-files`.split("\n")
|
13
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
|
+
gem.name = "openid-store-sequel"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = OpenID::Store::Sequel::VERSION
|
17
|
+
|
18
|
+
gem.add_runtime_dependency "ruby-openid"
|
19
|
+
gem.add_runtime_dependency "sequel"
|
20
|
+
|
21
|
+
gem.add_development_dependency "pg"
|
22
|
+
gem.add_development_dependency "rake"
|
23
|
+
gem.add_development_dependency "sqlite3"
|
24
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'openid/store/sequel'
|
3
|
+
|
4
|
+
DB = Sequel.connect(ENV['DATABASE_URL'] || "postgres://localhost/openid_store_sequel_test")
|
5
|
+
DB.create_table! :open_id_associations do
|
6
|
+
primary_key :id
|
7
|
+
File :server_url, :null => false
|
8
|
+
String :handle, :null => false
|
9
|
+
File :secret, :null => false
|
10
|
+
Integer :issued, :null => false
|
11
|
+
Integer :lifetime, :null => false
|
12
|
+
String :assoc_type, :null => false
|
13
|
+
end
|
14
|
+
|
15
|
+
DB.create_table! :open_id_nonces do
|
16
|
+
primary_key :id
|
17
|
+
String :server_url, :null => false
|
18
|
+
DateTime :timestamp, :null => false
|
19
|
+
String :salt, :null => false
|
20
|
+
end
|
@@ -0,0 +1,219 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
module OpenID
|
4
|
+
module Store
|
5
|
+
module StoreTestCase
|
6
|
+
@@allowed_handle = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
|
7
|
+
@@allowed_nonce = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
8
|
+
|
9
|
+
def _gen_nonce
|
10
|
+
OpenID::CryptUtil.random_string(8, @@allowed_nonce)
|
11
|
+
end
|
12
|
+
|
13
|
+
def _gen_handle(n)
|
14
|
+
OpenID::CryptUtil.random_string(n, @@allowed_handle)
|
15
|
+
end
|
16
|
+
|
17
|
+
def _gen_secret(n, chars=nil)
|
18
|
+
OpenID::CryptUtil.random_string(n, chars)
|
19
|
+
end
|
20
|
+
|
21
|
+
def _gen_assoc(issued, lifetime=600)
|
22
|
+
secret = _gen_secret(20)
|
23
|
+
handle = _gen_handle(128)
|
24
|
+
OpenID::Association.new(handle, secret, Time.now + issued, lifetime,
|
25
|
+
'HMAC-SHA1')
|
26
|
+
end
|
27
|
+
|
28
|
+
def _check_retrieve(url, handle=nil, expected=nil)
|
29
|
+
ret_assoc = @store.get_association(url, handle)
|
30
|
+
|
31
|
+
if expected.nil?
|
32
|
+
assert_nil(ret_assoc)
|
33
|
+
else
|
34
|
+
assert_equal(expected, ret_assoc)
|
35
|
+
assert_equal(expected.handle, ret_assoc.handle)
|
36
|
+
assert_equal(expected.secret, ret_assoc.secret)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def _check_remove(url, handle, expected)
|
41
|
+
present = @store.remove_association(url, handle)
|
42
|
+
assert_equal(expected, present)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_store
|
46
|
+
assoc = _gen_assoc(issued=0)
|
47
|
+
|
48
|
+
# Make sure that a missing association returns no result
|
49
|
+
_check_retrieve(server_url)
|
50
|
+
|
51
|
+
# Check that after storage, getting returns the same result
|
52
|
+
@store.store_association(server_url, assoc)
|
53
|
+
_check_retrieve(server_url, nil, assoc)
|
54
|
+
|
55
|
+
# more than once
|
56
|
+
_check_retrieve(server_url, nil, assoc)
|
57
|
+
|
58
|
+
# Storing more than once has no ill effect
|
59
|
+
@store.store_association(server_url, assoc)
|
60
|
+
_check_retrieve(server_url, nil, assoc)
|
61
|
+
|
62
|
+
# Removing an association that does not exist returns not present
|
63
|
+
_check_remove(server_url, assoc.handle + 'x', false)
|
64
|
+
|
65
|
+
# Removing an association that does not exist returns not present
|
66
|
+
_check_remove(server_url + 'x', assoc.handle, false)
|
67
|
+
|
68
|
+
# Removing an association that is present returns present
|
69
|
+
_check_remove(server_url, assoc.handle, true)
|
70
|
+
|
71
|
+
# but not present on subsequent calls
|
72
|
+
_check_remove(server_url, assoc.handle, false)
|
73
|
+
|
74
|
+
# Put assoc back in the store
|
75
|
+
@store.store_association(server_url, assoc)
|
76
|
+
|
77
|
+
# More recent and expires after assoc
|
78
|
+
assoc2 = _gen_assoc(issued=1)
|
79
|
+
@store.store_association(server_url, assoc2)
|
80
|
+
|
81
|
+
# After storing an association with a different handle, but the
|
82
|
+
# same server_url, the handle with the later expiration is returned.
|
83
|
+
_check_retrieve(server_url, nil, assoc2)
|
84
|
+
|
85
|
+
# We can still retrieve the older association
|
86
|
+
_check_retrieve(server_url, assoc.handle, assoc)
|
87
|
+
|
88
|
+
# Plus we can retrieve the association with the later expiration
|
89
|
+
# explicitly
|
90
|
+
_check_retrieve(server_url, assoc2.handle, assoc2)
|
91
|
+
|
92
|
+
# More recent, and expires earlier than assoc2 or assoc. Make sure
|
93
|
+
# that we're picking the one with the latest issued date and not
|
94
|
+
# taking into account the expiration.
|
95
|
+
assoc3 = _gen_assoc(issued=2, lifetime=100)
|
96
|
+
@store.store_association(server_url, assoc3)
|
97
|
+
|
98
|
+
_check_retrieve(server_url, nil, assoc3)
|
99
|
+
_check_retrieve(server_url, assoc.handle, assoc)
|
100
|
+
_check_retrieve(server_url, assoc2.handle, assoc2)
|
101
|
+
_check_retrieve(server_url, assoc3.handle, assoc3)
|
102
|
+
|
103
|
+
_check_remove(server_url, assoc2.handle, true)
|
104
|
+
|
105
|
+
_check_retrieve(server_url, nil, assoc3)
|
106
|
+
_check_retrieve(server_url, assoc.handle, assoc)
|
107
|
+
_check_retrieve(server_url, assoc2.handle, nil)
|
108
|
+
_check_retrieve(server_url, assoc3.handle, assoc3)
|
109
|
+
|
110
|
+
_check_remove(server_url, assoc2.handle, false)
|
111
|
+
_check_remove(server_url, assoc3.handle, true)
|
112
|
+
|
113
|
+
ret_assoc = @store.get_association(server_url, nil)
|
114
|
+
unexpected = [assoc2.handle, assoc3.handle]
|
115
|
+
assert(ret_assoc.nil? || !unexpected.member?(ret_assoc.handle),
|
116
|
+
"correct association")
|
117
|
+
|
118
|
+
_check_retrieve(server_url, assoc.handle, assoc)
|
119
|
+
_check_retrieve(server_url, assoc2.handle, nil)
|
120
|
+
_check_retrieve(server_url, assoc3.handle, nil)
|
121
|
+
|
122
|
+
_check_remove(server_url, assoc2.handle, false)
|
123
|
+
_check_remove(server_url, assoc.handle, true)
|
124
|
+
_check_remove(server_url, assoc3.handle, false)
|
125
|
+
|
126
|
+
_check_retrieve(server_url, nil, nil)
|
127
|
+
_check_retrieve(server_url, assoc.handle, nil)
|
128
|
+
_check_retrieve(server_url, assoc2.handle, nil)
|
129
|
+
_check_retrieve(server_url, assoc3.handle, nil)
|
130
|
+
|
131
|
+
_check_remove(server_url, assoc2.handle, false)
|
132
|
+
_check_remove(server_url, assoc.handle, false)
|
133
|
+
_check_remove(server_url, assoc3.handle, false)
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_assoc_cleanup
|
137
|
+
assocValid1 = _gen_assoc(-3600, 7200)
|
138
|
+
assocValid2 = _gen_assoc(-5)
|
139
|
+
assocExpired1 = _gen_assoc(-7200, 3600)
|
140
|
+
assocExpired2 = _gen_assoc(-7200, 3600)
|
141
|
+
|
142
|
+
@store.cleanup_associations
|
143
|
+
@store.store_association(server_url + '1', assocValid1)
|
144
|
+
@store.store_association(server_url + '1', assocExpired1)
|
145
|
+
@store.store_association(server_url + '2', assocExpired2)
|
146
|
+
@store.store_association(server_url + '3', assocValid2)
|
147
|
+
|
148
|
+
cleaned = @store.cleanup_associations()
|
149
|
+
assert_equal(2, cleaned, "cleaned up associations")
|
150
|
+
end
|
151
|
+
|
152
|
+
def _check_use_nonce(nonce, expected, server_url, msg='')
|
153
|
+
stamp, salt = Nonce::split_nonce(nonce)
|
154
|
+
actual = @store.use_nonce(server_url, stamp, salt)
|
155
|
+
assert_equal(expected, actual, msg)
|
156
|
+
end
|
157
|
+
|
158
|
+
def server_url
|
159
|
+
"http://www.myopenid.com/openid"
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_nonce
|
163
|
+
[server_url, ''].each{|url|
|
164
|
+
nonce1 = Nonce::mk_nonce
|
165
|
+
|
166
|
+
_check_use_nonce(nonce1, true, url, "#{url}: nonce allowed by default")
|
167
|
+
_check_use_nonce(nonce1, false, url, "#{url}: nonce not allowed twice")
|
168
|
+
_check_use_nonce(nonce1, false, url, "#{url}: nonce not allowed third time")
|
169
|
+
|
170
|
+
# old nonces shouldn't pass
|
171
|
+
old_nonce = Nonce::mk_nonce(3600)
|
172
|
+
_check_use_nonce(old_nonce, false, url, "Old nonce #{old_nonce.inspect} passed")
|
173
|
+
|
174
|
+
}
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_nonce_cleanup
|
178
|
+
now = Time.now.to_i
|
179
|
+
old_nonce1 = Nonce::mk_nonce(now - 20000)
|
180
|
+
old_nonce2 = Nonce::mk_nonce(now - 10000)
|
181
|
+
recent_nonce = Nonce::mk_nonce(now - 600)
|
182
|
+
|
183
|
+
orig_skew = Nonce.skew
|
184
|
+
Nonce.skew = 0
|
185
|
+
count = @store.cleanup_nonces
|
186
|
+
Nonce.skew = 1000000
|
187
|
+
ts, salt = Nonce::split_nonce(old_nonce1)
|
188
|
+
assert(@store.use_nonce(server_url, ts, salt), "oldnonce1")
|
189
|
+
ts, salt = Nonce::split_nonce(old_nonce2)
|
190
|
+
assert(@store.use_nonce(server_url, ts, salt), "oldnonce2")
|
191
|
+
ts, salt = Nonce::split_nonce(recent_nonce)
|
192
|
+
assert(@store.use_nonce(server_url, ts, salt), "recent_nonce")
|
193
|
+
|
194
|
+
Nonce.skew = 1000
|
195
|
+
cleaned = @store.cleanup_nonces
|
196
|
+
assert_equal(2, cleaned, "Cleaned #{cleaned} nonces")
|
197
|
+
|
198
|
+
Nonce.skew = 100000
|
199
|
+
ts, salt = Nonce::split_nonce(old_nonce1)
|
200
|
+
assert(@store.use_nonce(server_url, ts, salt), "oldnonce1 after cleanup")
|
201
|
+
ts, salt = Nonce::split_nonce(old_nonce2)
|
202
|
+
assert(@store.use_nonce(server_url, ts, salt), "oldnonce2 after cleanup")
|
203
|
+
ts, salt = Nonce::split_nonce(recent_nonce)
|
204
|
+
assert(!@store.use_nonce(server_url, ts, salt), "recent_nonce after cleanup")
|
205
|
+
|
206
|
+
Nonce.skew = orig_skew
|
207
|
+
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
class SequelStoreTestCase < Test::Unit::TestCase
|
212
|
+
include StoreTestCase
|
213
|
+
|
214
|
+
def setup
|
215
|
+
@store = OpenID::Store::Sequel.new
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
metadata
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: openid-store-sequel
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Dylan Egan
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: ruby-openid
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: sequel
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: pg
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: sqlite3
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
description: Storing your OpenIDs in your Sequels.
|
95
|
+
email:
|
96
|
+
- dylanegan@gmail.com
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- .gitignore
|
102
|
+
- .travis.yml
|
103
|
+
- Gemfile
|
104
|
+
- Makefile
|
105
|
+
- README.md
|
106
|
+
- Rakefile
|
107
|
+
- cat-attack.gif
|
108
|
+
- lib/openid/store/sequel.rb
|
109
|
+
- lib/openid/store/sequel/association.rb
|
110
|
+
- lib/openid/store/sequel/nonce.rb
|
111
|
+
- lib/openid/store/sequel/version.rb
|
112
|
+
- openid-store-sequel.gemspec
|
113
|
+
- test/helper.rb
|
114
|
+
- test/openid/store/sequel_test.rb
|
115
|
+
homepage: ''
|
116
|
+
licenses: []
|
117
|
+
post_install_message:
|
118
|
+
rdoc_options: []
|
119
|
+
require_paths:
|
120
|
+
- lib
|
121
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
123
|
+
requirements:
|
124
|
+
- - ! '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
|
+
none: false
|
129
|
+
requirements:
|
130
|
+
- - ! '>='
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
requirements: []
|
134
|
+
rubyforge_project:
|
135
|
+
rubygems_version: 1.8.21
|
136
|
+
signing_key:
|
137
|
+
specification_version: 3
|
138
|
+
summary: Storing OpenIDs in Sequels.
|
139
|
+
test_files:
|
140
|
+
- test/helper.rb
|
141
|
+
- test/openid/store/sequel_test.rb
|