diff options
| author | HumairAK <humair88@hotmail.com> | 2016-07-21 06:24:24 +0000 |
|---|---|---|
| committer | HumairAK <humair88@hotmail.com> | 2016-07-21 06:24:24 +0000 |
| commit | 2549ee68e435b77e7e07d3ea95363268cbfe9164 (patch) | |
| tree | 8f48f6447a4377f1bc15ae7d73dbab3337044720 /node_modules/express-session | |
| parent | d694c1a73f77def42c17b58027f046bf9e1af809 (diff) | |
Added other dependencies for authentication, made minor adjustments to index.js, added templating for exams, will remove dependencie modules later, keep for now
Diffstat (limited to 'node_modules/express-session')
| -rw-r--r-- | node_modules/express-session/HISTORY.md | 314 | ||||
| -rw-r--r-- | node_modules/express-session/LICENSE | 24 | ||||
| -rw-r--r-- | node_modules/express-session/README.md | 655 | ||||
| -rw-r--r-- | node_modules/express-session/index.js | 637 | ||||
| -rw-r--r-- | node_modules/express-session/package.json | 121 | ||||
| -rw-r--r-- | node_modules/express-session/session/cookie.js | 129 | ||||
| -rw-r--r-- | node_modules/express-session/session/memory.js | 185 | ||||
| -rw-r--r-- | node_modules/express-session/session/session.js | 142 | ||||
| -rw-r--r-- | node_modules/express-session/session/store.js | 94 |
9 files changed, 2301 insertions, 0 deletions
diff --git a/node_modules/express-session/HISTORY.md b/node_modules/express-session/HISTORY.md new file mode 100644 index 0000000..8ec8885 --- /dev/null +++ b/node_modules/express-session/HISTORY.md @@ -0,0 +1,314 @@ +1.14.0 / 2016-07-01 +=================== + + * Correctly inherit from `EventEmitter` class in `Store` base class + * Fix issue where `Set-Cookie` `Expires` was not always updated + * Methods are no longer enumerable on `req.session` object + * deps: cookie@0.3.1 + - Add `sameSite` option + - Improve error message when `encode` is not a function + - Improve error message when `expires` is not a `Date` + - perf: enable strict mode + - perf: use for loop in parse + - perf: use string concatination for serialization + * deps: parseurl@~1.3.1 + - perf: enable strict mode + * deps: uid-safe@~2.1.1 + - Use `random-bytes` for byte source + - deps: base64-url@1.2.2 + * perf: enable strict mode + * perf: remove argument reassignment + +1.13.0 / 2016-01-10 +=================== + + * Fix `rolling: true` to not set cookie when no session exists + - Better `saveUninitialized: false` + `rolling: true` behavior + * deps: crc@3.4.0 + +1.12.1 / 2015-10-29 +=================== + + * deps: cookie@0.2.3 + - Fix cookie `Max-Age` to never be a floating point number + +1.12.0 / 2015-10-25 +=================== + + * Support the value `'auto'` in the `cookie.secure` option + * deps: cookie@0.2.2 + - Throw on invalid values provided to `serialize` + * deps: depd@~1.1.0 + - Enable strict mode in more places + - Support web browser loading + * deps: on-headers@~1.0.1 + - perf: enable strict mode + +1.11.3 / 2015-05-22 +=================== + + * deps: cookie@0.1.3 + - Slight optimizations + * deps: crc@3.3.0 + +1.11.2 / 2015-05-10 +=================== + + * deps: debug@~2.2.0 + - deps: ms@0.7.1 + * deps: uid-safe@~2.0.0 + +1.11.1 / 2015-04-08 +=================== + + * Fix mutating `options.secret` value + +1.11.0 / 2015-04-07 +=================== + + * Support an array in `secret` option for key rotation + * deps: depd@~1.0.1 + +1.10.4 / 2015-03-15 +=================== + + * deps: debug@~2.1.3 + - Fix high intensity foreground color for bold + - deps: ms@0.7.0 + +1.10.3 / 2015-02-16 +=================== + + * deps: cookie-signature@1.0.6 + * deps: uid-safe@1.1.0 + - Use `crypto.randomBytes`, if available + - deps: base64-url@1.2.1 + +1.10.2 / 2015-01-31 +=================== + + * deps: uid-safe@1.0.3 + - Fix error branch that would throw + - deps: base64-url@1.2.0 + +1.10.1 / 2015-01-08 +=================== + + * deps: uid-safe@1.0.2 + - Remove dependency on `mz` + +1.10.0 / 2015-01-05 +=================== + + * Add `store.touch` interface for session stores + * Fix `MemoryStore` expiration with `resave: false` + * deps: debug@~2.1.1 + +1.9.3 / 2014-12-02 +================== + + * Fix error when `req.sessionID` contains a non-string value + +1.9.2 / 2014-11-22 +================== + + * deps: crc@3.2.1 + - Minor fixes + +1.9.1 / 2014-10-22 +================== + + * Remove unnecessary empty write call + - Fixes Node.js 0.11.14 behavior change + - Helps work-around Node.js 0.10.1 zlib bug + +1.9.0 / 2014-09-16 +================== + + * deps: debug@~2.1.0 + - Implement `DEBUG_FD` env variable support + * deps: depd@~1.0.0 + +1.8.2 / 2014-09-15 +================== + + * Use `crc` instead of `buffer-crc32` for speed + * deps: depd@0.4.5 + +1.8.1 / 2014-09-08 +================== + + * Keep `req.session.save` non-enumerable + * Prevent session prototype methods from being overwritten + +1.8.0 / 2014-09-07 +================== + + * Do not resave already-saved session at end of request + * deps: cookie-signature@1.0.5 + * deps: debug@~2.0.0 + +1.7.6 / 2014-08-18 +================== + + * Fix exception on `res.end(null)` calls + +1.7.5 / 2014-08-10 +================== + + * Fix parsing original URL + * deps: on-headers@~1.0.0 + * deps: parseurl@~1.3.0 + +1.7.4 / 2014-08-05 +================== + + * Fix response end delay for non-chunked responses + +1.7.3 / 2014-08-05 +================== + + * Fix `res.end` patch to call correct upstream `res.write` + +1.7.2 / 2014-07-27 +================== + + * deps: depd@0.4.4 + - Work-around v8 generating empty stack traces + +1.7.1 / 2014-07-26 +================== + + * deps: depd@0.4.3 + - Fix exception when global `Error.stackTraceLimit` is too low + +1.7.0 / 2014-07-22 +================== + + * Improve session-ending error handling + - Errors are passed to `next(err)` instead of `console.error` + * deps: debug@1.0.4 + * deps: depd@0.4.2 + - Add `TRACE_DEPRECATION` environment variable + - Remove non-standard grey color from color output + - Support `--no-deprecation` argument + - Support `--trace-deprecation` argument + +1.6.5 / 2014-07-11 +================== + + * Do not require `req.originalUrl` + * deps: debug@1.0.3 + - Add support for multiple wildcards in namespaces + +1.6.4 / 2014-07-07 +================== + + * Fix blank responses for stores with synchronous operations + +1.6.3 / 2014-07-04 +================== + + * Fix resave deprecation message + +1.6.2 / 2014-07-04 +================== + + * Fix confusing option deprecation messages + +1.6.1 / 2014-06-28 +================== + + * Fix saveUninitialized deprecation message + +1.6.0 / 2014-06-28 +================== + + * Add deprecation message to undefined `resave` option + * Add deprecation message to undefined `saveUninitialized` option + * Fix `res.end` patch to return correct value + * Fix `res.end` patch to handle multiple `res.end` calls + * Reject cookies with missing signatures + +1.5.2 / 2014-06-26 +================== + + * deps: cookie-signature@1.0.4 + - fix for timing attacks + +1.5.1 / 2014-06-21 +================== + + * Move hard-to-track-down `req.secret` deprecation message + +1.5.0 / 2014-06-19 +================== + + * Debug name is now "express-session" + * Deprecate integration with `cookie-parser` middleware + * Deprecate looking for secret in `req.secret` + * Directly read cookies; `cookie-parser` no longer required + * Directly set cookies; `res.cookie` no longer required + * Generate session IDs with `uid-safe`, faster and even less collisions + +1.4.0 / 2014-06-17 +================== + + * Add `genid` option to generate custom session IDs + * Add `saveUninitialized` option to control saving uninitialized sessions + * Add `unset` option to control unsetting `req.session` + * Generate session IDs with `rand-token` by default; reduce collisions + * deps: buffer-crc32@0.2.3 + +1.3.1 / 2014-06-14 +================== + + * Add description in package for npmjs.org listing + +1.3.0 / 2014-06-14 +================== + + * Integrate with express "trust proxy" by default + * deps: debug@1.0.2 + +1.2.1 / 2014-05-27 +================== + + * Fix `resave` such that `resave: true` works + +1.2.0 / 2014-05-19 +================== + + * Add `resave` option to control saving unmodified sessions + +1.1.0 / 2014-05-12 +================== + + * Add `name` option; replacement for `key` option + * Use `setImmediate` in MemoryStore for node.js >= 0.10 + +1.0.4 / 2014-04-27 +================== + + * deps: debug@0.8.1 + +1.0.3 / 2014-04-19 +================== + + * Use `res.cookie()` instead of `res.setHeader()` + * deps: cookie@0.1.2 + +1.0.2 / 2014-02-23 +================== + + * Add missing dependency to `package.json` + +1.0.1 / 2014-02-15 +================== + + * Add missing dependencies to `package.json` + +1.0.0 / 2014-02-15 +================== + + * Genesis from `connect` diff --git a/node_modules/express-session/LICENSE b/node_modules/express-session/LICENSE new file mode 100644 index 0000000..9b59ff8 --- /dev/null +++ b/node_modules/express-session/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2010 Sencha Inc. +Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca> +Copyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/express-session/README.md b/node_modules/express-session/README.md new file mode 100644 index 0000000..b88ed82 --- /dev/null +++ b/node_modules/express-session/README.md @@ -0,0 +1,655 @@ +# express-session + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] +[![Gratipay][gratipay-image]][gratipay-url] + +## Installation + +```bash +$ npm install express-session +``` + +## API + +```js +var session = require('express-session') +``` + +### session(options) + +Create a session middleware with the given `options`. + +**Note** Session data is _not_ saved in the cookie itself, just the session ID. +Session data is stored server-side. + +**Note** Since version 1.5.0, the [`cookie-parser` middleware](https://www.npmjs.com/package/cookie-parser) +no longer needs to be used for this module to work. This module now directly reads +and writes cookies on `req`/`res`. Using `cookie-parser` may result in issues +if the `secret` is not the same between this module and `cookie-parser`. + +**Warning** The default server-side session storage, `MemoryStore`, is _purposely_ +not designed for a production environment. It will leak memory under most +conditions, does not scale past a single process, and is meant for debugging and +developing. + +For a list of stores, see [compatible session stores](#compatible-session-stores). + +#### Options + +`express-session` accepts these properties in the options object. + +##### cookie + +Settings object for the session ID cookie. The default value is +`{ path: '/', httpOnly: true, secure: false, maxAge: null }`. + +The following are options that can be set in this object. + +###### domain + +Specifies the value for the `Domain` `Set-Cookie` attribute. By default, no domain +is set, and most clients will consider the cookie to apply to only the current +domain. + +###### expires + +Specifies the `Date` object to be the value for the `Expires` `Set-Cookie` attribute. +By default, no expiration is set, and most clients will consider this a +"non-persistent cookie" and will delete it on a condition like exiting a web browser +application. + +**Note** If both `expires` and `maxAge` are set in the options, then the last one +defined in the object is what is used. + +**Note** The `expires` option should not be set directly; instead only use the `maxAge` +option. + +###### httpOnly + +Specifies the `boolean` value for the `HttpOnly` `Set-Cookie` attribute. When truthy, +the `HttpOnly` attribute is set, otherwise it is not. By default, the `HttpOnly` +attribute is set. + +**Note** be careful when setting this to `true`, as compliant clients will not allow +client-side JavaScript to see the cookie in `document.cookie`. + +###### maxAge + +Specifies the `number` (in milliseconds) to use when calculating the `Expires` +`Set-Cookie` attribute. This is done by taking the current server time and adding +`maxAge` milliseconds to the value to calculate an `Expires` datetime. By default, +no maximum age is set. + +**Note** If both `expires` and `maxAge` are set in the options, then the last one +defined in the object is what is used. + +###### path + +Specifies the value for the `Path` `Set-Cookie`. By default, this is set to `'/'`, which +is the root path of the domain. + +###### sameSite + +Specifies the `boolean` or `string` to be the value for the `SameSite` `Set-Cookie` attribute. + + - `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement. + - `false` will not set the `SameSite` attribute. + - `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement. + - `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement. + +More information about the different enforcement levels can be found in the specification +https://tools.ietf.org/html/draft-west-first-party-cookies-07#section-4.1.1 + +**Note** This is an attribute that has not yet been fully standardized, and may change in +the future. This also means many clients may ignore this attribute until they understand it. + +###### secure + +Specifies the `boolean` value for the `Secure` `Set-Cookie` attribute. When truthy, +the `Secure` attribute is set, otherwise it is not. By default, the `Secure` +attribute is not set. + +**Note** be careful when setting this to `true`, as compliant clients will not send +the cookie back to the server in the future if the browser does not have an HTTPS +connection. + +Please note that `secure: true` is a **recommended** option. However, it requires +an https-enabled website, i.e., HTTPS is necessary for secure cookies. If `secure` +is set, and you access your site over HTTP, the cookie will not be set. If you +have your node.js behind a proxy and are using `secure: true`, you need to set +"trust proxy" in express: + +```js +var app = express() +app.set('trust proxy', 1) // trust first proxy +app.use(session({ + secret: 'keyboard cat', + resave: false, + saveUninitialized: true, + cookie: { secure: true } +})) +``` + +For using secure cookies in production, but allowing for testing in development, +the following is an example of enabling this setup based on `NODE_ENV` in express: + +```js +var app = express() +var sess = { + secret: 'keyboard cat', + cookie: {} +} + +if (app.get('env') === 'production') { + app.set('trust proxy', 1) // trust first proxy + sess.cookie.secure = true // serve secure cookies +} + +app.use(session(sess)) +``` + +The `cookie.secure` option can also be set to the special value `'auto'` to have +this setting automatically match the determined security of the connection. Be +careful when using this setting if the site is available both as HTTP and HTTPS, +as once the cookie is set on HTTPS, it will no longer be visible over HTTP. This +is useful when the Express `"trust proxy"` setting is properly setup to simplify +development vs production configuration. + +##### genid + +Function to call to generate a new session ID. Provide a function that returns +a string that will be used as a session ID. The function is given `req` as the +first argument if you want to use some value attached to `req` when generating +the ID. + +The default value is a function which uses the `uid-safe` library to generate IDs. + +**NOTE** be careful to generate unique IDs so your sessions do not conflict. + +```js +app.use(session({ + genid: function(req) { + return genuuid() // use UUIDs for session IDs + }, + secret: 'keyboard cat' +})) +``` + +##### name + +The name of the session ID cookie to set in the response (and read from in the +request). + +The default value is `'connect.sid'`. + +**Note** if you have multiple apps running on the same hostname (this is just +the name, i.e. `localhost` or `127.0.0.1`; different schemes and ports do not +name a different hostname), then you need to separate the session cookies from +each other. The simplest method is to simply set different `name`s per app. + +##### proxy + +Trust the reverse proxy when setting secure cookies (via the "X-Forwarded-Proto" +header). + +The default value is `undefined`. + + - `true` The "X-Forwarded-Proto" header will be used. + - `false` All headers are ignored and the connection is considered secure only + if there is a direct TLS/SSL connection. + - `undefined` Uses the "trust proxy" setting from express + +##### resave + +Forces the session to be saved back to the session store, even if the session +was never modified during the request. Depending on your store this may be +necessary, but it can also create race conditions where a client makes two +parallel requests to your server and changes made to the session in one +request may get overwritten when the other request ends, even if it made no +changes (this behavior also depends on what store you're using). + +The default value is `true`, but using the default has been deprecated, +as the default will change in the future. Please research into this setting +and choose what is appropriate to your use-case. Typically, you'll want +`false`. + +How do I know if this is necessary for my store? The best way to know is to +check with your store if it implements the `touch` method. If it does, then +you can safely set `resave: false`. If it does not implement the `touch` +method and your store sets an expiration date on stored sessions, then you +likely need `resave: true`. + +##### rolling + +Force a session identifier cookie to be set on every response. The expiration +is reset to the original [`maxAge`](#cookiemaxage), resetting the expiration +countdown. + +The default value is `false`. + +**Note** When this option is set to `true` but the `saveUninitialized` option is +set to `false`, the cookie will not be set on a response with an uninitialized +session. + +##### saveUninitialized + +Forces a session that is "uninitialized" to be saved to the store. A session is +uninitialized when it is new but not modified. Choosing `false` is useful for +implementing login sessions, reducing server storage usage, or complying with +laws that require permission before setting a cookie. Choosing `false` will also +help with race conditions where a client makes multiple parallel requests +without a session. + +The default value is `true`, but using the default has been deprecated, as the +default will change in the future. Please research into this setting and +choose what is appropriate to your use-case. + +**Note** if you are using Session in conjunction with PassportJS, Passport +will add an empty Passport object to the session for use after a user is +authenticated, which will be treated as a modification to the session, causing +it to be saved. *This has been fixed in PassportJS 0.3.0* + +##### secret + +**Required option** + +This is the secret used to sign the session ID cookie. This can be either a string +for a single secret, or an array of multiple secrets. If an array of secrets is +provided, only the first element will be used to sign the session ID cookie, while +all the elements will be considered when verifying the signature in requests. + +##### store + +The session store instance, defaults to a new `MemoryStore` instance. + +##### unset + +Control the result of unsetting `req.session` (through `delete`, setting to `null`, +etc.). + +The default value is `'keep'`. + + - `'destroy'` The session will be destroyed (deleted) when the response ends. + - `'keep'` The session in the store will be kept, but modifications made during + the request are ignored and not saved. + +### req.session + +To store or access session data, simply use the request property `req.session`, +which is (generally) serialized as JSON by the store, so nested objects +are typically fine. For example below is a user-specific view counter: + +```js +// Use the session middleware +app.use(session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }})) + +// Access the session as req.session +app.get('/', function(req, res, next) { + var sess = req.session + if (sess.views) { + sess.views++ + res.setHeader('Content-Type', 'text/html') + res.write('<p>views: ' + sess.views + '</p>') + res.write('<p>expires in: ' + (sess.cookie.maxAge / 1000) + 's</p>') + res.end() + } else { + sess.views = 1 + res.end('welcome to the session demo. refresh!') + } +}) +``` + +#### Session.regenerate() + +To regenerate the session simply invoke the method. Once complete, +a new SID and `Session` instance will be initialized at `req.session`. + +```js +req.session.regenerate(function(err) { + // will have a new session here +}) +``` + +#### Session.destroy() + +Destroys the session, removing `req.session`; will be re-generated next request. + +```js +req.session.destroy(function(err) { + // cannot access session here +}) +``` + +#### Session.reload() + +Reloads the session data. + +```js +req.session.reload(function(err) { + // session updated +}) +``` + +#### Session.save() + +Save the session back to the store, replacing the contents on the store with the +contents in memory (though a store may do something else--consult the store's +documentation for exact behavior). + +This method is automatically called at the end of the HTTP response if the +session data has been altered (though this behavior can be altered with various +options in the middleware constructor). Because of this, typically this method +does not need to be called. + +There are some cases where it is useful to call this method, for example, long- +lived requests or in WebSockets. + +```js +req.session.save(function(err) { + // session saved +}) +``` + +#### Session.touch() + +Updates the `.maxAge` property. Typically this is +not necessary to call, as the session middleware does this for you. + +### req.session.id + +Each session has a unique ID associated with it. This property will +contain the session ID and cannot be modified. + +### req.session.cookie + +Each session has a unique cookie object accompany it. This allows +you to alter the session cookie per visitor. For example we can +set `req.session.cookie.expires` to `false` to enable the cookie +to remain for only the duration of the user-agent. + +#### Cookie.maxAge + +Alternatively `req.session.cookie.maxAge` will return the time +remaining in milliseconds, which we may also re-assign a new value +to adjust the `.expires` property appropriately. The following +are essentially equivalent + +```js +var hour = 3600000 +req.session.cookie.expires = new Date(Date.now() + hour) +req.session.cookie.maxAge = hour +``` + +For example when `maxAge` is set to `60000` (one minute), and 30 seconds +has elapsed it will return `30000` until the current request has completed, +at which time `req.session.touch()` is called to reset `req.session.maxAge` +to its original value. + +```js +req.session.cookie.maxAge // => 30000 +``` + +### req.sessionID + +To get the ID of the loaded session, access the request property +`req.sessionID`. This is simply a read-only value set when a session +is loaded/created. + +## Session Store Implementation + +Every session store _must_ be an `EventEmitter` and implement specific +methods. The following methods are the list of **required**, **recommended**, +and **optional**. + + * Required methods are ones that this module will always call on the store. + * Recommended methods are ones that this module will call on the store if + available. + * Optional methods are ones this module does not call at all, but helps + present uniform stores to users. + +For an example implementation view the [connect-redis](http://github.com/visionmedia/connect-redis) repo. + +### store.all(callback) + +**Optional** + +This optional method is used to get all sessions in the store as an array. The +`callback` should be called as `callback(error, sessions)`. + +### store.destroy(sid, callback) + +**Required** + +This required method is used to destroy/delete a session from the store given +a session ID (`sid`). The `callback` should be called as `callback(error)` once +the session is destroyed. + +### store.clear(callback) + +**Optional** + +This optional method is used to delete all sessions from the store. The +`callback` should be called as `callback(error)` once the store is cleared. + +### store.length(callback) + +**Optional** + +This optional method is used to get the count of all sessions in the store. +The `callback` should be called as `callback(error, len)`. + +### store.get(sid, callback) + +**Required** + +This required method is used to get a session from the store given a session +ID (`sid`). The `callback` should be called as `callback(error, session)`. + +The `session` argument should be a session if found, otherwise `null` or +`undefined` if the session was not found (and there was no error). A special +case is made when `error.code === 'ENOENT'` to act like `callback(null, null)`. + +### store.set(sid, session, callback) + +**Required** + +This required method is used to upsert a session into the store given a +session ID (`sid`) and session (`session`) object. The callback should be +called as `callback(error)` once the session has been set in the store. + +### store.touch(sid, session, callback) + +**Recommended** + +This recommended method is used to "touch" a given session given a +session ID (`sid`) and session (`session`) object. The `callback` should be +called as `callback(error)` once the session has been touched. + +This is primarily used when the store will automatically delete idle sessions +and this method is used to signal to the store the given session is active, +potentially resetting the idle timer. + +## Compatible Session Stores + +The following modules implement a session store that is compatible with this +module. Please make a PR to add additional modules :) + +[![★][cassandra-store-image] cassandra-store][cassandra-store-url] An Apache Cassandra-based session store. + +[cassandra-store-url]: https://www.npmjs.com/package/cassandra-store +[cassandra-store-image]: https://img.shields.io/github/stars/webcc/cassandra-store.svg?label=%E2%98%85 + +[![★][cluster-store-image] cluster-store][cluster-store-url] A wrapper for using in-process / embedded +stores - such as SQLite (via knex), leveldb, files, or memory - with node cluster (desirable for Raspberry Pi 2 +and other multi-core embedded devices). + +[cluster-store-url]: https://www.npmjs.com/package/cluster-store +[cluster-store-image]: https://img.shields.io/github/stars/coolaj86/cluster-store.svg?label=%E2%98%85 + +[![★][connect-azuretables-image] connect-azuretables][connect-azuretables-url] An [Azure Table Storage](https://azure.microsoft.com/en-gb/services/storage/tables/)-based session store. + +[connect-azuretables-url]: https://www.npmjs.com/package/connect-azuretables +[connect-azuretables-image]: https://img.shields.io/github/stars/mike-goodwin/connect-azuretables.svg?label=%E2%98%85 + +[![★][connect-couchbase-image] connect-couchbase][connect-couchbase-url] A [couchbase](http://www.couchbase.com/)-based session store. + +[connect-couchbase-url]: https://www.npmjs.com/package/connect-couchbase +[connect-couchbase-image]: https://img.shields.io/github/stars/christophermina/connect-couchbase.svg?label=%E2%98%85 + +[![★][connect-dynamodb-image] connect-dynamodb][connect-dynamodb-url] A DynamoDB-based session store. + +[connect-dynamodb-url]: https://github.com/ca98am79/connect-dynamodb +[connect-dynamodb-image]: https://img.shields.io/github/stars/ca98am79/connect-dynamodb.svg?label=%E2%98%85 + +[![★][connect-mssql-image] connect-mssql][connect-mssql-url] A SQL Server-based session store. + +[connect-mssql-url]: https://www.npmjs.com/package/connect-mssql +[connect-mssql-image]: https://img.shields.io/github/stars/patriksimek/connect-mssql.svg?label=%E2%98%85 + +[![★][connect-monetdb-image] connect-monetdb][connect-monetdb-url] A MonetDB-based session store. + +[connect-monetdb-url]: https://www.npmjs.com/package/connect-monetdb +[connect-monetdb-image]: https://img.shields.io/github/stars/MonetDB/npm-connect-monetdb.svg?label=%E2%98%85 + +[![★][connect-mongo-image] connect-mongo][connect-mongo-url] A MongoDB-based session store. + +[connect-mongo-url]: https://www.npmjs.com/package/connect-mongo +[connect-mongo-image]: https://img.shields.io/github/stars/kcbanner/connect-mongo.svg?label=%E2%98%85 + +[![★][connect-mongodb-session-image] connect-mongodb-session][connect-mongodb-session-url] Lightweight MongoDB-based session store built and maintained by MongoDB. + +[connect-mongodb-session-url]: https://www.npmjs.com/package/connect-mongodb-session +[connect-mongodb-session-image]: https://img.shields.io/github/stars/mongodb-js/connect-mongodb-session.svg?label=%E2%98%85 + +[![★][connect-pg-simple-image] connect-pg-simple][connect-pg-simple-url] A PostgreSQL-based session store. + +[connect-pg-simple-url]: https://www.npmjs.com/package/connect-pg-simple +[connect-pg-simple-image]: https://img.shields.io/github/stars/voxpelli/node-connect-pg-simple.svg?label=%E2%98%85 + +[![★][connect-redis-image] connect-redis][connect-redis-url] A Redis-based session store. + +[connect-redis-url]: https://www.npmjs.com/package/connect-redis +[connect-redis-image]: https://img.shields.io/github/stars/tj/connect-redis.svg?label=%E2%98%85 + +[![★][connect-memcached-image] connect-memcached][connect-memcached-url] A memcached-based session store. + +[connect-memcached-url]: https://www.npmjs.com/package/connect-memcached +[connect-memcached-image]: https://img.shields.io/github/stars/balor/connect-memcached.svg?label=%E2%98%85 + +[![★][connect-session-knex-image] connect-session-knex][connect-session-knex-url] A session store using +[Knex.js](http://knexjs.org/), which is a SQL query builder for PostgreSQL, MySQL, MariaDB, SQLite3, and Oracle. + +[connect-session-knex-url]: https://www.npmjs.com/package/connect-session-knex +[connect-session-knex-image]: https://img.shields.io/github/stars/llambda/connect-session-knex.svg?label=%E2%98%85 + +[![★][connect-session-sequelize-image] connect-session-sequelize][connect-session-sequelize-url] A session store using +[Sequelize.js](http://sequelizejs.com/), which is a Node.js / io.js ORM for PostgreSQL, MySQL, SQLite and MSSQL. + +[connect-session-sequelize-url]: https://www.npmjs.com/package/connect-session-sequelize +[connect-session-sequelize-image]: https://img.shields.io/github/stars/mweibel/connect-session-sequelize.svg?label=%E2%98%85 + +[![★][express-mysql-session-image] express-mysql-session][express-mysql-session-url] A session store using native +[MySQL](https://www.mysql.com/) via the [node-mysql](https://github.com/felixge/node-mysql) module. + +[express-mysql-session-url]: https://www.npmjs.com/package/express-mysql-session +[express-mysql-session-image]: https://img.shields.io/github/stars/chill117/express-mysql-session.svg?label=%E2%98%85 + +[![★][connect-sqlite3-image] connect-sqlite3][connect-sqlite3-url] A [SQLite3](https://github.com/mapbox/node-sqlite3) session store modeled after the TJ's `connect-redis` store. + +[connect-sqlite3-url]: https://www.npmjs.com/package/connect-sqlite3 +[connect-sqlite3-image]: https://img.shields.io/github/stars/rawberg/connect-sqlite3.svg?label=%E2%98%85 + +[![★][express-nedb-session-image] express-nedb-session][express-nedb-session-url] A NeDB-based session store. + +[express-nedb-session-url]: https://www.npmjs.com/package/express-nedb-session +[express-nedb-session-image]: https://img.shields.io/github/stars/louischatriot/express-nedb-session.svg?label=%E2%98%85 + +[![★][level-session-store-image] level-session-store][level-session-store-url] A LevelDB-based session store. + +[level-session-store-url]: https://www.npmjs.com/package/level-session-store +[level-session-store-image]: https://img.shields.io/github/stars/scriptollc/level-session-store.svg?label=%E2%98%85 + +[![★][mssql-session-store-image] mssql-session-store][mssql-session-store-url] A SQL Server-based session store. + +[mssql-session-store-url]: https://www.npmjs.com/package/mssql-session-store +[mssql-session-store-image]: https://img.shields.io/github/stars/jwathen/mssql-session-store.svg?label=%E2%98%85 + +[![★][nedb-session-store-image] nedb-session-store][nedb-session-store-url] An alternate NeDB-based (either in-memory or file-persisted) session store. + +[nedb-session-store-url]: https://www.npmjs.com/package/nedb-session-store +[nedb-session-store-image]: https://img.shields.io/github/stars/JamesMGreene/nedb-session-store.svg?label=%E2%98%85 + +[![★][sequelstore-connect-image] sequelstore-connect][sequelstore-connect-url] A session store using [Sequelize.js](http://sequelizejs.com/). + +[sequelstore-connect-url]: https://www.npmjs.com/package/sequelstore-connect +[sequelstore-connect-image]: https://img.shields.io/github/stars/MattMcFarland/sequelstore-connect.svg?label=%E2%98%85 + +[![★][session-file-store-image] session-file-store][session-file-store-url] A file system-based session store. + +[session-file-store-url]: https://www.npmjs.com/package/session-file-store +[session-file-store-image]: https://img.shields.io/github/stars/valery-barysok/session-file-store.svg?label=%E2%98%85 + +[![★][session-rethinkdb-image] session-rethinkdb][session-rethinkdb-url] A [RethinkDB](http://rethinkdb.com/)-based session store. + +[session-rethinkdb-url]: https://www.npmjs.com/package/session-rethinkdb +[session-rethinkdb-image]: https://img.shields.io/github/stars/llambda/session-rethinkdb.svg?label=%E2%98%85 + +## Example + +A simple example using `express-session` to store page views for a user. + +```js +var express = require('express') +var parseurl = require('parseurl') +var session = require('express-session') + +var app = express() + +app.use(session({ + secret: 'keyboard cat', + resave: false, + saveUninitialized: true +})) + +app.use(function (req, res, next) { + var views = req.session.views + + if (!views) { + views = req.session.views = {} + } + + // get the url pathname + var pathname = parseurl(req).pathname + + // count the views + views[pathname] = (views[pathname] || 0) + 1 + + next() +}) + +app.get('/foo', function (req, res, next) { + res.send('you viewed this page ' + req.session.views['/foo'] + ' times') +}) + +app.get('/bar', function (req, res, next) { + res.send('you viewed this page ' + req.session.views['/bar'] + ' times') +}) +``` + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/express-session.svg +[npm-url]: https://npmjs.org/package/express-session +[travis-image]: https://img.shields.io/travis/expressjs/session/master.svg +[travis-url]: https://travis-ci.org/expressjs/session +[coveralls-image]: https://img.shields.io/coveralls/expressjs/session/master.svg +[coveralls-url]: https://coveralls.io/r/expressjs/session?branch=master +[downloads-image]: https://img.shields.io/npm/dm/express-session.svg +[downloads-url]: https://npmjs.org/package/express-session +[gratipay-image]: https://img.shields.io/gratipay/dougwilson.svg +[gratipay-url]: https://gratipay.com/dougwilson/ diff --git a/node_modules/express-session/index.js b/node_modules/express-session/index.js new file mode 100644 index 0000000..5794118 --- /dev/null +++ b/node_modules/express-session/index.js @@ -0,0 +1,637 @@ +/*! + * express-session + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var cookie = require('cookie'); +var crc = require('crc').crc32; +var debug = require('debug')('express-session'); +var deprecate = require('depd')('express-session'); +var parseUrl = require('parseurl'); +var uid = require('uid-safe').sync + , onHeaders = require('on-headers') + , signature = require('cookie-signature') + +var Session = require('./session/session') + , MemoryStore = require('./session/memory') + , Cookie = require('./session/cookie') + , Store = require('./session/store') + +// environment + +var env = process.env.NODE_ENV; + +/** + * Expose the middleware. + */ + +exports = module.exports = session; + +/** + * Expose constructors. + */ + +exports.Store = Store; +exports.Cookie = Cookie; +exports.Session = Session; +exports.MemoryStore = MemoryStore; + +/** + * Warning message for `MemoryStore` usage in production. + * @private + */ + +var warning = 'Warning: connect.session() MemoryStore is not\n' + + 'designed for a production environment, as it will leak\n' + + 'memory, and will not scale past a single process.'; + +/** + * Node.js 0.8+ async implementation. + * @private + */ + +/* istanbul ignore next */ +var defer = typeof setImmediate === 'function' + ? setImmediate + : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) } + +/** + * Setup session store with the given `options`. + * + * @param {Object} [options] + * @param {Object} [options.cookie] Options for cookie + * @param {Function} [options.genid] + * @param {String} [options.name=connect.sid] Session ID cookie name + * @param {Boolean} [options.proxy] + * @param {Boolean} [options.resave] Resave unmodified sessions back to the store + * @param {Boolean} [options.rolling] Enable/disable rolling session expiration + * @param {Boolean} [options.saveUninitialized] Save uninitialized sessions to the store + * @param {String|Array} [options.secret] Secret for signing session ID + * @param {Object} [options.store=MemoryStore] Session store + * @param {String} [options.unset] + * @return {Function} middleware + * @public + */ + +function session(options) { + var opts = options || {} + + // get the cookie options + var cookieOptions = opts.cookie || {} + + // get the session id generate function + var generateId = opts.genid || generateSessionId + + // get the session cookie name + var name = opts.name || opts.key || 'connect.sid' + + // get the session store + var store = opts.store || new MemoryStore() + + // get the trust proxy setting + var trustProxy = opts.proxy + + // get the resave session option + var resaveSession = opts.resave; + + // get the rolling session option + var rollingSessions = Boolean(opts.rolling) + + // get the save uninitialized session option + var saveUninitializedSession = opts.saveUninitialized + + // get the cookie signing secret + var secret = opts.secret + + if (typeof generateId !== 'function') { + throw new TypeError('genid option must be a function'); + } + + if (resaveSession === undefined) { + deprecate('undefined resave option; provide resave option'); + resaveSession = true; + } + + if (saveUninitializedSession === undefined) { + deprecate('undefined saveUninitialized option; provide saveUninitialized option'); + saveUninitializedSession = true; + } + + if (opts.unset && opts.unset !== 'destroy' && opts.unset !== 'keep') { + throw new TypeError('unset option must be "destroy" or "keep"'); + } + + // TODO: switch to "destroy" on next major + var unsetDestroy = opts.unset === 'destroy' + + if (Array.isArray(secret) && secret.length === 0) { + throw new TypeError('secret option array must contain one or more strings'); + } + + if (secret && !Array.isArray(secret)) { + secret = [secret]; + } + + if (!secret) { + deprecate('req.secret; provide secret option'); + } + + // notify user that this store is not + // meant for a production environment + if ('production' == env && store instanceof MemoryStore) { + /* istanbul ignore next: not tested */ + console.warn(warning); + } + + // generates the new session + store.generate = function(req){ + req.sessionID = generateId(req); + req.session = new Session(req); + req.session.cookie = new Cookie(cookieOptions); + + if (cookieOptions.secure === 'auto') { + req.session.cookie.secure = issecure(req, trustProxy); + } + }; + + var storeImplementsTouch = typeof store.touch === 'function'; + + // register event listeners for the store to track readiness + var storeReady = true + store.on('disconnect', function ondisconnect() { + storeReady = false + }) + store.on('connect', function onconnect() { + storeReady = true + }) + + return function session(req, res, next) { + // self-awareness + if (req.session) { + next() + return + } + + // Handle connection as if there is no session if + // the store has temporarily disconnected etc + if (!storeReady) { + debug('store is disconnected') + next() + return + } + + // pathname mismatch + var originalPath = parseUrl.original(req).pathname; + if (originalPath.indexOf(cookieOptions.path || '/') !== 0) return next(); + + // ensure a secret is available or bail + if (!secret && !req.secret) { + next(new Error('secret option required for sessions')); + return; + } + + // backwards compatibility for signed cookies + // req.secret is passed from the cookie parser middleware + var secrets = secret || [req.secret]; + + var originalHash; + var originalId; + var savedHash; + + // expose store + req.sessionStore = store; + + // get the session ID from the cookie + var cookieId = req.sessionID = getcookie(req, name, secrets); + + // set-cookie + onHeaders(res, function(){ + if (!req.session) { + debug('no session'); + return; + } + + if (!shouldSetCookie(req)) { + return; + } + + // only send secure cookies via https + if (req.session.cookie.secure && !issecure(req, trustProxy)) { + debug('not secured'); + return; + } + + // touch session + req.session.touch(); + + // set cookie + setcookie(res, name, req.sessionID, secrets[0], req.session.cookie.data); + }); + + // proxy end() to commit the session + var _end = res.end; + var _write = res.write; + var ended = false; + res.end = function end(chunk, encoding) { + if (ended) { + return false; + } + + ended = true; + + var ret; + var sync = true; + + function writeend() { + if (sync) { + ret = _end.call(res, chunk, encoding); + sync = false; + return; + } + + _end.call(res); + } + + function writetop() { + if (!sync) { + return ret; + } + + if (chunk == null) { + ret = true; + return ret; + } + + var contentLength = Number(res.getHeader('Content-Length')); + + if (!isNaN(contentLength) && contentLength > 0) { + // measure chunk + chunk = !Buffer.isBuffer(chunk) + ? new Buffer(chunk, encoding) + : chunk; + encoding = undefined; + + if (chunk.length !== 0) { + debug('split response'); + ret = _write.call(res, chunk.slice(0, chunk.length - 1)); + chunk = chunk.slice(chunk.length - 1, chunk.length); + return ret; + } + } + + ret = _write.call(res, chunk, encoding); + sync = false; + + return ret; + } + + if (shouldDestroy(req)) { + // destroy session + debug('destroying'); + store.destroy(req.sessionID, function ondestroy(err) { + if (err) { + defer(next, err); + } + + debug('destroyed'); + writeend(); + }); + + return writetop(); + } + + // no session to save + if (!req.session) { + debug('no session'); + return _end.call(res, chunk, encoding); + } + + if (shouldSave(req)) { + req.session.save(function onsave(err) { + if (err) { + defer(next, err); + } + + writeend(); + }); + + return writetop(); + } else if (storeImplementsTouch && shouldTouch(req)) { + // store implements touch method + debug('touching'); + store.touch(req.sessionID, req.session, function ontouch(err) { + if (err) { + defer(next, err); + } + + debug('touched'); + writeend(); + }); + + return writetop(); + } + + return _end.call(res, chunk, encoding); + }; + + // generate the session + function generate() { + store.generate(req); + originalId = req.sessionID; + originalHash = hash(req.session); + wrapmethods(req.session); + } + + // wrap session methods + function wrapmethods(sess) { + var _save = sess.save; + + function save() { + debug('saving %s', this.id); + savedHash = hash(this); + _save.apply(this, arguments); + } + + Object.defineProperty(sess, 'save', { + configurable: true, + enumerable: false, + value: save, + writable: true + }); + } + + // check if session has been modified + function isModified(sess) { + return originalId !== sess.id || originalHash !== hash(sess); + } + + // check if session has been saved + function isSaved(sess) { + return originalId === sess.id && savedHash === hash(sess); + } + + // determine if session should be destroyed + function shouldDestroy(req) { + return req.sessionID && unsetDestroy && req.session == null; + } + + // determine if session should be saved to store + function shouldSave(req) { + // cannot set cookie without a session ID + if (typeof req.sessionID !== 'string') { + debug('session ignored because of bogus req.sessionID %o', req.sessionID); + return false; + } + + return !saveUninitializedSession && cookieId !== req.sessionID + ? isModified(req.session) + : !isSaved(req.session) + } + + // determine if session should be touched + function shouldTouch(req) { + // cannot set cookie without a session ID + if (typeof req.sessionID !== 'string') { + debug('session ignored because of bogus req.sessionID %o', req.sessionID); + return false; + } + + return cookieId === req.sessionID && !shouldSave(req); + } + + // determine if cookie should be set on response + function shouldSetCookie(req) { + // cannot set cookie without a session ID + if (typeof req.sessionID !== 'string') { + return false; + } + + return cookieId != req.sessionID + ? saveUninitializedSession || isModified(req.session) + : rollingSessions || req.session.cookie.expires != null && isModified(req.session); + } + + // generate a session if the browser doesn't send a sessionID + if (!req.sessionID) { + debug('no SID sent, generating session'); + generate(); + next(); + return; + } + + // generate the session object + debug('fetching %s', req.sessionID); + store.get(req.sessionID, function(err, sess){ + // error handling + if (err) { + debug('error %j', err); + + if (err.code !== 'ENOENT') { + next(err); + return; + } + + generate(); + // no session + } else if (!sess) { + debug('no session found'); + generate(); + // populate req.session + } else { + debug('session found'); + store.createSession(req, sess); + originalId = req.sessionID; + originalHash = hash(sess); + + if (!resaveSession) { + savedHash = originalHash + } + + wrapmethods(req.session); + } + + next(); + }); + }; +}; + +/** + * Generate a session ID for a new session. + * + * @return {String} + * @private + */ + +function generateSessionId(sess) { + return uid(24); +} + +/** + * Get the session ID cookie from request. + * + * @return {string} + * @private + */ + +function getcookie(req, name, secrets) { + var header = req.headers.cookie; + var raw; + var val; + + // read from cookie header + if (header) { + var cookies = cookie.parse(header); + + raw = cookies[name]; + + if (raw) { + if (raw.substr(0, 2) === 's:') { + val = unsigncookie(raw.slice(2), secrets); + + if (val === false) { + debug('cookie signature invalid'); + val = undefined; + } + } else { + debug('cookie unsigned') + } + } + } + + // back-compat read from cookieParser() signedCookies data + if (!val && req.signedCookies) { + val = req.signedCookies[name]; + + if (val) { + deprecate('cookie should be available in req.headers.cookie'); + } + } + + // back-compat read from cookieParser() cookies data + if (!val && req.cookies) { + raw = req.cookies[name]; + + if (raw) { + if (raw.substr(0, 2) === 's:') { + val = unsigncookie(raw.slice(2), secrets); + + if (val) { + deprecate('cookie should be available in req.headers.cookie'); + } + + if (val === false) { + debug('cookie signature invalid'); + val = undefined; + } + } else { + debug('cookie unsigned') + } + } + } + + return val; +} + +/** + * Hash the given `sess` object omitting changes to `.cookie`. + * + * @param {Object} sess + * @return {String} + * @private + */ + +function hash(sess) { + return crc(JSON.stringify(sess, function (key, val) { + if (key !== 'cookie') { + return val; + } + })); +} + +/** + * Determine if request is secure. + * + * @param {Object} req + * @param {Boolean} [trustProxy] + * @return {Boolean} + * @private + */ + +function issecure(req, trustProxy) { + // socket is https server + if (req.connection && req.connection.encrypted) { + return true; + } + + // do not trust proxy + if (trustProxy === false) { + return false; + } + + // no explicit trust; try req.secure from express + if (trustProxy !== true) { + var secure = req.secure; + return typeof secure === 'boolean' + ? secure + : false; + } + + // read the proto from x-forwarded-proto header + var header = req.headers['x-forwarded-proto'] || ''; + var index = header.indexOf(','); + var proto = index !== -1 + ? header.substr(0, index).toLowerCase().trim() + : header.toLowerCase().trim() + + return proto === 'https'; +} + +/** + * Set cookie on response. + * + * @private + */ + +function setcookie(res, name, val, secret, options) { + var signed = 's:' + signature.sign(val, secret); + var data = cookie.serialize(name, signed, options); + + debug('set-cookie %s', data); + + var prev = res.getHeader('set-cookie') || []; + var header = Array.isArray(prev) ? prev.concat(data) + : Array.isArray(data) ? [prev].concat(data) + : [prev, data]; + + res.setHeader('set-cookie', header) +} + +/** + * Verify and decode the given `val` with `secrets`. + * + * @param {String} val + * @param {Array} secrets + * @returns {String|Boolean} + * @private + */ +function unsigncookie(val, secrets) { + for (var i = 0; i < secrets.length; i++) { + var result = signature.unsign(val, secrets[i]); + + if (result !== false) { + return result; + } + } + + return false; +} diff --git a/node_modules/express-session/package.json b/node_modules/express-session/package.json new file mode 100644 index 0000000..f35ec2e --- /dev/null +++ b/node_modules/express-session/package.json @@ -0,0 +1,121 @@ +{ + "_args": [ + [ + "express-session", + "/home/humair/School/csc309/a4/solutions_repo" + ] + ], + "_from": "express-session@latest", + "_id": "express-session@1.14.0", + "_inCache": true, + "_installable": true, + "_location": "/express-session", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/express-session-1.14.0.tgz_1467429048169_0.3337707840837538" + }, + "_npmUser": { + "email": "doug@somethingdoug.com", + "name": "dougwilson" + }, + "_npmVersion": "1.4.28", + "_phantomChildren": {}, + "_requested": { + "name": "express-session", + "raw": "express-session", + "rawSpec": "", + "scope": null, + "spec": "latest", + "type": "tag" + }, + "_requiredBy": [ + "/" + ], + "_resolved": "https://registry.npmjs.org/express-session/-/express-session-1.14.0.tgz", + "_shasum": "f5eeed3f38bfa0c6af27a0aeb8c9ec67dc07e39e", + "_shrinkwrap": null, + "_spec": "express-session", + "_where": "/home/humair/School/csc309/a4/solutions_repo", + "author": { + "email": "tj@vision-media.ca", + "name": "TJ Holowaychuk", + "url": "http://tjholowaychuk.com" + }, + "bugs": { + "url": "https://github.com/expressjs/session/issues" + }, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Joe Wagner", + "email": "njwjs722@gmail.com" + } + ], + "dependencies": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "crc": "3.4.0", + "debug": "~2.2.0", + "depd": "~1.1.0", + "on-headers": "~1.0.1", + "parseurl": "~1.3.1", + "uid-safe": "~2.1.1", + "utils-merge": "1.0.0" + }, + "description": "Simple session middleware for Express", + "devDependencies": { + "after": "0.8.1", + "cookie-parser": "1.4.3", + "express": "4.14.0", + "istanbul": "0.4.4", + "mocha": "2.5.3", + "supertest": "1.1.0" + }, + "directories": {}, + "dist": { + "shasum": "f5eeed3f38bfa0c6af27a0aeb8c9ec67dc07e39e", + "tarball": "https://registry.npmjs.org/express-session/-/express-session-1.14.0.tgz" + }, + "engines": { + "node": ">= 0.8.0" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "index.js", + "session/" + ], + "gitHead": "9fd23195578eac5962d52f46781a75a297fbe685", + "homepage": "https://github.com/expressjs/session", + "license": "MIT", + "maintainers": [ + { + "name": "defunctzombie", + "email": "shtylman@gmail.com" + }, + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "mscdex", + "email": "mscdex@mscdex.net" + } + ], + "name": "express-session", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/expressjs/session.git" + }, + "scripts": { + "test": "mocha --bail --reporter spec test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec test/" + }, + "version": "1.14.0" +} diff --git a/node_modules/express-session/session/cookie.js b/node_modules/express-session/session/cookie.js new file mode 100644 index 0000000..a4dbd8a --- /dev/null +++ b/node_modules/express-session/session/cookie.js @@ -0,0 +1,129 @@ +/*! + * Connect - session - Cookie + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + */ + +var merge = require('utils-merge') + , cookie = require('cookie'); + +/** + * Initialize a new `Cookie` with the given `options`. + * + * @param {IncomingMessage} req + * @param {Object} options + * @api private + */ + +var Cookie = module.exports = function Cookie(options) { + this.path = '/'; + this.maxAge = null; + this.httpOnly = true; + if (options) merge(this, options); + this.originalMaxAge = undefined == this.originalMaxAge + ? this.maxAge + : this.originalMaxAge; +}; + +/*! + * Prototype. + */ + +Cookie.prototype = { + + /** + * Set expires `date`. + * + * @param {Date} date + * @api public + */ + + set expires(date) { + this._expires = date; + this.originalMaxAge = this.maxAge; + }, + + /** + * Get expires `date`. + * + * @return {Date} + * @api public + */ + + get expires() { + return this._expires; + }, + + /** + * Set expires via max-age in `ms`. + * + * @param {Number} ms + * @api public + */ + + set maxAge(ms) { + this.expires = 'number' == typeof ms + ? new Date(Date.now() + ms) + : ms; + }, + + /** + * Get expires max-age in `ms`. + * + * @return {Number} + * @api public + */ + + get maxAge() { + return this.expires instanceof Date + ? this.expires.valueOf() - Date.now() + : this.expires; + }, + + /** + * Return cookie data object. + * + * @return {Object} + * @api private + */ + + get data() { + return { + originalMaxAge: this.originalMaxAge + , expires: this._expires + , secure: this.secure + , httpOnly: this.httpOnly + , domain: this.domain + , path: this.path + } + }, + + /** + * Return a serialized cookie string. + * + * @return {String} + * @api public + */ + + serialize: function(name, val){ + return cookie.serialize(name, val, this.data); + }, + + /** + * Return JSON representation of this cookie. + * + * @return {Object} + * @api private + */ + + toJSON: function(){ + return this.data; + } +}; diff --git a/node_modules/express-session/session/memory.js b/node_modules/express-session/session/memory.js new file mode 100644 index 0000000..25252b6 --- /dev/null +++ b/node_modules/express-session/session/memory.js @@ -0,0 +1,185 @@ +/*! + * express-session + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var Store = require('./store') +var util = require('util') + +/** + * Shim setImmediate for node.js < 0.10 + * @private + */ + +/* istanbul ignore next */ +var defer = typeof setImmediate === 'function' + ? setImmediate + : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) } + +/** + * Module exports. + */ + +module.exports = MemoryStore + +/** + * A session store in memory. + * @public + */ + +function MemoryStore() { + Store.call(this) + this.sessions = Object.create(null) +} + +/** + * Inherit from Store. + */ + +util.inherits(MemoryStore, Store) + +/** + * Get all active sessions. + * + * @param {function} callback + * @public + */ + +MemoryStore.prototype.all = function all(callback) { + var sessionIds = Object.keys(this.sessions) + var sessions = Object.create(null) + + for (var i = 0; i < sessionIds.length; i++) { + var sessionId = sessionIds[i] + var session = getSession.call(this, sessionId) + + if (session) { + sessions[sessionId] = session; + } + } + + callback && defer(callback, null, sessions) +} + +/** + * Clear all sessions. + * + * @param {function} callback + * @public + */ + +MemoryStore.prototype.clear = function clear(callback) { + this.sessions = Object.create(null) + callback && defer(callback) +} + +/** + * Destroy the session associated with the given session ID. + * + * @param {string} sessionId + * @public + */ + +MemoryStore.prototype.destroy = function destroy(sessionId, callback) { + delete this.sessions[sessionId] + callback && defer(callback) +} + +/** + * Fetch session by the given session ID. + * + * @param {string} sessionId + * @param {function} callback + * @public + */ + +MemoryStore.prototype.get = function get(sessionId, callback) { + defer(callback, null, getSession.call(this, sessionId)) +} + +/** + * Commit the given session associated with the given sessionId to the store. + * + * @param {string} sessionId + * @param {object} session + * @param {function} callback + * @public + */ + +MemoryStore.prototype.set = function set(sessionId, session, callback) { + this.sessions[sessionId] = JSON.stringify(session) + callback && defer(callback) +} + +/** + * Get number of active sessions. + * + * @param {function} callback + * @public + */ + +MemoryStore.prototype.length = function length(callback) { + this.all(function (err, sessions) { + if (err) return callback(err) + callback(null, Object.keys(sessions).length) + }) +} + +/** + * Touch the given session object associated with the given session ID. + * + * @param {string} sessionId + * @param {object} session + * @param {function} callback + * @public + */ + +MemoryStore.prototype.touch = function touch(sessionId, session, callback) { + var currentSession = getSession.call(this, sessionId) + + if (currentSession) { + // update expiration + currentSession.cookie = session.cookie + this.sessions[sessionId] = JSON.stringify(currentSession) + } + + callback && defer(callback) +} + +/** + * Get session from the store. + * @private + */ + +function getSession(sessionId) { + var sess = this.sessions[sessionId] + + if (!sess) { + return + } + + // parse + sess = JSON.parse(sess) + + var expires = typeof sess.cookie.expires === 'string' + ? new Date(sess.cookie.expires) + : sess.cookie.expires + + // destroy expired session + if (expires && expires <= Date.now()) { + delete this.sessions[sessionId] + return + } + + return sess +} diff --git a/node_modules/express-session/session/session.js b/node_modules/express-session/session/session.js new file mode 100644 index 0000000..2eacde6 --- /dev/null +++ b/node_modules/express-session/session/session.js @@ -0,0 +1,142 @@ +/*! + * Connect - session - Session + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +'use strict'; + +/** + * Expose Session. + */ + +module.exports = Session; + +/** + * Create a new `Session` with the given request and `data`. + * + * @param {IncomingRequest} req + * @param {Object} data + * @api private + */ + +function Session(req, data) { + Object.defineProperty(this, 'req', { value: req }); + Object.defineProperty(this, 'id', { value: req.sessionID }); + + if (typeof data === 'object' && data !== null) { + // merge data into this, ignoring prototype properties + for (var prop in data) { + if (!(prop in this)) { + this[prop] = data[prop] + } + } + } +} + +/** + * Update reset `.cookie.maxAge` to prevent + * the cookie from expiring when the + * session is still active. + * + * @return {Session} for chaining + * @api public + */ + +defineMethod(Session.prototype, 'touch', function touch() { + return this.resetMaxAge(); +}); + +/** + * Reset `.maxAge` to `.originalMaxAge`. + * + * @return {Session} for chaining + * @api public + */ + +defineMethod(Session.prototype, 'resetMaxAge', function resetMaxAge() { + this.cookie.maxAge = this.cookie.originalMaxAge; + return this; +}); + +/** + * Save the session data with optional callback `fn(err)`. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +defineMethod(Session.prototype, 'save', function save(fn) { + this.req.sessionStore.set(this.id, this, fn || function(){}); + return this; +}); + +/** + * Re-loads the session data _without_ altering + * the maxAge properties. Invokes the callback `fn(err)`, + * after which time if no exception has occurred the + * `req.session` property will be a new `Session` object, + * although representing the same session. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +defineMethod(Session.prototype, 'reload', function reload(fn) { + var req = this.req + , store = this.req.sessionStore; + store.get(this.id, function(err, sess){ + if (err) return fn(err); + if (!sess) return fn(new Error('failed to load session')); + store.createSession(req, sess); + fn(); + }); + return this; +}); + +/** + * Destroy `this` session. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +defineMethod(Session.prototype, 'destroy', function destroy(fn) { + delete this.req.session; + this.req.sessionStore.destroy(this.id, fn); + return this; +}); + +/** + * Regenerate this request's session. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +defineMethod(Session.prototype, 'regenerate', function regenerate(fn) { + this.req.sessionStore.regenerate(this.req, fn); + return this; +}); + +/** + * Helper function for creating a method on a prototype. + * + * @param {Object} obj + * @param {String} name + * @param {Function} fn + * @private + */ +function defineMethod(obj, name, fn) { + Object.defineProperty(obj, name, { + configurable: true, + enumerable: false, + value: fn, + writable: true + }); +}; diff --git a/node_modules/express-session/session/store.js b/node_modules/express-session/session/store.js new file mode 100644 index 0000000..387469c --- /dev/null +++ b/node_modules/express-session/session/store.js @@ -0,0 +1,94 @@ +/*! + * Connect - session - Store + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var Cookie = require('./cookie') +var EventEmitter = require('events').EventEmitter +var Session = require('./session') +var util = require('util') + +/** + * Module exports. + * @public + */ + +module.exports = Store + +/** + * Abstract base class for session stores. + * @public + */ + +function Store () { + EventEmitter.call(this) +} + +/** + * Inherit from EventEmitter. + */ + +util.inherits(Store, EventEmitter) + +/** + * Re-generate the given requests's session. + * + * @param {IncomingRequest} req + * @return {Function} fn + * @api public + */ + +Store.prototype.regenerate = function(req, fn){ + var self = this; + this.destroy(req.sessionID, function(err){ + self.generate(req); + fn(err); + }); +}; + +/** + * Load a `Session` instance via the given `sid` + * and invoke the callback `fn(err, sess)`. + * + * @param {String} sid + * @param {Function} fn + * @api public + */ + +Store.prototype.load = function(sid, fn){ + var self = this; + this.get(sid, function(err, sess){ + if (err) return fn(err); + if (!sess) return fn(); + var req = { sessionID: sid, sessionStore: self }; + fn(null, self.createSession(req, sess)) + }); +}; + +/** + * Create session from JSON `sess` data. + * + * @param {IncomingRequest} req + * @param {Object} sess + * @return {Session} + * @api private + */ + +Store.prototype.createSession = function(req, sess){ + var expires = sess.cookie.expires + , orig = sess.cookie.originalMaxAge; + sess.cookie = new Cookie(sess.cookie); + if ('string' == typeof expires) sess.cookie.expires = new Date(expires); + sess.cookie.originalMaxAge = orig; + req.session = new Session(req, sess); + return req.session; +}; |
