Skip to content

Instantly share code, notes, and snippets.

@gautiermichelin
Created November 1, 2015 10:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gautiermichelin/15bf48f92d93e019d55e to your computer and use it in GitHub Desktop.
Save gautiermichelin/15bf48f92d93e019d55e to your computer and use it in GitHub Desktop.
<?php
/** ---------------------------------------------------------------------
* app/lib/core/Auth/Adapters/PafiExternalDB.php : External database authentication backend using Joomla for CollectiveAccess
* ----------------------------------------------------------------------
* CollectiveAccess
* Open-source collections management software
* ----------------------------------------------------------------------
*
* Software by Whirl-i-Gig (http://www.whirl-i-gig.com)
* Copyright 2014 Whirl-i-Gig
* This file was created by Idéesculture for Project PAFI, LAUM & ENSIM - University of Le Mans, France
*
* For more information visit http://www.CollectiveAccess.org
*
* This program is free software; you may redistribute it and/or modify it under
* the terms of the provided license as published by Whirl-i-Gig
*
* CollectiveAccess is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTIES whatsoever, including any implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* This source code is free and modifiable under the terms of
* GNU General Public License. (http://www.gnu.org/copyleft/gpl.html). See
* the "license.txt" file for details, or visit the CollectiveAccess web site at
* http://www.CollectiveAccess.org
*
* @package CollectiveAccess
* @subpackage Auth
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License version 3
*
* ----------------------------------------------------------------------
*/
require_once(__CA_LIB_DIR__.'/core/Auth/BaseAuthAdapter.php');
require_once(__CA_LIB_DIR__.'/core/Auth/PasswordHash.php');
class PafiExternalDBAuthAdapter extends BaseAuthAdapter implements IAuthAdapter {
# --------------------------------------------------------------------------------
public function getPafiUser($ps_username, $ps_password = '', $pa_options=null) {
global $pafi_ext_db_params;
if(!$ps_username) {
return false;
}
$o_auth_config = Configuration::load(Configuration::load()->get('authentication_config'));
$o_log = new Eventlog();
$pafi_ext_db_params = $o_auth_config->get("pafi_ext_db_params");
$o_ext_db = new Db(null, array(
'host' => $pafi_ext_db_params["host"],
'username' => $pafi_ext_db_params["username"],
'password' => $pafi_ext_db_params["password"],
'database' => $pafi_ext_db_params["database"],
'type' => $pafi_ext_db_params["type"],
'persistent_connections' => ($pafi_ext_db_params["persistent_connections"] == "1")
), false);
$vs_joomla_path = $pafi_ext_db_params["joomla_path"];
// couldn't connect to external database
if(!$o_ext_db->connected()) {
$o_log->log(array(
'CODE' => 'LOGF', 'SOURCE' => 'PafiExternalDBAuthAdapter',
'MESSAGE' => _t('Could not login user %1 using PAFI external database because login to external database failed [%2]', $ps_username, $_SERVER['REMOTE_ADDR'])
));
return false;
}
// TODO GM : Clear text : need to encode through Joomla salting process
$ps_password_proc = $ps_password;
define('_JEXEC', 1);
if (file_exists($vs_joomla_path . '/defines.php')) include_once $vs_joomla_path . '/defines.php';
if (!defined('_JDEFINES')) {
define('JPATH_BASE', $vs_joomla_path);
require_once JPATH_BASE . '/includes/defines.php';
}
require_once JPATH_BASE . '/includes/framework.php';
// Instantiate the application.
$app = JFactory::getApplication('site');
// JFactory
require_once (JPATH_BASE .'/libraries/joomla/factory.php');
// Get a database object
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->select('id, password')
->from('#__users')
->where('username=' . $db->quote($ps_username));
$db->setQuery($query);
$result = $db->loadObject();
// We have a result
if ($result) {
$match = JUserHelper::verifyPassword($ps_password_proc, $result->password, $result->id);
if ($match === true) {
// Password is OK
//echo 'Joomla! Authentication was successful!';
//getting group names
$va_groups = JUserHelper::getUserGroups($result->id);
if (empty($va_groups)) {
echo "no groups!!!!";
return;
}
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('title')->from('#__usergroups')->where('id IN (' . implode(',', $va_groups) . ')');
$db->setQuery($query);
$va_groupnames = $db->loadColumn();
// creating answer array
$va_juser_infos = array(
"id" => $result->id,
"groups" => $va_groupnames,
"instance" => JUser::getInstance($result->id)
);
// if the user is already inside the CA DB, update the group he's linked to
PafiExternalDBAuthAdapter::updateUserGroups($ps_username, $va_groupnames);
return $va_juser_infos;
} else {
// Invalid password
// Prmitive error handling
die('Invalid password');
return false;
}
} else {
// Invalid user
// Prmitive error handling
die('Cound not find user in the database');
return false;
}
}
# --------------------------------------------------------------------------------
public static function authenticate($ps_username, $ps_password = '', $pa_options=null) {
$vt_user_info = PafiExternalDBAuthAdapter::getPafiUser($ps_username, $ps_password, $pa_options);
if($vt_user_info !== false) {
return true;
} else {
return false;
}
}
# --------------------------------------------------------------------------------
public static function createUserAndGetPassword($ps_username, $ps_password) {
global $pafi_ext_db_params;
// We don't create users in external databases, we assume they're already there
// We will create a password hash that is compatible with the CaUsers authentication adapter though
// That way users could, in theory, turn off external db authentication later. The hash will not be used
// for authentication in this adapter though.
return create_hash($ps_password);
}
public function updateUserGroups($ps_username, $pa_groups) {
$t_user = new ca_users();
if($t_user->load($ps_username)) {
$t_user->setMode(ACCESS_WRITE);
$t_user->removeFromAllGroups();
$t_user->addToGroups($pa_groups);
return true;
} else {
return false;
}
}
# --------------------------------------------------------------------------------
# getUserInfo : this function is only called if the user is not already inside the CA DB
# --------------------------------------------------------------------------------
public static function getUserInfo($ps_username, $ps_password) {
$vt_user_info = PafiExternalDBAuthAdapter::getPafiUser($ps_username, $ps_password);
$o_log = new Eventlog();
// user role and group membership syncing with directory
$t_user = new ca_users();
if(!$t_user->load($ps_username)) {
// Non existing user, inserting him inside the DB
$vt_user_instance =$vt_user_info["instance"];
//var_dump($vt_user_instance);
$t_user->setMode(ACCESS_WRITE);
$t_user->set("user_name",$vt_user_instance->username);
$t_user->set('userclass', 0); // 1=public user 0=back-end login allowed
$t_user->set("fname","_");
$t_user->set("lname",$vt_user_instance->name);
$t_user->set("email",$vt_user_instance->email);
$t_user->set("active", 1);
$t_user->insert();
if ($t_user->numErrors()) {
$o_log->log(array(
'CODE' => 'LOGF', 'SOURCE' => 'PafiExternalDBAuthAdapter',
'MESSAGE' => _t('Errors occurred when creating new user: %1', join('; ', $t_user->getErrors()))
));
} else {
$vn_user_id = $t_user->getPrimaryKey();
$o_log->log(array(
'CODE' => 'LOGF', 'SOURCE' => 'PafiExternalDBAuthAdapter',
'MESSAGE' => _t('Created new client login for <em>%1</em>. Login name is <em>%2</em>', $vs_fname.' '.$vs_lname, $vs_user_name)
));
}
PafiExternalDBAuthAdapter::updateUserGroups($ps_username, $vt_user_info["groups"]);
}
// User was already there or has been loaded, updating groups
$va_return['user_name'] = $vt_user_instance->username;
$va_return['active'] = $t_user->get("active");
$va_return['userclass'] = $t_user->get("userclass"); //$vn_user_class;
// map fields : no fields
// map preferences : no preferences
// user roles : no role, everything is handled through groups
$va_return['roles'] = array();
// set user groups
$va_return['groups'] = $vt_user_info["groups"];
return $va_return;
}
# --------------------------------------------------------------------------------
public static function supports($pn_feature) {
global $pafi_ext_db_params;
switch($pn_feature){
case __CA_AUTH_ADAPTER_FEATURE_AUTOCREATE_USERS__:
return true;
case __CA_AUTH_ADAPTER_FEATURE_RESET_PASSWORDS__:
case __CA_AUTH_ADAPTER_FEATURE_UPDATE_PASSWORDS__:
default:
return false;
}
}
# --------------------------------------------------------------------------------
public static function deleteUser($ps_username) {
global $pafi_ext_db_params;
// do something?
return true;
}
# --------------------------------------------------------------------------------
public static function getAccountManagementLink() {
global $pafi_ext_db_params;
$o_auth_cfg = Configuration::load(Configuration::load()->get('authentication_config'));
if($vs_link = $o_auth_cfg->get('extdb_manage_account_url')) {
return $vs_link;
}
return false;
}
# --------------------------------------------------------------------------------
}
class ExternalDBException extends Exception {}
@gautiermichelin
Copy link
Author

To activate this authentication adapter for CA :

  1. Define
auth_adapter = PafiExternalDB

inside app/conf/authentication.conf
2. Add at the end of app/conf/authentication.conf the next lines :

pafi_ext_db_params = {
    host                = localhost,
    username        = pafi_joomla_portal_user,
    password        = this_is_a_secret_password_I_wont_publish_here,
    database        = pafi_joomla_portal,
    type                = mysql,
    persistent_connections = 1,
    joomla_path         = /Volumes/Data/www/pafi/pafi_joomla_portal,
    ca_groups       = {
                    luthier,
                    musicien,
                    acousticien,
                    etudiant,
                    developpeur,
                    administrateur
                }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment