HR, the PR and competency of a company (naive approach)

This article is wrote before I take my course in HR, it represents my vision of it as I have interacted with it (such as being recruited)

HR is more often than not the deepest take people have in a company they wish to work in.

All these participants will carry a profound impression of the company. It is of extreme importance that HR realize this.

Those who are not called in are likely to carry a negative impression of the company due frustration. But it would be the recruiter minimal obligation to minimize the damage to PR and even maybe turn it into something positive!

Since the daily dynamics recruiters may forget the humans interactions taking place, and more often than not participants are discarded as non-fitting products. Without realizing, by selecting people based on simple text matching of skills and requirements are diminishing the importance of their own jobs.

Head software engineers that shape communities and influence the paths of technology development make lots of fun of clueless recruiters that don’t know what they are doing. The companies that they are recruiting for are mocked.

Not to say, that unless recruiters are in deep sync with both the technologies and products they are hiring people to develop / serve they cannot do a good job! Any correct screen would be sheer luck.

Bottom-line, HR shouldn’t be shallow recruiting somebody with skills x/y/z, must go through a deeper understanding and be as crafty as possible at the process. Much to learn from journalists in this sense.

Advertisements

Be able to communicate or failed to learn

Likewise Pics or it didn’t happen I will shift a bit the content of my posts as I am taking Project Management Diploma.

Frequently interesting insights take place but I don’t write, so they endup dissolved (they are not entirely gone anyways).

Subjects address interesting business topics such as TQM, Six Sigma, Accounting, Competitive Advantage, RH, Capacity Decisions and such will be addressed in future posts.

Remove jQTouch + maps lag

Hello!

jQTouch still is a pretty good tool, with performance out-of-the box for old mobiles (being faster then jQMobile), but with some sharp edges.

The problem I deal with in this post may come in a couple of factors, such as:

  • When combined with Google Maps, there is an insane lag when panning (scrolling) the map.
  • General scroll is slow.
  • Some components are slow, particularly when under CSS transition.

At first I thought that either it had a bad interaction with Phonegap, or poor handling of events.

What I find happening that was pretty bad, and almost made me drop it’s use entirely is that it applied some CSS perspective to the body on the bundled apple.css

bad transform

What a bad perspective..

This made the map feel laggy on the Desktop and incredibly bad on iOS!

So, as solution, you have at least 2 options:

1) Remove the property from the .css

2) After jQTouch has been initialized, run a function that remove  the 3D support flag, like so:

$(‘#jqt’).removeClass(‘supports3d’)

Done! =)

Posting a photo (as a business) to a Facebook Page via JavaScript SDK

The Facebook Javascript SDK (API) is not so well documented, what makes not so logical to post to a page, using it. For that I am about to show, make sure your connect scope having at least: “manage_pages,publish_actions,publish_stream”.

I am assuming you already succeeded providing login to the user; if this is not the case, refer to the docs.

We rely heavily on the FB.api method, the docs make a poorly job documenting, but is a starting point anyway. Also, notice the response is async.

Fetch all user pages (actually the first 5k), but only store the first as var page (this is just a sample)

var page = null;
FB.api('/me/accounts', function(response) { console.log(response); page = response.data[0]; })

Now, we want to publish a post to the page timeline, the thing is, we are not posting as ‘me’ anymore, we must post as the page, and it requires both the id and access_token!
I will make a sample function for it, the response is the post id if it all went well, or an error.

function postToPage(page, msg){
  FB.api('/'+page.id+'/feed', 'post', { message: msg, access_token: page.access_token },
    function(res) { console.log(res) }
  )
}
postToPage(page, 'hello fb-page world')

For last, posting a picture requre the url param, like so:

function photoToPage(page, src, msg){
  FB.api('/'+page.id+'/photos', 'post', { url: src, message:msg, access_token: page.access_token },
    function(res) { console.log(res) }
  )
}
photoToPage(page, 'http://24.media.tumblr.com/tumblr_m1ttif5puW1qcrr0lo1_500.png', 'nyan art')

