matthewtodd-openid-store-couchdb-chef 0.1.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/README.rdoc +5 -0
- data/Rakefile +20 -0
- data/lib/openid-store-couchdb.rb +1 -0
- data/lib/openid/store/couchdb.rb +90 -0
- data/lib/openid/store/couchdb/association.rb +94 -0
- data/lib/openid/store/couchdb/nonce.rb +75 -0
- metadata +95 -0
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
this_rakefile_uses_shoe = <<END
|
2
|
+
----------------------------------------
|
3
|
+
Please install Shoe:
|
4
|
+
gem sources --add http://gems.github.com
|
5
|
+
gem install matthewtodd-shoe
|
6
|
+
----------------------------------------
|
7
|
+
END
|
8
|
+
|
9
|
+
begin
|
10
|
+
gem 'matthewtodd-shoe'
|
11
|
+
rescue Gem::LoadError
|
12
|
+
abort this_rakefile_uses_shoe
|
13
|
+
else
|
14
|
+
require 'shoe'
|
15
|
+
end
|
16
|
+
|
17
|
+
Shoe.tie('openid-store-couchdb-chef', '0.1.0', 'A Chef-specific OpenID store for CouchDB.') do |spec|
|
18
|
+
spec.add_dependency 'ruby-openid'
|
19
|
+
spec.add_dependency 'chef'
|
20
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'openid/store/couchdb'
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'openid'
|
2
|
+
require 'openid/store/interface'
|
3
|
+
require 'openid/store/couchdb/association'
|
4
|
+
require 'openid/store/couchdb/nonce'
|
5
|
+
|
6
|
+
module OpenID #:nodoc:
|
7
|
+
module Store #:nodoc:
|
8
|
+
|
9
|
+
# From what I can tell, the original
|
10
|
+
# openid-store-couchdb[http://github.com/b/openid-store-couchdb] isn't
|
11
|
+
# entirely complete, and there seems to be no word on the
|
12
|
+
# progress[http://tickets.opscode.com/browse/CHEF-199] of integrating it
|
13
|
+
# into Chef proper. Also, it makes use of CouchDB features I don't yet
|
14
|
+
# support in hideabed[http://github.com/matthewtodd/hideabed].
|
15
|
+
#
|
16
|
+
# Also note that OpenID is largely going
|
17
|
+
# away[http://lists.opscode.com/sympa/arc/chef-dev/2009-06/msg00001.html]
|
18
|
+
# in Chef 0.8, so we really just need a stopgap measure.
|
19
|
+
class CouchDB < Interface
|
20
|
+
def initialize(*args)
|
21
|
+
Association.create_design_document
|
22
|
+
Nonce.create_design_document
|
23
|
+
end
|
24
|
+
|
25
|
+
# Put a Association object into storage. When implementing a store,
|
26
|
+
# don't assume that there are any limitations on the character set of
|
27
|
+
# the server_url. In particular, expect to see unescaped non-url-safe
|
28
|
+
# characters in the server_url field.
|
29
|
+
def store_association(server_url, association)
|
30
|
+
if document = Association.load(server_url, association.handle)
|
31
|
+
document.association = association
|
32
|
+
document.save
|
33
|
+
else
|
34
|
+
Association.create(server_url, association)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns a Association object from storage that matches the server_url.
|
39
|
+
# Returns nil if no such association is found or if the one matching
|
40
|
+
# association is expired. (Is allowed to GC expired associations when
|
41
|
+
# found.)
|
42
|
+
def get_association(server_url, handle=nil)
|
43
|
+
if document = Association.load(server_url, handle)
|
44
|
+
if document.expired?
|
45
|
+
document.destroy
|
46
|
+
nil
|
47
|
+
else
|
48
|
+
document.association
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# If there is a matching association, remove it from the store and
|
54
|
+
# return true, otherwise return false.
|
55
|
+
def remove_association(server_url, handle)
|
56
|
+
Association.destroy(server_url, handle)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Remove expired associations from the store. Not called during normal
|
60
|
+
# library operation, this method is for store admins to keep their
|
61
|
+
# storage from filling up with expired data.
|
62
|
+
def cleanup_associations
|
63
|
+
raise NotImplementedError
|
64
|
+
end
|
65
|
+
|
66
|
+
# Return true if the nonce has not been used before, and store it for a
|
67
|
+
# while to make sure someone doesn't try to use the same value again.
|
68
|
+
# Return false if the nonce has already been used or if the timestamp is
|
69
|
+
# not current. You can use OpenID::Store::Nonce::SKEW for your timestamp
|
70
|
+
# window.
|
71
|
+
#
|
72
|
+
# +server_url+:: URL of the server from which the nonce originated
|
73
|
+
# +timestamp+:: time the nonce was created in seconds since unix epoch
|
74
|
+
# +salt+:: A random string that makes two nonces issued by a server in
|
75
|
+
# the same second unique
|
76
|
+
def use_nonce(server_url, timestamp, salt)
|
77
|
+
Nonce.create(server_url, timestamp, salt)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Remove expired nonces from the store. Discards any nonce that is old
|
81
|
+
# enough that it wouldn't pass use_nonce Not called during normal
|
82
|
+
# library operation, this method is for store admins to keep their
|
83
|
+
# storage from filling up with expired data.
|
84
|
+
def cleanup_nonces
|
85
|
+
raise NotImplementedError
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module OpenID #:nodoc:
|
2
|
+
module Store #:nodoc:
|
3
|
+
class CouchDB < Interface
|
4
|
+
|
5
|
+
class Association
|
6
|
+
DESIGN_DOCUMENT = {
|
7
|
+
'version' => 1,
|
8
|
+
'language' => 'javascript',
|
9
|
+
'views' => {}
|
10
|
+
}
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def create_design_document
|
14
|
+
Chef::CouchDB.new.create_design_document('associations', DESIGN_DOCUMENT)
|
15
|
+
end
|
16
|
+
|
17
|
+
def create(server_url, association)
|
18
|
+
new(document_name(server_url, association.handle), association).save
|
19
|
+
end
|
20
|
+
|
21
|
+
def load(server_url, handle)
|
22
|
+
Chef::CouchDB.new.load('association', document_name(server_url, handle))
|
23
|
+
rescue Net::HTTPServerException
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def destroy(server_url, handle)
|
28
|
+
document = load(server_url, handle)
|
29
|
+
document ? document.destroy : false
|
30
|
+
end
|
31
|
+
|
32
|
+
def document_name(server_url, handle)
|
33
|
+
Base64.encode64("#{server_url}-#{handle}").chomp
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
attr_accessor :association
|
38
|
+
|
39
|
+
def initialize(name, association, couchdb_rev = nil)
|
40
|
+
@name = name
|
41
|
+
@association = association
|
42
|
+
@couchdb_rev = couchdb_rev
|
43
|
+
@couchdb = Chef::CouchDB.new
|
44
|
+
end
|
45
|
+
|
46
|
+
def destroy
|
47
|
+
@couchdb.delete('association', @name, @couchdb_rev)
|
48
|
+
rescue Net::HTTPServerException
|
49
|
+
false
|
50
|
+
else
|
51
|
+
true
|
52
|
+
end
|
53
|
+
|
54
|
+
def expired?
|
55
|
+
@association.expires_in <= 0
|
56
|
+
end
|
57
|
+
|
58
|
+
def save
|
59
|
+
results = @couchdb.store('association', @name, self)
|
60
|
+
@couchdb_rev = results['rev']
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.json_create(attributes)
|
64
|
+
name = attributes['name']
|
65
|
+
handle = attributes['handle']
|
66
|
+
secret = Base64.decode64(attributes['secret'])
|
67
|
+
issued = Time.at(attributes['issued'])
|
68
|
+
lifetime = attributes['lifetime']
|
69
|
+
assoc_type = attributes['assoc_type']
|
70
|
+
couchdb_rev = attributes['_rev']
|
71
|
+
association = OpenID::Association.new(handle, secret, issued, lifetime, assoc_type)
|
72
|
+
|
73
|
+
new(name, association, couchdb_rev)
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_json(*args)
|
77
|
+
result = {
|
78
|
+
'name' => @name,
|
79
|
+
'json_class' => self.class.name,
|
80
|
+
'chef_type' => 'association',
|
81
|
+
'handle' => @association.handle,
|
82
|
+
'secret' => Base64.encode64(@association.secret).chomp,
|
83
|
+
'issued' => @association.issued.to_i,
|
84
|
+
'lifetime' => @association.lifetime,
|
85
|
+
'assoc_type' => @association.assoc_type,
|
86
|
+
}
|
87
|
+
result['_rev'] = @couchdb_rev if @couchdb_rev
|
88
|
+
result.to_json(*args)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module OpenID #:nodoc:
|
2
|
+
module Store #:nodoc:
|
3
|
+
class CouchDB < Interface
|
4
|
+
|
5
|
+
class Nonce
|
6
|
+
DESIGN_DOCUMENT = {
|
7
|
+
'version' => 1,
|
8
|
+
'language' => 'javascript',
|
9
|
+
'views' => {}
|
10
|
+
}
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def create_design_document
|
14
|
+
Chef::CouchDB.new.create_design_document('nonces', DESIGN_DOCUMENT)
|
15
|
+
end
|
16
|
+
|
17
|
+
def create(server_url, timestamp, salt)
|
18
|
+
new(server_url, timestamp, salt).save
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(server_url, timestamp, salt, couchdb_rev = nil)
|
23
|
+
@server_url = server_url
|
24
|
+
@timestamp = Time.at(timestamp.to_i)
|
25
|
+
@salt = salt
|
26
|
+
@couchdb_rev = nil
|
27
|
+
@couchdb = Chef::CouchDB.new
|
28
|
+
end
|
29
|
+
|
30
|
+
def name
|
31
|
+
[@timestamp.utc.strftime(OpenID::Nonce::TIME_FMT), Base64.encode64(@server_url).chomp, Base64.encode64(@salt).chomp].join('-')
|
32
|
+
end
|
33
|
+
|
34
|
+
def save
|
35
|
+
return false unless valid?
|
36
|
+
|
37
|
+
begin
|
38
|
+
results = @couchdb.store('nonce', name, self)
|
39
|
+
rescue Net::HTTPServerException
|
40
|
+
false
|
41
|
+
else
|
42
|
+
@couchdb_rev = results['rev']
|
43
|
+
true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def valid?
|
48
|
+
OpenID::Nonce.check_timestamp(name)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.json_create(attributes)
|
52
|
+
server_url = attributes['server_url']
|
53
|
+
timestamp = attributes['timestamp']
|
54
|
+
salt = attributes['salt']
|
55
|
+
couchdb_rev = attributes['_rev']
|
56
|
+
|
57
|
+
new(server_url, timestamp, salt, couchdb_rev)
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_json(*args)
|
61
|
+
result = {
|
62
|
+
'json_class' => self.class.name,
|
63
|
+
'chef_type' => 'nonce',
|
64
|
+
'server_url' => @server_url,
|
65
|
+
'timestamp' => @timestamp.to_i,
|
66
|
+
'salt' => @salt,
|
67
|
+
}
|
68
|
+
result['_rev'] = @couchdb_rev if @couchdb_rev
|
69
|
+
result.to_json(*args)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: matthewtodd-openid-store-couchdb-chef
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matthew Todd
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-07-29 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: matthewtodd-shoe
|
17
|
+
type: :development
|
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: ruby-openid
|
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: chef
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
description:
|
46
|
+
email: matthew.todd@gmail.com
|
47
|
+
executables: []
|
48
|
+
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
extra_rdoc_files:
|
52
|
+
- README.rdoc
|
53
|
+
files:
|
54
|
+
- Rakefile
|
55
|
+
- README.rdoc
|
56
|
+
- lib/openid
|
57
|
+
- lib/openid/store
|
58
|
+
- lib/openid/store/couchdb
|
59
|
+
- lib/openid/store/couchdb/association.rb
|
60
|
+
- lib/openid/store/couchdb/nonce.rb
|
61
|
+
- lib/openid/store/couchdb.rb
|
62
|
+
- lib/openid-store-couchdb.rb
|
63
|
+
has_rdoc: false
|
64
|
+
homepage:
|
65
|
+
licenses:
|
66
|
+
post_install_message:
|
67
|
+
rdoc_options:
|
68
|
+
- --main
|
69
|
+
- README.rdoc
|
70
|
+
- --title
|
71
|
+
- openid-store-couchdb-chef-0.1.0
|
72
|
+
- --inline-source
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: "0"
|
80
|
+
version:
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: "0"
|
86
|
+
version:
|
87
|
+
requirements: []
|
88
|
+
|
89
|
+
rubyforge_project:
|
90
|
+
rubygems_version: 1.3.5
|
91
|
+
signing_key:
|
92
|
+
specification_version: 3
|
93
|
+
summary: A Chef-specific OpenID store for CouchDB.
|
94
|
+
test_files: []
|
95
|
+
|