Joomla 3.3 - How to store user password? - php

i'm trying to store user password in a plugin using joomla 3.3.6.
According to Joomla Documentation : https://docs.joomla.org/Inserting,_Updating_and_Removing_data_using_JDatabase
I created the following function :
/**
*
* Update Password
*
* #param unknown $idUser
* #param unknown $password
*/
public function updateUserPassword($idUser, $password) {
// Create a new query object.
$query = $this->db->getQuery ( true );
$value = JUserHelper::hashPassword($password);
// Prepare the insert query.
$query->update('#__users')
->set('password = ' . $this->db->quote($value))
->where('id = ' . $idUser);
// Set the query using our newly populated query object and execute it.
$this->db->setQuery ($query);
$updateResult = $this->db->execute ();
if ($updateResult == false) {
$errorMsg = $this->db->getErrorMsg ();
var_dump($errorMsg);
} else {
echo "Update Done";
}
}
This code is executed without any error or warning but the user record in table users remains unchanged.
$query value is :
UPDATE #__users
SET password = '$2y$10$hO2MfDLfG5ICy2yhZWXZG.GCQ89vYw26KHVisXuuD8baRU9WtuDR.'
WHERE id = 192
$query looks fine. Executing the query in mysqlworkbench by replacing #__ with my custom db prefix returns ok and i can see changes in db.
However the php code doesn't work.
Anyone have a clue about this ?
Dev.
EDIT
Code Change : Adding error handling in execute statement.
The message "Update Done" is printed.

From your code snippet, I don't see how you've determined that the code is executing without any error.
From the Joomla documentation
https://api.joomla.org/cms-3/classes/JDatabaseDriver.html#method_execute
your execute statement should have a return value of either a cursor or false.
$updateResult = $this->db->execute();
if($updateResult == false) {
$errorMsg = $this->db->getErrorMsg();
//display this in your method of choice
}
Depending on your server, there may also be an web server error log entry. On my LAMP development machine, it's in /var/log/apache2/error_log
Alternate method to modify a Joomla table record
$user_record = new stdClass();
$user_record->id = $idUser;
$user_record->password = $password;
$result = JFactory::getDbo()->insertObject('#__users', $user_record, $idUser);

Related

PHPUnit Test (Lagacy Route, Legacy Container) - test whether user is already created

I am using PHP, PHP Legacy Router and PHP Legacy Container.
I am using also PHPUnit test
I am trying to make a correct PHPUnit test, however, I am a begginer and I don`t know whether my code is ok or it is wrong.
In my NewUserService class I write 2 functions to get all emails and if the email is already existed in the db to return an error that user is created already.
My problem is how to test this functionality trough PHPUnit tests in my NewUserServiceTest
This is my functionality to test whether the user is already created
public function getAllUsersEmails()
{
$sql ="SELECT `email` FROM users";
$stmt = $this->container->get('db')->prepare($sql);
$stmt->execute();
if ($stmt->errorCode() != '00000') throw new Exception(sprintf(("Database error (%s): %s"), $stmt->errorCode(), $stmt->errorInfo()[2]));
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
/**
* #throws Exception
*/
private function repeatingEmailAddress($requestObj){
$allUsersEmails = NewUserService::getAllUsersEmails();
$allUsersEmailsValues = [];
foreach ($allUsersEmails as $value){
$allUsersEmailsValues[]=$value['email'];
}
if(in_array($requestObj['email'], $allUsersEmailsValues)){
throw new Exception("A user with that email is already created.", 400);
}
This is the unit test:
private function repeatingUserEmail(): array
{
$request = $this->createStub(ServerRequestInterface::class);
$requestJsonPayload = '{"email": "mj#hph.io", "role": 2, "first": "Griffin", "last": "Mitchell"}';
$requestStream = fopen('php://memory', 'r+');
fwrite($requestStream, $requestJsonPayload);
rewind($requestStream);
$request->method('getBody')->willReturn(new Stream($requestStream));
$routeArgs = ['id' => 4];
/* <container with user> */
$container = $this->getStandardContainer();
$user = $this->createMock(User::class);
$user->id = '1';
$user->role = '1';
$user->parent_entity = '11';
$user->email='mj#hph.io';
$container->add('current_user', $user);
$response = ['error' => 'A user with that email is already created.'];
$responseJsonPayload = json_encode($response);
$responseStream = fopen('php://memory', 'r+');
fwrite($responseStream, $responseJsonPayload);
rewind($responseStream);
$expectedResponse = $this->createMock(ResponseInterface::class);
$expectedResponse->method('getStatusCode')->willReturn(400);
$expectedResponse->method('getBody')->willReturn(new Stream($responseStream));
return [$request, $routeArgs, $container, $expectedResponse];
}
Is it correct? How should be done in a correct way?
First of all i suggest to make a isEmailExists($email) method that will search this specific email in the database and return bollean response (true/false). So you don't have to pull millions of emails from database and then loop through millions of rows and in the end you just throw an error.
Back to the test. I suggest to use the expectException assertion that you can find in the documentation
You can 1)add one row in you database and then try to pass the same email that will throw this error or 2)partial mock the
isEmailExists($email) to return true and throw your exception (without hit the database at all)

php7 - Custom SessionHandler raises session_write_close() warning

I upgraded my project from php5.6 to php7.0 and got from time to time a php warning about session_write_close(), showing me the correct path to my temp folder.
My project uses a custom database session handler which worked perfectly with the older php version.
The error is as follows:
Warning: Unknown: Failed to write session data (user). Please verify
that the current setting of session.save_path is correct (C:\my\path)
in Unknown on line 0
Here is my write() fucntion:
/**
* #param string $id
* #param string $data
* #return bool
* #throws Zend_Db_Adapter_Exception
*/
public function write($id, $data)
{
$dateTime = date('Y-m-d H:i:s');
$newDateTime = date('Y-m-d H:i:s', strtotime($dateTime . sprintf(' + %s seconds', $this->getMaxLifetime())));
$sessionValues = array("id" => $id, "expires_at" => $newDateTime, "session_data" => $data);
$sel = new Zend_Db_Select($this->_zdb);
$sel->from(self::TABLE_NAME, array('id'))
->where('id = ?', $id);
$sessionExists = (bool)$this->_zdb->fetchOne($sel);
if($sessionExists) {
$result = $this->_zdb->update(self::TABLE_NAME, $sessionValues, array('id = ?' => $id));
} else {
$result = $this->_zdb->insert(self::TABLE_NAME, $sessionValues);
}
if($result) {
return true;
} else {
return false;
}
}
Any ideas what I can do about it?
Ok, finally I found the solution:
My database adapter inside my custom session handler returns 0 on an update on the session table which doesn't update any values.
I returned the result of my query in the write()-function.
This guy here explained the problem.
The SessionHandlerInterface::write() function raises this warning in case it returns false.
Maybe this helps somebody else as well.

Openfire: Add user with subscription status as "both"

I am facing issue when i add user using RestApi
include "vendor/autoload.php";
$api = new Gidkom\OpenFireRestApi\OpenFireRestApi;
$api->secret = "mySecretKey";
$api->host = "HostName";
$api->port = "9090";
$api->useSSL = false;
$api->plugin = "/plugins/restapi/v1"; // plugin
For adding user to Roster i am using following code
$jid="xyz#domainname";
//Add to roster
$data=$api->addToRoster("abc", $jid);
Which points to OpenFireRestApi.php which do have function named addToRoster
/**
* Adds to this OpenFire user's roster
*
* #param string $username Username
* #param string $jid JID
* #param string|false $name Name (Optional)
* #param int|false $subscription Subscription (Optional)
* #return json|false Json with data or error, or False when something went fully wrong
*/
public function addToRoster($username, $jid, $name=false, $subscription=false)
{
$endpoint = '/users/'.$username.'/roster';
return $this->doRequest('post', $endpoint, compact('jid','name','subscription'));
}
So I've used
$data=$api->addToRoster("abc", $jid,"DummyName",3);
Where 3 is subscription type as both = 3 which is mentioned.
But when i add user shows subscription type as none only.
UPDATE
I came to know about subscription plugin
So I've installed plugin configure it
Plugin itself says it will automatically subscribe both way.
Afterwards i've again tried with
$data=$api->addToRoster("abc", $jid);
Which aspects to be working but again subscriptions is none only.
Any Help would be appreciated.
There is problem with php-openfire-restapi classes
Need to change name of parameters
So do following changes :
//Add to roster
$username = "username in which you want to add roster";
$jid = "another users JID";
$nickname= "nick name of another user";
$subscription ="3";
$result = $api->addToRoster($username, $jid,$nickname,$subscription);
and change following line in /src/Gidkom/OpenFireRestApi/OpenFireRestApi.php file
public function addToRoster($username, $jid, $name=false, $subscription=false)
{
$nickname=$name;
$subscriptionType=$subscription;
$endpoint = '/users/'.$username.'/roster';
return $this->doRequest('post', $endpoint, compact('jid','nickname','subscriptionType'));
}
Here I have changed parameter names.
Good Luck.

Codeigniter multiple database, conn_id returns object even if connection fails

I have been reading several posts plus the official guides about how to connect more than one database in CI. I currently connect to the default application database using the standard database.php configuration and load the other database on the fly when needed. The main purpose of this part of the app is to have an "import" feature where the users user inputs the foreign database connection data on the fly when requested.
As long as the second database connection data is correctly set, the app works like a breeze. When there's an error in the connection config I didn't find a working method to evaluate that a connection could not be estabilished to the other database.
I found out that I could check if $db->conn_id is false to eventually return an error to the user but for some reasons it returns an object no matter what.
This is a brief example of what I'm doing inside the model:
function plugin_subscribers_import_sfguard($channel_id)
{
// Get the channel object by its ID
$channel = $this->get_channel_by('id',$channel_id);
// Set the preferences for the second database
// from the channel informations we retrieved
$db['hostname'] = $channel->host;
$db['username'] = $channel->user;
$db['password'] = $channel->password;
$db['database'] = $channel->db;
$db['dbdriver'] = "mysql";
$db['pconnect'] = FALSE;
$db['db_debug'] = TRUE;
// Open the connection to the 2nd database
$other_db = $this->load->database($db,TRUE);
if ( ! $other_db->conn_id )
{
// This never gets executed as $other_db->conn_id always
// returns: "resource(34) of type (mysql link)"
return false;
}
else
{
// Execute the rest of the import script
$other_db->select('*');
$other_db->from('sf_guard_user');
$other_db->join('sf_guard_user_profile',
'sf_guard_user_profile.id=sf_guard_user.id',
'inner');
$query = $other_db->get();
}
}
I wonder if there's something I didn't get out of the whole thing or if I'm using the wrong logic to evaluate if the secondary database has a proper connection open.
I also tried to try/catch the connection issue with no success.
Thanks in advance for all the support you can offer.
Federico
It's because by setting the second parameter to TRUE (boolean) the function will return the database object and in the DB.php there is a function DB and the last code block is
function &DB($params = '', $active_record_override = NULL)
{
// ...
$driver = 'CI_DB_'.$params['dbdriver'].'_driver';
$DB = new $driver($params);
if ($DB->autoinit == TRUE)
{
$DB->initialize();
}
if (isset($params['stricton']) && $params['stricton'] == TRUE)
{
$DB->query('SET SESSION sql_mode="STRICT_ALL_TABLES"');
}
return $DB;
}
So, I think, if you call this
$other_db = $this->load->database($db,TRUE);
wiuthout the TRUE
$other_db = $this->load->database($db);
Then it could give you a different result.
Update : if i you want to use
$other_db = $this->load->database($db,TRUE);
then you can also check for a method availability using method_exists function, like
$other_db = $this->load->database($db,TRUE);
if( method_exists( $other_db, 'method_name' ) ) {
// ...
}

Using config variables inside functions

In the code given below, I am trying to modify it in such a way that the db connection variables are used from a config file. This should make the password more secure as I can restrict the config file's permissions.
Kindly let me know if there is a way by which I can modify the code to get the db variables from another file/config file?
class ActivitycodesCollection {
var $list, $err, $sql;
// --- Private variables for database access
var $_db_host = "######";
var $_db_username = "######";
var $_db_passwd = "######";
var $_db_name = "######";
function query ($where="") {
mysql_pconnect ($this->_db_host, $this->_db_username, $this->_db_passwd);
mysql_select_db ($this->_db_name);
$where = "WHERE " . $where;
$sql = "SELECT * FROM activitycodes $where";
$result = mysql_query ($sql);
$this->err = mysql_error();
$this->sql = $sql;
if (mysql_num_rows($result) > 0) {
while (list($id) = mysql_fetch_array ($result)) {
$this->list[$id] = new activitycodes($id);
}
}
}
}
I tried including the config.ini file in this class/function but it threw an error like
unexpected T_VARIABLE, expecting T_FUNCTION
Your code is hopelessly outdated.
1) Don't use var for properties, use private or protected.
2) Don't use mysql_* functions, use PDO.
3) Don't keep connection details inside the class. Just require PDO connection in constructor.
4) Don't trust any data outside your scope - don't allow just write some untrusted text into your SQL query (you do it by $where variable).
5) Read books. "PHP Objects, Patterns, and Practice" will help you now, and "Clean code" - little bit later.
Example:
class ActivitycodesCollection
{
private $list;
private $PDO;
private $table_name;
public function __construct(\PDO $PDO, $table_name)
{
$this->PDO = $PDO;
$this->table_name = $table_name;
}
public function fetchByParameter($parameter)
{
$query = $this->PDO->prepare("SELECT `id` FROM `{$this->table_name}` WHERE "
." some_field = :parameter");
if (!$query)
{
return false;
}
if (!($query->execute(array(':parameter'=> $parameter))))
{
return false;
}
$results = $query->fetchAll(\PDO::FETCH_ASSOC);
if (!empty($result))
{
foreach ($results as $result)
{
$id = $result['id'];
$this->list[$id] = new ActivityCodes($id);
}
}
}
}
Without seeing the "config" file it's not possible to say how to write a parser for it. A simple solution would be to write some php code which sets the variables - but if you include / require it, the variables will be set in global scope - not within the method. But you could eval(file_get_contents($config_file_path)) - which would set the variables in local scope at the risk of providing a method for code injection.
BTW there are a large number of issues with the code you have provided. Leaving aside the potential risk of SQL injection, if the method parameter is null / blank, then the query will be malformed (consider function query ($where="1"). Relying on specific column ordering is bad practice.
It's also hard to imagine how yo restrict access to this config file when the only practical means would be via suphp or base opendir.
Putting the SQL connection data in a separate files does not increase security at all. Actually, storing them in a file that does not have a .php extension makes it less secure since it might be accessible by a user while the code of a PHP file is not visible to any users. You also cannot use more restrictive permissions on the config file than on your PHP files since whatever user PHP is running as (usually the webserver user) needs to access them.
Simply store the connection data in a PHP file:
<?php
define('DB_HOST', '...');
define('DB_NAME', '...');
define('DB_USER', '...');
define('DB_PASS', '...');
Then include this file (outside your class definition) and use the constants when making the connection.
You can use parse_ini_file in you constructor.
class ActivitycodesCollection {
var $list, $err, $sql;
const CONFIG_FILE = 'config.ini';
// --- Private variables for database access
var $_db_host = ''
var $_db_username = '';
var $_db_passwd = '';
var $_db_name = '';
public function ActivitycodesCollection() {
$config = parse_ini_file(self::CONFIG_FILE);
$this->_db_host = $config['db']['host'];
//etc
}
public function query ($where="") {
mysql_pconnect ($this->_db_host, $this->_db_username, $this->_db_passwd);
mysql_select_db ($this->_db_name);
$where = "WHERE " . $where;
$sql = "SELECT * FROM activitycodes $where";
$result = mysql_query ($sql);
$this->err = mysql_error();
$this->sql = $sql;
if (mysql_num_rows($result) > 0) {
while (list($id) = mysql_fetch_array ($result)) {
$this->list[$id] = new activitycodes($id);
}
}
}
And the ini file should be something like that :
[db]
host = localhost
name = foo
user = bar
pass = baz

Categories