summaryrefslogtreecommitdiff
path: root/vendor/gems/couchrest_session_store/lib/couchrest/session
diff options
context:
space:
mode:
authorAzul <azul@riseup.net>2016-03-23 21:48:52 +0100
committerAzul <azul@riseup.net>2016-05-02 08:21:52 -0300
commit065859b90cc5ef403b8f47bd5394b343e556cc4d (patch)
treede62cd7a23b2db2a620911c6d861a7fda1d74a00 /vendor/gems/couchrest_session_store/lib/couchrest/session
parentabf600089a4bc4b5c7271e17b1fd95a95deb293f (diff)
upgrade: remove references to RestClient
CouchRest > 1.2 does not use RestClient anymore. So we should not try to catch its errors.
Diffstat (limited to 'vendor/gems/couchrest_session_store/lib/couchrest/session')
-rw-r--r--vendor/gems/couchrest_session_store/lib/couchrest/session/document.rb119
-rw-r--r--vendor/gems/couchrest_session_store/lib/couchrest/session/store.rb94
2 files changed, 213 insertions, 0 deletions
diff --git a/vendor/gems/couchrest_session_store/lib/couchrest/session/document.rb b/vendor/gems/couchrest_session_store/lib/couchrest/session/document.rb
new file mode 100644
index 0000000..b1e73cc
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/lib/couchrest/session/document.rb
@@ -0,0 +1,119 @@
+require 'couchrest/session/utility'
+require 'time'
+
+class CouchRest::Session::Document < CouchRest::Document
+ include CouchRest::Model::Configuration
+ include CouchRest::Model::Connection
+ include CouchRest::Session::Utility
+ include CouchRest::Model::Rotation
+
+ rotate_database 'sessions',
+ :every => 1.month, :expiration_field => :expires
+
+ def self.fetch(sid)
+ self.allocate.tap do |session_doc|
+ session_doc.fetch(sid)
+ end
+ end
+
+ def self.build(sid, session, options = {})
+ self.new(CouchRest::Document.new({"_id" => sid})).tap do |session_doc|
+ session_doc.update session, options
+ end
+ end
+
+ def self.build_or_update(sid, session, options = {})
+ options[:marshal_data] = true if options[:marshal_data].nil?
+ doc = self.fetch(sid)
+ doc.update(session, options)
+ return doc
+ rescue CouchRest::NotFound
+ self.build(sid, session, options)
+ 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
+
+ def initialize(doc)
+ @doc = doc
+ end
+
+ def fetch(sid = nil)
+ @doc = database.get(sid || doc['_id'])
+ end
+
+ def to_session
+ if doc["marshalled"]
+ session = unmarshal(doc["data"])
+ else
+ session = doc["data"]
+ end
+ return session
+ end
+
+ def delete
+ database.delete_doc(doc)
+ end
+
+ def update(session, options)
+ # clean up old data but leave id and revision intact
+ doc.reject! do |k,v|
+ k[0] != '_'
+ end
+ doc.merge! data_for_doc(session, options)
+ end
+
+ def save
+ database.save_doc(doc)
+ rescue CouchRest::Conflict
+ fetch
+ retry
+ rescue CouchRest::NotFound => exc
+ if exc.http_body =~ /no_db_file/
+ exc = CouchRest::StorageMissing.new(exc.response, database)
+ end
+ raise exc
+ end
+
+ def expired?
+ expires && expires < Time.now
+ end
+
+ protected
+
+ 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
+
+ def doc
+ @doc
+ 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
new file mode 100644
index 0000000..f209f54
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/lib/couchrest/session/store.rb
@@ -0,0 +1,94 @@
+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
+ doc = build_or_update_doc(sid, session, options)
+ doc.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
+ doc = secure_get(sid)
+ doc.to_session unless doc.expired?
+ end
+
+ def build_or_update_doc(sid, session, options)
+ CouchRest::Session::Document.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::Document.fetch(sid)
+ end
+
+end