From: Greg Burri Date: Mon, 5 May 2008 19:29:06 +0000 (+0000) Subject: MOD évite de faire plein de "register" à la suite et ainsi de saturer la bd de plein... X-Git-Tag: 1.0.0^2~109 X-Git-Url: http://git.euphorik.ch/index.cgi?a=commitdiff_plain;h=d9d05b6a2a13c2da190dd68d4409381d093679b2;p=euphorik.git MOD évite de faire plein de "register" à la suite et ainsi de saturer la bd de plein de comptes --- diff --git a/doc/TODO.txt b/doc/TODO.txt index ea55a31..22e81b6 100755 --- a/doc/TODO.txt +++ b/doc/TODO.txt @@ -13,11 +13,11 @@ * Un kick : l'utilisateur (ip) est kické et bannis pour 15 min * Un ban : l'utilisateur (ip) est kické et bannis pour 3 jours * Modification de la BD -> ajouter une relation "banned_ip" -* Traiter les tags TODO et FIXME dans le code +* Traiter les tags TODO et FIXME dans le code + * Mettre les constantes au niveau du serveur dans euphorik_defines.hrl (par exemple les temps lié au flood) * Cleaner le code (erl, js, xhtml, css) et eventuellement profiler un peu (le refresh est lent sous opera) * Restructurer le code Erlang : déplacer certaines fonctions d'un module à l'autre (ev. créer des modules) * Choisir une licence et la mettre un peu partout dans les sources, voir : http://www.gnu.org/licenses/gpl-howto.fr.html -* Trouver un moyen pour éviter la création à la suite de plusieurs comptes (via register). * Finir le script de mise en production * Make des modules. * Compactage des js lors de la mise en production (afin d'optimiser la bande passante lors de l'accès au site), regarder comment fait jQuery. @@ -146,6 +146,8 @@ [ok] Tester avec des caractères accentués sur Firefox, Safari, Opera et IE7. Les messages doivent être envoyés en UTF8. [ok] Tester avec des caractères exotiques (jap, coréen, etc..) [ok] Modifier la syntaxe des smiles actuels (pour pas qu'ils entre en conflit avec totoz) +[ok] Trouver un moyen pour éviter la création à la suite de plusieurs comptes (via register). + === Bugs === 1 : Critique diff --git a/doc/protocole3.txt b/doc/protocole3.txt index 585794a..feae1f0 100644 --- a/doc/protocole3.txt +++ b/doc/protocole3.txt @@ -89,7 +89,8 @@ ou "racine" : 123, "page" : 1 } - ] + ], + "ek_master" : true | false } @@ -184,11 +185,8 @@ ou "message_id" : 123, "contenu" : "Salut +++ poulpe" } -ou - { - "reply" : "error", - "error_message" : "blabla" - } +ou + === Envoie d'un troll === @@ -219,12 +217,26 @@ c -> s "answer_to" : [ 345, 532, ... ] } -s -> c - { - "reply" : "ok" | "error", - "error_message" : "blabla" +s -> c + +ou + + + +=== Bannissement === + +c -> s + { + "action" : "ban", + "cookie" : "LKJDLAKSJBFLKASN", + "duration" : 3, // en heure + "user_id" : 67 } - + +s -> c + +ou + === Ajout d'une correction d'un messages === Le client envoie un correctif sous la forme de texte supplémentaire à appondre au dernier messages. diff --git a/js/euphorik.js b/js/euphorik.js index e8311da..3503c7e 100755 --- a/js/euphorik.js +++ b/js/euphorik.js @@ -426,6 +426,7 @@ Client.prototype.resetDonneesPersonnelles = function() this.nickFormat = "nick" this.pagePrincipale = 1 + this.ek_master = false // les conversations, une conversation est un objet possédant les attributs suivants : // - racine (entier) @@ -706,6 +707,7 @@ Client.prototype.chargerDonnees = function(data) // les conversations thisClient.conversations = data["conversations"] + thisClient.ek_master = data["ek_master"] } this.dernierMessageErreur = data["error_message"] } diff --git a/modules/erl/euphorik_bd.erl b/modules/erl/euphorik_bd.erl index c836776..7703bd3 100755 --- a/modules/erl/euphorik_bd.erl +++ b/modules/erl/euphorik_bd.erl @@ -45,6 +45,14 @@ create_tables() -> {attributes, record_info(fields, user)}, {index, [cookie, login]}, {disc_copies, [node()]} + ]), + mnesia:create_table(ip_table, [ + {attributes, record_info(fields, ip_table)}, + {disc_copies, [node()]} + ]), + mnesia:create_table(troll, [ + {attributes, record_info(fields, troll)}, + {disc_copies, [node()]} ]). @@ -94,7 +102,34 @@ vers_version(6) -> end, record_info(fields, user), user - ). + ); +% Ajout de la table 'ip_table' +% Ajout du statut 'ek_master' pour les users +vers_version(7) -> + mnesia:transform_table( + user, + fun({user, Id, Cookie, Pseudo, Login, Password, Email, Date_creation, Date_derniere_connexion, Css, Nick_format, Indice_flood, Page_Principale, Conversations}) -> + {user, Id, Cookie, Pseudo, Login, Password, Email, Date_creation, Date_derniere_connexion, Css, Nick_format, Indice_flood, Page_Principale, Conversations, false, undefined} + end, + record_info(fields, user), + user + ), + mnesia:create_table(ip_table, [ + {attributes, record_info(fields, ip_table)}, + {disc_copies, [node()]} + ]), + mnesia:create_table(troll, [ + {attributes, record_info(fields, troll)}, + {disc_copies, [node()]} + ]); +vers_version(8) -> + mnesia:transform_table( + ip_table, + fun() -> null end, + record_info(fields, ip_table), + ip_table + ). + % exemple de peuplage de la BD, utilisé pour les tests diff --git a/modules/erl/euphorik_minichat.erl b/modules/erl/euphorik_minichat.erl index 6f229ac..35a9d97 100755 --- a/modules/erl/euphorik_minichat.erl +++ b/modules/erl/euphorik_minichat.erl @@ -35,10 +35,12 @@ nouveau_message/3, reset/0, % reservé : + can_register/1, resultat_transaction/1 ]). --include("../include/euphorik_bd.hrl"). +-include("../include/euphorik_bd.hrl"). +-include("../include/euphorik_defines.hrl"). -include_lib("stdlib/include/qlc.hrl"). % Un message est considéré comme du spam s'il est posté 1 seconde ou moins après le dernier posté @@ -424,8 +426,35 @@ repond_a(M_id) -> E#reponse_minichat.repondant =:= M_id, M#minichat.id =:= E#reponse_minichat.cible])) end - )). - + )). + + +% Si deux enregistrements consequtifs de la même IP sont fait en moins d'une seconde alors +% ip_table.nb_try_register est incrémenté de 1 sinon il est décrémenté de 1 (jusqu'a 0). +% Si ip_table.nb_try_register vaut 5 alors l'ip ne peux plus s'enregistrer pour une heure. +can_register(IP) -> + resultat_transaction(mnesia:transaction( + fun() -> + case qlc:e(qlc:q([I || I <- mnesia:table(ip_table), I#ip_table.ip =:= IP])) of + [] -> + mnesia:write(#ip_table{ip = IP, date_last_try_register = now()}), + true; + [T] -> + Delta = delta_date_ms(T#ip_table.date_last_try_register, now()), + if T#ip_table.nb_try_register =:= ?NB_MAX_FLOOD_REGISTER, Delta < ?TEMPS_BAN_FLOOD_REGISTER -> + false; + true -> + mnesia:write(#ip_table{ + ip = IP, + date_last_try_register = now(), + nb_try_register = T#ip_table.nb_try_register + if Delta < ?TEMPS_FLOOD_REGISTER -> 1; T#ip_table.nb_try_register > 0 -> -1; true -> 0 end + }), + true + end + end + end + )). + % Renvoie le résultat d'une transaction (en décomposant le tuple fournit) resultat_transaction({_, T}) -> diff --git a/modules/erl/euphorik_protocole.erl b/modules/erl/euphorik_protocole.erl index 7519ba8..59f8def 100755 --- a/modules/erl/euphorik_protocole.erl +++ b/modules/erl/euphorik_protocole.erl @@ -5,7 +5,7 @@ -module(euphorik_protocole). -export([ - register/1, + register/2, login/1, logout/1, profile/1, @@ -20,18 +20,32 @@ % Une utilisateur s'enregistre avec un tuple {Login, Password}. -register([{login, Login}, {password, Password}]) -> - case euphorik_minichat:user_by_login(Login) of - {ok, _} -> - erreur("Login déjà existant"); - _ -> - User = euphorik_minichat:nouveau_user(Login, Password, generer_cookie()), - json_reponse_login_ok(User) +register([{login, Login}, {password, Password}], IP) -> + Can_register = euphorik_minichat:can_register(IP), + if Can_register -> + case euphorik_minichat:user_by_login(Login) of + {ok, _} -> + erreur("Login déjà existant"); + _ -> + User = euphorik_minichat:nouveau_user(Login, Password, generer_cookie()), + json_reponse_login_ok(User) + end; + true -> + erreur_register_flood() end; % Enregistrement sans {Login, Password} -register([]) -> - User = euphorik_minichat:nouveau_user("", generer_cookie()), - json_reponse_login_ok(User). +register([], IP) -> + Can_register = euphorik_minichat:can_register(IP), + if Can_register -> + User = euphorik_minichat:nouveau_user("", generer_cookie()), + json_reponse_login_ok(User); + true -> + erreur_register_flood() + end. + +erreur_register_flood() -> + erreur("Trop de register (flood)"). + % Un utilisateur se logge (avec un couple {login, mot de passe}) diff --git a/modules/erl/euphorik_requests.erl b/modules/erl/euphorik_requests.erl index 7ee5c7d..6562e52 100755 --- a/modules/erl/euphorik_requests.erl +++ b/modules/erl/euphorik_requests.erl @@ -19,36 +19,36 @@ tester() -> que_dal. -% il faut catcher toutes les exceptions possibles -out(A) -> +out(A) -> + %io:format("~p~n~n", [A]), %inet:setopts(A#arg.clisock, inet:getopts(A#arg.clisock, [active])), {value, {_, Contenu}} = lists:keysearch("action", 1, yaws_api:parse_post(A)), - Ret = traiter_donnees(Contenu), + Ret = traiter_donnees(Contenu, 1), {content, "application/json", Ret}. -traiter_donnees(Contenu) -> +traiter_donnees(Contenu, IP) -> case json:decode_string(Contenu) of {ok, {struct, [{action, Action}| Reste]}} -> - json:encode(traiter_action(Action, Reste)); + json:encode(traiter_action(Action, Reste, IP)); _ -> error end. % authentification d'un client -traiter_action("authentification", JSON) -> +traiter_action("authentification", JSON, _) -> euphorik_protocole:login(JSON); % un client s'enregistre (pseudo + password) -traiter_action("register", JSON) -> - euphorik_protocole:register(JSON); +traiter_action("register", JSON, IP) -> + euphorik_protocole:register(JSON, IP); % modification du profile -traiter_action("set_profile", JSON) -> +traiter_action("set_profile", JSON, _) -> euphorik_protocole:profile(JSON); % un utilisateur attend un événement (par exemple l'arrivé d'un nouveau message) -traiter_action("wait_event", JSON) -> +traiter_action("wait_event", JSON, _) -> euphorik_protocole:wait_event(JSON); % un utilisateur envoie un message -traiter_action("put_message", JSON) -> +traiter_action("put_message", JSON, _) -> euphorik_protocole:put_message(JSON). \ No newline at end of file diff --git a/modules/include/euphorik_bd.hrl b/modules/include/euphorik_bd.hrl index 173ab09..6c6cb65 100755 --- a/modules/include/euphorik_bd.hrl +++ b/modules/include/euphorik_bd.hrl @@ -43,5 +43,30 @@ nick_format = nick, %atom(), peut valoir 'nick', 'login' ou 'nick_login' indice_flood = 0, % integer() est incrémenté lorsque l'utilisateur envoie trop rapidement des messages. page_principale = 1, % la page de la conversation principale - conversations = [] % [{integer(), integer()}], la liste des messages correspondant au conversation ainsi que la page affichée + conversations = [], % [{integer(), integer()}], la liste des messages correspondant au conversation ainsi que la page affichée + ek_master = false, + last_ip % integer(), undefined si inconnu }). + + +% identificateur : (ip) +-record(ip_table, + { + ip, % integer() + ban = false, + nb_try_register = 0, + nb_try_login = 0, % pour l'instant pas utilisé + date_last_try_register, + date_last_try_login % pour l'instant pas utilisé + }). + + +-record(troll, + { + id, + id_user, + date, % erlang:now() + contenu, % chaine de caractère + date_choosen % la date à laquelle le troll est mis sur la page principale + }). + \ No newline at end of file diff --git a/modules/include/euphorik_defines.hrl b/modules/include/euphorik_defines.hrl index e69de29..5c2d357 100755 --- a/modules/include/euphorik_defines.hrl +++ b/modules/include/euphorik_defines.hrl @@ -0,0 +1,11 @@ + + + + + +% le temps qu'une ip est bannie après avoir voulu s'etre enregistré trop de fois trop rapidement +-define(TEMPS_BAN_FLOOD_REGISTER, 60 * 60 * 1000). % 1 heure : en ms +% le temps entre deux tentatives de register pour compter un flood +-define(TEMPS_FLOOD_REGISTER, 1500). % 1500 ms +% après 5 flood l'ip fautive est considérée comme bannie +-define(NB_MAX_FLOOD_REGISTER, 5).