Arrêtez avec vos dates "user-friendly"

icon Tags de l'article :

Juin 01, 2015
Un petit article coup de gueule, une fois n'est pas coutume, rapport à une habitude de beaucoup de développeurs que je DETESTE : afficher des dates "user friendly".
Par exemple : "Il y a trois jours".

Franchement, vous considérez que vos utilisateurs sont des chèvres et ne savent pas faire la différence entre deux dates ?

Non, perso je préfère cent fois lire "Le 29/05/2015" plutôt que "il y a deux jours".

Je veux une date, une heure, je veux savoir à quel moment l'évènement s'est passé. Je ne veux pas avoir à aller, en permanence, mettre ma souris sur ta PUTAIN de date "simplifiée" pour savoir quelle est la véritable date.

Sans compter les ratés. Là j'ai un beau logiciel qui m'indique "il y a deux jours" pour un truc qui date du 29/05.

Si vous considérez que les gens sont débiles à ce point là, peut-être devriez-vous arrêter de développer pour eux.

A bon entendeur...

Relax your eyes

icon Tags de l'article : , ,

Avril 16, 2015
Hello les gens,

Comme beaucoup de développeurs, j'ai la mauvaise habitude de passer plusieurs heures sur le PC sans faire de pauses.

Le problème, c'est que mes yeux n'aiment vraiment pas, et qu'en plus les années passent, en plus ma myopie s'amplifie (et je suis sûr et certain que c'est à cause de mes trop longues sessions devant le PC).

Du coup, afin de me forcer à faire des pauses, j'ai décidé de développer un tout petit logiciel qui verrouille ma session 3 minutes toutes les heures. Ca peut sembler radical, mais c'est ce que j'ai trouvé de mieux. J'avais testé EyeDefender, plus complet, mais trop gentil (on appuie sur Echap et hop, la pause est terminée).

Le code source est disponible sur GitHub.

Et le zip est disponible ici.

L'application, ultra simpliste (pour le moment), ressemble à ça :



3 minutes avant la pause, elle affichera une infobulle d'alerte :



Et si vous êtes vraiment sur une tâche critique, vous pouvez décaler la pause de 3 minutes (mais une seule fois !) :



Enfin, vous pouvez la lancer avec l'argument -autostart pour qu'elle se lance automatiquement, ce qui peut être pratique si, comme moi, vous voulez la mettre au démarrage.

Bon dev et bonne journée à tous !

Afficher des bulles de notification dans la barre des tâches en C#

icon Tags de l'article : , ,

Avril 16, 2015
Hello,

Un besoin qui revient souvent en C#, pour des appli Winforms simples : pouvoir afficher des notifications dans la barre des tâches en C#.

Pour cela, j'utilise toujours la même méthode : un notifyIcon et l'appel à la méthode ShowBalloonTip :

this.notifyIconFormMain.Visible = true;
this.notifyIconFormMain.BalloonTipIcon = ToolTipIcon.Info;
this.notifyIconFormMain.BalloonTipTitle = "Relax your eyes";
this.notifyIconFormMain.BalloonTipText = string.Format("You will have to relax your eyes in {0} minutes.", minutes);
this.notifyIconFormMain.ShowBalloonTip(4); // 4 = le nombre de secondes d'affichage du message

Et voilà, une bulle apparaitra dans le coin de votre écran pour afficher votre message pendant 4 secondes !



Bon dev à tous !

Verrouiller une session en C#

icon Tags de l'article : , , ,

Avril 15, 2015
Hello,

Juste un mini article : comment verrouiller une session en C#.

La réponse est simple, à l'aide de ce petit morceau de code qui utilise user32.dll :

private const int WmSyscommand = 0x0112;
private const int ScMonitorpower = 0xF170;
private const int HwndBroadcast = 0xFFFF;
private const int ShutOffDisplay = 2;
[DllImport("user32.dll")]
private static extern void LockWorkStation();
[DllImport("user32.dll", SetLastError = true)]
private static extern bool PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

Voilà, vous n'avez plus qu'à appeler la jolie méthode LockWorkStation qui s'occupera de verrouiller la session utilisateur ! Pensez juste à faire attention quand vous testez, car si vous mettez ça dans une boucle vous risquez d'être bloqué... [oui, ça sent le vécu]

Bon dev!

source

Une classe de base pour manipuler SQLite facilement en C#

icon Tags de l'article : ,

Avril 03, 2015
Hello à tous,

Aujourd'hui je vais vous parler de SQLite. Lors d'un projet récent, j'ai eu à manipuler une BDD SQLite en C#. Pour cela j'ai créé une classe qui peut vous intéresser.

La première étape, pour manipuler du SQLite, est d'installer le package Nuget SQLite (et ses prérequis).

Ensuite, j'ai créé cette classe abstraite :

using System;
using System.Collections.Generic;
using System.Data.SQLite;

public abstract class BaseDA<T>
{
	public string ConnectionString { get; set; }

	public BaseDA(string connectionString)
	{
		this.ConnectionString = connectionString;
	}

	protected T GetUniqueItem(string sql, Func<SQLiteDataReader, T> mappingMethod)
	{
		var connection = new SQLiteConnection(this.ConnectionString);

		try
		{
			var command = new SQLiteCommand(sql, connection);

			var reader = command.ExecuteReader();

			if (reader.Read())
			{
				return mappingMethod(reader);
			}
		}
		finally
		{
			connection.Close();
		}

		return default(T);
	}

	protected IEnumerable<T> GetItems(string sql, Func<SQLiteDataReader, T> mappingMethod)
	{
		var connection = new SQLiteConnection(this.ConnectionString);

		try
		{
			var command = new SQLiteCommand(sql, connection);

			var reader = command.ExecuteReader();

			var result = new List<T>();

			while (reader.Read())
			{
				result.Add(mappingMethod(reader));
			}

			return result;
		}
		finally
		{
			connection.Close();
		}
	}

	protected int ExecuteNonQuery(string sql)
	{
		var connection = new SQLiteConnection(this.ConnectionString);

		try
		{
			var command = new SQLiteCommand(sql, connection);

			return command.ExecuteNonQuery();
		}
		finally
		{
			connection.Close();
		}
	}
}

Comme vous le voyez, cette classe contient 3 méthodes basiques me permettant de requêter facilement ma BDD SQLite.

Je n'ai plus qu'à créer une classe qui hérite de cette classe abstraite, pour, par exemple, gérer mes utilisateurs :

using ApiManager.BusinessEntities;
using System.Collections.Generic;
using System.Data.SQLite;

public class UserDA : BaseDA<UserBE>
{
	public UserDA(string connectionString) : base(connectionString)
	{
	}

	public UserBE GetUserByLogin(string login)
	{
		var sql = string.Format("SELECT * FROM User WHERE Login='{0}'", login);

		return GetUniqueItem(sql, this.MapUser);
	}

	public IEnumerable<UserBE> GetUsers()
	{
		var sql = "SELECT * FROM User";

		return (IEnumerable<UserBE>)GetItems(sql, this.MapUser);
	}

	public bool AddUser(UserBE user)
	{
		var sql = string.Format("INSERT INTO User VALUES ('{0}', '{1}', {2})", user.Login, user.Password, user.IsAdmin ? "1" : "0");

		return ExecuteNonQuery(sql) == 1;
	}

	public bool DeleteUser(int idUser)
	{
		var sql = string.Format("DELETE FROM User WHERE Id = {0}", idUser);

		return ExecuteNonQuery(sql) == 1;
	}

	private UserBE MapUser(SQLiteDataReader reader)
	{
		return new UserBE()
		{
			Id = (int)reader["Id"],
			Login = reader["Login"].ToString(),
			IsAdmin = (bool)reader["IsAdmin"],
			Password = reader["Password"].ToString()
		};
	}
}

Voilà, en résumé :
  • Ma classe mère, BaseDA, contient 3 méthodes pour requêter la BDD à partir de la connection string passée dans le constructeur.
  • Ensuite on crée une classe qui hérite de BaseDA et qui appelera le constructeur de cette dernière.
  • Enfin, on n'a plus qu'à appeler les méthodes de la classe mère avec le SQL désiré (et la méthode de mapping reader => objet dans le cas des méthodes de Get)

Voilà, on ne sait jamais, ça vous servira peut-être un jour !

Bonne journée à tous... Et bon weekend !

Comment stocker ses mots de passe en .Net

icon Tags de l'article : , ,

Novembre 24, 2014
Il existe de nombreuses façons de stocker les mots de passe pour une application ou un site web. La triste nouvelle, c'est que la majorité des sites et des applications n'utilisent pas les bonnes.

Aujourd'hui nous allons voir comment bien faire les choses.

Déjà, voici les différentes façons de faire, de la plus ridicule à la plus paranoïaque :

  • Niveau 0 : tout en clair. Rien de bien compliqué, aucune sécurité, la moindre fuite de données et on doit demander à nos utilisateurs de changer de mots de passe... Vraiment pas top pour l'image. Sécurité : 0%

  • Niveau 1 : mots de passe hashés avec une clef en dur. Pourquoi pas, sauf que... ça ne sert à rien. Le hacker n'aura qu'à générer des rainbow tables à partir de votre clef, et il aura les correspondances en clair pour tous les mots de passe hashés en base. Sécurité : 1%

  • Niveau 2 : on hashe les mots de passe avec un sel, généré aléatoirement pour chaque utilisateur. Un petit peu mieux. Seul bémol : il suffit de régénérer des Rainbow Tables, une par utilisateur, et ... on a tous les mots de passe. Sécurité : 5%

  • Niveau 3 : on hashe les mots de passe avec un sel, généré aléatoirement pour chaque utilisateur, à l'aide d'un algorithme lent : BlowFish. Ici on corrige le principal problème du niveau 2 : générer des Rainbow Tables pour chaque utilisateur peut prendre des jours, voire des mois... Sécurité : 80%

  • Niveau 4 : on utilise un module physique pour hasher les mots de passe. Si quelqu'un essaye de le déplacer ou d'y accéder, il effacera automatiquement toutes les données. Vous l'avez compris, il s'agit du mode paranoïaque ! Sécurité : 99%

Vous l'aurez compris, on va surtout s'intéresser au niveau 3, facilement réalisable et ne demandant pas, lui, d'investissements financiers. La clef repose sur le fait d'avoir un sel généré unique par utilisateur, et d'utiliser l'algorithme lent BlowFish. A l'échelle d'un site web, le temps de hash de l'algorithme est court. Mais lorsqu'on fait du bruteforce, le temps pour générer un dictionnaire entier de mots de passe est gigantesque !

La mise en place est plutôt simple :

Il faut d'abord créer deux entrées dans notre base, une pour le mot de passe hashé, et une pour le sel. Il ne faut jamais stocker ni déplacer le mot de passe non hashé. Si vous voulez bien faire les choses, utilisez HTTPS et stockez le sel ailleurs.



Ensuite, il faut ajouter BCrypt.Net à notre projet (via NuGet) :



Cette implémentation de l'algorithme BlowFish offre 2 méthodes : GenerateSalt et HashPassword, à utiliser comme suit :



Maintenant vous n'avez plus qu'à implémenter la bonne logique dans votre code :
  • Lorsque l'utilisateur s'inscrit, on génère et stocke un salt aléatoire pour lui, puis on se sert de ce salt pour hasher son mot de passe.
  • Lorsqu'il se connecte, on récupère le salt, et on hashe le mot de passe saisi à l'aide du salt pour ensuite comparer les deux hashs générés.
  • Lorsqu'il a perdu son mot de passe, on génère un mot de passe et un salt aléatoires, pour ensuite lui envoyer un mail avec son nouveau mot de passe.

Voilà, j'espère que ce petit article vous a plu,

Bonne soirée à tous !

Certificat IISExpress manquant

icon Tags de l'article :

Novembre 24, 2014
Un petit bug sur lequel je suis tombé il y a quelques jours, alors que je voulais lancer en local un projet Azure :

Windows Azure Tools: Error: IISExpress Development certificate is not installed.

Pour le résoudre, on m'avait suggéré plusieurs choses :
- réinstaller le SDK, aucun effet
- vérifier les prérequis dans les composants Windows (étape 11 ici), OK
- vérifier qu'on a bien la dernière version d'IISExpress d'installée, OK

Mais en allant dans les certificats (mmc / certificats) je me suis rendu compte que je n'avais tout simplement pas de certificat "localhost" pour IISExpress.



A son installation, IISExpress est censé installer un certificat localhost pour l'utiliser par la suite... Pourtant absent ici.

La solution ? Réparer IISExpress.



Tout simplement !

Bon dev à tous !

Partager l'accès à sa base de données SQL Server avec quelqu'un

icon Tags de l'article : ,

Septembre 17, 2014
Un truc qui a priori parait simple, mais qui au final ne l'est pas tant que ça...

Voyons comment faire.

Déjà il faut ouvrir son SQL Server Management Studio, aller dans les propriétés du serveur, l'onglet Connections, et vérifier que l'option Allow remote connections to this server est bien cochée.



Ensuite il faut ouvrir Sql Server Configuration Manager, aller dans SQL Server Network Configuration, Protocols for MSSQLSERVER et passer TCP/IP en Enabled :



Vérifier également dans l'onglet Sécurité que la connexion via Windows ET SQL Server est autorisée.

Enfin, il faut aller ouvrir le port TCP 1433 dans le pare-feu Windows :



Et voilà, simple non ?

Allez, bon dev à tous ! :)

Un petit outil pour gérer ses fichiers de traduction en PHP

icon Tags de l'article : , ,

Septembre 17, 2014
Hello,

Juste pour ceux que ça intéresse, voici un petit outil très simple que j'ai développé pour moi afin de gérer les traductions dans mes applications en PHP.

Resmanager (sur Github)

Le fonctionnement est très simple :
  • on remplit le fichier resources.lng avec nos traductions
  • on lance le petit exécutable ResourcesSplitter.exe
  • ce dernier va générer automatiquement des fichiers PHP avec nos traductions, un fichier par langue
  • on n'a plus qu'à inclure/utiliser ces fichiers dans nos applications

Le petit exe est fait en .Net, il est très simple et son code source est également présent sur le repository (fichier ResourcesSplitter.cs).

Voilà, on ne sait jamais, ça vous servira peut-être ! Si vous avez des questions n'hésitez pas !

Bon développement à tous !

(Et oui, pour ceux qui se demandent, je m'en sert pour la nouvelle version à venir de MyCryptoChat :)