matthewtodd-openid-store-couchdb-chef 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+