diff --git a/.circleci/config.yml b/.circleci/config.yml index 2d29d8f..9bc6713 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,6 +6,7 @@ jobs: docker: - image: circleci/node:dubnium - image: ibmcom/cloudant-developer + - image: redis steps: - checkout - restore_cache: diff --git a/README.md b/README.md index 7c88b62..776e1d5 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,11 @@ run: npm install ``` +### Redis + +Be sure that redis is running on the default port (6379). +For convenience you can run: `npm run redis`. + ### Database (CouchDB 2.x + Clouseau + Dreyfus) @@ -75,7 +80,7 @@ docker logs cloudant-developer ### App -Once cloudant is running run: +Once cloudant and redis are running run: ```sh npm run init @@ -131,7 +136,7 @@ For chrome: ### Tests -Once cloudant is running run: +Once cloudant and redis are running run: ```sh npm test diff --git a/package-lock.json b/package-lock.json index 85f3f33..35fcb12 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4469,6 +4469,11 @@ } } }, + "connect-redis": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-4.0.3.tgz", + "integrity": "sha512-Php0P0ShNfilW6f2d/2v7Q0VAiFeBYsg0bIgu8ST3x26CcQ1JtzV6vxPLUwK0uiq10hQSMR+HzSNhWbcvx6nLg==" + }, "console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", @@ -5420,6 +5425,11 @@ "dotenv-defaults": "^1.0.2" } }, + "double-ended-queue": { + "version": "2.1.0-0", + "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", + "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=" + }, "duplexer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", @@ -12602,6 +12612,26 @@ "minimatch": "3.0.4" } }, + "redis": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", + "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", + "requires": { + "double-ended-queue": "^2.1.0-0", + "redis-commands": "^1.2.0", + "redis-parser": "^2.6.0" + } + }, + "redis-commands": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.5.0.tgz", + "integrity": "sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg==" + }, + "redis-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", + "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=" + }, "redux": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.4.tgz", diff --git a/package.json b/package.json index 3870b00..f1e0992 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "main": "index.js", "scripts": { "cloudant": "docker restart cloudant-developer", + "redis": "redis-server /usr/local/etc/redis.conf", "log-cloudant": "docker logs cloudant-developer", "extension:watch": "webpack --config webpack-extension.config.js --watch --mode development", "extension:build": "cross-env NODE_ENV=production webpack --config webpack-extension.config.js --mode production", @@ -190,6 +191,7 @@ "classnames": "^2.2.6", "clipboard-copy": "^3.1.0", "concat-stream": "^2.0.0", + "connect-redis": "^4.0.3", "cors": "^2.8.5", "date-fns": "^2.5.1", "doi-regex": "^0.1.10", @@ -217,6 +219,7 @@ "react-dropzone": "^10.1.10", "react-icons": "^3.7.0", "react-router-dom": "^5.1.2", + "redis": "^2.8.0", "slug": "^1.1.0", "uuid": "^3.3.3", "xmldom": "^0.1.27" diff --git a/src/index.js b/src/index.js index 839dc20..5438b0a 100644 --- a/src/index.js +++ b/src/index.js @@ -2,13 +2,18 @@ import path from 'path'; import { STATUS_CODES } from 'http'; import express from 'express'; import session from 'express-session'; +import redis from 'redis'; +import connectRedis from 'connect-redis'; import authRoutes from './routes/auth-routes'; import appRoutes from './routes/app-routes'; import apiRoutes from './routes/api-routes'; import addDb from './middlewares/add-db'; import { createPassport } from './utils/orcid'; +import { createRedisConfig } from './utils/redis'; export function rapid(config = {}) { + const RedisStore = connectRedis(session); + const passport = createPassport(config); const app = express(); @@ -24,7 +29,10 @@ export function rapid(config = {}) { secret: config.sessionSecret || process.env.SESSION_SECRET || 'rapid-prereview', resave: false, - saveUninitialized: false + saveUninitialized: false, + store: new RedisStore({ + client: redis.createClient(createRedisConfig(config, { ns: 'sess' })) + }) }) ); app.use(passport.initialize()); diff --git a/src/utils/redis.js b/src/utils/redis.js new file mode 100644 index 0000000..850eacb --- /dev/null +++ b/src/utils/redis.js @@ -0,0 +1,21 @@ +export function createRedisConfig(config = {}, { ns } = {}) { + const opts = { + host: config.redisHost || process.env['REDIS_HOST'] || '127.0.0.1', + port: config.redisPort || process.env['REDIS_PORT'] || 6379 + }; + + let redisPrefix = config.redisPrefix || 'rpos:'; + if (ns) { + redisPrefix += `${ns}:`; + } + + opts.prefix = redisPrefix; + + const redisPassword = config.redisPassword || process.env['REDIS_PASSWORD']; + if (redisPassword) { + opts.pass = redisPassword; // for compatibility with RedisStore (used in the session middleware) + opts.password = redisPassword; + } + + return opts; +}