* Don’t try to run all functions in sequence, since the result comes asynchronously you wont have the var page set.

** kudos for Владимир Дворник answer on Stack Overflow for the url param not documented in the Page Graph API.

*** Security note. The JavaScript SDK can be very unsafe in the case a hacker is able to inject JS code in your page (and even happens in Twitter all the time even though they have millions in funding) they may take advantage of all of the user’s permissions.

Done!

ImageMagick on Joyent

It is really simple:


pkgin search ImageMagick # you will get some result like this:
ImageMagick-6.6.6.5 Package for display and interactive manipulation of images
p5-PerlMagick-6.6.6.5 Object-oriented Perl interface to ImageMagick
php53-imagick-5.3.5.2.2.2 Provides a wrapper to the ImageMagick library
ruby18-RMagick-2.13.1nb3 Ruby binding to ImageMagick
ruby18-mini-magick-2.1 Ruby wrapper for ImageMagick command line
ruby19-RMagick-2.13.1nb3 Ruby binding to ImageMagick
ruby19-mini-magick-2.1 Ruby wrapper for ImageMagick command line

Now, install the latest version, today it is 6.6.6.5, so run:

pkgin install ImageMagick-6.6.6.5

Done!

For the Node.js package “imagemagick” at “0.1.2” works for my use cases, which are just resizes 🙂
If you are using other languages you may need the other packages as well.

Mongoose validate unique field (insensitive)

Making a validation function for Mongoose (Node.js – MongoDB ODM) that checks upon validation field.

function uniqueFieldInsensitive ( modelName, field ){
	return function(val, cb){
		if( val && val.length ){ // if string not empty/null
			
			var query = mongoose.models[modelName]
				.where( field, new RegExp('^'+val+'$', 'i') ) // lookup the collection for somthing that looks like this field 
			
			if( !this.isNew ){ // if update, make sure we are not colliding with itself
				query = query.where('_id').ne(this._id)
			}
			
			query.count(function(err,n){
				// false when validation fails
				cb( n < 1 )
			})
		} else { // raise error of unique if empty // may be confusing, but is rightful
			cb( false )
		}
	}
}

Then call it to a field (aka path):

UserSchema.path('nick').validate( uniqueFieldInsensitive('User', 'nick' ), 'unique' )

Recommend you organize all validations in a file for itself, or even a folder if grows too big.

If you have a unique index set for the path you may just save it and check for the error raised; the thing is the format of the error.

Basic Authentication on Node.js – Express and Mongoose

via Axiom Zen

Hello!

This post is about the most important parts I can think of implementing signup and login to Node.js powered by Mongoose and Express.js.

This post have a huge audience, but guys, please keep in mind that this post was done a while ago. It works pretty well as a cook-book, but there probably are better options for achieving this nowadays, new npm packages and such.

Implementing last night, I was impressed on how fast had the functional part done (around 3 hours), pretty much the same time I’d had it done in Rails (if not faster).

Goal:

  • 3 urls: GET login & signup, POST login, POST signup.
  • User fields: email, nick, password(encrypted).
  • Validate (and show) messages for all fields.
I’ve setup a small Github project that may be used as example (assuming you have mongoDB installed and running in localhost) – DOWNLOAD IT FROM GITHUB  

Model: user.js

var Schema = mongoose.Schema
  , ObjectId = Schema.ObjectId
  , Validations = require('./validations.js')
  , salt = 'mySaltyString'
  , SHA2 = new (require('jshashes').SHA512)()

function encodePassword( pass ){
	if( typeof pass === 'string' && pass.length < 6 ) return ''

	return SHA2.b64_hmac(pass, salt )
}

var UserSchema = new Schema({
    nick        : {type: String, required: true, unique: true, trim: true }
  , email       : {type: String, required: true, unique: true, trim: true, lowercase: true }
  , password    : {type: String, set: encodePassword, required: true }
});

UserSchema.statics.classicLogin = function(login, pass, cb) {
	if( login && pass ){
		mongoose.models.User
			.where( 'email', login )
			.where( 'password', encodePassword(pass) )
	  	.findOne( cb )
	} else {
		// just to launch the standard error
		var o = new this({nick: 'VeryUniquejerewelA', password: '', email: login+'aaa'})
		o.save(cb)
	}
}
UserSchema.path('nick').validate( Validations.uniqueFieldInsensitive('User', 'nick' ), 'unique' )
UserSchema.path('email').validate( Validations.uniqueFieldInsensitive('User', 'email' ), 'unique' )
UserSchema.path('email').validate( Validations.emailFormat, 'format' )
UserSchema.path('password').validate( Validations.cannotBeEmpty, 'password' )
UserSchema.plugin( mongoose.availablePlugins.timestamper )

mongoose.model('User', UserSchema)

.Highlights of this code: We are using the package jshashes, which supplies many convenient encryption methods, among those SHA512 –strong enough
It is a good practice to use a salt along, represented by the var salt. In practice it makes way difficult for a cracker that acquired access to the database do decipher the passwords stored.
The method encodePassword is used at two occasions, when setting the User password, and when retrieving it from database.
UserSchema.statics is a object that stores additional static methods our User model will offer.
The function classicLogin requires both login and pass to search the db for existence, otherwise, it will launch an error (kinda of a smelly workaround to make it work dry )
UserSchema.path(…).validate offers us validations, in our case, we do not allow repeated email or nick, and password should be bigger at least 6 characters long. Also email should at least look like a email.
All those validations work along with the own Schema definition: required, unique, trim, lowercase

Route: auth.js

// app.get( '/auth/popover', auth.popover);
exports.popover = function(req, res){
	//req.session.popover = new Date()
	console.log('My session:', req.session)
  res.render('auth/index_pop', req.viewVars);
};

// CLASSIC LOGIN / SIGNUP       --because everyauth seems too messy for login+pass
// app.post('/auth/classic-signup', auth.classicSignup)
exports.classicSignup = function(req,res,next) {
	if( !req.body ){
		console.log('why u signup nobody?')
		return res.redirect('/?nobodySignup')
	}

	var user = new app.models.User()

	user.set('nick', req.body.nick)
	user.set('email', req.body.email)
	user.set('password', req.body.pass)
	user.set('providers', ['signup:'+user.get('email')])
	user.set('profiles', [{ _name: 'signup'}])

	user.save( function(err) {
		if( err ){ // validation failed

			req.viewVars.u = user
			return classicYieldErr( req, res, 'signUp', err)

		} else { // signup successful

			req.session.user = {
				provider: 'signup',
				id: user.get('id'),
				nick: user.get('nick'),
			}

			req.flash('notice', 'Welcome!')
			req.viewVars.welcome_login = "Welcome, "+user.nick

  		res.render('auth/win_pop', req.viewVars )
		}
	})
};

// app.post('/auth/classic-login',  auth.classicLogin)
exports.classicLogin = function(req,res,next) {
	if( !req.body ){
		console.log('why u login nobody?')
		return res.redirect('/?nobodyLogin')
	}

	app.models.User.classicLogin( req.body.email, req.body.pass, function(err, user) {
		if( err ){ // validation failed

			return classicYieldErr( req, res, 'signIn', err)

		} else {

			if( user ){ // login

				req.session.user = {
					provider: 'signup',
					id: user.get('id'),
					nick: user.get('nick'),
				}

				req.flash('notice', 'Welcome!')
				req.viewVars.welcome_login = "Welcome, "+user.nick

	  		res.render('auth/win_pop', req.viewVars )

			} else { // not found
				return classicYieldErr( req, res, 'signIn', {errors:
					{'loginpass': {
						name: 'V',
						path: 'login+password',
						type: 'loginpass'
					}
				}})
			}

		}
	})
};

// display form error
function classicYieldErr( req, res, mode, err ){
	req.viewVars.erroredForm = mode
	if( mode === 'signIn' ){
		req.viewVars.signin_errors = app.helpers.displayErrors( err )
	} else {
		req.viewVars.signup_errors = app.helpers.displayErrors( err )
	}
	req.viewVars.email = req.body.email

	res.render('auth/index_pop', req.viewVars);
}

Here we define the 3 routes;
– one route(GET) that defines one page for both login or signup
– one route(POST) to submit login
– one route(POST) to submit signup
About the last 2, their only role is to allow access for valid data. That is, valid signup data, or login+password existing in our collection from MongoDB.
The function classicYieldErr is there just to serve the errors in sort of an uniform way. We will see about this function on the next file

Model Helper: validations.js

exports.uniqueFieldInsensitive =  function ( modelName, field ){
	return function(val, cb){
		if( val && val.length ){ // if string not empty/null
			// only for new docs
			if( this.isNew ){
				mongoose.models[modelName].where(
					field, new RegExp('^'+val+'$', 'i')
				).count(function(err,n){
					// false when validation fails
					cb( n < 1 )
				})
			} else {
				cb( true )
			}
		} else { // raise error of unique if empty // may be confusing, but is rightful
			cb( false )
		}
	}
}

exports.emailFormat = function( val ){
	// false when validation fails
	return (/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i).test( val )
}

exports.cannotBeEmpty = function( val ){
	console.log('pass val is:', val)

	// not all passwords should be set, BUT when string, should be encoded
	if( typeof val === 'string' ){
		if( val.length ){ // when it comes empty, something went wrong!
			return true
		} else {
			return false
		}
	} else {
		return false
	}
}

This file contains some very important function, being intuitive, I will only comment on the first.
uniqueFieldInsensitive is actually a validation creator. It uses JS’s closure ability along with the powerful this object to wrap the context where this will represent whichever Model is calling it.
The intent of the function is to search the db for any repeated occurrence of the field, case-insensitive. This way the system will block a user “John” from signinup, if “john” is present.

Helper: form_helper.js


//app.helpers.displayErrors = require('./helpers/form_helper.js').displayErrors

stripErrors = function(mongooseErr){
	var prop, list = [];
	for( prop in mongooseErr.errors ){
		list.push( [mongooseErr.errors[prop].path, mongooseErr.errors[prop].type] )
	}
	return list
}

/*
 * Translate mongoose errors into a <li> of errors
 */
exports.displayErrors = function( mongooseErr ){

	console.log( 'mongoose errs', mongooseErr )

	var list = stripErrors( mongooseErr )

	var output = []
	list.forEach(function(e,i){
		switch( e[1] ){
			case( 'unique' ):
				output.push( e[0]+" is taken" )
				break;
			case( 'required' ):
				output.push( e[0]+" is "+e[1] )
				break;
			case( 'format' ):
				output.push( e[0]+" has a bad format" )
				break;
			case( 'password' ):
				output.push( "password should be at least 6 char long" )
				break;
			case( 'loginpass' ):
				output.push( "login+password not found" )
				break;

			default:
				output.push( e[0]+": "+e[1] )
				break;
		}
	})
	if( output.length ){
		// condense all items in an error list
		output = [output.join( '</li><li>\n' )]
		output.unshift( '<ul><li>' )
		output.push( '</li><ul>' )

		// wrap in a div
		output.unshift( "<div class='error block'>" )
		output.push('</div>')
	}
	return output.join('\n')
}

This file provides a translation from Mongoose errors to user-readable errors. In order to offer a good UX, it is important to give accurate feedback. Notice this file could benefit from some refinement 🙂

Don’t forget to download the code from github, it plays well along everyauth module 🙂

Cheers!