Friday, October 23, 2015

Alignment problem of Firefox that's non-existent on Chrome

Given this html:

<span class="form-search"></span>
<input class="search-query form-control" style="width: 200px" placeholder="Live search"/>


And CSS:

span.form-search {
    position: relative;       
}
span.form-search:before {
    display: block;
    width: 14px;
    height: 14px;
    content: "\e003";
    font-family: 'Glyphicons Halflings';
    background-position: -48px 0;
    position: absolute;
    top:8px;
    left:8px;
    opacity: .5;
    z-index: 1000;
}
input.search-query {
    padding-left:26px;
}

Live code: https://jsfiddle.net/L1pb9km3/

The above display perfectly ok with Chrome, but not on Firefox.

Chrome:





Firefox:






The work-around to make it work on Firefox is simple, just add a float: left to the span.form-search

span.form-search {
    position: relative;   
    float: left;    
}

Live code: https://jsfiddle.net/axjk3xss/

Yes it's easy to land on comet than to properly align stuff on web using CSS.

Tuesday, October 20, 2015

Can't set the $pristine on constructor

Let's say you are using a directive that has problem with pristine, i.e., on first load the aForm is already dirty:

<form name="c.aForm">
<someDirectiveWithBugHere></someDirectiveWithBugHere>
</form>

<div>{{c.aForm.$pristine}}</div>




You can't set the aForm to pristine on constructor, as aForm is not yet defined while on constructor:
module App.UserEdit
{
    export class MainController
    {
        aForm: ng.IFormController;

        constructor(public Resources: InhouseLib.Resources)
        {
             this.aForm.$setPristine();

        }
    }
}

Setting the form to pristine while on constructor would give this result:
TypeError: Cannot read property '$setPristine' of undefined
    at new MainController

A work-around is to set the pristine state after the form is loaded, and by calling the expression (that will set the pristine to clean) on ng-init:
<form name="c.aForm">
<someDirectiveWithBugHere></someDirectiveWithBugHere>
</form>
<div ng-init="c.setClean()"></div>

<div>{{c.aForm.$pristine}}</div>

Remove the $setPristine from the controller and move it to setClean:
module App.UserEdit
{
    export class MainController
    {

        aForm: ng.IFormController;

        constructor(public Resources: InhouseLib.Resources)
        {
        }
    
        setClean(): void
        {
            this.aForm.$setPristine();
        }
    }
}


Or if you don't want the controller to have concerns on those stuff, you can initialize the form's state directly on html.

<div ng-init="c.aForm.$setPristine();"></div>

<div>{{c.aForm.$pristine}}</div>

Sunday, October 4, 2015

Prevent ui.router's ui-sref from reloading the page

If a ui-router link points the page where it resides, it will cause a page reload on the page(s) that are reloaded, and thus it will cause flickering or noticeable delay.

<a ui-sref="root.app.editAd({id: ad.itemId})">{{ad.title}}</a>

To improve that, just perform ajax on an ng-click and just fetch the data that are needed to populate the information on the page, and prevent the href from reloading the page by using $event.preventDefault(). The href will just be used for bookmark purposes or if the user want to open the link on another tab or window. We can use ui.router href method for translating the state to link.

<a 
ng-click="ctrl.AppWide.edit(a.itemId); $event.preventDefault()" 
title="Change Information" 
href="{{c.$state.href('root.app.editAd',{id: a.itemId})}}" 
 {{a.title}}
</a>


To change the url after performing an ajax operation, use $state.go and pass the parameter notify false to it, so it will just change the url and not do a partial page reload.

this.$state.go('root.app.editAd', {id: this.savedId}, {notify: false});


Note: As of the time of the time of this writing, the notify false has a bug, it invokes the originating controller twice and sometimes it rejects the link the user clicked on from going to the link's page. There's already a solution to that, but it's not yet on the latest release of angular ui.router, have to patch the ui.router manually.


Happy Coding!

Wednesday, September 16, 2015

Using modules in Angular way

You can use a TypeScript module as it is in an Angular app. Just load and it use it right away.

However, if you want it done in Angular way, it's better. It makes the code more testable and the module dependencies on your code will be more obvious.

Here's an example. /shared/utilities/StringLib.ts
///<reference path="../../typings/node/node.d.ts"/>
///<reference path="../../typings/angularjs/angular.d.ts"/>

var isNode = typeof exports !== 'undefined' && this.exports !== exports;

module utilities.StringLib {

    export function isNumeric(n: string) : boolean {
        return !isNaN(parseFloat(n)) && isFinite(<any>n);
    }

    export function replaceAll(src: string, search: string, replacement: string) : string {
        return src.split(search).join(replacement)
    }
}

if (isNode) {
    module.exports = utilities.StringLib;
}
else {
    angular.module('utilities.stringLib',[])
        .factory('stringLib', () => {
            return utilities.StringLib;
        });
}


Then on the ocLazyLoadProvider's config add this:
{
    name: 'utilities.stringLib.files',
    files: ['/shared/utilities/StringLib.js']
}



To use, indicate the module name above on the module's dependency array parameter. On the last element of the array, nest an array, put the name of the list of file(s) of the module(s) that are being lazy-loaded. ocLazyLoad makes this lazy-loading possible.


The typeof operator for utilities.StringLib enables the autocomplete functionality for TypeScript on your IDE.


Note, put the <any> typecast to make the TypeScript compiler stop complaining of incompatible parameter, this lazy-loading mechanism is an extension of ocLazyLoad to Angular, and is not included on Angular's TypeScript definition file.


///<reference path="../../../shared/utilities/StringLib.ts"/>
///<reference path="../../../typings/angularjs/angular.d.ts"/>

module App.Product {

    export class Controller {
    
        constructor(public stringLib: typeof utilities.StringLib) {
        
            console.log(this.stringLib.isNumeric("1234"));
            console.log(this.stringLib.isNumeric("1234b"));        
        }
    
    }

}    
    

angular
    .module('niceApp', <any>
        [
            'utilities.stringLib',

            [                
                'utilities.stringLib.files'                
            ]
        ])
    .controller('ProductController', [
        'stringLib',
        
        App.Product.Controller
    ]);


Tuesday, September 15, 2015

Cannot read property 'name' of undefined

While playing with ocLazyLoad, I got the following error:

TypeError: Cannot read property 'name' of undefined
    at ocLazyLoad.js:554
    at Object.forEach (angular.js:336)
    at Object._loadDependencies (ocLazyLoad.js:539)
    at loadNext (ocLazyLoad.js:642)



Can you spot the error?

// directives
'ngTagsInput',
'ui.pagedown',
'puElasticInput',
'ui.bootstrap'

[
    'sharedState.appWide.files',
    'oitozero.ngSweetAlert.files',


Yeah, I just forgot the comma between 'ui.bootstrap' and the opening square bracket. Should be a syntax error, but due to javascript dynamic nature, it's not flagged as syntax error. Should explore JSLint.

Lazy-loading services with ocLazyLoad

While I'm converting a couchPotato-using Angular code to ocLazyLoad, I learned that ocLazyLoad can lazy load a service too.

On the controller, $ocLazyLoad and $injector must be passed, then get the lazy-loaded object via its name.

Root-Controller.ts:
module App.Root {

    export class Controller {

     
        constructor(
              public SweetAlert,
              public $state,
              
              public $ocLazyLoad,
              public $injector
         ) {

            this.$ocLazyLoad.load('/shared-state/AppWide.js').then(x => {
                var svc = this.$injector.get('someServiceNameHere');
                this.SweetAlert.swal(svc.title);
            });
        }

     

    }

}


angular
    .module('niceApp',<any> 
        [
            'oitozero.ngSweetAlert',   
                      
            [
                'oitozero.ngSweetAlert.files'
            ]
        ])
    .controller('RootController',
        [
            'SweetAlert',
            '$state',
            
            '$ocLazyLoad', 
            '$injector',
            
            App.Root.Controller
        ]);

AppWide.ts:
module SharedState
{
    export class AppWide
    {
        title : string;

        get isUploadVisible(): boolean {
            var theToken = this.$window.localStorage["theToken"];
            return theToken !== undefined;
        }

        constructor(public $window: ng.IWindowService) {
            this.title = "This must be changed";
        }


    }
}

angular.module('niceApp',[])
    .service('someServiceNameHere', 
             ['$window', SharedState.AppWide]);



The problem with the codes above, the controller has now a hard-dependency on $ocLazyLoad and $injector.

There's a nicer solution to the problem, just like SweetAlert, just wrap AppWide.ts to its own module, and make that new module a dependency module of niceApp module. Here's the configuration for AppWide.js:
$ocLazyLoadProvider.config({
            debug: true,
            modules: [
                {
                    name: 'oitozero.ngSweetAlert.files',
                    files: [
                        '/lib/angular-sweetalert/SweetAlert.js',
                        '/lib/sweetalert/dist/sweetalert.min.js',
                        '/lib/sweetAlert/dist/sweetalert.css'
                    ]
                },
                {
                    name: 'common.appWide.files',
                    files: [
                        '/shared-state/AppWide.js'
                    ]
                }
            ]
    });

AppWide.ts:
module SharedState
{
    export class AppWide
    {
        title : string;

        get isUploadVisible(): boolean {
            var theToken = this.$window.localStorage["theToken"];
            return theToken !== undefined;
        }

        constructor(public $window: ng.IWindowService) {
            this.title = "This must be changed";
        }


    }
}

angular.module('common.appWide',[])
    .service('someServiceNameHere', 
             ['$window', SharedState.AppWide]);


The controller is now free from $ocLazyLoad and $injector.

Root-Controller.ts:
module App.Root {

    export class Controller {

    
        constructor(
            public SweetAlert,
            public $state,
            
            public AppWide
        ) 
        {
            this.SweetAlert.swal(this.AppWide.title);
        }

    }

}


angular
    .module('niceApp',<any>
        [
            'oitozero.ngSweetAlert', 
            'common.appWide',
        
            [
                'oitozero.ngSweetAlert.files', 
                'common.appWide.files'
            ]
        ])
    .controller('RootController',
        [
            'SweetAlert',
            '$state',

            'someServiceNameHere', 

            App.Root.Controller
        ]);



Happy Lazy Loading!

Sunday, September 13, 2015

Boilerplate code for AngularJS, NodeJS, JWT and TypeScript

Pre-requisite:

JSON Web Token module:
npm install jwt-simple


Not pre-requisites. Makes UI development convenient.
* ui-router
* sweetAlert


For persistence of token even when the browser is refreshed, $window.sessionStorage would suffice, no need to use ng-storage. However, it's better to use $window.localStorage, $window.sessionStorage is for single tab only; if we open the same app in another tab, it won't be able to read the sessionStorage from the original tab. $window.localStorage can be accessed between tabs.


Authentication consist mainly of these parts:


Server-side:
* Auth.ts -- username and password authentication goes here
* CanBe.ts -- authorization goes here
* app.ts -- entry point of a node app

This is how an API can be authorized in nodejs's app.js. Insert the CanBe.accessedBy node RequestHandler before the API to be called, e.g.,

Without authorization:
app.get('/api/item', itemApi.search);


With authorization:
app.get('/api/item-secured', canBe.accessedBy(['rockstar']), itemApi.search);


Shared by server-side and client-side:
* ILoginDto.ts -- username and password transmitted from client-side to server-side
* ILoginResponseDto.ts -- Auth.ts's authentication response
* ITokenPayload.ts -- Not exactly used by client-side, if there's a need for the client-side to decode the middle part of the JWT, it goes in this data structure. The first part and middle part of JWT are publicly-available information, and as such, ITokenPayload should contain no sensitive information, e.g., password


Client-side:
* init.ts -- called by main.js. main.js is the conventional name for the app's entry point in a RequireJS-based apps.
* AuthService.ts -- called by login UI, to decouple the login controller if there will be changes in authentication mechanism
* HttpInterceptor.ts -- the money shot. this is where to make an angular application automatically send a header everytime an $http or $resource call happens



Auth.ts:
import express = require('express');

import jwt = require('jwt-simple');

export function verify(req: express.Request, res:express.Response, next: Function) : any {
    
    var loginDto = <shared.ILoginDto> req.body;
    
    var loginResponseDto = <shared.ILoginResponseDto> {};
    
    var isValidUser = dbAuthenticate(loginDto.username, loginDto.password);
    
    if (isValidUser) {
        
        var roles = dbGetUserRoles(loginDto.username);
        
        var tokenPayload = <shared.ITokenPayload> { username: loginDto.username, roles: roles };
    
        var payloadWithSignature = jwt.encode(tokenPayload, "safeguardThisSuperSecretKey");
    
        loginResponseDto.isUserValid = true;
        loginResponseDto.theAuthorizationToUse = "Bearer " + payloadWithSignature;
        
        res.json(loginResponseDto);            
    }
    else {
        loginResponseDto.isUserValid = false;
    
        res.status(401).json(loginResponseDto);    
    }    
}


function dbAuthenticate(username: string, password: string): any {
    
    if (username == "Thom" && password == "Yorke") {
        return true;
    }
    
    if (username == "Kurt" && password == "Cobain") {
        return true;
    }
    
    return false;
}


function dbGetUserRoles(username: string): string[] {
    
    if (username == "Thom") {
        return ["rockstar", "composer"];
    }
    
    if (username == "Kurt") {
        return ["composer"];
    }
    
    return [];
}


CanBe.ts:
import express = require('express');

import jwt = require('jwt-simple');


export function accessedBy(roles: string[]):any {
    accessedByBind.bind(roles);
}

function accessedByBind(roles:string[], req:express.Request, res:express.Response, next:Function): any {
    
    function unauthorized(): any {
        return res.sendStatus(401);
    }
    
    // === accessedByBind starts here ===
    
    var theAuthorizationToUse = req.headers["authorization"];
    
    if (theAuthorizationToUse === undefined) {
        return unauthorized();
    }
    
    var payloadWithSignature = theAuthorizationToUse.substr("Bearer ".length); 
    
    var tokenPayload = <shared.ITokenPayload> jwt.decode(payloadWithSignature, "safeguardThisSuperSecretKey");

    if (tokenPayload == undefined || tokenPayload.username == "") {
        return unauthorized();
    }
    
    if (tokenPayload.roles.filter(memberRole => roles.filter(allowedRole => memberRole == allowedRole).length > 0 ).length > 0) {
        return next();
    }
    
    return res.status(500).json({customError: "Unknown Error"});
    
}



ILoginDto.ts:
module shared {
    
    export interface ILoginDto {
        username: string;
        password: string;
    }
    
}

ILoginResponseDto.ts:
module shared {

    export interface ILoginResponseDto {
        isUserValid: boolean;
        theAuthorizationToUse: string;
    }
    
}

ITokenPayload.ts:
module shared {
    
    export interface ITokenPayload {
    
        username: string;
        roles: string[];
    
    }
}



init.js
// app initialization and dependency injections goes here

var angie:ng.IAngularStatic = require('angular');

var mod:ng.IModule = angie.module('niceApp', [
    'ui.router', 'ngResource', 'scs.couch-potato', 'ngFileUpload',
    'ngSanitize', 'ui.pagedown', 'ngTagsInput', 'puElasticInput', 'ui.bootstrap']);

mod.service('AuthService', ['$http', '$q', '$window', InhouseLib.AuthService]);
mod.factory('HttpInterceptor', ['$q', '$window', '$injector', 'TheSweetAlert', '$location', InhouseLib.HttpInterceptor]);

mod.config(['$httpProvider', ($httpProvider:ng.IHttpProvider) => {
    $httpProvider.interceptors.push('HttpInterceptor');
}]);


AuthService.ts:
module InhouseLib {

    export class AuthService {


        constructor(public $http:ng.IHttpService, public $q:ng.IQService, public $window: ng.IWindowService) {
        }

        verify(username:string, password:string):ng.IPromise<ng.IHttpPromiseCallbackArg<shared.ILoginResponseDto>> {

            var deferred = this.$q.defer();

            var u = <shared.ILoginDto>{};
            u.username = username;
            u.password = password;



            this.$http.post<shared.ILoginResponseDto>('/api/member/verify', u)
                .then(success => {

                    this.$window.localStorage["theToken"] = success.data.theAuthorizationToUse;

                    // This goes to then's success callback parameter
                    deferred.resolve(success);

                }, error => {

                    this.logout();

                    // this goes to then's error callback parameter
                    deferred.reject(error);

                });

            return deferred.promise;

        }

        logout(): void {
            delete this.$window.localStorage["theToken"];
        }

    }
}


HttpInterceptor.ts:
module InhouseLib {

    export function HttpInterceptor($q:ng.IQService,
                                    $window:ng.IWindowService,
                                    $injector:ng.auto.IInjectorService,
                                    TheSweetAlert,
                                    $location:ng.ILocationService)
    {

        return {
            request: (config):any => {
                config.headers = config.headers || {};

                var theToken = $window.localStorage["theToken"];

                if (theToken !== undefined) {
                    // token already include the word "Bearer "
                    config.headers.Authorization = theToken;
                }
                return config;
            },

            responseError: (response):any => {
                if (response.status === 401 || response.status === 403) {

                    // http://stackoverflow.com/questions/25495942/circular-dependency-found-http-templatefactory-view-state
                  
                    // ui-router's $state
                    // can use the $location.path(paramHere) to change the url. but since we are using ui-router
                    // it's better to use its $state component to route things around.
                    var $state:any = $injector.get('$state');

                    TheSweetAlert({title: "Oops", text: "Not allowed. Will redirect you to login page\n" +
                        "This is your current url: " + $location.path()}, () =>
                    {
                        $state.go('root.login');
                    });


                }
                return $q.reject(response);
            }
        };
    }// function HttpInterceptor

}

UPDATE:

Some code above has Cargo Culting in it, it uses $q.defer unnecessarily. Haven't properly learned the promise's fundamentals before :) Read: https://www.codelord.net/2015/09/24/%24q-dot-defer-youre-doing-it-wrong/

Thursday, September 10, 2015

Avoid multiple NOTs in conditions

TL;DR
Write code like how you are speaking in a conversation.


What's the flaw in this code?

if (e.which === 8 && e.target.nodeName !== "INPUT" || e.target.nodeName !== ")
    e.preventDefault();
}


How to express condition without being confused on when to use || or && operator?


First off, let's correct the most fundamental error on the logic above. && operator has higher precedence than || operator, or we can say && operator higher stickiness than || operator. The above is interpreted as:

if 
(

    (e.which === 8 && e.target.nodeName !== "INPUT")
 
    || 

    e.target.nodeName !== "SELECT"

)
{ 
    e.preventDefault();
}


To correct the incorrect unparenthesized code, use parenthesis:

if ( e.which === 8 && (e.target.nodeName !== "INPUT" || e.target.nodeName !== "SELECT") ) { 
    e.preventDefault();
}


Or since the code is not too indented, just nest the condition:

if (e.which === 8) {

    if (e.target.nodeName !== "INPUT" || e.target.nodeName !== "SELECT") { 
         e.preventDefault();
    }

}


Now that we get the harm out of the way, let's fix the second problem:

if (e.target.nodeName !== "INPUT" || e.target.nodeName !== "SELECT") {

}


What's wrong with the code above?

Yes, it always evaluates to true regardless of the value of e.target.nodeName.

This is where most developers are having a hard time when formulating a condition. The best way to express a logic is to express it like how you will say it in actual conversation. For example, if you want to advise your kid that if someone visits and he is not John, Paul, George, Ringo, then shoo him way. You will not say in English, "if he is not John, not Paul, not George, not Ringo, then shoo him away."

You will not repeat the NOT when you actually talk, instead you'll say: "if he is not John, Paul, George, Ringo, then shoo them away." You will only say NOT once. However, if you feel multiple NOTs is readable, you have to change the OR to AND to make the logic correct:

if e.target.nodeName ≠ "INPUT" and e.target.nodeName ≠ "SELECT" then
    disable navigation

But really, you won't say that in real life, you'll only say NOT once.

To code a correct logic, think of how you will write the condition if you will refactor or make a code shortcut. If you will move the condition to a function, you'll write it like this:

if not inputEditable(e.target.nodeName) then
    disable navigation


Now with that refactored code, the code writes itself:

inputEditable(nodeName) 

    if nodeName = "INPUT" or nodeName = "SELECT" then
        return true
    else
        return false

Here's the version when the condition above is inlined in if:

if not ( e.targetNodeName = "INPUT" or e.target.nodeName = "SELECT" ) then
    disable navigation


See? No more multiple NOTs, and the best thing is, the code is correct.


Just write things with one NOT, the right logic will write itself.



Happy Coding!

Tuesday, September 8, 2015

Using hallo on AngularJS and RequireJS (troubleshooting)

Requirement:
1. Hallo
npm install hallo

2. Hallo Angular Directive
Get the angular directive here: http://www.grobmeier.de/using-hallo-js-with-angularjs-14072013.html

3. Hallo requirejs.config paths:
"jQuery": "/lib/hallo/deps/jquery-1.9.0",
"jQueryUI" : "/lib/hallo/deps/jquery-ui-1.10.0.custom",
"rangyCore" : "/lib/hallo/deps/rangy-core-1.2.3",
"halloJS" : "/lib/hallo/examples/hallo",

