[opw-web] Working auth



commit f4a7088aa590e52ceea1925d4419aaf2eaedba58
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Sat Mar 8 12:27:35 2014 -0500

    Working auth

 classes/class_user.php                 |  228 +++++++++++++++++++++++++-------
 lang/en-gb.php                         |    4 +
 modules/mod_login.php                  |   33 +++++-
 modules/mod_user_profile.php           |   30 ++---
 schema.sql                             |   16 +++
 skins/easterngreen/html/tpl_login.html |   18 +++-
 6 files changed, 254 insertions(+), 75 deletions(-)
---
diff --git a/classes/class_user.php b/classes/class_user.php
index 39074a0..60585b2 100644
--- a/classes/class_user.php
+++ b/classes/class_user.php
@@ -19,6 +19,7 @@ class user
     // Constructor
     function __construct()
     {
+        $this->_hybridauth = null;
         $this->username = null;
         $this->sid = null;
         $this->is_admin = false;
@@ -26,6 +27,15 @@ class user
         $this->max_age = time() - 1800;
     }
 
+    function hybridauth() {
+        if (!isset($this->_hybridauth)) {
+            $authconfig = dirname(__FILE__) . '/../auth/config.php';
+            $this->_hybridauth = new Hybrid_Auth($authconfig);
+        }
+
+        return $this->_hybridauth;
+    }
+
     // Method for creating a new session
     function create_session($username, $is_admin = false)
     {
@@ -128,7 +138,7 @@ class user
     }
 
     // Get details of the user from LDAP
-    function get_details($username, $entries)
+    function get_details_ldap($username, $entries)
     {
         global $config, $db, $cache;
 
@@ -197,74 +207,190 @@ class user
     // Method for authenticating a user
     function login_openid($openid)
     {
-        global $config, $db;
-        $is_admin = false;
+        $hybridauth = $this->hybridauth();
+        if ($hybridauth->authenticate("OpenID", array (
+            'openid_identifier' => $openid,
+            'hauth_return_to' => Hybrid_Auth::getCurrentUrl() . '&p=OpenID'
+            ))) {
+            return $this->finish_login('OpenID');
+        } else {
+            return false;
+        }
+    }
 
-        try {
-          $authconfig = dirname(__FILE__) . '/../auth/config.php';
-          $hybridauth = new Hybrid_Auth($authconfig);
-          $openidauth = $hybridauth->authenticate("OpenID", array (
-            'openid_identifier' => $openid
-          ));
+    // Method for authenticating a user
+    function login_google()
+    {
+        $hybridauth = $this->hybridauth();
+        if ($hybridauth->authenticate("Google", array (
+            'hauth_return_to' => Hybrid_Auth::getCurrentUrl() . '&p=Google'
+        ))) {
+            return $this->finish_login('Google');
+        } else {
+            return false;
+        }
+    }
 
-          /*XXX
-          $is_user_logged_in = $openidauth->isUserConnected();
-          if (!$is_user_logged_in) {
+    // Method for authenticating a user
+    function login_facebook()
+    {
+        $hybridauth = $this->hybridauth();
+        if ($hybridauth->authenticate("Facebook", array (
+            'hauth_return_to' => Hybrid_Auth::getCurrentUrl() . '&p=Facebook'
+        ))) {
+            return $this->finish_login('Facebook');
+        } else {
             return false;
-          }
+        }
+    }
 
-          $user_profile = $openidauth->getUserProfile();
+    function lookup_identity($provider, $identifier)
+    {
+        global $db;
 
-          // access user profile data
-          echo "Ohai there! U are connected with: <b>{$openidauth->id}</b><br />";
-          echo "As: <b>{$user_profile->displayName}</b><br />";
-          echo "And your provider user identifier is: <b>{$user_profile->identifier}</b><br />";
+        $db->escape($provider);
+        $db->escape($identifier);
 
-          // or even inspect it
-          echo "<pre>" . print_r( $user_profile, true ) . "</pre><br />";
+        // Get current session data
+        $sql = "SELECT username FROM {$db->prefix}identities " .
+               "WHERE provider = '{$provider}' " .
+               "AND identifier = '{$identifier}'";
+        Hybrid_Logger::info("executing '${sql}'");
+        $row = $db->query($sql, true);
 
-          // uncomment the line below to get user friends list
-          // $openidauth->getUserContacts();
+        if (!is_null($row))
+           return $row['username'];
+        else
+           return null;
+    }
 
-          // uncomment the line below to post something to openidauth if you want to
-          // $openidauth->setUserStatus( "Hello world!" );
+    function lookup_user($username)
+    {
+        global $db;
 
-          // ex. on how to access the openidauth api with hybridauth
-          //     Returns the current count of friends, followers, updates (statuses) and favorites of the 
authenticating user.
-          //     https://dev.openidauth.com/docs/api/1/get/account/totals
-          $account_totals = $openidauth->api()->get( 'account/totals.json' );
+        $db->escape($username);
 
-          // print recived stats
-          echo "Here some of yours stats on Twitter:<br /><pre>" . print_r( $account_totals, true ) . 
"</pre>";
+        // Get current session data
+        $sql = "SELECT is_admin, fullname, email FROM {$db->prefix}profiles " .
+               "WHERE username = '{$username}'";
+        $row = $db->query($sql, true);
+        if (is_null($row)) {
+            return null;
+        } else {
+            $values = array();
 
-          // logout
-          echo "Logging out..";
-          $openidauth->logout();
-           */
+            $values['is_admin'] = $row['is_admin'] != 0;
+            $values['fullname'] = $row['fullname'];
+            $values['email'] = $row['email'];
 
+            return $values;
         }
-        catch (Exception $e) {
-          return false;
+    }
+
+    function create_user($provider, $identifier, $profile)
+    {
+        global $db;
+
+        $suffix = "";
+        $email = $profile->email;
+        if ($email != "") {
+            $pos = strpos($email, "@");
+            if ($pos === false)
+                $username = $email;
+            else
+                $username = substr($email, 0, $pos);
+        } else if ($profile->firstName != '' && $profile->lastName != '') {
+            $username = trim($profile->firstName) . "." . trim($profile->lastName);
+            $suffix = 1;
+        } else {
+            $username = 'user';
         }
 
-        /*TODO
-        if (true) {
-          $is_admin = true;
+        while ($this->lookup_user($username . $suffix)) {
+            if ($suffix === "")
+                $suffix = 1;
+            else
+                $suffix++;
         }
-         */
 
-        /*TODO
-        if (true) {
-          // Create a new session for the user
-          $this->create_session($username, $is_admin);
+        $username = $username . $suffix;
 
-          // Authentication was successful
-          return true;
+        if ($profile->emailVerified != "") {
+            $email = $profile->emailVerified;
+            $emailVerified = 1;
+        } else {
+            $email = $profile->email;
+            $emailVerified = 0;
         }
-         */
 
-        // Username was not found
-        return false;
+        // The OpenID provider sets displayName to a reversed lastname - firstname,
+        // if unset. Detect this to avoid thinking we got a real DisplayName from
+        // the provider.
+        $badDisplayName = trim( $this->user->profile->lastName . " " . $this->user->profile->firstName );
+
+        if ($profile->displayName != '' && $profile->displayName != $badDisplayName)
+            $fullname = $profile->displayName;
+        else if ($profile->firstName != '' && $profile->lastName != '')
+            $fullname = trim($profile->firstName) . " " . trim($profile->lastName);
+        else
+            $fullname = '';
+
+        $db->escape($username);
+        $db->escape($fullname);
+        $db->escape($email);
+
+        $sql = "INSERT INTO {$db->prefix}profiles " .
+                   "(username, fullname, email, emailVerified, is_admin) " .
+                   "VALUES ('{$username}', '{$fullname}', " .
+                   "        '{$email}', {$emailVerified}, 0)";
+        Hybrid_Logger::info("running: {$sql}");
+        $db->query($sql);
+
+        $db->escape($provider);
+        $db->escape($identifier);
+
+        $sql = "INSERT INTO {$db->prefix}identities " .
+                   "(provider, identifier, username) " .
+                   "VALUES ('{$provider}', '{$identifier}', '{$username}')";
+        Hybrid_Logger::info("running: {$sql}");
+        $db->query($sql);
+    }
+
+    function finish_login($provider)
+    {
+        $hybridauth = $this->hybridauth();
+
+        Hybrid_Logger::info("finish_login - $provider");
+
+        if ($provider == "OpenID" && $hybridauth->isConnectedWith("OpenID")) {
+            $adapter = $hybridauth->getAdapter("OpenID");
+            $profile = $adapter->getUserProfile();
+        } else if ($provider == "Google" && $hybridauth->isConnectedWith("Google")) {
+            $adapter = $hybridauth->getAdapter("Google");
+            $profile = $adapter->getUserProfile();
+        } else if ($provider == "Facebook" && $hybridauth->isConnectedWith("Facebook")) {
+            $adapter = $hybridauth->getAdapter("Facebook");
+            $profile = $adapter->getUserProfile();
+        } else {
+           return false;
+        }
+
+        Hybrid_Logger::info("finish_login - connected");
+
+        $identifier = $adapter->getUserProfile()->identifier;
+
+        Hybrid_Logger::info("finish_login - looking up identity");
+        $username = $this->lookup_identity($provider, $identifier);
+
+        if ($username == null) {
+            Hybrid_Logger::info("finish_login - create user");
+            $username = $this->create_user($provider, $identifier, $profile);
+        }
+
+        $info = $this->lookup_user($username);
+        $this->create_session($identifier, $info['is_admin']);
+
+        return true;
     }
 
     // Method for logging a user out
@@ -272,6 +398,9 @@ class user
     {
         global $core, $db;
 
+        $hybridauth = $this->hybridauth();
+        $hybridauth->logoutAllProviders();
+
         // Get username and session ID from cookie
         $username = $core->variable('username', '', true);
         $sid = $core->variable('session_id', '', true);
@@ -335,4 +464,3 @@ class user
         return str_replace(array('*', '\\', '(', ')'), array('\\*', '\\\\', '\\(', '\\)'), $string);
     }
 }
-
diff --git a/lang/en-gb.php b/lang/en-gb.php
index 1cb7a81..ea5ce70 100644
--- a/lang/en-gb.php
+++ b/lang/en-gb.php
@@ -75,6 +75,10 @@ $lang_data = array(
     'login_error'           => 'Login failed! Please notify the <a href="mailto:webmaster gnome org">' .
                                'webmaster</a> if the problem persists',
     'iko_credentials'       => 'Log into [[site_name]] using OpenID:',
+    'login_with_openid'     => 'Log into [[site_name]] using OpenID:',
+    'login_with_google'     => 'Log into [[site_name]] using your Google account:',
+    'login_with_facebook'   => 'Log into [[site_name]] using your Facebook account:',
+    'iko_credentials'       => 'Log into [[site_name]] using OpenID:',
     'password'              => 'Password',
     'create_account'        => 'Create a new account',
     'create_account_exp'    => 'Don\'t have an account? In order to log into [[site_name]], you\'ll need an 
OpenID account.',
diff --git a/modules/mod_login.php b/modules/mod_login.php
index 122e07b..2cc300a 100644
--- a/modules/mod_login.php
+++ b/modules/mod_login.php
@@ -11,6 +11,7 @@ if (!defined('IN_PANDORA')) exit;
 $username = $core->variable('username', '', false, true);
 $redir_url = $core->variable('r', '');
 $dest_url = !empty($redir_url) ? urldecode($redir_url) : $core->path();
+$provider = $core->variable('p', '');
 
 // Log the user out if already logged in
 if ($user->is_logged_in)
@@ -18,9 +19,17 @@ if ($user->is_logged_in)
     $core->redirect($dest_url);
 }
 
+// If we're on the end of successful authentication request
+if ($provider != '' && $user->finish_login($provider)) {
+    $core->redirect($dest_url);
+}
+
 // Login data was submitted
-$login_submit = isset($_POST['login']);
-if ($login_submit) {
+$login_openid = isset($_POST['login_openid']);
+$login_google = isset($_POST['login_google']);
+$login_facebook = isset($_POST['login_facebook']);
+
+if ($login_openid) {
     if (!empty($username)) {
         // Check if user is banned
         $is_banned = $user->is_banned($username);
@@ -45,6 +54,26 @@ if ($login_submit) {
     else {
         $error_message = $lang->get('enter_openid');
     }
+} else if ($login_google) {
+   $login_success = $user->login_google($username);
+
+   // Check if login succeeded
+   if ($login_success) {
+       $core->redirect($dest_url);
+   }
+   else {
+       $error_message = $lang->get('login_error');
+   }
+} else if ($login_facebook) {
+   $login_success = $user->login_facebook($username);
+
+   // Check if login succeeded
+   if ($login_success) {
+       $core->redirect($dest_url);
+   }
+   else {
+       $error_message = $lang->get('login_error');
+   }
 }
 
 // Assign skin data
diff --git a/modules/mod_user_profile.php b/modules/mod_user_profile.php
index 69c2975..4b5b8fd 100644
--- a/modules/mod_user_profile.php
+++ b/modules/mod_user_profile.php
@@ -15,34 +15,22 @@ $return_url = urldecode($return_encoded);
 $username = urldecode($username_encoded);
 
 // We need username for this module
-$user->restrict(!empty($username));
-
-// Build an array of the data that we need
-$required_data = array(
-    $config->ldap_fullname,
-    $config->ldap_mail,
-    $config->ldap_group,
-);
+if (empty($username)) {
+   $user->restrict(!is_null($user->username));
+   $username = $user->username;
+}
 
 // Get the user data
-$username_data = $user->get_details($username, $required_data);
+$username_data = $user->lookup_user($username);
 
 // Set the template data
-if (isset($username_data[$config->ldap_mail]))
+if (!is_null($username_data))
 {
     $is_admin   = false;
     $avatar_url = "?q=user_avatar&amp;u={$username_encoded}";
-    $full_name  = $username_data[$config->ldap_fullname][0];
-    $user_email = $username_data[$config->ldap_mail][0];
-
-    // Determine if the user is a site admin
-    foreach ($username_data[$config->ldap_group] as $group)
-    {
-        if ($group == $config->ldap_admin_group)
-        {
-            $is_admin = true;
-        }
-    }
+    $full_name  = $username_data['fullname'];
+    $user_email = $username_data['email'];
+    $is_admin = $username_data['is_admin'];
 
     // Assign profile variables
     $skin->assign(array(
diff --git a/schema.sql b/schema.sql
index 1243378..0bcc94f 100644
--- a/schema.sql
+++ b/schema.sql
@@ -71,3 +71,19 @@ CREATE TABLE `opw_queue` (
   PRIMARY KEY (`id`),
   FOREIGN KEY (`program_id`) REFERENCES `opw_programs`(`id`)
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+CREATE TABLE `opw_identities` (
+  `provider` varchar(20) NOT NULL,
+  `identifier` varchar(255) NOT NULL,
+  `username` varchar(255) NOT NULL,
+  PRIMARY KEY (`provider`, `identifier`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+CREATE TABLE `opw_profiles` (
+  `username` varchar(255) NOT NULL,
+  `fullname` varchar(255) NOT NULL,
+  `email` varchar(255) NOT NULL,
+  `emailVerified` tinyint(1) DEFAULT 0,
+  `is_admin` tinyint(1) DEFAULT 0,
+  PRIMARY KEY (`username`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
diff --git a/skins/easterngreen/html/tpl_login.html b/skins/easterngreen/html/tpl_login.html
index ed8f136..e7de0bc 100644
--- a/skins/easterngreen/html/tpl_login.html
+++ b/skins/easterngreen/html/tpl_login.html
@@ -6,7 +6,7 @@
     [[error_message]]
 </div>
 
-<h4>{{iko_credentials}}</h4>
+<h4>{{login_with_openid}}</h4>
 <br />
 
 <div class="control-group">
@@ -26,10 +26,24 @@
 -->
 
 <div class="form-actions">
-    <button type="submit" name="login" class="btn btn-primary">{{log_in}}</button>
+    <button type="submit" name="login_openid" class="btn btn-primary">{{log_in}}</button>
     <button type="reset" class="btn">{{reset}}</button>
 </div>
 
+<h4>{{login_with_google}}</h4>
+<br />
+
+<div class="form-actions">
+    <button type="submit" name="login_google" class="btn btn-primary">{{log_in}}</button>
+</div>
+
+<h4>{{login_with_facebook}}</h4>
+<br />
+
+<div class="form-actions">
+    <button type="submit" name="login_facebook" class="btn btn-primary">{{log_in}}</button>
+</div>
+
 <!--
 <div class="alert alert-info">
     <h3>{{create_account}}</h3>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]