Tuesday, February 22, 2022

Guess6 in React - source

The game itself is published here. Here's the full source code. It's surprisingly consise, feel free to study it on your own.
// index.tsx
import React from 'react';
import ReactDOM from 'react-dom';

import App from '@/app';

/**
 * Entry point
 */
class Program {
    
    Main() {

        var app = (
                <App />
        );

        ReactDOM.render(app, document.getElementById('guess6'));
    }
}

new Program().Main();

// App.tsx
import React, { useEffect, useState } from 'react';
import Dictionary from './dictionary';
import Keyboard from './keyboard';
import WordMatch from './wordMatch';

const App = () => {

  const EXPECTEDLENGTH = 6;

  const [words, setWords] = useState<Array<string>>([]);
  const [secretWord, setSecretWord] = useState<string>('');

  function getRandomWord(Dictionary: string[]): string {
    const randomIndex = Math.floor(Math.random() * (Dictionary.length));
    return Dictionary[randomIndex].toUpperCase();
  }

  function restartGame() {
      setWords([]);
      setSecretWord(getRandomWord(Dictionary));
  }
  
  function onWordTyped( newWord: string ) {
    setWords( words => words.concat([newWord]) );   
  }

  function giveUp() {
    if ( secretWord.length == EXPECTEDLENGTH ) {
      setWords( words => words.concat( secretWord ) );
    }
  }

  useEffect( () => {
    restartGame();
  }, []);

  return <>  
    <div>
      <button className='flatButton' onClick={() => restartGame()}>NEW GAME</button>
      <button className='flatButton' onClick={() => giveUp()}>GIVE UP</button>
    </div>
    <h1>Enter {EXPECTEDLENGTH}-letter word</h1>
    <Keyboard dictionary={Dictionary} expectedLength={EXPECTEDLENGTH} onWordTyped={onWordTyped} />
    {words.map( (word, index) => <ordMatch candidate={word} secret={secretWord} key={index} />)}
  </>
};

export default App;

// Keyboard.tsx
import React, { KeyboardEvent, useEffect, useState } from 'react';

const Keyboard = ({dictionary, expectedLength, onWordTyped} : 
    {dictionary: string[] | undefined, expectedLength: number, onWordTyped: (word: string) => void}) => {

    const [message, setMessage] = useState<string>('');
    const [word, setWord]       = useState<string>('');

    const LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    const QWERTY  = "QWERTYUIOP";
    const ASDF    = "ASDFGHJKL";
    const ZXCV    = "ZXCVBNM";

    function appendLetter(letter: string) {
        if ( word.length < expectedLength ) {
            setWord( w => w + letter );
            setMessage('');
        }
    }

    function clearWord() {
        setWord('');
        setMessage('');
    }

    function tryAcceptWord() {
        if ( word.length != expectedLength ) {
            setMessage(`Expected ${expectedLength} characters, got ${word.length} so far`);
            return;
        } 
        
        if ( dictionary !== undefined && dictionary.map( w => w.toUpperCase() ).indexOf( word ) < 0 ) {
            setMessage(`Word ${word} not in dictionary`);
            return;
        }
      
        onWordTyped(word);
        setWord('');
    }

    return <div>
        <div>
            <input className='keyboardInput' value={word} readOnly />
        </div>
        <div className='firstRow'>
            {QWERTY.split('').map( (letter) => <button className='letterButton flatButton'  
              onClick={() => appendLetter(letter)} key={letter}>{letter}</button> )}
        </div>
        <div className='secondRow'>
            {ASDF.split('').map( (letter) => <button className='letterButton flatButton'  
              onClick={() => appendLetter(letter)} key={letter}>{letter}</button> )}
            <button className='flatButton' onClick={() => clearWord()}>DEL</button>
        </div>
        <div className='thirdRow'>
            {ZXCV.split('').map( (letter) => <button className='letterButton flatButton'  
              onClick={() => appendLetter(letter)} key={letter}>{letter}</button> )}
            <button className='flatButton' onClick={() => tryAcceptWord()}>ENTER</button>
        </div>
        <div>{message}</div>
    </div>;
}

export default Keyboard;

// WordMatch.tsx
import React from 'react';

const WordMatch = ({candidate, secret} : {candidate: string, secret: string}) => {

    if ( candidate.length != secret.length ) {
        throw new Error('candidate and secret word must have same length');
    }

    type  letterState = 'USED' | undefined;
    const letterStates: Array<letterState> = Array<letterState>(candidate.length);

    function getLetterClass( index: number ) : string {        
        // match
        if ( secret[index] == candidate[index] ) {
            letterStates[index] = 'USED';
            return 'letter letterMatch';
        }
        // possible
        for ( let i=0; i<secret.length; i++ ) {
            if ( secret[i] == candidate[index] &&
                 letterStates[i] == undefined 
                ) {
                letterStates[i] = 'USED';
                return 'letter letterPossible';
            }
        }
        // none
        return 'letter letterWrong';
    }

    return <div>
        {candidate.split('').map( (letter, index) => 
            <span className={getLetterClass(index)} key={index}>{letter}</span>
        )}
    </div>;
}

export default WordMatch;

// Dictionary.ts
// https://eslforums.com/6-letter-words/

const Dictionary: Array<string> = [
"abacus",
// the rest of the dictionary here
"zoning"
];

export default Dictionary;

Guess6 in React

Saturday, January 8, 2022

WinForms Dependency Injection in .NET6

This entry is motivated by the discussion in one of StackOverflow's questions, the How to use dependency injection in WinForms. A correct answer by Reza Aghaei shows how the container can be created and used, however, one of drawbacks of Reza's answer is that the container is used directly, which makes this approach fall under the Service Locator antipattern.
I've decided then to create a follow up and show one of possible correct solutions. This solution is based on the Local Factory pattern.
We'll start with a form factory
public interface IFormFactory
{
	Form1 CreateForm1();
	Form2 CreateForm2();
}

public class FormFactory : IFormFactory
{
	static IFormFactory _provider;

	public static void SetProvider( IFormFactory provider )
	{
		_provider = provider;
	}

	public Form1 CreateForm1()
	{
		return _provider.CreateForm1();
	}

	public Form2 CreateForm2()
	{
		return _provider.CreateForm2();
	}
}
From now on, this factory is the primary client's interface to creating forms. The client code is no longer supposed to just call
var form1 = new Form1();
No, it's forbidden. Instead, the client should always call
var form1 = new FormFactory().CreateForm1();
(and similarily for other forms).
Note that while the factory is implemented, it doesn't do anything on its own! Instead it delegates the creation to a somehow mysterious provider which has to be injected into the factory. The idea behind this is that the provider will be injected, once, in the Composition Root which is a place in the code, close to the startup, and very high in the application stack so that all dependencies can be resolved there. So, the form factory doesn't need to know what provider will be ultimately injected into it.
This approach has a significant advantage - depending on actual requirements, different providers can be injected, for example you could have a DI-based provider (we'll write it in a moment) for an actual application and a stub provider for unit tests.
Anyway, let's have a form with a dependency:
public partial class Form1 : Form
{
	private IHelloWorldService _service;

	public Form1(IHelloWorldService service)
	{
		InitializeComponent();

		this._service = service;
	}
}
This form depends on a service and the service will be provided by the constructor. If the Form1 needs to create another form, Form2, it does it it a way we already discussed:
var form2 = new FormFactory().CreateForm2();
Things become more complicated, though, when a form needs not only dependant services but also, just some free parameters (strings, ints etc.). Normally, you'd have a constructor
public Form2( string something, int somethingElse ) ...
but now you need something more like
public Form2( ISomeService service1, IAnotherService service2, string something, int somethingElse ) ...
This is something we should really take a look into. Look once again, a real-life form possibly needs
  1. some parameters that are resolved by the container
  2. other parameters that should be provided by the form creator (not known by the container!).
How do we handle that?
To have a complete example, let's then modify the form factory
public interface IFormFactory
{
	Form1 CreateForm1();
	Form2 CreateForm2(string something);
}

public class FormFactory : IFormFactory
{
	static IFormFactory _provider;

	public static void SetProvider( IFormFactory provider )
	{
		_provider = provider;
	}

	public Form1 CreateForm1()
	{
		return _provider.CreateForm1();
	}

	public Form2 CreateForm2(string something)
	{
		return _provider.CreateForm2(something);
	}
}
And let's see how forms are defined
public partial class Form1 : Form
{
	private IHelloWorldService _service;

	public Form1(IHelloWorldService service)
	{
		InitializeComponent();

		this._service = service;
	}

	private void button1_Click( object sender, EventArgs e )
	{
		var form2 = new FormFactory().CreateForm2("foo");
		form2.Show();
	}
}

public partial class Form2 : Form
{
	private IHelloWorldService _service;
	private string _something;

	public Form2(IHelloWorldService service, string something)
	{
		InitializeComponent();

		this._service = service;
		this._something = something;

		this.Text = something;
	}
}
Can you see a pattern here?
  1. whenever a form (e.g. Form1) needs only dependand services, it's creation method in the FormFactory is empty (dependencies will be resolved by the container).
  2. whenever a form (e.g. Form2) needs dependand services and other free parameters, it's creation method in the FormFactory contains a list of arguments corresponding to these free parameters (service dependencies will be resolved by the container)
Now finally to the Composition Root. Let's start with the service
public interface IHelloWorldService
{
	string DoWork();
}

public class HelloWorldServiceImpl : IHelloWorldService
{
	public string DoWork()
	{
		return "hello world service::do work";
	}
}
Note that while the interface is supposed to be somewhere down in the stack (to be recognized by everyone), the implementation is free to be provided anywhere (forms don't need reference to the implementation!). Then, follows the starting code where the form factory is finally provided and the container is set up
internal static class Program
{
	[STAThread]
	static void Main()
	{
		var formFactory = CompositionRoot();

		ApplicationConfiguration.Initialize();
		Application.Run(formFactory.CreateForm1());
	}

	static IHostBuilder CreateHostBuilder()
	{
		return Host.CreateDefaultBuilder()
			.ConfigureServices((context, services) => {
				services.AddTransient<IHelloWorldService, HelloWorldServiceImpl>();
				services.AddTransient<Form1>();
				services.AddTransient<Func<string,Form2>>(
					container =>
						something =>
						{
							var helloWorldService = 
                                container.GetRequiredService<IHelloWorldService>();
							return new Form2(helloWorldService, something);
						});
			});
	}

	static IFormFactory CompositionRoot()
	{
		// host
		var hostBuilder = CreateHostBuilder();
		var host = hostBuilder.Build();

		// container
		var serviceProvider = host.Services;

		// form factory
		var formFactory = new FormFactoryImpl(serviceProvider);
		FormFactory.SetProvider(formFactory);

		return formFactory;
	}
}

public class FormFactoryImpl : IFormFactory
{
	private IServiceProvider _serviceProvider;

	public FormFactoryImpl(IServiceProvider serviceProvider)
	{
		this._serviceProvider = serviceProvider;
	}

	public Form1 CreateForm1()
	{
		return _serviceProvider.GetRequiredService<Form1>();
	}

	public Form2 CreateForm2(string something)
	{
		var _form2Factory = _serviceProvider.GetRequiredService<Func<string, Form2>>();
		return _form2Factory( something );
	}
}
First note how the container is created with Host.CreateDefaultBuilder, an easy task. Then note how services are registered and how forms are registered among other services.
This is straightforward for forms that don't have any dependencies, it's just
services.AddTransient<Form1>();
However, if a form needs both services and free parameters, it's registered as ... form creation function, a Func of any free parameters that returns actual form. Take a look at this
services.AddTransient<Func<string,Form2>>(
	container =>
		something =>
		{
			var helloWorldService = container.GetRequiredService<IHelloWorldService>();
			return new Form2(helloWorldService, something);
		});
That's clever. We register a form factory function using one of registration mechanisms that itself uses a factory function (yes, a factory that uses another factory, a Factception. Feel free to take a short break if you feel lost here). Our registered function, the Func<string, Form2> has a single parameter, the something (that corresponds to the free parameter of the form constructor) but its other dependencies are resolved ... by the container (which is what we wanted).
This is why the actual form factory needs to pay attention of what it resolves. A simple form is resolved as follows
return _serviceProvider.GetRequiredService<Form1>();
where the other is resolved in two steps. We first resolve the factory function and then use the creation's method parameter to feed it to the function:
var _form2Factory = _serviceProvider.GetRequiredService<Func<string, Form2>>();
return _form2Factory( something );
And, that's it. Whenever a form is created, is either
new FormFactory().CreateForm1();
for "simple" forms (with service dependencies only) or just
new FormFactory().CreateForm2("foo");
for forms that need both service dependncies and other free parameters.
Happy coding. A simple excercise for you is to provide a different form factory, a factory that doesn't use a container but composes dependencies directly, for example for unit tests.

.NET 6 WebAPI with JWT bearer token authentication minimal example

The console client:
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

var plainTextSecurityKey = "This is secret";

var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(plainTextSecurityKey));
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256Signature);

