Tuesday, January 17, 2017

Private Properties with JavaScript (prototypes)

Some are saying that JavaScript does not have private properties with prototypes and it is not like TypeScript or Python.

However, that is not fully correct, especially with this comparison.

Python doesn't have anything private. All the scopes are globally addressable and all the variables, properties and methods are accessible globally (as long as you know the scope path, which could be easily traced from within the software itself).

TypeScript is just a pre-processor. It will do extra semantic checks during compilation, but no enforcement of anything on runtime. 

However, it is generally untrue that you have no private properties available in JavaScript.

You do have scope inheritance and you don't have global access to any scope from outside. Therefore you can make private properties easily.

For example, if you have:

function F1() {
  var XXX = 0;
  return function () {
     return XXX;
  }
}

F1()() will respond with the value of XXX but there is no way to access XXX from outside.

So what about prototyping?
You can do this there too.

function F1() {
  var XXX = 'yyy'; // Private property
  function F1() {
     // You constructor is here
     this.YYY = 'xxx'; // public property
  }
  F1.prototype.method1 = function() {
    return XXX + this.YYY;
  }
  return new F1();
}

Then if you do:

x = F1();
or
x = new F1();  // Both works the same way
and check:
console.log(x.YYY); // output 'xxx'
console.log(x.XXX); // output Error
console.log(x.method1()); // output 'yyyxxx'

So everything works! You have prototyping with private and public properties.
The same way you can do private and public methods.

The only thing that will not work with this method is instanceof
x instanceof F1 will respond with false, because x is not an instance of the upper F1, but the inner F1

The current ES6 standard have classes, but they are essentially a wrapper on top of prototype. So this technique still apply. Additionally with Object.defineProperty you could apply extra protection on top of a property.

There is another approach to the problem. Without prototypes.

function F1() {
  if (!this instanceof F1) return; // Protect against global scope polution
  var XXX = 'yyy'; // Private property
  this.YYY = 'xxx'; // Public property
  function PrivateMethod() {
    return XXX + this.YYY;
  }
  this.method1 = function() {
    return PrivateMethod();
  }
}

With the shown above approach you have both private and public methods and properties, with workable instanceof

Monday, January 2, 2017

Python UniFI API for management of Ubiquity UniFI infrastructure

I am porting to Python the UniFi Browser API (PHP) which could be used to manage the UniFI AP infrastructure from external application to the UniCK Controller.

The port is completed, however, the work is ongoing, the API is updated (adding new calls and support for HotSpot 2.0) and changes may happen.

Documentation will come a bit later, but I guess the code is self explanatory.

For those who are interested, you could find it here:

Sunday, October 4, 2015

Passport-http Digest Authentication and Express 4+ bug fix

Passport is quite popular environment for implementing authentication under Node.JS and Express Framework.

Passport-http is a plug-in that provides Digest Authentication interfaces and is very popular for Passport.

However, since Express 4, the default approach to the Express routes is them to be relative.

Example - 
Express <=3 default application assumed that every file who extend Express with routes should specify the full path to the route in a similar to this approach:

app.js:
app.get('{fullpath}',function)...

Or:
require('routes/users')(app)

Where users.js do as well:

app.get('{fullpath',function)...

The default app of Express 4+ uses relative routes, which is quite better as it allows full isolation between the modules of the application.

Example:

app.js:
app.use('/rest',require('routes/rest'));

Where rest.js has:

router = require('express').Router();
router.get('/data', function)... // where data is relative url and the actual will be /rest/data

This simplifies the readability. Also it allows you to separate the authentication. You could have different authentication approach or configuration to each different module. And that works well with Passport.

For example:

app.js:
app.use(passport.initialize());
app.use(passport.session());

rest.js:
var DigestStrategy = require('passport-http').DigestStrategy;
... here there should be a code for authentication function using Digest ...

and then:
router.get('/data',authentication,function) ....

This simplifies, makes it more readable and isolates very much the code necessary for authentication.

Personally, I write my own authentication functions in a separate module, then I include them in the express route module where I want to use them and it became even more simpler:

rest.js:
var auth = require('../libs/auth.js');
Router.get('/data', auth('admins'), function) ...

I even could apply different permissions, roles like - if you have pre authenticated session, then the interface will not ask you for authentication (saved one RTT) but if you don't it will ask you for digest authentication. Quite simple and quite readable.

However, all this does not work with Passport-http, because of a very small bug within.

The bug:

For security reasons, passport-http module verifies that the authentication URI from the customer request is the same as the URL requested authentication. However, the authentication URI (creds.uri) is always full path, but it is compared to req.url which is always relative path. The comparision has to be between creds.uri and req.baseUrl+req.url.

And this is my fix proposed to the author of passport-http, which I hope will be merged with the code.

Friday, September 25, 2015

EmbeddedJS - async reimplementation

I like using Embedded JS together with RequireJS in very small projects. It is very small, lighting fast and extremely simple, powerful and extensive.

However, there are hundreds of implementations, most of them out of date, and particularly the implementation I like is not supported anymore. But that I mean not only that the author is not supporting it, but also it works unpredictably in some browsers because it rely on Sync XMLHttpRequest which is not allowed in the main thread anymore.

So I decided to rewrite that EJS implementation myself, in a way I could use it in async mode.

So allow me to introduce the new Async Embedded JS implementation, which is here at https://github.com/delian/embeddedjs

It supports Node, AMD (requirejs) and globals (as the original) and detect them automatically.
A little documentation can be found here https://github.com/delian/embeddedjs/blob/master/README.md

The new code is written in ES5 and uses the new Function method from ES6. That makes it working only in modern browsers (IE10+). But it makes it really really fast. By current estimates about twice faster than the original.

It is still work in progress (no avoidance of cached URLs for example), but works perfectly fine for me.

If you use it and hit a bug, please report it at the Issues page at Github

Saturday, August 22, 2015

JavaScript private methods and variables

Often I am told that JavaScript has no real private methods and variables the same way as this is for Python or Perl.

Although, that is true for Python and Perl (all scopes and their content are publicly accessible and there is always a way to list and access the content) it is not true for JavaScript.

JavaScript have one of the most powerful scoping technique available for a main-stream programing language and provides you with the ability to hide and make private some content if needed.

Let me show you an example:

function MyClass() {
    var fullyPrivateVar = 'xxxx';
    this.notFullyPrivateVar = 'yyyy';

    function privateMethod() {
        return fullyPrivateVar;
    }

    this.publicMethodWithPrivateAccess = function() { return privateMethod() }
}

MyClass.prototype.publicMethodWithNoPrivateAccess = function() {
    return this.notFullyPrivateVar;
}

x = new MyClass();
console.log(x.publicMethodWithNoPrivateAccess());
yyyy
console.log(x.publicMethodWithPrivateAccess());
xxxx

I think the example is self explanatory, but let me say few words on it:
In JavaScript you can have hierarchy of scopes and you can define unlimited amount function in functions levels (and scope levels) in difference to other programming languages where you have limited / fixed scope levels.

So I have a privateMethod and fullyPrivateVar defined within MyClass. Because of it, only things defined in this scope will have access to them. Like publicMethodWithPrivateAccess that I assign with the constructor to the newly constructed object. However,  publicMethodWithNoPrivateAccess is defined outside of the scope and has no access to those values. But it has access to everything in the this scope. One could argue, that this approach takes more memory for the methods because I define a new method with every initialization of the class (the function assignment). But that is not true. The function in the function is having a static code (it is not part of eval+variable) and is compiled during the initial javascript processing of the JS virtual machine. So it will not take extra memory. Only during execution the function will be dynamically assigned with the private scope of the constructor, something you want anyway.

Friday, March 13, 2015

Node.JS module to access Cisco IOS XR XML interface

Hello to all,

This is the early version of my module for Node.JS that allows configuring routers and retrieving information over Cisco IOS XR's XML interface.

The module is in its early phases - it still does not read IOS XR schema files and therefore decode the data (in JSON) in a little ugly way (too much arrays). I am planning to fix it, so there may be changes in the responses.

Please see bellow the first version of the documentation I've set in the github:

Module for Cisco XML API interface IOS XR

This is a small module that implements interface to Cisco IOS XR XML Interface.
This module open an maintain TCP session to the router, sends requests and receive responses.

Installation

To install the module do something like that:
npm install node-ciscoxml

Usage

It is very easy to use this module. See the methods bellow:

Load the module

To load and use the module, you have to use a code similar to this:
var cxml = require('node-ciscoxml');
var c = cxml( { ...connect options.. });

Module init and connect options

host (default 127.0.0.1) - the hostname of the router where we'll connect
port (default 38751) - the port of the router where XML API is listening
username (default guest) - the username used for authentication, if username is requested by the remote side
password (default guest) - the password used for authentication, if password is requested by the remote side
connectErrCnt (default 3) - how many times it will retry to connect in case of an error
autoConnect (default true) - should it try to auto connect to the remote side if a request is dispatched and there is no open session already
autoDisconnect (default 60000) - how much milliseconds we will wait for another request before the tcp session to the remote side is closed. If the value is 0, it will wait forever (or until the remote side disconnects). Bear in mind autoConnect set to false does not assume autoDisconnect set to 0/false as well.
userPromptRegex (default (Username|Login)) - the rule used to identify that the remote side requests for a username
passPromptRegex (default Password) - the rule used to identify that the remote side requests for a password
xmlPromptRegex (default XML>) - the rule used to identify successful login/connection
noDelay (default true) - disables the Nagle algorithm (true)
keepAlive (default 30000) - enabled or disables (value of 0) TCP keepalive for the socket
ssl (default false) - if it is set to true or an object, then SSL session will be opened. Node.js TLS module is used for that so if the ssl points to an object, the tls options are taken from it. Be careful - enabling SSL does not change the default port from 38751 to 38752. You have to set it explicitly!
Example:
var cxml = require('node-ciscoxml');
var c = cxml( {
    host: '10.10.1.1',
    port: 5000,
    username: 'xmlapi',
    password: 'xmlpass'
});

connect method

This method forces explicitly a connection. It could accept any options of the above.
Example:
var cxml = require('node-ciscoxml');
var c = cxml();
c.connect( {
    host: '10.10.1.1',
    port: 5000,
    username: 'xmlapi',
    password: 'xmlpass'
});
The connect method is not necessary to be used. If autoConnect is enabled (default) the module will automatically open and close tcp connections when needed.
Connect supports callback. Example:
var cxml = require('node-ciscoxml');
cxml().connect( {
    host: '10.10.1.1',
    port: 5000,
    username: 'xmlapi',
    password: 'xmlpass'
}, function(err) {
    if (!err)
        console.log('Successful connection');
});
The callback may be the only parameter as well. Example:
var cxml = require('node-ciscoxml');
cxml({
    host: '10.10.1.1',
    port: 5000,
    username: 'xmlapi',
    password: 'xmlpass'
}).connect(function(err) {
    if (!err)
        console.log('Successful connection');
});
Example with SSL:
var cxml = require('node-ciscoxml');
var fs = require('fs');
cxml({
    host: '10.10.1.1',
    port: 38752,
    username: 'xmlapi',
    password: 'xmlpass',
    ssl: {
          // These are necessary only if using the client certificate authentication
          key: fs.readFileSync('client-key.pem'),
          cert: fs.readFileSync('client-cert.pem'),
          // This is necessary only if the server uses the self-signed certificate
          ca: [ fs.readFileSync('server-cert.pem') ]
    }
}).connect(function(err) {
    if (!err)
        console.log('Successful connection');
});

disconnect method

This method explicitly disconnects a connection.

sendRaw method

.sendRaw(data,callback)
Parameters:
data - a string containing valid Cisco XML request to be sent
callback - function that will be called when a valid Cisco XML response is received
Example:
var cxml = require('node-ciscoxml');
var c = cxml({
    host: '10.10.1.1',
    port: 5000,
    username: 'xmlapi',
    password: 'xmlpass'
});

c.sendRaw('<Request><GetDataSpaceInfo/></Request>',function(err,data) {
    console.log('Received',err,data);
});

sendRawObj method

.sendRawObj(data,callback)
Parameters:
data - a javascript object that will be converted to a Cisco XML request
callback - function that will be called with valid Cisco XML response converted to javascript object
Example:
var cxml = require('node-ciscoxml');
var c = cxml({
    host: '10.10.1.1',
    port: 5000,
    username: 'xmlapi',
    password: 'xmlpass'
});

c.sendRawObj({ GetDataSpaceInfo: '' },function(err,data) {
    console.log('Received',err,data);
});

rootGetDataSpaceInfo method

.rootGetDataSpaceInfo(callback)
Equivalent to .sendRawObj for GetDataSpaceInfo command

getNext

Sends getNext request with a specific id, so we can retrieve the rest of the previous operation if it has been truncated.
id - the ID callback - the callback with the data (in js object format)
Keep in mind next response may be truncated as well, so you have to check for IteratorID all the time.
Example:
var cxml = require('node-ciscoxml');
var c = cxml({
    host: '10.10.1.1',
    port: 5000,
    username: 'xmlapi',
    password: 'xmlpass'
});

c.sendRawObj({ Get: { Configuration: {} } },function(err,data) {
    console.log('Received',err,data);
    if ((!err) && data && data.Response.$.IteratorID) {
        return c.getNext(data.Response.$.IteratorID,function(err,nextData) {
            // .. code to merge data with nextData
        });
    }
    // .. code
});

sendRequest method

