I am using the lastest version of CodeIgniter and TankAuth and all functions work properly such as login, logout, email and register. Currently when a user needs to login, you are redirected to a separate page, which is, /auth/login.
What I am experimenting with is loading the login page in a modal(using fancybox) instead of requiring the user to leave the current page and having to login.
The problem I am running into is how can I alter the standard TankAuth setup to use ajax to submit the form rather than submitting the form and then redirecting the user.
Here is the code from the auth/login controller:
function login()
{
if ($this->tank_auth->is_logged_in()) { // logged in
redirect('');
} elseif ($this->tank_auth->is_logged_in(FALSE)) { // logged in, not activated
redirect('/auth/send_again/');
} else {
$data['login_by_username'] = ($this->config->item('login_by_username', 'tank_auth') AND
$this->config->item('use_username', 'tank_auth'));
$data['login_by_email'] = $this->config->item('login_by_email', 'tank_auth');
$this->form_validation->set_rules('login', 'Login', 'trim|required|xss_clean');
$this->form_validation->set_rules('password', 'Password', 'trim|required|xss_clean');
$this->form_validation->set_rules('remember', 'Remember me', 'integer');
// Get login for counting attempts to login
if ($this->config->item('login_count_attempts', 'tank_auth') AND
($login = $this->input->post('login'))) {
$login = $this->security->xss_clean($login);
} else {
$login = '';
}
$data['use_recaptcha'] = $this->config->item('use_recaptcha', 'tank_auth');
if ($this->tank_auth->is_max_login_attempts_exceeded($login)) {
if ($data['use_recaptcha'])
$this->form_validation->set_rules('recaptcha_response_field', 'Confirmation Code', 'trim|xss_clean|required|callback__check_recaptcha');
else
$this->form_validation->set_rules('captcha', 'Confirmation Code', 'trim|xss_clean|required|callback__check_captcha');
}
$data['errors'] = array();
if ($this->form_validation->run()) { // validation ok
if ($this->tank_auth->login(
$this->form_validation->set_value('login'),
$this->form_validation->set_value('password'),
$this->form_validation->set_value('remember'),
$data['login_by_username'],
$data['login_by_email'])) { // success
redirect('');
} else {
$errors = $this->tank_auth->get_error_message();
if (isset($errors['banned'])) { // banned user
$this->_show_message($this->lang->line('auth_message_banned').' '.$errors['banned']);
} elseif (isset($errors['not_activated'])) { // not activated user
redirect('/auth/send_again/');
} else { // fail
foreach ($errors as $k => $v) $data['errors'][$k] = $this->lang->line($v);
}
}
}
$data['show_captcha'] = FALSE;
if ($this->tank_auth->is_max_login_attempts_exceeded($login)) {
$data['show_captcha'] = TRUE;
if ($data['use_recaptcha']) {
$data['recaptcha_html'] = $this->_create_recaptcha();
} else {
$data['captcha_html'] = $this->_create_captcha();
}
}
$this->load->view('auth/login_form', $data);
}
}
The code in the view is using php to open and submit the form as such:
<?php
$login = array(
'name' => 'login',
'id' => 'login',
'value' => set_value('login'),
'maxlength' => 80,
'size' => 30,
);
if ($login_by_username AND $login_by_email) {
$login_label = 'Email or login';
} else if ($login_by_username) {
$login_label = 'Login';
} else {
$login_label = 'Email';
}
$password = array(
'name' => 'password',
'id' => 'password',
'size' => 30,
);
$remember = array(
'name' => 'remember',
'id' => 'remember',
'value' => 1,
'checked' => set_value('remember'),
'style' => 'margin:0;padding:0',
);
$captcha = array(
'name' => 'captcha',
'id' => 'captcha',
'maxlength' => 8,
);
?>
<?php echo form_open($this->uri->uri_string()); ?>
<?php echo form_submit('submit', 'Let me in'); ?>
<?php echo form_close(); ?>
Would it be as simple as using a $.ajax request and setting the url to the /auth/login controller?
If that's the case then I assume i would also need to add a return ajax data of (true / false) to the auth/login controller.
Any help would be greatly appreciated.
Ok well I'm totally sure how the codeIgniter works but I will run you through the process of it so you can try and apply it.
Then to send the form you will have to target when the form is submitted. Say this is your form
<form id="target" action="destination.html">
<input type="text" value="Hello there" />
<input type="submit" value="Go" />
</form>
$('#target').submit(function() {
alert('Handler for .submit() called.');
return false;
});
This code will be run when you press the submit button. Caution: make sure return false; to stop the page refreshing.
Inside the submit function you will need to send the POST variables off to the php file that login processes.
$.post('doLogin.php', function(data) {
$('.result').html(data);
});
So it should end up something like this
$('#target').submit(function() {
$.post('doLogin.php', function(data) {
$('.result').html(data);
});
return false;
});
Please take a look at the jQuery API to better learn the jQuery functions.
get function to get the form
see when the form is submitted
jQuery post
That should help you get going
Related
I have an Admin controller which handles the user login and other admin functionality like managing a basic cms. In the constructor I check if the users session present which is set once they login. If not and they try to access a restricted page, they should be redirected. If I redirect to another page then when going to the login page I get redirected right away as obviously that check is done in the constructor, but as soon as I try to redirect to the login page I get an error:
This page isn’t working localhost redirected you too many times. Try
clearing your cookies. ERR_TOO_MANY_REDIRECTS
class Admin extends Controller {
public function __construct()
{
if(!isLoggedIn()) {
redirect('admin/login');
}
$this->AuthModel = $this->model('Auth');
}
isLoggedIn is a function:
function isLoggedIn() {
if(isset($_SESSION['user_id']) && isset($_SESSION['browser']) && $_SESSION['browser'] == $_SERVER['HTTP_USER_AGENT']) {
return true;
} else {
return false;
}
}
Login method:
public function login()
{
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
$password = trim($_POST['password']);
$data = [
'email' => $email,
'password' => $password,
'email_error' => '',
'pass_error' => '',
'no_user' => '',
'pass_wrong' => ''
];
if(!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
$data['email_error'] = 'Invalid email address <br />';
}
if(empty(trim($_POST['password']))) {
$data['pass_error'] = 'Password required';
}
if(!empty(trim($_POST['email'])) && !$this->AuthModel->getUserByEmail($email)) {
$data['no_user'] = 'Email does not exist';
}
if(!empty($data['email_error']) || !empty($data['pass_error']) || !empty($data['no_user'])) {
$this->view('admin/login', $data);
} else {
$loggedInUser = $this->AuthModel->login($email, $password);
if($loggedInUser) {
$this->CreateUserSession($loggedInUser);
} else {
$data['pass_wrong'] = 'Incorrect login details';
$this->view('admin/login', $data);
}
}
} else {
$data = [
'email' => '',
'password' => '',
'email_error' => '',
'pass_error' => '',
'no_user' =>'',
'pass_wrong' => ''
];
$this->view('admin/login', $data);
}
}
You are using same controller for login and other functionalities. Every time it checks for authentication and it gets no. And it loops over again. try to implement your login functionalities in a separate Controller.
I am trying to learn Codeigniter,I have the following code, it gives me "The page isn't redirecting properly..." error.
public function user_login_process() {
$this->form_validation->set_rules('username', 'Username', 'trim|required');
$this->form_validation->set_rules('password', 'Password', 'trim|required');
$classes['class'] = $this->show_classes();
$this->load->view('header');
if ($this->form_validation->run() == FALSE) {
if (isset($this->session->userdata['logged_in'])) {
$this->load->view('admin_page', $classes);
} else {
$this->load->view('login_form');
}
} else {
$data = array(
'username' => $this->input->post('username'),
'password' => $this->input->post('password')
);
$result = $this->login_database->login($data);
if ($result == TRUE) {
$username = $this->input->post('username');
$result = $this->login_database->read_user_information($username);
if ($result != false) {
$session_data = array(
'username' => $result[0]->user_name,
'email' => $result[0]->user_email,
);
$this->session->set_userdata('logged_in', $session_data);
$this->load->view('admin_page', $classes);
}
} else {
$data = array(
'error_message' => 'Invalid Username or Password'
);
$this->load->view('login_form', $data);
}
}
}
If I comment out this line
$this->load->view('header');
The page loads properly, without the header. But whenever I try to load header it fails. The problem is not with the header I believe as it loads properly on other pages.
Some context: I am trying to make an admin panel, there is a login page and a registration page and an admin page. This code segment handles the loading of admin page after successful login. Both the login and registration page loads the header file properly.
I looked into some related questions, but could not seem to find the correct solution to this issue, since I don't know what the actual issue is.
Any help is appreciated.
In your code, redirection and view file loading is not loading. Below I have written correct code with my comments where needed.
if (isset($this->session->userdata['logged_in'])) {
redirect(base_url('YOUR_AUTHORIZED_CONTROLLER_OR_FUNCTION'));
}
$this->form_validation->set_rules('username', 'Username', 'trim|required');
$this->form_validation->set_rules('password', 'Password', 'trim|required');
$classes['class'] = $this->show_classes();
$this->load->view('header');
if ($this->form_validation->run() == FALSE) {
// $this->session->userdata['logged_in'] this should not be used here. Instead you should validate your controller or methods for authorized area for logged in users
$this->load->view('login_form');
} else {
$data = array(
'username' => $this->input->post('username'),
'password' => $this->input->post('password')
);
$result = $this->login_database->login($data);
if ($result == TRUE) {
$username = $this->input->post('username');
$result = $this->login_database->read_user_information($username);
if ($result != false) {
$session_data = array(
'username' => $result[0]->user_name,
'email' => $result[0]->user_email,
);
$this->session->set_userdata('logged_in', $session_data);
// Commenting below line as you should redirect to your default authorised URL
//$this->load->view('admin_page', $classes);
$this->session->set_flashdata('success', 'Great! You have successfully logged in.');
redirect(base_url('YOUR_AUTHORIZED_DEFAULT_CONTROLLER_OR_FUNCTION'));
}
} else {
$this->session->set_flashdata('error', 'Invalid Username or Password');
// Redirect to login method and controller
redirect(base_url('LOGIN_ACTION'));
}
}
View:
In your view use below line to display error/success messages. It would be better to create new view file for displaying all messages in it and load this view just after header view loaded:
<?php echo $this->session->flashdata('error'); ?>
<?php echo $this->session->flashdata('success'); ?>
Let me know if you need any clarification.
Using codeigniter with ion_auth. On the login page, it appears that validation is not working; "if ($this->form_validation->run() == true)" is always returning false, but no error messages are displayed in the form. This is the straight out-of-the-box controller and view, I haven't edited anything. Not sure how to debug this; any ideas?
This is the function that is running, but not working:
function login()
{
$this->data['title'] = "Login";
//validate form input
$this->form_validation->set_rules('identity', 'Identity', 'required');
$this->form_validation->set_rules('password', 'Password', 'required');
if ($this->form_validation->run() == true)
{
// check to see if the user is logging in
// check for "remember me"
$remember = (bool) $this->input->post('remember');
if ($this->ion_auth->login($this->input->post('identity'), $this->input->post('password'), $remember))
{
//if the login is successful
//redirect them back to the home page
$this->session->set_flashdata('message', $this->ion_auth->messages());
redirect('/', 'refresh');
}
else
{
// if the login was un-successful
// redirect them back to the login page
$this->session->set_flashdata('message', $this->ion_auth->errors());
redirect('auth/login', 'refresh'); // use redirects instead of loading views for compatibility with MY_Controller libraries
}
}
else
{
// the user is not logging in so display the login page
// set the flash data error message if there is one
$this->data['message'] = (validation_errors()) ? validation_errors() : $this->session->flashdata('message');
$this->data['identity'] = array('name' => 'identity',
'id' => 'identity',
'type' => 'text',
'value' => $this->form_validation->set_value('identity'),
);
$this->data['password'] = array('name' => 'password',
'id' => 'password',
'type' => 'password',
);
$this->_render_page('auth/login', $this->data);
}
}
The page was posting to the wrong place. Duh.
I am trying to add a captcha for my login form in codeigniter.
The captcha is displaying fine. and problem is in verifying it.
When validate_captcha is being called the value from input post is correct but session value is new page value.(For example , if on the 1st page load captcha was 12345 (let's assume in second load it will be 54321) . then when in first load user inputs 12345 it will be checked with 54321.
What can I do?
Here is what I have tried
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Login extends CI_Controller
{
public function index()
{
$capCode = rand(10000, 99999);
$this->session->set_userdata(array('captcha'=>$capCode));
echo $this->session->userdata['captcha'];//for debug only
$this->load->helper('captcha');
$vals = array(
'word' => $capCode ,
'img_path' => CAPTCHA_PATH,
'img_url' => base_url().CAPTCHA_PATH,
'img_width' => '150',
'img_height' => 30,
'expiration' => 1200
);
$cap = create_captcha($vals);
$data = array('un' => $un,'defTab'=>'','captcha'=>$cap);
$this->load->library('form_validation');
//I need to load different data if form is result of a post($data['defTab'])
if($this->input->post('submit'))
{
$this->form_validation->set_rules('email', 'Email', 'required|valid_email');
$this->form_validation->set_rules('captcha', 'Captcha', 'required|callback_validate_captcha');
if ($this->form_validation->run() == FALSE)
{
$data['defTab'] = 'what i need';
$this->load->view('login',$data);
}
else
{
print_r($this->input->post());
}
}
else
{
$this->load->view('login',$data);
}
}
public function validate_captcha()
{
$sss=$this->input->post('captcha');
//I Use this line to find problem
$this->form_validation->set_message('validate_captcha', 'session:'.$this->session->userdata['captcha'].'\nPosted val:'.$sss);
if($sss!= $this->session->userdata['captcha'])
{
return false;
}
else
{
return true;
}
}
}
You have to set the session during creation of your form:
.
.
.
} else {
if (isset($cap["word"])) {
$this->session->set_userdata("word", $cap["word"]);
}
$this->load->view('login',$data);
}
And during the validation check it with:
if($this->input->post("word", TRUE) == $this->session->userdata("word")){
// do something
}
Before calling the create_captcha method use the below code to set the previous captcha
$this->session->set_userdata('prev_captcha',$this->session->userdata('captcha_word'));
provided captcha_word contains current captcha
and check like below
function checkCaptcha($str){
$word = $this->session->get('prev_captcha');
if(strcmp(strtoupper($str),strtoupper($word)) == 0){
return true;
}else{
return false;
}
}
So I have made a form with CodeIgniter and it does uses CodeIgniter's form validation
class to validate input fields. I have a total of 6 input fields which all are
required fields.
I would like to show the same error of "This field is required" even
if there are multiple empty fields, but right now it will show the error message for each
of the fields. So if I leave every field empty, it will echo the same message 6 times.
I won't paste any code here since I know how to use the actual validation class, just
don't know how to implement it in a way as said above.
Thanks in advance!
E: Now comes another problem, it doesn't show any errors, in fact the whole method will fail right after it's checking if the "add_user" button is submitted. I'm 100% sure that the name of my submit button is "add_user".
Sorry about bad indenting, I'll never learn how to use StackOverflow's indenting.
Here's my controller for adding a user:
<?php
class Users extends CI_Controller {
public function add_user()
{
if($this->input->post('add_user'))
{
$this->load->model('subject');
$data['subjects'] = $this->subject->get_all_subjects();
$data['schools'] = $this->subject->get_all_schools();
$this->load->library('form_validation');
$this->form_validation->set_rules('f_name', 'Etunimi', 'required');
$this->form_validation->set_rules('l_name', 'Sukunimi', 'min_length[3]');
$this->form_validation->set_rules('email', 'Sähköpostiosoite', 'matches[email_confirm]|is_unique[users.email]|valid_email');
$this->form_validation->set_rules('email_confirm', 'Sähköpostiosoite', 'valid_email');
$this->form_validation->set_rules('phone_number', 'Puhelinnumero', 'min_length[7]|max_length[10]');
if($this->input->post('user_type') == "moderator")
{
$this->load->library('form_validation');
$this->form_validation->set_rules('school', 'Koulutalo', 'required');
$this->form_validation->set_rules('subject', 'Laji', 'required');
}
$this->form_validation->set_message('required', 'Täyttämättömiä kenttiä');
$this->form_validation->set_message('min_length', '%s - kentässä on liian vähän merkkejä');
$this->form_validation->set_message('matches', 'Sähköpostit eivät täsmää');
$this->form_validation->set_message('is_unique', '%s on jo rekisteröity');
if($this->form_validation->run() == FALSE)
{
$this->output->set_content_type('application_json');
$this->output->set_output(json_encode(array('result' => 0, 'error' => $this->form_validation->error_array() )));
return false;
}
$first_part_username = substr($this->input->post('f_name'), 0, 2);
$second_part_username = substr($this->input->post('l_name'), 0, 3);
$first_part_username = strtolower($first_part_username);
$second_part_username = strtolower($second_part_username);
$this->load->helper('string');
$random_number = random_string('numeric', 4);
$username = $first_part_username . $second_part_username .$random_number;
$password = random_string('alnum', 8);
$this->load->model('user');
$name = ucfirst($this->input->post('f_name')). " " .ucfirst($this->input->post('l_name'));
$data = array (
'name' => $name,
'email' => $this->input->post('email'),
'username' => $username,
'password' => $this->phpass->hash($password),
'user_type' => $this->input->post('user_type'),
'phone_number' => $this->input->post('phone_number'),
'subject_id' => !($this->input->post('subject')) ? null : $this->input->post('subject'),
'school_id' => !($this->input->post('school')) ? null : $this->input->post('school')
);
$this->user->add_user($data);
$this->load->library('email');
$config['mailtype'] = 'html';
$this->email->initialize($config);
$this->email->from('your#example.com', 'Your Name');
$this->email->to($this->input->post('email'));
$this->email->subject('test test');
$this->email->message('Test');
if($this->email->send()) {
$this->output->set_content_type('application_json');
$this->output->set_output(json_encode(array('result'=>1, 'msg' => 'Uusi käyttäjä lisätty')));
}
}
/* It will echo out this one which is viewable from developer tab right after the form is submitted */
$this->output->set_content_type('application_json');
$this->output->set_output(json_encode(array('result'=>1, 'msg' => 'Form not submitted')));
}
}
?>
And the javascript:
$(document).ready(function() {
$("#add_user_form").on('submit', function(e) {
e.preventDefault();
$("#loading_spinner").show();
var from = $(this);
$.ajax({
url: from.attr('action'),
type: from.attr('method'),
data: $(from).serialize(),
}).done(function(data) {
if(data.result == 0) {
$("#forgot-pass-success").hide();
$("#forgot-pass-error").show();
$("#forgot-pass-error").fadeIn(1000).html("<p>" + data.error + "</p>");
}
if(data.result == 1) {
$("#forgot-pass-error").hide();
$("#forgot-pass-success").show();
$("#forgot-pass-success").fadeIn(1000).html("<p>" + data.msg + "</p>");
}
$("#loading_spinner").hide();
}, 'json');
return false;
});
});
Here is an example that returns the errors in a JSON string to process with jQuery, you have to load the form validation helper.
Load the library:
$this->load->library('form_validation');
/* Outputto Json Format */
$this->output->set_content_type('application_json');
/* Validate Form Data */
$this->form_validation->set_rules('login', 'Username', 'required|min_length[4]|max_length[16]|is_unique[user.login]');
$this->form_validation->set_rules('email', 'Email', 'required|valid_email|is_unique[user.email]');
$this->form_validation->set_rules('password', 'Password', 'required|min_lenght[6]|max_length[16]|matches[confirm_password]');
/* Custom Messages */
$this->form_validation->set_message('required', 'You must enter a %s.');
$this->form_validation->set_message('is_unique', 'That %s is already in use, please try again.');
$this->form_validation->set_message('valid_email', 'You must enter a vaild email address.');
if($this->form_validation->run() == false)
{
$this->output->set_output(json_encode(['result' => 0, 'error' => $this->form_validation->error_array()]));
return false;
}
$login = $this->input->post('login');
$email = $this->input->post('email');
$password = $this->input->post('password');
$confirm_password = $this->input->post('comfirm_password');
$user_id = // DO YOUR QUERY HERE
if($user_id)
{
$this->session->set_userdata(['user_id' => $user_id]);
$this->output->set_output(json_encode(['result' => 1]));
return false;
}
$this->output->set_output(json_encode(['result' => 0, 'error' => 'User not created.']));
EDIT:
Sorry I'm using a custom library to extend the form_validation so I can create arrays to return. Just make sure you save this in your library files as my_form_validation.php
class MY_Form_validation extends CI_Form_validation
{
// ------------------------------------------------------------------------
public function __construct($config = array())
{
parent::__construct($config);
}
// ------------------------------------------------------------------------
public function error_array()
{
if(count($this->_error_array > 0))
{
return $this->_error_array;
}
}
// ------------------------------------------------------------------------
}
EDIT: Example of dealing with this data in jQuery
<!-- Javascript POST -->
<script type="text/javascript">
$(function() {
// You need to create a div called #register_form_error
$("#register_form_error").hide();
// Your register form would go here in place of #regiser_form
$("#register_form").submit(function(evt) {
evt.preventDefault();
var url = $(this).attr('action');
var postData = $(this).serialize();
$.post(url, postData, function(o) {
if (o.result == 1) {
// If the registration was successful where to go.
window.location.href = '<?=site_url('where to go')?>';
} else {
// This is where all of the form errors will be displayed
$("#register_form_error").show();
var output = '<ul>';
for (var key in o.error) {
var value = o.error[key];
output += '<li>' + value + '</li>';
}
output += '</ul>';
$("#register_form_error").html(output);
}
}, 'json');
});
});
</script>
Lastly:
if($this->input->post('add_user'))
Shoud be:
if($this->input->post('$_POST'))
That way you get the entire post array.
Off the top of my head, you could try using individual errors.
In your view:
<?php
$form_errors = array(
form_error('field_1'),
form_error('field_2'),
form_error('field_3'),
form_error('field_4'),
form_error('field_5'),
form_error('field_6')
);
$error = FALSE;
foreach ($form_errors as $form_error)
{
if ( ! empty($form_error))
$error = TRUE;
}
if ($error)
echo "All fields are required".
?>
So basically what you are doing here, is filling an array of individual form errors. form_error() returns an empty string if the field is filled in correctly according to the validation rule, otherwise it will be an error message.
To confirm that everything is filled in correctly, you are looking for an array of empty strings. If a field isn't filled in correctly, your array will contain an element which has an error message.