var claimsIdentity = 
    new ClaimsIdentity(new List<Claim>()
    {
        new Claim(JwtRegisteredClaimNames.Name, "username1")
    });

var securityTokenDescriptor = new SecurityTokenDescriptor()
{
    Subject = claimsIdentity,
    SigningCredentials = signingCredentials
};

var tokenHandler          = new JwtSecurityTokenHandler();
var plainToken            = tokenHandler.CreateToken(securityTokenDescriptor);
var signedAndEncodedToken = tokenHandler.WriteToken(plainToken);

Console.WriteLine(plainToken);
Console.WriteLine(signedAndEncodedToken);

HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {signedAndEncodedToken}");

var res = await client.GetAsync("http://localhost:5242/api/Example");
if (res.StatusCode == System.Net.HttpStatusCode.OK)
{
    var result = await res.Content.ReadAsStringAsync();
    Console.WriteLine(result);
}
else
{
    Console.WriteLine($"Status: {res.StatusCode}");
}

Console.ReadLine();
The server:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

builder.Services
    .AddAuthentication()
    .AddJwtBearer(cfg =>
    {
        var plainTextSecurityKey = "This is secret";

        var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(plainTextSecurityKey));
        var signingCredentials = new SigningCredentials(signingKey,SecurityAlgorithms.HmacSha256Signature);

        cfg.RequireHttpsMetadata = false;
        cfg.TokenValidationParameters = new TokenValidationParameters()
        {            
            ValidateAudience = false,
            ValidateIssuer   = false,
            IssuerSigningKey = signingKey            
        };

        cfg.Events = new JwtBearerEvents()
        {
            OnAuthenticationFailed = async context =>
            {
                var ex = context.Exception;
                Console.WriteLine(ex.Message);
            }
        };
    });

builder.Services.AddControllers();

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[ApiController]
[Route("api/[controller]")]
public class ExampleController : ControllerBase
{

	public ExampleController()
	{
	}

	[HttpGet]
	public IActionResult Get()
	{
		return this.Ok("webapi service. authenticated as " + this.User.Identity.Name);
	}
}
I love .NET6 way of providing concise examples.

Friday, October 22, 2021

Visual Studio Code + TypeScript + React - how to start in 10 minutes (fall 2021 tutorial)

Just a short tutorial on how to start your adventure with TypeScript + React with Visual Studio Code. Without further ado:
Install node.js. Install Visual Studio Code.
Create an empty folder. Go to it and run VSC from there from the OS shell
code .
When in VSC, open the terminal and work from the terminal rather than the OS shell
npm init -y
npm install webpack webpack-cli
npm install typescript ts-loader
npm install react react-dom
npm install @types/react @types/react-dom
This will create package.json and install your dependencies.
At the root of your app create two files, tsconfig.json

{
    "compilerOptions": {
        "allowJs": false,
        "baseUrl": "./",
        "jsx": "react",
        "declaration": false,
        "esModuleInterop": true,
        "lib": ["ES6", "DOM"],
        "module": "commonjs",
        "moduleResolution": "node",
        "noImplicitAny": true,
        "outDir": "./dist/",
        "paths": {
        "@/*": ["src/*"]
        },
        "sourceMap": true,
        "target": "ES6"
    }
}
and webpack.config.js
    const path = require('path');
    const TerserPlugin = require("terser-webpack-plugin");

    module.exports = {
    //mode: 'production',
    mode: 'development',
    target: ['web','es6'],
    entry: {
        'index': './src/index.tsx'
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js'
    },
    devtool: 'source-map',
    module: {
        rules: [{
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
        }, ],
    },
    externals: {
        // Use external version of React
        //'react': 'React',
        //'react-dom': 'ReactDOM'
    },
    resolve: {
        // https://getfrontend.tips/shorten-import-paths-in-webpack/
        alias: {
        // Assume that the `src` folder is located at the root folder
        '@': path.join(__dirname, 'src'),
        },
        extensions: ['.tsx', '.ts', '.js'],
    },
    optimization: {
        minimize: false, // true/false
        minimizer: [
        new TerserPlugin({
            extractComments: false,
            terserOptions: {
            format: {
                comments: false,
            },
            },
        })
        ],
    },
    };
