Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

rack-state

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rack-state

  • 0.0.3
  • Rubygems
  • Socket score

Version published
Maintainers
1
Created
Source

= Rack::State -- Secure & Modular State Management

Rack::State is middleware that securely stores and manages object state.

Applications use the Manager API to set, get, and delete state of any object that requires persistence in a stateless environment.

== The Core Components

  • Rack::State
  • Rack::State::Manager
  • Rack::State::Store

== Diagram of All the Players

State (middleware) | +--> Manager (env[rack.state.KEY]) <-- API (get/set/delete object) | +--> client-side: cookie (KEY = token) | +--> server-side: Store (token, object) | +--> Memory +--> File +--> Postgres +--> PreparedPostgres

The KEY and Store adapter may be set for each instance of middleware.

== Design & Motivation

=== Primary goal

State management for multiple objects with independent control of the visibility, security, and storage of each object's state.

=== But we have Rack::Session

Rack::Session provides state management, but does so using only a single SessionHash, which is statically located in Rack's environment. The drawback is the lack of fine-grained control, efficiency, and multiple instances. This single hash-like object is always available to the entire application whether it is needed or not.

I attempted to modify and bend Rack::Session to meet my design goal, but there seemed to be no clean and easy solution. Rack::State was born...

=== Use Case

An application has the following areas that require data persistence:

  1. site-wide personalization -- real name, theme, etc.
  2. blog activity tracking -- articles read, favorites, shares
  3. secure store -- TLS for entire store, shopping cart, and checkout

Three instances of Rack::State can be used. The domain, path, expiration, token security (i.e., HttpOnly & Secure cookie flags) and storage backend can be set appropriately for each area.

For example, site-wide personalization may set path to "/" with a long expiration, but the secure store could use "/store" with expiration at end of session and set the HttpOnly and Secure flags as well. Additionally, site-wide personalization and blog activity tracking states could be stored in the database while the secure store state could be saved in files.

== Usage Examples

=== Manage a single state in memory

Here's a simple rackup (config.ru) file that uses the Rack::State middleware with default options.

require 'rack' require 'rack/state'

use Rack::State

run MyApp

The application can access the State::Manager via the environment. The following code sets up Rack::State to function similarly to Rack::Session.

def session env['rack.state.token'].get or env['rack.state.token'].set Hash.new end

session['username']

=== Multiple state management with different storage adapters

Below, the flash state will use the default Memory store and store will save state in files under "tmp/state-store" in the project's root. Additionally, if "/store" requires encryption it is wise to secure the token.

use Rack::State, key: 'flash', path: '/', max_age: 60*60 use Rack::State, key: 'store', path: '/store', secure: true, store: Rack::State::Store::File.new('tmp/state-store')

Then on the application side you may have some helper methods like this:

def flash env['rack.state.flash'].get or env['rack.state.flash'].set Flash.new end

def store env['rack.state.store'] end

store.set SecureStore.new # start shopping session

store.get.cart.add :item7 flash.notice 'Added Item 7'

store.get.transaction.process flash.notice 'Transaction successful' store.delete # remove from client/server after checkout

=== Choose a specific storage adapter depending on the environment

Here we use the Postgres store for production, otherwise use the default Memory store for development and testing.

if ENV['RACK_ENV'] == 'production' DB = PG::Connection.new use Rack::State, store: Rack::State::Store::Postgres.new(DB) else use Rack::State end

=== Keep state of an arbitrary object using helper methods

First setup the middleware key and helpers.

use Rack::State, key: 'myobj'

def my_object env['rack.state.myobj'].get end

def set_my_object(obj) obj ? env['rack.state.myobj'].set(obj) : env['rack.state.myobj'].delete end

Then get state tracking in your app.

set_my_object ObjectA.new # instance of ObjectA persistently stored my_object.do_something # interact with original instance set_my_object nil # remove instance from state store set_my_object ObjectB.new # do it all again with another object

== Install, Test & Contribute

Install the gem:

$ sudo gem install rack-state

Or clone the Mercurial repository:

$ hg clone http://code.pachl.us/rack-state

State is tested with Christian Neukirchen's awesome test framework, {Bacon}[https://github.com/chneukirchen/bacon]. Get some bacon and start cooking:

$ sudo gem install bacon

Run the entire test suite from the project's root:

$ bacon -a

To test a specific component, such as a new storage adapter, run:

$ bacon -Ilib spec/spec_COMPONENT.rb

After you fix a bug or develop a storage adapter, submit your code and tests.

TODO

== Links

Homepage :: http://ecentryx.com/gems/rack-state Ruby Gem :: https://rubygems.org/gems/rack-state Source Code :: https://bitbucket.org/pachl/rack-state/src Bug Tracker :: https://bitbucket.org/pachl/rack-state/issues

== Compatibility

Rack::State was developed and tested on OpenBSD[http://www.openbsd.org] 5.3 using Ruby[https://www.ruby-lang.org] 1.9.3 and Rack[https://github.com/rack/rack] 1.5.

== History

  1. 2013-09-05, v0.0.0: Initial design, development and testing
  2. 2013-09-22, v0.0.1: First public release
  3. 2013-09-22, v0.0.2: Update Gem info and documentation
  4. 2014-04-20, v0.0.3: Add homepage and bug tracker URLs

== License

({ISC License}[http://opensource.org/licenses/ISC])

Copyright (c) 2013, Clint Pachl pachl@ecentryx.com

Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

FAQs

Package last updated on 21 Apr 2014

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc