Skip to content

CL Auth Integration with Vanilla Forum Engine

World Wide Web Server edited this page Jul 4, 2012 · 16 revisions

Category:Core | Category:Core::Integration | Category:Library::Authorization

After a week of picking through code upon code, and even more time wasted on debugging errors, I finally managed to come up with a viable solution for using CL Auth (A New Codeigniter authentication system) in conjunction with the Vanilla Forum Engine. This is huge for so many reasons but mainly, it gives CI users another authentication/open source forum solution.

Before I proceed I must give thanks to Grahack, one of the contributors to FreakAuth. I used his integration AND Dip method/Vanilla integration doc as a foundation for this write up and the eventual code that lead to it's completion.

[b]Requirements[/b]

  1. [url=http://www.codeigniter.com]Codeigniter[/url] - You will need the Codeigniter Framework of course. I have this working with version 1.6.2 and have not tested 1.6.3 yet.
  2. You will then need to [url=http://codeigniter.com/wiki/dip_into_CI/]dip into CI[/url] - You will need to make use of this technique that has been dubbed "dipping into CI". It will provide you with a means to make use of CI in external applications without too much fuss (Use at your own risk).
  3. [url=http://www.jasonashdown.co.uk/ci/CL_Auth-BETA-v0.1.zip]CL Auth[/url] - You will need the latest copy of CL Auth.
  4. [url=http://www.getvanilla.com]Vanilla[/url] - You will need the latest copy of Vanilla

[b]Original Guides Used[/b]

[url=http://www.bubbleeconomics.com/blog/]Pligg Vanilla Integration Write Up[/url] <-- Originally made use of the [url=http://lussumo.com/docs/doku.php?id=vanilla:integration:drupal]Drupal Integration[/url] Doc over at Lussumo [url=http://codeigniter.com/wiki/dip_into_CI/]Dip into CI[/url] [url=http://lussumo.com/docs/doku.php?id=vanilla:integration:wordpress]Vanilla Integration with Wordpress[/url] [url=http://www.jasonashdown.co.uk/cl_auth_doc/]CL Auth Documentation[/url]

[b]Vanilla Installation[/b]

This part through me for a loop at first. I wasn't sure where to place the Vanilla directory in relation to my main Codeigniter application and system directory.

You have to install Vanilla in a subdirectory next to your System folder (In other words, it should live in your root folder). Run the installation and follow all of Vanilla's steps making sure to include Vanilla's database in the same table as your CI installation (Vanilla tables will be prefixed with "LUM_").

Note: If you are working on a test server and do not have a mysql password set for your mysql user, then you will want to add the following line to [b]/conf/database.php[/b]

[CODE] $Configuration['DATABASE_PASSWORD'] = ''; [/CODE]

Once Vanilla has been installed properly, we get to the good stuff.

[b]Database Mapping[/b]

in [b]/conf/database.php[/b], add the following lines before the closing php bracket ([b]?>[/b])

replace "YOUR USER TABLE NAME HERE" with the actual name of your User table. I used a prefix for my user table, but the default CL auth table is "users".

[code] //Integrate with CI here $DatabaseTables['User'] = 'YOUR USER TABLE NAME HERE'; include 'ci_integration_database.php'; // End CI integration [/code]

Now you must create the [b]CI_integration_database.php[/b]. In this file you are going to map the appropriate columns of your user table to Vanilla's DB schema.

[code] <?php // Vanilla-CI Authentication Integration

// Map existing and matching CI User columns $DatabaseColumns['User']['UserID'] = 'id'; $DatabaseColumns['User']['Name'] = 'username'; $DatabaseColumns['User']['Password'] = 'password'; $DatabaseColumns['User']['Email'] = 'email'; $DatabaseColumns['User']['DateLastActive'] = 'last_visit'; $DatabaseColumns['User']['DateFirstVisit'] = 'created';

// Also map the other CI User columns $DatabaseColumns['User']['group_id'] = 'group_id'; $DatabaseColumns['User']['user_ip'] = 'user_ip'; $DatabaseColumns['User']['username_clean'] = 'username_clean'; $DatabaseColumns['User']['banned'] = 'banned'; $DatabaseColumns['User']['ban_reason'] = 'ban_reason'; $DatabaseColumns['User']['login_attempts'] = 'login_attempts'; $DatabaseColumns['User']['newpass'] = 'newpass'; $DatabaseColumns['User']['newpass_key'] = 'newpass_key'; $DatabaseColumns['User']['newpass_time'] = 'newpass_time'; $DatabaseColumns['User']['active_time'] = 'active_time'; $DatabaseColumns['User']['modified'] = 'modified';

?> [/code]

Now you have to add the columns that are missing from Vanilla's user table to your User table. Hope I didn't mix anyone up there. It's simple, just run the following SQL code in your favorite Mysql Database management software, most likely it will be phpmyadmin, (Pay close attention to the warning): WARNING: The "users" in this script should be replaced by your table name if it is something besides "users".

[code] ALTER TABLE users ADD RoleID int(2) NOT NULL default '3', ADD StyleID int(3) NOT NULL default '1', ADD CustomStyle varchar(255) default NULL, ADD FirstName varchar(50) NOT NULL default '', ADD LastName varchar(50) NOT NULL default '', ADD VerificationKey varchar(50) NOT NULL default '', ADD EmailVerificationKey varchar(50) default NULL, ADD UtilizeEmail enum('1','0') NOT NULL default '0', ADD ShowName enum('1','0') NOT NULL default '1', ADD Icon varchar(255) default NULL, ADD Picture varchar(255) default NULL, ADD Attributes text NULL, ADD CountVisit int(8) NOT NULL default '0', ADD CountDiscussions int(8) NOT NULL default '0', ADD CountComments int(8) NOT NULL default '0', ADD DateFirstVisit datetime NOT NULL default '0000-00-00 00:00:00', ADD DateLastActive datetime NOT NULL default '0000-00-00 00:00:00', ADD RemoteIp varchar(100) NOT NULL default '', ADD LastDiscussionPost datetime default NULL, ADD DiscussionSpamCheck int(11) NOT NULL default '0', ADD LastCommentPost datetime default NULL, ADD CommentSpamCheck int(11) NOT NULL default '0', ADD UserBlocksCategories enum('1','0') NOT NULL default '0', ADD DefaultFormatType varchar(20) default NULL, ADD Discovery text, ADD Preferences text, ADD SendNewApplicantNotifications enum('1','0') NOT NULL default '0',

ADD KEY user_role (RoleID), ADD KEY user_style (StyleID), ADD KEY user_name (user_name); [/code]

Now you have to give your CI user the same Superadmin rights as the Vanilla Superadmin you created when you first installed Vanilla. Use the following SQL to achieve this and remember that we still need to change the "users" name here if our table uses a different name for "users".

[code] update users set RoleID=(select RoleID from LUM_User where id=1), StyleID=(select StyleID from LUM_User where id=1), CustomStyle=(select CustomStyle from LUM_User where id=1), FirstName=(select FirstName from LUM_User where id=1), LastName=(select LastName from LUM_User where id=1), VerificationKey=(select VerificationKey from LUM_User where id=1), EmailVerificationKey=(select EmailVerificationKey from LUM_User where id=1), UtilizeEmail=(select UtilizeEmail from LUM_User where id=1), ShowName=(select ShowName from LUM_User where id=1), Icon=(select Icon from LUM_User where id=1), Picture=(select Picture from LUM_User where id=1), Attributes=(select Attributes from LUM_User where id=1), CountVisit=(select CountVisit from LUM_User where id=1), CountDiscussions=(select CountDiscussions from LUM_User where id=1), CountComments=(select CountComments from LUM_User where id=1), DateFirstVisit=(select DateFirstVisit from LUM_User where id=1), DateLastActive=(select DateLastActive from LUM_User where id=1), RemoteIp=(select RemoteIp from LUM_User where id=1), LastDiscussionPost=(select LastDiscussionPost from LUM_User where id=1), DiscussionSpamCheck=(select DiscussionSpamCheck from LUM_User where id=1), LastCommentPost=(select LastCommentPost from LUM_User where id=1), CommentSpamCheck=(select CommentSpamCheck from LUM_User where id=1), UserBlocksCategories=(select UserBlocksCategories from LUM_User where id=1), DefaultFormatType=(select DefaultFormatType from LUM_User where id=1), Discovery=(select Discovery from LUM_User where id=1), Preferences=(select Preferences from LUM_User where id=1), SendNewApplicantNotifications=(select SendNewApplicantNotifications from LUM_User where id=1) where id=1; [/code]

[b]Now for the business end of it all.[/b]

The authenticator class is the class that makes the magic happen in Vanilla. It handles the logging in and logging out of users, as well as their sessions and cookies while they are on the site.

Add the following to [b]/conf/settings.php[/b]

[code] // CI integration $Configuration['AUTHENTICATION_MODULE'] = 'People/People.Class.CI_Authenticator.php'; $Configuration['SAFE_REDIRECT'] = '../index.php/auth/'; [/code]

Now we must create the [b]People.Class.CI_Authenticator.php[/b]. We are going to place this file in the [b]/library/People/[/b] folder.

[code] <?php /*

  • Copyright 2003 Mark O'Sullivan

  • This file is part of People: The Lussumo User Management System.

  • Lussumo's Software Library 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.

  • Lussumo's Software Library 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 Vanilla; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

  • The latest source code is available at www.lussumo.com

  • Contact Mark O'Sullivan at mark [at] lussumo [dot] com

  • Description: Codeigniter authentication interface. Written in part by Christophe Gragnic (grahack) & Nial Grimes (Pligg community member).

  • Also thanks to Mark O'Sullivan at Lussumo.com for his Wordpress Integration with Vanilla.

  • Devon Lambert (dnyce) - We've made changes to the authenticate, deauthenticate, and GetIdentity functions.

  • Authenticate and Deauthenticate will not be used and therefore should always return 1.

      • Applications utilizing this file: Vanilla; */ class Authenticator { var $Context;

    function Authenticator(&$Context) {
    $this->Context = &$Context; }

    function GetIdentity() {

      if (!session_id()) {
       session_set_cookie_params(0, $this->Context->Configuration['COOKIE_PATH'], $this->Context->Configuration['COOKIE_DOMAIN']);
       session_start();
      }
      
        // We have a guest till proven a member
      $UserID = 0;
      
      // Check if CI cookie is available (i.e. user has logged into CI/Auth Program)
      
      // Include the CI settings
      require($this->Context->Configuration['APPLICATION_PATH'].'../system/cidip/cidip_index.php');
            $obj =& get_instance();
       
      $Userid = $obj->cl_session->userdata('user_id'); 
      $Sessid = $obj->cl_session->userdata('session_id');
      $Username = $obj->cl_session->userdata('username');
      
       if(isset($_COOKIE['ci_session'])) {
      
      // Find user in the CI user table
      $s = $this->Context->ObjectFactory->NewContextObject($this->Context, 'SqlBuilder');
      $s->SetMainTable('User', 'u');
      $s->AddSelect('UserID', 'u');
      $s->AddSelect('Password', 'u');
      $s->AddWhere('u', 'Name', '', FormatStringForDatabaseInput($Username), '=');
        
      $Result = $this->Context->Database->Select($s,
       'Authenticator',
       'GetIdentity',
       'An error occurred while attempting to validate your remember me credentials');
    
      }
      
      if ($Result) {
    
               // Retrieve the username and encrypted password from the database
              while ($rows = $this->Context->Database->GetRow($Result)) {
              $UserID = ForceInt($rows['UserID'], 0);
              $Password = $rows['Password'];
      }
    
          if ($UserID > 0) {
               
              // 1. Update the user's information
              $this->UpdateLastVisit($UserID);
                                
              // 2. Log the user's IP address
              $this->LogIp($UserID);
          }
      }
           
      // If it has now been found, set up the session.
      $this->AssignSessionUserID($UserID);
      return $UserID;
    

    }

    // All methods below this point are specific to this authenticator and // should not be treated as interface methods. The only required interface // properties and methods appear above.

    function AssignSessionUserID($UserID) { if ($UserID > 0) { @$_SESSION[$this->Context->Configuration['SESSION_USER_IDENTIFIER']] = $UserID; } }

    function LogIp($UserID) { if ($this->Context->Configuration['LOG_ALL_IPS']) { $s = $this->Context->ObjectFactory->NewContextObject($this->Context, 'SqlBuilder'); $s->SetMainTable('IpHistory', 'i'); $s->AddFieldNameValue('UserID', $UserID); $s->AddFieldNameValue('RemoteIp', GetRemoteIp(1)); $s->AddFieldNameValue('DateLogged', MysqlDateTime());

       $this->Context->Database->Insert($s,
          'Authenticator',
          'LogIp',
          'An error occurred while logging your IP address.',
          false); // fail silently
    }
    

    }

    function SetCookieCredentials($CookieUserID, $VerificationKey) { // Note: 2592000 is 606024*30 or 30 days setcookie($this->Context->Configuration['COOKIE_USER_KEY'], $CookieUserID, time()+2592000, $this->Context->Configuration['COOKIE_PATH'], $this->Context->Configuration['COOKIE_DOMAIN']); setcookie($this->Context->Configuration['COOKIE_VERIFICATION_KEY'], $VerificationKey, time()+2592000, $this->Context->Configuration['COOKIE_PATH'], $this->Context->Configuration['COOKIE_DOMAIN']); }

    function UpdateLastVisit($UserID, $VerificationKey = '') { $s = $this->Context->ObjectFactory->NewContextObject($this->Context, 'SqlBuilder'); $s->SetMainTable('User', 'u'); $s->AddFieldNameValue('DateLastActive', MysqlDateTime()); if ($VerificationKey != '') $s->AddFieldNameValue('VerificationKey', $VerificationKey); $s->AddFieldNameValue('CountVisit', 'CountVisit + 1', 0); $s->AddWhere('u', 'UserID', '', $UserID, '=');

    $this->Context->Database->Update($s,
       'Authenticator',
       'UpdateLastVisit',
       'An error occurred while updating your profile.',
       false); // fail silently
    

    }

    function Authenticate() { return 1; }

    function DeAuthenticate() { return 1; } } ?> [/code]

Finally, we need to place one final touch on it all. Go to your "[b]themes[/b]" folder in Vanilla. Make a copy of the "[b]vanilla[/b]" folder found there. Name this copy whatever you would like, for our purposes we will call this folder "[b]Vanilla_2[/b]". This will provide you with a new theme/styling template that you can use to make changes to the look and feel of your forum.

Go back to the "[b]themes[/b]" folder, make a copy of the [b]head.php[/b], [b]menu.php[/b], and [b]foot.php[/b] and place the copies in your new "[b]Vanilla_2[/b]" folder.

Now open up the [b]menu.php[/b] in your new theme folder and find the section at the top that looks like this:

[code] echo '

'; if ($this->Context->Session->UserID > 0) { echo str_replace('//1', $this->Context->Session->User->Name, $this->Context->GetDefinition('SignedInAsX')).' (Context->Configuration['SIGNOUT_URL'].'">'.$this->Context->GetDefinition('SignOut').')'; } else { echo $this->Context->GetDefinition('NotSignedIn').' (Context->Configuration['SIGNIN_URL'], 'ReturnUrl='.GetRequestUri()).'">'.$this->Context->GetDefinition('SignIn').')'; } echo '
'; [/code]

Replace it all with the following:

[code] ?>

<?php echo '

'; ?>

<?php $obj =& get_instance(); ?>

<?php /*Login/Logout Loop */ ?> <? if ( $obj->cl_auth->isValidUser() ) : ?> <?=anchor($obj->config->item('CL_logout_uri'), 'Logout')?> <? else: ?> <?=anchor($obj->config->item('CL_login_uri'), 'Login')?> - <?=anchor($obj->config->item('CL_register_uri'), 'Register')?> <? endif; ?>

<?php /*END Login/Logout Loop */ ?>

<?php echo '

'; ?>

<?php [/code]

If you've installed CL Auth and Codeigniter properly, then you should now be able to log into CL Auth using [b]Your Website URL/auth/login[/b] and have your session/cookie carry over to Vanilla.

Go have fun, play around, test it, break it, and let me know if I've missed anything.

Clone this wiki locally