Skip to content

Commit

Permalink
Bug 968989 - Rename apiUser apiApp
Browse files Browse the repository at this point in the history
  • Loading branch information
simonwex authored and Christopher De Cairos committed Mar 28, 2014
1 parent ebf819d commit 22ca161
Show file tree
Hide file tree
Showing 12 changed files with 156 additions and 49 deletions.
5 changes: 0 additions & 5 deletions env.sample
Expand Up @@ -16,11 +16,6 @@ export MONGO_URL='mongodb://localhost/makeapi'
# Host and port for your Elastic search cluster
export ELASTIC_SEARCH_URL='http://localhost:9200'

# A List of allowed users for write operations to the database
# List in this format: "user:pass,user2:pass"
# You shouldn't use this username/password combo yourself
export ALLOWED_USERS='testuser:password'

# Persona
export AUDIENCE="http://localhost:7777"

Expand Down
5 changes: 2 additions & 3 deletions lib/middleware.js
Expand Up @@ -10,11 +10,10 @@ var http = require( "http" ),
hawkModule = require( "./hawk" )(),
tags = require( "./tags" )();


module.exports = function( makeModel, apiUserModel ) {
module.exports = function( makeModel, apiAppModel ) {
var Make = makeModel,
hawkOptions = {},
credentialsLookupStrategy = require( "./strategy" )( apiUserModel, env.get( "USE_DEV_KEY_LOOKUP" ) ),
credentialsLookupStrategy = require( "./strategy" )( apiAppModel, env.get( "USE_DEV_KEY_LOOKUP" ) ),
LOGIN_API = env.get( "LOGIN_SERVER_URL_WITH_AUTH" );

// API Key write permissions feature flag
Expand Down
8 changes: 6 additions & 2 deletions lib/models/apiUser.js → lib/models/apiApp.js
Expand Up @@ -16,6 +16,10 @@
required: true,
unique: true
},
domain: {
type: String,
required: true,
},
revoked: {
type: Boolean,
required: true,
Expand All @@ -33,8 +37,8 @@
}
});

var ApiUser = mongoose.model( "ApiUser" , schema );
var ApiApp = mongoose.model( "ApiApp" , schema );

