public static function authenticate($data)
 {
     $salt = Z_CONFIG::$AUTH_SALT;
     // TODO: config
     $dev = Z_ENV_TESTING_SITE ? "_test" : "";
     $databaseName = "zotero_www{$dev}";
     $username = $data['username'];
     $password = $data['password'];
     $isEmailAddress = strpos($username, '@') !== false;
     $cacheKey = 'userAuthHash_' . sha1($username . $salt . $password);
     $userID = Z_Core::$MC->get($cacheKey);
     if ($userID) {
         return $userID;
     }
     // Query the database looking for a salted SHA1 password
     $passwordSha1 = sha1($salt . $password);
     if (!$isEmailAddress) {
         // Try username
         $sql = "SELECT userID, username FROM {$databaseName}.users\n\t\t\t\t\t   WHERE username = ? AND password = ?\n\t\t\t\t\t   LIMIT 1";
         $params = array($username, $passwordSha1);
         try {
             $retry = true;
             $row = Zotero_WWW_DB_2::rowQuery($sql, $params);
             if (!$row) {
                 $retry = false;
                 $row = Zotero_WWW_DB_1::rowQuery($sql, $params);
             }
         } catch (Exception $e) {
             if ($retry) {
                 Z_Core::logError("WARNING: {$e} -- retrying on primary");
                 $row = Zotero_WWW_DB_1::rowQuery($sql, $params);
             }
         }
     } else {
         // Try both username and e-mail address
         $sql = "SELECT userID, username FROM {$databaseName}.users\n\t\t\t\t\t   WHERE username = ? AND password = ?\n\t\t\t\t\t   UNION\n\t\t\t\t\t   SELECT userID, username FROM {$databaseName}.users\n\t\t\t\t\t   WHERE email = ? AND password = ?\n\t\t\t\t\t   ORDER BY username = ? DESC\n\t\t\t\t\t   LIMIT 1";
         $params = array($username, $passwordSha1, $username, $passwordSha1, $username);
         try {
             $retry = true;
             $row = Zotero_WWW_DB_2::rowQuery($sql, $params);
             if (!$row) {
                 $retry = false;
                 $row = Zotero_WWW_DB_1::rowQuery($sql, $params);
             }
         } catch (Exception $e) {
             if ($retry) {
                 Z_Core::logError("WARNING: {$e} -- retrying on primary");
                 $row = Zotero_WWW_DB_1::rowQuery($sql, $params);
             }
         }
     }
     // If not found, check for an MD5 password
     if (!$row) {
         $passwordMd5 = md5($password);
         if (!$isEmailAddress) {
             // Try username
             $sql = "SELECT userID, username FROM {$databaseName}.users\n\t\t\t\t\t\t   WHERE username = ? AND password = ? LIMIT 1";
             $params = array($username, $passwordMd5);
             try {
                 $row = Zotero_WWW_DB_2::rowQuery($sql, $params);
             } catch (Exception $e) {
                 Z_Core::logError("WARNING: {$e} -- retrying on primary");
                 $row = Zotero_WWW_DB_1::rowQuery($sql, $params);
             }
         } else {
             // Try both username and e-mail address
             $sql = "SELECT userID, username FROM {$databaseName}.users\n\t\t\t\t\t\t   WHERE username = ? AND password = ?\n\t\t\t\t\t\t   UNION\n\t\t\t\t\t\t   SELECT userID, username FROM {$databaseName}.users\n\t\t\t\t\t\t   WHERE email = ? AND password = ?\n\t\t\t\t\t\t   ORDER BY username = ? DESC\n\t\t\t\t\t\t   LIMIT 1";
             $params = array($username, $passwordMd5, $username, $passwordMd5, $username);
             try {
                 $row = Zotero_WWW_DB_2::rowQuery($sql, $params);
             } catch (Exception $e) {
                 Z_Core::logError("WARNING: {$e} -- retrying on primary");
                 $row = Zotero_WWW_DB_1::rowQuery($sql, $params);
             }
         }
     }
     if (!$row) {
         return false;
     }
     self::updateUser($row['userID'], $row['username']);
     Z_Core::$MC->set($cacheKey, $row['userID'], 60);
     return $row['userID'];
 }