UBSession.js

/*
 @author pavel.mash
 */

// ***********   !!!!WARNING!!!!! **********************
// Module shared between server and client code
/**
 * Internal class, returned as a result of {@link UBConnection#authorize UBConnection.authorize()}
 * The main method is {@link UBSession#signature UBSession.signature}
 *
 * Developer never create this class directly.
 * @class
 * @protected
 */
function UBSession(authResponse, secretWord, authSchema){
    var data = authResponse,
        hexa8ID = hexa8(data.result.split('+')[0]),
        userData = data.uData?JSON.parse(data.uData):{lang: 'en'},
        //crc32SessionWord = crc32(secretWord),
        sessionWord = data.result, // sessionID || '+' || privateKey
        sessionPwdHash = secretWord || '',
        //typeof window === 'undefined'  -> UB.isServer
        sessionSaltCRC = (typeof window === 'undefined') ? ncrc32(0, sessionWord + sessionPwdHash) : null;

    /** @property {String} sessionID user session id converted to {@link UBSession#hexa8}
     * @protected
     * @readonly
     */
    Object.defineProperty(this, 'sessionID', {enumerable: true, writable: false, value: hexa8ID});
    /**
     * User logon name. Better to access this value using {@link UBConnection#userLogin UBConnection.userLogin()} method.
     * @type {String}
     * @private
     * @readonly
     */
    this.logonname = data.logonname;

    /** Contain custom user data. Usually filled inside **server** `onUserLogon` event handlers
     *
     * Do not use it directly, instead use helper method {@link UBConnection#userData UBConnection.userData()} instead.
     *
     * @type {Object}
     * @protected
     * @readonly
     */
     this.userData = userData;

    /**
     * Name of authentication schema
     * @type {String}
     * @protected
     * @readonly
     */
     this.authSchema = authSchema || 'UB';

    /**
     * Session signature for authorized request. Can be added as LAST parameter in url, or to Authorization header (preferred way)
     *
     *      $App.connection.authorize().then(function(session){
     *          // for URL
     *          return 'session_signature=' + session.signature()
     *          //for header
     *          return {Authorization: session.authSchema + ' ' + session.signature()}
     *      });
     *
     * @returns {string}
     */
    this.signature = function() {
        var
            timeStampI, hexaTime;
        if (this.authSchema === 'UBIP'){
            return this.logonname
        } else {
            timeStampI = Math.floor((new Date()).getTime() / 1000);
            hexaTime = hexa8(timeStampI);
            return  hexa8ID + hexaTime + hexa8((typeof window === 'undefined') ? ncrc32(sessionSaltCRC, hexaTime) : crc32(sessionWord + sessionPwdHash + hexaTime)); // + url?
        }
        // 1.7 return  hexa8ID + hexa8(timeStampI) + hexa8(crc32(timeStampI + '' + crc32SessionWord ));
    };

    /**
     * Return authorization header
     *
     *      $App.connection.authorize().then(function(session){
     *          return {Authorization: session.authHeader()}
     *      });
     *
     * @returns {string}
     */
    this.authHeader = function(){
        return  this.authSchema + ' ' + this.signature();
    };
}

/**
 * Return hexadecimal string of 8 character length from value
 * @param {String|Number} value
 * @returns {String}
 */
UBSession.prototype.hexa8 = function hexa8(value){
    var num = parseInt(value, 10),
        res = isNaN(num) ? '00000000' : num.toString(16);
    while(res.length < 8) {
        res = '0' + res;
    }
    return res;
};
var hexa8 = UBSession.prototype.hexa8;

var CRC32_POLYTABLES = {};
/*jslint bitwise: true */
/**
 * Calculate CRC32 checksum for string
 * @param {String} s string to calculate CRC32
 * @param {Number} [polynomial] polynomial basis. default to 0x04C11DB7
 * @param {Number} [initialValue] initial crc value. default to 0xFFFFFFFF
 * @param {Number} [finalXORValue] default to 0xFFFFFFFF
 * @returns {Number}
 */
UBSession.prototype.crc32 = function crc32(s, polynomial, initialValue, finalXORValue) {
    var table, i, j, c, crc;
    s = String(s);
    polynomial = polynomial || 0x04C11DB7;
    initialValue = initialValue || 0xFFFFFFFF;
    finalXORValue = finalXORValue || 0xFFFFFFFF;
    crc = initialValue;

    table = CRC32_POLYTABLES[polynomial];
    if (!table){
        table = CRC32_POLYTABLES[polynomial] = (function build(){
            var i, j, c, table = [],
                reverse = function (x, n) {
                    var b = 0;
                    while (n) {
                        b = b * 2 + x % 2;
                        x /= 2;
                        x -= x % 1;
                        n--;
                    }
                    return b;
                };
            for (i = 255; i >= 0; i--) {
                c = reverse(i, 32);

                for (j = 0; j < 8; j++) {
                    c = ((c * 2) ^ (((c >>> 31) % 2) * polynomial)) >>> 0;
                }

                table[i] = reverse(c, 32);
            }
            return table;
        })();
    }

    for (i = 0; i < s.length; i++) {
        c = s.charCodeAt(i);
        if (c > 255) {
            throw new RangeError();
        }
        j = (crc % 256) ^ c;
        crc = ((crc / 256) ^ table[j]) >>> 0;
    }
    return (crc ^ finalXORValue) >>> 0;
};
var crc32 = UBSession.prototype.crc32;

module.exports = UBSession;