From: Greg Burri Date: Sat, 10 May 2008 22:23:05 +0000 (+0000) Subject: ADD Bannissement (sans le slap) X-Git-Tag: 1.0.0^2~93 X-Git-Url: http://git.euphorik.ch/?p=euphorik.git;a=commitdiff_plain;h=01922222ac686c2507052c0cc1d755495145d154 ADD Bannissement (sans le slap) --- diff --git a/css/1/pageMinichat.css b/css/1/pageMinichat.css index d7cd580..234f9f5 100755 --- a/css/1/pageMinichat.css +++ b/css/1/pageMinichat.css @@ -21,6 +21,20 @@ opacity: 0.5; } +#outilsBan { + border-width: 1px 1px 1px 1px; + border-color: #253f18; + border-style: solid; + padding: 2px; + position: absolute; + display: none; +} +#outilsBan img { + float: right; + vertical-align: middle; + margin: 0px 0px 0px 0px; +} + #page.minichat .titreSmiles:hover { background-color: #2d8800; } diff --git a/doc/graphiques/icones/ban.xcf b/doc/graphiques/icones/ban.xcf new file mode 100644 index 0000000..5819921 Binary files /dev/null and b/doc/graphiques/icones/ban.xcf differ diff --git a/doc/graphiques/icones/kick.xcf b/doc/graphiques/icones/kick.xcf new file mode 100644 index 0000000..569ef77 Binary files /dev/null and b/doc/graphiques/icones/kick.xcf differ diff --git a/doc/graphiques/icones/slap.xcf b/doc/graphiques/icones/slap.xcf new file mode 100644 index 0000000..ef1af5d Binary files /dev/null and b/doc/graphiques/icones/slap.xcf differ diff --git a/doc/graphiques/path2383.png b/doc/graphiques/path2383.png new file mode 100644 index 0000000..6313230 Binary files /dev/null and b/doc/graphiques/path2383.png differ diff --git a/doc/protocole3.txt b/doc/protocole3.txt index f0b0b38..6c1032e 100644 --- a/doc/protocole3.txt +++ b/doc/protocole3.txt @@ -161,7 +161,8 @@ Le format de la date n'est pas formel. "last_page" : true | false, "messages" : [ { - "id" : 54, + "id" : 54, + "user_id" : 344, "date" : "Hier 17:26:54", "system" : true | false, "owner" : true | false, diff --git a/img/ban.gif b/img/ban.gif new file mode 100644 index 0000000..9a7d412 Binary files /dev/null and b/img/ban.gif differ diff --git a/img/kick.gif b/img/kick.gif new file mode 100644 index 0000000..ce127dd Binary files /dev/null and b/img/kick.gif differ diff --git a/img/slap.gif b/img/slap.gif new file mode 100644 index 0000000..2265fda Binary files /dev/null and b/img/slap.gif differ diff --git a/js/euphorik.js b/js/euphorik.js index 2d64fe2..6ed1963 100755 --- a/js/euphorik.js +++ b/js/euphorik.js @@ -673,10 +673,10 @@ Client.prototype.connexion = function(messageJson) Client.prototype.deconnexion = function() { - this.flush() + this.flush() + this.delCookie() this.setStatut(statutType.deconnected) // deconnexion this.resetDonneesPersonnelles() - this.delCookie () } Client.prototype.chargerDonnees = function(data) @@ -771,6 +771,39 @@ Client.prototype.majMenu = function() } } +Client.prototype.ban = function(userId, minutes) +{ + var thisClient = this + + // par défaut un ban correspond à 3 jours + if (typeof(minutes) == "undefined") + minutes = 60 * 24 * 3 + + jQuery.ajax({ + type: "POST", + url: "request", + dataType: "json", + data: this.util.jsonVersAction( + { + "action" : "ban", + "cookie" : thisClient.cookie, + "duration" : minutes, + "user_id" : userId + }), + success: + function(data) + { + if (data["reply"] == "error") + thisClient.util.messageDialogue(data["error_message"]) + } + }) +} + +Client.prototype.kick = function(userId) +{ + this.ban(userId, 15) +} + /////////////////////////////////////////////////////////////////////////////////////////////////// function initialiserListeStyles(client) diff --git a/js/pageMinichat.js b/js/pageMinichat.js index 2be7ca5..94f6e7c 100755 --- a/js/pageMinichat.js +++ b/js/pageMinichat.js @@ -40,6 +40,21 @@ PageMinichat.prototype.charger = function() this.util.setCaretToEnd(jQuery("form input.message")[0]) + // les outils de bannissement (uniquement pour les ekMaster) + if (this.client.ekMaster) + { + jQuery("body").append( + "
\"Ban\"Ban\"Avertissement\"
" + ) + jQuery("#outilsBan").hover( + function(){}, + function() + { + jQuery("#outilsBan").hide() + } + ) + } + // jQuery("body").append("
") // affichage des smiles @@ -134,6 +149,7 @@ PageMinichat.prototype.decharger = function() this.messages.stopAttenteCourante() jQuery("body #smiles").remove() + jQuery("body #outilsBan").remove() } PageMinichat.prototype.getJSONMessage = function(pseudo, message, repondA) @@ -209,7 +225,11 @@ PageMinichat.prototype.envoyerMessage = function(pseudo, message) thisPageMinichat.messages.conversations[c].messages[m].clientARepondu = true */ } - } + } + else if (data["reply"] == "error") + { + thisPageMinichat.util.messageDialogue(data["error_message"]) + } } } ) @@ -239,9 +259,10 @@ function Reponse(id, pseudo, login) * @param pseudo * @param contenu */ -function Message(id, date, pseudo, login, contenu) +function Message(id, auteurId, date, pseudo, login, contenu) { this.id = id + this.auteurId = auteurId this.date = date this.pseudo = pseudo this.login = login @@ -484,7 +505,7 @@ Conversation.prototype.flush = function(funClickOuvrirConv) "\">" + "
>
" + "[" + message.date + "]" + - "" + identifiant + ":" + + "" + identifiant + ":" + XHTMLrepondA + "" + (message.systeme ? this.formateur.remplacerBalisesHTML(message.contenu) : this.formateur.traitementComplet(message.contenu, message.pseudo)) + "" + "" @@ -518,13 +539,40 @@ Conversation.prototype.flush = function(funClickOuvrirConv) } ) + // les outils de bannissement (uniquement pour les ekMaster) + if (thisConversation.client.ekMaster) + jQuery(".pseudo", this).hover( + function(e) + { + var userId = parseInt(jQuery(this).attr("id").substr(4)) + var element = jQuery(e.target) + var h = element.height() + var offset = element.offset() + var outils = jQuery("#outilsBan").css("top", offset.top - 2).css("left", offset.left - 2).height(h < 16 ? 16 : h).width(element.width() + 16 * 3 + 4).show() + jQuery("img", outils).unbind() + jQuery("#kick", outils).click( + function(e) + { + thisConversation.client.kick(userId) + } + ) + jQuery("#ban", outils).click( + function(e) + { + thisConversation.client.ban(userId) + } + ) + }, + function(){} + ) + jQuery(this).click( function(event) { if (jQuery(event.target).is("a")) return // l'id du message - idMess = jQuery(this).attr("id") + var idMess = jQuery(this).attr("id") // extraction d'une conversation if (jQuery(event.target).is(".extraire")) @@ -611,9 +659,6 @@ function Messages(client, formateur, util) this.conversations = new Array() // les conversations, la première représente la conversation principale this.nouvelleConversation(0) - -// Obsolète - //this.idDernierMessage = null // l'id du dernier message connu // l'objet JSONHttpRequest représentant la connexion d'attente this.attenteCourante = null @@ -690,6 +735,7 @@ Messages.prototype.ajouterMessage = function(element, numConversation) var message = new Message( id, + element["user_id"], element["date"], element["nick"], element["login"], @@ -849,8 +895,6 @@ Messages.prototype.rafraichirMessages = function(vider) this.stopAttenteCourante() - /*if (vider) - this.idDernierMessage = null*/ if (vider) for (var i = 0; i < this.conversations.length; i++) this.conversations[i].idDernierMessageAffiche = 0 diff --git a/modules/erl/euphorik_bd.erl b/modules/erl/euphorik_bd.erl index 1b37b4c..87dab2f 100755 --- a/modules/erl/euphorik_bd.erl +++ b/modules/erl/euphorik_bd.erl @@ -29,6 +29,7 @@ % messages : nouveau_message/3, + nouveau_message_sys/1, messages/1, messages/2, messages/3, @@ -44,6 +45,8 @@ % ip : ip_table/0, ban/2, + deban/1, + est_banni/1, can_register/1, % versions : @@ -114,10 +117,11 @@ reset() -> mnesia:clear_table(counter), mnesia:clear_table(user), mnesia:clear_table(reponse_minichat), - mnesia:clear_table(minichat), + mnesia:clear_table(minichat), + mnesia:clear_table(ip_table), % crée l'utilisateur root mnesia:transaction(fun() -> - User = #user{id = 0, pseudo = "Sys", login = "Sys", date_creation = now(), date_derniere_connexion = now()}, + User = #user{id = 0, pseudo = "Sys", login = "Sys", date_creation = now(), date_derniere_connexion = now(), ek_master = true}, mnesia:write(User), User end). @@ -160,7 +164,7 @@ set_profile(Cookie, Login, Password, Pseudo, Email, Css, Nick_format, Page_princ % TODO : pourquoi ne pas tester avec la valeur "undefined" plutôt qu'avec "is_list" ? % TODO : validation plus strict des données (pas de page négative dans les conv par exemple) login = if is_list(Login) -> Login; true -> User#user.login end, - password = if is_list(Password) -> Password; true -> User#user.password end, + password = if is_list(Password) andalso Password =/= [] -> Password; true -> User#user.password end, pseudo = if is_list(Pseudo) -> Pseudo; true -> User#user.pseudo end, email = if is_list(Email) -> Email; true -> User#user.email end, css = if is_list(Css) -> Css; true -> User#user.css end, @@ -303,12 +307,6 @@ user_by_mess(Id) -> end )). - -% Renvoie l'utilisateur root -root() -> - {ok, User} = user_by_id(0), - User. - % Ajoute un message. Repond_A est une liste d'id auquel le message répond % retourne soit l'id du message soit erreur. @@ -324,7 +322,6 @@ nouveau_message(Mess, Auteur_id, Repond_A) -> if Nb_id_trouve =/= length(Repond_A) -> throw("Un ou plusieurs messages introuvable"); true -> ok end, - Id = nouvel_id(minichat), % compare les dernière Delta = delta_date_ms(Auteur#user.date_derniere_connexion, now()), Nouvel_indice_flood = Auteur#user.indice_flood + if Delta =< ?DUREE_SPAM -> 2; true -> -1 end, @@ -334,14 +331,13 @@ nouveau_message(Mess, Auteur_id, Repond_A) -> }, % est-ce que l'auteur à trop floodé ? if Auteur#user.indice_flood =/= ?INDICE_SPAM_MAX, Auteur_maj#user.indice_flood =:= ?INDICE_SPAM_MAX, Delta =< ?DUREE_BLOCAGE_SPAM -> - Root = root(), mnesia:write(Auteur#user{indice_flood = Auteur_maj#user.indice_flood}), - mnesia:write(#minichat{id=Id, auteur_id=Root#user.id, date=now(), pseudo=Root#user.pseudo, contenu=Auteur#user.pseudo ++ "(" ++ Auteur#user.login ++ ") est bloqué pour " ++ integer_to_list(trunc(?DUREE_BLOCAGE_SPAM / 1000)) ++ " secondes pour cause de flood.."}), - Id; + nouveau_message_sys(Auteur#user.pseudo ++ "(" ++ Auteur#user.login ++ ") est bloqué pour " ++ integer_to_list(trunc(?DUREE_BLOCAGE_SPAM / 1000)) ++ " secondes pour cause de flood.."); Auteur#user.indice_flood =:= ?INDICE_SPAM_MAX, Delta =< ?DUREE_BLOCAGE_SPAM -> erreur; true -> mnesia:write(Auteur_maj), + Id = nouvel_id(minichat), inserer_reponses(Id, Repond_A), mnesia:write(#minichat{id=Id, auteur_id=Auteur#user.id, date=now(), pseudo=Auteur#user.pseudo, contenu=Mess}), Id @@ -356,6 +352,18 @@ inserer_reponses(Id_repondant, [Id_mess | Reste]) -> inserer_reponses(_, []) -> ok. + +% Permet de créer un message système. +% Renvoie l'id du message système +nouveau_message_sys(Mess) -> + {ok, Root} = user_by_id(0), + mnesia:transaction( + fun() -> + Id = nouvel_id(minichat), + mnesia:write(#minichat{id=Id, auteur_id=0, date=now(), pseudo=Root#user.pseudo, contenu=Mess}) + end + ). + % Renvoie N messages se trouvant sur la première page messages(N) -> @@ -498,6 +506,47 @@ ban(IP, Duration) -> ). +% Débanni une ip +deban(IP) -> + ban(IP, 0). + + +% Renvoie soit {true, Temps} où Temps est le temps en minutes pendant lequel le user est encore banni +% ou false. +est_banni(User_id) -> + resultat_transaction(mnesia:transaction( + fun() -> + case qlc:e(qlc:q([ + {IP#ip_table.ban, IP#ip_table.ban_duration} || + U <- mnesia:table(user), + U#user.id =:= User_id, + IP <- mnesia:table(ip_table), + IP#ip_table.ip =:= U#user.last_ip + ])) of + [{Ban, Ban_duration}] -> + Echeance = date_plus_minutes(Ban, Ban_duration), + Now = now(), + if Echeance < Now -> % l'échéance est passée + false; + true -> + {true, trunc(delta_date_ms(Echeance, Now) / 1000 / 60)} + end; + _ -> + false + end + end + )). + + +% Ban est une date tel que retourner par now(). +% Ban_duration est un temps en minutes. +% retourne une date. +date_plus_minutes(Ban, Ban_duration) -> + Duration_sec = Ban_duration * 60, + {MegaSec, Sec, MicroSec} = Ban, + {MegaSec + if Sec + Duration_sec >= 1000000 -> 1; true -> 0 end,(Sec + Duration_sec) rem 1000000, MicroSec}. + + % 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. diff --git a/modules/erl/euphorik_protocole.erl b/modules/erl/euphorik_protocole.erl index 194961e..dc29bf5 100755 --- a/modules/erl/euphorik_protocole.erl +++ b/modules/erl/euphorik_protocole.erl @@ -150,22 +150,17 @@ wait_event(Data) -> Est_proprietaire = User =/= inconnu andalso User#user.id =:= Mess#minichat.auteur_id, A_repondu_a_message = User =/= inconnu andalso euphorik_bd:a_repondu_a_message(User#user.id, Mess#minichat.id), Est_une_reponse_a_user = User =/= inconnu andalso euphorik_bd:est_une_reponse_a_user(User#user.id, Mess#minichat.id), - User_mess = - if Mess#minichat.auteur_id =:= 0 -> - inconnu; - true -> - {ok, U2} = euphorik_bd:user_by_id(Mess#minichat.auteur_id), - U2 - end, + {ok, User_mess } = euphorik_bd:user_by_id(Mess#minichat.auteur_id), {struct, [ {id, Mess#minichat.id}, + {user_id, User_mess#user.id}, {date, format_date(Mess#minichat.date)}, {system, Mess#minichat.auteur_id =:= 0}, {owner, Est_proprietaire}, {answered, A_repondu_a_message}, {is_a_reply, Est_une_reponse_a_user}, {nick, Mess#minichat.pseudo}, - {login, if User_mess =:= inconnu -> Mess#minichat.pseudo; true -> User_mess#user.login end}, + {login, User_mess#user.login}, {content, Mess#minichat.contenu}, {answer_to, {array, lists:map( fun(Id_mess) -> @@ -205,21 +200,37 @@ put_message( ) -> case euphorik_bd:user_by_cookie(Cookie) of {ok, User} -> - Strip_content = string:strip(Content), - if (Strip_content =:= []) -> - erreur("Message vide"); - true -> - % TODO : non-atomique (update_pseudo+nouveau_message) - euphorik_bd:update_pseudo_user(User#user.id, Nick), - case euphorik_bd:nouveau_message(Strip_content, User#user.id, Answer_to) of - erreur -> erreur("Impossible d'ajouter un nouveau message"); - _ -> - json_reponse_ok() + case euphorik_bd:est_banni(User#user.id) of + {true, Temps_restant} -> + erreur("Vous êtes banni pour encore " ++ format_minutes(Temps_restant)); + _ -> + Strip_content = string:strip(Content), + if Strip_content =:= [] -> + erreur("Message vide"); + true -> + % TODO : non-atomique (update_pseudo+nouveau_message) + euphorik_bd:update_pseudo_user(User#user.id, Nick), + case euphorik_bd:nouveau_message(Strip_content, User#user.id, Answer_to) of + erreur -> erreur("Impossible d'ajouter un nouveau message"); + _ -> + json_reponse_ok() + end end end; - _ -> - erreur("Utilisateur inconnu") - end. + _ -> + erreur("Utilisateur inconnu") + end. + + +% Formatage de minutes. +% par exemple : "1min", "45min", "1h23min", "1jour 2h34min" +format_minutes(Min) -> + Jours = Min div (60 * 24), + Heures = Min rem (60 * 24) div 60, + Minutes = Min rem (60), + if Jours =/= 0 -> integer_to_list(Jours) ++ "Jour" ++ if Jours > 1 -> "s"; true -> "" end ++ " "; true -> "" end ++ + if Heures =/= 0 -> integer_to_list(Heures) ++ "h"; true -> "" end ++ + lists:flatten(io_lib:format(if Jours =:= 0, Heures =:= 0 -> "~w"; true -> "~2.2.0w" end, [Minutes])) ++ "min". % bannissement d'un utilisateur (son ip est bannie) @@ -229,18 +240,31 @@ ban( {duration, Duration}, {user_id, User_id} ]) -> - % controle que l'utilisateur est un admin - case euphorik_bd:user_by_cookie(Cookie) of - {ok, User = #user{ek_master = true}} -> - case euphorik_bd:user_by_id(User_id) of - {ok, User} -> - euphorik_bd:ban(User#user.last_ip, Duration); - _ -> - erreur("Utilisateur à bannir inconnu") - end; - _ -> - erreur("Utilisateur inconnu ou non ek master") - end. + % controle que l'utilisateur est un admin + case euphorik_bd:user_by_cookie(Cookie) of + {ok, User1 = #user{ek_master = true}} -> + case euphorik_bd:user_by_id(User_id) of + {ok, User1} -> + erreur("Il n'est pas possible de s'auto bannir"); + {ok, User2 = #user{ek_master = false}} -> + euphorik_bd:ban(User2#user.last_ip, Duration), + euphorik_bd:nouveau_message_sys(lists:flatten(io_lib:format("~s ~s est ~s pour ~s", + [ + User2#user.pseudo, + if User2#user.login =:= [] -> ""; true -> "(" ++ User2#user.login ++ ")" end, + if Duration =< 15 -> "kické"; true -> "banni" end, + format_minutes(Duration) + ] + ))), + json_reponse_ok(); + {ok, _} -> + erreur("L'utilisateur est lui même un ekMaster"); + _ -> + erreur("Utilisateur à bannir inconnu") + end; + _ -> + erreur("Utilisateur inconnu ou non ek master") + end. % Construit une erreur @@ -273,7 +297,7 @@ format_date(Date) -> end ++ io_lib:format("~2.10.0B:~2.10.0B:~2.10.0B", [Heure, Minute, Seconde]) ). - + json_reponse_ok() -> {struct, [{reply, "ok"}]}.