How to stop updating password in codeigniter in edit method? - php

When i edit a user and save it , it saves blank filed in database. It Save all other fields as it is, but for password i have to manually add password every time i edit a user.
This is my edit method::
if ($id)
{
$this->data['user'] = $this->user_m->get_emp($id);
count($this->data['user']) || $this->data['errors'][] = 'User could not be found';
$rules = $this->user_m->rules_admin;
$id || $rules['password']['rules'] .= '|required';
$this->form_validation->set_rules($rules);
// Process the form
if ($this->form_validation->run() == TRUE)
{
$data = $this->user_m->array_from_post(array('emp_id','name','last_name','email','password','phone','gender','designation','user_type','blood_group','date_birth','status','address'));
$data['password'] = $this->user_m->hash($data['password']);
$id = $this->session->userdata('id');
$this->user_m->save($data, $id);
redirect('admin/user/index');
}
}
// Load the view
$this->data['subview'] = 'employee/profile/edit';
$this->load->view('employee/_layout_main', $this->data);
This is my HASH METHOD:
public function hash ($string)
{
return hash('sha512', $string . config_item('encryption_key'));
}
Now i want that when i edit a user and i dont change his password i dont want the password updated to be blank instead keep the last inserted passoword.
But My Code generates this query:
UPDATE `users` SET `emp_id` = '21', `name` = 'Rajan', `last_name` = 'Jadav', `email` = 'rajan#bizrtc.com', `password` = '3eee66dbace42d2e671c52013e41de441b176dbaa0f7df33a5811b86c78b60ecb5328184bf1f5057f94817801140d7287f31c1fb06fa65550c356a33a8eec0db', `phone` = '999999999988', `gender` = 'Male', `designation` = 'Web', `user_type` = 'employee', `blood_group` = '+ve', `date_birth` = 'DD-MM-YYYY', `status` = 'Active', `address` = 'DD-MM-YYYY' WHERE `id` = 18
THe Model Code:
public function save($data, $id = NULL){
// Set timestamps
if ($this->_timestamps == TRUE) {
$now = date('Y-m-d H:i:s');
$id || $data['created'] = $now;
$data['modified'] = $now;
}
// Insert
if ($id === NULL) {
!isset($data[$this->_primary_key]) || $data[$this->_primary_key] = NULL;
$this->db->set($data);
$this->db->insert($this->_table_name);
$id = $this->db->insert_id();
}
// Update
else {
$filter = $this->_primary_filter;
$id = $filter($id);
$this->db->set($data);
$this->db->where($this->_primary_key, $id);
$this->db->update($this->_table_name);
}
return $id;
}
If I remove the hash method from controller then it inserts blank field and if i keep it it inserts false values

I just found a solution.
I will check if i have blank password if so then will unset it and if not then insert the new password using this:
if(!empty($data['password']))
{
$data['password'] = $this->user_m->hash($data['password']);
} else {
// We don't save an empty password
unset($data['password']);
}

1.) Add $this->output->enable_profiler(TRUE); to your code to enable Debug Profiling as described here
2.) In your controller add some var_dumps to check for the values of your vars:
$data = $this->user_m->array_from_post(array('emp_id','name','last_name','email','password','phone','gender','designation','user_type','blood_group','date_birth','status','address'));
// Let's dump the $data array and kill the app:
var_dump($data);die;
You can move the var_dump successively down step after step to see exactly what the value of your vars is.
Tip: I am guessing the problem is in the View (HTML Form) - But with Profiler and var_dump you should see that very easily.
Hope this helps - Good Luck!

A bad approach is to use unset password from your data before updating. In your code it would be like:
unset($data['password']);
Also if you don't want to update password on user edit just don't show the field.

Related

Multiple Database requests for login

I have three files that are relevant for this part of my login scenario:
/project/index.html
/project/api/user/login.php
/project/api/objects/user.php
The index.html has a simple login form in it, calling the ./api/user/login.php.
In this form I have a checkbox that is an option for the user in order to stay logged in or not.
If the user has selected this option, with every login, I would like to check if the credentials are correct (login function -> stmt1 in user.php) as well as to update the lastlogin (datetime), the identifier and securitytoken if the checkbox was set (login function -> stmt2 in user.php).
The user.php is included_once in the login.php that gets the values out of the index.html form and sends them to the login() function in the user.php.
Depending on the functions return value, the login.php decides if the login was successful or not.
The login itself (stmt1) works, but the update of lastlogin, identifier and securitytoken (stmt2) doesn't.
login.php
session_start();
// include database and object files
include_once '../config/database.php';
include_once '../objects/user.php';
// get database connection
$database = new Database();
$db = $database->getConnection();
// prepare user object
$user = new User($db);
// set ID property of user to be edited
$user->username = isset($_GET['username']) ? $_GET['username'] : die();
$user->password = base64_encode(isset($_GET['password']) ? $_GET['password'] : die());
$user->remember = isset($_GET['remember']) ? $_GET['remember'] : die();
$stmt1 = $user->login();
if($stmt1->rowCount() > 0){
// get retrieved row
$row1 = $stmt1->fetch(PDO::FETCH_ASSOC);
$_SESSION['userid'] = $row1['uid'];
// create array
$user_arr=array(
"status" => true,
"message" => "Login erfolgreich!",
"uid" => $row1['uid'],
"username" => $row1['username']
);
$stmt2 = $user->login();
$row2 = $stmt2->fetch(PDO::FETCH_ASSOC);
print_r($row2);
// create array
$user_arr=array(
"lastlogin" => $row2['lastlogin']
);
}
else{
$user_arr=array(
"status" => false,
"message" => "Benutzername und/oder Passwort nicht korrekt!",
);
}
// make it json format
print_r(json_encode($user_arr));
?>
user.php
function login(){
// select all query
$query1 = "SELECT
`uid`, `username`, `email`, `password`, `created`, `lastlogin`
FROM
" . $this->table_name . "
WHERE
username='".$this->username."' AND password='".$this->password."'";
// prepare query statement
$stmt1 = $this->conn->prepare($query1);
// execute query
$stmt1->execute();
return $stmt1;
// set up the remain logged in function
if(isset($this->remember)) {
$identifier = random_string();
$securitytoken = random_string();
$remember = ",identifier='".$identifier."',securitytoken='".$securitytoken."'";
setcookie("identifier",$identifier,time()+(3600*24*365)); //1 year valid
setcookie("securitytoken",$securitytoken,time()+(3600*24*365)); //1 year valid
} else {
$remember = "";
}
// update last login
$query2 = "UPDATE
" . $this->table_name . "
SET
`lastlogin` = '".date("Y-m-d H:i:s")."'
".$remember."
WHERE
username='".$this->username."' AND password='".$this->password."'";
// prepare query statement
$stmt2 = $this->conn->prepare($query2);
// execute query
$stmt2->execute();
return $stmt2;
}
function random_string(){
if(function_exists('random_bytes')) {
$bytes = random_bytes(16);
$str = bin2hex($bytes);
} else if(function_exists('openssl_random_pseudo_bytes')) {
$bytes = openssl_random_pseudo_bytes(16);
$str = bin2hex($bytes);
} else if(function_exists('mcrypt_create_iv')) {
$bytes = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);
$str = bin2hex($bytes);
} else {
//secret key should have >12 random chars
$str = md5(uniqid('SECRET KEY', true));
}
return $str;
}
In the user.php after return $stmt1;
The code is returned and the cookies are not set
I would do this... Check login... If true, save cookies with id and token
And then periodically check if token and id correspond... If so... Just UPDATE the last login time.
Note: your prepared statement is vulnerable!! Dont append the parameters with '.' use placeholders instead, and dont encode the password, is better to hash it... Then compare hashes

Fetching (not decrypt) md5 password from database

I've been working on a password setting where whenever user want to update their password, they cannot update the new password to be the same as the previous/current password. The password store in database is in md5 format.
So what I'm trying to do is converting first the new input password to md5 and compare it to one in the database. This might be a minor error, but after hours of trying and googling, I still cannot fetch the password in the database to do comparison.
I was thinking it might be the parameter. I'm a newbie and still learning, sorry if this was too simple for experts like guys. Thank you in advance for you time.
This is my model
public function getUserPassword($uid) {
$conditions = array('users.uid="'.$uid.'"');
$result = $this->find('all', array('conditions' => $conditions,'fields' => array('users.upwd')));
return $result;
}
Controller
$data = $this->request->data;
$uid = $data['uid'];
$new_pwd ='';
if($continue == true) {
if(md5($new_pwd) == $this->users->getUserPassword($uid)) {
$continue = false;
$return_msg = "New password cannot be the same as the old password";
}
}
View
<tr>
<td><input id="new_pwd" type="password" name="new_password"></input></td>
</tr>
The problem was the way you are fetching the data.It will return as $result['Model']['fieldsname']. So at the time of comparison you have to take care of that.Change the function getUserPassword() -
public function getUserPassword($uid) {
$result = $this->field('users.upwd', array('users.uid' => $uid)); //will return the value in db field
return $result;
}
And in controller -
$data = $this->request->data;
$uid = $data['uid'];
$new_pwd ='';
if($continue == true) {
if(md5($new_pwd) == $this->users->getUserPassword($uid)) {
$continue = false;
$return_msg = "New password cannot be the same as the old password";
}
}
the $new_pwd should be the new_password field in the request data.

need help inserting a default text value into mysql

end web developer, i was given a CMS done from another team and i have to link with my front-end. I have made some modifications, but due to my lack of php knowledge i have some issue here.
My users are able to fill up a form, where 1 text field is asking for their photo link. I want to check for if the value entered is not equal to what i want, then i will query insert a default avatar photo link to mysql to process.
code that i tried on php
// check if the variable $photo is empty, if it is, insert the default image link
if($photo = ""){
$photo="images/avatarDefault.png";
}
doesn't seem to work
<?php
if($_SERVER["REQUEST_METHOD"] === "POST")
{
//Used to establish connection with the database
include 'dbAuthen.php';
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
else
{
//Used to Validate User input
$valid = true;
//Getting Data from the POST
$username = sanitizeInput($_POST['username']);
$displayname = sanitizeInput($_POST['displayname']);
$password = sanitizeInput($_POST['password']);
//hash the password using Bcrypt - this is to prevent
//incompatibility from using PASSWORD_DEFAULT when the default PHP hashing algorithm is changed from bcrypt
$hashed_password = password_hash($password, PASSWORD_BCRYPT);
//Determining Type of the User
//if B - User is student
//if A - User is adin
if($_POST['type'] == 'true')
$type = 'B';
else
$type = 'A';
$email = sanitizeInput($_POST['email']);
$tutorGroup = sanitizeInput($_POST['tutorGroup']);
$courseID = sanitizeInput($_POST['courseID']);
$description = sanitizeInput($_POST['desc']);
$courseYear = date("Y");
$website = sanitizeInput($_POST['website']);
$skillSets = sanitizeInput($_POST['skillSets']);
$specialisation = sanitizeInput($_POST['specialisation']);
$photo = sanitizeInput($_POST['photo']);
// this is what i tried, checking if the value entered is empty, but doesn't work
if($photo = ""){
$photo="images/avatarDefault.png";
}
$resume = sanitizeInput($_POST['resume']);
//Validation for Username
$sql = "SELECT * FROM Users WHERE UserID= '$username'";
if (mysqli_num_rows(mysqli_query($con,$sql)) > 0){
echo 'User already exists! Please Change the Username!<br>';
$valid = false;
}
if($valid){
//Incomplete SQL Query
$sql = "INSERT INTO Users
VALUES ('$username','$displayname','$hashed_password','$type','$email', '$tutorGroup', ";
//Conditionally Concatenate Values
if(empty($courseID))
{
$sql = $sql . "NULL";
}
else
{
$sql = $sql . " '$courseID' ";
}
//Completed SQL Query
$sql = $sql . ", '$description', '$skillSets', '$specialisation', '$website', '$courseYear', '$photo', '$resume', DEFAULT)";
//retval from the SQL Query
if (!mysqli_query($con,$sql))
{
echo '*Error*: '. mysqli_error($con);
}
else
{
echo "*Success*: User Added!";
}
}
//if student create folder for them
if ($type == 'B')
{
//Store current reporting error
$oldErrorReporting = error_reporting();
//Remove E_WARNING from current error reporting level to prevent users from seeing code
error_reporting($oldErrorReporting ^ E_WARNING);
//Set current reporting error();
error_reporting($oldErrorReporting);
}
mysqli_close($con);
}
}
function sanitizeInput($data)
{
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
i've tried finding a way on mysql to insert default values but it seem impossible, so i have no choice but to query insert through php.
I have the logic but i'm not sure how to implement on the php with my lack of knowledge, i was thinking of checking either
1) if the photo link does not have the word .png/.jpg, $photo != ".png"
2) if the photo link length is too low $.photo.length < 10
can someone help me look into the code and tell me what i'm doing wrong? Thanks!
A very simple way with default values could be:
$photo = isset($photo) ? $photo : 'images/avatarDefault.png' ;
How it works is that it first it asks if the photo is set, if it is, use all ready inserted value, otherwise insert your default value,
Another (very alike) method to use:
$photo = !empty($photo) ? $photo : 'images/avatarDefault.png' ;
UPDATE
To check if it contains a certain "extension" would be a simple rewrite
$photo = preg_match('#\b(.jpg|.png)\b#', $photo ) ? $photo : "images/avatarDefault.png" ;
This way it checks wether the text / image link in $photo contains the .png file type, if it doesn't it inserts your default image
First thing that I notice is to use double =
if($photo == ""){
//...
}

Codeigniter session different site

Hi all I have two sites developed in codeigniter. These sites are completely different but the mdoel of user is similar like the login method because I thinked to recycle that code.
The problem is: If I log in into a site and open the other I am logged in inside it with the user of the other site that doesn't exist into my database.
Database are different, I don't know what is the problem or if I have to change my login method into my model or some configuration.
This is my method in the model:
function login($username = '', $password = '') {
$user_name = base64_decode($username);
$password = base64_decode($password);
//Make sure login info was sent
if($username == '' || $password == '') {
return FALSE;
}
//Check if already logged in
if( $this->session->userdata('username') == $username && $this->session->userdata('logged_in') ) {
//User is already logged in.
return TRUE;
}
//Check against user table
$this->db->where('username', $user_name);
$this->db->where('password', $this->encrypt->sha1($password) );
$this->db->where('active', 1);
$query = $this->db->get_where($this->user_table);
if ($query->num_rows() > 0) {
$row = $query->row_array();
//Destroy old session
$this->session->sess_destroy();
//Create a fresh, brand new session
$this->session->sess_create();
//Update Last Login
$data = array(
'last_login' => date('Y-m-d H:i:s')
);
$this->db->where('id', $row['id']);
$this->db->update($this->user_table, $data);
//Set session data
$this->session->set_userdata(array('id' => $row['id'], 'username' => $row['username'],'name' => $row['name'], 'surname' => $row['surname'], 'language' => $row['language']));
if ($row['type']==1){
//se è 1 è un administrator
$this->session->set_userdata(array('is_admin' => 1));
}
else{
$this->session->set_userdata(array('is_admin' => 0));
}
//Set logged_in to true
$this->session->set_userdata(array('logged_in' => TRUE));
//image profile
$this->db->where('user_id', $row['id']);
$query2 = $this->db->get_where('user_image_profile');
if ($query2->num_rows() > 0) {
$row_image = $query2->row_array();
$this->session->set_userdata(array('img_profile' => $row_image['filename']));
}
//Login was successful
return TRUE;
} else {
//No database result found
return FALSE;
}
}
I think the problem is in the config file. Here you use the same "encryption_key" for the both site for that reason when you log in one site and open the other one here you also logged. So you have to use different "encryption_key" for the both site.
like that for first web site-
$config['encryption_key'] = 'gHZc2let11sp3YAns00rggHlYNMp7CVX';
and the second one -
$config['encryption_key'] = 'V1M839GlUk65rKzm1GM67H66X1WLD6ay';
for each application you can configure the session to be stored in the database. change config file.
sess_use_database = true;
after that you need to create this table in your database
CREATE TABLE IF NOT EXISTS `ci_sessions` (
session_id VARCHAR(40) DEFAULT '0' NOT NULL,
ip_address VARCHAR(16) DEFAULT '0' NOT NULL,
user_agent VARCHAR(120) NOT NULL,
last_activity INT(10) UNSIGNED DEFAULT 0 NOT NULL,
user_data TEXT NOT NULL,
PRIMARY KEY (session_id),
KEY `last_activity_idx` (`last_activity`)
);

Pulling data off of sql table with php using sessions

I'm trying to pull data off my sql table with php unique to the session's ID, however I only get the position that the user is in when I echo anything out!
<?php
include 'core/init.php';
$user_info = $_SESSION['user_id'];
?>
<html>....
<h1><?php echo $user_info['firstname'];?>&nbsp<?php echo $user_info['firstname'];?> </h1>
displays as:
5 5
if I log in with the fifth position in the database!
The reason why you are getting 5 is for this code:
<?php echo $user_info['firstname'];?>
is that $_SESSION['user_id'] 's value is 5. So after the assignment $user_info's value is 5. Now because the $_SESSION['user_id'] is not set to an array as your intention seems to be. The result is that $user_info is taken as a string and ['firstname'] evaluates to [0]. If you like, you can update the ID 5 to 54, etc. You will always get the first character of your ID.
To correct this, try changing the last 2 lines before the return in your user_data function to:
$data = mysql_fetch_assoc(mysql_query("SELECT $fields FROM `users` WHERE `user_id` = $user_id"));
$data = array_merge(array($user_id), $data);
return $data;
if (logged_in() === true) {
$user_data = user_data($_SESSION['user_id'], 'username', 'first_name', 'last_name', 'email');
$user_data = user_data($session_user_id, 'user_id', 'username', 'first_name', 'last_name', 'email');
}
to:
if (logged_in() === true) {
$user_data = user_data($_SESSION['user_id'], 'username', 'first_name', 'last_name', 'email');
$_SESSION['user_id'] = $user_data;
}
if (logged_in === true) {
should be
if (logged_in()) {
for me it seems like you forgot to update data in session.
lets say here:
if (logged_in() === true) {
$user_data = user_data($_SESSION['user_id'], 'username', 'first_name', 'last_name', 'email');
$user_data = user_data($session_user_id, 'user_id', 'username', 'first_name', 'last_name', 'email');
$_SESSION = array_merge($_SESSION, $user_data);
}
hope it helps you to resolve your problems.
What I see that your in this line
<h1><?php echo $user_info['firstname'];?>&nbsp<?php echo $user_info['firstname'];?> </h1>
you are using "firstname", whereas in database it is named as "first_name", see underscore
<h1><?php echo $user_info['first_name'];?>&nbsp<?php echo $user_info['first_name'];?> </h1>
Let me know if this solves or not as I too want to know its answer
May help you some changes in your code
function user_data($user_id) {
$data = array ();
$user_id = (int)$user_id;
$func_num_args = func_num_args();
$func_get_args = func_get_args();
if ($func_num_args > 1) {
unset($func_get_args[0]);
$fields = '`'. implode('`, `', $func_get_args). '`';
echo '<br>'.
$que = "SELECT $fields FROM `users` WHERE `id` = $user_id";
$data = mysql_fetch_assoc(mysql_query($que));
print_r ($data);
return $data;
}
}
function logged_in() {
return (isset($_SESSION['id'])) ? true : false;
}
if (logged_in() === true) {
$user_data = user_data($_SESSION['user_id'], 'username', 'firstname', 'email');
//$user_data = user_data($session_user_id, 'user_id', 'username', 'firstname', 'email');
print_r($user_data);
}
echo
$user_info = $user_data;//$_SESSION['user_id'];
?>
<h1><?php echo $user_info['firstname'];?>&nbsp<?php echo $user_info['firstname'];?> </h1>
function user_data($data=array(),$whereData=array()) {
$str='';
if(isset($whereData) && is_array($whereData))
{
foreach($whereData as $key=>$val)
{
if($val!='')
if($str=='')
$str = $key." = '".$val."'";
else
$str .= " AND ".$key." = '".$val."'";
}
}
$condition =
$fields = implode(',' , $data);
if($str!=''){
$data = mysql_fetch_assoc(mysql_query("SELECT $fields FROM `users` WHERE $str"));
}
else
{
$data = mysql_fetch_assoc(mysql_query("SELECT $fields FROM `users` ));
}
return $data;
print_r ($data);
}
}
and
if (logged_in() === true) {
$data = array('username', 'first_name', 'last_name', 'email');
$where=array('user_id'=>$_SESSION['user_id'])
$_SESSION['data'] = user_data($data, $where);
}
and
<?php
include 'core/init.php';
$user_info = $_SESSION['data'];
?>
<html>....
<h1><?php echo $user_info['firstname'];?>&nbsp<?php echo $user_info['firstname'];?> </h1>
From experience of creating large code bases in PHP and when you expand the application you will find you are using more and more data all over the place from the users table. Also, the table should only really contain the most vital data that is comonly used and you do NOT want to be sending more than 1 or 2 queries to the users table per page hit as it can soon become a bottle neck. For this reason you are better storing all of the data data (move large fields to another table or fields rarely used). Then store the whole user record in a session which means any function, class etc can use it as it becomes a superglobal and you can trust it enough to use it throughout the entire application without needed to re-query the users table again and again.
I have written a working example (suing your db table structure) and commented it all throughout explaining why i have done it the way i have and some points you might want to consider.
//change from user_data() to get_user_data() so we know we are "getting" it, makes it a little clearer
function get_user_data($user_id) {
//protect agains sql injections
$user_id = mysql_real_escape_string($user_id);
//you should also be using mysqli or PDO, not the outdated mysql library - just check the php documentation if you don't believe me ;)
$result = mysql_query("SELECT * FROM `users` WHERE `id` = '{$user_id}' LIMIT 1");
//only if the previous query returned a result do we want to fetch an array from it
if ($result) {
return mysql_fetch_assoc($result);
}
//query didn't work (syntax error for example) so return blank array
return array();
}
//start and restore the session
session_start();
//if first page hit, set the user details element
if (isset($_SESSION['user_details']) == false) {
$_SESSION['user_details'] = array();
}
//if already logged in, refresh their user details incase there were any changes
if (isset($_SESSION['user_details']->user_id)) {
//refresh the user data
$_SESSION['user_details'] = get_user_data($_SESSION['user_details']->user_id);
}
//login
if (empty($_POST['id']) == false) {
$_POST['id'] = trim($_POST['id']);
if (is_numeric($_POST['id'])) {
$_SESSION['user_details'] = get_user_data($_POST['id']);
}
}
//logout
if (isset($_GET['logout'])) {
if ($_GET['logout'] == session_id()) {
$_SESSION['user_details'] = array();
}
}
//see if logged in so we know what to display
if (empty($_SESSION['user_details'])) {
//not logged in
print "<form method='post' action=''><label>User ID</label><input type='text' name='id' value='5' /><input type='submit' value='Login' /></form>";
} else {
//is logged in
print "<a href='?logout=" . rawurlencode(session_id()) . "'>logout</a>";
}
//proof that it works
print '<pre>';
print_r($_SESSION['user_details']);
print '</pre>';
P.S. Also you may want to start using LIMIT in your SQL queries as LIMIT 1 in the query above tells mysql that it can stop searching after it finds 1 result - and you should have an index on that column (preferably a primary index or unique index) to keep it lightening fast (or at least in the beginning anyway >< ).

Categories