diff options
Diffstat (limited to 'vendor/gems/couchrest_session_store/lib/couchrest')
6 files changed, 0 insertions, 639 deletions
diff --git a/vendor/gems/couchrest_session_store/lib/couchrest/model/database_method.rb b/vendor/gems/couchrest_session_store/lib/couchrest/model/database_method.rb deleted file mode 100644 index 6ecc8f3..0000000 --- a/vendor/gems/couchrest_session_store/lib/couchrest/model/database_method.rb +++ /dev/null @@ -1,131 +0,0 @@ -# -# Allow setting the database to happen dynamically. -# -# Unlike normal CouchRest::Model, the database is not automatically created -# unless you call database!() -# -# The method specified by `database_method` must exist as a class method but -# may optionally also exist as an instance method. -# - -module CouchRest - module Model - module DatabaseMethod - extend ActiveSupport::Concern - - def database - if self.class.database_method - self.class.server.database(call_database_method) - else - self.class.database - end - end - - def database! - if self.class.database_method - self.class.server.database!(call_database_method) - else - self.class.database! - end - end - - def database_exists?(db_name) - self.class.database_exists?(db_name) - end - - # - # The normal CouchRest::Model::Base comparison checks if the model's - # database objects are the same. That is not good for use here, since - # the objects will always be different. Instead, we compare the string - # that each database evaluates to. - # - def ==(other) - return false unless other.is_a?(Base) - if id.nil? && other.id.nil? - to_hash == other.to_hash - else - id == other.id && database.to_s == other.database.to_s - end - end - alias :eql? :== - - protected - - def call_database_method - if self.respond_to?(self.class.database_method) - name = self.send(self.class.database_method) - self.class.db_name_with_prefix(name) - else - self.class.send(:call_database_method) - end - end - - module ClassMethods - - def database_method(method = nil) - if method - @database_method = method - end - @database_method - end - alias :use_database_method :database_method - - def database - if database_method - if !self.respond_to?(database_method) - raise ArgumentError.new("Incorrect argument to database_method(): no such method '#{method}' found in class #{self}.") - end - self.server.database(call_database_method) - else - @database ||= prepare_database(super) - end - end - - def database! - if database_method - self.server.database!(call_database_method) - else - @database ||= prepare_database(super) - end - end - - # - # same as database(), but allows for an argument that gets passed through to - # database method. - # - def choose_database(*args) - self.server.database(call_database_method(*args)) - end - - def db_name_with_prefix(name) - conf = self.send(:connection_configuration) - [conf[:prefix], name, conf[:suffix]].reject{|i|i.to_s.empty?}.join(conf[:join]) - end - - def database_exists?(name) - name = db_name_with_prefix(name) - begin - CouchRest.head "#{self.server.uri}/#{name}" - return true - rescue CouchRest::NotFound - return false - end - end - - protected - - def call_database_method(*args) - name = nil - method = self.method(database_method) - if method.arity == 0 - name = method.call - else - name = method.call(*args) - end - db_name_with_prefix(name) - end - - end - end - end -end diff --git a/vendor/gems/couchrest_session_store/lib/couchrest/model/rotation.rb b/vendor/gems/couchrest_session_store/lib/couchrest/model/rotation.rb deleted file mode 100644 index 9e1a5c3..0000000 --- a/vendor/gems/couchrest_session_store/lib/couchrest/model/rotation.rb +++ /dev/null @@ -1,263 +0,0 @@ -module CouchRest - module Model - module Rotation - extend ActiveSupport::Concern - include CouchRest::Model::DatabaseMethod - - included do - use_database_method :rotated_database_name - end - - def create(*args) - super(*args) - rescue CouchRest::NotFound => exc - raise storage_missing(exc) - end - - def update(*args) - super(*args) - rescue CouchRest::NotFound => exc - raise storage_missing(exc) - end - - def destroy(*args) - super(*args) - rescue CouchRest::NotFound => exc - raise storage_missing(exc) - end - - private - - # returns a special 'storage missing' exception when the db has - # not been created. very useful, since this happens a lot and a - # generic 404 is not that helpful. - def storage_missing(exc) - if exc.http_body =~ /no_db_file/ - CouchRest::StorageMissing.new(exc.response, database) - else - exc - end - end - - public - - module ClassMethods - # - # Set up database rotation. - # - # base_name -- the name of the db before the rotation number is - # appended. - # - # options -- one of: - # - # * :every -- frequency of rotation - # * :expiration_field - what field to use to determine if a - # document is expired. - # * :timestamp_field - alternately, what field to use for the - # document timestamp. - # * :timeout -- used to expire documents with only a timestamp - # field (in minutes) - # - def rotate_database(base_name, options={}) - @rotation_base_name = base_name - @rotation_every = (options.delete(:every) || 30.days).to_i - @expiration_field = options.delete(:expiration_field) - @timestamp_field = options.delete(:timestamp_field) - @timeout = options.delete(:timeout) - if options.any? - raise ArgumentError.new('Could not understand options %s' % options.keys) - end - end - - # - # Check to see if dbs should be rotated. The :window - # argument specifies how far in advance we should - # create the new database (default 1.day). - # - # This method relies on the assumption that it is called - # at least once within each @rotation_every period. - # - def rotate_database_now(options={}) - window = options[:window] || 1.day - - now = Time.now.utc - current_name = rotated_database_name(now) - current_count = now.to_i/@rotation_every - - next_time = window.from_now.utc - next_name = rotated_database_name(next_time) - next_count = current_count+1 - - prev_name = current_name.sub(/(\d+)$/) {|i| i.to_i-1} - replication_started = false - old_name = prev_name.sub(/(\d+)$/) {|i| i.to_i-1} # even older than prev_name - trailing_edge_time = window.ago.utc - - if !database_exists?(current_name) - # we should have created the current db earlier, but if somehow - # it is missing we must make sure it exists. - create_new_rotated_database(:from => prev_name, :to => current_name) - replication_started = true - end - - if next_time.to_i/@rotation_every >= next_count && !database_exists?(next_name) - # time to create the next db in advance of actually needing it. - create_new_rotated_database(:from => current_name, :to => next_name) - end - - if trailing_edge_time.to_i/@rotation_every == current_count - # delete old dbs, but only after window time has past since the last rotation - if !replication_started && database_exists?(prev_name) - # delete previous, but only if we didn't just start replicating from it - self.server.database(db_name_with_prefix(prev_name)).delete! - end - if database_exists?(old_name) - # there are some edge cases, when rotate_database_now is run - # infrequently, that an older db might be left around. - self.server.database(db_name_with_prefix(old_name)).delete! - end - end - end - - def rotated_database_name(time=nil) - unless @rotation_base_name && @rotation_every - raise ArgumentError.new('missing @rotation_base_name or @rotation_every') - end - time ||= Time.now.utc - units = time.to_i / @rotation_every.to_i - "#{@rotation_base_name}_#{units}" - end - - # - # create a new empty database. - # - def create_database!(name=nil) - db = if name - self.server.database!(db_name_with_prefix(name)) - else - self.database! - end - create_rotation_filter(db) - if self.respond_to?(:design_doc) - design_doc.sync!(db) - # or maybe this?: - #self.design_docs.each do |design| - # design.migrate(to_db) - #end - end - return db - end - - protected - - # - # Creates database named by options[:to]. Optionally, set up - # continuous replication from the options[:from] db, if it exists. The - # assumption is that the from db will be destroyed later, cleaning up - # the replication once it is no longer needed. - # - # This method will also copy design documents if present in the from - # db, in the CouchRest::Model, or in a database named after - # @rotation_base_name. - # - def create_new_rotated_database(options={}) - from = options[:from] - to = options[:to] - to_db = self.create_database!(to) - if database_exists?(@rotation_base_name) - base_db = self.server.database(db_name_with_prefix(@rotation_base_name)) - copy_design_docs(base_db, to_db) - end - if from && from != to && database_exists?(from) - from_db = self.server.database(db_name_with_prefix(from)) - replicate_old_to_new(from_db, to_db) - end - end - - def copy_design_docs(from, to) - params = {:startkey => '_design/', :endkey => '_design0', :include_docs => true} - from.documents(params) do |doc_hash| - design = doc_hash['doc'] - begin - to.get(design['_id']) - rescue CouchRest::NotFound - design.delete('_rev') - to.save_doc(design) - end - end - end - - def create_rotation_filter(db) - name = 'rotation_filter' - filter_string = if @expiration_field - NOT_EXPIRED_FILTER % {:expires => @expiration_field} - elsif @timestamp_field && @timeout - NOT_TIMED_OUT_FILTER % {:timestamp => @timestamp_field, :timeout => (60 * @timeout)} - else - NOT_DELETED_FILTER - end - filters = {"not_expired" => filter_string} - db.save_doc("_id" => "_design/#{name}", "filters" => filters) - rescue CouchRest::Conflict - end - - # - # Replicates documents from_db to to_db, skipping documents that have - # expired or been deleted. - # - # NOTE: It would be better if we could do this: - # - # from_db.replicate_to(to_db, true, false, - # :filter => 'rotation_filter/not_expired') - # - # But replicate_to() does not support a filter argument, so we call - # the private method replication() directly. - # - def replicate_old_to_new(from_db, to_db) - create_rotation_filter(from_db) - from_db.send(:replicate, to_db, true, :source => from_db.name, :filter => 'rotation_filter/not_expired') - end - - # - # Three different filters, depending on how the model is set up. - # - # NOT_EXPIRED_FILTER is used when there is a single field that - # contains an absolute time for when the document has expired. The - # - # NOT_TIMED_OUT_FILTER is used when there is a field that records the - # timestamp of the last time the document was used. The expiration in - # this case is calculated from the timestamp plus @timeout. - # - # NOT_DELETED_FILTER is used when the other two cannot be. - # - NOT_EXPIRED_FILTER = "" + -%[function(doc, req) { - if (doc._deleted) { - return false; - } else if (typeof(doc.%{expires}) != "undefined") { - return Date.now() < (new Date(doc.%{expires})).getTime(); - } else { - return true; - } -}] - - NOT_TIMED_OUT_FILTER = "" + -%[function(doc, req) { - if (doc._deleted) { - return false; - } else if (typeof(doc.%{timestamp}) != "undefined") { - return Date.now() < (new Date(doc.%{timestamp})).getTime() + %{timeout}; - } else { - return true; - } -}] - - NOT_DELETED_FILTER = "" + -%[function(doc, req) { - return !doc._deleted; -}] - - end - end - end -end diff --git a/vendor/gems/couchrest_session_store/lib/couchrest/session.rb b/vendor/gems/couchrest_session_store/lib/couchrest/session.rb deleted file mode 100644 index 416a88d..0000000 --- a/vendor/gems/couchrest_session_store/lib/couchrest/session.rb +++ /dev/null @@ -1,105 +0,0 @@ -class CouchRest::Session -end - -require 'couchrest/session/utility' -require 'couchrest/session/document' - -module CouchRest - - class StorageMissing < Exception - attr_reader :db - def initialize(request, db) - super(request) - @db = db.name - @message = "The database '#{db}' does not exist." - end - end - - class Session - include CouchRest::Session::Utility - - def self.fetch(sid) - self.allocate.tap do |session_doc| - session_doc.fetch(sid) || raise(CouchRest::NotFound) - end - end - - def self.build(sid, session, options = {}) - session_doc = CouchRest::Session::Document.new "_id" => sid - self.new(session_doc). - update session, options - end - - def self.build_or_update(sid, session, options = {}) - options[:marshal_data] = true if options[:marshal_data].nil? - self.fetch(sid). - update session, options - rescue CouchRest::NotFound - self.build sid, session, options - end - - def initialize(doc) - @doc = doc - end - - def fetch(sid = nil) - @doc = CouchRest::Session::Document.fetch(sid || doc['_id']) - end - - def to_session - if doc["marshalled"] - session = unmarshal(doc["data"]) - else - session = doc["data"] - end - return session - end - - def delete - doc.destroy - end - - def update(session, options) - # clean up old data but leave id and revision intact - doc.reject! { |k,_v| k[0] != '_' } - doc.merge! data_for_doc(session, options) - self - end - - def save - doc.save - rescue CouchRest::Conflict - fetch - retry - rescue CouchRest::NotFound => exc - if exc.http_body =~ /no_db_file/ - exc = CouchRest::StorageMissing.new(exc.response, doc.database) - end - raise exc - end - - def expired? - expires && expires < Time.now - end - - protected - - attr_reader :doc - - def data_for_doc(session, options) - { "data" => options[:marshal_data] ? marshal(session) : session, - "marshalled" => options[:marshal_data], - "expires" => expiry_from_options(options) } - end - - def expiry_from_options(options) - expire_after = options[:expire_after] - expire_after && (Time.now + expire_after).utc - end - - def expires - doc["expires"] && Time.iso8601(doc["expires"]) - end - - end -end diff --git a/vendor/gems/couchrest_session_store/lib/couchrest/session/document.rb b/vendor/gems/couchrest_session_store/lib/couchrest/session/document.rb deleted file mode 100644 index dc938cf..0000000 --- a/vendor/gems/couchrest_session_store/lib/couchrest/session/document.rb +++ /dev/null @@ -1,34 +0,0 @@ -require 'time' - -class CouchRest::Session::Document < CouchRest::Document - include CouchRest::Model::Configuration - include CouchRest::Model::Connection - include CouchRest::Model::Rotation - - rotate_database 'sessions', - :every => 1.month, :expiration_field => :expires - - def self.fetch(id) - database.get(id) - end - - def self.find_by_expires(options = {}) - options[:reduce] ||= false - design = database.get '_design/Session' - response = design.view :by_expires, options - response['rows'] - end - - def self.create_database!(name=nil) - db = super(name) - begin - db.get('_design/Session') - rescue CouchRest::NotFound - design = File.read(File.expand_path('../../../../design/Session.json', __FILE__)) - design = JSON.parse(design) - db.save_doc(design.merge({"_id" => "_design/Session"})) - end - db - end - -end diff --git a/vendor/gems/couchrest_session_store/lib/couchrest/session/store.rb b/vendor/gems/couchrest_session_store/lib/couchrest/session/store.rb deleted file mode 100644 index 516d5dd..0000000 --- a/vendor/gems/couchrest_session_store/lib/couchrest/session/store.rb +++ /dev/null @@ -1,94 +0,0 @@ -class CouchRest::Session::Store < ActionDispatch::Session::AbstractStore - - # delegate configure to document - def self.configure(*args, &block) - CouchRest::Session::Document.configure *args, &block - end - - def self.set_options(options) - @options = options - if @options[:database] - CouchRest::Session::Document.use_database @options[:database] - end - end - - def initialize(app, options = {}) - super - self.class.set_options(options) - end - - def cleanup(rows) - rows.each do |row| - doc = CouchRest::Session::Document.fetch(row['id']) - doc.delete - end - end - - def expired - CouchRest::Session::Document.find_by_expires startkey: 1, - endkey: Time.now.utc.iso8601 - end - - def never_expiring - CouchRest::Session::Document.find_by_expires endkey: 1 - end - - private - - def get_session(env, sid) - if session = fetch_session(sid) - [sid, session] - else - [generate_sid, {}] - end - rescue CouchRest::NotFound - # session data does not exist anymore - return [sid, {}] - rescue CouchRest::Unauthorized, - Errno::EHOSTUNREACH, - Errno::ECONNREFUSED => e - # can't connect to couch. We add some status to the session - # so the app can react. (Display error for example) - return [sid, {"_status" => {"couch" => "unreachable"}}] - end - - def set_session(env, sid, session, options) - raise CouchRest::NotFound if /^_design\/(.*)/ =~ sid - couchrest_session = build_or_update_doc(sid, session, options) - couchrest_session.save - return sid - # if we can't store the session we just return false. - rescue CouchRest::Unauthorized, - Errno::EHOSTUNREACH, - Errno::ECONNREFUSED => e - return false - end - - def destroy_session(env, sid, options) - doc = secure_get(sid) - doc.delete - generate_sid unless options[:drop] - rescue CouchRest::NotFound - # already destroyed - we're done. - generate_sid unless options[:drop] - end - - def fetch_session(sid) - return nil unless sid - couchrest_session = secure_get(sid) - couchrest_session.to_session unless couchrest_session.expired? - end - - def build_or_update_doc(sid, session, options) - CouchRest::Session.build_or_update(sid, session, options) - end - - # prevent access to design docs - # this should be prevented on a couch permission level as well. - # but better be save than sorry. - def secure_get(sid) - raise CouchRest::NotFound if /^_design\/(.*)/ =~ sid - CouchRest::Session.fetch(sid) - end - -end diff --git a/vendor/gems/couchrest_session_store/lib/couchrest/session/utility.rb b/vendor/gems/couchrest_session_store/lib/couchrest/session/utility.rb deleted file mode 100644 index 3982c28..0000000 --- a/vendor/gems/couchrest_session_store/lib/couchrest/session/utility.rb +++ /dev/null @@ -1,12 +0,0 @@ -module CouchRest::Session::Utility - module_function - - def marshal(data) - ::Base64.encode64(Marshal.dump(data)) if data - end - - def unmarshal(data) - Marshal.load(::Base64.decode64(data)) if data - end - -end |