4. require's prior to Angular app initialization:
define(require => {

    require('jQuery');
    require('jQueryUI');
    require('rangyCore');
    require('halloJS');

    var angie: ng.IAngularStatic = require('angular');
    createHalloDirective(angie); // http://www.grobmeier.de/using-hallo-js-with-angularjs-14072013.html">http://www.grobmeier.de/using-hallo-js-with-angularjs-14072013.html

    var mod: ng.IModule = angie.module('niceApp', []);



/lib points to node_modules directory.



If you encountered this error:
TypeError: element.hallo is not a function

You need to use full jQuery instead of Angular's jQLite.


In your requirejs.config shim section, you must specify jQuery as a dependency of Angular, if it's not specified it will load jQLite instead:

"angular" : {
    "exports": "angular",
    deps: ["jQuery"]
}


You'll encounter these errors if you don't define the depedencies between hallo, rangy and jQueryUI:
Uncaught TypeError: $.widget is not a function
  (anonymous function) 
  (anonymous function) 
TypeError: element.hallo is not a function


To fix that, must add these dependencies on your requirejs.config shim section:
"jQueryUI": {
    deps: ["jQuery"]
},

"rangyCore" : {
    deps: ["jQueryUI"]
},

"halloJS" : {
    deps: ["rangyCore"]
}



Hallo directive should load correctly on your Angular app. However when you double click the hallo content, it'll show the following errors:
jQuery.fn.jQuery.init[1]
Uncaught TypeError: rangy.getSelection is not a function
  jQuery.widget.getSelection 


The rangy-core that's bundled via hallo obtained from npm yields that error. To fix that, install rangy directly:

npm install rangy

Then use that instead of the rangy-core that's bundled with hallo.

Point rangyCore to new path on requirejs.config paths:
"jQuery": "/lib/hallo/deps/jquery-1.9.0",
"jQueryUI" : "/lib/hallo/deps/jquery-ui-1.10.0.custom",
// "rangyCore" : "/lib/hallo/deps/rangy-core-1.2.3", // remove this
"rangyCore" : "/lib/rangy/lib/rangy-core", // change to this
"halloJS" : "/lib/hallo/examples/hallo",


There's still an error when you double click the hallo content, it'll show the following:
jQuery.fn.jQuery.init[1]
Uncaught ReferenceError: rangy is not defined
  jQuery.widget.getSelection 


To fix that that, put the rangy's instance on window:
require('jQuery');
require('jQueryUI');

var rangy = require('rangyCore');
window["rangy"] = rangy;
    
require('halloJS'); // hallo looks for rangy in global scope, that is, window

That's it, when you double click the hallo's content, the tools for formatting(Bold, Italic, etc) should pop up now.

Monday, September 7, 2015

TypeScript All Things

On following Angular controller code, the second parameter Item looks odd, it has no type.

And the only way we can get TypeScript's autocomplete goodness on that Item service is to explicitly assign the type on Item service's $promise's callback argument. We cannot get autocomplete support on customQuery method.

constructor(
    product: Domain.Product, 
    Item, 
    $stateParams, 
    appWide: SharedState.AppWide) 
{

    appWide.title = "Products";

    this.product = product;

    var tag = $stateParams.tag === undefined ? "" : $stateParams.tag;

    product.searched = tag === "" ? "" : "tag:" + tag.replaceAll("--", " ");

    product.search = () => {
        this.searched = product.searched;

        Item.customQuery({keywords: this.searched})
            .$promise.then((items : 
                Dto.SearchDto
                ) => {
                this.itemSearched = items.matches;
                product.tags = items.tags;
                product.locations = items.locations;
            });
    }; // search

    product.search();

}

Definition of Dto.SearchDto:
module Dto {
    export class SearchLocationDto {
        locationId: string;
        locationName: string;
    }

    export class SearchItemDto {
        itemId : number;
        itemTitle: string;
        itemDescription: string;
        itemTags: string;
    }

    export class SearchDto {
        matches: SearchItemDto[];
        tags: string[]  ;
        locations: SearchLocationDto[];
    }
}

Definition of Dto.IItemReturnedDto. This is the type of save's then's success callback argument. Just a primary key
module Dto {
    export interface IItemReturnedDto {
        item_id : number;
    }
}


Then on module initialization, objects are just returned typeless:
var mod:ng.IModule = angie.module('niceApp', ['ui.router', 'ngResource', 'scs.couch-potato', 'ngFileUpload']);

mod.factory('Item', ['$resource', ($resource:angular.resource.IResourceService) => {

    return $resource("/api/item-secured/:theItemId", null, {
        customQuery: {method: 'GET', isArray: false}
    });

}]);


To improve the above, provide type on a service derived from Angular's $resource. Following is the interface definition of customized angular resource method customQuery.
module InhouseLib {

    export interface ISearchParameter {
        keywords: string;
    }

    // the returned when doing save on resource is Dto.IItemReturnedDto
    export interface ISearchResource extends ng.resource.IResourceClass<ng.resource.IResource<Dto.IItemReturnedDto>> { 
        customQuery(ISearchParameter) : angular.resource.IResource<Dto.SearchDto>;
    }
}

Then on module initialization, use the type defined above.
mod.factory('Item', ['$resource', ($resource:ng.resource.IResourceService) : InhouseLib.ISearchResource => {


   var customQueryAction : ng.resource.IActionDescriptor = {
       method: 'GET',
       isArray: false
   };

   var r = <InhouseLib.ISearchResource> $resource ("/api/item/:theItemId", null, {
       customQuery: customQueryAction
   });

   return r;

}]);


Now on controller constructor, add the type for Item (line 3 on code at the bottom). Doing that, the autocomplete for customQuery on Item service shall pop-up upon typing the dot character.




And also, we can also now eliminate (on line 20) the type (Dto.SearchDto) of the callback argument items:

constructor(
     product: Domain.Product, 
     Item: InhouseLib.ISearchResource, 
     $stateParams, 
     appWide: SharedState.AppWide) 
 {

    appWide.title = "Products";

    this.product = product;

    var tag = $stateParams.tag === undefined ? "" : $stateParams.tag;

    product.searched = tag === "" ? "" : "tag:" + tag.replaceAll("--", " ");

    product.search = () => {
        this.searched = product.searched;

        Item.customQuery({keywords: this.searched})
            .$promise.then(items => {
                this.itemSearched = items.matches;
                product.tags = items.tags;
                product.locations = items.locations;
            });

    }; // search

    product.search();

}

And yet the IDE is smart to know the type and it gives an autocomplete when you type the variable name(items) and dot symbol. TypeScript and WebStorm IDE are nice.

Sunday, September 6, 2015

Custom Basic Authentication and Authorization with AngularJS, Node Express, TypeScript, Massive DAL and PostgreSQL

Design:
    • On successful login, the server shall send back the authentication header that will be saved to angular's $http pipeline
    • Authorization is roles-based
    • Member's role(s) are stored as text array in the database

Prerequisites:
    • Data Access Layer node module
        ○ npm install massive
    • Basic Authentication node module
        ○ npm install basic-auth



I'll go owl on this and just do a code dump and briefly explain each part and their relation to other parts.


What will be created:
    
    • Login screen:
        1. /public/app-dir/Login/Template.html
        2. /public/app-dir/Login/Controller.ts
        
    • Login and Response DTOs shared by client-side and server-side
    
        3. /shared/dto/LoginDto.ts
        4. /shared/dto/LoginResponseDto.ts
        
    • Authentication service for Angular
        5. /public/inhouse-lib/AuthService.ts
    
    • Authentication node service
        6. /api/member.ts
        7. /db/loginVerify.sql

    • Authorization for node REST APIs
        8. /server/CanBe.ts
        9. /db/verifyRoleAccess.sql

    • Member table
        10. server/ddl.sql

    
What need to be changed:
        11. Nodejs's app.ts
            i. Add initialization of massive DAL
            ii. Add authentication url to node
            iii. Authorize a REST API




1. public/app-dir/Login/Template.html
<style>

    .block label { display: inline-block; width: 140px; text-align: left; }

</style>

<div class="col-md-2 col-md-offset-5">
    <form ng-submit="c.login()">
        <div class="block">
            <label>Username</label>
            <input type="text" ng-model="c.username"/>
        </div>

        <div class="block">
            <label>Password</label>
            <input type="password" ng-model="c.password"/>
        </div>

        <div class="block">
            <label></label>
            <input type="submit" value="Login"/>
        </div>

    </form>
</div>

2. public/app-dir/Login/Controller.ts
///<reference path="../../lib-inhouse/doDefine.ts"/>
///<reference path="../../../typings/angularjs/angular.d.ts"/>
///<reference path="../../lib-inhouse/AuthService.ts"/>
///<reference path="../../../typings/sweetalert/sweetalert.d.ts"/>
///<reference path="../../shared-state/AppWide.ts"/>

module App.Login {

    export class Controller {


        username:string;
        password:string;


        // Dependency-injected sweet alert, so it can be easily mocked

        constructor(public authService:InhouseLib.AuthService, public $http:ng.IHttpService, public $state:any,
                    public TheSweetAlert:SweetAlert.SweetAlertStatic,
                    public appWide:SharedState.AppWide) {
        }


        login():void {


            this.authService.verify(this.username, this.password)
                .then(success => {
                    this.appWide.isUploadVisible = true;
                    this.$state.go('root.app.home');
                }, error => {
                    this.appWide.isUploadVisible = false;
                    this.TheSweetAlert(error.status.toString(), "Not authorized", "error");
                });


        }

    }
}


doDefine(require => {

    var mod:angular.IModule = require('eat');


    require('/shared/dto/LoginDto.js');


    mod["registerController"]('LoginController', ['AuthService', '$http', '$state', 'TheSweetAlert', 'AppWide',
        App.Login.Controller]);

});


authService.verify line 27, is where the setting and clearing of Basic Authentication information to Angular's $http pipeline happens, authService.verify returns a promise if the authentication is successful, if the user is not authenticated it goes to the promise's error callback parameter.


public/lib-inhouse/doDefine.ts
///<reference path="../../typings/requirejs/require.d.ts"/>

// the doDefine will be disabled during unit test

function doDefine(func: (cb) => any) {

    define(func);

}

3. shared/dto/LoginDto.ts
///<reference path="../../typings/node/node.d.ts"/>


module Dto {

    export class LoginDto {

        username: string;
        password: string;

    }

}



4. shared/dto/LoginResponseDto.ts
///<reference path="../../typings/node/node.d.ts"/>

module Dto {

    export class LoginResponseDto {

        isValidUser: boolean;

        theBasicAuthHeaderToUse: string;

    }

}

The theBasicAuthHeaderToUse is the header that will be received by Angular and shall be assigned to Angular's $http pipeline. Its format is:

Basic base64encodeOf(username + ': ' + password)

Sample format:
Basic VGhvbSBZb3JrZTpjcmVlcA==


5. public/lib-inhouse/AuthService.ts
///<reference path="../../typings/angularjs/angular.d.ts"/>
///<reference path="../../shared/dto/LoginDto.ts"/>
///<reference path="../../shared/dto/LoginResponseDto.ts"/>

module InhouseLib {

    export class AuthService {


        constructor(public $http:ng.IHttpService, public $q:ng.IQService) {
        }

        verify(username:string, password:string):ng.IPromise<ng.IHttpPromiseCallbackArg<Dto.LoginResponseDto>> {

            var deferred = this.$q.defer();

            var u = new Dto.LoginDto();
            u.username = username;
            u.password = password;



            this.$http.post<Dto.LoginResponseDto>('/api/member/verify', u)
                .then(success => {


                    this.$http.defaults.headers["common"]["Authorization"] = success.data.theBasicAuthHeaderToUse;

                    // This goes to then's success callback parameter
                    deferred.resolve(success);

                }, error => {

                    this.logout();

                    // this goes to then's error callback parameter
                    deferred.reject(error);

                });

            return deferred.promise;

        }

        logout(): void {
            delete this.$http.defaults.headers["common"]["Authorization"];
        }

    }

}



6. Authentication module. Do the base64 encoding of Basic username:passwordHere at the server.

api/member.ts
/// <reference path="../typings/express/express.d.ts"/>
/// <reference path="../typings/extend/extend.d.ts"/>
/// <reference path="../shared/dto/LoginDto.ts"/>
///<reference path="../shared/dto/LoginResponseDto.ts"/>


import express = require("express");

import extend = require('extend');


export function verify(req:express.Request, res:express.Response, next:Function):any {


    var app:express.Application = req["app"];
    var db = app.get('db');


    var loginDto = <Dto.LoginDto> req.body;
    console.log(loginDto.username);

    var loginResponseDto = <Dto.LoginResponseDto>{};

    db.loginVerify([loginDto.username, loginDto.password], (err, result) => {


        if (result.length == 0) {

            loginResponseDto.isValidUser = false;
            loginResponseDto.theBasicAuthHeaderToUse = "Ha! Are you expecting a returned value?!";
            res.status(401).json(loginResponseDto);

        }
        else {

            var member = result[0];
            var salted_password = member.salted_password;

            loginResponseDto.isValidUser = true;
            loginResponseDto.theBasicAuthHeaderToUse = 
                "Basic " + new Buffer(loginDto.username + ":" + loginDto.password).toString("base64");
            res.json(loginResponseDto);
        }

    });

}



7. db/loginVerify.sql

This is called by the Authentication module.

For a primer of bcrypt mechanism: http://www.ienablemuch.com/2014/10/bcrypt-primer.html

select member_name, salted_password
from member
where member_name = $1 and salted_password = crypt($2, salted_password);

This is where the authorization happens.


8. Authorization module

server/CanBe.ts
/// <reference path="../typings/express/express.d.ts"/>

import express = require('express');

var basicAuth = require('basic-auth');


export function accessedBy(roles:string[]):express.RequestHandler {
    return accessedByBind.bind(undefined, roles);
}


function accessedByBind(roles:string[], req:express.Request, res:express.Response, next:Function): any {

    function unauthorized(): any {
        res.set('WWW-Authenticate', 'Basic realm=Authorization Required');
        return res.sendStatus(401);
    }


    // === accessedByBind starts here ===

    var app:express.Application = req["app"];
    var db = app.get('db');


    var user = basicAuth(req);

    if (!user || !user.name || !user.pass) {
        return unauthorized();
    }

    var username = user.name;
    var password = user.pass;

    db.verifyRoleAccess([username, password, roles], (err, result) => {

        if (err == null) {
            var isAllowed = result[0].is_allowed;

            if (isAllowed)
                return next();
            else {
                return unauthorized();
            }
        }
        else {
            return res.status(500).json({customError: 'Unknown Error'});
        }

    });


}



9. db/verifyRoleAccess.sql

This is called by the CanBe Authorization module.

select exists(

select null
from member
where
member_name = $1 and salted_password = crypt($2, salted_password)
and roles && $3 -- check if $3 (arrayOfRoles) passed from canBe.accessedBy(arrayOfRolesHere) is in member.roles.

) as is_allowed;



10. server/ddl.sql
create table member
(
    member_id serial primary key,
    member_name citext not null unique,
    salted_password text not null, -- using bcrypt
    roles text[]
);

insert into member(member_name, salted_password, roles) values
('Thom Yorke', crypt('creep', gen_salt('bf')), '{"rockstar"}')


11. app.ts
var massive = require('massive'); // DAL
import memberApi = require('./api/member'); // authentication 
import canBe = require('./server/CanBe'); // authorization


var massiveInstance = massive.connectSync({connectionString: 'postgres://postgres:yourPasswordHere@localhost/commerce'});
app.set('db', massiveInstance);

app.post('/api/member/verify', memberApi.verify);

// unsecured API
app.get('/api/item', itemApi.search);

// just insert canBe.accessedBy before the itemApi.search RequestHandler REST API to secure the REST API
app.get('/api/item-secured', canBe.accessedBy(['rockstar']), itemApi.search); 

UPDATE:

Some code above has Cargo Culting in it, it uses $q.defer unnecessarily. Haven't properly learned the promise's fundamentals before :) Read: https://www.codelord.net/2015/09/24/%24q-dot-defer-youre-doing-it-wrong/

Don't marshal when you can cast

var loginDto = <Dto.LoginDto> {};
extend(loginDto, req.body); // marshal the req.body dictionary to strongly-typed object
console.log(loginDto.username);

The code above is inefficient, extending is an expensive process. The above could be simply rewritten as:

var loginDto = <Dto.LoginDto> req.body;
console.log(loginDto.username);


Imagine the nodejs code above if done with statically-typed framework such as ASP.NET MVC, the values from Request.Form (same as nodejs's req.body) need to be marshalled to DTO object every time a request is made, a bit inefficient.


You can make something efficient and be efficient (autocomplete support) when coding with TypeScript.

Thin Angular Controller

An example of caller of Authentication API:

App.Login.Controller.ts:
module App.Login {

    export class Controller {


        username:string;
        password:string;

        // Dependency-injected sweet alert, so it can be easily mocked
        constructor(public authApi:InhouseLib.AuthApi, public $http:ng.IHttpService, public $state:any,
                    public TheSweetAlert:SweetAlert.SweetAlertStatic,
                    public appWide:SharedState.AppWide) {
        }


        login():void {


            this.authApi.verify(this.username, this.password)
                .then(success => {
                    console.log(success.data.isValidUser);
                    this.appWide.isUploadVisible = true;
                    this.$http.defaults.headers["common"]["Authorization"] = success.data.theBasicAuthHeaderToUse;
                    this.$state.go('root.app.home');
                }, error => {
                    console.log(error.data.isValidUser);                    
                    this.appWide.isUploadVisible = false;
                    delete this.$http.defaults.headers["common"]["Authorization"];
                    this.TheSweetAlert("Oops...", "Not authorized", "error");                
                });

            }//login
            
        }//Controller
}


An example of Authentication API, AuthApi.ts:

///<reference path="../../typings/angularjs/angular.d.ts"/>
///<reference path="../../shared/dto/LoginDto.ts"/>
///<reference path="../../shared/dto/LoginResponseDto.ts"/>

module InhouseLib {

    export class AuthApi {

        constructor(public $http : ng.IHttpService) {

        }

        verify(username: string, password: string) : ng.IHttpPromise<Dto.LoginResponseDto> {

            var u = new Dto.LoginDto();
            u.username = username;
            u.password = password;


            return this.$http.post<Dto.LoginResponseDto>('/api/member/verify', u);

        }

    }

}


// Angular initialization code:
// mod.service('AuthApi', ['$http', InhouseLib.AuthApi]);



The problem with the caller(Login Controller) of the Authentication API is it does things that should not be of concern to it. One concern that should not be in the controller is the assigning and invalidating of Basic Authentication to angular's $http pipeline.


To improve that. The assigning and invalidating of Basic Authentication information to angular's $http pipeline should be done on AuthApi.ts. Following is an example. First, we must remove the code related to Basic Authentication away from the concerns of Login controller.

login():void {

    this.authApi.verify(this.username, this.password)
        .then(success => {
             console.log(success.isValidUser);
             this.appWide.isUploadVisible = true;
             this.$state.go('root.app.home');
        }, error => {
             console.log(error.isValidUser);                
             this.appWide.isUploadVisible = false;
             this.TheSweetAlert("Oops...", "Not authorized", "error");
        });


}


Then move that concern to AuthApi.ts:

verify(username: string, password: string) : ng.IPromise<Dto.LoginResponseDto> {

    var deferred = this.$q.defer();

    var u = new Dto.LoginDto();
    u.username = username;
    u.password = password;


    this.$http.post<Dto.LoginResponseDto>('/api/member/verify', u)
    .then(success => {

        this.$http.defaults.headers["common"]["Authorization"] = success.data.theBasicAuthHeaderToUse;

        // This goes to then's success callback parameter
        deferred.resolve(success.data);

    }, error => {

        delete this.$http.defaults.headers["common"]["Authorization"];

        // this goes to then's error callback parameter
        deferred.reject(error.data);

    });

    return deferred.promise;

}


If the caller code (Login Controller) has a need receive http status code returned by the server, return a promise of IHttpPromiseCallbackArg with an argument of the other information(Dto.LoginResponseDto) instead.

verify(username: string, password: string) :     
    ng.IPromise<ng.IHttpPromiseCallbackArg<Dto.LoginResponseDto>> 
{

    var deferred = this.$q.defer();

    var u = new Dto.LoginDto();
    u.username = username;
    u.password = password;


    this.$http.post<Dto.LoginResponseDto>('/api/member/verify', u)
        .then(success => {
            this.$http.defaults.headers["common"]["Authorization"] = success.data.theBasicAuthHeaderToUse;

            // This goes to then's success callback parameter
            deferred.resolve(success);

        }, error => {

            delete this.$http.defaults.headers["common"]["Authorization"];

            // this goes to then's error callback parameter
            deferred.reject(error);

        });

    return deferred.promise;

}


To access the other information(Dto.LoginResponseDto), access it via success.data and error.data. For the http status code, access it from success or error parameter, e.g., error.status.

login():void {


     this.authApi.verify(this.username, this.password)
         .then(success => {
             console.log(success.data.isValidUser);
             this.appWide.isUploadVisible = true;
             this.$state.go('root.app.home');
         }, error => {
             console.log(error.data.isValidUser);                
             this.appWide.isUploadVisible = false;
             this.TheSweetAlert(error.status.toString(), "Not authorized", "error");
         });

}

WebStorm Need Tight TypeScript Integration

Seriously.


Whereas Visual Studio Code coding assistance almost works flawlessly. For example Visual Studio Code shows on the tooltip the type of the parameter when hovering over the parameter:



..WebStorm has problem knowing the type:



Wishing there is TypeScriptStorm.

Thursday, September 3, 2015

Fast text search in PostgreSQL

This works in Postgres:


select * from location where location_id = any(array[1,6,8])

However, if you tried to match it against an array on another query, it won't work, even though the another query returns exactly one row only.

select * from location where location_id = any(select location_ids from province p where p.province_name = 'Metro Manila' limit 1)

Output:
ERROR:  operator does not exist: integer = integer[]
LINE 1: select * from location where location_id = any
                                                 ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.


To correct it, unnest the array:

select * from location where location_id = any(select unnest(location_ids) from province p where p.province_name = 'Metro Manila')

Might as well use IN:

select * from location where location_id in (select unnest(location_ids) from province p where p.province_name = 'Metro Manila')


There's a drawback on the queries above, it uses equal operator. In Postgres, indexers are bound to operator, and GIN, the indexing technology for indexing array, doesn’t support equal operator. See the detail here: http://stackoverflow.com/questions/4058731/can-postgresql-index-array-columns/29245753#29245753


So to optimize the query, use either of the following:


-- This query works same as the query at the bottom. The query at the bottom is more readable though.
-- The advantage of this query is if the province matches many rows, it would still work, say the province_name uses ILIKE operator.

select  *
from    location l
where   exists
        (
            select  p.location_ids
            from    province p
            where   p.province_name = 'Metro Manila'
                    and array[l.location_id] && p.location_ids
        );

The query uses overlap operator, &&. See the use of supported operators on arrays: http://www.postgresql.org/docs/9.1/static/functions-array.html

-- If province returns exactly one row, this is more readable than above
select   *
from     location l
where    array[l.location_id] && ( select location_ids p from province p where p.province_name = 'Metro Manila' );


Live code: http://sqlfiddle.com/#!15/6ac38/5


Happy Coding!

Monday, August 31, 2015

module.exports has lesser mental model when exporting a module

On my post about sharing TypeScript classes between client-side and server-side. I used exports rather than module.exports. However, as I later learned, it's better to use module.exports as it's the one being directly returned by the require function, module.exports is the real deal. If we uses module.exports rather than exports, we don't need to do this anymore:

class ExternalizedDomain {
    static Person : typeof Domain.Person = require('./shared/Domain/Person').DomainPerson;
    static Country : typeof Domain.Country = require('./shared/Domain/Country').DomainCountry;
}

And also the drawback of the idiom above is it is not compatible with proxyquire:

it("applies interest using stubbed calculator", () => {

 var calculatorStub : any = {};

 var financialCalculator : typeof Domain.FinancialCalculator = 
                  proxyquire('../shared/Domain/FinancialCalculator', { './Calculator': calculatorStub });

 var interestApplied = financialCalculator.applyInterest(200, 0.2);
 expect(interestApplied).toEqual(240);


 calculatorStub.multiply = (a,b) => 6;
 var interestAppliedFromStubbedCalculator = financialCalculator.applyInterest(100, 0.2);
 expect(interestAppliedFromStubbedCalculator).toEqual(6);
});


There's no way in proxyquire to specificy an specific property (e.g., .DomainPerson) of the object assigned to module.exports. To make the external module compatible with proxyquire, do as the following:


class ExternalizedDomain {
    static Person : typeof Domain.Person = require('./shared/Domain/Person');
    static Country : typeof Domain.Country = require('./shared/Domain/Country');
}


Then change the Person.ts and Country.ts to export things on module.exports:

Person.ts:
module Domain {
    export class Country {
        name : string;
    }
}

// Hack for converting internal module to external module
declare var exports: any;
if (typeof exports != 'undefined') {
    module.exports = Domain.Country;
}

Country.ts:
module Domain {
    export class Country {
        name : string;
    }
}


// Hack for converting internal module to external module
declare var exports: any;
if (typeof exports != 'undefined') {
    module.exports = Domain.Country;
}



Definition of Calculator.ts:
///<reference path="../../typings/node/node.d.ts"/>

var isNode = typeof exports !== 'undefined' && this.exports !== exports;


module Domain.Calculator {

    export function multiply(multiplicand: number, multiplier: number): number {

        return multiplicand * multiplier;
    }

    export function divide(dividend: number, divisor: number): number {

        return null;
    }
}



if (isNode) {
    module.exports = Domain.Calculator;
}


Definition of FinancialCalculator.ts:
/// <reference path="../../typings/node/node.d.ts"/>

///<reference path="Calculator.ts"/>


var isNode = typeof exports !== 'undefined' && this.exports !== exports;

var calculator : typeof Domain.Calculator = isNode ? require('./Calculator') : Domain.Calculator;


module Domain.FinancialCalculator {

    export function applyInterest(amount: number, percentInterest: number): number {

        return calculator.multiply(amount, 1 + percentInterest);
    }

}


if (isNode) {
    module.exports = Domain.FinancialCalculator;
}


On next post, I'll show the difference between TypeScript's classes and module when it comes to proxyquire.


Happy Coding!

TypeScript definition ambiguity woes. Which require function should go? RequireJS' or NodeJS'?

If you encountered this error:

Error:(49, 13) TS2403: Subsequent variable declarations must have the same type.  Variable 'require' must be of type 'Require', but here has type 'NodeRequire'.


It's better to remove RequireJS's require, as you can access the require functionality of RequireJS's through its syntax sugar a.k.a. simplified CommonJS wrapping.

RequireJS syntax sugar for require is done like this:
define(require => {
    var calculator : typeof SharedModel.Calculator = require('Calculator');
    var financialCalculator : typeof SharedModel.FinancialCalculator = require('FinancialCalculator');
});



On RequireJS's TypeScript definition, require.d.ts, comment or remove its require declaration:
// Ambient declarations for 'require' and 'define'
declare var requirejs: Require;
// declare var require: Require;
declare var define: RequireDefine;

Friday, August 28, 2015

Custom Basic Authentication and Authorization for Node Express

You have an existing REST API, and you wanted to protect it:

app.get('/api/something', (req: express.Request, res: express.Response, next: Function) => {
    res.json({message: 'Mensaje', description: 'Yeah!'});
});

The neatest way to protect your REST API is to make a function that returns a callback function for Basic Authentication so it can be chained on node express parameters, and the implementation detail can be hidden to user too. To wit, here's how it shall look like usage-wise:

import canBe = require('./CanBe');

app.get('/api/something', canBe.accessedBy(['guest']),  (req: express.Request, res: express.Response, next: Function) => {
    res.json({message: 'Mensaje', description: 'Yeah!'});
});


Most of the explanation of the use of bind shows its usefulness on the this object. The following code demonstrates another good use of bind function. What the called function accessedBy does is it returns the callback with a binded parameter (roles array parameter in the following example) by binding a leading parameter on the accessedByBind function; so when the callback function accessedByBind is called by node express, the roles parameter is passed to it too.


CanBe.ts:

/// <reference path="./typings/express/express.d.ts"/>

import express = require('express');

var basicAuth = require('basic-auth');


export function accessedBy(roles: string[]) : express.RequestHandler {
    return accessedByBind.bind(undefined, roles);
}


function accessedByBind(roles: string[], req: express.Request, res: express.Response, next: Function): express.RequestHandler {

    function unauthorized(res) : express.RequestHandler {
        res.set('WWW-Authenticate', 'Basic realm=Authorization Required');
        return res.send(401);
    }


    function isUserInRole(userName:string): boolean {

        var userRole: string;

        if (userName == "foo") {
            userRole = 'guest';
        }
        else {
            userRole = '';
        }

        var isAllowed = false;

        for(var i = 0; i < roles.length; ++i) {
            if (roles[i] == userRole) {
                isAllowed = true;
                break;
            }
        }

        console.log("Is allowed " + isAllowed)

        return isAllowed;

    }


    // === accessedByBind starts here ===


    var user = basicAuth(req);

    if (!user || !user.name || !user.pass) {
        return unauthorized(res);
    }


    if (user.name === 'foo' && user.pass === 'bar') {

        var isAllowed = isUserInRole(user.name);

        console.log("Is allowed " + isAllowed);

        if (isAllowed)
            return next();
        else
            return unauthorized(res);

    } else {
        return unauthorized(res);
    }

}


Here's .bind in a nutshell:

Live Code http://jsfiddle.net/b33gukgv/

function list(a,b,c) { 
    console.log('a: ' + a);
    console.log('b: ' + b);
    console.log('c: ' + c);    
    console.log(arguments);
}

//  Create a function with a preset leading argument
var always = list.bind(undefined, "Omni", "Present");

list("of", "good", "things");

always("something", "there", "to");

always("remind", "me");


Output:

This little thing called this

While learning the Basic Authentication on node express, I encountered the need to learn javascript more. One thing I learned today is the use of .bind function of javascript. I seen it being used most on javascript UI frameworks, I didn't bother to learn what's the use of that bind function, until today.

On Basic Authentication of node express, I need to pass an extra parameter to node express callback, that parameter is role. That role parameter is akin to Authorize attribute of ASP.NET MVC.

Here's a rough signature of node express callback:

interface Func {
    (random: number, basicAuthUser: string) : boolean;
}


function doSomething(...actions: Func[]) : void {
    
    var basicAuthUser = "davegrohl"; // obtained from browser's Basic Authentication    
    
    for(var i = 0; i < actions.length; ++i) {
        var a = actions[i];
        var okToContinue = a(Math.random() * 100, basicAuthUser);
        if (!okToContinue) 
            break;
    }
}

console.log('');
console.log('without authorization');
doSomething(
    (i,u) => { console.log('Alpha ' + i); return true; },
    (i,u) => { console.log('Beta ' + i); return true; }
    );


Then I think, authentication and authorization role mechanism could be slotted on the first parameter of the array. But how would I pass an extra parameter on the callback? Then an enlightenment from C# came. On C# object, the properties can be accessed even if the method reference is passed to callback. The solution could be written in C# like the following:


Live Code: https://dotnetfiddle.net/tSenYK
using System;
using System.Linq;
                    
public class Program
{
    public static void Main()
    {
        Console.WriteLine("Without authorization:");
        DoSomething(            
            (i,u) => { Console.WriteLine("Alpha " + i); return true; },
            (i,u) => { Console.WriteLine("Beta " + i); return true; }            
            );    
                
        Console.WriteLine();
        Console.WriteLine("Rockstar activity:");
        DoSomething(
            new Authorizer("rockstar").ActionToDo, // just pass the reference of method
            (i,u) => { Console.WriteLine("Alpha " + i); return true; },
            (i,u) => { Console.WriteLine("Beta " + i); return true; }            
            );                        
        
        Console.WriteLine();
        Console.WriteLine("Guest activity:");        
        DoSomething(
            new Authorizer("guest").ActionToDo,
            (i,u) => { Console.WriteLine("Alpha " + i); return true; },
            (i,u) => { Console.WriteLine("Beta " + i); return true; }            
        );    
    }
    
    
    // third-party framework. cannot change the signature
    public static void DoSomething(params Func<int, string, bool>[] actions)
    {
        var basicAuthUser = "davegrohl"; // obtained from browser's Basic Authentication        
        for(int i = 0; i < actions.Length; ++i)
        {
            var a = actions[i];
            bool okToContinue = a(new Random().Next(10), basicAuthUser);
            if (!okToContinue)
                break;
        }
        
    }
    

}



class Authorizer
{
    public string RoleAllowed { get; set; }
    
    public Authorizer(string roleAllowed)
    {
        this.RoleAllowed = roleAllowed;
    }
    
    string GetRole(string basicAuthUser)
    {
        return "rockstar"; // davegrohl's role fetched from database
    }
    
    public bool ActionToDo(int i, string basicAuthUser) 
    {
        // Database operation here.
        // Get the role of basicAuthUser
        var role = this.GetRole(basicAuthUser);
        
        
        
        return role == this.RoleAllowed;    
    }
}

Output:
Without authorization:
Alpha 4
Beta 4

Rockstar activity:
Alpha 4
Beta 4

Guest activity:


So I just need write the equivalent in TypeScript/JavaScript:

Live Code at TypeScriptLang


class Authorizer
{
    roleAllowed : string;
    
    constructor(roleAllowed: string)
    {
        this.roleAllowed = roleAllowed;
    }
    
        
    private getRole(basicAuthUser: string) : string {
        return "rockstar"; // davegrohl's role fetched from database
    }
    
    actionToDo(i: number, basicAuthUser: string) : boolean 
    {
        // Database operation here.
        // Get the role of basicAuthUser
        
        var role = this.getRole(basicAuthUser); // davegrohl's role fetched from database
                
        return role === this.roleAllowed;    
    }
}



    


interface Func {
    (random: number, basicAuthUser: string) : boolean;
}


function doSomething(...actions: Func[]) : void {
    
    var basicAuthUser = "davegrohl"; // obtained from browser's Basic Authentication    
    
    for(var i = 0; i < actions.length; ++i) {
        var a = actions[i];
        var okToContinue = a(Math.random() * 100, basicAuthUser);
        if (!okToContinue) 
            break;
    }
}

console.log('');
console.log('without authorization');
doSomething(
    (i,u) => { console.log('Alpha ' + i); return true; },
    (i,u) => { console.log('Beta ' + i); return true; }
    );
    


console.log('');
console.log("Rockstar activity:");
doSomething(
    new Authorizer("rockstar").actionToDo,
    (i,u) => { console.log("Alpha " + i); return true; },
    (i,u) => { console.log("Beta " + i); return true; }            
    );                        


console.log('');
console.log("Guest activity:");        
doSomething(
    new Authorizer("guest").actionToDo,
    (i,u) => { console.log("Alpha " + i); return true; },
    (i,u) => { console.log("Beta " + i); return true; }            
);    


However, it didn't work. The this object looks like it's not an instance af Authorizer class. The error says:





Then I add a console.log of the this object.
actionToDo(i: number, basicAuthUser: string) : boolean 
    {
        // Database operation here.
        // Get the role of basicAuthUser
        
        console.log(this);
        
        var role = this.getRole(basicAuthUser); // davegrohl's role fetched from database
                
        return role === this.roleAllowed;    
    }


Here's the output, oops it looks like the this object is not carried when passing the reference of the method to callbacks.



To make the long story short, the this object is not included when accessing the reference of the method. Not similar to C#

The solution is to bind the this object before passing the reference of the method to callback.

Correct:

Live Code at TypeScriptLang

class Authorizer
{
    roleAllowed : string;
    
    constructor(roleAllowed: string)
    {
        this.roleAllowed = roleAllowed;
    }
    
    getBindedActionToDo() : Func {
        return this.actionToDo.bind(this);
    }
    
    private getRole(basicAuthUser: string) : string {
        return "rockstar"; // davegrohl's role fetched from database
    }
    
    actionToDo(i: number, basicAuthUser: string) : boolean 
    {
        // Database operation here.
        // Get the role of basicAuthUser
        
        console.log(this);
        
        var role = this.getRole(basicAuthUser); // davegrohl's role fetched from database
                
        return role === this.roleAllowed;    
    }
}



interface Func {
    (random: number, basicAuthUser: string) : boolean;
}


function doSomething(...actions: Func[]) : void {
    
    var basicAuthUser = "davegrohl"; // obtained from browser's Basic Authentication    
    
    for(var i = 0; i < actions.length; ++i) {
        var a = actions[i];
        var okToContinue = a(Math.random() * 100, basicAuthUser);
        if (!okToContinue) 
            break;
    }
}

console.log('');
console.log('without authorization');
doSomething(
    (i,u) => { console.log('Alpha ' + i); return true; },
    (i,u) => { console.log('Beta ' + i); return true; }
    );
    


console.log('');
console.log("Rockstar activity:");
doSomething(
    new Authorizer("rockstar").getBindedActionToDo(),
    (i,u) => { console.log("Alpha " + i); return true; },
    (i,u) => { console.log("Beta " + i); return true; }            
    );                        


console.log('');
console.log("Guest activity:");        
doSomething(
    new Authorizer("guest").getBindedActionToDo(),
    (i,u) => { console.log("Alpha " + i); return true; },
    (i,u) => { console.log("Beta " + i); return true; }            
);    


Output:





Happy Coding!

Testing an AMD POJO Angular Controller

One of the nice things of Controllers in ASP.NET MVC is they are easy to test, just new the controller and you are good to go.

One of the nice things with new Angular removing reliance on $scope is we can now test controllers just by newing them, we don't need to worry where to get the $scope variable being passed to it. Our controller becomes very POJO, very easy to test.


An example of POJO controller.

///<reference path="../../../typings/requirejs/require.d.ts"/>
///<reference path="../../../typings/angularjs/angular.d.ts"/>
///<reference path="../../../shared/ViewValue/Header.ts"/>
///<reference path="../../../shared/Domain/Product.ts"/>


module App.ProductForSale {

    export class Controller {

        product : Domain.Product;

        percentDiscount: number;

        get discountedPrice() : number {

            return this.product.price * (1 - this.percentDiscount);
        }

        constructor(header: ViewValue.Header) {

            header.title = "Product for sale";

            this.product = new Domain.Product();
        }
    }
}


define(require => {

    var mod : angular.IModule = require('theMainModule');
    require('/shared/Domain/Product.js');

    mod["registerController"]('ProductForSaleController',['singletonHeader', App.ProductForSale.Controller]);

});


There's just one minor problem when testing the controller above. It's an AMD controller, to test it we should be able to ignore the define statement in it.


The easiest way to disable it is to monkey-patch the define function by changing it to something else. An example. Name this test setup as _must-be-runned-first.ts:


if (window["def"] == undefined) {
    window["def"] = window["define"];

    window["define"] = function(depArray : string[], c: any) {
        console.log('define intercepted');
        console.log(depArray);
    };
}



function doTest(test) {
    var def = window["def"];

    def(test);
}

doTest just wrap the test so tests uses the original define, other defines just got redirected.


Here's a sample test:

///<reference path="../typings/jasmine/jasmine.d.ts"/>
///<reference path="../typings/requirejs/require.d.ts"/>
///<reference path="_must-be-runned-first.ts"/>

doTest(require => {


    describe("Board Controller", () => {
        require('/base/public/app-dir/ProductForSale/Controller.js');
        require('/base/shared/ViewValue/Header.js');


        var h = new ViewValue.Header();

        it("computes discount", () => {

            var b = new App.ProductForSale.Controller(h);
            b.product.price = 50;
            b.percentDiscount = 0.10;
            var discountedPrice = 45;

            expect(b.discountedPrice).toEqual(discountedPrice);

        });
    });
});


By redefining the window["define"] to something else, requirejs won't complain of script error on theMainModule as it is not available when doing tests on controller.



Add test-main.js on files array of karma.conf

module.exports = function(config) {
    config.set({

        // base path that will be used to resolve all patterns (eg. files, exclude)
        basePath: '',


        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['jasmine', 'requirejs'],


        // list of files / patterns to load in the browser
        files: [
            'test-main.js',
            {pattern: 'shared/**/*.js', included: false},
            {pattern: 'public/**/*.js', included: false},
            {pattern: 'tests/*.js', included: false}
        ]
    });
}



Then on test-main.js, add the _must-be-runned-first.js as the first file to be dynamically-loaded, remove the .js extension when adding it to allTestFiles array.


var allTestFiles = [];

var TEST_REGEXP = /(spec|test)\.js$/i;

allTestFiles.push('tests/_must-be-runned-first');

// Get a list of all the test files to include
Object.keys(window.__karma__.files).forEach(function(file) {
    if (TEST_REGEXP.test(file)) {
        // Normalize paths to RequireJS module names.
        // If you require sub-dependencies of test files to be loaded as-is (requiring file extension)
        // then do not normalize the paths
        var normalizedTestModule = file.replace(/^\/base\/|\.js$/g, '');

        allTestFiles.push(normalizedTestModule);
    }
});


console.log(allTestFiles);

require.config({
    // Karma serves files under /base, which is the basePath from your config file
    baseUrl: '/base',


    // dynamically load all test files
    deps: allTestFiles,

    // we have to kickoff jasmine, as it is asynchronous
    callback: window.__karma__.start
});



Complete Code: https://github.com/MichaelBuen/PlayNodeTypescriptUirouterCouchpotato/tree/master/public


Happy Coding!

Tuesday, August 25, 2015

Angular Service and Factory are just the same

That is, the values of service/factory values being passed to controllers are singletons.

The only difference between the two; with service it's Angular's job to do the new'ing, with factory it's the responsibility of your factory's callback to do the new'ing. Despite the name factory, don't be confused that it gets called every time it is needed by controllers, that it can make a new instance every time it is called; in fact, the factory's callback is only called once by Angular, effectively its result is also cached just like service. Here are the screenshots showing how many times the service and factory are being called.


Service:


Factory:



As shown on screenshot, Domain.Product is new'd only once on service, even the factory is just called once. Hence the values being passed to controllers, be it from service or from factory, have just the same instance, are effectively singletons.


Imagine service is implemented as:
function service(nameHere, c) {
    cache[nameHere] = new c(); // new'd once only.
} 

Imagine factory is implemented as:
function factory(nameHere, c) {
    cache[nameHere] = c(); // called once only.
}


As for which one is used more often or should be used more often. If factory is called every time it is being needed on controller, it will fit the name factory more . But alas, factory is just called once, effectively returning singletons only, it's better to use service if all you need is singleton.


You can even use service if you want to make a real factory. Of course, you can also use factory if you want to make a real factory :)


/TheApp.ts:
///<reference path="../typings/requirejs/require.d.ts"/>
///<reference path="../typings/angularjs/angular.d.ts"/>

///<reference path="../shared/Domain/Product.ts"/>



define(['angular', 'angularUIRouter', 'angularResource', 'couchPotato' ], function(angular, angularUIRouter, angularResource, couchPotato) {

    var app = angular.module('niceApp',['ui.router','ngResource','scs.couch-potato']);


    var useService : boolean = true;

    if (useService)
        app.service('domainProduct', Domain.Product);
    else
        app.factory('domainProduct', () => {
            console.log('Factory');
            return new Domain.Product();
        });

    couchPotato.configureApp(app); // this dynamically adds registerProvider on angular module niceApp

    return app;

});

/shared/Domain/Product.ts:
module Domain {

    export class Product {
    
        name : string;
        yearModel : number;

        constructor() {
            this.name = "Initial Value";
            this.yearModel = 1900;

            console.log('Product Constructor');
        }
    }
}

/app-dir/Product/Controller.ts
//<reference path="../../../typings/requirejs/require.d.ts"/>
///<reference path="../../../typings/angularjs/angular.d.ts"/>
///<reference path="../../../shared/Domain/Product.ts"/>


class Controller {

    sampleMessage : string;

    domainProduct : Domain.Product;

    constructor($scope : angular.IScope, domainProduct) {

        console.log("Product's Controller: User of factory/services");
        
        this.domainProduct = domainProduct;

    }
    
}

define(['theApp'], function (app) {
    app.registerController('ProductController',['$scope', 'domainProduct', Controller]);
});

/app-dir/Product/SidebarController.ts
///<reference path="../../../typings/requirejs/require.d.ts"/>
///<reference path="../../../typings/angularjs/angular.d.ts"/>
///<reference path="../../../shared/Domain/Product.ts"/>

class Controller {

    sampleMessage : string;

    domainProduct : Domain.Product;

    constructor($scope : angular.IScope, domainProduct) {
    
        console.log("Product's Sidebar Controller: User of factory/services");

        this.domainProduct = domainProduct;
    }
}


define(['theApp'], function (app) {
    app.registerController('ProductSidebarController',['$scope', 'domainProduct', Controller]);
});

Saturday, August 22, 2015

Conflict between NodeJS's require and RequireJS's require TypeScript definitions

At the time of this writing, if you wanted to use TypeScript's umd (Universal Module Definition), you'll get an error between NodeJS's require and RequireJS's require TypeScript definitions.




A temporary solution to that is to disable the RequireJS's require, delete the ambient declaration for requirejs's require.

/typings/requirejs/require.d.ts
// Ambient declarations for 'require' and 'define'
declare var requirejs: Require;
// declare var require: Require // Delete or uncomment this
declare var define: RequireDefine;


This client-side config.ts won't work anymore:
requirejs.config({
    paths: {
        "jquery": "/jquery/dist/jquery"
    }
});
 
require(['app']); // this won't work


To make that work, access the client-side require via window object.
requirejs.config({
    paths: {
        "jquery": "/jquery/dist/jquery"
    }
});
 
var need : Require = window["require"];
need(['app']);