Skip to content
Snippets Groups Projects
Commit e1ad2dbd authored by Tyler Antonio's avatar Tyler Antonio
Browse files

Created a central database class and updated the PDO MetaDataStorangeHandler...

Created a central database class and updated the PDO MetaDataStorangeHandler to use it instead of its own database classes
parent 24b27b33
Branches
Tags
No related merge requests found
...@@ -197,6 +197,61 @@ $config = array( ...@@ -197,6 +197,61 @@ $config = array(
), ),
/*
* Database
*
* This database configuration is optional. If you are not using
* core funcationlity or modules that require a database, you can
* skip this configuration.
*/
/*
* Database connection string.
* Ensure that you have the required PDO database drive installed
* for your connection string.
*/
'database.dsn' => 'mysql:host=localhost;dbname=saml',
/*
* SQL database credentials
*/
'database.username' => 'simplesamlphp',
'database.password' => 'secret',
/*
* (Optional) Table prefix
*/
'database.prefix' => '',
/*
* True or false if you would like a persisent datata connection
*/
'database.persistent' => false,
/*
* Database slave configuration is optional as well. If you are only
* running a single database server, leave this blank. If you have
* a master/slave conifguration, you can define as many slave servers
* as you want here. Slaves will be picked at random to be queried from.
*
* Configuration options in the salve array are exactly the same as the
* options for the master (shown above) with the exception of the table
* prefix.
*/
'database.slaves' => array(
/*
array(
'dsn' => 'mysql:host=myslave;dbname=saml',
'username' => 'simplesamlphp',
'password' => 'secret',
'persistent' => false,
),
*/
),
/* /*
* Enable * Enable
* *
...@@ -572,13 +627,13 @@ $config = array( ...@@ -572,13 +627,13 @@ $config = array(
* hours (86400 seconds). Optional. * hours (86400 seconds). Optional.
* *
* PDO metadata handler: * PDO metadata handler:
* This metadata handler looks up for the metadata of an entity stored in a database. * This metadata handler looks up metadata of an entity stored in a database.
*
* Note: If you are using the PDO metadata handler, you must configure the database
* options in this configuration file.
*
* The PDO metadata handler defines the following options: * The PDO metadata handler defines the following options:
* - 'type': This is always 'pdo'. * - 'type': This is always 'pdo'.
* - 'dsn': The database connection string. Mandatory.
* - 'username': Database username
* - 'cachedir': Database password
* - 'usePersistentConnection': Enable/Disable persistent database connection. Default is false.
* *
* *
* Examples: * Examples:
...@@ -604,7 +659,7 @@ $config = array( ...@@ -604,7 +659,7 @@ $config = array(
* *
* This example defines an pdo source. * This example defines an pdo source.
* 'metadata.sources' => array( * 'metadata.sources' => array(
* array('type' => 'pdo', server => 'mysql:host=localhost;dbname=saml', 'username' => 'simplesamlphp', 'password' => 'SuperSecretPassword') * array('type' => 'pdo')
* ), * ),
* *
* Default: * Default:
......
<?php
/**
* This file implements functions to read and write to a group of database
* servers.
*
* This database class supports a single database, or a master/slave
* configuration with as many defined slaves as a user would like.
*
* The goal of this class is to provide a single mechanism to connect to a database
* that can be reused by any component within SimpleSAMLphp including modules.
* When using this class, the global configuration should be passed here, but
* in the case of a module that has a good reason to use a different database,
* such as sqlauth, an alternative config file can be provided.
*
* @author Tyler Antonio, University of Alberta. <tantonio@ualberta.ca>
* @package simpleSAMLphp
*/
class SimpleSAML_Database {
/**
* This variable holds the instance of the session - Singleton approach.
*/
private static $instance = array();
/**
* PDO Object for the Master database server
*/
private $dbMaster;
/**
* Array of PDO Objects for configured database
* slaves
*/
private $dbSlaves = array();
/**
* Prefix to apply to the tables
*/
private $tablePrefix;
/**
* Retrieves the current database instance. Will create a new one if there isn't an existing connection.
*
* @param object $altConfig Optional: Instance of a SimpleSAML_Configruation class
* @return SimpleSAML_Database The shared database connection.
*/
public static function getInstance($altConfig = null) {
$config = ($altConfig)? $altConfig : SimpleSAML_Configuration::getInstance();
$instanceId = spl_object_hash($config);
/* Check if we already have initialized the session. */
if (isset(self::$instance[$instanceId])) {
return self::$instance[$instanceId];
}
/* Create a new session. */
self::$instance[$instanceId] = new SimpleSAML_Database($config);
return self::$instance[$instanceId];
}
/**
* Private constructor that restricts instantiation to getInstance().
*
* @param object $config Instance of the SimpleSAML_Configruation class
*/
private function __construct($config) {
$driverOptions = array();
if ($config->getBoolean('database.persistent', TRUE)) {
$driverOptions = array(PDO::ATTR_PERSISTENT => TRUE);
}
// Connect to the master
$this->dbMaster = $this->connect($config->getValue('database.dsn'), $config->getValue('database.username'), $config->getValue('database.password'), $driverOptions);
// Connect to any configured slaves
$slaves = $config->getValue('database.slaves');
if (count($slaves >= 1)) {
foreach ($slaves as $slave) {
array_push($this->dbSlaves, $this->connect($slave['dsn'], $slave['username'], $slave['password'], $driverOptions));
}
}
$this->tablePrefix = $config->getString('database.prefix', '');
}
/**
* This function connects to a dabase.
*
* @param $dsn Database connection string
* @param $username SQL user
* @param $password SQL password
* @param $options PDO options
*
* @return PDO object
*/
private function connect($dsn, $username, $password, $options){
try{
$db = new PDO($dsn, $username, $password, $options);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $db;
} catch(PDOException $e){
throw new Exception("Database error: ". $e->getMessage());
}
}
/**
* This function randomly selects a slave database server
* to query. In the event no slaves are configured, it
* will return the master.
*
* @return PDO object
*/
private function getSlave(){
if (count($this->dbSlaves) > 0) {
$slaveId = rand(0,count($this->dbSlaves)-1);
return $this->dbSlaves[$slaveId];
} else {
return $this->dbMaster;
}
}
/**
* This function simply applies the table prefix to
* a suppled table name.
*
* @param $table Table to apply prefix,if configured
* @return string Table with configured prefix
*/
public function applyPrefix($table){
return $this->tablePrefix . $table;
}
/**
* This function queries the database
*
* @param $db PDO object to use
* @param $stmt Prepared SQL statement
* @param $params Parameters
*
* @return PDO statement object
*/
private function query($db, $stmt, $params){
assert('is_object($db)');
assert('is_string($stmt)');
assert('is_array($params)');
try{
$query = $db->prepare($stmt);
foreach ($params as $param => $value) {
if(is_array($value)){
$query->bindValue(":$param", $value[0], ($value[1])? $value[1] : PDO::PARAM_STR);
}
else{
$query->bindValue(":$param", $value, PDO::PARAM_STR);
}
}
$query->execute();
if ($query->execute() === FALSE) {
throw new Exception("Database error: " . var_export($this->pdo->errorInfo(), TRUE));
}
return $query;
} catch (PDOException $e){
throw new Exception("Database error: ". $e->getMessage());
}
}
/**
* This executes queries directly on the master.
*
* @param $stmt Prepared SQL statement
* @param $params Parameters
*
* @return PDO statement object
*/
public function write($stmt, $params = array()){
$db = $this->dbMaster;
return $this->query($db, $stmt, $params);
}
/**
* This executes queries on a database server
* that is determined by this::getSlave()
*
* @param $stmt Prepared SQL statement
* @param $params Parameters
*
* @return PDO statement object
*/
public function read($stmt, $params = array()){
$db = $this->getSlave();
return $this->query($db, $stmt, $params);
}
}
...@@ -20,7 +20,7 @@ class SimpleSAML_Metadata_MetaDataStorageHandlerPdo extends SimpleSAML_Metadata_ ...@@ -20,7 +20,7 @@ class SimpleSAML_Metadata_MetaDataStorageHandlerPdo extends SimpleSAML_Metadata_
/** /**
* The PDO object * The PDO object
*/ */
private $pdo; private $db;
/** /**
* Prefix to apply to the metadata table * Prefix to apply to the metadata table
...@@ -69,20 +69,9 @@ class SimpleSAML_Metadata_MetaDataStorageHandlerPdo extends SimpleSAML_Metadata_ ...@@ -69,20 +69,9 @@ class SimpleSAML_Metadata_MetaDataStorageHandlerPdo extends SimpleSAML_Metadata_
assert('is_array($config)'); assert('is_array($config)');
$globalConfig = SimpleSAML_Configuration::getInstance(); $globalConfig = SimpleSAML_Configuration::getInstance();
$this->db = SimpleSAML_Database::getInstance();
$cfgHelp = SimpleSAML_Configuration::loadFromArray($config, 'pdo metadata source'); $cfgHelp = SimpleSAML_Configuration::loadFromArray($config, 'pdo metadata source');
// determine the table prefix if one was set
$this->tablePrefix = $cfgHelp->getString('tablePrefix', '');
$this->dsn = $cfgHelp->getString('dsn');
$driverOptions = array();
if ($cfgHelp->getBoolean('usePersistentConnection', TRUE)) {
$driverOptions = array(PDO::ATTR_PERSISTENT => TRUE);
}
$this->pdo = new PDO($this->dsn, $cfgHelp->getValue('username', NULL), $cfgHelp->getValue('password', NULL), $driverOptions);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} }
...@@ -102,7 +91,7 @@ class SimpleSAML_Metadata_MetaDataStorageHandlerPdo extends SimpleSAML_Metadata_ ...@@ -102,7 +91,7 @@ class SimpleSAML_Metadata_MetaDataStorageHandlerPdo extends SimpleSAML_Metadata_
return NULL; return NULL;
} }
$stmt = $this->pdo->prepare("SELECT entity_id, entity_data FROM $tableName"); $stmt = $this->db->read("SELECT entity_id, entity_data FROM $tableName");
if($stmt->execute()) { if($stmt->execute()) {
$metadata = array(); $metadata = array();
...@@ -189,24 +178,24 @@ class SimpleSAML_Metadata_MetaDataStorageHandlerPdo extends SimpleSAML_Metadata_ ...@@ -189,24 +178,24 @@ class SimpleSAML_Metadata_MetaDataStorageHandlerPdo extends SimpleSAML_Metadata_
$tableName = $this->getTableName($set); $tableName = $this->getTableName($set);
$metadata = $this->pdo->prepare("SELECT entity_id, entity_data FROM $tableName WHERE entity_id = :entity_id"); $metadata = $this->db->read("SELECT entity_id, entity_data FROM $tableName WHERE entity_id = :entity_id", array(
$metadata->bindValue(":entity_id", $index, PDO::PARAM_STR); 'entity_id' => $index,
$metadata->execute(); ));
$retrivedEntityIDs = $metadata->fetch(); $retrivedEntityIDs = $metadata->fetch();
$params = array(
'entity_id' => $index,
'entity_data' => json_encode($entityData),
);
if($retrivedEntityIDs !== FALSE && count($retrivedEntityIDs) > 0){ if($retrivedEntityIDs !== FALSE && count($retrivedEntityIDs) > 0){
$stmt = $this->pdo->prepare("UPDATE $tableName SET entity_data = :entity_data WHERE entity_id = :entity_id"); $stmt = $this->db->write("UPDATE $tableName SET entity_data = :entity_data WHERE entity_id = :entity_id", $params);
} }
else{ else{
$stmt = $this->pdo->prepare("INSERT INTO $tableName (entity_id, entity_data) VALUES (:entity_id, :entity_data)"); $stmt = $this->db->write("INSERT INTO $tableName (entity_id, entity_data) VALUES (:entity_id, :entity_data)", $params);
} }
$stmt->bindValue(":entity_id", $index, PDO::PARAM_STR);
$stmt->bindValue(":entity_data", json_encode($entityData), PDO::PARAM_STR);
if ($stmt->execute() === FALSE) {
throw new Exception("PDO metadata handler: Database error: " . var_export($this->pdo->errorInfo(), TRUE));
}
return 1 === $stmt->rowCount(); return 1 === $stmt->rowCount();
} }
...@@ -220,7 +209,7 @@ class SimpleSAML_Metadata_MetaDataStorageHandlerPdo extends SimpleSAML_Metadata_ ...@@ -220,7 +209,7 @@ class SimpleSAML_Metadata_MetaDataStorageHandlerPdo extends SimpleSAML_Metadata_
private function getTableName($table) { private function getTableName($table) {
assert('is_string($table)'); assert('is_string($table)');
return str_replace("-", "_", $this->tablePrefix . $table); return $this->db->applyPrefix(str_replace("-", "_", $this->tablePrefix . $table));
} }
/** /**
...@@ -229,11 +218,8 @@ class SimpleSAML_Metadata_MetaDataStorageHandlerPdo extends SimpleSAML_Metadata_ ...@@ -229,11 +218,8 @@ class SimpleSAML_Metadata_MetaDataStorageHandlerPdo extends SimpleSAML_Metadata_
public function initDatabase() { public function initDatabase() {
foreach ($this->supportedSets as $set) { foreach ($this->supportedSets as $set) {
$tableName = $this->getTableName($set); $tableName = $this->getTableName($set);
$result = $this->pdo->exec("CREATE TABLE IF NOT EXISTS $tableName (entity_id VARCHAR(255) PRIMARY KEY NOT NULL, entity_data TEXT NOT NULL)"); $this->db->write("CREATE TABLE IF NOT EXISTS $tableName (entity_id VARCHAR(255) PRIMARY KEY NOT NULL, entity_data TEXT NOT NULL)");
if ($result === FALSE) {
throw new Exception("PDO metadata handler: Database error: " . var_export($this->pdo->errorInfo(), TRUE));
}
} }
} }
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment