Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Duplicated usernames and login_names in v5 #22

Closed
4 tasks
gberaudo opened this issue Apr 5, 2016 · 50 comments
Closed
4 tasks

Duplicated usernames and login_names in v5 #22

gberaudo opened this issue Apr 5, 2016 · 50 comments

Comments

@gberaudo
Copy link
Contributor

gberaudo commented Apr 5, 2016

The username and login_name fields are not unique in v5 as can be shown by the following 2 requests:

select id, username from app_users_private_data where username in (select username from app_users_private_data group by username having count(username) >= 2) order by username;

-> 42 results

select id, login_name from app_users_private_data where login_name in (select login_name from app_users_private_data group by login_name having count(*) >= 2) order by login_name;

-> 48 results

It is essential that the v5 database be fixed so that we can import in the topoguide and in Discourse
robustly and consistently.@fbunoz, could you please have a look to this?

  • the fields should be made unique (maybe by suffixing older accounts);
  • unique constraints should be added to the user table.

In addition, due to restrictions in the Discourse forum usernames, we cannot use the username field (forum name) as-is. The problem is that normalizing the username may result in non-unique usernames. @fbunoz, would it be possible to include a normalized and unique column in the dumps? In addition, a few weeks before the final migration could users be prevented to change their forum pseudo?

  • add a discourse_username column to v5 dump with a normalized and unique pseudo name;
  • block forum pseudo change in Discourse a few weeks before the final migration.
@gberaudo
Copy link
Contributor Author

gberaudo commented Apr 5, 2016

edit: deleted in favor of full solution in the comment below.

@gberaudo
Copy link
Contributor Author

gberaudo commented Apr 7, 2016

I created a small sql script that:

  • makes the login_name unique;
  • replaces the username column with a normalized and unique version compatible with Discourse;
  • adds constraints to the login_name and username columns.

Discourse has complicate rules for handling non-alphanumeric characters; this script reduces the complexity by completly discarding them.

The script must be reviewed and eventually adapted/fixed by the association before applying it to the v5 production database. A backup of the username column is created in old_username.

Before applying the script, some postgresql extensions must be installed with:

create extension unaccent;
create extension intarray;

create_unique_normalized_usernames.txt

@brunobesson
Copy link
Member

(I think intagg extension is missing too?)

