I do some database transaction and the set $new_user = TRUE like this
Model Code:
$data_insert = array
(
'username' => $username_post,
'password'=>$username_post,
);
$this->db->insert('Tenant', $data_insert);
$new_tenant_id = $this->db->insert_id();
//CREATE TABLE FOR THAT DISTRIBUTOR
$this->dbforge->add_field(
array(
'id' => array(
'type' => 'INT',
'constraint' => 10,
'unsigned' => TRUE,
'auto_increment' => TRUE
),
'site_key' => array(
'type' => 'VARCHAR',
'constraint' => '100',
),
'display_name' => array(
'type' => 'VARCHAR',
'constraint' => '100',
'null' => TRUE
),
'ext' => array(
'type' => 'VARCHAR',
'constraint' => '50',
'null' => TRUE
),
'auth_user' => array(
'type' => 'VARCHAR',
'constraint' => '100',
'null' => TRUE
),
'password' => array(
'type' => 'VARCHAR',
'constraint' => '128',
'null' => TRUE,
),
'base_ini_id' => array(
'type' => 'VARCHAR',
'constraint' => '50',
'null' => TRUE
),
'md_user' => array(
'type' => 'VARCHAR',
'constraint' => '128',
'null' => TRUE
),
'uc_user' => array(
'type' => 'VARCHAR',
'constraint' => '50',
'null' => TRUE
),
'uc_password' => array(
'type' => 'VARCHAR',
'constraint' => '100',
'null' => TRUE
),
'comments' => array(
'type' => 'VARCHAR',
'constraint' => '200',
'null' => TRUE
),
'custom_ini_filename' => array(
'type' => 'VARCHAR',
'constraint' => '100',
'null' => TRUE
),
'email' => array(
'type' => 'VARCHAR',
'constraint' => '100',
'null' => TRUE
),
));
$this->dbforge->add_key('id', TRUE);
if (!$this->db->table_exists('table_name'))
{
$this->dbforge->create_table($usertable);
}
//TABLE CREATED NOW ADD SOME DATA
$insert_data = array
(
'site_key' =>$site_post,
'tenant_id'=>$new_tenant_id
);
//TENANT CREATED AND THE SITE BY HIM IS ADDED TO DATABASE
$query = $this->db->insert('MLCSites',$insert_data);
$new_user = TRUE;
Now if i have the user in database then $validate is set to TRUE if not i check if $new_user == TRUE then I set loggedin = TRUE in my session like this:
if(!empty($validate))
{
if ($validate == TRUE)
{
// Log in user
$data = array(
'site' => $site->site_post,
'id' =>$tenant_id,
'username'=>$username_post,
'user_table'=>$usertable,
'nec_distributor'=>TRUE,
'loggedin' => TRUE,
);
$this->session->set_userdata($data);
return TRUE;
}
elseif ($new_user == TRUE)
{
// Log in user
$data = array(
'site' => $site->site_post,
'id' =>$new_tenant_id,
'username'=>$username_post,
'user_table'=>$usertable,
'nec_distributor'=>TRUE,
'loggedin' => TRUE,
);
$this->session->set_userdata($data);
return TRUE;
}
return FALSE;
}
Now in my controller i Check like this:
$dashboard ='customer/dashboard';
$rules = $this->distributor_m->rules;
$this->form_validation->set_rules($rules);
if ($this->distributor_m->login() == TRUE)
{
var_dump($this->session->all_userdata());
$this->distributor_m->loggedin() == FALSE || redirect($dashboard);
redirect($dashboard);
}
else
{
$this->session->set_flashdata('error', 'That email/password combination does not exist');
//redirect('secure/login', 'refresh');
}
But when i submit username and key, all the database transaction are done as per the code successfully. But there is nothing in my session, if I resend the form information then i see the SESSION data. So where I am going wrong?
There is no good and bad you can do anything you want. But Model we used to only interact with Database. So Controller is the one handle all the sites.
So its better if you add the session in controller. Its helpful in some ways too.
Ex: if you set flashdata you have to redirect the page. So in model you can't archive it. But if you do same on controller you are able to redirect where ever you want.
$this->session->set_flashdata('item', 'value');
redirect('controller/name');
1) Do not store all that information in the session. Make a long randomized string to use as a token. Store that token in the sesssion. Use that token to retrieve the user details from a database. Note that I'm not talking about saving the codeigniter session itself to a database. Use session files. Make your own user table to hold the user name, site, etc etc. Of course put in some other details like sign up date, last activity date, etc.
2) Set the session first. Before everything else you are doing. Especially before doing something as major as creating a new database table :-)
3) The session is set. Next page or whatever the user clicks on something that starts the table creation. Before you create the table, validate that the session is valid.
4) Models can be for many things not just interacting with a database. There are two schools of design in terms of controllers - wise people who advocate "thin controllers" that are clean, easy to maintain, and much less prone to errors. And those other people who stuff their controllers full of code and thus have "fat controllers". Not going to say which is better - so I will just imply it :-)
This code works fine .Have a glimpse.
In this case I have two kind of user: admin and customer
public function index()
{
if(($this->session->userdata('logged_in'))){
redirect('/customer/dashboard/', 'refresh');
}
if(isset($_POST['username']) && isset($_POST['password'])){
$this->form_validation->set_rules('username', 'Username', 'required');
$this->form_validation->set_rules('password', 'Password', 'required');
$username = $_POST['username'] ;
$password = md5($_POST['password']);
if ($this->form_validation->run() == FALSE)
{
echo "not success";
}
else
{
$this->load->model('Book_upload');
$user_details = $this->Book_upload->validate_user_login($username,$password);
if(count($user_details)==0){
echo "Invalid Login";
} else {
$newdata = array(
'userid' => $user_details[0]['AdminId'],
'username' => $user_details[0]['UserName'],
'role' => $user_details[0]['Role'],
'fullname' => $user_details[0]['FullName'],
'logged_in' => TRUE
);
$this->session->set_userdata($newdata);
$session_flag = $this->session->all_userdata();
if($session_flag['role'] == 'customer')
redirect('/customer/home/', 'refresh');
if($session_flag['role'] == 'admin')
redirect('/admin/dashboard/', 'refresh');
}
}
}
$this->load->view('customer/login');
}
Related
I'm using codeigniter 3, and I'm trying to use the form_validation library.
Basically, if validation fails, I'm catching the input data and then sending it back to the form.
So I'm sticking all form data in an array, like so:
// add input data to array
$org_data = array(
'org_id' => $this->input->post('org_id'),
'p_org_id' => $this->input->post('p_org_id'),
'account_ref' => $this->input->post('account_ref'),
'org_name' => $this->input->post('org_name'),
'address1' => $this->input->post('address1'),
'address2' => $this->input->post('address2'),
'address3' => $this->input->post('address3'),
'town' => $this->input->post('town'),
'county' => $this->input->post('county'),
'pcode' => $this->input->post('pcode'),
'phone' => $this->input->post('phone'),
'support_email' => $this->input->post('support_email'),
'notify_return' => $this->input->post('notify_return'),
'notify_email' => $this->input->post('notify_email'),
'email_interval' => $this->input->post('email_interval'),
'renewal_date' => $this->input->post('renewal_date'),
'login_reminder' => $this->input->post('login_reminder'),
'default_fireaware' => $this->input->post('default_fireaware'),
'open_training_url' => $this->input->post('open_training_url'),
);
All fine!
Now, to send the data back to the form, I am using the below.
$this->data['org_id'] = array(
'name' => 'org_id',
'id' => 'org_id',
'type' => 'text',
'value' => $this->form_validation->set_value('org_id'),
);
BUT
I don't want to create one of these for every input, so ideally I'd like to use a loop to create these. But I cant get it to work, I am getting undefined variable errors.
This is the loop in progress:
foreach($org_data as $key => $value){
$this->data['$key'] = array(
'name' => '$key',
'id' => '$key',
'type' => 'text',
'value' => $this->form_validation->set_value('$value'),
);
}
Can I use a loop to do this?
What are your thoughts?
use validation like this
$config = array(
array(
'field' => 'username',
'label' => 'Username',
'rules' => 'required'
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'required'
),
array(
'field' => 'passconf',
'label' => 'Password Confirmation',
'rules' => 'required'
),
array(
'field' => 'email',
'label' => 'Email',
'rules' => 'required'
)
);
$this->form_validation->set_rules($config);
if ($this->form_validation->run() == FALSE) {
$data['errors'] = validation_errors();
$this->load->view('yourview', $data);
} else {
$userData = $this->input->post();
$this->load->view('yourview', $data);
}
Basically, if validation fails, I'm catching the input data and then
sending it back to the form.
yeah i think this is the part to clarify - you don't need to do that at all -- thats the advantage of using set_value('fieldName'), it automatically echoes out the value. Same - on the form - with form_error( 'fieldName' ) it will display the field specific error message.
I wonder what is the best and the most secured way of handling user's input in Codeigniter. Basically I have form for user's profile made by form helper like this:
echo form_open();
echo form_label($this->lang->line('user_update_profile_first_name'), 'first_name');
echo form_input(array('type' => 'text', 'name' => 'first_name', 'id' => 'first_name', 'maxlength' => '255', 'required' => 'true', 'value' => set_value('first_name', $user_profile['first_name'], false)));
echo form_label($this->lang->line('user_update_profile_last_name'), 'last_name');
echo form_input(array('type' => 'text', 'name' => 'last_name', 'id' => 'last_name', 'maxlength' => '255', 'required' => 'true', 'value' => set_value('last_name', $user_profile['last_name'], false)));
echo form_label($this->lang->line('user_update_profile_birth_date'), 'birth_date');
echo form_input(array('type' => 'text', 'name' => 'birth_date', 'id' => 'birth_date', 'maxlength' => '255', 'required' => 'true', 'value' => set_value('birth_date', $user_profile['birth_date'],
echo form_submit(array('value' => $this->lang->line('user_update_profile_form_submit'), 'name' => 'submit', 'class' => 'btn btn-primary'));
echo form_close();
As you can see in my code I am skipping xss filtering provided in set_value function due to xss filtering is done in form_input() already.
My Controller function for inserting data in DB looks like this
$validation_rules = array(
array(
'field' => 'first_name',
'label' => $this->lang->line('user_update_profile_validation_error_first_name'),
'rules' => 'required|trim|max_length[255]'
),
array(
'field' => 'last_name',
'label' => $this->lang->line('user_update_profile_validation_error_last_name'),
'rules' => 'required|trim|max_length[255]'
),
array(
'field' => 'birth_date',
'label' => $this->lang->line('user_update_profile_validation_error_birth_date'),
'rules' => 'required|trim|max_length[255]'
)
);
$this->form_validation->set_rules($validation_rules);
if($this->form_validation->run()) {
$user_data = array(
'user_id' => $this->profile_data->user_id,
'first_name' => $this->input->post('first_name', TRUE),
'last_name' => $this->input->post('last_name', TRUE),
'birth_date' => date('Y-m-d',strtotime($this->input->post('birth_date', TRUE)))
);
if($this->user_model->update_user_profile($user_data)) {
$view_data['success'] = TRUE;
$new_site_language = $this->language_model->getLanguageFolderById($user_data['site_language']);
$this->lang->load('application/user_lang', $new_site_language);
} else {
$view_data['server_error'] = TRUE;
}
}
I am filtering here data from user by provided $this->input->post('', true) xss filter. In model I am inserting data to DB by active record class. I am just wondering if this is the right and secure way of handling users input if there is not needed something like htmlspecialchars() . But what happens when someone have some "special" chars in name like for example Someone O'Sombody or some names from foreign countries? I am also showing data in navbar using html_escape($this->profile_data->first_name) to prevent running users potentially dangerous code. Did I get this whole "security thing" in the right way or there should be something changed because of potential danger?
I have the below setup of validation rules. For some reason, 'on' => 'create' block doesn't work. The conditions to be implemented are standard create / modify regarding email. Also, in edit section, I'm getting the error from 'on' => 'create' block.
How to validate the email? I'm using CakePHP v 2.6.1.
public $validate = array(
'email' => array(
'required' => array(
'rule' => array('email'),
'message' => 'Kindly provide your email for verification.'
),
'maxLength' => array(
'rule' => array('maxLength', 255),
'message' => 'Email cannot be more than 255 characters.'
),
'editunique' => array(
'rule' => array('editunique'),
'message' => 'Provided Email address already exists.',
'on' => 'update'
),
'unique' => array(
'rule' => 'isUnique',
'message' => 'Provided Email already exists.',
'on' => 'create'
)
)
);
public function editunique($email) {
// email should be one and of the logged in user only.
if ($this->find('count', array(
'conditions' => array(
$this->alias . '.id <>' => $this->data[$this->alias]['id'],
$this->alias . '.email' => $email
)
)) > 1) {
return false;
}
}
Also, I'm not getting the $this->data[$this->alias]['id'] value.
My Controller has the following section:
if ($this->Client->hasAny(array('Client.id' => base64_decode(trim($this->request->query['client_id']))))){
if ( $this->request->is('ajax') && $this->request->is('post') ){
$this->Client->create();
$this->Client->id = base64_decode(trim($this->request->query['client_id']));
$this->Client->set($this->request->data);
// validate
if($this->Client->validates()) {
// save the data after validation
if($this->Client->save($this->request->data)){
}
}
}
}
I think you are misunderstanding what Cake's isUnique rule checks for and as a result over complicating things. Cake defines isUnique as:-
The data for the field must be unique, it cannot be used by any other rows
When it checks if a value is unique it is smart enough to exclude existing data of the current row (which appears to be what you are attempting to do with your editunique rule).
So you just need your validation rules to look like:-
public $validate = array(
'email' => array(
'required' => array(
'rule' => array('email'),
'message' => 'Kindly provide your email for verification.'
),
'maxLength' => array(
'rule' => array('maxLength', 255),
'message' => 'Email cannot be more than 255 characters.'
),
'unique' => array(
'rule' => 'isUnique',
'message' => 'Provided Email already exists.'
)
)
);
This removes the editunique rule and drops the on condition of your unique rule.
As of cakephp 3.0 in the entities table it should look something like this
namespace App\Model\Table;
public function validationDefault($validator)
{
$validator
->email('email')
->add('email', 'email', [
'rule' => [$this, 'isUnique'],
'message' => __('Email already registered')
])
->requirePresence('email', 'create')
->notEmpty('email', 'Email is Required', function( $context ){
if(isset($context['data']['role_id']) && $context['data']['role_id'] != 4){
return true;
}
return false;
});
return $validator;
}
}
function isUnique($email){
$user = $this->find('all')
->where([
'Users.email' => $email,
])
->first();
if($user){
return false;
}
return true;
}
I have a model which has a primary key of 'staff_code'
I have customer validation rules as below:
public $validate = array(
'staff_code' => array(
'unique' => array(
'rule' => 'isUnique',
'message' => 'This Staff Code already exists',
'last' => true
),
'sc_required' => array(
'rule' => 'notEmpty',
'message' => 'The Staff Code must be specified',
))
);
When the field is not unique the validation error does not display
Has anyone overcome this error, I think it is related to the primary key being inputted by the user.
I have to keep the schema as it is as it is used by another piece of software and would be a real nightmare to change the way this works.
Not sure if need but my view is :
<?php
echo $this->Form->create('Staff');
echo $this->Form->inputs(array(
'staff_code' => array('type' => 'text', 'autocomplete' => 'off'),
'login_name' => array('type' => 'text', 'autocomplete' => 'off'),
'person_name' => array('type' => 'text', 'autocomplete' => 'off'),
'password',
'_allowed_to_do_po',
'is_active'
));
echo $this->Form->input('role', array('options' =>
array('user' => 'user', 'admin' => 'admin'), 'empty' => false, 'default'=>'user'));
echo $this->Form->end(array(
'label' => 'Save',
'class' => 'btn'
));
?>
...and my custom save function from the Staff controller:
function emSave($data) {
if (!$this->find('first', array('conditions' => array('staff_code' => $data['Staff']['staff_code'])))) {
if ($this->save($data)) {
return true;
} else {
return false;
}
} else {
return false;
}
}
NB: The error messages work fine for my other fields that are no primary keys.
The problem is, I think, that you are doing a validation lookup in your controller before you are calling save. Save automatically calls your validation, so you don't need to look it up first, that's the whole point of the Unique rule, it does that for you.
You might also want to add 'required' => true to your validation if you want the field to be valid.
However, having a user input a primary key field in your database is bad practice in my opinion. It should be automatically generated and invisible to the user.
I'm not sure why I keep receiving all the errors instead of just the invalid fields even when I fill out some of the required fields properly.
Submissions Controller:
public function submit() {
$this->set('title_for_layout', 'Submit - ');
if ($this->request->is('ajax')) {
if (!empty($this->request->data)) {
$this->Submission->set($this->request->data);
if ($this->Submission->invalidFields($this->request->data)) {
$formErrors = $this->Submission->validationErrors;
} else {
$formErrors = null;
}
} else {
$formErrors = null;
}
$this->set(compact('formErrors'));
}
/Submissions/json/submit.ctp:
<?php
$toReturn = array(
'formErrors' => $formErrors
);
echo json_encode($toReturn);
Submission model:
var $validate = array(
'title' => array(
'title' => array(
'rule' => 'notEmpty',
'required' => true,
'allowEmpty' => false,
'message' => 'Please enter a title'
),
'minLength' => array(
'rule' => array('minLength', 5),
'message' => 'Please make your title longer (e.g. IJL John F. Kennedy donated his presidential salary to charity)'
),
'maxLength' => array(
'rule' => array('maxLength', 300),
'message' => 'Your title needs to be shorter'
),
),
'description' => array(
'shortDescription' => array(
'rule' => array('shortDescription'),
'message' => 'Your description needs to be longer'
),
'longDescription' => array(
'rule' => array('longDescription'),
'message' => 'Your description needs to be shorter'
),
),
'source' => array(
'source' => array(
'rule' => 'notEmpty',
'required' => true,
'allowEmpty' => false,
'message' => 'Enter a valid source URL (e.g. http://en.wikipedia.org/wiki/Penguins)'
),
'website' => array(
'rule' => 'url',
'message' => 'Enter a valid source URL (e.g. http://en.wikipedia.org/wiki/Penguins)'
),
),
'category' => array(
'category' => array(
'rule' => 'notEmpty',
'required' => true,
'allowEmpty' => false,
'message' => 'Please choose a category'
)
)
);
Form values that are getting serialized and sent:
Errors I'm getting in a json response:
Pulling hair out over here :|
You seem to have got a little muddle up with validates() and invalidFields()
invalidFields() returns the invalid fields after a validates(), see: http://book.cakephp.org/2.0/en/models/data-validation/validating-data-from-the-controller.html
So your code should look something like this:
$this->Submission->set($this->request->data);
if (!$this->Submission->validates()) {
$formErrors = $this->Submission->invalidFields();
} else {
$formErrors = null;
}
First, set the data to the model:
$this->ModelName->set($this->request->data);
Then, to check if the data validates, use the validates method of the model, which will return true if it validates and false if it doesn’t:
if ($this->ModelName->validates()) {
// it validated logic
} else {
// didn't validate logic
$errors = $this->ModelName->validationErrors;
}
Validating Data from the Controller