diff --git a/app.js b/app.js index e520d5b383..73b9528d9e 100644 --- a/app.js +++ b/app.js @@ -1,16 +1,17 @@ -var express = require('express'), - bodyParser = require('body-parser'), - log4js = require('log4js'), - logger = require('./lib/logger'), - routes = require('./lib/routes'), - eventApi = require('./lib/eventApi'), - featureApi = require('./lib/featureApi'), +var express = require('express'), + bodyParser = require('body-parser'), + cookieParser = require('cookie-parser'), + log4js = require('log4js'), + logger = require('./lib/logger'), + routes = require('./lib/routes'), + eventApi = require('./lib/eventApi'), + featureApi = require('./lib/featureApi'), featureArchiveApi = require('./lib/featureArchiveApi'), - strategyApi = require('./lib/strategyApi'), - validator = require('express-validator'), - app = express(), - router = express.Router(), - baseUriPath = process.env.BASE_URI_PATH || ''; + strategyApi = require('./lib/strategyApi'), + validator = require('express-validator'), + app = express(), + router = express.Router(), + baseUriPath = process.env.BASE_URI_PATH || ''; if(app.get('env') === 'development') { app.use(require('errorhandler')()); @@ -38,6 +39,8 @@ app.set('port', process.env.HTTP_PORT || process.env.PORT || 4242); app.use(baseUriPath, express.static(__dirname + '/public')); app.use(bodyParser.json({strict: false})); +app.use(cookieParser()); + eventApi(router); featureApi(router); featureArchiveApi(router); @@ -45,4 +48,4 @@ strategyApi(router); routes(router); app.use(baseUriPath, router); -module.exports = app; \ No newline at end of file +module.exports = app; diff --git a/lib/extractUser.js b/lib/extractUser.js new file mode 100644 index 0000000000..2da29b954e --- /dev/null +++ b/lib/extractUser.js @@ -0,0 +1,4 @@ +function extractUsername(req) { + return req.cookies.username || "unknown"; +} +module.exports = extractUsername; diff --git a/lib/featureApi.js b/lib/featureApi.js index 61ff4cfc1d..1593817699 100644 --- a/lib/featureApi.js +++ b/lib/featureApi.js @@ -7,6 +7,7 @@ var NameExistsError = require('./error/NameExistsError'); var NotFoundError = require('./error/NotFoundError'); var ValidationError = require('./error/ValidationError'); var validateRequest = require('./error/validateRequest'); +var extractUser = require('./extractUser'); module.exports = function (app) { @@ -33,7 +34,7 @@ module.exports = function (app) { .then(function() { return eventStore.create({ type: eventType.featureCreated, - createdBy: req.connection.remoteAddress, + createdBy: extractUser(req), data: req.body }); }) @@ -56,7 +57,7 @@ module.exports = function (app) { app.put('/features/:featureName', function (req, res) { var featureName = req.params.featureName; - var userName = req.connection.remoteAddress; + var userName = extractUser(req); var updatedFeature = req.body; updatedFeature.name = featureName; @@ -83,7 +84,7 @@ module.exports = function (app) { app.delete('/features/:featureName', function (req, res) { var featureName = req.params.featureName; - var userName = req.connection.remoteAddress; + var userName = extractUser(req); featureDb.getFeature(featureName) .then(function () { @@ -118,4 +119,3 @@ module.exports = function (app) { }); } }; - diff --git a/lib/strategyApi.js b/lib/strategyApi.js index 3b11e82ed8..a5ebb8fac0 100644 --- a/lib/strategyApi.js +++ b/lib/strategyApi.js @@ -5,7 +5,8 @@ var strategyDb = require('./strategyDb'); var logger = require('./logger'); var NameExistsError = require('./error/NameExistsError'); var ValidationError = require('./error/ValidationError'); -var validateRequest = require('./error/validateRequest'); +var validateRequest = require('./error/validateRequest'); +var extractUser = require('./extractUser'); module.exports = function (app) { @@ -24,7 +25,7 @@ module.exports = function (app) { app.delete('/strategies/:name', function (req, res) { eventStore.create({ type: eventType.strategyDeleted, - createdBy: req.connection.remoteAddress, + createdBy: extractUser(req), data: { name: req.params.name } @@ -44,7 +45,7 @@ module.exports = function (app) { .then(function() { return eventStore.create({ type: eventType.strategyCreated, - createdBy: req.connection.remoteAddress, + createdBy: extractUser(req), data: newStrategy }); }) @@ -75,4 +76,3 @@ module.exports = function (app) { } }; - diff --git a/package.json b/package.json index c24c85d044..aefc65538c 100644 --- a/package.json +++ b/package.json @@ -1,80 +1,81 @@ { - "name": "unleash-server", - "description": "unleash your features", - "version": "0.0.1", - "keywords": [ - "unleash", - "feature toggle", - "feature", - "toggle" + "name": "unleash-server", + "description": "unleash your features", + "version": "0.0.1", + "keywords": [ + "unleash", + "feature toggle", + "feature", + "toggle" + ], + "repository": { + "type": "git", + "url": "ssh://git@github.com:finn-no/unleash.git" + }, + "bugs": { + "url": "https://github.com/finn-no/unleash/issues" + }, + "private": true, + "scripts": { + "start": "NODE_ENV=production node server.js", + "build": "./node_modules/.bin/webpack", + "dev": "NODE_ENV=development supervisor --ignore ./node_modules/,./public/js server.js", + "test": "export PORT=4243 ; jest && jshint server.js lib test && jsxhint public/js/**/*.jsx && mocha test test/*.js && npm run coverage", + "docker-test": "export PORT=4243 ; ./scripts/docker-postgres.sh", + "pg-virtualenv-test": "pg_virtualenv npm run pg-virtualenv-chain", + "pg-virtualenv-chain": "export TEST_DATABASE_URL=postgres://$PGUSER:$PGPASSWORD@localhost:$PGPORT/postgres ; npm run db-migrate-testdb && npm test", + "db-migrate-testdb": "DATABASE_URL=$TEST_DATABASE_URL ./node_modules/.bin/db-migrate up", + "tdd": "mocha --watch test test/*", + "test-bamboo-ci": "mocha test test/*", + "coverage": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec", + "coverage-report": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage", + "postinstall": "npm run build", + "jest": "jest" + }, + "dependencies": { + "bluebird": "2.6.2", + "body-parser": "1.10.1", + "cookie-parser": "^1.3.3", + "db-migrate": "0.7.1", + "deep-diff": "^0.3.0", + "errorhandler": "1.3.2", + "express": "4.9.8", + "express-validator": "2.8.0", + "ini": "1.3.2", + "jsx-loader": "0.12.2", + "jsxhint": "0.4.15", + "knex": "^0.7.3", + "log4js": "0.6.21", + "moment": "^2.9.0", + "nconf": "0.6.9", + "pg": "3.6.1", + "react": "^0.12.0", + "reqwest": "^1.1.4", + "webpack": "1.4.15", + "webpack-dev-middleware": "^1.0.11" + }, + "devDependencies": { + "chai": "1.9.1", + "coveralls": "^2.11.2", + "istanbul": "0.3.2", + "jest-cli": "^0.1.18", + "jshint": "2.5.2", + "mocha": "1.20.1", + "mocha-lcov-reporter": "0.0.1", + "pre-commit": "0.0.9", + "react-tools": "^0.12.0", + "supertest": "0.13.0", + "supervisor": "0.6.0", + "xmlbuilder": "2.4.4" + }, + "jest": { + "scriptPreprocessor": "/jest-preprocessor.js", + "unmockedModulePathPatterns": [ + "/node_modules/react" ], - "repository": { - "type": "git", - "url": "ssh://git@github.com:finn-no/unleash.git" - }, - "bugs": { - "url": "https://github.com/finn-no/unleash/issues" - }, - "private": true, - "scripts": { - "start": "NODE_ENV=production node server.js", - "build": "./node_modules/.bin/webpack", - "dev": "NODE_ENV=development supervisor --ignore ./node_modules/,./public/js server.js", - "test": "export PORT=4243 ; jest && jshint server.js lib test && jsxhint public/js/**/*.jsx && mocha test test/*.js && npm run coverage", - "docker-test": "export PORT=4243 ; ./scripts/docker-postgres.sh", - "pg-virtualenv-test": "pg_virtualenv npm run pg-virtualenv-chain", - "pg-virtualenv-chain": "export TEST_DATABASE_URL=postgres://$PGUSER:$PGPASSWORD@localhost:$PGPORT/postgres ; npm run db-migrate-testdb && npm test", - "db-migrate-testdb": "DATABASE_URL=$TEST_DATABASE_URL ./node_modules/.bin/db-migrate up", - "tdd": "mocha --watch test test/*", - "test-bamboo-ci": "mocha test test/*", - "coverage": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec", - "coverage-report": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage", - "postinstall": "npm run build", - "jest": "jest" - }, - "dependencies": { - "bluebird": "2.6.2", - "body-parser": "1.10.1", - "db-migrate": "0.7.1", - "deep-diff": "^0.3.0", - "errorhandler": "1.3.2", - "express": "4.9.8", - "express-validator": "2.8.0", - "ini": "1.3.2", - "jsx-loader": "0.12.2", - "jsxhint": "0.4.15", - "knex": "^0.7.3", - "log4js": "0.6.21", - "moment": "^2.9.0", - "nconf": "0.6.9", - "pg": "3.6.1", - "react": "^0.12.0", - "reqwest": "^1.1.4", - "webpack": "1.4.15", - "webpack-dev-middleware": "^1.0.11" - }, - "devDependencies": { - "chai": "1.9.1", - "coveralls": "^2.11.2", - "istanbul": "0.3.2", - "jest-cli": "^0.1.18", - "jshint": "2.5.2", - "mocha": "1.20.1", - "mocha-lcov-reporter": "0.0.1", - "pre-commit": "0.0.9", - "react-tools": "^0.12.0", - "supertest": "0.13.0", - "supervisor": "0.6.0", - "xmlbuilder": "2.4.4" - }, - "jest": { - "scriptPreprocessor": "/jest-preprocessor.js", - "unmockedModulePathPatterns": [ - "/node_modules/react" - ], - "moduleFileExtensions": [ - "jsx", - "js" - ] - } + "moduleFileExtensions": [ + "jsx", + "js" + ] + } } diff --git a/public/js/app.jsx b/public/js/app.jsx index 3c9f8253da..22a8ea2ee3 100644 --- a/public/js/app.jsx +++ b/public/js/app.jsx @@ -1,11 +1,14 @@ var React = require('react'); var TabView = require('./components/TabView'); var Menu = require('./components/Menu'); +var UserStore = require('./stores/UserStore'); var LogEntriesComponent = React.createFactory(require('./components/log/LogEntriesComponent')); var FeatureTogglesComponent = React.createFactory(require('./components/feature/FeatureTogglesComponent')); var StrategiesComponent = React.createFactory(require('./components/strategy/StrategiesComponent')); var ArchiveFeatureComponent = React.createFactory(require('./components/feature/ArchiveFeatureComponent')); +UserStore.init(); + var tabPanes = [ { name: 'Feature Toggles', @@ -40,4 +43,4 @@ React.render( , document.getElementById('content') -); \ No newline at end of file +); diff --git a/public/js/components/Menu.jsx b/public/js/components/Menu.jsx index 1015009110..4bfce8a7c8 100644 --- a/public/js/components/Menu.jsx +++ b/public/js/components/Menu.jsx @@ -1,4 +1,5 @@ var React = require('react'); +var User = require('./User'); var Menu = React.createClass({ render: function() { return ( @@ -46,6 +47,9 @@ var Menu = React.createClass({ unleash admin +
+ +
@@ -54,4 +58,4 @@ var Menu = React.createClass({ } }); -module.exports = Menu; \ No newline at end of file +module.exports = Menu; diff --git a/public/js/components/User.jsx b/public/js/components/User.jsx new file mode 100644 index 0000000000..5a4a381c6f --- /dev/null +++ b/public/js/components/User.jsx @@ -0,0 +1,23 @@ +var React = require('react'); +var UserStore = require('../stores/UserStore'); + +var User = React.createClass({ + + onSave: function() { + var value = this.refs.username.getDOMNode().value.trim(); + UserStore.set(value); + }, + + render: function() { + return ( +
+ +
+ ); + } +}); + +module.exports = User; diff --git a/public/js/stores/UserStore.js b/public/js/stores/UserStore.js new file mode 100644 index 0000000000..93421e2660 --- /dev/null +++ b/public/js/stores/UserStore.js @@ -0,0 +1,34 @@ +var _username; + +//Ref: http://stackoverflow.com/questions/10730362/get-cookie-by-name +function readCookie(name) { + var nameEQ = name + "="; + var ca = document.cookie.split(';'); + for(var i=0;i < ca.length;i++) { + var c = ca[i]; + while (c.charAt(0)==' ') { + c = c.substring(1,c.length); + } + if (c.indexOf(nameEQ) === 0) { + return c.substring(nameEQ.length,c.length); + } + } + return null; +} + +var UserStore = { + init: function init() { + _username = readCookie("username"); + }, + + set: function set(username) { + _username=username; + document.cookie="username="+_username+"; expires=Thu, 18 Dec 2099 12:00:00 UTC"; + }, + + get: function get() { + return _username; + } +}; + +module.exports = UserStore;