openmrs/openmrs-contrib-id

View on GitHub
app/utils.js

Summary

Maintainability
A
0 mins
Test Coverage
'use strict';
/**
 * Some utility tools
 */
const crypto = require('crypto');
const _ = require('lodash');
const conf = require('./conf');
const request = require('request');
const qs = require('querystring');

// password hashing
exports.getSSHA = (cleartext, salt) => {
  if (_.isUndefined(salt)) {
    salt = new Buffer(crypto.randomBytes(20)).toString('base64');
  }
  const sum = crypto.createHash('sha1');
  sum.update(cleartext, 'utf-8');
  sum.update(salt, 'binary');
  const digest = sum.digest('binary');
  const ret = `{SSHA}${new Buffer(digest + salt, 'binary').toString('base64')}`;
  return ret;

};

exports.checkSSHA = (cleartext, hashed) => {
  if (hashed.substr(0, 6) !== '{SSHA}') {
    return false;
  }
  const hash = new Buffer(hashed.substr(6), 'base64');
  const salt = hash.toString('binary', 20);
  const newHash = exports.getSSHA(cleartext, salt);
  return newHash === hashed;
};

exports.isUsernameValid = username => {
  const usernameRegex = conf.user.usernameRegex;
  if (_.isEmpty(username) || !usernameRegex.test(username)) {
    // ensure it not empty first, avoid auto-cast for (null) or (undefined)
    return false;
  }
  return true;
};

exports.isEmailValid = email => {
  const emailRegex = conf.email.validation.emailRegex;
  if (_.isEmpty(email) || !emailRegex.test(email)) {
    return false;
  }
  return true;
};

// encode a string into base64
exports.encode64 = str => {
  const tmp = new Buffer(str);
  return tmp.toString('base64');
};

// decode a base64 string
exports.decode64 = str => {
  const tmp = new Buffer(str, 'base64');
  return tmp.toString('utf8');
};

// URL safe Base64 functions
exports.urlEncode64 = str => {
  str = exports.encode64(str);
  return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
};

exports.urlDecode64 = str => {
  str = str.replace(/-/g, '+').replace(/_/g, '/');
  let r = str.length % 4;
  while (r % 4) {
    ++r;
    str += '=';
  }
  return exports.decode64(str);
};

// new Recaptcha validator
const Recaptcha = exports.Recaptcha = function(secret) {
  if (_.isUndefined(secret)) {
    console.error('missing recaptcha secret');
    throw new Error('missing recaptcha secret');
  }
  this.secret = secret;
};

// make a GET request to verify reCAPTCHA
Recaptcha.prototype.verify = function(data, callback) {
  const baseUrl = 'https://www.google.com/recaptcha/api/siteverify';
  let query = {
    secret: this.secret,
  };
  if (_.isUndefined(data.response)) {
    return callback('missing recaptcha response');
  }
  query.response = data.response;
  if (data.remoteip) {
    query.remoteip = data.remoteip;
  }
  query = qs.stringify(query);

  const verifyUrl = `${baseUrl}?${query}`;
  request.get(verifyUrl, (err, response, body) => {
    if (err) {
      return callback(err);
    }
    body = JSON.parse(body);
    const errCode = body['error-codes'];
    if (errCode) {
      return callback(errCode);
    }
    return callback(null, body.success);
  });
};