summaryrefslogtreecommitdiff
path: root/vendor
diff options
context:
space:
mode:
Diffstat (limited to 'vendor')
-rw-r--r--vendor/gems/couchrest_session_store/.ruby-version1
-rw-r--r--vendor/gems/couchrest_session_store/.travis.yml6
-rw-r--r--vendor/gems/couchrest_session_store/Gemfile7
-rw-r--r--vendor/gems/couchrest_session_store/README.md133
-rw-r--r--vendor/gems/couchrest_session_store/Rakefile9
-rw-r--r--vendor/gems/couchrest_session_store/couchrest_session_store.gemspec25
-rw-r--r--vendor/gems/couchrest_session_store/design/Session.json8
-rw-r--r--vendor/gems/couchrest_session_store/lib/couchrest/session.rb15
-rw-r--r--vendor/gems/couchrest_session_store/lib/couchrest/session/utility.rb12
-rw-r--r--vendor/gems/couchrest_session_store/lib/couchrest_session_store.rb11
-rw-r--r--vendor/gems/couchrest_session_store/test/couch_tester.rb27
-rw-r--r--vendor/gems/couchrest_session_store/test/database_rotation_test.rb88
-rw-r--r--vendor/gems/couchrest_session_store/test/session_document_test.rb27
-rwxr-xr-xvendor/gems/couchrest_session_store/test/setup_couch.sh7
-rw-r--r--vendor/gems/couchrest_session_store/test/stress_test.rb51
-rw-r--r--vendor/gems/couchrest_session_store/test/test_clock.rb12
-rw-r--r--vendor/gems/couchrest_session_store/test/test_helper.rb9
17 files changed, 448 insertions, 0 deletions
diff --git a/vendor/gems/couchrest_session_store/.ruby-version b/vendor/gems/couchrest_session_store/.ruby-version
new file mode 100644
index 0000000..f3a9c9a
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/.ruby-version
@@ -0,0 +1 @@
+1.9.3-p194
diff --git a/vendor/gems/couchrest_session_store/.travis.yml b/vendor/gems/couchrest_session_store/.travis.yml
new file mode 100644
index 0000000..073d421
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/.travis.yml
@@ -0,0 +1,6 @@
+services:
+ - couchdb
+notifications:
+ email: false
+before_script:
+ - "test/setup_couch.sh"
diff --git a/vendor/gems/couchrest_session_store/Gemfile b/vendor/gems/couchrest_session_store/Gemfile
new file mode 100644
index 0000000..88b81a0
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/Gemfile
@@ -0,0 +1,7 @@
+source 'https://rubygems.org'
+
+# Specify your gem's dependencies in couchrest-session-store.gemspec
+gemspec
+
+gem 'debugger'
+
diff --git a/vendor/gems/couchrest_session_store/README.md b/vendor/gems/couchrest_session_store/README.md
new file mode 100644
index 0000000..60e692e
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/README.md
@@ -0,0 +1,133 @@
+# CouchRest::Session::Store #
+
+A simple session store based on CouchRest Model.
+
+## Setup ##
+
+`CouchRest::Session::Store` will automatically pick up the config/couch.yml
+file used by CouchRest Model.
+
+Cleaning up sessions requires a design document in the sessions database that
+enables querying by expiry. See `design/Session.json` for an example. This
+design document is loaded for tests, but you will need to load it on your own
+in a production environment. For example:
+
+ curl -X PUT username:password@localhost:5984/couchrest_sessions/_design/Session --data @design/Session.json
+
+## Options ##
+
+* marshal_data: (_defaults true_) - if set to false session data will be stored
+ directly in the couch document. Otherwise it's marshalled and base64 encoded
+ to enable restoring ruby data structures.
+* database: database to use combined with config prefix and suffix
+* expire_after: lifetime of a session in seconds.
+
+## Dynamic Databases ##
+
+This gem also includes the module `CouchRest::Model::DatabaseMethod`, which
+allow a Model to dynamically choose what database to use.
+
+An example of specifying database dynamically:
+
+ class Token < CouchRest::Model::Base
+ include CouchRest::Model::DatabaseMethod
+
+ use_database_method :database_name
+
+ def self.database_name
+ time = Time.now.utc
+ "tokens_#{time.year}_#{time.month}"
+ end
+ end
+
+A couple notes:
+
+Once you include `CouchRest::Model::DatabaseMethod`, the database is no longer
+automatically created. In this example, you would need to run
+`Token.database.create!` or `Token.database!` in order to create the database.
+
+The symbol passed to `database_method` must match the name of a class method,
+but if there is also an instance method with the same name then this instance
+method will be called when appropriate. To state the obvious, tread lightly:
+there be dragons when generating database names that depend on properties of
+the instance.
+
+## Database Rotation ##
+
+The module `CouchRest::Model::Rotation` can be included in a Model in
+order to use dynamic databases to perform database rotation.
+
+CouchDB is not good for ephemeral data because old documents are never really
+deleted: when you deleted a document, it just appends a new revision. The bulk
+of the old data is not stored, but it does store a record for each doc id and
+revision id for the document. In the case of ephemeral data, like tokens,
+sessions, or statistics, this will quickly bloat the database with a ton of
+useless deleted documents. The proper solution is to rotate the databases:
+create a new one regularly and delete the old one entirely. This will allow
+you to recover the storage space.
+
+A better solution might be to just use a different database for all
+ephemeral data, like MariaDB or Redis. But, if you really want to use CouchDB, this
+is how you can do it.
+
+An example of specifying database rotation:
+
+ class Token < CouchRest::Model::Base
+ include CouchRest::Model::Rotation
+
+ rotate_database 'tokens', :every => 30.days
+ end
+
+Then, in a task triggered by a cron job:
+
+ CouchRest::Model::Base.configure do |conf|
+ conf.environment = Rails.env
+ conf.connection_config_file = File.join(Rails.root, 'config', 'couchdb.admin.yml')
+ end
+ Token.rotate_database_now(:window => 1.day)
+
+Or perhaps:
+
+ Rails.application.eager_load!
+ CouchRest::Model::Rotation.descendants.each do |model|
+ model.rotate_database_now
+ end
+
+The `:window` argument to `rotate_database_now` specifies how far in advance we
+should create the new database (default 1.day). For ideal behavior, this value
+should be GREATER than or equal to the frequency with which the cron job is
+run. For example, if the cron job is run every hour, the argument can be
+`1.hour`, `2.hours`, `1.day`, but not `20.minutes`.
+
+The method `rotate_database_now` will do nothing if the database has already
+been rotated. Otherwise, as needed, it will create the new database, create
+the design documents, set up replication between the old and new databases,
+and delete the old database (once it is not used anymore).
+
+These actions will require admin access, so if your application normally runs
+without admin rights you will need specify a different configuration for
+CouchRest::Model before `rotate_database_now` is called.
+
+Known issues:
+
+* If you change the rotation period, there will be a break in the rotation
+ (old documents will not get replicated to the new rotated db) and the old db
+ will not get automatically deleted.
+
+* Calling `Model.database.delete!` will not necessarily remove all the
+ relevant databases because of the way prior and future databases are kept
+ for the 'window' period.
+
+## Changes ##
+
+0.3.0
+
+* Added support for dynamic and rotating databases.
+
+0.2.4
+
+* Do not crash if can't connect to CouchDB
+
+0.2.3
+
+* Better retry and conflict catching.d \ No newline at end of file
diff --git a/vendor/gems/couchrest_session_store/Rakefile b/vendor/gems/couchrest_session_store/Rakefile
new file mode 100644
index 0000000..8e1dc9c
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/Rakefile
@@ -0,0 +1,9 @@
+#!/usr/bin/env rake
+require "bundler/gem_tasks"
+require 'rake/testtask'
+
+task default: [:test]
+
+Rake::TestTask.new do |t|
+ t.pattern = "test/*_test.rb"
+end
diff --git a/vendor/gems/couchrest_session_store/couchrest_session_store.gemspec b/vendor/gems/couchrest_session_store/couchrest_session_store.gemspec
new file mode 100644
index 0000000..bf3b2b2
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/couchrest_session_store.gemspec
@@ -0,0 +1,25 @@
+# _*_ encoding: utf-8 -*-
+
+Gem::Specification.new do |gem|
+
+ gem.authors = ["Azul"]
+ gem.email = ["azul@leap.se"]
+ gem.summary = "A Rails Session Store based on CouchRest Model"
+ gem.description = gem.summary
+ gem.homepage = "http://github.com/azul/couchrest_session_store"
+
+ gem.has_rdoc = true
+# gem.extra_rdoc_files = ["LICENSE"]
+
+ gem.files = `git ls-files`.split("\n")
+ gem.name = "couchrest_session_store"
+ gem.require_paths = ["lib"]
+ gem.version = '0.4.0'
+
+ gem.add_dependency "couchrest"
+ gem.add_dependency "couchrest_model"
+ gem.add_dependency "actionpack", '~> 4.0'
+
+ gem.add_development_dependency "minitest"
+ gem.add_development_dependency "rake"
+end
diff --git a/vendor/gems/couchrest_session_store/design/Session.json b/vendor/gems/couchrest_session_store/design/Session.json
new file mode 100644
index 0000000..7020278
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/design/Session.json
@@ -0,0 +1,8 @@
+{
+ "views": {
+ "by_expires": {
+ "reduce": "_sum",
+ "map": "function(doc) {\n if(typeof doc.expires !== \"undefined\") {\n emit(doc.expires, 1);\n }\n}\n"
+ }
+ }
+}
diff --git a/vendor/gems/couchrest_session_store/lib/couchrest/session.rb b/vendor/gems/couchrest_session_store/lib/couchrest/session.rb
new file mode 100644
index 0000000..430732c
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/lib/couchrest/session.rb
@@ -0,0 +1,15 @@
+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
+
+ module Session
+ 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
new file mode 100644
index 0000000..3982c28
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/lib/couchrest/session/utility.rb
@@ -0,0 +1,12 @@
+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
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..78c6a25
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/lib/couchrest_session_store.rb
@@ -0,0 +1,11 @@
+require 'couchrest'
+require 'couchrest_model'
+# ensure compatibility with couchrest_model
+gem 'actionpack', '~> 4.0'
+require 'action_dispatch'
+
+require 'couchrest/model/database_method'
+require 'couchrest/model/rotation'
+require 'couchrest/session'
+require 'couchrest/session/store'
+require 'couchrest/session/document'
diff --git a/vendor/gems/couchrest_session_store/test/couch_tester.rb b/vendor/gems/couchrest_session_store/test/couch_tester.rb
new file mode 100644
index 0000000..b623044
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/test/couch_tester.rb
@@ -0,0 +1,27 @@
+#
+# Access the couch directly so we can test its state without relying
+# on the SessionStore
+#
+
+class CouchTester < CouchRest::Document
+ include CouchRest::Model::Configuration
+ include CouchRest::Model::Connection
+ include CouchRest::Model::Rotation
+
+ rotate_database 'sessions',
+ :every => 1.month, :expiration_field => :expires
+
+ def initialize(options = {})
+ end
+
+ def get(sid)
+ database.get(sid)
+ end
+
+ def update(sid, diff)
+ doc = database.get(sid)
+ doc.merge! diff
+ database.save_doc(doc)
+ end
+
+end
diff --git a/vendor/gems/couchrest_session_store/test/database_rotation_test.rb b/vendor/gems/couchrest_session_store/test/database_rotation_test.rb
new file mode 100644
index 0000000..856db11
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/test/database_rotation_test.rb
@@ -0,0 +1,88 @@
+require_relative 'test_helper'
+
+class RotationTest < MiniTest::Test
+
+ class Token < CouchRest::Model::Base
+ include CouchRest::Model::Rotation
+ property :token, String
+ rotate_database 'test_rotate', :every => 1.day
+ end
+
+ TEST_DB_RE = /test_rotate_\d+/
+
+ def test_rotate
+ delete_all_dbs
+ doc = nil
+ original_name = nil
+ next_db_name = nil
+
+ Time.stub :now, Time.gm(2015,3,7,0) do
+ Token.create_database!
+ doc = Token.create!(:token => 'aaaa')
+ original_name = Token.rotated_database_name
+ assert database_exists?(original_name)
+ assert_equal 1, count_dbs
+ end
+
+ # do nothing yet
+ Time.stub :now, Time.gm(2015,3,7,22) do
+ Token.rotate_database_now(:window => 1.hour)
+ assert_equal original_name, Token.rotated_database_name
+ assert_equal 1, count_dbs
+ end
+
+ # create next db, but don't switch yet.
+ Time.stub :now, Time.gm(2015,3,7,23) do
+ Token.rotate_database_now(:window => 1.hour)
+ assert_equal 2, count_dbs
+ next_db_name = Token.rotated_database_name(Time.gm(2015,3,8))
+ assert original_name != next_db_name
+ assert database_exists?(next_db_name)
+ sleep 0.2 # allow time for documents to replicate
+ assert_equal(
+ Token.get(doc.id).token,
+ Token.get(doc.id, database(next_db_name)).token
+ )
+ end
+
+ # use next db
+ Time.stub :now, Time.gm(2015,3,8) do
+ Token.rotate_database_now(:window => 1.hour)
+ assert_equal 2, count_dbs
+ assert_equal next_db_name, Token.rotated_database_name
+ token = Token.get(doc.id)
+ token.update_attributes(:token => 'bbbb')
+ assert_equal 'bbbb', Token.get(doc.id).token
+ assert_equal 'aaaa', Token.get(doc.id, database(original_name)).token
+ end
+
+ # delete prior db
+ Time.stub :now, Time.gm(2015,3,8,1) do
+ Token.rotate_database_now(:window => 1.hour)
+ assert_equal 1, count_dbs
+ end
+ end
+
+ private
+
+ def database(db_name)
+ Token.server.database(Token.db_name_with_prefix(db_name))
+ end
+
+ def database_exists?(dbname)
+ Token.database_exists?(dbname)
+ end
+
+ def delete_all_dbs(regexp=TEST_DB_RE)
+ Token.server.databases.each do |db|
+ if regexp.match(db)
+ Token.server.database(db).delete!
+ end
+ end
+ end
+
+ def count_dbs(regexp=TEST_DB_RE)
+ Token.server.databases.grep(regexp).count
+ end
+
+end
diff --git a/vendor/gems/couchrest_session_store/test/session_document_test.rb b/vendor/gems/couchrest_session_store/test/session_document_test.rb
new file mode 100644
index 0000000..2125d10
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/test/session_document_test.rb
@@ -0,0 +1,27 @@
+require File.expand_path(File.dirname(__FILE__) + '/test_helper')
+
+class SessionDocumentTest < MiniTest::Test
+
+ def test_storing_session
+ sid = '1234'
+ session = {'a' => 'b'}
+ options = {}
+ doc = CouchRest::Session::Document.build_or_update(sid, session, options)
+ doc.save
+ doc.fetch(sid)
+ assert_equal session, doc.to_session
+ end
+
+ def test_storing_session_with_conflict
+ sid = '1234'
+ session = {'a' => 'b'}
+ options = {}
+ doc = CouchRest::Session::Document.build_or_update(sid, session, options)
+ doc2 = CouchRest::Session::Document.build_or_update(sid, session, options)
+ doc.save
+ doc2.save
+ doc2.fetch(sid)
+ assert_equal session, doc2.to_session
+ end
+
+end
diff --git a/vendor/gems/couchrest_session_store/test/setup_couch.sh b/vendor/gems/couchrest_session_store/test/setup_couch.sh
new file mode 100755
index 0000000..731534b
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/test/setup_couch.sh
@@ -0,0 +1,7 @@
+HOST="http://localhost:5984"
+echo "couch version :"
+curl -X GET $HOST
+
+curl -X PUT $HOST/couchrest_sessions
+curl -X PUT $HOST/couchrest_sessions/_design/Session --data @design/Session.json
+
diff --git a/vendor/gems/couchrest_session_store/test/stress_test.rb b/vendor/gems/couchrest_session_store/test/stress_test.rb
new file mode 100644
index 0000000..b74b132
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/test/stress_test.rb
@@ -0,0 +1,51 @@
+require_relative 'test_helper'
+
+#
+# This doesn't really test much, but is useful if you want to see what happens
+# when you have a lot of documents.
+#
+
+class StressTest < MiniTest::Test
+
+ COUNT = 200 # change to 200,000 if you dare
+
+ class Stress < CouchRest::Model::Base
+ include CouchRest::Model::Rotation
+ property :token, String
+ property :expires_at, Time
+ rotate_database 'stress_test', :every => 1.day, :expiration_field => :expires_at
+ end
+
+ def test_stress
+ delete_all_dbs /^couchrest_stress_test_\d+$/
+
+ Stress.database!
+ COUNT.times do |i|
+ doc = Stress.create!(:token => SecureRandom.hex(32), :expires_at => expires(i))
+ end
+
+ Time.stub :now, 1.day.from_now do
+ Stress.rotate_database_now(:window => 1.hour)
+ sleep 0.5
+ assert_equal (COUNT/100)+1, Stress.database.info["doc_count"]
+ end
+ end
+
+ private
+
+ def delete_all_dbs(regexp=TEST_DB_RE)
+ Stress.server.databases.each do |db|
+ if regexp.match(db)
+ Stress.server.database(db).delete!
+ end
+ end
+ end
+
+ def expires(i)
+ if i % 100 == 0
+ 1.hour.from_now.utc
+ else
+ 1.hour.ago.utc
+ end
+ end
+end
diff --git a/vendor/gems/couchrest_session_store/test/test_clock.rb b/vendor/gems/couchrest_session_store/test/test_clock.rb
new file mode 100644
index 0000000..4170763
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/test/test_clock.rb
@@ -0,0 +1,12 @@
+class TestClock
+ attr_accessor :now
+
+ def initialize(tick = 60)
+ @tick = tick
+ @now = Time.now
+ end
+
+ def tick(seconds = nil)
+ @now += seconds || @tick
+ end
+end
diff --git a/vendor/gems/couchrest_session_store/test/test_helper.rb b/vendor/gems/couchrest_session_store/test/test_helper.rb
new file mode 100644
index 0000000..32f147d
--- /dev/null
+++ b/vendor/gems/couchrest_session_store/test/test_helper.rb
@@ -0,0 +1,9 @@
+require "rubygems"
+gem 'minitest'
+require 'minitest/autorun'
+require File.expand_path(File.dirname(__FILE__) + '/../lib/couchrest_session_store.rb')
+require File.expand_path(File.dirname(__FILE__) + '/couch_tester.rb')
+require File.expand_path(File.dirname(__FILE__) + '/test_clock.rb')
+
+# Create the session db if it does not already exist.
+CouchRest::Session::Document.create_database!