This method is equivalent to sendRawObj but it can automatically detect the need and resupply GetNext requests so the response is absolutley full. Therefore this method should be the preferred method for sending requests that expect very large replies.
Example:
var cxml = require('node-ciscoxml');
var c = cxml({
    host: '10.10.1.1',
    port: 5000,
    username: 'xmlapi',
    password: 'xmlpass'
});

c.sendRequest({ GetDataSpaceInfo: '' },function(err,data) {
    console.log('Received',err,data);
});

requestPath method

This is a method equivalent to sendRequest but instead of an object, the request may be formatted in a simple path string. This metod is not very useful for complex requests. But its value is in the ability to simplify very much the simple requests. The response is in JavaScript object
Example:
var cxml = require('node-ciscoxml');
var c = cxml({
    host: '10.10.1.1',
    port: 5000,
    username: 'xmlapi',
    password: 'xmlpass'
});

c.requestPath('Get.Configuration.Hostname',function(err,data) {
    console.log('Received',err,data);
});

reqPathPath method

This is the same method as requestPath, but the response is not an object, but a path array. The method supports optional filter, which has to be a RegExp object and all paths and values will be tested against it Only those returning true will be included in the response array.
Example:
var cxml = require('node-ciscoxml');
var c = cxml({
    host: '10.10.1.1',
    port: 5000,
    username: 'xmlapi',
    password: 'xmlpass'
});

c.reqPathPath('Get.Configuration.Hostname',/Hostname/,function(err,data) {
    console.log('Received',data[0]);
    // The output should be something like
    // [ 'Response("MajorVersion"="1","MinorVersion"="0").Get.Configuration.Hostname("MajorVersion"="1","MinorVersion"="0")',
           'asr9k-router' ] 
});
This method could be very useful for getting simple responses and configurations.

getConfig method

This method requests the whole configuration of the remote device and return it as object
Example:
c.getConfig(function(err,config) {
    console.log(err,config);
});

cliConfig method

This method is quite simple, it executes a command(s) in CLI Configuration mode and return the response in JS Object. You have to know that any configuration change in IOS XR is not effective unless it is committed!
Example:
c.cliConfig('username testuser\ngroup operator\n',function(err,data) {
    console.log(err,data);
    c.commit();
});

cliExec method

Executes a command(s) in CLI Exec mode and return the response in JS Object.
c.cliExec('show interfaces',function(err,data) {
    console.log(err,data?data.Response.CLI[0].Exec[0]);
});

commit method

Commit the current configuration.
Example:
c.commit(function(err,data) {
    console.log(err,data);
});

lock method

Locks the configuration mode.
Example:
c.lock(function(err,data) {
    console.log(err,data);
});

unlock method

Unlocks the configuration mode.
Example:
c.unlock(function(err,data) {
    console.log(err,data);
});

Configure Cisco IOS XR for XML agent

To configure IOS XR for remote XML configuration you have to:
Ensure you have *mgbl*** package installed and activated! Without it you will have no xml agentcommands!
Enable the XML agent with a similar configuration:
xml agent
  vrf default
    ipv4 access-list SECUREACCESS
  !
  ipv6 enable
  session timeout 10
  iteration on size 100000
!
You can enable tty and/or ssl agents as well!
(Keep in mind - full filtering of the XML access has to be done by the control-plane management-plane command! The XML interface does not use VTYs!)
You have to ensure you have correctly configured aaa as the xml agent uses default method for both authentication and authorization and that cannot be changed (last verified with IOS XR 5.3).
You have to have both aaa authentication and authorization. If authorization is not set (aaa authorization default local or none), you may not be able to log in. And you shall ensure that both the authentication and authorization share the same source (tacacs+ or local).
The default agent port is 38751 for the default agent and 38752 for SSL.

Debugging

The module uses "debug" module to log its outputs. You can enable the debugging by having in your code something like:
require('debug').enable('ciscoxml');
Or setting DEBUG environment to ciscoxml before starting the Node.JS

Wednesday, March 11, 2015

ExtJS short highlight of a gridrow in case of an update

In my ExtJS code I often update the values of records associated with Stores/Data Models associated with Grid Panel. 
Sometimes this an automated update received from the web server (an example you can see here) sometimes not.
However, as a user I like to be able to see if somewhere in the grid some data has been modified.

And to create a code, that highlight for a moment the row or a cell where a change happened is actually not so hard. 

Here is a small example how you can do that - you just have to bind to event 'itemupdate' on a tableview. See the example bellow, that is supposed to be self explanatory:

Ext.ComponentQuery.query('#mytableview').on('itemupdate', function(record, index, node) {
    node.className = node.className + ' x-grid-item-alt';
    setTimeout(function() {
        node.className = node.className.replace(/x-grid-item-alt/, '');
    }, 500);
});