return ApiUser;
return ApiApp;

};
2 changes: 1 addition & 1 deletion lib/models/make.js
Expand Up @@ -163,7 +163,7 @@ module.exports = function( mongoInstance ) {

Make.createMapping(function( err, mapping ) {
if ( err ) {
console.log( "failed to create mapping", err.toString() );
console.log( "Failed to create mapping. Is ElasticSearch Running?\n", err.toString() );
}
});

Expand Down
4 changes: 2 additions & 2 deletions lib/strategy.js
Expand Up @@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

module.exports = function( ApiUser, devMode ) {
module.exports = function( ApiApp, devMode ) {
var DEVKEY = "00000000-0000-0000-000000000000",
uuid = require( "uuid" );

Expand All @@ -26,7 +26,7 @@ module.exports = function( ApiUser, devMode ) {
algorithm: "sha256",
user: publickey
};
ApiUser.findOne({ publickey: publickey }, function( err, doc ) {
ApiApp.findOne({ publickey: publickey }, function( err, doc ) {
if ( err || !doc ) {
return callback( err );
}
Expand Down
101 changes: 101 additions & 0 deletions migrations/20140206-apiApp.js
@@ -0,0 +1,101 @@
/* This script will migrate all ApiUser records into ApiApp records
*
* run this script from the root of the project like so:
* node migrations/20140206-apiApp <existingContact>::<domain> <existingContact>::<domain> ...
*/

var habitat = require( "habitat" ),
async = require( "async" ),
validate = require( "mongoose-validator" ).validate,
slicedArgs = process.argv.slice( 2 ),
mongoStreamEnded = false,
env,
mongoose;

var domainMap = {};

slicedArgs.forEach(function( arg ) {
arg = arg.split( '::' );
domainMap[ arg[0] ] = arg[1];
});

function getApiUser( mongoose ) {
return mongoose.model( "ApiUser" , new mongoose.Schema({
privatekey: {
type: String,
required: true,
unique: true
},
publickey: {
type: String,
required: true,
unique: true
},
revoked: {
type: Boolean,
required: true,
"default": false
},
contact: {
type: String,
required: true,
validate: validate( "isEmail" )
},
admin: {
type: Boolean,
required: true,
"default": false
}
}));
}

habitat.load();
env = new habitat();

dbh = require( "../lib/mongoose" )( env, function( err ) {
if ( err ) {
console.log( err );
process.exit( 1 );
}

var ApiApp = require( "../lib/models/apiApp" )( env, dbh.mongoInstance() ),
ApiUser = getApiUser( dbh.mongoInstance() ),
stream = ApiUser.find().stream(),
queue = async.queue(function( doc, done ) {

var app = new ApiApp({
contact: doc.contact,
privatekey: doc.privatekey,
publickey: doc.publickey,
domain: domainMap[ doc.contact ],
revoked: doc.revoked,
admin: doc.admin
});

app.save(function( err ) {
if ( err ) {
console.log( "Failure saving document:" );
console.log( app );
console.log( err );
process.exit( 1 );
}
done();
});
}, 4 );// concurrency of 4

queue.drain = function() {
if ( mongoStreamEnded ) {
console.log( "completed!" );
process.exit( 0 );
}
};

stream.on( "data", function onData( doc ) {
queue.push( doc );
}).on( "error", function( err ) {
console.log( err );
process.exit( 1 );
}).on( "end", function() {
mongoStreamEnded = true;
});
});
14 changes: 8 additions & 6 deletions public/js/admin.js
Expand Up @@ -517,13 +517,14 @@ document.addEventListener( "DOMContentLoaded", function() {
pager.goToPage( 1 );

var contactEmail = document.querySelector( "#app-contact"),
createUser = document.querySelector( "#add-user" ),
createResult = document.querySelector( "#user-result" );
domain = document.querySelector( "#app-domain" ),
createApp = document.querySelector( "#add-app" ),
createResult = document.querySelector( "#app-result" );

function generateKeys() {
var request = new XMLHttpRequest();

request.open( "POST", "/admin/api/user", true );
request.open( "POST", "/admin/api/app", true );
request.setRequestHeader( "X-CSRF-Token", csrfToken ); // express.js uses a non-standard name for csrf-token
request.setRequestHeader( "Content-Type", "application/json; charset=utf-8" );
request.onreadystatechange = function() {
Expand All @@ -545,21 +546,22 @@ document.addEventListener( "DOMContentLoaded", function() {
}
};
request.send(JSON.stringify({
contact: contactEmail.value
contact: contactEmail.value,
domain: domain.value
}));
}

if ( isAdmin ) {

createUser.addEventListener( "keypress", function( e ) {
createApp.addEventListener( "keypress", function( e ) {
if ( e.which === 13 ) {
e.preventDefault();
e.stopPropagation();
generateKeys();
}
}, false );

createUser.addEventListener( "click", generateKeys, false );
createApp.addEventListener( "click", generateKeys, false );
}

// Remix Counter
Expand Down
24 changes: 12 additions & 12 deletions routes/admin.js
Expand Up @@ -8,9 +8,9 @@

var env = require( "../lib/environment" );

module.exports = function( apiUserModel ) {
module.exports = function( apiAppModel ) {
var uuid = require( "uuid" ),
ApiUser = apiUserModel,
App = apiAppModel,
audience = env.get( "AUDIENCE" ),
login = env.get( "LOGIN_SERVER" ),
personaHostname = env.get( "PERSONA_HOSTNAME", "https://login.persona.org" );
Expand All @@ -35,25 +35,25 @@ module.exports = function( apiUserModel ) {
personaHostname: personaHostname
});
},
addUser: function( req, res ) {
var newUser = req.body;
addApp: function( req, res ) {
var newApp = req.body;

if ( !newUser.contact ) {
if ( !newApp.contact || !newApp.domain ) {
return res.json( 400, { error: "Missing data" } );
}

newUser.privatekey = uuid.v4();
newUser.publickey = uuid.v4();
newUser.revoked = false;
newUser.admin = false;
newApp.privatekey = uuid.v4();
newApp.publickey = uuid.v4();
newApp.revoked = false;
newApp.admin = false;

var user = new ApiUser( newUser );
var app = new App( newApp );

user.save(function( err, user ) {
app.save(function( err, app ) {
if ( err ) {
res.json( 500, { error: err } );
} else {
res.json( { user: user } );
res.json( { app: app } );
}
});
}
Expand Down
6 changes: 3 additions & 3 deletions routes/index.js
Expand Up @@ -4,9 +4,9 @@

var env = require( "../lib/environment" );

module.exports = function routesCtor( makeModel, apiUserModel ) {
module.exports = function routesCtor( makeModel, apiAppModel ) {
var makeRoutes = require( "./make" )( makeModel ),
adminRoutes = require( "./admin" )( apiUserModel );
adminRoutes = require( "./admin" )( apiAppModel );

return {
index: function( req, res ) {
Expand All @@ -22,6 +22,6 @@ module.exports = function routesCtor( makeModel, apiUserModel ) {
healthcheck: makeRoutes.healthcheck,
admin: adminRoutes.admin,
login: adminRoutes.login,
addUser: adminRoutes.addUser
addApp: adminRoutes.addApp
};
};
14 changes: 7 additions & 7 deletions scripts/generateKeys.js
Expand Up @@ -28,27 +28,27 @@ dbh = require( "../lib/mongoose" )( env, function( err ) {
process.exit( 1 );
}

var ApiUser = require( "../lib/models/apiUser" )( env, dbh.mongoInstance() ),
users = [];
var ApiApp = require( "../lib/models/apiApp" )( env, dbh.mongoInstance() ),
apps = [];

for ( var i = 0; i < numPairs; i++ ) {
users.push( new ApiUser({
apps.push( new ApiApp({
contact: contactEmail,
privatekey: uuid.v4(),
publickey: uuid.v4(),
revoked: false,
admin: !!isAdmin
admin: !!isAdmin // This means "Internal Webmaker"
}));

}

async.eachSeries( users, function( user, cb ) {
user.save(function( err, user ){
async.eachSeries( apps, function( app, cb ) {
app.save(function( err, app ){
if ( err ) {
return cb( err );
}
console.log( "Keys generated for %s\nPRIVATEKEY: %s\nPUBLICKEY: %s\nadmin: %s",
contactEmail, user.privatekey, user.publickey, isAdmin );
contactEmail, app.privatekey, app.publickey, isAdmin );
cb();
});
}, function done( err ) {
Expand Down
8 changes: 4 additions & 4 deletions server.js
Expand Up @@ -19,7 +19,7 @@ var app = express(),
env = require( "./lib/environment" ),
Mongo = require( "./lib/mongoose" )(),
Make = require( "./lib/models/make" )( Mongo.mongoInstance() ),
ApiUser = require( "./lib/models/apiUser" )( Mongo.mongoInstance() ),
apiApp = require( "./lib/models/apiApp" )( Mongo.mongoInstance() ),
nunjucksEnv = new nunjucks.Environment( new nunjucks.FileSystemLoader( path.join( __dirname + "/views" ) ), { autoescape: true } ),
csrfMiddleware = express.csrf(),
webmakerAuth = new WebmakerAuth({
Expand Down Expand Up @@ -81,8 +81,8 @@ app.use(express.static(tmpDir));

app.use( app.router );

var routes = require( "./routes" )( Make, ApiUser ),
middleware = require( "./lib/middleware" )( Make, ApiUser );
var routes = require( "./routes" )( Make, apiApp ),
middleware = require( "./lib/middleware" )( Make, apiApp );

app.use( middleware.errorHandler );
app.use( middleware.fourOhFourHandler );
Expand Down Expand Up @@ -127,7 +127,7 @@ app.get( "/login", csrfMiddleware, routes.login );
app.get( "/admin", csrfMiddleware, middleware.collabAuth, routes.admin );

// Admin tool path for generating Hawk Keys
app.post( "/admin/api/user", csrfMiddleware, middleware.adminAuth, Mongo.isDbOnline, routes.addUser );
app.post( "/admin/api/app", csrfMiddleware, middleware.adminAuth, Mongo.isDbOnline, routes.addApp );

// Serve makeapi-client.js over http
app.get( "/js/make-api.js", function( req, res ) {
Expand Down
14 changes: 10 additions & 4 deletions views/admin.html
Expand Up @@ -145,14 +145,20 @@ <h3 class="remix-count-header"> Remix Count </h3>
</div>
</div>
<div class="control-group">
<label class="control-label" for="add-user"></label>
<label class="control-label" for="app-domain">Domain:</label>
<div class="controls">
<button id="add-user" type="button" name="add-user" class="btn btn-success">Add User</button>
<input id="app-domain" name="app-domain" placeholder="Domain" class="input-large" type="text">
</div>
</div>
<div class="control-group">
<label for="user-result" class="control-label"></label>
<textarea id="user-result" class="input-xlarge"></textarea>
<label class="control-label" for="add-app"></label>
<div class="controls">
<button id="add-app" type="button" name="add-app" class="btn btn-success">Add App</button>
</div>
</div>
<div class="control-group">
<label for="app-result" class="control-label"></label>
<textarea id="app-result" class="input-xlarge"></textarea>
</div>
</fieldset>
</form>
Expand Down

0 comments on commit 22ca161

Please sign in to comment.