There are few options in the webpack's configuration file that can be further changed, pay close attention to mode and minimize.
Now create two empty folders, src and dist, the first is where your source code goes, the second is where webpack will store its output.
Now create two TypeScript files. First is your entry point, index.tsx
import React from 'react';
import ReactDOM from 'react-dom';

import App from '@/app';

/**
 * Entry point
 */
class Program {
    
    Main() {

        var app = (
                <App />
        );

        ReactDOM.render(app, document.getElementById('root'));
    }
}

new Program().Main();
or using the new API that replaces ReactDOM.render
import React from 'react';
import { createRoot } from 'react-dom/client';

import App from '@/app';

/**
 * Entry point
 */
class Program {
    
    Main() {

        const app = (
            <React.StrictMode>
                <App />
            </React.StrictMode>
        );            

        const root = createRoot(document.getElementById('root'));

        root.render( app );    
    }
}

new Program().Main();
Second is your app's component, app.tsx
import React from 'react';

const App = () => {

  return <>  
    Hello world from React & Typescript
  </>
};

export default App;
The general rule here is that
  • if a module is a pure TypeScript, your file can have *.ts extension
  • if a module should contain JSX code, your file should have *.tsx extension
Modules are imported/exported between both without any restrictions.
Now add the last file, app.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script defer src="/dist/index.js"></script>
    <style>
    * , *:before, *:after { 
         box-sizing:border-box; 
    }
    html {
        background-color: rgb(234, 238, 243);
    }

    </style>
</head>
<body>    
    <div id="root"></div>
</body>
</html>
What you should have right now is
Now just invoke
webpack
(this assumes webpack is available globally, if not, npm-install both webpack and webpack-cli as global modules:
npm install -g webpack webpack-cli
) and the application will be built and the output, dist/index.js will be created. This is a single file bundle and it can be further optimized by switching mode to production in the config, as well as turning on minimization.
To test the app, install and run a simple HTTP server, e.g. live-server
npm install -g live-server
live-server
and add a launch configuration in VSC
{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "pwa-chrome",
            "request": "launch",
            "name": "Launch Chrome against localhost",
            "url": "http://localhost:8080/app.html",
            "webRoot": "${workspaceFolder}"
        }
    ]
}
Congratulations, you can start your app with F5 from within VSC, put breakpoints in your TypeScript and debug your code and continue work on your first great app. Happy coding!

Wednesday, October 20, 2021

IndexedDB can possibly fail on FireFox

A couple of minutes and a good coffee spent on an issue. The idb, a wrapper over IndexedDB was failing silently. An isolated demo was luckily showing something, it was A mutation operation was attempted on a database that did not allow mutations in the console.
What Google tells about this issue is that it's related to working in private mode. Which was definitely not my case. However, another very old discussion mentions a setting that turns off history. And yes, the setting is there, in Firefox. Go to Options, then Security and Privacy and then there's a switch that either turns on or turns off history tracking. For some reason it was turned off in my FF.
And yes, turning it on brings IndexedDB back to life.

Friday, October 1, 2021

tiny-totp.js, a tiny TOTP javascript implementation

Just published the tiny-totp.js code on Github. It's super tiny Javascript RFC6328 implementation. If you wonder what's that, it's the Timed One-Time Passwords specs that is widely used to implement two-factor authentication over web.

What this tiny library does is it computes one time passwords, given the master password. It's basically the same computation Google Authenticator or Microsoft Authenticator do, given the master password. It means that you can either implement your own client or even your own server side authentication that would be compatible with existing authenticators (including the two).

What's interesting here is that the implementation is really, really tiny and has 0 dependencies. Usually, people implement TOTP using two dependencies:

  • to handle the base32 encoding (master keys are usually provided in base32 encoding
  • to handle the hmacsha1 to calculate actual codes
This code avoids both dependencies - there's a tiny function to handle base32 and platform specific crypto provider is used to handle hmacsha1 (the node's crypto module when run against node or window.subtlecrypto when run in a browser).