Dynamic dependencies in Node.js and Ember

0

While working on a bower component for an Ember app, I ran into an issue trying to set up a dynamic hierarchical dependency setup.  As the service I was building is to be added as a dependency to several other projects, there may be any number of modules up the tree that also need to be included into the service’s scope.  While trying to work towards a solution, I came across an annoying limitation in the ES6 spec – you cannot easily import variable modules.

// Doesn't work
import { default as widgets } from '*/widgets/*';

My solution to this problem involved a bunch of digging into how Node implements the new ES6 spec.

The solution actually ended up being a not-terribly-complex one, which is surprising after the trouble I had trying to work to a solution. As an example, let us assume that you are working with a component, trying to import a group of dynamically generated modules from the global scope, say with a pattern of “*/services/*-widget”. Let us also assume that the second wildcard is named after the setting application – adding distinction to the specific widget within the require entries’ scope, and ensuring widgets aren’t overwritten. Finally, let us assume that there are three separate applications at play here, we will call them base, consumer, and public, with “public” being the parent application consuming “consumer”, which in turn consumes “base”.

Setting up the main widget, first I set up the object methods. Rather than setting the whole thing to “export default {…}” and calling it a day, I just define it to the variable “widgetReturn”.

// base/app/services/base-widget.js
// require entry: public/services/base-widget
var widgetReturn = {
	sample: "Base Sample",
	betterSample: "Base Better Sample"
};

For the sake of my sanity, I decided to take a regular expression approach rather than a much-more-involved manual check. The first regular expression will look for all of our widgets, the second will find the primary one. Both ignores the anything ending in “jshint”.

var widgetRegex = new RegExp("services\/(.+\w)-widget(?!\.jshint)", "g");
var precisionRegex = new RegExp("(.+)\/services\/(.+\w)-widget(?!\.jshint)", "g");

Next, we run through the list of required entries, trying to find matches, placing them either at the top of an array if it isn’t the primary entry, or the bottom if it is. This ensures that, while iterating through the resulting array, we include items in a more proper order.

var imports = []; // create an array of imported modules
for (var entry in window.require.entries) { // iterate through module entries
	if (entry.match(localeRegex)) { // does the entry match our first pattern?
		// grab an array of matches based on our second pattern
		var includeCheck = precisionRegex.exec(entry);
 
		// verify that the second pattern has a length of three: the module name, 
		// and the two wildcard matches.
		if (includeCheck !== null && includeCheck.length >= 3) {
			// if the two wildcards match, this is the primary entry
			if (includeCheck[1] === includeCheck[2]) {
				var include = Ember.RSVP.Promise.resolve(window.require(entry));
				imports.push(include);
			} else { // not primary
				var include = Ember.RSVP.Promise.resolve(window.require(entry));
				imports.unshift(include);
			}
		} else { // not primary
			var include = Ember.RSVP.Promise.resolve(window.require(entry));
			imports.unshift(include);
		}
	}
}

Finally, we iterate through the array of imported modules, appending or update the results of the base widget object. Once we’ve finished, we export the freshly-updated widgetReturn object.

for (var i=0; i<imports.length; i++) {
	var impwidget = imports[i]["_result"].default;
	for (var attrName in impwidget) {
		widgetReturn[attrName] = impwidget[attrName];
	}
}
 
export default widgetReturn;

Now, when your consuming applications define widgets of their own, they just need to export the object, and the service above will handle the rest of the work.

// consumer/app/services/consumer-widget.js
// require entry: public/services/consumer-widget
export default {
	sample: "Consumer Sample",
	notQuiteAsGood: "Consumer Not Quite As Good"
};
 
 
// app/services/public-widget.js
// require entry: public/services/public-widget
export default {
	sample: "Public Sample",
	awesome: "Public Awesome"
};

The resulting object being generated from an include of “public/services/base-widget” will return the following. Combining the elements from each of the widget files.

include { default as widgets } from "public/services/base-widget";
 
Widgets:{
	sample: "Public Sample",
	betterSample: "Base Better Sample",
	awesome: "Public Awesome",
	notQuiteAsGood: "Consumer Not Quite As Good"
};

Stand up a Heroku server with Ember

0

I recently started a pet project - some kind of interaction with the facebook API (no spoilers) – built in Ember with a Mongo data store and Rails back end.  There will be more details on that later, but as of now, I would like to complete it a little bit more first.  One thing was clear though, while I was building it, I just wanted to use Heroku to stand it up and get a standalone app running.

After the long and tedious process of bringing my computer up to date – Mid 2010 MBP, been using far-more-up-to-date work MBPs over the years, so this one kinda fell behind – I was ready to stand up a Heroku server and start working… and that was when I discovered that Heroku did not have a “Getting started with Ember” repo.  No big deal, I thought, it shouldn’t be all that hard to get up and running, they have NodeJS after all.  Turns out that it wasn’t all that easy.

As it turns out, Heroku really, really does not like EmberJS.  In the future, that very well may change, but as of right now, it was a no go.  After a whole bunch of internet sleuthing turned up no results, I just started playing around with it to see what it would accept – “heroku run bash” is a godsend.

Long story short, I ended up building a basic Ember app that Heroku didn’t hate, finding a nice mesh between a default NodeJS install and a Heroku setup, I found the “special sauce” of config settings that would result in a working application, and packaged it up in the repo embedded below.

I will revisit this at some point in the near future, as I am absolutely sure there is a way to do this without including the eleventy-billion bower/node component files, making this repo far more light-weight, but every attempt I’ve made so far resulted in Heroku crashing.

The worst thing about all this: about half-way through, I realized it wouldn’t be a good solution for my project.  Sheer curiosity and determination kept me going.  After I was finished, I figured I would share it publicly, making it easier for the next poor soul to try getting Ember working with Heroku.

Feel free to leave a comment below, or within Github, if you have any ideas on ways to improve on this.

https://github.com/jcorradino/ember-js-getting-started

Sears and Kmart Community

0

mySears Community, the place to go to get questions about your appliances and products answered.

The pitch

The Sears and Kmart Community is a place where customers can go to get their questions answered by product experts – whether it is about that weird noise their drier is making, or just a simple question about that TV they’ve had their eye on after seeing it in a weekly ad.  The Community also gives a customer the perfect opportunity to no only get their questions answered, but weigh in on another customer’s questions, or just read up on what is new in whatever field interests them, or find information about what the products they are interested in.

The nitty gritty

The Community sites are sitting on an nginx/MySQL framework with WordPress Networks doing the heavy lifting.  The sites boast well over 1.5 million users, and the ability to add much, much more with Sears and Kmart single sign on capabilities, as well as well as facebook, yahoo, and google single sign on connectivity.  This site will sync all user information across all Sears websites, allowing a returning user – regardless of which web property they visit – the ability to sign on without having to handle new user registration.  As I said above, this site uses networks, and shares many common elements – including themes, database tables, and plugins – all on one system.

This site utilizes a revolutionary “Section Front” implementation – created by Eddie Moya - allowing site editors the ability to create custom category pages with an easy to use and fully customizable click and drag interface.

Hash Authentication

0

The Hash Table generated using this method of authentication.

After coming across this article on Reddit today, and chatting with a good friend and colleague about the benefits and issues of using the authentication method outlined by the author, we both came to the conclusion that we were not fans of the way the author handled the hash table comparisons for users, so I decided to work on it a little bit at home and try to make it better.

Before I go into details, here are the database tables I created to get this authentication to work:

mysql> DESCRIBE hashes;
+_______+_____________+______+_____+_________+_______+
| FIELD  | TYPE         | NULL  | KEY | DEFAULT  | Extra |
+_______+_____________+______+_____+_________+_______+
| hash  | VARCHAR(64)   | NO   | PRI | NULL    |       |
| salt  | VARCHAR(64)   | NO   |     | NULL    |       |
+_______+_____________+______+_____+_________+_______+
2 ROWS IN SET (0.01 sec)
 
mysql> DESCRIBE users;
+__________+_____________+______+_____+_________+________________+
| FIELD     | TYPE         | NULL | KEY  | DEFAULT | Extra           |
+__________+_____________+______+_____+_________+________________+
| uid      | INT(11)       | NO   | PRI | NULL    | AUTO_INCREMENT  |
| username | VARCHAR(30)   | NO   |     | NULL    |                |
| hash     | VARCHAR(64)   | NO   |     | NULL    |                |
| salt     | VARCHAR(64)   | NO   |     | NULL    |                |
+__________+_____________+______+_____+_________+________________+
4 ROWS IN SET (0.00 sec)

I set the hash field in the hashes table to an indexed column to allow quick(er) searching through the table, trying to alleviate the issues we might run into if this table becomes too large. Without the user’s password, there is no connection between these two tables, as it is required to generate the data within the hash column in the hashes table. Creating a user would happen like so:

// note, this uses my database class, which can be found at http://code.imyourdeveloper.com/database.txt
function create($applicationSalt, $user) {
	//generate salts
	$userSalt = hash("sha256", $applicationSalt.rand().time());
	$hashesSalt = hash("sha256", $applicationSalt.rand().time().$applicationSalt);
 
	//generate hashes
	$userHash = hash("sha256", $applicationSalt.$user->password.$hashSalt);
	$hashesHash = hash("sha256", $applicationSalt.$user->password.$userSalt);
 
	//create queries
	$user = 'insert into users (uid, username, hash, salt) values (null, "'.$user->username.'", "'.$userHash.'", "'.$userSalt.'")';
	$hash = 'insert into hashes (hash, salt) values ("'.$hashesHash.'", "'.$hashesSalt.'")';
 
	//run queries
	$db->query($user);
	$db->query($hash);
}

This was a little bit of a pain, and took some staring at my monitor to wrap my head around, trying to remember what went where, but I eventually got it working. The application salt is your secret salt set in the application that you will use to salt data going to the database, and user passes through any data you want to write about the user to the database. A combination of the user salt, the application hash, and the user’s password is used to generate the user hash and the authentication lookup hash in the hashes table. When the user types in a password, it runs through the algorithm creating a hash, looks up that hash in the hashes table, recalculates another hash using a randomly generated salt in the hashes table, the user’s password, and the application salt, then compares with the hash in the Users table. If this matches, then the user is who he says he is, and is logged in. This happens like so:

function lookup($applicationSalt, $user) {
	GLOBAL $db;
 
	$userLookup = $db->getObj('select * from Users where username = "'.$user->username.'"');
	$check = $applicationHash.$user->password.$userLookup->salt;
	$hash = hash("sha256", $check);
 
	$hashSalt = $db->getObj("select * from Hashes where hash = '$hash'")->salt;
	if ($userLookup->hash == hash("sha256", $applicationSalt.$user->password.$hashSalt)) {
		return true; // logged in
	} else {
		return false; // login failed
	}
}

This may not be a perfect implementation of this code, but I wasn’t a fan of the way it was being handled in the other article; and this was a neat little problem to work on, so expect updates in the future.. The mathematical probability of you being able to brute force the user’s password was astronomically low before, but it was nothing more than a one-way relation. This way, you not only need to brute force the users password to go one way (towards the hashes table), but the password you get is likely not going to work, as another hash is checked going in reverse, ensuring the only string that is accepted is the user’s.

If you have any better ideas of how to implement this, please feel free to post it below. Click here for a full version of the code above.

Go to Top