Anyway, I ran the script on punbb_users table from a local copy of production server (only the relevant table punbb_users, don't be afraid!)

There seems to be a user with null username (id 310193 > http://www.camptocamp.org/users/310193/fr). That case should be handled (manually!)
Otherwise, there is no duplicate after processing the data. There are 1782 usernames updated, on a total of 47065 accounts.
Having a look at the data, we could also assume some of these duplicates come from duplicated accounts...

Still, the discriminating function seem not very nice to me. I would suggest, if nothing better arises, to:

  • replace dX for duplicates with -X (I understood underscore can be used if no repeated?)
  • replace sss with something... else

Maybe these questions could be adressed to the forum moderators?
On the other side, the function seems OK to me.

@fbunoz
Copy link

fbunoz commented Apr 7, 2016

The username size limits should be changed : the allowed size is between 2 and 25 characters.
I'll change the script to alllow '_-.' in username with discourse rules.
Moreover, I think we can try to allow current accent characters (needed minor changes in discourse). The choice to forbid accent is only ideologic, with the bad choice to use the username in profile url without ID. In V6, the profile url will be different (V5 format, with ID).
To support asian language, discourse must support multi-byte characters in username.
https://meta.discourse.org/t/why-are-usernames-so-restrictive/1315

@jmarcmod
Copy link

jmarcmod commented Apr 8, 2016

There seems to be a user with null username (id 310193 > http://www.camptocamp.org/users/310193/fr). That case should be handled (manually!)

Ce pseudo n'est pas vide, il est constitué d'un espace. Il a été créé par les modérateurs forum, pour que personne d'autre ne puisse le prendre (un petit malin l'avait fait avant nous, et on avait supprimé le compte).
Il ne servira à rien sur la V6 (puisque les espaces sont interdits), on peut donc l'oublier.

Autre remarque : si en apparence il y a des doublons sur la V5, c'est à cause des espaces ; en rajoutant un espace après le pseudo, on crée un pseudo différent, mais de même apparence.
Là aussi le même petit malin en a joué pour faire des usurpations, mais sauf erreur Bubu a depuis modifié le code pour qu'à l'inscription un pseudo ne puisse pas finir par un ou plusieurs espaces.

Pour la pertinence des remplacements (_ ou - ou .ou autres) une discussion au sein de l'assoce (essentiellement avec les modos forum), sur le forum V6 Réseau social donc, serait effectivement bienvenue, par mail c'est peu pratique ; mais il faudrait au préalable nous lister :

  • ce qui devient interdit ;
  • les options de remplacement.

Désolé, je lis l'anglais mais suis incapable de l'écrire...

J.Marc

@gberaudo
Copy link
Contributor Author

gberaudo commented Apr 8, 2016

Discourse has complicate rules for the special characters (_ . -).
No special character at the end of the username.
No successive special characters.
No "confusing" extenstion ath the end of the username.
So , it:

  • allows gui-llaume, gui.llaume, gui.llau.me, gui_llaume;
  • but forbids gui--llaume, gui-_llaume, guillaume_, guillaume.txt...

The main issue is how to normalize existing usernames with these complicate rules?
The attached SQL script workaround the difficulty by only allowing alphanumeric characters.
Do you see how to update it to handle special characters?

@gberaudo
Copy link
Contributor Author

gberaudo commented Apr 8, 2016

There is an additionnal restriction in Discourse: the usernames should be unique regardless of the case.
So having both guillaume and Guillaume is not allowed and the attached script should be updated.

@jmarcmod
Copy link

jmarcmod commented Apr 8, 2016

Merci gberaudo.

Pour la pertinence des remplacements (_ ou - ou .ou autres) une discussion au sein de l'assoce (essentiellement avec les modos forum), sur le forum V6 Réseau social donc, serait effectivement bienvenue.

La discussion est lancée :
http://www.camptocamp.org/forums/viewtopic.php?id=289198

@jmarcmod
Copy link

jmarcmod commented Apr 9, 2016

2 questions:

  • L'espace est bien un caractère interdit ? point crucial car c'est peut-être le caractère spécial le plus utilisé pour les pseudos V5.
  • Quelles sont les extensions interdites, outre .txt ? il y a une liste ?

@gberaudo
Copy link
Contributor Author

gberaudo commented Apr 9, 2016

@jmarcmod
Copy link

Désolé pour cette longue absence, suite au décès de mon père.
Pour la migration des pseudos, j'essaye de synthétiser les souhaits de l'Association pour le milieu de semaine prochaine (avant l'Ascension).

@gberaudo
Copy link
Contributor Author

gberaudo commented May 2, 2016

Mes condoléances. Merci pour ta persévérance, je regarderai ça probablement après le pont.

@jmarcmod
Copy link

jmarcmod commented May 30, 2016

Décidément le temps m'a manqué...
Voici enfin la synthèse de nos réflexions
(en espérant n'avoir pas fait trop d'erreurs).

Règles de formatage des pseudos sous Discourse

Caractères autorisés: 2 groupes

  • groupe A = alphanumériques = lettres (non accentuées) et chiffres i.e. A..Z | a..z | 0..9
  • groupe S = spéciaux underscore, tiret, point i.e. _ | - | .

NB: les lettres sont insensibles à la casse (en tenir compte car on crée ainsi facilement des doublons).

Caractères interdits: 2 groupes

  • groupe A' = autres alphanumériques = lettres accentuées, lettres grecques etc.
  • groupe S' = autres spéciaux i.e. ø | " | espace | ( | ) | @ | ' | [ | ] | & | * | ! | : | # | < | > | / | $ | etc.

Configurations interdites avec les caractères autorisés:

  • caractère spécial S en fin de pseudo
  • plusieurs caractères spéciaux S consécutifs (identiques ou pas)
  • fin de pseudo égal à une extension .* où l'étoile est l'une des chaîne suivantes: js | json | css | htm | html | xml | jpg | jpeg | png | gif | bmp | ico | tif | tiff | woff

Nombre de caractères autorisé:

  • entre 2 et 25

Les étapes de la migration

  1. En un premier temps, on va envoyer un mail (1) à tous ceux qui n'ont pas de pseudo forum V5 conforme aux normes V6 (= Discourse), en leur proposant de le modifier (il faudra évidemment leur donner la règle ci-dessus).
    Ceci ne créera pas de doublon (sur la V5, il est impossible de modifier son pseudo forum pour un autre déjà pris).
    (1) du moins si un envoi automatique est possible avec un tel filtrage, sinon il faudra envoyer le mail à tout les membres.

  2. Lors de la migration définitive, les pseudos encore non conformes seront automatiquement reformatés, avec gestion des doublons, selon le processus ci-dessous.

  3. Une fois la V6 en ligne, chaque membre pourra bien sûr rendre son pseudo un peu plus sexy (dans le respect des règles Discourse).

NB: pour ceux qui aiment que leur pseudo apparaisse avec une belle mise en forme, il y aura toujours la possibilité de le faire dans le champ du "nom d'utilisateur", qui apparait à droite du pseudo Discourse s'il lui est différent.


Processus de reformatage automatique

1) Mise en conformité

a) Pour toute combinaison de plusieurs caractères spéciaux (de type S ou S') consécutifs, identiques ou pas, on ne garde que le premier.
_Ex.: To--to et To-to et To-?.to deviennent To-to ; To""to et To@-to deviennent en un 1er temps To"to et To@to (mais par j) et f) ils deviendront Toto et To_to)

b) Tout caractère spécial (de type S ou S') en fin de pseudo est supprimé.
Ex.: Toto. et Toto+ deviennent Toto

c) Toute extension interdite est supprimée.
Ex.: Toto.jpg devient Toto

d) Remplacer les lettres accentuées par leur équivalent non accentué.
Ex.: Têtu devient Tetu

