Adds support for the user interface of Google Apps:
authorVincent Zanotti <vincent.zanotti@polytechnique.org>
Sun, 9 Mar 2008 19:08:43 +0000 (20:08 +0100)
committerVincent Zanotti <vincent.zanotti@polytechnique.org>
Mon, 10 Mar 2008 13:41:05 +0000 (14:41 +0100)
* Updates the gapps cron to send out emails on account creation.
* Adds an user page for preferences updates (account creation, account suspension, password change, ...).
* Adds a new mail storage backend, and updates the emails/redirect and emails pages.
* Adds a validation class for Google Apps accounts unsuspension.

Signed-off-by: Vincent Zanotti <vincent.zanotti@polytechnique.org>
18 files changed:
bin/cron/google_apps.php
configs/mails.conf
configs/platal.cron.in
configs/platal.ini
htdocs/xorg.php
include/emails.inc.php
include/googleapps.inc.php [new file with mode: 0644]
include/validations.inc.php
include/validations/googleapps.inc.php [new file with mode: 0644]
modules/email.php
modules/googleapps.php [new file with mode: 0644]
templates/emails/index.tpl
templates/emails/redirect.tpl
templates/googleapps/create.mail.tpl [new file with mode: 0644]
templates/googleapps/index.tpl [new file with mode: 0644]
templates/googleapps/unsuspend.mail.tpl [new file with mode: 0644]
templates/include/form.valid.gapps-unsuspend.tpl [new file with mode: 0644]
upgrade/0.9.16/07_google_apps.sql [new file with mode: 0644]

index 76cfcc5..698968e 100755 (executable)
  *  Foundation, Inc.,                                                      *
  *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
  ***************************************************************************/
-/* Updates the gapps_accounts table with Plat/al information. */
 
-require('./connect.db.inc.php');
-if (!$globals->googleapps->domain) {
+// Updates the gapps_accounts table with Plat/al information.
+// Cleans-up the job queue, and execute post-queue hooks.
+
+require_once('../connect.db.inc.php');
+require_once('../../classes/plmailer.php');
+require_once('../../include/googleapps.inc.php');
+if (!$globals->mailstorage->googleapps_domain) {
   exit;
 }
 
 /* Updates the l_userid parameter for newer user accounts. */
-$res = XDB::iterator("SELECT  g.g_account_name, a.id
-                        FROM  gapps_accounts AS g
-                   LEFT JOIN  aliases as a ON (a.alias = g.g_account_name AND a.type = 'a_vie')
-                       WHERE  (g.l_userid IS NULL OR g.l_userid <= 0) AND
-                              a.id IS NOT NULL");
+$res = XDB::iterator(
+    "SELECT  g.g_account_name, a.id
+       FROM  gapps_accounts AS g
+  LEFT JOIN  aliases as a ON (a.alias = g.g_account_name AND a.type = 'a_vie')
+      WHERE  (g.l_userid IS NULL OR g.l_userid <= 0) AND a.id IS NOT NULL");
+while ($account = $res->next()) {
+    XDB::execute(
+        "UPDATE  gapps_accounts
+            SET  l_userid = {?}
+          WHERE  g_account_name = {?}",
+        $account['id'], $account['g_account_name']);
+}
+
+/* Emits a warning for GApps accounts without local user_id. */
+$res = XDB::iterator(
+    "SELECT  g.g_account_name
+       FROM  gapps_accounts AS g
+  LEFT JOIN  aliases as a ON (a.alias = g.g_account_name AND a.type = 'a_vie')
+      WHERE  (g.l_userid IS NULL OR g.l_userid <= 0) AND a.id IS NULL");
 while ($account = $res->next()) {
-  XDB::execute("UPDATE  gapps_accounts
-                   SET  l_userid = {?}
-                 WHERE  g_account_name = {?}",
-               $account['id'], $account['g_account_name']);
+    if (!preg_match("/^admin-/", $account['g_account_name'])) {
+        printf("Warning: GApps account '%s' has no local user_id.\n", $account['g_account_name']);
+    }
 }
 
+/* Retrieves successful job queues for post-queue processing. */
+$res = XDB::iterator(
+    "SELECT  q_id, q_recipient_id, j_type, j_parameters
+       FROM  gapps_queue
+      WHERE  p_status = 'success' AND q_recipient_id IS NOT NULL");
+while ($job = $res->next()) {
+    if ($job['j_type'] == 'u_create') {
+        post_queue_u_create($job);
+    } else if ($job['j_type'] == 'u_update') {
+        post_queue_u_update($job);
+    }
+}
+
+/* Removes successful jobs, and old failed jobs. */
+XDB::execute(
+    "DELETE  FROM gapps_queue
+      WHERE  p_status = 'success' OR
+             (p_status = 'hardfail' AND p_end_date < DATE_SUB(NOW(), INTERVAL 15 DAY))");
+
 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
 ?>
index 40c08c0..061588e 100644 (file)
@@ -47,3 +47,6 @@ from="Polytechnique.org" <support@polytechnique.org>
 
 [carnet]
 from="Carnet Polytechnicien <support_carnet@polytechnique.org>"
+
+[googleapps]
+from="Polytechnique.org" <support@polytechnique.org>
index 4c57ba8..74f51c2 100644 (file)
@@ -31,6 +31,6 @@ WD=/home/web/prod/platal/bin/cron
 * * * * *       web     cd $WD; ./cron_ml_moderate.php > /dev/null
 
 # synchronisation google apps - plat/al
-0 3 * * *      web     cd $WD; ./google_apps.php
+12,42 * * * *  web     cd $WD; ./google_apps.php
 
 # vim:set noet syntax=crontab ts=8 sw=8 sts=8 enc=utf-8:
index e5ac94f..b1aaf00 100644 (file)
@@ -44,6 +44,7 @@ alias_dom2 = ""
 [MailStorage]
 imap_active = 0
 googleapps_active = 0
+googleapps_domain = ""
 
 [Manageurs]
 authorized_ips       = "129.104.30.32 129.104.30.33 213.251.145.200"
index f0faa4e..11d5ac1 100644 (file)
@@ -28,7 +28,7 @@ if (!($path = Env::v('n')) || ($path{0} < 'A' || $path{0} > 'Z')) {
                          'geoloc', 'lists', 'marketing', 'payment', 'platal',
                          'profile', 'register', 'search', 'stats', 'admin',
                          'newsletter', 'axletter', 'bandeau', 'survey',
-                         'gadgets');
+                         'gadgets', 'googleapps');
     $platal->run();
 
     exit;
index bf1ba1a..4909b68 100644 (file)
@@ -432,6 +432,7 @@ class MailStorage {
         XDB::execute("UPDATE  auth_user_md5
                          SET  mail_storage = {?}
                        WHERE  user_id = {?}", $this->storages->flags(), $this->uid);
+        return true;
     }
 
     public function enable()
@@ -440,6 +441,12 @@ class MailStorage {
         XDB::execute("UPDATE  auth_user_md5
                          SET  mail_storage = {?}
                        WHERE  user_id = {?}", $this->storages->flags(), $this->uid);
+        return true;
+    }
+
+    public function active()
+    {
+        return $this->storages->hasFlag($this->name);
     }
 }
 
@@ -450,5 +457,21 @@ class MailStorageIMAP extends MailStorage {
     }
 }
 
+class MailStorageGoogleApps extends MailStorage {
+    public function __construct($_uid)
+    {
+        parent::__construct($_uid, 'googleapps');
+    }
+    
+    public function disable() {
+        $redirect = new Redirect(S::v('uid'));
+        if (!$redirect->other_active(NULL)) {
+            return false;
+        }
+        
+        return parent::disable();
+    }
+}
+
 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
 ?>
diff --git a/include/googleapps.inc.php b/include/googleapps.inc.php
new file mode 100644 (file)
index 0000000..abfa384
--- /dev/null
@@ -0,0 +1,398 @@
+<?php
+/***************************************************************************
+ *  Copyright (C) 2003-2008 Polytechnique.org                              *
+ *  http://opensource.polytechnique.org/                                   *
+ *                                                                         *
+ *  This program is free software; you can redistribute it and/or modify   *
+ *  it under the terms of the GNU General Public License as published by   *
+ *  the Free Software Foundation; either version 2 of the License, or      *
+ *  (at your option) any later version.                                    *
+ *                                                                         *
+ *  This program is distributed in the hope that it will be useful,        *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ *  GNU General Public License for more details.                           *
+ *                                                                         *
+ *  You should have received a copy of the GNU General Public License      *
+ *  along with this program; if not, write to the Free Software            *
+ *  Foundation, Inc.,                                                      *
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
+ ***************************************************************************/
+
+// Checks the admin status of the @p account_name.
+function is_google_apps_administrator($account_name) {
+    static $last_account_name = null;
+    static $last_result = null;
+
+    if ($last_account_name == $account_name) {
+        return $last_result;
+    }
+
+    $res = XDB::query(
+        "SELECT  g_admin
+           FROM  gapps_accounts
+          WHERE  g_account_name = {?} AND g_status = 'active'",
+        $account_name);
+    $last_account_name = $account_name;
+    $last_result = ($res->numRows() > 0 ? (bool)$res->fetchOneRow() : false);
+    return $last_result;
+}
+
+// Post-queue job cleanup functions; they are used to update the plat/al database
+// when a specific Google Apps queue job enters 'success' state.
+function post_queue_u_create($job) {
+    global $globals;
+
+    // Retrieves the user parameters (userid and forlife).
+    $parameters = json_decode($job['j_parameters'], true);
+    $forlife = isset($parameters['username']) ? $parameters['username'] : null;
+    $userid = $job['q_recipient_id'];
+    if (!$forlife || !$userid) {
+        return;
+    }
+
+    // Adds a redirection to the Google Apps delivery address.
+    $account = new GoogleAppsAccount($userid, $forlife);
+    if ($account->activate_mail_redirection) {
+        require_once('emails.inc.php');
+        $storage = new MailStorageGoogleApps($userid);
+        $storage->enable();
+    }
+
+    // Sends an email to the account owner.
+    $res = XDB::query(
+        "SELECT  FIND_IN_SET('femme', u.flags), prenom
+           FROM  auth_user_md5 AS u
+     INNER JOIN  aliases AS a ON (a.id = u.user_id)
+          WHERE  a.alias = {?}",
+        $forlife);
+    list($sexe, $prenom) = $res->fetchOneRow();
+
+    $mailer = new PlMailer('googleapps/create.mail.tpl');
+    $mailer->assign('account', $account);
+    $mailer->assign('email', $forlife . '@' . $globals->mail->domain);
+    $mailer->assign('googleapps_domain', $globals->mailstorage->googleapps_domain);
+    $mailer->assign('prenom', $prenom);
+    $mailer->assign('sexe', $sexe);
+    $mailer->send();
+}
+
+function post_queue_u_update($job) {
+    global $globals;
+
+    // If the u_update job was an unsuspend request, re-adds the redirection
+    // to the Google Apps delivery address, provided the account is active (it might
+    // have been deleted between the unsuspension and the post-queue processing).
+    $parameters = json_decode($job['j_parameters'], true);
+    $forlife = isset($parameters['username']) ? $parameters['username'] : null;
+    $userid = $job['q_recipient_id'];
+    if (!$forlife || !$userid) {
+        return;
+    }
+
+    if (isset($parameters['suspended']) && $parameters['suspended'] == false) {
+        require_once('emails.inc.php');
+        $account = new GoogleAppsAccount($userid, $forlife);
+        if ($account->g_status == 'active') {
+            // Re-adds the email redirection (if the user did request it).
+            if ($account->activate_mail_redirection) {
+                $storage = new MailStorageGoogleApps($userid);
+                $storage->enable();
+            }
+
+            // Sends an email to the account owner.
+            $res = XDB::query(
+                "SELECT  FIND_IN_SET('femme', u.flags), prenom
+                   FROM  auth_user_md5 AS u
+             INNER JOIN  aliases AS a ON (a.id = u.user_id)
+                  WHERE  a.alias = {?}",
+                $forlife);
+            list($sexe, $prenom) = $res->fetchOneRow();
+
+            $mailer = new PlMailer('googleapps/unsuspend.mail.tpl');
+            $mailer->assign('account', $account);
+            $mailer->assign('email', $forlife . '@' . $globals->mail->domain);
+            $mailer->assign('prenom', $prenom);
+            $mailer->assign('sexe', $sexe);
+            $mailer->send();
+        }
+    }
+}
+
+// Reprensentation of an SQL-stored Google Apps account.
+class GoogleAppsAccount
+{
+    private $uid;
+    public $g_account_name;
+
+    public $sync_password;
+    public $activate_mail_redirection;
+    public $g_status;
+    public $g_suspension;
+    public $r_disk_usage;
+    public $r_creation;
+    public $r_last_login;
+    public $r_last_webmail;
+    public $reporting_date;
+
+    public $pending_create;
+    public $pending_delete;
+    public $pending_update;
+    public $pending_update_admin;
+    public $pending_update_other;
+    public $pending_update_password;
+    public $pending_update_suspension;
+
+    public $pending_validation_unsuspend;
+
+    public function __construct($uid, $account_name)
+    {
+        $this->uid = $uid;
+        $this->g_account_name = $account_name;
+        $this->g_status = NULL;
+
+        $res = XDB::query(
+            "SELECT  l_sync_password, l_activate_mail_redirection,
+                     g_account_name, g_status, g_suspension, r_disk_usage,
+                     UNIX_TIMESTAMP(r_creation) as r_creation,
+                     UNIX_TIMESTAMP(r_last_login) as r_last_login,
+                     UNIX_TIMESTAMP(r_last_webmail) as r_last_webmail
+               FROM  gapps_accounts
+              WHERE  g_account_name = {?}",
+            $account_name);
+        if ($account = $res->fetchOneAssoc()) {
+            $this->sync_password = $account['l_sync_password'];
+            $this->activate_mail_redirection = $account['l_activate_mail_redirection'];
+            $this->g_status = $account['g_status'];
+            $this->g_suspension = $account['g_suspension'];
+            $this->r_disk_usage = $account['r_disk_usage'];
+            $this->r_creation = $account['r_creation'];
+            $this->r_last_login = $account['r_last_webmail'];
+            $this->r_last_webmail = $account['r_last_webmail'];
+
+            $this->load_pending_counts();
+            $this->load_pending_validations();
+            if ($this->pending_update) {
+                $this->load_pending_updates();
+            }
+
+            $res = XDB::query("SELECT MAX(date) FROM gapps_reporting");
+            $this->reporting_date = $res->fetchOneCell();
+        }
+    }
+
+    // Account object initialization methods.
+    private function load_pending_counts()
+    {
+        // Determines if changes to the Google Account are currently waiting
+        // in the Google Apps queue.
+        $res = XDB::query(
+            "SELECT  SUM(j_type = 'u_create') AS pending_create,
+                     SUM(j_type = 'u_update') AS pending_update,
+                     SUM(j_type = 'u_delete') AS pending_delete
+               FROM  gapps_queue
+              WHERE  q_recipient_id = {?} AND
+                     p_status IN ('idle', 'active', 'softfail')
+           GROUP BY  j_type",
+            $this->uid);
+        $pending = $res->fetchOneAssoc();
+        $this->pending_create = $pending['pending_create'];
+        $this->pending_update = $pending['pending_update'];
+        $this->pending_delete = $pending['pending_delete'];
+
+        $this->pending_update_admin = false;
+        $this->pending_update_other = false;
+        $this->pending_update_password = false;
+        $this->pending_update_suspension = false;
+    }
+
+    private function load_pending_validations()
+    {
+        require_once('validations.inc.php');
+        $this->pending_validation_unsuspend =
+            Validate::get_typed_requests_count($this->uid, 'gapps-unsuspend');
+    }
+
+    private function load_pending_updates()
+    {
+        // If updates are pending, determines their nature (more specifically:
+        // determines which part of the account is concerned).
+        $res = XDB::iterator(
+            "SELECT  j_parameters
+               FROM  gapps_queue
+              WHERE  q_recipient_id = {?} AND
+                     p_status IN ('idle', 'active', 'softfail') AND
+                     j_type = 'u_update'",
+            $this->uid);
+        while ($update = $res->next()) {
+            $update_data = json_decode($update["j_parameters"], true);
+
+            if (isset($update_data["suspended"])) {
+                $this->pending_update_suspension = true;
+            } elseif (isset($update_data["password"])) {
+                $this->pending_update_password = true;
+            } elseif (isset($update_data["admin"])) {
+                $this->pending_update_admin = true;
+            } else {
+                $this->pending_update_other = true;
+            }
+        }
+    }
+
+    // Creates a queue job of the @p type, for the user represented by this
+    // GoogleAppsAccount object, using @p parameters.
+    private function create_queue_job($type, $parameters) {
+        $parameters["username"] = $this->g_account_name;
+        XDB::execute(
+            "INSERT  INTO gapps_queue
+                SET  q_owner_id = {?}, q_recipient_id = {?},
+                     p_entry_date = NOW(), p_notbefore_date = NOW(),
+                     p_priority = 'normal',
+                     j_type = {?}, j_parameters = {?}",
+            S::v('uid'),
+            $this->uid,
+            $type,
+            json_encode($parameters));
+    }
+
+    // Changes the GoogleApps password.
+    public function set_password($password) {
+        if ($this->g_status == NULL || $this->g_status == 'unprovisioned') {
+            return;
+        }
+
+        if (!$this->pending_update_password) {
+            $this->create_queue_job('u_update', array('password' => $password));
+        }
+    }
+
+    // Changes the password synchronization status ("sync = true" means that the
+    // Polytechnique.org password will be replicated to the Google Apps account).
+    public function set_password_sync($sync) {
+        if ($this->g_status == NULL || $this->g_status == 'unprovisioned') {
+            return;
+        }
+
+        $this->sync_password = $sync;
+        XDB::execute(
+            "UPDATE  gapps_accounts
+                SET  l_sync_password = {?}
+              WHERE  g_account_name = {?}",
+            $sync,
+            $this->g_account_name);
+    }
+
+    // Suspends the Google Apps account.
+    public function suspend() {
+        if ($this->g_status == NULL || $this->g_status == 'unprovisioned') {
+            return;
+        }
+
+        if (!$this->pending_update_suspension) {
+            $this->create_queue_job('u_update', array('suspended' => true));
+            $this->pending_update_suspension = true;
+        }
+    }
+
+    // Adds an unsuspension request to the validation queue (used on user-request).
+    public function unsuspend($activate_mail_redirection = NULL) {
+        if ($this->g_status == NULL || $this->g_status == 'unprovisioned') {
+            return;
+        }
+        if ($activate_mail_redirection !== NULL) {
+            $this->activate_mail_redirection = $activate_mail_redirection;
+            XDB::execute(
+                "UPDATE  gapps_accounts
+                    SET  l_activate_mail_redirection = {?}
+                  WHERE  g_account_name = {?}",
+                $activate_mail_redirection);
+        }
+
+        if (!$this->pending_update_suspension && !$this->pending_validation_unsuspend) {
+            require_once('validations.inc.php');
+            $unsuspend = new GoogleAppsUnsuspendReq($this->uid);
+            $unsuspend->submit();
+            $this->pending_validation_unsuspend = true;
+        }
+    }
+
+    // Unsuspends the Google Apps account (used on admin-request, or on validation of
+    // an user-request).
+    public function do_unsuspend() {
+        if ($this->g_status == NULL || $this->g_status == 'unprovisioned') {
+            return;
+        }
+
+        if (!$this->pending_update_suspension) {
+            if ($this->sync_password) {
+                $res = XDB::query(
+                    "SELECT  password
+                       FROM  auth_user_md5
+                      WHERE  user_id = {?}",
+                    $this->uid);
+                $password = ($res->numRows() > 0 ? $res->fetchOneCell() : false);
+            } else {
+                $password = false;
+            }
+
+            if ($password) {
+                $this->create_queue_job('u_update', array('suspended' => false, 'password' => $password));
+            } else {
+                $this->create_queue_job('u_update', array('suspended' => false));
+            }
+            $this->pending_update_suspension = true;
+            return true;
+        }
+        return false;
+    }
+
+    // Adds a creation request in the job queue.
+    public function create($password_sync, $password, $redirect_mails) {
+        if ($this->g_status != NULL) {
+            return;
+        }
+
+        if (!$this->pending_create) {
+            // Retrieves information on the new account.
+            $res = XDB::query(
+                "SELECT  nom, nom_usage, prenom
+                   FROM  auth_user_md5
+                  WHERE  user_id = {?}",
+                $this->uid);
+            list($nom, $nom_usage, $prenom) = $res->fetchOneRow();
+
+            // Adds an entry in the gapps_accounts table.
+            XDB::execute(
+                "INSERT  INTO gapps_accounts
+                    SET  l_userid = {?},
+                         l_sync_password = {?},
+                         l_activate_mail_redirection = {?},
+                         g_account_name = {?},
+                         g_first_name = {?},
+                         g_last_name = {?},
+                         g_status = 'unprovisioned'",
+                $this->uid,
+                $password_sync,
+                $redirect_mails,
+                $this->g_account_name,
+                $prenom,
+                ($nom_usage ? $nom_usage : $nom));
+
+            // Adds the creation job in the GApps queue.
+            $this->create_queue_job(
+                'u_create',
+                array(
+                    'username' => $this->g_account_name,
+                    'first_name' => $prenom,
+                    'last_name' => ($nom_usage ? $nom_usage : $nom),
+                    'password' => $password,
+                ));
+
+            // Updates the GoogleAppsAccount status.
+            $this->__construct($this->uid, $this->g_account_name);
+        }
+    }
+}
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>
index 4bab494..1b05e67 100644 (file)
@@ -313,6 +313,17 @@ abstract class Validate
     }
 
     // }}}
+    // {{{ function get_typed_requests_count()
+
+    /** same as get_typed_requests() but return the count of available requests.
+     */
+    static public function get_typed_requests_count($uid, $type)
+    {
+        $res = XDB::query('SELECT COUNT(data) FROM requests WHERE user_id={?} and type={?}', $uid, $type);
+        return $res->fetchOneCell();
+    }
+
+    // }}}
     // {{{ function _mail_body
 
     abstract protected function _mail_body($isok);
diff --git a/include/validations/googleapps.inc.php b/include/validations/googleapps.inc.php
new file mode 100644 (file)
index 0000000..7413d73
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+/***************************************************************************
+ *  Copyright (C) 2003-2008 Polytechnique.org                              *
+ *  http://opensource.polytechnique.org/                                   *
+ *                                                                         *
+ *  This program is free software; you can redistribute it and/or modify   *
+ *  it under the terms of the GNU General Public License as published by   *
+ *  the Free Software Foundation; either version 2 of the License, or      *
+ *  (at your option) any later version.                                    *
+ *                                                                         *
+ *  This program is distributed in the hope that it will be useful,        *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ *  GNU General Public License for more details.                           *
+ *                                                                         *
+ *  You should have received a copy of the GNU General Public License      *
+ *  along with this program; if not, write to the Free Software            *
+ *  Foundation, Inc.,                                                      *
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
+ ***************************************************************************/
+
+class GoogleAppsUnsuspendReq extends Validate
+{
+    private $account;
+    public $rules = "Bien faire attention à la raison de la suspension. Si le compte a été suspendu par Google,
+                  alors la raison s'affichera (mais seulement 24-48h après la suspension).
+                  Si l'utilisateur a désactivé lui-même son compte, la raison sera toujours vierge.";
+
+    public function __construct($_uid)
+    {
+        parent::__construct($_uid, true, 'gapps-unsuspend');
+    }
+
+    public function sendmail($isok)
+    {
+        // Using overloading to prevent the validation from sending emails, as a valid
+        // unsuspend will automatically generate an email when commited through
+        // the Google Apps provisioning API.
+        if (!$isok) {
+            parent::sendmail($isok);
+        }
+    }
+
+    public function formu()
+    {
+        return 'include/form.valid.gapps-unsuspend.tpl';
+    }
+
+    protected function _mail_subj()
+    {
+        return "[Polytechnique.org] Demande de réactivation de ton compte Google Apps";
+    }
+
+    protected function _mail_body($isok)
+    {
+        if (!$isok) {
+            return "  La demande que tu avais faite de réactivation de compte Google Apps a été refusée.";
+        }
+    }
+
+    public function commit()
+    {
+        require_once dirname(__FILE__) . '/../googleapps.inc.php';
+        $account = new GoogleAppsAccount($this->uid, $this->forlife);
+        return $account->do_unsuspend();
+    }
+
+    public function suspension_reason()
+    {
+        $res = XDB::query(
+            "SELECT  g_suspension
+               FROM  gapps_accounts
+              WHERE  g_account_name = {?}",
+            $this->forlife);
+        return $res->fetchOneCell();
+    }
+}
+
+/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker enc=utf-8: */
+?>
index e3f5e8e..f35b354 100644 (file)
@@ -231,14 +231,23 @@ class EmailModule extends PLModule
             $redirect->modify_one_email_redirect($email, $rewrite);
         }
 
-        if ($action == 'storage' && $email == 'imap') {
-            $storage = new MailStorageIMAP(S::v('uid'));
-            $subaction = @func_get_arg(3);
-            if ($subaction == 'active') {
-                $storage->enable();
+        if ($action == 'storage') {
+            if ($email == 'imap') {
+                $storage = new MailStorageIMAP(S::v('uid'));
+            } else if ($email == 'googleapps') {
+                $storage = new MailStorageGoogleApps(S::v('uid'));
+            } else {
+                $storage = NULL;
             }
-            if ($subaction == 'inactive') {
-                $storage->disable();
+
+            if ($storage) {
+                $subaction = @func_get_arg(3);
+                if ($subaction == 'active') {
+                    $storage->enable();
+                }
+                if ($subaction == 'inactive') {
+                    $storage->disable();
+                }
             }
         }
 
@@ -273,7 +282,7 @@ class EmailModule extends PLModule
                    FROM  aliases
                   WHERE  id={?} AND (type='a_vie' OR type='alias')
                ORDER BY  !FIND_IN_SET('usage',flags), LENGTH(alias)", $uid);
-        
+
         $page->assign('alias', $res->fetchAllAssoc());
         $page->assign('emails',$redirect->emails);
 
@@ -282,6 +291,12 @@ class EmailModule extends PLModule
                    FROM  auth_user_md5
                   WHERE  user_id = {?}", $uid);
         $page->assign('storage', explode(',', $res->fetchOneCell()));
+
+        $res = XDB::query(
+                "SELECT  g_status
+                   FROM  gapps_accounts
+                  WHERE  l_userid = {?}", $uid);
+        $page->assign('googleapps', ($res->numRows() > 0 ? $res->fetchOneCell() : false));
     }
 
     function handler_antispam(&$page, $statut_filtre = null)
diff --git a/modules/googleapps.php b/modules/googleapps.php
new file mode 100644 (file)
index 0000000..84c9a4f
--- /dev/null
@@ -0,0 +1,112 @@
+<?php
+/***************************************************************************
+ *  Copyright (C) 2003-2008 Polytechnique.org                              *
+ *  http://opensource.polytechnique.org/                                   *
+ *                                                                         *
+ *  This program is free software; you can redistribute it and/or modify   *
+ *  it under the terms of the GNU General Public License as published by   *
+ *  the Free Software Foundation; either version 2 of the License, or      *
+ *  (at your option) any later version.                                    *
+ *                                                                         *
+ *  This program is distributed in the hope that it will be useful,        *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ *  GNU General Public License for more details.                           *
+ *                                                                         *
+ *  You should have received a copy of the GNU General Public License      *
+ *  along with this program; if not, write to the Free Software            *
+ *  Foundation, Inc.,                                                      *
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
+ ***************************************************************************/
+
+class GoogleAppsModule extends PLModule
+{
+    function handlers()
+    {
+        global $globals;
+        if (!$globals->mailstorage->googleapps_domain) {
+            return array();
+        }
+
+        return array(
+            'googleapps' => $this->make_hook('index', AUTH_MDP),
+        );
+    }
+
+    function handler_index(&$page, $action = null, $subaction = null)
+    {
+        require_once("emails.inc.php");
+        require_once("googleapps.inc.php");
+        $page->changeTpl('googleapps/index.tpl');
+        $page->addJsLink('motdepasse.js');
+        $page->assign('xorg_title', 'Polytechnique.org - Compte Google Apps');
+
+        $account = new GoogleAppsAccount(S::v('uid'), S::v('forlife'));
+
+        // Fills up the 'is Google Apps redirection active' variable.
+        $page->assign('redirect_active', false);
+        $page->assign('redirect_unique', true);
+
+        if ($account->g_status == 'active') {
+            $redirect = new Redirect(S::v('uid'));
+            $page->assign('redirect_unique', !$redirect->other_active(NULL));
+
+            $storage = new MailStorageGoogleApps(S::v('uid'));
+            $page->assign('redirect_active', $storage->active());
+        }
+
+        // Updates the Google Apps account as required.
+        if ($action) {
+            if ($action == 'password') {
+                if ($subaction == 'sync') {
+                    $account->set_password_sync(true);
+                    $account->set_password($_SESSION['password']);
+                    $page->trig("Ton mot de passe Google Apps sera dorénavant synchronisé avec ton mot de passe Polytechnique.org.");
+                } else if ($subaction == 'nosync') {
+                    $account->set_password_sync(false);
+                } else if (Post::has('response2') && !$account->sync_password) {
+                    $account->set_password(Post::v('response2'));
+                }
+            }
+
+            if ($action == 'suspend' && Post::has('suspend') && $account->g_status == 'active') {
+                if ($account->pending_update_suspension) {
+                    $page->trig("Ton compte est déjà en cours de désactivation.");
+                } else {
+                    $storage = new MailStorageGoogleApps(S::v('uid'));
+                    if ($storage->disable()) {
+                        $account->suspend();
+                        $page->trig("Ton compte Google Apps est dorénavant désactivé.");
+                    } else {
+                        $page->trig("Ton compte Google Apps est ta seule adresse de redirection. Ton compte ne peux pas être désactivé.");
+                    }
+                }
+            } elseif ($action == 'unsuspend' && Post::has('unsuspend') && $account->g_status == 'disabled') {
+                $account->unsuspend(Post::b('redirect_mails', true));
+                $page->trig("Ta demande de réactivation a bien été prise en compte.");
+            }
+
+            if ($action == 'create') {
+                $page->assign('has_password_sync', Get::has('password_sync'));
+                $page->assign('password_sync', Get::b('password_sync', true));
+            }
+            if ($action == 'create' && Post::has('password_sync') && Post::has('redirect_mails')) {
+                $password_sync = Post::b('password_sync');
+                $redirect_mails = Post::b('redirect_mails');
+                if ($password_sync) {
+                    $password = $_SESSION['password'];
+                } else {
+                    $password = Post::v('response2');
+                }
+
+                $account->create($password_sync, $password, $redirect_mails);
+                $page->trig("La demande de création de ton compte Google Apps a bien été enregistrée.");
+            }
+        }
+
+        $page->assign('account', $account);
+    }
+}
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>
index 4d7c07c..636b1c8 100644 (file)
@@ -28,7 +28,7 @@
   function bestaliasUpdated() {
     showTempMessage('bestalias-msg', "Le changement a bien été effectué.", true);
   }
-</script>      
+</script>
 {/literal}
 <table class="bicol">
   <tr>
@@ -103,14 +103,10 @@ ton homonyme et toi-même ne disposeraient plus que des adresses de la forme pre
       Ton courrier est également stocké sur {if count($storage) eq 1}le compte suivant{else} les comptes suivants{/if}&nbsp;:
       <ul>
         {if in_array('googleapps', $storage)}
-        <li><a href="https://www.polytechnique.org/Xorg/GoogleApps">
-          <strong>Compte Google Apps / GMail de Polytechnique.org</strong>
-        </a></li>
+        <li><a href="googleapps"><strong>Compte Google Apps / GMail de Polytechnique.org</strong></a></li>
         {/if}
         {if in_array('imap', $storage)}
-        <li><a href="https://www.polytechnique.org/Xorg/IMAP">
-          <strong>Accès de secours aux emails (IMAP)</strong>
-        </a></li>
+        <li><a href="Xorg/IMAP"><strong>Accès de secours aux emails (IMAP)</strong></a></li>
         {/if}
       </ul>
       {/if}
index 5a5244e..dec1119 100644 (file)
@@ -66,7 +66,7 @@
   </p>
   <p>
     Enfin, la <strong>réécriture</strong> consiste à substituer à ton adresse email habituelle
-    (adresse wanadoo, yahoo, free, ou autre) ton adresse {#globals.mail.domain#} ou
+    (adresse gmail, orange, free, ou autre) ton adresse {#globals.mail.domain#} ou
     {#globals.mail.domain2#} dans l'adresse d'expédition de tes messages, lorsque le courrier
     passe par nos serveurs. Ceci arrive lorsque tu écris à un camarade sur son adresse {#globals.mail.domain#} ou
     {#globals.mail.domain2#}, ou lorsque tu utilises notre
         </td>
       </tr>
       {/foreach}
+      {if $googleapps eq 'active'}
+      <tr class="{cycle values="pair,impair"}">
+        <td><strong>Compte GMail / Google Apps</strong></td>
+        <td>
+          <input type="checkbox" value="googleapps" disabled="disabled"
+                 {if in_array('googleapps', $storage)}checked="checked"{/if} />
+        </td>
+        <td>-</td>
+        <td>
+          <a href="emails/redirect#googleapps">{icon name=information title="Plus d'informations"}</a>
+        </td>
+      </tr>
+      {/if}
       <script type="text/javascript">activeEnable(); showRemove();</script>
       <tr class="{cycle values="pair,impair"}"><td colspan="4">
         <form action="emails/redirect" method="post">
 </fieldset>
 {/if}
 
-{if count($storage) neq 0 or #globals.mailstorage.imap_active# or hasPerm('admin')}
+{* TODO(vincent.zanotti): remove the following block of code when both IMAP and GApps will be active. *}
+{if in_array('imap', $storage) neq 0 or #globals.mailstorage.imap_active# or hasPerm('admin')}
+  {assign var=has_imap value=true}
+{else}
+  {assign var=has_imap value=false}
+{/if}
+{if $googleapps or #globals.mailstorage.googleapps_active# or hasPerm('admin')}
+  {assign var=has_googleapps value=true}
+{else}
+  {assign var=has_googleapps value=false}
+{/if}
+
+{if $has_imap or $has_googleapps}
 <h1>Tes comptes de stockage de courrier</h1>
+{/if}
+{if $has_imap}
 <p>
   Polytechnique.org te propose de conserver les mails que tu reçois, pendant une durée limitée (environ 30 jours).
   Grâce à ce service, tu disposes d'une sauvegarde de tes mails en secours, au cas où, par exemple, tu effacerais
 </p>
 
 <table class="bicol" summary="Compte de stockage">
+  <col width="75%" />
+  <col width="25%" />
   <tr>
     <th colspan="2">Compte de stockage</th>
   </tr>
   <tr class="pair">
     <td>
-      <a href="https://www.polytechnique.org/Xorg/IMAP">
+      <a href="Xorg/IMAP">
         <strong>Accès de secours aux emails (IMAP)</strong>
       </a><br />Hébergé par Polytechnique.org
     </td>
-    <td>
+    <td style="text-align: center; vertical-align: middle">
       <form action="emails/redirect/storage/imap/{if in_array('imap', $storage)}inactive{else}active{/if}" method="post">
         {if in_array('imap', $storage)}
         <input type="submit" value="Désactiver" />
 </table>
 {/if}
 
+{if $has_googleapps}
+<br />
+<p>
+  Grâce à un partenariat avec Google, Polytechnique.org te propose également un compte
+  <b>Google Apps</b>, qui te permet de disposer des services Google (GMail pour
+  tes emails, Google Calendar, Google Docs, ...) sur une adresse polytechnique.org.
+</p>
+
+<table class="bicol" summary="Compte de stockage" id="googleapps">
+  <col width="75%" />
+  <col width="25%" />
+  <tr>
+    <th colspan="2">Compte de stockage</th>
+  </tr>
+  <tr class="pair">
+    {if $googleapps eq 'active'}
+    <td>
+      <a href="googleapps">
+        <strong>Redirection des emails vers GMail / Google Apps</strong>
+      </a><br />Hébergé par Google
+    </td>
+    <td style="text-align: center; vertical-align: middle">
+      <form action="emails/redirect/storage/googleapps/{if in_array('googleapps', $storage)}inactive{else}active{/if}" method="post">
+        {if in_array('googleapps', $storage)}
+        <input type="submit" value="Désactiver" />
+        {else}
+        <input type="submit" value="Activer" />
+        {/if}
+      </form>
+    </td>
+    {else}
+    <td colspan="2">
+      {if $googleapps eq 'disabled'}
+      Ton compte Google Apps est actuellement inactif.<br />
+      {else}
+      Tu n'as pas encore de compte Google Apps sur Polytechnique.org.<br />
+      {/if}
+      <a href="googleapps">Plus d'informations &hellip;</a>
+    </td>
+    {/if}
+  </tr>
+</table>
+{/if}
+
 {if $eleve}
 <h1>Pour les Élèves (non encore diplômés)</h1>
 <p>
diff --git a/templates/googleapps/create.mail.tpl b/templates/googleapps/create.mail.tpl
new file mode 100644 (file)
index 0000000..fac8a07
--- /dev/null
@@ -0,0 +1,55 @@
+{**************************************************************************}
+{*                                                                        *}
+{*  Copyright (C) 2003-2008 Polytechnique.org                             *}
+{*  http://opensource.polytechnique.org/                                  *}
+{*                                                                        *}
+{*  This program is free software; you can redistribute it and/or modify  *}
+{*  it under the terms of the GNU General Public License as published by  *}
+{*  the Free Software Foundation; either version 2 of the License, or     *}
+{*  (at your option) any later version.                                   *}
+{*                                                                        *}
+{*  This program is distributed in the hope that it will be useful,       *}
+{*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *}
+{*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *}
+{*  GNU General Public License for more details.                          *}
+{*                                                                        *}
+{*  You should have received a copy of the GNU General Public License     *}
+{*  along with this program; if not, write to the Free Software           *}
+{*  Foundation, Inc.,                                                     *}
+{*  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA               *}
+{*                                                                        *}
+{**************************************************************************}
+
+{config_load file="mails.conf" section="googleapps"}
+{if $mail_part eq 'head'}
+{from full=#from#}
+{to addr=$email}
+{cc full=#from#}
+{subject text="[Polytechnique.org] Création de ton compte Google Apps"}
+{elseif $mail_part eq 'wiki'}
+{if $sexe}Chère{else}Cher{/if} {$prenom},
+
+Ton compte Google Apps pour Polytechnique.org vient d'être crée.
+
+Tu peux accèder aux services offerts par Google Apps aux adresses suivantes:
+* [[http://google.polytechnique.org/|iGoogle, le portail des services Google Apps]] ;
+{if $account->activate_mail_redirection}
+* [[https://mail.google.com/a/{$googleapps_domain}/|GMail, pour accéder à tes emails Polytechnique.org]] ;
+{/if}
+* [[https://www.polytechnique.org/googleapps|Polytechnique.org, pour modifier les préférences de ton compte Google Apps]].
+
+Ton nom d'utilisateur pour ces services Google est '''{$account->g_account_name}'''
+{if $account->sync_password}
+et ton mot de passe est celui de Polytechnique.org.
+{else}
+et ton mot de passe est celui que tu as choisi lors de ta demande de compte.
+{/if}
+
+Tu trouveras plus d'informations dans la [[https://www.polytechnique.org/Xorg/GoogleApps|documentation]] sur Polytechnique.org.
+
+Cordialement,\\
+-- \\
+L'équipe de Polytechnique.org
+{/if}
+
+{* vim:set et sw=2 sts=2 sws=2: *}
diff --git a/templates/googleapps/index.tpl b/templates/googleapps/index.tpl
new file mode 100644 (file)
index 0000000..23400c9
--- /dev/null
@@ -0,0 +1,399 @@
+{**************************************************************************}
+{*                                                                        *}
+{*  Copyright (C) 2003-2008 Polytechnique.org                             *}
+{*  http://opensource.polytechnique.org/                                  *}
+{*                                                                        *}
+{*  This program is free software; you can redistribute it and/or modify  *}
+{*  it under the terms of the GNU General Public License as published by  *}
+{*  the Free Software Foundation; either version 2 of the License, or     *}
+{*  (at your option) any later version.                                   *}
+{*                                                                        *}
+{*  This program is distributed in the hope that it will be useful,       *}
+{*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *}
+{*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *}
+{*  GNU General Public License for more details.                          *}
+{*                                                                        *}
+{*  You should have received a copy of the GNU General Public License     *}
+{*  along with this program; if not, write to the Free Software           *}
+{*  Foundation, Inc.,                                                     *}
+{*  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA               *}
+{*                                                                        *}
+{**************************************************************************}
+
+<h1>Ton compte Google Apps / Polytechnique.org</h1>
+
+<p>Polytechnique.org te fournit un compte <b>Google Apps</b> qui te permet de disposer
+  des applications web de Google (<a href="http://mail.google.com/a/polytechnique.org/">GMail</a>,
+  <a href="http://www.google.com/calendar/hosted/polytechnique.org/">Google Calendar</a>,
+  <a href="http://docs.google.com/a/polytechnique.org/">Google Docs</a>, et bien d'autres)
+  sur ton adresse Polytechnique.org habituelle (<a href="Xorg/GoogleApps">plus d'informations</a>).
+</p>
+
+{if !$account->g_status}
+<p>Tu peux créer ton compte <i>Google Apps / Polytechnique.org</i> en utilisant le
+  formulaire ci-dessous.
+</p>
+<p><b>Attention :</b> ce compte Google Apps est hébergé par <b>Google</b>, et non
+  par Polytechnique.org. Nous te déconseillons d'y ranger des informations
+  confidentielles ou sensibles !<br />&nbsp;
+</p>
+
+<table class="bicol" id="create">
+  <col width="8%" />
+  <col width="92%" />
+  <tr>
+    <th colspan="2">Création d'un compte Google Apps</th>
+  </tr>
+
+  {if !$has_password_sync}
+    <form action="googleapps/create" method="get">
+    <tr class="impair">
+      <td colspan="2"><b>Mot de passe du compte :</b></td>
+    </tr>
+    <tr class="impair">
+      <td style="text-align: center">
+        <input type="radio" name="password_sync" value="1" checked="checked" id="pwsync_true" />
+      </td>
+      <td>
+        <label for="pwsync_true">Utiliser le même mot de passe pour Google Apps et Polytechnique.org.</label><br />
+        <span style="font-size: smaller; font-style: italic;">
+          Tes futurs changements de mot de passe seront synchronisés avec ton compte Google Apps.
+          Ton mot de passe ne sera jamais transmis non-chiffré par Polytechnique.org.
+        </span>
+      </td>
+    </tr>
+    <tr class="impair">
+      <td style="text-align: center">
+        <input type="radio" name="password_sync" value="0" id="pwsync_false" />
+      </td>
+      <td>
+        <label for="pwsync_false">Utiliser un mot de passe différent pour Google Apps.</label>
+      </td>
+    </tr>
+    <tr class="impair">
+      <td colspan="2" style="text-align: center">
+        <input type="submit" value="Continuer &gt;&gt;" />
+      </td>
+    </tr>
+    </form>
+  {else}
+    <tr class="impair">
+      <td colspan="2"><b>Mot de passe du compte :</b></td>
+    </tr>
+    {if $password_sync}
+      <tr class="impair">
+        <td></td>
+        <td>
+          Tu as choisi d'avoir le même mot de passe pour Google Apps et Polytechnique.org.<br />
+          Tu peux encore choisir d'utiliser des <a href="googleapps/create?password_sync=0">mots de passe différents</a>.
+        </td>
+      </tr>
+    {else}
+      <tr class="impair">
+        <td></td>
+        <td>Tu as choisi d'avoir un nouveau mot de passe pour ton compte Google Apps :</td>
+      </tr>
+      <tr class="impair">
+        <td colspan="2">
+          <form action="#" method="post" id="changepass">
+          <table class="tinybicol">
+            <tr>
+              <td class="titre">Nouveau mot de passe</td>
+              <td><input type="password" name="nouveau" onfocus="document.forms.changepass2.password_sync[1].checked = true;" /></td>
+            </tr>
+            <tr>
+              <td class="titre">Vérification</td>
+              <td><input type="password" name="nouveau2" onfocus="document.forms.changepass2.password_sync[1].checked = true;" /></td>
+            </tr>
+          </table>
+          </form>
+        </td>
+      </tr>
+      <tr class="impair">
+        <td></td>
+        <td>
+          Tu peux encore choisir d'<a href="googleapps/create?password_sync=1">avoir des mots de passes synchronisés</a>.
+        </td>
+      </tr>
+    {/if}
+
+    <form action="googleapps/create" method="post" id="changepass2">
+    <tr class="pair">
+      <td colspan="2"><b>Redirection des emails :</b></td>
+    </tr>
+    <tr class="pair">
+      <td style="text-align: center">
+        <input type="radio" name="redirect_mails" value="1" checked="checked" id="redirection_true" />
+      </td>
+      <td>
+        <label for="redirection_true">Rediriger mes emails vers mon compte Google Apps.</label><br />
+        <span style="font-size: smaller;">
+          Tes emails <i>Polytechnique.org</i> seront redirigés vers ton webmail <i>GMail</i> de Google Apps,
+          en plus d'être redirigés vers tes adresses actuelles.<br /><br />
+          <b>Attention : ton compte Google Apps est hébergé par <i>Google, Inc.</i></b><br />
+          Nous te déconseillons donc de rediriger tes emails vers Google Apps si tu utilises tes adresses Polytechnique.org
+          à des fin professionnelles ou pour des communications confidentielles.
+        </span>
+      </td>
+    </tr>
+    <tr class="pair">
+      <td style="text-align: center">
+        <input type="radio" name="redirect_mails" value="0" id="redirection_false" />
+      </td>
+      <td>
+        <label for="redirection_false">Ne <i>pas</i> rediriger mes emails vers mon compte Google Apps.</label><br />
+        <span style="font-size: smaller;">
+        </span>
+      </td>
+    </tr>
+
+    <tr class="impair">
+      <td colspan="2" style="text-align:center">
+        <input type="hidden" name="password_sync" value="{$password_sync}" />
+        {if $password_sync}
+          <input type="submit" value="Créer mon compte !" />
+        {else}
+          <input type="hidden" name="response2"  value="" />
+          <input type="submit" value="Créer mon compte !" onclick="EnCryptedResponse(); return false;" />
+        {/if}
+      </td>
+    </tr>
+    </form>
+  {/if}
+</table>
+
+{elseif $account->g_status eq 'unprovisioned' or $account->pending_create}
+<br />
+<table class="bicol" id="status">
+  <tr>
+    <th>État de ton compte</th>
+  </tr>
+  <tr class="impair">
+    <td>
+      Ton compte Google Apps est en cours de création.<br />
+      Tu recevras un email dès que l'opération sera terminée.
+    </td>
+  </tr>
+</table>
+
+{elseif $account->pending_delete}
+<br />
+<table class="bicol" id="status">
+  <tr>
+    <th>État de ton compte</th>
+  </tr>
+  <tr class="impair">
+    <td>
+      Ton compte Google Apps est en cours de suppression.
+    </td>
+  </tr>
+</table>
+
+{elseif $account->g_status eq 'disabled' or $account->pending_update_suspension}
+<br />
+<table class="bicol" id="status">
+  <tr>
+    <th>État de ton compte</th>
+  </tr>
+  <tr class="impair">
+    <td>
+      Ton compte Google Apps est actuellement <b>désactivé</b>. Tu ne reçois donc plus aucun
+      message sur ce compte.
+    </td>
+  </tr>
+  {if $account->pending_validation_unsuspend or ($account->g_status eq 'disabled' and $account->pending_update_suspension)}
+  <tr class="pair">
+    <td>
+      La réactivation de ton compte est en attente de validation.<br />
+      Tu recevras un email dès que l'opération sera terminée.
+    </td>
+  </tr>
+  {elseif $account->g_status neq 'disabled' and $account->pending_update_suspension}
+  <tr class="pair">
+    <td>
+      Les opérations de désactivation de ton compte Google Apps ne sont pas terminées, tu ne peux donc pas encore demander sa réactivation.
+    </td>
+  </tr>
+  {else}
+  {if $account->g_suspension}
+  <tr class="pair">
+    <td>
+      Ton compte est actuellement suspendu pour la raison suivante: <em>{$account->g_suspension}</em>.
+    </td>
+  </tr>
+  {/if}
+  <tr class="impair">
+    <td>
+      La réactivation de ton compte est soumise à une validation manuelle par un administrateur de Polytechnique.org.
+      Ton compte réactivé contiendra toutes tes anciennes données.
+      <br /><br />
+      <div class="center">
+        <form action="googleapps/unsuspend" method="post">
+          <input type="hidden" name="redirect_mails" value="1" />
+          <input type="submit" name="unsuspend" value="Réactiver mon compte Google Apps et y rediriger mes emails" />
+        </form>
+        <br />
+        <form action="googleapps/unsuspend" method="post">
+          <input type="hidden" name="redirect_mails" value="0" />
+          <input type="submit" name="unsuspend" value="Réactiver mon compte Google Apps et ne pas y rediriger mes emails" />
+        </form>
+      </div><br />
+      Tu pourras toujours <a href="emails/redirect">changer la redirection de tes emails</a> plus tard.
+    </td>
+  </tr>
+  {/if}
+</table>
+
+{else}
+<p>Tu peux utiliser ces services :</p>
+<ul>
+  <li>Soit en passant par la <a href="http://google.polytechnique.org/">la page d'accueil Google de Polytechnique.org</a> ;</li>
+  <li>Soit en utilisant directement les différents services :
+    <ul>
+      <li>Pour tes mails, sur le <a href="http://mail.google.com/a/polytechnique.org/">GMail de Polytechnique.org</a> ;</li>
+      <li>Pour ton calendrier, sur <a href="http://www.google.com/calendar/hosted/polytechnique.org/">Google Calendar</a> ;</li>
+      <li>Pour tes documents, sur <a href="http://docs.google.com/a/polytechnique.org/">Google Docs</a>.</li>
+    </ul>
+  </li>
+</ul>
+
+<table class="bicol" id="status">
+  <tr>
+    <th>État de ton compte</th>
+  </tr>
+  <tr class="impair">
+    <td>Ton compte <b>{$account->g_account_name}</b> existe{if $account->r_creation} depuis le {$account->r_creation|date_format:"%d/%m/%Y"}{/if}.</td>
+  </tr>
+  {if $account->reporting_date and $account->r_disk_usage}
+  <tr class="pair">
+    <td>Au {$account->reporting_date|date_format:"%d %B %Y"}, tu avais {$account->r_disk_usage/1024/1024|string_format:"%.1f"} Mo de mails.</td>
+  </tr>
+  {/if}
+  <tr class="impair">
+    {if $redirect_active and $redirect_unique}
+    <td>
+      Ta seule adresse de redirection de tes mails est celle de ton compte Google Apps.<br />
+      Si tu souhaites désactiver celui-ci, tu dois d'abord <a href="emails/redirect">ajouter une nouvelle adresse de redirection</a>.
+    </td>
+    {else}
+    <td>
+      Si tu ne souhaites plus utiliser ton compte, tu peux le désactiver :<br /><br />
+      <div class="center">
+        <form action="googleapps/suspend" method="post">
+          <input type="submit" name="suspend" value="Désactiver mon compte Google Apps" />
+        </form>
+      </div>
+      <div style="margin-top: 0.5em">
+        {icon name=error} Une fois ton compte désactivé, tu ne pourras plus accéder à tes mails sur Google Apps.<br />
+        {icon name=information} La réactivation est possible, mais nécessite d'être validée par un administrateur.
+      </div>
+    </td>
+    {/if}
+  </tr>
+</table>
+<br />
+
+<table class="bicol" id="password">
+  <tr>
+    <th>Ton mot de passe Google Apps</th>
+  </tr>
+  {if $account->sync_password}
+  <tr class="impair">
+    <td>
+      Le mot de passe de ton compte Google Apps est actuellement celui que tu utilises pour
+      Polytechnique.org. Tu peux :
+    </td>
+  </tr>
+
+  {if $account->pending_update_password}
+  <tr class="pair">
+    <td><div class="erreur">
+      Ton mot de passe est en cours de changement.<br />
+      Tu pourras à nouveau le modifier d'ici quelques secondes.
+    </div></td>
+  </tr>
+  {else}
+  <tr class="impair">
+    <td>
+      <ul style="margin-top: 0">
+        <li><a href="password">Changer ce mot de passe commun</a></li>
+        <li><a href="googleapps/password/nosync#password">Choisir d'avoir des mots de passe indépendants</a></li>
+      </ul>
+    </td>
+  </tr>
+  {/if}
+  {else}
+  <tr class="impair">
+    <td>
+      Tu as actuellement deux mots de passes indépendants (pour ton compte Polytechnique.org et pour ton compte Google Apps).
+      Tu peux :
+    </td>
+  </tr>
+
+  {if $account->pending_update_password}
+  <tr class="pair">
+    <td><div class="erreur">
+      Ton mot de passe est en cours de changement.<br />
+      Tu pourras à nouveau le modifier d'ici quelques secondes.
+    </div></td>
+  </tr>
+  {else}
+  <tr class="impair">
+    <td>
+      <ul style="margin-top: 0">
+        <li style="margin-bottom: 1em">
+          <a href="googleapps/password/sync">Choisir d'utiliser le même mot de passe pour les deux comptes.</a><br />
+          Attention, cette opération changera ton mot de passe Google Apps.
+        </li>
+        <li>
+          Changer le mot de passe de ton compte Google Apps:<br /><br />
+          <form action="googleapps/password#password" method="post" id="changepass">
+            <table class="tinybicol">
+              <tr>
+                <td class="titre">Nouveau mot de passe</td>
+                <td><input type="password" name="nouveau" /></td>
+              </tr>
+              <tr>
+                <td class="titre">Vérification</td>
+                <td><input type="password" name="nouveau2" /></td>
+              </tr>
+              <tr>
+                <td></td>
+                <td><input type="submit" value="Changer" onclick="EnCryptedResponse(); return false;" /></td>
+              </tr>
+            </table>
+          </form>
+          <form action="googleapps/password#password" method="post" id="changepass2">
+            <input type="hidden" name="response2"  value="" />
+          </form><br />
+          Pour une sécurité optimale, ton mot de passe circule de manière cryptée (https) et est stocké crypté irréversiblement sur nos serveurs, ainsi que sur ceux de Google.
+        </li>
+      </ul>
+    </td>
+  </tr>
+  {/if}
+  {/if}
+</table>
+<br />
+
+<table class="bicol" id="emails">
+  <tr>
+    <th>Redirection des emails vers Google Apps</th>
+  </tr>
+
+  <tr class="impair">
+    {if $redirect_active and !$redirect_unique}
+    <td>Tu reçois tes emails Polytechnique.org entre autres sur ton compte mail Google Apps.</td>
+    {elseif $redirect_active}
+    <td>Tu ne reçois tes emails Polytechnique.org <em>que</em> sur ton compte mail Google Apps.</td>
+    {else}
+    <td>Tu ne reçois <em>pas</em> tes emails Polytechnique.org sur ton compte mail Google Apps.</td>
+    {/if}
+  </tr>
+  <tr class="pair">
+    <td class="center"><a href="emails/redirect">Changer mes redirections mail</a></td>
+  </tr>
+</table>
+{/if}
+
+{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
diff --git a/templates/googleapps/unsuspend.mail.tpl b/templates/googleapps/unsuspend.mail.tpl
new file mode 100644 (file)
index 0000000..5e43939
--- /dev/null
@@ -0,0 +1,47 @@
+{**************************************************************************}
+{*                                                                        *}
+{*  Copyright (C) 2003-2008 Polytechnique.org                             *}
+{*  http://opensource.polytechnique.org/                                  *}
+{*                                                                        *}
+{*  This program is free software; you can redistribute it and/or modify  *}
+{*  it under the terms of the GNU General Public License as published by  *}
+{*  the Free Software Foundation; either version 2 of the License, or     *}
+{*  (at your option) any later version.                                   *}
+{*                                                                        *}
+{*  This program is distributed in the hope that it will be useful,       *}
+{*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *}
+{*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *}
+{*  GNU General Public License for more details.                          *}
+{*                                                                        *}
+{*  You should have received a copy of the GNU General Public License     *}
+{*  along with this program; if not, write to the Free Software           *}
+{*  Foundation, Inc.,                                                     *}
+{*  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA               *}
+{*                                                                        *}
+{**************************************************************************}
+
+{config_load file="mails.conf" section="googleapps"}
+{if $mail_part eq 'head'}
+{from full=#from#}
+{to addr=$email}
+{cc full=#from#}
+{subject text="[Polytechnique.org] Réactivation de ton compte Google Apps"}
+{elseif $mail_part eq 'wiki'}
+{if $sexe}Chère{else}Cher{/if} {$prenom},
+
+Ton compte Google Apps pour Polytechnique.org vient d'être réactivé.\\
+Ton nom d'utilisateur pour ces services Google est '''{$account->g_account_name}'''
+{if $account->sync_password}
+et ton mot de passe est celui de Polytechnique.org.
+{else}
+et ton mot de passe est celui que tu as choisi lors de ta demande de compte.
+{/if}
+
+Tu trouvera plus d'information dans la [[https://www.polytechnique.org/Xorg/GoogleApps|documentation]] sur Polytechnique.org.
+
+Cordialement,\\
+-- \\
+L'équipe de Polytechnique.org
+{/if}
+
+{* vim:set et sw=2 sts=2 sws=2: *}
diff --git a/templates/include/form.valid.gapps-unsuspend.tpl b/templates/include/form.valid.gapps-unsuspend.tpl
new file mode 100644 (file)
index 0000000..cd163d3
--- /dev/null
@@ -0,0 +1,29 @@
+{**************************************************************************}
+{*                                                                        *}
+{*  Copyright (C) 2003-2008 Polytechnique.org                             *}
+{*  http://opensource.polytechnique.org/                                  *}
+{*                                                                        *}
+{*  This program is free software; you can redistribute it and/or modify  *}
+{*  it under the terms of the GNU General Public License as published by  *}
+{*  the Free Software Foundation; either version 2 of the License, or     *}
+{*  (at your option) any later version.                                   *}
+{*                                                                        *}
+{*  This program is distributed in the hope that it will be useful,       *}
+{*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *}
+{*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *}
+{*  GNU General Public License for more details.                          *}
+{*                                                                        *}
+{*  You should have received a copy of the GNU General Public License     *}
+{*  along with this program; if not, write to the Free Software           *}
+{*  Foundation, Inc.,                                                     *}
+{*  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA               *}
+{*                                                                        *}
+{**************************************************************************}
+
+
+<tr class="pair">
+  <td class="titre">Motif de la suspension :</td>
+  <td>{$valid->suspension_reason()|default:"-none-"|nl2br}</td>
+</tr>
+
+{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
diff --git a/upgrade/0.9.16/07_google_apps.sql b/upgrade/0.9.16/07_google_apps.sql
new file mode 100644 (file)
index 0000000..c5942f0
--- /dev/null
@@ -0,0 +1,3 @@
+ALTER TABLE `requests_answers` MODIFY `category` enum('alias','liste','usage','photo','evts', 'gapps-unsuspend', 'marketing','orange','homonyme','nl','paiements','medal','broken','surveys') NOT NULL default 'alias';
+
+# vim:set syntax=mysql: