Class: Vines::Storage
- Inherits:
-
Object
- Object
- Vines::Storage
- Includes:
- Log
- Defined in:
- lib/vines/storage.rb,
lib/vines/storage/ldap.rb,
lib/vines/storage/null.rb,
lib/vines/storage/local.rb
Defined Under Namespace
Constant Summary collapse
- @@nicks =
{}
Instance Attribute Summary collapse
-
#ldap ⇒ Object
Returns the value of attribute ldap.
Class Method Summary collapse
-
.defer(method) ⇒ Object
Wrap a blocking IO method in a new method that pushes the original method onto EventMachine’s thread pool using EM#defer.
-
.fiber(method) ⇒ Object
Wrap a method with Fiber yield and resume logic.
- .from_name(name, &block) ⇒ Object
-
.register(name) ⇒ Object
Register a nickname that can be used in the config file to specify this storage implementation.
-
.wrap_ldap(method) ⇒ Object
Wrap an authenticate method with a new method that uses LDAP if it’s enabled in the config file.
Instance Method Summary collapse
-
#authenticate(username, password) ⇒ Object
Validate the username and password pair and return a
Vines::User
object on success. -
#find_fragment(jid, node) ⇒ Object
Return the Nokogiri::XML::Node for the XML fragment stored for this JID.
-
#find_user(jid) ⇒ Object
Return the
Vines::User
associated with the JID. -
#find_vcard(jid) ⇒ Object
Return the Nokogiri::XML::Node for the vcard stored for this JID.
-
#ldap? ⇒ Boolean
Return
true
if users are authenticated against an LDAP directory. -
#save_fragment(jid, fragment) ⇒ Object
Save the XML fragment to the database and return when the save is complete.
-
#save_user(user) ⇒ Object
Persist the
Vines::User
object to the database and return when the save is complete. -
#save_vcard(jid, card) ⇒ Object
Save the vcard to the database and return when the save is complete.
Methods included from Log
Instance Attribute Details
#ldap ⇒ Object
Returns the value of attribute ldap.
7 8 9 |
# File 'lib/vines/storage.rb', line 7 def ldap @ldap end |
Class Method Details
.defer(method) ⇒ Object
Wrap a blocking IO method in a new method that pushes the original method onto EventMachine’s thread pool using EM#defer. Storage classes implemented with blocking IO don’t need to worry about threading or blocking the EventMachine reactor thread if they wrap their methods with this one.
For example: def find_user(jid)
some_blocking_lookup(jid)
end defer :find_user
Storage classes that use asynchronous IO (through an EventMachine enabled library like em-http-request or em-redis) don’t need any special consideration and must not use this method.
37 38 39 40 41 42 43 44 45 46 |
# File 'lib/vines/storage.rb', line 37 def self.defer(method) old = instance_method(method) define_method method do |*args| fiber = Fiber.current op = operation { old.bind(self).call(*args) } cb = proc {|result| fiber.resume(result) } EM.defer(op, cb) Fiber.yield end end |
.fiber(method) ⇒ Object
Wrap a method with Fiber yield and resume logic. The method must yield its result to a block. This makes it easier to write asynchronous implementations of authenticate
, find_user
, and save_user
that block and return a result rather than yielding.
For example: def find_user(jid)
http = EM::HttpRequest.new(url).get
http.callback { yield build_user_from_http_response(http) }
end fiber :find_user
Because find_user
has been wrapped in Fiber logic, we can call it synchronously even though it uses asynchronous EventMachine calls.
user = storage.find_user(‘[email protected]’) puts user.nil?
82 83 84 85 86 87 88 89 90 91 |
# File 'lib/vines/storage.rb', line 82 def self.fiber(method) old = instance_method(method) define_method method do |*args| fiber, yielding = Fiber.current, true old.bind(self).call(*args) do |user| fiber.resume(user) rescue yielding = false end Fiber.yield if yielding end end |
.from_name(name, &block) ⇒ Object
17 18 19 20 21 |
# File 'lib/vines/storage.rb', line 17 def self.from_name(name, &block) klass = @@nicks[name.to_sym] raise "#{name} storage class not found" unless klass klass.new(&block) end |
.register(name) ⇒ Object
Register a nickname that can be used in the config file to specify this storage implementation.
13 14 15 |
# File 'lib/vines/storage.rb', line 13 def self.register(name) @@nicks[name.to_sym] = self end |
.wrap_ldap(method) ⇒ Object
Wrap an authenticate method with a new method that uses LDAP if it’s enabled in the config file. If LDAP is not enabled, invoke the original authenticate method as usual. This allows storage classes to implement their native authentication logic and not worry about handling LDAP.
For example: def authenticate(username, password)
some_user_lookup_by_password(username, password)
end wrap_ldap :authenticate
58 59 60 61 62 63 |
# File 'lib/vines/storage.rb', line 58 def self.wrap_ldap(method) old = instance_method(method) define_method method do |*args| ldap? ? authenticate_with_ldap(*args) : old.bind(self).call(*args) end end |
Instance Method Details
#authenticate(username, password) ⇒ Object
Validate the username and password pair and return a Vines::User
object on success. Return nil
on failure.
For example: user = storage.authenticate(‘[email protected]’, ‘secr3t’) puts user.nil?
This default implementation validates the password against a bcrypt hash of the password stored in the database. Sub-classes not using bcrypt passwords must override this method.
108 109 110 111 112 |
# File 'lib/vines/storage.rb', line 108 def authenticate(username, password) user = find_user(username) hash = BCrypt::Password.new(user.password) rescue nil (hash && hash == password) ? user : nil end |
#find_fragment(jid, node) ⇒ Object
Return the Nokogiri::XML::Node for the XML fragment stored for this JID. Return nil if the fragment could not be found. JID may be nil
, a String
, or a Vines::JID
object. It may be a bare JID or a full JID. Implementations of this method must convert the JID to a bare JID before searching for the fragment in the database.
Private XML storage uniquely identifies fragments by JID, root element name, and root element namespace.
root = Nokogiri::XML(‘<custom xmlns=“urn:custom:ns”/>’).root fragment = storage.find_fragment(‘[email protected]’, root) puts fragment.nil?
173 174 175 |
# File 'lib/vines/storage.rb', line 173 def find_fragment(jid, node) raise 'subclass must implement' end |
#find_user(jid) ⇒ Object
Return the Vines::User
associated with the JID. Return nil
if the user could not be found. JID may be nil
, a String
, or a Vines::JID
object. It may be a bare JID or a full JID. Implementations of this method must convert the JID to a bare JID before searching for the user in the database.
user = storage.find_user(‘[email protected]’) puts user.nil?
123 124 125 |
# File 'lib/vines/storage.rb', line 123 def find_user(jid) raise 'subclass must implement' end |
#find_vcard(jid) ⇒ Object
Return the Nokogiri::XML::Node for the vcard stored for this JID. Return nil if the vcard could not be found. JID may be nil
, a String
, or a Vines::JID
object. It may be a bare JID or a full JID. Implementations of this method must convert the JID to a bare JID before searching for the vcard in the database.
card = storage.find_vcard(‘[email protected]’) puts card.nil?
145 146 147 |
# File 'lib/vines/storage.rb', line 145 def find_vcard(jid) raise 'subclass must implement' end |
#ldap? ⇒ Boolean
Return true
if users are authenticated against an LDAP directory.
94 95 96 |
# File 'lib/vines/storage.rb', line 94 def ldap? !!ldap end |
#save_fragment(jid, fragment) ⇒ Object
Save the XML fragment to the database and return when the save is complete. JID may be a String
or a Vines::JID
object. It may be a bare JID or a full JID. Implementations of this method must convert the JID to a bare JID before saving the fragment. Fragment is a Nokogiri::XML::Node
object.
fragment = Nokogiri::XML(‘<custom xmlns=“urn:custom:ns”>some data</custom>’).root storage.save_fragment(‘[email protected]’, fragment) puts ‘saved’
185 186 187 |
# File 'lib/vines/storage.rb', line 185 def save_fragment(jid, fragment) raise 'subclass must implement' end |
#save_user(user) ⇒ Object
Persist the Vines::User
object to the database and return when the save is complete.
alice = Vines::User.new(:jid => ‘[email protected]’) storage.save_user(alice) puts ‘saved’
133 134 135 |
# File 'lib/vines/storage.rb', line 133 def save_user(user) raise 'subclass must implement' end |
#save_vcard(jid, card) ⇒ Object
Save the vcard to the database and return when the save is complete. JID may be a String
or a Vines::JID
object. It may be a bare JID or a full JID. Implementations of this method must convert the JID to a bare JID before saving the vcard. Card is a Nokogiri::XML::Node
object.
card = Nokogiri::XML(‘<vCard>…</vCard>’).root storage.save_vcard(‘[email protected]’, card) puts ‘saved’
157 158 159 |
# File 'lib/vines/storage.rb', line 157 def save_vcard(jid, card) raise 'subclass must implement' end |