Yoji SHIDARA
null+****@clear*****
Tue Dec 4 18:48:15 JST 2012
Yoji SHIDARA 2012-12-04 18:48:15 +0900 (Tue, 04 Dec 2012) New Revision: 3bf4b46de50c4b4b41092314b11b2c31428c0767 https://github.com/groonga/gcs-console/commit/3bf4b46de50c4b4b41092314b11b2c31428c0767 Log: Configure admin user at the first time Added files: lib/config.js views/admin-password.jade Modified files: app.js bin/gcs-console routes/index.js test/create-and-delete-domain.test.js test/create-and-search-domain.test.js test/index-fields.test.js test/index.test.js test/test-utils.js Modified: app.js (+17 -8) =================================================================== --- app.js 2012-11-29 12:21:19 +0900 (9ee899d) +++ app.js 2012-12-04 18:48:15 +0900 (c60d50b) @@ -3,17 +3,23 @@ var express = require('express') , http = require('http') , path = require('path'); var flash = require('connect-flash'); +var Config = require('./lib/config').Config; function setupApplication(app) { - var auth = function(req, res, next) { - // middleware that does nothing - next(); - }; + var auth; + + var config = new Config(app.get('home')); + app.set('config', config); - var user = app.get('user'), password = app.get('password'); - if (user && password) { - auth = express.basicAuth(user, password); - } + auth = function(req, res, next) { + var username = config.data.adminUsername; + var password = config.data.adminPassword; + if (username && password) { + return express.basicAuth(username, password)(req, res, next); + } else { + return res.redirect('/admin/password'); + } + }; app.configure(function(){ app.set('views', __dirname + '/views'); @@ -50,6 +56,9 @@ function setupApplication(app) { app.post('/domain/:name/index_fields', auth, routes.domainCreateIndexField); app.delete('/domain/:name/index_fields/:indexFieldName', auth, routes.domainDeleteIndexField); app.delete('/domain/:name', auth, routes.domainDelete); + + app.get('/admin/password', routes.adminPassword); + app.post('/admin/password', routes.adminPasswordPost); } module.exports.setupApplication = setupApplication; Modified: bin/gcs-console (+8 -20) =================================================================== --- bin/gcs-console 2012-11-29 12:21:19 +0900 (592a286) +++ bin/gcs-console 2012-12-04 18:48:15 +0900 (6782f40) @@ -11,8 +11,8 @@ var app = express(); var defaults = { port: process.env.GCS_CONSOLE_PORT || 7576, endpoint: process.env.GCS_CONSOLE_ENDPOINT || 'http://localhost:7575', - auth: process.env.GCS_CONSOLE_AUTH || '' -}; + gcsConsoleHome: process.env.GCS_CONSOLE_HOME || process.env.HOME + '/.gcs-console' +} program .version(version) @@ -24,33 +24,21 @@ program 'Endpoint of Target Server. [' + defaults.endpoint + ']', String, defaults.endpoint) - .option('--auth <user:password>', - 'Request basic authorizatoin', - String) + .option('--gcs-console-home [path]', + 'Config file path [' + defaults.gcsConsoleHome + ']', + String, + defaults.gcsConsoleHome) .parse(process.argv); app.set('port', program.port); app.set('endpoint', program.endpoint); - -if (program.auth) { - var match = program.auth.match(/^(.*?):(.*)$/); - if (match) { - var user = match[1], password = match[2]; - app.set('user', user); - app.set('password', password); - console.log('Basic authorization for user <' + user + '> is activated'); - } else { - console.log('You must specify the parameter for --auth in user:password'); - process.exit(-1); - } -} else { - console.log('Basic authorization is not configured. Anyone can control your Groonga CloudSearch Console.'); -} +app.set('home', program.gcsConsoleHome); setupApplication(app); http.createServer(app).listen(app.get('port'), function(){ console.log("Groonga CloudSearch Console listening on port " + app.get('port')); + console.log('Groonga CloudSearch home is at ' + app.get('home')); console.log('Backend is ' + app.get('endpoint')); }); Added: lib/config.js (+28 -0) 100644 =================================================================== --- /dev/null +++ lib/config.js 2012-12-04 18:48:15 +0900 (f3b24e4) @@ -0,0 +1,28 @@ +var fs = require('fs'); +var mkdirp = require('mkdirp'); + +var CONFIG_FILE_NAME = 'config.json'; +var Config = function(home) { + this.home = home; + this.load(); +}; + +Config.prototype = { + home: null, + data: {}, + configFilePath: function() { + return this.home + '/' + CONFIG_FILE_NAME; + }, + load: function() { + if (fs.existsSync(this.configFilePath())) { + this.data = JSON.parse(fs.readFileSync(this.configFilePath())); + } + }, + save: function() { + var json = JSON.stringify(this.data); + mkdirp.sync(this.home); + fs.writeFileSync(this.configFilePath(), json); + } +}; + +module.exports.Config = Config; Modified: routes/index.js (+31 -0) =================================================================== --- routes/index.js 2012-11-29 12:21:19 +0900 (3f3ba2c) +++ routes/index.js 2012-12-04 18:48:15 +0900 (7270553) @@ -352,3 +352,34 @@ exports.domainUploadPost = function(req, res) { }); }); }; + +exports.adminPassword = function(req, res) { + var config = req.app.get('config'); + if (config.data.adminUsername && config.data.adminPassword) { + return res.redirect('/'); + } + return res.render('admin-password'); +}; + +var Config = require('../lib/config').Config; +exports.adminPasswordPost = function(req, res) { + var config = req.app.get('config'); + + if (config.data.adminUsername && config.data.adminPassword) { + return res.redirect('/'); + } + + var username = req.body.username; + var password = req.body.password; + + if (username && password) { + config.data.adminUsername = username; + config.data.adminPassword = password; + config.save(); + return res.redirect('/'); + } else { + return res.render('admin-password', { + error: new Error('Username and Password should not be empty') + }); + } +}; Modified: test/create-and-delete-domain.test.js (+7 -1) =================================================================== --- test/create-and-delete-domain.test.js 2012-11-29 12:21:19 +0900 (7553787) +++ test/create-and-delete-domain.test.js 2012-12-04 18:48:15 +0900 (ba9207e) @@ -2,10 +2,15 @@ var assert = require('chai').assert; var Browser = require('zombie'); var Target = require('./test-utils').Target; +var config = { + adminUsername: 'user', + adminPassword: 'pass' +}; + suite('dashboard', function() { var target = new Target(); setup(function(done) { - target.setup(done) + target.setup(done, config) }); teardown(function() { target.teardown() @@ -13,6 +18,7 @@ suite('dashboard', function() { test('Create and delete a domain', function(done) { var browser = new Browser(); + browser.authenticate().basic('user', 'pass'); browser .visit(target.rootURL) .then(function() { Modified: test/create-and-search-domain.test.js (+8 -2) =================================================================== --- test/create-and-search-domain.test.js 2012-11-29 12:21:19 +0900 (30e1eac) +++ test/create-and-search-domain.test.js 2012-12-04 18:48:15 +0900 (ed7b74f) @@ -2,10 +2,15 @@ var assert = require('chai').assert; var Browser = require('zombie'); var Target = require('./test-utils').Target; +var config = { + adminUsername: 'user', + adminPassword: 'pass' +}; + suite('dashboard', function() { var target = new Target(); setup(function(done) { - target.setup(done) + target.setup(done, config) }); teardown(function() { target.teardown() @@ -13,6 +18,7 @@ suite('dashboard', function() { test('Create, upload and search', function(done) { var browser = new Browser(); + browser.authenticate().basic('user', 'pass'); browser .visit(target.rootURL) .then(function() { @@ -72,7 +78,7 @@ suite('dashboard', function() { .then(function() { // Zombie.js does not handle GET form at this time. // So hit the search result page directly. - return browser.visit('/domain/companies/search?query=tokyo'); + return browser.visit(target.rootURL + 'domain/companies/search?query=tokyo'); }) .then(function() { assert.equal(browser.text('.alert-info'), 'Found 3 records. Showing 1 - 3 (3 records).'); Modified: test/index-fields.test.js (+7 -1) =================================================================== --- test/index-fields.test.js 2012-11-29 12:21:19 +0900 (db54931) +++ test/index-fields.test.js 2012-12-04 18:48:15 +0900 (5641508) @@ -2,10 +2,15 @@ var assert = require('chai').assert; var Browser = require('zombie'); var Target = require('./test-utils').Target; +var config = { + adminUsername: 'user', + adminPassword: 'pass' +}; + suite('dashboard', function() { var target = new Target(); setup(function(done) { - target.setup(done) + target.setup(done, config) }); teardown(function() { target.teardown() @@ -13,6 +18,7 @@ suite('dashboard', function() { test('Create domain, add an index field and delete the index field', function(done) { var browser = new Browser(); + browser.authenticate().basic('user', 'pass'); browser .visit(target.rootURL) .then(function() { Modified: test/index.test.js (+42 -5) =================================================================== --- test/index.test.js 2012-11-29 12:21:19 +0900 (3148d94) +++ test/index.test.js 2012-12-04 18:48:15 +0900 (90499a2) @@ -2,7 +2,12 @@ var assert = require('chai').assert; var Browser = require('zombie'); var Target = require('./test-utils').Target; -suite('dashboard', function() { +var config = { + adminUsername: 'user', + adminPassword: 'pass' +}; + +suite('first time', function() { var target = new Target(); setup(function(done) { target.setup(done) @@ -11,8 +16,40 @@ suite('dashboard', function() { target.teardown() }); + test('config admin user', function(done) { + var browser = new Browser(); + + browser.authenticate().basic('user', 'pass'); + browser + .visit(target.rootURL) + .then(function() { + assert.equal(browser.location.pathname, '/admin/password'); + assert.equal(browser.text('.alert'), 'The admin account for Groonga CloudSearch Console has not been configured yet. You must configure it to use Groonga CloudSearch Console.'); + }) + .then(function() { + browser.fill('username', 'user'); + browser.fill('password', 'pass'); + return browser.pressButton('Save') + }) + .then(function() { + assert.equal(browser.text('title'), 'Groonga CloudSearch Console'); + }) + .then(done, done); + }); +}); + +suite('dashboard', function() { + var target = new Target(); + setup(function(done) { + target.setup(done, config) + }); + teardown(function() { + target.teardown() + }); + test('GET /', function(done) { var browser = new Browser(); + browser.authenticate().basic('user', 'pass'); browser.visit(target.rootURL). then(function() { assert.ok(browser.success); @@ -25,10 +62,10 @@ suite('dashboard', function() { }); }); -suite('Basic auth configured', function() { - var target = new Target({auth: 'user:password'}); +suite('Password configured', function() { + var target = new Target(); setup(function(done) { - target.setup(done) + target.setup(done, config) }); teardown(function() { target.teardown() @@ -57,7 +94,7 @@ suite('Basic auth configured', function() { test('GET / with correct password', function(done) { var browser = new Browser(); - browser.authenticate().basic('user', 'password'); + browser.authenticate().basic('user', 'pass'); browser.visit(target.rootURL) .then(function() { assert.ok(browser.success); Modified: test/test-utils.js (+13 -8) =================================================================== --- test/test-utils.js 2012-11-29 12:21:19 +0900 (42d2b28) +++ test/test-utils.js 2012-12-04 18:48:15 +0900 (0e4ff2b) @@ -27,15 +27,13 @@ var Target = function(options) { this.gcsPath = __dirname + '/../node_modules/.bin/gcs'; this.gcsConsolePath = __dirname + '/../bin/gcs-console'; this.rootURL = 'http://localhost:' + this.gcsConsolePort + '/'; - if (options) { - this.auth = options.auth; - } + this.gcsConsoleHome = this.databaseDir + '/gcs-console'; }; Target.prototype = { gcs: null, gcsConsole: null, - setup: function(done) { + setup: function(done, config) { var self = this; var gcsOptions = [ '--database-path', self.databasePath, @@ -43,11 +41,9 @@ Target.prototype = { ]; var gcsConsoleOptions = [ '--port', self.gcsConsolePort, - '--endpoint', 'http://localhost:' + self.gcsPort + '--endpoint', 'http://localhost:' + self.gcsPort, + '--gcs-console-home', self.gcsConsoleHome ]; - if (self.auth) { - gcsConsoleOptions = gcsConsoleOptions.concat(['--auth', self.auth]); - } if (!existsSync(self.gcsPath)) { var error = new Error('gcs executable is not found at ' + self.gcsPath + '. You need to setup gcs to test with gcs-console. Run "npm install gcs" (for the latest release) or "npm install git://github.com/groonga/gcs.git" (for the development)'); @@ -55,10 +51,19 @@ Target.prototype = { } mkdirp.sync(self.databaseDir); + self.gcs = runServer(self.gcsPath, gcsOptions, function() { process.on('exit', function() { self.teardown(); }); + + if (config) { + mkdirp.sync(self.gcsConsoleHome); + var configFilePath = self.gcsConsoleHome + '/config.json'; + var json = JSON.stringify(config); + fs.writeFileSync(configFilePath, json); + } + self.gcsConsole = runServer( self.gcsConsolePath, gcsConsoleOptions, Added: views/admin-password.jade (+20 -0) 100644 =================================================================== --- /dev/null +++ views/admin-password.jade 2012-12-04 18:48:15 +0900 (245607e) @@ -0,0 +1,20 @@ +extends layout + +block application + p.alert.alert-info + | The admin account for Groonga CloudSearch Console has not been configured yet. + | You must configure it to use Groonga CloudSearch Console. + + + form(action="/admin/password", method="post").form-horizontal + .control-group + label.control-label Username + .controls + input(type="text", name="username") + .control-group + label.control-label Password + .controls + input(type="password", name="password") + .control-group + .controls + button.btn.btn-primary(type="submit") Save -------------- next part -------------- HTML����������������������������... Download