Frozen global object

If your app uses global object as a config, you should make sure, that this object is truly readonly. So that an attacker can not modify it in dev console.

This is how to do it.

// example of frozen global object
// freeze the config object properties
const config = Object.freeze({
  httpApi: 'http://127.0.0.1:20003/v1',
  wsApi: 'ws://127.0.0.1:3000',
  enableReduxDevTools: true,
  minLegalAge: 18 // in years
});

// make sure that the config object can not be replaced
Object.defineProperty(window, "config", { 
  value: config,
  configurable: false,
  writable: false 
});

PS: I assume that “window” is sufficient as a global object. If your app runs in different environment then browser, then you will need to modify the code accordingly.

Custom command line shortcuts with Doskey

I’ve learned this nice trick from Petr Horáček aka Besir while working on Nakamotox. So the credit goes to him.

You can define custom commands via doskey (only on Windows) and then invoke them via command line. It is quite powerfull, because you can define alias for command with predefined attributes, so it save you lot of repetitive typing.

Steps:

  1. Open any text editor and define your shortcut commands
@echo off
REM example shortcut for docker-compose
doskey dcdu=docker-compose -f docker-compose-dev.yml up
doskey dcdd=docker-compose -f docker-compose-dev.yml down
  1. Add path to file with commands to registry:
  2. open regedit
  3. go to \HKEY_CURRENT_USER\Software\Microsoft\Command Processor
  4. define AutoRun
  5. enter path to file with doskey commands

Email validator for Angular

Angular has built in email validator, but it is very benevolent one. It allows for single letter domains, therefore email a@b is considered valid. Their motivation is that when used in intranet it can be perfectly valid email, because you can have custom domain names. But it does not make much sense in the broader internet. I would prefer if the built in validator would be stricter, or that there would be two validators, something like emailValidator and intranetEmailValidator.

Here is my solution, hope it will help someone

import {FormControl} from '@angular/forms';

// copied from http://emailregex.com/
export const emailRegexp = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

/**
 *
 * @param controlName
 * @returns {(control:FormControl)=>({validateEmail: boolean}|null)}
 */
export function validateEmail(controlName: string) {
  return (control: FormControl) => {
    const value = control.value;

    if (value != "" && (value.length <= 5 || !emailRegexp.test(value))) {
      return { "incorrectMailFormat": true };
    }

    return null;
  };
}

Example usage in component

ngOnInit() {
    this.model.email = this.currentEmail;

    this.changeEmailForm = this.formBuilder.group({
      email: [this.model.email, [
        Validators.required,
        validateEmail('email')
      ]]
    });
  }

Print document from cross-origin iframe

When you need to show content from some other site, such as Google Docs, you can easily embed it inside an iframe. Google Docs even generates it for you. But what if you need to print that document via some button click? You can not do that, because the cross-origin policy does not allow it.

You have basically two options.

A) Create some proxy function on your server. But that is only available when you actually have a server and not just some hosted WordPress.

B) Create proxy iframe, which you are actually allowed to print, because there is no cross-origin involved. Then load the desired iframe inside the proxy iframe. Attach onload=”print()” on the target iframe, so the print starts automatically once it is loaded.

Working solution is below, have a nice day 🙂 Let me know, if it helped you.

Comments and suggestions for improvements are welcome. Hints: The iframe is not destroyed after print() is invoked, which might lead to memory leaks. Second issue is that you might need to calculate height of the iframe content, so that it is correctly printed. But if you can safely guess it, then you are fine.

  /**
   * Load iframe from cross-origin via proxy iframe
   * and then invokes the print dialog.
   * It is not possible to call window.print() on the target iframe directly
   * because of cross-origin policy.
   * 
   * Downside is that the iframe stays loaded. 
   */
  function printIframe(url) {
    var proxyIframe = document.createElement('iframe');
    var body = document.getElementsByTagName('body')[0];
    body.appendChild(proxyIframe);
    proxyIframe.style.width = '100%';
    proxyIframe.style.height = '100%';
    proxyIframe.style.display = 'none';

    var contentWindow = proxyIframe.contentWindow;
    contentWindow.document.open();
    // Set dimensions according to your needs.
    // You may need to calculate the dynamically after the content has loaded
    contentWindow.document.write('<iframe src="' + url + '" onload="print();" width="1000" height="1800" frameborder="0" marginheight="0" marginwidth="0">');
    contentWindow.document.close();
  }

Workaround for ExpressionChangedAfterItHasBeenCheckedError in async pipe

Imagine that you have this piece of code, where userInfo$ is Observable and it value is not yet emitted.

<app-change-email [currentEmail]="(userInfo$ | async).user.email"></app-change-email>

The code works, but it will report error ExpressionChangedAfterItHasBeenCheckedError to the console (only in dev mode). That is because the component has received the value, but the value has changed later. Angular does not like it. I googled for solutions, but could not use them, or it would be too complicated in given setup.

Workaround is easy

<ng-template #loading>
    <div id="loading"></div>
</ng-template>

<ng-container *ngIf="userInfo$ | async; let userInfoState; else loading">
    <app-change-email [currentEmail]="userInfoState.user.email"></app-change-email>
</ng-container>

Angular custom event bubbling

Custom events in Angular by default do not bubble up. It is because they are not really events, they are based on EventEmitter, which is similar to pub/sub mechanism. You can read lengthy discussion about it on Angular’s Github. Unfortunately the examples provided by Angular team often mention $event as named parameter in the event listener, which only adds to the confusion. There are valid use cases when you really need the custom events to bubble up.

Luckily, you can still create DOM-native custom events, and they will bubble up as expected.

import { Component, OnInit, Input, ElementRef, Renderer } from '@angular/core';

@Component({
  selector: 'app-bubble',
  templateUrl: './bubble.component.html',
  styleUrls: ['./bubble.component.scss']
})
export class BubbleComponent implements OnInit {

  /**
   * Optional.
   * Defaults to 'myCustomEvent'
   */
  @Input()
  customEventName: string;

  private _defaultEventName: string = 'myCustomEvent';

  /**
   * Invokes DOM-native custom event, which bubbles up.
   * That solves the issue with EventEmmiter-based events, which are not really events and do not bubble up.
   */
  emitEvent() {
    const eventName = this.customEventName || this._defaultEventName;

    this.renderer.invokeElementMethod(
      this.elRef.nativeElement,
      'dispatchEvent',
      [new CustomEvent(eventName, {bubbles: true})]
    );
  }

  constructor(private elRef: ElementRef, private renderer: Renderer) { }

  ngOnInit() {
  }

}

And the html template

<button (click)="emitEvent()">Emit custom event which bubbles up</button>

Then somewhere up the DOM tree, you listen for the event like this

<app-my-listener (myCustomEvent)="doSomething($event)"></app-my-listener>

More reading:

https://www.radzen.com/blog/angular-event-bubbling/

Node_modules versus Docker

I’ve encountered strange error lately. Whenever I tried  to run npm install in my project’s folder, it failed. The error says something about not being able to unlink folder. The interesting think was that it only happened under certain circumstances.

The reason for this was the when I started docker compose up to run my project in Docker, it created some lock on the node_modules folder. And shutting down the container or even the whole Docker did not help. The lock stayed there.

The only way to workaround this (at least which I am aware of) is to restart the whole machine and then run npm install again. Notice that Docker for Windows starts when you log in, but the lock was created only after I started docker compose.

If there is someone who knows a solution, I would be glad.

Google’s ReCaptcha not appearing?

Recently I had a weird problem that Recaptcha has not rendered at all in most of the cases. It seemed random however, but most of the cases it failed. Later I’ve figured out, that it was caused by some network race conditions. The solution was then quite straightforwad: manual initialization of ReCaptcha after the script has been loaded.

I’ve wrapped the whole solution as Angular directive, so everything is in one place. Feel free to use it

.directive('recaptcha', ['$window',
    function ($window) {

    //
    // The actual directive definition object
    //
    return {
        restrict: 'AE',
        scope: {
            sitekey: '='
        },

        template: '<script async defer src="https://www.google.com/recaptcha/api.js?onload=onloadCallbackReCaptcha&render=explicit"></script><div id="g-recaptcha-manual"></div>',

        link: function (scope, element, attrs) {
            $window.onloadCallbackReCaptcha = function onloadCallbackReCaptcha() {
                $window.grecaptcha.render('g-recaptcha-manual', { 'sitekey': scope.sitekey });
            }
        }
    };
}]);

Example of usage

<recaptcha sitekey="'@Html.Raw(ConfigurationProvider.Instance.GetSetting("CaptchaSiteKey"))'"></recaptcha>

ES6 generators and async/await

Motivation for this blogpost was my initial ignorance regarding the upcoming ES6 and the generator function. Around christmas 2015 I was looking for a new job, and during one of the assigned test-jobs I had to use generator functions, the .co library, two different databases (one SQL and the other NoSQL)  and node.js. I failed, it was too much of new things to learn at once. But it planted the idea to really learn it and prove that I’ve mastered it. Hence this blog post 🙂 But there are some many new things coming to javascript land, that I still feel pretty much like a beginner 🙂

What really confused me, was the yield expression and the injection of variables. So, now that I understand it, I want to explain it 🙂

I have also created a git repository with sample code. Feel free to fork it and experiment.

So what is a generator function and why to use it?

In short: it is a function which execution can be paused at the yield expression. When the invokend function yields, it returns the control of execution to the UI thread, so it does not block. It can also act as a kind of “dependency-injection” (more on this later). The other advantage is that it allows to write asynchronous code which looks like synchronous. The obvious advantage is that it avoids the callback hell, nested callback etc. The code is much cleaner and easier to read and reason about.

Under the hood

The generator iterator is implemented as a state-machine provided either by JS runtime, or if not then by the Regenerator . It is a transpiler from ES6 to today’s javascript, so you can write future code today. If you are from the C# world you might know that the async/await is implemented in IL pretty much the same way as when using Regenerator. It also uses state machine, and is explained in depth in this Pluralsight course.

Explaining how state machines work is beyond the scope of this article (and I do not know enough about them yet).

Continue reading “ES6 generators and async/await”

Poznámky z Wisephora Live – 28.6.2016

Konference Wisephora byla skvělá, takže když jsem se dozvěděl, že bude mít neformální pokračování, věděl jsem, že budu chtít jít. A stálo to za to 🙂 Sešlo se nás překvapivě málo, asi 12-15 lidí, ale odnesl jsem si spoustu zajímavých myšlenek a podnětů. O tom je vlastně tento článek – shrnutí útržkovitých myšlenek.

Prvním hostem byl Petr Beneš, který dříve pracoval v České spořitelně, GE Money Bank a Accenture, nyní je poprvé na volné noze. A je to skvělý řečník.

——————————–

V současné době dochází k výrazné změně obchodních modelů, spousta obsahu je zdarma a firmy jsou nuceny vydělávat na něčem jiném. Firmy, které nejsou schopny se adaptovat, zaniknou. Dobrým příkladem je třeba krach amerického knihkupectví Borders. Ve své době to byl obrovský řetězec kamenných obchodů, který však podcenil nakupování přes internet (přesměrovával zákazníky na Amazon), příliš pozdě se pustil do prodeje e-knih. Vsadil na to, že lidé vždycky budou číst hlavně papírové knihy.

Konkurence dnes přichází z nečekaných úhlů. Výrobci telefonů se pouští do automobilového průmyslu (viz Apple nebo čínský LeEco), automobilky se mění v softwarové společnosti (viz Ford), hardwarové společnosti se mění v data analytics společnosti, tím jak sbírají data o svých uživatelích. Mnoho firem transformaci nezvládne, například Kodak, který jako první přišel s konceptem digitální fotografie, ale rozhodl se nekanibalizovat svůj prosperující business s kinofilmy. Tak to za něj udělali jiní. Facebook rozdává novým zaměstnancům příručku, kde je mimo jiné skvělé moto: If you don’t find a way to kill Facebook, someone else will.

facebook

Firmy, které naopak transformaci zvládly, jsou např. IBM nebo Accenture, které několikrát překopaly svůj business model.

Organizační struktura a firemní kultura jsou dvě různé věci. Můžete mít firmu s pevně danou hierarchií a skvělou kulturou a dobrými vztahy, nebo firmu s pevnou hierarchií, kde lidé nechtějí pracovat. Vybudovat firemní kulturu je těžké (mimochodem o tom bude příští TopMonks Caffé s Tomášem Hrivnákem).

Mohou se udržet “firmy pro dobro lidstva”, kterým nejde o zisk? (Otázka z panelové diskuze … nedošli jsme k žádnému závěru :))

Ve společnosti obecně je velká neflexibilita a setrvačnost. Například školní prázdniny původně vznikly jako kompromis mezi zájmy rolníků a záměrem Marie Terezie, když zaváděla povinnou školní docházku. Rodiče odmítali posílat děti v létě do školy, aby mohly pomáhat doma při žních, kdy bylo nejvíce práce. Dnes žně “nejsou”, ale prázdniny zůstaly. A s nimi v základě i skladba školních předmětů. Dalším příkladem je letní a zimní čas. Kolik dalších věcí jede čistě ze setrvačnosti a připadají nám samozřejmé?

Čím to, že v Izraeli je víc startupů než Evropě? V počtu startupů na hlavu jsou absolutně první. Viz kniha Startup Nation.

Average is over. Nové firmy vytvářejí svůj vlastní segment trhu, který dříve neexistoval. Objevují se giganti, kteří jsou schopni obsloužit celý trh, průměrní si již neškrtnou.

V Číně jsou dnes elitní školky (!), které si vybírají rodiče, jejichž děti k nim nastoupí. Tedy: rodiče musí projít přijímacím řízením školky, aby jejich dítě mohlo do školky nastoupit. Po elitní školce následuje elitní základka a pak elitní univerzita. Proč? Protože průměrní si už neškrtnou. To je obrovský tlak na děti.

Těším se na další Wisephora Live Meetup 🙂 Potkáme se tam?