diff --git a/.formatter.exs b/.formatter.exs
new file mode 100644
index 0000000..d2cda26
--- /dev/null
+++ b/.formatter.exs
@@ -0,0 +1,4 @@
+# Used by "mix format"
+[
+ inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
+]
diff --git a/.gitignore b/.gitignore
index 06c8bc5..555db7f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,30 @@
-/_build
-/deps
-/docs
+# The directory Mix will write compiled artifacts to.
+/_build/
+
+# If you run "mix test --cover", coverage assets end up here.
+/cover/
+
+# The directory Mix downloads your dependencies sources to.
+/deps/
+
+# Where third-party dependencies like ExDoc output generated docs.
+/doc/
+
+# Ignore .fetch files in case you like to edit your project deps locally.
+/.fetch
+
+# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump
+
+# Also ignore archive artifacts (built via "mix archive.build").
*.ez
-.elixir_ls/
+
+# Ignore package tarball (built via "mix hex.build").
+plug_rails_cookie_session_store-*.tar
+
+# Temporary files, for example, from tests.
+/tmp/
+
+# Misc.
.idea/
*.iml
diff --git a/LICENSE.md b/LICENSE.md
index 9209f68..0ada4ef 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,4 +1,4 @@
-The MIT License (MIT)
+# The MIT License (MIT)
Copyright (c) 2014 Chris Constantin
diff --git a/README.md b/README.md
index 620325a..465c64d 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,28 @@
-PlugRailsCookieSessionStore
-===========================
+# PlugRailsCookieSessionStore
+
+[](https://hex.pm/packages/plug_rails_cookie_session_store)
+[](https://hexdocs.pm/plug_rails_cookie_session_store/)
+[](https://hex.pm/packages/plug_rails_cookie_session_store)
+[](https://github.com/cconstantin/plug_rails_cookie_session_store/blob/master/LICENSE)
+[](https://github.com/cconstantin/plug_rails_cookie_session_store/commits/master)
Rails compatible Plug session store.
This allows you to share session information between Rails and a Plug-based framework like Phoenix.
-Version Information
-===================
+## Version Information
Version 2.0 and higher require OTP 22 or higher.
## Installation
-Add PlugRailsCookieSessionStore as a dependency to your `mix.exs` file:
+Add `:plug_rails_cookie_session_store` as a dependency to your `mix.exs` file:
```elixir
def deps do
- [{:plug_rails_cookie_session_store, "~> 2.0"}]
+ [
+ {:plug_rails_cookie_session_store, "~> 2.0"}
+ ]
end
```
@@ -84,7 +90,7 @@ Plug & Rails must use the same strategy for serializing cookie data.
end
```
- You can confirm that your app uses JSON by searching for
+ You can confirm that your app uses JSON by searching for:
```ruby
Rails.application.config.action_dispatch.cookies_serializer = :json
@@ -143,3 +149,10 @@ And print it on Phoenix in whatever Controller you want:
```elixir
Logger.debug get_session(conn, "foo")
```
+
+## Copyright and License
+
+Copyright (c) 2014 Chris Constantin
+
+Released under the MIT License, which can be found in the repository in
+[LICENSE.md](./LICENSE.md).
diff --git a/doc/.build b/doc/.build
deleted file mode 100644
index 35490d7..0000000
--- a/doc/.build
+++ /dev/null
@@ -1,15 +0,0 @@
-404.html
-PlugRailsCookieSessionStore.MessageEncryptor.html
-PlugRailsCookieSessionStore.MessageVerifier.html
-PlugRailsCookieSessionStore.html
-api-reference.html
-dist/app-f27ff079945e43879c46.js
-dist/elixir-a172fe91e725dcb259e2.css
-dist/html/fonts/icomoon.eot
-dist/html/fonts/icomoon.svg
-dist/html/fonts/icomoon.ttf
-dist/html/fonts/icomoon.woff
-dist/search_items-863ec2fe87.js
-dist/sidebar_items-45722afe85.js
-index.html
-search.html
diff --git a/doc/404.html b/doc/404.html
deleted file mode 100644
index 2a9e59f..0000000
--- a/doc/404.html
+++ /dev/null
@@ -1,128 +0,0 @@
-
-
-
Sorry, but the page you were trying to get to, does not exist. You
-may want to try searching this site using the sidebar
-
- or using our API Reference page
-
-to find what you were looking for.
MessageEncryptor is a simple way to encrypt values which get stored
-somewhere you don't trust.
-The cipher text and initialization vector are base64 encoded and
-returned to you.
-This can be used in situations similar to the MessageVerifier, but where
-you don't want users to be able to determine the value of the payload.
MessageVerifier makes it easy to generate and verify messages
-which are signed to prevent tampering.
-For example, the cookie store uses this verifier to send data
-to the client. Although the data can be read by the client, he
-cannot tamper it.
This cookie store is based on Plug.Crypto.MessageVerifier
-and Plug.Crypto.Message.Encryptor which encrypts and signs
-each cookie to ensure they can't be read nor tampered with.
Since this store uses crypto features, it requires you to
-set the :secret_key_base field in your connection. This
-can be easily achieved with a plug:
plug:put_secret_key_base
-
-defput_secret_key_base(conn,_)do
- put_inconn.secret_key_base,"-- LONG STRING WITH AT LEAST 64 BYTES --"
-end
-
- Options
-
-
:encrypt - specify whether to encrypt cookies, defaults to true.
-When this option is false, the cookie is still signed, meaning it
-can't be tempered with but its contents can be read;
:encryption_salt - a salt used with conn.secret_key_base to generate
-a key for encrypting/decrypting a cookie;
:signing_salt - a salt used with conn.secret_key_base to generate a
-key for signing/verifying a cookie;
:key_iterations - option passed to Plug.Crypto.KeyGenerator
-when generating the encryption and signing keys. Defaults to 1000;
:key_length - option passed to Plug.Crypto.KeyGenerator
-when generating the encryption and signing keys. Defaults to 32;
:key_digest - option passed to Plug.Crypto.KeyGenerator
-when generating the encryption and signing keys. Defaults to :sha256;
:serializer - cookie serializer module that defines encode/1 and
-decode/1 returning an {:ok, value} tuple. Defaults to
-:external_term_format.
-
- Examples
-
-
# Use the session plug with the table name
-plugPlug.Session,store:PlugRailsCookieSessionStore,
- key:"_my_app_session",
- encryption_salt:"cookie store encryption salt",
- signing_salt:"cookie store signing salt",
- key_length:64,
- serializer:Poison
MessageEncryptor is a simple way to encrypt values which get stored
-somewhere you don't trust.
-The cipher text and initialization vector are base64 encoded and
-returned to you.
-This can be used in situations similar to the MessageVerifier, but where
-you don't want users to be able to determine the value of the payload.
MessageVerifier makes it easy to generate and verify messages
-which are signed to prevent tampering.
-For example, the cookie store uses this verifier to send data
-to the client. Although the data can be read by the client, he
-cannot tamper it.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/dist/app-f27ff079945e43879c46.js b/doc/dist/app-f27ff079945e43879c46.js
deleted file mode 100644
index d87baed..0000000
--- a/doc/dist/app-f27ff079945e43879c46.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/*! For license information please see app-f27ff079945e43879c46.js.LICENSE.txt */
-!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=49)}([function(e,t,n){"use strict";function r(e){if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(e=function(e,t){if(!e)return;if("string"==typeof e)return o(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return o(e,t)}(e))){var t=0,n=function(){};return{s:n,n:function(){return t>=e.length?{done:!0}:{done:!1,value:e[t++]}},e:function(e){throw e},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,i,a=!0,l=!1;return{s:function(){r=e[Symbol.iterator]()},n:function(){var e=r.next();return a=e.done,e},e:function(e){l=!0,i=e},f:function(){try{a||null==r.return||r.return()}finally{if(l)throw i}}}}function o(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n/g,">").replace(/"/g,""")}function u(){return document.body.dataset.type}function c(e,t){if(e){var n,o=r(e);try{for(o.s();!(n=o.n()).done;){var i=n.value,a=i.nodeGroups&&i.nodeGroups.find((function(e){return e.nodes.some((function(e){return e.anchor===t}))}));if(a)return a.key}}catch(e){o.e(e)}finally{o.f()}return null}}function d(){return window.location.hash.replace(/^#/,"")}function f(e){return new URLSearchParams(window.location.search).get(e)}function p(e){return fetch(e).then((function(e){return e.ok})).catch((function(){return!1}))}function h(e){"loading"!==document.readyState?e():document.addEventListener("DOMContentLoaded",e)}function m(e){return!e||""===e.trim()}function y(e,t){var n;return function(){for(var r=arguments.length,o=new Array(r),i=0;i":">",'"':""","'":"'","`":"`","=":"="},o=/[&<>"'`=]/g,i=/[&<>"'`=]/;function a(e){return r[e]}function l(e){for(var t=1;t0){var s=I.utils.clone(t)||{};s.position=[a,l],s.index=o.length,o.push(new I.Token(n.slice(a,i),s))}a=i+1}}return o},I.tokenizer.separator=/[\s\-]+/,I.Pipeline=function(){this._stack=[]},I.Pipeline.registeredFunctions=Object.create(null),I.Pipeline.registerFunction=function(e,t){t in this.registeredFunctions&&I.utils.warn("Overwriting existing registered function: "+t),e.label=t,I.Pipeline.registeredFunctions[e.label]=e},I.Pipeline.warnIfFunctionNotRegistered=function(e){e.label&&e.label in this.registeredFunctions||I.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},I.Pipeline.load=function(e){var t=new I.Pipeline;return e.forEach((function(e){var n=I.Pipeline.registeredFunctions[e];if(!n)throw new Error("Cannot load unregistered function: "+e);t.add(n)})),t},I.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach((function(e){I.Pipeline.warnIfFunctionNotRegistered(e),this._stack.push(e)}),this)},I.Pipeline.prototype.after=function(e,t){I.Pipeline.warnIfFunctionNotRegistered(t);var n=this._stack.indexOf(e);if(-1==n)throw new Error("Cannot find existingFn");n+=1,this._stack.splice(n,0,t)},I.Pipeline.prototype.before=function(e,t){I.Pipeline.warnIfFunctionNotRegistered(t);var n=this._stack.indexOf(e);if(-1==n)throw new Error("Cannot find existingFn");this._stack.splice(n,0,t)},I.Pipeline.prototype.remove=function(e){var t=this._stack.indexOf(e);-1!=t&&this._stack.splice(t,1)},I.Pipeline.prototype.run=function(e){for(var t=this._stack.length,n=0;n1&&(ie&&(n=o),i!=e);)r=n-t,o=t+Math.floor(r/2),i=this.elements[2*o];return i==e||i>e?2*o:il?u+=2:a==l&&(t+=n[s+1]*r[u+1],s+=2,u+=2);return t},I.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},I.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),t=1,n=0;t0){var i,a=o.str.charAt(0);a in o.node.edges?i=o.node.edges[a]:(i=new I.TokenSet,o.node.edges[a]=i),1==o.str.length&&(i.final=!0),r.push({node:i,editsRemaining:o.editsRemaining,str:o.str.slice(1)})}if(0!=o.editsRemaining){if("*"in o.node.edges)var l=o.node.edges["*"];else{l=new I.TokenSet;o.node.edges["*"]=l}if(0==o.str.length&&(l.final=!0),r.push({node:l,editsRemaining:o.editsRemaining-1,str:o.str}),o.str.length>1&&r.push({node:o.node,editsRemaining:o.editsRemaining-1,str:o.str.slice(1)}),1==o.str.length&&(o.node.final=!0),o.str.length>=1){if("*"in o.node.edges)var s=o.node.edges["*"];else{s=new I.TokenSet;o.node.edges["*"]=s}1==o.str.length&&(s.final=!0),r.push({node:s,editsRemaining:o.editsRemaining-1,str:o.str.slice(1)})}if(o.str.length>1){var u,c=o.str.charAt(0),d=o.str.charAt(1);d in o.node.edges?u=o.node.edges[d]:(u=new I.TokenSet,o.node.edges[d]=u),1==o.str.length&&(u.final=!0),r.push({node:u,editsRemaining:o.editsRemaining-1,str:c+o.str.slice(2)})}}}return n},I.TokenSet.fromString=function(e){for(var t=new I.TokenSet,n=t,r=0,o=e.length;r=e;t--){var n=this.uncheckedNodes[t],r=n.child.toString();r in this.minimizedNodes?n.parent.edges[n.char]=this.minimizedNodes[r]:(n.child._str=r,this.minimizedNodes[r]=n.child),this.uncheckedNodes.pop()}},I.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},I.Index.prototype.search=function(e){return this.query((function(t){new I.QueryParser(e,t).parse()}))},I.Index.prototype.query=function(e){for(var t=new I.Query(this.fields),n=Object.create(null),r=Object.create(null),o=Object.create(null),i=Object.create(null),a=Object.create(null),l=0;l1?1:e},I.Builder.prototype.k1=function(e){this._k1=e},I.Builder.prototype.add=function(e,t){var n=e[this._ref],r=Object.keys(this._fields);this._documents[n]=t||{},this.documentCount+=1;for(var o=0;o=this.length)return I.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},I.QueryLexer.prototype.width=function(){return this.pos-this.start},I.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},I.QueryLexer.prototype.backup=function(){this.pos-=1},I.QueryLexer.prototype.acceptDigitRun=function(){var e,t;do{t=(e=this.next()).charCodeAt(0)}while(t>47&&t<58);e!=I.QueryLexer.EOS&&this.backup()},I.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(I.QueryLexer.TERM)),e.ignore(),e.more())return I.QueryLexer.lexText},I.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(I.QueryLexer.EDIT_DISTANCE),I.QueryLexer.lexText},I.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(I.QueryLexer.BOOST),I.QueryLexer.lexText},I.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(I.QueryLexer.TERM)},I.QueryLexer.termSeparator=I.tokenizer.separator,I.QueryLexer.lexText=function(e){for(;;){var t=e.next();if(t==I.QueryLexer.EOS)return I.QueryLexer.lexEOS;if(92!=t.charCodeAt(0)){if(":"==t)return I.QueryLexer.lexField;if("~"==t)return e.backup(),e.width()>0&&e.emit(I.QueryLexer.TERM),I.QueryLexer.lexEditDistance;if("^"==t)return e.backup(),e.width()>0&&e.emit(I.QueryLexer.TERM),I.QueryLexer.lexBoost;if("+"==t&&1===e.width())return e.emit(I.QueryLexer.PRESENCE),I.QueryLexer.lexText;if("-"==t&&1===e.width())return e.emit(I.QueryLexer.PRESENCE),I.QueryLexer.lexText;if(t.match(I.QueryLexer.termSeparator))return I.QueryLexer.lexTerm}else e.escapeCharacter()}},I.QueryParser=function(e,t){this.lexer=new I.QueryLexer(e),this.query=t,this.currentClause={},this.lexemeIdx=0},I.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=I.QueryParser.parseClause;e;)e=e(this);return this.query},I.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},I.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},I.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},I.QueryParser.parseClause=function(e){var t=e.peekLexeme();if(null!=t)switch(t.type){case I.QueryLexer.PRESENCE:return I.QueryParser.parsePresence;case I.QueryLexer.FIELD:return I.QueryParser.parseField;case I.QueryLexer.TERM:return I.QueryParser.parseTerm;default:var n="expected either a field or a term, found "+t.type;throw t.str.length>=1&&(n+=" with value '"+t.str+"'"),new I.QueryParseError(n,t.start,t.end)}},I.QueryParser.parsePresence=function(e){var t=e.consumeLexeme();if(null!=t){switch(t.str){case"-":e.currentClause.presence=I.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=I.Query.presence.REQUIRED;break;default:var n="unrecognised presence operator'"+t.str+"'";throw new I.QueryParseError(n,t.start,t.end)}var r=e.peekLexeme();if(null==r){n="expecting term or field, found nothing";throw new I.QueryParseError(n,t.start,t.end)}switch(r.type){case I.QueryLexer.FIELD:return I.QueryParser.parseField;case I.QueryLexer.TERM:return I.QueryParser.parseTerm;default:n="expecting term or field, found '"+r.type+"'";throw new I.QueryParseError(n,r.start,r.end)}}},I.QueryParser.parseField=function(e){var t=e.consumeLexeme();if(null!=t){if(-1==e.query.allFields.indexOf(t.str)){var n=e.query.allFields.map((function(e){return"'"+e+"'"})).join(", "),r="unrecognised field '"+t.str+"', possible fields: "+n;throw new I.QueryParseError(r,t.start,t.end)}e.currentClause.fields=[t.str];var o=e.peekLexeme();if(null==o){r="expecting term, found nothing";throw new I.QueryParseError(r,t.start,t.end)}switch(o.type){case I.QueryLexer.TERM:return I.QueryParser.parseTerm;default:r="expecting term, found '"+o.type+"'";throw new I.QueryParseError(r,o.start,o.end)}}},I.QueryParser.parseTerm=function(e){var t=e.consumeLexeme();if(null!=t){e.currentClause.term=t.str.toLowerCase(),-1!=t.str.indexOf("*")&&(e.currentClause.usePipeline=!1);var n=e.peekLexeme();if(null!=n)switch(n.type){case I.QueryLexer.TERM:return e.nextClause(),I.QueryParser.parseTerm;case I.QueryLexer.FIELD:return e.nextClause(),I.QueryParser.parseField;case I.QueryLexer.EDIT_DISTANCE:return I.QueryParser.parseEditDistance;case I.QueryLexer.BOOST:return I.QueryParser.parseBoost;case I.QueryLexer.PRESENCE:return e.nextClause(),I.QueryParser.parsePresence;default:var r="Unexpected lexeme type '"+n.type+"'";throw new I.QueryParseError(r,n.start,n.end)}else e.nextClause()}},I.QueryParser.parseEditDistance=function(e){var t=e.consumeLexeme();if(null!=t){var n=parseInt(t.str,10);if(isNaN(n)){var r="edit distance must be numeric";throw new I.QueryParseError(r,t.start,t.end)}e.currentClause.editDistance=n;var o=e.peekLexeme();if(null!=o)switch(o.type){case I.QueryLexer.TERM:return e.nextClause(),I.QueryParser.parseTerm;case I.QueryLexer.FIELD:return e.nextClause(),I.QueryParser.parseField;case I.QueryLexer.EDIT_DISTANCE:return I.QueryParser.parseEditDistance;case I.QueryLexer.BOOST:return I.QueryParser.parseBoost;case I.QueryLexer.PRESENCE:return e.nextClause(),I.QueryParser.parsePresence;default:r="Unexpected lexeme type '"+o.type+"'";throw new I.QueryParseError(r,o.start,o.end)}else e.nextClause()}},I.QueryParser.parseBoost=function(e){var t=e.consumeLexeme();if(null!=t){var n=parseInt(t.str,10);if(isNaN(n)){var r="boost must be numeric";throw new I.QueryParseError(r,t.start,t.end)}e.currentClause.boost=n;var o=e.peekLexeme();if(null!=o)switch(o.type){case I.QueryLexer.TERM:return e.nextClause(),I.QueryParser.parseTerm;case I.QueryLexer.FIELD:return e.nextClause(),I.QueryParser.parseField;case I.QueryLexer.EDIT_DISTANCE:return I.QueryParser.parseEditDistance;case I.QueryLexer.BOOST:return I.QueryParser.parseBoost;case I.QueryLexer.PRESENCE:return e.nextClause(),I.QueryParser.parsePresence;default:r="Unexpected lexeme type '"+o.type+"'";throw new I.QueryParseError(r,o.start,o.end)}else e.nextClause()}},void 0===(o="function"==typeof(r=function(){return I})?r.call(t,n,t,e):r)||(e.exports=o)}()},function(e,t,n){"use strict";n.d(t,"a",(function(){return o}));var r=n(0);function o(){Object(r.m)("[data-group-id]").forEach((function(e){var t=e.getAttribute("data-group-id");e.addEventListener("mouseenter",(function(e){i(t,!0)})),e.addEventListener("mouseleave",(function(e){i(t,!1)}))}))}function i(e,t){Object(r.m)('[data-group-id="'.concat(e,'"]')).forEach((function(e){e.classList.toggle("hll",t)}))}},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}t.__esModule=!0,t.HandlebarsEnvironment=c;var o=n(2),i=r(n(3)),a=n(8),l=n(35),s=r(n(9)),u=n(10);t.VERSION="4.7.6";t.COMPILER_REVISION=8;t.LAST_COMPATIBLE_COMPILER_REVISION=7;t.REVISION_CHANGES={1:"<= 1.0.rc.2",2:"== 1.0.0-rc.3",3:"== 1.0.0-rc.4",4:"== 1.x.x",5:"== 2.0.0-alpha.x",6:">= 2.0.0-beta.1",7:">= 4.0.0 <4.3.0",8:">= 4.3.0"};function c(e,t,n){this.helpers=e||{},this.partials=t||{},this.decorators=n||{},a.registerDefaultHelpers(this),l.registerDefaultDecorators(this)}c.prototype={constructor:c,logger:s.default,log:s.default.log,registerHelper:function(e,t){if("[object Object]"===o.toString.call(e)){if(t)throw new i.default("Arg not supported with multiple helpers");o.extend(this.helpers,e)}else this.helpers[e]=t},unregisterHelper:function(e){delete this.helpers[e]},registerPartial:function(e,t){if("[object Object]"===o.toString.call(e))o.extend(this.partials,e);else{if(void 0===t)throw new i.default('Attempting to register a partial called "'+e+'" as undefined');this.partials[e]=t}},unregisterPartial:function(e){delete this.partials[e]},registerDecorator:function(e,t){if("[object Object]"===o.toString.call(e)){if(t)throw new i.default("Arg not supported with multiple decorators");o.extend(this.decorators,e)}else this.decorators[e]=t},unregisterDecorator:function(e){delete this.decorators[e]},resetLoggedPropertyAccesses:function(){u.resetLoggedProperties()}};var d=s.default.log;t.log=d,t.createFrame=o.createFrame,t.logger=s.default},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}t.__esModule=!0,t.registerDefaultHelpers=function(e){o.default(e),i.default(e),a.default(e),l.default(e),s.default(e),u.default(e),c.default(e)},t.moveHelperToHooks=function(e,t,n){e.helpers[t]&&(e.hooks[t]=e.helpers[t],n||delete e.helpers[t])};var o=r(n(28)),i=r(n(29)),a=r(n(30)),l=r(n(31)),s=r(n(32)),u=r(n(33)),c=r(n(34))},function(e,t,n){"use strict";t.__esModule=!0;var r=n(2),o={methodMap:["debug","info","warn","error"],level:"info",lookupLevel:function(e){if("string"==typeof e){var t=r.indexOf(o.methodMap,e.toLowerCase());e=t>=0?t:parseInt(e,10)}return e},log:function(e){if(e=o.lookupLevel(e),"undefined"!=typeof console&&o.lookupLevel(o.level)<=e){var t=o.methodMap[e];console[t]||(t="log");for(var n=arguments.length,r=Array(n>1?n-1:0),i=1;i=t||n<0||h&&e-u>=i}function w(){var e=p();if(x(e))return O(e);l=setTimeout(w,function(e){var n=t-(e-s);return h?f(n,i-(e-u)):n}(e))}function O(e){return l=void 0,v&&r?g(e):(r=o=void 0,a)}function k(){var e=p(),n=x(e);if(r=arguments,o=this,s=e,n){if(void 0===l)return b(s);if(h)return l=setTimeout(w,t),g(s)}return void 0===l&&(l=setTimeout(w,t)),a}return t=y(t)||0,m(n)&&(c=!!n.leading,i=(h="maxWait"in n)?d(y(n.maxWait)||0,t):i,v="trailing"in n?!!n.trailing:v),k.cancel=function(){void 0!==l&&clearTimeout(l),u=0,r=s=o=l=void 0},k.flush=function(){return void 0===l?a:O(p())},k}function m(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}function y(e){if("number"==typeof e)return e;if(function(e){return"symbol"==typeof e||function(e){return!!e&&"object"==typeof e}(e)&&"[object Symbol]"==c.call(e)}(e))return NaN;if(m(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=m(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(n,"");var l=o.test(e);return l||i.test(e)?a(e.slice(2),l?2:8):r.test(e)?NaN:+e}e.exports=function(e,t,n){var r=!0,o=!0;if("function"!=typeof e)throw new TypeError("Expected a function");return m(n)&&(r="leading"in n?!!n.leading:r,o="trailing"in n?!!n.trailing:o),h(e,t,{leading:r,maxWait:t,trailing:o})}}).call(this,n(6))},function(e,t,n){var r=n(1);function o(e){return e&&(e.__esModule?e.default:e)}e.exports=(r.default||r).template({1:function(e,t,r,i,a,l,s){var u,c=null!=t?t:e.nullContext||{},d=e.lambda,f=e.escapeExpression,p=e.lookupProperty||function(e,t){if(Object.prototype.hasOwnProperty.call(e,t))return e[t]};return(null!=(u=o(n(42)).call(c,s[1],null!=(u=l[0][0])?p(u,"group"):u,{name:"groupChanged",hash:{},fn:e.program(2,a,0,l,s),inverse:e.noop,data:a,blockParams:l,loc:{start:{line:2,column:2},end:{line:4,column:19}}}))?u:"")+"\n"+(null!=(u=o(n(43)).call(c,s[1],l[0][0],{name:"nestingChanged",hash:{},fn:e.program(4,a,0,l,s),inverse:e.noop,data:a,blockParams:l,loc:{start:{line:6,column:2},end:{line:8,column:21}}}))?u:"")+'\n
-
-
-
-
diff --git a/lib/plug_rails_cookie_session_store.ex b/lib/plug_rails_cookie_session_store.ex
index 7399f30..5604b5d 100644
--- a/lib/plug_rails_cookie_session_store.ex
+++ b/lib/plug_rails_cookie_session_store.ex
@@ -50,6 +50,7 @@ defmodule PlugRailsCookieSessionStore do
signing_salt: "cookie store signing salt",
key_length: 64,
serializer: Poison
+
"""
@behaviour Plug.Session.Store
diff --git a/lib/plug_rails_cookie_session_store/message_encryptor.ex b/lib/plug_rails_cookie_session_store/message_encryptor.ex
index 06c1345..e2449bd 100644
--- a/lib/plug_rails_cookie_session_store/message_encryptor.ex
+++ b/lib/plug_rails_cookie_session_store/message_encryptor.ex
@@ -2,11 +2,15 @@ defmodule PlugRailsCookieSessionStore.MessageEncryptor do
@moduledoc ~S"""
`MessageEncryptor` is a simple way to encrypt values which get stored
somewhere you don't trust.
+
The cipher text and initialization vector are base64 encoded and
returned to you.
+
This can be used in situations similar to the `MessageVerifier`, but where
you don't want users to be able to determine the value of the payload.
+
## Example
+
secret_key_base = "072d1e0157c008193fe48a670cce031faa4e..."
encrypted_cookie_salt = "encrypted cookie"
encrypted_signed_cookie_salt = "signed encrypted cookie"
@@ -17,6 +21,7 @@ defmodule PlugRailsCookieSessionStore.MessageEncryptor do
encrypted = MessageEncryptor.encrypt_and_sign(encryptor, data)
decrypted = MessageEncryptor.verify_and_decrypt(encryptor, encrypted)
decrypted.current_user.name # => "José"
+
"""
alias PlugRailsCookieSessionStore.MessageVerifier
@@ -38,6 +43,7 @@ defmodule PlugRailsCookieSessionStore.MessageEncryptor do
@doc """
Decrypts and verifies a message.
+
We need to verify the message in order to avoid padding attacks.
Reference: http://www.limited-entropy.com/padding-oracle-attacks
"""
diff --git a/lib/plug_rails_cookie_session_store/message_verifier.ex b/lib/plug_rails_cookie_session_store/message_verifier.ex
index 059a4dd..8cb3223 100644
--- a/lib/plug_rails_cookie_session_store/message_verifier.ex
+++ b/lib/plug_rails_cookie_session_store/message_verifier.ex
@@ -2,13 +2,14 @@ defmodule PlugRailsCookieSessionStore.MessageVerifier do
@moduledoc """
`MessageVerifier` makes it easy to generate and verify messages
which are signed to prevent tampering.
+
For example, the cookie store uses this verifier to send data
to the client. Although the data can be read by the client, he
cannot tamper it.
"""
@doc """
- Decodes and verifies the encoded binary was not tampared with.
+ Decodes and verifies the encoded binary was not tampered with.
"""
def verify(binary, secret) when is_binary(binary) and is_binary(secret) do
case String.split(binary, "--") do
diff --git a/mix.exs b/mix.exs
index 09a5d4a..ed31468 100644
--- a/mix.exs
+++ b/mix.exs
@@ -1,32 +1,36 @@
defmodule PlugRailsCookieSessionStore.Mixfile do
use Mix.Project
+ @source_url "https://github.com/cconstantin/plug_rails_cookie_session_store"
+ @version "2.0.0"
+
def project do
[
app: :plug_rails_cookie_session_store,
- version: "2.0.0",
+ version: @version,
elixir: "~> 1.0",
- description: description(),
package: package(),
- deps: deps()
+ deps: deps(),
+ docs: docs()
]
end
def application do
- [applications: [:crypto, :logger, :plug_crypto]]
- end
-
- defp description do
- "Rails compatible Plug session store"
+ [
+ applications: [:crypto, :logger, :plug_crypto]
+ ]
end
defp package do
[
name: :plug_rails_cookie_session_store,
+ description: "Rails compatible Plug session store",
files: ["lib", "mix.exs", "README*", "LICENSE*"],
maintainers: ["Chris Constantin"],
licenses: ["MIT"],
- links: %{"Github" => "https://github.com/cconstantin/plug_rails_cookie_session_store"}
+ links: %{
+ "GitHub" => @source_url
+ }
]
end
@@ -34,7 +38,19 @@ defmodule PlugRailsCookieSessionStore.Mixfile do
[
{:plug, ">= 1.11.0"},
{:plug_crypto, ">= 1.2.0"},
- {:ex_doc, ">= 0.24.2", only: :dev}
+ {:ex_doc, ">= 0.24.2", only: :dev, runtime: false}
+ ]
+ end
+
+ defp docs do
+ [
+ extras: [
+ "LICENSE.md": [title: "License"],
+ "README.md": [title: "Overview"]
+ ],
+ main: "readme",
+ source_url: @source_url,
+ formatters: ["html"]
]
end
end