e) Remplacer les lettres grecques (ou d'autres langues) par leur équivalent latin.
Ex.: ωαza devient zaza

f) Remplacer par l'underscore _ ces 5 caractères spéciaux: espace | @ | & | : | /
Ex.: To@to devient To_to

g) Remplacer par le point . ces 2 caractères spéciaux: ' | *
Ex.: L'Incal devient L.Incal

h) Remplacer par le chiffre 0 ce caractère spécial: ø
Ex.: Jørgen devient J0rgen

i) Remplacer par la lettre majuscule S ce caractère spécial: $
Ex.: a$us devient aSus

j) Suppression pure et simple des autres caractères spéciaux de type S'
Ex. : To%to devient Toto ; "Toto", déjà raccourci en "Toto via b) devient Toto

2) Traitement des pseudos trop petits ou trop longs

a) Si après reformatage un pseudo se retrouve vide ou avec un seul caractère, on le remplace par user* avec à la place de l'étoile son ID V5.
Ex.: //// (d'ID 1234) devient d'abord _ puis user1234 ; le membre ???? (d'ID 5678) devient d'abord vide puis user5678

b) Si après reformatage un pseudo se retrouve avec plus de 25 caractères, on ne garde que les 25 premiers caractères.
Ex. : anti_constitutionnellement devient anti_constitutionnellemen

3) Traitement des doublons

a) En cas de doublons au sens V6 créés par le reformatage, les pseudos identiques se voient augmentés de la partie numérique de l'ID V5 (à l'exception du pseudo du membre le plus ancien, i.e. du pseudo à la plus petite ID, qui lui reste intact).
Ex.: Toto (d'ID 123), toto (d'ID 234), Toto* (d'ID 345) et toto (d'ID 1111) deviennent Toto, toto234, Toto345 et toto 1111_

b) Si l'ajout de l'ID fait dépasser les 25 caractères autorisés à au moins l'un des doublons, on enlève le nombre adéquat des derniers caractères (hors ID) pour chaque doublon concerné (ça ne concerne donc jamais le plus ancien des doublons).
Ex.: Anticonstitutionnelle (d'ID 123), Anticonstitutionnelle* (d'ID 2345) et anticonstitutionnelle (d'ID 34567) deviennent Anticonstitutionnelle, Anticonstitutionnelle2345 et anticonstitutionnell34567

@jmarcmod
Copy link

jmarcmod commented Nov 12, 2016

@gberaudo @fbunoz

Pour l'instant on ne peut pas vérifier sur la version beta comment la migration a normalisé le pseudo forum, puisque c'est bugué et qu'elle l'a remplacé par le login, cf #48.
Mais est-ce que la règle de transformation ci-dessus a été implantée ?

Edit : par ailleurs, est-il correct que la normalisation automatique des pseudos forum doit se faire lors de la migration (et incombe donc à la SA) ? ou faut-il que les dévs de l'assoce la fassent au préalable sur la V5 ? car dans ce dernier cas je n'ai rien vu bouger, et il y a urgence... on a demandé aux membres dont le pseudo n'est pas conforme de le modifier, mais tous ne l'auront pas fait.

@asaunier
Copy link
Member

est-il correct que la normalisation automatique des pseudos forum doit se faire lors de la migration (et incombe donc à la SA) ? ou faut-il que les dévs de l'assoce la fassent au préalable sur la V5 ?

Je ne sais pas. S'agit-il de ce script : https://github.com/c2corg/v6_api/blob/master/c2corg_api/scripts/migration/create_unique_normalized_usernames.sql ?
Si oui, est-ce qu'il a été executé sur la BD v5 utilisée pour la migration ?

@jmarcmod
Copy link

S'agit-il de ce script

Ce script date du 15 avril, il est donc antérieur aux règles que nous avons définies ci-dessus le 30 mai.

@fjacon
Copy link

fjacon commented Nov 15, 2016

L'implémentation du script de normalisation des pseudo v5 a toujours été hors scope pour la SA.

Le script fourni par Guillaume permettait uniquement de pouvoir continuer à travailler sans être bloqués ou obligés de faire des bricolages fragiles de notre côté.

Si l'association adapte le script (tout en restant conforme aux règles Discourse), alors la SA fera l'effort d'adapter les règles de validation de l'application:

  • validation du pseudo dans la page de changement de pseudo (angular checks);
  • validation du pseudo dans notre base de données (sql checks).

@fbunoz
Copy link

fbunoz commented Nov 15, 2016

L'implémentation du script de normalisation des pseudo v5 a toujours été hors scope pour la SA.

En effet.
Sauf qu'actuellement sur la démo, il y a des login qui sont migrés comme pseudos (par exemple le mien, qui n'a rien à voir avec mon pseudo forum ou pseudo topoguide, c'est donc sûr qu'il y a un bug qui a pris login_name à la place de user_name qq part). Donc on ne sait pas si le problème provient du script de normalisation (qui n'agit que sur la base V5), ou du script de migration.

@arnaud-morvan
Copy link
Member

Je rappelle que nous avons fixé hier un bug dans le SSO qui écrasait les username et name dans discourse avec le login du topoguide. See c2corg/v6_api@b9d795e

@asaunier
Copy link
Member

asaunier commented Nov 15, 2016

Sauf qu'actuellement sur la démo, il y a des login qui sont migrés comme pseudos (par exemple le mien, qui n'a rien à voir avec mon pseudo forum ou pseudo topoguide,

Je viens de tester dans la BD v5 qu'on a utilisée pour la migration (après application du script de normalisation) :

    topo_name     | username  
------------------+-----------
 Frédéric Bunoz   | Bubu
 Alex Saunier     | alexd1
 Catherine H.     | catherine
 J.Marc           | JMarcd1
 Herve Sergeraert | Lutin
(5 rows)

@jmarcmod
Copy link

J.Marc | JMarcd1

C'est effectivement ce que j'obtiens sur ma page account.
Mais sur discourse, ça se transforme en :
jmc | jmc2
(sachant que jmc est mon login).

@arnaud-morvan
Copy link
Member

J'ai peut-être oublié de préciser que la démo n'est pas à jour !!! Mais ceci a bien été fixé par c2corg/v6_api@b9d795e

@fbunoz
Copy link

fbunoz commented Nov 16, 2016

Ah ben oui, nous ne regardons que la demo officielle : http://forum.demov6.camptocamp.org/
S'il y a un autre site de test plus à jour où on a le droit de tester, il faut le dire, car toutes les issues que nous remontons proviennent de tests sur la demo officielle.

@arnaud-morvan
Copy link
Member

Je vais la mettre à jour dans quelques minutes

@fbunoz
Copy link

fbunoz commented Nov 16, 2016

La config admin sera conservée ? Car je n'ai pas eu le temps de la sauvegarder et je n'ai plus accès à la demo.

@jmarcmod
Copy link

jmarcmod commented Nov 16, 2016

Problème pour la modification du pseudo forum via la page account

J'ai tenté de modifier mon pseudo forum via la page account.
J'y arrive, mais à condition de respecter les règles du script initial ; en d'autres termes, je ne peux pas mettre de point (ni de tiret, ni d'underscore) dans mon pseudo forum, ni dépasser 16 caractères ; alors que discourse l'accepte.
Est-ce à dire que ce script ne concerne pas seulement la migration, mais aussi le transfert page account topoguide -> discourse ?

C'est bien plus embêtant que le problème de formatage à la migration ; ça voudrait dire qu'une fois la V6 en prod, il y aura des contraintes de pseudo forum plus strictes que dans discourse, qui empêcheront les gens d'avoir un pseudo à la fois proche de l'ancien et lisible.
Par exemple, lutin de la forêt (qui a lui-même changé en lutin.de.la.foret) devra se contenter définitivement de lutindelaforet, ce qui est très mauvais.

Je ne sais pas s'il faut ouvrir une nouvelle issue pour ce problème, ou si c'est lié au script de normalisation ?

@asaunier
Copy link
Member

Le formulaire "account" contient lui-même une validation cohérente avec celle du script de normalisation v5 : https://github.com/c2corg/v6_ui/blob/master/c2corg_ui/templates/account.html#L38

Pareil pour la base de données de l'API (qui fait foi) :
https://github.com/c2corg/v6_api/blob/master/c2corg_api/models/user.py#L78-L81

Si le script de normalisation est modifié il faudra aussi modifier ces validations. Idem si plus tard les règles sur les pseudos sont modifiées.

"lutindelaforet" je trouve ca bien plus cool comme pseudo que "lutin.de.la.foret".

@jmarcmod
Copy link

jmarcmod commented Nov 16, 2016

Le formulaire "account" contient lui-même une validation cohérente avec celle du script de normalisation v5

OK, comportement "cohérent" donc.
Mais pas souhaitable... Raison de plus pour améliorer ce script afin qu'il prenne vraiment en compte les règles des pseudos discourse, qui me semblent elles assez intelligentes.

"lutindelaforet" je trouve ca bien plus cool comme pseudo que "lutin.de.la.foret".

Parce que tu connais bien ce modo, et donc que ton esprit détache tout de suite les 4 mots ; ce n'est pas le cas quand on tombe dessus la première fois.
Les pseudos composés doivent pouvoir avoir les différents mots séparés par quelque chose.

@JosueBock
Copy link

JosueBock commented Nov 16, 2016

J.Marc : pour avoir le comportement que tu souhaites (remplacer ' ' et @ par _ ; remplacer ' et * par .) je pense qu'il suffit d'ajouter ces 2 lignes :

update punbb_users set username = substring(regexp_replace(unaccent(old_username), '[ @]', '_', 'g'), 0, 16);
update punbb_users set username = substring(regexp_replace(username, '['*]', '.', 'g'), 0, 16);
et transformer la ligne existante :
update punbb_users set username = substring(regexp_replace(username, '[^a-zA-Z0-9.-_]', '', 'g'), 0, 16);

(et donc surement changer 16 en 25 dans ces trois lignes, mais il faut faire ça proprement pour définir la même limite partout)

@jmarcmod
Copy link

Merci Josué !
Et donc si c'est si simple, autant l'appliquer à toutes les transformations proposées :

f) Remplacer par l'underscore _ ces 5 caractères spéciaux: espace | @ | & | : | /
Ex.: To@to devient To_to
g) Remplacer par le point . ces 2 caractères spéciaux: ' | *
Ex.: L'Incal devient L.Incal
h) Remplacer par le chiffre 0 ce caractère spécial: ø
Ex.: Jørgen devient J0rgen
i) Remplacer par la lettre majuscule S ce caractère spécial: $
Ex.: a$us devient aSus

@JosueBock
Copy link

JosueBock commented Nov 16, 2016

oui, le cas h) je suis pas sûr que ça fonctionne, ça dépend si 'ø' est bien reconnu comme tel. Les autres caractères ne devraient pas poser problème.

Pour supprimer plusieurs caractères spéciaux successifs, il faut ajouter encore une ligne de plus :

update punbb_users set username = substring(regexp_replace(username, '[.-_]{2,}', '', 'g'), 0, 16);

(il y aurait moyen de conserver le premier caractère spécial, en rafinant un peu)

Et pour supprimer les caractères spéciaux à la fin, quelque chose du style:
update punbb_users set username = substring(regexp_replace(username, '(.)[.-_]{1,}', '\1', 'g'), 0, 16);

Je regarde comment faire des tests pour confirmer tout cela...
édit : bon, je connais rien au sql. Si quelqu'un peut me donner les rudiments : comment exécuter 3 lignes de sql, alors je ferai les tests.

@stef74 stef74 added this to the Go Live milestone Nov 21, 2016
@fjacon
Copy link

fjacon commented Nov 24, 2016

@arnaud-morvan : work in progress ?

@arnaud-morvan
Copy link
Member

Yes, working on

@arnaud-morvan
Copy link
Member

Not sure about that we can do in the UI, simply remove the regex and API will do the validation.

@asaunier
Copy link
Member

Do you mean the ng-pattern at https://github.com/c2corg/v6_ui/blob/master/c2corg_ui/templates/auth.html#L77 ?

What about having a minimal regex to catch "easy" errors (list of accepted characters)? The API will handle more complex errors.

@jmarcmod
Copy link

jmarcmod commented Nov 29, 2016

Migration du 28/11
Pas d'amélioration, c'est toujours l'ancien script qui refuse point, tiret et underscore et limite à 15 caractères.
Est-ce qu'il y aura au moins la possibilité de modifier le pseudo forum dans ce sens via la page compte topoguide ?

@HSERGERAERT
Copy link

HSERGERAERT commented Nov 29, 2016 via email

@stef74
Copy link

stef74 commented Nov 29, 2016

La partie UI sera mise a jour demain.

@jmarcmod
Copy link

jmarcmod commented Nov 30, 2016

Visiblement, le 1er script de normalisation tient compte de la casse pour la détection des doublons, alors que discourse ignore la casse.
Exemple décelé sur la beta :

  • pseudo forum Loic sur la V5
  • pseudo forum Loic sur le topoguide
  • pseudo forum Loic1 sur discourse

Explication : il y a aussi sur la V5 un pseudo forum LOIC ; le script utilisé lors de la migration n'a pas vu de doublon, puisque ce script distingue les majuscules ; mais discourse a repéré un doublon, décidé de garder LOIC et de changer Loic en Loic1.
Résultat, on se retrouve sur la V6 avec 2 pseudos forum différents, un pour le topoguide + page compte, et un pour le forum.

NB : je ne savais pas s'il fallait que je poste cela ici ou sur l'issue api #547, dans le second cas merci de reporter ce problème dans l'autre issue.

@arnaud-morvan
Copy link
Member

Avec c2corg/v6_api#531 puis c2corg/v6_api#547 nous avons ajouté un index unique sur le forum_username en minuscules dans la base topoguide.
Le script de migration utilise le même index unique en minuscules, et fait toutes ses comparaisons en minuscules.

@jmarcmod
Copy link

Good job !

@jmarcmod
Copy link

Sur la beta, je vois que le nouveau script fonctionne (au moins pour point, tiret, underscore).

@jmarcmod
Copy link

En revanche on ne peut plus changer son pseudo forum : message d'erreur dans account :

Updating account failed:
Error with Discourse : Internal Server Error

@HSERGERAERT
Copy link

My pseudo forum is Lutin on v5
My pseudo forum was Lutin1 in the previous Beta version.
Now it becomes Lutin11310 (??!)
As mentionned in the previous post, right now it cannot be changed.
I'm lost with the last modifications, and honestly a bit worried.

@arnaud-morvan
Copy link
Member

I've followed the instructions here : #22 (comment)
We have applied strictly the same constrains as in discourse.
I was unable to handle problems such as :
michel => michel
michel => michel2
michel => michel3
and
michel2 => michel2
So I've used the ID of user as suffix.

Concerning the error with discourse, I will investigate ASAP.

@HSERGERAERT
Copy link

ID of the user as suffix explains why now my forum pseudo becomes Lutin11130, fine with me.

@jmarcmod
Copy link

jmarcmod commented Dec 10, 2016

Le nouveau script de normalisation a très bien fonctionné.
Merci à la SA d'avoir accepté de le coder à l'arrache !

@stef74 : issue à fermer je pense.

@stef74 stef74 closed this as completed Dec 15, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants