X-Git-Url: http://git.polytechnique.org/?a=blobdiff_plain;f=modules%2Fadmin.php;h=af06bef04ed8b815503904681d714d1fd2aa8e29;hb=ee71865181e96e7b0754ef9e7da4b3cb26f4c1d7;hp=97f3d2c1126602139b8187cda7d3813f34b5c8ac;hpb=55546c0db778c2d8f9d7debd30117931dc39ff16;p=platal.git diff --git a/modules/admin.php b/modules/admin.php index 97f3d2c..af06bef 100644 --- a/modules/admin.php +++ b/modules/admin.php @@ -1,6 +1,6 @@ $this->make_hook('phpinfo', AUTH_MDP, 'admin'), - 'admin' => $this->make_hook('default', AUTH_MDP, 'admin'), - 'admin/ax-xorg' => $this->make_hook('ax_xorg', AUTH_MDP, 'admin'), - 'admin/dead-but-active' => $this->make_hook('dead_but_active', AUTH_MDP, 'admin'), - 'admin/deaths' => $this->make_hook('deaths', AUTH_MDP, 'admin'), - 'admin/downtime' => $this->make_hook('downtime', AUTH_MDP, 'admin'), - 'admin/homonyms' => $this->make_hook('homonyms', AUTH_MDP, 'admin'), - 'admin/logger' => $this->make_hook('logger', AUTH_MDP, 'admin'), - 'admin/logger/actions' => $this->make_hook('logger_actions', AUTH_MDP, 'admin'), - 'admin/postfix/blacklist' => $this->make_hook('postfix_blacklist', AUTH_MDP, 'admin'), - 'admin/postfix/delayed' => $this->make_hook('postfix_delayed', AUTH_MDP, 'admin'), + 'phpinfo' => $this->make_hook('phpinfo', AUTH_MDP, 'admin'), + 'admin' => $this->make_hook('default', AUTH_MDP, 'admin'), + 'admin/ax-xorg' => $this->make_hook('ax_xorg', AUTH_MDP, 'admin'), + 'admin/dead-but-active' => $this->make_hook('dead_but_active', AUTH_MDP, 'admin'), + 'admin/deaths' => $this->make_hook('deaths', AUTH_MDP, 'admin'), + 'admin/downtime' => $this->make_hook('downtime', AUTH_MDP, 'admin'), + 'admin/homonyms' => $this->make_hook('homonyms', AUTH_MDP, 'admin'), + 'admin/logger' => $this->make_hook('logger', AUTH_MDP, 'admin'), + 'admin/logger/actions' => $this->make_hook('logger_actions', AUTH_MDP, 'admin'), + 'admin/postfix/blacklist' => $this->make_hook('postfix_blacklist', AUTH_MDP, 'admin'), + 'admin/postfix/delayed' => $this->make_hook('postfix_delayed', AUTH_MDP, 'admin'), 'admin/postfix/regexp_bounces' => $this->make_hook('postfix_regexpsbounces', AUTH_MDP, 'admin'), - 'admin/postfix/whitelist' => $this->make_hook('postfix_whitelist', AUTH_MDP, 'admin'), - 'admin/mx/broken' => $this->make_hook('mx_broken', AUTH_MDP, 'admin'), - 'admin/skins' => $this->make_hook('skins', AUTH_MDP, 'admin'), - 'admin/synchro_ax' => $this->make_hook('synchro_ax', AUTH_MDP, 'admin'), - 'admin/user' => $this->make_hook('user', AUTH_MDP, 'admin'), - 'admin/promo' => $this->make_hook('promo', AUTH_MDP, 'admin'), - 'admin/validate' => $this->make_hook('validate', AUTH_MDP, 'admin'), - 'admin/validate/answers' => $this->make_hook('validate_answers', AUTH_MDP, 'admin'), - 'admin/wiki' => $this->make_hook('wiki', AUTH_MDP, 'admin'), - 'admin/ipwatch' => $this->make_hook('ipwatch', AUTH_MDP, 'admin'), - 'admin/icons' => $this->make_hook('icons', AUTH_MDP, 'admin'), + 'admin/postfix/whitelist' => $this->make_hook('postfix_whitelist', AUTH_MDP, 'admin'), + 'admin/mx/broken' => $this->make_hook('mx_broken', AUTH_MDP, 'admin'), + 'admin/skins' => $this->make_hook('skins', AUTH_MDP, 'admin'), + 'admin/synchro_ax' => $this->make_hook('synchro_ax', AUTH_MDP, 'admin'), + 'admin/user' => $this->make_hook('user', AUTH_MDP, 'admin'), + 'admin/promo' => $this->make_hook('promo', AUTH_MDP, 'admin'), + 'admin/validate' => $this->make_hook('validate', AUTH_MDP, 'admin'), + 'admin/validate/answers' => $this->make_hook('validate_answers', AUTH_MDP, 'admin'), + 'admin/wiki' => $this->make_hook('wiki', AUTH_MDP, 'admin'), + 'admin/ipwatch' => $this->make_hook('ipwatch', AUTH_MDP, 'admin'), + 'admin/icons' => $this->make_hook('icons', AUTH_MDP, 'admin'), + 'admin/accounts' => $this->make_hook('accounts', AUTH_MDP, 'admin'), + 'admin/jobs' => $this->make_hook('jobs', AUTH_MDP, 'admin'), ); } @@ -70,20 +72,20 @@ class AdminModule extends PLModule if (Env::has('del')) { $crc = Env::v('crc'); XDB::execute("UPDATE postfix_mailseen SET release = 'del' WHERE crc = {?}", $crc); - $page->trigSuccess($crc." verra tous ses emails supprimés !"); + $page->trigSuccess($crc . " verra tous ses emails supprimés !"); } elseif (Env::has('ok')) { $crc = Env::v('crc'); XDB::execute("UPDATE postfix_mailseen SET release = 'ok' WHERE crc = {?}", $crc); - $page->trigSuccess($crc." a le droit de passer !"); + $page->trigSuccess($crc . " a le droit de passer !"); } $sql = XDB::iterator( "SELECT crc, nb, update_time, create_time, - FIND_IN_SET('del', release) AS del, - FIND_IN_SET('ok', release) AS ok - FROM postfix_mailseen + FIND_IN_SET('del', p.release) AS del, + FIND_IN_SET('ok', p.release) AS ok + FROM postfix_mailseen AS p WHERE nb >= 30 - ORDER BY release != ''"); + ORDER BY p.release != ''"); $page->assign_by_ref('mails', $sql); } @@ -128,7 +130,7 @@ class AdminModule extends PLModule MONTH(MAX(start)), MONTH(MIN(start)), DAYOFMONTH(MAX(start)), DAYOFMONTH(MIN(start)) - FROM logger.sessions"); + FROM #logger#.sessions"); list($ymax, $ymin, $mmax, $mmin, $dmax, $dmin) = $res->fetchOneRow(); if (($year < $ymin) || ($year == $ymin && $month < $mmin)) { @@ -166,7 +168,7 @@ class AdminModule extends PLModule if ($year) { $res = XDB::query("SELECT YEAR (MAX(start)), YEAR (MIN(start)), MONTH(MAX(start)), MONTH(MIN(start)) - FROM logger.sessions"); + FROM #logger#.sessions"); list($ymax, $ymin, $mmax, $mmin) = $res->fetchOneRow(); if (($year < $ymin) || ($year > $ymax)) { @@ -196,7 +198,7 @@ class AdminModule extends PLModule $years[0] = "----"; // retrieve available years - $res = XDB::query("select YEAR(MAX(start)), YEAR(MIN(start)) FROM logger.sessions"); + $res = XDB::query("select YEAR(MAX(start)), YEAR(MIN(start)) FROM #logger#.sessions"); list($max, $min) = $res->fetchOneRow(); for($i = intval($min); $i<=$max; $i++) { @@ -256,16 +258,16 @@ class AdminModule extends PLModule // we are viewing a session $res = XDB::query("SELECT ls.*, a.alias AS username, sa.alias AS suer - FROM logger.sessions AS ls - LEFT JOIN aliases AS a ON (a.id = ls.uid AND a.type='a_vie') - LEFT JOIN aliases AS sa ON (sa.id = ls.suid AND sa.type='a_vie') + FROM #logger#.sessions AS ls + LEFT JOIN #x4dat#.aliases AS a ON (a.id = ls.uid AND a.type='a_vie') + LEFT JOIN #x4dat#.aliases AS sa ON (sa.id = ls.suid AND sa.type='a_vie') WHERE ls.id = {?}", $arg); $page->assign('session', $a = $res->fetchOneAssoc()); $res = XDB::iterator('SELECT a.text, e.data, e.stamp - FROM logger.events AS e - LEFT JOIN logger.actions AS a ON e.action=a.id + FROM #logger#.events AS e + LEFT JOIN #logger#.actions AS a ON e.action=a.id WHERE e.session={?}', $arg); while ($myarr = $res->next()) { $page->append('events', $myarr); @@ -315,8 +317,8 @@ class AdminModule extends PLModule $where = $this->_makeWhere($year, $month, $day, $loguid); $select = "SELECT s.id, s.start, s.uid, a.alias as username - FROM logger.sessions AS s - LEFT JOIN aliases AS a ON (a.id = s.uid AND a.type='a_vie') + FROM #logger#.sessions AS s + LEFT JOIN #x4dat#.aliases AS a ON (a.id = s.uid AND a.type='a_vie') $where ORDER BY start DESC"; $res = XDB::iterator($select); @@ -330,9 +332,9 @@ class AdminModule extends PLModule // attach events $sql = "SELECT s.id, a.text - FROM logger.sessions AS s - LEFT JOIN logger.events AS e ON(e.session=s.id) - INNER JOIN logger.actions AS a ON(a.id=e.action) + FROM #logger#.sessions AS s + LEFT JOIN #logger#.events AS e ON(e.session=s.id) + INNER JOIN #logger#.actions AS a ON(a.id=e.action) $where"; $res = XDB::iterator($sql); @@ -356,333 +358,357 @@ class AdminModule extends PLModule $page->changeTpl('admin/utilisateurs.tpl'); $page->setTitle('Administration - Edit/Su/Log'); require_once("emails.inc.php"); - require_once("user.func.inc.php"); if (S::has('suid')) { - $page->kill("Déjà en SUID !!!"); + $page->kill("Déjà en SUID !!!"); } - if (Env::has('user_id')) { - $login = get_user_forlife(Env::i('user_id')); - if (empty($login)) { - $login = Env::i('user_id'); - } - } elseif (Env::has('login')) { - $login = get_user_forlife(Env::v('login')); + // Loads the user identity using the environment. + $user = null; + if ($login) { + $user = User::get($login); + } else if (Env::has('user_id')) { + $user = User::get(Env::i('user_id')); + } else if (Env::has('login')) { + $user = User::get(Env::v('login')); } - if(Env::has('logs_button') && $login) { - pl_redirect("admin/logger?loguser=$login&year=".date('Y')."&month=".date('m')); + if ($user) { + $login = $user->login(); + $registered = ($user->forlifeEmail() != null); + } else { + return; } - if (Env::has('ax_button') && $login) { - pl_redirect("admin/synchro_ax/$login"); + // Handles specific requests (AX sync, su...). + if(Env::has('logs_button') && $registered) { + pl_redirect("admin/logger?loguser=$login&year=".date('Y')."&month=".date('m')); } - if(Env::has('suid_button') && $login) { - S::logger()->log("suid_start", "login by ".S::v('forlife')); - $r = XDB::query("SELECT id - FROM aliases - WHERE alias={?}", $login); - if($uid = $r->fetchOneCell()) { - if (!Platal::session()->startSUID($uid)) { - $page->trigError('Impossible d\'effectuer un SUID sur ' . $uid); - } else { - $page->kill("coucou"); - pl_redirect(""); - } - } + if (Env::has('ax_button') && $registered) { + pl_redirect("admin/synchro_ax/" . $user->login()); } - if ($login) { - if (is_numeric($login)) { - $r = XDB::query("SELECT *, a.alias AS forlife, - FIND_IN_SET('watch', u.flags) AS watch, FIND_IN_SET('femme', u.flags) AS sexe, - (year(naissance) > promo - 15 or year(naissance) < promo - 25) AS naiss_err - FROM auth_user_md5 AS u - LEFT JOIN aliases AS a ON (a.id = u.user_id AND type= 'a_vie') - WHERE u.user_id = {?}", $login); + if(Env::has('suid_button') && $registered) { + S::logger()->log("suid_start", "login on " . $user->login()); + if (!Platal::session()->startSUID($user->id())) { + $page->trigError('Impossible d\'effectuer un SUID sur ' . $user->id()); } else { - $r = XDB::query("SELECT *, a.alias AS forlife, - FIND_IN_SET('watch', u.flags) AS watch, FIND_IN_SET('femme', u.flags) AS sexe, - (year(naissance) > promo - 15 or year(naissance) < promo - 25) AS naiss_err - FROM auth_user_md5 AS u - INNER JOIN aliases AS a ON ( a.id = u.user_id AND a.alias={?} AND type!='homonyme' )", $login); + pl_redirect(""); } - $mr = $r->fetchOneAssoc(); + } - // Checks the user has a forlife, as non-registered user can't have redirections. - if ($mr['forlife']) { - $redirect = new Redirect($mr['user_id']); - } + // Fetches user data. + $userinfo_query = "SELECT *, FIND_IN_SET('watch', flags) AS watch, FIND_IN_SET('femme', flags) AS sexe, + (year(naissance) > promo - 15 or year(naissance) < promo - 25) AS naiss_err + FROM auth_user_md5 + WHERE user_id = {?}"; + $mr = XDB::query($userinfo_query, $user->id())->fetchOneAssoc(); + $redirect = ($registered ? new Redirect($user) : null); - // Check if there was a submission - foreach($_POST as $key => $val) { - S::assert_xsrf_token(); + // Processes admin requests, if any. + foreach($_POST as $key => $val) { + S::assert_xsrf_token(); - switch ($key) { - case "add_fwd": - $email = trim(Env::v('email')); - if (!isvalid_email_redirection($email)) { - $page->trigError("Email non valide: $email"); - } else { - $redirect->add_email($email); - $page->trigSuccess("Ajout de $email effectué"); - } - break; + switch ($key) { + // Email redirection actions. + case "add_fwd": + $email = trim(Env::v('email')); + if (!isvalid_email_redirection($email)) { + $page->trigError("Email non valide: $email"); + } else { + $redirect->add_email($email); + $page->trigSuccess("Ajout de $email effectué"); + } + break; - case "del_fwd": - if (!empty($val)) { - $redirect->delete_email($val); - } - break; + case "del_fwd": + if (!empty($val)) { + $redirect->delete_email($val); + } + break; - case "del_alias": - if (!empty($val)) { - XDB::execute("DELETE FROM aliases - WHERE id={?} AND alias={?} - AND type!='a_vie' AND type!='homonyme'", $mr['user_id'], $val); - XDB::execute("UPDATE emails - SET rewrite = '' - WHERE uid = {?} AND rewrite LIKE CONCAT({?}, '@%')", - $mr['user_id'], $val); - fix_bestalias($mr['user_id']); - $page->trigSuccess($val." a été supprimé"); - } - break; - case "activate_fwd": - if (!empty($val)) { - $redirect->modify_one_email($val, true); - } - break; - case "deactivate_fwd": - if (!empty($val)) { - $redirect->modify_one_email($val, false); - } - break; - case "disable_fwd": - $redirect->disable(); - break; - case "enable_fwd": - $redirect->enable(); - break; - case "clean_fwd": - if (!empty($val)) { - $redirect->clean_errors($val); - } + case "activate_fwd": + if (!empty($val)) { + $redirect->modify_one_email($val, true); + } + break; + case "deactivate_fwd": + if (!empty($val)) { + $redirect->modify_one_email($val, false); + } + break; + case "disable_fwd": + $redirect->disable(); + break; + case "enable_fwd": + $redirect->enable(); + break; + case "clean_fwd": + if (!empty($val)) { + $redirect->clean_errors($val); + } + break; + + // Alias actions. + case "add_alias": + global $globals; + + // Splits new alias in user and fqdn. + $alias = trim(Env::v('email')); + if (strpos($alias, '@') !== false) { + list($alias, $domain) = explode('@', $alias); + } else { + $domain = $globals->mail->domain; + } + + // Checks for alias' user validity. + if (!preg_match('/[-a-z0-9\.]+/s', $alias)) { + $page->trigError("'$alias' n'est pas un alias valide"); break; - case "add_alias": - global $globals; - $alias = trim(Env::v('email')); - if (strpos($alias, '@') !== false) { - list($alias, $domain) = explode('@', $alias); + } + + // Eventually adds the alias to the right domain. + if ($domain == $globals->mail->alias_dom || $domain == $globals->mail->alias_dom2) { + $req = new AliasReq($user, $alias, 'Admin request', false); + if ($req->commit()) { + $page->trigSuccess("Nouvel alias '$alias@$domain' attribué"); } else { - $domain = $globals->mail->domain; + $page->trigError("Impossible d'ajouter l'alias '$alias@$domain', il est probablement déjà attribué"); } - if (!preg_match('/[-a-z0-9\.]+/s', $alias)) { - $page->trigError("'$alias' n'est pas un alias valide"); - } - if ($domain == $globals->mail->alias_dom || $domain == $globals->mail->alias_dom2) { - $req = new AliasReq($mr['user_id'], $alias, 'Admin request', false); - if ($req->commit()) { - $page->trigSuccess("Nouvel alias '$alias@$domain' attribué"); - } else { - $page->trigError("Impossible d'ajouter l'alias '$alias@$domain', il est probablement déjà attribué"); - } - } elseif ($domain == $globals->mail->domain || $domain == $globals->mail->domain2) { - if (XDB::execute("INSERT INTO aliases (id,alias,type) VALUES ({?}, {?}, 'alias')", - $mr['user_id'], $alias)) { - $page->trigSuccess("Nouvel alias '$alias' ajouté"); - } else { - $page->trigError("Impossible d'ajouter l'alias '$alias', il est probablement déjà attribué"); - } + } elseif ($domain == $globals->mail->domain || $domain == $globals->mail->domain2) { + $res = XDB::execute("INSERT INTO aliases (id,alias,type) VALUES ({?}, {?}, 'alias')", + $user->id(), $alias); + if ($res) { + $page->trigSuccess("Nouvel alias '$alias' ajouté"); } else { - $page->trigError("Le domaine '$domain' n'est pas valide"); + $page->trigError("Impossible d'ajouter l'alias '$alias', il est probablement déjà attribué"); } - break; - - case "best": - // 'bestalias' is the first bit of the set : 1 - // 255 is the max for flags (8 sets max) - XDB::execute("UPDATE aliases SET flags= flags & (255 - 1) WHERE id={?}", $mr['user_id']); - XDB::execute("UPDATE aliases - SET flags= flags | 1 - WHERE id={?} AND alias={?}", $mr['user_id'], $val); - break; + } else { + $page->trigError("Le domaine '$domain' n'est pas valide"); + } + break; + case "del_alias": + if (!empty($val)) { + XDB::execute("DELETE FROM aliases + WHERE id = {?} AND alias = {?} AND + type NOT IN ('a_vie', 'homonyme')", + $user->id(), $val); + XDB::execute("UPDATE emails + SET rewrite = '' + WHERE uid = {?} AND rewrite LIKE CONCAT({?}, '@%')", + $user->id(), $val); + fix_bestalias($user); + $page->trigSuccess("L'alias '$val' a été supprimé"); + } + break; - // Editer un profil - case "u_edit": - require_once('secure_hash.inc.php'); - $pass_encrypted = Env::v('newpass_clair') != "********" ? hash_encrypt(Env::v('newpass_clair')) : Env::v('passw'); - $naiss = Env::v('naissanceN'); - $deces = Env::v('decesN'); - $perms = Env::v('permsN'); - $prenm = Env::v('prenomN'); - $nom = Env::v('nomN'); - $nomusage = Env::v('nomusageN'); - $promo = Env::i('promoN'); - $sexe = Env::v('sexeN'); - $comm = trim(Env::v('commentN')); - $watch = Env::v('watchN'); - $flags = ''; - if ($sexe) { - $flags = 'femme'; - } - if ($watch) { - if ($flags) { - $flags .= ','; - } - $flags .= 'watch'; - } + case "best": + XDB::execute("UPDATE aliases + SET flags = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', flags, ','), ',bestalias,', ',')) + WHERE id = {?}", $user->id()); + XDB::execute("UPDATE aliases + SET flags = CONCAT_WS(',', IF(flags = '', NULL, flags), 'bestalias') + WHERE id = {?} AND alias = {?}", $user->id(), $val); + + // As having a non-null bestalias value is critical in + // plat/al's code, we do an a posteriori check on the + // validity of the bestalias. + fix_bestalias($user); + break; - if ($watch && !$comm) { - $page->trigError("Il est nécessaire de mettre un commentaire pour surveiller un compte"); - break; - } + // Profile edition. + case "u_edit": + // Loads new values from environment. + require_once('secure_hash.inc.php'); + $pass_encrypted = Env::v('newpass_clair') != "********" ? hash_encrypt(Env::v('newpass_clair')) : Env::v('passw'); + $naiss = Env::v('naissanceN'); + $deces = Env::v('decesN'); + $perms = Env::v('permsN'); + $prenom = Env::v('prenomN'); + $nom = Env::v('nomN'); + $nomusage = Env::v('nomusageN'); + $promo = Env::i('promoN'); + $sexe = Env::v('sexeN'); + $comm = trim(Env::v('commentN')); + $watch = Env::v('watchN'); + + $flags = ($sexe ? 'femme' : ''); + if ($watch) { + $flags .= ($flags ? ',watch' : 'watch'); + } + if ($watch && !$comm) { + $page->trigError("Il est nécessaire de mettre un commentaire pour surveiller un compte"); + break; + } - $watch = 'SELECT naissance, deces, password, perms, nom_usage, - prenom, nom, flags, promo, comment - FROM auth_user_md5 - WHERE user_id = ' . $mr['user_id']; - $res = XDB::query($watch); - $old_fields = $res->fetchOneAssoc(); - $query = "UPDATE auth_user_md5 SET - naissance = '$naiss', - deces = '$deces', - password = '$pass_encrypted', - perms = '$perms', - prenom = '".addslashes($prenm)."', - nom = '".addslashes($nom)."', - nom_usage = '".addslashes($nomusage)."', - flags = '$flags', - promo = $promo, - comment = '".addslashes($comm)."' - WHERE user_id = '{$mr['user_id']}'"; - if ($perms == 'disabled' && $old_fields['perms'] != 'disabled') { - // A user has been banned ==> ensure his php session has been killed - // This solution is ugly and overkill, but, it should be efficient. - kill_sessions(); - } - if (XDB::execute($query)) { - user_reindex($mr['user_id']); + // Fetches fields to watch for changes. + $watch_query = "SELECT naissance, deces, password, perms, nom_usage, + prenom, nom, flags, promo, comment + FROM auth_user_md5 + WHERE user_id = {?}"; + $old_fields = XDB::query($watch_query, $user->id())->fetchOneAssoc(); + + // If user was newly banned, we need to ensure her php session + // is killed. This hack is ugly (and largely overkill); it should + // however suits our needs. + if ($perms == 'disabled' && $old_fields['perms'] != 'disabled') { + kill_sessions(); + + // Also serve a reminder to the admin: disabling an account + // does not deactivate email forwarding. + $page->trigWarning("N'oubliez pas, le cas échéant, de désactiver les redirections et le compte GoogleApps de l'utilisateur."); + } - $res = XDB::query($watch); - $new_fields = $res->fetchOneAssoc(); + // Updates the user profile with the new values. + $res = XDB::execute("UPDATE auth_user_md5 + SET naissance = {?}, deces = {?}, password = {?}, + perms = {?}, prenom = {?}, nom = {?}, nom_usage = {?}, + flags = {?}, promo = {?}, comment = {?} + WHERE user_id = {?}", + $naiss, $deces, $pass_encrypted, + $perms, $prenom, $nom, $nomusage, + $flags, $promo, $comm, $user->id()); + if ($res) { + require_once("user.func.inc.php"); + user_reindex($user->id()); + $new_fields = XDB::query($watch_query, $user->id())->fetchOneAssoc(); + + // Redacts the password in the notification, to avoid transmitting + // sensitive information by email. + $new_fields['password'] = ($old_fields['password'] != $new_fields['password'] ? 'new' : 'old'); + $old_fields['password'] = 'old'; + + // Notifies the admins of the profile update. + $mailer = new PlMailer("admin/useredit.mail.tpl"); + $mailer->assign("admin", S::user()->login()); + $mailer->assign("user", $user->login()); + $mailer->assign('old', $old_fields); + $mailer->assign('new', $new_fields); + $mailer->send(); - $mailer = new PlMailer("admin/useredit.mail.tpl"); - $mailer->assign("admin", S::v('forlife')); - $mailer->assign("user", $mr['forlife']); - $mailer->assign('old', $old_fields); - $mailer->assign('new', $new_fields); - $mailer->send(); + $globals->updateNbIns(); + $page->trigSuccess("La mise à jour a été faite avec succès."); + } else { + $page->trigError("La mise à jour a échoué. S'il te plaît, vérifie les valeurs."); + } - // update number of subscribers (perms or deceased may have changed) - $globals->updateNbIns(); + // Checks for changes, and updates other tables of plat/al. + if (Env::v('nomusageN') != $mr['nom_usage']) { + set_new_usage($user->id(), Env::v('nomusageN'), make_username(Env::v('prenomN'), Env::v('nomusageN'))); + } + if (Env::v('decesN') != $mr['deces']) { + require_once 'notifs.inc.php'; + register_watch_op($user->id(), WATCH_DEATH, $mr['deces']); + user_clear_all_subs($user->id(), false); + } - $page->trigSuccess("updaté correctement."); - } - if (Env::v('nomusageN') != $mr['nom_usage']) { - set_new_usage($mr['user_id'], Env::v('nomusageN'), make_username(Env::v('prenomN'), Env::v('nomusageN'))); - } - if (Env::v('decesN') != $mr['deces']) { - require_once 'notifs.inc.php'; - register_watch_op($mr['user_id'], WATCH_DEATH, $mr['deces']); - user_clear_all_subs($mr['user_id'], false); - } - $r = XDB::query("SELECT *, a.alias AS forlife, - FIND_IN_SET('watch', u.flags) AS watch, FIND_IN_SET('femme', u.flags) AS sexe - FROM auth_user_md5 AS u - LEFT JOIN aliases AS a ON (a.id = u.user_id AND type= 'a_vie') - WHERE u.user_id = {?}", $mr['user_id']); - $mr = $r->fetchOneAssoc(); - - // If GoogleApps is enabled, the user did choose to use synchronized passwords, - // and the password was changed, updates the Google Apps password as well. - if ($globals->mailstorage->googleapps_domain && Env::v('newpass_clair') != "********") { + // Eventually updates the Google Apps account. + if ($globals->mailstorage->googleapps_domain) { + // If the user did choose to use synchronized passwords, + // and the password was changed, updates the Google Apps + // password as well. + if (Env::v('newpass_clair') != "********") { require_once 'googleapps.inc.php'; - $account = new GoogleAppsAccount($mr['user_id'], $mr['forlife']); + $account = new GoogleAppsAccount($user); if ($account->active() && $account->sync_password) { $account->set_password($pass_encrypted); } } + } - // If GoogleApps is enabled, and the user is now disabled, disables the Google Apps account as well. - if ($globals->mailstorage->googleapps_domain && - $new_fields['perms'] == 'disabled' && - $new_fields['perms'] != $old_fields['perms']) { - require_once 'googleapps.inc.php'; - $account = new GoogleAppsAccount($mr['user_id'], $mr['forlife']); - $account->suspend(); - } - break; - // DELETE FROM auth_user_md5 - case "u_kill": - user_clear_all_subs($mr['user_id']); - // update number of subscribers (perms or deceased may have changed) - $globals->updateNbIns(); - $page->trigSuccess("'{$mr['user_id']}' a été désinscrit !"); - $mailer = new PlMailer("admin/useredit.mail.tpl"); - $mailer->assign("admin", S::v('forlife')); - $mailer->assign("user", $mr['forlife']); - $mailer->assign("deletion", true); - $mailer->send(); - break; + // Reloads the user profile, to ensure the latest version will + // be served to the administrator. + $mr = XDB::query($userinfo_query, $user->id())->fetchOneAssoc(); - case "b_edit": - XDB::execute("DELETE FROM forums.innd WHERE uid = {?}", $mr['user_id']); - if (Env::v('write_perm') != "" || Env::v('read_perm') != "" || Env::v('commentaire') != "" ) { - XDB::execute("INSERT INTO forums.innd - SET ipmin = '0', - ipmax = '4294967295', - write_perm = {?}, - read_perm = {?}, - comment = {?}, - priority = '200', - uid = {?}", - Env::v('write_perm'), Env::v('read_perm'), Env::v('comment'), $mr['user_id']); - } - break; - } - } + break; + + // User re-registration. + case "u_kill": + require_once('user.func.inc.php'); + user_clear_all_subs($user->id()); + $globals->updateNbIns(); + $page->trigSuccess($user->login() . ' a été désinscrit !'); + + $mailer = new PlMailer("admin/useredit.mail.tpl"); + $mailer->assign("admin", S::user()->login()); + $mailer->assign("user", $user->login()); + $mailer->assign("deletion", true); + $mailer->send(); + break; - $res = XDB::query("SELECT start, host - FROM logger.sessions - WHERE uid={?} AND suid=0 - ORDER BY start DESC - LIMIT 1", $mr['user_id']); - list($lastlogin,$host) = $res->fetchOneRow(); - $page->assign('lastlogin', $lastlogin); - $page->assign('host', $host); - - $res = XDB::iterator("SELECT alias - FROM virtual - INNER JOIN virtual_redirect USING(vid) - WHERE type = 'user' AND redirect LIKE '" . $mr['forlife'] . "@%'"); - $page->assign('virtuals', $res); - - $page->assign('aliases', XDB::iterator( - "SELECT alias, type='a_vie' AS for_life,FIND_IN_SET('bestalias',flags) AS best,expire - FROM aliases - WHERE id = {?} AND type!='homonyme' - ORDER BY type!= 'a_vie'", $mr["user_id"])); - if ($mr['perms'] != 'pending' && isset($redirect)) { - $page->assign('emails', $redirect->emails); + // Forum ban update. + case "b_edit": + XDB::execute("DELETE FROM #forums#.innd WHERE uid = {?}", $user->id()); + if (Env::v('write_perm') != "" || Env::v('read_perm') != "" || Env::v('commentaire') != "" ) { + XDB::execute("INSERT INTO #forums#.innd + SET ipmin = '0', ipmax = '4294967295', + write_perm = {?}, read_perm = {?}, + comment = {?}, priority = '200', uid = {?}", + Env::v('write_perm'), Env::v('read_perm'), Env::v('comment'), $user->id()); + } + break; } + } - $page->assign('mr',$mr); + // Displays last login and last host information. + $res = XDB::query("SELECT start, host + FROM #logger#.sessions + WHERE uid = {?} AND suid = 0 + ORDER BY start DESC + LIMIT 1", $user->id()); + list($lastlogin,$host) = $res->fetchOneRow(); + $page->assign('lastlogin', $lastlogin); + $page->assign('host', $host); + + // Display active aliases. + $page->assign('virtuals', XDB::iterator( + "SELECT alias + FROM virtual + INNER JOIN virtual_redirect USING (vid) + WHERE type = 'user' AND (redirect = {?} OR redirect = {?})", + $user->forlifeEmail(), + // TODO: remove this über-ugly hack. The issue is that you need + // to remove all @m4x.org addresses in virtual_redirect first. + $user->login() . '@' . $globals->mail->domain2)); + + $page->assign('aliases', XDB::iterator( + "SELECT alias, type='a_vie' AS for_life,FIND_IN_SET('bestalias',flags) AS best,expire + FROM aliases + WHERE id = {?} AND type != 'homonyme' + ORDER BY type != 'a_vie'", $user->id())); + + // Displays email redirection and the general profile. + if ($registered && $redirect) { + $page->assign('emails', $redirect->emails); + } - // Bans forums - $res = XDB::query("SELECT write_perm, read_perm, comment - FROM forums.innd - WHERE uid = {?}", $mr['user_id']); - $bans = $res->fetchOneAssoc(); - $page->assign('bans', $bans); + $page->assign('mr', $mr); + $page->assign('user', $user); + + // Displays forum bans. + $res = XDB::query("SELECT write_perm, read_perm, comment + FROM #forums#.innd + WHERE uid = {?}", $user->id()); + $bans = $res->fetchOneAssoc(); + $page->assign('bans', $bans); + } + + function getHruid($line, $key, $relation) + { + $prenom = CSVImporter::getValue($line, 'prenom', $relation['prenom']); + $nom = CSVImporter::getValue($line, 'nom', $relation['nom']); + $promo = CSVImporter::getValue($line, 'promo', $relation['promo']); + + if ($prenom != 'NULL' && $nom != 'NULL' && $promo != 'NULL') { + return make_forlife($prenom, $nom, $promo); } + return null; } - function getMatricule($line, $key) + function getMatricule($line, $key, $relation) { $mat = $line['matricule']; $year = intval(substr($mat, 0, 3)); @@ -702,7 +728,7 @@ class AdminModule extends PLModule $action = Env::v('valid_promo') == 'Ajouter des membres' ? 'add' : 'ax'; pl_redirect('admin/promo/' . $action . '/' . Env::i('promo')); } else { - $page->trigError('Promo non valide'); + $page->trigError('Promotion non valide.'); } } @@ -714,12 +740,13 @@ class AdminModule extends PLModule } $importer = new CSVImporter('auth_user_md5', 'matricule'); - $importer->registerFunction('matricule', 'matricle Ecole vers X.org', array($this, 'getMatricule')); + $importer->registerFunction('matricule', 'matricule Ecole vers X.org', array($this, 'getMatricule')); switch ($action) { case 'add': - $fields = array('nom', 'nom_ini', 'prenom', 'naissance_ini', + $fields = array('hruid', 'nom', 'nom_ini', 'prenom', 'naissance_ini', 'prenom_ini', 'promo', 'promo_sortie', 'flags', 'matricule', 'matricule_ax', 'perms'); + $importer->forceValue('hruid', array($this, 'getHruid')); $importer->forceValue('promo', $promo); $importer->forceValue('promo_sortie', $promo + 3); break; @@ -730,7 +757,8 @@ class AdminModule extends PLModule $importer->apply($page, "admin/promo/$action/$promo", $fields); } - function handler_homonyms(&$page, $op = 'list', $target = null) { + function handler_homonyms(&$page, $op = 'list', $target = null) + { $page->changeTpl('admin/homonymes.tpl'); $page->setTitle('Administration - Homonymes'); require_once("homonymes.inc.php"); @@ -866,61 +894,50 @@ class AdminModule extends PLModule $page->setTitle('Administration - Décédés'); $res = XDB::iterator( - "SELECT u.promo, u.nom, u.prenom, u.deces, u.matricule_ax, a.alias, DATE(MAX(s.start)) AS last - FROM auth_user_md5 AS u - LEFT JOIN aliases AS a ON (a.id = u.user_id AND a.type = 'a_vie') - LEFT JOIN logger.sessions AS s ON (s.uid = u.user_id AND suid = 0) + "SELECT u.promo, u.nom, u.prenom, u.deces, u.hruid, DATE(MAX(s.start)) AS last + FROM #x4dat#.auth_user_md5 AS u + LEFT JOIN #logger#.sessions AS s ON (s.uid = u.user_id AND suid = 0) WHERE perms IN ('admin', 'user') AND deces <> 0 GROUP BY u.user_id ORDER BY u.promo, u.nom"); $page->assign('dead', $res); } - function handler_synchro_ax(&$page, $user = null, $action = null) { + function handler_synchro_ax(&$page, $login = null, $action = null) { $page->changeTpl('admin/synchro_ax.tpl'); $page->setTitle('Administration - Synchro AX'); + // Checks for synchronization requirements. require_once('synchro_ax.inc.php'); - if (is_ax_key_missing()) { $page->assign('no_private_key', true); $page->run(); } - require_once('user.func.inc.php'); - - if ($user) - $login = get_user_forlife($user); - - if (Env::has('user')) { - $login = get_user_forlife(Env::v('user')); - if ($login === false) { - return; - } + // Determines user identity using environment. + if ($login) { + $user = User::get($login); + } else if (Env::has('user')) { + $user = User::get(Env::v('user')); + } else if (Env::has('mat')) { + $res = XDB::query("SELECT user_id FROM auth_user_md5 WHERE matricule = {?}", Env::i('mat')); + $user = User::get($res->fetchOneCell()); + } else { + return; } - if (Env::has('mat')) { - $res = XDB::query( - "SELECT alias - FROM aliases AS a - INNER JOIN auth_user_md5 AS u ON (a.id=u.user_id AND a.type='a_vie') - WHERE matricule={?}", Env::i('mat')); - $login = $res->fetchOneCell(); + // Finally synchronizes the AX and plat/al information. + if ($action == 'import') { + ax_synchronize($user->login(), S::v('uid')); } - if ($login) { - if ($action == 'import') { - ax_synchronize($login, S::v('uid')); - } - // get details from user, but looking only info that can be seen by ax - $user = get_user_details($login, S::v('uid'), 'ax'); - $userax= get_user_ax($user['matricule_ax']); - require_once 'profil.func.inc.php'; - $diff = diff_user_details($userax, $user, 'ax'); - - $page->assign('x', $user); - $page->assign('diff', $diff); - } + require_once 'profil.func.inc.php'; + $userxorg = get_user_details($user->login(), S::v('uid'), 'ax'); + $userax = get_user_ax($userxorg['matricule_ax']); + $diff = diff_user_details($userax, $userxorg, 'ax'); + + $page->assign('x', $userxorg); + $page->assign('diff', $diff); } function handler_validate(&$page, $action = 'list', $id = null) @@ -1026,7 +1043,7 @@ class AdminModule extends PLModule function handler_logger_actions(&$page, $action = 'list', $id = null) { $page->setTitle('Administration - Actions'); $page->assign('title', 'Gestion des actions de logger'); - $table_editor = new PLTableEditor('admin/logger/actions','logger.actions','id'); + $table_editor = new PLTableEditor('admin/logger/actions','#logger#.actions','id'); $table_editor->describe('text','intitulé',true); $table_editor->describe('description','description',true); $table_editor->apply($page, $action, $id); @@ -1047,7 +1064,7 @@ class AdminModule extends PLModule { if (S::v('core_rss_hash')) { $page->setRssLink('Changement Récents', - '/Site/AllRecentChanges?action=rss&user=' . S::v('forlife') . '&hash=' . S::v('core_rss_hash')); + '/Site/AllRecentChanges?action=rss&user=' . S::v('hruid') . '&hash=' . S::v('core_rss_hash')); } // update wiki perms @@ -1107,7 +1124,6 @@ class AdminModule extends PLModule } $page->changeTpl('admin/wiki.tpl'); - $page->addJsLink('jquery.js'); $page->assign('wiki_pages', $wiki_tree); $page->assign('perms_opts', $perms); } @@ -1156,18 +1172,18 @@ class AdminModule extends PLModule $sql = "SELECT w.ip, IF(s.ip IS NULL, IF(w.ip = s2.ip, s2.host, s2.forward_host), IF(w.ip = s.ip, s.host, s.forward_host)), - w.mask, w.detection, w.state, a.alias AS forlife - FROM ip_watch AS w - LEFT JOIN logger.sessions AS s ON (s.ip = w.ip) - LEFT JOIN logger.sessions AS s2 ON (s2.forward_ip = w.ip) - LEFT JOIN aliases AS a ON (a.id = s.uid AND a.type = 'a_vie') - GROUP BY w.ip, a.alias - ORDER BY w.state, w.ip, a.alias"; + w.mask, w.detection, w.state, u.hruid + FROM #x4dat#.ip_watch AS w + LEFT JOIN #logger#.sessions AS s ON (s.ip = w.ip) + LEFT JOIN #logger#.sessions AS s2 ON (s2.forward_ip = w.ip) + LEFT JOIN #x4dat#.auth_user_md5 AS u ON (u.user_id = s.uid) + GROUP BY w.ip, u.hruid + ORDER BY w.state, w.ip, u.hruid"; $it = Xdb::iterRow($sql); $table = array(); $props = array(); - while (list($ip, $host, $mask, $date, $state, $forlife) = $it->next()) { + while (list($ip, $host, $mask, $date, $state, $hruid) = $it->next()) { $ip = uint_to_ip($ip); $mask = uint_to_ip($mask); if (count($props) == 0 || $props['ip'] != $ip) { @@ -1179,9 +1195,9 @@ class AdminModule extends PLModule 'host' => $host, 'detection' => $date, 'state' => $state, - 'users' => array($forlife)); + 'users' => array($hruid)); } else { - $props['users'][] = $forlife; + $props['users'][] = $hruid; } } if (count($props) > 0) { @@ -1190,18 +1206,18 @@ class AdminModule extends PLModule $page->assign('table', $table); } elseif ($action == 'edit') { $sql = "SELECT w.detection, w.state, w.last, w.description, w.mask, - a1.alias AS edit, a2.alias AS forlife, s.host - FROM ip_watch AS w - LEFT JOIN aliases AS a1 ON (a1.id = w.uid AND a1.type = 'a_vie') - LEFT JOIN logger.sessions AS s ON (w.ip = s.ip) - LEFT JOIN aliases AS a2 ON (a2.id = s.uid AND a2.type = 'a_vie') + u1.hruid AS edit, u2.hruid AS hruid, s.host + FROM #x4dat#.ip_watch AS w + LEFT JOIN #x4dat#.auth_user_md5 AS u1 ON (u1.user_id = w.uid) + LEFT JOIN #logger#.sessions AS s ON (w.ip = s.ip) + LEFT JOIN #x4dat#.auth_user_md5 AS u2 ON (u2.user_id = s.uid) WHERE w.ip = {?} - GROUP BY a2.alias - ORDER BY a2.alias"; + GROUP BY u2.hruid + ORDER BY u2.hruid"; $it = Xdb::iterRow($sql, ip_to_uint($ip)); $props = array(); - while (list($detection, $state, $last, $description, $mask, $edit, $forlife, $host) = $it->next()) { + while (list($detection, $state, $last, $description, $mask, $edit, $hruid, $host) = $it->next()) { if (count($props) == 0) { $props = array('ip' => $ip, 'mask' => uint_to_ip($mask), @@ -1211,9 +1227,9 @@ class AdminModule extends PLModule 'last' => $last, 'description' => $description, 'edit' => $edit, - 'users' => array($forlife)); + 'users' => array($hruid)); } else { - $props['users'][] = $forlife; + $props['users'][] = $hruid; } } $page->assign('ip', $props); @@ -1236,6 +1252,127 @@ class AdminModule extends PLModule sort($icons); $page->assign('icons', $icons); } + + function handler_accounts(&$page) + { + $page->changeTpl('admin/accounts.tpl'); + $page->assign('disabled', XDB::iterator('SELECT u.nom, u.prenom, u.promo, u.comment, u.hruid + FROM auth_user_md5 AS u + WHERE perms = \'disabled\' + ORDER BY nom, prenom')); + $page->assign('admins', XDB::iterator('SELECT u.nom, u.prenom, u.promo, u.hruid + FROM auth_user_md5 AS u + WHERE perms = \'admin\' + ORDER BY nom, prenom')); + } + + function handler_jobs(&$page, $id = -1) + { + $page->changeTpl('admin/jobs.tpl'); + + if (Env::has('search')) { + $res = XDB::query("SELECT e.id, e.name, e.acronym + FROM profile_job_enum AS e + WHERE e.name LIKE CONCAT('% ', {?}, '%') OR e.acronym LIKE CONCAT('% ', {?}, '%')", + Env::t('job'), Env::t('job')); + + if ($res->numRows() <= 20) { + $page->assign('jobs', $res->fetchAllAssoc()); + } else { + $page->trigError("Il y a trop d'entreprises correspondant à ton choix. Affine-le !"); + } + + $page->assign('askedJob', Env::v('job')); + return; + } + + if (Env::has('edit')) { + // TODO: use address and phone classes to update profile_job_enum and profile_phones once they are done. + + S::assert_xsrf_token(); + $selectedJob = Env::has('selectedJob'); + + XDB::execute("DELETE FROM profile_phones + WHERE uid = {?} AND link_type = 'hq'", + $id); + XDB::execute("DELETE FROM profile_addresses + WHERE jobid = {?} AND type = 'hq'", + $id); + XDB::execute('DELETE FROM profile_job_enum + WHERE id = {?}', + $id); + + if (Env::has('change')) { + XDB::execute('UPDATE profile_job + SET jobid = {?} + WHERE jobid = {?}', + Env::i('newJobId'), $id); + + $page->trigSuccess("L'entreprise a bien été remplacée."); + } else { + require_once 'profil.func.inc.php'; + require_once 'geocoding.inc.php'; + + $display_tel = format_display_number(Env::v('tel'), $error_tel); + $display_fax = format_display_number(Env::v('fax'), $error_fax); + $gmapsGeocoder = new GMapsGeocoder(); + $address = array('text' => Env::t('address')); + $address = $gmapsGeocoder->getGeocodedAddress($address); + Geocoder::getAreaId($address, 'administrativeArea'); + Geocoder::getAreaId($address, 'subAdministrativeArea'); + Geocoder::getAreaId($address, 'locality'); + + XDB::execute('UPDATE profile_job_enum + SET name = {?}, acronym = {?}, url = {?}, email = {?}, + NAF_code = {?}, AX_code = {?}, holdingid = {?} + WHERE id = {?}', + Env::t('name'), Env::t('acronym'), Env::t('url'), Env::t('email'), + Env::t('NAF_code'), Env::i('AX_code'), Env::i('holdingId'), $id); + + XDB::execute("INSERT INTO profile_phones (uid, link_type, link_id, tel_id, tel_type, + search_tel, display_tel, pub) + VALUES ({?}, 'hq', 0, 0, 'fixed', {?}, {?}, 'public'), + ({?}, 'hq', 0, 1, 'fax', {?}, {?}, 'public')", + $id, format_phone_number(Env::v('tel')), $display_tel, + $id, format_phone_number(Env::v('fax')), $display_fax); + + XDB::execute("INSERT INTO profile_addresses (jobid, type, id, accuracy, + text, postalText, postalCode, localityId, + subAdministrativeAreaId, administrativeAreaId, + countryId, latitude, longitude, updateTime, + north, south, east, west) + VALUES ({?}, 'hq', 0, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, + {?}, {?}, FROM_UNIXTIME({?}), {?}, {?}, {?}, {?})", + $id, $address['accuracy'], $address['text'], $address['postalText'], + $address['postalCode'], $address['localityId'], + $address['subAdministrativeAreaId'], $address['administrativeAreaId'], + $address['countryId'], $address['latitude'], $address['longitude'], + $address['updateTime'], $address['north'], $address['south'], + $address['east'], $address['west']); + + $page->trigSuccess("L'entreprise a bien été mise à jour."); + } + } + + if (!Env::has('change') && $id != -1) { + $res = XDB::query("SELECT e.id, e.name, e.acronym, e.url, e.email, e.NAF_code, e.AX_code, + h.id AS holdingId, h.name AS holdingName, h.acronym AS holdingAcronym, + t.display_tel AS tel, f.display_tel AS fax, a.text AS address + FROM profile_job_enum AS e + LEFT JOIN profile_job_enum AS h ON (e.holdingid = h.id) + LEFT JOIN profile_phones AS t ON (t.uid = e.id AND link_type = 'hq' AND tel_id = 0) + LEFT JOIN profile_phones AS f ON (f.uid = e.id AND link_type = 'hq' AND tel_id = 1) + LEFT JOIN profile_addresses AS a ON (a.jobid = e.id AND a.type = 'hq') + WHERE e.id = {?}", + $id); + + if ($res->numRows() == 0) { + $page->trigError('Auncune entreprise ne correspond à cet identifiant.'); + } else { + $page->assign('selectedJob', $res->fetchOneAssoc()); + } + } + } } // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: