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.
@@ -0,0 +1,5 @@
1
+ = openid-store-couchdb-chef
2
+
3
+ A Chef-specific[http://wiki.opscode.com/display/chef] OpenID store for CouchDB.
4
+
5
+ Extracted from skillet[http://github.com/matthewtodd/skillet], my attempt to run a Chef server on Heroku[http://heroku.com].
@@ -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
+